diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2021-10-22 20:52:48 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2021-11-01 18:57:19 +0100 |
commit | 68627126454762ddfb4605c0e58c634b54937ad0 (patch) | |
tree | 503b15b99a3bb7fe22669ff1297fe0cfbde24a49 /ucb/source | |
parent | 7110271f6a47dd19648864ad9e83e87a90f2d4fd (diff) |
ucb: webdav-curl: implement dead properties in PROPFIND/PROPPATCH
And delete a bunch of ghastly code.
Change-Id: I1a01bfda5f86202d537f87b97d83cc5c0a65ed0b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124079
Tested-by: Michael Stahl <michael.stahl@allotropia.de>
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'ucb/source')
-rw-r--r-- | ucb/source/ucp/webdav-curl/CurlSession.cxx | 18 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx | 403 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx | 12 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/webdavresponseparser.cxx | 50 |
4 files changed, 126 insertions, 357 deletions
diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx index 7c5bd5fe5973..e5dcd1a2ea3c 100644 --- a/ucb/source/ucp/webdav-curl/CurlSession.cxx +++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx @@ -11,6 +11,7 @@ #include "SerfLockStore.hxx" #include "DAVProperties.hxx" +#include "UCBDeadPropertyValue.hxx" #include "webdavresponseparser.hxx" #include <comphelper/attributelist.hxx> @@ -1354,9 +1355,6 @@ auto CurlSession::PROPPATCH(OUString const& rURIReference, CurlUri const uri(CurlProcessor::URIReferenceToURI(*this, rURIReference)); - //FIXME why does toXML encode stuff which parser ignores - //isUCBDeadProperty case not handled - // TODO: either set CURLOPT_INFILESIZE_LARGE or chunked? ::std::unique_ptr<curl_slist, deleter_from_fn<curl_slist_free_all>> pList( curl_slist_append(nullptr, "Transfer-Encoding: chunked")); @@ -1411,7 +1409,19 @@ auto CurlSession::PROPPATCH(OUString const& rURIReference, { if (DAVProperties::isUCBDeadProperty(name)) { - // TODO don't use UCBDeadPropertyValue::toXml, it's crazy + ::std::optional<::std::pair<OUString, OUString>> const oProp( + UCBDeadPropertyValue::toXML(rPropValue.value)); + if (oProp) + { + xWriter->startElement("ucbprop", nullptr); + xWriter->startElement("type", nullptr); + xWriter->characters(oProp->first); + xWriter->endElement("type"); + xWriter->startElement("value", nullptr); + xWriter->characters(oProp->second); + xWriter->endElement("value"); + xWriter->endElement("ucbprop"); + } } else { diff --git a/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx b/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx index 987662313cfd..4f3460a26785 100644 --- a/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx +++ b/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx @@ -37,267 +37,6 @@ constexpr OUStringLiteral aTypeFloat = u"float"; constexpr OUStringLiteral aTypeDouble = u"double"; // static -constexpr OUStringLiteral aXMLPre = u"<ucbprop><type>"; -constexpr OUStringLiteral aXMLMid = u"</type><value>"; -constexpr OUStringLiteral aXMLEnd = u"</value></ucbprop>"; - -/* - -#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: x<z - // PROPPATCH: - // - Encoded property value: x<z - // - UCBDeadPropertyValue::toXML result: - // <ucbprop><type>string</type><value>x<z</value></ucbprop> - // PROPFIND: - // - parser replaces < by > ==> error (not well formed) - - //FIXME this violates https://www.w3.org/TR/REC-xml/#indtd - 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<OUString>::get() ) @@ -326,94 +65,68 @@ bool UCBDeadPropertyValue::supportsType( const uno::Type & rType ) // static -bool UCBDeadPropertyValue::createFromXML( std::u16string_view /*rInData*/, - uno::Any & /*rOutData*/ ) +bool UCBDeadPropertyValue::createFromXML(OUString const& rType, + OUString const& rValue, + uno::Any & rOutData) { - bool success = false; + bool success = true; - /* - ne_xml_parser * parser = ne_xml_create(); - if ( parser ) + if (rType.equalsIgnoreAsciiCase(aTypeString)) { - 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 ) + rOutData <<= rValue; + } + else if (rType.equalsIgnoreAsciiCase(aTypeLong)) + { + rOutData <<= rValue.toInt32(); + } + else if (rType.equalsIgnoreAsciiCase(aTypeShort)) + { + rOutData <<= sal_Int16( rValue.toInt32() ); + } + else if (rType.equalsIgnoreAsciiCase(aTypeBoolean)) + { + if (rValue.equalsIgnoreAsciiCase(u"true")) + { + rOutData <<= true; + } + else { - 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; + rOutData <<= false; } } - */ + else if (rType.equalsIgnoreAsciiCase(aTypeChar)) + { + rOutData <<= rValue.toChar(); + } + else if (rType.equalsIgnoreAsciiCase(aTypeByte)) + { + rOutData <<= sal_Int8( rValue.toChar() ); + } + else if (rType.equalsIgnoreAsciiCase(aTypeHyper)) + { + rOutData <<= rValue.toInt64(); + } + else if (rType.equalsIgnoreAsciiCase(aTypeFloat)) + { + rOutData <<= rValue.toFloat(); + } + else if (rType.equalsIgnoreAsciiCase(aTypeDouble)) + { + rOutData <<= rValue.toDouble(); + } + else + { + SAL_WARN( "ucb.ucp.webdav", + "UCBDeadPropertyValue::createFromXML - " + "Unsupported property type!" ); + success = false; + } return success; } - // static -bool UCBDeadPropertyValue::toXML( const uno::Any & rInData, - OUString & rOutData ) +::std::optional<::std::pair<OUString, OUString>> +UCBDeadPropertyValue::toXML(const uno::Any & rInData) { // <ucbprop><type>the_type</type><value>the_value</value></ucbprop> @@ -498,18 +211,10 @@ bool UCBDeadPropertyValue::toXML( const uno::Any & rInData, SAL_WARN( "ucb.ucp.webdav", "UCBDeadPropertyValue::toXML - " "Unsupported property type!" ); - return false; + return {}; } - // Encode value! It must not contain XML reserved chars! - aStringValue = encodeValue( aStringValue ); - - rOutData = aXMLPre; - rOutData += aStringType; - rOutData += aXMLMid; - rOutData += aStringValue; - rOutData += aXMLEnd; - return true; + return { { aStringType, aStringValue } }; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx b/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx index c54d65c69573..8b696ed12da3 100644 --- a/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx +++ b/ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx @@ -20,6 +20,9 @@ #pragma once +#include <optional> +#include <utility> + #include <rtl/string.hxx> #include <com/sun/star/uno/Any.hxx> @@ -31,10 +34,11 @@ class UCBDeadPropertyValue public: static bool supportsType( const css::uno::Type & rType ); - static bool createFromXML( std::u16string_view rInData, - css::uno::Any & rOutData ); - static bool toXML( const css::uno::Any & rInData, - OUString & rOutData ); + static bool createFromXML(OUString const& rType, + OUString const& rValue, + css::uno::Any & rOutData); + static ::std::optional<::std::pair<OUString, OUString>> + toXML(const css::uno::Any & rInData); }; } diff --git a/ucb/source/ucp/webdav-curl/webdavresponseparser.cxx b/ucb/source/ucp/webdav-curl/webdavresponseparser.cxx index 4b6d0f848b66..478e9090990e 100644 --- a/ucb/source/ucp/webdav-curl/webdavresponseparser.cxx +++ b/ucb/source/ucp/webdav-curl/webdavresponseparser.cxx @@ -18,6 +18,10 @@ */ #include "webdavresponseparser.hxx" + +#include "DAVProperties.hxx" +#include "UCBDeadPropertyValue.hxx" + #include <com/sun/star/xml/sax/XDocumentHandler.hpp> #include <cppuhelper/implbase.hxx> #include <com/sun/star/xml/sax/Parser.hpp> @@ -33,6 +37,7 @@ #include <sal/log.hxx> using namespace com::sun::star; +using namespace http_dav_ucp; // WebDAVNamespace enum and StringToEnum converter @@ -92,6 +97,9 @@ namespace WebDAVName_getlastmodified, WebDAVName_creationdate, WebDAVName_getcontentlength, + WebDAVName_type, + WebDAVName_value, + WebDAVName_ucbprop, WebDAVName_last }; @@ -128,6 +136,9 @@ namespace aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString("getlastmodified"), WebDAVName_getlastmodified)); aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString("creationdate"), WebDAVName_creationdate)); aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString("getcontentlength"), WebDAVName_getcontentlength)); + aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString("type"), WebDAVName_type)); + aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString("value"), WebDAVName_value)); + aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString("ucbprop"), WebDAVName_ucbprop)); } const WebDAVNameMapper::const_iterator aResult(aWebDAVNameMapperList.find(rStr)); @@ -294,6 +305,8 @@ namespace WebDAVContext* mpContext; OUString maHref; OUString maStatus; + OUString m_UCBType; + OUString m_UCBValue; std::vector< http_dav_ucp::DAVPropertyValue > maResponseProperties; std::vector< http_dav_ucp::DAVPropertyValue > maPropStatProperties; std::vector< OUString > maResponseNames; @@ -794,6 +807,43 @@ namespace } case WebDAVNamespace_ucb_openoffice_org_dav_props: { + switch(mpContext->getWebDAVName()) + { + case WebDAVName_type: + { + m_UCBType = mpContext->getWhiteSpace(); + break; + } + case WebDAVName_value: + { + m_UCBValue = mpContext->getWhiteSpace(); + break; + } + case WebDAVName_ucbprop: + { + if (!m_UCBType.isEmpty() + && isCollectingProperties()) + { + http_dav_ucp::DAVPropertyValue aDAVPropertyValue; + OString const name(OUStringToOString(mpContext->getParent()->getName(), RTL_TEXTENCODING_UTF8)); + OString const nameSpace(OUStringToOString(mpContext->getParent()->getNamespace(), RTL_TEXTENCODING_UTF8)); + DAVProperties::createUCBPropName(nameSpace.getStr(), name.getStr(), aDAVPropertyValue.Name); + if (UCBDeadPropertyValue::createFromXML(m_UCBType, m_UCBValue, aDAVPropertyValue.Value)) + { + maPropStatProperties.push_back(aDAVPropertyValue); + } + else + { + SAL_INFO("ucb.ucp.webdav.curl", "cannot parse property value"); + } + } + m_UCBType.clear(); + m_UCBValue.clear(); + break; + } + default: + break; + } break; } } |