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 64 bool isDigit(sal_Unicode c) { //TODO: generally available? 65 return c >= '0' && c <= '9'; 66 } 67 68 bool isUpperCase(sal_Unicode c) { //TODO: generally available? 69 return c >= 'A' && c <= 'Z'; 70 } 71 72 bool isLowerCase(sal_Unicode c) { //TODO: generally available? 73 return c >= 'a' && c <= 'z'; 74 } 75 76 bool isAlpha(sal_Unicode c) { //TODO: generally available? 77 return isUpperCase(c) || isLowerCase(c); 78 } 79 80 bool isHexDigit(sal_Unicode c) { //TODO: generally available? 81 return isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); 82 } 83 84 sal_Unicode toLowerCase(sal_Unicode c) { //TODO: generally available? 85 return isUpperCase(c) ? c + ('a' - 'A') : c; 86 } 87 88 bool equalIgnoreCase(sal_Unicode c1, sal_Unicode c2) { 89 //TODO: generally available? 90 return toLowerCase(c1) == toLowerCase(c2); 91 } 92 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 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: 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 142 virtual rtl::OUString SAL_CALL getUriReference() 143 throw (com::sun::star::uno::RuntimeException) 144 { return m_base.getUriReference(); } 145 146 virtual sal_Bool SAL_CALL isAbsolute() 147 throw (com::sun::star::uno::RuntimeException) 148 { return m_base.isAbsolute(); } 149 150 virtual rtl::OUString SAL_CALL getScheme() 151 throw (com::sun::star::uno::RuntimeException) 152 { return m_base.getScheme(); } 153 154 virtual rtl::OUString SAL_CALL getSchemeSpecificPart() 155 throw (com::sun::star::uno::RuntimeException) 156 { return m_base.getSchemeSpecificPart(); } 157 158 virtual sal_Bool SAL_CALL isHierarchical() 159 throw (com::sun::star::uno::RuntimeException) 160 { return m_base.isHierarchical(); } 161 162 virtual sal_Bool SAL_CALL hasAuthority() 163 throw (com::sun::star::uno::RuntimeException) 164 { return m_base.hasAuthority(); } 165 166 virtual rtl::OUString SAL_CALL getAuthority() 167 throw (com::sun::star::uno::RuntimeException) 168 { return m_base.getAuthority(); } 169 170 virtual rtl::OUString SAL_CALL getPath() 171 throw (com::sun::star::uno::RuntimeException) 172 { return m_base.getPath(); } 173 174 virtual sal_Bool SAL_CALL hasRelativePath() 175 throw (com::sun::star::uno::RuntimeException) 176 { return m_base.hasRelativePath(); } 177 178 virtual sal_Int32 SAL_CALL getPathSegmentCount() 179 throw (com::sun::star::uno::RuntimeException) 180 { return m_base.getPathSegmentCount(); } 181 182 virtual rtl::OUString SAL_CALL getPathSegment(sal_Int32 index) 183 throw (com::sun::star::uno::RuntimeException) 184 { return m_base.getPathSegment(index); } 185 186 virtual sal_Bool SAL_CALL hasQuery() 187 throw (com::sun::star::uno::RuntimeException) 188 { return m_base.hasQuery(); } 189 190 virtual rtl::OUString SAL_CALL getQuery() 191 throw (com::sun::star::uno::RuntimeException) 192 { return m_base.getQuery(); } 193 194 virtual sal_Bool SAL_CALL hasFragment() 195 throw (com::sun::star::uno::RuntimeException) 196 { return m_base.hasFragment(); } 197 198 virtual rtl::OUString SAL_CALL getFragment() 199 throw (com::sun::star::uno::RuntimeException) 200 { return m_base.getFragment(); } 201 202 virtual void SAL_CALL setFragment(rtl::OUString const & fragment) 203 throw (com::sun::star::uno::RuntimeException) 204 { m_base.setFragment(fragment); } 205 206 virtual void SAL_CALL clearFragment() 207 throw (com::sun::star::uno::RuntimeException) 208 { m_base.clearFragment(); } 209 210 private: 211 UriReference(UriReference &); // not implemented 212 void operator =(UriReference); // not implemented 213 214 virtual ~UriReference() {} 215 216 stoc::uriproc::UriReference m_base; 217 }; 218 219 // throws std::bad_alloc 220 css::uno::Reference< css::uri::XUriReference > parseGeneric( 221 rtl::OUString const & scheme, rtl::OUString const & schemeSpecificPart) 222 { 223 bool isAbsolute = scheme.getLength() != 0; 224 bool isHierarchical 225 = !isAbsolute 226 || (schemeSpecificPart.getLength() > 0 && schemeSpecificPart[0] == '/'); 227 bool hasAuthority = false; 228 rtl::OUString authority; 229 rtl::OUString path; 230 bool hasQuery = false; 231 rtl::OUString query; 232 if (isHierarchical) { 233 sal_Int32 len = schemeSpecificPart.getLength(); 234 sal_Int32 i = 0; 235 if (len - i >= 2 && schemeSpecificPart[i] == '/' 236 && schemeSpecificPart[i + 1] == '/') 237 { 238 i += 2; 239 sal_Int32 n = i; 240 while (i < len && schemeSpecificPart[i] != '/' 241 && schemeSpecificPart[i] != '?') { 242 ++i; 243 } 244 hasAuthority = true; 245 authority = schemeSpecificPart.copy(n, i - n); 246 } 247 sal_Int32 n = i; 248 i = schemeSpecificPart.indexOf('?', i); 249 if (i == -1) { 250 i = len; 251 } 252 path = schemeSpecificPart.copy(n, i - n); 253 if (i != len) { 254 hasQuery = true; 255 query = schemeSpecificPart.copy(i + 1); 256 } 257 } else { 258 if (schemeSpecificPart.getLength() == 0) { 259 // The scheme-specific part of an opaque URI must not be empty: 260 return 0; 261 } 262 path = schemeSpecificPart; 263 } 264 return new UriReference( 265 scheme, isHierarchical, hasAuthority, authority, path, hasQuery, query); 266 } 267 268 typedef std::vector< sal_Int32 > Segments; 269 270 void processSegments( 271 Segments & segments, 272 css::uno::Reference< css::uri::XUriReference > const & uriReference, 273 bool base, bool processSpecialSegments) 274 { 275 sal_Int32 count = uriReference->getPathSegmentCount() - (base ? 1 : 0); 276 OSL_ASSERT(count <= SAL_MAX_INT32 - 1 && -count >= SAL_MIN_INT32 + 1); 277 for (sal_Int32 i = 0; i < count; ++i) { 278 if (processSpecialSegments) { 279 rtl::OUString segment(uriReference->getPathSegment(i)); 280 if (segment.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("."))) { 281 if (!base && i == count - 1) { 282 segments.push_back(0); 283 } 284 continue; 285 } else if (segment.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".."))) { 286 if (segments.empty() 287 || /*MSVC trouble: std::*/abs(segments.back()) == 1) 288 { 289 segments.push_back(base ? -1 : 1); 290 } else { 291 segments.pop_back(); 292 } 293 continue; 294 } 295 } 296 segments.push_back(base ? -(i + 2) : i + 2); 297 } 298 } 299 300 class Factory: public cppu::WeakImplHelper2< 301 css::lang::XServiceInfo, css::uri::XUriReferenceFactory > 302 { 303 public: 304 explicit Factory( 305 css::uno::Reference< css::uno::XComponentContext > const & context): 306 m_context(context) {} 307 308 virtual rtl::OUString SAL_CALL getImplementationName() 309 throw (css::uno::RuntimeException); 310 311 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName) 312 throw (css::uno::RuntimeException); 313 314 virtual css::uno::Sequence< rtl::OUString > SAL_CALL 315 getSupportedServiceNames() throw (css::uno::RuntimeException); 316 317 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL 318 parse(rtl::OUString const & uriReference) 319 throw (css::uno::RuntimeException); 320 321 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL 322 makeAbsolute( 323 css::uno::Reference< css::uri::XUriReference > const & baseUriReference, 324 css::uno::Reference< css::uri::XUriReference > const & uriReference, 325 sal_Bool processSpecialBaseSegments, 326 css::uri::RelativeUriExcessParentSegments excessParentSegments) 327 throw (css::uno::RuntimeException); 328 329 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL 330 makeRelative( 331 css::uno::Reference< css::uri::XUriReference > const & baseUriReference, 332 css::uno::Reference< css::uri::XUriReference > const & uriReference, 333 sal_Bool preferAuthorityOverRelativePath, 334 sal_Bool preferAbsoluteOverRelativePath, 335 sal_Bool encodeRetainedSpecialSegments) 336 throw (css::uno::RuntimeException); 337 338 private: 339 Factory(Factory &); // not implemented 340 void operator =(Factory); // not implemented 341 342 virtual ~Factory() {} 343 344 css::uno::Reference< css::uri::XUriReference > clone( 345 css::uno::Reference< css::uri::XUriReference > const & uriReference) 346 { return parse(uriReference->getUriReference()); } 347 348 css::uno::Reference< css::uno::XComponentContext > m_context; 349 }; 350 351 rtl::OUString Factory::getImplementationName() 352 throw (css::uno::RuntimeException) 353 { 354 return stoc_services::UriReferenceFactory::getImplementationName(); 355 } 356 357 sal_Bool Factory::supportsService(rtl::OUString const & serviceName) 358 throw (css::uno::RuntimeException) 359 { 360 return stoc::uriproc::supportsService( 361 getSupportedServiceNames(), serviceName); 362 } 363 364 css::uno::Sequence< rtl::OUString > Factory::getSupportedServiceNames() 365 throw (css::uno::RuntimeException) 366 { 367 return stoc_services::UriReferenceFactory::getSupportedServiceNames(); 368 } 369 370 css::uno::Reference< css::uri::XUriReference > Factory::parse( 371 rtl::OUString const & uriReference) throw (css::uno::RuntimeException) 372 { 373 sal_Int32 fragment = uriReference.indexOf('#'); 374 if (fragment == -1) { 375 fragment = uriReference.getLength(); 376 } 377 rtl::OUString scheme; 378 rtl::OUString schemeSpecificPart; 379 rtl::OUString serviceName; 380 sal_Int32 n = parseScheme(uriReference); 381 OSL_ASSERT(n < fragment); 382 if (n >= 0) { 383 scheme = uriReference.copy(0, n); 384 schemeSpecificPart = uriReference.copy(n + 1, fragment - (n + 1)); 385 rtl::OUStringBuffer buf; 386 buf.appendAscii( 387 RTL_CONSTASCII_STRINGPARAM("com.sun.star.uri.UriSchemeParser_")); 388 for (sal_Int32 i = 0; i < scheme.getLength(); ++i) { 389 sal_Unicode c = scheme[i]; 390 if (isUpperCase(c)) { 391 buf.append(toLowerCase(c)); 392 } else if (c == '+') { 393 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("PLUS")); 394 } else if (c == '-') { 395 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("HYPHEN")); 396 } else if (c == '.') { 397 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("DOT")); 398 } else { 399 OSL_ASSERT(isLowerCase(c) || isDigit(c)); 400 buf.append(c); 401 } 402 } 403 serviceName = buf.makeStringAndClear(); 404 } else { 405 schemeSpecificPart = uriReference.copy(0, fragment); 406 } 407 css::uno::Reference< css::uri::XUriSchemeParser > parser; 408 if (serviceName.getLength() != 0) { 409 css::uno::Reference< css::lang::XMultiComponentFactory > factory( 410 m_context->getServiceManager()); 411 if (factory.is()) { 412 css::uno::Reference< css::uno::XInterface > service; 413 try { 414 service = factory->createInstanceWithContext( 415 serviceName, m_context); 416 } catch (css::uno::RuntimeException &) { 417 throw; 418 } catch (css::uno::Exception & e) { 419 throw css::lang::WrappedTargetRuntimeException( 420 rtl::OUString::createFromAscii("creating service ") 421 + serviceName, 422 static_cast< cppu::OWeakObject * >(this), 423 css::uno::makeAny(e)); //TODO: preserve type of e 424 } 425 if (service.is()) { 426 parser = css::uno::Reference< css::uri::XUriSchemeParser >( 427 service, css::uno::UNO_QUERY_THROW); 428 } 429 } 430 } 431 css::uno::Reference< css::uri::XUriReference > uriRef; 432 if (parser.is()) { 433 uriRef = parser->parse(scheme, schemeSpecificPart); 434 } else { 435 try { 436 uriRef = parseGeneric(scheme, schemeSpecificPart); 437 } catch (std::bad_alloc &) { 438 throw css::uno::RuntimeException( 439 rtl::OUString::createFromAscii("std::bad_alloc"), 440 static_cast< cppu::OWeakObject * >(this)); 441 } 442 } 443 if (uriRef.is() && fragment != uriReference.getLength()) { 444 uriRef->setFragment(uriReference.copy(fragment + 1)); 445 } 446 return uriRef; 447 } 448 449 css::uno::Reference< css::uri::XUriReference > Factory::makeAbsolute( 450 css::uno::Reference< css::uri::XUriReference > const & baseUriReference, 451 css::uno::Reference< css::uri::XUriReference > const & uriReference, 452 sal_Bool processSpecialBaseSegments, 453 css::uri::RelativeUriExcessParentSegments excessParentSegments) 454 throw (css::uno::RuntimeException) 455 { 456 if (!baseUriReference.is() || !baseUriReference->isAbsolute() 457 || !baseUriReference->isHierarchical() || !uriReference.is()) { 458 return 0; 459 } else if (uriReference->isAbsolute()) { 460 return clone(uriReference); 461 } else if (!uriReference->hasAuthority() 462 && uriReference->getPath().getLength() == 0 463 && !uriReference->hasQuery()) { 464 css::uno::Reference< css::uri::XUriReference > abs( 465 clone(baseUriReference)); 466 if (uriReference->hasFragment()) { 467 abs->setFragment(uriReference->getFragment()); 468 } else { 469 abs->clearFragment(); 470 } 471 return abs; 472 } else { 473 rtl::OUStringBuffer abs(baseUriReference->getScheme()); 474 abs.append(static_cast< sal_Unicode >(':')); 475 if (uriReference->hasAuthority()) { 476 abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 477 abs.append(uriReference->getAuthority()); 478 } else if (baseUriReference->hasAuthority()) { 479 abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 480 abs.append(baseUriReference->getAuthority()); 481 } 482 if (uriReference->hasRelativePath()) { 483 Segments segments; 484 processSegments( 485 segments, baseUriReference, true, processSpecialBaseSegments); 486 processSegments(segments, uriReference, false, true); 487 // If the path component of the base URI reference is empty (which 488 // implies that the base URI reference denotes a "root entity"), and 489 // the resulting URI reference denotes the same root entity, make 490 // sure the path component of the resulting URI reference is also 491 // empty (and not "/"). RFC 2396 is unclear about this, and I chose 492 // these rules for consistent results. 493 bool slash = baseUriReference->getPath().getLength() != 0; 494 if (slash) { 495 abs.append(static_cast< sal_Unicode >('/')); 496 } 497 for (Segments::iterator i(segments.begin()); i != segments.end(); 498 ++i) 499 { 500 if (*i < -1) { 501 rtl::OUString segment( 502 baseUriReference->getPathSegment(-(*i + 2))); 503 if (segment.getLength() != 0 || segments.size() > 1) { 504 if (!slash) { 505 abs.append(static_cast< sal_Unicode >('/')); 506 } 507 abs.append(segment); 508 slash = true; 509 abs.append(static_cast< sal_Unicode >('/')); 510 } 511 } else if (*i > 1) { 512 rtl::OUString segment(uriReference->getPathSegment(*i - 2)); 513 if (segment.getLength() != 0 || segments.size() > 1) { 514 if (!slash) { 515 abs.append(static_cast< sal_Unicode >('/')); 516 } 517 abs.append(segment); 518 slash = false; 519 } 520 } else if (*i == 0) { 521 if (segments.size() > 1 && !slash) { 522 abs.append(static_cast< sal_Unicode >('/')); 523 } 524 } else { 525 switch (excessParentSegments) { 526 case css::uri::RelativeUriExcessParentSegments_ERROR: 527 return 0; 528 529 case css::uri::RelativeUriExcessParentSegments_RETAIN: 530 if (!slash) { 531 abs.append(static_cast< sal_Unicode >('/')); 532 } 533 abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("..")); 534 slash = *i < 0; 535 if (slash) { 536 abs.append(static_cast< sal_Unicode >('/')); 537 } 538 break; 539 540 case css::uri::RelativeUriExcessParentSegments_REMOVE: 541 break; 542 543 default: 544 OSL_ASSERT(false); 545 break; 546 } 547 } 548 } 549 } else { 550 abs.append(uriReference->getPath()); 551 } 552 if (uriReference->hasQuery()) { 553 abs.append(static_cast< sal_Unicode >('?')); 554 abs.append(uriReference->getQuery()); 555 } 556 if (uriReference->hasFragment()) { 557 abs.append(static_cast< sal_Unicode >('#')); 558 abs.append(uriReference->getFragment()); 559 } 560 return parse(abs.makeStringAndClear()); 561 } 562 } 563 564 css::uno::Reference< css::uri::XUriReference > Factory::makeRelative( 565 css::uno::Reference< css::uri::XUriReference > const & baseUriReference, 566 css::uno::Reference< css::uri::XUriReference > const & uriReference, 567 sal_Bool preferAuthorityOverRelativePath, 568 sal_Bool preferAbsoluteOverRelativePath, 569 sal_Bool encodeRetainedSpecialSegments) 570 throw (css::uno::RuntimeException) 571 { 572 if (!baseUriReference.is() || !baseUriReference->isAbsolute() 573 || !baseUriReference->isHierarchical() || !uriReference.is()) { 574 return 0; 575 } else if (!uriReference->isAbsolute() || !uriReference->isHierarchical() 576 || !baseUriReference->getScheme().equalsIgnoreAsciiCase( 577 uriReference->getScheme())) { 578 return clone(uriReference); 579 } else { 580 rtl::OUStringBuffer rel; 581 bool omitQuery = false; 582 if ((baseUriReference->hasAuthority() != uriReference->hasAuthority()) 583 || !equalIgnoreEscapeCase( 584 baseUriReference->getAuthority(), 585 uriReference->getAuthority())) 586 { 587 if (uriReference->hasAuthority()) { 588 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 589 rel.append(uriReference->getAuthority()); 590 } 591 rel.append(uriReference->getPath()); 592 } else if ((equalIgnoreEscapeCase( 593 baseUriReference->getPath(), uriReference->getPath()) 594 || (baseUriReference->getPath().getLength() <= 1 595 && uriReference->getPath().getLength() <= 1)) 596 && baseUriReference->hasQuery() == uriReference->hasQuery() 597 && equalIgnoreEscapeCase( 598 baseUriReference->getQuery(), uriReference->getQuery())) 599 { 600 omitQuery = true; 601 } else { 602 sal_Int32 count1 = std::max< sal_Int32 >( 603 baseUriReference->getPathSegmentCount(), 1); 604 sal_Int32 count2 = std::max< sal_Int32 >( 605 uriReference->getPathSegmentCount(), 1); 606 sal_Int32 i = 0; 607 for (; i < std::min(count1, count2) - 1; ++i) { 608 if (!equalIgnoreEscapeCase( 609 baseUriReference->getPathSegment(i), 610 uriReference->getPathSegment(i))) 611 { 612 break; 613 } 614 } 615 if (i == 0 && preferAbsoluteOverRelativePath 616 && (preferAuthorityOverRelativePath 617 || !uriReference->getPath().matchAsciiL( 618 RTL_CONSTASCII_STRINGPARAM("//")))) 619 { 620 if (baseUriReference->getPath().getLength() > 1 621 || uriReference->getPath().getLength() > 1) 622 { 623 if (uriReference->getPath().getLength() == 0) { 624 rel.append(static_cast< sal_Unicode >('/')); 625 } else { 626 OSL_ASSERT(uriReference->getPath()[0] == '/'); 627 if (uriReference->getPath().matchAsciiL( 628 RTL_CONSTASCII_STRINGPARAM("//"))) { 629 OSL_ASSERT(uriReference->hasAuthority()); 630 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); 631 rel.append(uriReference->getAuthority()); 632 } 633 rel.append(uriReference->getPath()); 634 } 635 } 636 } else { 637 bool segments = false; 638 for (sal_Int32 j = i; j < count1 - 1; ++j) { 639 if (segments) { 640 rel.append(static_cast< sal_Unicode >('/')); 641 } 642 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("..")); 643 segments = true; 644 } 645 if (i < count2 - 1 646 || (uriReference->getPathSegment(count2 - 1).getLength() 647 != 0)) 648 { 649 if (!segments 650 && (uriReference->getPathSegment(i).getLength() == 0 651 || (parseScheme(uriReference->getPathSegment(i)) 652 >= 0))) 653 { 654 rel.append(static_cast< sal_Unicode >('.')); 655 segments = true; 656 } 657 for (; i < count2; ++i) { 658 if (segments) { 659 rel.append(static_cast< sal_Unicode >('/')); 660 } 661 rtl::OUString s(uriReference->getPathSegment(i)); 662 if (encodeRetainedSpecialSegments 663 && s.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("."))) 664 { 665 rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("%2E")); 666 } else if (encodeRetainedSpecialSegments 667 && s.equalsAsciiL( 668 RTL_CONSTASCII_STRINGPARAM(".."))) 669 { 670 rel.appendAscii( 671 RTL_CONSTASCII_STRINGPARAM("%2E%2E")); 672 } else { 673 rel.append(s); 674 } 675 segments = true; 676 } 677 } 678 } 679 } 680 if (!omitQuery && uriReference->hasQuery()) { 681 rel.append(static_cast< sal_Unicode >('?')); 682 rel.append(uriReference->getQuery()); 683 } 684 if (uriReference->hasFragment()) { 685 rel.append(static_cast< sal_Unicode >('#')); 686 rel.append(uriReference->getFragment()); 687 } 688 return parse(rel.makeStringAndClear()); 689 } 690 } 691 692 } 693 694 namespace stoc_services { namespace UriReferenceFactory { 695 696 css::uno::Reference< css::uno::XInterface > create( 697 css::uno::Reference< css::uno::XComponentContext > const & context) 698 SAL_THROW((css::uno::Exception)) 699 { 700 try { 701 return static_cast< cppu::OWeakObject * >(new Factory(context)); 702 } catch (std::bad_alloc &) { 703 throw css::uno::RuntimeException( 704 rtl::OUString::createFromAscii("std::bad_alloc"), 0); 705 } 706 } 707 708 rtl::OUString getImplementationName() { 709 return rtl::OUString::createFromAscii( 710 "com.sun.star.comp.uri.UriReferenceFactory"); 711 } 712 713 css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { 714 css::uno::Sequence< rtl::OUString > s(1); 715 s[0] = rtl::OUString::createFromAscii( 716 "com.sun.star.uri.UriReferenceFactory"); 717 return s; 718 } 719 720 } } 721