bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / ucp / webdav / UCBDeadPropertyValue.cxx
bloba00ad35b60277ac0df24e3ad98ab12c8444c3355
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <string.h>
21 #include <osl/diagnose.h>
22 #include <rtl/ustrbuf.hxx>
23 #include "UCBDeadPropertyValue.hxx"
25 using namespace http_dav_ucp;
26 using namespace ::com::sun::star;
29 // static
30 const OUString UCBDeadPropertyValue::aTypeString
31 = OUString( "string" );
32 const OUString UCBDeadPropertyValue::aTypeLong
33 = OUString( "long" );
34 const OUString UCBDeadPropertyValue::aTypeShort
35 = OUString( "short" );
36 const OUString UCBDeadPropertyValue::aTypeBoolean
37 = OUString( "boolean" );
38 const OUString UCBDeadPropertyValue::aTypeChar
39 = OUString( "char" );
40 const OUString UCBDeadPropertyValue::aTypeByte
41 = OUString( "byte" );
42 const OUString UCBDeadPropertyValue::aTypeHyper
43 = OUString( "hyper" );
44 const OUString UCBDeadPropertyValue::aTypeFloat
45 = OUString( "float" );
46 const OUString UCBDeadPropertyValue::aTypeDouble
47 = OUString( "double" );
49 // static
50 const OUString UCBDeadPropertyValue::aXMLPre
51 = OUString( "<ucbprop><type>" );
52 const OUString UCBDeadPropertyValue::aXMLMid
53 = OUString( "</type><value>" );
54 const OUString UCBDeadPropertyValue::aXMLEnd
55 = OUString( "</value></ucbprop>" );
59 #define STATE_TOP (1)
61 #define STATE_UCBPROP (STATE_TOP)
62 #define STATE_TYPE (STATE_TOP + 1)
63 #define STATE_VALUE (STATE_TOP + 2)
65 extern "C" int UCBDeadPropertyValue_startelement_callback(
66 void *,
67 int parent,
68 const char * nspace,
69 const char *name,
70 const char ** )
72 if ( name != 0 )
74 switch ( parent )
76 case NE_XML_STATEROOT:
77 if ( strcmp( name, "ucbprop" ) == 0 )
78 return STATE_UCBPROP;
79 break;
81 case STATE_UCBPROP:
82 if ( strcmp( name, "type" ) == 0 )
83 return STATE_TYPE;
84 else if ( strcmp( name, "value" ) == 0 )
85 return STATE_VALUE;
86 break;
89 return NE_XML_DECLINE;
93 extern "C" int UCBDeadPropertyValue_chardata_callback(
94 void *userdata,
95 int state,
96 const char *buf,
97 size_t len )
99 UCBDeadPropertyValueParseContext * pCtx
100 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
102 switch ( state )
104 case STATE_TYPE:
105 SAL_WARN_IF( pCtx->pType, "ucb.ucp.webdav",
106 "UCBDeadPropertyValue_endelement_callback - "
107 "Type already set!" );
108 pCtx->pType
109 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
110 break;
112 case STATE_VALUE:
113 SAL_WARN_IF( pCtx->pValue, "ucb.ucp.webdav",
114 "UCBDeadPropertyValue_endelement_callback - "
115 "Value already set!" );
116 pCtx->pValue
117 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
118 break;
120 return 0; // zero to continue, non-zero to abort parsing
124 extern "C" int UCBDeadPropertyValue_endelement_callback(
125 void *userdata,
126 int state,
127 const char *,
128 const char * )
130 UCBDeadPropertyValueParseContext * pCtx
131 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
133 switch ( state )
135 case STATE_TYPE:
136 if ( !pCtx->pType )
137 return 1; // abort
138 break;
140 case STATE_VALUE:
141 if ( !pCtx->pValue )
142 return 1; // abort
143 break;
145 case STATE_UCBPROP:
146 if ( !pCtx->pType || ! pCtx->pValue )
147 return 1; // abort
148 break;
150 return 0; // zero to continue, non-zero to abort parsing
155 static OUString encodeValue( const OUString & rValue )
157 // Note: I do not use the usual &amp; + &lt; + &gt; encoding, because
158 // I want to prevent any XML parser from trying to 'understand'
159 // the value. This caused problems:
161 // Example:
162 // - Unencoded property value: x<z
163 // PROPPATCH:
164 // - Encoded property value: x&lt;z
165 // - UCBDeadPropertyValue::toXML result:
166 // <ucbprop><type>string</type><value>x&lt;z</value></ucbprop>
167 // PROPFIND:
168 // - parser replaces &lt; by > ==> error (not well formed)
170 OUStringBuffer aResult;
171 const sal_Unicode * pValue = rValue.getStr();
173 sal_Int32 nCount = rValue.getLength();
174 for ( sal_Int32 n = 0; n < nCount; ++n )
176 const sal_Unicode c = pValue[ n ];
178 if ( '%' == c )
179 aResult.appendAscii( "%per;" );
180 else if ( '<' == c )
181 aResult.appendAscii( "%lt;" );
182 else if ( '>' == c )
183 aResult.appendAscii( "%gt;" );
184 else
185 aResult.append( c );
187 return aResult.makeStringAndClear();
192 static OUString decodeValue( const OUString & rValue )
194 OUStringBuffer aResult;
195 const sal_Unicode * pValue = rValue.getStr();
197 sal_Int32 nPos = 0;
198 sal_Int32 nEnd = rValue.getLength();
200 while ( nPos < nEnd )
202 sal_Unicode c = pValue[ nPos ];
204 if ( '%' == c )
206 nPos++;
208 if ( nPos == nEnd )
210 SAL_WARN( "ucb.ucp.webdav",
211 "UCBDeadPropertyValue::decodeValue - syntax error!" );
212 return OUString();
215 c = pValue[ nPos ];
217 if ( 'p' == c )
219 // %per;
221 if ( nPos > nEnd - 4 )
223 SAL_WARN( "ucb.ucp.webdav",
224 "UCBDeadPropertyValue::decodeValue - syntax error!" );
225 return OUString();
228 if ( ( 'e' == pValue[ nPos + 1 ] )
230 ( 'r' == pValue[ nPos + 2 ] )
232 ( ';' == pValue[ nPos + 3 ] ) )
234 aResult.append( '%' );
235 nPos += 3;
237 else
239 SAL_WARN( "ucb.ucp.webdav",
240 "UCBDeadPropertyValue::decodeValue - syntax error!" );
241 return OUString();
244 else if ( 'l' == c )
246 // %lt;
248 if ( nPos > nEnd - 3 )
250 SAL_WARN( "ucb.ucp.webdav",
251 "UCBDeadPropertyValue::decodeValue - syntax error!" );
252 return OUString();
255 if ( ( 't' == pValue[ nPos + 1 ] )
257 ( ';' == pValue[ nPos + 2 ] ) )
259 aResult.append( '<' );
260 nPos += 2;
262 else
264 SAL_WARN( "ucb.ucp.webdav",
265 "UCBDeadPropertyValue::decodeValue - syntax error!" );
266 return OUString();
269 else if ( 'g' == c )
271 // %gt;
273 if ( nPos > nEnd - 3 )
275 SAL_WARN( "ucb.ucp.webdav",
276 "UCBDeadPropertyValue::decodeValue - syntax error!" );
277 return OUString();
280 if ( ( 't' == pValue[ nPos + 1 ] )
282 ( ';' == pValue[ nPos + 2 ] ) )
284 aResult.append( '>' );
285 nPos += 2;
287 else
289 SAL_WARN( "ucb.ucp.webdav",
290 "UCBDeadPropertyValue::decodeValue - syntax error!" );
291 return OUString();
294 else
296 SAL_WARN( "ucb.ucp.webdav",
297 "UCBDeadPropertyValue::decodeValue - syntax error!" );
298 return OUString();
301 else
302 aResult.append( c );
304 nPos++;
307 return OUString( aResult );
312 // static
313 bool UCBDeadPropertyValue::supportsType( const uno::Type & rType )
315 if ( ( rType != cppu::UnoType<OUString>::get() )
317 ( rType != cppu::UnoType<sal_Int32>::get() )
319 ( rType != cppu::UnoType<sal_Int16>::get() )
321 ( rType != cppu::UnoType<bool>::get() )
323 ( rType != cppu::UnoType<cppu::UnoCharType>::get() )
325 ( rType != cppu::UnoType<sal_Int8>::get() )
327 ( rType != cppu::UnoType<sal_Int64>::get() )
329 ( rType != cppu::UnoType<float>::get() )
331 ( rType != cppu::UnoType<double>::get() ) )
333 return false;
336 return true;
340 // static
341 bool UCBDeadPropertyValue::createFromXML( const OString & /*rInData*/,
342 uno::Any & /*rOutData*/ )
344 bool success = false;
347 ne_xml_parser * parser = ne_xml_create();
348 if ( parser )
350 UCBDeadPropertyValueParseContext aCtx;
351 ne_xml_push_handler( parser,
352 UCBDeadPropertyValue_startelement_callback,
353 UCBDeadPropertyValue_chardata_callback,
354 UCBDeadPropertyValue_endelement_callback,
355 &aCtx );
357 ne_xml_parse( parser, rInData.getStr(), rInData.getLength() );
359 success = !ne_xml_failed( parser );
361 ne_xml_destroy( parser );
363 if ( success )
365 if ( aCtx.pType && aCtx.pValue )
367 // Decode aCtx.pValue! It may contain XML reserved chars.
368 OUString aStringValue = decodeValue( *aCtx.pValue );
369 if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) )
371 rOutData <<= aStringValue;
373 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) )
375 rOutData <<= aStringValue.toInt32();
377 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) )
379 rOutData <<= sal_Int16( aStringValue.toInt32() );
381 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) )
383 if ( aStringValue.equalsIgnoreAsciiCase(
384 OUString( "true" ) ) )
385 rOutData <<= sal_Bool( sal_True );
386 else
387 rOutData <<= sal_Bool( sal_False );
389 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) )
391 rOutData <<= aStringValue.toChar();
393 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) )
395 rOutData <<= sal_Int8( aStringValue.toChar() );
397 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) )
399 rOutData <<= aStringValue.toInt64();
401 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) )
403 rOutData <<= aStringValue.toFloat();
405 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) )
407 rOutData <<= aStringValue.toDouble();
409 else
411 SAL_WARN( "ucb.ucp.webdav",
412 "UCBDeadPropertyValue::createFromXML - "
413 "Unsupported property type!" );
414 success = false;
417 else
418 success = false;
422 return success;
426 // static
427 bool UCBDeadPropertyValue::toXML( const uno::Any & rInData,
428 OUString & rOutData )
430 // <ucbprop><type>the_type</type><value>the_value</value></ucbprop>
432 // Check property type. Extract type and value as string.
434 const uno::Type& rType = rInData.getValueType();
435 OUString aStringValue;
436 OUString aStringType;
438 if ( rType == cppu::UnoType<OUString>::get() )
440 // string
441 rInData >>= aStringValue;
442 aStringType = aTypeString;
444 else if ( rType == cppu::UnoType<sal_Int32>::get() )
446 // long
447 sal_Int32 nValue = 0;
448 rInData >>= nValue;
449 aStringValue = OUString::number( nValue );
450 aStringType = aTypeLong;
452 else if ( rType == cppu::UnoType<sal_Int16>::get() )
454 // short
455 sal_Int32 nValue = 0;
456 rInData >>= nValue;
457 aStringValue = OUString::number( nValue );
458 aStringType = aTypeShort;
460 else if ( rType == cppu::UnoType<bool>::get() )
462 // boolean
463 sal_Bool bValue = false;
464 rInData >>= bValue;
465 aStringValue = OUString::boolean( bValue );
466 aStringType = aTypeBoolean;
468 else if ( rType == cppu::UnoType<cppu::UnoCharType>::get() )
470 // char
471 sal_Unicode cValue = 0;
472 rInData >>= cValue;
473 aStringValue = OUString( cValue );
474 aStringType = aTypeChar;
476 else if ( rType == cppu::UnoType<sal_Int8>::get() )
478 // byte
479 sal_Int8 nValue = 0;
480 rInData >>= nValue;
481 aStringValue = OUString( sal_Unicode( nValue ) );
482 aStringType = aTypeByte;
484 else if ( rType == cppu::UnoType<sal_Int64>::get() )
486 // hyper
487 sal_Int64 nValue = 0;
488 rInData >>= nValue;
489 aStringValue = OUString::number( nValue );
490 aStringType = aTypeHyper;
492 else if ( rType == cppu::UnoType<float>::get() )
494 // float
495 float nValue = 0;
496 rInData >>= nValue;
497 aStringValue = OUString::number( nValue );
498 aStringType = aTypeFloat;
500 else if ( rType == cppu::UnoType<double>::get() )
502 // double
503 double nValue = 0;
504 rInData >>= nValue;
505 aStringValue = OUString::number( nValue );
506 aStringType = aTypeDouble;
508 else
510 SAL_WARN( "ucb.ucp.webdav",
511 "UCBDeadPropertyValue::toXML - "
512 "Unsupported property type!" );
513 return false;
516 // Encode value! It must not contain XML reserved chars!
517 aStringValue = encodeValue( aStringValue );
519 rOutData = aXMLPre;
520 rOutData += aStringType;
521 rOutData += aXMLMid;
522 rOutData += aStringValue;
523 rOutData += aXMLEnd;
524 return true;
527 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */