diff options
author | Stephan Bergmann <sb@openoffice.org> | 2002-10-02 14:31:56 +0000 |
---|---|---|
committer | Stephan Bergmann <sb@openoffice.org> | 2002-10-02 14:31:56 +0000 |
commit | b1b9fbb8364cb35200b199ef17c411ba3cab4ed8 (patch) | |
tree | c1bb42c5370f582f07ed7b5e35c85b1c0a4c958b | |
parent | 86cb443a84e27ad8534860040b69103aa306ac28 (diff) |
#99853#
-rw-r--r-- | cppuhelper/inc/cppuhelper/unourl.hxx | 226 | ||||
-rw-r--r-- | cppuhelper/qa/sce/test_unourl.sce | 1 | ||||
-rw-r--r-- | cppuhelper/source/unourl.cxx | 329 |
3 files changed, 556 insertions, 0 deletions
diff --git a/cppuhelper/inc/cppuhelper/unourl.hxx b/cppuhelper/inc/cppuhelper/unourl.hxx new file mode 100644 index 000000000000..2ea9fed85785 --- /dev/null +++ b/cppuhelper/inc/cppuhelper/unourl.hxx @@ -0,0 +1,226 @@ +/************************************************************************* + * + * $RCSfile: unourl.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: sb $ $Date: 2002-10-02 15:27:47 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2002 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#if !defined INCLUDED_CPPUHELPER_UNOURL_HXX +#define INCLUDED_CPPUHELPER_UNOURL_HXX + +#include <memory> + +namespace rtl { class OUString; } + +namespace cppu { + +/** A descriptor as part of a UNO URL (connection descriptor or protocol + descriptor). + + Such a descriptor can also be useful outside the context of a full UNO URL. + For example, some functions take a string representing a connection or + protocol descriptor as input, and can use this class to parse the string. + */ +class UnoUrlDescriptor +{ +public: + /** @internal + */ + class Impl; + + /** Construct a descriptor from a string representation. + + @param rDescriptor + The string representation of a descriptor. + + @exception rtl::MalformedUriException + Thrown when the given string representation is invalid. + */ + explicit UnoUrlDescriptor(rtl::OUString const & rDescriptor); + + /** @internal + */ + explicit UnoUrlDescriptor(std::auto_ptr< Impl > & rImpl); + + UnoUrlDescriptor(UnoUrlDescriptor const & rOther); + + ~UnoUrlDescriptor(); + + UnoUrlDescriptor & operator =(UnoUrlDescriptor const & rOther); + + /** Return the string representation of the descriptor. + + @return + A reference to the string representation used to construct this + descriptor, without any modifications. The reference is valid for the + lifetime of this URL object. + */ + rtl::OUString const & getDescriptor() const; + + /** Return the name component of the descriptor. + + @return + A reference to the (case insensitive) name, in lower case form. The + reference is valid for the lifetime of this URL object. + */ + rtl::OUString const & getName() const; + + /** Test whether the parameters contain a key. + + @param + A (case insensitive) key. + + @return + True if the parameters contain a matching key/value pair. + */ + bool hasParameter(rtl::OUString const & rKey) const; + + /** Return the parameter value for a key. + + @param + A (case insensitive) key. + + @return + The (case sensitive) value associated with the given key, or an empty + string if there is no matching key/value pair. + */ + rtl::OUString getParameter(rtl::OUString const & rKey) const; + +private: + std::auto_ptr< Impl > m_xImpl; +}; + +/** Parse UNO URLs into their components. + + The ABNF for UNO URLs is as follows (see RFCs 2234, 2396, also see + <http://udk.openoffice.org/common/man/spec/uno-url.html>): + + uno-url = "UNO:" connection ";" protocol ";" object-name + connection = descriptor + protocol = descriptor + descriptor = name *("," parameter) + name = 1*alphanum + parameter = key "=" value + key = 1*alphanum + value = *vchar + valchar = unreserved / escaped / "$" / "&" / "+" / "/" / ":" / "?" / "@" + object-name = 1*ochar + ochar = unreserved / "$" / "&" / "+" / "," / "/" / ":" / "=" / "?" / "@" + + Within a descriptor, the name and the keys are case insensitive, and within + the parameter list all keys must be distinct. + + Parameter values are encoded using UTF-8. Note that parsing of parameter + values as done by UnoUrl and UnoUrlDescriptor is not strict: Invalid UTF-16 + entities in the input, as well as broken escape sequences ("%" not followed + by two hex digits) are copied verbatim to the output, invalid bytes in the + converted UTF-8 data are considered individual Unicode characters, and + invalid UTF-16 entities in the resulting output (e.g., a high surrogate not + followed by a low surrogate) are not detected. + */ +class UnoUrl +{ +public: + /** Construct a UNO URL from a string representation. + + @param rUrl + The string representation of a UNO URL. + + @exception rtl::MalformedUriException + Thrown when the given string representation is invalid. + */ + explicit UnoUrl(rtl::OUString const & rUrl); + + UnoUrl(UnoUrl const & rOther); + + ~UnoUrl(); + + UnoUrl & operator =(UnoUrl const & rOther); + + /** Return the connection descriptor component of the URL. + + @return + A reference to the connection descriptor. The reference is valid for + the lifetime of this URL object. + */ + UnoUrlDescriptor const & getConnection() const; + + /** Return the protocol descriptor component of the URL. + + @return + A reference to the protocol descriptor. The reference is valid for the + lifetime of this URL object. + */ + UnoUrlDescriptor const & getProtocol() const; + + /** Return the object-name component of the URL. + + @return + A reference to the (case sensitive) object-name. The reference is valid + for the lifetime of this URL object. + */ + rtl::OUString const & getObjectName() const; + +private: + class Impl; + + std::auto_ptr< Impl > m_xImpl; +}; + +} + +#endif // INCLUDED_RTL_UNOURL_HXX diff --git a/cppuhelper/qa/sce/test_unourl.sce b/cppuhelper/qa/sce/test_unourl.sce new file mode 100644 index 000000000000..d937ca31161d --- /dev/null +++ b/cppuhelper/qa/sce/test_unourl.sce @@ -0,0 +1 @@ +UnoUrl diff --git a/cppuhelper/source/unourl.cxx b/cppuhelper/source/unourl.cxx new file mode 100644 index 000000000000..d8c2c22c6f47 --- /dev/null +++ b/cppuhelper/source/unourl.cxx @@ -0,0 +1,329 @@ +/************************************************************************* + * + * $RCSfile: unourl.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: sb $ $Date: 2002-10-02 15:31:56 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2002 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include "cppuhelper/unourl.hxx" + +#include "osl/diagnose.h" +#include "rtl/malformeduriexception.hxx" +#include "rtl/string.h" +#include "rtl/textenc.h" +#include "rtl/uri.h" +#include "rtl/uri.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <map> + +using cppu::UnoUrl; +using cppu::UnoUrlDescriptor; + +namespace { + +inline bool isAlphanum(sal_Unicode c) +{ + return c >= 0x30 && c <= 0x39 // '0'--'9' + || c >= 0x41 && c <= 0x5A // 'A'--'Z' + || c >= 0x61 && c <= 0x7A; // 'a'--'z' +} + +} + +class UnoUrlDescriptor::Impl +{ +public: + typedef std::map< rtl::OUString, rtl::OUString > Parameters; + + rtl::OUString m_aDescriptor; + rtl::OUString m_aName; + Parameters m_aParameters; + + /** @exception rtl::MalformedUriException + */ + explicit inline Impl(rtl::OUString const & m_aDescriptor); + + inline Impl * clone() const { return new Impl(*this); } +}; + +inline UnoUrlDescriptor::Impl::Impl(rtl::OUString const & rDescriptor) +{ + m_aDescriptor = rDescriptor; + enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE }; + State eState = STATE_NAME0; + sal_Int32 nStart; + rtl::OUString aKey; + for (sal_Int32 i = 0;; ++i) + { + bool bEnd = i == rDescriptor.getLength(); + sal_Unicode c = bEnd ? 0 : rDescriptor.getStr()[i]; + switch (eState) + { + case STATE_NAME0: + if (bEnd || !isAlphanum(c)) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL contains bad descriptor name"))); + nStart = i; + eState = STATE_NAME; + break; + + case STATE_NAME: + if (bEnd || c == 0x2C) // ',' + { + m_aName + = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase(); + eState = STATE_KEY0; + } + else if (!isAlphanum(c)) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL contains bad descriptor name"))); + break; + + case STATE_KEY0: + if (bEnd || !isAlphanum(c)) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL contains bad parameter key"))); + nStart = i; + eState = STATE_KEY; + break; + + case STATE_KEY: + if (c == 0x3D) // '=' + { + aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase(); + nStart = i + 1; + eState = STATE_VALUE; + } + else if (bEnd || !isAlphanum(c)) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL contains bad parameter key"))); + break; + + case STATE_VALUE: + if (bEnd || c == 0x2C) // ',' + { + if (!m_aParameters.insert( + Parameters::value_type( + aKey, + rtl::Uri::decode(rDescriptor.copy(nStart, + i - nStart), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8))).second) + throw rtl::MalformedUriException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "UNO URL contains duplicated parameter"))); + eState = STATE_KEY0; + } + break; + } + if (bEnd) + break; + } +} + +UnoUrlDescriptor::UnoUrlDescriptor(rtl::OUString const & rDescriptor): + m_xImpl(new Impl(rDescriptor)) +{} + +UnoUrlDescriptor::UnoUrlDescriptor(std::auto_ptr< Impl > & rImpl): + m_xImpl(rImpl) +{} + +UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther): + m_xImpl(rOther.m_xImpl->clone()) +{} + +UnoUrlDescriptor::~UnoUrlDescriptor() +{} + +UnoUrlDescriptor & UnoUrlDescriptor::operator =(UnoUrlDescriptor const & rOther) +{ + m_xImpl.reset(rOther.m_xImpl->clone()); + return *this; +} + +rtl::OUString const & UnoUrlDescriptor::getDescriptor() const +{ + return m_xImpl->m_aDescriptor; +} + +rtl::OUString const & UnoUrlDescriptor::getName() const +{ + return m_xImpl->m_aName; +} + +bool UnoUrlDescriptor::hasParameter(rtl::OUString const & rKey) const +{ + return m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase()) + != m_xImpl->m_aParameters.end(); +} + +rtl::OUString UnoUrlDescriptor::getParameter(rtl::OUString const & rKey) const +{ + Impl::Parameters::const_iterator + aIt(m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase())); + return aIt == m_xImpl->m_aParameters.end() ? rtl::OUString() : aIt->second; +} + +class UnoUrl::Impl +{ +public: + UnoUrlDescriptor m_aConnection; + UnoUrlDescriptor m_aProtocol; + rtl::OUString m_aObjectName; + + inline Impl * clone() const { return new Impl(*this); } + + /** @exception rtl::MalformedUriException + */ + static inline Impl * create(rtl::OUString const & rUrl); + +private: + inline Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection, + std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol, + rtl::OUString const & rObjectName); +}; + +inline UnoUrl::Impl::Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection, + std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol, + rtl::OUString const & rObjectName): + m_aConnection(rConnection), + m_aProtocol(rProtocol), + m_aObjectName(rObjectName) +{} + +inline UnoUrl::Impl * UnoUrl::Impl::create(rtl::OUString const & rUrl) +{ + if (!rUrl.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("uno:"), 0)) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL does not start with \"uno:\""))); + sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:"); + sal_Int32 j = rUrl.indexOf(';', i); + if (j < 0) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL has too few semicolons"))); + std::auto_ptr< UnoUrlDescriptor::Impl > + xConnection(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i))); + i = j + 1; + j = rUrl.indexOf(0x3B, i); // ';' + if (j < 0) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL has too few semicolons"))); + std::auto_ptr< UnoUrlDescriptor::Impl > + xProtocol(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i))); + i = j + 1; + if (i == rUrl.getLength()) + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL contains empty ObjectName"))); + for (j = i; j < rUrl.getLength(); ++j) + { + sal_Unicode c = rUrl.getStr()[j]; + if (!isAlphanum(c) && c != 0x21 && c != 0x24 // '!', '$' + && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '(' + && c != 0x28 && c != 0x2A && c != 0x2B // ')', '*', '+' + && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.' + && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '=' + && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_' + && c != 0x7E) // '~' + throw rtl::MalformedUriException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "UNO URL contains invalid ObjectName"))); + } + return new Impl(xConnection, xProtocol, rUrl.copy(i)); +} + +UnoUrl::UnoUrl(rtl::OUString const & rUrl): m_xImpl(Impl::create(rUrl)) +{} + +UnoUrl::UnoUrl(UnoUrl const & rOther): m_xImpl(rOther.m_xImpl->clone()) +{} + +UnoUrl::~UnoUrl() +{} + +UnoUrl & UnoUrl::operator =(UnoUrl const & rOther) +{ + m_xImpl.reset(rOther.m_xImpl->clone()); + return *this; +} + +UnoUrlDescriptor const & UnoUrl::getConnection() const +{ + return m_xImpl->m_aConnection; +} + +UnoUrlDescriptor const & UnoUrl::getProtocol() const +{ + return m_xImpl->m_aProtocol; +} + +rtl::OUString const & UnoUrl::getObjectName() const +{ + return m_xImpl->m_aObjectName; +} |