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