1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <cppuhelper/unourl.hxx>
23 #include <osl/diagnose.h>
24 #include <rtl/malformeduriexception.hxx>
25 #include <rtl/string.h>
26 #include <rtl/textenc.h>
28 #include <rtl/uri.hxx>
29 #include <rtl/ustring.h>
30 #include <rtl/ustring.hxx>
31 #include <sal/types.h>
37 using cppu::UnoUrlDescriptor
;
41 inline bool isAlphanum(sal_Unicode c
)
43 return (c
>= 0x30 && c
<= 0x39) // '0'--'9'
44 || (c
>= 0x41 && c
<= 0x5A) // 'A'--'Z'
45 || (c
>= 0x61 && c
<= 0x7A); // 'a'--'z'
50 class UnoUrlDescriptor::Impl
53 typedef std::map
< rtl::OUString
, rtl::OUString
> Parameters
;
55 rtl::OUString m_aDescriptor
;
56 rtl::OUString m_aName
;
57 Parameters m_aParameters
;
59 /** @exception rtl::MalformedUriException
61 explicit inline Impl(rtl::OUString
const & m_aDescriptor
);
63 inline Impl
* clone() const { return new Impl(*this); }
66 inline UnoUrlDescriptor::Impl::Impl(rtl::OUString
const & rDescriptor
)
68 m_aDescriptor
= rDescriptor
;
69 enum State
{ STATE_NAME0
, STATE_NAME
, STATE_KEY0
, STATE_KEY
, STATE_VALUE
};
70 State eState
= STATE_NAME0
;
73 for (sal_Int32 i
= 0;; ++i
)
75 bool bEnd
= i
== rDescriptor
.getLength();
76 sal_Unicode c
= bEnd
? 0 : rDescriptor
[i
];
80 if (bEnd
|| !isAlphanum(c
))
81 throw rtl::MalformedUriException(
82 rtl::OUString("UNO URL contains bad descriptor name"));
88 if (bEnd
|| c
== 0x2C) // ','
91 = rDescriptor
.copy(nStart
, i
- nStart
).toAsciiLowerCase();
94 else if (!isAlphanum(c
))
95 throw rtl::MalformedUriException(
96 rtl::OUString("UNO URL contains bad descriptor name"));
100 if (bEnd
|| !isAlphanum(c
))
101 throw rtl::MalformedUriException(
102 rtl::OUString("UNO URL contains bad parameter key"));
108 if (c
== 0x3D) // '='
110 aKey
= rDescriptor
.copy(nStart
, i
- nStart
).toAsciiLowerCase();
112 eState
= STATE_VALUE
;
114 else if (bEnd
|| !isAlphanum(c
))
115 throw rtl::MalformedUriException(
116 rtl::OUString("UNO URL contains bad parameter key"));
120 if (bEnd
|| c
== 0x2C) // ','
122 if (!m_aParameters
.insert(
123 Parameters::value_type(
125 rtl::Uri::decode(rDescriptor
.copy(nStart
,
127 rtl_UriDecodeWithCharset
,
128 RTL_TEXTENCODING_UTF8
))).second
)
129 throw rtl::MalformedUriException(
130 rtl::OUString("UNO URL contains duplicated parameter"));
140 UnoUrlDescriptor::UnoUrlDescriptor(rtl::OUString
const & rDescriptor
):
141 m_pImpl(new Impl(rDescriptor
))
144 UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor
const & rOther
):
145 m_pImpl(rOther
.m_pImpl
->clone())
148 UnoUrlDescriptor::~UnoUrlDescriptor()
153 UnoUrlDescriptor
& UnoUrlDescriptor::operator =(UnoUrlDescriptor
const & rOther
)
155 std::unique_ptr
<Impl
> newImpl(rOther
.m_pImpl
->clone());
157 m_pImpl
= newImpl
.release();
161 rtl::OUString
const & UnoUrlDescriptor::getDescriptor() const
163 return m_pImpl
->m_aDescriptor
;
166 rtl::OUString
const & UnoUrlDescriptor::getName() const
168 return m_pImpl
->m_aName
;
171 bool UnoUrlDescriptor::hasParameter(rtl::OUString
const & rKey
) const
173 return m_pImpl
->m_aParameters
.find(rKey
.toAsciiLowerCase())
174 != m_pImpl
->m_aParameters
.end();
177 rtl::OUString
UnoUrlDescriptor::getParameter(rtl::OUString
const & rKey
) const
179 Impl::Parameters::const_iterator
180 aIt(m_pImpl
->m_aParameters
.find(rKey
.toAsciiLowerCase()));
181 return aIt
== m_pImpl
->m_aParameters
.end() ? rtl::OUString() : aIt
->second
;
187 UnoUrlDescriptor m_aConnection
;
188 UnoUrlDescriptor m_aProtocol
;
189 rtl::OUString m_aObjectName
;
191 inline Impl
* clone() const { return new Impl(*this); }
193 /** @exception rtl::MalformedUriException
195 static inline Impl
* create(rtl::OUString
const & rUrl
);
198 Impl(rtl::OUString
const & rConnectionDescriptor
,
199 rtl::OUString
const & rProtocolDescriptor
,
200 rtl::OUString
const & rObjectName
):
201 m_aConnection(rConnectionDescriptor
),
202 m_aProtocol(rProtocolDescriptor
),
203 m_aObjectName(rObjectName
)
207 inline UnoUrl::Impl
* UnoUrl::Impl::create(rtl::OUString
const & rUrl
)
209 if (!rUrl
.startsWithIgnoreAsciiCase("uno:"))
210 throw rtl::MalformedUriException(
211 rtl::OUString("UNO URL does not start with \"uno:\""));
212 sal_Int32 i
= RTL_CONSTASCII_LENGTH("uno:");
213 sal_Int32 j
= rUrl
.indexOf(';', i
);
215 throw rtl::MalformedUriException(
216 rtl::OUString("UNO URL has too few semicolons"));
217 rtl::OUString
aConnection(rUrl
.copy(i
, j
- i
));
219 j
= rUrl
.indexOf(0x3B, i
); // ';'
221 throw rtl::MalformedUriException(
222 rtl::OUString("UNO URL has too few semicolons"));
223 rtl::OUString
aProtocol(rUrl
.copy(i
, j
- i
));
225 if (i
== rUrl
.getLength())
226 throw rtl::MalformedUriException(
227 rtl::OUString("UNO URL contains empty ObjectName"));
228 for (j
= i
; j
< rUrl
.getLength(); ++j
)
230 sal_Unicode c
= rUrl
[j
];
231 if (!isAlphanum(c
) && c
!= 0x21 && c
!= 0x24 // '!', '$'
232 && c
!= 0x26 && c
!= 0x27 && c
!= 0x28 // '&', ''', '('
233 && c
!= 0x29 && c
!= 0x2A && c
!= 0x2B // ')', '*', '+'
234 && c
!= 0x2C && c
!= 0x2D && c
!= 0x2E // ',', '-', '.'
235 && c
!= 0x2F && c
!= 0x3A && c
!= 0x3D // '/', ':', '='
236 && c
!= 0x3F && c
!= 0x40 && c
!= 0x5F // '?', '@', '_'
238 throw rtl::MalformedUriException(
239 rtl::OUString("UNO URL contains invalid ObjectName"));
241 return new Impl(aConnection
, aProtocol
, rUrl
.copy(i
));
244 UnoUrl::UnoUrl(rtl::OUString
const & rUrl
): m_pImpl(Impl::create(rUrl
))
247 UnoUrl::UnoUrl(UnoUrl
const & rOther
): m_pImpl(rOther
.m_pImpl
->clone())
255 UnoUrl
& UnoUrl::operator =(UnoUrl
const & rOther
)
257 std::unique_ptr
<Impl
> newImpl(rOther
.m_pImpl
->clone());
259 m_pImpl
= newImpl
.release();
263 UnoUrlDescriptor
const & UnoUrl::getConnection() const
265 return m_pImpl
->m_aConnection
;
268 UnoUrlDescriptor
const & UnoUrl::getProtocol() const
270 return m_pImpl
->m_aProtocol
;
273 rtl::OUString
const & UnoUrl::getObjectName() const
275 return m_pImpl
->m_aObjectName
;
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */