LibreOffice Module configmgr (master)  1
data.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  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <algorithm>
23 #include <cassert>
24 
25 #include <com/sun/star/uno/RuntimeException.hpp>
26 #include <rtl/ref.hxx>
27 #include <rtl/string.h>
28 #include <rtl/ustrbuf.hxx>
29 #include <rtl/ustring.h>
30 #include <rtl/ustring.hxx>
31 #include <sal/log.hxx>
32 #include <sal/types.h>
33 
34 #include "additions.hxx"
35 #include "data.hxx"
36 #include "node.hxx"
37 #include "nodemap.hxx"
38 #include "rootnode.hxx"
39 #include "setnode.hxx"
40 
41 namespace configmgr {
42 
43 namespace {
44 
45 bool decode(
46  OUString const & encoded, sal_Int32 begin, sal_Int32 end,
47  OUString * decoded)
48 {
49  assert(
50  begin >= 0 && begin <= end && end <= encoded.getLength() &&
51  decoded != nullptr);
52  OUStringBuffer buf(end - begin);
53  while (begin != end) {
54  sal_Unicode c = encoded[begin++];
55  if (c == '&') {
56  if (encoded.match("amp;", begin)) {
57  buf.append('&');
58  begin += RTL_CONSTASCII_LENGTH("amp;");
59  } else if (encoded.match("quot;", begin)) {
60  buf.append('"');
61  begin += RTL_CONSTASCII_LENGTH("quot;");
62  } else if (encoded.match("apos;", begin)) {
63  buf.append('\'');
64  begin += RTL_CONSTASCII_LENGTH("apos;");
65  } else {
66  return false;
67  }
68  assert(begin <= end);
69  } else {
70  buf.append(c);
71  }
72  }
73  *decoded = buf.makeStringAndClear();
74  return true;
75 }
76 
77 }
78 
80  OUString const & templateName, OUString const & name)
81 {
82  if (templateName.isEmpty()) {
83  return name;
84  }
85  OUStringBuffer buf(128);
86  buf.append(templateName);
87  //TODO: verify template name contains no bad chars?
88  buf.append("['");
89  for (sal_Int32 i = 0; i < name.getLength(); ++i) {
90  sal_Unicode c = name[i];
91  switch (c) {
92  case '&':
93  buf.append("&amp;");
94  break;
95  case '"':
96  buf.append("&quot;");
97  break;
98  case '\'':
99  buf.append("&apos;");
100  break;
101  default:
102  buf.append(c);
103  break;
104  }
105  }
106  buf.append("']");
107  return buf.makeStringAndClear();
108 }
109 
111  OUString const & path, sal_Int32 index, OUString * name,
112  bool * setElement, OUString * templateName)
113 {
114  assert(
115  index >= 0 && index <= path.getLength() && name != nullptr &&
116  setElement != nullptr);
117  sal_Int32 i = index;
118  while (i < path.getLength() && path[i] != '/' && path[i] != '[') {
119  ++i;
120  }
121  if (i == path.getLength() || path[i] == '/') {
122  *name = path.copy(index, i - index);
123  *setElement = false;
124  return i;
125  }
126  if (templateName != nullptr) {
127  if (i - index == 1 && path[index] == '*') {
128  templateName->clear();
129  } else {
130  *templateName = path.copy(index, i - index);
131  }
132  }
133  if (++i == path.getLength()) {
134  return -1;
135  }
136  sal_Unicode del = path[i++];
137  if (del != '\'' && del != '"') {
138  return -1;
139  }
140  sal_Int32 j = path.indexOf(del, i);
141  if (j == -1 || j + 1 == path.getLength() || path[j + 1] != ']' ||
142  !decode(path, i, j, name))
143  {
144  return -1;
145  }
146  *setElement = true;
147  return j + 2;
148 }
149 
151  OUString const & component, OUString const & name)
152 {
153  if (component.indexOf(':') != -1 || name.indexOf(':') != -1) {
154  throw css::uno::RuntimeException(
155  "bad component/name pair containing colon " + component + "/" +
156  name);
157  }
158  return component + ":" + name;
159 }
160 
162  OUString const & shortName, OUString const & longName)
163 {
164  if (shortName.indexOf(':') == -1) {
165  sal_Int32 i = longName.indexOf(':') + 1;
166  assert(i > 0);
167  return
168  rtl_ustr_compare_WithLength(
169  shortName.getStr(), shortName.getLength(),
170  longName.getStr() + i, longName.getLength() - i) ==
171  0;
172  } else {
173  return shortName == longName;
174  }
175 }
176 
178 
180  OUString const & pathRepresentation,
181  OUString * canonicRepresentation, std::vector<OUString> * path, int * finalizedLayer)
182  const
183 {
184  if (pathRepresentation.isEmpty() || pathRepresentation[0] != '/') {
185  throw css::uno::RuntimeException(
186  "bad path " + pathRepresentation);
187  }
188  if (path != nullptr) {
189  path->clear();
190  }
191  if (pathRepresentation == "/") {
192  if (canonicRepresentation != nullptr) {
193  *canonicRepresentation = pathRepresentation;
194  }
195  if (finalizedLayer != nullptr) {
196  *finalizedLayer = NO_LAYER;
197  }
198  return root_;
199  }
200  OUString seg;
201  bool setElement;
202  OUString templateName;
203  sal_Int32 n = parseSegment(pathRepresentation, 1, &seg, &setElement, nullptr);
204  if (n == -1 || setElement)
205  {
206  throw css::uno::RuntimeException(
207  "bad path " + pathRepresentation);
208  }
209  NodeMap const & components = getComponents();
210  NodeMap::const_iterator i(components.find(seg));
211  OUStringBuffer canonic(128);
212  rtl::Reference< Node > parent;
213  int finalized = NO_LAYER;
214  for (rtl::Reference< Node > p(i == components.end() ? nullptr : i->second);;) {
215  if (!p.is()) {
216  return p;
217  }
218  if (canonicRepresentation != nullptr) {
219  canonic.append('/');
220  canonic.append(createSegment(templateName, seg));
221  }
222  if (path != nullptr) {
223  path->push_back(seg);
224  }
225  finalized = std::min(finalized, p->getFinalized());
226  if (n != pathRepresentation.getLength() &&
227  pathRepresentation[n++] != '/')
228  {
229  throw css::uno::RuntimeException(
230  "bad path " + pathRepresentation);
231  }
232  // for backwards compatibility, ignore a final slash
233  if (n == pathRepresentation.getLength()) {
234  if (canonicRepresentation != nullptr) {
235  *canonicRepresentation = canonic.makeStringAndClear();
236  }
237  if (finalizedLayer != nullptr) {
238  *finalizedLayer = finalized;
239  }
240  return p;
241  }
242  parent = p;
243  templateName.clear();
244  n = parseSegment(
245  pathRepresentation, n, &seg, &setElement, &templateName);
246  if (n == -1) {
247  throw css::uno::RuntimeException(
248  "bad path " + pathRepresentation);
249  }
250  // For backwards compatibility, allow set members to be accessed with
251  // simple path segments, like group members:
252  p = p->getMember(seg);
253  if (setElement) {
254  switch (parent->kind()) {
256  if (!templateName.isEmpty()) {
257  throw css::uno::RuntimeException(
258  "bad path " + pathRepresentation);
259  }
260  break;
261  case Node::KIND_SET:
262  if (!templateName.isEmpty() &&
263  !static_cast< SetNode * >(parent.get())->isValidTemplate(
264  templateName))
265  {
266  throw css::uno::RuntimeException(
267  "bad path " + pathRepresentation);
268  }
269  break;
270  default:
271  throw css::uno::RuntimeException(
272  "bad path " + pathRepresentation);
273  }
274  if (!templateName.isEmpty() && p != nullptr) {
275  assert(!p->getTemplateName().isEmpty());
276  if (!equalTemplateNames(templateName, p->getTemplateName())) {
277  throw css::uno::RuntimeException(
278  "bad path " + pathRepresentation);
279  }
280  }
281  }
282  }
283 }
284 
286  int layer, OUString const & fullName) const
287 {
288  return templates.findNode(layer, fullName);
289 }
290 
292  return root_->getMembers();
293 }
294 
296  OUString const & url, int layer)
297 {
298  rtl::Reference item(new ExtensionXcu);
299  ExtensionXcuAdditions::iterator i(
300  extensionXcuAdditions_.emplace(
301  url, rtl::Reference< ExtensionXcu >()).first);
302  if (i->second.is()) {
303  throw css::uno::RuntimeException(
304  "already added extension xcu " + url);
305  }
306  i->second = item;
307  item->layer = layer;
308  return &item->additions;
309 }
310 
312  OUString const & url)
313 {
314  ExtensionXcuAdditions::iterator i(extensionXcuAdditions_.find(url));
315  if (i == extensionXcuAdditions_.end()) {
316  // This can happen, as migration of pre OOo 3.3 UserInstallation
317  // extensions in dp_registry::backend::configuration::BackendImpl::
318  // PackageImpl::processPackage_ can cause just-in-time creation of
319  // extension xcu files that are never added via addExtensionXcuAdditions
320  // (also, there might be url spelling differences between calls to
321  // addExtensionXcuAdditions and removeExtensionXcuAdditions?):
322  SAL_INFO(
323  "configmgr",
324  "unknown Data::removeExtensionXcuAdditions(" << url << ")");
326  }
327  rtl::Reference< ExtensionXcu > item(i->second);
328  extensionXcuAdditions_.erase(i);
329  return item;
330 }
331 
332 }
333 
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
iterator find(const OUString &aStr)
Definition: nodemap.hxx:43
NodeMap templates
Definition: data.hxx:49
sal_Int64 n
sal_uInt16 sal_Unicode
rtl::Reference< ExtensionXcu > removeExtensionXcuAdditions(OUString const &url)
Definition: data.cxx:311
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
Additions * addExtensionXcuAdditions(OUString const &url, int layer)
Definition: data.cxx:295
static OUString fullTemplateName(OUString const &component, OUString const &name)
Definition: data.cxx:150
rtl::Reference< RootAccess > root_
std::vector< std::vector< OUString > > Additions
Definition: additions.hxx:31
int i
rtl::Reference< Node > resolvePathRepresentation(OUString const &pathRepresentation, OUString *canonicRepresentation, std::vector< OUString > *path, int *finalizedLayer) const
Definition: data.cxx:179
NodeMap & getComponents() const
Definition: data.cxx:291
static bool equalTemplateNames(OUString const &shortName, OUString const &longName)
Definition: data.cxx:161
#define SAL_INFO(area, stream)
void * p
static sal_Int32 parseSegment(OUString const &path, sal_Int32 index, OUString *name, bool *setElement, OUString *templateName)
Definition: data.cxx:110
rtl::Reference< Node > getTemplate(int layer, OUString const &fullName) const
Definition: data.cxx:285
static OUString createSegment(OUString const &templateName, OUString const &name)
Definition: data.cxx:79
OUString name
Definition: components.cxx:83
iterator end()
Definition: nodemap.hxx:49
NodeMapImpl::const_iterator const_iterator
Definition: nodemap.hxx:38
rtl::Reference< Node > findNode(int layer, OUString const &name) const
Definition: nodemap.cxx:43
rtl::Reference< Node > root_
Definition: data.hxx:92
ExtensionXcuAdditions extensionXcuAdditions_
Definition: data.hxx:94