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