1*3a7cf181SAndrew Rist /**************************************************************
2*3a7cf181SAndrew Rist *
3*3a7cf181SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*3a7cf181SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*3a7cf181SAndrew Rist * distributed with this work for additional information
6*3a7cf181SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*3a7cf181SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*3a7cf181SAndrew Rist * "License"); you may not use this file except in compliance
9*3a7cf181SAndrew Rist * with the License. You may obtain a copy of the License at
10*3a7cf181SAndrew Rist *
11*3a7cf181SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*3a7cf181SAndrew Rist *
13*3a7cf181SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*3a7cf181SAndrew Rist * software distributed under the License is distributed on an
15*3a7cf181SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*3a7cf181SAndrew Rist * KIND, either express or implied. See the License for the
17*3a7cf181SAndrew Rist * specific language governing permissions and limitations
18*3a7cf181SAndrew Rist * under the License.
19*3a7cf181SAndrew Rist *
20*3a7cf181SAndrew Rist *************************************************************/
21*3a7cf181SAndrew Rist
22*3a7cf181SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir #include "precompiled_configmgr.hxx"
25cdf0e10cSrcweir #include "sal/config.h"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <algorithm>
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include "com/sun/star/uno/Reference.hxx"
30cdf0e10cSrcweir #include "com/sun/star/uno/RuntimeException.hpp"
31cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp"
32cdf0e10cSrcweir #include "osl/diagnose.h"
33cdf0e10cSrcweir #include "rtl/ref.hxx"
34cdf0e10cSrcweir #include "rtl/string.h"
35cdf0e10cSrcweir #include "rtl/textenc.h"
36cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
37cdf0e10cSrcweir #include "rtl/ustring.h"
38cdf0e10cSrcweir #include "rtl/ustring.hxx"
39cdf0e10cSrcweir #include "sal/types.h"
40cdf0e10cSrcweir
41cdf0e10cSrcweir #include "additions.hxx"
42cdf0e10cSrcweir #include "data.hxx"
43cdf0e10cSrcweir #include "groupnode.hxx"
44cdf0e10cSrcweir #include "node.hxx"
45cdf0e10cSrcweir #include "nodemap.hxx"
46cdf0e10cSrcweir #include "setnode.hxx"
47cdf0e10cSrcweir
48cdf0e10cSrcweir namespace configmgr {
49cdf0e10cSrcweir
50cdf0e10cSrcweir namespace {
51cdf0e10cSrcweir
52cdf0e10cSrcweir namespace css = com::sun::star;
53cdf0e10cSrcweir
decode(rtl::OUString const & encoded,sal_Int32 begin,sal_Int32 end,rtl::OUString * decoded)54cdf0e10cSrcweir bool decode(
55cdf0e10cSrcweir rtl::OUString const & encoded, sal_Int32 begin, sal_Int32 end,
56cdf0e10cSrcweir rtl::OUString * decoded)
57cdf0e10cSrcweir {
58cdf0e10cSrcweir OSL_ASSERT(
59cdf0e10cSrcweir begin >= 0 && begin <= end && end <= encoded.getLength() &&
60cdf0e10cSrcweir decoded != 0);
61cdf0e10cSrcweir rtl::OUStringBuffer buf;
62cdf0e10cSrcweir while (begin != end) {
63cdf0e10cSrcweir sal_Unicode c = encoded[begin++];
64cdf0e10cSrcweir if (c == '&') {
65cdf0e10cSrcweir if (encoded.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("amp;"), begin))
66cdf0e10cSrcweir {
67cdf0e10cSrcweir buf.append(sal_Unicode('&'));
68cdf0e10cSrcweir begin += RTL_CONSTASCII_LENGTH("amp;");
69cdf0e10cSrcweir } else if (encoded.matchAsciiL(
70cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("quot;"), begin))
71cdf0e10cSrcweir {
72cdf0e10cSrcweir buf.append(sal_Unicode('"'));
73cdf0e10cSrcweir begin += RTL_CONSTASCII_LENGTH("quot;");
74cdf0e10cSrcweir } else if (encoded.matchAsciiL(
75cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("apos;"), begin))
76cdf0e10cSrcweir {
77cdf0e10cSrcweir buf.append(sal_Unicode('\''));
78cdf0e10cSrcweir begin += RTL_CONSTASCII_LENGTH("apos;");
79cdf0e10cSrcweir } else {
80cdf0e10cSrcweir return false;
81cdf0e10cSrcweir }
82cdf0e10cSrcweir OSL_ASSERT(begin <= end);
83cdf0e10cSrcweir } else {
84cdf0e10cSrcweir buf.append(c);
85cdf0e10cSrcweir }
86cdf0e10cSrcweir }
87cdf0e10cSrcweir *decoded = buf.makeStringAndClear();
88cdf0e10cSrcweir return true;
89cdf0e10cSrcweir }
90cdf0e10cSrcweir
91cdf0e10cSrcweir }
92cdf0e10cSrcweir
createSegment(rtl::OUString const & templateName,rtl::OUString const & name)93cdf0e10cSrcweir rtl::OUString Data::createSegment(
94cdf0e10cSrcweir rtl::OUString const & templateName, rtl::OUString const & name)
95cdf0e10cSrcweir {
96cdf0e10cSrcweir if (templateName.getLength() == 0) {
97cdf0e10cSrcweir return name;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir rtl::OUStringBuffer buf(templateName);
100cdf0e10cSrcweir //TODO: verify template name contains no bad chars?
101cdf0e10cSrcweir buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("['"));
102cdf0e10cSrcweir for (sal_Int32 i = 0; i < name.getLength(); ++i) {
103cdf0e10cSrcweir sal_Unicode c = name[i];
104cdf0e10cSrcweir switch (c) {
105cdf0e10cSrcweir case '&':
106cdf0e10cSrcweir buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("&"));
107cdf0e10cSrcweir break;
108cdf0e10cSrcweir case '"':
109cdf0e10cSrcweir buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("""));
110cdf0e10cSrcweir break;
111cdf0e10cSrcweir case '\'':
112cdf0e10cSrcweir buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("'"));
113cdf0e10cSrcweir break;
114cdf0e10cSrcweir default:
115cdf0e10cSrcweir buf.append(c);
116cdf0e10cSrcweir break;
117cdf0e10cSrcweir }
118cdf0e10cSrcweir }
119cdf0e10cSrcweir buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("']"));
120cdf0e10cSrcweir return buf.makeStringAndClear();
121cdf0e10cSrcweir }
122cdf0e10cSrcweir
parseSegment(rtl::OUString const & path,sal_Int32 index,rtl::OUString * name,bool * setElement,rtl::OUString * templateName)123cdf0e10cSrcweir sal_Int32 Data::parseSegment(
124cdf0e10cSrcweir rtl::OUString const & path, sal_Int32 index, rtl::OUString * name,
125cdf0e10cSrcweir bool * setElement, rtl::OUString * templateName)
126cdf0e10cSrcweir {
127cdf0e10cSrcweir OSL_ASSERT(
128cdf0e10cSrcweir index >= 0 && index <= path.getLength() && name != 0 &&
129cdf0e10cSrcweir setElement != 0);
130cdf0e10cSrcweir sal_Int32 i = index;
131cdf0e10cSrcweir while (i < path.getLength() && path[i] != '/' && path[i] != '[') {
132cdf0e10cSrcweir ++i;
133cdf0e10cSrcweir }
134cdf0e10cSrcweir if (i == path.getLength() || path[i] == '/') {
135cdf0e10cSrcweir *name = path.copy(index, i - index);
136cdf0e10cSrcweir *setElement = false;
137cdf0e10cSrcweir return i;
138cdf0e10cSrcweir }
139cdf0e10cSrcweir if (templateName != 0) {
140cdf0e10cSrcweir if (i - index == 1 && path[index] == '*') {
141cdf0e10cSrcweir *templateName = rtl::OUString();
142cdf0e10cSrcweir } else {
143cdf0e10cSrcweir *templateName = path.copy(index, i - index);
144cdf0e10cSrcweir }
145cdf0e10cSrcweir }
146cdf0e10cSrcweir if (++i == path.getLength()) {
147cdf0e10cSrcweir return -1;
148cdf0e10cSrcweir }
149cdf0e10cSrcweir sal_Unicode del = path[i++];
150cdf0e10cSrcweir if (del != '\'' && del != '"') {
151cdf0e10cSrcweir return -1;
152cdf0e10cSrcweir }
153cdf0e10cSrcweir sal_Int32 j = path.indexOf(del, i);
154cdf0e10cSrcweir if (j == -1 || j + 1 == path.getLength() || path[j + 1] != ']' ||
155cdf0e10cSrcweir !decode(path, i, j, name))
156cdf0e10cSrcweir {
157cdf0e10cSrcweir return -1;
158cdf0e10cSrcweir }
159cdf0e10cSrcweir *setElement = true;
160cdf0e10cSrcweir return j + 2;
161cdf0e10cSrcweir }
162cdf0e10cSrcweir
fullTemplateName(rtl::OUString const & component,rtl::OUString const & name)163cdf0e10cSrcweir rtl::OUString Data::fullTemplateName(
164cdf0e10cSrcweir rtl::OUString const & component, rtl::OUString const & name)
165cdf0e10cSrcweir {
166cdf0e10cSrcweir if (component.indexOf(':') != -1 || name.indexOf(':') != -1) {
167cdf0e10cSrcweir throw css::uno::RuntimeException(
168cdf0e10cSrcweir (rtl::OUString(
169cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM(
170cdf0e10cSrcweir "bad component/name pair containing colon ")) +
171cdf0e10cSrcweir component + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
172cdf0e10cSrcweir name),
173cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
174cdf0e10cSrcweir }
175cdf0e10cSrcweir rtl::OUStringBuffer buf(component);
176cdf0e10cSrcweir buf.append(sal_Unicode(':'));
177cdf0e10cSrcweir buf.append(name);
178cdf0e10cSrcweir return buf.makeStringAndClear();
179cdf0e10cSrcweir }
180cdf0e10cSrcweir
equalTemplateNames(rtl::OUString const & shortName,rtl::OUString const & longName)181cdf0e10cSrcweir bool Data::equalTemplateNames(
182cdf0e10cSrcweir rtl::OUString const & shortName, rtl::OUString const & longName)
183cdf0e10cSrcweir {
184cdf0e10cSrcweir if (shortName.indexOf(':') == -1) {
185cdf0e10cSrcweir sal_Int32 i = longName.indexOf(':') + 1;
186cdf0e10cSrcweir OSL_ASSERT(i > 0);
187cdf0e10cSrcweir return
188cdf0e10cSrcweir rtl_ustr_compare_WithLength(
189cdf0e10cSrcweir shortName.getStr(), shortName.getLength(),
190cdf0e10cSrcweir longName.getStr() + i, longName.getLength() - i) ==
191cdf0e10cSrcweir 0;
192cdf0e10cSrcweir } else {
193cdf0e10cSrcweir return shortName == longName;
194cdf0e10cSrcweir }
195cdf0e10cSrcweir }
196cdf0e10cSrcweir
findNode(int layer,NodeMap const & map,rtl::OUString const & name)197cdf0e10cSrcweir rtl::Reference< Node > Data::findNode(
198cdf0e10cSrcweir int layer, NodeMap const & map, rtl::OUString const & name)
199cdf0e10cSrcweir {
200cdf0e10cSrcweir NodeMap::const_iterator i(map.find(name));
201cdf0e10cSrcweir return i == map.end() || i->second->getLayer() > layer
202cdf0e10cSrcweir ? rtl::Reference< Node >() : i->second;
203cdf0e10cSrcweir }
204cdf0e10cSrcweir
resolvePathRepresentation(rtl::OUString const & pathRepresentation,rtl::OUString * canonicRepresentation,Path * path,int * finalizedLayer) const205cdf0e10cSrcweir rtl::Reference< Node > Data::resolvePathRepresentation(
206cdf0e10cSrcweir rtl::OUString const & pathRepresentation,
207cdf0e10cSrcweir rtl::OUString * canonicRepresentation, Path * path, int * finalizedLayer)
208cdf0e10cSrcweir const
209cdf0e10cSrcweir {
210cdf0e10cSrcweir if (pathRepresentation.getLength() == 0 || pathRepresentation[0] != '/') {
211cdf0e10cSrcweir throw css::uno::RuntimeException(
212cdf0e10cSrcweir (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
213cdf0e10cSrcweir pathRepresentation),
214cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
215cdf0e10cSrcweir }
216cdf0e10cSrcweir rtl::OUString seg;
217cdf0e10cSrcweir bool setElement;
218cdf0e10cSrcweir rtl::OUString templateName;
219cdf0e10cSrcweir sal_Int32 n = parseSegment(pathRepresentation, 1, &seg, &setElement, 0);
220cdf0e10cSrcweir if (n == -1 || setElement)
221cdf0e10cSrcweir {
222cdf0e10cSrcweir throw css::uno::RuntimeException(
223cdf0e10cSrcweir (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
224cdf0e10cSrcweir pathRepresentation),
225cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
226cdf0e10cSrcweir }
227cdf0e10cSrcweir NodeMap::const_iterator i(components.find(seg));
228cdf0e10cSrcweir rtl::OUStringBuffer canonic;
229cdf0e10cSrcweir if (path != 0) {
230cdf0e10cSrcweir path->clear();
231cdf0e10cSrcweir }
232cdf0e10cSrcweir rtl::Reference< Node > parent;
233cdf0e10cSrcweir int finalized = NO_LAYER;
234cdf0e10cSrcweir for (rtl::Reference< Node > p(i == components.end() ? 0 : i->second);;) {
235cdf0e10cSrcweir if (!p.is()) {
236cdf0e10cSrcweir return p;
237cdf0e10cSrcweir }
238cdf0e10cSrcweir if (canonicRepresentation != 0) {
239cdf0e10cSrcweir canonic.append(sal_Unicode('/'));
240cdf0e10cSrcweir canonic.append(createSegment(templateName, seg));
241cdf0e10cSrcweir }
242cdf0e10cSrcweir if (path != 0) {
243cdf0e10cSrcweir path->push_back(seg);
244cdf0e10cSrcweir }
245cdf0e10cSrcweir finalized = std::min(finalized, p->getFinalized());
246cdf0e10cSrcweir if (n != pathRepresentation.getLength() &&
247cdf0e10cSrcweir pathRepresentation[n++] != '/')
248cdf0e10cSrcweir {
249cdf0e10cSrcweir throw css::uno::RuntimeException(
250cdf0e10cSrcweir (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
251cdf0e10cSrcweir pathRepresentation),
252cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
253cdf0e10cSrcweir }
254cdf0e10cSrcweir // for backwards compatibility, ignore a final slash
255cdf0e10cSrcweir if (n == pathRepresentation.getLength()) {
256cdf0e10cSrcweir if (canonicRepresentation != 0) {
257cdf0e10cSrcweir *canonicRepresentation = canonic.makeStringAndClear();
258cdf0e10cSrcweir }
259cdf0e10cSrcweir if (finalizedLayer != 0) {
260cdf0e10cSrcweir *finalizedLayer = finalized;
261cdf0e10cSrcweir }
262cdf0e10cSrcweir return p;
263cdf0e10cSrcweir }
264cdf0e10cSrcweir parent = p;
265cdf0e10cSrcweir templateName = rtl::OUString();
266cdf0e10cSrcweir n = parseSegment(
267cdf0e10cSrcweir pathRepresentation, n, &seg, &setElement, &templateName);
268cdf0e10cSrcweir if (n == -1) {
269cdf0e10cSrcweir throw css::uno::RuntimeException(
270cdf0e10cSrcweir (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
271cdf0e10cSrcweir pathRepresentation),
272cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
273cdf0e10cSrcweir }
274cdf0e10cSrcweir // For backwards compatibility, allow set members to be accessed with
275cdf0e10cSrcweir // simple path segments, like group members:
276cdf0e10cSrcweir p = p->getMember(seg);
277cdf0e10cSrcweir if (setElement) {
278cdf0e10cSrcweir switch (parent->kind()) {
279cdf0e10cSrcweir case Node::KIND_LOCALIZED_PROPERTY:
280cdf0e10cSrcweir if (templateName.getLength() != 0) {
281cdf0e10cSrcweir throw css::uno::RuntimeException(
282cdf0e10cSrcweir (rtl::OUString(
283cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
284cdf0e10cSrcweir pathRepresentation),
285cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
286cdf0e10cSrcweir }
287cdf0e10cSrcweir break;
288cdf0e10cSrcweir case Node::KIND_SET:
289cdf0e10cSrcweir if (templateName.getLength() != 0 &&
290cdf0e10cSrcweir !dynamic_cast< SetNode * >(parent.get())->isValidTemplate(
291cdf0e10cSrcweir templateName))
292cdf0e10cSrcweir {
293cdf0e10cSrcweir throw css::uno::RuntimeException(
294cdf0e10cSrcweir (rtl::OUString(
295cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
296cdf0e10cSrcweir pathRepresentation),
297cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
298cdf0e10cSrcweir }
299cdf0e10cSrcweir break;
300cdf0e10cSrcweir default:
301cdf0e10cSrcweir throw css::uno::RuntimeException(
302cdf0e10cSrcweir (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
303cdf0e10cSrcweir pathRepresentation),
304cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
305cdf0e10cSrcweir }
306cdf0e10cSrcweir if (templateName.getLength() != 0 && p != 0) {
307cdf0e10cSrcweir OSL_ASSERT(p->getTemplateName().getLength() != 0);
308cdf0e10cSrcweir if (!equalTemplateNames(templateName, p->getTemplateName())) {
309cdf0e10cSrcweir throw css::uno::RuntimeException(
310cdf0e10cSrcweir (rtl::OUString(
311cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("bad path ")) +
312cdf0e10cSrcweir pathRepresentation),
313cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
314cdf0e10cSrcweir }
315cdf0e10cSrcweir }
316cdf0e10cSrcweir }
317cdf0e10cSrcweir }
318cdf0e10cSrcweir }
319cdf0e10cSrcweir
getTemplate(int layer,rtl::OUString const & fullName) const320cdf0e10cSrcweir rtl::Reference< Node > Data::getTemplate(
321cdf0e10cSrcweir int layer, rtl::OUString const & fullName) const
322cdf0e10cSrcweir {
323cdf0e10cSrcweir return findNode(layer, templates, fullName);
324cdf0e10cSrcweir }
325cdf0e10cSrcweir
addExtensionXcuAdditions(rtl::OUString const & url,int layer)326cdf0e10cSrcweir Additions * Data::addExtensionXcuAdditions(
327cdf0e10cSrcweir rtl::OUString const & url, int layer)
328cdf0e10cSrcweir {
329cdf0e10cSrcweir rtl::Reference< ExtensionXcu > item(new ExtensionXcu);
330cdf0e10cSrcweir ExtensionXcuAdditions::iterator i(
331cdf0e10cSrcweir extensionXcuAdditions_.insert(
332cdf0e10cSrcweir ExtensionXcuAdditions::value_type(
333cdf0e10cSrcweir url, rtl::Reference< ExtensionXcu >())).first);
334cdf0e10cSrcweir if (i->second.is()) {
335cdf0e10cSrcweir throw css::uno::RuntimeException(
336cdf0e10cSrcweir (rtl::OUString(
337cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM(
338cdf0e10cSrcweir "already added extension xcu ")) +
339cdf0e10cSrcweir url),
340cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
341cdf0e10cSrcweir }
342cdf0e10cSrcweir i->second = item;
343cdf0e10cSrcweir item->layer = layer;
344cdf0e10cSrcweir return &item->additions;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir
removeExtensionXcuAdditions(rtl::OUString const & url)347cdf0e10cSrcweir rtl::Reference< Data::ExtensionXcu > Data::removeExtensionXcuAdditions(
348cdf0e10cSrcweir rtl::OUString const & url)
349cdf0e10cSrcweir {
350cdf0e10cSrcweir ExtensionXcuAdditions::iterator i(extensionXcuAdditions_.find(url));
351cdf0e10cSrcweir if (i == extensionXcuAdditions_.end()) {
352cdf0e10cSrcweir // This can happen, as migration of pre OOo 3.3 UserInstallation
353cdf0e10cSrcweir // extensions in dp_registry::backend::configuration::BackendImpl::
354cdf0e10cSrcweir // PackageImpl::processPackage_ can cause just-in-time creation of
355cdf0e10cSrcweir // extension xcu files that are never added via addExtensionXcuAdditions
356cdf0e10cSrcweir // (also, there might be url spelling differences between calls to
357cdf0e10cSrcweir // addExtensionXcuAdditions and removeExtensionXcuAdditions?):
358cdf0e10cSrcweir OSL_TRACE(
359cdf0e10cSrcweir "unknown configmgr::Data::removeExtensionXcuAdditions(%s)",
360cdf0e10cSrcweir rtl::OUStringToOString(url, RTL_TEXTENCODING_UTF8).getStr());
361cdf0e10cSrcweir return rtl::Reference< ExtensionXcu >();
362cdf0e10cSrcweir }
363cdf0e10cSrcweir rtl::Reference< ExtensionXcu > item(i->second);
364cdf0e10cSrcweir extensionXcuAdditions_.erase(i);
365cdf0e10cSrcweir return item;
366cdf0e10cSrcweir }
367cdf0e10cSrcweir
368cdf0e10cSrcweir }
369