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