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 <sal/config.h>
21 :
22 : #include <algorithm>
23 : #include <cassert>
24 : #include <cstdlib>
25 : #include <exception>
26 : #include <vector>
27 :
28 : #include <boost/noncopyable.hpp>
29 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
30 : #include <com/sun/star/lang/XMultiComponentFactory.hpp>
31 : #include <com/sun/star/lang/XServiceInfo.hpp>
32 : #include <com/sun/star/uno/Any.hxx>
33 : #include <com/sun/star/uno/Exception.hpp>
34 : #include <com/sun/star/uno/Reference.hxx>
35 : #include <com/sun/star/uno/RuntimeException.hpp>
36 : #include <com/sun/star/uno/Sequence.hxx>
37 : #include <com/sun/star/uno/XComponentContext.hpp>
38 : #include <com/sun/star/uno/XInterface.hpp>
39 : #include <com/sun/star/uri/RelativeUriExcessParentSegments.hpp>
40 : #include <com/sun/star/uri/XUriReference.hpp>
41 : #include <com/sun/star/uri/XUriReferenceFactory.hpp>
42 : #include <com/sun/star/uri/XUriSchemeParser.hpp>
43 : #include <cppuhelper/implbase1.hxx>
44 : #include <cppuhelper/implbase2.hxx>
45 : #include <cppuhelper/supportsservice.hxx>
46 : #include <cppuhelper/weak.hxx>
47 : #include <rtl/character.hxx>
48 : #include <rtl/ustrbuf.hxx>
49 : #include <rtl/ustring.hxx>
50 : #include <sal/types.h>
51 :
52 : #include "UriReference.hxx"
53 : #include "stocservices.hxx"
54 :
55 : namespace {
56 :
57 178 : bool equalIgnoreEscapeCase(OUString const & s1, OUString const & s2) {
58 178 : if (s1.getLength() == s2.getLength()) {
59 496 : for (sal_Int32 i = 0; i < s1.getLength();) {
60 508 : if (s1[i] == '%' && s2[i] == '%' && s1.getLength() - i > 2
61 0 : && rtl::isAsciiHexDigit(s1[i + 1])
62 0 : && rtl::isAsciiHexDigit(s1[i + 2])
63 0 : && rtl::isAsciiHexDigit(s2[i + 1])
64 0 : && rtl::isAsciiHexDigit(s2[i + 2])
65 0 : && rtl::compareIgnoreAsciiCase(s1[i + 1], s2[i + 1]) == 0
66 254 : && rtl::compareIgnoreAsciiCase(s1[i + 2], s2[i + 2]) == 0)
67 : {
68 0 : i += 3;
69 254 : } else if (s1[i] != s2[i]) {
70 2 : return false;
71 : } else {
72 252 : ++i;
73 : }
74 : }
75 120 : return true;
76 : } else {
77 56 : return false;
78 : }
79 : }
80 :
81 164203 : sal_Int32 parseScheme(OUString const & uriReference) {
82 164203 : if (uriReference.getLength() >= 2 && rtl::isAsciiAlpha(uriReference[0])) {
83 1125592 : for (sal_Int32 i = 0; i < uriReference.getLength(); ++i) {
84 1107102 : sal_Unicode c = uriReference[i];
85 1107102 : if (c == ':') {
86 126063 : return i;
87 2040812 : } else if (!rtl::isAsciiAlpha(c) && !rtl::isAsciiDigit(c)
88 1045252 : && c != '+' && c != '-' && c != '.')
89 : {
90 17479 : break;
91 : }
92 : }
93 : }
94 38140 : return -1;
95 : }
96 :
97 : class UriReference:
98 : public cppu::WeakImplHelper1<css::uri::XUriReference>,
99 : private boost::noncopyable
100 : {
101 : public:
102 155023 : UriReference(
103 : OUString const & scheme, bool bIsHierarchical, bool bHasAuthority,
104 : OUString const & authority, OUString const & path,
105 : bool bHasQuery, OUString const & query):
106 : m_base(
107 : scheme, bIsHierarchical, bHasAuthority, authority, path, bHasQuery,
108 155023 : query)
109 155023 : {}
110 :
111 11835 : virtual OUString SAL_CALL getUriReference()
112 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
113 11835 : { return m_base.getUriReference(); }
114 :
115 76472 : virtual sal_Bool SAL_CALL isAbsolute()
116 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
117 76472 : { return m_base.isAbsolute(); }
118 :
119 38362 : virtual OUString SAL_CALL getScheme()
120 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
121 38362 : { return m_base.getScheme(); }
122 :
123 0 : virtual OUString SAL_CALL getSchemeSpecificPart()
124 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
125 0 : { return m_base.getSchemeSpecificPart(); }
126 :
127 38260 : virtual sal_Bool SAL_CALL isHierarchical()
128 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
129 38260 : { return m_base.isHierarchical(); }
130 :
131 114218 : virtual sal_Bool SAL_CALL hasAuthority()
132 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
133 114218 : { return m_base.hasAuthority(); }
134 :
135 38150 : virtual OUString SAL_CALL getAuthority()
136 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
137 38150 : { return m_base.getAuthority(); }
138 :
139 113834 : virtual OUString SAL_CALL getPath()
140 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
141 113834 : { return m_base.getPath(); }
142 :
143 38058 : virtual sal_Bool SAL_CALL hasRelativePath()
144 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
145 38058 : { return m_base.hasRelativePath(); }
146 :
147 76770 : virtual sal_Int32 SAL_CALL getPathSegmentCount()
148 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
149 76770 : { return m_base.getPathSegmentCount(); }
150 :
151 196602 : virtual OUString SAL_CALL getPathSegment(sal_Int32 index)
152 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
153 196602 : { return m_base.getPathSegment(index); }
154 :
155 38108 : virtual sal_Bool SAL_CALL hasQuery()
156 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
157 38108 : { return m_base.hasQuery(); }
158 :
159 12 : virtual OUString SAL_CALL getQuery()
160 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
161 12 : { return m_base.getQuery(); }
162 :
163 38104 : virtual sal_Bool SAL_CALL hasFragment()
164 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
165 38104 : { return m_base.hasFragment(); }
166 :
167 10 : virtual OUString SAL_CALL getFragment()
168 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
169 10 : { return m_base.getFragment(); }
170 :
171 20 : virtual void SAL_CALL setFragment(OUString const & fragment)
172 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
173 20 : { m_base.setFragment(fragment); }
174 :
175 11123 : virtual void SAL_CALL clearFragment()
176 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
177 11123 : { m_base.clearFragment(); }
178 :
179 : private:
180 310046 : virtual ~UriReference() {}
181 :
182 : stoc::uriproc::UriReference m_base;
183 : };
184 :
185 155023 : css::uno::Reference< css::uri::XUriReference > parseGeneric(
186 : OUString const & scheme, OUString const & schemeSpecificPart)
187 : {
188 155023 : bool isAbsolute = !scheme.isEmpty();
189 155023 : bool isHierarchical = !isAbsolute || schemeSpecificPart.startsWith("/");
190 155023 : bool hasAuthority = false;
191 155023 : OUString authority;
192 310046 : OUString path;
193 155023 : bool hasQuery = false;
194 310046 : OUString query;
195 155023 : if (isHierarchical) {
196 154959 : sal_Int32 len = schemeSpecificPart.getLength();
197 154959 : sal_Int32 i = 0;
198 464867 : if (len - i >= 2 && schemeSpecificPart[i] == '/'
199 271822 : && schemeSpecificPart[i + 1] == '/')
200 : {
201 116771 : i += 2;
202 116771 : sal_Int32 n = i;
203 350953 : while (i < len && schemeSpecificPart[i] != '/'
204 117411 : && schemeSpecificPart[i] != '?') {
205 320 : ++i;
206 : }
207 116771 : hasAuthority = true;
208 116771 : authority = schemeSpecificPart.copy(n, i - n);
209 : }
210 154959 : sal_Int32 n = i;
211 154959 : i = schemeSpecificPart.indexOf('?', i);
212 154959 : if (i == -1) {
213 154951 : i = len;
214 : }
215 154959 : path = schemeSpecificPart.copy(n, i - n);
216 154959 : if (i != len) {
217 8 : hasQuery = true;
218 8 : query = schemeSpecificPart.copy(i + 1);
219 : }
220 : } else {
221 64 : if (schemeSpecificPart.isEmpty()) {
222 : // The scheme-specific part of an opaque URI must not be empty:
223 0 : return 0;
224 : }
225 64 : path = schemeSpecificPart;
226 : }
227 : return new UriReference(
228 310046 : scheme, isHierarchical, hasAuthority, authority, path, hasQuery, query);
229 : }
230 :
231 : typedef std::vector< sal_Int32 > Segments;
232 :
233 76052 : void processSegments(
234 : Segments & segments,
235 : css::uno::Reference< css::uri::XUriReference > const & uriReference,
236 : bool base, bool processSpecialSegments)
237 : {
238 76052 : sal_Int32 count = uriReference->getPathSegmentCount() - (base ? 1 : 0);
239 : assert(count <= SAL_MAX_INT32 - 1 && -count >= SAL_MIN_INT32 + 1);
240 176076 : for (sal_Int32 i = 0; i < count; ++i) {
241 100024 : if (processSpecialSegments) {
242 100024 : OUString segment(uriReference->getPathSegment(i));
243 100024 : if ( segment == "." ) {
244 0 : if (!base && i == count - 1) {
245 0 : segments.push_back(0);
246 : }
247 0 : continue;
248 100024 : } else if ( segment == ".." ) {
249 2112 : if (segments.empty() || std::abs(segments.back()) == 1) {
250 0 : segments.push_back(base ? -1 : 1);
251 : } else {
252 2112 : segments.pop_back();
253 : }
254 2112 : continue;
255 97912 : }
256 : }
257 97912 : segments.push_back(base ? -(i + 2) : i + 2);
258 : }
259 76052 : }
260 :
261 : class Factory:
262 : public cppu::WeakImplHelper2<
263 : css::lang::XServiceInfo, css::uri::XUriReferenceFactory>,
264 : private boost::noncopyable
265 : {
266 : public:
267 28065 : explicit Factory(
268 : css::uno::Reference< css::uno::XComponentContext > const & context):
269 28065 : m_context(context) {}
270 :
271 : virtual OUString SAL_CALL getImplementationName()
272 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
273 :
274 : virtual sal_Bool SAL_CALL supportsService(OUString const & serviceName)
275 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
276 :
277 : virtual css::uno::Sequence< OUString > SAL_CALL
278 : getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
279 :
280 : virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
281 : parse(OUString const & uriReference)
282 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
283 :
284 : virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
285 : makeAbsolute(
286 : css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
287 : css::uno::Reference< css::uri::XUriReference > const & uriReference,
288 : sal_Bool processSpecialBaseSegments,
289 : css::uri::RelativeUriExcessParentSegments excessParentSegments)
290 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
291 :
292 : virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
293 : makeRelative(
294 : css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
295 : css::uno::Reference< css::uri::XUriReference > const & uriReference,
296 : sal_Bool preferAuthorityOverRelativePath,
297 : sal_Bool preferAbsoluteOverRelativePath,
298 : sal_Bool encodeRetainedSpecialSegments)
299 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
300 :
301 : private:
302 56130 : virtual ~Factory() {}
303 :
304 40 : css::uno::Reference< css::uri::XUriReference > clone(
305 : css::uno::Reference< css::uri::XUriReference > const & uriReference)
306 40 : { return parse(uriReference->getUriReference()); }
307 :
308 : css::uno::Reference< css::uno::XComponentContext > m_context;
309 : };
310 :
311 0 : OUString Factory::getImplementationName()
312 : throw (css::uno::RuntimeException, std::exception)
313 : {
314 0 : return stoc_services::UriReferenceFactory::getImplementationName();
315 : }
316 :
317 0 : sal_Bool Factory::supportsService(OUString const & serviceName)
318 : throw (css::uno::RuntimeException, std::exception)
319 : {
320 0 : return cppu::supportsService(this, serviceName);
321 : }
322 :
323 0 : css::uno::Sequence< OUString > Factory::getSupportedServiceNames()
324 : throw (css::uno::RuntimeException, std::exception)
325 : {
326 0 : return stoc_services::UriReferenceFactory::getSupportedServiceNames();
327 : }
328 :
329 164191 : css::uno::Reference< css::uri::XUriReference > Factory::parse(
330 : OUString const & uriReference)
331 : throw (css::uno::RuntimeException, std::exception)
332 : {
333 164191 : sal_Int32 fragment = uriReference.indexOf('#');
334 164191 : if (fragment == -1) {
335 164171 : fragment = uriReference.getLength();
336 : }
337 164191 : OUString scheme;
338 328382 : OUString schemeSpecificPart;
339 328382 : OUString serviceName;
340 164191 : sal_Int32 n = parseScheme(uriReference);
341 : assert(n < fragment);
342 164191 : if (n >= 0) {
343 126063 : scheme = uriReference.copy(0, n);
344 126063 : schemeSpecificPart = uriReference.copy(n + 1, fragment - (n + 1));
345 126063 : OUStringBuffer buf;
346 126063 : buf.append("com.sun.star.uri.UriSchemeParser_");
347 767907 : for (sal_Int32 i = 0; i < scheme.getLength(); ++i) {
348 641844 : sal_Unicode c = scheme[i];
349 641844 : if (rtl::isAsciiUpperCase(c)) {
350 108 : buf.append(static_cast<sal_Unicode>(rtl::toAsciiLowerCase(c)));
351 641736 : } else if (c == '+') {
352 0 : buf.append("PLUS");
353 641736 : } else if (c == '-') {
354 0 : buf.append("HYPHEN");
355 641736 : } else if (c == '.') {
356 27504 : buf.append("DOT");
357 : } else {
358 : assert(rtl::isAsciiLowerCase(c) || rtl::isAsciiDigit(c));
359 614232 : buf.append(c);
360 : }
361 : }
362 126063 : serviceName = buf.makeStringAndClear();
363 : } else {
364 38128 : schemeSpecificPart = uriReference.copy(0, fragment);
365 : }
366 328382 : css::uno::Reference< css::uri::XUriSchemeParser > parser;
367 164191 : if (!serviceName.isEmpty()) {
368 : css::uno::Reference< css::lang::XMultiComponentFactory > factory(
369 126063 : m_context->getServiceManager());
370 126063 : if (factory.is()) {
371 126063 : css::uno::Reference< css::uno::XInterface > service;
372 : try {
373 378189 : service = factory->createInstanceWithContext(
374 252126 : serviceName, m_context);
375 0 : } catch (css::uno::RuntimeException &) {
376 0 : throw;
377 0 : } catch (const css::uno::Exception & e) {
378 : throw css::lang::WrappedTargetRuntimeException(
379 0 : "creating service " + serviceName,
380 : static_cast< cppu::OWeakObject * >(this),
381 0 : css::uno::makeAny(e)); //TODO: preserve type of e
382 : }
383 126063 : if (service.is()) {
384 18336 : parser = css::uno::Reference< css::uri::XUriSchemeParser >(
385 9168 : service, css::uno::UNO_QUERY_THROW);
386 126063 : }
387 126063 : }
388 : }
389 : css::uno::Reference< css::uri::XUriReference > uriRef(
390 164191 : parser.is()
391 9168 : ? parser->parse(scheme, schemeSpecificPart)
392 173359 : : parseGeneric(scheme, schemeSpecificPart));
393 164191 : if (uriRef.is() && fragment != uriReference.getLength()) {
394 20 : uriRef->setFragment(uriReference.copy(fragment + 1));
395 : }
396 328382 : return uriRef;
397 : }
398 :
399 38026 : css::uno::Reference< css::uri::XUriReference > Factory::makeAbsolute(
400 : css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
401 : css::uno::Reference< css::uri::XUriReference > const & uriReference,
402 : sal_Bool processSpecialBaseSegments,
403 : css::uri::RelativeUriExcessParentSegments excessParentSegments)
404 : throw (css::uno::RuntimeException, std::exception)
405 : {
406 114078 : if (!baseUriReference.is() || !baseUriReference->isAbsolute()
407 76052 : || !baseUriReference->isHierarchical() || !uriReference.is()) {
408 0 : return 0;
409 38026 : } else if (uriReference->isAbsolute()) {
410 0 : return clone(uriReference);
411 114078 : } else if (!uriReference->hasAuthority()
412 114078 : && uriReference->getPath().isEmpty()
413 76052 : && !uriReference->hasQuery()) {
414 : css::uno::Reference< css::uri::XUriReference > abs(
415 0 : clone(baseUriReference));
416 0 : if (uriReference->hasFragment()) {
417 0 : abs->setFragment(uriReference->getFragment());
418 : } else {
419 0 : abs->clearFragment();
420 : }
421 0 : return abs;
422 : } else {
423 38026 : OUStringBuffer abs(baseUriReference->getScheme());
424 38026 : abs.append(':');
425 38026 : if (uriReference->hasAuthority()) {
426 0 : abs.append("//");
427 0 : abs.append(uriReference->getAuthority());
428 38026 : } else if (baseUriReference->hasAuthority()) {
429 38026 : abs.append("//");
430 38026 : abs.append(baseUriReference->getAuthority());
431 : }
432 38026 : if (uriReference->hasRelativePath()) {
433 38026 : Segments segments;
434 : processSegments(
435 38026 : segments, baseUriReference, true, processSpecialBaseSegments);
436 38026 : processSegments(segments, uriReference, false, true);
437 : // If the path component of the base URI reference is empty (which
438 : // implies that the base URI reference denotes a "root entity"), and
439 : // the resulting URI reference denotes the same root entity, make
440 : // sure the path component of the resulting URI reference is also
441 : // empty (and not "/"). RFC 2396 is unclear about this, and I chose
442 : // these rules for consistent results.
443 38026 : bool slash = !baseUriReference->getPath().isEmpty();
444 38026 : if (slash) {
445 38026 : abs.append('/');
446 : }
447 133826 : for (Segments::iterator i(segments.begin()); i != segments.end();
448 : ++i)
449 : {
450 95800 : if (*i < -1) {
451 : OUString segment(
452 38194 : baseUriReference->getPathSegment(-(*i + 2)));
453 38194 : if (!segment.isEmpty() || segments.size() > 1) {
454 38194 : if (!slash) {
455 0 : abs.append('/');
456 : }
457 38194 : abs.append(segment);
458 38194 : slash = true;
459 38194 : abs.append('/');
460 38194 : }
461 57606 : } else if (*i > 1) {
462 57606 : OUString segment(uriReference->getPathSegment(*i - 2));
463 57606 : if (!segment.isEmpty() || segments.size() > 1) {
464 57606 : if (!slash) {
465 19580 : abs.append('/');
466 : }
467 57606 : abs.append(segment);
468 57606 : slash = false;
469 57606 : }
470 0 : } else if (*i == 0) {
471 0 : if (segments.size() > 1 && !slash) {
472 0 : abs.append('/');
473 : }
474 : } else {
475 0 : switch (excessParentSegments) {
476 : case css::uri::RelativeUriExcessParentSegments_ERROR:
477 0 : return 0;
478 :
479 : case css::uri::RelativeUriExcessParentSegments_RETAIN:
480 0 : if (!slash) {
481 0 : abs.append('/');
482 : }
483 0 : abs.append("..");
484 0 : slash = *i < 0;
485 0 : if (slash) {
486 0 : abs.append('/');
487 : }
488 0 : break;
489 :
490 : case css::uri::RelativeUriExcessParentSegments_REMOVE:
491 0 : break;
492 :
493 : default:
494 : assert(false);
495 0 : break;
496 : }
497 : }
498 38026 : }
499 : } else {
500 0 : abs.append(uriReference->getPath());
501 : }
502 38026 : if (uriReference->hasQuery()) {
503 0 : abs.append('?');
504 0 : abs.append(uriReference->getQuery());
505 : }
506 38026 : if (uriReference->hasFragment()) {
507 0 : abs.append('#');
508 0 : abs.append(uriReference->getFragment());
509 : }
510 38026 : return parse(abs.makeStringAndClear());
511 : }
512 : }
513 :
514 102 : css::uno::Reference< css::uri::XUriReference > Factory::makeRelative(
515 : css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
516 : css::uno::Reference< css::uri::XUriReference > const & uriReference,
517 : sal_Bool preferAuthorityOverRelativePath,
518 : sal_Bool preferAbsoluteOverRelativePath,
519 : sal_Bool encodeRetainedSpecialSegments)
520 : throw (css::uno::RuntimeException, std::exception)
521 : {
522 306 : if (!baseUriReference.is() || !baseUriReference->isAbsolute()
523 204 : || !baseUriReference->isHierarchical() || !uriReference.is()) {
524 0 : return 0;
525 440 : } else if (!uriReference->isAbsolute() || !uriReference->isHierarchical()
526 408 : || !baseUriReference->getScheme().equalsIgnoreAsciiCase(
527 374 : uriReference->getScheme())) {
528 40 : return clone(uriReference);
529 : } else {
530 62 : OUStringBuffer rel;
531 62 : bool omitQuery = false;
532 186 : if ((baseUriReference->hasAuthority() != uriReference->hasAuthority())
533 310 : || !equalIgnoreEscapeCase(
534 62 : baseUriReference->getAuthority(),
535 310 : uriReference->getAuthority()))
536 : {
537 0 : if (uriReference->hasAuthority()) {
538 0 : rel.append("//");
539 0 : rel.append(uriReference->getAuthority());
540 : }
541 0 : rel.append(uriReference->getPath());
542 124 : } else if ((equalIgnoreEscapeCase(
543 310 : baseUriReference->getPath(), uriReference->getPath())
544 120 : || (baseUriReference->getPath().getLength() <= 1
545 62 : && uriReference->getPath().getLength() <= 1))
546 4 : && baseUriReference->hasQuery() == uriReference->hasQuery()
547 260 : && equalIgnoreEscapeCase(
548 74 : baseUriReference->getQuery(), uriReference->getQuery()))
549 : {
550 4 : omitQuery = true;
551 : } else {
552 : sal_Int32 count1 = std::max< sal_Int32 >(
553 58 : baseUriReference->getPathSegmentCount(), 1);
554 : sal_Int32 count2 = std::max< sal_Int32 >(
555 58 : uriReference->getPathSegmentCount(), 1);
556 58 : sal_Int32 i = 0;
557 108 : for (; i < std::min(count1, count2) - 1; ++i) {
558 100 : if (!equalIgnoreEscapeCase(
559 50 : baseUriReference->getPathSegment(i),
560 150 : uriReference->getPathSegment(i)))
561 : {
562 0 : break;
563 : }
564 : }
565 210 : if (i == 0 && preferAbsoluteOverRelativePath
566 130 : && (preferAuthorityOverRelativePath
567 58 : || !uriReference->getPath().startsWith("//")))
568 : {
569 144 : if (baseUriReference->getPath().getLength() > 1
570 144 : || uriReference->getPath().getLength() > 1)
571 : {
572 36 : if (uriReference->getPath().isEmpty()) {
573 0 : rel.append('/');
574 : } else {
575 : assert(uriReference->getPath()[0] == '/');
576 36 : if (uriReference->getPath().startsWith("//")) {
577 : assert(uriReference->hasAuthority());
578 0 : rel.append("//");
579 0 : rel.append(uriReference->getAuthority());
580 : }
581 36 : rel.append(uriReference->getPath());
582 : }
583 : }
584 : } else {
585 22 : bool segments = false;
586 34 : for (sal_Int32 j = i; j < count1 - 1; ++j) {
587 12 : if (segments) {
588 2 : rel.append('/');
589 : }
590 12 : rel.append("..");
591 12 : segments = true;
592 : }
593 72 : if (i < count2 - 1
594 82 : || (!uriReference->getPathSegment(count2 - 1).isEmpty()))
595 : {
596 76 : if (!segments
597 78 : && (uriReference->getPathSegment(i).isEmpty()
598 34 : || (parseScheme(uriReference->getPathSegment(i))
599 : >= 0)))
600 : {
601 0 : rel.append('.');
602 0 : segments = true;
603 : }
604 50 : for (; i < count2; ++i) {
605 28 : if (segments) {
606 16 : rel.append('/');
607 : }
608 28 : OUString s(uriReference->getPathSegment(i));
609 28 : if (encodeRetainedSpecialSegments && s == ".") {
610 0 : rel.append("%2E");
611 28 : } else if (encodeRetainedSpecialSegments && s == "..") {
612 0 : rel.append("%2E%2E");
613 : } else {
614 28 : rel.append(s);
615 : }
616 28 : segments = true;
617 28 : }
618 : }
619 : }
620 : }
621 62 : if (!omitQuery && uriReference->hasQuery()) {
622 4 : rel.append('?');
623 4 : rel.append(uriReference->getQuery());
624 : }
625 62 : if (uriReference->hasFragment()) {
626 8 : rel.append('#');
627 8 : rel.append(uriReference->getFragment());
628 : }
629 62 : return parse(rel.makeStringAndClear());
630 : }
631 : }
632 :
633 : }
634 :
635 : namespace stoc_services { namespace UriReferenceFactory {
636 :
637 28065 : css::uno::Reference< css::uno::XInterface > create(
638 : css::uno::Reference< css::uno::XComponentContext > const & context)
639 : {
640 28065 : return static_cast< cppu::OWeakObject * >(new Factory(context));
641 : }
642 :
643 411 : OUString getImplementationName() {
644 411 : return OUString("com.sun.star.comp.uri.UriReferenceFactory");
645 : }
646 :
647 187 : css::uno::Sequence< OUString > getSupportedServiceNames() {
648 187 : css::uno::Sequence< OUString > s(1);
649 187 : s[0] = "com.sun.star.uri.UriReferenceFactory";
650 187 : return s;
651 : }
652 :
653 : } }
654 :
655 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|