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 : : #include <string.h>
31 : : #include <rtl/uri.hxx>
32 : : #include <rtl/ustring.hxx>
33 : : #include <rtl/ustrbuf.hxx>
34 : : #include "ne_alloc.h"
35 : : #include "NeonUri.hxx"
36 : : #include "DAVException.hxx"
37 : :
38 : : #include "../inc/urihelper.hxx"
39 : :
40 : : using namespace webdav_ucp;
41 : :
42 : : # if defined __SUNPRO_CC
43 : : // FIXME: not sure whether initializing a ne_uri statically is supposed to work
44 : : // the string fields of ne_uri are char*, not const char*
45 : : # pragma disable_warn
46 : : # endif
47 : :
48 : : #if defined __GNUC__
49 : : #define GCC_VERSION (__GNUC__ * 10000 \
50 : : + __GNUC_MINOR__ * 100 \
51 : : + __GNUC_PATCHLEVEL__)
52 : : /* Diagnostics pragma was introduced with gcc-4.2.1 */
53 : : #if GCC_VERSION >= 40201
54 : : #pragma GCC diagnostic ignored "-Wwrite-strings"
55 : : #endif
56 : : #endif
57 : :
58 : : namespace {
59 : :
60 : : const ne_uri g_sUriDefaultsHTTP = { "http",
61 : : NULL,
62 : : NULL,
63 : : DEFAULT_HTTP_PORT,
64 : : NULL,
65 : : NULL,
66 : : NULL };
67 : : const ne_uri g_sUriDefaultsHTTPS = { "https",
68 : : NULL,
69 : : NULL,
70 : : DEFAULT_HTTPS_PORT,
71 : : NULL,
72 : : NULL,
73 : : NULL };
74 : : const ne_uri g_sUriDefaultsFTP = { "ftp",
75 : : NULL,
76 : : NULL,
77 : : DEFAULT_FTP_PORT,
78 : : NULL,
79 : : NULL,
80 : : NULL };
81 : : } // namespace
82 : :
83 : : # if defined __SUNPRO_CC
84 : : # pragma enable_warn
85 : : #endif
86 : :
87 : : // -------------------------------------------------------------------
88 : : // Constructor
89 : : // -------------------------------------------------------------------
90 : :
91 : : namespace {
92 : :
93 : : //TODO! rtl::OString::matchIgnoreAsciiCaseAsciiL() missing
94 : 4 : inline bool matchIgnoreAsciiCase(rtl::OString const & rStr1,
95 : : sal_Char const * pStr2,
96 : : sal_Int32 nStr2Len) SAL_THROW(())
97 : : {
98 : : return
99 : : rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
100 : 4 : rStr1.getStr(), rStr1.getLength(), pStr2, nStr2Len, nStr2Len)
101 : 4 : == 0;
102 : : }
103 : :
104 : : }
105 : :
106 : 0 : NeonUri::NeonUri( const ne_uri * inUri )
107 : 0 : throw ( DAVException )
108 : : {
109 [ # # ]: 0 : if ( inUri == 0 )
110 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
111 : :
112 [ # # ]: 0 : char * uri = ne_uri_unparse( inUri );
113 : :
114 [ # # ]: 0 : if ( uri == 0 )
115 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
116 : :
117 [ # # ]: 0 : init( rtl::OString( uri ), inUri );
118 : 0 : ne_free( uri );
119 : :
120 [ # # ]: 0 : calculateURI();
121 : 0 : }
122 : :
123 : 2 : NeonUri::NeonUri( const rtl::OUString & inUri )
124 : 2 : throw ( DAVException )
125 : : {
126 [ - + ]: 2 : if ( inUri.isEmpty() )
127 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
128 : :
129 : : // #i77023#
130 [ + - ]: 2 : rtl::OUString aEscapedUri( ucb_impl::urihelper::encodeURI( inUri ) );
131 : :
132 : : rtl::OString theInputUri(
133 [ + - ]: 2 : aEscapedUri.getStr(), aEscapedUri.getLength(), RTL_TEXTENCODING_UTF8 );
134 : :
135 : : ne_uri theUri;
136 [ + - ][ - + ]: 2 : if ( ne_uri_parse( theInputUri.getStr(), &theUri ) != 0 )
137 : : {
138 [ # # ]: 0 : ne_uri_free( &theUri );
139 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
140 : : }
141 : :
142 [ + - ]: 2 : init( theInputUri, &theUri );
143 [ + - ]: 2 : ne_uri_free( &theUri );
144 : :
145 [ + - ]: 2 : calculateURI();
146 : 2 : }
147 : :
148 : 2 : void NeonUri::init( const rtl::OString & rUri, const ne_uri * pUri )
149 : : {
150 : : // Complete URI.
151 : : const ne_uri * pUriDefs
152 : : = matchIgnoreAsciiCase( rUri,
153 : 2 : RTL_CONSTASCII_STRINGPARAM( "ftp:" ) ) ?
154 : : &g_sUriDefaultsFTP :
155 : : matchIgnoreAsciiCase( rUri,
156 : 2 : RTL_CONSTASCII_STRINGPARAM( "https:" ) ) ?
157 : : &g_sUriDefaultsHTTPS :
158 [ - + ][ - + ]: 4 : &g_sUriDefaultsHTTP;
159 : :
160 : : mScheme = rtl::OStringToOUString(
161 : : pUri->scheme ? pUri->scheme : pUriDefs->scheme,
162 [ + - ][ + - ]: 2 : RTL_TEXTENCODING_UTF8 );
163 : : mUserInfo = rtl::OStringToOUString(
164 : : pUri->userinfo ? pUri->userinfo : pUriDefs->userinfo,
165 [ + - ][ - + ]: 2 : RTL_TEXTENCODING_UTF8 );
166 : : mHostName = rtl::OStringToOUString(
167 : : pUri->host ? pUri->host : pUriDefs->host,
168 [ + - ][ + - ]: 2 : RTL_TEXTENCODING_UTF8 );
169 [ - + ]: 2 : mPort = pUri->port > 0 ? pUri->port : pUriDefs->port;
170 : : mPath = rtl::OStringToOUString(
171 : : pUri->path ? pUri->path : pUriDefs->path,
172 [ + - ][ + - ]: 2 : RTL_TEXTENCODING_UTF8 );
173 : :
174 [ - + ]: 2 : if ( pUri->query )
175 : : {
176 : 0 : mPath += rtl::OUString("?");
177 : : mPath += rtl::OStringToOUString(
178 [ # # ]: 0 : pUri->query, RTL_TEXTENCODING_UTF8 );
179 : : }
180 : :
181 [ - + ]: 2 : if ( pUri->fragment )
182 : : {
183 : 0 : mPath += rtl::OUString("#");
184 : : mPath += rtl::OStringToOUString(
185 [ # # ]: 0 : pUri->fragment, RTL_TEXTENCODING_UTF8 );
186 : : }
187 : 2 : }
188 : :
189 : : // -------------------------------------------------------------------
190 : : // Destructor
191 : : // -------------------------------------------------------------------
192 : 2 : NeonUri::~NeonUri( )
193 : : {
194 : 2 : }
195 : :
196 : 2 : void NeonUri::calculateURI ()
197 : : {
198 [ + - ]: 2 : rtl::OUStringBuffer aBuf( mScheme );
199 [ + - ]: 2 : aBuf.appendAscii( "://" );
200 [ - + ]: 2 : if ( !mUserInfo.isEmpty() )
201 : : {
202 : : //TODO! differentiate between empty and missing userinfo
203 [ # # ]: 0 : aBuf.append( mUserInfo );
204 [ # # ]: 0 : aBuf.appendAscii( "@" );
205 : : }
206 : : // Is host a numeric IPv6 address?
207 [ - + # # ]: 2 : if ( ( mHostName.indexOf( ':' ) != -1 ) &&
[ - + ]
208 : 0 : ( mHostName[ 0 ] != sal_Unicode( '[' ) ) )
209 : : {
210 [ # # ]: 0 : aBuf.appendAscii( "[" );
211 [ # # ]: 0 : aBuf.append( mHostName );
212 [ # # ]: 0 : aBuf.appendAscii( "]" );
213 : : }
214 : : else
215 : : {
216 [ + - ]: 2 : aBuf.append( mHostName );
217 : : }
218 : :
219 : : // append port, but only, if not default port.
220 : 2 : bool bAppendPort = true;
221 [ + - - - ]: 2 : switch ( mPort )
222 : : {
223 : : case DEFAULT_HTTP_PORT:
224 : 2 : bAppendPort = mScheme != "http";
225 : 2 : break;
226 : :
227 : : case DEFAULT_HTTPS_PORT:
228 : 0 : bAppendPort = mScheme != "https";
229 : 0 : break;
230 : :
231 : : case DEFAULT_FTP_PORT:
232 : 0 : bAppendPort = mScheme != "ftp";
233 : 0 : break;
234 : : }
235 [ - + ]: 2 : if ( bAppendPort )
236 : : {
237 [ # # ]: 0 : aBuf.appendAscii( ":" );
238 [ # # ]: 0 : aBuf.append( rtl::OUString::valueOf( mPort ) );
239 : : }
240 [ + - ]: 2 : aBuf.append( mPath );
241 : :
242 [ + - ]: 2 : mURI = aBuf.makeStringAndClear();
243 : 2 : }
244 : :
245 : 2 : ::rtl::OUString NeonUri::GetPathBaseName () const
246 : : {
247 : 2 : sal_Int32 nPos = mPath.lastIndexOf ('/');
248 : 2 : sal_Int32 nTrail = 0;
249 [ + - ]: 2 : if (nPos == mPath.getLength () - 1)
250 : : {
251 : : // Trailing slash found. Skip.
252 : 2 : nTrail = 1;
253 : 2 : nPos = mPath.lastIndexOf ('/', nPos);
254 : : }
255 [ + - ]: 2 : if (nPos != -1)
256 : : {
257 : : rtl::OUString aTemp(
258 : 2 : mPath.copy (nPos + 1, mPath.getLength () - nPos - 1 - nTrail) );
259 : :
260 : : // query, fragment present?
261 : 2 : nPos = aTemp.indexOf( '?' );
262 [ + - ]: 2 : if ( nPos == -1 )
263 : 2 : nPos = aTemp.indexOf( '#' );
264 : :
265 [ - + ]: 2 : if ( nPos != -1 )
266 : 0 : aTemp = aTemp.copy( 0, nPos );
267 : :
268 : 2 : return aTemp;
269 : : }
270 : : else
271 : 2 : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("/"));
272 : : }
273 : :
274 : 0 : bool NeonUri::operator== ( const NeonUri & rOther ) const
275 : : {
276 : 0 : return ( mURI == rOther.mURI );
277 : : }
278 : :
279 : 0 : ::rtl::OUString NeonUri::GetPathBaseNameUnescaped () const
280 : : {
281 : 0 : return unescape( GetPathBaseName() );
282 : : }
283 : :
284 : 0 : void NeonUri::AppendPath (const rtl::OUString& rPath)
285 : : {
286 [ # # ]: 0 : if (mPath.lastIndexOf ('/') != mPath.getLength () - 1)
287 : 0 : mPath += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("/"));
288 : :
289 : 0 : mPath += rPath;
290 : 0 : calculateURI ();
291 : 0 : };
292 : :
293 : : // static
294 : 0 : rtl::OUString NeonUri::escapeSegment( const rtl::OUString& segment )
295 : : {
296 : : return rtl::Uri::encode( segment,
297 : : rtl_UriCharClassPchar,
298 : : rtl_UriEncodeIgnoreEscapes,
299 : 0 : RTL_TEXTENCODING_UTF8 );
300 : : }
301 : :
302 : : // static
303 : 0 : rtl::OUString NeonUri::unescape( const rtl::OUString& segment )
304 : : {
305 : : return rtl::Uri::decode( segment,
306 : : rtl_UriDecodeWithCharset,
307 : 0 : RTL_TEXTENCODING_UTF8 );
308 : : }
309 : :
310 : : // static
311 : 0 : rtl::OUString NeonUri::makeConnectionEndPointString(
312 : : const rtl::OUString & rHostName, int nPort )
313 : : {
314 : 0 : rtl::OUStringBuffer aBuf;
315 : :
316 : : // Is host a numeric IPv6 address?
317 [ # # ]: 0 : if ( ( rHostName.indexOf( ':' ) != -1 ) &&
[ # # # # ]
318 : 0 : ( rHostName[ 0 ] != sal_Unicode( '[' ) ) )
319 : : {
320 [ # # ]: 0 : aBuf.appendAscii( "[" );
321 [ # # ]: 0 : aBuf.append( rHostName );
322 [ # # ]: 0 : aBuf.appendAscii( "]" );
323 : : }
324 : : else
325 : : {
326 [ # # ]: 0 : aBuf.append( rHostName );
327 : : }
328 : :
329 [ # # ][ # # ]: 0 : if ( ( nPort != DEFAULT_HTTP_PORT ) && ( nPort != DEFAULT_HTTPS_PORT ) )
330 : : {
331 [ # # ]: 0 : aBuf.appendAscii( ":" );
332 [ # # ]: 0 : aBuf.append( rtl::OUString::valueOf( sal_Int32( nPort ) ) );
333 : : }
334 [ # # ]: 0 : return aBuf.makeStringAndClear();
335 : : }
336 : :
337 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|