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 // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_cppuhelper.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include "cppuhelper/unourl.hxx" 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include "osl/diagnose.h" 34*cdf0e10cSrcweir #include "rtl/malformeduriexception.hxx" 35*cdf0e10cSrcweir #include "rtl/string.h" 36*cdf0e10cSrcweir #include "rtl/textenc.h" 37*cdf0e10cSrcweir #include "rtl/uri.h" 38*cdf0e10cSrcweir #include "rtl/uri.hxx" 39*cdf0e10cSrcweir #include "rtl/ustring.h" 40*cdf0e10cSrcweir #include "rtl/ustring.hxx" 41*cdf0e10cSrcweir #include "sal/types.h" 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir #include <map> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir using cppu::UnoUrl; 46*cdf0e10cSrcweir using cppu::UnoUrlDescriptor; 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir namespace { 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir inline bool isAlphanum(sal_Unicode c) 51*cdf0e10cSrcweir { 52*cdf0e10cSrcweir return (c >= 0x30 && c <= 0x39) // '0'--'9' 53*cdf0e10cSrcweir || (c >= 0x41 && c <= 0x5A) // 'A'--'Z' 54*cdf0e10cSrcweir || (c >= 0x61 && c <= 0x7A); // 'a'--'z' 55*cdf0e10cSrcweir } 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir } 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir class UnoUrlDescriptor::Impl 60*cdf0e10cSrcweir { 61*cdf0e10cSrcweir public: 62*cdf0e10cSrcweir typedef std::map< rtl::OUString, rtl::OUString > Parameters; 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir rtl::OUString m_aDescriptor; 65*cdf0e10cSrcweir rtl::OUString m_aName; 66*cdf0e10cSrcweir Parameters m_aParameters; 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir /** @exception rtl::MalformedUriException 69*cdf0e10cSrcweir */ 70*cdf0e10cSrcweir explicit inline Impl(rtl::OUString const & m_aDescriptor); 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir inline Impl * clone() const { return new Impl(*this); } 73*cdf0e10cSrcweir }; 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir inline UnoUrlDescriptor::Impl::Impl(rtl::OUString const & rDescriptor) 76*cdf0e10cSrcweir { 77*cdf0e10cSrcweir m_aDescriptor = rDescriptor; 78*cdf0e10cSrcweir enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE }; 79*cdf0e10cSrcweir State eState = STATE_NAME0; 80*cdf0e10cSrcweir sal_Int32 nStart = 0; 81*cdf0e10cSrcweir rtl::OUString aKey; 82*cdf0e10cSrcweir for (sal_Int32 i = 0;; ++i) 83*cdf0e10cSrcweir { 84*cdf0e10cSrcweir bool bEnd = i == rDescriptor.getLength(); 85*cdf0e10cSrcweir sal_Unicode c = bEnd ? 0 : rDescriptor.getStr()[i]; 86*cdf0e10cSrcweir switch (eState) 87*cdf0e10cSrcweir { 88*cdf0e10cSrcweir case STATE_NAME0: 89*cdf0e10cSrcweir if (bEnd || !isAlphanum(c)) 90*cdf0e10cSrcweir throw rtl::MalformedUriException( 91*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 92*cdf0e10cSrcweir "UNO URL contains bad descriptor name"))); 93*cdf0e10cSrcweir nStart = i; 94*cdf0e10cSrcweir eState = STATE_NAME; 95*cdf0e10cSrcweir break; 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir case STATE_NAME: 98*cdf0e10cSrcweir if (bEnd || c == 0x2C) // ',' 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir m_aName 101*cdf0e10cSrcweir = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase(); 102*cdf0e10cSrcweir eState = STATE_KEY0; 103*cdf0e10cSrcweir } 104*cdf0e10cSrcweir else if (!isAlphanum(c)) 105*cdf0e10cSrcweir throw rtl::MalformedUriException( 106*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 107*cdf0e10cSrcweir "UNO URL contains bad descriptor name"))); 108*cdf0e10cSrcweir break; 109*cdf0e10cSrcweir 110*cdf0e10cSrcweir case STATE_KEY0: 111*cdf0e10cSrcweir if (bEnd || !isAlphanum(c)) 112*cdf0e10cSrcweir throw rtl::MalformedUriException( 113*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 114*cdf0e10cSrcweir "UNO URL contains bad parameter key"))); 115*cdf0e10cSrcweir nStart = i; 116*cdf0e10cSrcweir eState = STATE_KEY; 117*cdf0e10cSrcweir break; 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir case STATE_KEY: 120*cdf0e10cSrcweir if (c == 0x3D) // '=' 121*cdf0e10cSrcweir { 122*cdf0e10cSrcweir aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase(); 123*cdf0e10cSrcweir nStart = i + 1; 124*cdf0e10cSrcweir eState = STATE_VALUE; 125*cdf0e10cSrcweir } 126*cdf0e10cSrcweir else if (bEnd || !isAlphanum(c)) 127*cdf0e10cSrcweir throw rtl::MalformedUriException( 128*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 129*cdf0e10cSrcweir "UNO URL contains bad parameter key"))); 130*cdf0e10cSrcweir break; 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir case STATE_VALUE: 133*cdf0e10cSrcweir if (bEnd || c == 0x2C) // ',' 134*cdf0e10cSrcweir { 135*cdf0e10cSrcweir if (!m_aParameters.insert( 136*cdf0e10cSrcweir Parameters::value_type( 137*cdf0e10cSrcweir aKey, 138*cdf0e10cSrcweir rtl::Uri::decode(rDescriptor.copy(nStart, 139*cdf0e10cSrcweir i - nStart), 140*cdf0e10cSrcweir rtl_UriDecodeWithCharset, 141*cdf0e10cSrcweir RTL_TEXTENCODING_UTF8))).second) 142*cdf0e10cSrcweir throw rtl::MalformedUriException( 143*cdf0e10cSrcweir rtl::OUString( 144*cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( 145*cdf0e10cSrcweir "UNO URL contains duplicated parameter"))); 146*cdf0e10cSrcweir eState = STATE_KEY0; 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir break; 149*cdf0e10cSrcweir } 150*cdf0e10cSrcweir if (bEnd) 151*cdf0e10cSrcweir break; 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir } 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(rtl::OUString const & rDescriptor): 156*cdf0e10cSrcweir m_xImpl(new Impl(rDescriptor)) 157*cdf0e10cSrcweir {} 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(std::auto_ptr< Impl > & rImpl): 160*cdf0e10cSrcweir m_xImpl(rImpl) 161*cdf0e10cSrcweir {} 162*cdf0e10cSrcweir 163*cdf0e10cSrcweir UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther): 164*cdf0e10cSrcweir m_xImpl(rOther.m_xImpl->clone()) 165*cdf0e10cSrcweir {} 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir UnoUrlDescriptor::~UnoUrlDescriptor() 168*cdf0e10cSrcweir {} 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir UnoUrlDescriptor & UnoUrlDescriptor::operator =(UnoUrlDescriptor const & rOther) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir m_xImpl.reset(rOther.m_xImpl->clone()); 173*cdf0e10cSrcweir return *this; 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir rtl::OUString const & UnoUrlDescriptor::getDescriptor() const 177*cdf0e10cSrcweir { 178*cdf0e10cSrcweir return m_xImpl->m_aDescriptor; 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir rtl::OUString const & UnoUrlDescriptor::getName() const 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir return m_xImpl->m_aName; 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir bool UnoUrlDescriptor::hasParameter(rtl::OUString const & rKey) const 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir return m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase()) 189*cdf0e10cSrcweir != m_xImpl->m_aParameters.end(); 190*cdf0e10cSrcweir } 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir rtl::OUString UnoUrlDescriptor::getParameter(rtl::OUString const & rKey) const 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir Impl::Parameters::const_iterator 195*cdf0e10cSrcweir aIt(m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase())); 196*cdf0e10cSrcweir return aIt == m_xImpl->m_aParameters.end() ? rtl::OUString() : aIt->second; 197*cdf0e10cSrcweir } 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir class UnoUrl::Impl 200*cdf0e10cSrcweir { 201*cdf0e10cSrcweir public: 202*cdf0e10cSrcweir UnoUrlDescriptor m_aConnection; 203*cdf0e10cSrcweir UnoUrlDescriptor m_aProtocol; 204*cdf0e10cSrcweir rtl::OUString m_aObjectName; 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir inline Impl * clone() const { return new Impl(*this); } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir /** @exception rtl::MalformedUriException 209*cdf0e10cSrcweir */ 210*cdf0e10cSrcweir static inline Impl * create(rtl::OUString const & rUrl); 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir private: 213*cdf0e10cSrcweir inline Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection, 214*cdf0e10cSrcweir std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol, 215*cdf0e10cSrcweir rtl::OUString const & rObjectName); 216*cdf0e10cSrcweir }; 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir inline UnoUrl::Impl::Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection, 219*cdf0e10cSrcweir std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol, 220*cdf0e10cSrcweir rtl::OUString const & rObjectName): 221*cdf0e10cSrcweir m_aConnection(rConnection), 222*cdf0e10cSrcweir m_aProtocol(rProtocol), 223*cdf0e10cSrcweir m_aObjectName(rObjectName) 224*cdf0e10cSrcweir {} 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir inline UnoUrl::Impl * UnoUrl::Impl::create(rtl::OUString const & rUrl) 227*cdf0e10cSrcweir { 228*cdf0e10cSrcweir if (!rUrl.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("uno:"), 0)) 229*cdf0e10cSrcweir throw rtl::MalformedUriException( 230*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 231*cdf0e10cSrcweir "UNO URL does not start with \"uno:\""))); 232*cdf0e10cSrcweir sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:"); 233*cdf0e10cSrcweir sal_Int32 j = rUrl.indexOf(';', i); 234*cdf0e10cSrcweir if (j < 0) 235*cdf0e10cSrcweir throw rtl::MalformedUriException( 236*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 237*cdf0e10cSrcweir "UNO URL has too few semicolons"))); 238*cdf0e10cSrcweir std::auto_ptr< UnoUrlDescriptor::Impl > 239*cdf0e10cSrcweir xConnection(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i))); 240*cdf0e10cSrcweir i = j + 1; 241*cdf0e10cSrcweir j = rUrl.indexOf(0x3B, i); // ';' 242*cdf0e10cSrcweir if (j < 0) 243*cdf0e10cSrcweir throw rtl::MalformedUriException( 244*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 245*cdf0e10cSrcweir "UNO URL has too few semicolons"))); 246*cdf0e10cSrcweir std::auto_ptr< UnoUrlDescriptor::Impl > 247*cdf0e10cSrcweir xProtocol(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i))); 248*cdf0e10cSrcweir i = j + 1; 249*cdf0e10cSrcweir if (i == rUrl.getLength()) 250*cdf0e10cSrcweir throw rtl::MalformedUriException( 251*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 252*cdf0e10cSrcweir "UNO URL contains empty ObjectName"))); 253*cdf0e10cSrcweir for (j = i; j < rUrl.getLength(); ++j) 254*cdf0e10cSrcweir { 255*cdf0e10cSrcweir sal_Unicode c = rUrl.getStr()[j]; 256*cdf0e10cSrcweir if (!isAlphanum(c) && c != 0x21 && c != 0x24 // '!', '$' 257*cdf0e10cSrcweir && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '(' 258*cdf0e10cSrcweir && c != 0x28 && c != 0x2A && c != 0x2B // ')', '*', '+' 259*cdf0e10cSrcweir && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.' 260*cdf0e10cSrcweir && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '=' 261*cdf0e10cSrcweir && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_' 262*cdf0e10cSrcweir && c != 0x7E) // '~' 263*cdf0e10cSrcweir throw rtl::MalformedUriException( 264*cdf0e10cSrcweir rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 265*cdf0e10cSrcweir "UNO URL contains invalid ObjectName"))); 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir return new Impl(xConnection, xProtocol, rUrl.copy(i)); 268*cdf0e10cSrcweir } 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir UnoUrl::UnoUrl(rtl::OUString const & rUrl): m_xImpl(Impl::create(rUrl)) 271*cdf0e10cSrcweir {} 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir UnoUrl::UnoUrl(UnoUrl const & rOther): m_xImpl(rOther.m_xImpl->clone()) 274*cdf0e10cSrcweir {} 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir UnoUrl::~UnoUrl() 277*cdf0e10cSrcweir {} 278*cdf0e10cSrcweir 279*cdf0e10cSrcweir UnoUrl & UnoUrl::operator =(UnoUrl const & rOther) 280*cdf0e10cSrcweir { 281*cdf0e10cSrcweir m_xImpl.reset(rOther.m_xImpl->clone()); 282*cdf0e10cSrcweir return *this; 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir 285*cdf0e10cSrcweir UnoUrlDescriptor const & UnoUrl::getConnection() const 286*cdf0e10cSrcweir { 287*cdf0e10cSrcweir return m_xImpl->m_aConnection; 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir UnoUrlDescriptor const & UnoUrl::getProtocol() const 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir return m_xImpl->m_aProtocol; 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir rtl::OUString const & UnoUrl::getObjectName() const 296*cdf0e10cSrcweir { 297*cdf0e10cSrcweir return m_xImpl->m_aObjectName; 298*cdf0e10cSrcweir } 299