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