Branch data Line data Source code
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/Reference.hxx"
26 : : #include "com/sun/star/uno/RuntimeException.hpp"
27 : : #include "com/sun/star/uno/XInterface.hpp"
28 : : #include "rtl/oustringostreaminserter.hxx"
29 : : #include "rtl/ref.hxx"
30 : : #include "rtl/string.h"
31 : : #include "rtl/ustrbuf.hxx"
32 : : #include "rtl/ustring.h"
33 : : #include "rtl/ustring.hxx"
34 : : #include "sal/log.hxx"
35 : : #include "sal/types.h"
36 : :
37 : : #include "additions.hxx"
38 : : #include "data.hxx"
39 : : #include "groupnode.hxx"
40 : : #include "node.hxx"
41 : : #include "nodemap.hxx"
42 : : #include "rootnode.hxx"
43 : : #include "setnode.hxx"
44 : :
45 : : namespace configmgr {
46 : :
47 : : namespace {
48 : :
49 : : namespace css = com::sun::star;
50 : :
51 : 37970 : bool decode(
52 : : rtl::OUString const & encoded, sal_Int32 begin, sal_Int32 end,
53 : : rtl::OUString * decoded)
54 : : {
55 : : assert(
56 : : begin >= 0 && begin <= end && end <= encoded.getLength() &&
57 : : decoded != 0);
58 : 37970 : rtl::OUStringBuffer buf;
59 [ + + ]: 663039 : while (begin != end) {
60 : 625069 : sal_Unicode c = encoded[begin++];
61 [ - + ]: 625069 : if (c == '&') {
62 [ # # ]: 0 : if (encoded.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("amp;"), begin))
63 : : {
64 [ # # ]: 0 : buf.append(sal_Unicode('&'));
65 : 0 : begin += RTL_CONSTASCII_LENGTH("amp;");
66 [ # # ]: 0 : } else if (encoded.matchAsciiL(
67 : 0 : RTL_CONSTASCII_STRINGPARAM("quot;"), begin))
68 : : {
69 [ # # ]: 0 : buf.append(sal_Unicode('"'));
70 : 0 : begin += RTL_CONSTASCII_LENGTH("quot;");
71 [ # # ]: 0 : } else if (encoded.matchAsciiL(
72 : 0 : RTL_CONSTASCII_STRINGPARAM("apos;"), begin))
73 : : {
74 [ # # ]: 0 : buf.append(sal_Unicode('\''));
75 : 0 : begin += RTL_CONSTASCII_LENGTH("apos;");
76 : : } else {
77 : 0 : return false;
78 : : }
79 : : assert(begin <= end);
80 : : } else {
81 [ + - ]: 625069 : buf.append(c);
82 : : }
83 : : }
84 [ + - ]: 37970 : *decoded = buf.makeStringAndClear();
85 : 37970 : return true;
86 : : }
87 : :
88 : : }
89 : :
90 : 372220 : rtl::OUString Data::createSegment(
91 : : rtl::OUString const & templateName, rtl::OUString const & name)
92 : : {
93 [ + + ]: 372220 : if (templateName.isEmpty()) {
94 : 356843 : return name;
95 : : }
96 [ + - ]: 15377 : rtl::OUStringBuffer buf(templateName);
97 : : //TODO: verify template name contains no bad chars?
98 [ + - ]: 15377 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("['"));
99 [ + + ]: 460484 : for (sal_Int32 i = 0; i < name.getLength(); ++i) {
100 : 445107 : sal_Unicode c = name[i];
101 [ - - - + ]: 445107 : switch (c) {
102 : : case '&':
103 [ # # ]: 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("&"));
104 : 0 : break;
105 : : case '"':
106 [ # # ]: 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("""));
107 : 0 : break;
108 : : case '\'':
109 [ # # ]: 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("'"));
110 : 0 : break;
111 : : default:
112 [ + - ]: 445107 : buf.append(c);
113 : 445107 : break;
114 : : }
115 : : }
116 [ + - ]: 15377 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("']"));
117 [ + - ]: 372220 : return buf.makeStringAndClear();
118 : : }
119 : :
120 : 1188959 : sal_Int32 Data::parseSegment(
121 : : rtl::OUString const & path, sal_Int32 index, rtl::OUString * name,
122 : : bool * setElement, rtl::OUString * templateName)
123 : : {
124 : : assert(
125 : : index >= 0 && index <= path.getLength() && name != 0 &&
126 : : setElement != 0);
127 : 1188959 : sal_Int32 i = index;
128 [ + + ][ + + ]: 17381312 : while (i < path.getLength() && path[i] != '/' && path[i] != '[') {
[ + + ][ + + ]
129 : 16192353 : ++i;
130 : : }
131 [ + + ][ + + ]: 1188959 : if (i == path.getLength() || path[i] == '/') {
[ + + ]
132 : 1150989 : *name = path.copy(index, i - index);
133 : 1150989 : *setElement = false;
134 : 1150989 : return i;
135 : : }
136 [ + - ]: 37970 : if (templateName != 0) {
137 [ + + ][ + - ]: 37970 : if (i - index == 1 && path[index] == '*') {
[ + + ]
138 : 22021 : *templateName = rtl::OUString();
139 : : } else {
140 : 15949 : *templateName = path.copy(index, i - index);
141 : : }
142 : : }
143 [ - + ]: 37970 : if (++i == path.getLength()) {
144 : 0 : return -1;
145 : : }
146 : 37970 : sal_Unicode del = path[i++];
147 [ - + ][ + + ]: 37970 : if (del != '\'' && del != '"') {
148 : 0 : return -1;
149 : : }
150 : 37970 : sal_Int32 j = path.indexOf(del, i);
151 [ + - ]: 75940 : if (j == -1 || j + 1 == path.getLength() || path[j + 1] != ']' ||
[ + - - + ]
[ - + ][ + - ]
152 : 37970 : !decode(path, i, j, name))
153 : : {
154 : 0 : return -1;
155 : : }
156 : 37970 : *setElement = true;
157 : 1188959 : return j + 2;
158 : : }
159 : :
160 : 148430 : rtl::OUString Data::fullTemplateName(
161 : : rtl::OUString const & component, rtl::OUString const & name)
162 : : {
163 [ + - ][ - + ]: 148430 : if (component.indexOf(':') != -1 || name.indexOf(':') != -1) {
[ - + ]
164 : : throw css::uno::RuntimeException(
165 : : (rtl::OUString(
166 : : RTL_CONSTASCII_USTRINGPARAM(
167 : : "bad component/name pair containing colon ")) +
168 : : component + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
169 : : name),
170 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
[ # # ]
171 : : }
172 [ + - ]: 148430 : rtl::OUStringBuffer buf(component);
173 [ + - ]: 148430 : buf.append(sal_Unicode(':'));
174 [ + - ]: 148430 : buf.append(name);
175 [ + - ]: 148430 : return buf.makeStringAndClear();
176 : : }
177 : :
178 : 2523333 : bool Data::equalTemplateNames(
179 : : rtl::OUString const & shortName, rtl::OUString const & longName)
180 : : {
181 [ + + ]: 2523333 : if (shortName.indexOf(':') == -1) {
182 : 50 : sal_Int32 i = longName.indexOf(':') + 1;
183 : : assert(i > 0);
184 : : return
185 : : rtl_ustr_compare_WithLength(
186 : : shortName.getStr(), shortName.getLength(),
187 : 50 : longName.getStr() + i, longName.getLength() - i) ==
188 : 50 : 0;
189 : : } else {
190 : 2523333 : return shortName == longName;
191 : : }
192 : : }
193 : :
194 : 2776779 : rtl::Reference< Node > Data::findNode(
195 : : int layer, NodeMap const & map, rtl::OUString const & name)
196 : : {
197 [ + - ]: 2776779 : NodeMap::const_iterator i(map.find(name));
198 [ + - ][ + - ]: 8330337 : return i == map.end() || i->second->getLayer() > layer
[ # # ]
199 [ - + ][ + - ]: 8330337 : ? rtl::Reference< Node >() : i->second;
[ + - ]
200 : : }
201 : :
202 [ + - ][ + - ]: 324 : Data::Data(): root_(new RootNode) {}
[ + - ][ + - ]
[ + - ][ + - ]
203 : :
204 : 148286 : rtl::Reference< Node > Data::resolvePathRepresentation(
205 : : rtl::OUString const & pathRepresentation,
206 : : rtl::OUString * canonicRepresentation, Path * path, int * finalizedLayer)
207 : : const
208 : : {
209 [ + - ][ - + ]: 148286 : if (pathRepresentation.isEmpty() || pathRepresentation[0] != '/') {
[ - + ]
210 : : throw css::uno::RuntimeException(
211 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
212 : : pathRepresentation),
213 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
214 : : }
215 [ + + ]: 148286 : if (path != 0) {
216 : 128079 : path->clear();
217 : : }
218 [ + + ]: 148286 : if ( pathRepresentation == "/" ) {
219 [ + + ]: 3431 : if (canonicRepresentation != 0) {
220 : 3369 : *canonicRepresentation = pathRepresentation;
221 : : }
222 [ + - ]: 3431 : if (finalizedLayer != 0) {
223 : 3431 : *finalizedLayer = NO_LAYER;
224 : : }
225 [ + - ]: 3431 : return root_;
226 : : }
227 : 144855 : rtl::OUString seg;
228 : : bool setElement;
229 : 144855 : rtl::OUString templateName;
230 [ + - ]: 144855 : sal_Int32 n = parseSegment(pathRepresentation, 1, &seg, &setElement, 0);
231 [ + - ][ - + ]: 144855 : if (n == -1 || setElement)
232 : : {
233 : : throw css::uno::RuntimeException(
234 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
235 : : pathRepresentation),
236 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
237 : : }
238 [ + - ]: 144855 : NodeMap const & components = getComponents();
239 [ + - ]: 144855 : NodeMap::const_iterator i(components.find(seg));
240 : 144855 : rtl::OUStringBuffer canonic;
241 : 144855 : rtl::Reference< Node > parent;
242 : 144855 : int finalized = NO_LAYER;
243 [ # # ][ + - ]: 241455 : for (rtl::Reference< Node > p(i == components.end() ? 0 : i->second);;) {
[ - + ]
244 [ - + ]: 241455 : if (!p.is()) {
245 [ # # ]: 0 : return p;
246 : : }
247 [ + + ]: 241455 : if (canonicRepresentation != 0) {
248 [ + - ]: 169137 : canonic.append(sal_Unicode('/'));
249 [ + - ][ + - ]: 169137 : canonic.append(createSegment(templateName, seg));
250 : : }
251 [ + + ]: 241455 : if (path != 0) {
252 [ + - ]: 205857 : path->push_back(seg);
253 : : }
254 [ + - ][ + - ]: 241455 : finalized = std::min(finalized, p->getFinalized());
255 [ + + - + ]: 346517 : if (n != pathRepresentation.getLength() &&
[ - + ]
256 : 105062 : pathRepresentation[n++] != '/')
257 : : {
258 : : throw css::uno::RuntimeException(
259 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
260 : : pathRepresentation),
261 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
262 : : }
263 : : // for backwards compatibility, ignore a final slash
264 [ + + ]: 241455 : if (n == pathRepresentation.getLength()) {
265 [ + + ]: 144855 : if (canonicRepresentation != 0) {
266 [ + - ]: 112298 : *canonicRepresentation = canonic.makeStringAndClear();
267 : : }
268 [ + - ]: 144855 : if (finalizedLayer != 0) {
269 : 144855 : *finalizedLayer = finalized;
270 : : }
271 [ + - ]: 144855 : return p;
272 : : }
273 [ + - ]: 96600 : parent = p;
274 : 96600 : templateName = rtl::OUString();
275 : : n = parseSegment(
276 [ + - ]: 96600 : pathRepresentation, n, &seg, &setElement, &templateName);
277 [ - + ]: 96600 : if (n == -1) {
278 : : throw css::uno::RuntimeException(
279 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
280 : : pathRepresentation),
281 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
282 : : }
283 : : // For backwards compatibility, allow set members to be accessed with
284 : : // simple path segments, like group members:
285 [ + - ][ + - ]: 96600 : p = p->getMember(seg);
[ + - ]
286 [ + + ]: 96600 : if (setElement) {
287 [ + - ]: 3295 : switch (parent->kind()) {
[ - + - ]
288 : : case Node::KIND_LOCALIZED_PROPERTY:
289 [ # # ]: 0 : if (!templateName.isEmpty()) {
290 : : throw css::uno::RuntimeException(
291 : : (rtl::OUString(
292 : : RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
293 : : pathRepresentation),
294 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
295 : : }
296 : 0 : break;
297 : : case Node::KIND_SET:
298 [ + + ][ - + ]: 4799 : if (!templateName.isEmpty() &&
[ - + ]
299 : 1504 : !dynamic_cast< SetNode * >(parent.get())->isValidTemplate(
300 [ + - ][ - + ]: 1504 : templateName))
301 : : {
302 : : throw css::uno::RuntimeException(
303 : : (rtl::OUString(
304 : : RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
305 : : pathRepresentation),
306 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
307 : : }
308 : 3295 : break;
309 : : default:
310 : : throw css::uno::RuntimeException(
311 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
312 : : pathRepresentation),
313 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
314 : : }
315 [ + + ][ + - ]: 3295 : if (!templateName.isEmpty() && p != 0) {
[ + - ][ + + ]
[ + - ]
[ + + # # ]
316 : : assert(!p->getTemplateName().isEmpty());
317 [ + - ][ - + ]: 1504 : if (!equalTemplateNames(templateName, p->getTemplateName())) {
318 : : throw css::uno::RuntimeException(
319 : : (rtl::OUString(
320 : : RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
321 : : pathRepresentation),
322 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
323 : : }
324 : : }
325 : : }
326 [ + - ][ + - ]: 148286 : }
327 : : }
328 : :
329 : 2532833 : rtl::Reference< Node > Data::getTemplate(
330 : : int layer, rtl::OUString const & fullName) const
331 : : {
332 : 2532833 : return findNode(layer, templates, fullName);
333 : : }
334 : :
335 : 242830 : NodeMap & Data::getComponents() const {
336 : 242830 : return root_->getMembers();
337 : : }
338 : :
339 : 0 : Additions * Data::addExtensionXcuAdditions(
340 : : rtl::OUString const & url, int layer)
341 : : {
342 [ # # ][ # # ]: 0 : rtl::Reference< ExtensionXcu > item(new ExtensionXcu);
[ # # ]
343 : : ExtensionXcuAdditions::iterator i(
344 : : extensionXcuAdditions_.insert(
345 : : ExtensionXcuAdditions::value_type(
346 [ # # ][ # # ]: 0 : url, rtl::Reference< ExtensionXcu >())).first);
[ # # ][ # # ]
347 [ # # ]: 0 : if (i->second.is()) {
348 : : throw css::uno::RuntimeException(
349 : : (rtl::OUString(
350 : : RTL_CONSTASCII_USTRINGPARAM(
351 : : "already added extension xcu ")) +
352 : : url),
353 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
354 : : }
355 [ # # ]: 0 : i->second = item;
356 : 0 : item->layer = layer;
357 [ # # ]: 0 : return &item->additions;
358 : : }
359 : :
360 : 0 : rtl::Reference< Data::ExtensionXcu > Data::removeExtensionXcuAdditions(
361 : : rtl::OUString const & url)
362 : : {
363 [ # # ]: 0 : ExtensionXcuAdditions::iterator i(extensionXcuAdditions_.find(url));
364 [ # # ]: 0 : if (i == extensionXcuAdditions_.end()) {
365 : : // This can happen, as migration of pre OOo 3.3 UserInstallation
366 : : // extensions in dp_registry::backend::configuration::BackendImpl::
367 : : // PackageImpl::processPackage_ can cause just-in-time creation of
368 : : // extension xcu files that are never added via addExtensionXcuAdditions
369 : : // (also, there might be url spelling differences between calls to
370 : : // addExtensionXcuAdditions and removeExtensionXcuAdditions?):
371 : : SAL_INFO(
372 : : "configmgr",
373 : : "unknown Data::removeExtensionXcuAdditions(" << url << ")");
374 : 0 : return rtl::Reference< ExtensionXcu >();
375 : : }
376 [ # # ]: 0 : rtl::Reference< ExtensionXcu > item(i->second);
377 [ # # ]: 0 : extensionXcuAdditions_.erase(i);
378 [ # # ][ # # ]: 0 : return item;
379 : : }
380 : :
381 : : }
382 : :
383 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|