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_ucb.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir /************************************************************************** 32*cdf0e10cSrcweir TODO 33*cdf0e10cSrcweir ************************************************************************** 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir *************************************************************************/ 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir #include "rtl/ustrbuf.hxx" 38*cdf0e10cSrcweir #include "osl/diagnose.h" 39*cdf0e10cSrcweir #include "comphelper/storagehelper.hxx" 40*cdf0e10cSrcweir 41*cdf0e10cSrcweir #include "../inc/urihelper.hxx" 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir #include "pkguri.hxx" 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir using namespace package_ucp; 46*cdf0e10cSrcweir using namespace rtl; 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir //========================================================================= 49*cdf0e10cSrcweir //========================================================================= 50*cdf0e10cSrcweir // 51*cdf0e10cSrcweir // PackageUri Implementation. 52*cdf0e10cSrcweir // 53*cdf0e10cSrcweir //========================================================================= 54*cdf0e10cSrcweir //========================================================================= 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir static void normalize( OUString& rURL ) 57*cdf0e10cSrcweir { 58*cdf0e10cSrcweir sal_Int32 nPos = 0; 59*cdf0e10cSrcweir do 60*cdf0e10cSrcweir { 61*cdf0e10cSrcweir nPos = rURL.indexOf( '%', nPos ); 62*cdf0e10cSrcweir if ( nPos != -1 ) 63*cdf0e10cSrcweir { 64*cdf0e10cSrcweir if ( nPos < ( rURL.getLength() - 2 ) ) 65*cdf0e10cSrcweir { 66*cdf0e10cSrcweir OUString aTmp = rURL.copy( nPos + 1, 2 ); 67*cdf0e10cSrcweir rURL = rURL.replaceAt( nPos + 1, 2, aTmp.toAsciiUpperCase() ); 68*cdf0e10cSrcweir nPos++; 69*cdf0e10cSrcweir } 70*cdf0e10cSrcweir } 71*cdf0e10cSrcweir } 72*cdf0e10cSrcweir while ( nPos != -1 ); 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir //========================================================================= 76*cdf0e10cSrcweir void PackageUri::init() const 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir // Already inited? 79*cdf0e10cSrcweir if ( m_aUri.getLength() && !m_aPath.getLength() ) 80*cdf0e10cSrcweir { 81*cdf0e10cSrcweir // Note: Maybe it's a re-init, setUri only resets m_aPath! 82*cdf0e10cSrcweir m_aPackage = m_aParentUri = m_aName = m_aParam = m_aScheme 83*cdf0e10cSrcweir = OUString(); 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir // URI must match at least: <sheme>://<non_empty_url_to_file> 86*cdf0e10cSrcweir if ( ( m_aUri.getLength() < PACKAGE_URL_SCHEME_LENGTH + 4 ) ) 87*cdf0e10cSrcweir { 88*cdf0e10cSrcweir // error, but remember that we did a init(). 89*cdf0e10cSrcweir m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 90*cdf0e10cSrcweir return; 91*cdf0e10cSrcweir } 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir // Scheme must be followed by '://' 94*cdf0e10cSrcweir if ( ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH ] 95*cdf0e10cSrcweir != sal_Unicode( ':' ) ) 96*cdf0e10cSrcweir || 97*cdf0e10cSrcweir ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 1 ] 98*cdf0e10cSrcweir != sal_Unicode( '/' ) ) 99*cdf0e10cSrcweir || 100*cdf0e10cSrcweir ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 2 ] 101*cdf0e10cSrcweir != sal_Unicode( '/' ) ) ) 102*cdf0e10cSrcweir { 103*cdf0e10cSrcweir // error, but remember that we did a init(). 104*cdf0e10cSrcweir m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 105*cdf0e10cSrcweir return; 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir rtl::OUString aPureUri; 109*cdf0e10cSrcweir sal_Int32 nParam = m_aUri.indexOf( '?' ); 110*cdf0e10cSrcweir if( nParam >= 0 ) 111*cdf0e10cSrcweir { 112*cdf0e10cSrcweir m_aParam = m_aUri.copy( nParam ); 113*cdf0e10cSrcweir aPureUri = m_aUri.copy( 0, nParam ); 114*cdf0e10cSrcweir } 115*cdf0e10cSrcweir else 116*cdf0e10cSrcweir aPureUri = m_aUri; 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir // Scheme is case insensitive. 119*cdf0e10cSrcweir m_aScheme = aPureUri.copy( 120*cdf0e10cSrcweir 0, PACKAGE_URL_SCHEME_LENGTH ).toAsciiLowerCase(); 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir if ( m_aScheme.equalsAsciiL( 123*cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( PACKAGE_URL_SCHEME ) ) 124*cdf0e10cSrcweir || m_aScheme.equalsAsciiL( 125*cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_URL_SCHEME ) ) ) 126*cdf0e10cSrcweir { 127*cdf0e10cSrcweir if ( m_aScheme.equalsAsciiL( 128*cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_URL_SCHEME ) ) ) 129*cdf0e10cSrcweir { 130*cdf0e10cSrcweir m_aParam += 131*cdf0e10cSrcweir ( m_aParam.getLength() 132*cdf0e10cSrcweir ? ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "&purezip" ) ) 133*cdf0e10cSrcweir : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "?purezip" ) ) ); 134*cdf0e10cSrcweir } 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir aPureUri = aPureUri.replaceAt( 0, 137*cdf0e10cSrcweir m_aScheme.getLength(), 138*cdf0e10cSrcweir m_aScheme ); 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir sal_Int32 nStart = PACKAGE_URL_SCHEME_LENGTH + 3; 141*cdf0e10cSrcweir sal_Int32 nEnd = aPureUri.lastIndexOf( '/' ); 142*cdf0e10cSrcweir if ( nEnd == PACKAGE_URL_SCHEME_LENGTH + 3 ) 143*cdf0e10cSrcweir { 144*cdf0e10cSrcweir // Only <scheme>:/// - Empty authority 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir // error, but remember that we did a init(). 147*cdf0e10cSrcweir m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 148*cdf0e10cSrcweir return; 149*cdf0e10cSrcweir } 150*cdf0e10cSrcweir else if ( nEnd == ( aPureUri.getLength() - 1 ) ) 151*cdf0e10cSrcweir { 152*cdf0e10cSrcweir if ( aPureUri.getStr()[ aPureUri.getLength() - 2 ] 153*cdf0e10cSrcweir == sal_Unicode( '/' ) ) 154*cdf0e10cSrcweir { 155*cdf0e10cSrcweir // Only <scheme>://// or <scheme>://<something>// 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir // error, but remember that we did a init(). 158*cdf0e10cSrcweir m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 159*cdf0e10cSrcweir return; 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir // Remove trailing slash. 163*cdf0e10cSrcweir aPureUri = aPureUri.copy( 0, nEnd ); 164*cdf0e10cSrcweir } 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir nEnd = aPureUri.indexOf( '/', nStart ); 168*cdf0e10cSrcweir if ( nEnd == -1 ) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir // root folder. 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir OUString aNormPackage = aPureUri.copy( nStart ); 173*cdf0e10cSrcweir normalize( aNormPackage ); 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir aPureUri = aPureUri.replaceAt( 176*cdf0e10cSrcweir nStart, aPureUri.getLength() - nStart, aNormPackage ); 177*cdf0e10cSrcweir m_aPackage 178*cdf0e10cSrcweir = ::ucb_impl::urihelper::decodeSegment( aNormPackage ); 179*cdf0e10cSrcweir m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 180*cdf0e10cSrcweir m_aUri = m_aUri.replaceAt( 0, 181*cdf0e10cSrcweir ( nParam >= 0 ) 182*cdf0e10cSrcweir ? nParam 183*cdf0e10cSrcweir : m_aUri.getLength(), aPureUri ); 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir sal_Int32 nLastSlash = m_aPackage.lastIndexOf( '/' ); 186*cdf0e10cSrcweir if ( nLastSlash != -1 ) 187*cdf0e10cSrcweir m_aName = ::ucb_impl::urihelper::decodeSegment( 188*cdf0e10cSrcweir m_aPackage.copy( nLastSlash + 1 ) ); 189*cdf0e10cSrcweir else 190*cdf0e10cSrcweir m_aName 191*cdf0e10cSrcweir = ::ucb_impl::urihelper::decodeSegment( m_aPackage ); 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir else 194*cdf0e10cSrcweir { 195*cdf0e10cSrcweir m_aPath = aPureUri.copy( nEnd + 1 ); 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir // Unexpected sequences of characters: 198*cdf0e10cSrcweir // - empty path segments 199*cdf0e10cSrcweir // - encoded slashes 200*cdf0e10cSrcweir // - parent folder segments ".." 201*cdf0e10cSrcweir // - current folder segments "." 202*cdf0e10cSrcweir if ( m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "//" ) ) ) != -1 203*cdf0e10cSrcweir || m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "%2F" ) ) ) != -1 204*cdf0e10cSrcweir || m_aPath.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "%2f" ) ) ) != -1 205*cdf0e10cSrcweir || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".." ) ) ) 206*cdf0e10cSrcweir || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ) ) 207*cdf0e10cSrcweir { 208*cdf0e10cSrcweir // error, but remember that we did a init(). 209*cdf0e10cSrcweir m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 210*cdf0e10cSrcweir return; 211*cdf0e10cSrcweir } 212*cdf0e10cSrcweir 213*cdf0e10cSrcweir OUString aNormPackage = aPureUri.copy( nStart, nEnd - nStart ); 214*cdf0e10cSrcweir normalize( aNormPackage ); 215*cdf0e10cSrcweir 216*cdf0e10cSrcweir aPureUri = aPureUri.replaceAt( 217*cdf0e10cSrcweir nStart, nEnd - nStart, aNormPackage ); 218*cdf0e10cSrcweir aPureUri = aPureUri.replaceAt( 219*cdf0e10cSrcweir nEnd + 1, 220*cdf0e10cSrcweir aPureUri.getLength() - nEnd - 1, 221*cdf0e10cSrcweir ::ucb_impl::urihelper::encodeURI( m_aPath ) ); 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir m_aPackage 224*cdf0e10cSrcweir = ::ucb_impl::urihelper::decodeSegment( aNormPackage ); 225*cdf0e10cSrcweir m_aPath = ::ucb_impl::urihelper::decodeSegment( m_aPath ); 226*cdf0e10cSrcweir m_aUri = m_aUri.replaceAt( 0, 227*cdf0e10cSrcweir ( nParam >= 0 ) 228*cdf0e10cSrcweir ? nParam 229*cdf0e10cSrcweir : m_aUri.getLength(), aPureUri ); 230*cdf0e10cSrcweir 231*cdf0e10cSrcweir sal_Int32 nLastSlash = aPureUri.lastIndexOf( '/' ); 232*cdf0e10cSrcweir if ( nLastSlash != -1 ) 233*cdf0e10cSrcweir { 234*cdf0e10cSrcweir m_aParentUri = aPureUri.copy( 0, nLastSlash ); 235*cdf0e10cSrcweir m_aName = ::ucb_impl::urihelper::decodeSegment( 236*cdf0e10cSrcweir aPureUri.copy( nLastSlash + 1 ) ); 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir } 239*cdf0e10cSrcweir 240*cdf0e10cSrcweir // success 241*cdf0e10cSrcweir m_bValid = true; 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir else 244*cdf0e10cSrcweir { 245*cdf0e10cSrcweir // error, but remember that we did a init(). 246*cdf0e10cSrcweir m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 247*cdf0e10cSrcweir } 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir } 250