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