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 <rtl/ustring.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include "DAVProperties.hxx"
28 #include "UCBDeadPropertyValue.hxx"
29 
30 #include "SerfPropPatchReqProcImpl.hxx"
31 #include "SerfTypes.hxx"
32 
33 namespace http_dav_ucp
34 {
35 
SerfPropPatchReqProcImpl(const char * inPath,const DAVRequestHeaders & inRequestHeaders,const std::vector<ProppatchValue> & inProperties,const char * inLockToken)36 SerfPropPatchReqProcImpl::SerfPropPatchReqProcImpl( const char* inPath,
37                                                     const DAVRequestHeaders& inRequestHeaders,
38                                                     const std::vector< ProppatchValue > & inProperties,
39                                                     const char* inLockToken )
40     : SerfRequestProcessorImpl( inPath, inRequestHeaders )
41     , mpProperties( &inProperties )
42     , mpLockToken( inLockToken )
43 {
44 }
45 
~SerfPropPatchReqProcImpl()46 SerfPropPatchReqProcImpl::~SerfPropPatchReqProcImpl()
47 {
48 }
49 
50 #define PROPPATCH_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?><propertyupdate xmlns=\"DAV:\">"
51 #define PROPPATCH_TRAILER "</propertyupdate>"
52 
createSerfRequestBucket(serf_request_t * inSerfRequest)53 serf_bucket_t * SerfPropPatchReqProcImpl::createSerfRequestBucket( serf_request_t * inSerfRequest )
54 {
55     serf_bucket_alloc_t* pSerfBucketAlloc = serf_request_get_alloc( inSerfRequest );
56 
57     // body bucket
58     serf_bucket_t* body_bkt = 0;
59     rtl::OString aBodyText;
60     {
61         // create and fill body bucket with properties to be set or removed
62         static const struct
63         {
64             const char *str;
65             sal_Int32   len;
66         }
67         OpCode [] = {
68             { RTL_CONSTASCII_STRINGPARAM( "set" ) },
69             { RTL_CONSTASCII_STRINGPARAM( "remove" ) }
70         };
71         const int nPropCount = ( mpProperties != 0 )
72                                ? mpProperties->size()
73                                : 0;
74         if ( nPropCount > 0 )
75         {
76             rtl::OUStringBuffer aBuffer;
77             // add PropPatch xml header in front
78             aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( PROPPATCH_HEADER ));
79 
80             // <*operation code*><prop>
81 
82             ProppatchOperation lastOp = (*mpProperties)[ 0 ].operation;
83             aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "<" ));
84             aBuffer.appendAscii( OpCode[lastOp].str, OpCode[lastOp].len );
85             aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "><prop>" ));
86 
87             SerfPropName thePropName;
88             for ( int n = 0; n < nPropCount; ++n )
89             {
90                 const ProppatchValue & rProperty = (*mpProperties)[ n ];
91                 // split fullname into namespace and name!
92                 DAVProperties::createSerfPropName( rProperty.name,
93                                                    thePropName );
94 
95                 if ( rProperty.operation != lastOp )
96                 {
97                     // </prop></*last operation code*><*operation code><prop>
98                     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "</prop></" ));
99                     aBuffer.appendAscii( OpCode[lastOp].str, OpCode[lastOp].len );
100                     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "><" ));
101                     aBuffer.appendAscii( OpCode[rProperty.operation].str, OpCode[rProperty.operation].len );
102                     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "><prop>" ));
103                 }
104 
105                 // <*propname* xmlns="*propns*"
106                 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "<" ));
107                 aBuffer.appendAscii( thePropName.name );
108                 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " xmlns=\"" ));
109                 aBuffer.appendAscii( thePropName.nspace );
110                 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\"" ));
111 
112                 if ( rProperty.operation == PROPSET )
113                 {
114                     // >*property value*</*propname*>
115                     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( ">" ));
116 
117                     rtl::OUString aStringValue;
118                     if ( DAVProperties::isUCBDeadProperty( thePropName ) )
119                     {
120                         UCBDeadPropertyValue::toXML( rProperty.value,
121                                                      aStringValue );
122                     }
123                     else
124                     {
125                         rProperty.value >>= aStringValue;
126                     }
127                     aBuffer.append( aStringValue );
128                     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "</" ));
129                     aBuffer.appendAscii( thePropName.name );
130                     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( ">" ));
131                 }
132                 else
133                 {
134                     // />
135                     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "/>" ));
136                 }
137 
138                 lastOp = rProperty.operation;
139             }
140 
141             // </prop></*last operation code*>
142             aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "</prop></" ));
143             aBuffer.appendAscii( OpCode[lastOp].str, OpCode[lastOp].len );
144             aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( ">" ));
145 
146             // add PropPatch xml trailer at end
147             aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( PROPPATCH_TRAILER ));
148 
149             aBodyText = rtl::OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
150             body_bkt = serf_bucket_simple_copy_create( aBodyText.getStr(),
151                                                        aBodyText.getLength(),
152                                                        pSerfBucketAlloc );
153         }
154     }
155 
156     // create serf request
157     serf_bucket_t *req_bkt = serf_request_bucket_request_create( inSerfRequest,
158                                                                  "PROPPATCH",
159                                                                  getPathStr(),
160                                                                  body_bkt,
161                                                                  pSerfBucketAlloc ) ;
162     handleChunkedEncoding(req_bkt, aBodyText.getLength());
163 
164     // set request header fields
165     serf_bucket_t* hdrs_bkt = serf_bucket_request_get_headers( req_bkt );
166     if (hdrs_bkt != NULL)
167     {
168         // general header fields provided by caller
169         setRequestHeaders( hdrs_bkt );
170 
171         // request specific header fields
172         if(mpLockToken)
173         {
174             serf_bucket_headers_set( hdrs_bkt, "if", mpLockToken );
175         }
176         if ( body_bkt != 0 && aBodyText.getLength() > 0 )
177         {
178             serf_bucket_headers_set( hdrs_bkt, "Content-Type", "application/xml" );
179         }
180     }
181     else
182     {
183         OSL_ASSERT("Headers Bucket missing");
184     }
185 
186     return req_bkt;
187 }
188 
processChunkOfResponseData(const char *,apr_size_t)189 void SerfPropPatchReqProcImpl::processChunkOfResponseData( const char* /*data*/,
190                                                            apr_size_t /*len*/ )
191 {
192     // nothing to do;
193 }
194 
handleEndOfResponseData(serf_bucket_t *)195 void SerfPropPatchReqProcImpl::handleEndOfResponseData( serf_bucket_t * /*inSerfResponseBucket*/ )
196 {
197     // nothing to do;
198 }
199 
200 } // namespace http_dav_ucp
201