Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : /**************************************************************************
22 : TODO
23 : **************************************************************************
24 :
25 : *************************************************************************/
26 :
27 : #include "rtl/ustrbuf.hxx"
28 : #include "osl/diagnose.h"
29 : #include "comphelper/storagehelper.hxx"
30 :
31 : #include "../inc/urihelper.hxx"
32 :
33 : #include "pkguri.hxx"
34 :
35 : using namespace package_ucp;
36 :
37 :
38 :
39 :
40 :
41 : // PackageUri Implementation.
42 :
43 :
44 :
45 :
46 0 : static void normalize( OUString& rURL )
47 : {
48 0 : sal_Int32 nPos = 0;
49 0 : do
50 : {
51 0 : nPos = rURL.indexOf( '%', nPos );
52 0 : if ( nPos != -1 )
53 : {
54 0 : if ( nPos < ( rURL.getLength() - 2 ) )
55 : {
56 0 : OUString aTmp = rURL.copy( nPos + 1, 2 );
57 0 : rURL = rURL.replaceAt( nPos + 1, 2, aTmp.toAsciiUpperCase() );
58 0 : nPos++;
59 : }
60 : }
61 : }
62 : while ( nPos != -1 );
63 0 : }
64 :
65 :
66 0 : void PackageUri::init() const
67 : {
68 : // Already inited?
69 0 : if ( !m_aUri.isEmpty() && m_aPath.isEmpty() )
70 : {
71 : // Note: Maybe it's a re-init, setUri only resets m_aPath!
72 0 : m_aPackage = m_aParentUri = m_aName = m_aParam = m_aScheme
73 0 : = OUString();
74 :
75 : // URI must match at least: <sheme>://<non_empty_url_to_file>
76 0 : if ( ( m_aUri.getLength() < PACKAGE_URL_SCHEME_LENGTH + 4 ) )
77 : {
78 : // error, but remember that we did a init().
79 0 : m_aPath = "/";
80 0 : return;
81 : }
82 :
83 : // Scheme must be followed by '://'
84 0 : if ( ( m_aUri[ PACKAGE_URL_SCHEME_LENGTH ] != ':' )
85 0 : ||
86 0 : ( m_aUri[ PACKAGE_URL_SCHEME_LENGTH + 1 ] != '/' )
87 0 : ||
88 0 : ( m_aUri[ PACKAGE_URL_SCHEME_LENGTH + 2 ] != '/' ) )
89 : {
90 : // error, but remember that we did a init().
91 0 : m_aPath = "/";
92 0 : return;
93 : }
94 :
95 0 : OUString aPureUri;
96 0 : sal_Int32 nParam = m_aUri.indexOf( '?' );
97 0 : if( nParam >= 0 )
98 : {
99 0 : m_aParam = m_aUri.copy( nParam );
100 0 : aPureUri = m_aUri.copy( 0, nParam );
101 : }
102 : else
103 0 : aPureUri = m_aUri;
104 :
105 : // Scheme is case insensitive.
106 0 : m_aScheme = aPureUri.copy(
107 0 : 0, PACKAGE_URL_SCHEME_LENGTH ).toAsciiLowerCase();
108 :
109 0 : if ( m_aScheme == PACKAGE_URL_SCHEME || m_aScheme == PACKAGE_ZIP_URL_SCHEME )
110 : {
111 0 : if ( m_aScheme == PACKAGE_ZIP_URL_SCHEME )
112 : {
113 0 : m_aParam +=
114 0 : ( !m_aParam.isEmpty()
115 : ? OUString( "&purezip" )
116 0 : : OUString( "?purezip" ) );
117 : }
118 :
119 0 : aPureUri = aPureUri.replaceAt( 0,
120 : m_aScheme.getLength(),
121 0 : m_aScheme );
122 :
123 0 : sal_Int32 nStart = PACKAGE_URL_SCHEME_LENGTH + 3;
124 0 : sal_Int32 nEnd = aPureUri.lastIndexOf( '/' );
125 0 : if ( nEnd == PACKAGE_URL_SCHEME_LENGTH + 3 )
126 : {
127 : // Only <scheme>:/// - Empty authority
128 :
129 : // error, but remember that we did a init().
130 0 : m_aPath = "/";
131 0 : return;
132 : }
133 0 : else if ( nEnd == ( aPureUri.getLength() - 1 ) )
134 : {
135 0 : if ( aPureUri[ aPureUri.getLength() - 2 ] == '/' )
136 : {
137 : // Only <scheme>://// or <scheme>://<something>
138 :
139 : // error, but remember that we did a init().
140 0 : m_aPath = "/";
141 0 : return;
142 : }
143 :
144 : // Remove trailing slash.
145 0 : aPureUri = aPureUri.copy( 0, nEnd );
146 : }
147 :
148 :
149 0 : nEnd = aPureUri.indexOf( '/', nStart );
150 0 : if ( nEnd == -1 )
151 : {
152 : // root folder.
153 :
154 0 : OUString aNormPackage = aPureUri.copy( nStart );
155 0 : normalize( aNormPackage );
156 :
157 0 : aPureUri = aPureUri.replaceAt(
158 0 : nStart, aPureUri.getLength() - nStart, aNormPackage );
159 : m_aPackage
160 0 : = ::ucb_impl::urihelper::decodeSegment( aNormPackage );
161 0 : m_aPath = "/";
162 0 : m_aUri = m_aUri.replaceAt( 0,
163 : ( nParam >= 0 )
164 : ? nParam
165 0 : : m_aUri.getLength(), aPureUri );
166 :
167 0 : sal_Int32 nLastSlash = m_aPackage.lastIndexOf( '/' );
168 0 : if ( nLastSlash != -1 )
169 0 : m_aName = ::ucb_impl::urihelper::decodeSegment(
170 0 : m_aPackage.copy( nLastSlash + 1 ) );
171 : else
172 : m_aName
173 0 : = ::ucb_impl::urihelper::decodeSegment( m_aPackage );
174 : }
175 : else
176 : {
177 0 : m_aPath = aPureUri.copy( nEnd + 1 );
178 :
179 : // Unexpected sequences of characters:
180 : // - empty path segments
181 : // - encoded slashes
182 : // - parent folder segments ".."
183 : // - current folder segments "."
184 0 : if ( m_aPath.indexOf( "//" ) != -1
185 0 : || m_aPath.indexOf( "%2F" ) != -1
186 0 : || m_aPath.indexOf( "%2f" ) != -1
187 0 : || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, OUString( ".." ) )
188 0 : || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, OUString( "." ) ) )
189 : {
190 : // error, but remember that we did a init().
191 0 : m_aPath = "/";
192 0 : return;
193 : }
194 :
195 0 : OUString aNormPackage = aPureUri.copy( nStart, nEnd - nStart );
196 0 : normalize( aNormPackage );
197 :
198 0 : aPureUri = aPureUri.replaceAt(
199 0 : nStart, nEnd - nStart, aNormPackage );
200 0 : aPureUri = aPureUri.replaceAt(
201 : nEnd + 1,
202 0 : aPureUri.getLength() - nEnd - 1,
203 0 : ::ucb_impl::urihelper::encodeURI( m_aPath ) );
204 :
205 : m_aPackage
206 0 : = ::ucb_impl::urihelper::decodeSegment( aNormPackage );
207 0 : m_aPath = ::ucb_impl::urihelper::decodeSegment( m_aPath );
208 0 : m_aUri = m_aUri.replaceAt( 0,
209 : ( nParam >= 0 )
210 : ? nParam
211 0 : : m_aUri.getLength(), aPureUri );
212 :
213 0 : sal_Int32 nLastSlash = aPureUri.lastIndexOf( '/' );
214 0 : if ( nLastSlash != -1 )
215 : {
216 0 : m_aParentUri = aPureUri.copy( 0, nLastSlash );
217 0 : m_aName = ::ucb_impl::urihelper::decodeSegment(
218 0 : aPureUri.copy( nLastSlash + 1 ) );
219 0 : }
220 : }
221 :
222 : // success
223 0 : m_bValid = true;
224 : }
225 : else
226 : {
227 : // error, but remember that we did a init().
228 0 : m_aPath = "/";
229 0 : }
230 : }
231 : }
232 :
233 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|