Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : /**************************************************************************
31 : : TODO
32 : : **************************************************************************
33 : :
34 : : *************************************************************************/
35 : :
36 : : #include "rtl/ustrbuf.hxx"
37 : : #include "osl/diagnose.h"
38 : : #include "comphelper/storagehelper.hxx"
39 : :
40 : : #include "../inc/urihelper.hxx"
41 : :
42 : : #include "pkguri.hxx"
43 : :
44 : : using namespace package_ucp;
45 : :
46 : : using ::rtl::OUString;
47 : :
48 : : //=========================================================================
49 : : //=========================================================================
50 : : //
51 : : // PackageUri Implementation.
52 : : //
53 : : //=========================================================================
54 : : //=========================================================================
55 : :
56 : 820 : static void normalize( OUString& rURL )
57 : : {
58 : 820 : sal_Int32 nPos = 0;
59 [ + + ]: 14738 : do
60 : : {
61 : 14738 : nPos = rURL.indexOf( '%', nPos );
62 [ + + ]: 14738 : if ( nPos != -1 )
63 : : {
64 [ + - ]: 13918 : if ( nPos < ( rURL.getLength() - 2 ) )
65 : : {
66 : 13918 : OUString aTmp = rURL.copy( nPos + 1, 2 );
67 : 13918 : rURL = rURL.replaceAt( nPos + 1, 2, aTmp.toAsciiUpperCase() );
68 : 13918 : nPos++;
69 : : }
70 : : }
71 : : }
72 : : while ( nPos != -1 );
73 : 820 : }
74 : :
75 : : //=========================================================================
76 : 6400 : void PackageUri::init() const
77 : : {
78 : : // Already inited?
79 [ + - ][ + + ]: 6400 : if ( !m_aUri.isEmpty() && m_aPath.isEmpty() )
[ + + ]
80 : : {
81 : : // Note: Maybe it's a re-init, setUri only resets m_aPath!
82 : : m_aPackage = m_aParentUri = m_aName = m_aParam = m_aScheme
83 : 820 : = OUString();
84 : :
85 : : // URI must match at least: <sheme>://<non_empty_url_to_file>
86 [ - + ]: 820 : if ( ( m_aUri.getLength() < PACKAGE_URL_SCHEME_LENGTH + 4 ) )
87 : : {
88 : : // error, but remember that we did a init().
89 [ # # ]: 0 : m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
90 : : return;
91 : : }
92 : :
93 : : // Scheme must be followed by '://'
94 [ + - + - : 2460 : if ( ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH ]
- + ][ - + ]
95 : : != sal_Unicode( ':' ) )
96 : : ||
97 : 820 : ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 1 ]
98 : : != sal_Unicode( '/' ) )
99 : : ||
100 : 820 : ( m_aUri.getStr()[ PACKAGE_URL_SCHEME_LENGTH + 2 ]
101 : : != sal_Unicode( '/' ) ) )
102 : : {
103 : : // error, but remember that we did a init().
104 [ # # ]: 0 : m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
105 : : return;
106 : : }
107 : :
108 : 820 : rtl::OUString aPureUri;
109 : 820 : sal_Int32 nParam = m_aUri.indexOf( '?' );
110 [ - + ]: 820 : if( nParam >= 0 )
111 : : {
112 : 0 : m_aParam = m_aUri.copy( nParam );
113 : 0 : aPureUri = m_aUri.copy( 0, nParam );
114 : : }
115 : : else
116 : 820 : aPureUri = m_aUri;
117 : :
118 : : // Scheme is case insensitive.
119 : : m_aScheme = aPureUri.copy(
120 : 820 : 0, PACKAGE_URL_SCHEME_LENGTH ).toAsciiLowerCase();
121 : :
122 [ + - ][ + - ]: 820 : if ( m_aScheme == PACKAGE_URL_SCHEME || m_aScheme == PACKAGE_ZIP_URL_SCHEME )
[ + + ]
123 : : {
124 [ + + ]: 820 : if ( m_aScheme == PACKAGE_ZIP_URL_SCHEME )
125 : : {
126 : : m_aParam +=
127 : 746 : ( !m_aParam.isEmpty()
128 : : ? ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "&purezip" ) )
129 [ # # ][ + - ]: 746 : : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "?purezip" ) ) );
[ - + ]
130 : : }
131 : :
132 : : aPureUri = aPureUri.replaceAt( 0,
133 : : m_aScheme.getLength(),
134 : 820 : m_aScheme );
135 : :
136 : 820 : sal_Int32 nStart = PACKAGE_URL_SCHEME_LENGTH + 3;
137 : 820 : sal_Int32 nEnd = aPureUri.lastIndexOf( '/' );
138 [ - + ]: 820 : if ( nEnd == PACKAGE_URL_SCHEME_LENGTH + 3 )
139 : : {
140 : : // Only <scheme>:/// - Empty authority
141 : :
142 : : // error, but remember that we did a init().
143 [ # # ]: 0 : m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
144 : : return;
145 : : }
146 [ + + ]: 820 : else if ( nEnd == ( aPureUri.getLength() - 1 ) )
147 : : {
148 [ - + ]: 136 : if ( aPureUri.getStr()[ aPureUri.getLength() - 2 ]
149 : : == sal_Unicode( '/' ) )
150 : : {
151 : : // Only <scheme>://// or <scheme>://<something>//
152 : :
153 : : // error, but remember that we did a init().
154 [ # # ]: 0 : m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
155 : : return;
156 : : }
157 : :
158 : : // Remove trailing slash.
159 : 136 : aPureUri = aPureUri.copy( 0, nEnd );
160 : : }
161 : :
162 : :
163 : 820 : nEnd = aPureUri.indexOf( '/', nStart );
164 [ + + ]: 820 : if ( nEnd == -1 )
165 : : {
166 : : // root folder.
167 : :
168 : 404 : OUString aNormPackage = aPureUri.copy( nStart );
169 : 404 : normalize( aNormPackage );
170 : :
171 : : aPureUri = aPureUri.replaceAt(
172 : 404 : nStart, aPureUri.getLength() - nStart, aNormPackage );
173 : : m_aPackage
174 : 404 : = ::ucb_impl::urihelper::decodeSegment( aNormPackage );
175 [ + - ]: 404 : m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
176 : : m_aUri = m_aUri.replaceAt( 0,
177 : : ( nParam >= 0 )
178 : : ? nParam
179 [ + - ]: 404 : : m_aUri.getLength(), aPureUri );
180 : :
181 : 404 : sal_Int32 nLastSlash = m_aPackage.lastIndexOf( '/' );
182 [ + - ]: 404 : if ( nLastSlash != -1 )
183 : : m_aName = ::ucb_impl::urihelper::decodeSegment(
184 : 404 : m_aPackage.copy( nLastSlash + 1 ) );
185 : : else
186 : : m_aName
187 : 404 : = ::ucb_impl::urihelper::decodeSegment( m_aPackage );
188 : : }
189 : : else
190 : : {
191 : 416 : m_aPath = aPureUri.copy( nEnd + 1 );
192 : :
193 : : // Unexpected sequences of characters:
194 : : // - empty path segments
195 : : // - encoded slashes
196 : : // - parent folder segments ".."
197 : : // - current folder segments "."
198 [ + - ][ - + ]: 2496 : if ( m_aPath.indexOf( "//" ) != -1
[ - + ][ + -
+ - + - ]
199 : 416 : || m_aPath.indexOf( "%2F" ) != -1
200 : 416 : || m_aPath.indexOf( "%2f" ) != -1
201 [ + - ][ + - ]: 832 : || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".." ) ) )
[ + - ][ # # ]
202 [ + - ][ + - ]: 832 : || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ) )
[ + - ][ # # ]
203 : : {
204 : : // error, but remember that we did a init().
205 [ # # ]: 0 : m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
206 : : return;
207 : : }
208 : :
209 : 416 : OUString aNormPackage = aPureUri.copy( nStart, nEnd - nStart );
210 : 416 : normalize( aNormPackage );
211 : :
212 : : aPureUri = aPureUri.replaceAt(
213 : 416 : nStart, nEnd - nStart, aNormPackage );
214 : : aPureUri = aPureUri.replaceAt(
215 : : nEnd + 1,
216 : 416 : aPureUri.getLength() - nEnd - 1,
217 [ + - ]: 832 : ::ucb_impl::urihelper::encodeURI( m_aPath ) );
218 : :
219 : : m_aPackage
220 : 416 : = ::ucb_impl::urihelper::decodeSegment( aNormPackage );
221 : 416 : m_aPath = ::ucb_impl::urihelper::decodeSegment( m_aPath );
222 : : m_aUri = m_aUri.replaceAt( 0,
223 : : ( nParam >= 0 )
224 : : ? nParam
225 [ + - ]: 416 : : m_aUri.getLength(), aPureUri );
226 : :
227 : 416 : sal_Int32 nLastSlash = aPureUri.lastIndexOf( '/' );
228 [ + - ]: 416 : if ( nLastSlash != -1 )
229 : : {
230 : 416 : m_aParentUri = aPureUri.copy( 0, nLastSlash );
231 : : m_aName = ::ucb_impl::urihelper::decodeSegment(
232 : 416 : aPureUri.copy( nLastSlash + 1 ) );
233 : 416 : }
234 : : }
235 : :
236 : : // success
237 : 820 : m_bValid = true;
238 : : }
239 : : else
240 : : {
241 : : // error, but remember that we did a init().
242 [ # # ]: 820 : m_aPath = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
243 [ + - ]: 6400 : }
244 : : }
245 : : }
246 : :
247 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|