summaryrefslogtreecommitdiff
path: root/ucb/source
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-10-22 20:52:48 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2021-11-01 18:57:19 +0100
commit68627126454762ddfb4605c0e58c634b54937ad0 (patch)
tree503b15b99a3bb7fe22669ff1297fe0cfbde24a49 /ucb/source
parent7110271f6a47dd19648864ad9e83e87a90f2d4fd (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.cxx18
-rw-r--r--ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx403
-rw-r--r--ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx12
-rw-r--r--ucb/source/ucp/webdav-curl/webdavresponseparser.cxx50
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 &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 )
{
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;
}
}