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( ) throw (xml::sax::SAXException, uno::RuntimeException); 394 virtual void SAL_CALL endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException); 395 virtual void SAL_CALL startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) 396 throw (xml::sax::SAXException, uno::RuntimeException); 397 virtual void SAL_CALL endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException); 398 virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException); 399 virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (xml::sax::SAXException, uno::RuntimeException); 400 virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (xml::sax::SAXException, uno::RuntimeException); 401 virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) throw (xml::sax::SAXException, uno::RuntimeException); 402 getResult_PropFind() const403 const std::vector< http_dav_ucp::DAVResource >& getResult_PropFind() const { return maResult_PropFind; } getResult_PropName() const404 const std::vector< http_dav_ucp::DAVResourceInfo >& getResult_PropName() const { return maResult_PropName; } getResult_Lock() const405 const http_dav_ucp::DAVPropertyValue& getResult_Lock() const { return maResult_Lock; } 406 }; 407 WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode)408 WebDAVResponseParser::WebDAVResponseParser(WebDAVResponseParserMode eWebDAVResponseParserMode) 409 : maResult_PropFind(), 410 maResult_PropName(), 411 maResult_Lock(), 412 mpContext(0), 413 maHref(), 414 maHrefLocks(), 415 maStatus(), 416 maResponseProperties(), 417 maPropStatProperties(), 418 maResponseNames(), 419 maPropStatNames(), 420 maLockTokens(), 421 maLockEntries(), 422 maLocks(), 423 maLockScope(ucb::LockScope_EXCLUSIVE), 424 maLockType(ucb::LockType_WRITE), 425 maLockDepth(ucb::LockDepth_ZERO), 426 maLockOwner(), 427 maLockTimeout(0), 428 meWebDAVResponseParserMode(eWebDAVResponseParserMode), 429 mbResourceTypeCollection(false), 430 mbLockScopeSet(false), 431 mbLockTypeSet(false), 432 mbLockDiscoveryActive(false) 433 { 434 } 435 ~WebDAVResponseParser()436 WebDAVResponseParser::~WebDAVResponseParser() 437 { 438 OSL_ENSURE(!mpContext, "Parser destructed with existing content (!)"); 439 while(mpContext) 440 { 441 pop_context(); 442 } 443 } 444 startDocument()445 void SAL_CALL WebDAVResponseParser::startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) 446 { 447 OSL_ENSURE(!mpContext, "Parser start with existing content (!)"); 448 } 449 endDocument()450 void SAL_CALL WebDAVResponseParser::endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException) 451 { 452 OSL_ENSURE(!mpContext, "Parser end with existing content (!)"); 453 } 454 startElement(const::rtl::OUString & aName,const uno::Reference<xml::sax::XAttributeList> & xAttribs)455 void SAL_CALL WebDAVResponseParser::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) 456 throw (xml::sax::SAXException, uno::RuntimeException) 457 { 458 const sal_Int32 nLen(aName.getLength()); 459 460 if(nLen) 461 { 462 // create new context (push) 463 mpContext = new WebDAVContext(mpContext, aName, xAttribs); 464 465 if(collectThisPropertyAsName()) 466 { 467 // When collecting property names and parent is prop there is no need 468 // to handle the content of this property deeper (evtl. preparations) 469 } 470 else 471 { 472 switch(mpContext->getWebDAVNamespace()) 473 { 474 default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled 475 { 476 break; 477 } 478 case WebDAVNamespace_DAV: 479 { 480 switch(mpContext->getWebDAVName()) 481 { 482 default: // WebDAVName_unknown, WebDAVName_last or unhandled 483 { 484 break; 485 } 486 case WebDAVName_propstat: 487 { 488 // propstat start 489 if(isCollectingProperties()) 490 { 491 // reset maPropStatProperties 492 maPropStatProperties.clear(); 493 } 494 else 495 { 496 // when collecting properties reset maPropStatNames 497 maPropStatNames.clear(); 498 } 499 break; 500 } 501 case WebDAVName_response: 502 { 503 // response start, reset Href and status and maResponseProperties 504 maHref = maStatus = ::rtl::OUString(); 505 506 if(isCollectingProperties()) 507 { 508 // reset maResponseProperties 509 maResponseProperties.clear(); 510 } 511 else 512 { 513 // reset maResponseNames when collecting properties 514 maResponseNames.clear(); 515 } 516 break; 517 } 518 case WebDAVName_resourcetype: 519 { 520 // resourcetype start, reset collection 521 mbResourceTypeCollection = false; 522 break; 523 } 524 case WebDAVName_supportedlock: 525 { 526 // supportedlock start, reset maLockEntries 527 maLockEntries.realloc(0); 528 break; 529 } 530 case WebDAVName_lockentry: 531 { 532 // lockentry start, reset maLockEntries 533 mbLockScopeSet = false; 534 mbLockTypeSet = false; 535 break; 536 } 537 case WebDAVName_lockdiscovery: 538 { 539 // lockentry start, reset maLocks 540 maLocks.realloc(0); 541 mbLockDiscoveryActive = true; 542 break; 543 } 544 case WebDAVName_activelock: 545 { 546 // activelockstart, reset vars 547 mbLockScopeSet = false; 548 mbLockTypeSet = false; 549 mbLockTokenSet = false; 550 maLockTokens.realloc(0); 551 maHrefLocks = ::rtl::OUString(); 552 break; 553 } 554 case WebDAVName_locktoken: 555 { 556 mbLockTokenSet = true; 557 break; 558 } 559 } 560 break; 561 } 562 case WebDAVNamespace_ucb_openoffice_org_dav_props: 563 { 564 break; 565 } 566 } 567 } 568 } 569 } 570 endElement(const::rtl::OUString & aName)571 void SAL_CALL WebDAVResponseParser::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException) 572 { 573 const sal_Int32 nLen(aName.getLength()); 574 OSL_ENSURE(mpContext, "Parser EndElement without content (!)"); 575 576 if(mpContext && nLen) 577 { 578 if(collectThisPropertyAsName()) 579 { 580 // When collecting property names and parent is prop, just append the prop name 581 // to the collection, no need to parse deeper 582 maPropStatNames.push_back(mpContext->getNamespace() + mpContext->getName()); 583 } 584 else 585 { 586 switch(mpContext->getWebDAVNamespace()) 587 { 588 default: // WebDAVNamespace_unknown, WebDAVNamespace_last or unhandled 589 { 590 break; 591 } 592 case WebDAVNamespace_DAV: 593 { 594 switch(mpContext->getWebDAVName()) 595 { 596 default: // WebDAVName_unknown, WebDAVName_last or unhandled 597 { 598 break; 599 } 600 case WebDAVName_href: 601 { 602 // href end, save it if we have whitespace 603 if(whitespaceIsAvailable()) 604 { 605 if(mbLockDiscoveryActive) 606 { 607 maHrefLocks = mpContext->getWhiteSpace(); 608 } 609 else 610 { 611 maHref = mpContext->getWhiteSpace(); 612 } 613 } 614 break; 615 } 616 case WebDAVName_status: 617 { 618 // status end, save it if we have whitespace 619 if(whitespaceIsAvailable()) 620 { 621 maStatus = mpContext->getWhiteSpace(); 622 } 623 break; 624 } 625 case WebDAVName_getlastmodified: 626 { 627 // getlastmodified end, safe if content is correct 628 if(propertyIsReady()) 629 { 630 static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:getlastmodified")); 631 http_dav_ucp::DAVPropertyValue aDAVPropertyValue; 632 633 aDAVPropertyValue.Name = aStr; 634 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace(); 635 maPropStatProperties.push_back(aDAVPropertyValue); 636 } 637 break; 638 } 639 case WebDAVName_creationdate: 640 { 641 // creationdate end, safe if content is correct 642 if(propertyIsReady()) 643 { 644 static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:creationdate")); 645 http_dav_ucp::DAVPropertyValue aDAVPropertyValue; 646 647 aDAVPropertyValue.Name = aStr; 648 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace(); 649 maPropStatProperties.push_back(aDAVPropertyValue); 650 } 651 break; 652 } 653 case WebDAVName_collection: 654 { 655 // collection end, check and set 656 if(hasParent(WebDAVName_resourcetype)) 657 { 658 mbResourceTypeCollection = true; 659 } 660 break; 661 } 662 case WebDAVName_resourcetype: 663 { 664 // resourcetype end, check for collection 665 if(hasParent(WebDAVName_prop)) 666 { 667 static rtl::OUString aStrA(rtl::OUString::createFromAscii("DAV:resourcetype")); 668 static rtl::OUString aStrB(rtl::OUString::createFromAscii("collection")); 669 http_dav_ucp::DAVPropertyValue aDAVPropertyValue; 670 671 aDAVPropertyValue.Name = aStrA; 672 aDAVPropertyValue.Value <<= (mbResourceTypeCollection ? aStrB : rtl::OUString()); 673 maPropStatProperties.push_back(aDAVPropertyValue); 674 } 675 break; 676 } 677 case WebDAVName_getcontentlength: 678 { 679 // getcontentlength end, safe if content is correct 680 if(propertyIsReady()) 681 { 682 static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:getcontentlength")); 683 http_dav_ucp::DAVPropertyValue aDAVPropertyValue; 684 685 aDAVPropertyValue.Name = aStr; 686 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace(); 687 maPropStatProperties.push_back(aDAVPropertyValue); 688 } 689 break; 690 } 691 case WebDAVName_getcontenttype: 692 { 693 // getcontenttype end, safe if content is correct 694 if(propertyIsReady()) 695 { 696 static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:getcontenttype")); 697 http_dav_ucp::DAVPropertyValue aDAVPropertyValue; 698 699 aDAVPropertyValue.Name = aStr; 700 aDAVPropertyValue.Value <<= mpContext->getWhiteSpace(); 701 maPropStatProperties.push_back(aDAVPropertyValue); 702 } 703 break; 704 } 705 case WebDAVName_supportedlock: 706 { 707 // supportedlock end 708 if(hasParent(WebDAVName_prop) && maLockEntries.hasElements()) 709 { 710 static rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:supportedlock")); 711 http_dav_ucp::DAVPropertyValue aDAVPropertyValue; 712 713 aDAVPropertyValue.Name = aStr; 714 aDAVPropertyValue.Value <<= maLockEntries; 715 maPropStatProperties.push_back(aDAVPropertyValue); 716 } 717 break; 718 } 719 case WebDAVName_lockentry: 720 { 721 // lockentry end 722 if(hasParent(WebDAVName_supportedlock) && (mbLockScopeSet && mbLockTypeSet)) 723 { 724 const sal_Int32 nLength(maLockEntries.getLength()); 725 ucb::LockEntry aEntry; 726 727 aEntry.Scope = maLockScope; 728 aEntry.Type = maLockType; 729 maLockEntries.realloc(nLength + 1); 730 maLockEntries[nLength] = aEntry; 731 } 732 break; 733 } 734 case WebDAVName_exclusive: 735 { 736 // exclusive lockscope end 737 if(hasParent(WebDAVName_lockscope) || hasParent(WebDAVName_activelock)) 738 { 739 maLockScope = ucb::LockScope_EXCLUSIVE; 740 mbLockScopeSet = true; 741 } 742 break; 743 } 744 case WebDAVName_shared: 745 { 746 // shared lockscope end 747 if(hasParent(WebDAVName_lockscope) || hasParent(WebDAVName_activelock)) 748 { 749 maLockScope = ucb::LockScope_SHARED; 750 mbLockScopeSet = true; 751 } 752 break; 753 } 754 case WebDAVName_write: 755 { 756 // write locktype end 757 if(hasParent(WebDAVName_locktype) || hasParent(WebDAVName_activelock)) 758 { 759 maLockType = ucb::LockType_WRITE; 760 mbLockTypeSet = true; 761 } 762 break; 763 } 764 case WebDAVName_lockdiscovery: 765 { 766 // lockdiscovery end 767 if(hasParent(WebDAVName_prop)) 768 { 769 static ::rtl::OUString aStr(rtl::OUString::createFromAscii("DAV:lockdiscovery")); 770 if(isWaitingLockResponse()) 771 { 772 maResult_Lock.Name = aStr; 773 maResult_Lock.Value <<= maLocks; 774 } 775 else 776 { 777 ::http_dav_ucp::DAVPropertyValue aDAVPropertyValue; 778 779 aDAVPropertyValue.Name = aStr; 780 aDAVPropertyValue.Value <<= maLocks; 781 maPropStatProperties.push_back(aDAVPropertyValue); 782 } 783 } 784 mbLockDiscoveryActive = false; 785 break; 786 } 787 case WebDAVName_activelock: 788 { 789 if(hasParent(WebDAVName_lockdiscovery) && 790 mbLockScopeSet && mbLockTypeSet && mbLockTokenSet) 791 { 792 const sal_Int32 nLength(maLocks.getLength()); 793 ucb::Lock aLock; 794 795 aLock.Scope = maLockScope; 796 aLock.Type = maLockType; 797 //add tokens, depth, timeout, owner 798 aLock.LockTokens = maLockTokens; 799 aLock.Depth = maLockDepth; 800 aLock.Owner <<= maLockOwner; 801 aLock.Timeout = maLockTimeout; 802 maLocks.realloc(nLength + 1); 803 maLocks[nLength] = aLock; 804 } 805 break; 806 } 807 case WebDAVName_locktoken: 808 { 809 if(hasParent(WebDAVName_activelock)) 810 { 811 //add a token to the list of tokens 812 const sal_Int32 nLength(maLockTokens.getLength()); 813 maLockTokens.realloc(nLength + 1); 814 maLockTokens[nLength] = maHrefLocks; 815 mbLockTokenSet = true; 816 } 817 break; 818 } 819 case WebDAVName_timeout: 820 { 821 if(hasParent(WebDAVName_activelock)) 822 { 823 ::rtl::OUString aStr( mpContext->getWhiteSpace().toAsciiLowerCase()); 824 static ::rtl::OUString aInfinite( ::rtl::OUString::createFromAscii( "infinite" ) ); 825 static ::rtl::OUString aSecond( ::rtl::OUString::createFromAscii( "second-" ) ); 826 //look for infinity 827 sal_Int32 secondIndex; 828 if(aStr.indexOf(aInfinite) != -1) 829 { 830 maLockTimeout = -1; 831 } 832 else if((secondIndex = aStr.indexOf(aSecond)) != -1) 833 { 834 secondIndex += aSecond.getLength(); 835 maLockTimeout = aStr.copy(secondIndex).toInt64(); 836 } 837 } 838 break; 839 } 840 case WebDAVName_owner: 841 { 842 if(whitespaceIsAvailable()) 843 { 844 if(hasParent(WebDAVName_activelock)) 845 { 846 maLockOwner = mpContext->getWhiteSpace(); 847 } 848 } 849 break; 850 } 851 case WebDAVName_depth: 852 { 853 if(hasParent(WebDAVName_activelock)) 854 { 855 //set depth, one of three values 856 ::rtl::OUString aStr( mpContext->getWhiteSpace() ); 857 //default to zero, if not found 858 maLockDepth = ucb::LockDepth_ZERO; 859 if(aStr.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("0"))) 860 maLockDepth = ucb::LockDepth_ZERO; 861 else if(aStr.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("1"))) 862 maLockDepth = ucb::LockDepth_ONE; 863 else if(aStr.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("infinity"))) 864 maLockDepth = ucb::LockDepth_INFINITY; 865 } 866 break; 867 } 868 case WebDAVName_propstat: 869 { 870 // propstat end, check status 871 if(maStatus.getLength()) 872 { 873 static ::rtl::OUString aStrStatusOkay(::rtl::OUString::createFromAscii("HTTP/1.1 200 OK")); 874 875 if(maStatus.equals(aStrStatusOkay)) 876 { 877 if(isCollectingProperties()) 878 { 879 if(maPropStatProperties.size()) 880 { 881 // append to maResponseProperties if okay 882 maResponseProperties.insert(maResponseProperties.end(), maPropStatProperties.begin(), maPropStatProperties.end()); 883 } 884 } 885 else 886 { 887 if(maPropStatNames.size()) 888 { 889 // when collecting properties append to 890 maResponseNames.insert(maResponseNames.end(), maPropStatNames.begin(), maPropStatNames.end()); 891 } 892 } 893 } 894 } 895 break; 896 } 897 case WebDAVName_response: 898 { 899 // response end 900 if(maHref.getLength()) 901 { 902 if(isCollectingProperties()) 903 { 904 // create DAVResource when we have content 905 if(maResponseProperties.size()) 906 { 907 ::http_dav_ucp::DAVResource aDAVResource; 908 909 aDAVResource.uri = maHref; 910 aDAVResource.properties = maResponseProperties; 911 maResult_PropFind.push_back(aDAVResource); 912 } 913 } 914 else 915 { 916 // when collecting properties add them to result when there are some 917 if(maResponseNames.size()) 918 { 919 http_dav_ucp::DAVResourceInfo aDAVResourceInfo(maHref); 920 921 aDAVResourceInfo.properties = maResponseNames; 922 maResult_PropName.push_back(aDAVResourceInfo); 923 } 924 } 925 } 926 break; 927 } 928 } 929 break; 930 } 931 case WebDAVNamespace_ucb_openoffice_org_dav_props: 932 { 933 break; 934 } 935 } 936 } 937 938 // destroy last context (pop) 939 pop_context(); 940 } 941 } 942 characters(const::rtl::OUString & aChars)943 void SAL_CALL WebDAVResponseParser::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException) 944 { 945 // collect whitespace over evtl. several calls in mpContext 946 OSL_ENSURE(mpContext, "Parser characters without content (!)"); 947 const sal_Int32 nLen(aChars.getLength()); 948 949 if(mpContext && nLen) 950 { 951 // remove leading/trailing blanks and CRLF 952 const ::rtl::OUString aTrimmedChars(aChars.trim()); 953 954 if(aTrimmedChars.getLength()) 955 { 956 ::rtl::OUString aNew(mpContext->getWhiteSpace()); 957 958 if(aNew.getLength()) 959 { 960 // add one char when appending (see html1.1 spec) 961 aNew += ::rtl::OUString(sal_Unicode(' ')); 962 } 963 964 aNew += aTrimmedChars; 965 mpContext->setWhiteSpace(aNew); 966 } 967 } 968 } 969 ignorableWhitespace(const::rtl::OUString &)970 void SAL_CALL WebDAVResponseParser::ignorableWhitespace( const ::rtl::OUString& /*aWhitespaces*/ ) throw (xml::sax::SAXException, uno::RuntimeException) 971 { 972 } 973 processingInstruction(const::rtl::OUString &,const::rtl::OUString &)974 void SAL_CALL WebDAVResponseParser::processingInstruction( const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) 975 throw (xml::sax::SAXException, uno::RuntimeException) 976 { 977 } 978 setDocumentLocator(const uno::Reference<xml::sax::XLocator> &)979 void SAL_CALL WebDAVResponseParser::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ ) throw (xml::sax::SAXException, uno::RuntimeException) 980 { 981 } 982 } // end of anonymous namespace 983 984 ////////////////////////////////////////////////////////////////////////////// 985 // wrapper for various calls to the parser 986 987 namespace 988 { 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)989 void parseWebDAVPropNameResponse( 990 const uno::Reference< io::XInputStream >& xInputStream, 991 std::vector< http_dav_ucp::DAVResource >& rPropFind, 992 std::vector< http_dav_ucp::DAVResourceInfo >& rPropName, 993 http_dav_ucp::DAVPropertyValue& rPropValue, 994 WebDAVResponseParserMode eWebDAVResponseParserMode) 995 { 996 if(xInputStream.is()) 997 { 998 try 999 { 1000 // prepare ParserInputSrouce 1001 xml::sax::InputSource myInputSource; 1002 myInputSource.aInputStream = xInputStream; 1003 1004 // get parser 1005 uno::Reference< xml::sax::XParser > xParser( 1006 comphelper::getProcessServiceFactory()->createInstance( 1007 rtl::OUString::createFromAscii("com.sun.star.xml.sax.Parser") ), 1008 uno::UNO_QUERY_THROW ); 1009 1010 // create parser; connect parser and filter 1011 WebDAVResponseParser* pWebDAVResponseParser = new WebDAVResponseParser(eWebDAVResponseParserMode); 1012 uno::Reference< xml::sax::XDocumentHandler > xWebDAVHdl(pWebDAVResponseParser); 1013 xParser->setDocumentHandler(xWebDAVHdl); 1014 1015 // finally, parse the stream 1016 xParser->parseStream(myInputSource); 1017 1018 // get result 1019 switch(eWebDAVResponseParserMode) 1020 { 1021 case WebDAVResponseParserMode_PropFind: 1022 { 1023 rPropFind = pWebDAVResponseParser->getResult_PropFind(); 1024 break; 1025 } 1026 case WebDAVResponseParserMode_PropName: 1027 { 1028 rPropName = pWebDAVResponseParser->getResult_PropName(); 1029 break; 1030 } 1031 case WebDAVResponseParserMode_LockResponse: 1032 { 1033 rPropValue = pWebDAVResponseParser->getResult_Lock(); 1034 break; 1035 } 1036 } 1037 } 1038 catch(uno::Exception&) 1039 { 1040 OSL_ENSURE(false, "WebDAV Parse error (!)"); 1041 } 1042 } 1043 } 1044 } // end of anonymous namespace 1045 1046 ////////////////////////////////////////////////////////////////////////////// 1047 // helper to parse a XML WebDAV response 1048 1049 namespace http_dav_ucp 1050 { parseWebDAVPropFindResponse(const uno::Reference<io::XInputStream> & xInputStream)1051 std::vector< DAVResource > parseWebDAVPropFindResponse(const uno::Reference< io::XInputStream >& xInputStream) 1052 { 1053 std::vector< DAVResource > aRetval; 1054 std::vector< DAVResourceInfo > aFoo; 1055 DAVPropertyValue aFoo2; 1056 1057 parseWebDAVPropNameResponse(xInputStream, aRetval, aFoo, aFoo2, WebDAVResponseParserMode_PropFind); 1058 return aRetval; 1059 } 1060 parseWebDAVPropNameResponse(const uno::Reference<io::XInputStream> & xInputStream)1061 std::vector< DAVResourceInfo > parseWebDAVPropNameResponse(const uno::Reference< io::XInputStream >& xInputStream) 1062 { 1063 std::vector< DAVResource > aFoo; 1064 std::vector< DAVResourceInfo > aRetval; 1065 DAVPropertyValue aFoo2; 1066 1067 parseWebDAVPropNameResponse(xInputStream, aFoo, aRetval, aFoo2, WebDAVResponseParserMode_PropName); 1068 return aRetval; 1069 } 1070 parseWebDAVLockResponse(const uno::Reference<io::XInputStream> & xInputStream)1071 http_dav_ucp::DAVPropertyValue parseWebDAVLockResponse(const uno::Reference< io::XInputStream >& xInputStream) 1072 { 1073 std::vector< DAVResource > aFoo2; 1074 std::vector< DAVResourceInfo > aFoo; 1075 http_dav_ucp::DAVPropertyValue aRetval; 1076 1077 1078 parseWebDAVPropNameResponse(xInputStream, aFoo2, aFoo, aRetval, WebDAVResponseParserMode_LockResponse); 1079 return aRetval; 1080 } 1081 1082 } // namespace http_dav_ucp 1083 1084 ////////////////////////////////////////////////////////////////////////////// 1085 // eof 1086