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 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 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 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 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 141 SerfUri::~SerfUri( ) 142 { 143 } 144 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 189 ::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 218 bool SerfUri::operator== ( const SerfUri & rOther ) const 219 { 220 return ( mURI == rOther.mURI ); 221 } 222 223 ::rtl::OUString SerfUri::GetPathBaseNameUnescaped () const 224 { 225 return unescape( GetPathBaseName() ); 226 } 227 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 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 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 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