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