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