/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include "UCBDeadPropertyValue.hxx" using namespace http_dav_ucp; using namespace ::com::sun::star; // static const OUString UCBDeadPropertyValue::aTypeString = "string"; const OUString UCBDeadPropertyValue::aTypeLong = "long"; const OUString UCBDeadPropertyValue::aTypeShort = "short"; const OUString UCBDeadPropertyValue::aTypeBoolean = "boolean"; const OUString UCBDeadPropertyValue::aTypeChar = "char"; const OUString UCBDeadPropertyValue::aTypeByte = "byte"; const OUString UCBDeadPropertyValue::aTypeHyper = "hyper"; const OUString UCBDeadPropertyValue::aTypeFloat = "float"; const OUString UCBDeadPropertyValue::aTypeDouble = "double"; // static const OUString UCBDeadPropertyValue::aXMLPre = ""; const OUString UCBDeadPropertyValue::aXMLMid = ""; const OUString UCBDeadPropertyValue::aXMLEnd = ""; /* #define STATE_TOP (1) #define STATE_UCBPROP (STATE_TOP) #define STATE_TYPE (STATE_TOP + 1) #define STATE_VALUE (STATE_TOP + 2) extern "C" int UCBDeadPropertyValue_startelement_callback( void *, int parent, const char * nspace, const char *name, const char ** ) { if ( name != 0 ) { switch ( parent ) { case NE_XML_STATEROOT: if ( strcmp( name, "ucbprop" ) == 0 ) return STATE_UCBPROP; break; case STATE_UCBPROP: if ( strcmp( name, "type" ) == 0 ) return STATE_TYPE; else if ( strcmp( name, "value" ) == 0 ) return STATE_VALUE; break; } } return NE_XML_DECLINE; } extern "C" int UCBDeadPropertyValue_chardata_callback( void *userdata, int state, const char *buf, size_t len ) { UCBDeadPropertyValueParseContext * pCtx = static_cast< UCBDeadPropertyValueParseContext * >( userdata ); switch ( state ) { case STATE_TYPE: SAL_WARN_IF( pCtx->pType, "ucb.ucp.webdav", "UCBDeadPropertyValue_endelement_callback - " "Type already set!" ); pCtx->pType = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); break; case STATE_VALUE: SAL_WARN_IF( pCtx->pValue, "ucb.ucp.webdav", "UCBDeadPropertyValue_endelement_callback - " "Value already set!" ); pCtx->pValue = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US ); break; } return 0; // zero to continue, non-zero to abort parsing } extern "C" int UCBDeadPropertyValue_endelement_callback( void *userdata, int state, const char *, const char * ) { UCBDeadPropertyValueParseContext * pCtx = static_cast< UCBDeadPropertyValueParseContext * >( userdata ); switch ( state ) { case STATE_TYPE: if ( !pCtx->pType ) return 1; // abort break; case STATE_VALUE: if ( !pCtx->pValue ) return 1; // abort break; case STATE_UCBPROP: if ( !pCtx->pType || ! pCtx->pValue ) return 1; // abort break; } return 0; // zero to continue, non-zero to abort parsing } */ static OUString encodeValue( const OUString & rValue ) { // Note: I do not use the usual & + < + > encoding, because // I want to prevent any XML parser from trying to 'understand' // the value. This caused problems: // Example: // - Unencoded property value: xstringx<z // PROPFIND: // - parser replaces < by > ==> error (not well formed) OUStringBuffer aResult; const sal_Unicode * pValue = rValue.getStr(); sal_Int32 nCount = rValue.getLength(); for ( sal_Int32 n = 0; n < nCount; ++n ) { const sal_Unicode c = pValue[ n ]; if ( '%' == c ) aResult.append( "%per;" ); else if ( '<' == c ) aResult.append( "%lt;" ); else if ( '>' == c ) aResult.append( "%gt;" ); else aResult.append( c ); } return aResult.makeStringAndClear(); } /* static OUString decodeValue( const OUString & rValue ) { OUStringBuffer aResult; const sal_Unicode * pValue = rValue.getStr(); sal_Int32 nPos = 0; sal_Int32 nEnd = rValue.getLength(); while ( nPos < nEnd ) { sal_Unicode c = pValue[ nPos ]; if ( '%' == c ) { nPos++; if ( nPos == nEnd ) { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } c = pValue[ nPos ]; if ( 'p' == c ) { // %per; if ( nPos > nEnd - 4 ) { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } if ( ( 'e' == pValue[ nPos + 1 ] ) && ( 'r' == pValue[ nPos + 2 ] ) && ( ';' == pValue[ nPos + 3 ] ) ) { aResult.append( '%' ); nPos += 3; } else { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } } else if ( 'l' == c ) { // %lt; if ( nPos > nEnd - 3 ) { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } if ( ( 't' == pValue[ nPos + 1 ] ) && ( ';' == pValue[ nPos + 2 ] ) ) { aResult.append( '<' ); nPos += 2; } else { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } } else if ( 'g' == c ) { // %gt; if ( nPos > nEnd - 3 ) { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } if ( ( 't' == pValue[ nPos + 1 ] ) && ( ';' == pValue[ nPos + 2 ] ) ) { aResult.append( '>' ); nPos += 2; } else { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } } else { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::decodeValue - syntax error!" ); return OUString(); } } else aResult.append( c ); nPos++; } return OUString( aResult ); } */ // static bool UCBDeadPropertyValue::supportsType( const uno::Type & rType ) { if ( ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) && ( rType != cppu::UnoType::get() ) ) { return false; } return true; } // static bool UCBDeadPropertyValue::createFromXML( const OString & /*rInData*/, uno::Any & /*rOutData*/ ) { bool success = false; /* ne_xml_parser * parser = ne_xml_create(); if ( parser ) { UCBDeadPropertyValueParseContext aCtx; ne_xml_push_handler( parser, UCBDeadPropertyValue_startelement_callback, UCBDeadPropertyValue_chardata_callback, UCBDeadPropertyValue_endelement_callback, &aCtx ); ne_xml_parse( parser, rInData.getStr(), rInData.getLength() ); success = !ne_xml_failed( parser ); ne_xml_destroy( parser ); if ( success ) { if ( aCtx.pType && aCtx.pValue ) { // Decode aCtx.pValue! It may contain XML reserved chars. OUString aStringValue = decodeValue( *aCtx.pValue ); if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) ) { rOutData <<= aStringValue; } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) ) { rOutData <<= aStringValue.toInt32(); } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) ) { rOutData <<= sal_Int16( aStringValue.toInt32() ); } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) ) { if ( aStringValue.equalsIgnoreAsciiCase( OUString( "true" ) ) ) rOutData <<= sal_Bool( sal_True ); else rOutData <<= sal_Bool( sal_False ); } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) ) { rOutData <<= aStringValue.toChar(); } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) ) { rOutData <<= sal_Int8( aStringValue.toChar() ); } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) ) { rOutData <<= aStringValue.toInt64(); } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) ) { rOutData <<= aStringValue.toFloat(); } else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) ) { rOutData <<= aStringValue.toDouble(); } else { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::createFromXML - " "Unsupported property type!" ); success = false; } } else success = false; } } */ return success; } // static bool UCBDeadPropertyValue::toXML( const uno::Any & rInData, OUString & rOutData ) { // the_typethe_value // Check property type. Extract type and value as string. const uno::Type& rType = rInData.getValueType(); OUString aStringValue; OUString aStringType; if ( rType == cppu::UnoType::get() ) { // string rInData >>= aStringValue; aStringType = aTypeString; } else if ( rType == cppu::UnoType::get() ) { // long sal_Int32 nValue = 0; rInData >>= nValue; aStringValue = OUString::number( nValue ); aStringType = aTypeLong; } else if ( rType == cppu::UnoType::get() ) { // short sal_Int32 nValue = 0; rInData >>= nValue; aStringValue = OUString::number( nValue ); aStringType = aTypeShort; } else if ( rType == cppu::UnoType::get() ) { // boolean bool bValue = false; rInData >>= bValue; aStringValue = OUString::boolean( bValue ); aStringType = aTypeBoolean; } else if ( rType == cppu::UnoType::get() ) { // char sal_Unicode cValue = 0; rInData >>= cValue; aStringValue = OUString( cValue ); aStringType = aTypeChar; } else if ( rType == cppu::UnoType::get() ) { // byte sal_Int8 nValue = 0; rInData >>= nValue; aStringValue = OUString( sal_Unicode( nValue ) ); aStringType = aTypeByte; } else if ( rType == cppu::UnoType::get() ) { // hyper sal_Int64 nValue = 0; rInData >>= nValue; aStringValue = OUString::number( nValue ); aStringType = aTypeHyper; } else if ( rType == cppu::UnoType::get() ) { // float float nValue = 0; rInData >>= nValue; aStringValue = OUString::number( nValue ); aStringType = aTypeFloat; } else if ( rType == cppu::UnoType::get() ) { // double double nValue = 0; rInData >>= nValue; aStringValue = OUString::number( nValue ); aStringType = aTypeDouble; } else { SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::toXML - " "Unsupported property type!" ); return false; } // Encode value! It must not contain XML reserved chars! aStringValue = encodeValue( aStringValue ); rOutData = aXMLPre; rOutData += aStringType; rOutData += aXMLMid; rOutData += aStringValue; rOutData += aXMLEnd; return true; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */