merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / misc / urihelper.cxx
blob5771ed9dffa2c5818a9c7947720f46524649e059
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: urihelper.cxx,v $
10 * $Revision: 1.22.136.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include <urihelper.hxx>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
36 #include "com/sun/star/lang/XMultiComponentFactory.hpp"
37 #include "com/sun/star/ucb/Command.hpp"
38 #include <com/sun/star/ucb/FileSystemNotation.hpp>
39 #include "com/sun/star/ucb/IllegalIdentifierException.hpp"
40 #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
41 #include "com/sun/star/ucb/XCommandEnvironment.hpp"
42 #include "com/sun/star/ucb/XCommandProcessor.hpp"
43 #include "com/sun/star/ucb/XContent.hpp"
44 #include "com/sun/star/ucb/XContentIdentifierFactory.hpp"
45 #include "com/sun/star/ucb/XContentProvider.hpp"
46 #include <com/sun/star/ucb/XContentProviderManager.hpp>
47 #include "com/sun/star/uno/Any.hxx"
48 #include "com/sun/star/uno/Exception.hpp"
49 #include "com/sun/star/uno/Reference.hxx"
50 #include "com/sun/star/uno/RuntimeException.hpp"
51 #include "com/sun/star/uno/Sequence.hxx"
52 #include "com/sun/star/uno/XComponentContext.hpp"
53 #include "com/sun/star/uno/XInterface.hpp"
54 #include "com/sun/star/uri/UriReferenceFactory.hpp"
55 #include "com/sun/star/uri/XUriReference.hpp"
56 #include "com/sun/star/uri/XUriReferenceFactory.hpp"
57 #include "cppuhelper/exc_hlp.hxx"
58 #include "comphelper/processfactory.hxx"
59 #include "osl/diagnose.h"
60 #include "rtl/ustrbuf.hxx"
61 #include "rtl/ustring.h"
62 #include "rtl/ustring.hxx"
63 #include "sal/types.h"
64 #include <tools/debug.hxx>
65 #include <tools/inetmime.hxx>
66 #include <ucbhelper/contentbroker.hxx>
67 #include <unotools/charclass.hxx>
68 #include "rtl/instance.hxx"
70 namespace unnamed_svtools_urihelper {}
71 using namespace unnamed_svtools_urihelper;
72 // unnamed namespaces don't work well yet...
74 namespace css = com::sun::star;
75 using namespace com::sun::star;
77 //============================================================================
79 // SmartRel2Abs
81 //============================================================================
83 namespace unnamed_svtools_urihelper {
85 inline UniString toUniString(ByteString const & rString)
87 return UniString(rString, RTL_TEXTENCODING_ISO_8859_1);
90 inline UniString toUniString(UniString const & rString)
92 return rString;
95 template< typename Str >
96 inline UniString SmartRel2Abs_Impl(INetURLObject const & rTheBaseURIRef,
97 Str const & rTheRelURIRef,
98 Link const & rMaybeFileHdl,
99 bool bCheckFileExists,
100 bool bIgnoreFragment,
101 INetURLObject::EncodeMechanism
102 eEncodeMechanism,
103 INetURLObject::DecodeMechanism
104 eDecodeMechanism,
105 rtl_TextEncoding eCharset,
106 bool bRelativeNonURIs,
107 INetURLObject::FSysStyle eStyle)
109 // Backwards compatibility:
110 if (rTheRelURIRef.Len() != 0 && rTheRelURIRef.GetChar(0) == '#')
111 return toUniString(rTheRelURIRef);
113 INetURLObject aAbsURIRef;
114 if (rTheBaseURIRef.HasError())
115 aAbsURIRef.
116 SetSmartURL(rTheRelURIRef, eEncodeMechanism, eCharset, eStyle);
117 else
119 bool bWasAbsolute;
120 aAbsURIRef = rTheBaseURIRef.smartRel2Abs(rTheRelURIRef,
121 bWasAbsolute,
122 bIgnoreFragment,
123 eEncodeMechanism,
124 eCharset,
125 bRelativeNonURIs,
126 eStyle);
127 if (bCheckFileExists
128 && !bWasAbsolute
129 && (aAbsURIRef.GetProtocol() == INET_PROT_FILE
130 || aAbsURIRef.GetProtocol() == INET_PROT_VND_SUN_STAR_WFS))
132 INetURLObject aNonFileURIRef;
133 aNonFileURIRef.SetSmartURL(rTheRelURIRef,
134 eEncodeMechanism,
135 eCharset,
136 eStyle);
137 if (!aNonFileURIRef.HasError()
138 && aNonFileURIRef.GetProtocol() != INET_PROT_FILE)
140 bool bMaybeFile = false;
141 if (rMaybeFileHdl.IsSet())
143 UniString aFilePath(toUniString(rTheRelURIRef));
144 bMaybeFile = rMaybeFileHdl.Call(&aFilePath) != 0;
146 if (!bMaybeFile)
147 aAbsURIRef = aNonFileURIRef;
151 return aAbsURIRef.GetMainURL(eDecodeMechanism, eCharset);
156 UniString
157 URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
158 ByteString const & rTheRelURIRef,
159 Link const & rMaybeFileHdl,
160 bool bCheckFileExists,
161 bool bIgnoreFragment,
162 INetURLObject::EncodeMechanism eEncodeMechanism,
163 INetURLObject::DecodeMechanism eDecodeMechanism,
164 rtl_TextEncoding eCharset,
165 bool bRelativeNonURIs,
166 INetURLObject::FSysStyle eStyle)
168 return SmartRel2Abs_Impl(rTheBaseURIRef, rTheRelURIRef, rMaybeFileHdl,
169 bCheckFileExists, bIgnoreFragment,
170 eEncodeMechanism, eDecodeMechanism, eCharset,
171 bRelativeNonURIs, eStyle);
174 UniString
175 URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
176 UniString const & rTheRelURIRef,
177 Link const & rMaybeFileHdl,
178 bool bCheckFileExists,
179 bool bIgnoreFragment,
180 INetURLObject::EncodeMechanism eEncodeMechanism,
181 INetURLObject::DecodeMechanism eDecodeMechanism,
182 rtl_TextEncoding eCharset,
183 bool bRelativeNonURIs,
184 INetURLObject::FSysStyle eStyle)
186 return SmartRel2Abs_Impl(rTheBaseURIRef, rTheRelURIRef, rMaybeFileHdl,
187 bCheckFileExists, bIgnoreFragment,
188 eEncodeMechanism, eDecodeMechanism, eCharset,
189 bRelativeNonURIs, eStyle);
192 //============================================================================
194 // SetMaybeFileHdl
196 //============================================================================
198 namespace { struct MaybeFileHdl : public rtl::Static< Link, MaybeFileHdl > {}; }
200 void URIHelper::SetMaybeFileHdl(Link const & rTheMaybeFileHdl)
202 MaybeFileHdl::get() = rTheMaybeFileHdl;
205 //============================================================================
207 // GetMaybeFileHdl
209 //============================================================================
211 Link URIHelper::GetMaybeFileHdl()
213 return MaybeFileHdl::get();
216 namespace {
218 bool isAbsoluteHierarchicalUriReference(
219 css::uno::Reference< css::uri::XUriReference > const & uriReference)
221 return uriReference.is() && uriReference->isAbsolute()
222 && uriReference->isHierarchical() && !uriReference->hasRelativePath();
225 // To improve performance, assume that if for any prefix URL of a given
226 // hierarchical URL either a UCB content cannot be created, or the UCB content
227 // does not support the getCasePreservingURL command, then this will hold for
228 // any other prefix URL of the given URL, too:
229 enum Result { Success, GeneralFailure, SpecificFailure };
231 Result normalizePrefix(
232 css::uno::Reference< css::ucb::XContentProvider > const & broker,
233 rtl::OUString const & uri, rtl::OUString * normalized)
235 OSL_ASSERT(broker.is() && normalized != 0);
236 css::uno::Reference< css::ucb::XContent > content;
237 try {
238 content = broker->queryContent(
239 css::uno::Reference< css::ucb::XContentIdentifierFactory >(
240 broker, css::uno::UNO_QUERY_THROW)->createContentIdentifier(
241 uri));
242 } catch (css::ucb::IllegalIdentifierException &) {}
243 if (!content.is()) {
244 return GeneralFailure;
246 try {
247 #if OSL_DEBUG_LEVEL > 0
248 bool ok =
249 #endif
250 (css::uno::Reference< css::ucb::XCommandProcessor >(
251 content, css::uno::UNO_QUERY_THROW)->execute(
252 css::ucb::Command(
253 rtl::OUString(
254 RTL_CONSTASCII_USTRINGPARAM(
255 "getCasePreservingURL")),
256 -1, css::uno::Any()),
258 css::uno::Reference< css::ucb::XCommandEnvironment >())
259 >>= *normalized);
260 OSL_ASSERT(ok);
261 } catch (css::uno::RuntimeException &) {
262 throw;
263 } catch (css::ucb::UnsupportedCommandException &) {
264 return GeneralFailure;
265 } catch (css::uno::Exception &) {
266 return SpecificFailure;
268 return Success;
271 rtl::OUString normalize(
272 css::uno::Reference< css::ucb::XContentProvider > const & broker,
273 css::uno::Reference< css::uri::XUriReferenceFactory > const & uriFactory,
274 rtl::OUString const & uriReference)
276 // normalizePrefix can potentially fail (a typically example being a file
277 // URL that denotes a non-existing resource); in such a case, try to
278 // normalize as long a prefix of the given URL as possible (i.e., normalize
279 // all the existing directories within the path):
280 rtl::OUString normalized;
281 sal_Int32 n = uriReference.indexOf('#');
282 normalized = n == -1 ? uriReference : uriReference.copy(0, n);
283 switch (normalizePrefix(broker, normalized, &normalized)) {
284 case Success:
285 return n == -1 ? normalized : normalized + uriReference.copy(n);
286 case GeneralFailure:
287 return uriReference;
288 case SpecificFailure:
289 default:
290 break;
292 css::uno::Reference< css::uri::XUriReference > ref(
293 uriFactory->parse(uriReference));
294 if (!isAbsoluteHierarchicalUriReference(ref)) {
295 return uriReference;
297 sal_Int32 count = ref->getPathSegmentCount();
298 if (count < 2) {
299 return uriReference;
301 rtl::OUStringBuffer head(ref->getScheme());
302 head.append(static_cast< sal_Unicode >(':'));
303 if (ref->hasAuthority()) {
304 head.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
305 head.append(ref->getAuthority());
307 for (sal_Int32 i = count - 1; i > 0; --i) {
308 rtl::OUStringBuffer buf(head);
309 for (sal_Int32 j = 0; j < i; ++j) {
310 buf.append(static_cast< sal_Unicode >('/'));
311 buf.append(ref->getPathSegment(j));
313 normalized = buf.makeStringAndClear();
314 if (normalizePrefix(broker, normalized, &normalized) != SpecificFailure)
316 buf.append(normalized);
317 css::uno::Reference< css::uri::XUriReference > preRef(
318 uriFactory->parse(normalized));
319 if (!isAbsoluteHierarchicalUriReference(preRef)) {
320 // This could only happen if something is inconsistent:
321 break;
323 sal_Int32 preCount = preRef->getPathSegmentCount();
324 // normalizePrefix may have added or removed a final slash:
325 if (preCount != i) {
326 if (preCount == i - 1) {
327 buf.append(static_cast< sal_Unicode >('/'));
328 } else if (preCount - 1 == i && buf.getLength() > 0
329 && buf.charAt(buf.getLength() - 1) == '/')
331 buf.setLength(buf.getLength() - 1);
332 } else {
333 // This could only happen if something is inconsistent:
334 break;
337 for (sal_Int32 j = i; j < count; ++j) {
338 buf.append(static_cast< sal_Unicode >('/'));
339 buf.append(ref->getPathSegment(j));
341 if (ref->hasQuery()) {
342 buf.append(static_cast< sal_Unicode >('?'));
343 buf.append(ref->getQuery());
345 if (ref->hasFragment()) {
346 buf.append(static_cast< sal_Unicode >('#'));
347 buf.append(ref->getFragment());
349 return buf.makeStringAndClear();
352 return uriReference;
357 css::uno::Reference< css::uri::XUriReference >
358 URIHelper::normalizedMakeRelative(
359 css::uno::Reference< css::uno::XComponentContext > const & context,
360 rtl::OUString const & baseUriReference, rtl::OUString const & uriReference)
362 OSL_ASSERT(context.is());
363 css::uno::Reference< css::lang::XMultiComponentFactory > componentFactory(
364 context->getServiceManager());
365 if (!componentFactory.is()) {
366 throw css::uno::RuntimeException(
367 rtl::OUString(
368 RTL_CONSTASCII_USTRINGPARAM(
369 "component context has no service manager")),
370 css::uno::Reference< css::uno::XInterface >());
372 css::uno::Sequence< css::uno::Any > args(2);
373 args[0] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Local"));
374 args[1] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office"));
375 css::uno::Reference< css::ucb::XContentProvider > broker;
376 try {
377 broker = css::uno::Reference< css::ucb::XContentProvider >(
378 componentFactory->createInstanceWithArgumentsAndContext(
379 rtl::OUString(
380 RTL_CONSTASCII_USTRINGPARAM(
381 "com.sun.star.ucb.UniversalContentBroker")),
382 args, context),
383 css::uno::UNO_QUERY_THROW);
384 } catch (css::uno::RuntimeException &) {
385 throw;
386 } catch (css::uno::Exception &) {
387 css::uno::Any exception(cppu::getCaughtException());
388 throw css::lang::WrappedTargetRuntimeException(
389 rtl::OUString(
390 RTL_CONSTASCII_USTRINGPARAM(
391 "creating com.sun.star.ucb.UniversalContentBroker failed")),
392 css::uno::Reference< css::uno::XInterface >(),
393 exception);
395 css::uno::Reference< css::uri::XUriReferenceFactory > uriFactory(
396 css::uri::UriReferenceFactory::create(context));
397 return uriFactory->makeRelative(
398 uriFactory->parse(normalize(broker, uriFactory, baseUriReference)),
399 uriFactory->parse(normalize(broker, uriFactory, uriReference)), true,
400 true, false);
403 rtl::OUString URIHelper::simpleNormalizedMakeRelative(
404 rtl::OUString const & baseUriReference, rtl::OUString const & uriReference)
406 com::sun::star::uno::Reference< com::sun::star::uri::XUriReference > rel(
407 URIHelper::normalizedMakeRelative(
408 com::sun::star::uno::Reference<
409 com::sun::star::uno::XComponentContext >(
410 (com::sun::star::uno::Reference<
411 com::sun::star::beans::XPropertySet >(
412 comphelper::getProcessServiceFactory(),
413 com::sun::star::uno::UNO_QUERY_THROW)->
414 getPropertyValue(
415 rtl::OUString(
416 RTL_CONSTASCII_USTRINGPARAM("DefaultContext")))),
417 com::sun::star::uno::UNO_QUERY_THROW),
418 baseUriReference, uriReference));
419 return rel.is() ? rel->getUriReference() : uriReference;
422 //============================================================================
424 // FindFirstURLInText
426 //============================================================================
428 namespace unnamed_svtools_urihelper {
430 inline xub_StrLen nextChar(UniString const & rStr, xub_StrLen nPos)
432 return INetMIME::isHighSurrogate(rStr.GetChar(nPos))
433 && rStr.Len() - nPos >= 2
434 && INetMIME::isLowSurrogate(rStr.GetChar(nPos + 1)) ?
435 nPos + 2 : nPos + 1;
438 bool isBoundary1(CharClass const & rCharClass, UniString const & rStr,
439 xub_StrLen nPos, xub_StrLen nEnd)
441 if (nPos == nEnd)
442 return true;
443 if (rCharClass.isLetterNumeric(rStr, nPos))
444 return false;
445 switch (rStr.GetChar(nPos))
447 case '$':
448 case '%':
449 case '&':
450 case '-':
451 case '/':
452 case '@':
453 case '\\':
454 return false;
455 default:
456 return true;
460 bool isBoundary2(CharClass const & rCharClass, UniString const & rStr,
461 xub_StrLen nPos, xub_StrLen nEnd)
463 if (nPos == nEnd)
464 return true;
465 if (rCharClass.isLetterNumeric(rStr, nPos))
466 return false;
467 switch (rStr.GetChar(nPos))
469 case '!':
470 case '#':
471 case '$':
472 case '%':
473 case '&':
474 case '\'':
475 case '*':
476 case '+':
477 case '-':
478 case '/':
479 case '=':
480 case '?':
481 case '@':
482 case '^':
483 case '_':
484 case '`':
485 case '{':
486 case '|':
487 case '}':
488 case '~':
489 return false;
490 default:
491 return true;
495 bool checkWChar(CharClass const & rCharClass, UniString const & rStr,
496 xub_StrLen * pPos, xub_StrLen * pEnd, bool bBackslash = false,
497 bool bPipe = false)
499 sal_Unicode c = rStr.GetChar(*pPos);
500 if (INetMIME::isUSASCII(c))
502 static sal_uInt8 const aMap[128]
503 = { 0, 0, 0, 0, 0, 0, 0, 0,
504 0, 0, 0, 0, 0, 0, 0, 0,
505 0, 0, 0, 0, 0, 0, 0, 0,
506 0, 0, 0, 0, 0, 0, 0, 0,
507 0, 1, 0, 0, 4, 4, 4, 1, // !"#$%&'
508 1, 1, 1, 1, 1, 4, 1, 4, // ()*+,-./
509 4, 4, 4, 4, 4, 4, 4, 4, // 01234567
510 4, 4, 1, 1, 0, 1, 0, 1, // 89:;<=>?
511 4, 4, 4, 4, 4, 4, 4, 4, // @ABCDEFG
512 4, 4, 4, 4, 4, 4, 4, 4, // HIJKLMNO
513 4, 4, 4, 4, 4, 4, 4, 4, // PQRSTUVW
514 4, 4, 4, 1, 2, 1, 0, 1, // XYZ[\]^_
515 0, 4, 4, 4, 4, 4, 4, 4, // `abcdefg
516 4, 4, 4, 4, 4, 4, 4, 4, // hijklmno
517 4, 4, 4, 4, 4, 4, 4, 4, // pqrstuvw
518 4, 4, 4, 0, 3, 0, 1, 0 }; // xyz{|}~
519 switch (aMap[c])
521 default: // not uric
522 return false;
524 case 1: // uric
525 ++(*pPos);
526 return true;
528 case 2: // "\"
529 if (bBackslash)
531 *pEnd = ++(*pPos);
532 return true;
534 else
535 return false;
537 case 3: // "|"
538 if (bPipe)
540 *pEnd = ++(*pPos);
541 return true;
543 else
544 return false;
546 case 4: // alpha, digit, "$", "%", "&", "-", "/", "@" (see
547 // isBoundary1)
548 *pEnd = ++(*pPos);
549 return true;
552 else if (rCharClass.isLetterNumeric(rStr, *pPos))
554 *pEnd = *pPos = nextChar(rStr, *pPos);
555 return true;
557 else
558 return false;
561 sal_uInt32 scanDomain(UniString const & rStr, xub_StrLen * pPos,
562 xub_StrLen nEnd)
564 sal_Unicode const * pBuffer = rStr.GetBuffer();
565 sal_Unicode const * p = pBuffer + *pPos;
566 sal_uInt32 nLabels = INetURLObject::scanDomain(p, pBuffer + nEnd, false);
567 *pPos = sal::static_int_cast< xub_StrLen >(p - pBuffer);
568 return nLabels;
573 UniString
574 URIHelper::FindFirstURLInText(UniString const & rText,
575 xub_StrLen & rBegin,
576 xub_StrLen & rEnd,
577 CharClass const & rCharClass,
578 INetURLObject::EncodeMechanism eMechanism,
579 rtl_TextEncoding eCharset,
580 INetURLObject::FSysStyle eStyle)
582 if (!(rBegin <= rEnd && rEnd <= rText.Len()))
583 return UniString();
585 // Search for the first substring of [rBegin..rEnd[ that matches any of the
586 // following productions (for which the appropriate style bit is set in
587 // eStyle, if applicable).
589 // 1st Production (known scheme):
590 // \B1 <one of the known schemes, except file> ":" 1*wchar ["#" 1*wchar]
591 // \B1
593 // 2nd Production (file):
594 // \B1 "FILE:" 1*(wchar / "\" / "|") ["#" 1*wchar] \B1
596 // 3rd Production (ftp):
597 // \B1 "FTP" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
599 // 4th Production (http):
600 // \B1 "WWW" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
602 // 5th Production (mailto):
603 // \B2 local-part "@" domain \B1
605 // 6th Production (UNC file):
606 // \B1 "\\" domain "\" *(wchar / "\") \B1
608 // 7th Production (DOS file):
609 // \B1 ALPHA ":\" *(wchar / "\") \B1
611 // 8th Production (Unix-like DOS file):
612 // \B1 ALPHA ":/" *(wchar / "\") \B1
614 // The productions use the following auxiliary rules.
616 // local-part = atom *("." atom)
617 // atom = 1*(alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+"
618 // / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}"
619 // / "~")
620 // domain = label *("." label)
621 // label = alphanum [*(alphanum / "-") alphanum]
622 // alphanum = ALPHA / DIGIT
623 // wchar = <any uric character (ignoring the escaped rule), or "%", or
624 // a letter or digit (according to rCharClass)>
626 // "\B1" (boundary 1) stands for the beginning or end of the block of text,
627 // or a character that is neither (a) a letter or digit (according to
628 // rCharClass), nor (b) any of "$", "%", "&", "-", "/", "@", or "\".
629 // (FIXME: What was the rationale for this set of punctuation characters?)
631 // "\B2" (boundary 2) stands for the beginning or end of the block of text,
632 // or a character that is neither (a) a letter or digit (according to
633 // rCharClass), nor (b) any of "!", "#", "$", "%", "&", "'", "*", "+", "-",
634 // "/", "=", "?", "@", "^", "_", "`", "{", "|", "}", or "~" (i.e., an RFC
635 // 822 <atom> character, or "@" from \B1's set above).
637 // Productions 1--4, and 6--8 try to find a maximum-length match, but they
638 // stop at the first <wchar> character that is a "\B1" character which is
639 // only followed by "\B1" characters (taking "\" and "|" characters into
640 // account appropriately). Production 5 simply tries to find a maximum-
641 // length match.
643 // Productions 1--4 use the given eMechanism and eCharset. Productions 5--9
644 // use ENCODE_ALL.
646 // Productions 6--9 are only applicable if the FSYS_DOS bit is set in
647 // eStyle.
649 bool bBoundary1 = true;
650 bool bBoundary2 = true;
651 for (xub_StrLen nPos = rBegin; nPos != rEnd; nPos = nextChar(rText, nPos))
653 sal_Unicode c = rText.GetChar(nPos);
654 if (bBoundary1)
656 if (INetMIME::isAlpha(c))
658 xub_StrLen i = nPos;
659 INetProtocol eScheme
660 = INetURLObject::CompareProtocolScheme(UniString(rText, i,
661 rEnd));
662 if (eScheme == INET_PROT_FILE) // 2nd
664 while (rText.GetChar(i++) != ':') ;
665 xub_StrLen nPrefixEnd = i;
666 xub_StrLen nUriEnd = i;
667 while (i != rEnd
668 && checkWChar(rCharClass, rText, &i, &nUriEnd, true,
669 true)) ;
670 if (i != nPrefixEnd && rText.GetChar(i) == '#')
672 ++i;
673 while (i != rEnd
674 && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
676 if (nUriEnd != nPrefixEnd
677 && isBoundary1(rCharClass, rText, nUriEnd, rEnd))
679 INetURLObject aUri(UniString(rText, nPos,
680 nUriEnd - nPos),
681 INET_PROT_FILE, eMechanism, eCharset,
682 eStyle);
683 if (!aUri.HasError())
685 rBegin = nPos;
686 rEnd = nUriEnd;
687 return
688 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
692 else if (eScheme != INET_PROT_NOT_VALID) // 1st
694 while (rText.GetChar(i++) != ':') ;
695 xub_StrLen nPrefixEnd = i;
696 xub_StrLen nUriEnd = i;
697 while (i != rEnd
698 && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
699 if (i != nPrefixEnd && rText.GetChar(i) == '#')
701 ++i;
702 while (i != rEnd
703 && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
705 if (nUriEnd != nPrefixEnd
706 && (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
707 || rText.GetChar(nUriEnd) == '\\'))
709 INetURLObject aUri(UniString(rText, nPos,
710 nUriEnd - nPos),
711 INET_PROT_HTTP, eMechanism,
712 eCharset);
713 if (!aUri.HasError())
715 rBegin = nPos;
716 rEnd = nUriEnd;
717 return
718 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
723 // 3rd, 4th:
724 i = nPos;
725 sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
726 if (nLabels >= 3
727 && rText.GetChar(nPos + 3) == '.'
728 && (((rText.GetChar(nPos) == 'w'
729 || rText.GetChar(nPos) == 'W')
730 && (rText.GetChar(nPos + 1) == 'w'
731 || rText.GetChar(nPos + 1) == 'W')
732 && (rText.GetChar(nPos + 2) == 'w'
733 || rText.GetChar(nPos + 2) == 'W'))
734 || ((rText.GetChar(nPos) == 'f'
735 || rText.GetChar(nPos) == 'F')
736 && (rText.GetChar(nPos + 1) == 't'
737 || rText.GetChar(nPos + 1) == 'T')
738 && (rText.GetChar(nPos + 2) == 'p'
739 || rText.GetChar(nPos + 2) == 'P'))))
740 // (note that rText.GetChar(nPos + 3) is guaranteed to be
741 // valid)
743 xub_StrLen nUriEnd = i;
744 if (i != rEnd && rText.GetChar(i) == '/')
746 nUriEnd = ++i;
747 while (i != rEnd
748 && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
750 if (i != rEnd && rText.GetChar(i) == '#')
752 ++i;
753 while (i != rEnd
754 && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
756 if (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
757 || rText.GetChar(nUriEnd) == '\\')
759 INetURLObject aUri(UniString(rText, nPos,
760 nUriEnd - nPos),
761 INET_PROT_HTTP, eMechanism,
762 eCharset);
763 if (!aUri.HasError())
765 rBegin = nPos;
766 rEnd = nUriEnd;
767 return
768 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
773 if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 3
774 && rText.GetChar(nPos + 1) == ':'
775 && (rText.GetChar(nPos + 2) == '/'
776 || rText.GetChar(nPos + 2) == '\\')) // 7th, 8th
778 i = nPos + 3;
779 xub_StrLen nUriEnd = i;
780 while (i != rEnd
781 && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
782 if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
784 INetURLObject aUri(UniString(rText, nPos,
785 nUriEnd - nPos),
786 INET_PROT_FILE,
787 INetURLObject::ENCODE_ALL,
788 RTL_TEXTENCODING_UTF8,
789 INetURLObject::FSYS_DOS);
790 if (!aUri.HasError())
792 rBegin = nPos;
793 rEnd = nUriEnd;
794 return
795 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
800 else if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 2
801 && rText.GetChar(nPos) == '\\'
802 && rText.GetChar(nPos + 1) == '\\') // 6th
804 xub_StrLen i = nPos + 2;
805 sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
806 if (nLabels >= 1 && i != rEnd && rText.GetChar(i) == '\\')
808 xub_StrLen nUriEnd = ++i;
809 while (i != rEnd
810 && checkWChar(rCharClass, rText, &i, &nUriEnd,
811 true)) ;
812 if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
814 INetURLObject aUri(UniString(rText, nPos,
815 nUriEnd - nPos),
816 INET_PROT_FILE,
817 INetURLObject::ENCODE_ALL,
818 RTL_TEXTENCODING_UTF8,
819 INetURLObject::FSYS_DOS);
820 if (!aUri.HasError())
822 rBegin = nPos;
823 rEnd = nUriEnd;
824 return
825 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
831 if (bBoundary2 && INetMIME::isAtomChar(c)) // 5th
833 bool bDot = false;
834 for (xub_StrLen i = nPos + 1; i != rEnd; ++i)
836 sal_Unicode c2 = rText.GetChar(i);
837 if (INetMIME::isAtomChar(c2))
838 bDot = false;
839 else if (bDot)
840 break;
841 else if (c2 == '.')
842 bDot = true;
843 else
845 if (c2 == '@')
847 ++i;
848 sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
849 if (nLabels >= 1
850 && isBoundary1(rCharClass, rText, i, rEnd))
852 INetURLObject aUri(UniString(rText, nPos, i - nPos),
853 INET_PROT_MAILTO,
854 INetURLObject::ENCODE_ALL);
855 if (!aUri.HasError())
857 rBegin = nPos;
858 rEnd = i;
859 return aUri.GetMainURL(
860 INetURLObject::DECODE_TO_IURI);
864 break;
868 bBoundary1 = isBoundary1(rCharClass, rText, nPos, rEnd);
869 bBoundary2 = isBoundary2(rCharClass, rText, nPos, rEnd);
871 rBegin = rEnd;
872 return UniString();
875 //============================================================================
877 // removePassword
879 //============================================================================
881 UniString
882 URIHelper::removePassword(UniString const & rURI,
883 INetURLObject::EncodeMechanism eEncodeMechanism,
884 INetURLObject::DecodeMechanism eDecodeMechanism,
885 rtl_TextEncoding eCharset)
887 INetURLObject aObj(rURI, eEncodeMechanism, eCharset);
888 return aObj.HasError() ?
889 rURI :
890 String(aObj.GetURLNoPass(eDecodeMechanism, eCharset));
893 //============================================================================
895 // queryFSysStyle
897 //============================================================================
899 INetURLObject::FSysStyle URIHelper::queryFSysStyle(UniString const & rFileUrl,
900 bool bAddConvenienceStyles)
901 throw (uno::RuntimeException)
903 ::ucbhelper::ContentBroker const * pBroker = ::ucbhelper::ContentBroker::get();
904 uno::Reference< ucb::XContentProviderManager > xManager;
905 if (pBroker)
906 xManager = pBroker->getContentProviderManagerInterface();
907 uno::Reference< beans::XPropertySet > xProperties;
908 if (xManager.is())
909 xProperties
910 = uno::Reference< beans::XPropertySet >(
911 xManager->queryContentProvider(rFileUrl), uno::UNO_QUERY);
912 sal_Int32 nNotation = ucb::FileSystemNotation::UNKNOWN_NOTATION;
913 if (xProperties.is())
916 xProperties->getPropertyValue(rtl::OUString(
917 RTL_CONSTASCII_USTRINGPARAM(
918 "FileSystemNotation")))
919 >>= nNotation;
921 catch (beans::UnknownPropertyException const &) {}
922 catch (lang::WrappedTargetException const &) {}
924 // The following code depends on the fact that the
925 // com::sun::star::ucb::FileSystemNotation constants range from UNKNOWN to
926 // MAC, without any holes. The table below has two entries per notation,
927 // the first is used if bAddConvenienceStyles == false, while the second
928 // is used if bAddConvenienceStyles == true:
929 static INetURLObject::FSysStyle const aMap[][2]
930 = { { INetURLObject::FSysStyle(0),
931 INetURLObject::FSYS_DETECT },
932 // UNKNOWN
933 { INetURLObject::FSYS_UNX,
934 INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
935 | INetURLObject::FSYS_UNX) },
936 // UNIX
937 { INetURLObject::FSYS_DOS,
938 INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
939 | INetURLObject::FSYS_UNX
940 | INetURLObject::FSYS_DOS) },
941 // DOS
942 { INetURLObject::FSYS_MAC,
943 INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
944 | INetURLObject::FSYS_UNX
945 | INetURLObject::FSYS_MAC) } };
946 return aMap[nNotation < ucb::FileSystemNotation::UNKNOWN_NOTATION
947 || nNotation > ucb::FileSystemNotation::MAC_NOTATION ?
949 nNotation
950 - ucb::FileSystemNotation::UNKNOWN_NOTATION]
951 [bAddConvenienceStyles];