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