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