blob: b1f29fc28bc9a4ccb0a134fe82834c36b4f45034 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svl.hxx"
#include <svl/urihelper.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
#include "com/sun/star/ucb/Command.hpp"
#include <com/sun/star/ucb/FileSystemNotation.hpp>
#include "com/sun/star/ucb/IllegalIdentifierException.hpp"
#include "com/sun/star/ucb/UnsupportedCommandException.hpp"
#include "com/sun/star/ucb/XCommandEnvironment.hpp"
#include "com/sun/star/ucb/XCommandProcessor.hpp"
#include "com/sun/star/ucb/XContent.hpp"
#include "com/sun/star/ucb/XContentIdentifierFactory.hpp"
#include "com/sun/star/ucb/XContentProvider.hpp"
#include <com/sun/star/ucb/XContentProviderManager.hpp>
#include "com/sun/star/uno/Any.hxx"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hpp"
#include "com/sun/star/uri/UriReferenceFactory.hpp"
#include "com/sun/star/uri/XUriReference.hpp"
#include "com/sun/star/uri/XUriReferenceFactory.hpp"
#include "cppuhelper/exc_hlp.hxx"
#include "comphelper/processfactory.hxx"
#include "osl/diagnose.h"
#include "rtl/ustrbuf.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include <tools/debug.hxx>
#include <tools/inetmime.hxx>
#include <ucbhelper/contentbroker.hxx>
#include <unotools/charclass.hxx>
#include "rtl/instance.hxx"
namespace unnamed_svl_urihelper {}
using namespace unnamed_svl_urihelper;
// unnamed namespaces don't work well yet...
namespace css = com::sun::star;
using namespace com::sun::star;
//============================================================================
//
// SmartRel2Abs
//
//============================================================================
namespace unnamed_svl_urihelper {
inline UniString toUniString(ByteString const & rString)
{
return UniString(rString, RTL_TEXTENCODING_ISO_8859_1);
}
inline UniString toUniString(UniString const & rString)
{
return rString;
}
template< typename Str >
inline UniString SmartRel2Abs_Impl(INetURLObject const & rTheBaseURIRef,
Str const & rTheRelURIRef,
Link const & rMaybeFileHdl,
bool bCheckFileExists,
bool bIgnoreFragment,
INetURLObject::EncodeMechanism
eEncodeMechanism,
INetURLObject::DecodeMechanism
eDecodeMechanism,
rtl_TextEncoding eCharset,
bool bRelativeNonURIs,
INetURLObject::FSysStyle eStyle)
{
// Backwards compatibility:
if (rTheRelURIRef.Len() != 0 && rTheRelURIRef.GetChar(0) == '#')
return toUniString(rTheRelURIRef);
INetURLObject aAbsURIRef;
if (rTheBaseURIRef.HasError())
aAbsURIRef.
SetSmartURL(rTheRelURIRef, eEncodeMechanism, eCharset, eStyle);
else
{
bool bWasAbsolute;
aAbsURIRef = rTheBaseURIRef.smartRel2Abs(rTheRelURIRef,
bWasAbsolute,
bIgnoreFragment,
eEncodeMechanism,
eCharset,
bRelativeNonURIs,
eStyle);
if (bCheckFileExists
&& !bWasAbsolute
&& (aAbsURIRef.GetProtocol() == INET_PROT_FILE))
{
INetURLObject aNonFileURIRef;
aNonFileURIRef.SetSmartURL(rTheRelURIRef,
eEncodeMechanism,
eCharset,
eStyle);
if (!aNonFileURIRef.HasError()
&& aNonFileURIRef.GetProtocol() != INET_PROT_FILE)
{
bool bMaybeFile = false;
if (rMaybeFileHdl.IsSet())
{
UniString aFilePath(toUniString(rTheRelURIRef));
bMaybeFile = rMaybeFileHdl.Call(&aFilePath) != 0;
}
if (!bMaybeFile)
aAbsURIRef = aNonFileURIRef;
}
}
}
return aAbsURIRef.GetMainURL(eDecodeMechanism, eCharset);
}
}
UniString
URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
ByteString const & rTheRelURIRef,
Link const & rMaybeFileHdl,
bool bCheckFileExists,
bool bIgnoreFragment,
INetURLObject::EncodeMechanism eEncodeMechanism,
INetURLObject::DecodeMechanism eDecodeMechanism,
rtl_TextEncoding eCharset,
bool bRelativeNonURIs,
INetURLObject::FSysStyle eStyle)
{
return SmartRel2Abs_Impl(rTheBaseURIRef, rTheRelURIRef, rMaybeFileHdl,
bCheckFileExists, bIgnoreFragment,
eEncodeMechanism, eDecodeMechanism, eCharset,
bRelativeNonURIs, eStyle);
}
UniString
URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
UniString const & rTheRelURIRef,
Link const & rMaybeFileHdl,
bool bCheckFileExists,
bool bIgnoreFragment,
INetURLObject::EncodeMechanism eEncodeMechanism,
INetURLObject::DecodeMechanism eDecodeMechanism,
rtl_TextEncoding eCharset,
bool bRelativeNonURIs,
INetURLObject::FSysStyle eStyle)
{
return SmartRel2Abs_Impl(rTheBaseURIRef, rTheRelURIRef, rMaybeFileHdl,
bCheckFileExists, bIgnoreFragment,
eEncodeMechanism, eDecodeMechanism, eCharset,
bRelativeNonURIs, eStyle);
}
//============================================================================
//
// SetMaybeFileHdl
//
//============================================================================
namespace { struct MaybeFileHdl : public rtl::Static< Link, MaybeFileHdl > {}; }
void URIHelper::SetMaybeFileHdl(Link const & rTheMaybeFileHdl)
{
MaybeFileHdl::get() = rTheMaybeFileHdl;
}
//============================================================================
//
// GetMaybeFileHdl
//
//============================================================================
Link URIHelper::GetMaybeFileHdl()
{
return MaybeFileHdl::get();
}
namespace {
bool isAbsoluteHierarchicalUriReference(
css::uno::Reference< css::uri::XUriReference > const & uriReference)
{
return uriReference.is() && uriReference->isAbsolute()
&& uriReference->isHierarchical() && !uriReference->hasRelativePath();
}
// To improve performance, assume that if for any prefix URL of a given
// hierarchical URL either a UCB content cannot be created, or the UCB content
// does not support the getCasePreservingURL command, then this will hold for
// any other prefix URL of the given URL, too:
enum Result { Success, GeneralFailure, SpecificFailure };
Result normalizePrefix(
css::uno::Reference< css::ucb::XContentProvider > const & broker,
rtl::OUString const & uri, rtl::OUString * normalized)
{
OSL_ASSERT(broker.is() && normalized != 0);
css::uno::Reference< css::ucb::XContent > content;
try {
content = broker->queryContent(
css::uno::Reference< css::ucb::XContentIdentifierFactory >(
broker, css::uno::UNO_QUERY_THROW)->createContentIdentifier(
uri));
} catch (css::ucb::IllegalIdentifierException &) {}
if (!content.is()) {
return GeneralFailure;
}
try {
#if OSL_DEBUG_LEVEL > 0
bool ok =
#endif
(css::uno::Reference< css::ucb::XCommandProcessor >(
content, css::uno::UNO_QUERY_THROW)->execute(
css::ucb::Command(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"getCasePreservingURL")),
-1, css::uno::Any()),
0,
css::uno::Reference< css::ucb::XCommandEnvironment >())
>>= *normalized);
OSL_ASSERT(ok);
} catch (css::uno::RuntimeException &) {
throw;
} catch (css::ucb::UnsupportedCommandException &) {
return GeneralFailure;
} catch (css::uno::Exception &) {
return SpecificFailure;
}
return Success;
}
rtl::OUString normalize(
css::uno::Reference< css::ucb::XContentProvider > const & broker,
css::uno::Reference< css::uri::XUriReferenceFactory > const & uriFactory,
rtl::OUString const & uriReference)
{
// normalizePrefix can potentially fail (a typically example being a file
// URL that denotes a non-existing resource); in such a case, try to
// normalize as long a prefix of the given URL as possible (i.e., normalize
// all the existing directories within the path):
rtl::OUString normalized;
sal_Int32 n = uriReference.indexOf('#');
normalized = n == -1 ? uriReference : uriReference.copy(0, n);
switch (normalizePrefix(broker, normalized, &normalized)) {
case Success:
return n == -1 ? normalized : normalized + uriReference.copy(n);
case GeneralFailure:
return uriReference;
case SpecificFailure:
default:
break;
}
css::uno::Reference< css::uri::XUriReference > ref(
uriFactory->parse(uriReference));
if (!isAbsoluteHierarchicalUriReference(ref)) {
return uriReference;
}
sal_Int32 count = ref->getPathSegmentCount();
if (count < 2) {
return uriReference;
}
rtl::OUStringBuffer head(ref->getScheme());
head.append(static_cast< sal_Unicode >(':'));
if (ref->hasAuthority()) {
head.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
head.append(ref->getAuthority());
}
for (sal_Int32 i = count - 1; i > 0; --i) {
rtl::OUStringBuffer buf(head);
for (sal_Int32 j = 0; j < i; ++j) {
buf.append(static_cast< sal_Unicode >('/'));
buf.append(ref->getPathSegment(j));
}
normalized = buf.makeStringAndClear();
if (normalizePrefix(broker, normalized, &normalized) != SpecificFailure)
{
buf.append(normalized);
css::uno::Reference< css::uri::XUriReference > preRef(
uriFactory->parse(normalized));
if (!isAbsoluteHierarchicalUriReference(preRef)) {
// This could only happen if something is inconsistent:
break;
}
sal_Int32 preCount = preRef->getPathSegmentCount();
// normalizePrefix may have added or removed a final slash:
if (preCount != i) {
if (preCount == i - 1) {
buf.append(static_cast< sal_Unicode >('/'));
} else if (preCount - 1 == i && buf.getLength() > 0
&& buf.charAt(buf.getLength() - 1) == '/')
{
buf.setLength(buf.getLength() - 1);
} else {
// This could only happen if something is inconsistent:
break;
}
}
for (sal_Int32 j = i; j < count; ++j) {
buf.append(static_cast< sal_Unicode >('/'));
buf.append(ref->getPathSegment(j));
}
if (ref->hasQuery()) {
buf.append(static_cast< sal_Unicode >('?'));
buf.append(ref->getQuery());
}
if (ref->hasFragment()) {
buf.append(static_cast< sal_Unicode >('#'));
buf.append(ref->getFragment());
}
return buf.makeStringAndClear();
}
}
return uriReference;
}
}
css::uno::Reference< css::uri::XUriReference >
URIHelper::normalizedMakeRelative(
css::uno::Reference< css::uno::XComponentContext > const & context,
rtl::OUString const & baseUriReference, rtl::OUString const & uriReference)
{
OSL_ASSERT(context.is());
css::uno::Reference< css::lang::XMultiComponentFactory > componentFactory(
context->getServiceManager());
if (!componentFactory.is()) {
throw css::uno::RuntimeException(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"component context has no service manager")),
css::uno::Reference< css::uno::XInterface >());
}
css::uno::Sequence< css::uno::Any > args(2);
args[0] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Local"));
args[1] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office"));
css::uno::Reference< css::ucb::XContentProvider > broker;
try {
broker = css::uno::Reference< css::ucb::XContentProvider >(
componentFactory->createInstanceWithArgumentsAndContext(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.ucb.UniversalContentBroker")),
args, context),
css::uno::UNO_QUERY_THROW);
} catch (css::uno::RuntimeException &) {
throw;
} catch (css::uno::Exception &) {
css::uno::Any exception(cppu::getCaughtException());
throw css::lang::WrappedTargetRuntimeException(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"creating com.sun.star.ucb.UniversalContentBroker failed")),
css::uno::Reference< css::uno::XInterface >(),
exception);
}
css::uno::Reference< css::uri::XUriReferenceFactory > uriFactory(
css::uri::UriReferenceFactory::create(context));
return uriFactory->makeRelative(
uriFactory->parse(normalize(broker, uriFactory, baseUriReference)),
uriFactory->parse(normalize(broker, uriFactory, uriReference)), true,
true, false);
}
rtl::OUString URIHelper::simpleNormalizedMakeRelative(
rtl::OUString const & baseUriReference, rtl::OUString const & uriReference)
{
com::sun::star::uno::Reference< com::sun::star::uri::XUriReference > rel(
URIHelper::normalizedMakeRelative(
com::sun::star::uno::Reference<
com::sun::star::uno::XComponentContext >(
(com::sun::star::uno::Reference<
com::sun::star::beans::XPropertySet >(
comphelper::getProcessServiceFactory(),
com::sun::star::uno::UNO_QUERY_THROW)->
getPropertyValue(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("DefaultContext")))),
com::sun::star::uno::UNO_QUERY_THROW),
baseUriReference, uriReference));
return rel.is() ? rel->getUriReference() : uriReference;
}
//============================================================================
//
// FindFirstURLInText
//
//============================================================================
namespace unnamed_svl_urihelper {
inline xub_StrLen nextChar(UniString const & rStr, xub_StrLen nPos)
{
return INetMIME::isHighSurrogate(rStr.GetChar(nPos))
&& rStr.Len() - nPos >= 2
&& INetMIME::isLowSurrogate(rStr.GetChar(nPos + 1)) ?
nPos + 2 : nPos + 1;
}
bool isBoundary1(CharClass const & rCharClass, UniString const & rStr,
xub_StrLen nPos, xub_StrLen nEnd)
{
if (nPos == nEnd)
return true;
if (rCharClass.isLetterNumeric(rStr, nPos))
return false;
switch (rStr.GetChar(nPos))
{
case '$':
case '%':
case '&':
case '-':
case '/':
case '@':
case '\\':
return false;
default:
return true;
}
}
bool isBoundary2(CharClass const & rCharClass, UniString const & rStr,
xub_StrLen nPos, xub_StrLen nEnd)
{
if (nPos == nEnd)
return true;
if (rCharClass.isLetterNumeric(rStr, nPos))
return false;
switch (rStr.GetChar(nPos))
{
case '!':
case '#':
case '$':
case '%':
case '&':
case '\'':
case '*':
case '+':
case '-':
case '/':
case '=':
case '?':
case '@':
case '^':
case '_':
case '`':
case '{':
case '|':
case '}':
case '~':
return false;
default:
return true;
}
}
bool checkWChar(CharClass const & rCharClass, UniString const & rStr,
xub_StrLen * pPos, xub_StrLen * pEnd, bool bBackslash = false,
bool bPipe = false)
{
sal_Unicode c = rStr.GetChar(*pPos);
if (INetMIME::isUSASCII(c))
{
static sal_uInt8 const aMap[128]
= { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 4, 4, 4, 1, // !"#$%&'
1, 1, 1, 1, 1, 4, 1, 4, // ()*+,-./
4, 4, 4, 4, 4, 4, 4, 4, // 01234567
4, 4, 1, 1, 0, 1, 0, 1, // 89:;<=>?
4, 4, 4, 4, 4, 4, 4, 4, // @ABCDEFG
4, 4, 4, 4, 4, 4, 4, 4, // HIJKLMNO
4, 4, 4, 4, 4, 4, 4, 4, // PQRSTUVW
4, 4, 4, 1, 2, 1, 0, 1, // XYZ[\]^_
0, 4, 4, 4, 4, 4, 4, 4, // `abcdefg
4, 4, 4, 4, 4, 4, 4, 4, // hijklmno
4, 4, 4, 4, 4, 4, 4, 4, // pqrstuvw
4, 4, 4, 0, 3, 0, 1, 0 }; // xyz{|}~
switch (aMap[c])
{
default: // not uric
return false;
case 1: // uric
++(*pPos);
return true;
case 2: // "\"
if (bBackslash)
{
*pEnd = ++(*pPos);
return true;
}
else
return false;
case 3: // "|"
if (bPipe)
{
*pEnd = ++(*pPos);
return true;
}
else
return false;
case 4: // alpha, digit, "$", "%", "&", "-", "/", "@" (see
// isBoundary1)
*pEnd = ++(*pPos);
return true;
}
}
else if (rCharClass.isLetterNumeric(rStr, *pPos))
{
*pEnd = *pPos = nextChar(rStr, *pPos);
return true;
}
else
return false;
}
sal_uInt32 scanDomain(UniString const & rStr, xub_StrLen * pPos,
xub_StrLen nEnd)
{
sal_Unicode const * pBuffer = rStr.GetBuffer();
sal_Unicode const * p = pBuffer + *pPos;
sal_uInt32 nLabels = INetURLObject::scanDomain(p, pBuffer + nEnd, false);
*pPos = sal::static_int_cast< xub_StrLen >(p - pBuffer);
return nLabels;
}
}
UniString
URIHelper::FindFirstURLInText(UniString const & rText,
xub_StrLen & rBegin,
xub_StrLen & rEnd,
CharClass const & rCharClass,
INetURLObject::EncodeMechanism eMechanism,
rtl_TextEncoding eCharset,
INetURLObject::FSysStyle eStyle)
{
if (!(rBegin <= rEnd && rEnd <= rText.Len()))
return UniString();
// Search for the first substring of [rBegin..rEnd[ that matches any of the
// following productions (for which the appropriate style bit is set in
// eStyle, if applicable).
//
// 1st Production (known scheme):
// \B1 <one of the known schemes, except file> ":" 1*wchar ["#" 1*wchar]
// \B1
//
// 2nd Production (file):
// \B1 "FILE:" 1*(wchar / "\" / "|") ["#" 1*wchar] \B1
//
// 3rd Production (ftp):
// \B1 "FTP" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
//
// 4th Production (http):
// \B1 "WWW" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
//
// 5th Production (mailto):
// \B2 local-part "@" domain \B1
//
// 6th Production (UNC file):
// \B1 "\\" domain "\" *(wchar / "\") \B1
//
// 7th Production (DOS file):
// \B1 ALPHA ":\" *(wchar / "\") \B1
//
// 8th Production (Unix-like DOS file):
// \B1 ALPHA ":/" *(wchar / "\") \B1
//
// The productions use the following auxiliary rules.
//
// local-part = atom *("." atom)
// atom = 1*(alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+"
// / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}"
// / "~")
// domain = label *("." label)
// label = alphanum [*(alphanum / "-") alphanum]
// alphanum = ALPHA / DIGIT
// wchar = <any uric character (ignoring the escaped rule), or "%", or
// a letter or digit (according to rCharClass)>
//
// "\B1" (boundary 1) stands for the beginning or end of the block of text,
// or a character that is neither (a) a letter or digit (according to
// rCharClass), nor (b) any of "$", "%", "&", "-", "/", "@", or "\".
// (FIXME: What was the rationale for this set of punctuation characters?)
//
// "\B2" (boundary 2) stands for the beginning or end of the block of text,
// or a character that is neither (a) a letter or digit (according to
// rCharClass), nor (b) any of "!", "#", "$", "%", "&", "'", "*", "+", "-",
// "/", "=", "?", "@", "^", "_", "`", "{", "|", "}", or "~" (i.e., an RFC
// 822 <atom> character, or "@" from \B1's set above).
//
// Productions 1--4, and 6--8 try to find a maximum-length match, but they
// stop at the first <wchar> character that is a "\B1" character which is
// only followed by "\B1" characters (taking "\" and "|" characters into
// account appropriately). Production 5 simply tries to find a maximum-
// length match.
//
// Productions 1--4 use the given eMechanism and eCharset. Productions 5--9
// use ENCODE_ALL.
//
// Productions 6--9 are only applicable if the FSYS_DOS bit is set in
// eStyle.
bool bBoundary1 = true;
bool bBoundary2 = true;
for (xub_StrLen nPos = rBegin; nPos != rEnd; nPos = nextChar(rText, nPos))
{
sal_Unicode c = rText.GetChar(nPos);
if (bBoundary1)
{
if (INetMIME::isAlpha(c))
{
xub_StrLen i = nPos;
INetProtocol eScheme
= INetURLObject::CompareProtocolScheme(UniString(rText, i,
rEnd));
if (eScheme == INET_PROT_FILE) // 2nd
{
while (rText.GetChar(i++) != ':') ;
xub_StrLen nPrefixEnd = i;
xub_StrLen nUriEnd = i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd, true,
true)) ;
if (i != nPrefixEnd && rText.GetChar(i) == '#')
{
++i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
}
if (nUriEnd != nPrefixEnd
&& isBoundary1(rCharClass, rText, nUriEnd, rEnd))
{
INetURLObject aUri(UniString(rText, nPos,
nUriEnd - nPos),
INET_PROT_FILE, eMechanism, eCharset,
eStyle);
if (!aUri.HasError())
{
rBegin = nPos;
rEnd = nUriEnd;
return
aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
}
}
}
else if (eScheme != INET_PROT_NOT_VALID) // 1st
{
while (rText.GetChar(i++) != ':') ;
xub_StrLen nPrefixEnd = i;
xub_StrLen nUriEnd = i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
if (i != nPrefixEnd && rText.GetChar(i) == '#')
{
++i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
}
if (nUriEnd != nPrefixEnd
&& (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
|| rText.GetChar(nUriEnd) == '\\'))
{
INetURLObject aUri(UniString(rText, nPos,
nUriEnd - nPos),
INET_PROT_HTTP, eMechanism,
eCharset);
if (!aUri.HasError())
{
rBegin = nPos;
rEnd = nUriEnd;
return
aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
}
}
}
// 3rd, 4th:
i = nPos;
sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
if (nLabels >= 3
&& rText.GetChar(nPos + 3) == '.'
&& (((rText.GetChar(nPos) == 'w'
|| rText.GetChar(nPos) == 'W')
&& (rText.GetChar(nPos + 1) == 'w'
|| rText.GetChar(nPos + 1) == 'W')
&& (rText.GetChar(nPos + 2) == 'w'
|| rText.GetChar(nPos + 2) == 'W'))
|| ((rText.GetChar(nPos) == 'f'
|| rText.GetChar(nPos) == 'F')
&& (rText.GetChar(nPos + 1) == 't'
|| rText.GetChar(nPos + 1) == 'T')
&& (rText.GetChar(nPos + 2) == 'p'
|| rText.GetChar(nPos + 2) == 'P'))))
// (note that rText.GetChar(nPos + 3) is guaranteed to be
// valid)
{
xub_StrLen nUriEnd = i;
if (i != rEnd && rText.GetChar(i) == '/')
{
nUriEnd = ++i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
}
if (i != rEnd && rText.GetChar(i) == '#')
{
++i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
}
if (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
|| rText.GetChar(nUriEnd) == '\\')
{
INetURLObject aUri(UniString(rText, nPos,
nUriEnd - nPos),
INET_PROT_HTTP, eMechanism,
eCharset);
if (!aUri.HasError())
{
rBegin = nPos;
rEnd = nUriEnd;
return
aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
}
}
}
if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 3
&& rText.GetChar(nPos + 1) == ':'
&& (rText.GetChar(nPos + 2) == '/'
|| rText.GetChar(nPos + 2) == '\\')) // 7th, 8th
{
i = nPos + 3;
xub_StrLen nUriEnd = i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
{
INetURLObject aUri(UniString(rText, nPos,
nUriEnd - nPos),
INET_PROT_FILE,
INetURLObject::ENCODE_ALL,
RTL_TEXTENCODING_UTF8,
INetURLObject::FSYS_DOS);
if (!aUri.HasError())
{
rBegin = nPos;
rEnd = nUriEnd;
return
aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
}
}
}
}
else if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 2
&& rText.GetChar(nPos) == '\\'
&& rText.GetChar(nPos + 1) == '\\') // 6th
{
xub_StrLen i = nPos + 2;
sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
if (nLabels >= 1 && i != rEnd && rText.GetChar(i) == '\\')
{
xub_StrLen nUriEnd = ++i;
while (i != rEnd
&& checkWChar(rCharClass, rText, &i, &nUriEnd,
true)) ;
if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
{
INetURLObject aUri(UniString(rText, nPos,
nUriEnd - nPos),
INET_PROT_FILE,
INetURLObject::ENCODE_ALL,
RTL_TEXTENCODING_UTF8,
INetURLObject::FSYS_DOS);
if (!aUri.HasError())
{
rBegin = nPos;
rEnd = nUriEnd;
return
aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
}
}
}
}
}
if (bBoundary2 && INetMIME::isAtomChar(c)) // 5th
{
bool bDot = false;
for (xub_StrLen i = nPos + 1; i != rEnd; ++i)
{
sal_Unicode c2 = rText.GetChar(i);
if (INetMIME::isAtomChar(c2))
bDot = false;
else if (bDot)
break;
else if (c2 == '.')
bDot = true;
else
{
if (c2 == '@')
{
++i;
sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
if (nLabels >= 1
&& isBoundary1(rCharClass, rText, i, rEnd))
{
INetURLObject aUri(UniString(rText, nPos, i - nPos),
INET_PROT_MAILTO,
INetURLObject::ENCODE_ALL);
if (!aUri.HasError())
{
rBegin = nPos;
rEnd = i;
return aUri.GetMainURL(
INetURLObject::DECODE_TO_IURI);
}
}
}
break;
}
}
}
bBoundary1 = isBoundary1(rCharClass, rText, nPos, rEnd);
bBoundary2 = isBoundary2(rCharClass, rText, nPos, rEnd);
}
rBegin = rEnd;
return UniString();
}
//============================================================================
//
// removePassword
//
//============================================================================
UniString
URIHelper::removePassword(UniString const & rURI,
INetURLObject::EncodeMechanism eEncodeMechanism,
INetURLObject::DecodeMechanism eDecodeMechanism,
rtl_TextEncoding eCharset)
{
INetURLObject aObj(rURI, eEncodeMechanism, eCharset);
return aObj.HasError() ?
rURI :
String(aObj.GetURLNoPass(eDecodeMechanism, eCharset));
}
//============================================================================
//
// queryFSysStyle
//
//============================================================================
INetURLObject::FSysStyle URIHelper::queryFSysStyle(UniString const & rFileUrl,
bool bAddConvenienceStyles)
throw (uno::RuntimeException)
{
::ucbhelper::ContentBroker const * pBroker = ::ucbhelper::ContentBroker::get();
uno::Reference< ucb::XContentProviderManager > xManager;
if (pBroker)
xManager = pBroker->getContentProviderManagerInterface();
uno::Reference< beans::XPropertySet > xProperties;
if (xManager.is())
xProperties
= uno::Reference< beans::XPropertySet >(
xManager->queryContentProvider(rFileUrl), uno::UNO_QUERY);
sal_Int32 nNotation = ucb::FileSystemNotation::UNKNOWN_NOTATION;
if (xProperties.is())
try
{
xProperties->getPropertyValue(rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"FileSystemNotation")))
>>= nNotation;
}
catch (beans::UnknownPropertyException const &) {}
catch (lang::WrappedTargetException const &) {}
// The following code depends on the fact that the
// com::sun::star::ucb::FileSystemNotation constants range from UNKNOWN to
// MAC, without any holes. The table below has two entries per notation,
// the first is used if bAddConvenienceStyles == false, while the second
// is used if bAddConvenienceStyles == true:
static INetURLObject::FSysStyle const aMap[][2]
= { { INetURLObject::FSysStyle(0),
INetURLObject::FSYS_DETECT },
// UNKNOWN
{ INetURLObject::FSYS_UNX,
INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
| INetURLObject::FSYS_UNX) },
// UNIX
{ INetURLObject::FSYS_DOS,
INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
| INetURLObject::FSYS_UNX
| INetURLObject::FSYS_DOS) },
// DOS
{ INetURLObject::FSYS_MAC,
INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
| INetURLObject::FSYS_UNX
| INetURLObject::FSYS_MAC) } };
return aMap[nNotation < ucb::FileSystemNotation::UNKNOWN_NOTATION
|| nNotation > ucb::FileSystemNotation::MAC_NOTATION ?
0 :
nNotation
- ucb::FileSystemNotation::UNKNOWN_NOTATION]
[bAddConvenienceStyles];
}