xref: /trunk/main/cppuhelper/source/unourl.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_cppuhelper.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "cppuhelper/unourl.hxx"
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include "osl/diagnose.h"
34*cdf0e10cSrcweir #include "rtl/malformeduriexception.hxx"
35*cdf0e10cSrcweir #include "rtl/string.h"
36*cdf0e10cSrcweir #include "rtl/textenc.h"
37*cdf0e10cSrcweir #include "rtl/uri.h"
38*cdf0e10cSrcweir #include "rtl/uri.hxx"
39*cdf0e10cSrcweir #include "rtl/ustring.h"
40*cdf0e10cSrcweir #include "rtl/ustring.hxx"
41*cdf0e10cSrcweir #include "sal/types.h"
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #include <map>
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir using cppu::UnoUrl;
46*cdf0e10cSrcweir using cppu::UnoUrlDescriptor;
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir namespace {
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir inline bool isAlphanum(sal_Unicode c)
51*cdf0e10cSrcweir {
52*cdf0e10cSrcweir     return (c >= 0x30 && c <= 0x39) // '0'--'9'
53*cdf0e10cSrcweir         || (c >= 0x41 && c <= 0x5A) // 'A'--'Z'
54*cdf0e10cSrcweir         || (c >= 0x61 && c <= 0x7A); // 'a'--'z'
55*cdf0e10cSrcweir }
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir }
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir class UnoUrlDescriptor::Impl
60*cdf0e10cSrcweir {
61*cdf0e10cSrcweir public:
62*cdf0e10cSrcweir     typedef std::map< rtl::OUString, rtl::OUString > Parameters;
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir     rtl::OUString m_aDescriptor;
65*cdf0e10cSrcweir     rtl::OUString m_aName;
66*cdf0e10cSrcweir     Parameters m_aParameters;
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir     /** @exception rtl::MalformedUriException
69*cdf0e10cSrcweir      */
70*cdf0e10cSrcweir     explicit inline Impl(rtl::OUString const & m_aDescriptor);
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir     inline Impl * clone() const { return new Impl(*this); }
73*cdf0e10cSrcweir };
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir inline UnoUrlDescriptor::Impl::Impl(rtl::OUString const & rDescriptor)
76*cdf0e10cSrcweir {
77*cdf0e10cSrcweir     m_aDescriptor = rDescriptor;
78*cdf0e10cSrcweir     enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE };
79*cdf0e10cSrcweir     State eState = STATE_NAME0;
80*cdf0e10cSrcweir     sal_Int32 nStart = 0;
81*cdf0e10cSrcweir     rtl::OUString aKey;
82*cdf0e10cSrcweir     for (sal_Int32 i = 0;; ++i)
83*cdf0e10cSrcweir     {
84*cdf0e10cSrcweir         bool bEnd = i == rDescriptor.getLength();
85*cdf0e10cSrcweir         sal_Unicode c = bEnd ? 0 : rDescriptor.getStr()[i];
86*cdf0e10cSrcweir         switch (eState)
87*cdf0e10cSrcweir         {
88*cdf0e10cSrcweir         case STATE_NAME0:
89*cdf0e10cSrcweir             if (bEnd || !isAlphanum(c))
90*cdf0e10cSrcweir                 throw rtl::MalformedUriException(
91*cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
92*cdf0e10cSrcweir                                       "UNO URL contains bad descriptor name")));
93*cdf0e10cSrcweir             nStart = i;
94*cdf0e10cSrcweir             eState = STATE_NAME;
95*cdf0e10cSrcweir             break;
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir         case STATE_NAME:
98*cdf0e10cSrcweir             if (bEnd || c == 0x2C) // ','
99*cdf0e10cSrcweir             {
100*cdf0e10cSrcweir                 m_aName
101*cdf0e10cSrcweir                     = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
102*cdf0e10cSrcweir                 eState = STATE_KEY0;
103*cdf0e10cSrcweir             }
104*cdf0e10cSrcweir             else if (!isAlphanum(c))
105*cdf0e10cSrcweir                 throw rtl::MalformedUriException(
106*cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
107*cdf0e10cSrcweir                                       "UNO URL contains bad descriptor name")));
108*cdf0e10cSrcweir             break;
109*cdf0e10cSrcweir 
110*cdf0e10cSrcweir         case STATE_KEY0:
111*cdf0e10cSrcweir             if (bEnd || !isAlphanum(c))
112*cdf0e10cSrcweir                 throw rtl::MalformedUriException(
113*cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
114*cdf0e10cSrcweir                                       "UNO URL contains bad parameter key")));
115*cdf0e10cSrcweir             nStart = i;
116*cdf0e10cSrcweir             eState = STATE_KEY;
117*cdf0e10cSrcweir             break;
118*cdf0e10cSrcweir 
119*cdf0e10cSrcweir         case STATE_KEY:
120*cdf0e10cSrcweir             if (c == 0x3D) // '='
121*cdf0e10cSrcweir             {
122*cdf0e10cSrcweir                 aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
123*cdf0e10cSrcweir                 nStart = i + 1;
124*cdf0e10cSrcweir                 eState = STATE_VALUE;
125*cdf0e10cSrcweir             }
126*cdf0e10cSrcweir             else if (bEnd || !isAlphanum(c))
127*cdf0e10cSrcweir                 throw rtl::MalformedUriException(
128*cdf0e10cSrcweir                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
129*cdf0e10cSrcweir                                       "UNO URL contains bad parameter key")));
130*cdf0e10cSrcweir             break;
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir         case STATE_VALUE:
133*cdf0e10cSrcweir             if (bEnd || c == 0x2C) // ','
134*cdf0e10cSrcweir             {
135*cdf0e10cSrcweir                 if (!m_aParameters.insert(
136*cdf0e10cSrcweir                         Parameters::value_type(
137*cdf0e10cSrcweir                             aKey,
138*cdf0e10cSrcweir                             rtl::Uri::decode(rDescriptor.copy(nStart,
139*cdf0e10cSrcweir                                                               i - nStart),
140*cdf0e10cSrcweir                                              rtl_UriDecodeWithCharset,
141*cdf0e10cSrcweir                                              RTL_TEXTENCODING_UTF8))).second)
142*cdf0e10cSrcweir                     throw rtl::MalformedUriException(
143*cdf0e10cSrcweir                         rtl::OUString(
144*cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM(
145*cdf0e10cSrcweir                                 "UNO URL contains duplicated parameter")));
146*cdf0e10cSrcweir                 eState = STATE_KEY0;
147*cdf0e10cSrcweir             }
148*cdf0e10cSrcweir             break;
149*cdf0e10cSrcweir         }
150*cdf0e10cSrcweir         if (bEnd)
151*cdf0e10cSrcweir             break;
152*cdf0e10cSrcweir     }
153*cdf0e10cSrcweir }
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(rtl::OUString const & rDescriptor):
156*cdf0e10cSrcweir     m_xImpl(new Impl(rDescriptor))
157*cdf0e10cSrcweir {}
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(std::auto_ptr< Impl > & rImpl):
160*cdf0e10cSrcweir     m_xImpl(rImpl)
161*cdf0e10cSrcweir {}
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther):
164*cdf0e10cSrcweir     m_xImpl(rOther.m_xImpl->clone())
165*cdf0e10cSrcweir {}
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir UnoUrlDescriptor::~UnoUrlDescriptor()
168*cdf0e10cSrcweir {}
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir UnoUrlDescriptor & UnoUrlDescriptor::operator =(UnoUrlDescriptor const & rOther)
171*cdf0e10cSrcweir {
172*cdf0e10cSrcweir     m_xImpl.reset(rOther.m_xImpl->clone());
173*cdf0e10cSrcweir     return *this;
174*cdf0e10cSrcweir }
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir rtl::OUString const & UnoUrlDescriptor::getDescriptor() const
177*cdf0e10cSrcweir {
178*cdf0e10cSrcweir     return m_xImpl->m_aDescriptor;
179*cdf0e10cSrcweir }
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir rtl::OUString const & UnoUrlDescriptor::getName() const
182*cdf0e10cSrcweir {
183*cdf0e10cSrcweir     return m_xImpl->m_aName;
184*cdf0e10cSrcweir }
185*cdf0e10cSrcweir 
186*cdf0e10cSrcweir bool UnoUrlDescriptor::hasParameter(rtl::OUString const & rKey) const
187*cdf0e10cSrcweir {
188*cdf0e10cSrcweir     return m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase())
189*cdf0e10cSrcweir         != m_xImpl->m_aParameters.end();
190*cdf0e10cSrcweir }
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir rtl::OUString UnoUrlDescriptor::getParameter(rtl::OUString const & rKey) const
193*cdf0e10cSrcweir {
194*cdf0e10cSrcweir     Impl::Parameters::const_iterator
195*cdf0e10cSrcweir         aIt(m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase()));
196*cdf0e10cSrcweir     return aIt == m_xImpl->m_aParameters.end() ? rtl::OUString() : aIt->second;
197*cdf0e10cSrcweir }
198*cdf0e10cSrcweir 
199*cdf0e10cSrcweir class UnoUrl::Impl
200*cdf0e10cSrcweir {
201*cdf0e10cSrcweir public:
202*cdf0e10cSrcweir     UnoUrlDescriptor m_aConnection;
203*cdf0e10cSrcweir     UnoUrlDescriptor m_aProtocol;
204*cdf0e10cSrcweir     rtl::OUString m_aObjectName;
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir     inline Impl * clone() const { return new Impl(*this); }
207*cdf0e10cSrcweir 
208*cdf0e10cSrcweir     /** @exception rtl::MalformedUriException
209*cdf0e10cSrcweir      */
210*cdf0e10cSrcweir     static inline Impl * create(rtl::OUString const & rUrl);
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir private:
213*cdf0e10cSrcweir     inline Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
214*cdf0e10cSrcweir                 std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
215*cdf0e10cSrcweir                 rtl::OUString const & rObjectName);
216*cdf0e10cSrcweir };
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir inline UnoUrl::Impl::Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
219*cdf0e10cSrcweir                           std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
220*cdf0e10cSrcweir                           rtl::OUString const & rObjectName):
221*cdf0e10cSrcweir     m_aConnection(rConnection),
222*cdf0e10cSrcweir     m_aProtocol(rProtocol),
223*cdf0e10cSrcweir     m_aObjectName(rObjectName)
224*cdf0e10cSrcweir {}
225*cdf0e10cSrcweir 
226*cdf0e10cSrcweir inline UnoUrl::Impl * UnoUrl::Impl::create(rtl::OUString const & rUrl)
227*cdf0e10cSrcweir {
228*cdf0e10cSrcweir     if (!rUrl.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("uno:"), 0))
229*cdf0e10cSrcweir         throw rtl::MalformedUriException(
230*cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
231*cdf0e10cSrcweir                               "UNO URL does not start with \"uno:\"")));
232*cdf0e10cSrcweir     sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:");
233*cdf0e10cSrcweir     sal_Int32 j = rUrl.indexOf(';', i);
234*cdf0e10cSrcweir     if (j < 0)
235*cdf0e10cSrcweir         throw rtl::MalformedUriException(
236*cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
237*cdf0e10cSrcweir                               "UNO URL has too few semicolons")));
238*cdf0e10cSrcweir     std::auto_ptr< UnoUrlDescriptor::Impl >
239*cdf0e10cSrcweir         xConnection(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
240*cdf0e10cSrcweir     i = j + 1;
241*cdf0e10cSrcweir     j = rUrl.indexOf(0x3B, i); // ';'
242*cdf0e10cSrcweir     if (j < 0)
243*cdf0e10cSrcweir         throw rtl::MalformedUriException(
244*cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
245*cdf0e10cSrcweir                               "UNO URL has too few semicolons")));
246*cdf0e10cSrcweir     std::auto_ptr< UnoUrlDescriptor::Impl >
247*cdf0e10cSrcweir         xProtocol(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
248*cdf0e10cSrcweir     i = j + 1;
249*cdf0e10cSrcweir     if (i == rUrl.getLength())
250*cdf0e10cSrcweir         throw rtl::MalformedUriException(
251*cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
252*cdf0e10cSrcweir                               "UNO URL contains empty ObjectName")));
253*cdf0e10cSrcweir     for (j = i; j < rUrl.getLength(); ++j)
254*cdf0e10cSrcweir     {
255*cdf0e10cSrcweir         sal_Unicode c = rUrl.getStr()[j];
256*cdf0e10cSrcweir         if (!isAlphanum(c) && c != 0x21 && c != 0x24 // '!', '$'
257*cdf0e10cSrcweir             && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '('
258*cdf0e10cSrcweir             && c != 0x28 && c != 0x2A && c != 0x2B // ')', '*', '+'
259*cdf0e10cSrcweir             && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.'
260*cdf0e10cSrcweir             && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '='
261*cdf0e10cSrcweir             && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_'
262*cdf0e10cSrcweir             && c != 0x7E) // '~'
263*cdf0e10cSrcweir             throw rtl::MalformedUriException(
264*cdf0e10cSrcweir                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
265*cdf0e10cSrcweir                                   "UNO URL contains invalid ObjectName")));
266*cdf0e10cSrcweir     }
267*cdf0e10cSrcweir     return new Impl(xConnection, xProtocol, rUrl.copy(i));
268*cdf0e10cSrcweir }
269*cdf0e10cSrcweir 
270*cdf0e10cSrcweir UnoUrl::UnoUrl(rtl::OUString const & rUrl): m_xImpl(Impl::create(rUrl))
271*cdf0e10cSrcweir {}
272*cdf0e10cSrcweir 
273*cdf0e10cSrcweir UnoUrl::UnoUrl(UnoUrl const & rOther): m_xImpl(rOther.m_xImpl->clone())
274*cdf0e10cSrcweir {}
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir UnoUrl::~UnoUrl()
277*cdf0e10cSrcweir {}
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir UnoUrl & UnoUrl::operator =(UnoUrl const & rOther)
280*cdf0e10cSrcweir {
281*cdf0e10cSrcweir     m_xImpl.reset(rOther.m_xImpl->clone());
282*cdf0e10cSrcweir     return *this;
283*cdf0e10cSrcweir }
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir UnoUrlDescriptor const & UnoUrl::getConnection() const
286*cdf0e10cSrcweir {
287*cdf0e10cSrcweir     return m_xImpl->m_aConnection;
288*cdf0e10cSrcweir }
289*cdf0e10cSrcweir 
290*cdf0e10cSrcweir UnoUrlDescriptor const & UnoUrl::getProtocol() const
291*cdf0e10cSrcweir {
292*cdf0e10cSrcweir     return m_xImpl->m_aProtocol;
293*cdf0e10cSrcweir }
294*cdf0e10cSrcweir 
295*cdf0e10cSrcweir rtl::OUString const & UnoUrl::getObjectName() const
296*cdf0e10cSrcweir {
297*cdf0e10cSrcweir     return m_xImpl->m_aObjectName;
298*cdf0e10cSrcweir }
299