xref: /aoo41x/main/cppuhelper/source/unourl.cxx (revision 9d7e27ac)
1*9d7e27acSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9d7e27acSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9d7e27acSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9d7e27acSAndrew Rist  * distributed with this work for additional information
6*9d7e27acSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9d7e27acSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9d7e27acSAndrew Rist  * "License"); you may not use this file except in compliance
9*9d7e27acSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*9d7e27acSAndrew Rist  *
11*9d7e27acSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*9d7e27acSAndrew Rist  *
13*9d7e27acSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9d7e27acSAndrew Rist  * software distributed under the License is distributed on an
15*9d7e27acSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9d7e27acSAndrew Rist  * KIND, either express or implied.  See the License for the
17*9d7e27acSAndrew Rist  * specific language governing permissions and limitations
18*9d7e27acSAndrew Rist  * under the License.
19*9d7e27acSAndrew Rist  *
20*9d7e27acSAndrew Rist  *************************************************************/
21*9d7e27acSAndrew Rist 
22*9d7e27acSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_cppuhelper.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "cppuhelper/unourl.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "osl/diagnose.h"
30cdf0e10cSrcweir #include "rtl/malformeduriexception.hxx"
31cdf0e10cSrcweir #include "rtl/string.h"
32cdf0e10cSrcweir #include "rtl/textenc.h"
33cdf0e10cSrcweir #include "rtl/uri.h"
34cdf0e10cSrcweir #include "rtl/uri.hxx"
35cdf0e10cSrcweir #include "rtl/ustring.h"
36cdf0e10cSrcweir #include "rtl/ustring.hxx"
37cdf0e10cSrcweir #include "sal/types.h"
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <map>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir using cppu::UnoUrl;
42cdf0e10cSrcweir using cppu::UnoUrlDescriptor;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir namespace {
45cdf0e10cSrcweir 
isAlphanum(sal_Unicode c)46cdf0e10cSrcweir inline bool isAlphanum(sal_Unicode c)
47cdf0e10cSrcweir {
48cdf0e10cSrcweir     return (c >= 0x30 && c <= 0x39) // '0'--'9'
49cdf0e10cSrcweir         || (c >= 0x41 && c <= 0x5A) // 'A'--'Z'
50cdf0e10cSrcweir         || (c >= 0x61 && c <= 0x7A); // 'a'--'z'
51cdf0e10cSrcweir }
52cdf0e10cSrcweir 
53cdf0e10cSrcweir }
54cdf0e10cSrcweir 
55cdf0e10cSrcweir class UnoUrlDescriptor::Impl
56cdf0e10cSrcweir {
57cdf0e10cSrcweir public:
58cdf0e10cSrcweir     typedef std::map< rtl::OUString, rtl::OUString > Parameters;
59cdf0e10cSrcweir 
60cdf0e10cSrcweir     rtl::OUString m_aDescriptor;
61cdf0e10cSrcweir     rtl::OUString m_aName;
62cdf0e10cSrcweir     Parameters m_aParameters;
63cdf0e10cSrcweir 
64cdf0e10cSrcweir     /** @exception rtl::MalformedUriException
65cdf0e10cSrcweir      */
66cdf0e10cSrcweir     explicit inline Impl(rtl::OUString const & m_aDescriptor);
67cdf0e10cSrcweir 
clone() const68cdf0e10cSrcweir     inline Impl * clone() const { return new Impl(*this); }
69cdf0e10cSrcweir };
70cdf0e10cSrcweir 
Impl(rtl::OUString const & rDescriptor)71cdf0e10cSrcweir inline UnoUrlDescriptor::Impl::Impl(rtl::OUString const & rDescriptor)
72cdf0e10cSrcweir {
73cdf0e10cSrcweir     m_aDescriptor = rDescriptor;
74cdf0e10cSrcweir     enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE };
75cdf0e10cSrcweir     State eState = STATE_NAME0;
76cdf0e10cSrcweir     sal_Int32 nStart = 0;
77cdf0e10cSrcweir     rtl::OUString aKey;
78cdf0e10cSrcweir     for (sal_Int32 i = 0;; ++i)
79cdf0e10cSrcweir     {
80cdf0e10cSrcweir         bool bEnd = i == rDescriptor.getLength();
81cdf0e10cSrcweir         sal_Unicode c = bEnd ? 0 : rDescriptor.getStr()[i];
82cdf0e10cSrcweir         switch (eState)
83cdf0e10cSrcweir         {
84cdf0e10cSrcweir         case STATE_NAME0:
85cdf0e10cSrcweir             if (bEnd || !isAlphanum(c))
86cdf0e10cSrcweir                 throw rtl::MalformedUriException(
87cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
88cdf0e10cSrcweir                                       "UNO URL contains bad descriptor name")));
89cdf0e10cSrcweir             nStart = i;
90cdf0e10cSrcweir             eState = STATE_NAME;
91cdf0e10cSrcweir             break;
92cdf0e10cSrcweir 
93cdf0e10cSrcweir         case STATE_NAME:
94cdf0e10cSrcweir             if (bEnd || c == 0x2C) // ','
95cdf0e10cSrcweir             {
96cdf0e10cSrcweir                 m_aName
97cdf0e10cSrcweir                     = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
98cdf0e10cSrcweir                 eState = STATE_KEY0;
99cdf0e10cSrcweir             }
100cdf0e10cSrcweir             else if (!isAlphanum(c))
101cdf0e10cSrcweir                 throw rtl::MalformedUriException(
102cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
103cdf0e10cSrcweir                                       "UNO URL contains bad descriptor name")));
104cdf0e10cSrcweir             break;
105cdf0e10cSrcweir 
106cdf0e10cSrcweir         case STATE_KEY0:
107cdf0e10cSrcweir             if (bEnd || !isAlphanum(c))
108cdf0e10cSrcweir                 throw rtl::MalformedUriException(
109cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
110cdf0e10cSrcweir                                       "UNO URL contains bad parameter key")));
111cdf0e10cSrcweir             nStart = i;
112cdf0e10cSrcweir             eState = STATE_KEY;
113cdf0e10cSrcweir             break;
114cdf0e10cSrcweir 
115cdf0e10cSrcweir         case STATE_KEY:
116cdf0e10cSrcweir             if (c == 0x3D) // '='
117cdf0e10cSrcweir             {
118cdf0e10cSrcweir                 aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
119cdf0e10cSrcweir                 nStart = i + 1;
120cdf0e10cSrcweir                 eState = STATE_VALUE;
121cdf0e10cSrcweir             }
122cdf0e10cSrcweir             else if (bEnd || !isAlphanum(c))
123cdf0e10cSrcweir                 throw rtl::MalformedUriException(
124cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
125cdf0e10cSrcweir                                       "UNO URL contains bad parameter key")));
126cdf0e10cSrcweir             break;
127cdf0e10cSrcweir 
128cdf0e10cSrcweir         case STATE_VALUE:
129cdf0e10cSrcweir             if (bEnd || c == 0x2C) // ','
130cdf0e10cSrcweir             {
131cdf0e10cSrcweir                 if (!m_aParameters.insert(
132cdf0e10cSrcweir                         Parameters::value_type(
133cdf0e10cSrcweir                             aKey,
134cdf0e10cSrcweir                             rtl::Uri::decode(rDescriptor.copy(nStart,
135cdf0e10cSrcweir                                                               i - nStart),
136cdf0e10cSrcweir                                              rtl_UriDecodeWithCharset,
137cdf0e10cSrcweir                                              RTL_TEXTENCODING_UTF8))).second)
138cdf0e10cSrcweir                     throw rtl::MalformedUriException(
139cdf0e10cSrcweir                         rtl::OUString(
140cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM(
141cdf0e10cSrcweir                                 "UNO URL contains duplicated parameter")));
142cdf0e10cSrcweir                 eState = STATE_KEY0;
143cdf0e10cSrcweir             }
144cdf0e10cSrcweir             break;
145cdf0e10cSrcweir         }
146cdf0e10cSrcweir         if (bEnd)
147cdf0e10cSrcweir             break;
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir }
150cdf0e10cSrcweir 
UnoUrlDescriptor(rtl::OUString const & rDescriptor)151cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(rtl::OUString const & rDescriptor):
152cdf0e10cSrcweir     m_xImpl(new Impl(rDescriptor))
153cdf0e10cSrcweir {}
154cdf0e10cSrcweir 
UnoUrlDescriptor(std::auto_ptr<Impl> & rImpl)155cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(std::auto_ptr< Impl > & rImpl):
156cdf0e10cSrcweir     m_xImpl(rImpl)
157cdf0e10cSrcweir {}
158cdf0e10cSrcweir 
UnoUrlDescriptor(UnoUrlDescriptor const & rOther)159cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther):
160cdf0e10cSrcweir     m_xImpl(rOther.m_xImpl->clone())
161cdf0e10cSrcweir {}
162cdf0e10cSrcweir 
~UnoUrlDescriptor()163cdf0e10cSrcweir UnoUrlDescriptor::~UnoUrlDescriptor()
164cdf0e10cSrcweir {}
165cdf0e10cSrcweir 
operator =(UnoUrlDescriptor const & rOther)166cdf0e10cSrcweir UnoUrlDescriptor & UnoUrlDescriptor::operator =(UnoUrlDescriptor const & rOther)
167cdf0e10cSrcweir {
168cdf0e10cSrcweir     m_xImpl.reset(rOther.m_xImpl->clone());
169cdf0e10cSrcweir     return *this;
170cdf0e10cSrcweir }
171cdf0e10cSrcweir 
getDescriptor() const172cdf0e10cSrcweir rtl::OUString const & UnoUrlDescriptor::getDescriptor() const
173cdf0e10cSrcweir {
174cdf0e10cSrcweir     return m_xImpl->m_aDescriptor;
175cdf0e10cSrcweir }
176cdf0e10cSrcweir 
getName() const177cdf0e10cSrcweir rtl::OUString const & UnoUrlDescriptor::getName() const
178cdf0e10cSrcweir {
179cdf0e10cSrcweir     return m_xImpl->m_aName;
180cdf0e10cSrcweir }
181cdf0e10cSrcweir 
hasParameter(rtl::OUString const & rKey) const182cdf0e10cSrcweir bool UnoUrlDescriptor::hasParameter(rtl::OUString const & rKey) const
183cdf0e10cSrcweir {
184cdf0e10cSrcweir     return m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase())
185cdf0e10cSrcweir         != m_xImpl->m_aParameters.end();
186cdf0e10cSrcweir }
187cdf0e10cSrcweir 
getParameter(rtl::OUString const & rKey) const188cdf0e10cSrcweir rtl::OUString UnoUrlDescriptor::getParameter(rtl::OUString const & rKey) const
189cdf0e10cSrcweir {
190cdf0e10cSrcweir     Impl::Parameters::const_iterator
191cdf0e10cSrcweir         aIt(m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase()));
192cdf0e10cSrcweir     return aIt == m_xImpl->m_aParameters.end() ? rtl::OUString() : aIt->second;
193cdf0e10cSrcweir }
194cdf0e10cSrcweir 
195cdf0e10cSrcweir class UnoUrl::Impl
196cdf0e10cSrcweir {
197cdf0e10cSrcweir public:
198cdf0e10cSrcweir     UnoUrlDescriptor m_aConnection;
199cdf0e10cSrcweir     UnoUrlDescriptor m_aProtocol;
200cdf0e10cSrcweir     rtl::OUString m_aObjectName;
201cdf0e10cSrcweir 
clone() const202cdf0e10cSrcweir     inline Impl * clone() const { return new Impl(*this); }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     /** @exception rtl::MalformedUriException
205cdf0e10cSrcweir      */
206cdf0e10cSrcweir     static inline Impl * create(rtl::OUString const & rUrl);
207cdf0e10cSrcweir 
208cdf0e10cSrcweir private:
209cdf0e10cSrcweir     inline Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
210cdf0e10cSrcweir                 std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
211cdf0e10cSrcweir                 rtl::OUString const & rObjectName);
212cdf0e10cSrcweir };
213cdf0e10cSrcweir 
Impl(std::auto_ptr<UnoUrlDescriptor::Impl> & rConnection,std::auto_ptr<UnoUrlDescriptor::Impl> & rProtocol,rtl::OUString const & rObjectName)214cdf0e10cSrcweir inline UnoUrl::Impl::Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
215cdf0e10cSrcweir                           std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
216cdf0e10cSrcweir                           rtl::OUString const & rObjectName):
217cdf0e10cSrcweir     m_aConnection(rConnection),
218cdf0e10cSrcweir     m_aProtocol(rProtocol),
219cdf0e10cSrcweir     m_aObjectName(rObjectName)
220cdf0e10cSrcweir {}
221cdf0e10cSrcweir 
create(rtl::OUString const & rUrl)222cdf0e10cSrcweir inline UnoUrl::Impl * UnoUrl::Impl::create(rtl::OUString const & rUrl)
223cdf0e10cSrcweir {
224cdf0e10cSrcweir     if (!rUrl.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("uno:"), 0))
225cdf0e10cSrcweir         throw rtl::MalformedUriException(
226cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
227cdf0e10cSrcweir                               "UNO URL does not start with \"uno:\"")));
228cdf0e10cSrcweir     sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:");
229cdf0e10cSrcweir     sal_Int32 j = rUrl.indexOf(';', i);
230cdf0e10cSrcweir     if (j < 0)
231cdf0e10cSrcweir         throw rtl::MalformedUriException(
232cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
233cdf0e10cSrcweir                               "UNO URL has too few semicolons")));
234cdf0e10cSrcweir     std::auto_ptr< UnoUrlDescriptor::Impl >
235cdf0e10cSrcweir         xConnection(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
236cdf0e10cSrcweir     i = j + 1;
237cdf0e10cSrcweir     j = rUrl.indexOf(0x3B, i); // ';'
238cdf0e10cSrcweir     if (j < 0)
239cdf0e10cSrcweir         throw rtl::MalformedUriException(
240cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
241cdf0e10cSrcweir                               "UNO URL has too few semicolons")));
242cdf0e10cSrcweir     std::auto_ptr< UnoUrlDescriptor::Impl >
243cdf0e10cSrcweir         xProtocol(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
244cdf0e10cSrcweir     i = j + 1;
245cdf0e10cSrcweir     if (i == rUrl.getLength())
246cdf0e10cSrcweir         throw rtl::MalformedUriException(
247cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
248cdf0e10cSrcweir                               "UNO URL contains empty ObjectName")));
249cdf0e10cSrcweir     for (j = i; j < rUrl.getLength(); ++j)
250cdf0e10cSrcweir     {
251cdf0e10cSrcweir         sal_Unicode c = rUrl.getStr()[j];
252cdf0e10cSrcweir         if (!isAlphanum(c) && c != 0x21 && c != 0x24 // '!', '$'
253cdf0e10cSrcweir             && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '('
254cdf0e10cSrcweir             && c != 0x28 && c != 0x2A && c != 0x2B // ')', '*', '+'
255cdf0e10cSrcweir             && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.'
256cdf0e10cSrcweir             && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '='
257cdf0e10cSrcweir             && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_'
258cdf0e10cSrcweir             && c != 0x7E) // '~'
259cdf0e10cSrcweir             throw rtl::MalformedUriException(
260cdf0e10cSrcweir                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
261cdf0e10cSrcweir                                   "UNO URL contains invalid ObjectName")));
262cdf0e10cSrcweir     }
263cdf0e10cSrcweir     return new Impl(xConnection, xProtocol, rUrl.copy(i));
264cdf0e10cSrcweir }
265cdf0e10cSrcweir 
UnoUrl(rtl::OUString const & rUrl)266cdf0e10cSrcweir UnoUrl::UnoUrl(rtl::OUString const & rUrl): m_xImpl(Impl::create(rUrl))
267cdf0e10cSrcweir {}
268cdf0e10cSrcweir 
UnoUrl(UnoUrl const & rOther)269cdf0e10cSrcweir UnoUrl::UnoUrl(UnoUrl const & rOther): m_xImpl(rOther.m_xImpl->clone())
270cdf0e10cSrcweir {}
271cdf0e10cSrcweir 
~UnoUrl()272cdf0e10cSrcweir UnoUrl::~UnoUrl()
273cdf0e10cSrcweir {}
274cdf0e10cSrcweir 
operator =(UnoUrl const & rOther)275cdf0e10cSrcweir UnoUrl & UnoUrl::operator =(UnoUrl const & rOther)
276cdf0e10cSrcweir {
277cdf0e10cSrcweir     m_xImpl.reset(rOther.m_xImpl->clone());
278cdf0e10cSrcweir     return *this;
279cdf0e10cSrcweir }
280cdf0e10cSrcweir 
getConnection() const281cdf0e10cSrcweir UnoUrlDescriptor const & UnoUrl::getConnection() const
282cdf0e10cSrcweir {
283cdf0e10cSrcweir     return m_xImpl->m_aConnection;
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
getProtocol() const286cdf0e10cSrcweir UnoUrlDescriptor const & UnoUrl::getProtocol() const
287cdf0e10cSrcweir {
288cdf0e10cSrcweir     return m_xImpl->m_aProtocol;
289cdf0e10cSrcweir }
290cdf0e10cSrcweir 
getObjectName() const291cdf0e10cSrcweir rtl::OUString const & UnoUrl::getObjectName() const
292cdf0e10cSrcweir {
293cdf0e10cSrcweir     return m_xImpl->m_aObjectName;
294cdf0e10cSrcweir }
295