bump product version to 4.1.6.2
[LibreOffice.git] / ucb / source / ucp / ftp / ftpcontent.cxx
blob3e145ad1876626405521e41899cb6682d2fb10e6
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/simpleauthenticationrequest.hxx>
50 #include <com/sun/star/lang/IllegalAccessException.hpp>
51 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
52 #include <com/sun/star/beans/UnknownPropertyException.hpp>
53 #include <com/sun/star/beans/Property.hpp>
54 #include <com/sun/star/beans/PropertyValue.hpp>
55 #include <com/sun/star/ucb/XCommandInfo.hpp>
56 #include <com/sun/star/io/XActiveDataSink.hpp>
57 #include <com/sun/star/io/XOutputStream.hpp>
58 #include <com/sun/star/io/XActiveDataStreamer.hpp>
59 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
60 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
61 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
62 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
63 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
64 #include <com/sun/star/ucb/InteractiveIOException.hpp>
65 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
66 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
67 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
68 #include <com/sun/star/ucb/NameClashException.hpp>
69 #include <com/sun/star/ucb/OpenMode.hpp>
70 #include <com/sun/star/ucb/IOErrorCode.hpp>
72 using namespace ftp;
73 using namespace com::sun::star::task;
74 using namespace com::sun::star::container;
75 using namespace com::sun::star::lang;
76 using namespace com::sun::star::uno;
77 using namespace com::sun::star::ucb;
78 using namespace com::sun::star::beans;
79 using namespace com::sun::star::io;
80 using namespace com::sun::star::sdbc;
84 //=========================================================================
85 //=========================================================================
87 // Content Implementation.
89 //=========================================================================
90 //=========================================================================
92 FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
93 FTPContentProvider* pProvider,
94 const Reference< XContentIdentifier >& Identifier,
95 const FTPURL& aFTPURL)
96 : ContentImplHelper(rxContext,pProvider,Identifier),
97 m_pFCP(pProvider),
98 m_aFTPURL(aFTPURL),
99 m_bInserted(false),
100 m_bTitleSet(false)
106 FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
107 FTPContentProvider* pProvider,
108 const Reference< XContentIdentifier >& Identifier,
109 const ContentInfo& Info)
110 : ContentImplHelper(rxContext,pProvider,Identifier),
111 m_pFCP(pProvider),
112 m_aFTPURL(Identifier->getContentIdentifier(),
113 pProvider),
114 m_bInserted(true),
115 m_bTitleSet(false),
116 m_aInfo(Info)
122 //=========================================================================
124 FTPContent::~FTPContent()
129 //=========================================================================
131 // XInterface methods.
133 //=========================================================================
135 XINTERFACE_IMPL_6( FTPContent,
136 XTypeProvider,
137 XServiceInfo,
138 XContent,
139 XCommandProcessor,
140 XContentCreator,
141 XChild);
143 //=========================================================================
145 // XTypeProvider methods.
147 //=========================================================================
149 XTYPEPROVIDER_IMPL_6( FTPContent,
150 XTypeProvider,
151 XServiceInfo,
152 XContent,
153 XCommandProcessor,
154 XContentCreator,
155 XChild);
157 //=========================================================================
159 // XServiceInfo methods.
161 //=========================================================================
163 // needed, because the service shall not be creatable!!
164 #undef XSERVICEINFO_CREATE_INSTANCE_IMPL
165 #define XSERVICEINFO_CREATE_INSTANCE_IMPL( Class )
167 XSERVICEINFO_IMPL_1( FTPContent,
168 OUString( "com.sun.star.comp.FTPContent"),
169 OUString( "com.sun.star.ucb.FTPContent"));
173 //=========================================================================
175 // XContent methods.
177 //=========================================================================
179 // virtual
180 OUString SAL_CALL FTPContent::getContentType()
181 throw( RuntimeException )
183 return OUString(FTP_CONTENT_TYPE);
187 //=========================================================================
189 // XCommandProcessor methods.
191 //=========================================================================
194 //virtual
195 void SAL_CALL FTPContent::abort( sal_Int32 /*CommandId*/ )
196 throw( RuntimeException )
202 /***************************************************************************/
203 /* */
204 /* Internal implementation class. */
205 /* */
206 /***************************************************************************/
209 class ResultSetFactoryI
210 : public ResultSetFactory
212 public:
214 ResultSetFactoryI(const Reference<XComponentContext >& rxContext,
215 const Reference<XContentProvider >& xProvider,
216 sal_Int32 nOpenMode,
217 const Sequence<Property>& seq,
218 const Sequence<NumberedSortingInfo>& seqSort,
219 const std::vector<FTPDirentry>& dirvec)
220 : m_xContext(rxContext),
221 m_xProvider(xProvider),
222 m_nOpenMode(nOpenMode),
223 m_seq(seq),
224 m_seqSort(seqSort),
225 m_dirvec(dirvec)
229 virtual ResultSetBase* createResultSet()
231 return new ResultSetI(m_xContext,
232 m_xProvider,
233 m_nOpenMode,
234 m_seq,
235 m_seqSort,
236 m_dirvec);
239 public:
241 Reference< XComponentContext > m_xContext;
242 Reference< XContentProvider > m_xProvider;
243 sal_Int32 m_nOpenMode;
244 Sequence< Property > m_seq;
245 Sequence< NumberedSortingInfo > m_seqSort;
246 std::vector<FTPDirentry> m_dirvec;
251 //=========================================================================
253 // XCommandProcessor methods.
255 //=========================================================================
257 enum ACTION { NOACTION,
258 THROWAUTHENTICATIONREQUEST,
259 THROWACCESSDENIED,
260 THROWINTERACTIVECONNECT,
261 THROWRESOLVENAME,
262 THROWQUOTE,
263 THROWNOFILE,
264 THROWGENERAL };
267 // virtual
268 Any SAL_CALL FTPContent::execute(
269 const Command& aCommand,
270 sal_Int32 /*CommandId*/,
271 const Reference<
272 XCommandEnvironment >& Environment
274 throw(
275 Exception,
276 CommandAbortedException,
277 RuntimeException
280 ACTION action(NOACTION);
281 Any aRet;
283 while(true)
284 try {
285 if(action == THROWAUTHENTICATIONREQUEST) {
286 // try to get a continuation first
287 OUString aRealm,aPassword,aAccount;
288 m_pFCP->forHost(m_aFTPURL.host(),
289 m_aFTPURL.port(),
290 m_aFTPURL.username(),
291 aPassword,
292 aAccount);
293 rtl::Reference<ucbhelper::SimpleAuthenticationRequest>
294 p( new ucbhelper::SimpleAuthenticationRequest(
295 m_aFTPURL.ident(false, false),
296 m_aFTPURL.host(), // ServerName
297 ucbhelper::SimpleAuthenticationRequest::ENTITY_NA,
298 aRealm,
299 ucbhelper::SimpleAuthenticationRequest
300 ::ENTITY_FIXED,
301 m_aFTPURL.username(),
302 ucbhelper::SimpleAuthenticationRequest
303 ::ENTITY_MODIFY,
304 aPassword));
306 Reference<XInteractionHandler> xInteractionHandler;
307 if(Environment.is())
308 xInteractionHandler =
309 Environment->getInteractionHandler();
311 if( xInteractionHandler.is()) {
312 xInteractionHandler->handle(p.get());
314 Reference<XInterface> xSelection(
315 p->getSelection().get());
317 if(Reference<XInteractionRetry>(
318 xSelection,UNO_QUERY).is())
319 action = NOACTION;
320 else if(Reference<XInteractionSupplyAuthentication>(
321 xSelection,UNO_QUERY).is()) {
322 m_pFCP->setHost(
323 m_aFTPURL.host(),
324 m_aFTPURL.port(),
325 m_aFTPURL.username(),
326 p->getAuthenticationSupplier()->getPassword(),
327 aAccount);
328 action = NOACTION;
331 aRet = p->getRequest();
334 // if(aCommand.Name.compareToAscii(
335 // "getPropertyValues") == 0 &&
336 // action != NOACTION) {
337 // // It is not allowed to throw if
338 // // command is getPropertyValues
339 // rtl::Reference<ucbhelper::PropertyValueSet> xRow =
340 // new ucbhelper::PropertyValueSet(m_xSMgr);
341 // Sequence<Property> Properties;
342 // aCommand.Argument >>= Properties;
343 // for(int i = 0; i < Properties.getLength(); ++i)
344 // xRow->appendVoid(Properties[i]);
345 // aRet <<= Reference<XRow>(xRow.get());
346 // return aRet;
347 // }
349 switch (action)
351 case NOACTION:
352 break;
354 case THROWAUTHENTICATIONREQUEST:
355 ucbhelper::cancelCommandExecution(
356 aRet,
357 Reference<XCommandEnvironment>(0));
358 break;
360 case THROWACCESSDENIED:
362 Sequence<Any> seq(1);
363 PropertyValue value;
364 value.Name = OUString("Uri");
365 value.Handle = -1;
366 value.Value <<= m_aFTPURL.ident(false,false);
367 value.State = PropertyState_DIRECT_VALUE;
368 seq[0] <<= value;
369 ucbhelper::cancelCommandExecution(
370 IOErrorCode_ACCESS_DENIED,
371 seq,
372 Environment);
373 break;
375 case THROWINTERACTIVECONNECT:
377 InteractiveNetworkConnectException excep;
378 excep.Server = m_aFTPURL.host();
379 aRet <<= excep;
380 ucbhelper::cancelCommandExecution(
381 aRet,
382 Environment);
383 break;
385 case THROWRESOLVENAME:
387 InteractiveNetworkResolveNameException excep;
388 excep.Server = m_aFTPURL.host();
389 aRet <<= excep;
390 ucbhelper::cancelCommandExecution(
391 aRet,
392 Environment);
393 break;
395 case THROWNOFILE:
397 Sequence<Any> seq(1);
398 PropertyValue value;
399 value.Name = OUString("Uri");
400 value.Handle = -1;
401 value.Value <<= m_aFTPURL.ident(false,false);
402 value.State = PropertyState_DIRECT_VALUE;
403 seq[0] <<= value;
404 ucbhelper::cancelCommandExecution(
405 IOErrorCode_NO_FILE,
406 seq,
407 Environment);
408 break;
410 case THROWQUOTE:
411 case THROWGENERAL:
412 ucbhelper::cancelCommandExecution(
413 IOErrorCode_GENERAL,
414 Sequence<Any>(0),
415 Environment);
416 break;
419 if(aCommand.Name.compareToAscii("getPropertyValues") == 0) {
420 Sequence<Property> Properties;
421 if(!(aCommand.Argument >>= Properties))
423 aRet <<= IllegalArgumentException(
424 OUString( "Wrong argument type!" ),
425 static_cast< cppu::OWeakObject * >(this),
426 -1);
427 ucbhelper::cancelCommandExecution(aRet,Environment);
430 aRet <<= getPropertyValues(Properties,Environment);
432 else if(aCommand.Name.compareToAscii("setPropertyValues") == 0)
434 Sequence<PropertyValue> propertyValues;
436 if( ! ( aCommand.Argument >>= propertyValues ) ) {
437 aRet <<= IllegalArgumentException(
438 OUString( "Wrong argument type!" ),
439 static_cast< cppu::OWeakObject * >(this),
440 -1);
441 ucbhelper::cancelCommandExecution(aRet,Environment);
444 aRet <<= setPropertyValues(propertyValues);
446 else if(aCommand.Name.compareToAscii("getCommandInfo") == 0) {
447 // Note: Implemented by base class.
448 aRet <<= getCommandInfo(Environment);
450 else if(aCommand.Name.compareToAscii("getPropertySetInfo") == 0) {
451 // Note: Implemented by base class.
452 aRet <<= getPropertySetInfo(Environment);
454 else if(aCommand.Name.compareToAscii( "insert" ) == 0)
456 InsertCommandArgument aInsertArgument;
457 if ( ! ( aCommand.Argument >>= aInsertArgument ) ) {
458 aRet <<= IllegalArgumentException(
459 OUString( "Wrong argument type!" ),
460 static_cast< cppu::OWeakObject * >(this),
461 -1);
462 ucbhelper::cancelCommandExecution(aRet,Environment);
464 insert(aInsertArgument,Environment);
466 else if(aCommand.Name.compareToAscii("delete") == 0) {
467 m_aFTPURL.del();
468 deleted();
470 else if(aCommand.Name.compareToAscii( "open" ) == 0) {
471 OpenCommandArgument2 aOpenCommand;
472 if ( !( aCommand.Argument >>= aOpenCommand ) ) {
473 aRet <<= IllegalArgumentException(
474 OUString( "Wrong argument type!" ),
475 static_cast< cppu::OWeakObject * >(this),
476 -1);
478 ucbhelper::cancelCommandExecution(aRet,Environment);
481 if(aOpenCommand.Mode == OpenMode::DOCUMENT) {
482 // Open as a document
483 Reference<XActiveDataSink>
484 xActiveDataSink(aOpenCommand.Sink,UNO_QUERY);
485 Reference< XOutputStream >
486 xOutputStream(aOpenCommand.Sink,UNO_QUERY);
488 if(xActiveDataSink.is()) {
489 xActiveDataSink->setInputStream(
490 new ucbhelper::FdInputStream(m_aFTPURL.open()));
492 else if(xOutputStream.is()) {
493 Reference<XInputStream> xStream(
494 new ucbhelper::FdInputStream(m_aFTPURL.open()));
495 Sequence<sal_Int8> byte_seq(4096);
496 sal_Int32 n = 1000; // value does not matter here
497 for (;;) {
498 n = xStream->readBytes(byte_seq,4096);
499 if (n == 0) {
500 break;
502 try {
503 if(byte_seq.getLength() != n)
504 byte_seq.realloc(n);
505 xOutputStream->writeBytes(byte_seq);
506 } catch(const NotConnectedException&) {
508 } catch(const BufferSizeExceededException&) {
510 } catch(const IOException&) {
514 if(n) {
515 Sequence<Any> seq(1);
516 PropertyValue value;
517 value.Name = OUString("Uri");
518 value.Handle = -1;
519 value.Value <<= m_aFTPURL.ident(false,false);
520 value.State = PropertyState_DIRECT_VALUE;
521 seq[0] <<= value;
522 ucbhelper::cancelCommandExecution(
523 IOErrorCode_UNKNOWN,
524 seq,
525 Environment);
528 else {
529 aRet <<= UnsupportedDataSinkException(
530 OUString(),
531 static_cast< cppu::OWeakObject * >(this),
532 aOpenCommand.Sink);
533 ucbhelper::cancelCommandExecution(aRet,Environment);
536 else if(aOpenCommand.Mode == OpenMode::ALL ||
537 aOpenCommand.Mode == OpenMode::DOCUMENTS ||
538 aOpenCommand.Mode == OpenMode::FOLDERS ) {
539 std::vector<FTPDirentry> resvec =
540 m_aFTPURL.list(sal_Int16(aOpenCommand.Mode));
541 Reference< XDynamicResultSet > xSet
542 = new DynamicResultSet(
543 m_xContext,
544 this,
545 aOpenCommand,
546 Environment,
547 new ResultSetFactoryI(m_xContext,
548 m_xProvider.get(),
549 aOpenCommand.Mode,
550 aOpenCommand.Properties,
551 aOpenCommand.SortingInfo,
552 resvec));
553 aRet <<= xSet;
555 else if(aOpenCommand.Mode ==
556 OpenMode::DOCUMENT_SHARE_DENY_NONE ||
557 aOpenCommand.Mode ==
558 OpenMode::DOCUMENT_SHARE_DENY_WRITE) {
559 // Unsupported OpenMode
560 aRet <<= UnsupportedOpenModeException(
561 OUString(),
562 static_cast< cppu::OWeakObject * >(this),
563 static_cast< sal_Int16 >(aOpenCommand.Mode));
564 ucbhelper::cancelCommandExecution(aRet,Environment);
566 else {
567 aRet <<= IllegalArgumentException(
568 OUString( "Unexpected OpenMode!" ),
569 static_cast< cppu::OWeakObject * >(this),
570 -1);
572 ucbhelper::cancelCommandExecution(aRet,Environment);
574 } else if(aCommand.Name.compareToAscii("createNewContent") == 0) {
575 ContentInfo aArg;
576 if (!(aCommand.Argument >>= aArg)) {
577 ucbhelper::cancelCommandExecution(
578 makeAny(
579 IllegalArgumentException(
580 OUString( "Wrong argument type!" ),
581 static_cast< cppu::OWeakObject * >(this),
582 -1)),
583 Environment);
584 // Unreachable
586 aRet <<= createNewContent(aArg);
587 } else {
588 aRet <<= UnsupportedCommandException(
589 aCommand.Name,
590 static_cast< cppu::OWeakObject * >(this));
591 ucbhelper::cancelCommandExecution(aRet,Environment);
594 return aRet;
595 } catch(const curl_exception& e) {
596 if(e.code() == CURLE_COULDNT_CONNECT)
597 action = THROWINTERACTIVECONNECT;
598 else if(e.code() == CURLE_COULDNT_RESOLVE_HOST )
599 action = THROWRESOLVENAME;
600 else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT ||
601 e.code() == CURLE_LOGIN_DENIED ||
602 e.code() == CURLE_BAD_PASSWORD_ENTERED ||
603 e.code() == CURLE_FTP_WEIRD_PASS_REPLY)
604 action = THROWAUTHENTICATIONREQUEST;
605 else if(e.code() == CURLE_FTP_ACCESS_DENIED)
606 action = THROWACCESSDENIED;
607 else if(e.code() == CURLE_FTP_QUOTE_ERROR)
608 action = THROWQUOTE;
609 else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE)
610 action = THROWNOFILE;
611 else
612 // nothing known about the cause of the error
613 action = THROWGENERAL;
617 #define FTP_FILE OUString( "application/vnd.sun.staroffice.ftp-file")
619 #define FTP_FOLDER OUString( "application/vnd.sun.staroffice.ftp-folder")
621 Sequence<ContentInfo > SAL_CALL
622 FTPContent::queryCreatableContentsInfo( )
623 throw (RuntimeException)
625 return queryCreatableContentsInfo_Static();
628 // static
629 Sequence<ContentInfo >
630 FTPContent::queryCreatableContentsInfo_Static( )
631 throw (RuntimeException)
633 Sequence< ContentInfo > seq(2);
635 seq[0].Type = FTP_FILE;
636 seq[0].Attributes = ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
637 | ContentInfoAttribute::KIND_DOCUMENT;
638 Sequence< Property > props( 1 );
639 props[0] = Property(
640 OUString("Title"),
642 getCppuType( static_cast< OUString* >( 0 ) ),
643 PropertyAttribute::MAYBEVOID
644 | PropertyAttribute::BOUND );
645 seq[0].Properties = props;
647 // folder
648 seq[1].Type = FTP_FOLDER;
649 seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER;
650 seq[1].Properties = props;
652 return seq;
655 Reference<XContent > SAL_CALL
656 FTPContent::createNewContent( const ContentInfo& Info )
657 throw (RuntimeException)
659 if( Info.Type =="application/vnd.sun.staroffice.ftp-file" || Info.Type == "application/vnd.sun.staroffice.ftp-folder" )
660 return new FTPContent(m_xContext,
661 m_pFCP,
662 m_xIdentifier,Info);
663 else
664 return Reference<XContent>(0);
670 Reference<XInterface > SAL_CALL
671 FTPContent::getParent( )
672 throw (RuntimeException)
674 Reference<XContentIdentifier>
675 xIdent(new FTPContentIdentifier(m_aFTPURL.parent(false)));
676 Reference<XContent> xContent(m_xProvider->queryContent(xIdent));
677 return Reference<XInterface>(xContent,UNO_QUERY);
681 void SAL_CALL
682 FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
683 throw (NoSupportException,
684 RuntimeException)
686 throw NoSupportException();
691 OUString FTPContent::getParentURL()
693 return m_aFTPURL.parent();
697 class InsertData
698 : public CurlInput {
700 public:
702 InsertData(const Reference<XInputStream>& xInputStream)
703 : m_xInputStream(xInputStream) { }
704 virtual ~InsertData() {}
706 // returns the number of bytes actually read
707 virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested);
709 private:
711 Reference<XInputStream> m_xInputStream;
716 sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
718 sal_Int32 m = 0;
720 if(m_xInputStream.is()) {
721 Sequence<sal_Int8> seq(nBytesRequested);
722 m = m_xInputStream->readBytes(seq,nBytesRequested);
723 memcpy(dest,seq.getConstArray(),m);
725 return m;
729 void FTPContent::insert(const InsertCommandArgument& aInsertCommand,
730 const Reference<XCommandEnvironment>& Env)
732 osl::MutexGuard aGuard(m_aMutex);
734 if(m_bInserted && !m_bTitleSet) {
735 MissingPropertiesException excep;
736 excep.Properties.realloc(1);
737 excep.Properties[0] = OUString("Title");
738 Any aAny; aAny <<= excep;
739 ucbhelper::cancelCommandExecution(aAny,Env);
742 if(m_bInserted &&
743 m_aInfo.Type == FTP_FILE &&
744 !aInsertCommand.Data.is())
746 MissingInputStreamException excep;
747 Any aAny; aAny <<= excep;
748 ucbhelper::cancelCommandExecution(aAny,Env);
751 bool bReplace(aInsertCommand.ReplaceExisting);
753 retry:
754 try {
755 if(m_aInfo.Type == FTP_FILE) {
756 InsertData data(aInsertCommand.Data);
757 m_aFTPURL.insert(bReplace,&data);
758 } else if(m_aInfo.Type == FTP_FOLDER)
759 m_aFTPURL.mkdir(bReplace);
760 } catch(const curl_exception& e) {
761 if(e.code() == FILE_EXIST_DURING_INSERT ||
762 e.code() == FOLDER_EXIST_DURING_INSERT) {
763 // Deprecated, not used anymore:
764 NameClashException excep;
765 excep.Name = m_aFTPURL.child();
766 Any aAny;
767 aAny <<= excep;
768 ucbhelper::cancelCommandExecution(aAny,Env);
769 } else if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT ||
770 e.code() == FILE_MIGHT_EXIST_DURING_INSERT) {
771 // Interact
772 Reference<XInteractionHandler> xInt;
773 if(Env.is())
774 xInt = Env->getInteractionHandler();
776 UnsupportedNameClashException excep;
777 excep.NameClash = 0; //NameClash::ERROR;
779 if(!xInt.is()) {
780 Any aAny;
781 aAny <<= excep;
782 ucbhelper::cancelCommandExecution(aAny,Env);
785 XInteractionRequestImpl* p =
786 new XInteractionRequestImpl(m_aFTPURL.child());
787 Reference<XInteractionRequest> req(p);
788 xInt->handle(req);
789 if(p->approved()) {
790 bReplace = true;
791 goto retry;
793 else
794 throw excep;
796 else
797 throw;
800 // May not be reached, because both mkdir and insert can throw curl-
801 // exceptions
802 m_bInserted = false;
803 inserted();
808 Reference< XRow > FTPContent::getPropertyValues(
809 const Sequence< Property >& seqProp,
810 const Reference<XCommandEnvironment>& /*environment*/
813 rtl::Reference<ucbhelper::PropertyValueSet> xRow =
814 new ucbhelper::PropertyValueSet(m_xContext);
816 FTPDirentry aDirEntry = m_aFTPURL.direntry();
818 for(sal_Int32 i = 0; i < seqProp.getLength(); ++i) {
819 const OUString& Name = seqProp[i].Name;
820 if(Name.compareToAscii("Title") == 0)
821 xRow->appendString(seqProp[i],aDirEntry.m_aName);
822 else if(Name.compareToAscii("CreatableContentsInfo") == 0)
823 xRow->appendObject(seqProp[i],
824 makeAny(queryCreatableContentsInfo()));
825 else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) {
826 if(Name.compareToAscii("ContentType") == 0)
827 xRow->appendString(seqProp[i],
828 aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR
829 ? FTP_FOLDER
830 : FTP_FILE );
831 else if(Name.compareToAscii("IsReadOnly") == 0)
832 xRow->appendBoolean(seqProp[i],
833 aDirEntry.m_nMode
834 & INETCOREFTP_FILEMODE_WRITE
836 : 1 );
837 else if(Name.compareToAscii("IsDocument") == 0)
838 xRow->appendBoolean(seqProp[i],
839 ! sal_Bool(aDirEntry.m_nMode &
840 INETCOREFTP_FILEMODE_ISDIR));
841 else if(Name.compareToAscii("IsFolder") == 0)
842 xRow->appendBoolean(seqProp[i],
843 sal_Bool(aDirEntry.m_nMode &
844 INETCOREFTP_FILEMODE_ISDIR));
845 else if(Name.compareToAscii("Size") == 0)
846 xRow->appendLong(seqProp[i],
847 aDirEntry.m_nSize);
848 else if(Name.compareToAscii("DateCreated") == 0)
849 xRow->appendTimestamp(seqProp[i],
850 aDirEntry.m_aDate);
851 else
852 xRow->appendVoid(seqProp[i]);
853 } else
854 xRow->appendVoid(seqProp[i]);
857 return Reference<XRow>(xRow.get());
862 Sequence<Any> FTPContent::setPropertyValues(
863 const Sequence<PropertyValue>& seqPropVal)
865 Sequence<Any> ret(seqPropVal.getLength());
866 Sequence<PropertyChangeEvent > evt;
868 osl::MutexGuard aGuard(m_aMutex);
869 for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
870 if ( seqPropVal[i].Name == "Title" ) {
871 OUString Title;
872 if(!(seqPropVal[i].Value >>= Title)) {
873 ret[i] <<= IllegalTypeException();
874 continue;
875 } else if(Title.isEmpty()) {
876 ret[i] <<= IllegalArgumentException();
877 continue;
880 if(m_bInserted) {
881 m_aFTPURL.child(Title);
882 m_xIdentifier =
883 new FTPContentIdentifier(m_aFTPURL.ident(false,false));
884 m_bTitleSet = true;
885 } else
886 try {
887 OUString OldTitle = m_aFTPURL.ren(Title);
888 evt.realloc(1);
889 evt[0].PropertyName =
890 OUString("Title");
891 evt[0].Further = false;
892 evt[0].PropertyHandle = -1;
893 evt[0].OldValue <<= OldTitle;
894 evt[0].NewValue <<= Title;
895 } catch(const curl_exception&) {
896 InteractiveIOException excep;
897 // any better possibility here?
898 // ( the error code is always CURLE_FTP_QUOTE_ERROR )
899 excep.Code = IOErrorCode_ACCESS_DENIED;
900 ret[i] <<= excep;
902 } else {
903 Sequence<Property> props =
904 getProperties(Reference<XCommandEnvironment>(0));
906 // either unknown or read-only
907 ret[i] <<= UnknownPropertyException();
908 for(sal_Int32 j = 0; j < props.getLength(); ++j)
909 if(props[j].Name == seqPropVal[i].Name) {
910 ret[i] <<= IllegalAccessException(
911 OUString( "Property is read-only!"),
912 //props[j].Attributes & PropertyAttribute::READONLY
913 // ? "Property is read-only!"
914 // : "Access denied!"),
915 static_cast< cppu::OWeakObject * >( this ));
916 break;
921 if(evt.getLength()) {
922 // title has changed
923 notifyPropertiesChange(evt);
924 exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
927 return ret;
930 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */