xref: /aoo42x/main/svl/source/misc/urihelper.cxx (revision 40df464e)
1*40df464eSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*40df464eSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*40df464eSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*40df464eSAndrew Rist  * distributed with this work for additional information
6*40df464eSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*40df464eSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*40df464eSAndrew Rist  * "License"); you may not use this file except in compliance
9*40df464eSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*40df464eSAndrew Rist  *
11*40df464eSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*40df464eSAndrew Rist  *
13*40df464eSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*40df464eSAndrew Rist  * software distributed under the License is distributed on an
15*40df464eSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*40df464eSAndrew Rist  * KIND, either express or implied.  See the License for the
17*40df464eSAndrew Rist  * specific language governing permissions and limitations
18*40df464eSAndrew Rist  * under the License.
19*40df464eSAndrew Rist  *
20*40df464eSAndrew Rist  *************************************************************/
21*40df464eSAndrew Rist 
22*40df464eSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svl.hxx"
26cdf0e10cSrcweir #include <svl/urihelper.hxx>
27cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
28cdf0e10cSrcweir #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
29cdf0e10cSrcweir #include "com/sun/star/lang/XMultiComponentFactory.hpp"
30cdf0e10cSrcweir #include "com/sun/star/ucb/Command.hpp"
31cdf0e10cSrcweir #include <com/sun/star/ucb/FileSystemNotation.hpp>
32cdf0e10cSrcweir #include "com/sun/star/ucb/IllegalIdentifierException.hpp"
33cdf0e10cSrcweir #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
34cdf0e10cSrcweir #include "com/sun/star/ucb/XCommandEnvironment.hpp"
35cdf0e10cSrcweir #include "com/sun/star/ucb/XCommandProcessor.hpp"
36cdf0e10cSrcweir #include "com/sun/star/ucb/XContent.hpp"
37cdf0e10cSrcweir #include "com/sun/star/ucb/XContentIdentifierFactory.hpp"
38cdf0e10cSrcweir #include "com/sun/star/ucb/XContentProvider.hpp"
39cdf0e10cSrcweir #include <com/sun/star/ucb/XContentProviderManager.hpp>
40cdf0e10cSrcweir #include "com/sun/star/uno/Any.hxx"
41cdf0e10cSrcweir #include "com/sun/star/uno/Exception.hpp"
42cdf0e10cSrcweir #include "com/sun/star/uno/Reference.hxx"
43cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp"
44cdf0e10cSrcweir #include "com/sun/star/uno/Sequence.hxx"
45cdf0e10cSrcweir #include "com/sun/star/uno/XComponentContext.hpp"
46cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp"
47cdf0e10cSrcweir #include "com/sun/star/uri/UriReferenceFactory.hpp"
48cdf0e10cSrcweir #include "com/sun/star/uri/XUriReference.hpp"
49cdf0e10cSrcweir #include "com/sun/star/uri/XUriReferenceFactory.hpp"
50cdf0e10cSrcweir #include "cppuhelper/exc_hlp.hxx"
51cdf0e10cSrcweir #include "comphelper/processfactory.hxx"
52cdf0e10cSrcweir #include "osl/diagnose.h"
53cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
54cdf0e10cSrcweir #include "rtl/ustring.h"
55cdf0e10cSrcweir #include "rtl/ustring.hxx"
56cdf0e10cSrcweir #include "sal/types.h"
57cdf0e10cSrcweir #include <tools/debug.hxx>
58cdf0e10cSrcweir #include <tools/inetmime.hxx>
59cdf0e10cSrcweir #include <ucbhelper/contentbroker.hxx>
60cdf0e10cSrcweir #include <unotools/charclass.hxx>
61cdf0e10cSrcweir #include "rtl/instance.hxx"
62cdf0e10cSrcweir 
63cdf0e10cSrcweir namespace unnamed_svl_urihelper {}
64cdf0e10cSrcweir using namespace unnamed_svl_urihelper;
65cdf0e10cSrcweir 	// unnamed namespaces don't work well yet...
66cdf0e10cSrcweir 
67cdf0e10cSrcweir namespace css = com::sun::star;
68cdf0e10cSrcweir using namespace com::sun::star;
69cdf0e10cSrcweir 
70cdf0e10cSrcweir //============================================================================
71cdf0e10cSrcweir //
72cdf0e10cSrcweir //  SmartRel2Abs
73cdf0e10cSrcweir //
74cdf0e10cSrcweir //============================================================================
75cdf0e10cSrcweir 
76cdf0e10cSrcweir namespace unnamed_svl_urihelper {
77cdf0e10cSrcweir 
toUniString(ByteString const & rString)78cdf0e10cSrcweir inline UniString toUniString(ByteString const & rString)
79cdf0e10cSrcweir {
80cdf0e10cSrcweir 	return UniString(rString, RTL_TEXTENCODING_ISO_8859_1);
81cdf0e10cSrcweir }
82cdf0e10cSrcweir 
toUniString(UniString const & rString)83cdf0e10cSrcweir inline UniString toUniString(UniString const & rString)
84cdf0e10cSrcweir {
85cdf0e10cSrcweir 	return rString;
86cdf0e10cSrcweir }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir template< typename Str >
SmartRel2Abs_Impl(INetURLObject const & rTheBaseURIRef,Str const & rTheRelURIRef,Link const & rMaybeFileHdl,bool bCheckFileExists,bool bIgnoreFragment,INetURLObject::EncodeMechanism eEncodeMechanism,INetURLObject::DecodeMechanism eDecodeMechanism,rtl_TextEncoding eCharset,bool bRelativeNonURIs,INetURLObject::FSysStyle eStyle)89cdf0e10cSrcweir inline UniString SmartRel2Abs_Impl(INetURLObject const & rTheBaseURIRef,
90cdf0e10cSrcweir 								   Str const & rTheRelURIRef,
91cdf0e10cSrcweir 								   Link const & rMaybeFileHdl,
92cdf0e10cSrcweir 								   bool bCheckFileExists,
93cdf0e10cSrcweir 								   bool bIgnoreFragment,
94cdf0e10cSrcweir 								   INetURLObject::EncodeMechanism
95cdf0e10cSrcweir 								       eEncodeMechanism,
96cdf0e10cSrcweir 								   INetURLObject::DecodeMechanism
97cdf0e10cSrcweir 								       eDecodeMechanism,
98cdf0e10cSrcweir 								   rtl_TextEncoding eCharset,
99cdf0e10cSrcweir 								   bool bRelativeNonURIs,
100cdf0e10cSrcweir 								   INetURLObject::FSysStyle eStyle)
101cdf0e10cSrcweir {
102cdf0e10cSrcweir 	// Backwards compatibility:
103cdf0e10cSrcweir 	if (rTheRelURIRef.Len() != 0 && rTheRelURIRef.GetChar(0) == '#')
104cdf0e10cSrcweir 		return toUniString(rTheRelURIRef);
105cdf0e10cSrcweir 
106cdf0e10cSrcweir 	INetURLObject aAbsURIRef;
107cdf0e10cSrcweir     if (rTheBaseURIRef.HasError())
108cdf0e10cSrcweir         aAbsURIRef.
109cdf0e10cSrcweir             SetSmartURL(rTheRelURIRef, eEncodeMechanism, eCharset, eStyle);
110cdf0e10cSrcweir     else
111cdf0e10cSrcweir     {
112cdf0e10cSrcweir         bool bWasAbsolute;
113cdf0e10cSrcweir 		aAbsURIRef = rTheBaseURIRef.smartRel2Abs(rTheRelURIRef,
114cdf0e10cSrcweir                                                  bWasAbsolute,
115cdf0e10cSrcweir                                                  bIgnoreFragment,
116cdf0e10cSrcweir                                                  eEncodeMechanism,
117cdf0e10cSrcweir                                                  eCharset,
118cdf0e10cSrcweir                                                  bRelativeNonURIs,
119cdf0e10cSrcweir                                                  eStyle);
120cdf0e10cSrcweir         if (bCheckFileExists
121cdf0e10cSrcweir             && !bWasAbsolute
122cdf0e10cSrcweir             && (aAbsURIRef.GetProtocol() == INET_PROT_FILE))
123cdf0e10cSrcweir         {
124cdf0e10cSrcweir             INetURLObject aNonFileURIRef;
125cdf0e10cSrcweir             aNonFileURIRef.SetSmartURL(rTheRelURIRef,
126cdf0e10cSrcweir                                        eEncodeMechanism,
127cdf0e10cSrcweir                                        eCharset,
128cdf0e10cSrcweir                                        eStyle);
129cdf0e10cSrcweir             if (!aNonFileURIRef.HasError()
130cdf0e10cSrcweir                 && aNonFileURIRef.GetProtocol() != INET_PROT_FILE)
131cdf0e10cSrcweir             {
132cdf0e10cSrcweir                 bool bMaybeFile = false;
133cdf0e10cSrcweir                 if (rMaybeFileHdl.IsSet())
134cdf0e10cSrcweir                 {
135cdf0e10cSrcweir                     UniString aFilePath(toUniString(rTheRelURIRef));
136cdf0e10cSrcweir                     bMaybeFile = rMaybeFileHdl.Call(&aFilePath) != 0;
137cdf0e10cSrcweir                 }
138cdf0e10cSrcweir                 if (!bMaybeFile)
139cdf0e10cSrcweir                     aAbsURIRef = aNonFileURIRef;
140cdf0e10cSrcweir             }
141cdf0e10cSrcweir         }
142cdf0e10cSrcweir     }
143cdf0e10cSrcweir 	return aAbsURIRef.GetMainURL(eDecodeMechanism, eCharset);
144cdf0e10cSrcweir }
145cdf0e10cSrcweir 
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir UniString
SmartRel2Abs(INetURLObject const & rTheBaseURIRef,ByteString const & rTheRelURIRef,Link const & rMaybeFileHdl,bool bCheckFileExists,bool bIgnoreFragment,INetURLObject::EncodeMechanism eEncodeMechanism,INetURLObject::DecodeMechanism eDecodeMechanism,rtl_TextEncoding eCharset,bool bRelativeNonURIs,INetURLObject::FSysStyle eStyle)149cdf0e10cSrcweir URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
150cdf0e10cSrcweir 						ByteString const & rTheRelURIRef,
151cdf0e10cSrcweir 						Link const & rMaybeFileHdl,
152cdf0e10cSrcweir 						bool bCheckFileExists,
153cdf0e10cSrcweir 						bool bIgnoreFragment,
154cdf0e10cSrcweir 						INetURLObject::EncodeMechanism eEncodeMechanism,
155cdf0e10cSrcweir 						INetURLObject::DecodeMechanism eDecodeMechanism,
156cdf0e10cSrcweir 						rtl_TextEncoding eCharset,
157cdf0e10cSrcweir 						bool bRelativeNonURIs,
158cdf0e10cSrcweir 						INetURLObject::FSysStyle eStyle)
159cdf0e10cSrcweir {
160cdf0e10cSrcweir 	return SmartRel2Abs_Impl(rTheBaseURIRef, rTheRelURIRef, rMaybeFileHdl,
161cdf0e10cSrcweir 							 bCheckFileExists, bIgnoreFragment,
162cdf0e10cSrcweir 							 eEncodeMechanism, eDecodeMechanism, eCharset,
163cdf0e10cSrcweir 							 bRelativeNonURIs, eStyle);
164cdf0e10cSrcweir }
165cdf0e10cSrcweir 
166cdf0e10cSrcweir UniString
SmartRel2Abs(INetURLObject const & rTheBaseURIRef,UniString const & rTheRelURIRef,Link const & rMaybeFileHdl,bool bCheckFileExists,bool bIgnoreFragment,INetURLObject::EncodeMechanism eEncodeMechanism,INetURLObject::DecodeMechanism eDecodeMechanism,rtl_TextEncoding eCharset,bool bRelativeNonURIs,INetURLObject::FSysStyle eStyle)167cdf0e10cSrcweir URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
168cdf0e10cSrcweir 						UniString const & rTheRelURIRef,
169cdf0e10cSrcweir 						Link const & rMaybeFileHdl,
170cdf0e10cSrcweir 						bool bCheckFileExists,
171cdf0e10cSrcweir 						bool bIgnoreFragment,
172cdf0e10cSrcweir 						INetURLObject::EncodeMechanism eEncodeMechanism,
173cdf0e10cSrcweir 						INetURLObject::DecodeMechanism eDecodeMechanism,
174cdf0e10cSrcweir 						rtl_TextEncoding eCharset,
175cdf0e10cSrcweir 						bool bRelativeNonURIs,
176cdf0e10cSrcweir 						INetURLObject::FSysStyle eStyle)
177cdf0e10cSrcweir {
178cdf0e10cSrcweir 	return SmartRel2Abs_Impl(rTheBaseURIRef, rTheRelURIRef, rMaybeFileHdl,
179cdf0e10cSrcweir 							 bCheckFileExists, bIgnoreFragment,
180cdf0e10cSrcweir 							 eEncodeMechanism, eDecodeMechanism, eCharset,
181cdf0e10cSrcweir 							 bRelativeNonURIs, eStyle);
182cdf0e10cSrcweir }
183cdf0e10cSrcweir 
184cdf0e10cSrcweir //============================================================================
185cdf0e10cSrcweir //
186cdf0e10cSrcweir //  SetMaybeFileHdl
187cdf0e10cSrcweir //
188cdf0e10cSrcweir //============================================================================
189cdf0e10cSrcweir 
190cdf0e10cSrcweir namespace { struct MaybeFileHdl : public rtl::Static< Link, MaybeFileHdl > {}; }
191cdf0e10cSrcweir 
SetMaybeFileHdl(Link const & rTheMaybeFileHdl)192cdf0e10cSrcweir void URIHelper::SetMaybeFileHdl(Link const & rTheMaybeFileHdl)
193cdf0e10cSrcweir {
194cdf0e10cSrcweir 	MaybeFileHdl::get() = rTheMaybeFileHdl;
195cdf0e10cSrcweir }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir //============================================================================
198cdf0e10cSrcweir //
199cdf0e10cSrcweir //  GetMaybeFileHdl
200cdf0e10cSrcweir //
201cdf0e10cSrcweir //============================================================================
202cdf0e10cSrcweir 
GetMaybeFileHdl()203cdf0e10cSrcweir Link URIHelper::GetMaybeFileHdl()
204cdf0e10cSrcweir {
205cdf0e10cSrcweir 	return MaybeFileHdl::get();
206cdf0e10cSrcweir }
207cdf0e10cSrcweir 
208cdf0e10cSrcweir namespace {
209cdf0e10cSrcweir 
isAbsoluteHierarchicalUriReference(css::uno::Reference<css::uri::XUriReference> const & uriReference)210cdf0e10cSrcweir bool isAbsoluteHierarchicalUriReference(
211cdf0e10cSrcweir     css::uno::Reference< css::uri::XUriReference > const & uriReference)
212cdf0e10cSrcweir {
213cdf0e10cSrcweir     return uriReference.is() && uriReference->isAbsolute()
214cdf0e10cSrcweir         && uriReference->isHierarchical() && !uriReference->hasRelativePath();
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
217cdf0e10cSrcweir // To improve performance, assume that if for any prefix URL of a given
218cdf0e10cSrcweir // hierarchical URL either a UCB content cannot be created, or the UCB content
219cdf0e10cSrcweir // does not support the getCasePreservingURL command, then this will hold for
220cdf0e10cSrcweir // any other prefix URL of the given URL, too:
221cdf0e10cSrcweir enum Result { Success, GeneralFailure, SpecificFailure };
222cdf0e10cSrcweir 
normalizePrefix(css::uno::Reference<css::ucb::XContentProvider> const & broker,rtl::OUString const & uri,rtl::OUString * normalized)223cdf0e10cSrcweir Result normalizePrefix(
224cdf0e10cSrcweir     css::uno::Reference< css::ucb::XContentProvider > const & broker,
225cdf0e10cSrcweir     rtl::OUString const & uri, rtl::OUString * normalized)
226cdf0e10cSrcweir {
227cdf0e10cSrcweir     OSL_ASSERT(broker.is() && normalized != 0);
228cdf0e10cSrcweir     css::uno::Reference< css::ucb::XContent > content;
229cdf0e10cSrcweir     try {
230cdf0e10cSrcweir         content = broker->queryContent(
231cdf0e10cSrcweir             css::uno::Reference< css::ucb::XContentIdentifierFactory >(
232cdf0e10cSrcweir                 broker, css::uno::UNO_QUERY_THROW)->createContentIdentifier(
233cdf0e10cSrcweir                     uri));
234cdf0e10cSrcweir     } catch (css::ucb::IllegalIdentifierException &) {}
235cdf0e10cSrcweir     if (!content.is()) {
236cdf0e10cSrcweir         return GeneralFailure;
237cdf0e10cSrcweir     }
238cdf0e10cSrcweir     try {
239cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 0
240cdf0e10cSrcweir         bool ok =
241cdf0e10cSrcweir         #endif
242cdf0e10cSrcweir             (css::uno::Reference< css::ucb::XCommandProcessor >(
243cdf0e10cSrcweir                    content, css::uno::UNO_QUERY_THROW)->execute(
244cdf0e10cSrcweir                        css::ucb::Command(
245cdf0e10cSrcweir                            rtl::OUString(
246cdf0e10cSrcweir                                RTL_CONSTASCII_USTRINGPARAM(
247cdf0e10cSrcweir                                    "getCasePreservingURL")),
248cdf0e10cSrcweir                            -1, css::uno::Any()),
249cdf0e10cSrcweir                        0,
250cdf0e10cSrcweir                        css::uno::Reference< css::ucb::XCommandEnvironment >())
251cdf0e10cSrcweir                >>= *normalized);
252cdf0e10cSrcweir         OSL_ASSERT(ok);
253cdf0e10cSrcweir     } catch (css::uno::RuntimeException &) {
254cdf0e10cSrcweir         throw;
255cdf0e10cSrcweir     } catch (css::ucb::UnsupportedCommandException &) {
256cdf0e10cSrcweir         return GeneralFailure;
257cdf0e10cSrcweir     } catch (css::uno::Exception &) {
258cdf0e10cSrcweir         return SpecificFailure;
259cdf0e10cSrcweir     }
260cdf0e10cSrcweir     return Success;
261cdf0e10cSrcweir }
262cdf0e10cSrcweir 
normalize(css::uno::Reference<css::ucb::XContentProvider> const & broker,css::uno::Reference<css::uri::XUriReferenceFactory> const & uriFactory,rtl::OUString const & uriReference)263cdf0e10cSrcweir rtl::OUString normalize(
264cdf0e10cSrcweir     css::uno::Reference< css::ucb::XContentProvider > const & broker,
265cdf0e10cSrcweir     css::uno::Reference< css::uri::XUriReferenceFactory > const & uriFactory,
266cdf0e10cSrcweir     rtl::OUString const & uriReference)
267cdf0e10cSrcweir {
268cdf0e10cSrcweir     // normalizePrefix can potentially fail (a typically example being a file
269cdf0e10cSrcweir     // URL that denotes a non-existing resource); in such a case, try to
270cdf0e10cSrcweir     // normalize as long a prefix of the given URL as possible (i.e., normalize
271cdf0e10cSrcweir     // all the existing directories within the path):
272cdf0e10cSrcweir     rtl::OUString normalized;
273cdf0e10cSrcweir     sal_Int32 n = uriReference.indexOf('#');
274cdf0e10cSrcweir     normalized = n == -1 ? uriReference : uriReference.copy(0, n);
275cdf0e10cSrcweir     switch (normalizePrefix(broker, normalized, &normalized)) {
276cdf0e10cSrcweir     case Success:
277cdf0e10cSrcweir         return n == -1 ? normalized : normalized + uriReference.copy(n);
278cdf0e10cSrcweir     case GeneralFailure:
279cdf0e10cSrcweir         return uriReference;
280cdf0e10cSrcweir     case SpecificFailure:
281cdf0e10cSrcweir     default:
282cdf0e10cSrcweir         break;
283cdf0e10cSrcweir     }
284cdf0e10cSrcweir     css::uno::Reference< css::uri::XUriReference > ref(
285cdf0e10cSrcweir         uriFactory->parse(uriReference));
286cdf0e10cSrcweir     if (!isAbsoluteHierarchicalUriReference(ref)) {
287cdf0e10cSrcweir         return uriReference;
288cdf0e10cSrcweir     }
289cdf0e10cSrcweir     sal_Int32 count = ref->getPathSegmentCount();
290cdf0e10cSrcweir     if (count < 2) {
291cdf0e10cSrcweir         return uriReference;
292cdf0e10cSrcweir     }
293cdf0e10cSrcweir     rtl::OUStringBuffer head(ref->getScheme());
294cdf0e10cSrcweir     head.append(static_cast< sal_Unicode >(':'));
295cdf0e10cSrcweir     if (ref->hasAuthority()) {
296cdf0e10cSrcweir         head.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
297cdf0e10cSrcweir         head.append(ref->getAuthority());
298cdf0e10cSrcweir     }
299cdf0e10cSrcweir     for (sal_Int32 i = count - 1; i > 0; --i) {
300cdf0e10cSrcweir         rtl::OUStringBuffer buf(head);
301cdf0e10cSrcweir         for (sal_Int32 j = 0; j < i; ++j) {
302cdf0e10cSrcweir             buf.append(static_cast< sal_Unicode >('/'));
303cdf0e10cSrcweir             buf.append(ref->getPathSegment(j));
304cdf0e10cSrcweir         }
305cdf0e10cSrcweir         normalized = buf.makeStringAndClear();
306cdf0e10cSrcweir         if (normalizePrefix(broker, normalized, &normalized) != SpecificFailure)
307cdf0e10cSrcweir         {
308cdf0e10cSrcweir             buf.append(normalized);
309cdf0e10cSrcweir             css::uno::Reference< css::uri::XUriReference > preRef(
310cdf0e10cSrcweir                 uriFactory->parse(normalized));
311cdf0e10cSrcweir             if (!isAbsoluteHierarchicalUriReference(preRef)) {
312cdf0e10cSrcweir                 // This could only happen if something is inconsistent:
313cdf0e10cSrcweir                 break;
314cdf0e10cSrcweir             }
315cdf0e10cSrcweir             sal_Int32 preCount = preRef->getPathSegmentCount();
316cdf0e10cSrcweir             // normalizePrefix may have added or removed a final slash:
317cdf0e10cSrcweir             if (preCount != i) {
318cdf0e10cSrcweir                 if (preCount == i - 1) {
319cdf0e10cSrcweir                     buf.append(static_cast< sal_Unicode >('/'));
320cdf0e10cSrcweir                 } else if (preCount - 1 == i && buf.getLength() > 0
321cdf0e10cSrcweir                            && buf.charAt(buf.getLength() - 1) == '/')
322cdf0e10cSrcweir                 {
323cdf0e10cSrcweir                     buf.setLength(buf.getLength() - 1);
324cdf0e10cSrcweir                 } else {
325cdf0e10cSrcweir                     // This could only happen if something is inconsistent:
326cdf0e10cSrcweir                     break;
327cdf0e10cSrcweir                 }
328cdf0e10cSrcweir             }
329cdf0e10cSrcweir             for (sal_Int32 j = i; j < count; ++j) {
330cdf0e10cSrcweir                 buf.append(static_cast< sal_Unicode >('/'));
331cdf0e10cSrcweir                 buf.append(ref->getPathSegment(j));
332cdf0e10cSrcweir             }
333cdf0e10cSrcweir             if (ref->hasQuery()) {
334cdf0e10cSrcweir                 buf.append(static_cast< sal_Unicode >('?'));
335cdf0e10cSrcweir                 buf.append(ref->getQuery());
336cdf0e10cSrcweir             }
337cdf0e10cSrcweir             if (ref->hasFragment()) {
338cdf0e10cSrcweir                 buf.append(static_cast< sal_Unicode >('#'));
339cdf0e10cSrcweir                 buf.append(ref->getFragment());
340cdf0e10cSrcweir             }
341cdf0e10cSrcweir             return buf.makeStringAndClear();
342cdf0e10cSrcweir         }
343cdf0e10cSrcweir     }
344cdf0e10cSrcweir     return uriReference;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir 
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir css::uno::Reference< css::uri::XUriReference >
normalizedMakeRelative(css::uno::Reference<css::uno::XComponentContext> const & context,rtl::OUString const & baseUriReference,rtl::OUString const & uriReference)350cdf0e10cSrcweir URIHelper::normalizedMakeRelative(
351cdf0e10cSrcweir     css::uno::Reference< css::uno::XComponentContext > const & context,
352cdf0e10cSrcweir     rtl::OUString const & baseUriReference, rtl::OUString const & uriReference)
353cdf0e10cSrcweir {
354cdf0e10cSrcweir     OSL_ASSERT(context.is());
355cdf0e10cSrcweir     css::uno::Reference< css::lang::XMultiComponentFactory > componentFactory(
356cdf0e10cSrcweir         context->getServiceManager());
357cdf0e10cSrcweir     if (!componentFactory.is()) {
358cdf0e10cSrcweir         throw css::uno::RuntimeException(
359cdf0e10cSrcweir             rtl::OUString(
360cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
361cdf0e10cSrcweir                     "component context has no service manager")),
362cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
363cdf0e10cSrcweir     }
364cdf0e10cSrcweir     css::uno::Sequence< css::uno::Any > args(2);
365cdf0e10cSrcweir     args[0] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Local"));
366cdf0e10cSrcweir     args[1] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office"));
367cdf0e10cSrcweir     css::uno::Reference< css::ucb::XContentProvider > broker;
368cdf0e10cSrcweir     try {
369cdf0e10cSrcweir         broker = css::uno::Reference< css::ucb::XContentProvider >(
370cdf0e10cSrcweir             componentFactory->createInstanceWithArgumentsAndContext(
371cdf0e10cSrcweir                 rtl::OUString(
372cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
373cdf0e10cSrcweir                         "com.sun.star.ucb.UniversalContentBroker")),
374cdf0e10cSrcweir                 args, context),
375cdf0e10cSrcweir             css::uno::UNO_QUERY_THROW);
376cdf0e10cSrcweir     } catch (css::uno::RuntimeException &) {
377cdf0e10cSrcweir         throw;
378cdf0e10cSrcweir     } catch (css::uno::Exception &) {
379cdf0e10cSrcweir         css::uno::Any exception(cppu::getCaughtException());
380cdf0e10cSrcweir         throw css::lang::WrappedTargetRuntimeException(
381cdf0e10cSrcweir             rtl::OUString(
382cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
383cdf0e10cSrcweir                     "creating com.sun.star.ucb.UniversalContentBroker failed")),
384cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >(),
385cdf0e10cSrcweir             exception);
386cdf0e10cSrcweir     }
387cdf0e10cSrcweir     css::uno::Reference< css::uri::XUriReferenceFactory > uriFactory(
388cdf0e10cSrcweir         css::uri::UriReferenceFactory::create(context));
389cdf0e10cSrcweir     return uriFactory->makeRelative(
390cdf0e10cSrcweir         uriFactory->parse(normalize(broker, uriFactory, baseUriReference)),
391cdf0e10cSrcweir         uriFactory->parse(normalize(broker, uriFactory, uriReference)), true,
392cdf0e10cSrcweir         true, false);
393cdf0e10cSrcweir }
394cdf0e10cSrcweir 
simpleNormalizedMakeRelative(rtl::OUString const & baseUriReference,rtl::OUString const & uriReference)395cdf0e10cSrcweir rtl::OUString URIHelper::simpleNormalizedMakeRelative(
396cdf0e10cSrcweir     rtl::OUString const & baseUriReference, rtl::OUString const & uriReference)
397cdf0e10cSrcweir {
398cdf0e10cSrcweir     com::sun::star::uno::Reference< com::sun::star::uri::XUriReference > rel(
399cdf0e10cSrcweir         URIHelper::normalizedMakeRelative(
400cdf0e10cSrcweir             com::sun::star::uno::Reference<
401cdf0e10cSrcweir             com::sun::star::uno::XComponentContext >(
402cdf0e10cSrcweir                 (com::sun::star::uno::Reference<
403cdf0e10cSrcweir                  com::sun::star::beans::XPropertySet >(
404cdf0e10cSrcweir                     comphelper::getProcessServiceFactory(),
405cdf0e10cSrcweir                     com::sun::star::uno::UNO_QUERY_THROW)->
406cdf0e10cSrcweir                  getPropertyValue(
407cdf0e10cSrcweir                      rtl::OUString(
408cdf0e10cSrcweir                          RTL_CONSTASCII_USTRINGPARAM("DefaultContext")))),
409cdf0e10cSrcweir                 com::sun::star::uno::UNO_QUERY_THROW),
410cdf0e10cSrcweir             baseUriReference, uriReference));
411cdf0e10cSrcweir     return rel.is() ? rel->getUriReference() : uriReference;
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir //============================================================================
415cdf0e10cSrcweir //
416cdf0e10cSrcweir //  FindFirstURLInText
417cdf0e10cSrcweir //
418cdf0e10cSrcweir //============================================================================
419cdf0e10cSrcweir 
420cdf0e10cSrcweir namespace unnamed_svl_urihelper {
421cdf0e10cSrcweir 
nextChar(UniString const & rStr,xub_StrLen nPos)422cdf0e10cSrcweir inline xub_StrLen nextChar(UniString const & rStr, xub_StrLen nPos)
423cdf0e10cSrcweir {
424cdf0e10cSrcweir 	return INetMIME::isHighSurrogate(rStr.GetChar(nPos))
425cdf0e10cSrcweir 		   && rStr.Len() - nPos >= 2
426cdf0e10cSrcweir 		   && INetMIME::isLowSurrogate(rStr.GetChar(nPos + 1)) ?
427cdf0e10cSrcweir 		       nPos + 2 : nPos + 1;
428cdf0e10cSrcweir }
429cdf0e10cSrcweir 
isBoundary1(CharClass const & rCharClass,UniString const & rStr,xub_StrLen nPos,xub_StrLen nEnd)430cdf0e10cSrcweir bool isBoundary1(CharClass const & rCharClass, UniString const & rStr,
431cdf0e10cSrcweir                  xub_StrLen nPos, xub_StrLen nEnd)
432cdf0e10cSrcweir {
433cdf0e10cSrcweir     if (nPos == nEnd)
434cdf0e10cSrcweir         return true;
435cdf0e10cSrcweir     if (rCharClass.isLetterNumeric(rStr, nPos))
436cdf0e10cSrcweir         return false;
437cdf0e10cSrcweir     switch (rStr.GetChar(nPos))
438cdf0e10cSrcweir     {
439cdf0e10cSrcweir     case '$':
440cdf0e10cSrcweir     case '%':
441cdf0e10cSrcweir     case '&':
442cdf0e10cSrcweir     case '-':
443cdf0e10cSrcweir     case '/':
444cdf0e10cSrcweir     case '@':
445cdf0e10cSrcweir     case '\\':
446cdf0e10cSrcweir         return false;
447cdf0e10cSrcweir     default:
448cdf0e10cSrcweir         return true;
449cdf0e10cSrcweir     }
450cdf0e10cSrcweir }
451cdf0e10cSrcweir 
isBoundary2(CharClass const & rCharClass,UniString const & rStr,xub_StrLen nPos,xub_StrLen nEnd)452cdf0e10cSrcweir bool isBoundary2(CharClass const & rCharClass, UniString const & rStr,
453cdf0e10cSrcweir                  xub_StrLen nPos, xub_StrLen nEnd)
454cdf0e10cSrcweir {
455cdf0e10cSrcweir     if (nPos == nEnd)
456cdf0e10cSrcweir         return true;
457cdf0e10cSrcweir     if (rCharClass.isLetterNumeric(rStr, nPos))
458cdf0e10cSrcweir         return false;
459cdf0e10cSrcweir     switch (rStr.GetChar(nPos))
460cdf0e10cSrcweir     {
461cdf0e10cSrcweir     case '!':
462cdf0e10cSrcweir     case '#':
463cdf0e10cSrcweir     case '$':
464cdf0e10cSrcweir     case '%':
465cdf0e10cSrcweir     case '&':
466cdf0e10cSrcweir     case '\'':
467cdf0e10cSrcweir     case '*':
468cdf0e10cSrcweir     case '+':
469cdf0e10cSrcweir     case '-':
470cdf0e10cSrcweir     case '/':
471cdf0e10cSrcweir     case '=':
472cdf0e10cSrcweir     case '?':
473cdf0e10cSrcweir     case '@':
474cdf0e10cSrcweir     case '^':
475cdf0e10cSrcweir     case '_':
476cdf0e10cSrcweir     case '`':
477cdf0e10cSrcweir     case '{':
478cdf0e10cSrcweir     case '|':
479cdf0e10cSrcweir     case '}':
480cdf0e10cSrcweir     case '~':
481cdf0e10cSrcweir         return false;
482cdf0e10cSrcweir     default:
483cdf0e10cSrcweir         return true;
484cdf0e10cSrcweir     }
485cdf0e10cSrcweir }
486cdf0e10cSrcweir 
checkWChar(CharClass const & rCharClass,UniString const & rStr,xub_StrLen * pPos,xub_StrLen * pEnd,bool bBackslash=false,bool bPipe=false)487cdf0e10cSrcweir bool checkWChar(CharClass const & rCharClass, UniString const & rStr,
488cdf0e10cSrcweir                 xub_StrLen * pPos, xub_StrLen * pEnd, bool bBackslash = false,
489cdf0e10cSrcweir                 bool bPipe = false)
490cdf0e10cSrcweir {
491cdf0e10cSrcweir 	sal_Unicode c = rStr.GetChar(*pPos);
492cdf0e10cSrcweir 	if (INetMIME::isUSASCII(c))
493cdf0e10cSrcweir 	{
494cdf0e10cSrcweir 		static sal_uInt8 const aMap[128]
495cdf0e10cSrcweir 			= { 0, 0, 0, 0, 0, 0, 0, 0,
496cdf0e10cSrcweir 				0, 0, 0, 0, 0, 0, 0, 0,
497cdf0e10cSrcweir 				0, 0, 0, 0, 0, 0, 0, 0,
498cdf0e10cSrcweir 				0, 0, 0, 0, 0, 0, 0, 0,
499cdf0e10cSrcweir 				0, 1, 0, 0, 4, 4, 4, 1,   //  !"#$%&'
500cdf0e10cSrcweir 				1, 1, 1, 1, 1, 4, 1, 4,   // ()*+,-./
501cdf0e10cSrcweir 				4, 4, 4, 4, 4, 4, 4, 4,   // 01234567
502cdf0e10cSrcweir 				4, 4, 1, 1, 0, 1, 0, 1,   // 89:;<=>?
503cdf0e10cSrcweir 				4, 4, 4, 4, 4, 4, 4, 4,   // @ABCDEFG
504cdf0e10cSrcweir 				4, 4, 4, 4, 4, 4, 4, 4,   // HIJKLMNO
505cdf0e10cSrcweir 				4, 4, 4, 4, 4, 4, 4, 4,   // PQRSTUVW
506cdf0e10cSrcweir 				4, 4, 4, 1, 2, 1, 0, 1,   // XYZ[\]^_
507cdf0e10cSrcweir 				0, 4, 4, 4, 4, 4, 4, 4,   // `abcdefg
508cdf0e10cSrcweir 				4, 4, 4, 4, 4, 4, 4, 4,   // hijklmno
509cdf0e10cSrcweir 				4, 4, 4, 4, 4, 4, 4, 4,   // pqrstuvw
510cdf0e10cSrcweir 				4, 4, 4, 0, 3, 0, 1, 0 }; // xyz{|}~
511cdf0e10cSrcweir 		switch (aMap[c])
512cdf0e10cSrcweir 		{
513cdf0e10cSrcweir 			default: // not uric
514cdf0e10cSrcweir 				return false;
515cdf0e10cSrcweir 
516cdf0e10cSrcweir 			case 1: // uric
517cdf0e10cSrcweir 				++(*pPos);
518cdf0e10cSrcweir 				return true;
519cdf0e10cSrcweir 
520cdf0e10cSrcweir 			case 2: // "\"
521cdf0e10cSrcweir 				if (bBackslash)
522cdf0e10cSrcweir 				{
523cdf0e10cSrcweir 					*pEnd = ++(*pPos);
524cdf0e10cSrcweir 					return true;
525cdf0e10cSrcweir 				}
526cdf0e10cSrcweir 				else
527cdf0e10cSrcweir 					return false;
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 			case 3: // "|"
530cdf0e10cSrcweir 				if (bPipe)
531cdf0e10cSrcweir 				{
532cdf0e10cSrcweir 					*pEnd = ++(*pPos);
533cdf0e10cSrcweir 					return true;
534cdf0e10cSrcweir 				}
535cdf0e10cSrcweir 				else
536cdf0e10cSrcweir 					return false;
537cdf0e10cSrcweir 
538cdf0e10cSrcweir 			case 4: // alpha, digit, "$", "%", "&", "-", "/", "@" (see
539cdf0e10cSrcweir                     // isBoundary1)
540cdf0e10cSrcweir 				*pEnd = ++(*pPos);
541cdf0e10cSrcweir 				return true;
542cdf0e10cSrcweir 		}
543cdf0e10cSrcweir 	}
544cdf0e10cSrcweir 	else if (rCharClass.isLetterNumeric(rStr, *pPos))
545cdf0e10cSrcweir 	{
546cdf0e10cSrcweir 		*pEnd = *pPos = nextChar(rStr, *pPos);
547cdf0e10cSrcweir 		return true;
548cdf0e10cSrcweir 	}
549cdf0e10cSrcweir 	else
550cdf0e10cSrcweir 		return false;
551cdf0e10cSrcweir }
552cdf0e10cSrcweir 
scanDomain(UniString const & rStr,xub_StrLen * pPos,xub_StrLen nEnd)553cdf0e10cSrcweir sal_uInt32 scanDomain(UniString const & rStr, xub_StrLen * pPos,
554cdf0e10cSrcweir                       xub_StrLen nEnd)
555cdf0e10cSrcweir {
556cdf0e10cSrcweir 	sal_Unicode const * pBuffer = rStr.GetBuffer();
557cdf0e10cSrcweir 	sal_Unicode const * p = pBuffer + *pPos;
558cdf0e10cSrcweir 	sal_uInt32 nLabels = INetURLObject::scanDomain(p, pBuffer + nEnd, false);
559cdf0e10cSrcweir 	*pPos = sal::static_int_cast< xub_StrLen >(p - pBuffer);
560cdf0e10cSrcweir 	return nLabels;
561cdf0e10cSrcweir }
562cdf0e10cSrcweir 
563cdf0e10cSrcweir }
564cdf0e10cSrcweir 
565cdf0e10cSrcweir UniString
FindFirstURLInText(UniString const & rText,xub_StrLen & rBegin,xub_StrLen & rEnd,CharClass const & rCharClass,INetURLObject::EncodeMechanism eMechanism,rtl_TextEncoding eCharset,INetURLObject::FSysStyle eStyle)566cdf0e10cSrcweir URIHelper::FindFirstURLInText(UniString const & rText,
567cdf0e10cSrcweir                               xub_StrLen & rBegin,
568cdf0e10cSrcweir                               xub_StrLen & rEnd,
569cdf0e10cSrcweir                               CharClass const & rCharClass,
570cdf0e10cSrcweir                               INetURLObject::EncodeMechanism eMechanism,
571cdf0e10cSrcweir                               rtl_TextEncoding eCharset,
572cdf0e10cSrcweir                               INetURLObject::FSysStyle eStyle)
573cdf0e10cSrcweir {
574cdf0e10cSrcweir     if (!(rBegin <= rEnd && rEnd <= rText.Len()))
575cdf0e10cSrcweir         return UniString();
576cdf0e10cSrcweir 
577cdf0e10cSrcweir     // Search for the first substring of [rBegin..rEnd[ that matches any of the
578cdf0e10cSrcweir     // following productions (for which the appropriate style bit is set in
579cdf0e10cSrcweir     // eStyle, if applicable).
580cdf0e10cSrcweir     //
581cdf0e10cSrcweir     // 1st Production (known scheme):
582cdf0e10cSrcweir     //    \B1 <one of the known schemes, except file> ":" 1*wchar ["#" 1*wchar]
583cdf0e10cSrcweir     //        \B1
584cdf0e10cSrcweir     //
585cdf0e10cSrcweir     // 2nd Production (file):
586cdf0e10cSrcweir     //    \B1 "FILE:" 1*(wchar / "\" / "|") ["#" 1*wchar] \B1
587cdf0e10cSrcweir     //
588cdf0e10cSrcweir     // 3rd Production (ftp):
589cdf0e10cSrcweir     //    \B1 "FTP" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
590cdf0e10cSrcweir     //
591cdf0e10cSrcweir     // 4th Production (http):
592cdf0e10cSrcweir     //    \B1 "WWW" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
593cdf0e10cSrcweir     //
594cdf0e10cSrcweir     // 5th Production (mailto):
595cdf0e10cSrcweir     //    \B2 local-part "@" domain \B1
596cdf0e10cSrcweir     //
597cdf0e10cSrcweir     // 6th Production (UNC file):
598cdf0e10cSrcweir     //    \B1 "\\" domain "\" *(wchar / "\") \B1
599cdf0e10cSrcweir     //
600cdf0e10cSrcweir     // 7th Production (DOS file):
601cdf0e10cSrcweir     //    \B1 ALPHA ":\" *(wchar / "\") \B1
602cdf0e10cSrcweir     //
603cdf0e10cSrcweir     // 8th Production (Unix-like DOS file):
604cdf0e10cSrcweir     //    \B1 ALPHA ":/" *(wchar / "\") \B1
605cdf0e10cSrcweir     //
606cdf0e10cSrcweir     // The productions use the following auxiliary rules.
607cdf0e10cSrcweir     //
608cdf0e10cSrcweir     //    local-part = atom *("." atom)
609cdf0e10cSrcweir     //    atom = 1*(alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+"
610cdf0e10cSrcweir     //              / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}"
611cdf0e10cSrcweir     //              / "~")
612cdf0e10cSrcweir     //    domain = label *("." label)
613cdf0e10cSrcweir     //    label = alphanum [*(alphanum / "-") alphanum]
614cdf0e10cSrcweir     //    alphanum = ALPHA / DIGIT
615cdf0e10cSrcweir     //    wchar = <any uric character (ignoring the escaped rule), or "%", or
616cdf0e10cSrcweir     //             a letter or digit (according to rCharClass)>
617cdf0e10cSrcweir     //
618cdf0e10cSrcweir     // "\B1" (boundary 1) stands for the beginning or end of the block of text,
619cdf0e10cSrcweir     // or a character that is neither (a) a letter or digit (according to
620cdf0e10cSrcweir     // rCharClass), nor (b) any of "$", "%", "&", "-", "/", "@", or "\".
621cdf0e10cSrcweir     // (FIXME:  What was the rationale for this set of punctuation characters?)
622cdf0e10cSrcweir     //
623cdf0e10cSrcweir     // "\B2" (boundary 2) stands for the beginning or end of the block of text,
624cdf0e10cSrcweir     // or a character that is neither (a) a letter or digit (according to
625cdf0e10cSrcweir     // rCharClass), nor (b) any of "!", "#", "$", "%", "&", "'", "*", "+", "-",
626cdf0e10cSrcweir     // "/", "=", "?", "@", "^", "_", "`", "{", "|", "}", or "~" (i.e., an RFC
627cdf0e10cSrcweir     // 822 <atom> character, or "@" from \B1's set above).
628cdf0e10cSrcweir     //
629cdf0e10cSrcweir     // Productions 1--4, and 6--8 try to find a maximum-length match, but they
630cdf0e10cSrcweir     // stop at the first <wchar> character that is a "\B1" character which is
631cdf0e10cSrcweir     // only followed by "\B1" characters (taking "\" and "|" characters into
632cdf0e10cSrcweir     // account appropriately).  Production 5 simply tries to find a maximum-
633cdf0e10cSrcweir     // length match.
634cdf0e10cSrcweir     //
635cdf0e10cSrcweir     // Productions 1--4 use the given eMechanism and eCharset.  Productions 5--9
636cdf0e10cSrcweir     // use ENCODE_ALL.
637cdf0e10cSrcweir     //
638cdf0e10cSrcweir     // Productions 6--9 are only applicable if the FSYS_DOS bit is set in
639cdf0e10cSrcweir     // eStyle.
640cdf0e10cSrcweir 
641cdf0e10cSrcweir     bool bBoundary1 = true;
642cdf0e10cSrcweir     bool bBoundary2 = true;
643cdf0e10cSrcweir     for (xub_StrLen nPos = rBegin; nPos != rEnd; nPos = nextChar(rText, nPos))
644cdf0e10cSrcweir     {
645cdf0e10cSrcweir         sal_Unicode c = rText.GetChar(nPos);
646cdf0e10cSrcweir         if (bBoundary1)
647cdf0e10cSrcweir         {
648cdf0e10cSrcweir             if (INetMIME::isAlpha(c))
649cdf0e10cSrcweir             {
650cdf0e10cSrcweir                 xub_StrLen i = nPos;
651cdf0e10cSrcweir                 INetProtocol eScheme
652cdf0e10cSrcweir                     = INetURLObject::CompareProtocolScheme(UniString(rText, i,
653cdf0e10cSrcweir                                                                      rEnd));
654cdf0e10cSrcweir                 if (eScheme == INET_PROT_FILE) // 2nd
655cdf0e10cSrcweir                 {
656cdf0e10cSrcweir                     while (rText.GetChar(i++) != ':') ;
657cdf0e10cSrcweir                     xub_StrLen nPrefixEnd = i;
658cdf0e10cSrcweir                     xub_StrLen nUriEnd = i;
659cdf0e10cSrcweir                     while (i != rEnd
660cdf0e10cSrcweir                            && checkWChar(rCharClass, rText, &i, &nUriEnd, true,
661cdf0e10cSrcweir                                          true)) ;
662cdf0e10cSrcweir                     if (i != nPrefixEnd && rText.GetChar(i) == '#')
663cdf0e10cSrcweir                     {
664cdf0e10cSrcweir                         ++i;
665cdf0e10cSrcweir                         while (i != rEnd
666cdf0e10cSrcweir                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
667cdf0e10cSrcweir                     }
668cdf0e10cSrcweir                     if (nUriEnd != nPrefixEnd
669cdf0e10cSrcweir                         && isBoundary1(rCharClass, rText, nUriEnd, rEnd))
670cdf0e10cSrcweir                     {
671cdf0e10cSrcweir                         INetURLObject aUri(UniString(rText, nPos,
672cdf0e10cSrcweir                                                      nUriEnd - nPos),
673cdf0e10cSrcweir                                            INET_PROT_FILE, eMechanism, eCharset,
674cdf0e10cSrcweir                                            eStyle);
675cdf0e10cSrcweir                         if (!aUri.HasError())
676cdf0e10cSrcweir                         {
677cdf0e10cSrcweir                             rBegin = nPos;
678cdf0e10cSrcweir                             rEnd = nUriEnd;
679cdf0e10cSrcweir                             return
680cdf0e10cSrcweir                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
681cdf0e10cSrcweir                         }
682cdf0e10cSrcweir                     }
683cdf0e10cSrcweir                 }
684cdf0e10cSrcweir                 else if (eScheme != INET_PROT_NOT_VALID) // 1st
685cdf0e10cSrcweir                 {
686cdf0e10cSrcweir                     while (rText.GetChar(i++) != ':') ;
687cdf0e10cSrcweir                     xub_StrLen nPrefixEnd = i;
688cdf0e10cSrcweir                     xub_StrLen nUriEnd = i;
689cdf0e10cSrcweir                     while (i != rEnd
690cdf0e10cSrcweir                            && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
691cdf0e10cSrcweir                     if (i != nPrefixEnd && rText.GetChar(i) == '#')
692cdf0e10cSrcweir                     {
693cdf0e10cSrcweir                         ++i;
694cdf0e10cSrcweir                         while (i != rEnd
695cdf0e10cSrcweir                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
696cdf0e10cSrcweir                     }
697cdf0e10cSrcweir                     if (nUriEnd != nPrefixEnd
698cdf0e10cSrcweir                         && (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
699cdf0e10cSrcweir                             || rText.GetChar(nUriEnd) == '\\'))
700cdf0e10cSrcweir                     {
701cdf0e10cSrcweir                         INetURLObject aUri(UniString(rText, nPos,
702cdf0e10cSrcweir                                                      nUriEnd - nPos),
703cdf0e10cSrcweir                                            INET_PROT_HTTP, eMechanism,
704cdf0e10cSrcweir                                            eCharset);
705cdf0e10cSrcweir                         if (!aUri.HasError())
706cdf0e10cSrcweir                         {
707cdf0e10cSrcweir                             rBegin = nPos;
708cdf0e10cSrcweir                             rEnd = nUriEnd;
709cdf0e10cSrcweir                             return
710cdf0e10cSrcweir                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
711cdf0e10cSrcweir                         }
712cdf0e10cSrcweir                     }
713cdf0e10cSrcweir                 }
714cdf0e10cSrcweir 
715cdf0e10cSrcweir                 // 3rd, 4th:
716cdf0e10cSrcweir                 i = nPos;
717cdf0e10cSrcweir                 sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
718cdf0e10cSrcweir                 if (nLabels >= 3
719cdf0e10cSrcweir                     && rText.GetChar(nPos + 3) == '.'
720cdf0e10cSrcweir                     && (((rText.GetChar(nPos) == 'w'
721cdf0e10cSrcweir                           || rText.GetChar(nPos) == 'W')
722cdf0e10cSrcweir                          && (rText.GetChar(nPos + 1) == 'w'
723cdf0e10cSrcweir                              || rText.GetChar(nPos + 1) == 'W')
724cdf0e10cSrcweir                          && (rText.GetChar(nPos + 2) == 'w'
725cdf0e10cSrcweir                              || rText.GetChar(nPos + 2) == 'W'))
726cdf0e10cSrcweir                         || ((rText.GetChar(nPos) == 'f'
727cdf0e10cSrcweir                              || rText.GetChar(nPos) == 'F')
728cdf0e10cSrcweir                             && (rText.GetChar(nPos + 1) == 't'
729cdf0e10cSrcweir                                 || rText.GetChar(nPos + 1) == 'T')
730cdf0e10cSrcweir                             && (rText.GetChar(nPos + 2) == 'p'
731cdf0e10cSrcweir                                 || rText.GetChar(nPos + 2) == 'P'))))
732cdf0e10cSrcweir                     // (note that rText.GetChar(nPos + 3) is guaranteed to be
733cdf0e10cSrcweir                     // valid)
734cdf0e10cSrcweir                 {
735cdf0e10cSrcweir                     xub_StrLen nUriEnd = i;
736cdf0e10cSrcweir                     if (i != rEnd && rText.GetChar(i) == '/')
737cdf0e10cSrcweir                     {
738cdf0e10cSrcweir                         nUriEnd = ++i;
739cdf0e10cSrcweir                         while (i != rEnd
740cdf0e10cSrcweir                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
741cdf0e10cSrcweir                     }
742cdf0e10cSrcweir                     if (i != rEnd && rText.GetChar(i) == '#')
743cdf0e10cSrcweir                     {
744cdf0e10cSrcweir                         ++i;
745cdf0e10cSrcweir                         while (i != rEnd
746cdf0e10cSrcweir                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
747cdf0e10cSrcweir                     }
748cdf0e10cSrcweir                     if (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
749cdf0e10cSrcweir                         || rText.GetChar(nUriEnd) == '\\')
750cdf0e10cSrcweir                     {
751cdf0e10cSrcweir                         INetURLObject aUri(UniString(rText, nPos,
752cdf0e10cSrcweir                                                      nUriEnd - nPos),
753cdf0e10cSrcweir                                            INET_PROT_HTTP, eMechanism,
754cdf0e10cSrcweir                                            eCharset);
755cdf0e10cSrcweir                         if (!aUri.HasError())
756cdf0e10cSrcweir                         {
757cdf0e10cSrcweir                             rBegin = nPos;
758cdf0e10cSrcweir                             rEnd = nUriEnd;
759cdf0e10cSrcweir                             return
760cdf0e10cSrcweir                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
761cdf0e10cSrcweir                         }
762cdf0e10cSrcweir                     }
763cdf0e10cSrcweir                 }
764cdf0e10cSrcweir 
765cdf0e10cSrcweir                 if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 3
766cdf0e10cSrcweir                     && rText.GetChar(nPos + 1) == ':'
767cdf0e10cSrcweir                     && (rText.GetChar(nPos + 2) == '/'
768cdf0e10cSrcweir                         || rText.GetChar(nPos + 2) == '\\')) // 7th, 8th
769cdf0e10cSrcweir                 {
770cdf0e10cSrcweir                     i = nPos + 3;
771cdf0e10cSrcweir                     xub_StrLen nUriEnd = i;
772cdf0e10cSrcweir                     while (i != rEnd
773cdf0e10cSrcweir                            && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
774cdf0e10cSrcweir                     if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
775cdf0e10cSrcweir                     {
776cdf0e10cSrcweir                         INetURLObject aUri(UniString(rText, nPos,
777cdf0e10cSrcweir                                                      nUriEnd - nPos),
778cdf0e10cSrcweir                                            INET_PROT_FILE,
779cdf0e10cSrcweir                                            INetURLObject::ENCODE_ALL,
780cdf0e10cSrcweir                                            RTL_TEXTENCODING_UTF8,
781cdf0e10cSrcweir                                            INetURLObject::FSYS_DOS);
782cdf0e10cSrcweir                         if (!aUri.HasError())
783cdf0e10cSrcweir                         {
784cdf0e10cSrcweir                             rBegin = nPos;
785cdf0e10cSrcweir                             rEnd = nUriEnd;
786cdf0e10cSrcweir                             return
787cdf0e10cSrcweir                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
788cdf0e10cSrcweir                         }
789cdf0e10cSrcweir                     }
790cdf0e10cSrcweir                 }
791cdf0e10cSrcweir             }
792cdf0e10cSrcweir             else if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 2
793cdf0e10cSrcweir                      && rText.GetChar(nPos) == '\\'
794cdf0e10cSrcweir                      && rText.GetChar(nPos + 1) == '\\') // 6th
795cdf0e10cSrcweir             {
796cdf0e10cSrcweir                 xub_StrLen i = nPos + 2;
797cdf0e10cSrcweir                 sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
798cdf0e10cSrcweir                 if (nLabels >= 1 && i != rEnd && rText.GetChar(i) == '\\')
799cdf0e10cSrcweir                 {
800cdf0e10cSrcweir                     xub_StrLen nUriEnd = ++i;
801cdf0e10cSrcweir                     while (i != rEnd
802cdf0e10cSrcweir                            && checkWChar(rCharClass, rText, &i, &nUriEnd,
803cdf0e10cSrcweir                                          true)) ;
804cdf0e10cSrcweir                     if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
805cdf0e10cSrcweir                     {
806cdf0e10cSrcweir                         INetURLObject aUri(UniString(rText, nPos,
807cdf0e10cSrcweir                                                      nUriEnd - nPos),
808cdf0e10cSrcweir                                            INET_PROT_FILE,
809cdf0e10cSrcweir                                            INetURLObject::ENCODE_ALL,
810cdf0e10cSrcweir                                            RTL_TEXTENCODING_UTF8,
811cdf0e10cSrcweir                                            INetURLObject::FSYS_DOS);
812cdf0e10cSrcweir                         if (!aUri.HasError())
813cdf0e10cSrcweir                         {
814cdf0e10cSrcweir                             rBegin = nPos;
815cdf0e10cSrcweir                             rEnd = nUriEnd;
816cdf0e10cSrcweir                             return
817cdf0e10cSrcweir                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
818cdf0e10cSrcweir                         }
819cdf0e10cSrcweir                     }
820cdf0e10cSrcweir                 }
821cdf0e10cSrcweir             }
822cdf0e10cSrcweir         }
823cdf0e10cSrcweir         if (bBoundary2 && INetMIME::isAtomChar(c)) // 5th
824cdf0e10cSrcweir         {
825cdf0e10cSrcweir             bool bDot = false;
826cdf0e10cSrcweir             for (xub_StrLen i = nPos + 1; i != rEnd; ++i)
827cdf0e10cSrcweir             {
828cdf0e10cSrcweir                 sal_Unicode c2 = rText.GetChar(i);
829cdf0e10cSrcweir                 if (INetMIME::isAtomChar(c2))
830cdf0e10cSrcweir                     bDot = false;
831cdf0e10cSrcweir                 else if (bDot)
832cdf0e10cSrcweir                     break;
833cdf0e10cSrcweir                 else if (c2 == '.')
834cdf0e10cSrcweir                     bDot = true;
835cdf0e10cSrcweir                 else
836cdf0e10cSrcweir                 {
837cdf0e10cSrcweir                     if (c2 == '@')
838cdf0e10cSrcweir                     {
839cdf0e10cSrcweir                         ++i;
840cdf0e10cSrcweir                         sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
841cdf0e10cSrcweir                         if (nLabels >= 1
842cdf0e10cSrcweir                             && isBoundary1(rCharClass, rText, i, rEnd))
843cdf0e10cSrcweir                         {
844cdf0e10cSrcweir                             INetURLObject aUri(UniString(rText, nPos, i - nPos),
845cdf0e10cSrcweir                                                INET_PROT_MAILTO,
846cdf0e10cSrcweir                                                INetURLObject::ENCODE_ALL);
847cdf0e10cSrcweir                             if (!aUri.HasError())
848cdf0e10cSrcweir                             {
849cdf0e10cSrcweir                                 rBegin = nPos;
850cdf0e10cSrcweir                                 rEnd = i;
851cdf0e10cSrcweir                                 return aUri.GetMainURL(
852cdf0e10cSrcweir                                            INetURLObject::DECODE_TO_IURI);
853cdf0e10cSrcweir                             }
854cdf0e10cSrcweir                         }
855cdf0e10cSrcweir                     }
856cdf0e10cSrcweir                     break;
857cdf0e10cSrcweir                 }
858cdf0e10cSrcweir             }
859cdf0e10cSrcweir         }
860cdf0e10cSrcweir         bBoundary1 = isBoundary1(rCharClass, rText, nPos, rEnd);
861cdf0e10cSrcweir         bBoundary2 = isBoundary2(rCharClass, rText, nPos, rEnd);
862cdf0e10cSrcweir     }
863cdf0e10cSrcweir     rBegin = rEnd;
864cdf0e10cSrcweir     return UniString();
865cdf0e10cSrcweir }
866cdf0e10cSrcweir 
867cdf0e10cSrcweir //============================================================================
868cdf0e10cSrcweir //
869cdf0e10cSrcweir //  removePassword
870cdf0e10cSrcweir //
871cdf0e10cSrcweir //============================================================================
872cdf0e10cSrcweir 
873cdf0e10cSrcweir UniString
removePassword(UniString const & rURI,INetURLObject::EncodeMechanism eEncodeMechanism,INetURLObject::DecodeMechanism eDecodeMechanism,rtl_TextEncoding eCharset)874cdf0e10cSrcweir URIHelper::removePassword(UniString const & rURI,
875cdf0e10cSrcweir 						  INetURLObject::EncodeMechanism eEncodeMechanism,
876cdf0e10cSrcweir 						  INetURLObject::DecodeMechanism eDecodeMechanism,
877cdf0e10cSrcweir 						  rtl_TextEncoding eCharset)
878cdf0e10cSrcweir {
879cdf0e10cSrcweir 	INetURLObject aObj(rURI, eEncodeMechanism, eCharset);
880cdf0e10cSrcweir 	return aObj.HasError() ?
881cdf0e10cSrcweir 		       rURI :
882cdf0e10cSrcweir 		       String(aObj.GetURLNoPass(eDecodeMechanism, eCharset));
883cdf0e10cSrcweir }
884cdf0e10cSrcweir 
885cdf0e10cSrcweir //============================================================================
886cdf0e10cSrcweir //
887cdf0e10cSrcweir //  queryFSysStyle
888cdf0e10cSrcweir //
889cdf0e10cSrcweir //============================================================================
890cdf0e10cSrcweir 
queryFSysStyle(UniString const & rFileUrl,bool bAddConvenienceStyles)891cdf0e10cSrcweir INetURLObject::FSysStyle URIHelper::queryFSysStyle(UniString const & rFileUrl,
892cdf0e10cSrcweir 												   bool bAddConvenienceStyles)
893cdf0e10cSrcweir 	throw (uno::RuntimeException)
894cdf0e10cSrcweir {
895cdf0e10cSrcweir 	::ucbhelper::ContentBroker const * pBroker = ::ucbhelper::ContentBroker::get();
896cdf0e10cSrcweir 	uno::Reference< ucb::XContentProviderManager > xManager;
897cdf0e10cSrcweir 	if (pBroker)
898cdf0e10cSrcweir 		xManager = pBroker->getContentProviderManagerInterface();
899cdf0e10cSrcweir 	uno::Reference< beans::XPropertySet > xProperties;
900cdf0e10cSrcweir 	if (xManager.is())
901cdf0e10cSrcweir 		xProperties
902cdf0e10cSrcweir 			= uno::Reference< beans::XPropertySet >(
903cdf0e10cSrcweir 				  xManager->queryContentProvider(rFileUrl), uno::UNO_QUERY);
904cdf0e10cSrcweir 	sal_Int32 nNotation = ucb::FileSystemNotation::UNKNOWN_NOTATION;
905cdf0e10cSrcweir 	if (xProperties.is())
906cdf0e10cSrcweir 		try
907cdf0e10cSrcweir 		{
908cdf0e10cSrcweir 			xProperties->getPropertyValue(rtl::OUString(
909cdf0e10cSrcweir 				                              RTL_CONSTASCII_USTRINGPARAM(
910cdf0e10cSrcweir 												  "FileSystemNotation")))
911cdf0e10cSrcweir 				>>= nNotation;
912cdf0e10cSrcweir 		}
913cdf0e10cSrcweir 		catch (beans::UnknownPropertyException const &) {}
914cdf0e10cSrcweir 		catch (lang::WrappedTargetException const &) {}
915cdf0e10cSrcweir 
916cdf0e10cSrcweir 	// The following code depends on the fact that the
917cdf0e10cSrcweir 	// com::sun::star::ucb::FileSystemNotation constants range from UNKNOWN to
918cdf0e10cSrcweir 	// MAC, without any holes.  The table below has two entries per notation,
919cdf0e10cSrcweir 	// the first is used if bAddConvenienceStyles == false, while the second
920cdf0e10cSrcweir 	// is used if bAddConvenienceStyles == true:
921cdf0e10cSrcweir 	static INetURLObject::FSysStyle const aMap[][2]
922cdf0e10cSrcweir 		= { { INetURLObject::FSysStyle(0),
923cdf0e10cSrcweir 			  INetURLObject::FSYS_DETECT },
924cdf0e10cSrcweir 			    // UNKNOWN
925cdf0e10cSrcweir 			{ INetURLObject::FSYS_UNX,
926cdf0e10cSrcweir 			  INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
927cdf0e10cSrcweir 									       | INetURLObject::FSYS_UNX) },
928cdf0e10cSrcweir 			    // UNIX
929cdf0e10cSrcweir 			{ INetURLObject::FSYS_DOS,
930cdf0e10cSrcweir 			  INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
931cdf0e10cSrcweir 									       | INetURLObject::FSYS_UNX
932cdf0e10cSrcweir 									       | INetURLObject::FSYS_DOS) },
933cdf0e10cSrcweir 			    // DOS
934cdf0e10cSrcweir 			{ INetURLObject::FSYS_MAC,
935cdf0e10cSrcweir 			  INetURLObject::FSysStyle(INetURLObject::FSYS_VOS
936cdf0e10cSrcweir 									       | INetURLObject::FSYS_UNX
937cdf0e10cSrcweir 									       | INetURLObject::FSYS_MAC) } };
938cdf0e10cSrcweir 	return aMap[nNotation < ucb::FileSystemNotation::UNKNOWN_NOTATION
939cdf0e10cSrcweir 			    || nNotation > ucb::FileSystemNotation::MAC_NOTATION ?
940cdf0e10cSrcweir 			            0 :
941cdf0e10cSrcweir 			            nNotation
942cdf0e10cSrcweir 			                - ucb::FileSystemNotation::UNKNOWN_NOTATION]
943cdf0e10cSrcweir 		           [bAddConvenienceStyles];
944cdf0e10cSrcweir }
945