xref: /aoo4110/main/ucb/source/ucp/webdav/SerfUri.cxx (revision b1cdbd2c)
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