1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_stoc.hxx"
26
27 #include "stocservices.hxx"
28
29 #include "UriReference.hxx"
30 #include "supportsService.hxx"
31
32 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
33 #include "com/sun/star/lang/XMultiComponentFactory.hpp"
34 #include "com/sun/star/lang/XServiceInfo.hpp"
35 #include "com/sun/star/uno/Any.hxx"
36 #include "com/sun/star/uno/Exception.hpp"
37 #include "com/sun/star/uno/Reference.hxx"
38 #include "com/sun/star/uno/RuntimeException.hpp"
39 #include "com/sun/star/uno/Sequence.hxx"
40 #include "com/sun/star/uno/XComponentContext.hpp"
41 #include "com/sun/star/uno/XInterface.hpp"
42 #include "com/sun/star/uri/RelativeUriExcessParentSegments.hpp"
43 #include "com/sun/star/uri/XUriReference.hpp"
44 #include "com/sun/star/uri/XUriReferenceFactory.hpp"
45 #include "com/sun/star/uri/XUriSchemeParser.hpp"
46 #include "cppuhelper/implbase1.hxx"
47 #include "cppuhelper/implbase2.hxx"
48 #include "cppuhelper/weak.hxx"
49 #include "osl/diagnose.h"
50 #include "rtl/string.h"
51 #include "rtl/ustrbuf.hxx"
52 #include "rtl/ustring.hxx"
53 #include "sal/types.h"
54
55 #include <algorithm>
56 #include /*MSVC trouble: <cstdlib>*/ <stdlib.h>
57 #include <new>
58 #include <vector>
59
60 namespace css = com::sun::star;
61
62 namespace {
63
isDigit(sal_Unicode c)64 bool isDigit(sal_Unicode c) { //TODO: generally available?
65 return c >= '0' && c <= '9';
66 }
67
isUpperCase(sal_Unicode c)68 bool isUpperCase(sal_Unicode c) { //TODO: generally available?
69 return c >= 'A' && c <= 'Z';
70 }
71
isLowerCase(sal_Unicode c)72 bool isLowerCase(sal_Unicode c) { //TODO: generally available?
73 return c >= 'a' && c <= 'z';
74 }
75
isAlpha(sal_Unicode c)76 bool isAlpha(sal_Unicode c) { //TODO: generally available?
77 return isUpperCase(c) || isLowerCase(c);
78 }
79
isHexDigit(sal_Unicode c)80 bool isHexDigit(sal_Unicode c) { //TODO: generally available?
81 return isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
82 }
83
toLowerCase(sal_Unicode c)84 sal_Unicode toLowerCase(sal_Unicode c) { //TODO: generally available?
85 return isUpperCase(c) ? c + ('a' - 'A') : c;
86 }
87
equalIgnoreCase(sal_Unicode c1,sal_Unicode c2)88 bool equalIgnoreCase(sal_Unicode c1, sal_Unicode c2) {
89 //TODO: generally available?
90 return toLowerCase(c1) == toLowerCase(c2);
91 }
92
equalIgnoreEscapeCase(rtl::OUString const & s1,rtl::OUString const & s2)93 bool equalIgnoreEscapeCase(rtl::OUString const & s1, rtl::OUString const & s2) {
94 if (s1.getLength() == s2.getLength()) {
95 for (sal_Int32 i = 0; i < s1.getLength();) {
96 if (s1[i] == '%' && s2[i] == '%' && s1.getLength() - i > 2
97 && isHexDigit(s1[i + 1]) && isHexDigit(s1[i + 2])
98 && isHexDigit(s2[i + 1]) && isHexDigit(s2[i + 2])
99 && equalIgnoreCase(s1[i + 1], s2[i + 1])
100 && equalIgnoreCase(s1[i + 2], s2[i + 2]))
101 {
102 i += 3;
103 } else if (s1[i] != s2[i]) {
104 return false;
105 } else {
106 ++i;
107 }
108 }
109 return true;
110 } else {
111 return false;
112 }
113 }
114
parseScheme(rtl::OUString const & uriReference)115 sal_Int32 parseScheme(rtl::OUString const & uriReference) {
116 if (uriReference.getLength() >= 2 && isAlpha(uriReference[0])) {
117 for (sal_Int32 i = 0; i < uriReference.getLength(); ++i) {
118 sal_Unicode c = uriReference[i];
119 if (c == ':') {
120 return i;
121 } else if (!isAlpha(c) && !isDigit(c) && c != '+' && c != '-'
122 && c != '.')
123 {
124 break;
125 }
126 }
127 }
128 return -1;
129 }
130
131 class UriReference: public cppu::WeakImplHelper1< css::uri::XUriReference > {
132 public:
UriReference(rtl::OUString const & scheme,bool bIsHierarchical,bool bHasAuthority,rtl::OUString const & authority,rtl::OUString const & path,bool bHasQuery,rtl::OUString const & query)133 UriReference(
134 rtl::OUString const & scheme, bool bIsHierarchical, bool bHasAuthority,
135 rtl::OUString const & authority, rtl::OUString const & path,
136 bool bHasQuery, rtl::OUString const & query):
137 m_base(
138 scheme, bIsHierarchical, bHasAuthority, authority, path, bHasQuery,
139 query)
140 {}
141
getUriReference()142 virtual rtl::OUString SAL_CALL getUriReference()
143 { return m_base.getUriReference(); }
144
isAbsolute()145 virtual sal_Bool SAL_CALL isAbsolute()
146 { return m_base.isAbsolute(); }
147
getScheme()148 virtual rtl::OUString SAL_CALL getScheme()
149 { return m_base.getScheme(); }
150
getSchemeSpecificPart()151 virtual rtl::OUString SAL_CALL getSchemeSpecificPart()
152 { return m_base.getSchemeSpecificPart(); }
153
isHierarchical()154 virtual sal_Bool SAL_CALL isHierarchical()
155 { return m_base.isHierarchical(); }
156
hasAuthority()157 virtual sal_Bool SAL_CALL hasAuthority()
158 { return m_base.hasAuthority(); }
159
getAuthority()160 virtual rtl::OUString SAL_CALL getAuthority()
161 { return m_base.getAuthority(); }
162
getPath()163 virtual rtl::OUString SAL_CALL getPath()
164 { return m_base.getPath(); }
165
hasRelativePath()166 virtual sal_Bool SAL_CALL hasRelativePath()
167 { return m_base.hasRelativePath(); }
168
getPathSegmentCount()169 virtual sal_Int32 SAL_CALL getPathSegmentCount()
170 { return m_base.getPathSegmentCount(); }
171
getPathSegment(sal_Int32 index)172 virtual rtl::OUString SAL_CALL getPathSegment(sal_Int32 index)
173 { return m_base.getPathSegment(index); }
174
hasQuery()175 virtual sal_Bool SAL_CALL hasQuery()
176 { return m_base.hasQuery(); }
177
getQuery()178 virtual rtl::OUString SAL_CALL getQuery()
179 { return m_base.getQuery(); }
180
hasFragment()181 virtual sal_Bool SAL_CALL hasFragment()
182 { return m_base.hasFragment(); }
183
getFragment()184 virtual rtl::OUString SAL_CALL getFragment()
185 { return m_base.getFragment(); }
186
setFragment(rtl::OUString const & fragment)187 virtual void SAL_CALL setFragment(rtl::OUString const & fragment)
188 { m_base.setFragment(fragment); }
189
clearFragment()190 virtual void SAL_CALL clearFragment()
191 { m_base.clearFragment(); }
192
193 private:
194 UriReference(UriReference &); // not implemented
195 void operator =(UriReference); // not implemented
196
~UriReference()197 virtual ~UriReference() {}
198
199 stoc::uriproc::UriReference m_base;
200 };
201
202 // throws std::bad_alloc
parseGeneric(rtl::OUString const & scheme,rtl::OUString const & schemeSpecificPart)203 css::uno::Reference< css::uri::XUriReference > parseGeneric(
204 rtl::OUString const & scheme, rtl::OUString const & schemeSpecificPart)
205 {
206 bool isAbsolute = scheme.getLength() != 0;
207 bool isHierarchical
208 = !isAbsolute
209 || (schemeSpecificPart.getLength() > 0 && schemeSpecificPart[0] == '/');
210 bool hasAuthority = false;
211 rtl::OUString authority;
212 rtl::OUString path;
213 bool hasQuery = false;
214 rtl::OUString query;
215 if (isHierarchical) {
216 sal_Int32 len = schemeSpecificPart.getLength();
217 sal_Int32 i = 0;
218 if (len - i >= 2 && schemeSpecificPart[i] == '/'
219 && schemeSpecificPart[i + 1] == '/')
220 {
221 i += 2;
222 sal_Int32 n = i;
223 while (i < len && schemeSpecificPart[i] != '/'
224 && schemeSpecificPart[i] != '?') {
225 ++i;
226 }
227 hasAuthority = true;
228 authority = schemeSpecificPart.copy(n, i - n);
229 }
230 sal_Int32 n = i;
231 i = schemeSpecificPart.indexOf('?', i);
232 if (i == -1) {
233 i = len;
234 }
235 path = schemeSpecificPart.copy(n, i - n);
236 if (i != len) {
237 hasQuery = true;
238 query = schemeSpecificPart.copy(i + 1);
239 }
240 } else {
241 if (schemeSpecificPart.getLength() == 0) {
242 // The scheme-specific part of an opaque URI must not be empty:
243 return 0;
244 }
245 path = schemeSpecificPart;
246 }
247 return new UriReference(
248 scheme, isHierarchical, hasAuthority, authority, path, hasQuery, query);
249 }
250
251 typedef std::vector< sal_Int32 > Segments;
252
processSegments(Segments & segments,css::uno::Reference<css::uri::XUriReference> const & uriReference,bool base,bool processSpecialSegments)253 void processSegments(
254 Segments & segments,
255 css::uno::Reference< css::uri::XUriReference > const & uriReference,
256 bool base, bool processSpecialSegments)
257 {
258 sal_Int32 count = uriReference->getPathSegmentCount() - (base ? 1 : 0);
259 OSL_ASSERT(count <= SAL_MAX_INT32 - 1 && -count >= SAL_MIN_INT32 + 1);
260 for (sal_Int32 i = 0; i < count; ++i) {
261 if (processSpecialSegments) {
262 rtl::OUString segment(uriReference->getPathSegment(i));
263 if (segment.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("."))) {
264 if (!base && i == count - 1) {
265 segments.push_back(0);
266 }
267 continue;
268 } else if (segment.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".."))) {
269 if (segments.empty()
270 || /*MSVC trouble: std::*/abs(segments.back()) == 1)
271 {
272 segments.push_back(base ? -1 : 1);
273 } else {
274 segments.pop_back();
275 }
276 continue;
277 }
278 }
279 segments.push_back(base ? -(i + 2) : i + 2);
280 }
281 }
282
283 class Factory: public cppu::WeakImplHelper2<
284 css::lang::XServiceInfo, css::uri::XUriReferenceFactory >
285 {
286 public:
Factory(css::uno::Reference<css::uno::XComponentContext> const & context)287 explicit Factory(
288 css::uno::Reference< css::uno::XComponentContext > const & context):
289 m_context(context) {}
290
291 virtual rtl::OUString SAL_CALL getImplementationName();
292
293 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName);
294
295 virtual css::uno::Sequence< rtl::OUString > SAL_CALL
296 getSupportedServiceNames();
297
298 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
299 parse(rtl::OUString const & uriReference);
300
301 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
302 makeAbsolute(
303 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
304 css::uno::Reference< css::uri::XUriReference > const & uriReference,
305 sal_Bool processSpecialBaseSegments,
306 css::uri::RelativeUriExcessParentSegments excessParentSegments);
307
308 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
309 makeRelative(
310 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
311 css::uno::Reference< css::uri::XUriReference > const & uriReference,
312 sal_Bool preferAuthorityOverRelativePath,
313 sal_Bool preferAbsoluteOverRelativePath,
314 sal_Bool encodeRetainedSpecialSegments);
315
316 private:
317 Factory(Factory &); // not implemented
318 void operator =(Factory); // not implemented
319
~Factory()320 virtual ~Factory() {}
321
clone(css::uno::Reference<css::uri::XUriReference> const & uriReference)322 css::uno::Reference< css::uri::XUriReference > clone(
323 css::uno::Reference< css::uri::XUriReference > const & uriReference)
324 { return parse(uriReference->getUriReference()); }
325
326 css::uno::Reference< css::uno::XComponentContext > m_context;
327 };
328
getImplementationName()329 rtl::OUString Factory::getImplementationName()
330 {
331 return stoc_services::UriReferenceFactory::getImplementationName();
332 }
333
supportsService(rtl::OUString const & serviceName)334 sal_Bool Factory::supportsService(rtl::OUString const & serviceName)
335 {
336 return stoc::uriproc::supportsService(
337 getSupportedServiceNames(), serviceName);
338 }
339
getSupportedServiceNames()340 css::uno::Sequence< rtl::OUString > Factory::getSupportedServiceNames()
341 {
342 return stoc_services::UriReferenceFactory::getSupportedServiceNames();
343 }
344
parse(rtl::OUString const & uriReference)345 css::uno::Reference< css::uri::XUriReference > Factory::parse(
346 rtl::OUString const & uriReference)
347 {
348 sal_Int32 fragment = uriReference.indexOf('#');
349 if (fragment == -1) {
350 fragment = uriReference.getLength();
351 }
352 rtl::OUString scheme;
353 rtl::OUString schemeSpecificPart;
354 rtl::OUString serviceName;
355 sal_Int32 n = parseScheme(uriReference);
356 OSL_ASSERT(n < fragment);
357 if (n >= 0) {
358 scheme = uriReference.copy(0, n);
359 schemeSpecificPart = uriReference.copy(n + 1, fragment - (n + 1));
360 rtl::OUStringBuffer buf;
361 buf.appendAscii(
362 RTL_CONSTASCII_STRINGPARAM("com.sun.star.uri.UriSchemeParser_"));
363 for (sal_Int32 i = 0; i < scheme.getLength(); ++i) {
364 sal_Unicode c = scheme[i];
365 if (isUpperCase(c)) {
366 buf.append(toLowerCase(c));
367 } else if (c == '+') {
368 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("PLUS"));
369 } else if (c == '-') {
370 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("HYPHEN"));
371 } else if (c == '.') {
372 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("DOT"));
373 } else {
374 OSL_ASSERT(isLowerCase(c) || isDigit(c));
375 buf.append(c);
376 }
377 }
378 serviceName = buf.makeStringAndClear();
379 } else {
380 schemeSpecificPart = uriReference.copy(0, fragment);
381 }
382 css::uno::Reference< css::uri::XUriSchemeParser > parser;
383 if (serviceName.getLength() != 0) {
384 css::uno::Reference< css::lang::XMultiComponentFactory > factory(
385 m_context->getServiceManager());
386 if (factory.is()) {
387 css::uno::Reference< css::uno::XInterface > service;
388 try {
389 service = factory->createInstanceWithContext(
390 serviceName, m_context);
391 } catch (css::uno::RuntimeException &) {
392 throw;
393 } catch (css::uno::Exception & e) {
394 throw css::lang::WrappedTargetRuntimeException(
395 rtl::OUString::createFromAscii("creating service ")
396 + serviceName,
397 static_cast< cppu::OWeakObject * >(this),
398 css::uno::makeAny(e)); //TODO: preserve type of e
399 }
400 if (service.is()) {
401 parser = css::uno::Reference< css::uri::XUriSchemeParser >(
402 service, css::uno::UNO_QUERY_THROW);
403 }
404 }
405 }
406 css::uno::Reference< css::uri::XUriReference > uriRef;
407 if (parser.is()) {
408 uriRef = parser->parse(scheme, schemeSpecificPart);
409 } else {
410 try {
411 uriRef = parseGeneric(scheme, schemeSpecificPart);
412 } catch (std::bad_alloc &) {
413 throw css::uno::RuntimeException(
414 rtl::OUString::createFromAscii("std::bad_alloc"),
415 static_cast< cppu::OWeakObject * >(this));
416 }
417 }
418 if (uriRef.is() && fragment != uriReference.getLength()) {
419 uriRef->setFragment(uriReference.copy(fragment + 1));
420 }
421 return uriRef;
422 }
423
makeAbsolute(css::uno::Reference<css::uri::XUriReference> const & baseUriReference,css::uno::Reference<css::uri::XUriReference> const & uriReference,sal_Bool processSpecialBaseSegments,css::uri::RelativeUriExcessParentSegments excessParentSegments)424 css::uno::Reference< css::uri::XUriReference > Factory::makeAbsolute(
425 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
426 css::uno::Reference< css::uri::XUriReference > const & uriReference,
427 sal_Bool processSpecialBaseSegments,
428 css::uri::RelativeUriExcessParentSegments excessParentSegments)
429 {
430 if (!baseUriReference.is() || !baseUriReference->isAbsolute()
431 || !baseUriReference->isHierarchical() || !uriReference.is()) {
432 return 0;
433 } else if (uriReference->isAbsolute()) {
434 return clone(uriReference);
435 } else if (!uriReference->hasAuthority()
436 && uriReference->getPath().getLength() == 0
437 && !uriReference->hasQuery()) {
438 css::uno::Reference< css::uri::XUriReference > abs(
439 clone(baseUriReference));
440 if (uriReference->hasFragment()) {
441 abs->setFragment(uriReference->getFragment());
442 } else {
443 abs->clearFragment();
444 }
445 return abs;
446 } else {
447 rtl::OUStringBuffer abs(baseUriReference->getScheme());
448 abs.append(static_cast< sal_Unicode >(':'));
449 if (uriReference->hasAuthority()) {
450 abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
451 abs.append(uriReference->getAuthority());
452 } else if (baseUriReference->hasAuthority()) {
453 abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
454 abs.append(baseUriReference->getAuthority());
455 }
456 if (uriReference->hasRelativePath()) {
457 Segments segments;
458 processSegments(
459 segments, baseUriReference, true, processSpecialBaseSegments);
460 processSegments(segments, uriReference, false, true);
461 // If the path component of the base URI reference is empty (which
462 // implies that the base URI reference denotes a "root entity"), and
463 // the resulting URI reference denotes the same root entity, make
464 // sure the path component of the resulting URI reference is also
465 // empty (and not "/"). RFC 2396 is unclear about this, and I chose
466 // these rules for consistent results.
467 bool slash = baseUriReference->getPath().getLength() != 0;
468 if (slash) {
469 abs.append(static_cast< sal_Unicode >('/'));
470 }
471 for (Segments::iterator i(segments.begin()); i != segments.end();
472 ++i)
473 {
474 if (*i < -1) {
475 rtl::OUString segment(
476 baseUriReference->getPathSegment(-(*i + 2)));
477 if (segment.getLength() != 0 || segments.size() > 1) {
478 if (!slash) {
479 abs.append(static_cast< sal_Unicode >('/'));
480 }
481 abs.append(segment);
482 slash = true;
483 abs.append(static_cast< sal_Unicode >('/'));
484 }
485 } else if (*i > 1) {
486 rtl::OUString segment(uriReference->getPathSegment(*i - 2));
487 if (segment.getLength() != 0 || segments.size() > 1) {
488 if (!slash) {
489 abs.append(static_cast< sal_Unicode >('/'));
490 }
491 abs.append(segment);
492 slash = false;
493 }
494 } else if (*i == 0) {
495 if (segments.size() > 1 && !slash) {
496 abs.append(static_cast< sal_Unicode >('/'));
497 }
498 } else {
499 switch (excessParentSegments) {
500 case css::uri::RelativeUriExcessParentSegments_ERROR:
501 return 0;
502
503 case css::uri::RelativeUriExcessParentSegments_RETAIN:
504 if (!slash) {
505 abs.append(static_cast< sal_Unicode >('/'));
506 }
507 abs.appendAscii(RTL_CONSTASCII_STRINGPARAM(".."));
508 slash = *i < 0;
509 if (slash) {
510 abs.append(static_cast< sal_Unicode >('/'));
511 }
512 break;
513
514 case css::uri::RelativeUriExcessParentSegments_REMOVE:
515 break;
516
517 default:
518 OSL_ASSERT(false);
519 break;
520 }
521 }
522 }
523 } else {
524 abs.append(uriReference->getPath());
525 }
526 if (uriReference->hasQuery()) {
527 abs.append(static_cast< sal_Unicode >('?'));
528 abs.append(uriReference->getQuery());
529 }
530 if (uriReference->hasFragment()) {
531 abs.append(static_cast< sal_Unicode >('#'));
532 abs.append(uriReference->getFragment());
533 }
534 return parse(abs.makeStringAndClear());
535 }
536 }
537
makeRelative(css::uno::Reference<css::uri::XUriReference> const & baseUriReference,css::uno::Reference<css::uri::XUriReference> const & uriReference,sal_Bool preferAuthorityOverRelativePath,sal_Bool preferAbsoluteOverRelativePath,sal_Bool encodeRetainedSpecialSegments)538 css::uno::Reference< css::uri::XUriReference > Factory::makeRelative(
539 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
540 css::uno::Reference< css::uri::XUriReference > const & uriReference,
541 sal_Bool preferAuthorityOverRelativePath,
542 sal_Bool preferAbsoluteOverRelativePath,
543 sal_Bool encodeRetainedSpecialSegments)
544 {
545 if (!baseUriReference.is() || !baseUriReference->isAbsolute()
546 || !baseUriReference->isHierarchical() || !uriReference.is()) {
547 return 0;
548 } else if (!uriReference->isAbsolute() || !uriReference->isHierarchical()
549 || !baseUriReference->getScheme().equalsIgnoreAsciiCase(
550 uriReference->getScheme())) {
551 return clone(uriReference);
552 } else {
553 rtl::OUStringBuffer rel;
554 bool omitQuery = false;
555 if ((baseUriReference->hasAuthority() != uriReference->hasAuthority())
556 || !equalIgnoreEscapeCase(
557 baseUriReference->getAuthority(),
558 uriReference->getAuthority()))
559 {
560 if (uriReference->hasAuthority()) {
561 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
562 rel.append(uriReference->getAuthority());
563 }
564 rel.append(uriReference->getPath());
565 } else if ((equalIgnoreEscapeCase(
566 baseUriReference->getPath(), uriReference->getPath())
567 || (baseUriReference->getPath().getLength() <= 1
568 && uriReference->getPath().getLength() <= 1))
569 && baseUriReference->hasQuery() == uriReference->hasQuery()
570 && equalIgnoreEscapeCase(
571 baseUriReference->getQuery(), uriReference->getQuery()))
572 {
573 omitQuery = true;
574 } else {
575 sal_Int32 count1 = std::max< sal_Int32 >(
576 baseUriReference->getPathSegmentCount(), 1);
577 sal_Int32 count2 = std::max< sal_Int32 >(
578 uriReference->getPathSegmentCount(), 1);
579 sal_Int32 i = 0;
580 for (; i < std::min(count1, count2) - 1; ++i) {
581 if (!equalIgnoreEscapeCase(
582 baseUriReference->getPathSegment(i),
583 uriReference->getPathSegment(i)))
584 {
585 break;
586 }
587 }
588 if (i == 0 && preferAbsoluteOverRelativePath
589 && (preferAuthorityOverRelativePath
590 || !uriReference->getPath().matchAsciiL(
591 RTL_CONSTASCII_STRINGPARAM("//"))))
592 {
593 if (baseUriReference->getPath().getLength() > 1
594 || uriReference->getPath().getLength() > 1)
595 {
596 if (uriReference->getPath().getLength() == 0) {
597 rel.append(static_cast< sal_Unicode >('/'));
598 } else {
599 OSL_ASSERT(uriReference->getPath()[0] == '/');
600 if (uriReference->getPath().matchAsciiL(
601 RTL_CONSTASCII_STRINGPARAM("//"))) {
602 OSL_ASSERT(uriReference->hasAuthority());
603 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
604 rel.append(uriReference->getAuthority());
605 }
606 rel.append(uriReference->getPath());
607 }
608 }
609 } else {
610 bool segments = false;
611 for (sal_Int32 j = i; j < count1 - 1; ++j) {
612 if (segments) {
613 rel.append(static_cast< sal_Unicode >('/'));
614 }
615 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM(".."));
616 segments = true;
617 }
618 if (i < count2 - 1
619 || (uriReference->getPathSegment(count2 - 1).getLength()
620 != 0))
621 {
622 if (!segments
623 && (uriReference->getPathSegment(i).getLength() == 0
624 || (parseScheme(uriReference->getPathSegment(i))
625 >= 0)))
626 {
627 rel.append(static_cast< sal_Unicode >('.'));
628 segments = true;
629 }
630 for (; i < count2; ++i) {
631 if (segments) {
632 rel.append(static_cast< sal_Unicode >('/'));
633 }
634 rtl::OUString s(uriReference->getPathSegment(i));
635 if (encodeRetainedSpecialSegments
636 && s.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".")))
637 {
638 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("%2E"));
639 } else if (encodeRetainedSpecialSegments
640 && s.equalsAsciiL(
641 RTL_CONSTASCII_STRINGPARAM("..")))
642 {
643 rel.appendAscii(
644 RTL_CONSTASCII_STRINGPARAM("%2E%2E"));
645 } else {
646 rel.append(s);
647 }
648 segments = true;
649 }
650 }
651 }
652 }
653 if (!omitQuery && uriReference->hasQuery()) {
654 rel.append(static_cast< sal_Unicode >('?'));
655 rel.append(uriReference->getQuery());
656 }
657 if (uriReference->hasFragment()) {
658 rel.append(static_cast< sal_Unicode >('#'));
659 rel.append(uriReference->getFragment());
660 }
661 return parse(rel.makeStringAndClear());
662 }
663 }
664
665 }
666
667 namespace stoc_services { namespace UriReferenceFactory {
668
create(css::uno::Reference<css::uno::XComponentContext> const & context)669 css::uno::Reference< css::uno::XInterface > create(
670 css::uno::Reference< css::uno::XComponentContext > const & context)
671 {
672 try {
673 return static_cast< cppu::OWeakObject * >(new Factory(context));
674 } catch (std::bad_alloc &) {
675 throw css::uno::RuntimeException(
676 rtl::OUString::createFromAscii("std::bad_alloc"), 0);
677 }
678 }
679
getImplementationName()680 rtl::OUString getImplementationName() {
681 return rtl::OUString::createFromAscii(
682 "com.sun.star.comp.uri.UriReferenceFactory");
683 }
684
getSupportedServiceNames()685 css::uno::Sequence< rtl::OUString > getSupportedServiceNames() {
686 css::uno::Sequence< rtl::OUString > s(1);
687 s[0] = rtl::OUString::createFromAscii(
688 "com.sun.star.uri.UriReferenceFactory");
689 return s;
690 }
691
692 } }
693