1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_ucb.hxx"
24
25 #include <string.h>
26 #include <rtl/uri.hxx>
27 #include <rtl/ustring.hxx>
28 #include <rtl/ustrbuf.hxx>
29 #include "SerfUri.hxx"
30 #include "DAVException.hxx"
31 #include "AprEnv.hxx"
32
33 #include "../inc/urihelper.hxx"
34
35 using namespace http_dav_ucp;
36
37 # if defined __SUNPRO_CC
38 # pragma enable_warn
39 #endif
40
41 // -------------------------------------------------------------------
42 // Constructor
43 // -------------------------------------------------------------------
44
45 namespace {
46
matchIgnoreAsciiCase(rtl::OString const & rStr1,sal_Char const * pStr2,sal_Int32 nStr2Len)47 inline bool matchIgnoreAsciiCase(rtl::OString const & rStr1,
48 sal_Char const * pStr2,
49 sal_Int32 nStr2Len) SAL_THROW(())
50 {
51 return
52 rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
53 rStr1.getStr(), rStr1.getLength(), pStr2, nStr2Len, nStr2Len)
54 == 0;
55 }
56
57 }
58
SerfUri(const apr_uri_t * inUri)59 SerfUri::SerfUri( const apr_uri_t * inUri )
60 throw ( DAVException )
61 : mAprUri( *inUri )
62 , mURI()
63 , mScheme()
64 , mUserInfo()
65 , mHostName()
66 , mPort()
67 , mPath()
68 {
69 if ( inUri == 0 )
70 throw DAVException( DAVException::DAV_INVALID_ARG );
71
72 char * uri = apr_uri_unparse( apr_environment::AprEnv::getAprEnv()->getAprPool(), &mAprUri, 0 );
73
74 if ( uri == 0 )
75 throw DAVException( DAVException::DAV_INVALID_ARG );
76
77 init( &mAprUri );
78
79 calculateURI();
80 }
81
SerfUri(const rtl::OUString & inUri)82 SerfUri::SerfUri( const rtl::OUString & inUri )
83 throw ( DAVException )
84 : mAprUri()
85 , mURI()
86 , mScheme()
87 , mUserInfo()
88 , mHostName()
89 , mPort()
90 , mPath()
91 {
92 if ( inUri.getLength() <= 0 )
93 throw DAVException( DAVException::DAV_INVALID_ARG );
94
95 // #i77023#
96 rtl::OUString aEscapedUri( ucb_impl::urihelper::encodeURI( inUri ) );
97
98 rtl::OString theInputUri(
99 aEscapedUri.getStr(), aEscapedUri.getLength(), RTL_TEXTENCODING_UTF8 );
100
101 if ( apr_uri_parse( apr_environment::AprEnv::getAprEnv()->getAprPool(),
102 theInputUri.getStr(), &mAprUri ) != APR_SUCCESS )
103 {
104 throw DAVException( DAVException::DAV_INVALID_ARG );
105 }
106 if ( !mAprUri.port )
107 {
108 mAprUri.port = apr_uri_port_of_scheme( mAprUri.scheme );
109 }
110 if ( !mAprUri.path )
111 {
112 mAprUri.path = "/";
113 }
114
115 init( &mAprUri );
116
117 calculateURI();
118 }
119
init(const apr_uri_t * pUri)120 void SerfUri::init( const apr_uri_t * pUri )
121 {
122 mScheme = rtl::OStringToOUString( pUri->scheme, RTL_TEXTENCODING_UTF8 );
123 mUserInfo = rtl::OStringToOUString( pUri->user, RTL_TEXTENCODING_UTF8 );
124 mHostName = rtl::OStringToOUString( pUri->hostname, RTL_TEXTENCODING_UTF8 );
125 mPort = pUri->port;
126 mPath = rtl::OStringToOUString( pUri->path, RTL_TEXTENCODING_UTF8 );
127
128 if ( pUri->query )
129 {
130 mPath += rtl::OUString::createFromAscii( "?" );
131 mPath += rtl::OStringToOUString( pUri->query, RTL_TEXTENCODING_UTF8 );
132 }
133
134 if ( pUri->fragment )
135 {
136 mPath += rtl::OUString::createFromAscii( "#" );
137 mPath += rtl::OStringToOUString( pUri->fragment, RTL_TEXTENCODING_UTF8 );
138 }
139 }
140
~SerfUri()141 SerfUri::~SerfUri( )
142 {
143 }
144
calculateURI()145 void SerfUri::calculateURI ()
146 {
147 rtl::OUStringBuffer aBuf( mScheme );
148 aBuf.appendAscii( "://" );
149 if ( mUserInfo.getLength() > 0 )
150 {
151 aBuf.append( mUserInfo );
152 aBuf.appendAscii( "@" );
153 }
154 // Is host a numeric IPv6 address?
155 if ( ( mHostName.indexOf( ':' ) != -1 ) &&
156 ( mHostName[ 0 ] != sal_Unicode( '[' ) ) )
157 {
158 aBuf.appendAscii( "[" );
159 aBuf.append( mHostName );
160 aBuf.appendAscii( "]" );
161 }
162 else
163 {
164 aBuf.append( mHostName );
165 }
166
167 // append port, but only, if not default port.
168 bool bAppendPort = true;
169 switch ( mPort )
170 {
171 case DEFAULT_HTTP_PORT:
172 bAppendPort = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "http" ) );
173 break;
174
175 case DEFAULT_HTTPS_PORT:
176 bAppendPort = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "https" ) );
177 break;
178 }
179 if ( bAppendPort )
180 {
181 aBuf.appendAscii( ":" );
182 aBuf.append( rtl::OUString::valueOf( mPort ) );
183 }
184 aBuf.append( mPath );
185
186 mURI = aBuf.makeStringAndClear();
187 }
188
GetPathBaseName() const189 ::rtl::OUString SerfUri::GetPathBaseName () const
190 {
191 sal_Int32 nPos = mPath.lastIndexOf ('/');
192 sal_Int32 nTrail = 0;
193 if (nPos == mPath.getLength () - 1)
194 {
195 // Trailing slash found. Skip.
196 nTrail = 1;
197 nPos = mPath.lastIndexOf ('/', nPos);
198 }
199 if (nPos != -1)
200 {
201 rtl::OUString aTemp(
202 mPath.copy (nPos + 1, mPath.getLength () - nPos - 1 - nTrail) );
203
204 // query, fragment present?
205 nPos = aTemp.indexOf( '?' );
206 if ( nPos == -1 )
207 nPos = aTemp.indexOf( '#' );
208
209 if ( nPos != -1 )
210 aTemp = aTemp.copy( 0, nPos );
211
212 return aTemp;
213 }
214 else
215 return rtl::OUString::createFromAscii ("/");
216 }
217
operator ==(const SerfUri & rOther) const218 bool SerfUri::operator== ( const SerfUri & rOther ) const
219 {
220 return ( mURI == rOther.mURI );
221 }
222
GetPathBaseNameUnescaped() const223 ::rtl::OUString SerfUri::GetPathBaseNameUnescaped () const
224 {
225 return unescape( GetPathBaseName() );
226 }
227
AppendPath(const rtl::OUString & rPath)228 void SerfUri::AppendPath (const rtl::OUString& rPath)
229 {
230 if (mPath.lastIndexOf ('/') != mPath.getLength () - 1)
231 mPath += rtl::OUString::createFromAscii ("/");
232
233 mPath += rPath;
234 calculateURI ();
235 };
236
237 // static
escapeSegment(const rtl::OUString & segment)238 rtl::OUString SerfUri::escapeSegment( const rtl::OUString& segment )
239 {
240 return rtl::Uri::encode( segment,
241 rtl_UriCharClassPchar,
242 rtl_UriEncodeIgnoreEscapes,
243 RTL_TEXTENCODING_UTF8 );
244 }
245
246 // static
unescape(const rtl::OUString & segment)247 rtl::OUString SerfUri::unescape( const rtl::OUString& segment )
248 {
249 return rtl::Uri::decode( segment,
250 rtl_UriDecodeWithCharset,
251 RTL_TEXTENCODING_UTF8 );
252 }
253
254 // static
makeConnectionEndPointString(const rtl::OUString & rHostName,int nPort)255 rtl::OUString SerfUri::makeConnectionEndPointString(
256 const rtl::OUString & rHostName, int nPort )
257 {
258 rtl::OUStringBuffer aBuf;
259
260 // Is host a numeric IPv6 address?
261 if ( ( rHostName.indexOf( ':' ) != -1 ) &&
262 ( rHostName[ 0 ] != sal_Unicode( '[' ) ) )
263 {
264 aBuf.appendAscii( "[" );
265 aBuf.append( rHostName );
266 aBuf.appendAscii( "]" );
267 }
268 else
269 {
270 aBuf.append( rHostName );
271 }
272
273 if ( ( nPort != DEFAULT_HTTP_PORT ) && ( nPort != DEFAULT_HTTPS_PORT ) )
274 {
275 aBuf.appendAscii( ":" );
276 aBuf.append( rtl::OUString::valueOf( sal_Int32( nPort ) ) );
277 }
278 return aBuf.makeStringAndClear();
279 }
280
281