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