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 #include <sal/config.h>
30
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 // FIXME: not sure whether initializing a ne_uri statically is supposed to work
43 // the string fields of ne_uri are char*, not const char*
44
45 #ifdef __GNUC__
46 #pragma GCC diagnostic ignored "-Wwrite-strings"
47 #endif
48
49 namespace {
50
51 const ne_uri g_sUriDefaultsHTTP = { const_cast<char *>("http"),
52 const_cast<char *>(""),
53 const_cast<char *>(""),
54 DEFAULT_HTTP_PORT,
55 const_cast<char *>(""),
56 nullptr,
57 nullptr };
58 const ne_uri g_sUriDefaultsHTTPS = { const_cast<char *>("https"),
59 const_cast<char *>(""),
60 const_cast<char *>(""),
61 DEFAULT_HTTPS_PORT,
62 const_cast<char *>(""),
63 nullptr,
64 nullptr };
65 const ne_uri g_sUriDefaultsFTP = { const_cast<char *>("ftp"),
66 const_cast<char *>(""),
67 const_cast<char *>(""),
68 DEFAULT_FTP_PORT,
69 const_cast<char *>(""),
70 nullptr,
71 nullptr };
72 } // namespace
73
NeonUri(const ne_uri * inUri)74 NeonUri::NeonUri( const ne_uri * inUri )
75 {
76 if ( inUri == nullptr )
77 throw DAVException( DAVException::DAV_INVALID_ARG );
78
79 char * uri = ne_uri_unparse( inUri );
80
81 if ( uri == nullptr )
82 throw DAVException( DAVException::DAV_INVALID_ARG );
83
84 init( OString( uri ), inUri );
85 ne_free( uri );
86
87 calculateURI();
88 }
89
NeonUri(const OUString & inUri)90 NeonUri::NeonUri( const OUString & inUri )
91 {
92 if ( inUri.isEmpty() )
93 throw DAVException( DAVException::DAV_INVALID_ARG );
94
95 // #i77023#
96 OUString aEscapedUri( ucb_impl::urihelper::encodeURI( inUri ) );
97
98 OString theInputUri(
99 aEscapedUri.getStr(), aEscapedUri.getLength(), RTL_TEXTENCODING_UTF8 );
100
101 ne_uri theUri;
102 if ( ne_uri_parse( theInputUri.getStr(), &theUri ) != 0 )
103 {
104 ne_uri_free( &theUri );
105 throw DAVException( DAVException::DAV_INVALID_ARG );
106 }
107
108 init( theInputUri, &theUri );
109 ne_uri_free( &theUri );
110
111 calculateURI();
112 }
113
init(const OString & rUri,const ne_uri * pUri)114 void NeonUri::init( const OString & rUri, const ne_uri * pUri )
115 {
116 // Complete URI.
117 const ne_uri * pUriDefs
118 = rUri.matchIgnoreAsciiCase( "ftp:" ) ?
119 &g_sUriDefaultsFTP :
120 rUri.matchIgnoreAsciiCase( "https:" ) ?
121 &g_sUriDefaultsHTTPS :
122 &g_sUriDefaultsHTTP;
123
124 mScheme = OStringToOUString(
125 pUri->scheme ? pUri->scheme : pUriDefs->scheme,
126 RTL_TEXTENCODING_UTF8 );
127 mUserInfo = OStringToOUString(
128 pUri->userinfo ? pUri->userinfo : pUriDefs->userinfo,
129 RTL_TEXTENCODING_UTF8 );
130 mHostName = OStringToOUString(
131 pUri->host ? pUri->host : pUriDefs->host,
132 RTL_TEXTENCODING_UTF8 );
133 mPort = pUri->port > 0 ? pUri->port : pUriDefs->port;
134 mPath = OStringToOUString(
135 pUri->path ? pUri->path : pUriDefs->path,
136 RTL_TEXTENCODING_UTF8 );
137
138 if ( pUri->query )
139 {
140 mPath += "?" + OStringToOUString( pUri->query, RTL_TEXTENCODING_UTF8 );
141 }
142
143 if ( pUri->fragment )
144 {
145 mPath += "#" + OStringToOUString( pUri->fragment, RTL_TEXTENCODING_UTF8 );
146 }
147 }
148
calculateURI()149 void NeonUri::calculateURI ()
150 {
151 OUStringBuffer aBuf( 256 );
152 aBuf.append( mScheme );
153 aBuf.append( "://" );
154 if ( !mUserInfo.isEmpty() )
155 {
156 //TODO! differentiate between empty and missing userinfo
157 aBuf.append( mUserInfo );
158 aBuf.append( "@" );
159 }
160 // Is host a numeric IPv6 address?
161 if ( ( mHostName.indexOf( ':' ) != -1 ) &&
162 ( mHostName[ 0 ] != '[' ) )
163 {
164 aBuf.append( "[" );
165 aBuf.append( mHostName );
166 aBuf.append( "]" );
167 }
168 else
169 {
170 aBuf.append( mHostName );
171 }
172
173 // append port, but only, if not default port.
174 bool bAppendPort = true;
175 switch ( mPort )
176 {
177 case DEFAULT_HTTP_PORT:
178 bAppendPort = mScheme != "http";
179 break;
180
181 case DEFAULT_HTTPS_PORT:
182 bAppendPort = mScheme != "https";
183 break;
184
185 case DEFAULT_FTP_PORT:
186 bAppendPort = mScheme != "ftp";
187 break;
188 }
189 if ( bAppendPort )
190 {
191 aBuf.append( ":" );
192 aBuf.append( mPort );
193 }
194 aBuf.append( mPath );
195
196 mURI = aBuf.makeStringAndClear();
197 }
198
GetPathBaseName() const199 OUString NeonUri::GetPathBaseName () const
200 {
201 sal_Int32 nPos = mPath.lastIndexOf ('/');
202 sal_Int32 nTrail = 0;
203 if (nPos == mPath.getLength () - 1)
204 {
205 // Trailing slash found. Skip.
206 nTrail = 1;
207 nPos = mPath.lastIndexOf ('/', nPos);
208 }
209 if (nPos != -1)
210 {
211 OUString aTemp(
212 mPath.copy (nPos + 1, mPath.getLength () - nPos - 1 - nTrail) );
213
214 // query, fragment present?
215 nPos = aTemp.indexOf( '?' );
216 if ( nPos == -1 )
217 nPos = aTemp.indexOf( '#' );
218
219 if ( nPos != -1 )
220 aTemp = aTemp.copy( 0, nPos );
221
222 return aTemp;
223 }
224 else
225 return "/";
226 }
227
operator ==(const NeonUri & rOther) const228 bool NeonUri::operator== ( const NeonUri & rOther ) const
229 {
230 return ( mURI == rOther.mURI );
231 }
232
GetPathBaseNameUnescaped() const233 OUString NeonUri::GetPathBaseNameUnescaped () const
234 {
235 return unescape( GetPathBaseName() );
236 }
237
AppendPath(std::u16string_view rPath)238 void NeonUri::AppendPath (std::u16string_view rPath)
239 {
240 if (mPath.lastIndexOf ('/') != mPath.getLength () - 1)
241 mPath += "/";
242
243 mPath += rPath;
244 calculateURI ();
245 };
246
247 // static
escapeSegment(const OUString & segment)248 OUString NeonUri::escapeSegment( const OUString& segment )
249 {
250 return rtl::Uri::encode( segment,
251 rtl_UriCharClassPchar,
252 rtl_UriEncodeIgnoreEscapes,
253 RTL_TEXTENCODING_UTF8 );
254 }
255
256 // static
unescape(const OUString & segment)257 OUString NeonUri::unescape( const OUString& segment )
258 {
259 return rtl::Uri::decode( segment,
260 rtl_UriDecodeWithCharset,
261 RTL_TEXTENCODING_UTF8 );
262 }
263
264 // static
makeConnectionEndPointString(const OUString & rHostName,int nPort)265 OUString NeonUri::makeConnectionEndPointString(
266 const OUString & rHostName, int nPort )
267 {
268 OUStringBuffer aBuf;
269
270 // Is host a numeric IPv6 address?
271 if ( ( rHostName.indexOf( ':' ) != -1 ) &&
272 ( rHostName[ 0 ] != '[' ) )
273 {
274 aBuf.append( "[" );
275 aBuf.append( rHostName );
276 aBuf.append( "]" );
277 }
278 else
279 {
280 aBuf.append( rHostName );
281 }
282
283 if ( ( nPort != DEFAULT_HTTP_PORT ) && ( nPort != DEFAULT_HTTPS_PORT ) )
284 {
285 aBuf.append( ":" );
286 aBuf.append( static_cast<sal_Int32>(nPort) );
287 }
288 return aBuf.makeStringAndClear();
289 }
290
291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
292