29#include <com/sun/star/xml/sax/Parser.hpp>
30#include <com/sun/star/xml/sax/InputSource.hpp>
31#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
32#include <com/sun/star/ucb/LockEntry.hpp>
33#include <com/sun/star/ucb/LockScope.hpp>
34#include <com/sun/star/ucb/LockType.hpp>
35#include <com/sun/star/ucb/Lock.hpp>
37#include <unordered_map>
52 WebDAVNamespace_unknown = 0,
54 WebDAVNamespace_ucb_openoffice_org_dav_props,
59 WebDAVNamespace StrToWebDAVNamespace(::std::u16string_view rStr)
63 return WebDAVNamespace_DAV;
65 else if (rStr == u
"http://ucb.openoffice.org/dav/props/")
67 return WebDAVNamespace_ucb_openoffice_org_dav_props;
70 return WebDAVNamespace_unknown;
79 WebDAVName_unknown = 0,
80 WebDAVName_activelock,
81 WebDAVName_lockdiscovery,
82 WebDAVName_multistatus,
87 WebDAVName_resourcetype,
88 WebDAVName_collection,
89 WebDAVName_getcontenttype,
90 WebDAVName_supportedlock,
102 WebDAVName_getlastmodified,
103 WebDAVName_creationdate,
104 WebDAVName_getcontentlength,
112 WebDAVName StrToWebDAVName(
const OUString& rStr)
114 typedef std::unordered_map< OUString, WebDAVName > WebDAVNameMapper;
115 typedef std::pair< OUString, WebDAVName > WebDAVNameValueType;
116 static WebDAVNameMapper aWebDAVNameMapperList;
118 if(aWebDAVNameMapperList.empty())
120 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"activelock"), WebDAVName_activelock));
121 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"lockdiscovery"), WebDAVName_lockdiscovery));
122 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"multistatus"), WebDAVName_multistatus));
123 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"response"), WebDAVName_response));
124 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"href"), WebDAVName_href));
125 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"propstat"), WebDAVName_propstat));
126 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"prop"), WebDAVName_prop));
127 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"resourcetype"), WebDAVName_resourcetype));
128 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"collection"), WebDAVName_collection));
129 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"getcontenttype"), WebDAVName_getcontenttype));
130 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"supportedlock"), WebDAVName_supportedlock));
131 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"lockentry"), WebDAVName_lockentry));
132 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"lockscope"), WebDAVName_lockscope));
133 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"depth"), WebDAVName_depth));
134 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"locktoken"), WebDAVName_locktoken));
135 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"exclusive"), WebDAVName_exclusive));
136 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"locktype"), WebDAVName_locktype));
137 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"owner"), WebDAVName_owner));
138 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"timeout"), WebDAVName_timeout));
139 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"write"), WebDAVName_write));
140 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"shared"), WebDAVName_shared));
141 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"status"), WebDAVName_status));
142 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"getlastmodified"), WebDAVName_getlastmodified));
143 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"creationdate"), WebDAVName_creationdate));
144 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"getcontentlength"), WebDAVName_getcontentlength));
145 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"type"), WebDAVName_type));
146 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"value"), WebDAVName_value));
147 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"ucbprop"), WebDAVName_ucbprop));
150 const WebDAVNameMapper::const_iterator aResult(aWebDAVNameMapperList.find(rStr));
152 if(aResult == aWebDAVNameMapperList.end())
154 return WebDAVName_unknown;
158 return aResult->second;
168 typedef std::map< OUString, OUString > NamespaceMap;
174 NamespaceMap maNamespaceMap;
175 OUString maWhiteSpace;
177 OUString maNamespace;
180 WebDAVNamespace maWebDAVNamespace;
181 WebDAVName maWebDAVName;
184 void parseForNamespaceTokens(
const uno::Reference< xml::sax::XAttributeList >& xAttribs);
185 OUString mapNamespaceToken(
const OUString& rToken)
const;
186 void splitName(
const OUString& rSource);
189 WebDAVContext(WebDAVContext* pParent,
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs);
191 WebDAVContext* getParent()
const {
return mpParent; }
192 OUString& getWhiteSpace() {
return maWhiteSpace; }
193 void setWhiteSpace(
const OUString& rNew) { maWhiteSpace = rNew; }
195 const OUString& getNamespace()
const {
return maNamespace; }
196 const OUString& getName()
const {
return maName; }
197 const WebDAVNamespace& getWebDAVNamespace()
const {
return maWebDAVNamespace; }
198 const WebDAVName& getWebDAVName()
const {
return maWebDAVName; }
201 void WebDAVContext::parseForNamespaceTokens(
const uno::Reference< xml::sax::XAttributeList >& xAttribs)
203 const sal_Int16
nAttributes(xAttribs->getLength());
207 const OUString
aName(xAttribs->getNameByIndex(a));
208 const sal_Int32 nLen(
aName.getLength());
212 if(
aName.startsWith(
"xmlns"))
216 if(-1 != nIndex && nIndex + 1 < nLen)
218 const OUString aToken(
aName.copy(nIndex + 1));
220 maNamespaceMap.emplace(aToken, xAttribs->getValueByIndex(a));
227 OUString WebDAVContext::mapNamespaceToken(
const OUString& rToken)
const
229 NamespaceMap::const_iterator iter = maNamespaceMap.find(rToken);
231 if(maNamespaceMap.end() == iter)
235 return getParent()->mapNamespaceToken(rToken);
244 return (*iter).second;
248 void WebDAVContext::splitName(
const OUString& rSource)
250 const sal_Int32 nLen(rSource.getLength());
256 const sal_Int32
nIndex(rSource.indexOf(
':', 0));
258 if(nIndex > 0 && ((nIndex + 1) < nLen))
260 maNamespace = mapNamespaceToken(rSource.copy(0, nIndex));
261 maName = rSource.copy(nIndex + 1);
266 WebDAVContext::WebDAVContext(WebDAVContext* pParent,
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs)
272 maWebDAVNamespace(WebDAVNamespace_unknown),
273 maWebDAVName(WebDAVName_unknown)
275 const sal_Int16
nAttributes(xAttribs->getLength());
280 parseForNamespaceTokens(xAttribs);
287 maWebDAVNamespace = StrToWebDAVNamespace(maNamespace);
288 maWebDAVName = StrToWebDAVName(maName);
297 enum WebDAVResponseParserMode
299 WebDAVResponseParserMode_PropFind = 0,
300 WebDAVResponseParserMode_PropName,
301 WebDAVResponseParserMode_Lock
304 class WebDAVResponseParser :
public cppu::WeakImplHelper< css::xml::sax::XDocumentHandler >
307 std::vector< ucb::Lock > maResult_Lock;
308 std::vector< http_dav_ucp::DAVResource > maResult_PropFind;
309 std::vector< http_dav_ucp::DAVResourceInfo > maResult_PropName;
316 std::vector< http_dav_ucp::DAVPropertyValue > maResponseProperties;
317 std::vector< http_dav_ucp::DAVPropertyValue > maPropStatProperties;
318 std::vector< OUString > maResponseNames;
319 std::vector< OUString > maPropStatNames;
320 uno::Sequence< ucb::LockEntry > maLockEntries;
321 ucb::LockScope maLockScope;
322 ucb::LockType maLockType;
324 WebDAVResponseParserMode meWebDAVResponseParserMode;
326 bool mbResourceTypeCollection : 1;
327 bool mbLockScopeSet : 1;
328 bool mbLockTypeSet : 1;
331 bool whitespaceIsAvailable()
const
335 bool hasParent(WebDAVName aWebDAVName)
const
339 bool propertyIsReady()
const
341 return hasParent(WebDAVName_prop) && whitespaceIsAvailable();
343 bool isCollectingProperties()
const
345 return WebDAVResponseParserMode_PropFind == meWebDAVResponseParserMode;
347 bool isCollectingPropNames()
const
349 return WebDAVResponseParserMode_PropName == meWebDAVResponseParserMode;
351 bool collectThisPropertyAsName()
const
353 return isCollectingPropNames() && hasParent(WebDAVName_prop);
365 SAL_WARN(
"ucb.ucp.webdav",
"Parser context pop without context (!)");
370 explicit WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode);
371 virtual ~WebDAVResponseParser()
override;
374 virtual void SAL_CALL startDocument( )
override;
375 virtual void SAL_CALL endDocument( )
override;
376 virtual void SAL_CALL startElement(
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs )
override;
377 virtual void SAL_CALL endElement(
const OUString& aName )
override;
378 virtual void SAL_CALL characters(
const OUString& aChars )
override;
379 virtual void SAL_CALL ignorableWhitespace(
const OUString& aWhitespaces )
override;
380 virtual void SAL_CALL processingInstruction(
const OUString& aTarget,
const OUString& aData )
override;
381 virtual void SAL_CALL setDocumentLocator(
const uno::Reference< xml::sax::XLocator >& xLocator )
override;
383 const std::vector< ucb::Lock >& getResult_Lock()
const {
return maResult_Lock; }
384 const std::vector< http_dav_ucp::DAVResource >& getResult_PropFind()
const {
return maResult_PropFind; }
385 const std::vector< http_dav_ucp::DAVResourceInfo >& getResult_PropName()
const {
return maResult_PropName; }
388 WebDAVResponseParser::WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode)
389 : maResult_PropFind(),
394 maResponseProperties(),
395 maPropStatProperties(),
399 maLockScope(
ucb::LockScope_EXCLUSIVE),
400 maLockType(
ucb::LockType_WRITE),
401 meWebDAVResponseParserMode(eWebDAVResponseParserMode),
402 mbResourceTypeCollection(false),
403 mbLockScopeSet(false),
408 WebDAVResponseParser::~WebDAVResponseParser()
410 SAL_WARN_IF(mpContext,
"ucb.ucp.webdav",
"Parser destructed with existing content (!)");
417 void SAL_CALL WebDAVResponseParser::startDocument( )
419 SAL_WARN_IF(mpContext,
"ucb.ucp.webdav",
"Parser start with existing content (!)");
422 void SAL_CALL WebDAVResponseParser::endDocument( )
424 SAL_WARN_IF(mpContext,
"ucb.ucp.webdav",
"Parser end with existing content (!)");
427 void SAL_CALL WebDAVResponseParser::startElement(
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs )
429 const sal_Int32 nLen(
aName.getLength());
434 mpContext =
new WebDAVContext(mpContext, aName, xAttribs);
436 if(collectThisPropertyAsName())
449 case WebDAVNamespace_DAV:
457 case WebDAVName_propstat:
460 if(isCollectingProperties())
463 maPropStatProperties.clear();
468 maPropStatNames.clear();
472 case WebDAVName_response:
478 if(isCollectingProperties())
481 maResponseProperties.clear();
486 maResponseNames.clear();
490 case WebDAVName_resourcetype:
493 mbResourceTypeCollection =
false;
496 case WebDAVName_supportedlock:
499 maLockEntries.realloc(0);
502 case WebDAVName_lockentry:
505 mbLockScopeSet =
false;
506 mbLockTypeSet =
false;
509 case WebDAVName_activelock:
511 maLock = ucb::Lock();
517 case WebDAVNamespace_ucb_openoffice_org_dav_props:
526 OUString MakePropertyName(WebDAVContext
const& rContext)
530 OString
const nameSpace(
OUStringToOString(rContext.getNamespace(), RTL_TEXTENCODING_UTF8));
531 DAVProperties::createUCBPropName(nameSpace.getStr(),
name.getStr(), ret);
535 void SAL_CALL WebDAVResponseParser::endElement(
const OUString& aName )
537 const sal_Int32 nLen(
aName.getLength());
538 SAL_WARN_IF(!mpContext,
"ucb.ucp.webdav",
"Parser EndElement without content (!)");
540 if(mpContext && nLen)
542 if(collectThisPropertyAsName())
545 OUString
const name(MakePropertyName(*mpContext));
546 maPropStatNames.emplace_back(name);
556 case WebDAVNamespace_DAV:
564 case WebDAVName_href:
567 if(whitespaceIsAvailable())
573 maHref = ::rtl::Uri::encode(
mpContext->getWhiteSpace(),
574 rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes,
575 RTL_TEXTENCODING_UTF8);
579 case WebDAVName_status:
582 if(whitespaceIsAvailable())
588 case WebDAVName_getlastmodified:
591 if(propertyIsReady())
595 aDAVPropertyValue.
Name =
"DAV:getlastmodified";
597 maPropStatProperties.push_back(aDAVPropertyValue);
601 case WebDAVName_creationdate:
604 if(propertyIsReady())
608 aDAVPropertyValue.
Name =
"DAV:creationdate";
610 maPropStatProperties.push_back(aDAVPropertyValue);
614 case WebDAVName_collection:
617 if(hasParent(WebDAVName_resourcetype))
619 mbResourceTypeCollection =
true;
623 case WebDAVName_resourcetype:
626 if(hasParent(WebDAVName_prop))
630 aDAVPropertyValue.
Name =
"DAV:resourcetype";
631 aDAVPropertyValue.
Value <<= (mbResourceTypeCollection ? OUString(
"collection") : OUString());
632 maPropStatProperties.push_back(aDAVPropertyValue);
636 case WebDAVName_getcontentlength:
639 if(propertyIsReady())
643 aDAVPropertyValue.
Name =
"DAV:getcontentlength";
645 maPropStatProperties.push_back(aDAVPropertyValue);
649 case WebDAVName_getcontenttype:
652 if(propertyIsReady())
656 aDAVPropertyValue.
Name =
"DAV:getcontenttype";
658 maPropStatProperties.push_back(aDAVPropertyValue);
662 case WebDAVName_supportedlock:
665 if(hasParent(WebDAVName_prop) && maLockEntries.hasElements())
669 aDAVPropertyValue.
Name =
"DAV:supportedlock";
670 aDAVPropertyValue.
Value <<= maLockEntries;
671 maPropStatProperties.push_back(aDAVPropertyValue);
675 case WebDAVName_lockentry:
678 if(hasParent(WebDAVName_supportedlock) && (mbLockScopeSet && mbLockTypeSet))
680 const sal_Int32
nLength(maLockEntries.getLength());
681 ucb::LockEntry aEntry;
683 aEntry.Scope = maLockScope;
684 aEntry.Type = maLockType;
685 maLockEntries.realloc(nLength + 1);
686 maLockEntries.getArray()[
nLength] = aEntry;
690 case WebDAVName_owner:
692 maLock.Owner <<=
mpContext->getWhiteSpace();
695 case WebDAVName_timeout:
697 const OUString sTimeout(
mpContext->getWhiteSpace());
698 if (sTimeout ==
"Infinite")
700 else if (sTimeout.startsWith(
"Second-"))
704 case WebDAVName_locktoken:
706 const OUString sLockToken(maHref);
707 SAL_WARN_IF(!sLockToken.startsWith(
"opaquelocktoken:"),
"ucb.ucp.webdav",
708 "Parser error: wrong 'locktoken' value.");
709 const sal_Int32
nLength(maLock.LockTokens.getLength());
710 maLock.LockTokens.realloc(nLength+1);
711 maLock.LockTokens.getArray()[
nLength] = sLockToken;
714 case WebDAVName_exclusive:
717 if(hasParent(WebDAVName_lockscope))
719 maLockScope = ucb::LockScope_EXCLUSIVE;
720 mbLockScopeSet =
true;
724 case WebDAVName_shared:
727 if(hasParent(WebDAVName_lockscope))
729 maLockScope = ucb::LockScope_SHARED;
730 mbLockScopeSet =
true;
734 case WebDAVName_write:
737 if(hasParent(WebDAVName_locktype))
739 maLockType = ucb::LockType_WRITE;
740 mbLockTypeSet =
true;
744 case WebDAVName_depth:
746 OUString
const chars(
mpContext->getWhiteSpace());
749 maLock.Depth = ucb::LockDepth_ZERO;
751 else if (chars ==
"1")
753 maLock.Depth = ucb::LockDepth_ONE;
755 else if (chars ==
"infinity")
757 maLock.Depth = ucb::LockDepth_INFINITY;
761 case WebDAVName_activelock:
763 maLock.Type = maLockType;
764 maLock.Scope = maLockScope;
765 maResult_Lock.push_back(maLock);
768 case WebDAVName_lockdiscovery:
772 if (isCollectingProperties())
776 aDAVPropertyValue.
Name =
"DAV:lockdiscovery";
777 aDAVPropertyValue.
Value <<= ::comphelper::containerToSequence(maResult_Lock);
778 maPropStatProperties.push_back(aDAVPropertyValue);
782 case WebDAVName_propstat:
785 if(maStatus.getLength())
787 if(maStatus ==
"HTTP/1.1 200 OK")
789 if(isCollectingProperties())
791 if(!maPropStatProperties.empty())
794 maResponseProperties.insert(maResponseProperties.end(), maPropStatProperties.begin(), maPropStatProperties.end());
799 if(!maPropStatNames.empty())
802 maResponseNames.insert(maResponseNames.end(), maPropStatNames.begin(), maPropStatNames.end());
809 case WebDAVName_response:
812 if(maHref.getLength())
814 if(isCollectingProperties())
817 if(!maResponseProperties.empty())
821 aDAVResource.
uri = maHref;
822 aDAVResource.
properties = maResponseProperties;
823 maResult_PropFind.push_back(aDAVResource);
829 if(!maResponseNames.empty())
833 aDAVResourceInfo.
properties = maResponseNames;
834 maResult_PropName.push_back(aDAVResourceInfo);
843 case WebDAVNamespace_ucb_openoffice_org_dav_props:
847 case WebDAVName_type:
852 case WebDAVName_value:
857 case WebDAVName_ucbprop:
859 if (!m_UCBType.isEmpty()
860 && isCollectingProperties())
863 aDAVPropertyValue.
Name = MakePropertyName(*
mpContext->getParent());
864 if (UCBDeadPropertyValue::createFromXML(m_UCBType, m_UCBValue, aDAVPropertyValue.
Value))
866 maPropStatProperties.push_back(aDAVPropertyValue);
870 SAL_INFO(
"ucb.ucp.webdav.curl",
"cannot parse property value");
890 void SAL_CALL WebDAVResponseParser::characters(
const OUString& aChars )
893 SAL_WARN_IF(!mpContext,
"ucb.ucp.webdav",
"Parser characters without content (!)");
894 const sal_Int32 nLen(aChars.getLength());
896 if(mpContext && nLen)
899 const OUString aTrimmedChars(aChars.trim());
901 if(aTrimmedChars.getLength())
903 OUString aNew(
mpContext->getWhiteSpace());
911 aNew += aTrimmedChars;
917 void SAL_CALL WebDAVResponseParser::ignorableWhitespace(
const OUString& )
921 void SAL_CALL WebDAVResponseParser::processingInstruction(
const OUString& ,
const OUString& )
925 void SAL_CALL WebDAVResponseParser::setDocumentLocator(
const uno::Reference< xml::sax::XLocator >& )
936 void parseWebDAVResponse(
937 const uno::Reference< io::XInputStream >& xInputStream,
938 std::vector< T >& rResult,
939 WebDAVResponseParserMode eWebDAVResponseParserMode,
940 std::vector<T>
const & (WebDAVResponseParser::* fn)()
const)
942 if(xInputStream.is())
947 xml::sax::InputSource myInputSource;
948 myInputSource.aInputStream = xInputStream;
951 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(
956 new WebDAVResponseParser(eWebDAVResponseParserMode));
957 uno::Reference< xml::sax::XDocumentHandler > xWebDAVHdl(pWebDAVResponseParser);
958 xParser->setDocumentHandler(xWebDAVHdl);
961 xParser->parseStream(myInputSource);
964 rResult = (pWebDAVResponseParser.get()->*fn)();
966 catch(uno::Exception&)
968 SAL_WARN(
"ucb.ucp.webdav",
"WebDAV Parse error (!)");
981 std::vector< ucb::Lock > aResult;
982 parseWebDAVResponse< ucb::Lock >(xInputStream, aResult, WebDAVResponseParserMode_Lock, &WebDAVResponseParser::getResult_Lock);
988 std::vector< DAVResource > aResult;
989 parseWebDAVResponse< DAVResource >(xInputStream, aResult, WebDAVResponseParserMode_PropFind, &WebDAVResponseParser::getResult_PropFind);
995 std::vector< DAVResourceInfo > aResult;
996 parseWebDAVResponse< DAVResourceInfo >(xInputStream, aResult, WebDAVResponseParserMode_PropName, &WebDAVResponseParser::getResult_PropName);
RegionData_Impl * mpParent
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
Reference< XComponentContext > getProcessComponentContext()
std::vector< ucb::Lock > parseWebDAVLockResponse(const uno::Reference< io::XInputStream > &xInputStream)
std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream > &xInputStream)
std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream > &xInputStream)
sal_Int64 toInt64(std::u16string_view str, sal_Int16 radix=10)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
ParserContextSharedPtr mpContext
std::vector< OUString > properties
std::vector< DAVPropertyValue > properties