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 } 1661 } 1662 else 1663 { 1664 // No server access for just created (not yet committed) objects. 1665 // Only a minimal set of properties supported at this stage. 1666 if (m_bTransient) 1667 xProps.reset( new ContentProperties( aUnescapedTitle, 1668 m_bCollection ) ); 1669 } 1670 1671 sal_Int32 nCount = rProperties.getLength(); 1672 for ( sal_Int32 n = 0; n < nCount; ++n ) 1673 { 1674 const rtl::OUString rName = rProperties[ n ].Name; 1675 if ( rName.equalsAsciiL( 1676 RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) ) 1677 { 1678 // Add BaseURI property, if requested. 1679 xProps->addProperty( 1680 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ), 1681 uno::makeAny( getBaseURI( xResAccess ) ), 1682 true ); 1683 } 1684 else if ( rName.equalsAsciiL( 1685 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1686 { 1687 // Add CreatableContentsInfo property, if requested. 1688 sal_Bool bFolder = sal_False; 1689 xProps->getValue( 1690 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) ) 1691 >>= bFolder; 1692 xProps->addProperty( 1693 rtl::OUString( 1694 RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ), 1695 uno::makeAny( bFolder 1696 ? queryCreatableContentsInfo() 1697 : uno::Sequence< ucb::ContentInfo >() ), 1698 true ); 1699 } 1700 } 1701 1702 uno::Reference< sdbc::XRow > xResultRow 1703 = getPropertyValues( xSMgr, 1704 rProperties, 1705 *xProps, 1706 xProvider, 1707 xIdentifier->getContentIdentifier() ); 1708 1709 { 1710 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1711 1712 if ( !m_xCachedProps.get() ) 1713 m_xCachedProps.reset( new CachableContentProperties( *xProps.get() ) ); 1714 else 1715 m_xCachedProps->addProperties( *xProps.get() ); 1716 1717 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 1718 m_aEscapedTitle = SerfUri::escapeSegment( aUnescapedTitle ); 1719 } 1720 1721 return xResultRow; 1722 } 1723 1724 //========================================================================= 1725 uno::Sequence< uno::Any > Content::setPropertyValues( 1726 const uno::Sequence< beans::PropertyValue >& rValues, 1727 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 1728 throw ( uno::Exception ) 1729 { 1730 uno::Reference< lang::XMultiServiceFactory > xSMgr; 1731 uno::Reference< ucb::XContentIdentifier > xIdentifier; 1732 rtl::Reference< ContentProvider > xProvider; 1733 sal_Bool bTransient; 1734 std::auto_ptr< DAVResourceAccess > xResAccess; 1735 1736 { 1737 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1738 1739 xProvider.set( m_pProvider ); 1740 xIdentifier.set( m_xIdentifier ); 1741 bTransient = m_bTransient; 1742 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 1743 xSMgr.set( m_xSMgr ); 1744 } 1745 1746 uno::Sequence< uno::Any > aRet( rValues.getLength() ); 1747 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); 1748 sal_Int32 nChanged = 0; 1749 1750 beans::PropertyChangeEvent aEvent; 1751 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 1752 aEvent.Further = sal_False; 1753 // aEvent.PropertyName = 1754 aEvent.PropertyHandle = -1; 1755 // aEvent.OldValue = 1756 // aEvent.NewValue = 1757 1758 std::vector< ProppatchValue > aProppatchValues; 1759 std::vector< sal_Int32 > aProppatchPropsPositions; 1760 1761 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; 1762 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 1763 1764 sal_Bool bExchange = sal_False; 1765 rtl::OUString aNewTitle; 1766 rtl::OUString aOldTitle; 1767 sal_Int32 nTitlePos = -1; 1768 1769 uno::Reference< beans::XPropertySetInfo > xInfo; 1770 1771 const beans::PropertyValue* pValues = rValues.getConstArray(); 1772 sal_Int32 nCount = rValues.getLength(); 1773 for ( sal_Int32 n = 0; n < nCount; ++n ) 1774 { 1775 const beans::PropertyValue& rValue = pValues[ n ]; 1776 const rtl::OUString & rName = rValue.Name; 1777 1778 beans::Property aTmpProp; 1779 xProvider->getProperty( rName, aTmpProp ); 1780 1781 if ( aTmpProp.Attributes & beans::PropertyAttribute::READONLY ) 1782 { 1783 // Read-only property! 1784 aRet[ n ] <<= lang::IllegalAccessException( 1785 rtl::OUString::createFromAscii( 1786 "Property is read-only!" ), 1787 static_cast< cppu::OWeakObject * >( this ) ); 1788 continue; 1789 } 1790 1791 ////////////////////////////////////////////////////////////////// 1792 // Mandatory props. 1793 ////////////////////////////////////////////////////////////////// 1794 1795 if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 1796 { 1797 // Read-only property! 1798 aRet[ n ] <<= lang::IllegalAccessException( 1799 rtl::OUString::createFromAscii( 1800 "Property is read-only!" ), 1801 static_cast< cppu::OWeakObject * >( this ) ); 1802 } 1803 else if ( rName.equalsAsciiL( 1804 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 1805 { 1806 // Read-only property! 1807 aRet[ n ] <<= lang::IllegalAccessException( 1808 rtl::OUString::createFromAscii( 1809 "Property is read-only!" ), 1810 static_cast< cppu::OWeakObject * >( this ) ); 1811 } 1812 else if ( rName.equalsAsciiL( 1813 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 1814 { 1815 // Read-only property! 1816 aRet[ n ] <<= lang::IllegalAccessException( 1817 rtl::OUString::createFromAscii( 1818 "Property is read-only!" ), 1819 static_cast< cppu::OWeakObject * >( this ) ); 1820 } 1821 else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 1822 { 1823 rtl::OUString aNewValue; 1824 if ( rValue.Value >>= aNewValue ) 1825 { 1826 // No empty titles! 1827 if ( aNewValue.getLength() > 0 ) 1828 { 1829 try 1830 { 1831 SerfUri aURI( xIdentifier->getContentIdentifier() ); 1832 aOldTitle = aURI.GetPathBaseNameUnescaped(); 1833 1834 if ( aNewValue != aOldTitle ) 1835 { 1836 // modified title -> modified URL -> exchange ! 1837 if ( !bTransient ) 1838 bExchange = sal_True; 1839 1840 // new value will be set later... 1841 aNewTitle = aNewValue; 1842 1843 // remember position within sequence of values (for 1844 // error handling). 1845 nTitlePos = n; 1846 } 1847 } 1848 catch ( DAVException const & ) 1849 { 1850 aRet[ n ] <<= lang::IllegalArgumentException( 1851 rtl::OUString::createFromAscii( 1852 "Invalid content identifier!" ), 1853 static_cast< cppu::OWeakObject * >( this ), 1854 -1 ); 1855 } 1856 } 1857 else 1858 { 1859 aRet[ n ] <<= lang::IllegalArgumentException( 1860 rtl::OUString::createFromAscii( 1861 "Empty title not allowed!" ), 1862 static_cast< cppu::OWeakObject * >( this ), 1863 -1 ); 1864 } 1865 } 1866 else 1867 { 1868 aRet[ n ] <<= beans::IllegalTypeException( 1869 rtl::OUString::createFromAscii( 1870 "Property value has wrong type!" ), 1871 static_cast< cppu::OWeakObject * >( this ) ); 1872 } 1873 } 1874 else 1875 { 1876 ////////////////////////////////////////////////////////////// 1877 // Optional props. 1878 ////////////////////////////////////////////////////////////// 1879 1880 rtl::OUString aSpecialName; 1881 bool bIsSpecial = DAVProperties::isUCBSpecialProperty( rName, aSpecialName ); 1882 1883 if ( !xInfo.is() ) 1884 xInfo = getPropertySetInfo( xEnv, 1885 sal_False /* don't cache data */ ); 1886 1887 if ( !xInfo->hasPropertyByName( bIsSpecial ? aSpecialName : rName ) ) 1888 { 1889 // Check, whether property exists. Skip otherwise. 1890 // PROPPATCH::set would add the property automatically, which 1891 // is not allowed for "setPropertyValues" command! 1892 aRet[ n ] <<= beans::UnknownPropertyException( 1893 rtl::OUString::createFromAscii( 1894 "Property is unknown!" ), 1895 static_cast< cppu::OWeakObject * >( this ) ); 1896 continue; 1897 } 1898 1899 if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) 1900 { 1901 // Read-only property! 1902 aRet[ n ] <<= lang::IllegalAccessException( 1903 rtl::OUString::createFromAscii( 1904 "Property is read-only!" ), 1905 static_cast< cppu::OWeakObject * >( this ) ); 1906 } 1907 else if ( rName.equalsAsciiL( 1908 RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) 1909 { 1910 // Read-only property! 1911 aRet[ n ] <<= lang::IllegalAccessException( 1912 rtl::OUString::createFromAscii( 1913 "Property is read-only!" ), 1914 static_cast< cppu::OWeakObject * >( this ) ); 1915 } 1916 else if ( rName.equalsAsciiL( 1917 RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) 1918 { 1919 // Read-only property! 1920 aRet[ n ] <<= lang::IllegalAccessException( 1921 rtl::OUString::createFromAscii( 1922 "Property is read-only!" ), 1923 static_cast< cppu::OWeakObject * >( this ) ); 1924 } 1925 else if ( rName.equalsAsciiL( 1926 RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) 1927 { 1928 // Read-only property! 1929 // (but could be writable, if 'getcontenttype' would be) 1930 aRet[ n ] <<= lang::IllegalAccessException( 1931 rtl::OUString::createFromAscii( 1932 "Property is read-only!" ), 1933 static_cast< cppu::OWeakObject * >( this ) ); 1934 } 1935 if ( rName.equalsAsciiL( 1936 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1937 { 1938 // Read-only property! 1939 aRet[ n ] <<= lang::IllegalAccessException( 1940 rtl::OUString::createFromAscii( 1941 "Property is read-only!" ), 1942 static_cast< cppu::OWeakObject * >( this ) ); 1943 } 1944 else 1945 { 1946 if ( getResourceType( xEnv, xResAccess ) == DAV ) 1947 { 1948 // Property value will be set on server. 1949 ProppatchValue aValue( PROPSET, rName, rValue.Value ); 1950 aProppatchValues.push_back( aValue ); 1951 1952 // remember position within sequence of values (for 1953 // error handling). 1954 aProppatchPropsPositions.push_back( n ); 1955 } 1956 else 1957 { 1958 // Property value will be stored in local property store. 1959 if ( !bTriedToGetAdditonalPropSet && 1960 !xAdditionalPropSet.is() ) 1961 { 1962 xAdditionalPropSet 1963 = getAdditionalPropertySet( sal_False ); 1964 bTriedToGetAdditonalPropSet = sal_True; 1965 } 1966 1967 if ( xAdditionalPropSet.is() ) 1968 { 1969 try 1970 { 1971 uno::Any aOldValue 1972 = xAdditionalPropSet->getPropertyValue( rName ); 1973 if ( aOldValue != rValue.Value ) 1974 { 1975 xAdditionalPropSet->setPropertyValue( 1976 rName, rValue.Value ); 1977 1978 aEvent.PropertyName = rName; 1979 aEvent.OldValue = aOldValue; 1980 aEvent.NewValue = rValue.Value; 1981 1982 aChanges.getArray()[ nChanged ] = aEvent; 1983 nChanged++; 1984 } 1985 } 1986 catch ( beans::UnknownPropertyException const & e ) 1987 { 1988 aRet[ n ] <<= e; 1989 } 1990 catch ( lang::WrappedTargetException const & e ) 1991 { 1992 aRet[ n ] <<= e; 1993 } 1994 catch ( beans::PropertyVetoException const & e ) 1995 { 1996 aRet[ n ] <<= e; 1997 } 1998 catch ( lang::IllegalArgumentException const & e ) 1999 { 2000 aRet[ n ] <<= e; 2001 } 2002 } 2003 else 2004 { 2005 aRet[ n ] <<= uno::Exception( 2006 rtl::OUString::createFromAscii( 2007 "No property set for storing the value!" ), 2008 static_cast< cppu::OWeakObject * >( this ) ); 2009 } 2010 } 2011 } 2012 } 2013 } // for 2014 2015 if ( !bTransient && aProppatchValues.size() ) 2016 { 2017 try 2018 { 2019 // Set property values at server. 2020 xResAccess->PROPPATCH( aProppatchValues, xEnv ); 2021 2022 std::vector< ProppatchValue >::const_iterator it 2023 = aProppatchValues.begin(); 2024 std::vector< ProppatchValue >::const_iterator end 2025 = aProppatchValues.end(); 2026 2027 while ( it != end ) 2028 { 2029 aEvent.PropertyName = (*it).name; 2030 aEvent.OldValue = uno::Any(); // @@@ to expensive to obtain! 2031 aEvent.NewValue = (*it).value; 2032 2033 aChanges.getArray()[ nChanged ] = aEvent; 2034 nChanged++; 2035 2036 ++it; 2037 } 2038 } 2039 catch ( DAVException const & e ) 2040 { 2041 // OSL_ENSURE( sal_False, 2042 // "Content::setPropertyValues - PROPPATCH failed!" ); 2043 2044 #if 1 2045 cancelCommandExecution( e, xEnv ); 2046 // unreachable 2047 #else 2048 // Note: PROPPATCH either sets ALL property values OR NOTHING. 2049 2050 std::vector< sal_Int32 >::const_iterator it 2051 = aProppatchPropsPositions.begin(); 2052 std::vector< sal_Int32 >::const_iterator end 2053 = aProppatchPropsPositions.end(); 2054 2055 while ( it != end ) 2056 { 2057 // Set error. 2058 aRet[ (*it) ] <<= MapDAVException( e, sal_True ); 2059 ++it; 2060 } 2061 #endif 2062 } 2063 } 2064 2065 if ( bExchange ) 2066 { 2067 // Assemble new content identifier... 2068 2069 rtl::OUString aNewURL = getParentURL(); 2070 if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) ) 2071 aNewURL += rtl::OUString::createFromAscii( "/" ); 2072 2073 aNewURL += SerfUri::escapeSegment( aNewTitle ); 2074 2075 uno::Reference< ucb::XContentIdentifier > xNewId 2076 = new ::ucbhelper::ContentIdentifier( xSMgr, aNewURL ); 2077 uno::Reference< ucb::XContentIdentifier > xOldId = xIdentifier; 2078 2079 try 2080 { 2081 SerfUri sourceURI( xOldId->getContentIdentifier() ); 2082 SerfUri targetURI( xNewId->getContentIdentifier() ); 2083 targetURI.SetScheme( sourceURI.GetScheme() ); 2084 2085 xResAccess->MOVE( 2086 sourceURI.GetPath(), targetURI.GetURI(), sal_False, xEnv ); 2087 // @@@ Should check for resources that could not be moved 2088 // (due to source access or target overwrite) and send 2089 // this information through the interaction handler. 2090 2091 // @@@ Existing content should be checked to see if it needs 2092 // to be deleted at the source 2093 2094 // @@@ Existing content should be checked to see if it has 2095 // been overwritten at the target 2096 2097 if ( exchangeIdentity( xNewId ) ) 2098 { 2099 xResAccess->setURL( aNewURL ); 2100 2101 // DAV resources store all additional props on server! 2102 // // Adapt Additional Core Properties. 2103 // renameAdditionalPropertySet( xOldId->getContentIdentifier(), 2104 // xNewId->getContentIdentifier(), 2105 // sal_True ); 2106 } 2107 else 2108 { 2109 // Do not set new title! 2110 aNewTitle = rtl::OUString(); 2111 2112 // Set error . 2113 aRet[ nTitlePos ] <<= uno::Exception( 2114 rtl::OUString::createFromAscii( "Exchange failed!" ), 2115 static_cast< cppu::OWeakObject * >( this ) ); 2116 } 2117 } 2118 catch ( DAVException const & e ) 2119 { 2120 // Do not set new title! 2121 aNewTitle = rtl::OUString(); 2122 2123 // Set error . 2124 aRet[ nTitlePos ] <<= MapDAVException( e, sal_True ); 2125 } 2126 } 2127 2128 if ( aNewTitle.getLength() ) 2129 { 2130 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2131 2132 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); 2133 aEvent.OldValue = uno::makeAny( aOldTitle ); 2134 aEvent.NewValue = uno::makeAny( aNewTitle ); 2135 2136 m_aEscapedTitle = SerfUri::escapeSegment( aNewTitle ); 2137 2138 aChanges.getArray()[ nChanged ] = aEvent; 2139 nChanged++; 2140 } 2141 2142 if ( nChanged > 0 ) 2143 { 2144 aChanges.realloc( nChanged ); 2145 notifyPropertiesChange( aChanges ); 2146 } 2147 2148 { 2149 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2150 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 2151 } 2152 2153 return aRet; 2154 } 2155 2156 //========================================================================= 2157 uno::Any Content::open( 2158 const ucb::OpenCommandArgument2 & rArg, 2159 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2160 throw( uno::Exception ) 2161 { 2162 uno::Any aRet; 2163 2164 sal_Bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) || 2165 ( rArg.Mode == ucb::OpenMode::FOLDERS ) || 2166 ( rArg.Mode == ucb::OpenMode::DOCUMENTS ) ); 2167 if ( bOpenFolder ) 2168 { 2169 if ( isFolder( xEnv ) ) 2170 { 2171 // Open collection. 2172 2173 uno::Reference< ucb::XDynamicResultSet > xSet 2174 = new DynamicResultSet( m_xSMgr, this, rArg, xEnv ); 2175 aRet <<= xSet; 2176 } 2177 else 2178 { 2179 // Error: Not a folder! 2180 2181 rtl::OUStringBuffer aMsg; 2182 aMsg.appendAscii( "Non-folder resource cannot be " 2183 "opened as folder! Wrong Open Mode!" ); 2184 2185 ucbhelper::cancelCommandExecution( 2186 uno::makeAny( 2187 lang::IllegalArgumentException( 2188 aMsg.makeStringAndClear(), 2189 static_cast< cppu::OWeakObject * >( this ), 2190 -1 ) ), 2191 xEnv ); 2192 // Unreachable 2193 } 2194 } 2195 2196 if ( rArg.Sink.is() ) 2197 { 2198 // Open document. 2199 2200 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || 2201 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) 2202 { 2203 // Currently(?) unsupported. 2204 ucbhelper::cancelCommandExecution( 2205 uno::makeAny( 2206 ucb::UnsupportedOpenModeException( 2207 rtl::OUString(), 2208 static_cast< cppu::OWeakObject * >( this ), 2209 sal_Int16( rArg.Mode ) ) ), 2210 xEnv ); 2211 // Unreachable 2212 } 2213 2214 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 2215 uno::Reference< io::XOutputStream > xOut 2216 = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY ); 2217 if ( xOut.is() ) 2218 { 2219 // PUSH: write data 2220 try 2221 { 2222 std::auto_ptr< DAVResourceAccess > xResAccess; 2223 2224 { 2225 osl::MutexGuard aGuard( m_aMutex ); 2226 2227 xResAccess.reset( 2228 new DAVResourceAccess( *m_xResAccess.get() ) ); 2229 } 2230 2231 DAVResource aResource; 2232 std::vector< rtl::OUString > aHeaders; 2233 2234 xResAccess->GET( xOut, aHeaders, aResource, xEnv ); 2235 m_bDidGetOrHead = true; 2236 2237 { 2238 osl::MutexGuard aGuard( m_aMutex ); 2239 2240 // cache headers. 2241 if ( !m_xCachedProps.get()) 2242 m_xCachedProps.reset( 2243 new CachableContentProperties( aResource ) ); 2244 else 2245 m_xCachedProps->addProperties( aResource ); 2246 2247 m_xResAccess.reset( 2248 new DAVResourceAccess( *xResAccess.get() ) ); 2249 } 2250 } 2251 catch ( DAVException const & e ) 2252 { 2253 cancelCommandExecution( e, xEnv ); 2254 // Unreachable 2255 } 2256 } 2257 else 2258 { 2259 uno::Reference< io::XActiveDataSink > xDataSink 2260 = uno::Reference< io::XActiveDataSink >( rArg.Sink, 2261 uno::UNO_QUERY ); 2262 if ( xDataSink.is() ) 2263 { 2264 // PULL: wait for client read 2265 try 2266 { 2267 std::auto_ptr< DAVResourceAccess > xResAccess; 2268 { 2269 osl::MutexGuard aGuard( m_aMutex ); 2270 2271 xResAccess.reset( 2272 new DAVResourceAccess( *m_xResAccess.get() ) ); 2273 } 2274 2275 // fill inputsream sync; return if all data present 2276 DAVResource aResource; 2277 std::vector< rtl::OUString > aHeaders; 2278 2279 uno::Reference< io::XInputStream > xIn 2280 = xResAccess->GET( aHeaders, aResource, xEnv ); 2281 m_bDidGetOrHead = true; 2282 2283 { 2284 osl::MutexGuard aGuard( m_aMutex ); 2285 2286 // cache headers. 2287 if ( !m_xCachedProps.get()) 2288 m_xCachedProps.reset( 2289 new CachableContentProperties( aResource ) ); 2290 else 2291 m_xCachedProps->addProperties( 2292 aResource.properties ); 2293 2294 m_xResAccess.reset( 2295 new DAVResourceAccess( *xResAccess.get() ) ); 2296 } 2297 2298 xDataSink->setInputStream( xIn ); 2299 } 2300 catch ( DAVException const & e ) 2301 { 2302 cancelCommandExecution( e, xEnv ); 2303 // Unreachable 2304 } 2305 } 2306 else 2307 { 2308 // Note: aOpenCommand.Sink may contain an XStream 2309 // implementation. Support for this type of 2310 // sink is optional... 2311 ucbhelper::cancelCommandExecution( 2312 uno::makeAny( 2313 ucb::UnsupportedDataSinkException( 2314 rtl::OUString(), 2315 static_cast< cppu::OWeakObject * >( this ), 2316 rArg.Sink ) ), 2317 xEnv ); 2318 // Unreachable 2319 } 2320 } 2321 } 2322 2323 return aRet; 2324 } 2325 2326 //========================================================================= 2327 void Content::post( 2328 const ucb::PostCommandArgument2 & rArg, 2329 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2330 throw( uno::Exception ) 2331 { 2332 uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY ); 2333 if ( xSink.is() ) 2334 { 2335 try 2336 { 2337 std::auto_ptr< DAVResourceAccess > xResAccess; 2338 { 2339 osl::MutexGuard aGuard( m_aMutex ); 2340 xResAccess.reset( 2341 new DAVResourceAccess( *m_xResAccess.get() ) ); 2342 } 2343 2344 uno::Reference< io::XInputStream > xResult 2345 = xResAccess->POST( rArg.MediaType, 2346 rArg.Referer, 2347 rArg.Source, 2348 xEnv ); 2349 2350 { 2351 osl::MutexGuard aGuard( m_aMutex ); 2352 m_xResAccess.reset( 2353 new DAVResourceAccess( *xResAccess.get() ) ); 2354 } 2355 2356 xSink->setInputStream( xResult ); 2357 } 2358 catch ( DAVException const & e ) 2359 { 2360 cancelCommandExecution( e, xEnv, sal_True ); 2361 // Unreachable 2362 } 2363 } 2364 else 2365 { 2366 uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY ); 2367 if ( xResult.is() ) 2368 { 2369 try 2370 { 2371 std::auto_ptr< DAVResourceAccess > xResAccess; 2372 { 2373 osl::MutexGuard aGuard( m_aMutex ); 2374 xResAccess.reset( 2375 new DAVResourceAccess( *m_xResAccess.get() ) ); 2376 } 2377 2378 xResAccess->POST( rArg.MediaType, 2379 rArg.Referer, 2380 rArg.Source, 2381 xResult, 2382 xEnv ); 2383 2384 { 2385 osl::MutexGuard aGuard( m_aMutex ); 2386 m_xResAccess.reset( 2387 new DAVResourceAccess( *xResAccess.get() ) ); 2388 } 2389 } 2390 catch ( DAVException const & e ) 2391 { 2392 cancelCommandExecution( e, xEnv, sal_True ); 2393 // Unreachable 2394 } 2395 } 2396 else 2397 { 2398 ucbhelper::cancelCommandExecution( 2399 uno::makeAny( 2400 ucb::UnsupportedDataSinkException( 2401 rtl::OUString(), 2402 static_cast< cppu::OWeakObject * >( this ), 2403 rArg.Sink ) ), 2404 xEnv ); 2405 // Unreachable 2406 } 2407 } 2408 } 2409 2410 //========================================================================= 2411 void Content::queryChildren( ContentRefList& rChildren ) 2412 { 2413 // Obtain a list with a snapshot of all currently instanciated contents 2414 // from provider and extract the contents which are direct children 2415 // of this content. 2416 2417 ::ucbhelper::ContentRefList aAllContents; 2418 m_xProvider->queryExistingContents( aAllContents ); 2419 2420 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 2421 sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); 2422 2423 if ( nURLPos != ( aURL.getLength() - 1 ) ) 2424 { 2425 // No trailing slash found. Append. 2426 aURL += rtl::OUString::createFromAscii( "/" ); 2427 } 2428 2429 sal_Int32 nLen = aURL.getLength(); 2430 2431 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); 2432 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); 2433 2434 while ( it != end ) 2435 { 2436 ::ucbhelper::ContentImplHelperRef xChild = (*it); 2437 rtl::OUString aChildURL 2438 = xChild->getIdentifier()->getContentIdentifier(); 2439 2440 // Is aURL a prefix of aChildURL? 2441 if ( ( aChildURL.getLength() > nLen ) && 2442 ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) 2443 { 2444 sal_Int32 nPos = nLen; 2445 nPos = aChildURL.indexOf( '/', nPos ); 2446 2447 if ( ( nPos == -1 ) || 2448 ( nPos == ( aChildURL.getLength() - 1 ) ) ) 2449 { 2450 // No further slashes / only a final slash. It's a child! 2451 rChildren.push_back( 2452 ::http_dav_ucp::Content::ContentRef( 2453 static_cast< ::http_dav_ucp::Content * >( 2454 xChild.get() ) ) ); 2455 } 2456 } 2457 ++it; 2458 } 2459 } 2460 2461 //========================================================================= 2462 void Content::insert( 2463 const uno::Reference< io::XInputStream > & xInputStream, 2464 sal_Bool bReplaceExisting, 2465 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 2466 throw( uno::Exception ) 2467 { 2468 sal_Bool bTransient, bCollection; 2469 rtl::OUString aEscapedTitle; 2470 std::auto_ptr< DAVResourceAccess > xResAccess; 2471 2472 { 2473 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2474 2475 bTransient = m_bTransient; 2476 bCollection = m_bCollection; 2477 aEscapedTitle = m_aEscapedTitle; 2478 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 2479 } 2480 2481 // Check, if all required properties are present. 2482 2483 if ( aEscapedTitle.getLength() == 0 ) 2484 { 2485 OSL_ENSURE( sal_False, "Content::insert - Title missing!" ); 2486 2487 uno::Sequence< rtl::OUString > aProps( 1 ); 2488 aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" ); 2489 ucbhelper::cancelCommandExecution( 2490 uno::makeAny( ucb::MissingPropertiesException( 2491 rtl::OUString(), 2492 static_cast< cppu::OWeakObject * >( this ), 2493 aProps ) ), 2494 Environment ); 2495 // Unreachable 2496 } 2497 2498 if ( !bReplaceExisting ) 2499 { 2500 /* [RFC 2616] - HTTP 2501 2502 The PUT method requests that the enclosed entity be stored under the 2503 supplied Request-URI. If the Request-URI refers to an already 2504 existing resource, the enclosed entity SHOULD be considered as a 2505 modified version of the one residing on the origin server. 2506 */ 2507 2508 /* [RFC 2518] - WebDAV 2509 2510 MKCOL creates a new collection resource at the location specified by 2511 the Request-URI. If the resource identified by the Request-URI is 2512 non-null then the MKCOL MUST fail. 2513 */ 2514 2515 // ==> Complain on PUT, continue on MKCOL. 2516 if ( !bTransient || ( bTransient && !bCollection ) ) 2517 { 2518 #undef ERROR 2519 ucb::UnsupportedNameClashException aEx( 2520 rtl::OUString::createFromAscii( "Unable to write without overwrite!" ), 2521 static_cast< cppu::OWeakObject * >( this ), 2522 ucb::NameClash::ERROR ); 2523 2524 uno::Reference< task::XInteractionHandler > xIH; 2525 2526 if ( Environment.is() ) 2527 xIH = Environment->getInteractionHandler(); 2528 2529 if ( xIH.is() ) 2530 { 2531 uno::Any aExAsAny( uno::makeAny( aEx ) ); 2532 2533 rtl::Reference< ucbhelper::SimpleInteractionRequest > xRequest 2534 = new ucbhelper::SimpleInteractionRequest( 2535 aExAsAny, 2536 ucbhelper::CONTINUATION_APPROVE 2537 | ucbhelper::CONTINUATION_DISAPPROVE ); 2538 xIH->handle( xRequest.get() ); 2539 2540 const sal_Int32 nResp = xRequest->getResponse(); 2541 2542 switch ( nResp ) 2543 { 2544 case ucbhelper::CONTINUATION_UNKNOWN: 2545 // Not handled; throw. 2546 throw aEx; 2547 // break; 2548 2549 case ucbhelper::CONTINUATION_APPROVE: 2550 // Continue -> Overwrite. 2551 bReplaceExisting = sal_True; 2552 break; 2553 2554 case ucbhelper::CONTINUATION_DISAPPROVE: 2555 // Abort. 2556 throw ucb::CommandFailedException( 2557 rtl::OUString(), 2558 uno::Reference< uno::XInterface >(), 2559 aExAsAny ); 2560 // break; 2561 2562 default: 2563 OSL_ENSURE( sal_False, 2564 "Content::insert - " 2565 "Unknown interaction selection!" ); 2566 throw ucb::CommandFailedException( 2567 rtl::OUString::createFromAscii( 2568 "Unknown interaction selection!" ), 2569 uno::Reference< uno::XInterface >(), 2570 aExAsAny ); 2571 // break; 2572 } 2573 } 2574 else 2575 { 2576 // No IH; throw. 2577 throw aEx; 2578 } 2579 } 2580 } 2581 2582 if ( bTransient ) 2583 { 2584 // Assemble new content identifier... 2585 rtl::OUString aURL = getParentURL(); 2586 if ( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ) ) 2587 aURL += rtl::OUString::createFromAscii( "/" ); 2588 2589 aURL += aEscapedTitle; 2590 2591 try 2592 { 2593 xResAccess->setURL( aURL ); 2594 2595 if ( bCollection ) 2596 xResAccess->MKCOL( Environment ); 2597 else 2598 xResAccess->PUT( xInputStream, Environment ); 2599 } 2600 catch ( DAVException const & except ) 2601 { 2602 if ( bCollection ) 2603 { 2604 if ( except.getStatus() == SC_METHOD_NOT_ALLOWED ) 2605 { 2606 // [RFC 2518] - WebDAV 2607 // 405 (Method Not Allowed) - MKCOL can only be 2608 // executed on a deleted/non-existent resource. 2609 2610 if ( bReplaceExisting ) 2611 { 2612 // Destroy old resource. 2613 try 2614 { 2615 xResAccess->DESTROY( Environment ); 2616 } 2617 catch ( DAVException const & e ) 2618 { 2619 cancelCommandExecution( e, Environment, sal_True ); 2620 // Unreachable 2621 } 2622 2623 // Insert (recursion!). 2624 insert( xInputStream, bReplaceExisting, Environment ); 2625 2626 { 2627 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2628 m_xResAccess.reset( 2629 new DAVResourceAccess( *xResAccess.get() ) ); 2630 } 2631 2632 // Success! 2633 return; 2634 } 2635 else 2636 { 2637 rtl::OUString aTitle; 2638 try 2639 { 2640 SerfUri aURI( aURL ); 2641 aTitle = aURI.GetPathBaseNameUnescaped(); 2642 } 2643 catch ( DAVException const & ) 2644 { 2645 } 2646 2647 ucbhelper::cancelCommandExecution( 2648 uno::makeAny( 2649 ucb::NameClashException( 2650 rtl::OUString(), 2651 static_cast< cppu::OWeakObject * >( this ), 2652 task::InteractionClassification_ERROR, 2653 aTitle ) ), 2654 Environment ); 2655 // Unreachable 2656 } 2657 } 2658 } 2659 2660 cancelCommandExecution( except, Environment, sal_True ); 2661 // Unreachable 2662 } 2663 2664 { 2665 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2666 m_xIdentifier 2667 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); 2668 } 2669 2670 inserted(); 2671 2672 { 2673 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2674 m_bTransient = sal_False; 2675 } 2676 } 2677 else 2678 { 2679 if ( !xInputStream.is() ) 2680 { 2681 ucbhelper::cancelCommandExecution( 2682 uno::makeAny( 2683 ucb::MissingInputStreamException( 2684 rtl::OUString(), 2685 static_cast< cppu::OWeakObject * >( this ) ) ), 2686 Environment ); 2687 // Unreachable 2688 } 2689 2690 try 2691 { 2692 xResAccess->PUT( xInputStream, Environment ); 2693 } 2694 catch ( DAVException const & e ) 2695 { 2696 cancelCommandExecution( e, Environment, sal_True ); 2697 // Unreachable 2698 } 2699 } 2700 2701 { 2702 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2703 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 2704 } 2705 } 2706 2707 //========================================================================= 2708 void Content::transfer( 2709 const ucb::TransferInfo & rArgs, 2710 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 2711 throw( uno::Exception ) 2712 { 2713 uno::Reference< lang::XMultiServiceFactory > xSMgr; 2714 uno::Reference< ucb::XContentIdentifier > xIdentifier; 2715 uno::Reference< ucb::XContentProvider > xProvider; 2716 std::auto_ptr< DAVResourceAccess > xResAccess; 2717 2718 { 2719 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2720 2721 xSMgr.set( m_xSMgr ); 2722 xIdentifier.set( m_xIdentifier ); 2723 xProvider.set( m_xProvider.get() ); 2724 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 2725 } 2726 2727 rtl::OUString aTargetURI; 2728 try 2729 { 2730 SerfUri sourceURI( rArgs.SourceURL ); 2731 SerfUri targetURI( xIdentifier->getContentIdentifier() ); 2732 aTargetURI = targetURI.GetPathBaseNameUnescaped(); 2733 2734 // Check source's and target's URL scheme 2735 // 2736 const rtl::OUString aScheme = sourceURI.GetScheme().toAsciiLowerCase(); 2737 if ( aScheme.equalsAsciiL( 2738 RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) ) 2739 { 2740 sourceURI.SetScheme( 2741 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2742 } 2743 else if ( aScheme.equalsAsciiL( 2744 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) ) 2745 { 2746 sourceURI.SetScheme( 2747 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2748 } 2749 else if ( aScheme.equalsAsciiL( 2750 RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) ) 2751 { 2752 sourceURI.SetScheme( 2753 rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) ); 2754 } 2755 else 2756 { 2757 if ( !aScheme.equalsAsciiL( 2758 RTL_CONSTASCII_STRINGPARAM( HTTP_URL_SCHEME ) ) && 2759 !aScheme.equalsAsciiL( 2760 RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME ) ) ) 2761 { 2762 ucbhelper::cancelCommandExecution( 2763 uno::makeAny( 2764 ucb::InteractiveBadTransferURLException( 2765 rtl::OUString::createFromAscii( 2766 "Unsupported URL scheme!" ), 2767 static_cast< cppu::OWeakObject * >( this ) ) ), 2768 Environment ); 2769 // Unreachable 2770 } 2771 } 2772 2773 if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL( 2774 RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) ) 2775 targetURI.SetScheme( 2776 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2777 else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL( 2778 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) ) 2779 targetURI.SetScheme( 2780 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) ); 2781 2782 // @@@ This implementation of 'transfer' only works 2783 // if the source and target are located at same host. 2784 // (Neon does not support cross-server copy/move) 2785 2786 // Check for same host 2787 // 2788 if ( sourceURI.GetHost().getLength() && 2789 ( sourceURI.GetHost() != targetURI.GetHost() ) ) 2790 { 2791 ucbhelper::cancelCommandExecution( 2792 uno::makeAny( ucb::InteractiveBadTransferURLException( 2793 rtl::OUString::createFromAscii( 2794 "Different hosts!" ), 2795 static_cast< cppu::OWeakObject * >( this ) ) ), 2796 Environment ); 2797 // Unreachable 2798 } 2799 2800 rtl::OUString aTitle = rArgs.NewTitle; 2801 2802 if ( !aTitle.getLength() ) 2803 aTitle = sourceURI.GetPathBaseNameUnescaped(); 2804 2805 if ( aTitle.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "/" ) ) ) 2806 { 2807 // kso: ??? 2808 aTitle = rtl::OUString(); 2809 } 2810 2811 targetURI.AppendPath( aTitle ); 2812 2813 rtl::OUString aTargetURL = xIdentifier->getContentIdentifier(); 2814 if ( ( aTargetURL.lastIndexOf( '/' ) + 1 ) 2815 != aTargetURL.getLength() ) 2816 aTargetURL += rtl::OUString::createFromAscii( "/" ); 2817 2818 aTargetURL += aTitle; 2819 2820 uno::Reference< ucb::XContentIdentifier > xTargetId 2821 = new ::ucbhelper::ContentIdentifier( xSMgr, aTargetURL ); 2822 2823 DAVResourceAccess aSourceAccess( xSMgr, 2824 xResAccess->getSessionFactory(), 2825 sourceURI.GetURI() ); 2826 2827 if ( rArgs.MoveData == sal_True ) 2828 { 2829 uno::Reference< ucb::XContentIdentifier > xId 2830 = new ::ucbhelper::ContentIdentifier( xSMgr, rArgs.SourceURL ); 2831 2832 // Note: The static cast is okay here, because its sure that 2833 // xProvider is always the WebDAVContentProvider. 2834 rtl::Reference< Content > xSource 2835 = static_cast< Content * >( 2836 xProvider->queryContent( xId ).get() ); 2837 2838 // [RFC 2518] - WebDAV 2839 // If a resource exists at the destination and the Overwrite 2840 // header is "T" then prior to performing the move the server 2841 // MUST perform a DELETE with "Depth: infinity" on the 2842 // destination resource. If the Overwrite header is set to 2843 // "F" then the operation will fail. 2844 2845 aSourceAccess.MOVE( sourceURI.GetPath(), 2846 targetURI.GetURI(), 2847 rArgs.NameClash 2848 == ucb::NameClash::OVERWRITE, 2849 Environment ); 2850 2851 if ( xSource.is() ) 2852 { 2853 // Propagate destruction to listeners. 2854 xSource->destroy( sal_True ); 2855 } 2856 2857 // DAV resources store all additional props on server! 2858 // // Rename own and all children's Additional Core Properties. 2859 // renameAdditionalPropertySet( xId->getContentIdentifier(), 2860 // xTargetId->getContentIdentifier(), 2861 // sal_True ); 2862 } 2863 else 2864 { 2865 // [RFC 2518] - WebDAV 2866 // If a resource exists at the destination and the Overwrite 2867 // header is "T" then prior to performing the copy the server 2868 // MUST perform a DELETE with "Depth: infinity" on the 2869 // destination resource. If the Overwrite header is set to 2870 // "F" then the operation will fail. 2871 2872 aSourceAccess.COPY( sourceURI.GetPath(), 2873 targetURI.GetURI(), 2874 rArgs.NameClash 2875 == ucb::NameClash::OVERWRITE, 2876 Environment ); 2877 2878 // DAV resources store all additional props on server! 2879 // // Copy own and all children's Additional Core Properties. 2880 // copyAdditionalPropertySet( xId->getContentIdentifier(), 2881 // xTargetId->getContentIdentifier(), 2882 // sal_True ); 2883 } 2884 2885 // Note: The static cast is okay here, because its sure that 2886 // xProvider is always the WebDAVContentProvider. 2887 rtl::Reference< Content > xTarget 2888 = static_cast< Content * >( 2889 xProvider->queryContent( xTargetId ).get() ); 2890 2891 // Announce transfered content in its new folder. 2892 xTarget->inserted(); 2893 } 2894 catch ( ucb::IllegalIdentifierException const & ) 2895 { 2896 // queryContent 2897 } 2898 catch ( DAVException const & e ) 2899 { 2900 // [RFC 2518] - WebDAV 2901 // 412 (Precondition Failed) - The server was unable to maintain 2902 // the liveness of the properties listed in the propertybehavior 2903 // XML element or the Overwrite header is "F" and the state of 2904 // the destination resource is non-null. 2905 2906 if ( e.getStatus() == SC_PRECONDITION_FAILED ) 2907 { 2908 switch ( rArgs.NameClash ) 2909 { 2910 case 0/*ucb::NameClash::ERROR*/: 2911 { 2912 ucbhelper::cancelCommandExecution( 2913 uno::makeAny( 2914 ucb::NameClashException( 2915 rtl::OUString(), 2916 static_cast< cppu::OWeakObject * >( this ), 2917 task::InteractionClassification_ERROR, 2918 aTargetURI ) ), 2919 Environment ); 2920 // Unreachable 2921 } 2922 2923 case ucb::NameClash::OVERWRITE: 2924 break; 2925 2926 case ucb::NameClash::KEEP: // deprecated 2927 case ucb::NameClash::RENAME: 2928 case ucb::NameClash::ASK: 2929 default: 2930 { 2931 ucbhelper::cancelCommandExecution( 2932 uno::makeAny( 2933 ucb::UnsupportedNameClashException( 2934 rtl::OUString(), 2935 static_cast< cppu::OWeakObject * >( this ), 2936 rArgs.NameClash ) ), 2937 Environment ); 2938 // Unreachable 2939 } 2940 } 2941 } 2942 2943 cancelCommandExecution( e, Environment, sal_True ); 2944 // Unreachable 2945 } 2946 2947 { 2948 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2949 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 2950 } 2951 } 2952 2953 //========================================================================= 2954 void Content::destroy( sal_Bool bDeletePhysical ) 2955 throw( uno::Exception ) 2956 { 2957 // @@@ take care about bDeletePhysical -> trashcan support 2958 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 2959 2960 uno::Reference< ucb::XContent > xThis = this; 2961 2962 deleted(); 2963 2964 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2965 2966 // Process instanciated children... 2967 2968 ::http_dav_ucp::Content::ContentRefList aChildren; 2969 queryChildren( aChildren ); 2970 2971 ContentRefList::const_iterator it = aChildren.begin(); 2972 ContentRefList::const_iterator end = aChildren.end(); 2973 2974 while ( it != end ) 2975 { 2976 (*it)->destroy( bDeletePhysical ); 2977 ++it; 2978 } 2979 } 2980 2981 //========================================================================= 2982 bool Content::supportsExclusiveWriteLock( 2983 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 2984 { 2985 if ( getResourceType( Environment ) == DAV ) 2986 { 2987 if ( m_xCachedProps.get() ) 2988 { 2989 uno::Sequence< ucb::LockEntry > aSupportedLocks; 2990 if ( m_xCachedProps->getValue( DAVProperties::SUPPORTEDLOCK ) 2991 >>= aSupportedLocks ) 2992 { 2993 for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n ) 2994 { 2995 if ( aSupportedLocks[ n ].Scope 2996 == ucb::LockScope_EXCLUSIVE && 2997 aSupportedLocks[ n ].Type 2998 == ucb::LockType_WRITE ) 2999 return true; 3000 } 3001 } 3002 } 3003 } 3004 return false; 3005 } 3006 3007 //========================================================================= 3008 void Content::lock( 3009 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 3010 throw( uno::Exception ) 3011 { 3012 try 3013 { 3014 std::auto_ptr< DAVResourceAccess > xResAccess; 3015 { 3016 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3017 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 3018 } 3019 3020 uno::Any aOwnerAny; 3021 aOwnerAny 3022 <<= rtl::OUString::createFromAscii( "http://ucb.openoffice.org" ); 3023 3024 ucb::Lock aLock( 3025 ucb::LockScope_EXCLUSIVE, 3026 ucb::LockType_WRITE, 3027 ucb::LockDepth_ZERO, 3028 aOwnerAny, 3029 180, // lock timeout in secs 3030 //-1, // infinite lock 3031 uno::Sequence< ::rtl::OUString >() ); 3032 3033 xResAccess->LOCK( aLock, Environment ); 3034 3035 { 3036 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3037 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 3038 } 3039 } 3040 catch ( DAVException const & e ) 3041 { 3042 cancelCommandExecution( e, Environment, sal_False ); 3043 // Unreachable 3044 } 3045 } 3046 3047 //========================================================================= 3048 void Content::unlock( 3049 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 3050 throw( uno::Exception ) 3051 { 3052 try 3053 { 3054 std::auto_ptr< DAVResourceAccess > xResAccess; 3055 { 3056 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3057 xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); 3058 } 3059 3060 xResAccess->UNLOCK( Environment ); 3061 3062 { 3063 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3064 m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); 3065 } 3066 } 3067 catch ( DAVException const & e ) 3068 { 3069 cancelCommandExecution( e, Environment, sal_False ); 3070 // Unreachable 3071 } 3072 } 3073 3074 //========================================================================= 3075 sal_Bool Content::exchangeIdentity( 3076 const uno::Reference< ucb::XContentIdentifier >& xNewId ) 3077 { 3078 if ( !xNewId.is() ) 3079 return sal_False; 3080 3081 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 3082 3083 uno::Reference< ucb::XContent > xThis = this; 3084 3085 // Already persistent? 3086 if ( m_bTransient ) 3087 { 3088 OSL_ENSURE( sal_False, "Content::exchangeIdentity - Not persistent!" ); 3089 return sal_False; 3090 } 3091 3092 // Exchange own identitity. 3093 3094 // Fail, if a content with given id already exists. 3095 // if ( !hasData( xNewId ) ) 3096 { 3097 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); 3098 3099 aGuard.clear(); 3100 if ( exchange( xNewId ) ) 3101 { 3102 // Process instanciated children... 3103 3104 ContentRefList aChildren; 3105 queryChildren( aChildren ); 3106 3107 ContentRefList::const_iterator it = aChildren.begin(); 3108 ContentRefList::const_iterator end = aChildren.end(); 3109 3110 while ( it != end ) 3111 { 3112 ContentRef xChild = (*it); 3113 3114 // Create new content identifier for the child... 3115 uno::Reference< ucb::XContentIdentifier > 3116 xOldChildId = xChild->getIdentifier(); 3117 rtl::OUString aOldChildURL 3118 = xOldChildId->getContentIdentifier(); 3119 rtl::OUString aNewChildURL 3120 = aOldChildURL.replaceAt( 3121 0, 3122 aOldURL.getLength(), 3123 xNewId->getContentIdentifier() ); 3124 uno::Reference< ucb::XContentIdentifier > xNewChildId 3125 = new ::ucbhelper::ContentIdentifier( 3126 m_xSMgr, aNewChildURL ); 3127 3128 if ( !xChild->exchangeIdentity( xNewChildId ) ) 3129 return sal_False; 3130 3131 ++it; 3132 } 3133 return sal_True; 3134 } 3135 } 3136 3137 OSL_ENSURE( sal_False, 3138 "Content::exchangeIdentity - " 3139 "Panic! Cannot exchange identity!" ); 3140 return sal_False; 3141 } 3142 3143 //========================================================================= 3144 sal_Bool Content::isFolder( 3145 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 3146 throw( uno::Exception ) 3147 { 3148 { 3149 osl::MutexGuard aGuard( m_aMutex ); 3150 3151 if ( m_bTransient ) 3152 return m_bCollection; 3153 } 3154 3155 uno::Sequence< beans::Property > aProperties( 1 ); 3156 aProperties[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); 3157 aProperties[ 0 ].Handle = -1; 3158 uno::Reference< sdbc::XRow > xRow( getPropertyValues( aProperties, xEnv ) ); 3159 if ( xRow.is() ) 3160 { 3161 try 3162 { 3163 return xRow->getBoolean( 1 ); 3164 } 3165 catch ( sdbc::SQLException const & ) 3166 { 3167 } 3168 } 3169 3170 return sal_False; 3171 } 3172 3173 //========================================================================= 3174 uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) 3175 { 3176 // Map DAVException... 3177 uno::Any aException; 3178 3179 rtl::OUString aURL; 3180 if ( m_bTransient ) 3181 { 3182 aURL = getParentURL(); 3183 if ( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ) ) 3184 aURL += rtl::OUString::createFromAscii( "/" ); 3185 3186 aURL += m_aEscapedTitle; 3187 } 3188 else 3189 { 3190 aURL = m_xIdentifier->getContentIdentifier(); 3191 } 3192 3193 switch ( e.getStatus() ) 3194 { 3195 case SC_NOT_FOUND: 3196 { 3197 uno::Sequence< uno::Any > aArgs( 1 ); 3198 aArgs[ 0 ] <<= beans::PropertyValue( 3199 rtl::OUString::createFromAscii("Uri"), -1, 3200 uno::makeAny(aURL), 3201 beans::PropertyState_DIRECT_VALUE); 3202 3203 aException <<= 3204 ucb::InteractiveAugmentedIOException( 3205 rtl::OUString::createFromAscii( "Not found!" ), 3206 static_cast< cppu::OWeakObject * >( this ), 3207 task::InteractionClassification_ERROR, 3208 ucb::IOErrorCode_NOT_EXISTING, 3209 aArgs ); 3210 return aException; 3211 } 3212 default: 3213 break; 3214 } 3215 3216 switch ( e.getError() ) 3217 { 3218 case DAVException::DAV_HTTP_ERROR: 3219 { 3220 if ( bWrite ) 3221 aException <<= 3222 ucb::InteractiveNetworkWriteException( 3223 e.getData(), 3224 static_cast< cppu::OWeakObject * >( this ), 3225 task::InteractionClassification_ERROR, 3226 e.getData() ); 3227 else 3228 aException <<= 3229 ucb::InteractiveNetworkReadException( 3230 e.getData(), 3231 static_cast< cppu::OWeakObject * >( this ), 3232 task::InteractionClassification_ERROR, 3233 e.getData() ); 3234 break; 3235 } 3236 3237 case DAVException::DAV_HTTP_LOOKUP: 3238 aException <<= 3239 ucb::InteractiveNetworkResolveNameException( 3240 rtl::OUString(), 3241 static_cast< cppu::OWeakObject * >( this ), 3242 task::InteractionClassification_ERROR, 3243 e.getData() ); 3244 break; 3245 3246 // @@@ No matching InteractiveNetwork*Exception 3247 // case DAVException::DAV_HTTP_AUTH: 3248 // break; 3249 3250 // @@@ No matching InteractiveNetwork*Exception 3251 // case DAVException::DAV_HTTP_AUTHPROXY: 3252 // break; 3253 3254 case DAVException::DAV_HTTP_CONNECT: 3255 aException <<= 3256 ucb::InteractiveNetworkConnectException( 3257 rtl::OUString(), 3258 static_cast< cppu::OWeakObject * >( this ), 3259 task::InteractionClassification_ERROR, 3260 e.getData() ); 3261 break; 3262 3263 // @@@ No matching InteractiveNetwork*Exception 3264 // case DAVException::DAV_HTTP_TIMEOUT: 3265 // break; 3266 3267 // @@@ No matching InteractiveNetwork*Exception 3268 // case DAVException::DAV_HTTP_REDIRECT: 3269 // break; 3270 3271 // @@@ No matching InteractiveNetwork*Exception 3272 // case DAVException::DAV_SESSION_CREATE: 3273 // break; 3274 3275 case DAVException::DAV_INVALID_ARG: 3276 aException <<= 3277 lang::IllegalArgumentException( 3278 rtl::OUString(), 3279 static_cast< cppu::OWeakObject * >( this ), 3280 -1 ); 3281 break; 3282 3283 case DAVException::DAV_LOCKED: 3284 #if 1 3285 aException <<= 3286 ucb::InteractiveLockingLockedException( 3287 rtl::OUString::createFromAscii( "Locked!" ), 3288 static_cast< cppu::OWeakObject * >( this ), 3289 task::InteractionClassification_ERROR, 3290 aURL, 3291 sal_False ); // not SelfOwned 3292 #else 3293 { 3294 uno::Sequence< uno::Any > aArgs( 1 ); 3295 aArgs[ 0 ] <<= beans::PropertyValue( 3296 rtl::OUString::createFromAscii("Uri"), -1, 3297 uno::makeAny(aURL), 3298 beans::PropertyState_DIRECT_VALUE); 3299 3300 aException <<= 3301 ucb::InteractiveAugmentedIOException( 3302 rtl::OUString::createFromAscii( "Locked!" ), 3303 static_cast< cppu::OWeakObject * >( this ), 3304 task::InteractionClassification_ERROR, 3305 ucb::IOErrorCode_LOCKING_VIOLATION, 3306 aArgs ); 3307 } 3308 #endif 3309 break; 3310 3311 case DAVException::DAV_LOCKED_SELF: 3312 aException <<= 3313 ucb::InteractiveLockingLockedException( 3314 rtl::OUString::createFromAscii( "Locked (self)!" ), 3315 static_cast< cppu::OWeakObject * >( this ), 3316 task::InteractionClassification_ERROR, 3317 aURL, 3318 sal_True ); // SelfOwned 3319 break; 3320 3321 case DAVException::DAV_NOT_LOCKED: 3322 aException <<= 3323 ucb::InteractiveLockingNotLockedException( 3324 rtl::OUString::createFromAscii( "Not locked!" ), 3325 static_cast< cppu::OWeakObject * >( this ), 3326 task::InteractionClassification_ERROR, 3327 aURL ); 3328 break; 3329 3330 case DAVException::DAV_LOCK_EXPIRED: 3331 aException <<= 3332 ucb::InteractiveLockingLockExpiredException( 3333 rtl::OUString::createFromAscii( "Lock expired!" ), 3334 static_cast< cppu::OWeakObject * >( this ), 3335 task::InteractionClassification_ERROR, 3336 aURL ); 3337 break; 3338 3339 default: 3340 aException <<= 3341 ucb::InteractiveNetworkGeneralException( 3342 rtl::OUString(), 3343 static_cast< cppu::OWeakObject * >( this ), 3344 task::InteractionClassification_ERROR ); 3345 break; 3346 } 3347 3348 return aException; 3349 } 3350 3351 //========================================================================= 3352 // static 3353 bool Content::shouldAccessNetworkAfterException( const DAVException & e ) 3354 { 3355 if ( ( e.getStatus() == SC_NOT_FOUND ) || 3356 ( e.getError() == DAVException::DAV_HTTP_LOOKUP ) || 3357 ( e.getError() == DAVException::DAV_HTTP_CONNECT ) || 3358 ( e.getError() == DAVException::DAV_HTTP_AUTH ) || 3359 ( e.getError() == DAVException::DAV_HTTP_AUTHPROXY ) ) 3360 return false; 3361 3362 return true; 3363 } 3364 3365 //========================================================================= 3366 void Content::cancelCommandExecution( 3367 const DAVException & e, 3368 const uno::Reference< ucb::XCommandEnvironment > & xEnv, 3369 sal_Bool bWrite /* = sal_False */ ) 3370 throw ( uno::Exception ) 3371 { 3372 ucbhelper::cancelCommandExecution( MapDAVException( e, bWrite ), xEnv ); 3373 // Unreachable 3374 } 3375 3376 //========================================================================= 3377 const rtl::OUString 3378 Content::getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ) 3379 { 3380 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3381 3382 // First, try to obtain value of response header "Content-Location". 3383 if ( m_xCachedProps.get() ) 3384 { 3385 rtl::OUString aLocation; 3386 m_xCachedProps->getValue( rtl::OUString( 3387 RTL_CONSTASCII_USTRINGPARAM( 3388 "Content-Location" ) ) ) >>= aLocation; 3389 if ( aLocation.getLength() ) 3390 { 3391 try 3392 { 3393 // Do not use m_xIdentifier->getContentIdentifier() because it 3394 // for example does not reflect redirects applied to requests 3395 // done using the original URI but m_xResAccess' URI does. 3396 return rtl::Uri::convertRelToAbs( rResAccess->getURL(), 3397 aLocation ); 3398 } 3399 catch ( rtl::MalformedUriException const & ) 3400 { 3401 } 3402 } 3403 } 3404 3405 return rtl::OUString( rResAccess->getURL() ); 3406 } 3407 3408 //========================================================================= 3409 const Content::ResourceType & Content::getResourceType( 3410 const uno::Reference< ucb::XCommandEnvironment >& xEnv, 3411 const std::auto_ptr< DAVResourceAccess > & rResAccess ) 3412 throw ( uno::Exception ) 3413 { 3414 if ( m_eResourceType == UNKNOWN ) 3415 { 3416 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3417 3418 ResourceType eResourceType; 3419 eResourceType = m_eResourceType; 3420 3421 const rtl::OUString & rURL = rResAccess->getURL(); 3422 const rtl::OUString aScheme( 3423 rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() ); 3424 3425 try 3426 { 3427 // Try to fetch some frequently used property value, e.g. those 3428 // used when loading documents... along with identifying whether 3429 // this is a DAV resource. 3430 std::vector< DAVResource > resources; 3431 std::vector< rtl::OUString > aPropNames; 3432 uno::Sequence< beans::Property > aProperties( 5 ); 3433 aProperties[ 0 ].Name 3434 = rtl::OUString::createFromAscii( "IsFolder" ); 3435 aProperties[ 1 ].Name 3436 = rtl::OUString::createFromAscii( "IsDocument" ); 3437 aProperties[ 2 ].Name 3438 = rtl::OUString::createFromAscii( "IsReadOnly" ); 3439 aProperties[ 3 ].Name 3440 = rtl::OUString::createFromAscii( "MediaType" ); 3441 aProperties[ 4 ].Name 3442 = DAVProperties::SUPPORTEDLOCK; 3443 3444 ContentProperties::UCBNamesToDAVNames( 3445 aProperties, aPropNames ); 3446 3447 rResAccess->PROPFIND( 3448 DAVZERO, aPropNames, resources, xEnv ); 3449 3450 // TODO - is this really only one? 3451 if ( resources.size() == 1 ) 3452 { 3453 m_xCachedProps.reset( 3454 new CachableContentProperties( resources[ 0 ] ) ); 3455 m_xCachedProps->containsAllNames( 3456 aProperties, m_aFailedPropNames ); 3457 } 3458 3459 eResourceType = DAV; 3460 } 3461 catch ( DAVException const & e ) 3462 { 3463 rResAccess->resetUri(); 3464 3465 if ( e.getStatus() == SC_METHOD_NOT_ALLOWED ) 3466 { 3467 // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the 3468 // resource is NON_DAV 3469 eResourceType = NON_DAV; 3470 } 3471 // cancel command execution is case that no user authentication data has been provided. 3472 if ( e.getError() == DAVException::DAV_HTTP_NOAUTH ) 3473 { 3474 cancelCommandExecution( e, uno::Reference< ucb::XCommandEnvironment >() ); 3475 } 3476 } 3477 m_eResourceType = eResourceType; 3478 } 3479 return m_eResourceType; 3480 } 3481 3482 //========================================================================= 3483 const Content::ResourceType & Content::getResourceType( 3484 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 3485 throw ( uno::Exception ) 3486 { 3487 return getResourceType( xEnv, m_xResAccess ); 3488 } 3489