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 
35 using cppu::UnoUrl;
37 
39 {
40 public:
41  typedef std::map< OUString, OUString > Parameters;
42 
43  OUString m_aDescriptor;
44  OUString m_aName;
45  Parameters m_aParameters;
46 
49  explicit inline Impl(OUString const & m_aDescriptor);
50 
51  Impl * clone() const { return new Impl(*this); }
52 };
53 
54 inline UnoUrlDescriptor::Impl::Impl(OUString const & rDescriptor)
55 {
56  m_aDescriptor = rDescriptor;
57  enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE };
58  State eState = STATE_NAME0;
59  sal_Int32 nStart = 0;
60  OUString aKey;
61  for (sal_Int32 i = 0;; ++i)
62  {
63  bool bEnd = i == rDescriptor.getLength();
64  sal_Unicode c = bEnd ? 0 : rDescriptor[i];
65  switch (eState)
66  {
67  case STATE_NAME0:
68  if (bEnd || !rtl::isAsciiAlphanumeric(c))
69  throw rtl::MalformedUriException(
70  "UNO URL contains bad descriptor name");
71  nStart = i;
72  eState = STATE_NAME;
73  break;
74 
75  case STATE_NAME:
76  if (bEnd || c == 0x2C) // ','
77  {
78  m_aName
79  = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
80  eState = STATE_KEY0;
81  }
82  else if (!rtl::isAsciiAlphanumeric(c))
83  throw rtl::MalformedUriException(
84  "UNO URL contains bad descriptor name");
85  break;
86 
87  case STATE_KEY0:
88  if (bEnd || !rtl::isAsciiAlphanumeric(c))
89  throw rtl::MalformedUriException(
90  "UNO URL contains bad parameter key");
91  nStart = i;
92  eState = STATE_KEY;
93  break;
94 
95  case STATE_KEY:
96  if (c == 0x3D) // '='
97  {
98  aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
99  nStart = i + 1;
100  eState = STATE_VALUE;
101  }
102  else if (bEnd || !rtl::isAsciiAlphanumeric(c))
103  throw rtl::MalformedUriException(
104  "UNO URL contains bad parameter key");
105  break;
106 
107  case STATE_VALUE:
108  if (bEnd || c == 0x2C) // ','
109  {
110  if (!m_aParameters.emplace(
111  aKey,
112  rtl::Uri::decode(rDescriptor.copy(nStart,
113  i - nStart),
114  rtl_UriDecodeWithCharset,
115  RTL_TEXTENCODING_UTF8)).second)
116  throw rtl::MalformedUriException(
117  "UNO URL contains duplicated parameter");
118  eState = STATE_KEY0;
119  }
120  break;
121  }
122  if (bEnd)
123  break;
124  }
125 }
126 
127 UnoUrlDescriptor::UnoUrlDescriptor(OUString const & rDescriptor):
128  m_pImpl(new Impl(rDescriptor))
129 {}
130 
131 UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther):
132  m_pImpl(rOther.m_pImpl->clone())
133 {}
134 
136 {
137  delete m_pImpl;
138 }
139 
141 {
142  if (this != &rOther)
143  {
144  std::unique_ptr<Impl> newImpl(rOther.m_pImpl->clone());
145  delete m_pImpl;
146  m_pImpl = newImpl.release();
147  }
148  return *this;
149 }
150 
151 OUString const & UnoUrlDescriptor::getDescriptor() const
152 {
153  return m_pImpl->m_aDescriptor;
154 }
155 
156 OUString const & UnoUrlDescriptor::getName() const
157 {
158  return m_pImpl->m_aName;
159 }
160 
161 bool UnoUrlDescriptor::hasParameter(OUString const & rKey) const
162 {
163  return m_pImpl->m_aParameters.find(rKey.toAsciiLowerCase())
164  != m_pImpl->m_aParameters.end();
165 }
166 
167 OUString UnoUrlDescriptor::getParameter(OUString const & rKey) const
168 {
169  Impl::Parameters::const_iterator
170  aIt(m_pImpl->m_aParameters.find(rKey.toAsciiLowerCase()));
171  return aIt == m_pImpl->m_aParameters.end() ? OUString() : aIt->second;
172 }
173 
175 {
176 public:
179  OUString m_aObjectName;
180 
181  Impl * clone() const { return new Impl(*this); }
182 
185  static inline Impl * create(OUString const & rUrl);
186 
187 private:
188  Impl(OUString const & rConnectionDescriptor,
189  OUString const & rProtocolDescriptor,
190  OUString const & rObjectName):
191  m_aConnection(rConnectionDescriptor),
192  m_aProtocol(rProtocolDescriptor),
193  m_aObjectName(rObjectName)
194  {}
195 };
196 
197 inline UnoUrl::Impl * UnoUrl::Impl::create(OUString const & rUrl)
198 {
199  if (!rUrl.startsWithIgnoreAsciiCase("uno:"))
200  throw rtl::MalformedUriException("UNO URL does not start with \"uno:\"");
201  sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:");
202  sal_Int32 j = rUrl.indexOf(';', i);
203  if (j < 0)
204  throw rtl::MalformedUriException("UNO URL has too few semicolons");
205  OUString aConnection(rUrl.copy(i, j - i));
206  i = j + 1;
207  j = rUrl.indexOf(0x3B, i); // ';'
208  if (j < 0)
209  throw rtl::MalformedUriException("UNO URL has too few semicolons");
210  OUString aProtocol(rUrl.copy(i, j - i));
211  i = j + 1;
212  if (i == rUrl.getLength())
213  throw rtl::MalformedUriException("UNO URL contains empty ObjectName");
214  for (j = i; j < rUrl.getLength(); ++j)
215  {
216  sal_Unicode c = rUrl[j];
217  if (!rtl::isAsciiAlphanumeric(c) && c != 0x21 && c != 0x24 // '!', '$'
218  && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '('
219  && c != 0x29 && c != 0x2A && c != 0x2B // ')', '*', '+'
220  && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.'
221  && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '='
222  && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_'
223  && c != 0x7E) // '~'
224  throw rtl::MalformedUriException("UNO URL contains invalid ObjectName");
225  }
226  return new Impl(aConnection, aProtocol, rUrl.copy(i));
227 }
228 
229 UnoUrl::UnoUrl(OUString const & rUrl): m_pImpl(Impl::create(rUrl))
230 {}
231 
232 UnoUrl::UnoUrl(UnoUrl const & rOther): m_pImpl(rOther.m_pImpl->clone())
233 {}
234 
236 {
237  delete m_pImpl;
238 }
239 
241 {
242  if (this != &rOther)
243  {
244  std::unique_ptr<Impl> newImpl(rOther.m_pImpl->clone());
245  delete m_pImpl;
246  m_pImpl = newImpl.release();
247  }
248  return *this;
249 }
250 
252 {
253  return m_pImpl->m_aConnection;
254 }
255 
257 {
258  return m_pImpl->m_aProtocol;
259 }
260 
261 OUString const & UnoUrl::getObjectName() const
262 {
263  return m_pImpl->m_aObjectName;
264 }
265 
266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::map< OUString, OUString > Parameters
Definition: unourl.cxx:41
OUString m_aObjectName
Definition: unourl.cxx:179
Parse UNO URLs into their components.
Definition: unourl.hxx:132
Impl(OUString const &m_aDescriptor)
Definition: unourl.cxx:54
bool hasParameter(rtl::OUString const &rKey) const
Test whether the parameters contain a key.
Definition: unourl.cxx:161
UnoUrlDescriptor & operator=(UnoUrlDescriptor const &rOther)
Definition: unourl.cxx:140
sal_uInt16 sal_Unicode
rtl::OUString const & getObjectName() const
Return the object-name component of the URL.
Definition: unourl.cxx:261
rtl::OUString const & getName() const
Return the name component of the descriptor.
Definition: unourl.cxx:156
Impl * m_pImpl
Definition: unourl.hxx:176
Reference< deployment::XPackageRegistry > create(Reference< deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, Reference< XComponentContext > const &xComponentContext)
UnoUrlDescriptor const & getConnection() const
Return the connection descriptor component of the URL.
Definition: unourl.cxx:251
int i
A descriptor as part of a UNO URL (connection descriptor or protocol descriptor). ...
Definition: unourl.hxx:41
static Impl * create(OUString const &rUrl)
Definition: unourl.cxx:197
UnoUrlDescriptor m_aConnection
Definition: unourl.cxx:177
UnoUrlDescriptor m_aProtocol
Definition: unourl.cxx:178
Impl * clone() const
Definition: unourl.cxx:181
State
rtl::OUString const & getDescriptor() const
Return the string representation of the descriptor.
Definition: unourl.cxx:151
T * clone(T *const other)
Impl(OUString const &rConnectionDescriptor, OUString const &rProtocolDescriptor, OUString const &rObjectName)
Definition: unourl.cxx:188
UnoUrlDescriptor const & getProtocol() const
Return the protocol descriptor component of the URL.
Definition: unourl.cxx:256
#define STATE_VALUE
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
Impl * clone() const
Definition: unourl.cxx:51
UnoUrl & operator=(UnoUrl const &rOther)
Definition: unourl.cxx:240
rtl::OUString getParameter(rtl::OUString const &rKey) const
Return the parameter value for a key.
Definition: unourl.cxx:167