ucb/source/ucp/webdav-curl/CurlSession.cxx          |   18 
 ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx |  403 ++------------------
 ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx |   12 
 ucb/source/ucp/webdav-curl/webdavresponseparser.cxx |   50 ++
 4 files changed, 126 insertions(+), 357 deletions(-)

New commits:
commit 68627126454762ddfb4605c0e58c634b54937ad0
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Oct 22 20:52:48 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Nov 1 18:57:19 2021 +0100

    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.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

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
@@ -36,267 +36,6 @@ constexpr OUStringLiteral aTypeHyper = u"hyper";
 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 &amp; + &lt; + &gt; 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&lt;z
-    //       - UCBDeadPropertyValue::toXML result:
-    //              <ucbprop><type>string</type><value>x&lt;z</value></ucbprop>
-    //       PROPFIND:
-    //       - parser replaces &lt; 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 )
 {
@@ -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;
                     }
                 }

Reply via email to