cid#1607171 Data race condition
[LibreOffice.git] / ucb / source / ucp / image / ucpimage.cxx
blob530db7c249243f1f9ae98f5e269c91351da3c204
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/.
8 */
10 #include <sal/config.h>
12 #include <cassert>
14 #include <com/sun/star/lang/XServiceInfo.hpp>
15 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
16 #include <com/sun/star/ucb/XContentProvider.hpp>
17 #include <com/sun/star/uno/XComponentContext.hpp>
18 #include <com/sun/star/uri/UriReferenceFactory.hpp>
19 #include <comphelper/compbase.hxx>
20 #include <cppuhelper/supportsservice.hxx>
21 #include <rtl/uri.hxx>
22 #include <rtl/ustrbuf.hxx>
23 #include <utility>
24 #include <vcl/ImageTree.hxx>
25 #include <vcl/svapp.hxx>
26 #include <ucbhelper/content.hxx>
28 // A LO-private ("implementation detail") UCP used to access images from help
29 // content, with theme fallback and localization support as provided by VCL's
30 // ImageTree.
32 // The URL scheme is
34 // "vnd.libreoffice.image://"<theme><path>["?lang="<language-tag>]
36 namespace {
38 class Provider final:
39 public comphelper::WeakComponentImplHelper<
40 css::lang::XServiceInfo, css::ucb::XContentProvider>
42 public:
43 explicit Provider(
44 css::uno::Reference<css::uno::XComponentContext> context):
45 context_(std::move(context))
48 private:
49 OUString SAL_CALL getImplementationName() override
50 { return u"com.sun.star.comp.ucb.ImageContentProvider"_ustr; }
52 sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
53 { return cppu::supportsService(this, ServiceName); }
55 css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
57 return css::uno::Sequence<OUString>{
58 u"com.sun.star.ucb.ImageContentProvider"_ustr};
61 css::uno::Reference<css::ucb::XContent> SAL_CALL queryContent(
62 css::uno::Reference<css::ucb::XContentIdentifier> const & Identifier)
63 override
65 css::uno::Reference<css::uno::XComponentContext> context;
67 std::unique_lock g(m_aMutex);
68 context = context_;
70 if (!context.is()) {
71 throw css::lang::DisposedException();
73 auto url(Identifier->getContentIdentifier());
74 auto uri(css::uri::UriReferenceFactory::create(context)->parse(url));
75 if (!(uri.is()
76 && uri->getScheme().equalsIgnoreAsciiCase(
77 "vnd.libreoffice.image")))
79 throw css::ucb::IllegalIdentifierException(url);
81 auto auth(
82 rtl::Uri::decode(
83 uri->getAuthority(), rtl_UriDecodeStrict,
84 RTL_TEXTENCODING_UTF8));
85 if (auth.isEmpty()) {
86 throw css::ucb::IllegalIdentifierException(url);
88 auto path(uri->getPath());
89 if (path.isEmpty()) {
90 throw css::ucb::IllegalIdentifierException(url);
92 OUStringBuffer buf;
93 assert(path[0] == '/');
94 for (sal_Int32 i = 1;;) {
95 auto j = path.indexOf('/', i);
96 if (j == -1) {
97 j = path.getLength();
99 auto seg(
100 rtl::Uri::decode(
101 path.copy(i, j - i), rtl_UriDecodeStrict,
102 RTL_TEXTENCODING_UTF8));
103 if (seg.isEmpty()) {
104 throw css::ucb::IllegalIdentifierException(url);
106 if (i != 1) {
107 buf.append('/');
109 buf.append(seg);
110 if (j == path.getLength()) {
111 break;
113 i = j + 1;
115 auto decPath(buf.makeStringAndClear());
116 OUString lang;
117 if (uri->hasQuery()) {
118 if (!uri->getQuery().startsWith("lang=", &lang)) {
119 throw css::ucb::IllegalIdentifierException(url);
121 lang = rtl::Uri::decode(
122 lang, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
123 if (lang.isEmpty()) {
124 throw css::ucb::IllegalIdentifierException(url);
127 OUString newUrl;
129 SolarMutexGuard g;
130 newUrl = ImageTree::get().getImageUrl(decPath, auth, lang);
132 ucbhelper::Content content;
133 return
134 ucbhelper::Content::create(
135 newUrl, css::uno::Reference<css::ucb::XCommandEnvironment>(),
136 context, content)
137 ? content.get() : css::uno::Reference<css::ucb::XContent>();
140 sal_Int32 SAL_CALL compareContentIds(
141 css::uno::Reference<css::ucb::XContentIdentifier> const & Id1,
142 css::uno::Reference<css::ucb::XContentIdentifier> const & Id2) override
144 return Id1->getContentIdentifier().compareTo(
145 Id2->getContentIdentifier());
148 void disposing(std::unique_lock<std::mutex>&) override {
149 context_.clear();
152 css::uno::Reference<css::uno::XComponentContext> context_;
157 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
158 com_sun_star_comp_ucb_ImageContentProvider_get_implementation(
159 css::uno::XComponentContext * context,
160 css::uno::Sequence<css::uno::Any> const &)
162 return cppu::acquire(new Provider(context));
165 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */