LibreOffice Module ucb (master) 1
ucpimage.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 */
9
10#include <sal/config.h>
11
12#include <cassert>
13
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>
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>
27
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.
31//
32// The URL scheme is
33//
34// "vnd.libreoffice.image://"<theme><path>["?lang="<language-tag>]
35
36namespace {
37
38class Provider final:
40 css::lang::XServiceInfo, css::ucb::XContentProvider>
41{
42public:
43 explicit Provider(
44 css::uno::Reference<css::uno::XComponentContext> context):
45 context_(std::move(context))
46 {}
47
48private:
49 OUString SAL_CALL getImplementationName() override
50 { return "com.sun.star.comp.ucb.ImageContentProvider"; }
51
52 sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
53 { return cppu::supportsService(this, ServiceName); }
54
55 css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
56 {
57 return css::uno::Sequence<OUString>{
58 "com.sun.star.ucb.ImageContentProvider"};
59 }
60
61 css::uno::Reference<css::ucb::XContent> SAL_CALL queryContent(
62 css::uno::Reference<css::ucb::XContentIdentifier> const & Identifier)
63 override
64 {
65 css::uno::Reference<css::uno::XComponentContext> context;
66 {
67 std::unique_lock g(m_aMutex);
68 context = context_;
69 }
70 if (!context.is()) {
71 throw css::lang::DisposedException();
72 }
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")))
78 {
79 throw css::ucb::IllegalIdentifierException(url);
80 }
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);
87 }
88 auto path(uri->getPath());
89 if (path.isEmpty()) {
90 throw css::ucb::IllegalIdentifierException(url);
91 }
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();
98 }
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);
105 }
106 if (i != 1) {
107 buf.append('/');
108 }
109 buf.append(seg);
110 if (j == path.getLength()) {
111 break;
112 }
113 i = j + 1;
114 }
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);
120 }
121 lang = rtl::Uri::decode(
122 lang, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
123 if (lang.isEmpty()) {
124 throw css::ucb::IllegalIdentifierException(url);
125 }
126 }
127 OUString newUrl;
128 {
130 newUrl = ImageTree::get().getImageUrl(decPath, auth, lang);
131 }
132 ucbhelper::Content content;
133 return
135 newUrl, css::uno::Reference<css::ucb::XCommandEnvironment>(),
136 context, content)
137 ? content.get() : css::uno::Reference<css::ucb::XContent>();
138 }
139
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
143 {
144 return Id1->getContentIdentifier().compareTo(
145 Id2->getContentIdentifier());
146 }
147
148 void disposing(std::unique_lock<std::mutex>&) override {
149 context_.clear();
150 }
151
152 css::uno::Reference<css::uno::XComponentContext> context_;
153};
154
155}
156
157extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
159 css::uno::XComponentContext * context,
160 css::uno::Sequence<css::uno::Any> const &)
161{
162 return cppu::acquire(new Provider(context));
163}
164
165/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
VCL_DLLPUBLIC OUString getImageUrl(OUString const &name, OUString const &style, OUString const &lang)
static VCL_DLLPUBLIC ImageTree & get()
virtual void disposing(std::unique_lock< std::mutex > &)
static bool create(const OUString &rURL, const css::uno::Reference< css::ucb::XCommandEnvironment > &rEnv, const css::uno::Reference< css::uno::XComponentContext > &rCtx, Content &rContent)
css::uno::Reference< css::ucb::XContent > get() const
std::mutex m_aMutex
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
bool parse(OUString const &uri, SourceProviderScannerData *data)
unsigned char sal_Bool
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_ucb_ImageContentProvider_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Definition: ucpimage.cxx:158
uno::Reference< uno::XComponentContext > context_