LibreOffice Module ucb (master)  1
webdavresponseparser.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include "webdavresponseparser.hxx"
21 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
22 #include <cppuhelper/implbase.hxx>
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>
30 #include <map>
31 #include <unordered_map>
32 #include <sal/log.hxx>
33 
34 using namespace com::sun::star;
35 
36 
37 // WebDAVNamespace enum and StringToEnum converter
38 namespace
39 {
41  {
42  WebDAVNamespace_unknown = 0,
43  WebDAVNamespace_DAV,
44  WebDAVNamespace_ucb_openoffice_org_dav_props,
45 
46  WebDAVNamespace_last
47  };
48 
49  WebDAVNamespace StrToWebDAVNamespace(const OUString& rStr)
50  {
51  if(rStr == "DAV:")
52  {
53  return WebDAVNamespace_DAV;
54  }
55  else if(rStr == "http://ucb.openoffice.org/dav/props/")
56  {
57  return WebDAVNamespace_ucb_openoffice_org_dav_props;
58  }
59 
60  return WebDAVNamespace_unknown;
61  }
62 } // end of anonymous namespace
63 
64 // WebDAVName enum and StringToEnum converter using unordered_map
65 namespace
66 {
68  {
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,
93 
94  WebDAVName_last
95  };
96 
97  WebDAVName StrToWebDAVName(const OUString& rStr)
98  {
99  typedef std::unordered_map< OUString, WebDAVName > WebDAVNameMapper;
100  typedef std::pair< OUString, WebDAVName > WebDAVNameValueType;
101  static WebDAVNameMapper aWebDAVNameMapperList;
102 
103  if(aWebDAVNameMapperList.empty())
104  {
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));
128  }
129 
130  const WebDAVNameMapper::const_iterator aResult(aWebDAVNameMapperList.find(rStr));
131 
132  if(aResult == aWebDAVNameMapperList.end())
133  {
134  return WebDAVName_unknown;
135  }
136  else
137  {
138  return aResult->second;
139  }
140  }
141 } // end of anonymous namespace
142 
143 
144 // WebDAVContext, holding information for each start/endElement pair
145 
146 namespace
147 {
148  typedef std::map< OUString, OUString > NamespaceMap;
149 
150  class WebDAVContext
151  {
152  private:
153  WebDAVContext* mpParent;
154  NamespaceMap maNamespaceMap;
155  OUString maWhiteSpace;
156 
157  OUString maNamespace;
158  OUString maName;
159 
160  WebDAVNamespace maWebDAVNamespace;
161  WebDAVName maWebDAVName;
162 
163  // local helpers
164  void parseForNamespaceTokens(const uno::Reference< xml::sax::XAttributeList >& xAttribs);
165  OUString mapNamespaceToken(const OUString& rToken) const;
166  void splitName(const OUString& rSource);
167 
168  public:
169  WebDAVContext(WebDAVContext* pParent, const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs);
170 
171  WebDAVContext* getParent() const { return mpParent; }
172  OUString& getWhiteSpace() { return maWhiteSpace; }
173  void setWhiteSpace(const OUString& rNew) { maWhiteSpace = rNew; }
174 
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; }
179  };
180 
181  void WebDAVContext::parseForNamespaceTokens(const uno::Reference< xml::sax::XAttributeList >& xAttribs)
182  {
183  const sal_Int16 nAttributes(xAttribs->getLength());
184 
185  for(sal_Int16 a(0); a < nAttributes; a++)
186  {
187  const OUString aName(xAttribs->getNameByIndex(a));
188  const sal_Int32 nLen(aName.getLength());
189 
190  if(nLen)
191  {
192  if(aName.startsWith("xmlns"))
193  {
194  const sal_Int32 nIndex(aName.indexOf(':', 0));
195 
196  if(-1 != nIndex && nIndex + 1 < nLen)
197  {
198  const OUString aToken(aName.copy(nIndex + 1));
199 
200  maNamespaceMap.emplace(aToken, xAttribs->getValueByIndex(a));
201  }
202  }
203  }
204  }
205  }
206 
207  OUString WebDAVContext::mapNamespaceToken(const OUString& rToken) const
208  {
209  NamespaceMap::const_iterator iter = maNamespaceMap.find(rToken);
210 
211  if(maNamespaceMap.end() == iter)
212  {
213  if(getParent())
214  {
215  return getParent()->mapNamespaceToken(rToken);
216  }
217  else
218  {
219  return rToken;
220  }
221  }
222  else
223  {
224  return (*iter).second;
225  }
226  }
227 
228  void WebDAVContext::splitName(const OUString& rSource)
229  {
230  const sal_Int32 nLen(rSource.getLength());
231  maNamespace.clear();
232  maName = rSource;
233 
234  if(nLen)
235  {
236  const sal_Int32 nIndex(rSource.indexOf(':', 0));
237 
238  if(nIndex > 0 && ((nIndex + 1) < nLen))
239  {
240  maNamespace = mapNamespaceToken(rSource.copy(0, nIndex));
241  maName = rSource.copy(nIndex + 1);
242  }
243  }
244  }
245 
246  WebDAVContext::WebDAVContext(WebDAVContext* pParent, const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs)
247  : mpParent(pParent),
248  maNamespaceMap(),
249  maWhiteSpace(),
250  maNamespace(),
251  maName(),
252  maWebDAVNamespace(WebDAVNamespace_unknown),
253  maWebDAVName(WebDAVName_unknown)
254  {
255  const sal_Int16 nAttributes(xAttribs->getLength());
256 
257  if(nAttributes)
258  {
259  // parse evtl. namespace entries
260  parseForNamespaceTokens(xAttribs);
261  }
262 
263  // split name to namespace and name
264  splitName(aName);
265 
266  // evaluate enums for namespace and name
267  maWebDAVNamespace = StrToWebDAVNamespace(maNamespace);
268  maWebDAVName = StrToWebDAVName(maName);
269  }
270 } // end of anonymous namespace
271 
272 
273 // the Xml parser itself
274 
275 namespace
276 {
278  {
279  WebDAVResponseParserMode_PropFind = 0,
280  WebDAVResponseParserMode_PropName,
281  WebDAVResponseParserMode_Lock
282  };
283 
284  class WebDAVResponseParser : public cppu::WeakImplHelper< css::xml::sax::XDocumentHandler >
285  {
286  private:
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;
290 
291  WebDAVContext* mpContext;
292  OUString maHref;
293  OUString maStatus;
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;
301  ucb::Lock maLock;
302  WebDAVResponseParserMode meWebDAVResponseParserMode;
303 
304  bool mbResourceTypeCollection : 1;
305  bool mbLockScopeSet : 1;
306  bool mbLockTypeSet : 1;
307 
308  // local helpers
309  bool whitespaceIsAvailable() const
310  {
311  return mpContext && mpContext->getWhiteSpace().getLength();
312  }
313  bool hasParent(WebDAVName aWebDAVName) const
314  {
315  return mpContext && mpContext->getParent() && aWebDAVName == mpContext->getParent()->getWebDAVName();
316  }
317  bool propertyIsReady() const
318  {
319  return hasParent(WebDAVName_prop) && whitespaceIsAvailable();
320  }
321  bool isCollectingProperties() const
322  {
323  return WebDAVResponseParserMode_PropFind == meWebDAVResponseParserMode;
324  }
325  bool isCollectingPropNames() const
326  {
327  return WebDAVResponseParserMode_PropName == meWebDAVResponseParserMode;
328  }
329  bool collectThisPropertyAsName() const
330  {
331  return isCollectingPropNames() && hasParent(WebDAVName_prop);
332  }
333  void pop_context()
334  {
335  if(mpContext)
336  {
337  WebDAVContext* pTemp = mpContext;
338  mpContext = mpContext->getParent();
339  delete pTemp;
340  }
341  else
342  {
343  SAL_WARN( "ucb.ucp.webdav", "Parser context pop without context (!)");
344  }
345  }
346 
347  public:
348  explicit WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode);
349  virtual ~WebDAVResponseParser() override;
350 
351  // Methods XDocumentHandler
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;
360 
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; }
364  };
365 
366  WebDAVResponseParser::WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode)
367  : maResult_PropFind(),
368  maResult_PropName(),
369  mpContext(nullptr),
370  maHref(),
371  maStatus(),
372  maResponseProperties(),
373  maPropStatProperties(),
374  maResponseNames(),
375  maPropStatNames(),
376  maLockEntries(),
377  maLockScope(ucb::LockScope_EXCLUSIVE),
378  maLockType(ucb::LockType_WRITE),
379  meWebDAVResponseParserMode(eWebDAVResponseParserMode),
380  mbResourceTypeCollection(false),
381  mbLockScopeSet(false),
382  mbLockTypeSet(false)
383  {
384  }
385 
386  WebDAVResponseParser::~WebDAVResponseParser()
387  {
388  SAL_WARN_IF(mpContext, "ucb.ucp.webdav", "Parser destructed with existing content (!)");
389  while(mpContext)
390  {
391  pop_context();
392  }
393  }
394 
395  void SAL_CALL WebDAVResponseParser::startDocument( )
396  {
397  SAL_WARN_IF(mpContext, "ucb.ucp.webdav", "Parser start with existing content (!)");
398  }
399 
400  void SAL_CALL WebDAVResponseParser::endDocument( )
401  {
402  SAL_WARN_IF(mpContext, "ucb.ucp.webdav", "Parser end with existing content (!)");
403  }
404 
405  void SAL_CALL WebDAVResponseParser::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
406  {
407  const sal_Int32 nLen(aName.getLength());
408 
409  if(nLen)
410  {
411  // create new context (push)
412  mpContext = new WebDAVContext(mpContext, aName, xAttribs);
413 
414  if(collectThisPropertyAsName())
415  {
416  // When collecting property names and parent is prop there is no need
417  // to handle the content of this property deeper (evtl. preparations)
418  }
419  else
420  {
421  switch(mpContext->getWebDAVNamespace())
422  {
423  default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
424  {
425  break;
426  }
427  case WebDAVNamespace_DAV:
428  {
429  switch(mpContext->getWebDAVName())
430  {
431  default: // WebDAVName_unknown, WebDAVName_last or unhandled
432  {
433  break;
434  }
435  case WebDAVName_propstat:
436  {
437  // propstat start
438  if(isCollectingProperties())
439  {
440  // reset maPropStatProperties
441  maPropStatProperties.clear();
442  }
443  else
444  {
445  // when collecting properties reset maPropStatNames
446  maPropStatNames.clear();
447  }
448  break;
449  }
450  case WebDAVName_response:
451  {
452  // response start, reset Href and status and maResponseProperties
453  maHref.clear();
454  maStatus.clear();
455 
456  if(isCollectingProperties())
457  {
458  // reset maResponseProperties
459  maResponseProperties.clear();
460  }
461  else
462  {
463  // reset maResponseNames when collecting properties
464  maResponseNames.clear();
465  }
466  break;
467  }
468  case WebDAVName_resourcetype:
469  {
470  // resourcetype start, reset collection
471  mbResourceTypeCollection = false;
472  break;
473  }
474  case WebDAVName_supportedlock:
475  {
476  // supportedlock start, reset maLockEntries
477  maLockEntries.realloc(0);
478  break;
479  }
480  case WebDAVName_lockentry:
481  {
482  // lockentry start, reset maLockEntries
483  mbLockScopeSet = false;
484  mbLockTypeSet = false;
485  break;
486  }
487  case WebDAVName_activelock:
488  {
489  maLock = ucb::Lock();
490  break;
491  }
492  }
493  break;
494  }
495  case WebDAVNamespace_ucb_openoffice_org_dav_props:
496  {
497  break;
498  }
499  }
500  }
501  }
502  }
503 
504  void SAL_CALL WebDAVResponseParser::endElement( const OUString& aName )
505  {
506  const sal_Int32 nLen(aName.getLength());
507  SAL_WARN_IF(!mpContext, "ucb.ucp.webdav", "Parser EndElement without content (!)");
508 
509  if(mpContext && nLen)
510  {
511  if(collectThisPropertyAsName())
512  {
513  // When collecting property names and parent is prop, just append the prop name
514  // to the collection, no need to parse deeper
515  maPropStatNames.push_back(mpContext->getNamespace() + mpContext->getName());
516  }
517  else
518  {
519  switch(mpContext->getWebDAVNamespace())
520  {
521  default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
522  {
523  break;
524  }
525  case WebDAVNamespace_DAV:
526  {
527  switch(mpContext->getWebDAVName())
528  {
529  default: // WebDAVName_unknown, WebDAVName_last or unhandled
530  {
531  break;
532  }
533  case WebDAVName_href:
534  {
535  // href end, save it if we have whitespace
536  if(whitespaceIsAvailable())
537  {
538  maHref = mpContext->getWhiteSpace();
539  }
540  break;
541  }
542  case WebDAVName_status:
543  {
544  // status end, save it if we have whitespace
545  if(whitespaceIsAvailable())
546  {
547  maStatus = mpContext->getWhiteSpace();
548  }
549  break;
550  }
551  case WebDAVName_getlastmodified:
552  {
553  // getlastmodified end, safe if content is correct
554  if(propertyIsReady())
555  {
556  http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
557 
558  aDAVPropertyValue.Name = "DAV:getlastmodified";
559  aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
560  maPropStatProperties.push_back(aDAVPropertyValue);
561  }
562  break;
563  }
564  case WebDAVName_creationdate:
565  {
566  // creationdate end, safe if content is correct
567  if(propertyIsReady())
568  {
569  http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
570 
571  aDAVPropertyValue.Name = "DAV:creationdate";
572  aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
573  maPropStatProperties.push_back(aDAVPropertyValue);
574  }
575  break;
576  }
577  case WebDAVName_collection:
578  {
579  // collection end, check and set
580  if(hasParent(WebDAVName_resourcetype))
581  {
582  mbResourceTypeCollection = true;
583  }
584  break;
585  }
586  case WebDAVName_resourcetype:
587  {
588  // resourcetype end, check for collection
589  if(hasParent(WebDAVName_prop))
590  {
591  http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
592 
593  aDAVPropertyValue.Name = "DAV:resourcetype";
594  aDAVPropertyValue.Value <<= (mbResourceTypeCollection ? OUString("collection") : OUString());
595  maPropStatProperties.push_back(aDAVPropertyValue);
596  }
597  break;
598  }
599  case WebDAVName_getcontentlength:
600  {
601  // getcontentlength end, safe if content is correct
602  if(propertyIsReady())
603  {
604  http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
605 
606  aDAVPropertyValue.Name = "DAV:getcontentlength";
607  aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
608  maPropStatProperties.push_back(aDAVPropertyValue);
609  }
610  break;
611  }
612  case WebDAVName_getcontenttype:
613  {
614  // getcontenttype end, safe if content is correct
615  if(propertyIsReady())
616  {
617  http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
618 
619  aDAVPropertyValue.Name = "DAV:getcontenttype";
620  aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
621  maPropStatProperties.push_back(aDAVPropertyValue);
622  }
623  break;
624  }
625  case WebDAVName_supportedlock:
626  {
627  // supportedlock end
628  if(hasParent(WebDAVName_prop) && maLockEntries.hasElements())
629  {
630  http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
631 
632  aDAVPropertyValue.Name = "DAV:supportedlock";
633  aDAVPropertyValue.Value <<= maLockEntries;
634  maPropStatProperties.push_back(aDAVPropertyValue);
635  }
636  break;
637  }
638  case WebDAVName_lockentry:
639  {
640  // lockentry end
641  if(hasParent(WebDAVName_supportedlock) && (mbLockScopeSet && mbLockTypeSet))
642  {
643  const sal_Int32 nLength(maLockEntries.getLength());
644  ucb::LockEntry aEntry;
645 
646  aEntry.Scope = maLockScope;
647  aEntry.Type = maLockType;
648  maLockEntries.realloc(nLength + 1);
649  maLockEntries[nLength] = aEntry;
650  }
651  break;
652  }
653  case WebDAVName_owner:
654  {
655  maLock.Owner <<= mpContext->getWhiteSpace();
656  break;
657  }
658  case WebDAVName_timeout:
659  {
660  const OUString sTimeout(mpContext->getWhiteSpace());
661  if (sTimeout == "Infinite")
662  maLock.Timeout = -1;
663  else if (sTimeout.startsWith("Second-"))
664  maLock.Timeout = sTimeout.copy(7).toInt64();
665  break;
666  }
667  case WebDAVName_locktoken:
668  {
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;
675  break;
676  }
677  case WebDAVName_exclusive:
678  {
679  // exclusive lockscope end
680  if(hasParent(WebDAVName_lockscope))
681  {
682  maLockScope = ucb::LockScope_EXCLUSIVE;
683  mbLockScopeSet = true;
684  }
685  break;
686  }
687  case WebDAVName_shared:
688  {
689  // shared lockscope end
690  if(hasParent(WebDAVName_lockscope))
691  {
692  maLockScope = ucb::LockScope_SHARED;
693  mbLockScopeSet = true;
694  }
695  break;
696  }
697  case WebDAVName_write:
698  {
699  // write locktype end
700  if(hasParent(WebDAVName_locktype))
701  {
702  maLockType = ucb::LockType_WRITE;
703  mbLockTypeSet = true;
704  }
705  break;
706  }
707  case WebDAVName_activelock:
708  {
709  maLock.Type = maLockType;
710  maLock.Scope = maLockScope;
711  maResult_Lock.push_back(maLock);
712  }
713  [[fallthrough]]; // I hope intentional?
714  case WebDAVName_propstat:
715  {
716  // propstat end, check status
717  if(maStatus.getLength())
718  {
719  if(maStatus == "HTTP/1.1 200 OK")
720  {
721  if(isCollectingProperties())
722  {
723  if(!maPropStatProperties.empty())
724  {
725  // append to maResponseProperties if okay
726  maResponseProperties.insert(maResponseProperties.end(), maPropStatProperties.begin(), maPropStatProperties.end());
727  }
728  }
729  else
730  {
731  if(!maPropStatNames.empty())
732  {
733  // when collecting properties append to
734  maResponseNames.insert(maResponseNames.end(), maPropStatNames.begin(), maPropStatNames.end());
735  }
736  }
737  }
738  }
739  break;
740  }
741  case WebDAVName_response:
742  {
743  // response end
744  if(maHref.getLength())
745  {
746  if(isCollectingProperties())
747  {
748  // create DAVResource when we have content
749  if(!maResponseProperties.empty())
750  {
751  http_dav_ucp::DAVResource aDAVResource;
752 
753  aDAVResource.uri = maHref;
754  aDAVResource.properties = maResponseProperties;
755  maResult_PropFind.push_back(aDAVResource);
756  }
757  }
758  else
759  {
760  // when collecting properties add them to result when there are some
761  if(!maResponseNames.empty())
762  {
763  http_dav_ucp::DAVResourceInfo aDAVResourceInfo(maHref);
764 
765  aDAVResourceInfo.properties = maResponseNames;
766  maResult_PropName.push_back(aDAVResourceInfo);
767  }
768  }
769  }
770  break;
771  }
772  }
773  break;
774  }
775  case WebDAVNamespace_ucb_openoffice_org_dav_props:
776  {
777  break;
778  }
779  }
780  }
781 
782  // destroy last context (pop)
783  pop_context();
784  }
785  }
786 
787  void SAL_CALL WebDAVResponseParser::characters( const OUString& aChars )
788  {
789  // collect whitespace over evtl. several calls in mpContext
790  SAL_WARN_IF(!mpContext, "ucb.ucp.webdav", "Parser characters without content (!)");
791  const sal_Int32 nLen(aChars.getLength());
792 
793  if(mpContext && nLen)
794  {
795  // remove leading/trailing blanks and CRLF
796  const OUString aTrimmedChars(aChars.trim());
797 
798  if(aTrimmedChars.getLength())
799  {
800  OUString aNew(mpContext->getWhiteSpace());
801 
802  if(aNew.getLength())
803  {
804  // add one char when appending (see html1.1 spec)
805  aNew += " ";
806  }
807 
808  aNew += aTrimmedChars;
809  mpContext->setWhiteSpace(aNew);
810  }
811  }
812  }
813 
814  void SAL_CALL WebDAVResponseParser::ignorableWhitespace( const OUString& /*aWhitespaces*/ )
815  {
816  }
817 
818  void SAL_CALL WebDAVResponseParser::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ )
819  {
820  }
821 
822  void SAL_CALL WebDAVResponseParser::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ )
823  {
824  }
825 } // end of anonymous namespace
826 
827 
828 // wrapper for various calls to the parser
829 
830 namespace
831 {
832  template<typename T>
833  void parseWebDAVResponse(
834  const uno::Reference< io::XInputStream >& xInputStream,
835  std::vector< T >& rResult,
836  WebDAVResponseParserMode eWebDAVResponseParserMode,
837  std::vector<T> const & (WebDAVResponseParser::* fn)() const)
838  {
839  if(xInputStream.is())
840  {
841  try
842  {
843  // prepare ParserInputSrouce
844  xml::sax::InputSource myInputSource;
845  myInputSource.aInputStream = xInputStream;
846 
847  // get parser
848  uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(
850 
851  // create parser; connect parser and filter
852  WebDAVResponseParser* pWebDAVResponseParser = new WebDAVResponseParser(eWebDAVResponseParserMode);
853  uno::Reference< xml::sax::XDocumentHandler > xWebDAVHdl(pWebDAVResponseParser);
854  xParser->setDocumentHandler(xWebDAVHdl);
855 
856  // finally, parse the stream
857  xParser->parseStream(myInputSource);
858 
859  // get result
860  rResult = (pWebDAVResponseParser->*fn)();
861  }
862  catch(uno::Exception&)
863  {
864  SAL_WARN("ucb.ucp.webdav", "WebDAV Parse error (!)");
865  }
866  }
867  }
868 } // end of anonymous namespace
869 
870 
871 // helper to parse a XML WebDAV response
872 
873 namespace http_dav_ucp
874 {
875  std::vector< ucb::Lock > parseWebDAVLockResponse(const uno::Reference< io::XInputStream >& xInputStream)
876  {
877  std::vector< ucb::Lock > aResult;
878  parseWebDAVResponse< ucb::Lock >(xInputStream, aResult, WebDAVResponseParserMode_Lock, &WebDAVResponseParser::getResult_Lock);
879  return aResult;
880  }
881 
882  std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream >& xInputStream)
883  {
884  std::vector< DAVResource > aResult;
885  parseWebDAVResponse< DAVResource >(xInputStream, aResult, WebDAVResponseParserMode_PropFind, &WebDAVResponseParser::getResult_PropFind);
886  return aResult;
887  }
888 
889  std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream >& xInputStream)
890  {
891  std::vector< DAVResourceInfo > aResult;
892  parseWebDAVResponse< DAVResourceInfo >(xInputStream, aResult, WebDAVResponseParserMode_PropName, &WebDAVResponseParser::getResult_PropName);
893  return aResult;
894  }
895 } // namespace http_dav_ucp
896 
897 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::vector< ucb::Lock > parseWebDAVLockResponse(const uno::Reference< io::XInputStream > &xInputStream)
OUString const maName
ParserContextSharedPtr mpContext
std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream > &xInputStream)
#define SAL_WARN_IF(condition, area, stream)
Reference< XComponentContext > getProcessComponentContext()
std::vector< DAVPropertyValue > properties
Definition: DAVResource.hxx:44
std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream > &xInputStream)
OString const aName
WebDAVResponseParserMode
#define SAL_WARN(area, stream)
sal_Int32 const nLength