Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svl/urihelper.hxx>
21 : #include "com/sun/star/ucb/Command.hpp"
22 : #include "com/sun/star/ucb/IllegalIdentifierException.hpp"
23 : #include "com/sun/star/ucb/UniversalContentBroker.hpp"
24 : #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
25 : #include "com/sun/star/ucb/XCommandEnvironment.hpp"
26 : #include "com/sun/star/ucb/XCommandProcessor.hpp"
27 : #include "com/sun/star/ucb/XContent.hpp"
28 : #include "com/sun/star/ucb/XUniversalContentBroker.hpp"
29 : #include "com/sun/star/uno/Any.hxx"
30 : #include "com/sun/star/uno/Exception.hpp"
31 : #include "com/sun/star/uno/Reference.hxx"
32 : #include "com/sun/star/uno/RuntimeException.hpp"
33 : #include "com/sun/star/uno/XComponentContext.hpp"
34 : #include "com/sun/star/uri/UriReferenceFactory.hpp"
35 : #include "com/sun/star/uri/XUriReference.hpp"
36 : #include "com/sun/star/uri/XUriReferenceFactory.hpp"
37 : #include "comphelper/processfactory.hxx"
38 : #include "osl/diagnose.h"
39 : #include "rtl/ustrbuf.hxx"
40 : #include "rtl/ustring.h"
41 : #include "rtl/ustring.hxx"
42 : #include "sal/types.h"
43 : #include <tools/inetmime.hxx>
44 : #include <unotools/charclass.hxx>
45 : #include "rtl/instance.hxx"
46 :
47 : using namespace com::sun::star;
48 :
49 : //============================================================================
50 : //
51 : // SmartRel2Abs
52 : //
53 : //============================================================================
54 :
55 4 : OUString URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
56 : OUString const & rTheRelURIRef,
57 : Link const & rMaybeFileHdl,
58 : bool bCheckFileExists,
59 : bool bIgnoreFragment,
60 : INetURLObject::EncodeMechanism eEncodeMechanism,
61 : INetURLObject::DecodeMechanism eDecodeMechanism,
62 : rtl_TextEncoding eCharset,
63 : bool bRelativeNonURIs,
64 : INetURLObject::FSysStyle eStyle)
65 : {
66 : // Backwards compatibility:
67 4 : if (!rTheRelURIRef.isEmpty() && rTheRelURIRef[0] == '#')
68 0 : return rTheRelURIRef;
69 :
70 4 : INetURLObject aAbsURIRef;
71 4 : if (rTheBaseURIRef.HasError())
72 0 : aAbsURIRef. SetSmartURL(rTheRelURIRef, eEncodeMechanism, eCharset, eStyle);
73 : else
74 : {
75 : bool bWasAbsolute;
76 : aAbsURIRef = rTheBaseURIRef.smartRel2Abs(rTheRelURIRef,
77 : bWasAbsolute,
78 : bIgnoreFragment,
79 : eEncodeMechanism,
80 : eCharset,
81 : bRelativeNonURIs,
82 4 : eStyle);
83 4 : if (bCheckFileExists
84 0 : && !bWasAbsolute
85 0 : && (aAbsURIRef.GetProtocol() == INET_PROT_FILE))
86 : {
87 0 : INetURLObject aNonFileURIRef;
88 : aNonFileURIRef.SetSmartURL(rTheRelURIRef,
89 : eEncodeMechanism,
90 : eCharset,
91 0 : eStyle);
92 0 : if (!aNonFileURIRef.HasError()
93 0 : && aNonFileURIRef.GetProtocol() != INET_PROT_FILE)
94 : {
95 0 : bool bMaybeFile = false;
96 0 : if (rMaybeFileHdl.IsSet())
97 : {
98 0 : OUString aFilePath(rTheRelURIRef);
99 0 : bMaybeFile = rMaybeFileHdl.Call(&aFilePath) != 0;
100 : }
101 0 : if (!bMaybeFile)
102 0 : aAbsURIRef = aNonFileURIRef;
103 0 : }
104 : }
105 : }
106 4 : return aAbsURIRef.GetMainURL(eDecodeMechanism, eCharset);
107 : }
108 :
109 : //============================================================================
110 : //
111 : // SetMaybeFileHdl
112 : //
113 : //============================================================================
114 :
115 : namespace { struct MaybeFileHdl : public rtl::Static< Link, MaybeFileHdl > {}; }
116 :
117 41 : void URIHelper::SetMaybeFileHdl(Link const & rTheMaybeFileHdl)
118 : {
119 41 : MaybeFileHdl::get() = rTheMaybeFileHdl;
120 41 : }
121 :
122 : //============================================================================
123 : //
124 : // GetMaybeFileHdl
125 : //
126 : //============================================================================
127 :
128 0 : Link URIHelper::GetMaybeFileHdl()
129 : {
130 0 : return MaybeFileHdl::get();
131 : }
132 :
133 : namespace {
134 :
135 32 : bool isAbsoluteHierarchicalUriReference(
136 : css::uno::Reference< css::uri::XUriReference > const & uriReference)
137 : {
138 64 : return uriReference.is() && uriReference->isAbsolute()
139 64 : && uriReference->isHierarchical() && !uriReference->hasRelativePath();
140 : }
141 :
142 : // To improve performance, assume that if for any prefix URL of a given
143 : // hierarchical URL either a UCB content cannot be created, or the UCB content
144 : // does not support the getCasePreservingURL command, then this will hold for
145 : // any other prefix URL of the given URL, too:
146 : enum Result { Success, GeneralFailure, SpecificFailure };
147 :
148 64 : Result normalizePrefix( css::uno::Reference< css::ucb::XUniversalContentBroker > const & broker,
149 : OUString const & uri, OUString * normalized)
150 : {
151 : OSL_ASSERT(broker.is() && normalized != 0);
152 64 : css::uno::Reference< css::ucb::XContent > content;
153 : try {
154 64 : content = broker->queryContent(broker->createContentIdentifier(uri));
155 0 : } catch (css::ucb::IllegalIdentifierException &) {}
156 64 : if (!content.is()) {
157 32 : return GeneralFailure;
158 : }
159 : try {
160 : #if OSL_DEBUG_LEVEL > 0
161 : bool ok =
162 : #endif
163 : (css::uno::Reference< css::ucb::XCommandProcessor >(
164 64 : content, css::uno::UNO_QUERY_THROW)->execute(
165 : css::ucb::Command("getCasePreservingURL",
166 : -1, css::uno::Any()),
167 : 0,
168 32 : css::uno::Reference< css::ucb::XCommandEnvironment >())
169 48 : >>= *normalized);
170 : OSL_ASSERT(ok);
171 0 : } catch (css::uno::RuntimeException &) {
172 0 : throw;
173 0 : } catch (css::ucb::UnsupportedCommandException &) {
174 0 : return GeneralFailure;
175 32 : } catch (css::uno::Exception &) {
176 16 : return SpecificFailure;
177 : }
178 16 : return Success;
179 : }
180 :
181 48 : OUString normalize(
182 : css::uno::Reference< css::ucb::XUniversalContentBroker > const & broker,
183 : css::uno::Reference< css::uri::XUriReferenceFactory > const & uriFactory,
184 : OUString const & uriReference)
185 : {
186 : // normalizePrefix can potentially fail (a typically example being a file
187 : // URL that denotes a non-existing resource); in such a case, try to
188 : // normalize as long a prefix of the given URL as possible (i.e., normalize
189 : // all the existing directories within the path):
190 48 : OUString normalized;
191 48 : sal_Int32 n = uriReference.indexOf('#');
192 48 : normalized = n == -1 ? uriReference : uriReference.copy(0, n);
193 48 : switch (normalizePrefix(broker, normalized, &normalized)) {
194 : case Success:
195 0 : return n == -1 ? normalized : normalized + uriReference.copy(n);
196 : case GeneralFailure:
197 32 : return uriReference;
198 : case SpecificFailure:
199 : default:
200 16 : break;
201 : }
202 : css::uno::Reference< css::uri::XUriReference > ref(
203 16 : uriFactory->parse(uriReference));
204 16 : if (!isAbsoluteHierarchicalUriReference(ref)) {
205 0 : return uriReference;
206 : }
207 16 : sal_Int32 count = ref->getPathSegmentCount();
208 16 : if (count < 2) {
209 0 : return uriReference;
210 : }
211 16 : OUStringBuffer head(ref->getScheme());
212 16 : head.append(static_cast< sal_Unicode >(':'));
213 16 : if (ref->hasAuthority()) {
214 0 : head.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
215 0 : head.append(ref->getAuthority());
216 : }
217 16 : for (sal_Int32 i = count - 1; i > 0; --i) {
218 16 : OUStringBuffer buf(head);
219 40 : for (sal_Int32 j = 0; j < i; ++j) {
220 24 : buf.append(static_cast< sal_Unicode >('/'));
221 24 : buf.append(ref->getPathSegment(j));
222 : }
223 16 : normalized = buf.makeStringAndClear();
224 16 : if (normalizePrefix(broker, normalized, &normalized) != SpecificFailure)
225 : {
226 16 : buf.append(normalized);
227 : css::uno::Reference< css::uri::XUriReference > preRef(
228 16 : uriFactory->parse(normalized));
229 16 : if (!isAbsoluteHierarchicalUriReference(preRef)) {
230 : // This could only happen if something is inconsistent:
231 : break;
232 : }
233 16 : sal_Int32 preCount = preRef->getPathSegmentCount();
234 : // normalizePrefix may have added or removed a final slash:
235 16 : if (preCount != i) {
236 6 : if (preCount == i - 1) {
237 2 : buf.append(static_cast< sal_Unicode >('/'));
238 8 : } else if (preCount - 1 == i && buf.getLength() > 0
239 4 : && buf[buf.getLength() - 1] == '/')
240 : {
241 4 : buf.setLength(buf.getLength() - 1);
242 : } else {
243 : // This could only happen if something is inconsistent:
244 : break;
245 : }
246 : }
247 32 : for (sal_Int32 j = i; j < count; ++j) {
248 16 : buf.append(static_cast< sal_Unicode >('/'));
249 16 : buf.append(ref->getPathSegment(j));
250 : }
251 16 : if (ref->hasQuery()) {
252 0 : buf.append(static_cast< sal_Unicode >('?'));
253 0 : buf.append(ref->getQuery());
254 : }
255 16 : if (ref->hasFragment()) {
256 2 : buf.append(static_cast< sal_Unicode >('#'));
257 2 : buf.append(ref->getFragment());
258 : }
259 16 : return buf.makeStringAndClear();
260 : }
261 16 : }
262 0 : return uriReference;
263 : }
264 :
265 : }
266 :
267 : css::uno::Reference< css::uri::XUriReference >
268 24 : URIHelper::normalizedMakeRelative(
269 : css::uno::Reference< css::uno::XComponentContext > const & context,
270 : OUString const & baseUriReference, OUString const & uriReference)
271 : {
272 : OSL_ASSERT(context.is());
273 : css::uno::Reference< css::ucb::XUniversalContentBroker > broker(
274 24 : css::ucb::UniversalContentBroker::create(context));
275 : css::uno::Reference< css::uri::XUriReferenceFactory > uriFactory(
276 24 : css::uri::UriReferenceFactory::create(context));
277 24 : return uriFactory->makeRelative(
278 24 : uriFactory->parse(normalize(broker, uriFactory, baseUriReference)),
279 24 : uriFactory->parse(normalize(broker, uriFactory, uriReference)), true,
280 72 : true, false);
281 : }
282 :
283 0 : OUString URIHelper::simpleNormalizedMakeRelative(
284 : OUString const & baseUriReference, OUString const & uriReference)
285 : {
286 : com::sun::star::uno::Reference< com::sun::star::uri::XUriReference > rel(
287 : URIHelper::normalizedMakeRelative(
288 : comphelper::getProcessComponentContext(), baseUriReference,
289 0 : uriReference));
290 0 : return rel.is() ? rel->getUriReference() : uriReference;
291 : }
292 :
293 : //============================================================================
294 : //
295 : // FindFirstURLInText
296 : //
297 : //============================================================================
298 :
299 : namespace {
300 :
301 1456 : inline sal_Int32 nextChar(OUString const & rStr, sal_Int32 nPos)
302 : {
303 1456 : return INetMIME::isHighSurrogate(rStr[nPos])
304 0 : && rStr.getLength() - nPos >= 2
305 0 : && INetMIME::isLowSurrogate(rStr[nPos + 1]) ?
306 1456 : nPos + 2 : nPos + 1;
307 : }
308 :
309 1506 : bool isBoundary1(CharClass const & rCharClass, OUString const & rStr,
310 : sal_Int32 nPos, sal_Int32 nEnd)
311 : {
312 1506 : if (nPos == nEnd)
313 16 : return true;
314 1490 : if (rCharClass.isLetterNumeric(rStr, nPos))
315 1166 : return false;
316 324 : switch (rStr[nPos])
317 : {
318 : case '$':
319 : case '%':
320 : case '&':
321 : case '-':
322 : case '/':
323 : case '@':
324 : case '\\':
325 34 : return false;
326 : default:
327 290 : return true;
328 : }
329 : }
330 :
331 1456 : bool isBoundary2(CharClass const & rCharClass, OUString const & rStr,
332 : sal_Int32 nPos, sal_Int32 nEnd)
333 : {
334 1456 : if (nPos == nEnd)
335 0 : return true;
336 1456 : if (rCharClass.isLetterNumeric(rStr, nPos))
337 1166 : return false;
338 290 : switch (rStr[nPos])
339 : {
340 : case '!':
341 : case '#':
342 : case '$':
343 : case '%':
344 : case '&':
345 : case '\'':
346 : case '*':
347 : case '+':
348 : case '-':
349 : case '/':
350 : case '=':
351 : case '?':
352 : case '@':
353 : case '^':
354 : case '_':
355 : case '`':
356 : case '{':
357 : case '|':
358 : case '}':
359 : case '~':
360 26 : return false;
361 : default:
362 264 : return true;
363 : }
364 : }
365 :
366 442 : bool checkWChar(CharClass const & rCharClass, OUString const & rStr,
367 : sal_Int32 * pPos, sal_Int32 * pEnd, bool bBackslash = false,
368 : bool bPipe = false)
369 : {
370 442 : sal_Unicode c = rStr[*pPos];
371 442 : if (INetMIME::isUSASCII(c))
372 : {
373 : static sal_uInt8 const aMap[128]
374 : = { 0, 0, 0, 0, 0, 0, 0, 0,
375 : 0, 0, 0, 0, 0, 0, 0, 0,
376 : 0, 0, 0, 0, 0, 0, 0, 0,
377 : 0, 0, 0, 0, 0, 0, 0, 0,
378 : 0, 1, 0, 0, 4, 4, 4, 1, // !"#$%&'
379 : 1, 1, 1, 1, 1, 4, 1, 4, // ()*+,-./
380 : 4, 4, 4, 4, 4, 4, 4, 4, // 01234567
381 : 4, 4, 1, 1, 0, 1, 0, 1, // 89:;<=>?
382 : 4, 4, 4, 4, 4, 4, 4, 4, // @ABCDEFG
383 : 4, 4, 4, 4, 4, 4, 4, 4, // HIJKLMNO
384 : 4, 4, 4, 4, 4, 4, 4, 4, // PQRSTUVW
385 : 4, 4, 4, 1, 2, 1, 0, 1, // XYZ[\]^_
386 : 0, 4, 4, 4, 4, 4, 4, 4, // `abcdefg
387 : 4, 4, 4, 4, 4, 4, 4, 4, // hijklmno
388 : 4, 4, 4, 4, 4, 4, 4, 4, // pqrstuvw
389 : 4, 4, 4, 0, 3, 0, 1, 0 }; // xyz{|}~
390 442 : switch (aMap[c])
391 : {
392 : default: // not uric
393 8 : return false;
394 :
395 : case 1: // uric
396 82 : ++(*pPos);
397 82 : return true;
398 :
399 : case 2: // "\"
400 0 : if (bBackslash)
401 : {
402 0 : *pEnd = ++(*pPos);
403 0 : return true;
404 : }
405 : else
406 0 : return false;
407 :
408 : case 3: // "|"
409 10 : if (bPipe)
410 : {
411 10 : *pEnd = ++(*pPos);
412 10 : return true;
413 : }
414 : else
415 0 : return false;
416 :
417 : case 4: // alpha, digit, "$", "%", "&", "-", "/", "@" (see
418 : // isBoundary1)
419 342 : *pEnd = ++(*pPos);
420 342 : return true;
421 : }
422 : }
423 0 : else if (rCharClass.isLetterNumeric(rStr, *pPos))
424 : {
425 0 : *pEnd = *pPos = nextChar(rStr, *pPos);
426 0 : return true;
427 : }
428 : else
429 0 : return false;
430 : }
431 :
432 262 : sal_uInt32 scanDomain(OUString const & rStr, sal_Int32 * pPos,
433 : sal_Int32 nEnd)
434 : {
435 262 : sal_Unicode const * pBuffer = rStr.getStr();
436 262 : sal_Unicode const * p = pBuffer + *pPos;
437 262 : sal_uInt32 nLabels = INetURLObject::scanDomain(p, pBuffer + nEnd, false);
438 262 : *pPos = sal::static_int_cast< sal_Int32 >(p - pBuffer);
439 262 : return nLabels;
440 : }
441 :
442 : }
443 :
444 142 : OUString URIHelper::FindFirstURLInText(OUString const & rText,
445 : sal_Int32 & rBegin,
446 : sal_Int32 & rEnd,
447 : CharClass const & rCharClass,
448 : INetURLObject::EncodeMechanism eMechanism,
449 : rtl_TextEncoding eCharset,
450 : INetURLObject::FSysStyle eStyle)
451 : {
452 142 : if (!(rBegin <= rEnd && rEnd <= rText.getLength()))
453 0 : return OUString();
454 :
455 : // Search for the first substring of [rBegin..rEnd[ that matches any of the
456 : // following productions (for which the appropriate style bit is set in
457 : // eStyle, if applicable).
458 : //
459 : // 1st Production (known scheme):
460 : // \B1 <one of the known schemes, except file> ":" 1*wchar ["#" 1*wchar]
461 : // \B1
462 : //
463 : // 2nd Production (file):
464 : // \B1 "FILE:" 1*(wchar / "\" / "|") ["#" 1*wchar] \B1
465 : //
466 : // 3rd Production (ftp):
467 : // \B1 "FTP" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
468 : //
469 : // 4th Production (http):
470 : // \B1 "WWW" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
471 : //
472 : // 5th Production (mailto):
473 : // \B2 local-part "@" domain \B1
474 : //
475 : // 6th Production (UNC file):
476 : // \B1 "\\" domain "\" *(wchar / "\") \B1
477 : //
478 : // 7th Production (DOS file):
479 : // \B1 ALPHA ":\" *(wchar / "\") \B1
480 : //
481 : // 8th Production (Unix-like DOS file):
482 : // \B1 ALPHA ":/" *(wchar / "\") \B1
483 : //
484 : // The productions use the following auxiliary rules.
485 : //
486 : // local-part = atom *("." atom)
487 : // atom = 1*(alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+"
488 : // / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}"
489 : // / "~")
490 : // domain = label *("." label)
491 : // label = alphanum [*(alphanum / "-") alphanum]
492 : // alphanum = ALPHA / DIGIT
493 : // wchar = <any uric character (ignoring the escaped rule), or "%", or
494 : // a letter or digit (according to rCharClass)>
495 : //
496 : // "\B1" (boundary 1) stands for the beginning or end of the block of text,
497 : // or a character that is neither (a) a letter or digit (according to
498 : // rCharClass), nor (b) any of "$", "%", "&", "-", "/", "@", or "\".
499 : // (FIXME: What was the rationale for this set of punctuation characters?)
500 : //
501 : // "\B2" (boundary 2) stands for the beginning or end of the block of text,
502 : // or a character that is neither (a) a letter or digit (according to
503 : // rCharClass), nor (b) any of "!", "#", "$", "%", "&", "'", "*", "+", "-",
504 : // "/", "=", "?", "@", "^", "_", "`", "{", "|", "}", or "~" (i.e., an RFC
505 : // 822 <atom> character, or "@" from \B1's set above).
506 : //
507 : // Productions 1--4, and 6--8 try to find a maximum-length match, but they
508 : // stop at the first <wchar> character that is a "\B1" character which is
509 : // only followed by "\B1" characters (taking "\" and "|" characters into
510 : // account appropriately). Production 5 simply tries to find a maximum-
511 : // length match.
512 : //
513 : // Productions 1--4 use the given eMechanism and eCharset. Productions 5--9
514 : // use ENCODE_ALL.
515 : //
516 : // Productions 6--9 are only applicable if the FSYS_DOS bit is set in
517 : // eStyle.
518 :
519 142 : bool bBoundary1 = true;
520 142 : bool bBoundary2 = true;
521 1598 : for (sal_Int32 nPos = rBegin; nPos != rEnd; nPos = nextChar(rText, nPos))
522 : {
523 1496 : sal_Unicode c = rText[nPos];
524 1496 : if (bBoundary1)
525 : {
526 316 : if (INetMIME::isAlpha(c))
527 : {
528 260 : sal_Int32 i = nPos;
529 260 : INetProtocol eScheme = INetURLObject::CompareProtocolScheme(rText.copy(i, rEnd - i));
530 260 : if (eScheme == INET_PROT_FILE) // 2nd
531 : {
532 10 : while (rText[i++] != ':') ;
533 10 : sal_Int32 nPrefixEnd = i;
534 10 : sal_Int32 nUriEnd = i;
535 80 : while (i != rEnd
536 : && checkWChar(rCharClass, rText, &i, &nUriEnd, true,
537 70 : true)) ;
538 10 : if (i != nPrefixEnd && rText[i] == (sal_Unicode)'#')
539 : {
540 4 : ++i;
541 20 : while (i != rEnd
542 16 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
543 : }
544 18 : if (nUriEnd != nPrefixEnd
545 8 : && isBoundary1(rCharClass, rText, nUriEnd, rEnd))
546 : {
547 : INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
548 : INET_PROT_FILE, eMechanism, eCharset,
549 8 : eStyle);
550 8 : if (!aUri.HasError())
551 : {
552 8 : rBegin = nPos;
553 8 : rEnd = nUriEnd;
554 : return
555 8 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
556 8 : }
557 : }
558 : }
559 250 : else if (eScheme != INET_PROT_NOT_VALID) // 1st
560 : {
561 98 : while (rText[i++] != ':') ;
562 98 : sal_Int32 nPrefixEnd = i;
563 98 : sal_Int32 nUriEnd = i;
564 370 : while (i != rEnd
565 272 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
566 98 : if (i != nPrefixEnd && rText[i] == '#')
567 : {
568 0 : ++i;
569 0 : while (i != rEnd
570 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
571 : }
572 108 : if (nUriEnd != nPrefixEnd
573 10 : && (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
574 0 : || rText[nUriEnd] == '\\'))
575 : {
576 : INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
577 : INET_PROT_HTTP, eMechanism,
578 10 : eCharset);
579 10 : if (!aUri.HasError())
580 : {
581 8 : rBegin = nPos;
582 8 : rEnd = nUriEnd;
583 : return
584 8 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
585 10 : }
586 : }
587 : }
588 :
589 : // 3rd, 4th:
590 244 : i = nPos;
591 244 : sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
592 494 : if (nLabels >= 3
593 52 : && rText[nPos + 3] == '.'
594 48 : && (((rText[nPos] == 'w'
595 44 : || rText[nPos] == 'W')
596 4 : && (rText[nPos + 1] == 'w'
597 2 : || rText[nPos + 1] == 'W')
598 4 : && (rText[nPos + 2] == 'w'
599 2 : || rText[nPos + 2] == 'W'))
600 44 : || ((rText[nPos] == 'f'
601 42 : || rText[nPos] == 'F')
602 4 : && (rText[nPos + 1] == 't'
603 0 : || rText[nPos + 1] == 'T')
604 4 : && (rText[nPos + 2] == 'p'
605 0 : || rText[nPos + 2] == 'P'))))
606 : // (note that rText.GetChar(nPos + 3) is guaranteed to be
607 : // valid)
608 : {
609 8 : sal_Int32 nUriEnd = i;
610 8 : if (i != rEnd && rText[i] == '/')
611 : {
612 4 : nUriEnd = ++i;
613 28 : while (i != rEnd
614 24 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
615 : }
616 8 : if (i != rEnd && rText[i] == '#')
617 : {
618 0 : ++i;
619 0 : while (i != rEnd
620 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
621 : }
622 8 : if (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
623 0 : || rText[nUriEnd] == '\\')
624 : {
625 : INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
626 : INET_PROT_HTTP, eMechanism,
627 8 : eCharset);
628 8 : if (!aUri.HasError())
629 : {
630 8 : rBegin = nPos;
631 8 : rEnd = nUriEnd;
632 : return
633 8 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
634 8 : }
635 : }
636 : }
637 :
638 478 : if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 3
639 234 : && rText[nPos + 1] == ':'
640 6 : && (rText[nPos + 2] == '/'
641 2 : || rText[nPos + 2] == '\\')) // 7th, 8th
642 : {
643 6 : i = nPos + 3;
644 6 : sal_Int32 nUriEnd = i;
645 44 : while (i != rEnd
646 38 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
647 6 : if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
648 : {
649 : INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
650 : INET_PROT_FILE,
651 : INetURLObject::ENCODE_ALL,
652 : RTL_TEXTENCODING_UTF8,
653 6 : INetURLObject::FSYS_DOS);
654 6 : if (!aUri.HasError())
655 : {
656 6 : rBegin = nPos;
657 6 : rEnd = nUriEnd;
658 : return
659 6 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
660 6 : }
661 : }
662 : }
663 : }
664 110 : else if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 2
665 48 : && rText[nPos] == '\\'
666 6 : && rText[nPos + 1] == '\\') // 6th
667 : {
668 2 : sal_Int32 i = nPos + 2;
669 2 : sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
670 2 : if (nLabels >= 1 && i != rEnd && rText[i] == '\\')
671 : {
672 2 : sal_Int32 nUriEnd = ++i;
673 24 : while (i != rEnd
674 : && checkWChar(rCharClass, rText, &i, &nUriEnd,
675 22 : true)) ;
676 2 : if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
677 : {
678 : INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
679 : INET_PROT_FILE,
680 : INetURLObject::ENCODE_ALL,
681 : RTL_TEXTENCODING_UTF8,
682 2 : INetURLObject::FSYS_DOS);
683 2 : if (!aUri.HasError())
684 : {
685 2 : rBegin = nPos;
686 2 : rEnd = nUriEnd;
687 : return
688 2 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
689 2 : }
690 : }
691 : }
692 : }
693 : }
694 1464 : if (bBoundary2 && INetMIME::isAtomChar(c)) // 5th
695 : {
696 258 : bool bDot = false;
697 2156 : for (sal_Int32 i = nPos + 1; i != rEnd; ++i)
698 : {
699 2128 : sal_Unicode c2 = rText[i];
700 2128 : if (INetMIME::isAtomChar(c2))
701 1694 : bDot = false;
702 434 : else if (bDot)
703 12 : break;
704 422 : else if (c2 == '.')
705 204 : bDot = true;
706 : else
707 : {
708 218 : if (c2 == '@')
709 : {
710 16 : ++i;
711 16 : sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
712 32 : if (nLabels >= 1
713 16 : && isBoundary1(rCharClass, rText, i, rEnd))
714 : {
715 : INetURLObject aUri(rText.copy(nPos, i - nPos),
716 : INET_PROT_MAILTO,
717 8 : INetURLObject::ENCODE_ALL);
718 8 : if (!aUri.HasError())
719 : {
720 8 : rBegin = nPos;
721 8 : rEnd = i;
722 : return aUri.GetMainURL(
723 8 : INetURLObject::DECODE_TO_IURI);
724 8 : }
725 : }
726 : }
727 210 : break;
728 : }
729 : }
730 : }
731 1456 : bBoundary1 = isBoundary1(rCharClass, rText, nPos, rEnd);
732 1456 : bBoundary2 = isBoundary2(rCharClass, rText, nPos, rEnd);
733 : }
734 102 : rBegin = rEnd;
735 102 : return OUString();
736 : }
737 :
738 : //============================================================================
739 : //
740 : // removePassword
741 : //
742 : //============================================================================
743 :
744 0 : OUString URIHelper::removePassword(OUString const & rURI,
745 : INetURLObject::EncodeMechanism eEncodeMechanism,
746 : INetURLObject::DecodeMechanism eDecodeMechanism,
747 : rtl_TextEncoding eCharset)
748 : {
749 0 : INetURLObject aObj(rURI, eEncodeMechanism, eCharset);
750 0 : return aObj.HasError() ?
751 : rURI :
752 0 : aObj.GetURLNoPass(eDecodeMechanism, eCharset);
753 : }
754 :
755 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|