Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / ucb / source / ucp / ftp / ftpcontent.cxx
blob7a791ede90931846b0562cd3efc0638be6626623
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
22 TODO
23 **************************************************************************
25 *************************************************************************/
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include "ftpdynresultset.hxx"
29 #include "ftpresultsetfactory.hxx"
30 #include "ftpresultsetI.hxx"
31 #include "ftpcontent.hxx"
32 #include "ftpcontentprovider.hxx"
33 #include "ftpdirp.hxx"
34 #include "ftpcontentidentifier.hxx"
35 #include "ftpcfunc.hxx"
36 #include "ftpstrcont.hxx"
37 #include "ftpintreq.hxx"
39 #include <memory>
40 #include <vector>
41 #include <string.h>
42 #include "curl.hxx"
43 #include <curl/easy.h>
44 #include <comphelper/processfactory.hxx>
45 #include <ucbhelper/cancelcommandexecution.hxx>
46 #include <ucbhelper/contentidentifier.hxx>
47 #include <ucbhelper/fd_inputstream.hxx>
48 #include <ucbhelper/propertyvalueset.hxx>
49 #include <ucbhelper/contentidentifier.hxx>
50 #include <ucbhelper/cancelcommandexecution.hxx>
51 #include <ucbhelper/simpleauthenticationrequest.hxx>
52 #include <com/sun/star/lang/IllegalAccessException.hpp>
53 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
54 #include <com/sun/star/beans/UnknownPropertyException.hpp>
55 #include <com/sun/star/beans/Property.hpp>
56 #include <com/sun/star/beans/PropertyValue.hpp>
57 #include <com/sun/star/ucb/XCommandInfo.hpp>
58 #include <com/sun/star/io/XActiveDataSink.hpp>
59 #include <com/sun/star/io/XOutputStream.hpp>
60 #include <com/sun/star/io/XActiveDataStreamer.hpp>
61 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
62 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
63 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
64 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
65 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
66 #include <com/sun/star/ucb/InteractiveIOException.hpp>
67 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
68 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
69 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
70 #include <com/sun/star/ucb/NameClashException.hpp>
71 #include <com/sun/star/ucb/OpenMode.hpp>
72 #include <com/sun/star/ucb/IOErrorCode.hpp>
74 using namespace ftp;
75 using namespace com::sun::star::task;
76 using namespace com::sun::star::container;
77 using namespace com::sun::star::lang;
78 using namespace com::sun::star::uno;
79 using namespace com::sun::star::ucb;
80 using namespace com::sun::star::beans;
81 using namespace com::sun::star::io;
82 using namespace com::sun::star::sdbc;
86 //=========================================================================
87 //=========================================================================
89 // Content Implementation.
91 //=========================================================================
92 //=========================================================================
94 FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
95 FTPContentProvider* pProvider,
96 const Reference< XContentIdentifier >& Identifier,
97 const FTPURL& aFTPURL)
98 : ContentImplHelper(rxContext,pProvider,Identifier),
99 m_pFCP(pProvider),
100 m_aFTPURL(aFTPURL),
101 m_bInserted(false),
102 m_bTitleSet(false)
108 FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
109 FTPContentProvider* pProvider,
110 const Reference< XContentIdentifier >& Identifier,
111 const ContentInfo& Info)
112 : ContentImplHelper(rxContext,pProvider,Identifier),
113 m_pFCP(pProvider),
114 m_aFTPURL(Identifier->getContentIdentifier(),
115 pProvider),
116 m_bInserted(true),
117 m_bTitleSet(false),
118 m_aInfo(Info)
124 //=========================================================================
126 FTPContent::~FTPContent()
131 //=========================================================================
133 // XInterface methods.
135 //=========================================================================
137 XINTERFACE_IMPL_6( FTPContent,
138 XTypeProvider,
139 XServiceInfo,
140 XContent,
141 XCommandProcessor,
142 XContentCreator,
143 XChild);
145 //=========================================================================
147 // XTypeProvider methods.
149 //=========================================================================
151 XTYPEPROVIDER_IMPL_6( FTPContent,
152 XTypeProvider,
153 XServiceInfo,
154 XContent,
155 XCommandProcessor,
156 XContentCreator,
157 XChild);
159 //=========================================================================
161 // XServiceInfo methods.
163 //=========================================================================
165 // needed, because the service shall not be creatable!!
166 #undef XSERVICEINFO_CREATE_INSTANCE_IMPL
167 #define XSERVICEINFO_CREATE_INSTANCE_IMPL( Class )
169 XSERVICEINFO_IMPL_1( FTPContent,
170 rtl::OUString( "com.sun.star.comp.FTPContent"),
171 rtl::OUString( "com.sun.star.ucb.FTPContent"));
175 //=========================================================================
177 // XContent methods.
179 //=========================================================================
181 // virtual
182 rtl::OUString SAL_CALL FTPContent::getContentType()
183 throw( RuntimeException )
185 return rtl::OUString(FTP_CONTENT_TYPE);
189 //=========================================================================
191 // XCommandProcessor methods.
193 //=========================================================================
196 //virtual
197 void SAL_CALL FTPContent::abort( sal_Int32 /*CommandId*/ )
198 throw( RuntimeException )
204 /***************************************************************************/
205 /* */
206 /* Internal implementation class. */
207 /* */
208 /***************************************************************************/
211 class ResultSetFactoryI
212 : public ResultSetFactory
214 public:
216 ResultSetFactoryI(const Reference<XComponentContext >& rxContext,
217 const Reference<XContentProvider >& xProvider,
218 sal_Int32 nOpenMode,
219 const Sequence<Property>& seq,
220 const Sequence<NumberedSortingInfo>& seqSort,
221 const std::vector<FTPDirentry>& dirvec)
222 : m_xContext(rxContext),
223 m_xProvider(xProvider),
224 m_nOpenMode(nOpenMode),
225 m_seq(seq),
226 m_seqSort(seqSort),
227 m_dirvec(dirvec)
231 virtual ResultSetBase* createResultSet()
233 return new ResultSetI(m_xContext,
234 m_xProvider,
235 m_nOpenMode,
236 m_seq,
237 m_seqSort,
238 m_dirvec);
241 public:
243 Reference< XComponentContext > m_xContext;
244 Reference< XContentProvider > m_xProvider;
245 sal_Int32 m_nOpenMode;
246 Sequence< Property > m_seq;
247 Sequence< NumberedSortingInfo > m_seqSort;
248 std::vector<FTPDirentry> m_dirvec;
253 //=========================================================================
255 // XCommandProcessor methods.
257 //=========================================================================
259 enum ACTION { NOACTION,
260 THROWAUTHENTICATIONREQUEST,
261 THROWACCESSDENIED,
262 THROWINTERACTIVECONNECT,
263 THROWRESOLVENAME,
264 THROWQUOTE,
265 THROWNOFILE,
266 THROWGENERAL };
269 // virtual
270 Any SAL_CALL FTPContent::execute(
271 const Command& aCommand,
272 sal_Int32 /*CommandId*/,
273 const Reference<
274 XCommandEnvironment >& Environment
276 throw(
277 Exception,
278 CommandAbortedException,
279 RuntimeException
282 ACTION action(NOACTION);
283 Any aRet;
285 while(true)
286 try {
287 if(action == THROWAUTHENTICATIONREQUEST) {
288 // try to get a continuation first
289 rtl::OUString aRealm,aPassword,aAccount;
290 m_pFCP->forHost(m_aFTPURL.host(),
291 m_aFTPURL.port(),
292 m_aFTPURL.username(),
293 aPassword,
294 aAccount);
295 rtl::Reference<ucbhelper::SimpleAuthenticationRequest>
296 p( new ucbhelper::SimpleAuthenticationRequest(
297 m_aFTPURL.ident(false, false),
298 m_aFTPURL.host(), // ServerName
299 ucbhelper::SimpleAuthenticationRequest::ENTITY_NA,
300 aRealm,
301 ucbhelper::SimpleAuthenticationRequest
302 ::ENTITY_FIXED,
303 m_aFTPURL.username(),
304 ucbhelper::SimpleAuthenticationRequest
305 ::ENTITY_MODIFY,
306 aPassword));
308 Reference<XInteractionHandler> xInteractionHandler;
309 if(Environment.is())
310 xInteractionHandler =
311 Environment->getInteractionHandler();
313 if( xInteractionHandler.is()) {
314 xInteractionHandler->handle(p.get());
316 Reference<XInterface> xSelection(
317 p->getSelection().get());
319 if(Reference<XInteractionRetry>(
320 xSelection,UNO_QUERY).is())
321 action = NOACTION;
322 else if(Reference<XInteractionSupplyAuthentication>(
323 xSelection,UNO_QUERY).is()) {
324 m_pFCP->setHost(
325 m_aFTPURL.host(),
326 m_aFTPURL.port(),
327 m_aFTPURL.username(),
328 p->getAuthenticationSupplier()->getPassword(),
329 aAccount);
330 action = NOACTION;
333 aRet = p->getRequest();
336 // if(aCommand.Name.compareToAscii(
337 // "getPropertyValues") == 0 &&
338 // action != NOACTION) {
339 // // It is not allowed to throw if
340 // // command is getPropertyValues
341 // rtl::Reference<ucbhelper::PropertyValueSet> xRow =
342 // new ucbhelper::PropertyValueSet(m_xSMgr);
343 // Sequence<Property> Properties;
344 // aCommand.Argument >>= Properties;
345 // for(int i = 0; i < Properties.getLength(); ++i)
346 // xRow->appendVoid(Properties[i]);
347 // aRet <<= Reference<XRow>(xRow.get());
348 // return aRet;
349 // }
351 switch (action)
353 case NOACTION:
354 break;
356 case THROWAUTHENTICATIONREQUEST:
357 ucbhelper::cancelCommandExecution(
358 aRet,
359 Reference<XCommandEnvironment>(0));
360 break;
362 case THROWACCESSDENIED:
364 Sequence<Any> seq(1);
365 PropertyValue value;
366 value.Name = rtl::OUString("Uri");
367 value.Handle = -1;
368 value.Value <<= m_aFTPURL.ident(false,false);
369 value.State = PropertyState_DIRECT_VALUE;
370 seq[0] <<= value;
371 ucbhelper::cancelCommandExecution(
372 IOErrorCode_ACCESS_DENIED,
373 seq,
374 Environment);
375 break;
377 case THROWINTERACTIVECONNECT:
379 InteractiveNetworkConnectException excep;
380 excep.Server = m_aFTPURL.host();
381 aRet <<= excep;
382 ucbhelper::cancelCommandExecution(
383 aRet,
384 Environment);
385 break;
387 case THROWRESOLVENAME:
389 InteractiveNetworkResolveNameException excep;
390 excep.Server = m_aFTPURL.host();
391 aRet <<= excep;
392 ucbhelper::cancelCommandExecution(
393 aRet,
394 Environment);
395 break;
397 case THROWNOFILE:
399 Sequence<Any> seq(1);
400 PropertyValue value;
401 value.Name = rtl::OUString("Uri");
402 value.Handle = -1;
403 value.Value <<= m_aFTPURL.ident(false,false);
404 value.State = PropertyState_DIRECT_VALUE;
405 seq[0] <<= value;
406 ucbhelper::cancelCommandExecution(
407 IOErrorCode_NO_FILE,
408 seq,
409 Environment);
410 break;
412 case THROWQUOTE:
413 case THROWGENERAL:
414 ucbhelper::cancelCommandExecution(
415 IOErrorCode_GENERAL,
416 Sequence<Any>(0),
417 Environment);
418 break;
421 if(aCommand.Name.compareToAscii("getPropertyValues") == 0) {
422 Sequence<Property> Properties;
423 if(!(aCommand.Argument >>= Properties))
425 aRet <<= IllegalArgumentException(
426 rtl::OUString( "Wrong argument type!" ),
427 static_cast< cppu::OWeakObject * >(this),
428 -1);
429 ucbhelper::cancelCommandExecution(aRet,Environment);
432 aRet <<= getPropertyValues(Properties,Environment);
434 else if(aCommand.Name.compareToAscii("setPropertyValues") == 0)
436 Sequence<PropertyValue> propertyValues;
438 if( ! ( aCommand.Argument >>= propertyValues ) ) {
439 aRet <<= IllegalArgumentException(
440 rtl::OUString( "Wrong argument type!" ),
441 static_cast< cppu::OWeakObject * >(this),
442 -1);
443 ucbhelper::cancelCommandExecution(aRet,Environment);
446 aRet <<= setPropertyValues(propertyValues);
448 else if(aCommand.Name.compareToAscii("getCommandInfo") == 0) {
449 // Note: Implemented by base class.
450 aRet <<= getCommandInfo(Environment);
452 else if(aCommand.Name.compareToAscii("getPropertySetInfo") == 0) {
453 // Note: Implemented by base class.
454 aRet <<= getPropertySetInfo(Environment);
456 else if(aCommand.Name.compareToAscii( "insert" ) == 0)
458 InsertCommandArgument aInsertArgument;
459 if ( ! ( aCommand.Argument >>= aInsertArgument ) ) {
460 aRet <<= IllegalArgumentException(
461 rtl::OUString( "Wrong argument type!" ),
462 static_cast< cppu::OWeakObject * >(this),
463 -1);
464 ucbhelper::cancelCommandExecution(aRet,Environment);
466 insert(aInsertArgument,Environment);
468 else if(aCommand.Name.compareToAscii("delete") == 0) {
469 m_aFTPURL.del();
470 deleted();
472 else if(aCommand.Name.compareToAscii( "open" ) == 0) {
473 OpenCommandArgument2 aOpenCommand;
474 if ( !( aCommand.Argument >>= aOpenCommand ) ) {
475 aRet <<= IllegalArgumentException(
476 rtl::OUString( "Wrong argument type!" ),
477 static_cast< cppu::OWeakObject * >(this),
478 -1);
480 ucbhelper::cancelCommandExecution(aRet,Environment);
483 if(aOpenCommand.Mode == OpenMode::DOCUMENT) {
484 // Open as a document
485 Reference<XActiveDataSink>
486 xActiveDataSink(aOpenCommand.Sink,UNO_QUERY);
487 Reference< XOutputStream >
488 xOutputStream(aOpenCommand.Sink,UNO_QUERY);
490 if(xActiveDataSink.is()) {
491 xActiveDataSink->setInputStream(
492 new ucbhelper::FdInputStream(m_aFTPURL.open()));
494 else if(xOutputStream.is()) {
495 Reference<XInputStream> xStream(
496 new ucbhelper::FdInputStream(m_aFTPURL.open()));
497 Sequence<sal_Int8> byte_seq(4096);
498 sal_Int32 n = 1000; // value does not matter here
499 for (;;) {
500 n = xStream->readBytes(byte_seq,4096);
501 if (n == 0) {
502 break;
504 try {
505 if(byte_seq.getLength() != n)
506 byte_seq.realloc(n);
507 xOutputStream->writeBytes(byte_seq);
508 } catch(const NotConnectedException&) {
510 } catch(const BufferSizeExceededException&) {
512 } catch(const IOException&) {
516 if(n) {
517 Sequence<Any> seq(1);
518 PropertyValue value;
519 value.Name = rtl::OUString("Uri");
520 value.Handle = -1;
521 value.Value <<= m_aFTPURL.ident(false,false);
522 value.State = PropertyState_DIRECT_VALUE;
523 seq[0] <<= value;
524 ucbhelper::cancelCommandExecution(
525 IOErrorCode_UNKNOWN,
526 seq,
527 Environment);
530 else {
531 aRet <<= UnsupportedDataSinkException(
532 rtl::OUString(),
533 static_cast< cppu::OWeakObject * >(this),
534 aOpenCommand.Sink);
535 ucbhelper::cancelCommandExecution(aRet,Environment);
538 else if(aOpenCommand.Mode == OpenMode::ALL ||
539 aOpenCommand.Mode == OpenMode::DOCUMENTS ||
540 aOpenCommand.Mode == OpenMode::FOLDERS ) {
541 std::vector<FTPDirentry> resvec =
542 m_aFTPURL.list(sal_Int16(aOpenCommand.Mode));
543 Reference< XDynamicResultSet > xSet
544 = new DynamicResultSet(
545 m_xContext,
546 this,
547 aOpenCommand,
548 Environment,
549 new ResultSetFactoryI(m_xContext,
550 m_xProvider.get(),
551 aOpenCommand.Mode,
552 aOpenCommand.Properties,
553 aOpenCommand.SortingInfo,
554 resvec));
555 aRet <<= xSet;
557 else if(aOpenCommand.Mode ==
558 OpenMode::DOCUMENT_SHARE_DENY_NONE ||
559 aOpenCommand.Mode ==
560 OpenMode::DOCUMENT_SHARE_DENY_WRITE) {
561 // Unsupported OpenMode
562 aRet <<= UnsupportedOpenModeException(
563 rtl::OUString(),
564 static_cast< cppu::OWeakObject * >(this),
565 static_cast< sal_Int16 >(aOpenCommand.Mode));
566 ucbhelper::cancelCommandExecution(aRet,Environment);
568 else {
569 aRet <<= IllegalArgumentException(
570 rtl::OUString( "Unexpected OpenMode!" ),
571 static_cast< cppu::OWeakObject * >(this),
572 -1);
574 ucbhelper::cancelCommandExecution(aRet,Environment);
576 } else if(aCommand.Name.compareToAscii("createNewContent") == 0) {
577 ContentInfo aArg;
578 if (!(aCommand.Argument >>= aArg)) {
579 ucbhelper::cancelCommandExecution(
580 makeAny(
581 IllegalArgumentException(
582 rtl::OUString( "Wrong argument type!" ),
583 static_cast< cppu::OWeakObject * >(this),
584 -1)),
585 Environment);
586 // Unreachable
588 aRet <<= createNewContent(aArg);
589 } else {
590 aRet <<= UnsupportedCommandException(
591 aCommand.Name,
592 static_cast< cppu::OWeakObject * >(this));
593 ucbhelper::cancelCommandExecution(aRet,Environment);
596 return aRet;
597 } catch(const curl_exception& e) {
598 if(e.code() == CURLE_COULDNT_CONNECT)
599 action = THROWINTERACTIVECONNECT;
600 else if(e.code() == CURLE_COULDNT_RESOLVE_HOST )
601 action = THROWRESOLVENAME;
602 else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT ||
603 e.code() == CURLE_LOGIN_DENIED ||
604 e.code() == CURLE_BAD_PASSWORD_ENTERED ||
605 e.code() == CURLE_FTP_WEIRD_PASS_REPLY)
606 action = THROWAUTHENTICATIONREQUEST;
607 else if(e.code() == CURLE_FTP_ACCESS_DENIED)
608 action = THROWACCESSDENIED;
609 else if(e.code() == CURLE_FTP_QUOTE_ERROR)
610 action = THROWQUOTE;
611 else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE)
612 action = THROWNOFILE;
613 else
614 // nothing known about the cause of the error
615 action = THROWGENERAL;
619 #define FTP_FILE rtl::OUString( "application/vnd.sun.staroffice.ftp-file")
621 #define FTP_FOLDER rtl::OUString( "application/vnd.sun.staroffice.ftp-folder")
623 Sequence<ContentInfo > SAL_CALL
624 FTPContent::queryCreatableContentsInfo( )
625 throw (RuntimeException)
627 return queryCreatableContentsInfo_Static();
630 // static
631 Sequence<ContentInfo >
632 FTPContent::queryCreatableContentsInfo_Static( )
633 throw (RuntimeException)
635 Sequence< ContentInfo > seq(2);
637 seq[0].Type = FTP_FILE;
638 seq[0].Attributes = ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
639 | ContentInfoAttribute::KIND_DOCUMENT;
640 Sequence< Property > props( 1 );
641 props[0] = Property(
642 rtl::OUString("Title"),
644 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
645 PropertyAttribute::MAYBEVOID
646 | PropertyAttribute::BOUND );
647 seq[0].Properties = props;
649 // folder
650 seq[1].Type = FTP_FOLDER;
651 seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER;
652 seq[1].Properties = props;
654 return seq;
657 Reference<XContent > SAL_CALL
658 FTPContent::createNewContent( const ContentInfo& Info )
659 throw (RuntimeException)
661 if( Info.Type =="application/vnd.sun.staroffice.ftp-file" || Info.Type == "application/vnd.sun.staroffice.ftp-folder" )
662 return new FTPContent(m_xContext,
663 m_pFCP,
664 m_xIdentifier,Info);
665 else
666 return Reference<XContent>(0);
672 Reference<XInterface > SAL_CALL
673 FTPContent::getParent( )
674 throw (RuntimeException)
676 Reference<XContentIdentifier>
677 xIdent(new FTPContentIdentifier(m_aFTPURL.parent(false)));
678 Reference<XContent> xContent(m_xProvider->queryContent(xIdent));
679 return Reference<XInterface>(xContent,UNO_QUERY);
683 void SAL_CALL
684 FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
685 throw (NoSupportException,
686 RuntimeException)
688 throw NoSupportException();
693 rtl::OUString FTPContent::getParentURL()
695 return m_aFTPURL.parent();
699 class InsertData
700 : public CurlInput {
702 public:
704 InsertData(const Reference<XInputStream>& xInputStream)
705 : m_xInputStream(xInputStream) { }
706 virtual ~InsertData() {}
708 // returns the number of bytes actually read
709 virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested);
711 private:
713 Reference<XInputStream> m_xInputStream;
718 sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
720 sal_Int32 m = 0;
722 if(m_xInputStream.is()) {
723 Sequence<sal_Int8> seq(nBytesRequested);
724 m = m_xInputStream->readBytes(seq,nBytesRequested);
725 memcpy(dest,seq.getConstArray(),m);
727 return m;
731 void FTPContent::insert(const InsertCommandArgument& aInsertCommand,
732 const Reference<XCommandEnvironment>& Env)
734 osl::MutexGuard aGuard(m_aMutex);
736 if(m_bInserted && !m_bTitleSet) {
737 MissingPropertiesException excep;
738 excep.Properties.realloc(1);
739 excep.Properties[0] = rtl::OUString("Title");
740 Any aAny; aAny <<= excep;
741 ucbhelper::cancelCommandExecution(aAny,Env);
744 if(m_bInserted &&
745 m_aInfo.Type == FTP_FILE &&
746 !aInsertCommand.Data.is())
748 MissingInputStreamException excep;
749 Any aAny; aAny <<= excep;
750 ucbhelper::cancelCommandExecution(aAny,Env);
753 bool bReplace(aInsertCommand.ReplaceExisting);
755 retry:
756 try {
757 if(m_aInfo.Type == FTP_FILE) {
758 InsertData data(aInsertCommand.Data);
759 m_aFTPURL.insert(bReplace,&data);
760 } else if(m_aInfo.Type == FTP_FOLDER)
761 m_aFTPURL.mkdir(bReplace);
762 } catch(const curl_exception& e) {
763 if(e.code() == FILE_EXIST_DURING_INSERT ||
764 e.code() == FOLDER_EXIST_DURING_INSERT) {
765 // Deprecated, not used anymore:
766 NameClashException excep;
767 excep.Name = m_aFTPURL.child();
768 Any aAny;
769 aAny <<= excep;
770 ucbhelper::cancelCommandExecution(aAny,Env);
771 } else if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT ||
772 e.code() == FILE_MIGHT_EXIST_DURING_INSERT) {
773 // Interact
774 Reference<XInteractionHandler> xInt;
775 if(Env.is())
776 xInt = Env->getInteractionHandler();
778 UnsupportedNameClashException excep;
779 excep.NameClash = 0; //NameClash::ERROR;
781 if(!xInt.is()) {
782 Any aAny;
783 aAny <<= excep;
784 ucbhelper::cancelCommandExecution(aAny,Env);
787 XInteractionRequestImpl* p =
788 new XInteractionRequestImpl(m_aFTPURL.child());
789 Reference<XInteractionRequest> req(p);
790 xInt->handle(req);
791 if(p->approved()) {
792 bReplace = true;
793 goto retry;
795 else
796 throw excep;
798 else
799 throw;
802 // May not be reached, because both mkdir and insert can throw curl-
803 // exceptions
804 m_bInserted = false;
805 inserted();
810 Reference< XRow > FTPContent::getPropertyValues(
811 const Sequence< Property >& seqProp,
812 const Reference<XCommandEnvironment>& /*environment*/
815 rtl::Reference<ucbhelper::PropertyValueSet> xRow =
816 new ucbhelper::PropertyValueSet(m_xContext);
818 FTPDirentry aDirEntry = m_aFTPURL.direntry();
820 for(sal_Int32 i = 0; i < seqProp.getLength(); ++i) {
821 const rtl::OUString& Name = seqProp[i].Name;
822 if(Name.compareToAscii("Title") == 0)
823 xRow->appendString(seqProp[i],aDirEntry.m_aName);
824 else if(Name.compareToAscii("CreatableContentsInfo") == 0)
825 xRow->appendObject(seqProp[i],
826 makeAny(queryCreatableContentsInfo()));
827 else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) {
828 if(Name.compareToAscii("ContentType") == 0)
829 xRow->appendString(seqProp[i],
830 aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR
831 ? FTP_FOLDER
832 : FTP_FILE );
833 else if(Name.compareToAscii("IsReadOnly") == 0)
834 xRow->appendBoolean(seqProp[i],
835 aDirEntry.m_nMode
836 & INETCOREFTP_FILEMODE_WRITE
838 : 1 );
839 else if(Name.compareToAscii("IsDocument") == 0)
840 xRow->appendBoolean(seqProp[i],
841 ! sal_Bool(aDirEntry.m_nMode &
842 INETCOREFTP_FILEMODE_ISDIR));
843 else if(Name.compareToAscii("IsFolder") == 0)
844 xRow->appendBoolean(seqProp[i],
845 sal_Bool(aDirEntry.m_nMode &
846 INETCOREFTP_FILEMODE_ISDIR));
847 else if(Name.compareToAscii("Size") == 0)
848 xRow->appendLong(seqProp[i],
849 aDirEntry.m_nSize);
850 else if(Name.compareToAscii("DateCreated") == 0)
851 xRow->appendTimestamp(seqProp[i],
852 aDirEntry.m_aDate);
853 else
854 xRow->appendVoid(seqProp[i]);
855 } else
856 xRow->appendVoid(seqProp[i]);
859 return Reference<XRow>(xRow.get());
864 Sequence<Any> FTPContent::setPropertyValues(
865 const Sequence<PropertyValue>& seqPropVal)
867 Sequence<Any> ret(seqPropVal.getLength());
868 Sequence<PropertyChangeEvent > evt;
870 osl::MutexGuard aGuard(m_aMutex);
871 for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
872 if ( seqPropVal[i].Name == "Title" ) {
873 rtl::OUString Title;
874 if(!(seqPropVal[i].Value >>= Title)) {
875 ret[i] <<= IllegalTypeException();
876 continue;
877 } else if(Title.isEmpty()) {
878 ret[i] <<= IllegalArgumentException();
879 continue;
882 if(m_bInserted) {
883 m_aFTPURL.child(Title);
884 m_xIdentifier =
885 new FTPContentIdentifier(m_aFTPURL.ident(false,false));
886 m_bTitleSet = true;
887 } else
888 try {
889 rtl::OUString OldTitle = m_aFTPURL.ren(Title);
890 evt.realloc(1);
891 evt[0].PropertyName =
892 rtl::OUString("Title");
893 evt[0].Further = false;
894 evt[0].PropertyHandle = -1;
895 evt[0].OldValue <<= OldTitle;
896 evt[0].NewValue <<= Title;
897 } catch(const curl_exception&) {
898 InteractiveIOException excep;
899 // any better possibility here?
900 // ( the error code is always CURLE_FTP_QUOTE_ERROR )
901 excep.Code = IOErrorCode_ACCESS_DENIED;
902 ret[i] <<= excep;
904 } else {
905 Sequence<Property> props =
906 getProperties(Reference<XCommandEnvironment>(0));
908 // either unknown or read-only
909 ret[i] <<= UnknownPropertyException();
910 for(sal_Int32 j = 0; j < props.getLength(); ++j)
911 if(props[j].Name == seqPropVal[i].Name) {
912 ret[i] <<= IllegalAccessException(
913 rtl::OUString( "Property is read-only!"),
914 //props[j].Attributes & PropertyAttribute::READONLY
915 // ? "Property is read-only!"
916 // : "Access denied!"),
917 static_cast< cppu::OWeakObject * >( this ));
918 break;
923 if(evt.getLength()) {
924 // title has changed
925 notifyPropertiesChange(evt);
926 exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
929 return ret;
932 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */