Avoid potential negative array index access to cached text.
[LibreOffice.git] / configmgr / source / configurationregistry.cxx
blob4900b9f97d5277e9375dcc52218f4def47774327
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 <sal/config.h>
22 #include <cassert>
24 #include <com/sun/star/beans/NamedValue.hpp>
25 #include <com/sun/star/container/NoSuchElementException.hpp>
26 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
27 #include <com/sun/star/container/XNamed.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
31 #include <com/sun/star/registry/InvalidRegistryException.hpp>
32 #include <com/sun/star/registry/InvalidValueException.hpp>
33 #include <com/sun/star/registry/RegistryKeyType.hpp>
34 #include <com/sun/star/registry/RegistryValueType.hpp>
35 #include <com/sun/star/registry/XRegistryKey.hpp>
36 #include <com/sun/star/registry/XSimpleRegistry.hpp>
37 #include <com/sun/star/uno/Any.hxx>
38 #include <com/sun/star/uno/DeploymentException.hpp>
39 #include <com/sun/star/uno/Exception.hpp>
40 #include <com/sun/star/uno/Reference.hxx>
41 #include <com/sun/star/uno/RuntimeException.hpp>
42 #include <com/sun/star/uno/Sequence.hxx>
43 #include <com/sun/star/uno/Type.hxx>
44 #include <com/sun/star/uno/TypeClass.hpp>
45 #include <com/sun/star/uno/XComponentContext.hpp>
46 #include <com/sun/star/uno/XInterface.hpp>
47 #include <com/sun/star/util/XFlushable.hpp>
48 #include <cppu/unotype.hxx>
49 #include <cppuhelper/exc_hlp.hxx>
50 #include <cppuhelper/implbase.hxx>
51 #include <cppuhelper/supportsservice.hxx>
52 #include <cppuhelper/weak.hxx>
53 #include <mutex>
54 #include <rtl/ustring.hxx>
55 #include <utility>
56 #include <sal/types.h>
58 namespace com::sun::star::util {
59 class XFlushListener;
62 namespace configmgr::configuration_registry {
64 namespace {
66 class Service:
67 public cppu::WeakImplHelper<
68 css::lang::XServiceInfo, css::registry::XSimpleRegistry,
69 css::util::XFlushable >
71 public:
72 explicit Service(css::uno::Reference< css::uno::XComponentContext > const & context);
74 private:
75 Service(const Service&) = delete;
76 Service& operator=(const Service&) = delete;
78 virtual ~Service() override {}
80 virtual OUString SAL_CALL getImplementationName() override
81 { return "com.sun.star.comp.configuration.ConfigurationRegistry"; }
83 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
84 { return cppu::supportsService(this, ServiceName); }
86 virtual css::uno::Sequence< OUString > SAL_CALL
87 getSupportedServiceNames() override
88 { return { "com.sun.star.configuration.ConfigurationRegistry" }; }
90 virtual OUString SAL_CALL getURL() override;
92 virtual void SAL_CALL open(
93 OUString const & rURL, sal_Bool bReadOnly, sal_Bool) override;
95 virtual sal_Bool SAL_CALL isValid() override;
97 virtual void SAL_CALL close() override;
99 virtual void SAL_CALL destroy() override;
101 virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL
102 getRootKey() override;
104 virtual sal_Bool SAL_CALL isReadOnly() override;
106 virtual void SAL_CALL mergeKey(OUString const &, OUString const &) override;
108 virtual void SAL_CALL flush() override;
110 virtual void SAL_CALL addFlushListener(
111 css::uno::Reference< css::util::XFlushListener > const &) override;
113 virtual void SAL_CALL removeFlushListener(
114 css::uno::Reference< css::util::XFlushListener > const &) override;
116 void checkValid();
118 void checkValid_RuntimeException();
120 void doClose();
122 css::uno::Reference< css::lang::XMultiServiceFactory > provider_;
123 std::mutex mutex_;
124 css::uno::Reference< css::uno::XInterface > access_;
125 OUString url_;
126 bool readOnly_;
128 friend class RegistryKey;
131 class RegistryKey:
132 public cppu::WeakImplHelper< css::registry::XRegistryKey >
134 public:
135 RegistryKey(Service & service, css::uno::Any value):
136 service_(service), value_(std::move(value)) {}
138 private:
139 RegistryKey(const RegistryKey&) = delete;
140 RegistryKey& operator=(const RegistryKey&) = delete;
142 virtual ~RegistryKey() override {}
144 virtual OUString SAL_CALL getKeyName() override;
146 virtual sal_Bool SAL_CALL isReadOnly() override;
148 virtual sal_Bool SAL_CALL isValid() override;
150 virtual css::registry::RegistryKeyType SAL_CALL getKeyType(
151 OUString const &) override;
153 virtual css::registry::RegistryValueType SAL_CALL getValueType() override;
155 virtual sal_Int32 SAL_CALL getLongValue() override;
157 virtual void SAL_CALL setLongValue(sal_Int32) override;
159 virtual css::uno::Sequence< sal_Int32 > SAL_CALL getLongListValue() override;
161 virtual void SAL_CALL setLongListValue(
162 css::uno::Sequence< sal_Int32 > const &) override;
164 virtual OUString SAL_CALL getAsciiValue() override;
166 virtual void SAL_CALL setAsciiValue(OUString const &) override;
168 virtual css::uno::Sequence< OUString > SAL_CALL getAsciiListValue() override;
170 virtual void SAL_CALL setAsciiListValue(
171 css::uno::Sequence< OUString > const &) override;
173 virtual OUString SAL_CALL getStringValue() override;
175 virtual void SAL_CALL setStringValue(OUString const &) override;
177 virtual css::uno::Sequence< OUString > SAL_CALL getStringListValue() override;
179 virtual void SAL_CALL setStringListValue(
180 css::uno::Sequence< OUString > const &) override;
182 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBinaryValue() override;
184 virtual void SAL_CALL setBinaryValue(css::uno::Sequence< sal_Int8 > const &) override;
186 virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL openKey(
187 OUString const & aKeyName) override;
189 virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL
190 createKey(OUString const &) override;
192 virtual void SAL_CALL closeKey() override;
194 virtual void SAL_CALL deleteKey(OUString const &) override;
196 virtual
197 css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
198 SAL_CALL openKeys() override;
200 virtual css::uno::Sequence< OUString > SAL_CALL getKeyNames() override;
202 virtual sal_Bool SAL_CALL createLink(
203 OUString const &, OUString const &) override;
205 virtual void SAL_CALL deleteLink(OUString const &) override;
207 virtual OUString SAL_CALL getLinkTarget(OUString const &) override;
209 virtual OUString SAL_CALL getResolvedName(
210 OUString const & aKeyName) override;
212 Service & service_;
213 css::uno::Any value_;
216 Service::Service(
217 css::uno::Reference< css::uno::XComponentContext > const & context)
218 : readOnly_(false)
220 assert(context.is());
221 try {
222 provider_.set(
223 context->getServiceManager()->createInstanceWithContext(
224 "com.sun.star.configuration.DefaultProvider", context),
225 css::uno::UNO_QUERY_THROW);
226 } catch (css::uno::RuntimeException &) {
227 throw;
228 } catch (css::uno::Exception & e) {
229 throw css::uno::DeploymentException(
230 ("component context fails to supply service"
231 " com.sun.star.configuration.DefaultProvider of type"
232 " com.sun.star.lang.XMultiServiceFactory: " + e.Message),
233 context);
237 OUString Service::getURL() {
238 std::unique_lock g(mutex_);
239 checkValid_RuntimeException();
240 return url_;
243 void Service::open(OUString const & rURL, sal_Bool bReadOnly, sal_Bool)
245 //TODO: bCreate
246 std::unique_lock g(mutex_);
247 if (access_.is()) {
248 doClose();
250 css::uno::Sequence< css::uno::Any > args{ css::uno::Any(
251 css::beans::NamedValue("nodepath", css::uno::Any(rURL))) };
252 try {
253 access_ = provider_->createInstanceWithArguments(
254 (bReadOnly
255 ? OUString("com.sun.star.configuration.ConfigurationAccess")
256 : OUString(
257 "com.sun.star.configuration.ConfigurationUpdateAccess")),
258 args);
259 } catch (css::uno::RuntimeException &) {
260 throw;
261 } catch (css::uno::Exception & e) {
262 css::uno::Any anyEx = cppu::getCaughtException();
263 throw css::lang::WrappedTargetRuntimeException(
264 "com.sun.star.configuration.ConfigurationRegistry: open failed: " +
265 e.Message,
266 getXWeak(), anyEx );
268 url_ = rURL;
269 readOnly_ = bReadOnly;
272 sal_Bool Service::isValid() {
273 std::unique_lock g(mutex_);
274 return access_.is();
277 void Service::close()
279 std::unique_lock g(mutex_);
280 checkValid();
281 doClose();
284 void Service::destroy()
286 throw css::uno::RuntimeException(
287 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
288 getXWeak());
291 css::uno::Reference< css::registry::XRegistryKey > Service::getRootKey()
293 std::unique_lock g(mutex_);
294 checkValid();
295 return new RegistryKey(*this, css::uno::Any(access_));
298 sal_Bool Service::isReadOnly() {
299 std::unique_lock g(mutex_);
300 checkValid_RuntimeException();
301 return readOnly_;
304 void Service::mergeKey(OUString const &, OUString const &)
306 throw css::uno::RuntimeException(
307 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
308 getXWeak());
311 void Service::flush()
313 throw css::uno::RuntimeException(
314 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
315 getXWeak());
318 void Service::addFlushListener(
319 css::uno::Reference< css::util::XFlushListener > const &)
321 throw css::uno::RuntimeException(
322 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
323 getXWeak());
326 void Service::removeFlushListener(
327 css::uno::Reference< css::util::XFlushListener > const &)
329 throw css::uno::RuntimeException(
330 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
331 getXWeak());
334 void Service::checkValid() {
335 if (!access_.is()) {
336 throw css::registry::InvalidRegistryException(
337 "com.sun.star.configuration.ConfigurationRegistry: not valid",
338 getXWeak());
342 void Service::checkValid_RuntimeException() {
343 if (!access_.is()) {
344 throw css::uno::RuntimeException(
345 "com.sun.star.configuration.ConfigurationRegistry: not valid",
346 getXWeak());
350 void Service::doClose() {
351 access_.clear();
354 OUString RegistryKey::getKeyName() {
355 std::unique_lock g(service_.mutex_);
356 service_.checkValid_RuntimeException();
357 css::uno::Reference< css::container::XNamed > named;
358 if (value_ >>= named) {
359 return named->getName();
361 throw css::uno::RuntimeException(
362 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
363 getXWeak());
366 sal_Bool RegistryKey::isReadOnly()
368 std::unique_lock g(service_.mutex_);
369 service_.checkValid_RuntimeException();
370 return service_.readOnly_; //TODO: read-only sub-nodes in update access?
373 sal_Bool RegistryKey::isValid() {
374 return service_.isValid();
377 css::registry::RegistryKeyType RegistryKey::getKeyType(OUString const &)
379 std::unique_lock g(service_.mutex_);
380 service_.checkValid();
381 return css::registry::RegistryKeyType_KEY;
384 css::registry::RegistryValueType RegistryKey::getValueType()
386 std::unique_lock g(service_.mutex_);
387 service_.checkValid();
388 css::uno::Type t(value_.getValueType());
389 switch (t.getTypeClass()) {
390 case css::uno::TypeClass_LONG:
391 return css::registry::RegistryValueType_LONG;
392 case css::uno::TypeClass_STRING:
393 return css::registry::RegistryValueType_STRING;
394 case css::uno::TypeClass_SEQUENCE:
395 if (t == cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()) {
396 return css::registry::RegistryValueType_BINARY;
397 } else if (t == cppu::UnoType< css::uno::Sequence< sal_Int32 > >::get())
399 return css::registry::RegistryValueType_LONGLIST;
400 } else if (t ==
401 cppu::UnoType< css::uno::Sequence< OUString > >::get())
403 return css::registry::RegistryValueType_STRINGLIST;
405 [[fallthrough]];
406 default:
407 return css::registry::RegistryValueType_NOT_DEFINED;
411 sal_Int32 RegistryKey::getLongValue()
413 std::unique_lock g(service_.mutex_);
414 service_.checkValid();
415 sal_Int32 v = 0;
416 if (value_ >>= v) {
417 return v;
419 throw css::registry::InvalidValueException(
420 "com.sun.star.configuration.ConfigurationRegistry",
421 getXWeak());
424 void RegistryKey::setLongValue(sal_Int32)
426 throw css::uno::RuntimeException(
427 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
428 getXWeak());
431 css::uno::Sequence< sal_Int32 > RegistryKey::getLongListValue()
433 std::unique_lock g(service_.mutex_);
434 service_.checkValid();
435 css::uno::Sequence< sal_Int32 > v;
436 if (value_ >>= v) {
437 return v;
439 throw css::registry::InvalidValueException(
440 "com.sun.star.configuration.ConfigurationRegistry",
441 getXWeak());
444 void RegistryKey::setLongListValue(css::uno::Sequence< sal_Int32 > const &)
446 throw css::uno::RuntimeException(
447 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
448 getXWeak());
451 OUString RegistryKey::getAsciiValue()
453 std::unique_lock g(service_.mutex_);
454 service_.checkValid();
455 OUString v;
456 if (value_ >>= v) {
457 return v;
459 throw css::registry::InvalidValueException(
460 "com.sun.star.configuration.ConfigurationRegistry",
461 getXWeak());
464 void RegistryKey::setAsciiValue(OUString const &)
466 throw css::uno::RuntimeException(
467 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
468 getXWeak());
471 css::uno::Sequence< OUString > RegistryKey::getAsciiListValue()
473 std::unique_lock g(service_.mutex_);
474 service_.checkValid();
475 css::uno::Sequence< OUString > v;
476 if (value_ >>= v) {
477 return v;
479 throw css::registry::InvalidValueException(
480 "com.sun.star.configuration.ConfigurationRegistry",
481 getXWeak());
484 void RegistryKey::setAsciiListValue(css::uno::Sequence< OUString > const &)
486 throw css::uno::RuntimeException(
487 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
488 getXWeak());
491 OUString RegistryKey::getStringValue()
493 std::unique_lock g(service_.mutex_);
494 service_.checkValid();
495 OUString v;
496 if (value_ >>= v) {
497 return v;
499 throw css::registry::InvalidValueException(
500 "com.sun.star.configuration.ConfigurationRegistry",
501 getXWeak());
504 void RegistryKey::setStringValue(OUString const &)
506 throw css::uno::RuntimeException(
507 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
508 getXWeak());
511 css::uno::Sequence< OUString > RegistryKey::getStringListValue()
513 std::unique_lock g(service_.mutex_);
514 service_.checkValid();
515 css::uno::Sequence< OUString > v;
516 if (value_ >>= v) {
517 return v;
519 throw css::registry::InvalidValueException(
520 "com.sun.star.configuration.ConfigurationRegistry",
521 getXWeak());
524 void RegistryKey::setStringListValue(
525 css::uno::Sequence< OUString > const &)
527 throw css::uno::RuntimeException(
528 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
529 getXWeak());
532 css::uno::Sequence< sal_Int8 > RegistryKey::getBinaryValue()
534 std::unique_lock g(service_.mutex_);
535 service_.checkValid();
536 css::uno::Sequence< sal_Int8 > v;
537 if (value_ >>= v) {
538 return v;
540 throw css::registry::InvalidValueException(
541 "com.sun.star.configuration.ConfigurationRegistry",
542 getXWeak());
545 void RegistryKey::setBinaryValue(css::uno::Sequence< sal_Int8 > const &)
547 throw css::uno::RuntimeException(
548 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
549 getXWeak());
552 css::uno::Reference< css::registry::XRegistryKey > RegistryKey::openKey(
553 OUString const & aKeyName)
555 std::unique_lock g(service_.mutex_);
556 service_.checkValid_RuntimeException();
557 css::uno::Reference< css::container::XHierarchicalNameAccess > access;
558 if (value_ >>= access) {
559 try {
560 return new RegistryKey(
561 service_, access->getByHierarchicalName(aKeyName));
562 } catch (css::container::NoSuchElementException &) {}
564 return css::uno::Reference< css::registry::XRegistryKey >();
567 css::uno::Reference< css::registry::XRegistryKey > RegistryKey::createKey(
568 OUString const &)
570 throw css::uno::RuntimeException(
571 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
572 getXWeak());
575 void RegistryKey::closeKey()
577 std::unique_lock g(service_.mutex_);
578 service_.checkValid_RuntimeException();
581 void RegistryKey::deleteKey(OUString const &)
583 throw css::uno::RuntimeException(
584 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
585 getXWeak());
588 css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
589 RegistryKey::openKeys()
591 throw css::uno::RuntimeException(
592 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
593 getXWeak());
596 css::uno::Sequence< OUString > RegistryKey::getKeyNames()
598 throw css::uno::RuntimeException(
599 "com.sun.star.configuration.ConfigurationRegistry: not implemented",
600 getXWeak());
603 sal_Bool RegistryKey::createLink(OUString const &, OUString const &)
605 std::unique_lock g(service_.mutex_);
606 service_.checkValid_RuntimeException();
607 return false;
610 void RegistryKey::deleteLink(OUString const &)
612 std::unique_lock g(service_.mutex_);
613 service_.checkValid_RuntimeException();
616 OUString RegistryKey::getLinkTarget(OUString const &)
618 std::unique_lock g(service_.mutex_);
619 service_.checkValid_RuntimeException();
620 return OUString();
623 OUString RegistryKey::getResolvedName(OUString const & aKeyName)
625 std::unique_lock g(service_.mutex_);
626 service_.checkValid_RuntimeException();
627 return aKeyName;
632 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
633 com_sun_star_comp_configuration_ConfigurationRegistry_get_implementation(
634 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
636 return cppu::acquire(new Service(context));
641 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */