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>
19 #include <cppuhelper/compbase.hxx>
21 #include <osl/mutex.hxx>
22 #include <rtl/uri.hxx>
23 #include <rtl/ustrbuf.hxx>
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 
36 namespace {
37 
38 class Provider final:
39  private osl::Mutex,
40  public cppu::WeakComponentImplHelper<
41  css::lang::XServiceInfo, css::ucb::XContentProvider>
42 {
43 public:
44  explicit Provider(
45  css::uno::Reference<css::uno::XComponentContext> const & context):
46  WeakComponentImplHelper(*static_cast<Mutex *>(this)), context_(context)
47  {}
48 
49 private:
50  OUString SAL_CALL getImplementationName() override
51  { return "com.sun.star.comp.ucb.ImageContentProvider"; }
52 
53  sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
54  { return cppu::supportsService(this, ServiceName); }
55 
56  css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
57  {
58  return css::uno::Sequence<OUString>{
59  "com.sun.star.ucb.ImageContentProvider"};
60  }
61 
62  css::uno::Reference<css::ucb::XContent> SAL_CALL queryContent(
63  css::uno::Reference<css::ucb::XContentIdentifier> const & Identifier)
64  override
65  {
66  css::uno::Reference<css::uno::XComponentContext> context;
67  {
68  osl::MutexGuard g(*this);
69  context = context_;
70  }
71  if (!context.is()) {
72  throw css::lang::DisposedException();
73  }
74  auto url(Identifier->getContentIdentifier());
75  auto uri(css::uri::UriReferenceFactory::create(context)->parse(url));
76  if (!(uri.is()
77  && uri->getScheme().equalsIgnoreAsciiCase(
78  "vnd.libreoffice.image")))
79  {
80  throw css::ucb::IllegalIdentifierException(url);
81  }
82  auto auth(
83  rtl::Uri::decode(
84  uri->getAuthority(), rtl_UriDecodeStrict,
85  RTL_TEXTENCODING_UTF8));
86  if (auth.isEmpty()) {
87  throw css::ucb::IllegalIdentifierException(url);
88  }
89  auto path(uri->getPath());
90  if (path.isEmpty()) {
91  throw css::ucb::IllegalIdentifierException(url);
92  }
93  OUStringBuffer buf;
94  assert(path[0] == '/');
95  for (sal_Int32 i = 1;;) {
96  auto j = path.indexOf('/', i);
97  if (j == -1) {
98  j = path.getLength();
99  }
100  auto seg(
101  rtl::Uri::decode(
102  path.copy(i, j - i), rtl_UriDecodeStrict,
103  RTL_TEXTENCODING_UTF8));
104  if (seg.isEmpty()) {
105  throw css::ucb::IllegalIdentifierException(url);
106  }
107  if (i != 1) {
108  buf.append('/');
109  }
110  buf.append(seg);
111  if (j == path.getLength()) {
112  break;
113  }
114  i = j + 1;
115  }
116  auto decPath(buf.makeStringAndClear());
117  OUString lang;
118  if (uri->hasQuery()) {
119  if (!uri->getQuery().startsWith("lang=", &lang)) {
120  throw css::ucb::IllegalIdentifierException(url);
121  }
122  lang = rtl::Uri::decode(
123  lang, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8);
124  if (lang.isEmpty()) {
125  throw css::ucb::IllegalIdentifierException(url);
126  }
127  }
128  OUString newUrl;
129  {
130  SolarMutexGuard g;
131  newUrl = ImageTree::get().getImageUrl(decPath, auth, lang);
132  }
133  ucbhelper::Content content;
134  return
136  newUrl, css::uno::Reference<css::ucb::XCommandEnvironment>(),
137  context, content)
138  ? content.get() : css::uno::Reference<css::ucb::XContent>();
139  }
140 
141  sal_Int32 SAL_CALL compareContentIds(
142  css::uno::Reference<css::ucb::XContentIdentifier> const & Id1,
143  css::uno::Reference<css::ucb::XContentIdentifier> const & Id2) override
144  {
145  return Id1->getContentIdentifier().compareTo(
146  Id2->getContentIdentifier());
147  }
148 
149  void SAL_CALL disposing() override {
150  context_.clear();
151  }
152 
153  css::uno::Reference<css::uno::XComponentContext> context_;
154 };
155 
156 }
157 
158 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
160  css::uno::XComponentContext * context,
161  css::uno::Sequence<css::uno::Any> const &)
162 {
163  return cppu::acquire(new Provider(context));
164 }
165 
166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
VCL_DLLPUBLIC OUString getImageUrl(OUString const &name, OUString const &style, OUString const &lang)
static bool create(const OUString &rURL, const css::uno::Reference< css::ucb::XCommandEnvironment > &rEnv, const css::uno::Reference< css::uno::XComponentContext > &rCtx, Content &rContent)
OUString getImplementationName()
static VCL_DLLPUBLIC ImageTree & get()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
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:159
css::uno::Sequence< OUString > getSupportedServiceNames()
int i
unsigned char sal_Bool
css::uno::Reference< css::ucb::XContent > get() const
bool parse(OUString const &uri, SourceProviderScannerData *data)