1*3a7cf181SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 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 10cdf0e10cSrcweir * 11*3a7cf181SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 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. 19cdf0e10cSrcweir * 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 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 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 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 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 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 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 205cdf0e10cSrcweir 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 320cdf0e10cSrcweir rtl::Reference< Node > Data::getTemplate( 321cdf0e10cSrcweir int layer, rtl::OUString const & fullName) const 322cdf0e10cSrcweir { 323cdf0e10cSrcweir return findNode(layer, templates, fullName); 324cdf0e10cSrcweir } 325cdf0e10cSrcweir 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 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