xref: /trunk/main/ucb/source/ucp/webdav/webdavresponseparser.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_webdav.hxx"
24 
25 #include "webdavresponseparser.hxx"
26 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
27 #include <cppuhelper/implbase2.hxx>
28 #include <com/sun/star/xml/sax/XParser.hpp>
29 #include <com/sun/star/xml/sax/InputSource.hpp>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/seqstream.hxx>
32 #include <com/sun/star/ucb/Lock.hpp>
33 #include <com/sun/star/ucb/LockDepth.hpp>
34 #include <com/sun/star/ucb/LockEntry.hpp>
35 #include <com/sun/star/ucb/LockScope.hpp>
36 #include <com/sun/star/ucb/LockType.hpp>
37 #include <map>
38 #include <hash_map>
39 
40 //////////////////////////////////////////////////////////////////////////////
41 
42 using namespace com::sun::star;
43 
44 //////////////////////////////////////////////////////////////////////////////
45 // WebDAVNamespace enum and StringToEnum converter
46 
47 namespace
48 {
49     enum WebDAVNamespace
50     {
51         WebDAVNamespace_unknown = 0,
52         WebDAVNamespace_DAV,
53         WebDAVNamespace_ucb_openoffice_org_dav_props,
54 
55         WebDAVNamespace_last
56     };
57 
StrToWebDAVNamespace(const rtl::OUString & rStr)58     WebDAVNamespace StrToWebDAVNamespace(const rtl::OUString& rStr)
59     {
60         static ::rtl::OUString aStrDAV(::rtl::OUString::createFromAscii("DAV:"));
61         static ::rtl::OUString aStrUcbOpenofficeOrgDAVProps(::rtl::OUString::createFromAscii("http://ucb.openoffice.org/dav/props/"));
62 
63         if(rStr.equals(aStrDAV))
64         {
65             return WebDAVNamespace_DAV;
66         }
67         else if(rStr.equals(aStrUcbOpenofficeOrgDAVProps))
68         {
69             return WebDAVNamespace_ucb_openoffice_org_dav_props;
70         }
71 
72         return WebDAVNamespace_unknown;
73     }
74 } // end of anonymous namespace
75 
76 //////////////////////////////////////////////////////////////////////////////
77 // WebDAVName enum and StringToEnum converter using hash_map
78 
79 namespace
80 {
81     enum WebDAVName
82     {
83         WebDAVName_unknown = 0,
84         WebDAVName_multistatus,
85         WebDAVName_response,
86         WebDAVName_href,
87         WebDAVName_propstat,
88         WebDAVName_prop,
89         WebDAVName_resourcetype,
90         WebDAVName_collection,
91         WebDAVName_getcontenttype,
92         WebDAVName_supportedlock,
93         WebDAVName_lockentry,
94         WebDAVName_lockscope,
95         WebDAVName_exclusive,
96         WebDAVName_locktype,
97         WebDAVName_write,
98         WebDAVName_shared,
99         WebDAVName_lockdiscovery,
100         WebDAVName_activelock,
101         WebDAVName_depth,
102         WebDAVName_owner,
103         WebDAVName_timeout,
104         WebDAVName_locktoken,
105         WebDAVName_status,
106         WebDAVName_getlastmodified,
107         WebDAVName_creationdate,
108         WebDAVName_getcontentlength,
109 
110         WebDAVName_last
111     };
112 
StrToWebDAVName(const rtl::OUString & rStr)113     WebDAVName StrToWebDAVName(const rtl::OUString& rStr)
114     {
115         typedef std::hash_map< rtl::OUString, WebDAVName, rtl::OUStringHash > WebDAVNameMapper;
116         typedef std::pair< rtl::OUString, WebDAVName > WebDAVNameValueType;
117         static WebDAVNameMapper aWebDAVNameMapperList;
118 
119         if(aWebDAVNameMapperList.empty())
120         {
121             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("multistatus"), WebDAVName_multistatus));
122             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("response"), WebDAVName_response));
123             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("href"), WebDAVName_href));
124             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("propstat"), WebDAVName_propstat));
125             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("prop"), WebDAVName_prop));
126             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("resourcetype"), WebDAVName_resourcetype));
127             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("collection"), WebDAVName_collection));
128             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("getcontenttype"), WebDAVName_getcontenttype));
129             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("supportedlock"), WebDAVName_supportedlock));
130             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("lockentry"), WebDAVName_lockentry));
131             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("lockscope"), WebDAVName_lockscope));
132             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("exclusive"), WebDAVName_exclusive));
133             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("locktype"), WebDAVName_locktype));
134             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("write"), WebDAVName_write));
135             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("shared"), WebDAVName_shared));
136             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("lockdiscovery"), WebDAVName_lockdiscovery));
137             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("activelock"), WebDAVName_activelock));
138             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("depth"), WebDAVName_depth));
139             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("owner"), WebDAVName_owner));
140             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("timeout"), WebDAVName_timeout));
141             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("locktoken"), WebDAVName_locktoken));
142             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("status"), WebDAVName_status));
143             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("getlastmodified"), WebDAVName_getlastmodified));
144             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("creationdate"), WebDAVName_creationdate));
145             aWebDAVNameMapperList.insert(WebDAVNameValueType(rtl::OUString::createFromAscii("getcontentlength"), WebDAVName_getcontentlength));
146         }
147 
148         const WebDAVNameMapper::const_iterator aResult(aWebDAVNameMapperList.find(rStr));
149 
150         if(aResult == aWebDAVNameMapperList.end())
151         {
152             return WebDAVName_unknown;
153         }
154         else
155         {
156             return aResult->second;
157         }
158     }
159 } // end of anonymous namespace
160 
161 //////////////////////////////////////////////////////////////////////////////
162 // WebDAVContext, holding information for each start/endElement pair
163 
164 namespace
165 {
166     typedef std::map< ::rtl::OUString, ::rtl::OUString > NamespaceMap;
167     typedef std::pair< const ::rtl::OUString, ::rtl::OUString > NamespaceValueType;
168 
169     class WebDAVContext
170     {
171     private:
172         WebDAVContext*              mpParent;
173         NamespaceMap                maNamespaceMap;
174         ::rtl::OUString             maWhiteSpace;
175 
176         ::rtl::OUString             maNamespace;
177         ::rtl::OUString             maName;
178 
179         WebDAVNamespace             maWebDAVNamespace;
180         WebDAVName                  maWebDAVName;
181 
182         // local helpers
183         void parseForNamespaceTokens(const uno::Reference< xml::sax::XAttributeList >& xAttribs);
184         ::rtl::OUString mapNamespaceToken(const ::rtl::OUString& rToken) const;
185         void splitName(const ::rtl::OUString& rSource);
186 
187     public:
188         WebDAVContext(WebDAVContext* pParent, const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs);
189         ~WebDAVContext();
190 
getParent() const191         WebDAVContext* getParent() const { return mpParent; }
getWhiteSpace()192         ::rtl::OUString& getWhiteSpace() { return maWhiteSpace; }
setWhiteSpace(const::rtl::OUString & rNew)193         void setWhiteSpace(const ::rtl::OUString& rNew) { maWhiteSpace = rNew; }
194 
getNamespace() const195         const ::rtl::OUString& getNamespace() const { return maNamespace; }
getName() const196         const ::rtl::OUString& getName() const { return maName; }
getWebDAVNamespace() const197         WebDAVNamespace getWebDAVNamespace() const { return maWebDAVNamespace; }
getWebDAVName() const198         WebDAVName getWebDAVName() const { return maWebDAVName; }
199     };
200 
parseForNamespaceTokens(const uno::Reference<xml::sax::XAttributeList> & xAttribs)201     void WebDAVContext::parseForNamespaceTokens(const uno::Reference< xml::sax::XAttributeList >& xAttribs)
202     {
203         const sal_Int16 nAttributes(xAttribs->getLength());
204         static ::rtl::OUString aStrXmlns(::rtl::OUString::createFromAscii("xmlns"));
205 
206         for(sal_Int16 a(0); a < nAttributes; a++)
207         {
208             const ::rtl::OUString aName(xAttribs->getNameByIndex(a));
209             const sal_Int32 nLen(aName.getLength());
210 
211             if(nLen)
212             {
213                 if(aName.match(aStrXmlns, 0))
214                 {
215                     const sal_Int32 nIndex(aName.indexOf(sal_Unicode(':'), 0));
216 
217                     if(-1 != nIndex && nIndex + 1 < nLen)
218                     {
219                         const ::rtl::OUString aToken(aName.copy(nIndex + 1));
220 
221                         maNamespaceMap.insert(NamespaceValueType(aToken, xAttribs->getValueByIndex(a)));
222                     }
223                 }
224             }
225         }
226     }
227 
mapNamespaceToken(const::rtl::OUString & rToken) const228     ::rtl::OUString WebDAVContext::mapNamespaceToken(const ::rtl::OUString& rToken) const
229     {
230         NamespaceMap::const_iterator iter = maNamespaceMap.find(rToken);
231 
232         if(maNamespaceMap.end() == iter)
233         {
234             if(getParent())
235             {
236                 return getParent()->mapNamespaceToken(rToken);
237             }
238             else
239             {
240                 return rToken;
241             }
242         }
243         else
244         {
245             return (*iter).second;
246         }
247     }
248 
splitName(const::rtl::OUString & rSource)249     void WebDAVContext::splitName(const ::rtl::OUString& rSource)
250     {
251         const sal_Int32 nLen(rSource.getLength());
252         maNamespace = ::rtl::OUString();
253         maName = rSource;
254 
255         if(nLen)
256         {
257             const sal_Int32 nIndex(rSource.indexOf(sal_Unicode(':'), 0));
258 
259             if(-1 != nIndex && nIndex > 0 && nIndex + 1 < nLen)
260             {
261                 maNamespace = mapNamespaceToken(rSource.copy(0, nIndex));
262                 maName = rSource.copy(nIndex + 1);
263             }
264         }
265     }
266 
WebDAVContext(WebDAVContext * pParent,const::rtl::OUString & aName,const uno::Reference<xml::sax::XAttributeList> & xAttribs)267     WebDAVContext::WebDAVContext(WebDAVContext* pParent, const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs)
268     :   mpParent(pParent),
269         maNamespaceMap(),
270         maWhiteSpace(),
271         maNamespace(),
272         maName(),
273         maWebDAVNamespace(WebDAVNamespace_unknown),
274         maWebDAVName(WebDAVName_unknown)
275     {
276         const sal_Int16 nAttributes(xAttribs->getLength());
277 
278         if(nAttributes)
279         {
280             // parse evtl. namespace entries
281             parseForNamespaceTokens(xAttribs);
282         }
283 
284         // split name to namespace and name
285         splitName(aName);
286 
287         // evaluate enums for namespace and name
288         maWebDAVNamespace = StrToWebDAVNamespace(maNamespace);
289         maWebDAVName = StrToWebDAVName(maName);
290     }
291 
~WebDAVContext()292     WebDAVContext::~WebDAVContext()
293     {
294     }
295 } // end of anonymous namespace
296 
297 //////////////////////////////////////////////////////////////////////////////
298 // the Xml parser itself
299 
300 namespace
301 {
302     enum WebDAVResponseParserMode
303     {
304         WebDAVResponseParserMode_PropFind = 0,
305         WebDAVResponseParserMode_PropName,
306         WebDAVResponseParserMode_LockResponse
307     };
308 
309     class WebDAVResponseParser : public cppu::WeakImplHelper1< com::sun::star::xml::sax::XDocumentHandler >
310     {
311     private:
312         std::vector< http_dav_ucp::DAVResource >      maResult_PropFind;
313         std::vector< http_dav_ucp::DAVResourceInfo >  maResult_PropName;
314         http_dav_ucp::DAVPropertyValue                maResult_Lock;
315 
316         WebDAVContext*                              mpContext;
317         ::rtl::OUString                             maHref;
318         ::rtl::OUString                             maHrefLocks; //this is used for locks, when lockdiscoveryactive
319 
320         ::rtl::OUString                             maStatus;
321         std::vector< http_dav_ucp::DAVPropertyValue > maResponseProperties;
322         std::vector< http_dav_ucp::DAVPropertyValue > maPropStatProperties;
323         std::vector< ::rtl::OUString >              maResponseNames;
324         std::vector< ::rtl::OUString >              maPropStatNames;
325         uno::Sequence< ::rtl::OUString >            maLockTokens;
326         uno::Sequence< ucb::LockEntry >             maLockEntries;
327         uno::Sequence< ucb::Lock >                  maLocks;    //the returned locks following a lockdiscovery request
328         ucb::LockScope                              maLockScope;
329         ucb::LockType                               maLockType;
330         ucb::LockDepth                              maLockDepth;
331         ::rtl::OUString                             maLockOwner;
332         sal_Int64                                   maLockTimeout;
333         ::rtl::OUString                             maLockToken;
334 
335       WebDAVResponseParserMode                    meWebDAVResponseParserMode;
336 
337         // bitfield
338         bool                                        mbResourceTypeCollection : 1;
339         bool                                        mbLockScopeSet : 1;
340         bool                                        mbLockTypeSet : 1;
341         bool                                        mbLockTokenSet : 1;
342         //TODO: add other flag to manage reading od token, depth, timeout, owner
343         bool                                        mbLockDiscoveryActive : 1;
344 
345         // local helpers
whitespaceIsAvailable() const346         bool whitespaceIsAvailable() const
347         {
348             return mpContext && mpContext->getWhiteSpace().getLength();
349         }
hasParent(WebDAVName aWebDAVName) const350         bool hasParent(WebDAVName aWebDAVName) const
351         {
352             return mpContext && mpContext->getParent() && aWebDAVName == mpContext->getParent()->getWebDAVName();
353         }
propertyIsReady() const354         bool propertyIsReady() const
355         {
356             return hasParent(WebDAVName_prop) && whitespaceIsAvailable();
357         }
isCollectingProperties() const358         bool isCollectingProperties() const
359         {
360             return WebDAVResponseParserMode_PropFind == meWebDAVResponseParserMode;
361         }
isCollectingPropNames() const362         bool isCollectingPropNames() const
363         {
364             return WebDAVResponseParserMode_PropName == meWebDAVResponseParserMode;
365         }
isWaitingLockResponse() const366         bool isWaitingLockResponse() const
367         {
368             return WebDAVResponseParserMode_LockResponse == meWebDAVResponseParserMode;
369         }
collectThisPropertyAsName() const370         bool collectThisPropertyAsName() const
371         {
372             return isCollectingPropNames() && hasParent(WebDAVName_prop);
373         }
pop_context()374         void pop_context()
375         {
376             if(mpContext)
377             {
378                 WebDAVContext* pTemp = mpContext;
379                 mpContext = mpContext->getParent();
380                 delete pTemp;
381             }
382             else
383             {
384                 OSL_ENSURE(false, "Parser context pop without context (!)");
385             }
386         }
387 
388     public:
389         WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode);
390         ~WebDAVResponseParser();
391 
392         // Methods XDocumentHandler
393         virtual void SAL_CALL startDocument(  );
394         virtual void SAL_CALL endDocument(  );
395         virtual void SAL_CALL startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs );
396         virtual void SAL_CALL endElement( const ::rtl::OUString& aName );
397         virtual void SAL_CALL characters( const ::rtl::OUString& aChars );
398         virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces );
399         virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData );
400         virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator );
401 
getResult_PropFind() const402         const std::vector< http_dav_ucp::DAVResource >& getResult_PropFind() const { return maResult_PropFind; }
getResult_PropName() const403         const std::vector< http_dav_ucp::DAVResourceInfo >& getResult_PropName() const { return maResult_PropName; }
getResult_Lock() const404         const http_dav_ucp::DAVPropertyValue& getResult_Lock() const { return maResult_Lock; }
405     };
406 
WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode)407     WebDAVResponseParser::WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode)
408     :   maResult_PropFind(),
409         maResult_PropName(),
410         maResult_Lock(),
411         mpContext(0),
412         maHref(),
413         maHrefLocks(),
414         maStatus(),
415         maResponseProperties(),
416         maPropStatProperties(),
417         maResponseNames(),
418         maPropStatNames(),
419         maLockTokens(),
420         maLockEntries(),
421         maLocks(),
422         maLockScope(ucb::LockScope_EXCLUSIVE),
423         maLockType(ucb::LockType_WRITE),
424         maLockDepth(ucb::LockDepth_ZERO),
425         maLockOwner(),
426         maLockTimeout(0),
427         meWebDAVResponseParserMode(eWebDAVResponseParserMode),
428         mbResourceTypeCollection(false),
429         mbLockScopeSet(false),
430         mbLockTypeSet(false),
431         mbLockDiscoveryActive(false)
432     {
433     }
434 
~WebDAVResponseParser()435     WebDAVResponseParser::~WebDAVResponseParser()
436     {
437         OSL_ENSURE(!mpContext, "Parser destructed with existing content (!)");
438         while(mpContext)
439         {
440             pop_context();
441         }
442     }
443 
startDocument()444     void SAL_CALL WebDAVResponseParser::startDocument(  )
445     {
446         OSL_ENSURE(!mpContext, "Parser start with existing content (!)");
447     }
448 
endDocument()449     void SAL_CALL WebDAVResponseParser::endDocument(  )
450     {
451         OSL_ENSURE(!mpContext, "Parser end with existing content (!)");
452     }
453 
startElement(const::rtl::OUString & aName,const uno::Reference<xml::sax::XAttributeList> & xAttribs)454     void SAL_CALL WebDAVResponseParser::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
455     {
456         const sal_Int32 nLen(aName.getLength());
457 
458         if(nLen)
459         {
460             // create new context (push)
461             mpContext = new WebDAVContext(mpContext, aName, xAttribs);
462 
463             if(collectThisPropertyAsName())
464             {
465                 // When collecting property names and parent is prop there is no need
466                 // to handle the content of this property deeper (evtl. preparations)
467             }
468             else
469             {
470                 switch(mpContext->getWebDAVNamespace())
471                 {
472                     default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
473                     {
474                         break;
475                     }
476                     case WebDAVNamespace_DAV:
477                     {
478                         switch(mpContext->getWebDAVName())
479                         {
480                             default: // WebDAVName_unknown, WebDAVName_last or unhandled
481                             {
482                                 break;
483                             }
484                             case WebDAVName_propstat:
485                             {
486                                 // propstat start
487                                 if(isCollectingProperties())
488                                 {
489                                     // reset maPropStatProperties
490                                     maPropStatProperties.clear();
491                                 }
492                                 else
493                                 {
494                                     // when collecting properties reset maPropStatNames
495                                     maPropStatNames.clear();
496                                 }
497                                 break;
498                             }
499                             case WebDAVName_response:
500                             {
501                                 // response start, reset Href and status and maResponseProperties
502                                 maHref = maStatus = ::rtl::OUString();
503 
504                                 if(isCollectingProperties())
505                                 {
506                                     // reset maResponseProperties
507                                     maResponseProperties.clear();
508                                 }
509                                 else
510                                 {
511                                     // reset maResponseNames when collecting properties
512                                     maResponseNames.clear();
513                                 }
514                                 break;
515                             }
516                             case WebDAVName_resourcetype:
517                             {
518                                 // resourcetype start, reset collection
519                                 mbResourceTypeCollection = false;
520                                 break;
521                             }
522                             case WebDAVName_supportedlock:
523                             {
524                                 // supportedlock start, reset maLockEntries
525                                 maLockEntries.realloc(0);
526                                 break;
527                             }
528                             case WebDAVName_lockentry:
529                             {
530                                 // lockentry start, reset maLockEntries
531                                 mbLockScopeSet = false;
532                                 mbLockTypeSet = false;
533                                 break;
534                             }
535                             case WebDAVName_lockdiscovery:
536                             {
537                                 // lockentry start, reset maLocks
538                                 maLocks.realloc(0);
539                                 mbLockDiscoveryActive = true;
540                                 break;
541                             }
542                             case WebDAVName_activelock:
543                             {
544                                 //  activelockstart, reset vars
545                                 mbLockScopeSet = false;
546                                 mbLockTypeSet = false;
547                                 mbLockTokenSet = false;
548                                 maLockTokens.realloc(0);
549                                 maHrefLocks = ::rtl::OUString();
550                                 break;
551                             }
552                             case WebDAVName_locktoken:
553                             {
554                                 mbLockTokenSet = true;
555                                 break;
556                             }
557                         }
558                         break;
559                     }
560                     case WebDAVNamespace_ucb_openoffice_org_dav_props:
561                     {
562                         break;
563                     }
564                 }
565             }
566         }
567     }
568 
endElement(const::rtl::OUString & aName)569     void SAL_CALL WebDAVResponseParser::endElement( const ::rtl::OUString& aName )
570     {
571         const sal_Int32 nLen(aName.getLength());
572         OSL_ENSURE(mpContext, "Parser EndElement without content (!)");
573 
574         if(mpContext && nLen)
575         {
576             if(collectThisPropertyAsName())
577             {
578                 // When collecting property names and parent is prop, just append the prop name
579                 // to the collection, no need to parse deeper
580                 maPropStatNames.push_back(mpContext->getNamespace() + mpContext->getName());
581             }
582             else
583             {
584                 switch(mpContext->getWebDAVNamespace())
585                 {
586                     default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled
587                     {
588                         break;
589                     }
590                     case WebDAVNamespace_DAV:
591                     {
592                         switch(mpContext->getWebDAVName())
593                         {
594                             default: // WebDAVName_unknown, WebDAVName_last or unhandled
595                             {
596                                 break;
597                             }
598                             case WebDAVName_href:
599                             {
600                                 // href end, save it if we have whitespace
601                                 if(whitespaceIsAvailable())
602                                 {
603                                     if(mbLockDiscoveryActive)
604                                     {
605                                         maHrefLocks = mpContext->getWhiteSpace();
606                                     }
607                                     else
608                                     {
609                                         maHref = mpContext->getWhiteSpace();
610                                     }
611                                 }
612                                 break;
613                             }
614                             case WebDAVName_status:
615                             {
616                                 // status end, save it if we have whitespace
617                                 if(whitespaceIsAvailable())
618                                 {
619                                     maStatus = mpContext->getWhiteSpace();
620                                 }
621                                 break;
622                             }
623                             case WebDAVName_getlastmodified:
624                             {
625                                 // getlastmodified end, safe if content is correct
626                                 if(propertyIsReady())
627                                 {
628                                     static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:getlastmodified"));
629                                     http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
630 
631                                     aDAVPropertyValue.Name = aStr;
632                                     aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
633                                     maPropStatProperties.push_back(aDAVPropertyValue);
634                                 }
635                                 break;
636                             }
637                             case WebDAVName_creationdate:
638                             {
639                                 // creationdate end, safe if content is correct
640                                 if(propertyIsReady())
641                                 {
642                                     static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:creationdate"));
643                                     http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
644 
645                                     aDAVPropertyValue.Name = aStr;
646                                     aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
647                                     maPropStatProperties.push_back(aDAVPropertyValue);
648                                 }
649                                 break;
650                             }
651                             case WebDAVName_collection:
652                             {
653                                 // collection end, check and set
654                                 if(hasParent(WebDAVName_resourcetype))
655                                 {
656                                     mbResourceTypeCollection = true;
657                                 }
658                                 break;
659                             }
660                             case WebDAVName_resourcetype:
661                             {
662                                 // resourcetype end, check for collection
663                                 if(hasParent(WebDAVName_prop))
664                                 {
665                                     static rtl::OUString aStrA(rtl::OUString::createFromAscii("DAV:resourcetype"));
666                                     static rtl::OUString aStrB(rtl::OUString::createFromAscii("collection"));
667                                     http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
668 
669                                     aDAVPropertyValue.Name = aStrA;
670                                     aDAVPropertyValue.Value <<= (mbResourceTypeCollection ? aStrB : rtl::OUString());
671                                     maPropStatProperties.push_back(aDAVPropertyValue);
672                                 }
673                                 break;
674                             }
675                             case WebDAVName_getcontentlength:
676                             {
677                                 // getcontentlength end, safe if content is correct
678                                 if(propertyIsReady())
679                                 {
680                                     static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:getcontentlength"));
681                                     http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
682 
683                                     aDAVPropertyValue.Name = aStr;
684                                     aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
685                                     maPropStatProperties.push_back(aDAVPropertyValue);
686                                 }
687                                 break;
688                             }
689                             case WebDAVName_getcontenttype:
690                             {
691                                 // getcontenttype end, safe if content is correct
692                                 if(propertyIsReady())
693                                 {
694                                     static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:getcontenttype"));
695                                     http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
696 
697                                     aDAVPropertyValue.Name = aStr;
698                                     aDAVPropertyValue.Value <<= mpContext->getWhiteSpace();
699                                     maPropStatProperties.push_back(aDAVPropertyValue);
700                                 }
701                                 break;
702                             }
703                             case WebDAVName_supportedlock:
704                             {
705                                 // supportedlock end
706                                 if(hasParent(WebDAVName_prop) && maLockEntries.hasElements())
707                                 {
708                                     static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:supportedlock"));
709                                     http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
710 
711                                     aDAVPropertyValue.Name = aStr;
712                                     aDAVPropertyValue.Value <<= maLockEntries;
713                                     maPropStatProperties.push_back(aDAVPropertyValue);
714                                 }
715                                 break;
716                             }
717                             case WebDAVName_lockentry:
718                             {
719                                 // lockentry end
720                                 if(hasParent(WebDAVName_supportedlock) && (mbLockScopeSet && mbLockTypeSet))
721                                 {
722                                     const sal_Int32 nLength(maLockEntries.getLength());
723                                     ucb::LockEntry aEntry;
724 
725                                     aEntry.Scope = maLockScope;
726                                     aEntry.Type = maLockType;
727                                     maLockEntries.realloc(nLength + 1);
728                                     maLockEntries[nLength] = aEntry;
729                                 }
730                                 break;
731                             }
732                             case WebDAVName_exclusive:
733                             {
734                                 // exclusive lockscope end
735                                 if(hasParent(WebDAVName_lockscope) || hasParent(WebDAVName_activelock))
736                                 {
737                                     maLockScope = ucb::LockScope_EXCLUSIVE;
738                                     mbLockScopeSet = true;
739                                 }
740                                 break;
741                             }
742                             case WebDAVName_shared:
743                             {
744                                 // shared lockscope end
745                                 if(hasParent(WebDAVName_lockscope) || hasParent(WebDAVName_activelock))
746                                 {
747                                     maLockScope = ucb::LockScope_SHARED;
748                                     mbLockScopeSet = true;
749                                 }
750                                 break;
751                             }
752                             case WebDAVName_write:
753                             {
754                                 // write locktype end
755                                 if(hasParent(WebDAVName_locktype) || hasParent(WebDAVName_activelock))
756                                 {
757                                     maLockType = ucb::LockType_WRITE;
758                                     mbLockTypeSet = true;
759                                 }
760                                 break;
761                             }
762                             case WebDAVName_lockdiscovery:
763                             {
764                                 // lockdiscovery end
765                                 if(hasParent(WebDAVName_prop))
766                                 {
767                                     static ::rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:lockdiscovery"));
768                                     if(isWaitingLockResponse())
769                                     {
770                                         maResult_Lock.Name = aStr;
771                                         maResult_Lock.Value <<= maLocks;
772                                     }
773                                     else
774                                     {
775                                         ::http_dav_ucp::DAVPropertyValue aDAVPropertyValue;
776 
777                                         aDAVPropertyValue.Name = aStr;
778                                         aDAVPropertyValue.Value <<= maLocks;
779                                         maPropStatProperties.push_back(aDAVPropertyValue);
780                                     }
781                                 }
782                                 mbLockDiscoveryActive = false;
783                                 break;
784                             }
785                             case WebDAVName_activelock:
786                             {
787                                 if(hasParent(WebDAVName_lockdiscovery) &&
788                                    mbLockScopeSet && mbLockTypeSet && mbLockTokenSet)
789                                 {
790                                     const sal_Int32 nLength(maLocks.getLength());
791                                     ucb::Lock aLock;
792 
793                                     aLock.Scope = maLockScope;
794                                     aLock.Type = maLockType;
795                                     //add tokens, depth, timeout, owner
796                                     aLock.LockTokens = maLockTokens;
797                                     aLock.Depth = maLockDepth;
798                                     aLock.Owner <<= maLockOwner;
799                                     aLock.Timeout = maLockTimeout;
800                                     maLocks.realloc(nLength + 1);
801                                     maLocks[nLength] = aLock;
802                                 }
803                                 break;
804                             }
805                             case WebDAVName_locktoken:
806                             {
807                                 if(hasParent(WebDAVName_activelock))
808                                 {
809                                     //add a token to the list of tokens
810                                     const sal_Int32 nLength(maLockTokens.getLength());
811                                     maLockTokens.realloc(nLength + 1);
812                                     maLockTokens[nLength] = maHrefLocks;
813                                     mbLockTokenSet = true;
814                                 }
815                                 break;
816                             }
817                             case WebDAVName_timeout:
818                             {
819                                 if(hasParent(WebDAVName_activelock))
820                                 {
821                                     ::rtl::OUString aStr( mpContext->getWhiteSpace().toAsciiLowerCase());
822                                     static ::rtl::OUString aInfinite( ::rtl::OUString::createFromAscii( "infinite" ) );
823                                     static ::rtl::OUString aSecond( ::rtl::OUString::createFromAscii( "second-" ) );
824                                     //look for infinity
825                                     sal_Int32 secondIndex;
826                                     if(aStr.indexOf(aInfinite) != -1)
827                                     {
828                                         maLockTimeout = -1;
829                                     }
830                                     else if((secondIndex = aStr.indexOf(aSecond)) != -1)
831                                     {
832                                         secondIndex += aSecond.getLength();
833                                         maLockTimeout = aStr.copy(secondIndex).toInt64();
834                                     }
835                                 }
836                                 break;
837                             }
838                             case WebDAVName_owner:
839                             {
840                                 if(whitespaceIsAvailable())
841                                 {
842                                     if(hasParent(WebDAVName_activelock))
843                                     {
844                                         maLockOwner = mpContext->getWhiteSpace();
845                                     }
846                                 }
847                                 break;
848                             }
849                             case WebDAVName_depth:
850                             {
851                                 if(hasParent(WebDAVName_activelock))
852                                 {
853                                     //set depth, one of three values
854                                     ::rtl::OUString aStr( mpContext->getWhiteSpace() );
855                                     //default to zero, if not found
856                                     maLockDepth = ucb::LockDepth_ZERO;
857                                     if(aStr.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("0")))
858                                        maLockDepth = ucb::LockDepth_ZERO;
859                                     else if(aStr.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("1")))
860                                        maLockDepth = ucb::LockDepth_ONE;
861                                     else if(aStr.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("infinity")))
862                                        maLockDepth = ucb::LockDepth_INFINITY;
863                                 }
864                                 break;
865                             }
866                             case WebDAVName_propstat:
867                             {
868                                 // propstat end, check status
869                                 if(maStatus.getLength())
870                                 {
871                                     static ::rtl::OUString aStrStatusOkay(::rtl::OUString::createFromAscii("HTTP/1.1 200 OK"));
872 
873                                     if(maStatus.equals(aStrStatusOkay))
874                                     {
875                                         if(isCollectingProperties())
876                                         {
877                                             if(maPropStatProperties.size())
878                                             {
879                                                 // append to maResponseProperties if okay
880                                                 maResponseProperties.insert(maResponseProperties.end(), maPropStatProperties.begin(), maPropStatProperties.end());
881                                             }
882                                         }
883                                         else
884                                         {
885                                             if(maPropStatNames.size())
886                                             {
887                                                 // when collecting properties append to
888                                                 maResponseNames.insert(maResponseNames.end(), maPropStatNames.begin(), maPropStatNames.end());
889                                             }
890                                         }
891                                     }
892                                 }
893                                 break;
894                             }
895                             case WebDAVName_response:
896                             {
897                                 // response end
898                                 if(maHref.getLength())
899                                 {
900                                     if(isCollectingProperties())
901                                     {
902                                         // create DAVResource when we have content
903                                         if(maResponseProperties.size())
904                                         {
905                                             ::http_dav_ucp::DAVResource aDAVResource;
906 
907                                             aDAVResource.uri = maHref;
908                                             aDAVResource.properties = maResponseProperties;
909                                             maResult_PropFind.push_back(aDAVResource);
910                                         }
911                                     }
912                                     else
913                                     {
914                                         // when collecting properties add them to result when there are some
915                                         if(maResponseNames.size())
916                                         {
917                                             http_dav_ucp::DAVResourceInfo aDAVResourceInfo(maHref);
918 
919                                             aDAVResourceInfo.properties = maResponseNames;
920                                             maResult_PropName.push_back(aDAVResourceInfo);
921                                         }
922                                     }
923                                 }
924                                 break;
925                             }
926                         }
927                         break;
928                     }
929                     case WebDAVNamespace_ucb_openoffice_org_dav_props:
930                     {
931                         break;
932                     }
933                 }
934             }
935 
936             // destroy last context (pop)
937             pop_context();
938         }
939     }
940 
characters(const::rtl::OUString & aChars)941     void SAL_CALL WebDAVResponseParser::characters( const ::rtl::OUString& aChars )
942     {
943         // collect whitespace over evtl. several calls in mpContext
944         OSL_ENSURE(mpContext, "Parser characters without content (!)");
945         const sal_Int32 nLen(aChars.getLength());
946 
947         if(mpContext && nLen)
948         {
949             // remove leading/trailing blanks and CRLF
950             const ::rtl::OUString aTrimmedChars(aChars.trim());
951 
952             if(aTrimmedChars.getLength())
953             {
954                 ::rtl::OUString aNew(mpContext->getWhiteSpace());
955 
956                 if(aNew.getLength())
957                 {
958                     // add one char when appending (see html1.1 spec)
959                     aNew += ::rtl::OUString(sal_Unicode(' '));
960                 }
961 
962                 aNew += aTrimmedChars;
963                 mpContext->setWhiteSpace(aNew);
964             }
965         }
966     }
967 
ignorableWhitespace(const::rtl::OUString &)968     void SAL_CALL WebDAVResponseParser::ignorableWhitespace( const ::rtl::OUString& /*aWhitespaces*/ )
969     {
970     }
971 
processingInstruction(const::rtl::OUString &,const::rtl::OUString &)972     void SAL_CALL WebDAVResponseParser::processingInstruction( const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ )
973     {
974     }
975 
setDocumentLocator(const uno::Reference<xml::sax::XLocator> &)976     void SAL_CALL WebDAVResponseParser::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ )
977     {
978     }
979 } // end of anonymous namespace
980 
981 //////////////////////////////////////////////////////////////////////////////
982 // wrapper for various calls to the parser
983 
984 namespace
985 {
parseWebDAVPropNameResponse(const uno::Reference<io::XInputStream> & xInputStream,std::vector<http_dav_ucp::DAVResource> & rPropFind,std::vector<http_dav_ucp::DAVResourceInfo> & rPropName,http_dav_ucp::DAVPropertyValue & rPropValue,WebDAVResponseParserMode eWebDAVResponseParserMode)986     void parseWebDAVPropNameResponse(
987         const uno::Reference< io::XInputStream >& xInputStream,
988         std::vector< http_dav_ucp::DAVResource >& rPropFind,
989         std::vector< http_dav_ucp::DAVResourceInfo >& rPropName,
990         http_dav_ucp::DAVPropertyValue&           rPropValue,
991         WebDAVResponseParserMode eWebDAVResponseParserMode)
992     {
993         if(xInputStream.is())
994         {
995             try
996             {
997                 // prepare ParserInputSrouce
998                 xml::sax::InputSource myInputSource;
999                 myInputSource.aInputStream = xInputStream;
1000 
1001                 // get parser
1002                 uno::Reference< xml::sax::XParser > xParser(
1003                     comphelper::getProcessServiceFactory()->createInstance(
1004                         rtl::OUString::createFromAscii("com.sun.star.xml.sax.Parser") ),
1005                     uno::UNO_QUERY_THROW );
1006 
1007                 // create parser; connect parser and filter
1008                 WebDAVResponseParser* pWebDAVResponseParser = new WebDAVResponseParser(eWebDAVResponseParserMode);
1009                 uno::Reference< xml::sax::XDocumentHandler > xWebDAVHdl(pWebDAVResponseParser);
1010                 xParser->setDocumentHandler(xWebDAVHdl);
1011 
1012                 // finally, parse the stream
1013                 xParser->parseStream(myInputSource);
1014 
1015                 // get result
1016                 switch(eWebDAVResponseParserMode)
1017                 {
1018                     case WebDAVResponseParserMode_PropFind:
1019                     {
1020                         rPropFind = pWebDAVResponseParser->getResult_PropFind();
1021                         break;
1022                     }
1023                     case WebDAVResponseParserMode_PropName:
1024                     {
1025                         rPropName = pWebDAVResponseParser->getResult_PropName();
1026                         break;
1027                     }
1028                     case WebDAVResponseParserMode_LockResponse:
1029                     {
1030                         rPropValue = pWebDAVResponseParser->getResult_Lock();
1031                         break;
1032                     }
1033                 }
1034             }
1035             catch(uno::Exception&)
1036             {
1037                 OSL_ENSURE(false, "WebDAV Parse error (!)");
1038             }
1039         }
1040     }
1041 } // end of anonymous namespace
1042 
1043 //////////////////////////////////////////////////////////////////////////////
1044 // helper to parse a XML WebDAV response
1045 
1046 namespace http_dav_ucp
1047 {
parseWebDAVPropFindResponse(const uno::Reference<io::XInputStream> & xInputStream)1048     std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream >& xInputStream)
1049     {
1050         std::vector< DAVResource > aRetval;
1051         std::vector< DAVResourceInfo > aFoo;
1052         DAVPropertyValue               aFoo2;
1053 
1054         parseWebDAVPropNameResponse(xInputStream, aRetval, aFoo, aFoo2, WebDAVResponseParserMode_PropFind);
1055         return aRetval;
1056     }
1057 
parseWebDAVPropNameResponse(const uno::Reference<io::XInputStream> & xInputStream)1058     std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream >& xInputStream)
1059     {
1060         std::vector< DAVResource > aFoo;
1061         std::vector< DAVResourceInfo > aRetval;
1062         DAVPropertyValue               aFoo2;
1063 
1064         parseWebDAVPropNameResponse(xInputStream, aFoo, aRetval, aFoo2, WebDAVResponseParserMode_PropName);
1065         return aRetval;
1066     }
1067 
parseWebDAVLockResponse(const uno::Reference<io::XInputStream> & xInputStream)1068     http_dav_ucp::DAVPropertyValue parseWebDAVLockResponse(const uno::Reference< io::XInputStream >& xInputStream)
1069     {
1070         std::vector< DAVResource > aFoo2;
1071         std::vector< DAVResourceInfo > aFoo;
1072         http_dav_ucp::DAVPropertyValue               aRetval;
1073 
1074 
1075         parseWebDAVPropNameResponse(xInputStream, aFoo2, aFoo, aRetval, WebDAVResponseParserMode_LockResponse);
1076         return aRetval;
1077     }
1078 
1079 } // namespace http_dav_ucp
1080 
1081 //////////////////////////////////////////////////////////////////////////////
1082 // eof
1083