1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_ucb.hxx" 30 31 /************************************************************************** 32 TODO 33 ************************************************************************** 34 35 *************************************************************************/ 36 #include <com/sun/star/beans/PropertyAttribute.hpp> 37 38 #include "ftpdynresultset.hxx" 39 #include "ftpresultsetfactory.hxx" 40 #include "ftpresultsetI.hxx" 41 #include "ftpcontent.hxx" 42 #include "ftpcontentprovider.hxx" 43 #include "ftpinpstr.hxx" 44 #include "ftpdirp.hxx" 45 #include "ftpcontentidentifier.hxx" 46 #include "ftpcfunc.hxx" 47 #include "ftpstrcont.hxx" 48 #include "ftpintreq.hxx" 49 50 #include <memory> 51 #include <vector> 52 #include <rtl/memory.h> 53 #include "curl.hxx" 54 #include <curl/easy.h> 55 #include <ucbhelper/cancelcommandexecution.hxx> 56 #include <ucbhelper/contentidentifier.hxx> 57 #include <ucbhelper/propertyvalueset.hxx> 58 #include <ucbhelper/contentidentifier.hxx> 59 #include <ucbhelper/cancelcommandexecution.hxx> 60 #include <ucbhelper/simpleauthenticationrequest.hxx> 61 #include <com/sun/star/lang/IllegalAccessException.hpp> 62 #include <com/sun/star/ucb/ContentInfoAttribute.hpp> 63 #include <com/sun/star/beans/UnknownPropertyException.hpp> 64 #include <com/sun/star/beans/Property.hpp> 65 #include <com/sun/star/beans/PropertyValue.hpp> 66 #include <com/sun/star/ucb/XCommandInfo.hpp> 67 #include <com/sun/star/io/XActiveDataSink.hpp> 68 #include <com/sun/star/io/XOutputStream.hpp> 69 #include <com/sun/star/io/XActiveDataStreamer.hpp> 70 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> 71 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 72 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> 73 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> 74 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> 75 #include <com/sun/star/ucb/InteractiveIOException.hpp> 76 #include <com/sun/star/ucb/MissingPropertiesException.hpp> 77 #include <com/sun/star/ucb/MissingInputStreamException.hpp> 78 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp> 79 #include <com/sun/star/ucb/NameClashException.hpp> 80 //#include <com/sun/star/ucb/NameClash.hpp> 81 #include <com/sun/star/ucb/OpenMode.hpp> 82 #include <com/sun/star/ucb/IOErrorCode.hpp> 83 84 using namespace ftp; 85 using namespace com::sun::star::task; 86 using namespace com::sun::star::container; 87 using namespace com::sun::star::lang; 88 using namespace com::sun::star::uno; 89 using namespace com::sun::star::ucb; 90 using namespace com::sun::star::beans; 91 using namespace com::sun::star::io; 92 using namespace com::sun::star::sdbc; 93 94 95 96 //========================================================================= 97 //========================================================================= 98 // 99 // Content Implementation. 100 // 101 //========================================================================= 102 //========================================================================= 103 104 FTPContent::FTPContent( const Reference< XMultiServiceFactory >& rxSMgr, 105 FTPContentProvider* pProvider, 106 const Reference< XContentIdentifier >& Identifier, 107 const FTPURL& aFTPURL) 108 : ContentImplHelper(rxSMgr,pProvider,Identifier), 109 m_pFCP(pProvider), 110 m_aFTPURL(aFTPURL), 111 m_bInserted(false), 112 m_bTitleSet(false) 113 { 114 } 115 116 117 118 FTPContent::FTPContent( const Reference< XMultiServiceFactory >& rxSMgr, 119 FTPContentProvider* pProvider, 120 const Reference< XContentIdentifier >& Identifier, 121 const ContentInfo& Info) 122 : ContentImplHelper(rxSMgr,pProvider,Identifier), 123 m_pFCP(pProvider), 124 m_aFTPURL(Identifier->getContentIdentifier(), 125 pProvider), 126 m_bInserted(true), 127 m_bTitleSet(false), 128 m_aInfo(Info) 129 { 130 } 131 132 133 134 //========================================================================= 135 136 FTPContent::~FTPContent() 137 { 138 } 139 140 141 //========================================================================= 142 // 143 // XInterface methods. 144 // 145 //========================================================================= 146 147 XINTERFACE_IMPL_6( FTPContent, 148 XTypeProvider, 149 XServiceInfo, 150 XContent, 151 XCommandProcessor, 152 XContentCreator, 153 XChild); 154 155 //========================================================================= 156 // 157 // XTypeProvider methods. 158 // 159 //========================================================================= 160 161 XTYPEPROVIDER_IMPL_6( FTPContent, 162 XTypeProvider, 163 XServiceInfo, 164 XContent, 165 XCommandProcessor, 166 XContentCreator, 167 XChild); 168 169 //========================================================================= 170 // 171 // XServiceInfo methods. 172 // 173 //========================================================================= 174 175 // needed, because the service shall not be creatable!! 176 #undef XSERVICEINFO_CREATE_INSTANCE_IMPL 177 #define XSERVICEINFO_CREATE_INSTANCE_IMPL( Class ) 178 179 XSERVICEINFO_IMPL_1( FTPContent, 180 rtl::OUString::createFromAscii( 181 "com.sun.star.comp.FTPContent"), 182 rtl::OUString::createFromAscii( 183 "com.sun.star.ucb.FTPContent")); 184 185 186 187 //========================================================================= 188 // 189 // XContent methods. 190 // 191 //========================================================================= 192 193 // virtual 194 rtl::OUString SAL_CALL FTPContent::getContentType() 195 throw( RuntimeException ) 196 { 197 return rtl::OUString::createFromAscii(FTP_CONTENT_TYPE); 198 } 199 200 201 //========================================================================= 202 // 203 // XCommandProcessor methods. 204 // 205 //========================================================================= 206 207 208 //virtual 209 void SAL_CALL FTPContent::abort( sal_Int32 /*CommandId*/ ) 210 throw( RuntimeException ) 211 { 212 } 213 214 215 216 /***************************************************************************/ 217 /* */ 218 /* Internal implementation class. */ 219 /* */ 220 /***************************************************************************/ 221 222 223 class ResultSetFactoryI 224 : public ResultSetFactory 225 { 226 public: 227 228 ResultSetFactoryI(const Reference<XMultiServiceFactory >& xSMgr, 229 const Reference<XContentProvider >& xProvider, 230 sal_Int32 nOpenMode, 231 const Sequence<Property>& seq, 232 const Sequence<NumberedSortingInfo>& seqSort, 233 const std::vector<FTPDirentry>& dirvec) 234 : m_xSMgr(xSMgr), 235 m_xProvider(xProvider), 236 m_nOpenMode(nOpenMode), 237 m_seq(seq), 238 m_seqSort(seqSort), 239 m_dirvec(dirvec) 240 { 241 } 242 243 virtual ResultSetBase* createResultSet() 244 { 245 return new ResultSetI(m_xSMgr, 246 m_xProvider, 247 m_nOpenMode, 248 m_seq, 249 m_seqSort, 250 m_dirvec); 251 } 252 253 public: 254 255 Reference< XMultiServiceFactory > m_xSMgr; 256 Reference< XContentProvider > m_xProvider; 257 sal_Int32 m_nOpenMode; 258 Sequence< Property > m_seq; 259 Sequence< NumberedSortingInfo > m_seqSort; 260 std::vector<FTPDirentry> m_dirvec; 261 }; 262 263 264 265 //========================================================================= 266 // 267 // XCommandProcessor methods. 268 // 269 //========================================================================= 270 271 enum ACTION { NOACTION, 272 THROWAUTHENTICATIONREQUEST, 273 THROWACCESSDENIED, 274 THROWINTERACTIVECONNECT, 275 THROWRESOLVENAME, 276 THROWQUOTE, 277 THROWNOFILE, 278 THROWGENERAL }; 279 280 281 // virtual 282 Any SAL_CALL FTPContent::execute( 283 const Command& aCommand, 284 sal_Int32 /*CommandId*/, 285 const Reference< 286 XCommandEnvironment >& Environment 287 ) 288 throw( 289 Exception, 290 CommandAbortedException, 291 RuntimeException 292 ) 293 { 294 ACTION action(NOACTION); 295 Any aRet; 296 297 while(true) 298 try { 299 if(action == THROWAUTHENTICATIONREQUEST) { 300 // try to get a continuation first 301 rtl::OUString aRealm,aPassword,aAccount; 302 m_pFCP->forHost(m_aFTPURL.host(), 303 m_aFTPURL.port(), 304 m_aFTPURL.username(), 305 aPassword, 306 aAccount); 307 rtl::Reference<ucbhelper::SimpleAuthenticationRequest> 308 p( new ucbhelper::SimpleAuthenticationRequest( 309 m_aFTPURL.ident(false, false), 310 m_aFTPURL.host(), // ServerName 311 ucbhelper::SimpleAuthenticationRequest::ENTITY_NA, 312 aRealm, 313 ucbhelper::SimpleAuthenticationRequest 314 ::ENTITY_FIXED, 315 m_aFTPURL.username(), 316 ucbhelper::SimpleAuthenticationRequest 317 ::ENTITY_MODIFY, 318 aPassword)); 319 320 Reference<XInteractionHandler> xInteractionHandler; 321 if(Environment.is()) 322 xInteractionHandler = 323 Environment->getInteractionHandler(); 324 325 if( xInteractionHandler.is()) { 326 xInteractionHandler->handle(p.get()); 327 328 Reference<XInterface> xSelection( 329 p->getSelection().get()); 330 331 if(Reference<XInteractionRetry>( 332 xSelection,UNO_QUERY).is()) 333 action = NOACTION; 334 else if(Reference<XInteractionSupplyAuthentication>( 335 xSelection,UNO_QUERY).is()) { 336 m_pFCP->setHost( 337 m_aFTPURL.host(), 338 m_aFTPURL.port(), 339 m_aFTPURL.username(), 340 p->getAuthenticationSupplier()->getPassword(), 341 aAccount); 342 action = NOACTION; 343 } 344 } 345 aRet = p->getRequest(); 346 } 347 348 // if(aCommand.Name.compareToAscii( 349 // "getPropertyValues") == 0 && 350 // action != NOACTION) { 351 // // It is not allowed to throw if 352 // // command is getPropertyValues 353 // rtl::Reference<ucbhelper::PropertyValueSet> xRow = 354 // new ucbhelper::PropertyValueSet(m_xSMgr); 355 // Sequence<Property> Properties; 356 // aCommand.Argument >>= Properties; 357 // for(int i = 0; i < Properties.getLength(); ++i) 358 // xRow->appendVoid(Properties[i]); 359 // aRet <<= Reference<XRow>(xRow.get()); 360 // return aRet; 361 // } 362 363 switch (action) 364 { 365 case NOACTION: 366 break; 367 368 case THROWAUTHENTICATIONREQUEST: 369 ucbhelper::cancelCommandExecution( 370 aRet, 371 Reference<XCommandEnvironment>(0)); 372 break; 373 374 case THROWACCESSDENIED: 375 { 376 Sequence<Any> seq(1); 377 PropertyValue value; 378 value.Name = rtl::OUString::createFromAscii("Uri"); 379 value.Handle = -1; 380 value.Value <<= m_aFTPURL.ident(false,false); 381 value.State = PropertyState_DIRECT_VALUE; 382 seq[0] <<= value; 383 ucbhelper::cancelCommandExecution( 384 IOErrorCode_ACCESS_DENIED, 385 seq, 386 Environment); 387 break; 388 } 389 case THROWINTERACTIVECONNECT: 390 { 391 InteractiveNetworkConnectException excep; 392 excep.Server = m_aFTPURL.host(); 393 aRet <<= excep; 394 ucbhelper::cancelCommandExecution( 395 aRet, 396 Environment); 397 break; 398 } 399 case THROWRESOLVENAME: 400 { 401 InteractiveNetworkResolveNameException excep; 402 excep.Server = m_aFTPURL.host(); 403 aRet <<= excep; 404 ucbhelper::cancelCommandExecution( 405 aRet, 406 Environment); 407 break; 408 } 409 case THROWNOFILE: 410 { 411 Sequence<Any> seq(1); 412 PropertyValue value; 413 value.Name = rtl::OUString::createFromAscii("Uri"); 414 value.Handle = -1; 415 value.Value <<= m_aFTPURL.ident(false,false); 416 value.State = PropertyState_DIRECT_VALUE; 417 seq[0] <<= value; 418 ucbhelper::cancelCommandExecution( 419 IOErrorCode_NO_FILE, 420 seq, 421 Environment); 422 break; 423 } 424 case THROWQUOTE: 425 case THROWGENERAL: 426 ucbhelper::cancelCommandExecution( 427 IOErrorCode_GENERAL, 428 Sequence<Any>(0), 429 Environment); 430 break; 431 } 432 433 if(aCommand.Name.compareToAscii("getPropertyValues") == 0) { 434 Sequence<Property> Properties; 435 if(!(aCommand.Argument >>= Properties)) 436 { 437 aRet <<= IllegalArgumentException( 438 rtl::OUString::createFromAscii( 439 "Wrong argument type!" ), 440 static_cast< cppu::OWeakObject * >(this), 441 -1); 442 ucbhelper::cancelCommandExecution(aRet,Environment); 443 } 444 445 aRet <<= getPropertyValues(Properties,Environment); 446 } 447 else if(aCommand.Name.compareToAscii("setPropertyValues") == 0) 448 { 449 Sequence<PropertyValue> propertyValues; 450 451 if( ! ( aCommand.Argument >>= propertyValues ) ) { 452 aRet <<= IllegalArgumentException( 453 rtl::OUString::createFromAscii( 454 "Wrong argument type!" ), 455 static_cast< cppu::OWeakObject * >(this), 456 -1); 457 ucbhelper::cancelCommandExecution(aRet,Environment); 458 } 459 460 aRet <<= setPropertyValues(propertyValues); 461 } 462 else if(aCommand.Name.compareToAscii("getCommandInfo") == 0) { 463 // Note: Implemented by base class. 464 aRet <<= getCommandInfo(Environment); 465 } 466 else if(aCommand.Name.compareToAscii("getPropertySetInfo") == 0) { 467 // Note: Implemented by base class. 468 aRet <<= getPropertySetInfo(Environment); 469 } 470 else if(aCommand.Name.compareToAscii( "insert" ) == 0) 471 { 472 InsertCommandArgument aInsertArgument; 473 if ( ! ( aCommand.Argument >>= aInsertArgument ) ) { 474 aRet <<= IllegalArgumentException( 475 rtl::OUString::createFromAscii( 476 "Wrong argument type!" ), 477 static_cast< cppu::OWeakObject * >(this), 478 -1); 479 ucbhelper::cancelCommandExecution(aRet,Environment); 480 } 481 insert(aInsertArgument,Environment); 482 } 483 else if(aCommand.Name.compareToAscii("delete") == 0) { 484 m_aFTPURL.del(); 485 deleted(); 486 } 487 else if(aCommand.Name.compareToAscii( "open" ) == 0) { 488 OpenCommandArgument2 aOpenCommand; 489 if ( !( aCommand.Argument >>= aOpenCommand ) ) { 490 aRet <<= IllegalArgumentException( 491 rtl::OUString::createFromAscii( 492 "Wrong argument type!" ), 493 static_cast< cppu::OWeakObject * >(this), 494 -1); 495 496 ucbhelper::cancelCommandExecution(aRet,Environment); 497 } 498 499 if(aOpenCommand.Mode == OpenMode::DOCUMENT) { 500 // Open as a document 501 Reference<XActiveDataSink> 502 xActiveDataSink(aOpenCommand.Sink,UNO_QUERY); 503 Reference< XOutputStream > 504 xOutputStream(aOpenCommand.Sink,UNO_QUERY); 505 506 if(xActiveDataSink.is()) { 507 xActiveDataSink->setInputStream( 508 new FTPInputStream(m_aFTPURL.open())); 509 } 510 else if(xOutputStream.is()) { 511 Reference<XInputStream> xStream( 512 new FTPInputStream(m_aFTPURL.open())); 513 Sequence<sal_Int8> byte_seq(4096); 514 sal_Int32 n = 1000; // value does not matter here 515 for (;;) { 516 n = xStream->readBytes(byte_seq,4096); 517 if (n == 0) { 518 break; 519 } 520 try { 521 if(byte_seq.getLength() != n) 522 byte_seq.realloc(n); 523 xOutputStream->writeBytes(byte_seq); 524 } catch(const NotConnectedException&) { 525 526 } catch(const BufferSizeExceededException&) { 527 528 } catch(const IOException&) { 529 530 } 531 } 532 if(n) { 533 Sequence<Any> seq(1); 534 PropertyValue value; 535 value.Name = 536 rtl::OUString::createFromAscii("Uri"); 537 value.Handle = -1; 538 value.Value <<= m_aFTPURL.ident(false,false); 539 value.State = PropertyState_DIRECT_VALUE; 540 seq[0] <<= value; 541 ucbhelper::cancelCommandExecution( 542 IOErrorCode_UNKNOWN, 543 seq, 544 Environment); 545 } 546 } 547 else { 548 aRet <<= UnsupportedDataSinkException( 549 rtl::OUString(), 550 static_cast< cppu::OWeakObject * >(this), 551 aOpenCommand.Sink); 552 ucbhelper::cancelCommandExecution(aRet,Environment); 553 } 554 } 555 else if(aOpenCommand.Mode == OpenMode::ALL || 556 aOpenCommand.Mode == OpenMode::DOCUMENTS || 557 aOpenCommand.Mode == OpenMode::FOLDERS ) { 558 std::vector<FTPDirentry> resvec = 559 m_aFTPURL.list(sal_Int16(aOpenCommand.Mode)); 560 Reference< XDynamicResultSet > xSet 561 = new DynamicResultSet( 562 m_xSMgr, 563 this, 564 aOpenCommand, 565 Environment, 566 new ResultSetFactoryI(m_xSMgr, 567 m_xProvider.get(), 568 aOpenCommand.Mode, 569 aOpenCommand.Properties, 570 aOpenCommand.SortingInfo, 571 resvec)); 572 aRet <<= xSet; 573 } 574 else if(aOpenCommand.Mode == 575 OpenMode::DOCUMENT_SHARE_DENY_NONE || 576 aOpenCommand.Mode == 577 OpenMode::DOCUMENT_SHARE_DENY_WRITE) { 578 // Unsupported OpenMode 579 aRet <<= UnsupportedOpenModeException( 580 rtl::OUString(), 581 static_cast< cppu::OWeakObject * >(this), 582 static_cast< sal_Int16 >(aOpenCommand.Mode)); 583 ucbhelper::cancelCommandExecution(aRet,Environment); 584 } 585 else { 586 aRet <<= IllegalArgumentException( 587 rtl::OUString::createFromAscii( 588 "Unexpected OpenMode!" ), 589 static_cast< cppu::OWeakObject * >(this), 590 -1); 591 592 ucbhelper::cancelCommandExecution(aRet,Environment); 593 } 594 } else if(aCommand.Name.compareToAscii("createNewContent") == 0) { 595 ContentInfo aArg; 596 if (!(aCommand.Argument >>= aArg)) { 597 ucbhelper::cancelCommandExecution( 598 makeAny( 599 IllegalArgumentException( 600 rtl::OUString::createFromAscii( 601 "Wrong argument type!" ), 602 static_cast< cppu::OWeakObject * >(this), 603 -1)), 604 Environment); 605 // Unreachable 606 } 607 aRet <<= createNewContent(aArg); 608 } else { 609 aRet <<= UnsupportedCommandException( 610 aCommand.Name, 611 static_cast< cppu::OWeakObject * >(this)); 612 ucbhelper::cancelCommandExecution(aRet,Environment); 613 } 614 615 return aRet; 616 } catch(const curl_exception& e) { 617 if(e.code() == CURLE_COULDNT_CONNECT) 618 action = THROWINTERACTIVECONNECT; 619 else if(e.code() == CURLE_COULDNT_RESOLVE_HOST ) 620 action = THROWRESOLVENAME; 621 else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT || 622 e.code() == CURLE_LOGIN_DENIED || 623 e.code() == CURLE_BAD_PASSWORD_ENTERED || 624 e.code() == CURLE_FTP_WEIRD_PASS_REPLY) 625 action = THROWAUTHENTICATIONREQUEST; 626 else if(e.code() == CURLE_FTP_ACCESS_DENIED) 627 action = THROWACCESSDENIED; 628 else if(e.code() == CURLE_FTP_QUOTE_ERROR) 629 action = THROWQUOTE; 630 else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE) 631 action = THROWNOFILE; 632 else 633 // nothing known about the cause of the error 634 action = THROWGENERAL; 635 } 636 } 637 638 #define FTP_FILE rtl::OUString::createFromAscii( \ 639 "application/" \ 640 "vnd.sun.staroffice.ftp-file") 641 642 #define FTP_FOLDER rtl::OUString::createFromAscii( \ 643 "application/" \ 644 "vnd.sun.staroffice.ftp-folder") 645 646 Sequence<ContentInfo > SAL_CALL 647 FTPContent::queryCreatableContentsInfo( ) 648 throw (RuntimeException) 649 { 650 return queryCreatableContentsInfo_Static(); 651 } 652 653 // static 654 Sequence<ContentInfo > 655 FTPContent::queryCreatableContentsInfo_Static( ) 656 throw (RuntimeException) 657 { 658 Sequence< ContentInfo > seq(2); 659 660 seq[0].Type = FTP_FILE; 661 seq[0].Attributes = ContentInfoAttribute::INSERT_WITH_INPUTSTREAM 662 | ContentInfoAttribute::KIND_DOCUMENT; 663 Sequence< Property > props( 1 ); 664 props[0] = Property( 665 rtl::OUString::createFromAscii( "Title" ), 666 -1, 667 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 668 PropertyAttribute::MAYBEVOID 669 | PropertyAttribute::BOUND ); 670 seq[0].Properties = props; 671 672 // folder 673 seq[1].Type = FTP_FOLDER; 674 seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER; 675 seq[1].Properties = props; 676 677 return seq; 678 } 679 680 Reference<XContent > SAL_CALL 681 FTPContent::createNewContent( const ContentInfo& Info ) 682 throw (RuntimeException) 683 { 684 if(Info.Type.equalsAscii("application/" 685 "vnd.sun.staroffice.ftp-file") || 686 Info.Type.equalsAscii("application/" 687 "vnd.sun.staroffice.ftp-folder")) 688 return new FTPContent(m_xSMgr, 689 m_pFCP, 690 m_xIdentifier,Info); 691 else 692 return Reference<XContent>(0); 693 } 694 695 696 697 698 Reference<XInterface > SAL_CALL 699 FTPContent::getParent( ) 700 throw (RuntimeException) 701 { 702 Reference<XContentIdentifier> 703 xIdent(new FTPContentIdentifier(m_aFTPURL.parent(false))); 704 Reference<XContent> xContent(m_xProvider->queryContent(xIdent)); 705 return Reference<XInterface>(xContent,UNO_QUERY); 706 } 707 708 709 void SAL_CALL 710 FTPContent::setParent(const Reference<XInterface >& /*Parent*/ ) 711 throw (NoSupportException, 712 RuntimeException) 713 { 714 throw NoSupportException(); 715 } 716 717 718 719 rtl::OUString FTPContent::getParentURL() 720 { 721 return m_aFTPURL.parent(); 722 } 723 724 725 class InsertData 726 : public CurlInput { 727 728 public: 729 730 InsertData(const Reference<XInputStream>& xInputStream) 731 : m_xInputStream(xInputStream) { } 732 virtual ~InsertData() {} 733 734 // returns the number of bytes actually read 735 virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested); 736 737 private: 738 739 Reference<XInputStream> m_xInputStream; 740 }; 741 742 743 744 sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested) 745 { 746 sal_Int32 m = 0; 747 748 if(m_xInputStream.is()) { 749 Sequence<sal_Int8> seq(nBytesRequested); 750 m = m_xInputStream->readBytes(seq,nBytesRequested); 751 rtl_copyMemory(dest,seq.getConstArray(),m); 752 } 753 return m; 754 } 755 756 757 void FTPContent::insert(const InsertCommandArgument& aInsertCommand, 758 const Reference<XCommandEnvironment>& Env) 759 { 760 osl::MutexGuard aGuard(m_aMutex); 761 762 if(m_bInserted && !m_bTitleSet) { 763 MissingPropertiesException excep; 764 excep.Properties.realloc(1); 765 excep.Properties[0] = rtl::OUString::createFromAscii("Title"); 766 Any aAny; aAny <<= excep; 767 ucbhelper::cancelCommandExecution(aAny,Env); 768 } 769 770 if(m_bInserted && 771 m_aInfo.Type == FTP_FILE && 772 !aInsertCommand.Data.is()) 773 { 774 MissingInputStreamException excep; 775 Any aAny; aAny <<= excep; 776 ucbhelper::cancelCommandExecution(aAny,Env); 777 } 778 779 bool bReplace(aInsertCommand.ReplaceExisting); 780 781 retry: 782 try { 783 if(m_aInfo.Type == FTP_FILE) { 784 InsertData data(aInsertCommand.Data); 785 m_aFTPURL.insert(bReplace,&data); 786 } else if(m_aInfo.Type == FTP_FOLDER) 787 m_aFTPURL.mkdir(bReplace); 788 } catch(const curl_exception& e) { 789 if(e.code() == FILE_EXIST_DURING_INSERT || 790 e.code() == FOLDER_EXIST_DURING_INSERT) { 791 // Deprecated, not used anymore: 792 NameClashException excep; 793 excep.Name = m_aFTPURL.child(); 794 Any aAny; 795 aAny <<= excep; 796 ucbhelper::cancelCommandExecution(aAny,Env); 797 } else if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT || 798 e.code() == FILE_MIGHT_EXIST_DURING_INSERT) { 799 // Interact 800 Reference<XInteractionHandler> xInt; 801 if(Env.is()) 802 xInt = Env->getInteractionHandler(); 803 804 UnsupportedNameClashException excep; 805 excep.NameClash = 0; //NameClash::ERROR; 806 807 if(!xInt.is()) { 808 Any aAny; 809 aAny <<= excep; 810 ucbhelper::cancelCommandExecution(aAny,Env); 811 } 812 813 XInteractionRequestImpl* p = 814 new XInteractionRequestImpl(m_aFTPURL.child()); 815 Reference<XInteractionRequest> req(p); 816 xInt->handle(req); 817 if(p->approved()) { 818 bReplace = true; 819 goto retry; 820 } 821 else 822 throw excep; 823 } 824 else 825 throw; 826 } 827 828 // May not be reached, because both mkdir and insert can throw curl- 829 // exceptions 830 m_bInserted = false; 831 inserted(); 832 } 833 834 835 836 Reference< XRow > FTPContent::getPropertyValues( 837 const Sequence< Property >& seqProp, 838 const Reference<XCommandEnvironment>& /*environment*/ 839 ) 840 { 841 rtl::Reference<ucbhelper::PropertyValueSet> xRow = 842 new ucbhelper::PropertyValueSet(m_xSMgr); 843 844 FTPDirentry aDirEntry = m_aFTPURL.direntry(); 845 846 for(sal_Int32 i = 0; i < seqProp.getLength(); ++i) { 847 const rtl::OUString& Name = seqProp[i].Name; 848 if(Name.compareToAscii("Title") == 0) 849 xRow->appendString(seqProp[i],aDirEntry.m_aName); 850 else if(Name.compareToAscii("CreatableContentsInfo") == 0) 851 xRow->appendObject(seqProp[i], 852 makeAny(queryCreatableContentsInfo())); 853 else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) { 854 if(Name.compareToAscii("ContentType") == 0) 855 xRow->appendString(seqProp[i], 856 aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR 857 ? FTP_FOLDER 858 : FTP_FILE ); 859 else if(Name.compareToAscii("IsReadOnly") == 0) 860 xRow->appendBoolean(seqProp[i], 861 aDirEntry.m_nMode 862 & INETCOREFTP_FILEMODE_WRITE 863 ? 0 864 : 1 ); 865 else if(Name.compareToAscii("IsDocument") == 0) 866 xRow->appendBoolean(seqProp[i], 867 ! sal_Bool(aDirEntry.m_nMode & 868 INETCOREFTP_FILEMODE_ISDIR)); 869 else if(Name.compareToAscii("IsFolder") == 0) 870 xRow->appendBoolean(seqProp[i], 871 sal_Bool(aDirEntry.m_nMode & 872 INETCOREFTP_FILEMODE_ISDIR)); 873 else if(Name.compareToAscii("Size") == 0) 874 xRow->appendLong(seqProp[i], 875 aDirEntry.m_nSize); 876 else if(Name.compareToAscii("DateCreated") == 0) 877 xRow->appendTimestamp(seqProp[i], 878 aDirEntry.m_aDate); 879 else 880 xRow->appendVoid(seqProp[i]); 881 } else 882 xRow->appendVoid(seqProp[i]); 883 } 884 885 return Reference<XRow>(xRow.get()); 886 } 887 888 889 890 Sequence<Any> FTPContent::setPropertyValues( 891 const Sequence<PropertyValue>& seqPropVal) 892 { 893 Sequence<Any> ret(seqPropVal.getLength()); 894 Sequence<PropertyChangeEvent > evt; 895 896 osl::MutexGuard aGuard(m_aMutex); 897 for(sal_Int32 i = 0; i < ret.getLength(); ++i) { 898 if(seqPropVal[i].Name.equalsAscii("Title")) { 899 rtl::OUString Title; 900 if(!(seqPropVal[i].Value >>= Title)) { 901 ret[i] <<= IllegalTypeException(); 902 continue; 903 } else if(!Title.getLength()) { 904 ret[i] <<= IllegalArgumentException(); 905 continue; 906 } 907 908 if(m_bInserted) { 909 m_aFTPURL.child(Title); 910 m_xIdentifier = 911 new FTPContentIdentifier(m_aFTPURL.ident(false,false)); 912 m_bTitleSet = true; 913 } else 914 try { 915 rtl::OUString OldTitle = m_aFTPURL.ren(Title); 916 evt.realloc(1); 917 evt[0].PropertyName = 918 rtl::OUString::createFromAscii("Title"); 919 evt[0].Further = false; 920 evt[0].PropertyHandle = -1; 921 evt[0].OldValue <<= OldTitle; 922 evt[0].NewValue <<= Title; 923 } catch(const curl_exception&) { 924 InteractiveIOException excep; 925 // any better possibility here? 926 // ( the error code is always CURLE_FTP_QUOTE_ERROR ) 927 excep.Code = IOErrorCode_ACCESS_DENIED; 928 ret[i] <<= excep; 929 } 930 } else { 931 Sequence<Property> props = 932 getProperties(Reference<XCommandEnvironment>(0)); 933 934 // either unknown or read-only 935 ret[i] <<= UnknownPropertyException(); 936 for(sal_Int32 j = 0; j < props.getLength(); ++j) 937 if(props[j].Name == seqPropVal[i].Name) { 938 ret[i] <<= IllegalAccessException( 939 rtl::OUString::createFromAscii( 940 "Property is read-only!"), 941 //props[j].Attributes & PropertyAttribute::READONLY 942 // ? "Property is read-only!" 943 // : "Access denied!"), 944 static_cast< cppu::OWeakObject * >( this )); 945 break; 946 } 947 } 948 } 949 950 if(evt.getLength()) { 951 // title has changed 952 notifyPropertiesChange(evt); 953 exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false))); 954 } 955 956 return ret; 957 } 958