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 } 138 } 139 140 // create serf request 141 serf_bucket_t *req_bkt = serf_request_bucket_request_create( inSerfRequest, 142 "PROPPATCH", 143 getPathStr(), 144 body_bkt, 145 pSerfBucketAlloc ) ; 146 147 // TODO - correct header data 148 // set request header fields 149 serf_bucket_t* hdrs_bkt = serf_bucket_request_get_headers( req_bkt ); 150 serf_bucket_headers_setn( hdrs_bkt, "User-Agent", "www.openoffice.org/ucb/" ); 151 serf_bucket_headers_setn( hdrs_bkt, "Accept-Encoding", "gzip"); 152 153 // request specific header fields 154 if ( body_bkt != 0 && aBodyText.getLength() > 0 ) 155 { 156 serf_bucket_headers_setn( hdrs_bkt, "Content-Type", "application/xml" ); 157 serf_bucket_headers_setn( hdrs_bkt, "Content-Length", 158 rtl::OUStringToOString( rtl::OUString::valueOf( aBodyText.getLength() ), RTL_TEXTENCODING_UTF8 ) ); 159 } 160 161 return req_bkt; 162 } 163 164 165 bool SerfPropPatchReqProcImpl::processSerfResponseBucket( serf_request_t * /*inSerfRequest*/, 166 serf_bucket_t * inSerfResponseBucket, 167 apr_pool_t * /*inAprPool*/, 168 apr_status_t & outStatus ) 169 { 170 const char* data; 171 apr_size_t len; 172 173 while (1) { 174 outStatus = serf_bucket_read(inSerfResponseBucket, 2048, &data, &len); 175 if (SERF_BUCKET_READ_ERROR(outStatus)) 176 { 177 return true; 178 } 179 180 /* are we done yet? */ 181 if (APR_STATUS_IS_EOF(outStatus)) 182 { 183 outStatus = APR_EOF; 184 return true; 185 } 186 187 /* have we drained the response so far? */ 188 if ( APR_STATUS_IS_EAGAIN( outStatus ) ) 189 { 190 return false; 191 } 192 } 193 194 /* NOTREACHED */ 195 return true; 196 } 197 198 } // namespace http_dav_ucp 199