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 2 : 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 2 : if (!rTheRelURIRef.isEmpty() && rTheRelURIRef[0] == '#')
68 0 : return rTheRelURIRef;
69 :
70 2 : INetURLObject aAbsURIRef;
71 2 : 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 2 : eStyle);
83 2 : 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 2 : 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 9 : void URIHelper::SetMaybeFileHdl(Link const & rTheMaybeFileHdl)
118 : {
119 9 : MaybeFileHdl::get() = rTheMaybeFileHdl;
120 9 : }
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 0 : bool isAbsoluteHierarchicalUriReference(
136 : css::uno::Reference< css::uri::XUriReference > const & uriReference)
137 : {
138 0 : return uriReference.is() && uriReference->isAbsolute()
139 0 : && 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 0 : 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 0 : css::uno::Reference< css::ucb::XContent > content;
153 : try {
154 0 : content = broker->queryContent(broker->createContentIdentifier(uri));
155 0 : } catch (css::ucb::IllegalIdentifierException &) {}
156 0 : if (!content.is()) {
157 0 : return GeneralFailure;
158 : }
159 : try {
160 : #if OSL_DEBUG_LEVEL > 0
161 : bool ok =
162 : #endif
163 : (css::uno::Reference< css::ucb::XCommandProcessor >(
164 0 : content, css::uno::UNO_QUERY_THROW)->execute(
165 : css::ucb::Command("getCasePreservingURL",
166 : -1, css::uno::Any()),
167 : 0,
168 0 : css::uno::Reference< css::ucb::XCommandEnvironment >())
169 0 : >>= *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 0 : } catch (css::uno::Exception &) {
176 0 : return SpecificFailure;
177 : }
178 0 : return Success;
179 : }
180 :
181 0 : 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 0 : OUString normalized;
191 0 : sal_Int32 n = uriReference.indexOf('#');
192 0 : normalized = n == -1 ? uriReference : uriReference.copy(0, n);
193 0 : switch (normalizePrefix(broker, normalized, &normalized)) {
194 : case Success:
195 0 : return n == -1 ? normalized : normalized + uriReference.copy(n);
196 : case GeneralFailure:
197 0 : return uriReference;
198 : case SpecificFailure:
199 : default:
200 0 : break;
201 : }
202 : css::uno::Reference< css::uri::XUriReference > ref(
203 0 : uriFactory->parse(uriReference));
204 0 : if (!isAbsoluteHierarchicalUriReference(ref)) {
205 0 : return uriReference;
206 : }
207 0 : sal_Int32 count = ref->getPathSegmentCount();
208 0 : if (count < 2) {
209 0 : return uriReference;
210 : }
211 0 : OUStringBuffer head(ref->getScheme());
212 0 : head.append(static_cast< sal_Unicode >(':'));
213 0 : if (ref->hasAuthority()) {
214 0 : head.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
215 0 : head.append(ref->getAuthority());
216 : }
217 0 : for (sal_Int32 i = count - 1; i > 0; --i) {
218 0 : OUStringBuffer buf(head);
219 0 : for (sal_Int32 j = 0; j < i; ++j) {
220 0 : buf.append(static_cast< sal_Unicode >('/'));
221 0 : buf.append(ref->getPathSegment(j));
222 : }
223 0 : normalized = buf.makeStringAndClear();
224 0 : if (normalizePrefix(broker, normalized, &normalized) != SpecificFailure)
225 : {
226 0 : buf.append(normalized);
227 : css::uno::Reference< css::uri::XUriReference > preRef(
228 0 : uriFactory->parse(normalized));
229 0 : if (!isAbsoluteHierarchicalUriReference(preRef)) {
230 : // This could only happen if something is inconsistent:
231 : break;
232 : }
233 0 : sal_Int32 preCount = preRef->getPathSegmentCount();
234 : // normalizePrefix may have added or removed a final slash:
235 0 : if (preCount != i) {
236 0 : if (preCount == i - 1) {
237 0 : buf.append(static_cast< sal_Unicode >('/'));
238 0 : } else if (preCount - 1 == i && buf.getLength() > 0
239 0 : && buf[buf.getLength() - 1] == '/')
240 : {
241 0 : buf.setLength(buf.getLength() - 1);
242 : } else {
243 : // This could only happen if something is inconsistent:
244 : break;
245 : }
246 : }
247 0 : for (sal_Int32 j = i; j < count; ++j) {
248 0 : buf.append(static_cast< sal_Unicode >('/'));
249 0 : buf.append(ref->getPathSegment(j));
250 : }
251 0 : if (ref->hasQuery()) {
252 0 : buf.append(static_cast< sal_Unicode >('?'));
253 0 : buf.append(ref->getQuery());
254 : }
255 0 : if (ref->hasFragment()) {
256 0 : buf.append(static_cast< sal_Unicode >('#'));
257 0 : buf.append(ref->getFragment());
258 : }
259 0 : return buf.makeStringAndClear();
260 : }
261 0 : }
262 0 : return uriReference;
263 : }
264 :
265 : }
266 :
267 : css::uno::Reference< css::uri::XUriReference >
268 0 : 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 0 : css::ucb::UniversalContentBroker::create(context));
275 : css::uno::Reference< css::uri::XUriReferenceFactory > uriFactory(
276 0 : css::uri::UriReferenceFactory::create(context));
277 0 : return uriFactory->makeRelative(
278 0 : uriFactory->parse(normalize(broker, uriFactory, baseUriReference)),
279 0 : uriFactory->parse(normalize(broker, uriFactory, uriReference)), true,
280 0 : 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 0 : inline sal_Int32 nextChar(OUString const & rStr, sal_Int32 nPos)
302 : {
303 0 : return INetMIME::isHighSurrogate(rStr[nPos])
304 0 : && rStr.getLength() - nPos >= 2
305 0 : && INetMIME::isLowSurrogate(rStr[nPos + 1]) ?
306 0 : nPos + 2 : nPos + 1;
307 : }
308 :
309 0 : bool isBoundary1(CharClass const & rCharClass, OUString const & rStr,
310 : sal_Int32 nPos, sal_Int32 nEnd)
311 : {
312 0 : if (nPos == nEnd)
313 0 : return true;
314 0 : if (rCharClass.isLetterNumeric(rStr, nPos))
315 0 : return false;
316 0 : switch (rStr[nPos])
317 : {
318 : case '$':
319 : case '%':
320 : case '&':
321 : case '-':
322 : case '/':
323 : case '@':
324 : case '\\':
325 0 : return false;
326 : default:
327 0 : return true;
328 : }
329 : }
330 :
331 0 : bool isBoundary2(CharClass const & rCharClass, OUString const & rStr,
332 : sal_Int32 nPos, sal_Int32 nEnd)
333 : {
334 0 : if (nPos == nEnd)
335 0 : return true;
336 0 : if (rCharClass.isLetterNumeric(rStr, nPos))
337 0 : return false;
338 0 : 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 0 : return false;
361 : default:
362 0 : return true;
363 : }
364 : }
365 :
366 0 : bool checkWChar(CharClass const & rCharClass, OUString const & rStr,
367 : sal_Int32 * pPos, sal_Int32 * pEnd, bool bBackslash = false,
368 : bool bPipe = false)
369 : {
370 0 : sal_Unicode c = rStr[*pPos];
371 0 : 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 0 : switch (aMap[c])
391 : {
392 : default: // not uric
393 0 : return false;
394 :
395 : case 1: // uric
396 0 : ++(*pPos);
397 0 : 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 0 : if (bPipe)
410 : {
411 0 : *pEnd = ++(*pPos);
412 0 : return true;
413 : }
414 : else
415 0 : return false;
416 :
417 : case 4: // alpha, digit, "$", "%", "&", "-", "/", "@" (see
418 : // isBoundary1)
419 0 : *pEnd = ++(*pPos);
420 0 : 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 0 : sal_uInt32 scanDomain(OUString const & rStr, sal_Int32 * pPos,
433 : sal_Int32 nEnd)
434 : {
435 0 : sal_Unicode const * pBuffer = rStr.getStr();
436 0 : sal_Unicode const * p = pBuffer + *pPos;
437 0 : sal_uInt32 nLabels = INetURLObject::scanDomain(p, pBuffer + nEnd, false);
438 0 : *pPos = sal::static_int_cast< sal_Int32 >(p - pBuffer);
439 0 : return nLabels;
440 : }
441 :
442 : }
443 :
444 0 : 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 0 : 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 0 : bool bBoundary1 = true;
520 0 : bool bBoundary2 = true;
521 0 : for (sal_Int32 nPos = rBegin; nPos != rEnd; nPos = nextChar(rText, nPos))
522 : {
523 0 : sal_Unicode c = rText[nPos];
524 0 : if (bBoundary1)
525 : {
526 0 : if (INetMIME::isAlpha(c))
527 : {
528 0 : sal_Int32 i = nPos;
529 0 : INetProtocol eScheme = INetURLObject::CompareProtocolScheme(rText.copy(i, rEnd - i));
530 0 : if (eScheme == INET_PROT_FILE) // 2nd
531 : {
532 0 : while (rText[i++] != ':') ;
533 0 : sal_Int32 nPrefixEnd = i;
534 0 : sal_Int32 nUriEnd = i;
535 0 : while (i != rEnd
536 : && checkWChar(rCharClass, rText, &i, &nUriEnd, true,
537 0 : true)) ;
538 0 : if (i != nPrefixEnd && rText[i] == (sal_Unicode)'#')
539 : {
540 0 : ++i;
541 0 : while (i != rEnd
542 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
543 : }
544 0 : if (nUriEnd != nPrefixEnd
545 0 : && isBoundary1(rCharClass, rText, nUriEnd, rEnd))
546 : {
547 : INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
548 : INET_PROT_FILE, eMechanism, eCharset,
549 0 : eStyle);
550 0 : if (!aUri.HasError())
551 : {
552 0 : rBegin = nPos;
553 0 : rEnd = nUriEnd;
554 : return
555 0 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
556 0 : }
557 : }
558 : }
559 0 : else if (eScheme != INET_PROT_NOT_VALID) // 1st
560 : {
561 0 : while (rText[i++] != ':') ;
562 0 : sal_Int32 nPrefixEnd = i;
563 0 : sal_Int32 nUriEnd = i;
564 0 : while (i != rEnd
565 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
566 0 : if (i != nPrefixEnd && rText[i] == '#')
567 : {
568 0 : ++i;
569 0 : while (i != rEnd
570 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
571 : }
572 0 : if (nUriEnd != nPrefixEnd
573 0 : && (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
574 0 : || rText[nUriEnd] == '\\'))
575 : {
576 : INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
577 : INET_PROT_HTTP, eMechanism,
578 0 : eCharset);
579 0 : if (!aUri.HasError())
580 : {
581 0 : rBegin = nPos;
582 0 : rEnd = nUriEnd;
583 : return
584 0 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
585 0 : }
586 : }
587 : }
588 :
589 : // 3rd, 4th:
590 0 : i = nPos;
591 0 : sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
592 0 : if (nLabels >= 3
593 0 : && rText[nPos + 3] == '.'
594 0 : && (((rText[nPos] == 'w'
595 0 : || rText[nPos] == 'W')
596 0 : && (rText[nPos + 1] == 'w'
597 0 : || rText[nPos + 1] == 'W')
598 0 : && (rText[nPos + 2] == 'w'
599 0 : || rText[nPos + 2] == 'W'))
600 0 : || ((rText[nPos] == 'f'
601 0 : || rText[nPos] == 'F')
602 0 : && (rText[nPos + 1] == 't'
603 0 : || rText[nPos + 1] == 'T')
604 0 : && (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 0 : sal_Int32 nUriEnd = i;
610 0 : if (i != rEnd && rText[i] == '/')
611 : {
612 0 : nUriEnd = ++i;
613 0 : while (i != rEnd
614 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
615 : }
616 0 : if (i != rEnd && rText[i] == '#')
617 : {
618 0 : ++i;
619 0 : while (i != rEnd
620 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
621 : }
622 0 : 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 0 : eCharset);
628 0 : if (!aUri.HasError())
629 : {
630 0 : rBegin = nPos;
631 0 : rEnd = nUriEnd;
632 : return
633 0 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
634 0 : }
635 : }
636 : }
637 :
638 0 : if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 3
639 0 : && rText[nPos + 1] == ':'
640 0 : && (rText[nPos + 2] == '/'
641 0 : || rText[nPos + 2] == '\\')) // 7th, 8th
642 : {
643 0 : i = nPos + 3;
644 0 : sal_Int32 nUriEnd = i;
645 0 : while (i != rEnd
646 0 : && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
647 0 : 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 0 : INetURLObject::FSYS_DOS);
654 0 : if (!aUri.HasError())
655 : {
656 0 : rBegin = nPos;
657 0 : rEnd = nUriEnd;
658 : return
659 0 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
660 0 : }
661 : }
662 : }
663 : }
664 0 : else if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 2
665 0 : && rText[nPos] == '\\'
666 0 : && rText[nPos + 1] == '\\') // 6th
667 : {
668 0 : sal_Int32 i = nPos + 2;
669 0 : sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
670 0 : if (nLabels >= 1 && i != rEnd && rText[i] == '\\')
671 : {
672 0 : sal_Int32 nUriEnd = ++i;
673 0 : while (i != rEnd
674 : && checkWChar(rCharClass, rText, &i, &nUriEnd,
675 0 : true)) ;
676 0 : 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 0 : INetURLObject::FSYS_DOS);
683 0 : if (!aUri.HasError())
684 : {
685 0 : rBegin = nPos;
686 0 : rEnd = nUriEnd;
687 : return
688 0 : aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
689 0 : }
690 : }
691 : }
692 : }
693 : }
694 0 : if (bBoundary2 && INetMIME::isAtomChar(c)) // 5th
695 : {
696 0 : bool bDot = false;
697 0 : for (sal_Int32 i = nPos + 1; i != rEnd; ++i)
698 : {
699 0 : sal_Unicode c2 = rText[i];
700 0 : if (INetMIME::isAtomChar(c2))
701 0 : bDot = false;
702 0 : else if (bDot)
703 0 : break;
704 0 : else if (c2 == '.')
705 0 : bDot = true;
706 : else
707 : {
708 0 : if (c2 == '@')
709 : {
710 0 : ++i;
711 0 : sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
712 0 : if (nLabels >= 1
713 0 : && isBoundary1(rCharClass, rText, i, rEnd))
714 : {
715 : INetURLObject aUri(rText.copy(nPos, i - nPos),
716 : INET_PROT_MAILTO,
717 0 : INetURLObject::ENCODE_ALL);
718 0 : if (!aUri.HasError())
719 : {
720 0 : rBegin = nPos;
721 0 : rEnd = i;
722 : return aUri.GetMainURL(
723 0 : INetURLObject::DECODE_TO_IURI);
724 0 : }
725 : }
726 : }
727 0 : break;
728 : }
729 : }
730 : }
731 0 : bBoundary1 = isBoundary1(rCharClass, rText, nPos, rEnd);
732 0 : bBoundary2 = isBoundary2(rCharClass, rText, nPos, rEnd);
733 : }
734 0 : rBegin = rEnd;
735 0 : 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: */
|