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 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_ucb.hxx" 26 27 /************************************************************************** 28 TODO 29 ************************************************************************** 30 31 *************************************************************************/ 32 33 #include <osl/diagnose.h> 34 #include <osl/doublecheckedlocking.h> 35 #include <rtl/uri.hxx> 36 #include <rtl/ustrbuf.hxx> 37 #include <ucbhelper/contentidentifier.hxx> 38 #include <ucbhelper/propertyvalueset.hxx> 39 #include <ucbhelper/simpleinteractionrequest.hxx> 40 #include <ucbhelper/cancelcommandexecution.hxx> 41 42 #include <com/sun/star/beans/PropertyAttribute.hpp> 43 #include <com/sun/star/beans/PropertySetInfoChange.hpp> 44 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp> 45 #include <com/sun/star/beans/PropertyValue.hpp> 46 #include <com/sun/star/io/XActiveDataSink.hpp> 47 #include <com/sun/star/io/XOutputStream.hpp> 48 #include <com/sun/star/lang/IllegalAccessException.hpp> 49 #include <com/sun/star/task/PasswordContainerInteractionHandler.hpp> 50 #include <com/sun/star/ucb/CommandEnvironment.hpp> 51 #include <com/sun/star/ucb/CommandFailedException.hpp> 52 #include <com/sun/star/ucb/ContentInfoAttribute.hpp> 53 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 54 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> 55 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 56 #include <com/sun/star/ucb/InteractiveLockingLockedException.hpp> 57 #include <com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp> 58 #include <com/sun/star/ucb/InteractiveLockingNotLockedException.hpp> 59 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> 60 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp> 61 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp> 62 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> 63 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> 64 #include <com/sun/star/ucb/MissingInputStreamException.hpp> 65 #include <com/sun/star/ucb/MissingPropertiesException.hpp> 66 #include <com/sun/star/ucb/NameClash.hpp> 67 #include <com/sun/star/ucb/NameClashException.hpp> 68 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 69 #include <com/sun/star/ucb/OpenMode.hpp> 70 #include <com/sun/star/ucb/PostCommandArgument2.hpp> 71 #include <com/sun/star/ucb/PropertyCommandArgument.hpp> 72 #include <com/sun/star/ucb/TransferInfo.hpp> 73 #include <com/sun/star/ucb/UnsupportedCommandException.hpp> 74 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> 75 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp> 76 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> 77 #include <com/sun/star/ucb/XCommandInfo.hpp> 78 #include <com/sun/star/ucb/XPersistentPropertySet.hpp> 79 #include <com/sun/star/uno/XComponentContext.hpp> 80 81 #include "webdavcontent.hxx" 82 #include "webdavprovider.hxx" 83 #include "webdavresultset.hxx" 84 #include "ContentProperties.hxx" 85 #include "SerfUri.hxx" 86 #include "UCBDeadPropertyValue.hxx" 87 88 using namespace com::sun::star; 89 using namespace http_dav_ucp; 90 91 namespace 92 { 93 static void lcl_sendPartialGETRequest( bool &bError, 94 DAVException &aLastException, 95 const std::vector< rtl::OUString > aProps, 96 std::vector< rtl::OUString > &aHeaderNames, 97 const std::auto_ptr< DAVResourceAccess > &xResAccess, 98 std::auto_ptr< ContentProperties > &xProps, 99 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 100 { 101 bool bIsRequestSize = false; 102 DAVResource aResource; 103 DAVRequestHeaders aPartialGet; 104 aPartialGet.push_back( 105 DAVRequestHeader( 106 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Range" ) ), 107 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "bytes=0-0" )))); 108 109 for ( std::vector< rtl::OUString >::const_iterator it = aHeaderNames.begin(); 110 it != aHeaderNames.end(); it++ ) 111 { 112 if ( it->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) ) 113 { 114 bIsRequestSize = true; 115 break; 116 } 117 } 118 119 if ( bIsRequestSize ) 120 { 121 // we need to know if the server accepts range requests for a resource 122 // and the range unit it uses 123 aHeaderNames.push_back( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Accept-Ranges" ) ) ); 124 aHeaderNames.push_back( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Content-Range" ) ) ); 125 } 126 try 127 { 128 uno::Reference< io::XInputStream > xIn = xResAccess->GET( aPartialGet, 129 aHeaderNames, 130 aResource, 131 xEnv ); 132 bError = false; 133 134 if ( bIsRequestSize ) 135 { 136 // the ContentProperties maps "Content-Length" to the UCB "Size" property 137 // This would have an unrealistic value of 1 byte because we did only a partial GET 138 // Solution: if "Content-Range" is present, map it with UCB "Size" property 139 rtl::OUString aAcceptRanges, aContentRange, aContentLength; 140 std::vector< DAVPropertyValue > &aResponseProps = aResource.properties; 141 for ( std::vector< DAVPropertyValue >::const_iterator it = aResponseProps.begin(); 142 it != aResponseProps.end(); it++ ) 143 { 144 if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Accept-Ranges" ) ) ) 145 it->Value >>= aAcceptRanges; 146 else if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Range" ) ) ) 147 it->Value >>= aContentRange; 148 else if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) ) 149 it->Value >>= aContentLength; 150 } 151 152 sal_Int64 nSize = 1; 153 if ( aContentLength.getLength() ) 154 { 155 nSize = aContentLength.toInt64(); 156 } 157 158 // according to http://tools.ietf.org/html/rfc2616#section-3.12 159 // the only range unit defined is "bytes" and implementations 160 // MAY ignore ranges specified using other units. 161 if ( nSize == 1 && 162 aContentRange.getLength() && 163 aAcceptRanges.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "bytes" ) ) ) 164 { 165 // Parse the Content-Range to get the size 166 // vid. http://tools.ietf.org/html/rfc2616#section-14.16 167 // Content-Range: <range unit> <bytes range>/<size> 168 sal_Int32 nSlash = aContentRange.lastIndexOf( sal_Unicode('/')); 169 if ( nSlash != -1 ) 170 { 171 rtl::OUString aSize = aContentRange.copy( nSlash + 1 ); 172 // "*" means that the instance-length is unknown at the time when the response was generated 173 if ( !aSize.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "*" ))) 174 { 175 for ( std::vector< DAVPropertyValue >::iterator it = aResponseProps.begin(); 176 it != aResponseProps.end(); it++ ) 177 { 178 if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) ) 179 { 180 it->Value <<= aSize; 181 break; 182 } 183 } 184 } 185 } 186 } 187 } 188 189 if ( xProps.get() ) 190 xProps->addProperties( 191 aProps, 192 ContentProperties( aResource ) ); 193 else 194 xProps.reset ( new ContentProperties( aResource ) ); 195 } 196 catch ( DAVException const & ex ) 197 { 198 aLastException = ex; 199 } 200 } 201 } 202 203 //========================================================================= 204 //========================================================================= 205 // 206 // Content Implementation. 207 // 208 //========================================================================= 209 //========================================================================= 210 211 //========================================================================= 212 // ctr for content on an existing webdav resource 213 Content::Content( 214 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 215 ContentProvider* pProvider, 216 const uno::Reference< ucb::XContentIdentifier >& Identifier, 217 rtl::Reference< DAVSessionFactory > const & rSessionFactory ) 218 throw ( ucb::ContentCreationException ) 219 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 220 m_eResourceType( UNKNOWN ), 221 m_pProvider( pProvider ), 222 m_bTransient( false ), 223 m_bCollection( false ), 224 m_bDidGetOrHead( false ) 225 { 226 try 227 { 228 m_xResAccess.reset( new DAVResourceAccess( 229 rxSMgr, 230 rSessionFactory, 231 Identifier->getContentIdentifier() ) ); 232 233 SerfUri aURI( Identifier->getContentIdentifier() ); 234 m_aEscapedTitle = aURI.GetPathBaseName(); 235 } 236 catch ( DAVException const & ) 237 { 238 throw ucb::ContentCreationException(); 239 } 240 } 241 242 //========================================================================= 243 // ctr for content on an non-existing webdav resource 244 Content::Content( 245 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 246 ContentProvider* pProvider, 247 const uno::Reference< ucb::XContentIdentifier >& Identifier, 248 rtl::Reference< DAVSessionFactory > const & rSessionFactory, 249 sal_Bool isCollection ) 250 throw ( ucb::ContentCreationException ) 251 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 252 m_eResourceType( UNKNOWN ), 253 m_pProvider( pProvider ), 254 m_bTransient( true ), 255 m_bCollection( isCollection ), 256 m_bDidGetOrHead( false ) 257 { 258 try 259 { 260 m_xResAccess.reset( new DAVResourceAccess( 261 rxSMgr, rSessionFactory, Identifier->getContentIdentifier() ) ); 262 } 263 catch ( DAVException const & ) 264 { 265 throw ucb::ContentCreationException(); 266 } 267 268 // Do not set m_aEscapedTitle here! Content::insert relays on this!!! 269 } 270 271 //========================================================================= 272 // virtual 273 Content::~Content() 274 { 275 } 276 277 //========================================================================= 278 // 279 // XInterface methods. 280 // 281 //========================================================================= 282 283 // virtual 284 void SAL_CALL Content::acquire() 285 throw( ) 286 { 287 ContentImplHelper::acquire(); 288 } 289 290 //========================================================================= 291 // virtual 292 void SAL_CALL Content::release() 293 throw( ) 294 { 295 ContentImplHelper::release(); 296 } 297 298 //========================================================================= 299 // virtual 300 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) 301 throw ( uno::RuntimeException ) 302 { 303 // Note: isFolder may require network activities! So call it only 304 // if it is really necessary!!! 305 uno::Any aRet = cppu::queryInterface( 306 rType, 307 static_cast< ucb::XContentCreator * >( this ) ); 308 if ( aRet.hasValue() ) 309 { 310 try 311 { 312 uno::Reference< beans::XPropertySet > const xProps( 313 m_xSMgr, uno::UNO_QUERY_THROW ); 314 uno::Reference< uno::XComponentContext > xCtx; 315 xCtx.set( xProps->getPropertyValue( 316 rtl::OUString( 317 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), 318 uno::UNO_QUERY_THROW ); 319 320 uno::Reference< task::XInteractionHandler > xIH( 321 task::PasswordContainerInteractionHandler::create( xCtx ) ); 322 323 // Supply a command env to isFolder() that contains an interaction 324 // handler that uses the password container service to obtain 325 // credentials without displaying a password gui. 326 327 uno::Reference< ucb::XCommandEnvironment > xCmdEnv( 328 ucb::CommandEnvironment::create( 329 xCtx, 330 xIH, 331 uno::Reference< ucb::XProgressHandler >() ) ); 332 333 return isFolder( xCmdEnv ) ? aRet : uno::Any(); 334 } 335 catch ( uno::RuntimeException const & ) 336 { 337 throw; 338 } 339 catch ( uno::Exception const & ) 340 { 341 return uno::Any(); 342 } 343 } 344 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); 345 } 346 347 //========================================================================= 348 // 349 // XTypeProvider methods. 350 // 351 //========================================================================= 352 353 XTYPEPROVIDER_COMMON_IMPL( Content ); 354 355 //========================================================================= 356 // virtual 357 uno::Sequence< uno::Type > SAL_CALL Content::getTypes() 358 throw( uno::RuntimeException ) 359 { 360 sal_Bool bFolder = sal_False; 361 try 362 { 363 bFolder 364 = isFolder( uno::Reference< ucb::XCommandEnvironment >() ); 365 } 366 catch ( uno::RuntimeException const & ) 367 { 368 throw; 369 } 370 catch ( uno::Exception const & ) 371 { 372 } 373 374 cppu::OTypeCollection * pCollection = 0; 375 376 if ( bFolder ) 377 { 378 static cppu::OTypeCollection* pFolderTypes = 0; 379 380 pCollection = pFolderTypes; 381 if ( !pCollection ) 382 { 383 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 384 385 pCollection = pFolderTypes; 386 if ( !pCollection ) 387 { 388 static cppu::OTypeCollection aCollection( 389 CPPU_TYPE_REF( lang::XTypeProvider ), 390 CPPU_TYPE_REF( lang::XServiceInfo ), 391 CPPU_TYPE_REF( lang::XComponent ), 392 CPPU_TYPE_REF( ucb::XContent ), 393 CPPU_TYPE_REF( ucb::XCommandProcessor ), 394 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 395 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 396 CPPU_TYPE_REF( beans::XPropertyContainer ), 397 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 398 CPPU_TYPE_REF( container::XChild ), 399 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! 400 pCollection = &aCollection; 401 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 402 pFolderTypes = pCollection; 403 } 404 } 405 else { 406 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 407 } 408 } 409 else 410 { 411 static cppu::OTypeCollection* pDocumentTypes = 0; 412 413 pCollection = pDocumentTypes; 414 if ( !pCollection ) 415 { 416 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 417 418 pCollection = pDocumentTypes; 419 if ( !pCollection ) 420 { 421 static cppu::OTypeCollection aCollection( 422 CPPU_TYPE_REF( lang::XTypeProvider ), 423 CPPU_TYPE_REF( lang::XServiceInfo ), 424 CPPU_TYPE_REF( lang::XComponent ), 425 CPPU_TYPE_REF( ucb::XContent ), 426 CPPU_TYPE_REF( ucb::XCommandProcessor ), 427 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 428 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 429 CPPU_TYPE_REF( beans::XPropertyContainer ), 430 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 431 CPPU_TYPE_REF( container::XChild ) ); 432 pCollection = &aCollection; 433 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 434 pDocumentTypes = pCollection; 435 } 436 } 437 else { 438 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 439 } 440 } 441 442 return (*pCollection).getTypes(); 443 } 444 445 //========================================================================= 446 // 447 // XServiceInfo methods. 448 // 449 //========================================================================= 450 451 // virtual 452 rtl::OUString SAL_CALL Content::getImplementationName() 453 throw( uno::RuntimeException ) 454 { 455 return rtl::OUString::createFromAscii( 456 "com.sun.star.comp.ucb.WebDAVContent" ); 457 } 458 459 //========================================================================= 460 // virtual 461 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() 462 throw( uno::RuntimeException ) 463 { 464 uno::Sequence< rtl::OUString > aSNS( 1 ); 465 aSNS.getArray()[ 0 ] 466 = rtl::OUString::createFromAscii( WEBDAV_CONTENT_SERVICE_NAME ); 467 return aSNS; 468 } 469 470 //========================================================================= 471 // 472 // XContent methods. 473 // 474 //========================================================================= 475 476 // virtual 477 rtl::OUString SAL_CALL Content::getContentType() 478 throw( uno::RuntimeException ) 479 { 480 sal_Bool bFolder = sal_False; 481 try 482 { 483 bFolder 484 = isFolder( uno::Reference< ucb::XCommandEnvironment >() ); 485 } 486 catch ( uno::RuntimeException const & ) 487 { 488 throw; 489 } 490 catch ( uno::Exception const & ) 491 { 492 } 493 494 if ( bFolder ) 495 return rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE ); 496 497 return rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE ); 498 } 499 500 //========================================================================= 501 // 502 // XCommandProcessor methods. 503 // 504 //========================================================================= 505 506 // virtual 507 uno::Any SAL_CALL Content::execute( 508 const ucb::Command& aCommand, 509 sal_Int32 /*CommandId*/, 510 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 511 throw( uno::Exception, 512 ucb::CommandAbortedException, 513 uno::RuntimeException ) 514 { 515 OSL_TRACE( ">>>>> Content::execute: start: command: %s, env: %s", 516 rtl::OUStringToOString( aCommand.Name, 517 RTL_TEXTENCODING_UTF8 ).getStr(), 518 Environment.is() ? "present" : "missing" ); 519 520 uno::Any aRet; 521 522 if ( aCommand.Name.equalsAsciiL( 523 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) 524 { 525 ////////////////////////////////////////////////////////////////// 526 // getPropertyValues 527 ////////////////////////////////////////////////////////////////// 528 529 uno::Sequence< beans::Property > Properties; 530 if ( !( aCommand.Argument >>= Properties ) ) 531 { 532 ucbhelper::cancelCommandExecution( 533 uno::makeAny( lang::IllegalArgumentException( 534 rtl::OUString::createFromAscii( 535 "Wrong argument type!" ), 536 static_cast< cppu::OWeakObject * >( this ), 537 -1 ) ), 538 Environment ); 539 // Unreachable 540 } 541 542 aRet <<= getPropertyValues( Properties, Environment ); 543 } 544 else if ( aCommand.Name.equalsAsciiL( 545 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) 546 { 547 ////////////////////////////////////////////////////////////////// 548 // setPropertyValues 549 ////////////////////////////////////////////////////////////////// 550 551 uno::Sequence< beans::PropertyValue > aProperties; 552 if ( !( aCommand.Argument >>= aProperties ) ) 553 { 554 ucbhelper::cancelCommandExecution( 555 uno::makeAny( lang::IllegalArgumentException( 556 rtl::OUString::createFromAscii( 557 "Wrong argument type!" ), 558 static_cast< cppu::OWeakObject * >( this ), 559 -1 ) ), 560 Environment ); 561 // Unreachable 562 } 563 564 if ( !aProperties.getLength() ) 565 { 566 ucbhelper::cancelCommandExecution( 567 uno::makeAny( lang::IllegalArgumentException( 568 rtl::OUString::createFromAscii( 569 "No properties!" ), 570 static_cast< cppu::OWeakObject * >( this ), 571 -1 ) ), 572 Environment ); 573 // Unreachable 574 } 575 576 aRet <<= setPropertyValues( aProperties, Environment ); 577 } 578 else if ( aCommand.Name.equalsAsciiL( 579 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) 580 { 581 ////////////////////////////////////////////////////////////////// 582 // getPropertySetInfo 583 ////////////////////////////////////////////////////////////////// 584 585 // Note: Implemented by base class. 586 aRet <<= getPropertySetInfo( Environment, 587 sal_False /* don't cache data */ ); 588 } 589 else if ( aCommand.Name.equalsAsciiL( 590 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) 591 { 592 ////////////////////////////////////////////////////////////////// 593 // getCommandInfo 594 ////////////////////////////////////////////////////////////////// 595 596 // Note: Implemented by base class. 597 aRet <<= getCommandInfo( Environment, sal_False ); 598 } 599 else if ( aCommand.Name.equalsAsciiL( 600 RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) 601 { 602 ////////////////////////////////////////////////////////////////// 603 // open 604 ////////////////////////////////////////////////////////////////// 605 606 ucb::OpenCommandArgument2 aOpenCommand; 607 if ( !( aCommand.Argument >>= aOpenCommand ) ) 608 { 609 ucbhelper::cancelCommandExecution( 610 uno::makeAny( lang::IllegalArgumentException( 611 rtl::OUString::createFromAscii( 612 "Wrong argument type!" ), 613 static_cast< cppu::OWeakObject * >( this ), 614 -1 ) ), 615 Environment ); 616 // Unreachable 617 } 618 619 aRet = open( aOpenCommand, Environment ); 620 } 621 else if ( aCommand.Name.equalsAsciiL( 622 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) 623 { 624 ////////////////////////////////////////////////////////////////// 625 // insert 626 ////////////////////////////////////////////////////////////////// 627 628 ucb::InsertCommandArgument arg; 629 if ( !( aCommand.Argument >>= arg ) ) 630 { 631 ucbhelper::cancelCommandExecution( 632 uno::makeAny( lang::IllegalArgumentException( 633 rtl::OUString::createFromAscii( 634 "Wrong argument type!" ), 635 static_cast< cppu::OWeakObject * >( this ), 636 -1 ) ), 637 Environment ); 638 // Unreachable 639 } 640 641 insert( arg.Data, arg.ReplaceExisting, Environment ); 642 } 643 else if ( aCommand.Name.equalsAsciiL( 644 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) 645 { 646 ////////////////////////////////////////////////////////////////// 647 // delete 648 ////////////////////////////////////////////////////////////////// 649 650 sal_Bool bDeletePhysical = sal_False; 651 aCommand.Argument >>= bDeletePhysical; 652 653 // KSO: Ignore parameter and destroy the content, if you don't support 654 // putting objects into trashcan. ( Since we do not have a trash can 655 // service yet (src603), you actually have no other choice. ) 656 // if ( bDeletePhysical ) 657 // { 658 try 659 { 660 std::auto_ptr< DAVResourceAccess > xResAccess; 661 { 662 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 663 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 664 } 665 xResAccess->DESTROY( Environment ); 666 { 667 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 668 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 669 } 670 } 671 catch ( DAVException const & e ) 672 { 673 cancelCommandExecution( e, Environment, sal_True ); 674 // Unreachable 675 } 676 // } 677 678 // Propagate destruction. 679 destroy( bDeletePhysical ); 680 681 // Remove own and all children's Additional Core Properties. 682 removeAdditionalPropertySet( sal_True ); 683 } 684 else if ( aCommand.Name.equalsAsciiL( 685 RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) 686 && isFolder( Environment ) ) 687 { 688 ////////////////////////////////////////////////////////////////// 689 // transfer 690 // ( Not available at documents ) 691 ////////////////////////////////////////////////////////////////// 692 693 ucb::TransferInfo transferArgs; 694 if ( !( aCommand.Argument >>= transferArgs ) ) 695 { 696 ucbhelper::cancelCommandExecution( 697 uno::makeAny( lang::IllegalArgumentException( 698 rtl::OUString::createFromAscii( 699 "Wrong argument type!" ), 700 static_cast< cppu::OWeakObject * >( this ), 701 -1 ) ), 702 Environment ); 703 // Unreachable 704 } 705 706 transfer( transferArgs, Environment ); 707 } 708 else if ( aCommand.Name.equalsAsciiL( 709 RTL_CONSTASCII_STRINGPARAM( "post" ) ) ) 710 { 711 ////////////////////////////////////////////////////////////////// 712 // post 713 ////////////////////////////////////////////////////////////////// 714 715 ucb::PostCommandArgument2 aArg; 716 if ( !( aCommand.Argument >>= aArg ) ) 717 { 718 ucbhelper::cancelCommandExecution( 719 uno::makeAny( lang::IllegalArgumentException( 720 rtl::OUString::createFromAscii( 721 "Wrong argument type!" ), 722 static_cast< cppu::OWeakObject * >( this ), 723 -1 ) ), 724 Environment ); 725 // Unreachable 726 } 727 728 post( aArg, Environment ); 729 } 730 else if ( aCommand.Name.equalsAsciiL( 731 RTL_CONSTASCII_STRINGPARAM( "lock" ) ) && 732 supportsExclusiveWriteLock( Environment ) ) 733 { 734 ////////////////////////////////////////////////////////////////// 735 // lock 736 ////////////////////////////////////////////////////////////////// 737 738 lock( Environment ); 739 } 740 else if ( aCommand.Name.equalsAsciiL( 741 RTL_CONSTASCII_STRINGPARAM( "unlock" ) ) && 742 supportsExclusiveWriteLock( Environment ) ) 743 { 744 ////////////////////////////////////////////////////////////////// 745 // unlock 746 ////////////////////////////////////////////////////////////////// 747 748 unlock( Environment ); 749 } 750 else if ( aCommand.Name.equalsAsciiL( 751 RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && 752 isFolder( Environment ) ) 753 { 754 ////////////////////////////////////////////////////////////////// 755 // createNewContent 756 ////////////////////////////////////////////////////////////////// 757 758 ucb::ContentInfo aArg; 759 if ( !( aCommand.Argument >>= aArg ) ) 760 { 761 ucbhelper::cancelCommandExecution( 762 uno::makeAny( lang::IllegalArgumentException( 763 rtl::OUString::createFromAscii( 764 "Wrong argument type!" ), 765 static_cast< cppu::OWeakObject * >( this ), 766 -1 ) ), 767 Environment ); 768 // Unreachable 769 } 770 771 aRet = uno::makeAny( createNewContent( aArg ) ); 772 } 773 else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "addProperty" ))) 774 { 775 ucb::PropertyCommandArgument aPropArg; 776 if ( !( aCommand.Argument >>= aPropArg )) 777 { 778 ucbhelper::cancelCommandExecution( 779 uno::makeAny( lang::IllegalArgumentException( 780 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 781 "Wrong argument type!" )), 782 static_cast< cppu::OWeakObject * >( this ), 783 -1 ) ), 784 Environment ); 785 } 786 787 // TODO when/if XPropertyContainer is removed, 788 // the command execution can be canceled in addProperty 789 try 790 { 791 addProperty( aPropArg, Environment ); 792 } 793 catch ( const beans::PropertyExistException &e ) 794 { 795 ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment ); 796 } 797 catch ( const beans::IllegalTypeException&e ) 798 { 799 ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment ); 800 } 801 catch ( const lang::IllegalArgumentException&e ) 802 { 803 ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment ); 804 } 805 } 806 else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "removeProperty" ))) 807 { 808 rtl::OUString sPropName; 809 if ( !( aCommand.Argument >>= sPropName ) ) 810 { 811 ucbhelper::cancelCommandExecution( 812 uno::makeAny( lang::IllegalArgumentException( 813 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 814 "Wrong argument type!" )), 815 static_cast< cppu::OWeakObject * >( this ), 816 -1 ) ), 817 Environment ); 818 } 819 820 // TODO when/if XPropertyContainer is removed, 821 // the command execution can be canceled in removeProperty 822 try 823 { 824 removeProperty( sPropName, Environment ); 825 } 826 catch( const beans::UnknownPropertyException &e ) 827 { 828 ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment ); 829 } 830 catch( const beans::NotRemoveableException &e ) 831 { 832 ucbhelper::cancelCommandExecution( uno::makeAny( e ), Environment ); 833 } 834 } 835 else 836 { 837 ////////////////////////////////////////////////////////////////// 838 // Unsupported command 839 ////////////////////////////////////////////////////////////////// 840 841 ucbhelper::cancelCommandExecution( 842 uno::makeAny( ucb::UnsupportedCommandException( 843 aCommand.Name, 844 static_cast< cppu::OWeakObject * >( this ) ) ), 845 Environment ); 846 // Unreachable 847 } 848 849 OSL_TRACE( "<<<<< Content::execute: end: command: %s", 850 rtl::OUStringToOString( aCommand.Name, 851 RTL_TEXTENCODING_UTF8 ).getStr() ); 852 853 return aRet; 854 } 855 856 //========================================================================= 857 // virtual 858 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) 859 throw( uno::RuntimeException ) 860 { 861 try 862 { 863 std::auto_ptr< DAVResourceAccess > xResAccess; 864 { 865 osl::MutexGuard aGuard( m_aMutex ); 866 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 867 } 868 xResAccess->abort(); 869 { 870 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 871 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 872 } 873 } 874 catch ( DAVException const & ) 875 { 876 // abort failed! 877 } 878 } 879 880 //========================================================================= 881 // 882 // XPropertyContainer methods. 883 // 884 //========================================================================= 885 886 void Content::addProperty( const com::sun::star::ucb::PropertyCommandArgument &aCmdArg, 887 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 888 throw( beans::PropertyExistException, 889 beans::IllegalTypeException, 890 lang::IllegalArgumentException, 891 uno::RuntimeException ) 892 { 893 // if ( m_bTransient ) 894 // @@@ ??? 895 const beans::Property aProperty = aCmdArg.Property; 896 const uno::Any aDefaultValue = aCmdArg.DefaultValue; 897 898 // check property Name 899 if ( !aProperty.Name.getLength() ) 900 throw lang::IllegalArgumentException( 901 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 902 "\"addProperty\" with empty Property.Name")), 903 static_cast< ::cppu::OWeakObject * >( this ), 904 -1 ); 905 906 // Check property type. 907 if ( !UCBDeadPropertyValue::supportsType( aProperty.Type ) ) 908 throw beans::IllegalTypeException( 909 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 910 "\"addProperty\" unsupported Property.Type")), 911 static_cast< ::cppu::OWeakObject * >( this ) ); 912 913 // check default value 914 if ( aDefaultValue.hasValue() && aDefaultValue.getValueType() != aProperty.Type ) 915 throw beans::IllegalTypeException( 916 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 917 "\"addProperty\" DefaultValue does not match Property.Type")), 918 static_cast< ::cppu::OWeakObject * >( this ) ); 919 920 ////////////////////////////////////////////////////////////////////// 921 // Make sure a property with the requested name does not already 922 // exist in dynamic and static(!) properties. 923 ////////////////////////////////////////////////////////////////////// 924 925 // Take into account special properties with custom namespace 926 // using <prop:the_propname xmlns:prop="the_namespace"> 927 rtl::OUString aSpecialName; 928 bool bIsSpecial = DAVProperties::isUCBSpecialProperty( aProperty.Name, aSpecialName ); 929 930 // Note: This requires network access! 931 if ( getPropertySetInfo( xEnv, sal_False /* don't cache data */ ) 932 ->hasPropertyByName( bIsSpecial ? aSpecialName : aProperty.Name ) ) 933 { 934 // Property does already exist. 935 throw beans::PropertyExistException(); 936 } 937 938 ////////////////////////////////////////////////////////////////////// 939 // Add a new dynamic property. 940 ////////////////////////////////////////////////////////////////////// 941 942 ProppatchValue aValue( PROPSET, aProperty.Name, aDefaultValue ); 943 944 std::vector< ProppatchValue > aProppatchValues; 945 aProppatchValues.push_back( aValue ); 946 947 try 948 { 949 // Set property value at server. 950 std::auto_ptr< DAVResourceAccess > xResAccess; 951 { 952 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 953 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 954 } 955 xResAccess->PROPPATCH( aProppatchValues, xEnv ); 956 { 957 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 958 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 959 } 960 961 // Notify propertyset info change listeners. 962 beans::PropertySetInfoChangeEvent evt( 963 static_cast< cppu::OWeakObject * >( this ), 964 bIsSpecial ? aSpecialName : aProperty.Name, 965 -1, // No handle available 966 beans::PropertySetInfoChange::PROPERTY_INSERTED ); 967 notifyPropertySetInfoChange( evt ); 968 } 969 catch ( DAVException const & e ) 970 { 971 if ( e.getStatus() == SC_FORBIDDEN ) 972 { 973 // Support for setting arbitrary dead properties is optional! 974 975 // Store property locally. 976 ContentImplHelper::addProperty( bIsSpecial ? aSpecialName : aProperty.Name, 977 aProperty.Attributes, 978 aDefaultValue ); 979 } 980 else 981 { 982 if ( shouldAccessNetworkAfterException( e ) ) 983 { 984 try 985 { 986 const ResourceType & rType = getResourceType( xEnv ); 987 switch ( rType ) 988 { 989 case UNKNOWN: 990 case DAV: 991 throw lang::IllegalArgumentException(); 992 993 case NON_DAV: 994 // Store property locally. 995 ContentImplHelper::addProperty( bIsSpecial ? aSpecialName : aProperty.Name, 996 aProperty.Attributes, 997 aDefaultValue ); 998 break; 999 1000 default: 1001 OSL_ENSURE( sal_False, 1002 "Content::addProperty - " 1003 "Unsupported resource type!" ); 1004 break; 1005 } 1006 } 1007 catch ( uno::Exception const & ) 1008 { 1009 OSL_ENSURE( sal_False, 1010 "Content::addProperty - " 1011 "Unable to determine resource type!" ); 1012 } 1013 } 1014 else 1015 { 1016 OSL_ENSURE( sal_False, 1017 "Content::addProperty - " 1018 "Unable to determine resource type!" ); 1019 } 1020 } 1021 } 1022 } 1023 1024 void Content::removeProperty( const rtl::OUString& Name, 1025 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 1026 throw( beans::UnknownPropertyException, 1027 beans::NotRemoveableException, 1028 uno::RuntimeException ) 1029 { 1030 #if 0 1031 // @@@ REMOVEABLE z.Z. nicht richtig an der PropSetInfo gesetzt!!! 1032 try 1033 { 1034 beans::Property aProp 1035 = getPropertySetInfo( xEnv, sal_False /* don't cache data */ ) 1036 ->getPropertyByName( Name ); 1037 1038 if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVEABLE ) ) 1039 { 1040 // Not removeable! 1041 throw beans::NotRemoveableException(); 1042 } 1043 } 1044 catch ( beans::UnknownPropertyException const & ) 1045 { 1046 //OSL_ENSURE( sal_False, "removeProperty - Unknown property!" ); 1047 throw; 1048 } 1049 #endif 1050 1051 ////////////////////////////////////////////////////////////////////// 1052 // Try to remove property from server. 1053 ////////////////////////////////////////////////////////////////////// 1054 1055 try 1056 { 1057 std::vector< ProppatchValue > aProppatchValues; 1058 ProppatchValue aValue( PROPREMOVE, Name, uno::Any() ); 1059 aProppatchValues.push_back( aValue ); 1060 1061 // Remove property value from server. 1062 std::auto_ptr< DAVResourceAccess > xResAccess; 1063 { 1064 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1065 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 1066 } 1067 xResAccess->PROPPATCH( aProppatchValues, xEnv ); 1068 { 1069 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1070 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 1071 } 1072 1073 // Notify propertyset info change listeners. 1074 beans::PropertySetInfoChangeEvent evt( 1075 static_cast< cppu::OWeakObject * >( this ), 1076 Name, 1077 -1, // No handle available 1078 beans::PropertySetInfoChange::PROPERTY_REMOVED ); 1079 notifyPropertySetInfoChange( evt ); 1080 } 1081 catch ( DAVException const & e ) 1082 { 1083 if ( e.getStatus() == SC_FORBIDDEN ) 1084 { 1085 // Support for setting arbitrary dead properties is optional! 1086 1087 // Try to remove property from local store. 1088 ContentImplHelper::removeProperty( Name ); 1089 } 1090 else 1091 { 1092 if ( shouldAccessNetworkAfterException( e ) ) 1093 { 1094 try 1095 { 1096 const ResourceType & rType = getResourceType( xEnv ); 1097 switch ( rType ) 1098 { 1099 case UNKNOWN: 1100 case DAV: 1101 throw beans::UnknownPropertyException(); 1102 1103 case NON_DAV: 1104 // Try to remove property from local store. 1105 ContentImplHelper::removeProperty( Name ); 1106 break; 1107 1108 default: 1109 OSL_ENSURE( sal_False, 1110 "Content::removeProperty - " 1111 "Unsupported resource type!" ); 1112 break; 1113 } 1114 } 1115 catch ( uno::Exception const & ) 1116 { 1117 OSL_ENSURE( sal_False, 1118 "Content::removeProperty - " 1119 "Unable to determine resource type!" ); 1120 } 1121 } 1122 else 1123 { 1124 OSL_ENSURE( sal_False, 1125 "Content::removeProperty - " 1126 "Unable to determine resource type!" ); 1127 // throw beans::UnknownPropertyException(); 1128 } 1129 } 1130 } 1131 } 1132 1133 // virtual 1134 void SAL_CALL Content::addProperty( const rtl::OUString& Name, 1135 sal_Int16 Attributes, 1136 const uno::Any& DefaultValue ) 1137 throw( beans::PropertyExistException, 1138 beans::IllegalTypeException, 1139 lang::IllegalArgumentException, 1140 uno::RuntimeException ) 1141 { 1142 beans::Property aProperty; 1143 aProperty.Name = Name; 1144 aProperty.Type = DefaultValue.getValueType(); 1145 aProperty.Attributes = Attributes; 1146 aProperty.Handle = -1; 1147 1148 addProperty( ucb::PropertyCommandArgument( aProperty, DefaultValue ), 1149 uno::Reference< ucb::XCommandEnvironment >()); 1150 } 1151 1152 // virtual 1153 void SAL_CALL Content::removeProperty( const rtl::OUString& Name ) 1154 throw( beans::UnknownPropertyException, 1155 beans::NotRemoveableException, 1156 uno::RuntimeException ) 1157 { 1158 removeProperty( Name, 1159 uno::Reference< ucb::XCommandEnvironment >() ); 1160 } 1161 1162 //========================================================================= 1163 // 1164 // XContentCreator methods. 1165 // 1166 //========================================================================= 1167 1168 // virtual 1169 uno::Sequence< ucb::ContentInfo > SAL_CALL 1170 Content::queryCreatableContentsInfo() 1171 throw( uno::RuntimeException ) 1172 { 1173 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1174 1175 uno::Sequence< ucb::ContentInfo > aSeq( 2 ); 1176 1177 // document. 1178 aSeq.getArray()[ 0 ].Type 1179 = rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE ); 1180 aSeq.getArray()[ 0 ].Attributes 1181 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM 1182 | ucb::ContentInfoAttribute::KIND_DOCUMENT; 1183 1184 beans::Property aProp; 1185 m_pProvider->getProperty( 1186 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), aProp ); 1187 1188 uno::Sequence< beans::Property > aDocProps( 1 ); 1189 aDocProps.getArray()[ 0 ] = aProp; 1190 aSeq.getArray()[ 0 ].Properties = aDocProps; 1191 1192 // folder. 1193 aSeq.getArray()[ 1 ].Type 1194 = rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE ); 1195 aSeq.getArray()[ 1 ].Attributes 1196 = ucb::ContentInfoAttribute::KIND_FOLDER; 1197 1198 uno::Sequence< beans::Property > aFolderProps( 1 ); 1199 aFolderProps.getArray()[ 0 ] = aProp; 1200 aSeq.getArray()[ 1 ].Properties = aFolderProps; 1201 return aSeq; 1202 } 1203 1204 //========================================================================= 1205 // virtual 1206 uno::Reference< ucb::XContent > SAL_CALL 1207 Content::createNewContent( const ucb::ContentInfo& Info ) 1208 throw( uno::RuntimeException ) 1209 { 1210 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1211 1212 if ( !Info.Type.getLength() ) 1213 return uno::Reference< ucb::XContent >(); 1214 1215 if ( ( !Info.Type.equalsAsciiL( 1216 RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE ) ) ) 1217 && 1218 ( !Info.Type.equalsAsciiL( 1219 RTL_CONSTASCII_STRINGPARAM( WEBDAV_CONTENT_TYPE ) ) ) ) 1220 return uno::Reference< ucb::XContent >(); 1221 1222 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 1223 1224 OSL_ENSURE( aURL.getLength() > 0, 1225 "WebdavContent::createNewContent - empty identifier!" ); 1226 1227 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) 1228 aURL += rtl::OUString::createFromAscii( "/" ); 1229 1230 sal_Bool isCollection; 1231 if ( Info.Type.equalsAsciiL( 1232 RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE ) ) ) 1233 { 1234 aURL += rtl::OUString::createFromAscii( "New_Collection" ); 1235 isCollection = sal_True; 1236 } 1237 else 1238 { 1239 aURL += rtl::OUString::createFromAscii( "New_Content" ); 1240 isCollection = sal_False; 1241 } 1242 1243 uno::Reference< ucb::XContentIdentifier > xId( 1244 new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) ); 1245 1246 // create the local content 1247 try 1248 { 1249 return new ::http_dav_ucp::Content( m_xSMgr, 1250 m_pProvider, 1251 xId, 1252 m_xResAccess->getSessionFactory(), 1253 isCollection ); 1254 } 1255 catch ( ucb::ContentCreationException & ) 1256 { 1257 return uno::Reference< ucb::XContent >(); 1258 } 1259 } 1260 1261 //========================================================================= 1262 // virtual 1263 rtl::OUString Content::getParentURL() 1264 { 1265 // <scheme>:// -> "" 1266 // <scheme>://foo -> "" 1267 // <scheme>://foo/ -> "" 1268 // <scheme>://foo/bar -> <scheme>://foo/ 1269 // <scheme>://foo/bar/ -> <scheme>://foo/ 1270 // <scheme>://foo/bar/abc -> <scheme>://foo/bar/ 1271 1272 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 1273 1274 sal_Int32 nPos = aURL.lastIndexOf( '/' ); 1275 if ( nPos == ( aURL.getLength() - 1 ) ) 1276 { 1277 // Trailing slash found. Skip. 1278 nPos = aURL.lastIndexOf( '/', nPos ); 1279 } 1280 1281 sal_Int32 nPos1 = aURL.lastIndexOf( '/', nPos ); 1282 if ( nPos1 != -1 ) 1283 nPos1 = aURL.lastIndexOf( '/', nPos1 ); 1284 1285 if ( nPos1 == -1 ) 1286 return rtl::OUString(); 1287 1288 return rtl::OUString( aURL.copy( 0, nPos + 1 ) ); 1289 } 1290 1291 //========================================================================= 1292 // 1293 // Non-interface methods. 1294 // 1295 //========================================================================= 1296 1297 // static 1298 uno::Reference< sdbc::XRow > Content::getPropertyValues( 1299 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 1300 const uno::Sequence< beans::Property >& rProperties, 1301 const ContentProperties& rData, 1302 const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider, 1303 const rtl::OUString& rContentId ) 1304 { 1305 // Note: Empty sequence means "get values of all supported properties". 1306 1307 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow 1308 = new ::ucbhelper::PropertyValueSet( rSMgr ); 1309 1310 sal_Int32 nCount = rProperties.getLength(); 1311 if ( nCount ) 1312 { 1313 uno::Reference< beans::XPropertySet > xAdditionalPropSet; 1314 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 1315 1316 const beans::Property* pProps = rProperties.getConstArray(); 1317 for ( sal_Int32 n = 0; n < nCount; ++n ) 1318 { 1319 const beans::Property& rProp = pProps[ n ]; 1320 1321 // Process standard UCB, DAV and HTTP properties. 1322 const uno::Any & rValue = rData.getValue( rProp.Name ); 1323 if ( rValue.hasValue() ) 1324 { 1325 xRow->appendObject( rProp, rValue ); 1326 } 1327 else 1328 { 1329 // Process local Additional Properties. 1330 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 1331 { 1332 xAdditionalPropSet 1333 = uno::Reference< beans::XPropertySet >( 1334 rProvider->getAdditionalPropertySet( rContentId, 1335 sal_False ), 1336 uno::UNO_QUERY ); 1337 bTriedToGetAdditonalPropSet = sal_True; 1338 } 1339 1340 if ( !xAdditionalPropSet.is() || 1341 !xRow->appendPropertySetValue( 1342 xAdditionalPropSet, rProp ) ) 1343 { 1344 // Append empty entry. 1345 xRow->appendVoid( rProp ); 1346 } 1347 } 1348 } 1349 } 1350 else 1351 { 1352 // Append all standard UCB, DAV and HTTP properties. 1353 1354 const std::auto_ptr< PropertyValueMap > & xProps = rData.getProperties(); 1355 1356 PropertyValueMap::const_iterator it = xProps->begin(); 1357 PropertyValueMap::const_iterator end = xProps->end(); 1358 1359 ContentProvider * pProvider 1360 = static_cast< ContentProvider * >( rProvider.get() ); 1361 beans::Property aProp; 1362 1363 while ( it != end ) 1364 { 1365 if ( pProvider->getProperty( (*it).first, aProp ) ) 1366 xRow->appendObject( aProp, (*it).second.value() ); 1367 1368 ++it; 1369 } 1370 1371 // Append all local Additional Properties. 1372 uno::Reference< beans::XPropertySet > xSet( 1373 rProvider->getAdditionalPropertySet( rContentId, sal_False ), 1374 uno::UNO_QUERY ); 1375 xRow->appendPropertySet( xSet ); 1376 } 1377 1378 return uno::Reference< sdbc::XRow >( xRow.get() ); 1379 } 1380 1381 //========================================================================= 1382 uno::Reference< sdbc::XRow > Content::getPropertyValues( 1383 const uno::Sequence< beans::Property >& rProperties, 1384 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 1385 throw ( uno::Exception ) 1386 { 1387 std::auto_ptr< ContentProperties > xProps; 1388 std::auto_ptr< ContentProperties > xCachedProps; 1389 std::auto_ptr< DAVResourceAccess > xResAccess; 1390 rtl::OUString aUnescapedTitle; 1391 bool bHasAll = false; 1392 uno::Reference< lang::XMultiServiceFactory > xSMgr; 1393 uno::Reference< ucb::XContentIdentifier > xIdentifier; 1394 rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider; 1395 1396 { 1397 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1398 1399 aUnescapedTitle = SerfUri::unescape( m_aEscapedTitle ); 1400 xSMgr.set( m_xSMgr ); 1401 xIdentifier.set( m_xIdentifier ); 1402 xProvider.set( m_xProvider.get() ); 1403 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 1404 1405 // First, ask cache... 1406 if ( m_xCachedProps.get() ) 1407 { 1408 xCachedProps.reset( new ContentProperties( *m_xCachedProps.get() ) ); 1409 1410 std::vector< rtl::OUString > aMissingProps; 1411 if ( xCachedProps->containsAllNames( rProperties, aMissingProps ) ) 1412 { 1413 // All properties are already in cache! No server access needed. 1414 bHasAll = true; 1415 } 1416 1417 // use the cached ContentProperties instance 1418 xProps.reset( new ContentProperties( *xCachedProps.get() ) ); 1419 } 1420 } 1421 1422 if ( !m_bTransient && !bHasAll ) 1423 { 1424 ///////////////////////////////////////////////////////////////////// 1425 // Obtain values from server... 1426 ///////////////////////////////////////////////////////////////////// 1427 1428 // First, identify whether resource is DAV or not 1429 const ResourceType & rType = getResourceType( xEnv, xResAccess ); 1430 1431 bool bNetworkAccessAllowed = true; 1432 1433 if ( DAV == rType ) 1434 { 1435 // cache lookup... getResourceType may fill the props cache via 1436 // PROPFIND! 1437 if ( m_xCachedProps.get() ) 1438 { 1439 xCachedProps.reset( 1440 new ContentProperties( *m_xCachedProps.get() ) ); 1441 1442 std::vector< rtl::OUString > aMissingProps; 1443 if ( xCachedProps->containsAllNames( 1444 rProperties, aMissingProps ) ) 1445 { 1446 // All properties are already in cache! No server access 1447 // needed. 1448 bHasAll = true; 1449 } 1450 1451 // use the cached ContentProperties instance 1452 xProps.reset( new ContentProperties( *xCachedProps.get() ) ); 1453 } 1454 1455 if ( !bHasAll ) 1456 { 1457 // Only DAV resources support PROPFIND 1458 std::vector< rtl::OUString > aPropNames; 1459 1460 uno::Sequence< beans::Property > aProperties( 1461 rProperties.getLength() ); 1462 1463 if ( m_aFailedPropNames.size() > 0 ) 1464 { 1465 sal_Int32 nProps = 0; 1466 sal_Int32 nCount = rProperties.getLength(); 1467 for ( sal_Int32 n = 0; n < nCount; ++n ) 1468 { 1469 const rtl::OUString & rName = rProperties[ n ].Name; 1470 1471 std::vector< rtl::OUString >::const_iterator it 1472 = m_aFailedPropNames.begin(); 1473 std::vector< rtl::OUString >::const_iterator end 1474 = m_aFailedPropNames.end(); 1475 1476 while ( it != end ) 1477 { 1478 if ( *it == rName ) 1479 break; 1480 1481 ++it; 1482 } 1483 1484 if ( it == end ) 1485 { 1486 aProperties[ nProps ] = rProperties[ n ]; 1487 nProps++; 1488 } 1489 } 1490 1491 aProperties.realloc( nProps ); 1492 } 1493 else 1494 { 1495 aProperties = rProperties; 1496 } 1497 1498 if ( aProperties.getLength() > 0 ) 1499 ContentProperties::UCBNamesToDAVNames( 1500 aProperties, aPropNames ); 1501 1502 if ( aPropNames.size() > 0 ) 1503 { 1504 std::vector< DAVResource > resources; 1505 try 1506 { 1507 xResAccess->PROPFIND( 1508 DAVZERO, aPropNames, resources, xEnv ); 1509 1510 if ( 1 == resources.size() ) 1511 { 1512 if ( xProps.get()) 1513 xProps->addProperties( 1514 aPropNames, 1515 ContentProperties( resources[ 0 ] )); 1516 else 1517 xProps.reset( 1518 new ContentProperties( resources[ 0 ] ) ); 1519 } 1520 } 1521 catch ( DAVException const & e ) 1522 { 1523 bNetworkAccessAllowed 1524 = shouldAccessNetworkAfterException( e ); 1525 1526 if ( !bNetworkAccessAllowed ) 1527 { 1528 cancelCommandExecution( e, xEnv ); 1529 // unreachable 1530 } 1531 } 1532 } 1533 } 1534 } 1535 1536 if ( bNetworkAccessAllowed ) 1537 { 1538 // All properties obtained already? 1539 std::vector< rtl::OUString > aMissingProps; 1540 if ( !( xProps.get() 1541 && xProps->containsAllNames( 1542 rProperties, aMissingProps ) ) 1543 || !m_bDidGetOrHead ) 1544 { 1545 // Possibly the missing props can be obtained using a HEAD 1546 // request. 1547 1548 std::vector< rtl::OUString > aHeaderNames; 1549 ContentProperties::UCBNamesToHTTPNames( 1550 rProperties, 1551 aHeaderNames, 1552 true /* bIncludeUnmatched */ ); 1553 1554 if ( aHeaderNames.size() > 0 ) 1555 { 1556 try 1557 { 1558 DAVResource resource; 1559 xResAccess->HEAD( aHeaderNames, resource, xEnv ); 1560 m_bDidGetOrHead = true; 1561 1562 if ( xProps.get() ) 1563 xProps->addProperties( 1564 aMissingProps, 1565 ContentProperties( resource ) ); 1566 else 1567 xProps.reset ( new ContentProperties( resource ) ); 1568 1569 if ( m_eResourceType == NON_DAV ) 1570 xProps->addProperties( aMissingProps, 1571 ContentProperties( 1572 aUnescapedTitle, 1573 false ) ); 1574 } 1575 catch ( DAVException const & e ) 1576 { 1577 // non "general-purpose servers" may not support HEAD requests 1578 // see http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 1579 // In this case, perform a partial GET only to get the header info 1580 // vid. http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 1581 // WARNING if the server does not support partial GETs, 1582 // the GET will transfer the whole content 1583 bool bError = true; 1584 DAVException aLastException = e; 1585 1586 // According to the spec. the origin server SHOULD return 1587 // * 405 (Method Not Allowed): 1588 // the method is known but not allowed for the requested resource 1589 // * 501 (Not Implemented): 1590 // the method is unrecognized or not implemented 1591 // TODO SC_NOT_FOUND is only for google-code server 1592 if ( aLastException.getStatus() == SC_NOT_IMPLEMENTED || 1593 aLastException.getStatus() == SC_METHOD_NOT_ALLOWED || 1594 aLastException.getStatus() == SC_NOT_FOUND ) 1595 { 1596 lcl_sendPartialGETRequest( bError, 1597 aLastException, 1598 aMissingProps, 1599 aHeaderNames, 1600 xResAccess, 1601 xProps, 1602 xEnv ); 1603 m_bDidGetOrHead = !bError; 1604 } 1605 1606 if ( bError ) 1607 { 1608 if ( !(bNetworkAccessAllowed 1609 = shouldAccessNetworkAfterException( aLastException )) ) 1610 { 1611 cancelCommandExecution( aLastException, xEnv ); 1612 // unreachable 1613 } 1614 } 1615 } 1616 } 1617 } 1618 } 1619 1620 // might trigger HTTP redirect. 1621 // Therefore, title must be updated here. 1622 SerfUri aUri( xResAccess->getURL() ); 1623 aUnescapedTitle = aUri.GetPathBaseNameUnescaped(); 1624 1625 if ( rType == UNKNOWN ) 1626 { 1627 xProps.reset( new ContentProperties( aUnescapedTitle ) ); 1628 } 1629 1630 // For DAV resources we only know the Title, for non-DAV 1631 // resources we additionally know that it is a document. 1632 1633 if ( rType == DAV ) 1634 { 1635 //xProps.reset( 1636 // new ContentProperties( aUnescapedTitle ) ); 1637 xProps->addProperty( 1638 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), 1639 uno::makeAny( aUnescapedTitle ), 1640 true ); 1641 } 1642 else 1643 { 1644 if ( !xProps.get() ) 1645 xProps.reset( new ContentProperties( aUnescapedTitle, false ) ); 1646 else 1647 xProps->addProperty( 1648 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), 1649 uno::makeAny( aUnescapedTitle ), 1650 true ); 1651 1652 xProps->addProperty( 1653 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), 1654 uno::makeAny( false ), 1655 true ); 1656 xProps->addProperty( 1657 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), 1658 uno::makeAny( true ), 1659 true ); 1660 xProps->addProperty( 1661 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ), 1662 uno::makeAny( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( WEBDAV_CONTENT_TYPE ) ) ), 1663 true ); 1664 } 1665 } 1666 else 1667 { 1668 // No server access for just created (not yet committed) objects. 1669 // Only a minimal set of properties supported at this stage. 1670 if (m_bTransient) 1671 xProps.reset( new ContentProperties( aUnescapedTitle, 1672 m_bCollection ) ); 1673 } 1674 1675 sal_Int32 nCount = rProperties.getLength(); 1676 for ( sal_Int32 n = 0; n < nCount; ++n ) 1677 { 1678 const rtl::OUString rName = rProperties[ n ].Name; 1679 if ( rName.equalsAsciiL( 1680 RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) ) 1681 { 1682 // Add BaseURI property, if requested. 1683 xProps->addProperty( 1684 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ), 1685 uno::makeAny( getBaseURI( xResAccess ) ), 1686 true ); 1687 } 1688 else if ( rName.equalsAsciiL( 1689 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1690 { 1691 // Add CreatableContentsInfo property, if requested. 1692 sal_Bool bFolder = sal_False; 1693 xProps->getValue( 1694 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) ) 1695 >>= bFolder; 1696 xProps->addProperty( 1697 rtl::OUString( 1698 RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ), 1699 uno::makeAny( bFolder 1700 ? queryCreatableContentsInfo() 1701 : uno::Sequence< ucb::ContentInfo >() ), 1702 true ); 1703 } 1704 } 1705 1706 uno::Reference< sdbc::XRow > xResultRow 1707 = getPropertyValues( xSMgr, 1708 rProperties, 1709 *xProps, 1710 xProvider, 1711 xIdentifier->getContentIdentifier() ); 1712 1713 { 1714 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1715 1716 if ( !m_xCachedProps.get() ) 1717 m_xCachedProps.reset( new CachableContentProperties( *xProps.get() ) ); 1718 else 1719 m_xCachedProps->addProperties( *xProps.get() ); 1720 1721 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 1722 m_aEscapedTitle = SerfUri::escapeSegment( aUnescapedTitle ); 1723 } 1724 1725 return xResultRow; 1726 } 1727 1728 //========================================================================= 1729 uno::Sequence< uno::Any > Content::setPropertyValues( 1730 const uno::Sequence< beans::PropertyValue >& rValues, 1731 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 1732 throw ( uno::Exception ) 1733 { 1734 uno::Reference< lang::XMultiServiceFactory > xSMgr; 1735 uno::Reference< ucb::XContentIdentifier > xIdentifier; 1736 rtl::Reference< ContentProvider > xProvider; 1737 sal_Bool bTransient; 1738 std::auto_ptr< DAVResourceAccess > xResAccess; 1739 1740 { 1741 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1742 1743 xProvider.set( m_pProvider ); 1744 xIdentifier.set( m_xIdentifier ); 1745 bTransient = m_bTransient; 1746 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 1747 xSMgr.set( m_xSMgr ); 1748 } 1749 1750 uno::Sequence< uno::Any > aRet( rValues.getLength() ); 1751 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); 1752 sal_Int32 nChanged = 0; 1753 1754 beans::PropertyChangeEvent aEvent; 1755 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 1756 aEvent.Further = sal_False; 1757 // aEvent.PropertyName = 1758 aEvent.PropertyHandle = -1; 1759 // aEvent.OldValue = 1760 // aEvent.NewValue = 1761 1762 std::vector< ProppatchValue > aProppatchValues; 1763 std::vector< sal_Int32 > aProppatchPropsPositions; 1764 1765 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; 1766 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 1767 1768 sal_Bool bExchange = sal_False; 1769 rtl::OUString aNewTitle; 1770 rtl::OUString aOldTitle; 1771 sal_Int32 nTitlePos = -1; 1772 1773 uno::Reference< beans::XPropertySetInfo > xInfo; 1774 1775 const beans::PropertyValue* pValues = rValues.getConstArray(); 1776 sal_Int32 nCount = rValues.getLength(); 1777 for ( sal_Int32 n = 0; n < nCount; ++n ) 1778 { 1779 const beans::PropertyValue& rValue = pValues[ n ]; 1780 const rtl::OUString & rName = rValue.Name; 1781 1782 beans::Property aTmpProp; 1783 xProvider->getProperty( rName, aTmpProp ); 1784 1785 if ( aTmpProp.Attributes & beans::PropertyAttribute::READONLY ) 1786 { 1787 // Read-only property! 1788 aRet[ n ] <<= lang::IllegalAccessException( 1789 rtl::OUString::createFromAscii( 1790 "Property is read-only!" ), 1791 static_cast< cppu::OWeakObject * >( this ) ); 1792 continue; 1793 } 1794 1795 ////////////////////////////////////////////////////////////////// 1796 // Mandatory props. 1797 ////////////////////////////////////////////////////////////////// 1798 1799 if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 1800 { 1801 // Read-only property! 1802 aRet[ n ] <<= lang::IllegalAccessException( 1803 rtl::OUString::createFromAscii( 1804 "Property is read-only!" ), 1805 static_cast< cppu::OWeakObject * >( this ) ); 1806 } 1807 else if ( rName.equalsAsciiL( 1808 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 1809 { 1810 // Read-only property! 1811 aRet[ n ] <<= lang::IllegalAccessException( 1812 rtl::OUString::createFromAscii( 1813 "Property is read-only!" ), 1814 static_cast< cppu::OWeakObject * >( this ) ); 1815 } 1816 else if ( rName.equalsAsciiL( 1817 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 1818 { 1819 // Read-only property! 1820 aRet[ n ] <<= lang::IllegalAccessException( 1821 rtl::OUString::createFromAscii( 1822 "Property is read-only!" ), 1823 static_cast< cppu::OWeakObject * >( this ) ); 1824 } 1825 else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 1826 { 1827 rtl::OUString aNewValue; 1828 if ( rValue.Value >>= aNewValue ) 1829 { 1830 // No empty titles! 1831 if ( aNewValue.getLength() > 0 ) 1832 { 1833 try 1834 { 1835 SerfUri aURI( xIdentifier->getContentIdentifier() ); 1836 aOldTitle = aURI.GetPathBaseNameUnescaped(); 1837 1838 if ( aNewValue != aOldTitle ) 1839 { 1840 // modified title -> modified URL -> exchange ! 1841 if ( !bTransient ) 1842 bExchange = sal_True; 1843 1844 // new value will be set later... 1845 aNewTitle = aNewValue; 1846 1847 // remember position within sequence of values (for 1848 // error handling). 1849 nTitlePos = n; 1850 } 1851 } 1852 catch ( DAVException const & ) 1853 { 1854 aRet[ n ] <<= lang::IllegalArgumentException( 1855 rtl::OUString::createFromAscii( 1856 "Invalid content identifier!" ), 1857 static_cast< cppu::OWeakObject * >( this ), 1858 -1 ); 1859 } 1860 } 1861 else 1862 { 1863 aRet[ n ] <<= lang::IllegalArgumentException( 1864 rtl::OUString::createFromAscii( 1865 "Empty title not allowed!" ), 1866 static_cast< cppu::OWeakObject * >( this ), 1867 -1 ); 1868 } 1869 } 1870 else 1871 { 1872 aRet[ n ] <<= beans::IllegalTypeException( 1873 rtl::OUString::createFromAscii( 1874 "Property value has wrong type!" ), 1875 static_cast< cppu::OWeakObject * >( this ) ); 1876 } 1877 } 1878 else 1879 { 1880 ////////////////////////////////////////////////////////////// 1881 // Optional props. 1882 ////////////////////////////////////////////////////////////// 1883 1884 rtl::OUString aSpecialName; 1885 bool bIsSpecial = DAVProperties::isUCBSpecialProperty( rName, aSpecialName ); 1886 1887 if ( !xInfo.is() ) 1888 xInfo = getPropertySetInfo( xEnv, 1889 sal_False /* don't cache data */ ); 1890 1891 if ( !xInfo->hasPropertyByName( bIsSpecial ? aSpecialName : rName ) ) 1892 { 1893 // Check, whether property exists. Skip otherwise. 1894 // PROPPATCH::set would add the property automatically, which 1895 // is not allowed for "setPropertyValues" command! 1896 aRet[ n ] <<= beans::UnknownPropertyException( 1897 rtl::OUString::createFromAscii( 1898 "Property is unknown!" ), 1899 static_cast< cppu::OWeakObject * >( this ) ); 1900 continue; 1901 } 1902 1903 if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) 1904 { 1905 // Read-only property! 1906 aRet[ n ] <<= lang::IllegalAccessException( 1907 rtl::OUString::createFromAscii( 1908 "Property is read-only!" ), 1909 static_cast< cppu::OWeakObject * >( this ) ); 1910 } 1911 else if ( rName.equalsAsciiL( 1912 RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) 1913 { 1914 // Read-only property! 1915 aRet[ n ] <<= lang::IllegalAccessException( 1916 rtl::OUString::createFromAscii( 1917 "Property is read-only!" ), 1918 static_cast< cppu::OWeakObject * >( this ) ); 1919 } 1920 else if ( rName.equalsAsciiL( 1921 RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) 1922 { 1923 // Read-only property! 1924 aRet[ n ] <<= lang::IllegalAccessException( 1925 rtl::OUString::createFromAscii( 1926 "Property is read-only!" ), 1927 static_cast< cppu::OWeakObject * >( this ) ); 1928 } 1929 else if ( rName.equalsAsciiL( 1930 RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) 1931 { 1932 // Read-only property! 1933 // (but could be writable, if 'getcontenttype' would be) 1934 aRet[ n ] <<= lang::IllegalAccessException( 1935 rtl::OUString::createFromAscii( 1936 "Property is read-only!" ), 1937 static_cast< cppu::OWeakObject * >( this ) ); 1938 } 1939 if ( rName.equalsAsciiL( 1940 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1941 { 1942 // Read-only property! 1943 aRet[ n ] <<= lang::IllegalAccessException( 1944 rtl::OUString::createFromAscii( 1945 "Property is read-only!" ), 1946 static_cast< cppu::OWeakObject * >( this ) ); 1947 } 1948 else 1949 { 1950 if ( getResourceType( xEnv, xResAccess ) == DAV ) 1951 { 1952 // Property value will be set on server. 1953 ProppatchValue aValue( PROPSET, rName, rValue.Value ); 1954 aProppatchValues.push_back( aValue ); 1955 1956 // remember position within sequence of values (for 1957 // error handling). 1958 aProppatchPropsPositions.push_back( n ); 1959 } 1960 else 1961 { 1962 // Property value will be stored in local property store. 1963 if ( !bTriedToGetAdditonalPropSet && 1964 !xAdditionalPropSet.is() ) 1965 { 1966 xAdditionalPropSet 1967 = getAdditionalPropertySet( sal_False ); 1968 bTriedToGetAdditonalPropSet = sal_True; 1969 } 1970 1971 if ( xAdditionalPropSet.is() ) 1972 { 1973 try 1974 { 1975 uno::Any aOldValue 1976 = xAdditionalPropSet->getPropertyValue( rName ); 1977 if ( aOldValue != rValue.Value ) 1978 { 1979 xAdditionalPropSet->setPropertyValue( 1980 rName, rValue.Value ); 1981 1982 aEvent.PropertyName = rName; 1983 aEvent.OldValue = aOldValue; 1984 aEvent.NewValue = rValue.Value; 1985 1986 aChanges.getArray()[ nChanged ] = aEvent; 1987 nChanged++; 1988 } 1989 } 1990 catch ( beans::UnknownPropertyException const & e ) 1991 { 1992 aRet[ n ] <<= e; 1993 } 1994 catch ( lang::WrappedTargetException const & e ) 1995 { 1996 aRet[ n ] <<= e; 1997 } 1998 catch ( beans::PropertyVetoException const & e ) 1999 { 2000 aRet[ n ] <<= e; 2001 } 2002 catch ( lang::IllegalArgumentException const & e ) 2003 { 2004 aRet[ n ] <<= e; 2005 } 2006 } 2007 else 2008 { 2009 aRet[ n ] <<= uno::Exception( 2010 rtl::OUString::createFromAscii( 2011 "No property set for storing the value!" ), 2012 static_cast< cppu::OWeakObject * >( this ) ); 2013 } 2014 } 2015 } 2016 } 2017 } // for 2018 2019 if ( !bTransient && aProppatchValues.size() ) 2020 { 2021 try 2022 { 2023 // Set property values at server. 2024 xResAccess->PROPPATCH( aProppatchValues, xEnv ); 2025 2026 std::vector< ProppatchValue >::const_iterator it 2027 = aProppatchValues.begin(); 2028 std::vector< ProppatchValue >::const_iterator end 2029 = aProppatchValues.end(); 2030 2031 while ( it != end ) 2032 { 2033 aEvent.PropertyName = (*it).name; 2034 aEvent.OldValue = uno::Any(); // @@@ to expensive to obtain! 2035 aEvent.NewValue = (*it).value; 2036 2037 aChanges.getArray()[ nChanged ] = aEvent; 2038 nChanged++; 2039 2040 ++it; 2041 } 2042 } 2043 catch ( DAVException const & e ) 2044 { 2045 // OSL_ENSURE( sal_False, 2046 // "Content::setPropertyValues - PROPPATCH failed!" ); 2047 2048 #if 1 2049 cancelCommandExecution( e, xEnv ); 2050 // unreachable 2051 #else 2052 // Note: PROPPATCH either sets ALL property values OR NOTHING. 2053 2054 std::vector< sal_Int32 >::const_iterator it 2055 = aProppatchPropsPositions.begin(); 2056 std::vector< sal_Int32 >::const_iterator end 2057 = aProppatchPropsPositions.end(); 2058 2059 while ( it != end ) 2060 { 2061 // Set error. 2062 aRet[ (*it) ] <<= MapDAVException( e, sal_True ); 2063 ++it; 2064 } 2065 #endif 2066 } 2067 } 2068 2069 if ( bExchange ) 2070 { 2071 // Assemble new content identifier... 2072 2073 rtl::OUString aNewURL = getParentURL(); 2074 if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) ) 2075 aNewURL += rtl::OUString::createFromAscii( "/" ); 2076 2077 aNewURL += SerfUri::escapeSegment( aNewTitle ); 2078 2079 uno::Reference< ucb::XContentIdentifier > xNewId 2080 = new ::ucbhelper::ContentIdentifier( xSMgr, aNewURL ); 2081 uno::Reference< ucb::XContentIdentifier > xOldId = xIdentifier; 2082 2083 try 2084 { 2085 SerfUri sourceURI( xOldId->getContentIdentifier() ); 2086 SerfUri targetURI( xNewId->getContentIdentifier() ); 2087 targetURI.SetScheme( sourceURI.GetScheme() ); 2088 2089 xResAccess->MOVE( 2090 sourceURI.GetPath(), targetURI.GetURI(), sal_False, xEnv ); 2091 // @@@ Should check for resources that could not be moved 2092 // (due to source access or target overwrite) and send 2093 // this information through the interaction handler. 2094 2095 // @@@ Existing content should be checked to see if it needs 2096 // to be deleted at the source 2097 2098 // @@@ Existing content should be checked to see if it has 2099 // been overwritten at the target 2100 2101 if ( exchangeIdentity( xNewId ) ) 2102 { 2103 xResAccess->setURL( aNewURL ); 2104 2105 // DAV resources store all additional props on server! 2106 // // Adapt Additional Core Properties. 2107 // renameAdditionalPropertySet( xOldId->getContentIdentifier(), 2108 // xNewId->getContentIdentifier(), 2109 // sal_True ); 2110 } 2111 else 2112 { 2113 // Do not set new title! 2114 aNewTitle = rtl::OUString(); 2115 2116 // Set error . 2117 aRet[ nTitlePos ] <<= uno::Exception( 2118 rtl::OUString::createFromAscii( "Exchange failed!" ), 2119 static_cast< cppu::OWeakObject * >( this ) ); 2120 } 2121 } 2122 catch ( DAVException const & e ) 2123 { 2124 // Do not set new title! 2125 aNewTitle = rtl::OUString(); 2126 2127 // Set error . 2128 aRet[ nTitlePos ] <<= MapDAVException( e, sal_True ); 2129 } 2130 } 2131 2132 if ( aNewTitle.getLength() ) 2133 { 2134 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2135 2136 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); 2137 aEvent.OldValue = uno::makeAny( aOldTitle ); 2138 aEvent.NewValue = uno::makeAny( aNewTitle ); 2139 2140 m_aEscapedTitle = SerfUri::escapeSegment( aNewTitle ); 2141 2142 aChanges.getArray()[ nChanged ] = aEvent; 2143 nChanged++; 2144 } 2145 2146 if ( nChanged > 0 ) 2147 { 2148 aChanges.realloc( nChanged ); 2149 notifyPropertiesChange( aChanges ); 2150 } 2151 2152 { 2153 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2154 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 2155 } 2156 2157 return aRet; 2158 } 2159 2160 //========================================================================= 2161 uno::Any Content::open( 2162 const ucb::OpenCommandArgument2 & rArg, 2163 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2164 throw( uno::Exception ) 2165 { 2166 uno::Any aRet; 2167 2168 sal_Bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) || 2169 ( rArg.Mode == ucb::OpenMode::FOLDERS ) || 2170 ( rArg.Mode == ucb::OpenMode::DOCUMENTS ) ); 2171 if ( bOpenFolder ) 2172 { 2173 if ( isFolder( xEnv ) ) 2174 { 2175 // Open collection. 2176 2177 uno::Reference< ucb::XDynamicResultSet > xSet 2178 = new DynamicResultSet( m_xSMgr, this, rArg, xEnv ); 2179 aRet <<= xSet; 2180 } 2181 else 2182 { 2183 // Error: Not a folder! 2184 2185 rtl::OUStringBuffer aMsg; 2186 aMsg.appendAscii( "Non-folder resource cannot be " 2187 "opened as folder! Wrong Open Mode!" ); 2188 2189 ucbhelper::cancelCommandExecution( 2190 uno::makeAny( 2191 lang::IllegalArgumentException( 2192 aMsg.makeStringAndClear(), 2193 static_cast< cppu::OWeakObject * >( this ), 2194 -1 ) ), 2195 xEnv ); 2196 // Unreachable 2197 } 2198 } 2199 2200 if ( rArg.Sink.is() ) 2201 { 2202 // Open document. 2203 2204 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || 2205 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) 2206 { 2207 // Currently(?) unsupported. 2208 ucbhelper::cancelCommandExecution( 2209 uno::makeAny( 2210 ucb::UnsupportedOpenModeException( 2211 rtl::OUString(), 2212 static_cast< cppu::OWeakObject * >( this ), 2213 sal_Int16( rArg.Mode ) ) ), 2214 xEnv ); 2215 // Unreachable 2216 } 2217 2218 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 2219 uno::Reference< io::XOutputStream > xOut 2220 = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY ); 2221 if ( xOut.is() ) 2222 { 2223 // PUSH: write data 2224 try 2225 { 2226 std::auto_ptr< DAVResourceAccess > xResAccess; 2227 2228 { 2229 osl::MutexGuard aGuard( m_aMutex ); 2230 2231 xResAccess.reset( 2232 new DAVResourceAccess( *m_xResAccess.get() ) ); 2233 } 2234 2235 DAVResource aResource; 2236 std::vector< rtl::OUString > aHeaders; 2237 2238 xResAccess->GET( xOut, aHeaders, aResource, xEnv ); 2239 m_bDidGetOrHead = true; 2240 2241 { 2242 osl::MutexGuard aGuard( m_aMutex ); 2243 2244 // cache headers. 2245 if ( !m_xCachedProps.get()) 2246 m_xCachedProps.reset( 2247 new CachableContentProperties( aResource ) ); 2248 else 2249 m_xCachedProps->addProperties( aResource ); 2250 2251 m_xResAccess.reset( 2252 new DAVResourceAccess( *xResAccess.get() ) ); 2253 } 2254 } 2255 catch ( DAVException const & e ) 2256 { 2257 cancelCommandExecution( e, xEnv ); 2258 // Unreachable 2259 } 2260 } 2261 else 2262 { 2263 uno::Reference< io::XActiveDataSink > xDataSink 2264 = uno::Reference< io::XActiveDataSink >( rArg.Sink, 2265 uno::UNO_QUERY ); 2266 if ( xDataSink.is() ) 2267 { 2268 // PULL: wait for client read 2269 try 2270 { 2271 std::auto_ptr< DAVResourceAccess > xResAccess; 2272 { 2273 osl::MutexGuard aGuard( m_aMutex ); 2274 2275 xResAccess.reset( 2276 new DAVResourceAccess( *m_xResAccess.get() ) ); 2277 } 2278 2279 // fill inputsream sync; return if all data present 2280 DAVResource aResource; 2281 std::vector< rtl::OUString > aHeaders; 2282 2283 uno::Reference< io::XInputStream > xIn 2284 = xResAccess->GET( aHeaders, aResource, xEnv ); 2285 m_bDidGetOrHead = true; 2286 2287 { 2288 osl::MutexGuard aGuard( m_aMutex ); 2289 2290 // cache headers. 2291 if ( !m_xCachedProps.get()) 2292 m_xCachedProps.reset( 2293 new CachableContentProperties( aResource ) ); 2294 else 2295 m_xCachedProps->addProperties( 2296 aResource.properties ); 2297 2298 m_xResAccess.reset( 2299 new DAVResourceAccess( *xResAccess.get() ) ); 2300 } 2301 2302 xDataSink->setInputStream( xIn ); 2303 } 2304 catch ( DAVException const & e ) 2305 { 2306 cancelCommandExecution( e, xEnv ); 2307 // Unreachable 2308 } 2309 } 2310 else 2311 { 2312 // Note: aOpenCommand.Sink may contain an XStream 2313 // implementation. Support for this type of 2314 // sink is optional... 2315 ucbhelper::cancelCommandExecution( 2316 uno::makeAny( 2317 ucb::UnsupportedDataSinkException( 2318 rtl::OUString(), 2319 static_cast< cppu::OWeakObject * >( this ), 2320 rArg.Sink ) ), 2321 xEnv ); 2322 // Unreachable 2323 } 2324 } 2325 } 2326 2327 return aRet; 2328 } 2329 2330 //========================================================================= 2331 void Content::post( 2332 const ucb::PostCommandArgument2 & rArg, 2333 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2334 throw( uno::Exception ) 2335 { 2336 uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY ); 2337 if ( xSink.is() ) 2338 { 2339 try 2340 { 2341 std::auto_ptr< DAVResourceAccess > xResAccess; 2342 { 2343 osl::MutexGuard aGuard( m_aMutex ); 2344 xResAccess.reset( 2345 new DAVResourceAccess( *m_xResAccess.get() ) ); 2346 } 2347 2348 uno::Reference< io::XInputStream > xResult 2349 = xResAccess->POST( rArg.MediaType, 2350 rArg.Referer, 2351 rArg.Source, 2352 xEnv ); 2353 2354 { 2355 osl::MutexGuard aGuard( m_aMutex ); 2356 m_xResAccess.reset( 2357 new DAVResourceAccess( *xResAccess.get() ) ); 2358 } 2359 2360 xSink->setInputStream( xResult ); 2361 } 2362 catch ( DAVException const & e ) 2363 { 2364 cancelCommandExecution( e, xEnv, sal_True ); 2365 // Unreachable 2366 } 2367 } 2368 else 2369 { 2370 uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY ); 2371 if ( xResult.is() ) 2372 { 2373 try 2374 { 2375 std::auto_ptr< DAVResourceAccess > xResAccess; 2376 { 2377 osl::MutexGuard aGuard( m_aMutex ); 2378 xResAccess.reset( 2379 new DAVResourceAccess( *m_xResAccess.get() ) ); 2380 } 2381 2382 xResAccess->POST( rArg.MediaType, 2383 rArg.Referer, 2384 rArg.Source, 2385 xResult, 2386 xEnv ); 2387 2388 { 2389 osl::MutexGuard aGuard( m_aMutex ); 2390 m_xResAccess.reset( 2391 new DAVResourceAccess( *xResAccess.get() ) ); 2392 } 2393 } 2394 catch ( DAVException const & e ) 2395 { 2396 cancelCommandExecution( e, xEnv, sal_True ); 2397 // Unreachable 2398 } 2399 } 2400 else 2401 { 2402 ucbhelper::cancelCommandExecution( 2403 uno::makeAny( 2404 ucb::UnsupportedDataSinkException( 2405 rtl::OUString(), 2406 static_cast< cppu::OWeakObject * >( this ), 2407 rArg.Sink ) ), 2408 xEnv ); 2409 // Unreachable 2410 } 2411 } 2412 } 2413 2414 //========================================================================= 2415 void Content::queryChildren( ContentRefList& rChildren ) 2416 { 2417 // Obtain a list with a snapshot of all currently instanciated contents 2418 // from provider and extract the contents which are direct children 2419 // of this content. 2420 2421 ::ucbhelper::ContentRefList aAllContents; 2422 m_xProvider->queryExistingContents( aAllContents ); 2423 2424 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 2425 sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); 2426 2427 if ( nURLPos != ( aURL.getLength() - 1 ) ) 2428 { 2429 // No trailing slash found. Append. 2430 aURL += rtl::OUString::createFromAscii( "/" ); 2431 } 2432 2433 sal_Int32 nLen = aURL.getLength(); 2434 2435 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); 2436 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); 2437 2438 while ( it != end ) 2439 { 2440 ::ucbhelper::ContentImplHelperRef xChild = (*it); 2441 rtl::OUString aChildURL 2442 = xChild->getIdentifier()->getContentIdentifier(); 2443 2444 // Is aURL a prefix of aChildURL? 2445 if ( ( aChildURL.getLength() > nLen ) && 2446 ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) 2447 { 2448 sal_Int32 nPos = nLen; 2449 nPos = aChildURL.indexOf( '/', nPos ); 2450 2451 if ( ( nPos == -1 ) || 2452 ( nPos == ( aChildURL.getLength() - 1 ) ) ) 2453 { 2454 // No further slashes / only a final slash. It's a child! 2455 rChildren.push_back( 2456 ::http_dav_ucp::Content::ContentRef( 2457 static_cast< ::http_dav_ucp::Content * >( 2458 xChild.get() ) ) ); 2459 } 2460 } 2461 ++it; 2462 } 2463 } 2464 2465 //========================================================================= 2466 void Content::insert( 2467 const uno::Reference< io::XInputStream > & xInputStream, 2468 sal_Bool bReplaceExisting, 2469 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 2470 throw( uno::Exception ) 2471 { 2472 sal_Bool bTransient, bCollection; 2473 rtl::OUString aEscapedTitle; 2474 std::auto_ptr< DAVResourceAccess > xResAccess; 2475 2476 { 2477 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2478 2479 bTransient = m_bTransient; 2480 bCollection = m_bCollection; 2481 aEscapedTitle = m_aEscapedTitle; 2482 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 2483 } 2484 2485 // Check, if all required properties are present. 2486 2487 if ( aEscapedTitle.getLength() == 0 ) 2488 { 2489 OSL_ENSURE( sal_False, "Content::insert - Title missing!" ); 2490 2491 uno::Sequence< rtl::OUString > aProps( 1 ); 2492 aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" ); 2493 ucbhelper::cancelCommandExecution( 2494 uno::makeAny( ucb::MissingPropertiesException( 2495 rtl::OUString(), 2496 static_cast< cppu::OWeakObject * >( this ), 2497 aProps ) ), 2498 Environment ); 2499 // Unreachable 2500 } 2501 2502 if ( !bReplaceExisting ) 2503 { 2504 /* [RFC 2616] - HTTP 2505 2506 The PUT method requests that the enclosed entity be stored under the 2507 supplied Request-URI. If the Request-URI refers to an already 2508 existing resource, the enclosed entity SHOULD be considered as a 2509 modified version of the one residing on the origin server. 2510 */ 2511 2512 /* [RFC 2518] - WebDAV 2513 2514 MKCOL creates a new collection resource at the location specified by 2515 the Request-URI. If the resource identified by the Request-URI is 2516 non-null then the MKCOL MUST fail. 2517 */ 2518 2519 // ==> Complain on PUT, continue on MKCOL. 2520 if ( !bTransient || ( bTransient && !bCollection ) ) 2521 { 2522 #undef ERROR 2523 ucb::UnsupportedNameClashException aEx( 2524 rtl::OUString::createFromAscii( "Unable to write without overwrite!" ), 2525 static_cast< cppu::OWeakObject * >( this ), 2526 ucb::NameClash::ERROR ); 2527 2528 uno::Reference< task::XInteractionHandler > xIH; 2529 2530 if ( Environment.is() ) 2531 xIH = Environment->getInteractionHandler(); 2532 2533 if ( xIH.is() ) 2534 { 2535 uno::Any aExAsAny( uno::makeAny( aEx ) ); 2536 2537 rtl::Reference< ucbhelper::SimpleInteractionRequest > xRequest 2538 = new ucbhelper::SimpleInteractionRequest( 2539 aExAsAny, 2540 ucbhelper::CONTINUATION_APPROVE 2541 | ucbhelper::CONTINUATION_DISAPPROVE ); 2542 xIH->handle( xRequest.get() ); 2543 2544 const sal_Int32 nResp = xRequest->getResponse(); 2545 2546 switch ( nResp ) 2547 { 2548 case ucbhelper::CONTINUATION_UNKNOWN: 2549 // Not handled; throw. 2550 throw aEx; 2551 // break; 2552 2553 case ucbhelper::CONTINUATION_APPROVE: 2554 // Continue -> Overwrite. 2555 bReplaceExisting = sal_True; 2556 break; 2557 2558 case ucbhelper::CONTINUATION_DISAPPROVE: 2559 // Abort. 2560 throw ucb::CommandFailedException( 2561 rtl::OUString(), 2562 uno::Reference< uno::XInterface >(), 2563 aExAsAny ); 2564 // break; 2565 2566 default: 2567 OSL_ENSURE( sal_False, 2568 "Content::insert - " 2569 "Unknown interaction selection!" ); 2570 throw ucb::CommandFailedException( 2571 rtl::OUString::createFromAscii( 2572 "Unknown interaction selection!" ), 2573 uno::Reference< uno::XInterface >(), 2574 aExAsAny ); 2575 // break; 2576 } 2577 } 2578 else 2579 { 2580 // No IH; throw. 2581 throw aEx; 2582 } 2583 } 2584 } 2585 2586 if ( bTransient ) 2587 { 2588 // Assemble new content identifier... 2589 rtl::OUString aURL = getParentURL(); 2590 if ( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ) ) 2591 aURL += rtl::OUString::createFromAscii( "/" ); 2592 2593 aURL += aEscapedTitle; 2594 2595 try 2596 { 2597 xResAccess->setURL( aURL ); 2598 2599 if ( bCollection ) 2600 xResAccess->MKCOL( Environment ); 2601 else 2602 xResAccess->PUT( xInputStream, Environment ); 2603 } 2604 catch ( DAVException const & except ) 2605 { 2606 if ( bCollection ) 2607 { 2608 if ( except.getStatus() == SC_METHOD_NOT_ALLOWED ) 2609 { 2610 // [RFC 2518] - WebDAV 2611 // 405 (Method Not Allowed) - MKCOL can only be 2612 // executed on a deleted/non-existent resource. 2613 2614 if ( bReplaceExisting ) 2615 { 2616 // Destroy old resource. 2617 try 2618 { 2619 xResAccess->DESTROY( Environment ); 2620 } 2621 catch ( DAVException const & e ) 2622 { 2623 cancelCommandExecution( e, Environment, sal_True ); 2624 // Unreachable 2625 } 2626 2627 // Insert (recursion!). 2628 insert( xInputStream, bReplaceExisting, Environment ); 2629 2630 { 2631 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2632 m_xResAccess.reset( 2633 new DAVResourceAccess( *xResAccess.get() ) ); 2634 } 2635 2636 // Success! 2637 return; 2638 } 2639 else 2640 { 2641 rtl::OUString aTitle; 2642 try 2643 { 2644 SerfUri aURI( aURL ); 2645 aTitle = aURI.GetPathBaseNameUnescaped(); 2646 } 2647 catch ( DAVException const & ) 2648 { 2649 } 2650 2651 ucbhelper::cancelCommandExecution( 2652 uno::makeAny( 2653 ucb::NameClashException( 2654 rtl::OUString(), 2655 static_cast< cppu::OWeakObject * >( this ), 2656 task::InteractionClassification_ERROR, 2657 aTitle ) ), 2658 Environment ); 2659 // Unreachable 2660 } 2661 } 2662 } 2663 2664 cancelCommandExecution( except, Environment, sal_True ); 2665 // Unreachable 2666 } 2667 2668 { 2669 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2670 m_xIdentifier 2671 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); 2672 } 2673 2674 inserted(); 2675 2676 { 2677 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2678 m_bTransient = sal_False; 2679 } 2680 } 2681 else 2682 { 2683 if ( !xInputStream.is() ) 2684 { 2685 ucbhelper::cancelCommandExecution( 2686 uno::makeAny( 2687 ucb::MissingInputStreamException( 2688 rtl::OUString(), 2689 static_cast< cppu::OWeakObject * >( this ) ) ), 2690 Environment ); 2691 // Unreachable 2692 } 2693 2694 try 2695 { 2696 xResAccess->PUT( xInputStream, Environment ); 2697 } 2698 catch ( DAVException const & e ) 2699 { 2700 cancelCommandExecution( e, Environment, sal_True ); 2701 // Unreachable 2702 } 2703 } 2704 2705 { 2706 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2707 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 2708 } 2709 } 2710 2711 //========================================================================= 2712 void Content::transfer( 2713 const ucb::TransferInfo & rArgs, 2714 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 2715 throw( uno::Exception ) 2716 { 2717 uno::Reference< lang::XMultiServiceFactory > xSMgr; 2718 uno::Reference< ucb::XContentIdentifier > xIdentifier; 2719 uno::Reference< ucb::XContentProvider > xProvider; 2720 std::auto_ptr< DAVResourceAccess > xResAccess; 2721 2722 { 2723 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2724 2725 xSMgr.set( m_xSMgr ); 2726 xIdentifier.set( m_xIdentifier ); 2727 xProvider.set( m_xProvider.get() ); 2728 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 2729 } 2730 2731 rtl::OUString aTargetURI; 2732 try 2733 { 2734 SerfUri sourceURI( rArgs.SourceURL ); 2735 SerfUri targetURI( xIdentifier->getContentIdentifier() ); 2736 aTargetURI = targetURI.GetPathBaseNameUnescaped(); 2737 2738 // Check source's and target's URL scheme 2739 // 2740 const rtl::OUString aScheme = sourceURI.GetScheme().toAsciiLowerCase(); 2741 if ( aScheme.equalsAsciiL( 2742 RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) ) 2743 { 2744 sourceURI.SetScheme( 2745 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2746 } 2747 else if ( aScheme.equalsAsciiL( 2748 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) ) 2749 { 2750 sourceURI.SetScheme( 2751 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2752 } 2753 else if ( aScheme.equalsAsciiL( 2754 RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) ) 2755 { 2756 sourceURI.SetScheme( 2757 rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) ); 2758 } 2759 else 2760 { 2761 if ( !aScheme.equalsAsciiL( 2762 RTL_CONSTASCII_STRINGPARAM( HTTP_URL_SCHEME ) ) && 2763 !aScheme.equalsAsciiL( 2764 RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME ) ) ) 2765 { 2766 ucbhelper::cancelCommandExecution( 2767 uno::makeAny( 2768 ucb::InteractiveBadTransferURLException( 2769 rtl::OUString::createFromAscii( 2770 "Unsupported URL scheme!" ), 2771 static_cast< cppu::OWeakObject * >( this ) ) ), 2772 Environment ); 2773 // Unreachable 2774 } 2775 } 2776 2777 if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL( 2778 RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) ) 2779 targetURI.SetScheme( 2780 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2781 else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL( 2782 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) ) 2783 targetURI.SetScheme( 2784 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2785 2786 // @@@ This implementation of 'transfer' only works 2787 // if the source and target are located at same host. 2788 // (Neon does not support cross-server copy/move) 2789 2790 // Check for same host 2791 // 2792 if ( sourceURI.GetHost().getLength() && 2793 ( sourceURI.GetHost() != targetURI.GetHost() ) ) 2794 { 2795 ucbhelper::cancelCommandExecution( 2796 uno::makeAny( ucb::InteractiveBadTransferURLException( 2797 rtl::OUString::createFromAscii( 2798 "Different hosts!" ), 2799 static_cast< cppu::OWeakObject * >( this ) ) ), 2800 Environment ); 2801 // Unreachable 2802 } 2803 2804 rtl::OUString aTitle = rArgs.NewTitle; 2805 2806 if ( !aTitle.getLength() ) 2807 aTitle = sourceURI.GetPathBaseNameUnescaped(); 2808 2809 if ( aTitle.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "/" ) ) ) 2810 { 2811 // kso: ??? 2812 aTitle = rtl::OUString(); 2813 } 2814 2815 targetURI.AppendPath( aTitle ); 2816 2817 rtl::OUString aTargetURL = xIdentifier->getContentIdentifier(); 2818 if ( ( aTargetURL.lastIndexOf( '/' ) + 1 ) 2819 != aTargetURL.getLength() ) 2820 aTargetURL += rtl::OUString::createFromAscii( "/" ); 2821 2822 aTargetURL += aTitle; 2823 2824 uno::Reference< ucb::XContentIdentifier > xTargetId 2825 = new ::ucbhelper::ContentIdentifier( xSMgr, aTargetURL ); 2826 2827 DAVResourceAccess aSourceAccess( xSMgr, 2828 xResAccess->getSessionFactory(), 2829 sourceURI.GetURI() ); 2830 2831 if ( rArgs.MoveData == sal_True ) 2832 { 2833 uno::Reference< ucb::XContentIdentifier > xId 2834 = new ::ucbhelper::ContentIdentifier( xSMgr, rArgs.SourceURL ); 2835 2836 // Note: The static cast is okay here, because its sure that 2837 // xProvider is always the WebDAVContentProvider. 2838 rtl::Reference< Content > xSource 2839 = static_cast< Content * >( 2840 xProvider->queryContent( xId ).get() ); 2841 2842 // [RFC 2518] - WebDAV 2843 // If a resource exists at the destination and the Overwrite 2844 // header is "T" then prior to performing the move the server 2845 // MUST perform a DELETE with "Depth: infinity" on the 2846 // destination resource. If the Overwrite header is set to 2847 // "F" then the operation will fail. 2848 2849 aSourceAccess.MOVE( sourceURI.GetPath(), 2850 targetURI.GetURI(), 2851 rArgs.NameClash 2852 == ucb::NameClash::OVERWRITE, 2853 Environment ); 2854 2855 if ( xSource.is() ) 2856 { 2857 // Propagate destruction to listeners. 2858 xSource->destroy( sal_True ); 2859 } 2860 2861 // DAV resources store all additional props on server! 2862 // // Rename own and all children's Additional Core Properties. 2863 // renameAdditionalPropertySet( xId->getContentIdentifier(), 2864 // xTargetId->getContentIdentifier(), 2865 // sal_True ); 2866 } 2867 else 2868 { 2869 // [RFC 2518] - WebDAV 2870 // If a resource exists at the destination and the Overwrite 2871 // header is "T" then prior to performing the copy the server 2872 // MUST perform a DELETE with "Depth: infinity" on the 2873 // destination resource. If the Overwrite header is set to 2874 // "F" then the operation will fail. 2875 2876 aSourceAccess.COPY( sourceURI.GetPath(), 2877 targetURI.GetURI(), 2878 rArgs.NameClash 2879 == ucb::NameClash::OVERWRITE, 2880 Environment ); 2881 2882 // DAV resources store all additional props on server! 2883 // // Copy own and all children's Additional Core Properties. 2884 // copyAdditionalPropertySet( xId->getContentIdentifier(), 2885 // xTargetId->getContentIdentifier(), 2886 // sal_True ); 2887 } 2888 2889 // Note: The static cast is okay here, because its sure that 2890 // xProvider is always the WebDAVContentProvider. 2891 rtl::Reference< Content > xTarget 2892 = static_cast< Content * >( 2893 xProvider->queryContent( xTargetId ).get() ); 2894 2895 // Announce transfered content in its new folder. 2896 xTarget->inserted(); 2897 } 2898 catch ( ucb::IllegalIdentifierException const & ) 2899 { 2900 // queryContent 2901 } 2902 catch ( DAVException const & e ) 2903 { 2904 // [RFC 2518] - WebDAV 2905 // 412 (Precondition Failed) - The server was unable to maintain 2906 // the liveness of the properties listed in the propertybehavior 2907 // XML element or the Overwrite header is "F" and the state of 2908 // the destination resource is non-null. 2909 2910 if ( e.getStatus() == SC_PRECONDITION_FAILED ) 2911 { 2912 switch ( rArgs.NameClash ) 2913 { 2914 case 0/*ucb::NameClash::ERROR*/: 2915 { 2916 ucbhelper::cancelCommandExecution( 2917 uno::makeAny( 2918 ucb::NameClashException( 2919 rtl::OUString(), 2920 static_cast< cppu::OWeakObject * >( this ), 2921 task::InteractionClassification_ERROR, 2922 aTargetURI ) ), 2923 Environment ); 2924 // Unreachable 2925 } 2926 2927 case ucb::NameClash::OVERWRITE: 2928 break; 2929 2930 case ucb::NameClash::KEEP: // deprecated 2931 case ucb::NameClash::RENAME: 2932 case ucb::NameClash::ASK: 2933 default: 2934 { 2935 ucbhelper::cancelCommandExecution( 2936 uno::makeAny( 2937 ucb::UnsupportedNameClashException( 2938 rtl::OUString(), 2939 static_cast< cppu::OWeakObject * >( this ), 2940 rArgs.NameClash ) ), 2941 Environment ); 2942 // Unreachable 2943 } 2944 } 2945 } 2946 2947 cancelCommandExecution( e, Environment, sal_True ); 2948 // Unreachable 2949 } 2950 2951 { 2952 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2953 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 2954 } 2955 } 2956 2957 //========================================================================= 2958 void Content::destroy( sal_Bool bDeletePhysical ) 2959 throw( uno::Exception ) 2960 { 2961 // @@@ take care about bDeletePhysical -> trashcan support 2962 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 2963 2964 uno::Reference< ucb::XContent > xThis = this; 2965 2966 deleted(); 2967 2968 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2969 2970 // Process instanciated children... 2971 2972 ::http_dav_ucp::Content::ContentRefList aChildren; 2973 queryChildren( aChildren ); 2974 2975 ContentRefList::const_iterator it = aChildren.begin(); 2976 ContentRefList::const_iterator end = aChildren.end(); 2977 2978 while ( it != end ) 2979 { 2980 (*it)->destroy( bDeletePhysical ); 2981 ++it; 2982 } 2983 } 2984 2985 //========================================================================= 2986 bool Content::supportsExclusiveWriteLock( 2987 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 2988 { 2989 if ( getResourceType( Environment ) == DAV ) 2990 { 2991 if ( m_xCachedProps.get() ) 2992 { 2993 uno::Sequence< ucb::LockEntry > aSupportedLocks; 2994 if ( m_xCachedProps->getValue( DAVProperties::SUPPORTEDLOCK ) 2995 >>= aSupportedLocks ) 2996 { 2997 for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n ) 2998 { 2999 if ( aSupportedLocks[ n ].Scope 3000 == ucb::LockScope_EXCLUSIVE && 3001 aSupportedLocks[ n ].Type 3002 == ucb::LockType_WRITE ) 3003 return true; 3004 } 3005 } 3006 } 3007 } 3008 return false; 3009 } 3010 3011 //========================================================================= 3012 void Content::lock( 3013 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 3014 throw( uno::Exception ) 3015 { 3016 try 3017 { 3018 std::auto_ptr< DAVResourceAccess > xResAccess; 3019 { 3020 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3021 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 3022 } 3023 3024 uno::Any aOwnerAny; 3025 aOwnerAny 3026 <<= rtl::OUString::createFromAscii( "http://ucb.openoffice.org" ); 3027 3028 ucb::Lock aLock( 3029 ucb::LockScope_EXCLUSIVE, 3030 ucb::LockType_WRITE, 3031 ucb::LockDepth_ZERO, 3032 aOwnerAny, 3033 180, // lock timeout in secs 3034 //-1, // infinite lock 3035 uno::Sequence< ::rtl::OUString >() ); 3036 3037 xResAccess->LOCK( aLock, Environment ); 3038 3039 { 3040 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3041 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 3042 } 3043 } 3044 catch ( DAVException const & e ) 3045 { 3046 cancelCommandExecution( e, Environment, sal_False ); 3047 // Unreachable 3048 } 3049 } 3050 3051 //========================================================================= 3052 void Content::unlock( 3053 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 3054 throw( uno::Exception ) 3055 { 3056 try 3057 { 3058 std::auto_ptr< DAVResourceAccess > xResAccess; 3059 { 3060 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3061 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 3062 } 3063 3064 xResAccess->UNLOCK( Environment ); 3065 3066 { 3067 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3068 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 3069 } 3070 } 3071 catch ( DAVException const & e ) 3072 { 3073 cancelCommandExecution( e, Environment, sal_False ); 3074 // Unreachable 3075 } 3076 } 3077 3078 //========================================================================= 3079 sal_Bool Content::exchangeIdentity( 3080 const uno::Reference< ucb::XContentIdentifier >& xNewId ) 3081 { 3082 if ( !xNewId.is() ) 3083 return sal_False; 3084 3085 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 3086 3087 uno::Reference< ucb::XContent > xThis = this; 3088 3089 // Already persistent? 3090 if ( m_bTransient ) 3091 { 3092 OSL_ENSURE( sal_False, "Content::exchangeIdentity - Not persistent!" ); 3093 return sal_False; 3094 } 3095 3096 // Exchange own identitity. 3097 3098 // Fail, if a content with given id already exists. 3099 // if ( !hasData( xNewId ) ) 3100 { 3101 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); 3102 3103 aGuard.clear(); 3104 if ( exchange( xNewId ) ) 3105 { 3106 // Process instanciated children... 3107 3108 ContentRefList aChildren; 3109 queryChildren( aChildren ); 3110 3111 ContentRefList::const_iterator it = aChildren.begin(); 3112 ContentRefList::const_iterator end = aChildren.end(); 3113 3114 while ( it != end ) 3115 { 3116 ContentRef xChild = (*it); 3117 3118 // Create new content identifier for the child... 3119 uno::Reference< ucb::XContentIdentifier > 3120 xOldChildId = xChild->getIdentifier(); 3121 rtl::OUString aOldChildURL 3122 = xOldChildId->getContentIdentifier(); 3123 rtl::OUString aNewChildURL 3124 = aOldChildURL.replaceAt( 3125 0, 3126 aOldURL.getLength(), 3127 xNewId->getContentIdentifier() ); 3128 uno::Reference< ucb::XContentIdentifier > xNewChildId 3129 = new ::ucbhelper::ContentIdentifier( 3130 m_xSMgr, aNewChildURL ); 3131 3132 if ( !xChild->exchangeIdentity( xNewChildId ) ) 3133 return sal_False; 3134 3135 ++it; 3136 } 3137 return sal_True; 3138 } 3139 } 3140 3141 OSL_ENSURE( sal_False, 3142 "Content::exchangeIdentity - " 3143 "Panic! Cannot exchange identity!" ); 3144 return sal_False; 3145 } 3146 3147 //========================================================================= 3148 sal_Bool Content::isFolder( 3149 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 3150 throw( uno::Exception ) 3151 { 3152 { 3153 osl::MutexGuard aGuard( m_aMutex ); 3154 3155 if ( m_bTransient ) 3156 return m_bCollection; 3157 } 3158 3159 uno::Sequence< beans::Property > aProperties( 1 ); 3160 aProperties[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); 3161 aProperties[ 0 ].Handle = -1; 3162 uno::Reference< sdbc::XRow > xRow( getPropertyValues( aProperties, xEnv ) ); 3163 if ( xRow.is() ) 3164 { 3165 try 3166 { 3167 return xRow->getBoolean( 1 ); 3168 } 3169 catch ( sdbc::SQLException const & ) 3170 { 3171 } 3172 } 3173 3174 return sal_False; 3175 } 3176 3177 //========================================================================= 3178 uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) 3179 { 3180 // Map DAVException... 3181 uno::Any aException; 3182 3183 rtl::OUString aURL; 3184 if ( m_bTransient ) 3185 { 3186 aURL = getParentURL(); 3187 if ( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ) ) 3188 aURL += rtl::OUString::createFromAscii( "/" ); 3189 3190 aURL += m_aEscapedTitle; 3191 } 3192 else 3193 { 3194 aURL = m_xIdentifier->getContentIdentifier(); 3195 } 3196 3197 switch ( e.getStatus() ) 3198 { 3199 case SC_NOT_FOUND: 3200 { 3201 uno::Sequence< uno::Any > aArgs( 1 ); 3202 aArgs[ 0 ] <<= beans::PropertyValue( 3203 rtl::OUString::createFromAscii("Uri"), -1, 3204 uno::makeAny(aURL), 3205 beans::PropertyState_DIRECT_VALUE); 3206 3207 aException <<= 3208 ucb::InteractiveAugmentedIOException( 3209 rtl::OUString::createFromAscii( "Not found!" ), 3210 static_cast< cppu::OWeakObject * >( this ), 3211 task::InteractionClassification_ERROR, 3212 ucb::IOErrorCode_NOT_EXISTING, 3213 aArgs ); 3214 return aException; 3215 } 3216 default: 3217 break; 3218 } 3219 3220 switch ( e.getError() ) 3221 { 3222 case DAVException::DAV_HTTP_ERROR: 3223 { 3224 if ( bWrite ) 3225 aException <<= 3226 ucb::InteractiveNetworkWriteException( 3227 e.getData(), 3228 static_cast< cppu::OWeakObject * >( this ), 3229 task::InteractionClassification_ERROR, 3230 e.getData() ); 3231 else 3232 aException <<= 3233 ucb::InteractiveNetworkReadException( 3234 e.getData(), 3235 static_cast< cppu::OWeakObject * >( this ), 3236 task::InteractionClassification_ERROR, 3237 e.getData() ); 3238 break; 3239 } 3240 3241 case DAVException::DAV_HTTP_LOOKUP: 3242 aException <<= 3243 ucb::InteractiveNetworkResolveNameException( 3244 rtl::OUString(), 3245 static_cast< cppu::OWeakObject * >( this ), 3246 task::InteractionClassification_ERROR, 3247 e.getData() ); 3248 break; 3249 3250 // @@@ No matching InteractiveNetwork*Exception 3251 // case DAVException::DAV_HTTP_AUTH: 3252 // break; 3253 3254 // @@@ No matching InteractiveNetwork*Exception 3255 // case DAVException::DAV_HTTP_AUTHPROXY: 3256 // break; 3257 3258 case DAVException::DAV_HTTP_CONNECT: 3259 aException <<= 3260 ucb::InteractiveNetworkConnectException( 3261 rtl::OUString(), 3262 static_cast< cppu::OWeakObject * >( this ), 3263 task::InteractionClassification_ERROR, 3264 e.getData() ); 3265 break; 3266 3267 // @@@ No matching InteractiveNetwork*Exception 3268 // case DAVException::DAV_HTTP_TIMEOUT: 3269 // break; 3270 3271 // @@@ No matching InteractiveNetwork*Exception 3272 // case DAVException::DAV_HTTP_REDIRECT: 3273 // break; 3274 3275 // @@@ No matching InteractiveNetwork*Exception 3276 // case DAVException::DAV_SESSION_CREATE: 3277 // break; 3278 3279 case DAVException::DAV_INVALID_ARG: 3280 aException <<= 3281 lang::IllegalArgumentException( 3282 rtl::OUString(), 3283 static_cast< cppu::OWeakObject * >( this ), 3284 -1 ); 3285 break; 3286 3287 case DAVException::DAV_LOCKED: 3288 #if 1 3289 aException <<= 3290 ucb::InteractiveLockingLockedException( 3291 rtl::OUString::createFromAscii( "Locked!" ), 3292 static_cast< cppu::OWeakObject * >( this ), 3293 task::InteractionClassification_ERROR, 3294 aURL, 3295 sal_False ); // not SelfOwned 3296 #else 3297 { 3298 uno::Sequence< uno::Any > aArgs( 1 ); 3299 aArgs[ 0 ] <<= beans::PropertyValue( 3300 rtl::OUString::createFromAscii("Uri"), -1, 3301 uno::makeAny(aURL), 3302 beans::PropertyState_DIRECT_VALUE); 3303 3304 aException <<= 3305 ucb::InteractiveAugmentedIOException( 3306 rtl::OUString::createFromAscii( "Locked!" ), 3307 static_cast< cppu::OWeakObject * >( this ), 3308 task::InteractionClassification_ERROR, 3309 ucb::IOErrorCode_LOCKING_VIOLATION, 3310 aArgs ); 3311 } 3312 #endif 3313 break; 3314 3315 case DAVException::DAV_LOCKED_SELF: 3316 aException <<= 3317 ucb::InteractiveLockingLockedException( 3318 rtl::OUString::createFromAscii( "Locked (self)!" ), 3319 static_cast< cppu::OWeakObject * >( this ), 3320 task::InteractionClassification_ERROR, 3321 aURL, 3322 sal_True ); // SelfOwned 3323 break; 3324 3325 case DAVException::DAV_NOT_LOCKED: 3326 aException <<= 3327 ucb::InteractiveLockingNotLockedException( 3328 rtl::OUString::createFromAscii( "Not locked!" ), 3329 static_cast< cppu::OWeakObject * >( this ), 3330 task::InteractionClassification_ERROR, 3331 aURL ); 3332 break; 3333 3334 case DAVException::DAV_LOCK_EXPIRED: 3335 aException <<= 3336 ucb::InteractiveLockingLockExpiredException( 3337 rtl::OUString::createFromAscii( "Lock expired!" ), 3338 static_cast< cppu::OWeakObject * >( this ), 3339 task::InteractionClassification_ERROR, 3340 aURL ); 3341 break; 3342 3343 default: 3344 aException <<= 3345 ucb::InteractiveNetworkGeneralException( 3346 rtl::OUString(), 3347 static_cast< cppu::OWeakObject * >( this ), 3348 task::InteractionClassification_ERROR ); 3349 break; 3350 } 3351 3352 return aException; 3353 } 3354 3355 // #i124421# force the availability of type_info symbols for exceptions 3356 // that used to be passed around in uno::Any variables and thrown later 3357 void ucb_dummyThrower( int i) { 3358 switch( i) { 3359 case 10: throw ucb::InteractiveNetworkGeneralException(); 3360 case 11: throw ucb::InteractiveAugmentedIOException(); 3361 case 12: throw ucb::InteractiveNetworkGeneralException(); 3362 case 13: throw ucb::InteractiveNetworkWriteException(); 3363 case 14: throw ucb::InteractiveNetworkReadException(); 3364 case 15: throw ucb::InteractiveNetworkConnectException(); 3365 case 16: throw ucb::InteractiveLockingLockedException(); 3366 case 17: throw ucb::InteractiveLockingNotLockedException(); 3367 case 18: throw ucb::InteractiveNetworkGeneralException(); 3368 case 19: throw ucb::InteractiveLockingLockExpiredException(); 3369 } 3370 } 3371 3372 //========================================================================= 3373 // static 3374 bool Content::shouldAccessNetworkAfterException( const DAVException & e ) 3375 { 3376 if ( ( e.getStatus() == SC_NOT_FOUND ) || 3377 ( e.getError() == DAVException::DAV_HTTP_LOOKUP ) || 3378 ( e.getError() == DAVException::DAV_HTTP_CONNECT ) || 3379 ( e.getError() == DAVException::DAV_HTTP_AUTH ) || 3380 ( e.getError() == DAVException::DAV_HTTP_AUTHPROXY ) ) 3381 return false; 3382 3383 return true; 3384 } 3385 3386 //========================================================================= 3387 void Content::cancelCommandExecution( 3388 const DAVException & e, 3389 const uno::Reference< ucb::XCommandEnvironment > & xEnv, 3390 sal_Bool bWrite /* = sal_False */ ) 3391 throw ( uno::Exception ) 3392 { 3393 ucbhelper::cancelCommandExecution( MapDAVException( e, bWrite ), xEnv ); 3394 // Unreachable 3395 } 3396 3397 //========================================================================= 3398 const rtl::OUString 3399 Content::getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ) 3400 { 3401 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3402 3403 // First, try to obtain value of response header "Content-Location". 3404 if ( m_xCachedProps.get() ) 3405 { 3406 rtl::OUString aLocation; 3407 m_xCachedProps->getValue( rtl::OUString( 3408 RTL_CONSTASCII_USTRINGPARAM( 3409 "Content-Location" ) ) ) >>= aLocation; 3410 if ( aLocation.getLength() ) 3411 { 3412 try 3413 { 3414 // Do not use m_xIdentifier->getContentIdentifier() because it 3415 // for example does not reflect redirects applied to requests 3416 // done using the original URI but m_xResAccess' URI does. 3417 return rtl::Uri::convertRelToAbs( rResAccess->getURL(), 3418 aLocation ); 3419 } 3420 catch ( rtl::MalformedUriException const & ) 3421 { 3422 } 3423 } 3424 } 3425 3426 return rtl::OUString( rResAccess->getURL() ); 3427 } 3428 3429 //========================================================================= 3430 const Content::ResourceType & Content::getResourceType( 3431 const uno::Reference< ucb::XCommandEnvironment >& xEnv, 3432 const std::auto_ptr< DAVResourceAccess > & rResAccess ) 3433 throw ( uno::Exception ) 3434 { 3435 if ( m_eResourceType == UNKNOWN ) 3436 { 3437 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3438 3439 ResourceType eResourceType; 3440 eResourceType = m_eResourceType; 3441 3442 const rtl::OUString & rURL = rResAccess->getURL(); 3443 const rtl::OUString aScheme( 3444 rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() ); 3445 3446 try 3447 { 3448 // Try to fetch some frequently used property value, e.g. those 3449 // used when loading documents... along with identifying whether 3450 // this is a DAV resource. 3451 std::vector< DAVResource > resources; 3452 std::vector< rtl::OUString > aPropNames; 3453 uno::Sequence< beans::Property > aProperties( 5 ); 3454 aProperties[ 0 ].Name 3455 = rtl::OUString::createFromAscii( "IsFolder" ); 3456 aProperties[ 1 ].Name 3457 = rtl::OUString::createFromAscii( "IsDocument" ); 3458 aProperties[ 2 ].Name 3459 = rtl::OUString::createFromAscii( "IsReadOnly" ); 3460 aProperties[ 3 ].Name 3461 = rtl::OUString::createFromAscii( "MediaType" ); 3462 aProperties[ 4 ].Name 3463 = DAVProperties::SUPPORTEDLOCK; 3464 3465 ContentProperties::UCBNamesToDAVNames( 3466 aProperties, aPropNames ); 3467 3468 rResAccess->PROPFIND( 3469 DAVZERO, aPropNames, resources, xEnv ); 3470 3471 // TODO - is this really only one? 3472 if ( resources.size() == 1 ) 3473 { 3474 m_xCachedProps.reset( 3475 new CachableContentProperties( resources[ 0 ] ) ); 3476 m_xCachedProps->containsAllNames( 3477 aProperties, m_aFailedPropNames ); 3478 } 3479 3480 eResourceType = DAV; 3481 } 3482 catch ( DAVException const & e ) 3483 { 3484 rResAccess->resetUri(); 3485 3486 if ( e.getStatus() == SC_METHOD_NOT_ALLOWED ) 3487 { 3488 // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the 3489 // resource is NON_DAV 3490 eResourceType = NON_DAV; 3491 } 3492 // cancel command execution is case that no user authentication data has been provided. 3493 if ( e.getError() == DAVException::DAV_HTTP_NOAUTH ) 3494 { 3495 cancelCommandExecution( e, uno::Reference< ucb::XCommandEnvironment >() ); 3496 } 3497 } 3498 m_eResourceType = eResourceType; 3499 } 3500 return m_eResourceType; 3501 } 3502 3503 //========================================================================= 3504 const Content::ResourceType & Content::getResourceType( 3505 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 3506 throw ( uno::Exception ) 3507 { 3508 return getResourceType( xEnv, m_xResAccess ); 3509 } 3510