21 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
23 #include <com/sun/star/xml/sax/Parser.hpp>
24 #include <com/sun/star/xml/sax/InputSource.hpp>
26 #include <com/sun/star/ucb/LockEntry.hpp>
27 #include <com/sun/star/ucb/LockScope.hpp>
28 #include <com/sun/star/ucb/LockType.hpp>
29 #include <com/sun/star/ucb/Lock.hpp>
31 #include <unordered_map>
42 WebDAVNamespace_unknown = 0,
44 WebDAVNamespace_ucb_openoffice_org_dav_props,
53 return WebDAVNamespace_DAV;
55 else if(rStr ==
"http://ucb.openoffice.org/dav/props/")
57 return WebDAVNamespace_ucb_openoffice_org_dav_props;
60 return WebDAVNamespace_unknown;
69 WebDAVName_unknown = 0,
70 WebDAVName_activelock,
71 WebDAVName_multistatus,
76 WebDAVName_resourcetype,
77 WebDAVName_collection,
78 WebDAVName_getcontenttype,
79 WebDAVName_supportedlock,
90 WebDAVName_getlastmodified,
91 WebDAVName_creationdate,
92 WebDAVName_getcontentlength,
97 WebDAVName StrToWebDAVName(
const OUString& rStr)
99 typedef std::unordered_map< OUString, WebDAVName > WebDAVNameMapper;
100 typedef std::pair< OUString, WebDAVName > WebDAVNameValueType;
101 static WebDAVNameMapper aWebDAVNameMapperList;
103 if(aWebDAVNameMapperList.empty())
105 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"activelock"), WebDAVName_activelock));
106 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"multistatus"), WebDAVName_multistatus));
107 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"response"), WebDAVName_response));
108 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"href"), WebDAVName_href));
109 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"propstat"), WebDAVName_propstat));
110 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"prop"), WebDAVName_prop));
111 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"resourcetype"), WebDAVName_resourcetype));
112 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"collection"), WebDAVName_collection));
113 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"getcontenttype"), WebDAVName_getcontenttype));
114 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"supportedlock"), WebDAVName_supportedlock));
115 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"lockentry"), WebDAVName_lockentry));
116 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"lockscope"), WebDAVName_lockscope));
117 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"locktoken"), WebDAVName_locktoken));
118 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"exclusive"), WebDAVName_exclusive));
119 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"locktype"), WebDAVName_locktype));
120 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"owner"), WebDAVName_owner));
121 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"timeout"), WebDAVName_timeout));
122 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"write"), WebDAVName_write));
123 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"shared"), WebDAVName_shared));
124 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"status"), WebDAVName_status));
125 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"getlastmodified"), WebDAVName_getlastmodified));
126 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"creationdate"), WebDAVName_creationdate));
127 aWebDAVNameMapperList.insert(WebDAVNameValueType(OUString(
"getcontentlength"), WebDAVName_getcontentlength));
130 const WebDAVNameMapper::const_iterator aResult(aWebDAVNameMapperList.find(rStr));
132 if(aResult == aWebDAVNameMapperList.end())
134 return WebDAVName_unknown;
138 return aResult->second;
148 typedef std::map< OUString, OUString > NamespaceMap;
154 NamespaceMap maNamespaceMap;
155 OUString maWhiteSpace;
157 OUString maNamespace;
164 void parseForNamespaceTokens(
const uno::Reference< xml::sax::XAttributeList >& xAttribs);
165 OUString mapNamespaceToken(
const OUString& rToken)
const;
166 void splitName(
const OUString& rSource);
169 WebDAVContext(WebDAVContext* pParent,
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs);
171 WebDAVContext* getParent()
const {
return mpParent; }
172 OUString& getWhiteSpace() {
return maWhiteSpace; }
173 void setWhiteSpace(
const OUString& rNew) { maWhiteSpace = rNew; }
175 const OUString& getNamespace()
const {
return maNamespace; }
176 const OUString& getName()
const {
return maName; }
177 const WebDAVNamespace& getWebDAVNamespace()
const {
return maWebDAVNamespace; }
178 const WebDAVName& getWebDAVName()
const {
return maWebDAVName; }
181 void WebDAVContext::parseForNamespaceTokens(
const uno::Reference< xml::sax::XAttributeList >& xAttribs)
183 const sal_Int16
nAttributes(xAttribs->getLength());
187 const OUString
aName(xAttribs->getNameByIndex(a));
188 const sal_Int32 nLen(
aName.getLength());
192 if(
aName.startsWith(
"xmlns"))
196 if(-1 != nIndex && nIndex + 1 < nLen)
198 const OUString aToken(
aName.copy(nIndex + 1));
200 maNamespaceMap.emplace(aToken, xAttribs->getValueByIndex(a));
207 OUString WebDAVContext::mapNamespaceToken(
const OUString& rToken)
const
209 NamespaceMap::const_iterator iter = maNamespaceMap.find(rToken);
211 if(maNamespaceMap.end() == iter)
215 return getParent()->mapNamespaceToken(rToken);
224 return (*iter).second;
228 void WebDAVContext::splitName(
const OUString& rSource)
230 const sal_Int32 nLen(rSource.getLength());
236 const sal_Int32
nIndex(rSource.indexOf(
':', 0));
238 if(nIndex > 0 && ((nIndex + 1) < nLen))
240 maNamespace = mapNamespaceToken(rSource.copy(0, nIndex));
241 maName = rSource.copy(nIndex + 1);
246 WebDAVContext::WebDAVContext(WebDAVContext* pParent,
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs)
252 maWebDAVNamespace(WebDAVNamespace_unknown),
253 maWebDAVName(WebDAVName_unknown)
255 const sal_Int16 nAttributes(xAttribs->getLength());
260 parseForNamespaceTokens(xAttribs);
267 maWebDAVNamespace = StrToWebDAVNamespace(maNamespace);
268 maWebDAVName = StrToWebDAVName(maName);
279 WebDAVResponseParserMode_PropFind = 0,
280 WebDAVResponseParserMode_PropName,
281 WebDAVResponseParserMode_Lock
284 class WebDAVResponseParser :
public cppu::WeakImplHelper< css::xml::sax::XDocumentHandler >
287 std::vector< ucb::Lock > maResult_Lock;
288 std::vector< http_dav_ucp::DAVResource > maResult_PropFind;
289 std::vector< http_dav_ucp::DAVResourceInfo > maResult_PropName;
294 std::vector< http_dav_ucp::DAVPropertyValue > maResponseProperties;
295 std::vector< http_dav_ucp::DAVPropertyValue > maPropStatProperties;
296 std::vector< OUString > maResponseNames;
297 std::vector< OUString > maPropStatNames;
298 uno::Sequence< ucb::LockEntry > maLockEntries;
299 ucb::LockScope maLockScope;
300 ucb::LockType maLockType;
304 bool mbResourceTypeCollection : 1;
305 bool mbLockScopeSet : 1;
306 bool mbLockTypeSet : 1;
309 bool whitespaceIsAvailable()
const
311 return mpContext && mpContext->getWhiteSpace().getLength();
315 return mpContext && mpContext->getParent() && aWebDAVName == mpContext->getParent()->getWebDAVName();
317 bool propertyIsReady()
const
319 return hasParent(WebDAVName_prop) && whitespaceIsAvailable();
321 bool isCollectingProperties()
const
323 return WebDAVResponseParserMode_PropFind == meWebDAVResponseParserMode;
325 bool isCollectingPropNames()
const
327 return WebDAVResponseParserMode_PropName == meWebDAVResponseParserMode;
329 bool collectThisPropertyAsName()
const
331 return isCollectingPropNames() && hasParent(WebDAVName_prop);
337 WebDAVContext* pTemp = mpContext;
338 mpContext = mpContext->getParent();
343 SAL_WARN(
"ucb.ucp.webdav",
"Parser context pop without context (!)");
349 virtual ~WebDAVResponseParser()
override;
352 virtual void SAL_CALL startDocument( )
override;
353 virtual void SAL_CALL endDocument( )
override;
354 virtual void SAL_CALL startElement(
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs )
override;
355 virtual void SAL_CALL endElement(
const OUString& aName )
override;
356 virtual void SAL_CALL characters(
const OUString& aChars )
override;
357 virtual void SAL_CALL ignorableWhitespace(
const OUString& aWhitespaces )
override;
358 virtual void SAL_CALL processingInstruction(
const OUString& aTarget,
const OUString&
aData )
override;
359 virtual void SAL_CALL setDocumentLocator(
const uno::Reference< xml::sax::XLocator >& xLocator )
override;
361 const std::vector< ucb::Lock >& getResult_Lock()
const {
return maResult_Lock; }
362 const std::vector< http_dav_ucp::DAVResource >& getResult_PropFind()
const {
return maResult_PropFind; }
363 const std::vector< http_dav_ucp::DAVResourceInfo >& getResult_PropName()
const {
return maResult_PropName; }
367 : maResult_PropFind(),
372 maResponseProperties(),
373 maPropStatProperties(),
377 maLockScope(
ucb::LockScope_EXCLUSIVE),
378 maLockType(
ucb::LockType_WRITE),
379 meWebDAVResponseParserMode(eWebDAVResponseParserMode),
380 mbResourceTypeCollection(false),
381 mbLockScopeSet(false),
386 WebDAVResponseParser::~WebDAVResponseParser()
388 SAL_WARN_IF(mpContext,
"ucb.ucp.webdav",
"Parser destructed with existing content (!)");
395 void SAL_CALL WebDAVResponseParser::startDocument( )
397 SAL_WARN_IF(mpContext,
"ucb.ucp.webdav",
"Parser start with existing content (!)");
400 void SAL_CALL WebDAVResponseParser::endDocument( )
402 SAL_WARN_IF(mpContext,
"ucb.ucp.webdav",
"Parser end with existing content (!)");
405 void SAL_CALL WebDAVResponseParser::startElement(
const OUString& aName,
const uno::Reference< xml::sax::XAttributeList >& xAttribs )
407 const sal_Int32 nLen(aName.getLength());
412 mpContext =
new WebDAVContext(mpContext, aName, xAttribs);
414 if(collectThisPropertyAsName())
421 switch(mpContext->getWebDAVNamespace())
427 case WebDAVNamespace_DAV:
429 switch(mpContext->getWebDAVName())
435 case WebDAVName_propstat:
438 if(isCollectingProperties())
441 maPropStatProperties.clear();
446 maPropStatNames.clear();
450 case WebDAVName_response:
456 if(isCollectingProperties())
459 maResponseProperties.clear();
464 maResponseNames.clear();
468 case WebDAVName_resourcetype:
471 mbResourceTypeCollection =
false;
474 case WebDAVName_supportedlock:
477 maLockEntries.realloc(0);
480 case WebDAVName_lockentry:
483 mbLockScopeSet =
false;
484 mbLockTypeSet =
false;
487 case WebDAVName_activelock:
489 maLock = ucb::Lock();
495 case WebDAVNamespace_ucb_openoffice_org_dav_props:
504 void SAL_CALL WebDAVResponseParser::endElement(
const OUString& aName )
506 const sal_Int32 nLen(aName.getLength());
507 SAL_WARN_IF(!mpContext,
"ucb.ucp.webdav",
"Parser EndElement without content (!)");
509 if(mpContext && nLen)
511 if(collectThisPropertyAsName())
515 maPropStatNames.push_back(mpContext->getNamespace() + mpContext->getName());
519 switch(mpContext->getWebDAVNamespace())
525 case WebDAVNamespace_DAV:
527 switch(mpContext->getWebDAVName())
533 case WebDAVName_href:
536 if(whitespaceIsAvailable())
538 maHref = mpContext->getWhiteSpace();
542 case WebDAVName_status:
545 if(whitespaceIsAvailable())
547 maStatus = mpContext->getWhiteSpace();
551 case WebDAVName_getlastmodified:
554 if(propertyIsReady())
558 aDAVPropertyValue.
Name =
"DAV:getlastmodified";
559 aDAVPropertyValue.
Value <<= mpContext->getWhiteSpace();
560 maPropStatProperties.push_back(aDAVPropertyValue);
564 case WebDAVName_creationdate:
567 if(propertyIsReady())
571 aDAVPropertyValue.
Name =
"DAV:creationdate";
572 aDAVPropertyValue.
Value <<= mpContext->getWhiteSpace();
573 maPropStatProperties.push_back(aDAVPropertyValue);
577 case WebDAVName_collection:
580 if(hasParent(WebDAVName_resourcetype))
582 mbResourceTypeCollection =
true;
586 case WebDAVName_resourcetype:
589 if(hasParent(WebDAVName_prop))
593 aDAVPropertyValue.
Name =
"DAV:resourcetype";
594 aDAVPropertyValue.
Value <<= (mbResourceTypeCollection ? OUString(
"collection") : OUString());
595 maPropStatProperties.push_back(aDAVPropertyValue);
599 case WebDAVName_getcontentlength:
602 if(propertyIsReady())
606 aDAVPropertyValue.
Name =
"DAV:getcontentlength";
607 aDAVPropertyValue.
Value <<= mpContext->getWhiteSpace();
608 maPropStatProperties.push_back(aDAVPropertyValue);
612 case WebDAVName_getcontenttype:
615 if(propertyIsReady())
619 aDAVPropertyValue.
Name =
"DAV:getcontenttype";
620 aDAVPropertyValue.
Value <<= mpContext->getWhiteSpace();
621 maPropStatProperties.push_back(aDAVPropertyValue);
625 case WebDAVName_supportedlock:
628 if(hasParent(WebDAVName_prop) && maLockEntries.hasElements())
632 aDAVPropertyValue.
Name =
"DAV:supportedlock";
633 aDAVPropertyValue.
Value <<= maLockEntries;
634 maPropStatProperties.push_back(aDAVPropertyValue);
638 case WebDAVName_lockentry:
641 if(hasParent(WebDAVName_supportedlock) && (mbLockScopeSet && mbLockTypeSet))
643 const sal_Int32
nLength(maLockEntries.getLength());
644 ucb::LockEntry aEntry;
646 aEntry.Scope = maLockScope;
647 aEntry.Type = maLockType;
648 maLockEntries.realloc(nLength + 1);
649 maLockEntries[
nLength] = aEntry;
653 case WebDAVName_owner:
655 maLock.Owner <<= mpContext->getWhiteSpace();
658 case WebDAVName_timeout:
660 const OUString sTimeout(mpContext->getWhiteSpace());
661 if (sTimeout ==
"Infinite")
663 else if (sTimeout.startsWith(
"Second-"))
664 maLock.Timeout = sTimeout.copy(7).toInt64();
667 case WebDAVName_locktoken:
669 const OUString sLockToken(maHref);
670 SAL_WARN_IF(!sLockToken.startsWith(
"opaquelocktoken:"),
"ucb.ucp.webdav",
671 "Parser error: wrong 'locktoken' value.");
672 const sal_Int32
nLength(maLock.LockTokens.getLength());
673 maLock.LockTokens.realloc(nLength+1);
674 maLock.LockTokens[
nLength] = sLockToken;
677 case WebDAVName_exclusive:
680 if(hasParent(WebDAVName_lockscope))
682 maLockScope = ucb::LockScope_EXCLUSIVE;
683 mbLockScopeSet =
true;
687 case WebDAVName_shared:
690 if(hasParent(WebDAVName_lockscope))
692 maLockScope = ucb::LockScope_SHARED;
693 mbLockScopeSet =
true;
697 case WebDAVName_write:
700 if(hasParent(WebDAVName_locktype))
702 maLockType = ucb::LockType_WRITE;
703 mbLockTypeSet =
true;
707 case WebDAVName_activelock:
709 maLock.Type = maLockType;
710 maLock.Scope = maLockScope;
711 maResult_Lock.push_back(maLock);
714 case WebDAVName_propstat:
717 if(maStatus.getLength())
719 if(maStatus ==
"HTTP/1.1 200 OK")
721 if(isCollectingProperties())
723 if(!maPropStatProperties.empty())
726 maResponseProperties.insert(maResponseProperties.end(), maPropStatProperties.begin(), maPropStatProperties.end());
731 if(!maPropStatNames.empty())
734 maResponseNames.insert(maResponseNames.end(), maPropStatNames.begin(), maPropStatNames.end());
741 case WebDAVName_response:
744 if(maHref.getLength())
746 if(isCollectingProperties())
749 if(!maResponseProperties.empty())
753 aDAVResource.
uri = maHref;
754 aDAVResource.
properties = maResponseProperties;
755 maResult_PropFind.push_back(aDAVResource);
761 if(!maResponseNames.empty())
765 aDAVResourceInfo.properties = maResponseNames;
766 maResult_PropName.push_back(aDAVResourceInfo);
775 case WebDAVNamespace_ucb_openoffice_org_dav_props:
787 void SAL_CALL WebDAVResponseParser::characters(
const OUString& aChars )
790 SAL_WARN_IF(!mpContext,
"ucb.ucp.webdav",
"Parser characters without content (!)");
791 const sal_Int32 nLen(aChars.getLength());
793 if(mpContext && nLen)
796 const OUString aTrimmedChars(aChars.trim());
798 if(aTrimmedChars.getLength())
800 OUString aNew(mpContext->getWhiteSpace());
808 aNew += aTrimmedChars;
809 mpContext->setWhiteSpace(aNew);
814 void SAL_CALL WebDAVResponseParser::ignorableWhitespace(
const OUString& )
818 void SAL_CALL WebDAVResponseParser::processingInstruction(
const OUString& ,
const OUString& )
822 void SAL_CALL WebDAVResponseParser::setDocumentLocator(
const uno::Reference< xml::sax::XLocator >& )
833 void parseWebDAVResponse(
834 const uno::Reference< io::XInputStream >& xInputStream,
835 std::vector< T >& rResult,
837 std::vector<T>
const & (WebDAVResponseParser::* fn)()
const)
839 if(xInputStream.is())
844 xml::sax::InputSource myInputSource;
845 myInputSource.aInputStream = xInputStream;
848 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(
852 WebDAVResponseParser* pWebDAVResponseParser =
new WebDAVResponseParser(eWebDAVResponseParserMode);
853 uno::Reference< xml::sax::XDocumentHandler > xWebDAVHdl(pWebDAVResponseParser);
854 xParser->setDocumentHandler(xWebDAVHdl);
857 xParser->parseStream(myInputSource);
860 rResult = (pWebDAVResponseParser->*fn)();
862 catch(uno::Exception&)
864 SAL_WARN(
"ucb.ucp.webdav",
"WebDAV Parse error (!)");
877 std::vector< ucb::Lock > aResult;
878 parseWebDAVResponse< ucb::Lock >(xInputStream, aResult, WebDAVResponseParserMode_Lock, &WebDAVResponseParser::getResult_Lock);
884 std::vector< DAVResource > aResult;
885 parseWebDAVResponse< DAVResource >(xInputStream, aResult, WebDAVResponseParserMode_PropFind, &WebDAVResponseParser::getResult_PropFind);
891 std::vector< DAVResourceInfo > aResult;
892 parseWebDAVResponse< DAVResourceInfo >(xInputStream, aResult, WebDAVResponseParserMode_PropName, &WebDAVResponseParser::getResult_PropName);
std::vector< ucb::Lock > parseWebDAVLockResponse(const uno::Reference< io::XInputStream > &xInputStream)
ParserContextSharedPtr mpContext
std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream > &xInputStream)
RegionData_Impl * mpParent
#define SAL_WARN_IF(condition, area, stream)
Reference< XComponentContext > getProcessComponentContext()
std::vector< DAVPropertyValue > properties
std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream > &xInputStream)
#define SAL_WARN(area, stream)