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