bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / ucp / webdav / webdavresponseparser.cxx
blobca485d1004a2a9d09d408ed246c7e211f9e50c49
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"
21 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
22 #include <cppuhelper/implbase2.hxx>
23 #include <com/sun/star/xml/sax/Parser.hpp>
24 #include <com/sun/star/xml/sax/InputSource.hpp>
25 #include <comphelper/processfactory.hxx>
26 #include <comphelper/seqstream.hxx>
27 #include <com/sun/star/ucb/LockEntry.hpp>
28 #include <com/sun/star/ucb/LockScope.hpp>
29 #include <com/sun/star/ucb/LockType.hpp>
30 #include <com/sun/star/ucb/Lock.hpp>
31 #include <map>
32 #include <unordered_map>
34 using namespace com::sun::star;
37 // WebDAVNamespace enum and StringToEnum converter
38 namespace
40 enum WebDAVNamespace
42 WebDAVNamespace_unknown = 0,
43 WebDAVNamespace_DAV,
44 WebDAVNamespace_ucb_openoffice_org_dav_props,
46 WebDAVNamespace_last
49 WebDAVNamespace StrToWebDAVNamespace(const OUString& rStr)
51 if(rStr == "DAV:")
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;
62 } // end of anonymous namespace
64 // WebDAVName enum and StringToEnum converter using unordered_map
65 namespace
67 enum WebDAVName
69 WebDAVName_unknown = 0,
70 WebDAVName_activelock,
71 WebDAVName_multistatus,
72 WebDAVName_response,
73 WebDAVName_href,
74 WebDAVName_propstat,
75 WebDAVName_prop,
76 WebDAVName_resourcetype,
77 WebDAVName_collection,
78 WebDAVName_getcontenttype,
79 WebDAVName_supportedlock,
80 WebDAVName_lockentry,
81 WebDAVName_lockscope,
82 WebDAVName_locktoken,
83 WebDAVName_exclusive,
84 WebDAVName_locktype,
85 WebDAVName_owner,
86 WebDAVName_timeout,
87 WebDAVName_write,
88 WebDAVName_shared,
89 WebDAVName_status,
90 WebDAVName_getlastmodified,
91 WebDAVName_creationdate,
92 WebDAVName_getcontentlength,
94 WebDAVName_last
97 WebDAVName StrToWebDAVName(const OUString& rStr)
99 typedef std::unordered_map< OUString, WebDAVName, OUStringHash > 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;
136 else
138 return aResult->second;
141 } // end of anonymous namespace
144 // WebDAVContext, holding information for each start/endElement pair
146 namespace
148 typedef std::map< OUString, OUString > NamespaceMap;
149 typedef std::pair< const OUString, OUString > NamespaceValueType;
151 class WebDAVContext
153 private:
154 WebDAVContext* mpParent;
155 NamespaceMap maNamespaceMap;
156 OUString maWhiteSpace;
158 OUString maNamespace;
159 OUString maName;
161 WebDAVNamespace maWebDAVNamespace;
162 WebDAVName maWebDAVName;
164 // local helpers
165 void parseForNamespaceTokens(const uno::Reference< xml::sax::XAttributeList >& xAttribs);
166 OUString mapNamespaceToken(const OUString& rToken) const;
167 void splitName(const OUString& rSource);
169 public:
170 WebDAVContext(WebDAVContext* pParent, const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs);
171 ~WebDAVContext();
173 WebDAVContext* getParent() const { return mpParent; }
174 OUString& getWhiteSpace() { return maWhiteSpace; }
175 void setWhiteSpace(const OUString& rNew) { maWhiteSpace = rNew; }
177 const OUString& getNamespace() const { return maNamespace; }
178 const OUString& getName() const { return maName; }
179 const WebDAVNamespace& getWebDAVNamespace() const { return maWebDAVNamespace; }
180 const WebDAVName& getWebDAVName() const { return maWebDAVName; }
183 void WebDAVContext::parseForNamespaceTokens(const uno::Reference< xml::sax::XAttributeList >& xAttribs)
185 const sal_Int16 nAttributes(xAttribs->getLength());
187 for(sal_Int16 a(0); a < nAttributes; a++)
189 const OUString aName(xAttribs->getNameByIndex(a));
190 const sal_Int32 nLen(aName.getLength());
192 if(nLen)
194 if(aName.startsWith("xmlns"))
196 const sal_Int32 nIndex(aName.indexOf(':', 0));
198 if(-1 != nIndex && nIndex + 1 < nLen)
200 const OUString aToken(aName.copy(nIndex + 1));
202 maNamespaceMap.insert(NamespaceValueType(aToken, xAttribs->getValueByIndex(a)));
209 OUString WebDAVContext::mapNamespaceToken(const OUString& rToken) const
211 NamespaceMap::const_iterator iter = maNamespaceMap.find(rToken);
213 if(maNamespaceMap.end() == iter)
215 if(getParent())
217 return getParent()->mapNamespaceToken(rToken);
219 else
221 return rToken;
224 else
226 return (*iter).second;
230 void WebDAVContext::splitName(const OUString& rSource)
232 const sal_Int32 nLen(rSource.getLength());
233 maNamespace = "";
234 maName = rSource;
236 if(nLen)
238 const sal_Int32 nIndex(rSource.indexOf(':', 0));
240 if(nIndex > 0 && ((nIndex + 1) < nLen))
242 maNamespace = mapNamespaceToken(rSource.copy(0, nIndex));
243 maName = rSource.copy(nIndex + 1);
248 WebDAVContext::WebDAVContext(WebDAVContext* pParent, const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs)
249 : mpParent(pParent),
250 maNamespaceMap(),
251 maWhiteSpace(),
252 maNamespace(),
253 maName(),
254 maWebDAVNamespace(WebDAVNamespace_unknown),
255 maWebDAVName(WebDAVName_unknown)
257 const sal_Int16 nAttributes(xAttribs->getLength());
259 if(nAttributes)
261 // parse evtl. namespace entries
262 parseForNamespaceTokens(xAttribs);
265 // split name to namespace and name
266 splitName(aName);
268 // evaluate enums for namespace and name
269 maWebDAVNamespace = StrToWebDAVNamespace(maNamespace);
270 maWebDAVName = StrToWebDAVName(maName);
273 WebDAVContext::~WebDAVContext()
276 } // end of anonymous namespace
279 // the Xml parser itself
281 namespace
283 enum WebDAVResponseParserMode
285 WebDAVResponseParserMode_PropFind = 0,
286 WebDAVResponseParserMode_PropName,
287 WebDAVResponseParserMode_Lock
290 class WebDAVResponseParser : public cppu::WeakImplHelper1< com::sun::star::xml::sax::XDocumentHandler >
292 private:
293 std::vector< ucb::Lock > maResult_Lock;
294 std::vector< http_dav_ucp::DAVResource > maResult_PropFind;
295 std::vector< http_dav_ucp::DAVResourceInfo > maResult_PropName;
297 WebDAVContext* mpContext;
298 OUString maHref;
299 OUString maStatus;
300 std::vector< http_dav_ucp::DAVPropertyValue > maResponseProperties;
301 std::vector< http_dav_ucp::DAVPropertyValue > maPropStatProperties;
302 std::vector< OUString > maResponseNames;
303 std::vector< OUString > maPropStatNames;
304 uno::Sequence< ucb::LockEntry > maLockEntries;
305 ucb::LockScope maLockScope;
306 ucb::LockType maLockType;
307 ucb::Lock maLock;
308 WebDAVResponseParserMode meWebDAVResponseParserMode;
310 // bitfield
311 bool mbResourceTypeCollection : 1;
312 bool mbLockScopeSet : 1;
313 bool mbLockTypeSet : 1;
315 // local helpers
316 bool whitespaceIsAvailable() const
318 return mpContext && mpContext->getWhiteSpace().getLength();
320 bool hasParent(WebDAVName aWebDAVName) const
322 return mpContext && mpContext->getParent() && aWebDAVName == mpContext->getParent()->getWebDAVName();
324 bool propertyIsReady() const
326 return hasParent(WebDAVName_prop) && whitespaceIsAvailable();
328 bool isCollectingProperties() const
330 return WebDAVResponseParserMode_PropFind == meWebDAVResponseParserMode;
332 bool isCollectingPropNames() const
334 return WebDAVResponseParserMode_PropName == meWebDAVResponseParserMode;
336 bool collectThisPropertyAsName() const
338 return isCollectingPropNames() && hasParent(WebDAVName_prop);
340 void pop_context()
342 if(mpContext)
344 WebDAVContext* pTemp = mpContext;
345 mpContext = mpContext->getParent();
346 delete pTemp;
348 else
350 SAL_WARN( "ucb.ucp.webdav", "Parser context pop without context (!)");
354 public:
355 WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode);
356 virtual ~WebDAVResponseParser();
358 // Methods XDocumentHandler
359 virtual void SAL_CALL startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
360 virtual void SAL_CALL endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
361 virtual void SAL_CALL startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
362 virtual void SAL_CALL endElement( const OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
363 virtual void SAL_CALL characters( const OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
364 virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
365 virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
366 virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) throw (xml::sax::SAXException, uno::RuntimeException) SAL_OVERRIDE;
368 const std::vector< ucb::Lock >& getResult_Lock() const { return maResult_Lock; }
369 const std::vector< http_dav_ucp::DAVResource >& getResult_PropFind() const { return maResult_PropFind; }
370 const std::vector< http_dav_ucp::DAVResourceInfo >& getResult_PropName() const { return maResult_PropName; }
373 WebDAVResponseParser::WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode)
374 : maResult_PropFind(),
375 maResult_PropName(),
376 mpContext(0),
377 maHref(),
378 maStatus(),
379 maResponseProperties(),
380 maPropStatProperties(),
381 maResponseNames(),
382 maPropStatNames(),
383 maLockEntries(),
384 maLockScope(ucb::LockScope_EXCLUSIVE),
385 maLockType(ucb::LockType_WRITE),
386 meWebDAVResponseParserMode(eWebDAVResponseParserMode),
387 mbResourceTypeCollection(false),
388 mbLockScopeSet(false),
389 mbLockTypeSet(false)
393 WebDAVResponseParser::~WebDAVResponseParser()
395 SAL_WARN_IF(mpContext, "ucb.ucp.webdav", "Parser destructed with existing content (!)");
396 while(mpContext)
398 pop_context();
402 void SAL_CALL WebDAVResponseParser::startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException)
404 SAL_WARN_IF(mpContext, "ucb.ucp.webdav", "Parser start with existing content (!)");
407 void SAL_CALL WebDAVResponseParser::endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException)
409 SAL_WARN_IF(mpContext, "ucb.ucp.webdav", "Parser end with existing content (!)");
412 void SAL_CALL WebDAVResponseParser::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException)
414 const sal_Int32 nLen(aName.getLength());
416 if(nLen)
418 // create new context (push)
419 mpContext = new WebDAVContext(mpContext, aName, xAttribs);
421 if(collectThisPropertyAsName())
423 // When collecting property names and parent is prop there is no need
424 // to handle the content of this property deeper (evtl. preparations)
426 else
428 switch(mpContext->getWebDAVNamespace())
430 default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
432 break;
434 case WebDAVNamespace_DAV:
436 switch(mpContext->getWebDAVName())
438 default: // WebDAVName_unknown, WebDAVName_last or unhandled
440 break;
442 case WebDAVName_propstat:
444 // propstat start
445 if(isCollectingProperties())
447 // reset maPropStatProperties
448 maPropStatProperties.clear();
450 else
452 // when collecting properties reset maPropStatNames
453 maPropStatNames.clear();
455 break;
457 case WebDAVName_response:
459 // response start, reset Href and status and maResponseProperties
460 maHref = maStatus = "";
462 if(isCollectingProperties())
464 // reset maResponseProperties
465 maResponseProperties.clear();
467 else
469 // reset maResponseNames when collecting properties
470 maResponseNames.clear();
472 break;
474 case WebDAVName_resourcetype:
476 // resourcetype start, reset collection
477 mbResourceTypeCollection = false;
478 break;
480 case WebDAVName_supportedlock:
482 // supportedlock start, reset maLockEntries
483 maLockEntries.realloc(0);
484 break;
486 case WebDAVName_lockentry:
488 // lockentry start, reset maLockEntries
489 mbLockScopeSet = false;
490 mbLockTypeSet = false;
491 break;
493 case WebDAVName_activelock:
495 maLock = ucb::Lock();
496 break;
499 break;
501 case WebDAVNamespace_ucb_openoffice_org_dav_props:
503 break;
510 void SAL_CALL WebDAVResponseParser::endElement( const OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException)
512 const sal_Int32 nLen(aName.getLength());
513 SAL_WARN_IF(!mpContext, "ucb.ucp.webdav", "Parser EndElement without content (!)");
515 if(mpContext && nLen)
517 if(collectThisPropertyAsName())
519 // When collecting property names and parent is prop, just append the prop name
520 // to the collection, no need to parse deeper
521 maPropStatNames.push_back(mpContext->getNamespace() + mpContext->getName());
523 else
525 switch(mpContext->getWebDAVNamespace())
527 default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
529 break;
531 case WebDAVNamespace_DAV:
533 switch(mpContext->getWebDAVName())
535 default: // WebDAVName_unknown, WebDAVName_last or unhandled
537 break;
539 case WebDAVName_href:
541 // href end, save it if we have whitespace
542 if(whitespaceIsAvailable())
544 maHref = mpContext->getWhiteSpace();
546 break;
548 case WebDAVName_status:
550 // status end, save it if we have whitespace
551 if(whitespaceIsAvailable())
553 maStatus = mpContext->getWhiteSpace();
555 break;
557 case WebDAVName_getlastmodified:
559 // getlastmodified end, safe if content is correct
560 if(propertyIsReady())
562 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
564 aDAVPropertyValue.Name = "DAV:getlastmodified";
565 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
566 maPropStatProperties.push_back(aDAVPropertyValue);
568 break;
570 case WebDAVName_creationdate:
572 // creationdate end, safe if content is correct
573 if(propertyIsReady())
575 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
577 aDAVPropertyValue.Name = "DAV:creationdate";
578 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
579 maPropStatProperties.push_back(aDAVPropertyValue);
581 break;
583 case WebDAVName_collection:
585 // collection end, check and set
586 if(hasParent(WebDAVName_resourcetype))
588 mbResourceTypeCollection = true;
590 break;
592 case WebDAVName_resourcetype:
594 // resourcetype end, check for collection
595 if(hasParent(WebDAVName_prop))
597 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
599 aDAVPropertyValue.Name = "DAV:resourcetype";
600 aDAVPropertyValue.Value <<= (mbResourceTypeCollection ? OUString("collection") : OUString());
601 maPropStatProperties.push_back(aDAVPropertyValue);
603 break;
605 case WebDAVName_getcontentlength:
607 // getcontentlength end, safe if content is correct
608 if(propertyIsReady())
610 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
612 aDAVPropertyValue.Name = "DAV:getcontentlength";
613 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
614 maPropStatProperties.push_back(aDAVPropertyValue);
616 break;
618 case WebDAVName_getcontenttype:
620 // getcontenttype end, safe if content is correct
621 if(propertyIsReady())
623 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
625 aDAVPropertyValue.Name = "DAV:getcontenttype";
626 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
627 maPropStatProperties.push_back(aDAVPropertyValue);
629 break;
631 case WebDAVName_supportedlock:
633 // supportedlock end
634 if(hasParent(WebDAVName_prop) && maLockEntries.hasElements())
636 http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
638 aDAVPropertyValue.Name = "DAV:supportedlock";
639 aDAVPropertyValue.Value <<= maLockEntries;
640 maPropStatProperties.push_back(aDAVPropertyValue);
642 break;
644 case WebDAVName_lockentry:
646 // lockentry end
647 if(hasParent(WebDAVName_supportedlock) && (mbLockScopeSet && mbLockTypeSet))
649 const sal_Int32 nLength(maLockEntries.getLength());
650 ucb::LockEntry aEntry;
652 aEntry.Scope = maLockScope;
653 aEntry.Type = maLockType;
654 maLockEntries.realloc(nLength + 1);
655 maLockEntries[nLength] = aEntry;
657 break;
659 case WebDAVName_owner:
661 maLock.Owner <<= mpContext->getWhiteSpace();
662 break;
664 case WebDAVName_timeout:
666 const OUString sTimeout(mpContext->getWhiteSpace());
667 if (sTimeout == "Infinite")
668 maLock.Timeout = -1;
669 else if (sTimeout.startsWith("Second-"))
670 maLock.Timeout = sTimeout.copy(7).toInt64();
671 break;
673 case WebDAVName_locktoken:
675 const OUString sLockToken(maHref);
676 SAL_WARN_IF(!sLockToken.startsWith("opaquelocktoken:"), "ucb.ucp.webdav",
677 "Parser error: wrong 'locktoken' value.");
678 const sal_Int32 nLength(maLock.LockTokens.getLength());
679 maLock.LockTokens.realloc(nLength+1);
680 maLock.LockTokens[nLength] = sLockToken;
681 break;
683 case WebDAVName_exclusive:
685 // exclusive lockscope end
686 if(hasParent(WebDAVName_lockscope))
688 maLockScope = ucb::LockScope_EXCLUSIVE;
689 mbLockScopeSet = true;
691 break;
693 case WebDAVName_shared:
695 // shared lockscope end
696 if(hasParent(WebDAVName_lockscope))
698 maLockScope = ucb::LockScope_SHARED;
699 mbLockScopeSet = true;
701 break;
703 case WebDAVName_write:
705 // write locktype end
706 if(hasParent(WebDAVName_locktype))
708 maLockType = ucb::LockType_WRITE;
709 mbLockTypeSet = true;
711 break;
713 case WebDAVName_activelock:
715 maLock.Type = maLockType;
716 maLock.Scope = maLockScope;
717 maResult_Lock.push_back(maLock);
719 case WebDAVName_propstat:
721 // propstat end, check status
722 if(maStatus.getLength())
724 if(maStatus == "HTTP/1.1 200 OK")
726 if(isCollectingProperties())
728 if(!maPropStatProperties.empty())
730 // append to maResponseProperties if okay
731 maResponseProperties.insert(maResponseProperties.end(), maPropStatProperties.begin(), maPropStatProperties.end());
734 else
736 if(!maPropStatNames.empty())
738 // when collecting properties append to
739 maResponseNames.insert(maResponseNames.end(), maPropStatNames.begin(), maPropStatNames.end());
744 break;
746 case WebDAVName_response:
748 // respose end
749 if(maHref.getLength())
751 if(isCollectingProperties())
753 // create DAVResource when we have content
754 if(!maResponseProperties.empty())
756 http_dav_ucp::DAVResource aDAVResource;
758 aDAVResource.uri = maHref;
759 aDAVResource.properties = maResponseProperties;
760 maResult_PropFind.push_back(aDAVResource);
763 else
765 // when collecting properties add them to result when there are some
766 if(!maResponseNames.empty())
768 http_dav_ucp::DAVResourceInfo aDAVResourceInfo(maHref);
770 aDAVResourceInfo.properties = maResponseNames;
771 maResult_PropName.push_back(aDAVResourceInfo);
775 break;
778 break;
780 case WebDAVNamespace_ucb_openoffice_org_dav_props:
782 break;
787 // destroy last context (pop)
788 pop_context();
792 void SAL_CALL WebDAVResponseParser::characters( const OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException)
794 // collect whitespace over evtl. several calls in mpContext
795 SAL_WARN_IF(!mpContext, "ucb.ucp.webdav", "Parser characters without content (!)");
796 const sal_Int32 nLen(aChars.getLength());
798 if(mpContext && nLen)
800 // remove leading/trailing blanks and CRLF
801 const OUString aTrimmedChars(aChars.trim());
803 if(aTrimmedChars.getLength())
805 OUString aNew(mpContext->getWhiteSpace());
807 if(aNew.getLength())
809 // add one char when appending (see html1.1 spec)
810 aNew += OUString(' ');
813 aNew += aTrimmedChars;
814 mpContext->setWhiteSpace(aNew);
819 void SAL_CALL WebDAVResponseParser::ignorableWhitespace( const OUString& /*aWhitespaces*/ ) throw (xml::sax::SAXException, uno::RuntimeException)
823 void SAL_CALL WebDAVResponseParser::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ ) throw (xml::sax::SAXException, uno::RuntimeException)
827 void SAL_CALL WebDAVResponseParser::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ ) throw (xml::sax::SAXException, uno::RuntimeException)
830 } // end of anonymous namespace
833 // wrapper for various calls to the parser
835 namespace
837 template<typename T>
838 void parseWebDAVResponse(
839 const uno::Reference< io::XInputStream >& xInputStream,
840 std::vector< T >& rResult,
841 WebDAVResponseParserMode eWebDAVResponseParserMode)
843 if(xInputStream.is())
847 // prepare ParserInputSrouce
848 xml::sax::InputSource myInputSource;
849 myInputSource.aInputStream = xInputStream;
851 // get parser
852 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(
853 comphelper::getProcessComponentContext() );
855 // create parser; connect parser and filter
856 WebDAVResponseParser* pWebDAVResponseParser = new WebDAVResponseParser(eWebDAVResponseParserMode);
857 uno::Reference< xml::sax::XDocumentHandler > xWebDAVHdl(pWebDAVResponseParser);
858 xParser->setDocumentHandler(xWebDAVHdl);
860 // finally, parse the stream
861 xParser->parseStream(myInputSource);
863 // get result
864 switch(eWebDAVResponseParserMode)
866 // *(std::vector<T>*) & is a horrible hack but hopefully works,
867 // I was not able to come up with something sane :-/
868 case WebDAVResponseParserMode_PropFind:
869 rResult = *(std::vector<T>*) &pWebDAVResponseParser->getResult_PropFind();
870 break;
871 case WebDAVResponseParserMode_PropName:
872 rResult = *(std::vector<T>*) &pWebDAVResponseParser->getResult_PropName();
873 break;
874 case WebDAVResponseParserMode_Lock:
875 rResult = *(std::vector<T>*) &pWebDAVResponseParser->getResult_Lock();
876 break;
879 catch(uno::Exception&)
881 SAL_WARN("ucb.ucp.webdav", "WebDAV Parse error (!)");
885 } // end of anonymous namespace
888 // helper to parse a XML WebDAV response
890 namespace http_dav_ucp
892 std::vector< ucb::Lock > parseWebDAVLockResponse(const uno::Reference< io::XInputStream >& xInputStream)
894 std::vector< ucb::Lock > aResult;
895 parseWebDAVResponse< ucb::Lock >(xInputStream, aResult, WebDAVResponseParserMode_Lock);
896 return aResult;
899 std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream >& xInputStream)
901 std::vector< DAVResource > aResult;
902 parseWebDAVResponse< DAVResource >(xInputStream, aResult, WebDAVResponseParserMode_PropFind);
903 return aResult;
906 std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream >& xInputStream)
908 std::vector< DAVResourceInfo > aResult;
909 parseWebDAVResponse< DAVResourceInfo >(xInputStream, aResult, WebDAVResponseParserMode_PropName);
910 return aResult;
912 } // namespace http_dav_ucp
914 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */