1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "stocservices.hxx"
23 #include "UriReference.hxx"
24 #include "supportsService.hxx"
26 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
27 #include "com/sun/star/lang/XMultiComponentFactory.hpp"
28 #include "com/sun/star/lang/XServiceInfo.hpp"
29 #include "com/sun/star/uno/Any.hxx"
30 #include "com/sun/star/uno/Exception.hpp"
31 #include "com/sun/star/uno/Reference.hxx"
32 #include "com/sun/star/uno/RuntimeException.hpp"
33 #include "com/sun/star/uno/Sequence.hxx"
34 #include "com/sun/star/uno/XComponentContext.hpp"
35 #include "com/sun/star/uno/XInterface.hpp"
36 #include "com/sun/star/uri/RelativeUriExcessParentSegments.hpp"
37 #include "com/sun/star/uri/XUriReference.hpp"
38 #include "com/sun/star/uri/XUriReferenceFactory.hpp"
39 #include "com/sun/star/uri/XUriSchemeParser.hpp"
40 #include "cppuhelper/implbase1.hxx"
41 #include "cppuhelper/implbase2.hxx"
42 #include "cppuhelper/weak.hxx"
43 #include "osl/diagnose.h"
44 #include "rtl/character.hxx"
45 #include "rtl/string.h"
46 #include "rtl/ustrbuf.hxx"
47 #include "rtl/ustring.hxx"
48 #include "sal/types.h"
51 #include /*MSVC trouble: <cstdlib>*/ <stdlib.h>
57 //TODO: move comphelper::string::misc into something like
58 //sal/salhelper and use those instead
60 sal_Unicode
toLowerCase(sal_Unicode c
) {
61 return rtl::isAsciiUpperCase(c
) ? c
+ ('a' - 'A') : c
;
64 bool equalIgnoreCase(sal_Unicode c1
, sal_Unicode c2
) {
65 return toLowerCase(c1
) == toLowerCase(c2
);
68 bool equalIgnoreEscapeCase(OUString
const & s1
, OUString
const & s2
) {
69 if (s1
.getLength() == s2
.getLength()) {
70 for (sal_Int32 i
= 0; i
< s1
.getLength();) {
71 if (s1
[i
] == '%' && s2
[i
] == '%' && s1
.getLength() - i
> 2
72 && rtl::isAsciiHexDigit(s1
[i
+ 1]) && rtl::isAsciiHexDigit(s1
[i
+ 2])
73 && rtl::isAsciiHexDigit(s2
[i
+ 1]) && rtl::isAsciiHexDigit(s2
[i
+ 2])
74 && equalIgnoreCase(s1
[i
+ 1], s2
[i
+ 1])
75 && equalIgnoreCase(s1
[i
+ 2], s2
[i
+ 2]))
78 } else if (s1
[i
] != s2
[i
]) {
90 sal_Int32
parseScheme(OUString
const & uriReference
) {
91 if (uriReference
.getLength() >= 2 && rtl::isAsciiAlpha(uriReference
[0])) {
92 for (sal_Int32 i
= 0; i
< uriReference
.getLength(); ++i
) {
93 sal_Unicode c
= uriReference
[i
];
96 } else if (!rtl::isAsciiAlpha(c
) && !rtl::isAsciiDigit(c
) && c
!= '+' && c
!= '-'
106 class UriReference
: public cppu::WeakImplHelper1
< css::uri::XUriReference
> {
109 OUString
const & scheme
, bool bIsHierarchical
, bool bHasAuthority
,
110 OUString
const & authority
, OUString
const & path
,
111 bool bHasQuery
, OUString
const & query
):
113 scheme
, bIsHierarchical
, bHasAuthority
, authority
, path
, bHasQuery
,
117 virtual OUString SAL_CALL
getUriReference()
118 throw (com::sun::star::uno::RuntimeException
)
119 { return m_base
.getUriReference(); }
121 virtual sal_Bool SAL_CALL
isAbsolute()
122 throw (com::sun::star::uno::RuntimeException
)
123 { return m_base
.isAbsolute(); }
125 virtual OUString SAL_CALL
getScheme()
126 throw (com::sun::star::uno::RuntimeException
)
127 { return m_base
.getScheme(); }
129 virtual OUString SAL_CALL
getSchemeSpecificPart()
130 throw (com::sun::star::uno::RuntimeException
)
131 { return m_base
.getSchemeSpecificPart(); }
133 virtual sal_Bool SAL_CALL
isHierarchical()
134 throw (com::sun::star::uno::RuntimeException
)
135 { return m_base
.isHierarchical(); }
137 virtual sal_Bool SAL_CALL
hasAuthority()
138 throw (com::sun::star::uno::RuntimeException
)
139 { return m_base
.hasAuthority(); }
141 virtual OUString SAL_CALL
getAuthority()
142 throw (com::sun::star::uno::RuntimeException
)
143 { return m_base
.getAuthority(); }
145 virtual OUString SAL_CALL
getPath()
146 throw (com::sun::star::uno::RuntimeException
)
147 { return m_base
.getPath(); }
149 virtual sal_Bool SAL_CALL
hasRelativePath()
150 throw (com::sun::star::uno::RuntimeException
)
151 { return m_base
.hasRelativePath(); }
153 virtual sal_Int32 SAL_CALL
getPathSegmentCount()
154 throw (com::sun::star::uno::RuntimeException
)
155 { return m_base
.getPathSegmentCount(); }
157 virtual OUString SAL_CALL
getPathSegment(sal_Int32 index
)
158 throw (com::sun::star::uno::RuntimeException
)
159 { return m_base
.getPathSegment(index
); }
161 virtual sal_Bool SAL_CALL
hasQuery()
162 throw (com::sun::star::uno::RuntimeException
)
163 { return m_base
.hasQuery(); }
165 virtual OUString SAL_CALL
getQuery()
166 throw (com::sun::star::uno::RuntimeException
)
167 { return m_base
.getQuery(); }
169 virtual sal_Bool SAL_CALL
hasFragment()
170 throw (com::sun::star::uno::RuntimeException
)
171 { return m_base
.hasFragment(); }
173 virtual OUString SAL_CALL
getFragment()
174 throw (com::sun::star::uno::RuntimeException
)
175 { return m_base
.getFragment(); }
177 virtual void SAL_CALL
setFragment(OUString
const & fragment
)
178 throw (com::sun::star::uno::RuntimeException
)
179 { m_base
.setFragment(fragment
); }
181 virtual void SAL_CALL
clearFragment()
182 throw (com::sun::star::uno::RuntimeException
)
183 { m_base
.clearFragment(); }
186 UriReference(UriReference
&); // not implemented
187 void operator =(UriReference
); // not implemented
189 virtual ~UriReference() {}
191 stoc::uriproc::UriReference m_base
;
194 // throws std::bad_alloc
195 css::uno::Reference
< css::uri::XUriReference
> parseGeneric(
196 OUString
const & scheme
, OUString
const & schemeSpecificPart
)
198 bool isAbsolute
= !scheme
.isEmpty();
201 || (!schemeSpecificPart
.isEmpty() && schemeSpecificPart
[0] == '/');
202 bool hasAuthority
= false;
205 bool hasQuery
= false;
207 if (isHierarchical
) {
208 sal_Int32 len
= schemeSpecificPart
.getLength();
210 if (len
- i
>= 2 && schemeSpecificPart
[i
] == '/'
211 && schemeSpecificPart
[i
+ 1] == '/')
215 while (i
< len
&& schemeSpecificPart
[i
] != '/'
216 && schemeSpecificPart
[i
] != '?') {
220 authority
= schemeSpecificPart
.copy(n
, i
- n
);
223 i
= schemeSpecificPart
.indexOf('?', i
);
227 path
= schemeSpecificPart
.copy(n
, i
- n
);
230 query
= schemeSpecificPart
.copy(i
+ 1);
233 if (schemeSpecificPart
.isEmpty()) {
234 // The scheme-specific part of an opaque URI must not be empty:
237 path
= schemeSpecificPart
;
239 return new UriReference(
240 scheme
, isHierarchical
, hasAuthority
, authority
, path
, hasQuery
, query
);
243 typedef std::vector
< sal_Int32
> Segments
;
245 void processSegments(
247 css::uno::Reference
< css::uri::XUriReference
> const & uriReference
,
248 bool base
, bool processSpecialSegments
)
250 sal_Int32 count
= uriReference
->getPathSegmentCount() - (base
? 1 : 0);
251 OSL_ASSERT(count
<= SAL_MAX_INT32
- 1 && -count
>= SAL_MIN_INT32
+ 1);
252 for (sal_Int32 i
= 0; i
< count
; ++i
) {
253 if (processSpecialSegments
) {
254 OUString
segment(uriReference
->getPathSegment(i
));
255 if ( segment
== "." ) {
256 if (!base
&& i
== count
- 1) {
257 segments
.push_back(0);
260 } else if ( segment
== ".." ) {
262 || /*MSVC trouble: std::*/abs(segments
.back()) == 1)
264 segments
.push_back(base
? -1 : 1);
271 segments
.push_back(base
? -(i
+ 2) : i
+ 2);
275 class Factory
: public cppu::WeakImplHelper2
<
276 css::lang::XServiceInfo
, css::uri::XUriReferenceFactory
>
280 css::uno::Reference
< css::uno::XComponentContext
> const & context
):
281 m_context(context
) {}
283 virtual OUString SAL_CALL
getImplementationName()
284 throw (css::uno::RuntimeException
);
286 virtual sal_Bool SAL_CALL
supportsService(OUString
const & serviceName
)
287 throw (css::uno::RuntimeException
);
289 virtual css::uno::Sequence
< OUString
> SAL_CALL
290 getSupportedServiceNames() throw (css::uno::RuntimeException
);
292 virtual css::uno::Reference
< css::uri::XUriReference
> SAL_CALL
293 parse(OUString
const & uriReference
)
294 throw (css::uno::RuntimeException
);
296 virtual css::uno::Reference
< css::uri::XUriReference
> SAL_CALL
298 css::uno::Reference
< css::uri::XUriReference
> const & baseUriReference
,
299 css::uno::Reference
< css::uri::XUriReference
> const & uriReference
,
300 sal_Bool processSpecialBaseSegments
,
301 css::uri::RelativeUriExcessParentSegments excessParentSegments
)
302 throw (css::uno::RuntimeException
);
304 virtual css::uno::Reference
< css::uri::XUriReference
> SAL_CALL
306 css::uno::Reference
< css::uri::XUriReference
> const & baseUriReference
,
307 css::uno::Reference
< css::uri::XUriReference
> const & uriReference
,
308 sal_Bool preferAuthorityOverRelativePath
,
309 sal_Bool preferAbsoluteOverRelativePath
,
310 sal_Bool encodeRetainedSpecialSegments
)
311 throw (css::uno::RuntimeException
);
314 Factory(Factory
&); // not implemented
315 void operator =(Factory
); // not implemented
317 virtual ~Factory() {}
319 css::uno::Reference
< css::uri::XUriReference
> clone(
320 css::uno::Reference
< css::uri::XUriReference
> const & uriReference
)
321 { return parse(uriReference
->getUriReference()); }
323 css::uno::Reference
< css::uno::XComponentContext
> m_context
;
326 OUString
Factory::getImplementationName()
327 throw (css::uno::RuntimeException
)
329 return stoc_services::UriReferenceFactory::getImplementationName();
332 sal_Bool
Factory::supportsService(OUString
const & serviceName
)
333 throw (css::uno::RuntimeException
)
335 return stoc::uriproc::supportsService(
336 getSupportedServiceNames(), serviceName
);
339 css::uno::Sequence
< OUString
> Factory::getSupportedServiceNames()
340 throw (css::uno::RuntimeException
)
342 return stoc_services::UriReferenceFactory::getSupportedServiceNames();
345 css::uno::Reference
< css::uri::XUriReference
> Factory::parse(
346 OUString
const & uriReference
) throw (css::uno::RuntimeException
)
348 sal_Int32 fragment
= uriReference
.indexOf('#');
349 if (fragment
== -1) {
350 fragment
= uriReference
.getLength();
353 OUString schemeSpecificPart
;
354 OUString serviceName
;
355 sal_Int32 n
= parseScheme(uriReference
);
356 OSL_ASSERT(n
< fragment
);
358 scheme
= uriReference
.copy(0, n
);
359 schemeSpecificPart
= uriReference
.copy(n
+ 1, fragment
- (n
+ 1));
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 (rtl::isAsciiUpperCase(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"));
374 OSL_ASSERT(rtl::isAsciiLowerCase(c
) || rtl::isAsciiDigit(c
));
378 serviceName
= buf
.makeStringAndClear();
380 schemeSpecificPart
= uriReference
.copy(0, fragment
);
382 css::uno::Reference
< css::uri::XUriSchemeParser
> parser
;
383 if (!serviceName
.isEmpty()) {
384 css::uno::Reference
< css::lang::XMultiComponentFactory
> factory(
385 m_context
->getServiceManager());
387 css::uno::Reference
< css::uno::XInterface
> service
;
389 service
= factory
->createInstanceWithContext(
390 serviceName
, m_context
);
391 } catch (css::uno::RuntimeException
&) {
393 } catch (const css::uno::Exception
& e
) {
394 throw css::lang::WrappedTargetRuntimeException(
395 OUString("creating service ")
397 static_cast< cppu::OWeakObject
* >(this),
398 css::uno::makeAny(e
)); //TODO: preserve type of e
401 parser
= css::uno::Reference
< css::uri::XUriSchemeParser
>(
402 service
, css::uno::UNO_QUERY_THROW
);
406 css::uno::Reference
< css::uri::XUriReference
> uriRef
;
408 uriRef
= parser
->parse(scheme
, schemeSpecificPart
);
411 uriRef
= parseGeneric(scheme
, schemeSpecificPart
);
412 } catch (std::bad_alloc
&) {
413 throw css::uno::RuntimeException(
414 OUString("std::bad_alloc"),
415 static_cast< cppu::OWeakObject
* >(this));
418 if (uriRef
.is() && fragment
!= uriReference
.getLength()) {
419 uriRef
->setFragment(uriReference
.copy(fragment
+ 1));
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 throw (css::uno::RuntimeException
)
431 if (!baseUriReference
.is() || !baseUriReference
->isAbsolute()
432 || !baseUriReference
->isHierarchical() || !uriReference
.is()) {
434 } else if (uriReference
->isAbsolute()) {
435 return clone(uriReference
);
436 } else if (!uriReference
->hasAuthority()
437 && uriReference
->getPath().isEmpty()
438 && !uriReference
->hasQuery()) {
439 css::uno::Reference
< css::uri::XUriReference
> abs(
440 clone(baseUriReference
));
441 if (uriReference
->hasFragment()) {
442 abs
->setFragment(uriReference
->getFragment());
444 abs
->clearFragment();
448 OUStringBuffer
abs(baseUriReference
->getScheme());
449 abs
.append(static_cast< sal_Unicode
>(':'));
450 if (uriReference
->hasAuthority()) {
451 abs
.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
452 abs
.append(uriReference
->getAuthority());
453 } else if (baseUriReference
->hasAuthority()) {
454 abs
.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
455 abs
.append(baseUriReference
->getAuthority());
457 if (uriReference
->hasRelativePath()) {
460 segments
, baseUriReference
, true, processSpecialBaseSegments
);
461 processSegments(segments
, uriReference
, false, true);
462 // If the path component of the base URI reference is empty (which
463 // implies that the base URI reference denotes a "root entity"), and
464 // the resulting URI reference denotes the same root entity, make
465 // sure the path component of the resulting URI reference is also
466 // empty (and not "/"). RFC 2396 is unclear about this, and I chose
467 // these rules for consistent results.
468 bool slash
= !baseUriReference
->getPath().isEmpty();
470 abs
.append(static_cast< sal_Unicode
>('/'));
472 for (Segments::iterator
i(segments
.begin()); i
!= segments
.end();
477 baseUriReference
->getPathSegment(-(*i
+ 2)));
478 if (!segment
.isEmpty() || segments
.size() > 1) {
480 abs
.append(static_cast< sal_Unicode
>('/'));
484 abs
.append(static_cast< sal_Unicode
>('/'));
487 OUString
segment(uriReference
->getPathSegment(*i
- 2));
488 if (!segment
.isEmpty() || segments
.size() > 1) {
490 abs
.append(static_cast< sal_Unicode
>('/'));
495 } else if (*i
== 0) {
496 if (segments
.size() > 1 && !slash
) {
497 abs
.append(static_cast< sal_Unicode
>('/'));
500 switch (excessParentSegments
) {
501 case css::uri::RelativeUriExcessParentSegments_ERROR
:
504 case css::uri::RelativeUriExcessParentSegments_RETAIN
:
506 abs
.append(static_cast< sal_Unicode
>('/'));
508 abs
.appendAscii(RTL_CONSTASCII_STRINGPARAM(".."));
511 abs
.append(static_cast< sal_Unicode
>('/'));
515 case css::uri::RelativeUriExcessParentSegments_REMOVE
:
525 abs
.append(uriReference
->getPath());
527 if (uriReference
->hasQuery()) {
528 abs
.append(static_cast< sal_Unicode
>('?'));
529 abs
.append(uriReference
->getQuery());
531 if (uriReference
->hasFragment()) {
532 abs
.append(static_cast< sal_Unicode
>('#'));
533 abs
.append(uriReference
->getFragment());
535 return parse(abs
.makeStringAndClear());
539 css::uno::Reference
< css::uri::XUriReference
> Factory::makeRelative(
540 css::uno::Reference
< css::uri::XUriReference
> const & baseUriReference
,
541 css::uno::Reference
< css::uri::XUriReference
> const & uriReference
,
542 sal_Bool preferAuthorityOverRelativePath
,
543 sal_Bool preferAbsoluteOverRelativePath
,
544 sal_Bool encodeRetainedSpecialSegments
)
545 throw (css::uno::RuntimeException
)
547 if (!baseUriReference
.is() || !baseUriReference
->isAbsolute()
548 || !baseUriReference
->isHierarchical() || !uriReference
.is()) {
550 } else if (!uriReference
->isAbsolute() || !uriReference
->isHierarchical()
551 || !baseUriReference
->getScheme().equalsIgnoreAsciiCase(
552 uriReference
->getScheme())) {
553 return clone(uriReference
);
556 bool omitQuery
= false;
557 if ((baseUriReference
->hasAuthority() != uriReference
->hasAuthority())
558 || !equalIgnoreEscapeCase(
559 baseUriReference
->getAuthority(),
560 uriReference
->getAuthority()))
562 if (uriReference
->hasAuthority()) {
563 rel
.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
564 rel
.append(uriReference
->getAuthority());
566 rel
.append(uriReference
->getPath());
567 } else if ((equalIgnoreEscapeCase(
568 baseUriReference
->getPath(), uriReference
->getPath())
569 || (baseUriReference
->getPath().getLength() <= 1
570 && uriReference
->getPath().getLength() <= 1))
571 && baseUriReference
->hasQuery() == uriReference
->hasQuery()
572 && equalIgnoreEscapeCase(
573 baseUriReference
->getQuery(), uriReference
->getQuery()))
577 sal_Int32 count1
= std::max
< sal_Int32
>(
578 baseUriReference
->getPathSegmentCount(), 1);
579 sal_Int32 count2
= std::max
< sal_Int32
>(
580 uriReference
->getPathSegmentCount(), 1);
582 for (; i
< std::min(count1
, count2
) - 1; ++i
) {
583 if (!equalIgnoreEscapeCase(
584 baseUriReference
->getPathSegment(i
),
585 uriReference
->getPathSegment(i
)))
590 if (i
== 0 && preferAbsoluteOverRelativePath
591 && (preferAuthorityOverRelativePath
592 || !uriReference
->getPath().matchAsciiL(
593 RTL_CONSTASCII_STRINGPARAM("//"))))
595 if (baseUriReference
->getPath().getLength() > 1
596 || uriReference
->getPath().getLength() > 1)
598 if (uriReference
->getPath().isEmpty()) {
599 rel
.append(static_cast< sal_Unicode
>('/'));
601 OSL_ASSERT(uriReference
->getPath()[0] == '/');
602 if (uriReference
->getPath().matchAsciiL(
603 RTL_CONSTASCII_STRINGPARAM("//"))) {
604 OSL_ASSERT(uriReference
->hasAuthority());
605 rel
.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
606 rel
.append(uriReference
->getAuthority());
608 rel
.append(uriReference
->getPath());
612 bool segments
= false;
613 for (sal_Int32 j
= i
; j
< count1
- 1; ++j
) {
615 rel
.append(static_cast< sal_Unicode
>('/'));
617 rel
.appendAscii(RTL_CONSTASCII_STRINGPARAM(".."));
621 || (!uriReference
->getPathSegment(count2
- 1).isEmpty()))
624 && (uriReference
->getPathSegment(i
).isEmpty()
625 || (parseScheme(uriReference
->getPathSegment(i
))
628 rel
.append(static_cast< sal_Unicode
>('.'));
631 for (; i
< count2
; ++i
) {
633 rel
.append(static_cast< sal_Unicode
>('/'));
635 OUString
s(uriReference
->getPathSegment(i
));
636 if (encodeRetainedSpecialSegments
637 && s
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".")))
639 rel
.appendAscii(RTL_CONSTASCII_STRINGPARAM("%2E"));
640 } else if (encodeRetainedSpecialSegments
642 RTL_CONSTASCII_STRINGPARAM("..")))
645 RTL_CONSTASCII_STRINGPARAM("%2E%2E"));
654 if (!omitQuery
&& uriReference
->hasQuery()) {
655 rel
.append(static_cast< sal_Unicode
>('?'));
656 rel
.append(uriReference
->getQuery());
658 if (uriReference
->hasFragment()) {
659 rel
.append(static_cast< sal_Unicode
>('#'));
660 rel
.append(uriReference
->getFragment());
662 return parse(rel
.makeStringAndClear());
668 namespace stoc_services
{ namespace UriReferenceFactory
{
670 css::uno::Reference
< css::uno::XInterface
> create(
671 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
672 SAL_THROW((css::uno::Exception
))
675 return static_cast< cppu::OWeakObject
* >(new Factory(context
));
676 } catch (std::bad_alloc
&) {
677 throw css::uno::RuntimeException(
678 OUString("std::bad_alloc"), 0);
682 OUString
getImplementationName() {
683 return OUString("com.sun.star.comp.uri.UriReferenceFactory");
686 css::uno::Sequence
< OUString
> getSupportedServiceNames() {
687 css::uno::Sequence
< OUString
> s(1);
688 s
[0] = OUString("com.sun.star.uri.UriReferenceFactory");
694 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */