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