merge the formfield patch from ooo-build
[ooovba.git] / stoc / source / uriproc / UriSchemeParser_vndDOTsunDOTstarDOTscript.cxx
blob3b1e2c52fed4277d8cf0f71d750736d886dd18e7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: UriSchemeParser_vndDOTsunDOTstarDOTscript.cxx,v $
10 * $Revision: 1.8 $
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"
57 #include <new>
59 namespace css = com::sun::star;
61 namespace {
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)
67 : -1;
70 int parseEscaped(rtl::OUString const & part, sal_Int32 * index) {
71 if (part.getLength() - *index < 3 || part[*index] != '%') {
72 return -1;
74 int n1 = getHexWeight(part[*index + 1]);
75 int n2 = getHexWeight(part[*index + 2]);
76 if (n1 < 0 || n2 < 0) {
77 return -1;
79 *index += 3;
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 == '=') {
90 break;
91 } else if (c == '%') {
92 sal_Int32 i = *index;
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) {
97 sal_Int32 encoded;
98 int shift;
99 sal_Int32 min;
100 if (n <= 0xDF) {
101 encoded = (n & 0x1F) << 6;
102 shift = 0;
103 min = 0x80;
104 } else if (n <= 0xEF) {
105 encoded = (n & 0x0F) << 12;
106 shift = 6;
107 min = 0x800;
108 } else if (n <= 0xF7) {
109 encoded = (n & 0x07) << 18;
110 shift = 12;
111 min = 0x10000;
112 } else if (n <= 0xFB) {
113 encoded = (n & 0x03) << 24;
114 shift = 18;
115 min = 0x200000;
116 } else {
117 encoded = 0;
118 shift = 24;
119 min = 0x4000000;
121 bool utf8 = true;
122 for (; shift >= 0; shift -= 6) {
123 n = parseEscaped(part, &i);
124 if (n < 0x80 || n > 0xBF) {
125 utf8 = false;
126 break;
128 encoded |= (n & 0x3F) << shift;
130 if (!utf8 || encoded < min
131 || (encoded >= 0xD800 && encoded <= 0xDFFF)
132 || encoded > 0x10FFFF)
134 break;
136 if (encoded <= 0xFFFF) {
137 buf.append(static_cast< sal_Unicode >(encoded));
138 } else {
139 buf.append(static_cast< sal_Unicode >(
140 (encoded >> 10) | 0xD800));
141 buf.append(static_cast< sal_Unicode >(
142 (encoded & 0x3FF) | 0xDC00));
144 } else {
145 break;
147 *index = i;
148 } else {
149 buf.append(c);
150 ++*index;
153 return buf.makeStringAndClear();
156 namespace
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(
172 fragment,
173 aCharClass,
174 rtl_UriEncodeIgnoreEscapes,
175 RTL_TEXTENCODING_UTF8
180 bool parseSchemeSpecificPart(rtl::OUString const & part) {
181 sal_Int32 len = part.getLength();
182 sal_Int32 i = 0;
183 if (parsePart(part, true, &i).getLength() == 0 || part[0] == '/') {
184 return false;
186 if (i == len) {
187 return true;
189 for (;;) {
190 ++i; // skip '?' or '&'
191 if (parsePart(part, false, &i).getLength() == 0 || i == len
192 || part[i] != '=')
194 return false;
196 ++i;
197 parsePart(part, false, &i);
198 if (i == len) {
199 return true;
201 if (part[i] != '&') {
202 return false;
207 class UrlReference:
208 public cppu::WeakImplHelper1< css::uri::XVndSunStarScriptUrlReference >
210 public:
211 UrlReference(rtl::OUString const & scheme, rtl::OUString const & path):
212 m_base(
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);
298 private:
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);
311 sal_Int32 i = 0;
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);
322 sal_Int32 i = 0;
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 );
356 if (!bExistent) {
357 i = m_base.m_path.getLength();
360 rtl::OUStringBuffer newPath;
361 newPath.append(m_base.m_path.copy(0, i));
362 if (!bExistent) {
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));
368 if (bExistent) {
369 /*oldValue = */
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) {
378 sal_Int32 i = 0;
379 parsePart(m_base.m_path, true, &i); // skip name
380 for (;;) {
381 if (i == m_base.m_path.getLength()) {
382 return -1;
384 ++i; // skip '?' or '&'
385 rtl::OUString k = parsePart(m_base.m_path, false, &i);
386 ++i; // skip '='
387 if (k == key) {
388 return i;
390 parsePart(m_base.m_path, false, &i); // skip value
394 class Parser: public cppu::WeakImplHelper2<
395 css::lang::XServiceInfo, css::uri::XUriSchemeParser >
397 public:
398 Parser() {}
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
410 parse(
411 rtl::OUString const & scheme, rtl::OUString const & schemeSpecificPart)
412 throw (css::uno::RuntimeException);
414 private:
415 Parser(Parser &); // not implemented
416 void operator =(Parser); // not implemented
418 virtual ~Parser() {}
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 >
443 Parser::parse(
444 rtl::OUString const & scheme, rtl::OUString const & schemeSpecificPart)
445 throw (css::uno::RuntimeException)
447 if (!parseSchemeSpecificPart(schemeSpecificPart)) {
448 return 0;
450 try {
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
468 try {
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");
485 return s;