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 #include "SerfRequestProcessorImpl.hxx"
23 #include "webdavuseragent.hxx"
24 
25 namespace
26 {
27 // Define a magic value that is used by serf to reset chunked
28 // encoding.  The value definition is not supported by serf, hence the
29 // definition here.
30 static const apr_int64_t SERF_UNKNOWN_LENGTH (-1);
31 }
32 
33 namespace http_dav_ucp
34 {
35 
SerfRequestProcessorImpl(const char * inPath,const DAVRequestHeaders & inRequestHeaders)36 SerfRequestProcessorImpl::SerfRequestProcessorImpl( const char* inPath,
37                                                     const DAVRequestHeaders& inRequestHeaders )
38     : mPathStr( inPath )
39     , mrRequestHeaders( inRequestHeaders )
40     , mbUseChunkedEncoding( false )
41 {
42 }
43 
~SerfRequestProcessorImpl()44 SerfRequestProcessorImpl::~SerfRequestProcessorImpl()
45 {
46 }
47 
getPathStr() const48 const char* SerfRequestProcessorImpl::getPathStr() const
49 {
50     return mPathStr;
51 }
52 
activateChunkedEncoding()53 void SerfRequestProcessorImpl::activateChunkedEncoding()
54 {
55     mbUseChunkedEncoding = true;
56 }
57 
useChunkedEncoding() const58 bool SerfRequestProcessorImpl::useChunkedEncoding() const
59 {
60     return mbUseChunkedEncoding;
61 }
62 
63 
handleChunkedEncoding(serf_bucket_t * pRequestBucket,apr_int64_t nLength) const64 void SerfRequestProcessorImpl::handleChunkedEncoding (
65     serf_bucket_t* pRequestBucket,
66     apr_int64_t nLength) const
67 {
68     if (pRequestBucket != NULL)
69     {
70         if (useChunkedEncoding())
71         {
72             // Activate chunked encoding.
73             serf_bucket_request_set_CL(pRequestBucket, SERF_UNKNOWN_LENGTH);
74         }
75         else
76         {
77             // Deactivate chunked encoding by setting the length.
78             serf_bucket_request_set_CL(pRequestBucket, nLength);
79         }
80     }
81 }
82 
83 
setRequestHeaders(serf_bucket_t * inoutSerfHeaderBucket)84 void SerfRequestProcessorImpl::setRequestHeaders( serf_bucket_t* inoutSerfHeaderBucket )
85 {
86     bool bHasUserAgent( false );
87     DAVRequestHeaders::const_iterator aHeaderIter( mrRequestHeaders.begin() );
88     const DAVRequestHeaders::const_iterator aEnd( mrRequestHeaders.end() );
89 
90     while ( aHeaderIter != aEnd )
91     {
92         const rtl::OString aHeader = rtl::OUStringToOString( (*aHeaderIter).first,
93                                                                RTL_TEXTENCODING_UTF8 );
94         const rtl::OString aValue = rtl::OUStringToOString( (*aHeaderIter).second,
95                                                             RTL_TEXTENCODING_UTF8 );
96 
97         OSL_TRACE( "Request Header - \"%s: %s\"", aHeader.getStr(), aValue.getStr() );
98         if ( !bHasUserAgent )
99             bHasUserAgent = aHeaderIter->first.equalsAsciiL(
100                 RTL_CONSTASCII_STRINGPARAM( "User-Agent" ) );
101 
102         serf_bucket_headers_setc( inoutSerfHeaderBucket,
103                                   aHeader.getStr(),
104                                   aValue.getStr() );
105 
106         ++aHeaderIter;
107     }
108 
109     if ( !bHasUserAgent )
110     {
111         const rtl::OUString &rUserAgent = WebDAVUserAgent::get();
112         serf_bucket_headers_set( inoutSerfHeaderBucket,
113                                  "User-Agent",
114                                  rtl::OUStringToOString( rUserAgent, RTL_TEXTENCODING_UTF8 ).getStr() );
115     }
116 
117     serf_bucket_headers_set( inoutSerfHeaderBucket, "Accept-Encoding", "gzip");
118 }
119 
processSerfResponseBucket(serf_request_t *,serf_bucket_t * inSerfResponseBucket,apr_pool_t *,apr_status_t & outStatus)120 bool SerfRequestProcessorImpl::processSerfResponseBucket( serf_request_t * /*inSerfRequest*/,
121                                                           serf_bucket_t * inSerfResponseBucket,
122                                                           apr_pool_t * /*inAprPool*/,
123                                                           apr_status_t & outStatus )
124 {
125     const char* data;
126     apr_size_t len;
127 
128     while (1) {
129         outStatus = serf_bucket_read(inSerfResponseBucket, 8096, &data, &len);
130         if (SERF_BUCKET_READ_ERROR(outStatus))
131         {
132             return true;
133         }
134 
135         if ( len > 0 )
136         {
137             processChunkOfResponseData( data, len );
138         }
139 
140         /* are we done yet? */
141         if (APR_STATUS_IS_EOF(outStatus))
142         {
143             handleEndOfResponseData( inSerfResponseBucket );
144 
145             outStatus = APR_EOF;
146             return true;
147         }
148 
149         /* have we drained the response so far? */
150         if ( APR_STATUS_IS_EAGAIN( outStatus ) )
151         {
152             return false;
153         }
154     }
155 
156     /* NOTREACHED */
157     return true;
158 }
159 
160 } // namespace http_dav_ucp
161 
162