tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / stoc / source / uriproc / UriSchemeParser_vndDOTsunDOTstarDOTscript.cxx
blob03fab8b59e04458c9551815fc8282a98d10e2657
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include "UriReference.hxx"
22 #include <com/sun/star/lang/IllegalArgumentException.hpp>
23 #include <com/sun/star/lang/XServiceInfo.hpp>
24 #include <com/sun/star/uno/Reference.hxx>
25 #include <com/sun/star/uno/Sequence.hxx>
26 #include <com/sun/star/uri/XUriSchemeParser.hpp>
27 #include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
28 #include <cppuhelper/implbase.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <cppuhelper/weak.hxx>
31 #include <rtl/character.hxx>
32 #include <rtl/uri.hxx>
33 #include <rtl/ustrbuf.hxx>
34 #include <rtl/ustring.hxx>
35 #include <sal/types.h>
36 #include <o3tl/safeint.hxx>
38 #include <string_view>
40 namespace com::sun::star::uno { class XComponentContext; }
41 namespace com::sun::star::uno { class XInterface; }
42 namespace com::sun::star::uri { class XUriReference; }
44 namespace {
46 int getHexWeight(sal_Unicode c) {
47 return c >= '0' && c <= '9' ? static_cast< int >(c - '0')
48 : c >= 'A' && c <= 'F' ? static_cast< int >(c - 'A' + 10)
49 : c >= 'a' && c <= 'f' ? static_cast< int >(c - 'a' + 10)
50 : -1;
53 int parseEscaped(std::u16string_view part, sal_Int32 * index) {
54 if (part.size() - *index < 3 || part[*index] != '%') {
55 return -1;
57 int n1 = getHexWeight(part[*index + 1]);
58 int n2 = getHexWeight(part[*index + 2]);
59 if (n1 < 0 || n2 < 0) {
60 return -1;
62 *index += 3;
63 return (n1 << 4) | n2;
66 OUString parsePart(
67 std::u16string_view part, bool namePart, sal_Int32 * index)
69 OUStringBuffer buf(64);
70 while (o3tl::make_unsigned(*index) < part.size()) {
71 sal_Unicode c = part[*index];
72 if (namePart ? c == '?' : c == '&' || c == '=') {
73 break;
74 } else if (c == '%') {
75 sal_Int32 i = *index;
76 int n = parseEscaped(part, &i);
77 if (n >= 0 && n <= 0x7F) {
78 buf.append(static_cast< sal_Unicode >(n));
79 } else if (n >= 0xC0 && n <= 0xFC) {
80 sal_Int32 encoded;
81 int shift;
82 sal_Int32 min;
83 if (n <= 0xDF) {
84 encoded = (n & 0x1F) << 6;
85 shift = 0;
86 min = 0x80;
87 } else if (n <= 0xEF) {
88 encoded = (n & 0x0F) << 12;
89 shift = 6;
90 min = 0x800;
91 } else if (n <= 0xF7) {
92 encoded = (n & 0x07) << 18;
93 shift = 12;
94 min = 0x10000;
95 } else if (n <= 0xFB) {
96 encoded = (n & 0x03) << 24;
97 shift = 18;
98 min = 0x200000;
99 } else {
100 encoded = 0;
101 shift = 24;
102 min = 0x4000000;
104 bool utf8 = true;
105 for (; shift >= 0; shift -= 6) {
106 n = parseEscaped(part, &i);
107 if (n < 0x80 || n > 0xBF) {
108 utf8 = false;
109 break;
111 encoded |= (n & 0x3F) << shift;
113 if (!utf8 || !rtl::isUnicodeScalarValue(encoded)
114 || encoded < min)
116 break;
118 buf.appendUtf32(encoded);
119 } else {
120 break;
122 *index = i;
123 } else {
124 buf.append(c);
125 ++*index;
128 return buf.makeStringAndClear();
131 OUString encodeNameOrParamFragment(OUString const & fragment) {
132 static constexpr auto nameOrParamFragment = rtl::createUriCharClass(
133 u8"!$'()*+,-.0123456789:;@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz~");
134 return rtl::Uri::encode(
135 fragment, nameOrParamFragment.data(), rtl_UriEncodeIgnoreEscapes,
136 RTL_TEXTENCODING_UTF8);
139 bool parseSchemeSpecificPart(std::u16string_view part) {
140 size_t len = part.size();
141 sal_Int32 i = 0;
142 if (parsePart(part, true, &i).isEmpty() || part[0] == '/') {
143 return false;
145 if (o3tl::make_unsigned(i) == len) {
146 return true;
148 for (;;) {
149 ++i; // skip '?' or '&'
150 if (parsePart(part, false, &i).isEmpty() || o3tl::make_unsigned(i) == len
151 || part[i] != '=')
153 return false;
155 ++i;
156 parsePart(part, false, &i);
157 if (o3tl::make_unsigned(i) == len) {
158 return true;
160 if (part[i] != '&') {
161 return false;
166 class UrlReference:
167 public cppu::WeakImplHelper<css::uri::XVndSunStarScriptUrlReference>
169 public:
170 UrlReference(OUString const & scheme, OUString const & path):
171 m_base(
172 scheme, false, OUString(), path, false, OUString())
175 UrlReference(const UrlReference&) = delete;
176 UrlReference& operator=(const UrlReference&) = delete;
178 virtual OUString SAL_CALL getUriReference() override
179 { return m_base.getUriReference(); }
181 virtual sal_Bool SAL_CALL isAbsolute() override
182 { return m_base.isAbsolute(); }
184 virtual OUString SAL_CALL getScheme() override
185 { return m_base.getScheme(); }
187 virtual OUString SAL_CALL getSchemeSpecificPart() override
188 { return m_base.getSchemeSpecificPart(); }
190 virtual sal_Bool SAL_CALL isHierarchical() override
191 { return m_base.isHierarchical(); }
193 virtual sal_Bool SAL_CALL hasAuthority() override
194 { return m_base.hasAuthority(); }
196 virtual OUString SAL_CALL getAuthority() override
197 { return m_base.getAuthority(); }
199 virtual OUString SAL_CALL getPath() override
200 { return m_base.getPath(); }
202 virtual sal_Bool SAL_CALL hasRelativePath() override
203 { return m_base.hasRelativePath(); }
205 virtual sal_Int32 SAL_CALL getPathSegmentCount() override
206 { return m_base.getPathSegmentCount(); }
208 virtual OUString SAL_CALL getPathSegment(sal_Int32 index) override
209 { return m_base.getPathSegment(index); }
211 virtual sal_Bool SAL_CALL hasQuery() override
212 { return m_base.hasQuery(); }
214 virtual OUString SAL_CALL getQuery() override
215 { return m_base.getQuery(); }
217 virtual sal_Bool SAL_CALL hasFragment() override
218 { return m_base.hasFragment(); }
220 virtual OUString SAL_CALL getFragment() override
221 { return m_base.getFragment(); }
223 virtual void SAL_CALL setFragment(OUString const & fragment) override
224 { m_base.setFragment(fragment); }
226 virtual void SAL_CALL clearFragment() override
227 { m_base.clearFragment(); }
229 virtual OUString SAL_CALL getName() override;
231 virtual void SAL_CALL setName(OUString const & name) override;
233 virtual sal_Bool SAL_CALL hasParameter(OUString const & key) override;
235 virtual OUString SAL_CALL getParameter(OUString const & key) override;
237 virtual void SAL_CALL setParameter(OUString const & key, OUString const & value) override;
239 private:
240 virtual ~UrlReference() override {}
242 sal_Int32 findParameter(std::u16string_view key) const;
244 stoc::uriproc::UriReference m_base;
247 OUString UrlReference::getName() {
248 std::lock_guard g(m_base.m_mutex);
249 sal_Int32 i = 0;
250 return parsePart(m_base.m_path, true, &i);
253 void SAL_CALL UrlReference::setName(OUString const & name)
255 if (name.isEmpty())
256 throw css::lang::IllegalArgumentException(
257 OUString(), *this, 1);
259 std::lock_guard g(m_base.m_mutex);
260 sal_Int32 i = 0;
261 parsePart(m_base.m_path, true, &i);
263 m_base.m_path = encodeNameOrParamFragment(name) + m_base.m_path.subView(i);
266 sal_Bool UrlReference::hasParameter(OUString const & key)
268 std::lock_guard g(m_base.m_mutex);
269 return findParameter(key) >= 0;
272 OUString UrlReference::getParameter(OUString const & key)
274 std::lock_guard g(m_base.m_mutex);
275 sal_Int32 i = findParameter(key);
276 return i >= 0 ? parsePart(m_base.m_path, false, &i) : OUString();
279 void UrlReference::setParameter(OUString const & key, OUString const & value)
281 if (key.isEmpty())
282 throw css::lang::IllegalArgumentException(
283 OUString(), *this, 1);
285 std::lock_guard g(m_base.m_mutex);
286 sal_Int32 i = findParameter(key);
287 bool bExistent = ( i>=0 );
288 if (!bExistent) {
289 i = m_base.m_path.getLength();
292 OUStringBuffer newPath(128);
293 newPath.append(m_base.m_path.subView(0, i));
294 if (!bExistent) {
295 newPath.append( m_base.m_path.indexOf('?') < 0 ? '?' : '&' );
296 newPath.append(encodeNameOrParamFragment(key) + "=");
298 newPath.append(encodeNameOrParamFragment(value));
299 if (bExistent) {
300 /*oldValue = */
301 parsePart(m_base.m_path, false, &i); // skip key
302 newPath.append(m_base.m_path.subView(i));
305 m_base.m_path = newPath.makeStringAndClear();
308 sal_Int32 UrlReference::findParameter(std::u16string_view key) const {
309 sal_Int32 i = 0;
310 parsePart(m_base.m_path, true, &i); // skip name
311 for (;;) {
312 if (i == m_base.m_path.getLength()) {
313 return -1;
315 ++i; // skip '?' or '&'
316 OUString k = parsePart(m_base.m_path, false, &i);
317 ++i; // skip '='
318 if (k == key) {
319 return i;
321 parsePart(m_base.m_path, false, &i); // skip value
325 class Parser:
326 public cppu::WeakImplHelper<
327 css::lang::XServiceInfo, css::uri::XUriSchemeParser>
329 public:
330 Parser() {}
332 Parser(const Parser&) = delete;
333 Parser& operator=(const Parser&) = delete;
335 virtual OUString SAL_CALL getImplementationName() override;
337 virtual sal_Bool SAL_CALL supportsService(OUString const & serviceName) override;
339 virtual css::uno::Sequence< OUString > SAL_CALL
340 getSupportedServiceNames() override;
342 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
343 parse(
344 OUString const & scheme, OUString const & schemeSpecificPart) override;
346 private:
347 virtual ~Parser() override {}
350 OUString Parser::getImplementationName()
352 return u"com.sun.star.comp.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript"_ustr;
355 sal_Bool Parser::supportsService(OUString const & serviceName)
357 return cppu::supportsService(this, serviceName);
360 css::uno::Sequence< OUString > Parser::getSupportedServiceNames()
362 return { u"com.sun.star.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript"_ustr };
365 css::uno::Reference< css::uri::XUriReference >
366 Parser::parse(
367 OUString const & scheme, OUString const & schemeSpecificPart)
369 if (!parseSchemeSpecificPart(schemeSpecificPart)) {
370 return nullptr;
372 return new UrlReference(scheme, schemeSpecificPart);
377 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
378 com_sun_star_comp_uri_UriSchemeParser_vndDOTsunDOTstarDOTscript_get_implementation(css::uno::XComponentContext*,
379 css::uno::Sequence<css::uno::Any> const &)
381 //TODO: single instance
382 return ::cppu::acquire(new Parser());
385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */