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 <SerfPropFindReqProcImpl.hxx>
26 #include <SerfTypes.hxx>
27 #include <DAVProperties.hxx>
28 
29 #include <webdavresponseparser.hxx>
30 #include <comphelper/seqstream.hxx>
31 
32 using namespace com::sun::star;
33 
34 namespace http_dav_ucp
35 {
36 
37 SerfPropFindReqProcImpl::SerfPropFindReqProcImpl( const char* inPath,
38                                                   const Depth inDepth,
39                                                   const std::vector< ::rtl::OUString > & inPropNames,
40                                                   std::vector< DAVResource > & ioResources )
41     : SerfRequestProcessorImpl( inPath )
42     , mDepthStr( 0 )
43     , mpPropNames( &inPropNames )
44     , mpResources( &ioResources )
45     , mpResInfo( 0 )
46     , mbOnlyPropertyNames( false )
47     , xInputStream( new SerfInputStream() )
48 {
49     init( inDepth );
50 }
51 
52 SerfPropFindReqProcImpl::SerfPropFindReqProcImpl( const char* inPath,
53                                                   const Depth inDepth,
54                                                   std::vector< DAVResourceInfo > & ioResInfo )
55     : SerfRequestProcessorImpl( inPath )
56     , mDepthStr( 0 )
57     , mpPropNames( 0 )
58     , mpResources( 0 )
59     , mpResInfo( &ioResInfo )
60     , mbOnlyPropertyNames( true )
61     , xInputStream( new SerfInputStream() )
62 {
63     init( inDepth );
64 }
65 
66 void SerfPropFindReqProcImpl::init( const Depth inDepth )
67 {
68     switch ( inDepth )
69     {
70         case DAVZERO:
71             mDepthStr = "0";
72             break;
73         case DAVONE:
74             mDepthStr = "1";
75             break;
76         case DAVINFINITY:
77             mDepthStr = "infinity";
78             break;
79     }
80 }
81 
82 SerfPropFindReqProcImpl::~SerfPropFindReqProcImpl()
83 {
84 }
85 
86 #define PROPFIND_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?><propfind xmlns=\"DAV:\">"
87 #define PROPFIND_TRAILER "</propfind>"
88 
89 serf_bucket_t * SerfPropFindReqProcImpl::createSerfRequestBucket( serf_request_t * inSerfRequest )
90 {
91     serf_bucket_alloc_t* pSerfBucketAlloc = serf_request_get_alloc( inSerfRequest );
92 
93     // body bucket - certain properties OR all properties OR only property names
94     serf_bucket_t* body_bkt = 0;
95     sal_Int32 nDataLen = 0;
96     {
97         // create and fill body bucket with requested properties
98         body_bkt = serf_bucket_aggregate_create( pSerfBucketAlloc );
99 
100         serf_bucket_t* tmp = 0;
101         const int nPropCount = ( !mbOnlyPropertyNames && mpPropNames )
102                                ? mpPropNames->size()
103                                : 0;
104         if ( nPropCount > 0 )
105         {
106             SerfPropName thePropName;
107             for ( int theIndex = 0; theIndex < nPropCount; theIndex ++ )
108             {
109                 // split fullname into namespace and name!
110                 DAVProperties::createSerfPropName( (*mpPropNames)[ theIndex ],
111                                                    thePropName );
112 
113                 /* <*propname* xmlns="*propns*" /> */
114                 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("<", 1, pSerfBucketAlloc );
115                 serf_bucket_aggregate_append( body_bkt, tmp );
116                 nDataLen += 1;
117 
118                 tmp = SERF_BUCKET_SIMPLE_STRING( thePropName.name, pSerfBucketAlloc );
119                 serf_bucket_aggregate_append( body_bkt, tmp );
120                 nDataLen += strlen(thePropName.name);
121 
122                 tmp = SERF_BUCKET_SIMPLE_STRING_LEN( " xmlns=\"",
123                                                      sizeof(" xmlns=\"")-1,
124                                                      pSerfBucketAlloc );
125                 serf_bucket_aggregate_append( body_bkt, tmp );
126                 nDataLen += sizeof(" xmlns=\"")-1;
127 
128                 tmp = SERF_BUCKET_SIMPLE_STRING( thePropName.nspace, pSerfBucketAlloc );
129                 serf_bucket_aggregate_append( body_bkt, tmp );
130                 nDataLen += strlen(thePropName.nspace);
131 
132                 tmp = SERF_BUCKET_SIMPLE_STRING_LEN( "\"/>", sizeof("\"/>")-1,
133                                                      pSerfBucketAlloc );
134                 serf_bucket_aggregate_append( body_bkt, tmp );
135                 nDataLen += sizeof("\"/>")-1;
136             }
137 
138             tmp = SERF_BUCKET_SIMPLE_STRING_LEN("<prop>",
139                                                 sizeof("<prop>")-1,
140                                                 pSerfBucketAlloc );
141             serf_bucket_aggregate_prepend(body_bkt, tmp);
142             nDataLen += sizeof("<prop>")-1;
143 
144             tmp = SERF_BUCKET_SIMPLE_STRING_LEN("</prop>",
145                                                 sizeof("</prop>")-1,
146                                                 pSerfBucketAlloc );
147             serf_bucket_aggregate_append(body_bkt, tmp);
148             nDataLen += sizeof("</prop>")-1;
149         }
150         else
151         {
152             if ( mbOnlyPropertyNames )
153             {
154                 tmp = SERF_BUCKET_SIMPLE_STRING_LEN( "<propname/>",
155                                                      sizeof("<propname/>")-1,
156                                                      pSerfBucketAlloc );
157                 nDataLen += sizeof("<propname/>")-1;
158             }
159             else
160             {
161                 tmp = SERF_BUCKET_SIMPLE_STRING_LEN( "<allprop/>",
162                                                      sizeof("<allprop/>")-1,
163                                                      pSerfBucketAlloc );
164                 nDataLen += sizeof("<allprop/>")-1;
165             }
166             serf_bucket_aggregate_append( body_bkt, tmp );
167         }
168 
169         tmp = SERF_BUCKET_SIMPLE_STRING_LEN( PROPFIND_HEADER,
170                                              sizeof(PROPFIND_HEADER)-1,
171                                              pSerfBucketAlloc );
172         serf_bucket_aggregate_prepend(body_bkt, tmp);
173         nDataLen += sizeof(PROPFIND_HEADER)-1;
174 
175         tmp = SERF_BUCKET_SIMPLE_STRING_LEN(PROPFIND_TRAILER,
176                                             sizeof(PROPFIND_TRAILER)-1,
177                                             pSerfBucketAlloc );
178         serf_bucket_aggregate_append(body_bkt, tmp);
179         nDataLen += sizeof(PROPFIND_TRAILER)-1;
180     }
181 
182     // create serf request
183     serf_bucket_t *req_bkt = serf_request_bucket_request_create( inSerfRequest,
184                                                                  "PROPFIND",
185                                                                  getPathStr(),
186                                                                  body_bkt,
187                                                                  serf_request_get_alloc( inSerfRequest ) );
188 
189     // TODO - correct header data
190     // set request header fields
191     serf_bucket_t* hdrs_bkt = serf_bucket_request_get_headers( req_bkt );
192     serf_bucket_headers_setn( hdrs_bkt, "User-Agent", "www.openoffice.org/ucb/" );
193     serf_bucket_headers_setn( hdrs_bkt, "Accept-Encoding", "gzip");
194 
195     // request specific header fields
196     serf_bucket_headers_setn( hdrs_bkt, "Depth", mDepthStr );
197     serf_bucket_headers_setn( hdrs_bkt, "Content-Type", "application/xml" );
198     serf_bucket_headers_setn( hdrs_bkt, "Content-Length",
199                               rtl::OUStringToOString( rtl::OUString::valueOf( nDataLen ), RTL_TEXTENCODING_UTF8 ) );
200 
201     return req_bkt;
202 }
203 
204 
205 bool SerfPropFindReqProcImpl::processSerfResponseBucket( serf_request_t * /*inSerfRequest*/,
206                                                          serf_bucket_t * inSerfResponseBucket,
207                                                          apr_pool_t * /*inAprPool*/,
208                                                          apr_status_t & outStatus )
209 {
210     const char* data;
211     apr_size_t len;
212 
213     while (1) {
214         outStatus = serf_bucket_read(inSerfResponseBucket, 2048, &data, &len);
215         if (SERF_BUCKET_READ_ERROR(outStatus))
216         {
217             return true;
218         }
219 
220         if ( len > 0 )
221         {
222             xInputStream->AddToStream( data, len );
223         }
224 
225         /* are we done yet? */
226         if (APR_STATUS_IS_EOF(outStatus))
227         {
228             if ( mbOnlyPropertyNames )
229             {
230                 const std::vector< DAVResourceInfo > rResInfo( parseWebDAVPropNameResponse( xInputStream.get() ) );
231                 *mpResInfo = rResInfo;
232             }
233             else
234             {
235                 const std::vector< DAVResource > rResources( parseWebDAVPropFindResponse( xInputStream.get() ) );
236                 *mpResources = rResources;
237             }
238 
239             outStatus = APR_EOF;
240             return true;
241         }
242 
243         /* have we drained the response so far? */
244         if ( APR_STATUS_IS_EAGAIN( outStatus ) )
245         {
246             return false;
247         }
248     }
249 
250     /* NOTREACHED */
251     return true;
252 }
253 
254 } // namespace http_dav_ucp
255