1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: UriSchemeParser_vndDOTsunDOTstarDOTscript.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
34 #include "stocservices.hxx"
36 #include "UriReference.hxx"
37 #include "supportsService.hxx"
39 #include "com/sun/star/lang/IllegalArgumentException.hpp"
40 #include "com/sun/star/lang/XServiceInfo.hpp"
41 #include "com/sun/star/uno/Reference.hxx"
42 #include "com/sun/star/uno/RuntimeException.hpp"
43 #include "com/sun/star/uno/Sequence.hxx"
44 #include "com/sun/star/uno/XInterface.hpp"
45 #include "com/sun/star/uri/XUriReference.hpp"
46 #include "com/sun/star/uri/XUriSchemeParser.hpp"
47 #include "com/sun/star/uri/XVndSunStarScriptUrlReference.hpp"
48 #include "cppuhelper/implbase1.hxx"
49 #include "cppuhelper/implbase2.hxx"
50 #include "cppuhelper/weak.hxx"
51 #include "osl/mutex.hxx"
52 #include "rtl/uri.hxx"
53 #include "rtl/ustrbuf.hxx"
54 #include "rtl/ustring.hxx"
55 #include "sal/types.h"
59 namespace css
= com::sun::star
;
63 int getHexWeight(sal_Unicode c
) {
64 return c
>= '0' && c
<= '9' ? static_cast< int >(c
- '0')
65 : c
>= 'A' && c
<= 'F' ? static_cast< int >(c
- 'A' + 10)
66 : c
>= 'a' && c
<= 'f' ? static_cast< int >(c
- 'a' + 10)
70 int parseEscaped(rtl::OUString
const & part
, sal_Int32
* index
) {
71 if (part
.getLength() - *index
< 3 || part
[*index
] != '%') {
74 int n1
= getHexWeight(part
[*index
+ 1]);
75 int n2
= getHexWeight(part
[*index
+ 2]);
76 if (n1
< 0 || n2
< 0) {
80 return (n1
<< 4) | n2
;
83 rtl::OUString
parsePart(
84 rtl::OUString
const & part
, bool namePart
, sal_Int32
* index
)
86 rtl::OUStringBuffer buf
;
87 while (*index
< part
.getLength()) {
88 sal_Unicode c
= part
[*index
];
89 if (namePart
? c
== '?' : c
== '&' || c
== '=') {
91 } else if (c
== '%') {
93 int n
= parseEscaped(part
, &i
);
94 if (n
>= 0 && n
<= 0x7F) {
95 buf
.append(static_cast< sal_Unicode
>(n
));
96 } else if (n
>= 0xC0 && n
<= 0xFC) {
101 encoded
= (n
& 0x1F) << 6;
104 } else if (n
<= 0xEF) {
105 encoded
= (n
& 0x0F) << 12;
108 } else if (n
<= 0xF7) {
109 encoded
= (n
& 0x07) << 18;
112 } else if (n
<= 0xFB) {
113 encoded
= (n
& 0x03) << 24;
122 for (; shift
>= 0; shift
-= 6) {
123 n
= parseEscaped(part
, &i
);
124 if (n
< 0x80 || n
> 0xBF) {
128 encoded
|= (n
& 0x3F) << shift
;
130 if (!utf8
|| encoded
< min
131 || (encoded
>= 0xD800 && encoded
<= 0xDFFF)
132 || encoded
> 0x10FFFF)
136 if (encoded
<= 0xFFFF) {
137 buf
.append(static_cast< sal_Unicode
>(encoded
));
139 buf
.append(static_cast< sal_Unicode
>(
140 (encoded
>> 10) | 0xD800));
141 buf
.append(static_cast< sal_Unicode
>(
142 (encoded
& 0x3FF) | 0xDC00));
153 return buf
.makeStringAndClear();
158 static rtl::OUString
encodeNameOrParamFragment( rtl::OUString
const & fragment
)
160 static sal_Bool
const aCharClass
[] =
161 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* NameOrParamFragment */
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
163 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* !"#$%&'()*+,-./*/
164 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /*0123456789:;<=>?*/
165 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
166 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, /*PQRSTUVWXYZ[\]^_*/
167 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
168 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
171 return rtl::Uri::encode(
174 rtl_UriEncodeIgnoreEscapes
,
175 RTL_TEXTENCODING_UTF8
180 bool parseSchemeSpecificPart(rtl::OUString
const & part
) {
181 sal_Int32 len
= part
.getLength();
183 if (parsePart(part
, true, &i
).getLength() == 0 || part
[0] == '/') {
190 ++i
; // skip '?' or '&'
191 if (parsePart(part
, false, &i
).getLength() == 0 || i
== len
197 parsePart(part
, false, &i
);
201 if (part
[i
] != '&') {
208 public cppu::WeakImplHelper1
< css::uri::XVndSunStarScriptUrlReference
>
211 UrlReference(rtl::OUString
const & scheme
, rtl::OUString
const & path
):
213 scheme
, false, false, rtl::OUString(), path
, false, rtl::OUString())
216 virtual rtl::OUString SAL_CALL
getUriReference()
217 throw (com::sun::star::uno::RuntimeException
)
218 { return m_base
.getUriReference(); }
220 virtual sal_Bool SAL_CALL
isAbsolute()
221 throw (com::sun::star::uno::RuntimeException
)
222 { return m_base
.isAbsolute(); }
224 virtual rtl::OUString SAL_CALL
getScheme()
225 throw (com::sun::star::uno::RuntimeException
)
226 { return m_base
.getScheme(); }
228 virtual rtl::OUString SAL_CALL
getSchemeSpecificPart()
229 throw (com::sun::star::uno::RuntimeException
)
230 { return m_base
.getSchemeSpecificPart(); }
232 virtual sal_Bool SAL_CALL
isHierarchical()
233 throw (com::sun::star::uno::RuntimeException
)
234 { return m_base
.isHierarchical(); }
236 virtual sal_Bool SAL_CALL
hasAuthority()
237 throw (com::sun::star::uno::RuntimeException
)
238 { return m_base
.hasAuthority(); }
240 virtual rtl::OUString SAL_CALL
getAuthority()
241 throw (com::sun::star::uno::RuntimeException
)
242 { return m_base
.getAuthority(); }
244 virtual rtl::OUString SAL_CALL
getPath()
245 throw (com::sun::star::uno::RuntimeException
)
246 { return m_base
.getPath(); }
248 virtual sal_Bool SAL_CALL
hasRelativePath()
249 throw (com::sun::star::uno::RuntimeException
)
250 { return m_base
.hasRelativePath(); }
252 virtual sal_Int32 SAL_CALL
getPathSegmentCount()
253 throw (com::sun::star::uno::RuntimeException
)
254 { return m_base
.getPathSegmentCount(); }
256 virtual rtl::OUString SAL_CALL
getPathSegment(sal_Int32 index
)
257 throw (com::sun::star::uno::RuntimeException
)
258 { return m_base
.getPathSegment(index
); }
260 virtual sal_Bool SAL_CALL
hasQuery()
261 throw (com::sun::star::uno::RuntimeException
)
262 { return m_base
.hasQuery(); }
264 virtual rtl::OUString SAL_CALL
getQuery()
265 throw (com::sun::star::uno::RuntimeException
)
266 { return m_base
.getQuery(); }
268 virtual sal_Bool SAL_CALL
hasFragment()
269 throw (com::sun::star::uno::RuntimeException
)
270 { return m_base
.hasFragment(); }
272 virtual rtl::OUString SAL_CALL
getFragment()
273 throw (com::sun::star::uno::RuntimeException
)
274 { return m_base
.getFragment(); }
276 virtual void SAL_CALL
setFragment(rtl::OUString
const & fragment
)
277 throw (com::sun::star::uno::RuntimeException
)
278 { m_base
.setFragment(fragment
); }
280 virtual void SAL_CALL
clearFragment()
281 throw (com::sun::star::uno::RuntimeException
)
282 { m_base
.clearFragment(); }
284 virtual rtl::OUString SAL_CALL
getName() throw (css::uno::RuntimeException
);
286 virtual void SAL_CALL
setName(rtl::OUString
const & name
)
287 throw (css::uno::RuntimeException
, css::lang::IllegalArgumentException
);
289 virtual sal_Bool SAL_CALL
hasParameter(rtl::OUString
const & key
)
290 throw (css::uno::RuntimeException
);
292 virtual rtl::OUString SAL_CALL
getParameter(rtl::OUString
const & key
)
293 throw (css::uno::RuntimeException
);
295 virtual void SAL_CALL
setParameter(rtl::OUString
const & key
, rtl::OUString
const & value
)
296 throw (css::uno::RuntimeException
, css::lang::IllegalArgumentException
);
299 UrlReference(UrlReference
&); // not implemented
300 void operator =(UrlReference
); // not implemented
302 virtual ~UrlReference() {}
304 sal_Int32
findParameter(rtl::OUString
const & key
);
306 stoc::uriproc::UriReference m_base
;
309 rtl::OUString
UrlReference::getName() throw (css::uno::RuntimeException
) {
310 osl::MutexGuard
g(m_base
.m_mutex
);
312 return parsePart(m_base
.m_path
, true, &i
);
315 void SAL_CALL
UrlReference::setName(rtl::OUString
const & name
) throw (css::uno::RuntimeException
, css::lang::IllegalArgumentException
)
317 if (name
.getLength() == 0)
318 throw css::lang::IllegalArgumentException(
319 ::rtl::OUString(), *this, 1);
321 osl::MutexGuard
g(m_base
.m_mutex
);
323 parsePart(m_base
.m_path
, true, &i
);
325 rtl::OUStringBuffer newPath
;
326 newPath
.append(encodeNameOrParamFragment(name
));
327 newPath
.append(m_base
.m_path
.copy(i
));
328 m_base
.m_path
= newPath
.makeStringAndClear();
331 sal_Bool
UrlReference::hasParameter(rtl::OUString
const & key
)
332 throw (css::uno::RuntimeException
)
334 osl::MutexGuard
g(m_base
.m_mutex
);
335 return findParameter(key
) >= 0;
338 rtl::OUString
UrlReference::getParameter(rtl::OUString
const & key
)
339 throw (css::uno::RuntimeException
)
341 osl::MutexGuard
g(m_base
.m_mutex
);
342 sal_Int32 i
= findParameter(key
);
343 return i
>= 0 ? parsePart(m_base
.m_path
, false, &i
) : rtl::OUString();
346 void UrlReference::setParameter(rtl::OUString
const & key
, rtl::OUString
const & value
)
347 throw (css::uno::RuntimeException
, css::lang::IllegalArgumentException
)
349 if (key
.getLength() == 0)
350 throw css::lang::IllegalArgumentException(
351 ::rtl::OUString(), *this, 1);
353 osl::MutexGuard
g(m_base
.m_mutex
);
354 sal_Int32 i
= findParameter(key
);
355 bool bExistent
= ( i
>=0 );
357 i
= m_base
.m_path
.getLength();
360 rtl::OUStringBuffer newPath
;
361 newPath
.append(m_base
.m_path
.copy(0, i
));
363 newPath
.append(sal_Unicode(m_base
.m_path
.indexOf('?') < 0 ? '?' : '&'));
364 newPath
.append(encodeNameOrParamFragment(key
));
365 newPath
.append(sal_Unicode('='));
367 newPath
.append(encodeNameOrParamFragment(value
));
370 parsePart(m_base
.m_path
, false, &i
); // skip key
371 newPath
.append(m_base
.m_path
.copy(i
));
374 m_base
.m_path
= newPath
.makeStringAndClear();
377 sal_Int32
UrlReference::findParameter(rtl::OUString
const & key
) {
379 parsePart(m_base
.m_path
, true, &i
); // skip name
381 if (i
== m_base
.m_path
.getLength()) {
384 ++i
; // skip '?' or '&'
385 rtl::OUString k
= parsePart(m_base
.m_path
, false, &i
);
390 parsePart(m_base
.m_path
, false, &i
); // skip value
394 class Parser
: public cppu::WeakImplHelper2
<
395 css::lang::XServiceInfo
, css::uri::XUriSchemeParser
>
400 virtual rtl::OUString SAL_CALL
getImplementationName()
401 throw (css::uno::RuntimeException
);
403 virtual sal_Bool SAL_CALL
supportsService(rtl::OUString
const & serviceName
)
404 throw (css::uno::RuntimeException
);
406 virtual css::uno::Sequence
< rtl::OUString
> SAL_CALL
407 getSupportedServiceNames() throw (css::uno::RuntimeException
);
409 virtual css::uno::Reference
< css::uri::XUriReference
> SAL_CALL
411 rtl::OUString
const & scheme
, rtl::OUString
const & schemeSpecificPart
)
412 throw (css::uno::RuntimeException
);
415 Parser(Parser
&); // not implemented
416 void operator =(Parser
); // not implemented
421 rtl::OUString
Parser::getImplementationName()
422 throw (css::uno::RuntimeException
)
424 return stoc_services::UriSchemeParser_vndDOTsunDOTstarDOTscript::
425 getImplementationName();
428 sal_Bool
Parser::supportsService(rtl::OUString
const & serviceName
)
429 throw (css::uno::RuntimeException
)
431 return stoc::uriproc::supportsService(
432 getSupportedServiceNames(), serviceName
);
435 css::uno::Sequence
< rtl::OUString
> Parser::getSupportedServiceNames()
436 throw (css::uno::RuntimeException
)
438 return stoc_services::UriSchemeParser_vndDOTsunDOTstarDOTscript::
439 getSupportedServiceNames();
442 css::uno::Reference
< css::uri::XUriReference
>
444 rtl::OUString
const & scheme
, rtl::OUString
const & schemeSpecificPart
)
445 throw (css::uno::RuntimeException
)
447 if (!parseSchemeSpecificPart(schemeSpecificPart
)) {
451 return new UrlReference(scheme
, schemeSpecificPart
);
452 } catch (std::bad_alloc
&) {
453 throw css::uno::RuntimeException(
454 rtl::OUString::createFromAscii("std::bad_alloc"), 0);
460 namespace stoc_services
{
461 namespace UriSchemeParser_vndDOTsunDOTstarDOTscript
{
463 css::uno::Reference
< css::uno::XInterface
> create(
464 css::uno::Reference
< css::uno::XComponentContext
> const &)
465 SAL_THROW((css::uno::Exception
))
467 //TODO: single instance
469 return static_cast< cppu::OWeakObject
* >(new Parser
);
470 } catch (std::bad_alloc
&) {
471 throw css::uno::RuntimeException(
472 rtl::OUString::createFromAscii("std::bad_alloc"), 0);
476 rtl::OUString
getImplementationName() {
477 return rtl::OUString::createFromAscii(
478 "com.sun.star.comp.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript");
481 css::uno::Sequence
< rtl::OUString
> getSupportedServiceNames() {
482 css::uno::Sequence
< rtl::OUString
> s(1);
483 s
[0] = rtl::OUString::createFromAscii(
484 "com.sun.star.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript");