Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / ucp / webdav-curl / webdavresponseparser.cxx
blob9a0500d01bff6e92e488ceeea56e7d1b83192cc9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "webdavresponseparser.hxx"
22 #include "DAVProperties.hxx"
23 #include "UCBDeadPropertyValue.hxx"
25 #include <comphelper/processfactory.hxx>
26 #include <comphelper/sequence.hxx>
28 #include <cppuhelper/implbase.hxx>
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>
36 #include <map>
37 #include <unordered_map>
38 #include <rtl/ref.hxx>
39 #include <rtl/uri.hxx>
40 #include <sal/log.hxx>
41 #include <o3tl/string_view.hxx>
43 using namespace com::sun::star;
44 using namespace http_dav_ucp;
47 // WebDAVNamespace enum and StringToEnum converter
48 namespace
50 enum WebDAVNamespace
52 WebDAVNamespace_unknown = 0,
53 WebDAVNamespace_DAV,
54 WebDAVNamespace_ucb_openoffice_org_dav_props,
56 WebDAVNamespace_last
59 WebDAVNamespace StrToWebDAVNamespace(::std::u16string_view rStr)
61 if (rStr == u"DAV:")
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;
72 } // end of anonymous namespace
74 // WebDAVName enum and StringToEnum converter using unordered_map
75 namespace
77 enum WebDAVName
79 WebDAVName_unknown = 0,
80 WebDAVName_activelock,
81 WebDAVName_lockdiscovery,
82 WebDAVName_multistatus,
83 WebDAVName_response,
84 WebDAVName_href,
85 WebDAVName_propstat,
86 WebDAVName_prop,
87 WebDAVName_resourcetype,
88 WebDAVName_collection,
89 WebDAVName_getcontenttype,
90 WebDAVName_supportedlock,
91 WebDAVName_lockentry,
92 WebDAVName_lockscope,
93 WebDAVName_depth,
94 WebDAVName_locktoken,
95 WebDAVName_exclusive,
96 WebDAVName_locktype,
97 WebDAVName_owner,
98 WebDAVName_timeout,
99 WebDAVName_write,
100 WebDAVName_shared,
101 WebDAVName_status,
102 WebDAVName_getlastmodified,
103 WebDAVName_creationdate,
104 WebDAVName_getcontentlength,
105 WebDAVName_type,
106 WebDAVName_value,
107 WebDAVName_ucbprop,
109 WebDAVName_last
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;
156 else
158 return aResult->second;
161 } // end of anonymous namespace
164 // WebDAVContext, holding information for each start/endElement pair
166 namespace
168 typedef std::map< OUString, OUString > NamespaceMap;
170 class WebDAVContext
172 private:
173 WebDAVContext* mpParent;
174 NamespaceMap maNamespaceMap;
175 OUString maWhiteSpace;
177 OUString maNamespace;
178 OUString maName;
180 WebDAVNamespace maWebDAVNamespace;
181 WebDAVName maWebDAVName;
183 // local helpers
184 void parseForNamespaceTokens(const uno::Reference< xml::sax::XAttributeList >& xAttribs);
185 OUString mapNamespaceToken(const OUString& rToken) const;
186 void splitName(const OUString& rSource);
188 public:
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());
205 for(sal_Int16 a(0); a < nAttributes; a++)
207 const OUString aName(xAttribs->getNameByIndex(a));
208 const sal_Int32 nLen(aName.getLength());
210 if(nLen)
212 if(aName.startsWith("xmlns"))
214 const sal_Int32 nIndex(aName.indexOf(':', 0));
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)
233 if(getParent())
235 return getParent()->mapNamespaceToken(rToken);
237 else
239 return rToken;
242 else
244 return (*iter).second;
248 void WebDAVContext::splitName(const OUString& rSource)
250 const sal_Int32 nLen(rSource.getLength());
251 maNamespace.clear();
252 maName = rSource;
254 if(nLen)
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)
267 : mpParent(pParent),
268 maNamespaceMap(),
269 maWhiteSpace(),
270 maNamespace(),
271 maName(),
272 maWebDAVNamespace(WebDAVNamespace_unknown),
273 maWebDAVName(WebDAVName_unknown)
275 const sal_Int16 nAttributes(xAttribs->getLength());
277 if(nAttributes)
279 // parse evtl. namespace entries
280 parseForNamespaceTokens(xAttribs);
283 // split name to namespace and name
284 splitName(aName);
286 // evaluate enums for namespace and name
287 maWebDAVNamespace = StrToWebDAVNamespace(maNamespace);
288 maWebDAVName = StrToWebDAVName(maName);
290 } // end of anonymous namespace
293 // the Xml parser itself
295 namespace
297 enum WebDAVResponseParserMode
299 WebDAVResponseParserMode_PropFind = 0,
300 WebDAVResponseParserMode_PropName,
301 WebDAVResponseParserMode_Lock
304 class WebDAVResponseParser : public cppu::WeakImplHelper< css::xml::sax::XDocumentHandler >
306 private:
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;
311 WebDAVContext* mpContext;
312 OUString maHref;
313 OUString maStatus;
314 OUString m_UCBType;
315 OUString m_UCBValue;
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;
323 ucb::Lock maLock;
324 WebDAVResponseParserMode meWebDAVResponseParserMode;
326 bool mbResourceTypeCollection : 1;
327 bool mbLockScopeSet : 1;
328 bool mbLockTypeSet : 1;
330 // local helpers
331 bool whitespaceIsAvailable() const
333 return mpContext && mpContext->getWhiteSpace().getLength();
335 bool hasParent(WebDAVName aWebDAVName) const
337 return mpContext && mpContext->getParent() && aWebDAVName == mpContext->getParent()->getWebDAVName();
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);
355 void pop_context()
357 if(mpContext)
359 WebDAVContext* pTemp = mpContext;
360 mpContext = mpContext->getParent();
361 delete pTemp;
363 else
365 SAL_WARN( "ucb.ucp.webdav", "Parser context pop without context (!)");
369 public:
370 explicit WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode);
371 virtual ~WebDAVResponseParser() override;
373 // Methods XDocumentHandler
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(),
390 maResult_PropName(),
391 mpContext(nullptr),
392 maHref(),
393 maStatus(),
394 maResponseProperties(),
395 maPropStatProperties(),
396 maResponseNames(),
397 maPropStatNames(),
398 maLockEntries(),
399 maLockScope(ucb::LockScope_EXCLUSIVE),
400 maLockType(ucb::LockType_WRITE),
401 meWebDAVResponseParserMode(eWebDAVResponseParserMode),
402 mbResourceTypeCollection(false),
403 mbLockScopeSet(false),
404 mbLockTypeSet(false)
408 WebDAVResponseParser::~WebDAVResponseParser()
410 SAL_WARN_IF(mpContext, "ucb.ucp.webdav", "Parser destructed with existing content (!)");
411 while(mpContext)
413 pop_context();
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());
431 if(nLen)
433 // create new context (push)
434 mpContext = new WebDAVContext(mpContext, aName, xAttribs);
436 if(collectThisPropertyAsName())
438 // When collecting property names and parent is prop there is no need
439 // to handle the content of this property deeper (evtl. preparations)
441 else
443 switch(mpContext->getWebDAVNamespace())
445 default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
447 break;
449 case WebDAVNamespace_DAV:
451 switch(mpContext->getWebDAVName())
453 default: // WebDAVName_unknown, WebDAVName_last or unhandled
455 break;
457 case WebDAVName_propstat:
459 // propstat start
460 if(isCollectingProperties())
462 // reset maPropStatProperties
463 maPropStatProperties.clear();
465 else
467 // when collecting properties reset maPropStatNames
468 maPropStatNames.clear();
470 break;
472 case WebDAVName_response:
474 // response start, reset Href and status and maResponseProperties
475 maHref.clear();
476 maStatus.clear();
478 if(isCollectingProperties())
480 // reset maResponseProperties
481 maResponseProperties.clear();
483 else
485 // reset maResponseNames when collecting properties
486 maResponseNames.clear();
488 break;
490 case WebDAVName_resourcetype:
492 // resourcetype start, reset collection
493 mbResourceTypeCollection = false;
494 break;
496 case WebDAVName_supportedlock:
498 // supportedlock start, reset maLockEntries
499 maLockEntries.realloc(0);
500 break;
502 case WebDAVName_lockentry:
504 // lockentry start, reset maLockEntries
505 mbLockScopeSet = false;
506 mbLockTypeSet = false;
507 break;
509 case WebDAVName_activelock:
511 maLock = ucb::Lock();
512 break;
515 break;
517 case WebDAVNamespace_ucb_openoffice_org_dav_props:
519 break;
526 OUString MakePropertyName(WebDAVContext const& rContext)
528 OUString ret;
529 OString const name(OUStringToOString(rContext.getName(), RTL_TEXTENCODING_UTF8));
530 OString const nameSpace(OUStringToOString(rContext.getNamespace(), RTL_TEXTENCODING_UTF8));
531 DAVProperties::createUCBPropName(nameSpace.getStr(), name.getStr(), ret);
532 return 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())
544 // name must be encoded as expected by createSerfPropName()
545 OUString const name(MakePropertyName(*mpContext));
546 maPropStatNames.emplace_back(name);
548 else
550 switch(mpContext->getWebDAVNamespace())
552 default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
554 break;
556 case WebDAVNamespace_DAV:
558 switch(mpContext->getWebDAVName())
560 default: // WebDAVName_unknown, WebDAVName_last or unhandled
562 break;
564 case WebDAVName_href:
566 // href end, save it if we have whitespace
567 if(whitespaceIsAvailable())
569 // Sharepoint 2016 workaround: apparently
570 // the result is an IRI (RFC 3987 possibly?)
571 // so try to encode the non-ASCII chars
572 // without changing anything else
573 maHref = ::rtl::Uri::encode(mpContext->getWhiteSpace(),
574 rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes,
575 RTL_TEXTENCODING_UTF8);
577 break;
579 case WebDAVName_status:
581 // status end, save it if we have whitespace
582 if(whitespaceIsAvailable())
584 maStatus = mpContext->getWhiteSpace();
586 break;
588 case WebDAVName_getlastmodified:
590 // getlastmodified end, safe if content is correct
591 if(propertyIsReady())
593 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
595 aDAVPropertyValue.Name = "DAV:getlastmodified";
596 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
597 maPropStatProperties.push_back(aDAVPropertyValue);
599 break;
601 case WebDAVName_creationdate:
603 // creationdate end, safe if content is correct
604 if(propertyIsReady())
606 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
608 aDAVPropertyValue.Name = "DAV:creationdate";
609 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
610 maPropStatProperties.push_back(aDAVPropertyValue);
612 break;
614 case WebDAVName_collection:
616 // collection end, check and set
617 if(hasParent(WebDAVName_resourcetype))
619 mbResourceTypeCollection = true;
621 break;
623 case WebDAVName_resourcetype:
625 // resourcetype end, check for collection
626 if(hasParent(WebDAVName_prop))
628 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
630 aDAVPropertyValue.Name = "DAV:resourcetype";
631 aDAVPropertyValue.Value <<= (mbResourceTypeCollection ? OUString("collection") : OUString());
632 maPropStatProperties.push_back(aDAVPropertyValue);
634 break;
636 case WebDAVName_getcontentlength:
638 // getcontentlength end, safe if content is correct
639 if(propertyIsReady())
641 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
643 aDAVPropertyValue.Name = "DAV:getcontentlength";
644 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
645 maPropStatProperties.push_back(aDAVPropertyValue);
647 break;
649 case WebDAVName_getcontenttype:
651 // getcontenttype end, safe if content is correct
652 if(propertyIsReady())
654 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
656 aDAVPropertyValue.Name = "DAV:getcontenttype";
657 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
658 maPropStatProperties.push_back(aDAVPropertyValue);
660 break;
662 case WebDAVName_supportedlock:
664 // supportedlock end
665 if(hasParent(WebDAVName_prop) && maLockEntries.hasElements())
667 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
669 aDAVPropertyValue.Name = "DAV:supportedlock";
670 aDAVPropertyValue.Value <<= maLockEntries;
671 maPropStatProperties.push_back(aDAVPropertyValue);
673 break;
675 case WebDAVName_lockentry:
677 // lockentry end
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;
688 break;
690 case WebDAVName_owner:
692 maLock.Owner <<= mpContext->getWhiteSpace();
693 break;
695 case WebDAVName_timeout:
697 const OUString sTimeout(mpContext->getWhiteSpace());
698 if (sTimeout == "Infinite")
699 maLock.Timeout = -1;
700 else if (sTimeout.startsWith("Second-"))
701 maLock.Timeout = o3tl::toInt64(sTimeout.subView(7));
702 break;
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;
712 break;
714 case WebDAVName_exclusive:
716 // exclusive lockscope end
717 if(hasParent(WebDAVName_lockscope))
719 maLockScope = ucb::LockScope_EXCLUSIVE;
720 mbLockScopeSet = true;
722 break;
724 case WebDAVName_shared:
726 // shared lockscope end
727 if(hasParent(WebDAVName_lockscope))
729 maLockScope = ucb::LockScope_SHARED;
730 mbLockScopeSet = true;
732 break;
734 case WebDAVName_write:
736 // write locktype end
737 if(hasParent(WebDAVName_locktype))
739 maLockType = ucb::LockType_WRITE;
740 mbLockTypeSet = true;
742 break;
744 case WebDAVName_depth:
746 OUString const chars(mpContext->getWhiteSpace());
747 if (chars == "0")
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;
759 break;
761 case WebDAVName_activelock:
763 maLock.Type = maLockType;
764 maLock.Scope = maLockScope;
765 maResult_Lock.push_back(maLock);
766 break;
768 case WebDAVName_lockdiscovery:
770 // lockdiscovery may be requested via PROPFIND,
771 // in addition to LOCK! so return it 2 ways
772 if (isCollectingProperties())
774 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
776 aDAVPropertyValue.Name = "DAV:lockdiscovery";
777 aDAVPropertyValue.Value <<= ::comphelper::containerToSequence(maResult_Lock);
778 maPropStatProperties.push_back(aDAVPropertyValue);
780 break;
782 case WebDAVName_propstat:
784 // propstat end, check status
785 if(maStatus.getLength())
787 if(maStatus == "HTTP/1.1 200 OK")
789 if(isCollectingProperties())
791 if(!maPropStatProperties.empty())
793 // append to maResponseProperties if okay
794 maResponseProperties.insert(maResponseProperties.end(), maPropStatProperties.begin(), maPropStatProperties.end());
797 else
799 if(!maPropStatNames.empty())
801 // when collecting properties append to
802 maResponseNames.insert(maResponseNames.end(), maPropStatNames.begin(), maPropStatNames.end());
807 break;
809 case WebDAVName_response:
811 // response end
812 if(maHref.getLength())
814 if(isCollectingProperties())
816 // create DAVResource when we have content
817 if(!maResponseProperties.empty())
819 http_dav_ucp::DAVResource aDAVResource;
821 aDAVResource.uri = maHref;
822 aDAVResource.properties = maResponseProperties;
823 maResult_PropFind.push_back(aDAVResource);
826 else
828 // when collecting properties add them to result when there are some
829 if(!maResponseNames.empty())
831 http_dav_ucp::DAVResourceInfo aDAVResourceInfo;
833 aDAVResourceInfo.properties = maResponseNames;
834 maResult_PropName.push_back(aDAVResourceInfo);
838 break;
841 break;
843 case WebDAVNamespace_ucb_openoffice_org_dav_props:
845 switch(mpContext->getWebDAVName())
847 case WebDAVName_type:
849 m_UCBType = mpContext->getWhiteSpace();
850 break;
852 case WebDAVName_value:
854 m_UCBValue = mpContext->getWhiteSpace();
855 break;
857 case WebDAVName_ucbprop:
859 if (!m_UCBType.isEmpty()
860 && isCollectingProperties())
862 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
863 aDAVPropertyValue.Name = MakePropertyName(*mpContext->getParent());
864 if (UCBDeadPropertyValue::createFromXML(m_UCBType, m_UCBValue, aDAVPropertyValue.Value))
866 maPropStatProperties.push_back(aDAVPropertyValue);
868 else
870 SAL_INFO("ucb.ucp.webdav.curl", "cannot parse property value");
873 m_UCBType.clear();
874 m_UCBValue.clear();
875 break;
877 default:
878 break;
880 break;
885 // destroy last context (pop)
886 pop_context();
890 void SAL_CALL WebDAVResponseParser::characters( const OUString& aChars )
892 // collect whitespace over evtl. several calls in mpContext
893 SAL_WARN_IF(!mpContext, "ucb.ucp.webdav", "Parser characters without content (!)");
894 const sal_Int32 nLen(aChars.getLength());
896 if(mpContext && nLen)
898 // remove leading/trailing blanks and CRLF
899 const OUString aTrimmedChars(aChars.trim());
901 if(aTrimmedChars.getLength())
903 OUString aNew(mpContext->getWhiteSpace());
905 if(aNew.getLength())
907 // add one char when appending (see html1.1 spec)
908 aNew += " ";
911 aNew += aTrimmedChars;
912 mpContext->setWhiteSpace(aNew);
917 void SAL_CALL WebDAVResponseParser::ignorableWhitespace( const OUString& /*aWhitespaces*/ )
921 void SAL_CALL WebDAVResponseParser::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ )
925 void SAL_CALL WebDAVResponseParser::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ )
928 } // end of anonymous namespace
931 // wrapper for various calls to the parser
933 namespace
935 template<typename T>
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())
946 // prepare ParserInputSource
947 xml::sax::InputSource myInputSource;
948 myInputSource.aInputStream = xInputStream;
950 // get parser
951 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(
952 comphelper::getProcessComponentContext() );
954 // create parser; connect parser and filter
955 rtl::Reference<WebDAVResponseParser> const pWebDAVResponseParser(
956 new WebDAVResponseParser(eWebDAVResponseParserMode));
957 uno::Reference< xml::sax::XDocumentHandler > xWebDAVHdl(pWebDAVResponseParser);
958 xParser->setDocumentHandler(xWebDAVHdl);
960 // finally, parse the stream
961 xParser->parseStream(myInputSource);
963 // get result
964 rResult = (pWebDAVResponseParser.get()->*fn)();
966 catch(uno::Exception&)
968 SAL_WARN("ucb.ucp.webdav", "WebDAV Parse error (!)");
972 } // end of anonymous namespace
975 // helper to parse a XML WebDAV response
977 namespace http_dav_ucp
979 std::vector< ucb::Lock > parseWebDAVLockResponse(const uno::Reference< io::XInputStream >& xInputStream)
981 std::vector< ucb::Lock > aResult;
982 parseWebDAVResponse< ucb::Lock >(xInputStream, aResult, WebDAVResponseParserMode_Lock, &WebDAVResponseParser::getResult_Lock);
983 return aResult;
986 std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream >& xInputStream)
988 std::vector< DAVResource > aResult;
989 parseWebDAVResponse< DAVResource >(xInputStream, aResult, WebDAVResponseParserMode_PropFind, &WebDAVResponseParser::getResult_PropFind);
990 return aResult;
993 std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream >& xInputStream)
995 std::vector< DAVResourceInfo > aResult;
996 parseWebDAVResponse< DAVResourceInfo >(xInputStream, aResult, WebDAVResponseParserMode_PropName, &WebDAVResponseParser::getResult_PropName);
997 return aResult;
999 } // namespace http_dav_ucp
1001 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */