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