// A slightly modified version of Pchar in rtl/source/uri.c, but without // encoding slashes:
constexpr auto uriCharClass = rtl::createUriCharClass(
u8"!$&'()*+,-./0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~");
bool convert(OUStringBuffer const & in, OStringBuffer * append) {
assert(append != nullptr); for (sal_Size nConvert = in.getLength();;) { autoconst oldLen = append->getLength(); auto n = std::min(
std::max(nConvert, sal_Size(PATH_MAX)),
sal_Size(std::numeric_limits<sal_Int32>::max() - oldLen)); // approximation of required converted size auto s = append->appendUninitialized(n);
sal_uInt32 info;
sal_Size converted; //TODO: context, for reliable treatment of DESTBUFFERTOSMALL:
n = UnicodeToTextConverter_Impl::getInstance().convert(
in.getStr() + in.getLength() - nConvert, nConvert, s, n,
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
| RTL_UNICODETOTEXT_FLAGS_FLUSH),
&info, &converted); if ((info & RTL_UNICODETOTEXT_INFO_ERROR) != 0) { returnfalse;
}
append->setLength(oldLen + n);
assert(converted <= nConvert);
nConvert -= converted;
assert((nConvert == 0) == ((info & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL) == 0)); if ((info & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL) == 0) { break;
}
} returntrue;
}
bool decodeFromUtf8(std::u16string_view text, OString * result) {
assert(result != nullptr); auto p = text.data(); autoconst end = p + text.size();
OUStringBuffer ubuf(static_cast<int>(text.size()));
OStringBuffer bbuf(PATH_MAX); while (p < end) {
rtl::uri::detail::EscapeType t;
sal_uInt32 c = rtl::uri::detail::readUcs4(&p, end, true, RTL_TEXTENCODING_UTF8, &t); switch (t) { case rtl::uri::detail::EscapeNo: if (c == '%') { returnfalse;
}
[[fallthrough]]; case rtl::uri::detail::EscapeChar: if (rtl::isSurrogate(c)) { returnfalse;
}
ubuf.appendUtf32(c); break; case rtl::uri::detail::EscapeOctet: if (!convert(ubuf, &bbuf)) { returnfalse;
}
ubuf.setLength(0);
assert(c <= 0xFF);
bbuf.append(char(c)); break;
}
} if (!convert(ubuf, &bbuf)) { returnfalse;
}
*result = bbuf.makeStringAndClear(); returntrue;
}
template<typename T> oslFileError getSystemPathFromFileUrl(
OUString const & url, T * path, bool resolveHome)
{
assert(path != nullptr); // For compatibility with assumptions in other parts of the code base, // assume that anything starting with a slash is a system path instead of a // (relative) file URL (except if it starts with two slashes, in which case // it is a relative URL with an authority component): if (url.isEmpty()
|| (url[0] == '/' && (url.getLength() == 1 || url[1] != '/')))
{ return osl_File_E_INVAL;
} // Check for non file scheme:
sal_Int32 i = 0; if (rtl::isAsciiAlpha(url[0])) { for (sal_Int32 j = 1; j != url.getLength(); ++j) { auto c = url[j]; if (c == ':') { if (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
url.pData->buffer, j,
RTL_CONSTASCII_STRINGPARAM("file"))
!= 0)
{ return osl_File_E_INVAL;
}
i = j + 1; break;
} if (!rtl::isAsciiAlphanumeric(c) && c != '+' && c != '-'
&& c != '.')
{ break;
}
}
} // Handle query or fragment: if (url.indexOf('?', i) != -1 || url.indexOf('#', i) != -1) return osl_File_E_INVAL; // Handle authority, supporting a host of "localhost", "127.0.0.1", or the exact value (e.g., // not supporting an additional final dot, for simplicity) reported by osl_getLocalHostnameFQDN // (and, in each case, ignoring case of ASCII letters): if (url.getLength() - i >= 2 && url[i] == '/' && url[i + 1] == '/')
{
i += 2;
sal_Int32 j = url.indexOf('/', i); if (j == -1)
j = url.getLength(); if (j != i
&& (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
url.pData->buffer + i, j - i,
RTL_CONSTASCII_STRINGPARAM("localhost"))
!= 0)
&& (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
url.pData->buffer + i, j - i,
RTL_CONSTASCII_STRINGPARAM("127.0.0.1"))
!= 0))
{
OUString hostname; // The 'file' URI Scheme does imply that we want a FQDN in this case // See https://tools.ietf.org/html/rfc8089#section-3 if (osl_getLocalHostnameFQDN(&hostname.pData) != osl_Socket_Ok
|| (rtl_ustr_compareIgnoreAsciiCase_WithLength(
url.pData->buffer + i, j - i, hostname.getStr(), hostname.getLength())
!= 0))
{ return osl_File_E_INVAL;
}
}
i = j;
} // Handle empty path: if (i == url.getLength())
{
*path = "/"; return osl_File_E_None;
} // Path must not contain %2F: if (url.indexOf("%2F", i) != -1 || url.indexOf("%2f", i) != -1) return osl_File_E_INVAL;
if constexpr (std::is_same_v<T, rtl::OString>) { if (!decodeFromUtf8(url.subView(i), path)) { return osl_File_E_INVAL;
}
} elseif constexpr (std::is_same_v<T, rtl::OUString>) {
*path = rtl::Uri::decode(
url.copy(i), rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
} else {
static_assert(std::is_same_v<T, rtl::OString> || std::is_same_v<T, rtl::OUString>);
} // Path must not contain %2F: if (path->indexOf('\0') != -1) return osl_File_E_INVAL;
/* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ if( systemPath.startsWith("~") )
{ /* check if another user is specified */ if( ( systemPath.getLength() == 1 ) ||
( systemPath[1] == '/' ) )
{ /* osl_getHomeDir returns file URL */
oslSecurity pSecurity = osl_getCurrentSecurity();
osl_getHomeDir( pSecurity , &pTmp );
osl_freeSecurityHandle( pSecurity );
sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath)
{ /* we may always skip -2 because we mayatleaststandona'/'but eitherthereisnoothercharacter beforethis'/'orit'sanother characterthanthe'/'
*/
sal_Unicode* p = ustrtoend(aPath) - 2;
/* move back to the next path separator
or to the start of the string */ while ((p > aPath) && (*p != '/'))
p--;
oslFileError osl_getAbsoluteFileURL_impl_(const OUString& unresolved_path, OUString& resolved_path)
{ /* the given unresolved path must not exceed PATH_MAX */ if (unresolved_path.getLength() >= (PATH_MAX - 2)) return oslTranslateFileError(ENAMETOOLONG);
/* reserve space for leading '/' and trailing '\0'
do not exceed this limit */
sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2;
/* if realpath fails with error ENOTDIR, EACCES or ENOENT wewillnotcallitagain,because_osl_realpathshouldalso
work with non existing directories etc. */ bool realpath_failed = false;
oslFileError ferr;
path_resolved_so_far[0] = '\0';
while (*punresolved != '\0')
{ /* ignore '/.' , skip one part back when '/..' */ if ((*punresolved == '.') && (*presolvedsf == '/'))
{ if (*(punresolved + 1) == '\0')
{
punresolved++; continue;
} if (*(punresolved + 1) == '/')
{
punresolved += 2; continue;
} if ((*(punresolved + 1) == '.') && (*(punresolved + 2) == '\0' || (*(punresolved + 2) == '/')))
{
_rmlastpathtoken(path_resolved_so_far);
/* a file or directory name may start with '.' */ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) return oslTranslateFileError(ENAMETOOLONG);
if (!realpath_failed)
{
ferr = _osl_resolvepath(
path_resolved_so_far,
&realpath_failed);
if (ferr != osl_File_E_None) return ferr;
if (!_islastchr(path_resolved_so_far, '/'))
{ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) return oslTranslateFileError(ENAMETOOLONG);
ustrchrcat('/', path_resolved_so_far);
}
}
} else// any other character
{ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) return oslTranslateFileError(ENAMETOOLONG);
oslFileError osl_getAbsoluteFileURL(
rtl_uString* ustrBaseDirURL,
rtl_uString* ustrRelativeURL,
rtl_uString** pustrAbsoluteURL)
{ /* Work around the below call to getSystemPathFromFileURL rejecting input thatstartswith"/"(forwhateverreasonitbehavesthatway;but
changing that would start to break lots of tests at least) */
OUString relUrl(ustrRelativeURL); if (relUrl.startsWith("//"))
relUrl = "file:" + relUrl; elseif (relUrl.startsWith("/"))
relUrl = "file://" + relUrl;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.