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