LibreOffice Module cppuhelper (master) 1
unourl.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include <cppuhelper/unourl.hxx>
22
23#include <rtl/malformeduriexception.hxx>
24#include <rtl/string.h>
25#include <rtl/textenc.h>
26#include <rtl/uri.h>
27#include <rtl/uri.hxx>
28#include <rtl/ustring.hxx>
29#include <rtl/character.hxx>
30#include <sal/types.h>
31
32#include <map>
33#include <memory>
34#include <utility>
35
36using cppu::UnoUrl;
38
40{
41public:
42 typedef std::map< OUString, OUString > Parameters;
43
44 OUString m_aDescriptor;
45 OUString m_aName;
47
50 explicit inline Impl(OUString const & m_aDescriptor);
51
52 Impl * clone() const { return new Impl(*this); }
53};
54
55inline UnoUrlDescriptor::Impl::Impl(OUString const & rDescriptor)
56{
57 m_aDescriptor = rDescriptor;
58 enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE };
59 State eState = STATE_NAME0;
60 sal_Int32 nStart = 0;
61 OUString aKey;
62 for (sal_Int32 i = 0;; ++i)
63 {
64 bool bEnd = i == rDescriptor.getLength();
65 sal_Unicode c = bEnd ? 0 : rDescriptor[i];
66 switch (eState)
67 {
68 case STATE_NAME0:
69 if (bEnd || !rtl::isAsciiAlphanumeric(c))
70 throw rtl::MalformedUriException(
71 "UNO URL contains bad descriptor name");
72 nStart = i;
73 eState = STATE_NAME;
74 break;
75
76 case STATE_NAME:
77 if (bEnd || c == 0x2C) // ','
78 {
80 = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
81 eState = STATE_KEY0;
82 }
83 else if (!rtl::isAsciiAlphanumeric(c))
84 throw rtl::MalformedUriException(
85 "UNO URL contains bad descriptor name");
86 break;
87
88 case STATE_KEY0:
89 if (bEnd || !rtl::isAsciiAlphanumeric(c))
90 throw rtl::MalformedUriException(
91 "UNO URL contains bad parameter key");
92 nStart = i;
93 eState = STATE_KEY;
94 break;
95
96 case STATE_KEY:
97 if (c == 0x3D) // '='
98 {
99 aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
100 nStart = i + 1;
101 eState = STATE_VALUE;
102 }
103 else if (bEnd || !rtl::isAsciiAlphanumeric(c))
104 throw rtl::MalformedUriException(
105 "UNO URL contains bad parameter key");
106 break;
107
108 case STATE_VALUE:
109 if (bEnd || c == 0x2C) // ','
110 {
111 if (!m_aParameters.emplace(
112 aKey,
113 rtl::Uri::decode(rDescriptor.copy(nStart,
114 i - nStart),
115 rtl_UriDecodeWithCharset,
116 RTL_TEXTENCODING_UTF8)).second)
117 throw rtl::MalformedUriException(
118 "UNO URL contains duplicated parameter");
119 eState = STATE_KEY0;
120 }
121 break;
122 }
123 if (bEnd)
124 break;
125 }
126}
127
128UnoUrlDescriptor::UnoUrlDescriptor(OUString const & rDescriptor):
129 m_pImpl(new Impl(rDescriptor))
130{}
131
132UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther):
133 m_pImpl(rOther.m_pImpl->clone())
134{}
135
137{
138 delete m_pImpl;
139}
140
142{
143 if (this != &rOther)
144 {
145 std::unique_ptr<Impl> newImpl(rOther.m_pImpl->clone());
146 delete m_pImpl;
147 m_pImpl = newImpl.release();
148 }
149 return *this;
150}
151
152OUString const & UnoUrlDescriptor::getDescriptor() const
153{
154 return m_pImpl->m_aDescriptor;
155}
156
157OUString const & UnoUrlDescriptor::getName() const
158{
159 return m_pImpl->m_aName;
160}
161
162bool UnoUrlDescriptor::hasParameter(OUString const & rKey) const
163{
164 return m_pImpl->m_aParameters.find(rKey.toAsciiLowerCase())
165 != m_pImpl->m_aParameters.end();
166}
167
168OUString UnoUrlDescriptor::getParameter(OUString const & rKey) const
169{
170 Impl::Parameters::const_iterator
171 aIt(m_pImpl->m_aParameters.find(rKey.toAsciiLowerCase()));
172 return aIt == m_pImpl->m_aParameters.end() ? OUString() : aIt->second;
173}
174
176{
177public:
181
182 Impl * clone() const { return new Impl(*this); }
183
186 static inline Impl * create(OUString const & rUrl);
187
188private:
189 Impl(OUString const & rConnectionDescriptor,
190 OUString const & rProtocolDescriptor,
191 OUString aObjectName):
192 m_aConnection(rConnectionDescriptor),
193 m_aProtocol(rProtocolDescriptor),
194 m_aObjectName(std::move(aObjectName))
195 {}
196};
197
198inline UnoUrl::Impl * UnoUrl::Impl::create(OUString const & rUrl)
199{
200 if (!rUrl.startsWithIgnoreAsciiCase("uno:"))
201 throw rtl::MalformedUriException("UNO URL does not start with \"uno:\"");
202 sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:");
203 sal_Int32 j = rUrl.indexOf(';', i);
204 if (j < 0)
205 throw rtl::MalformedUriException("UNO URL has too few semicolons");
206 OUString aConnection(rUrl.copy(i, j - i));
207 i = j + 1;
208 j = rUrl.indexOf(0x3B, i); // ';'
209 if (j < 0)
210 throw rtl::MalformedUriException("UNO URL has too few semicolons");
211 OUString aProtocol(rUrl.copy(i, j - i));
212 i = j + 1;
213 if (i == rUrl.getLength())
214 throw rtl::MalformedUriException("UNO URL contains empty ObjectName");
215 for (j = i; j < rUrl.getLength(); ++j)
216 {
217 sal_Unicode c = rUrl[j];
218 if (!rtl::isAsciiAlphanumeric(c) && c != 0x21 && c != 0x24 // '!', '$'
219 && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '('
220 && c != 0x29 && c != 0x2A && c != 0x2B // ')', '*', '+'
221 && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.'
222 && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '='
223 && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_'
224 && c != 0x7E) // '~'
225 throw rtl::MalformedUriException("UNO URL contains invalid ObjectName");
226 }
227 return new Impl(aConnection, aProtocol, rUrl.copy(i));
228}
229
230UnoUrl::UnoUrl(OUString const & rUrl): m_pImpl(Impl::create(rUrl))
231{}
232
233UnoUrl::UnoUrl(UnoUrl const & rOther): m_pImpl(rOther.m_pImpl->clone())
234{}
235
237{
238 delete m_pImpl;
239}
240
242{
243 if (this != &rOther)
244 {
245 std::unique_ptr<Impl> newImpl(rOther.m_pImpl->clone());
246 delete m_pImpl;
247 m_pImpl = newImpl.release();
248 }
249 return *this;
250}
251
253{
254 return m_pImpl->m_aConnection;
255}
256
258{
259 return m_pImpl->m_aProtocol;
260}
261
262OUString const & UnoUrl::getObjectName() const
263{
264 return m_pImpl->m_aObjectName;
265}
266
267/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
std::map< OUString, OUString > Parameters
Definition: unourl.cxx:42
Impl(OUString const &m_aDescriptor)
Definition: unourl.cxx:55
Impl * clone() const
Definition: unourl.cxx:52
UnoUrlDescriptor m_aConnection
Definition: unourl.cxx:178
static Impl * create(OUString const &rUrl)
Definition: unourl.cxx:198
Impl * clone() const
Definition: unourl.cxx:182
UnoUrlDescriptor m_aProtocol
Definition: unourl.cxx:179
Impl(OUString const &rConnectionDescriptor, OUString const &rProtocolDescriptor, OUString aObjectName)
Definition: unourl.cxx:189
OUString m_aObjectName
Definition: unourl.cxx:180
A descriptor as part of a UNO URL (connection descriptor or protocol descriptor).
Definition: unourl.hxx:46
rtl::OUString const & getDescriptor() const
Return the string representation of the descriptor.
Definition: unourl.cxx:152
rtl::OUString const & getName() const
Return the name component of the descriptor.
Definition: unourl.cxx:157
bool hasParameter(rtl::OUString const &rKey) const
Test whether the parameters contain a key.
Definition: unourl.cxx:162
rtl::OUString getParameter(rtl::OUString const &rKey) const
Return the parameter value for a key.
Definition: unourl.cxx:168
UnoUrlDescriptor & operator=(UnoUrlDescriptor const &rOther)
Definition: unourl.cxx:141
Parse UNO URLs into their components.
Definition: unourl.hxx:137
UnoUrlDescriptor const & getConnection() const
Return the connection descriptor component of the URL.
Definition: unourl.cxx:252
Impl * m_pImpl
Definition: unourl.hxx:180
rtl::OUString const & getObjectName() const
Return the object-name component of the URL.
Definition: unourl.cxx:262
UnoUrl & operator=(UnoUrl const &rOther)
Definition: unourl.cxx:241
UnoUrlDescriptor const & getProtocol() const
Return the protocol descriptor component of the URL.
Definition: unourl.cxx:257
T * clone(T *const other)
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
int i
State
sal_uInt16 sal_Unicode