summaryrefslogtreecommitdiff
path: root/ucb/source/ucp/ftp/ftpcontent.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/ftp/ftpcontent.cxx')
-rw-r--r--ucb/source/ucp/ftp/ftpcontent.cxx957
1 files changed, 957 insertions, 0 deletions
diff --git a/ucb/source/ucp/ftp/ftpcontent.cxx b/ucb/source/ucp/ftp/ftpcontent.cxx
new file mode 100644
index 000000000000..4659197b81b5
--- /dev/null
+++ b/ucb/source/ucp/ftp/ftpcontent.cxx
@@ -0,0 +1,957 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include "ftpdynresultset.hxx"
+#include "ftpresultsetfactory.hxx"
+#include "ftpresultsetI.hxx"
+#include "ftpcontent.hxx"
+#include "ftpcontentprovider.hxx"
+#include "ftpinpstr.hxx"
+#include "ftpdirp.hxx"
+#include "ftpcontentidentifier.hxx"
+#include "ftpcfunc.hxx"
+#include "ftpstrcont.hxx"
+#include "ftpintreq.hxx"
+
+#include <memory>
+#include <vector>
+#include <rtl/memory.h>
+#include "curl.hxx"
+#include <curl/easy.h>
+#include <ucbhelper/cancelcommandexecution.hxx>
+#include <ucbhelper/contentidentifier.hxx>
+#include <ucbhelper/propertyvalueset.hxx>
+#include <ucbhelper/contentidentifier.hxx>
+#include <ucbhelper/cancelcommandexecution.hxx>
+#include <ucbhelper/simpleauthenticationrequest.hxx>
+#include <com/sun/star/lang/IllegalAccessException.hpp>
+#include <com/sun/star/ucb/ContentInfoAttribute.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XActiveDataStreamer.hpp>
+#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/ucb/MissingPropertiesException.hpp>
+#include <com/sun/star/ucb/MissingInputStreamException.hpp>
+#include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
+#include <com/sun/star/ucb/NameClashException.hpp>
+//#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+
+using namespace ftp;
+using namespace com::sun::star::task;
+using namespace com::sun::star::container;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::io;
+using namespace com::sun::star::sdbc;
+
+
+
+//=========================================================================
+//=========================================================================
+//
+// Content Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+FTPContent::FTPContent( const Reference< XMultiServiceFactory >& rxSMgr,
+ FTPContentProvider* pProvider,
+ const Reference< XContentIdentifier >& Identifier,
+ const FTPURL& aFTPURL)
+ : ContentImplHelper(rxSMgr,pProvider,Identifier),
+ m_pFCP(pProvider),
+ m_aFTPURL(aFTPURL),
+ m_bInserted(false),
+ m_bTitleSet(false)
+{
+}
+
+
+
+FTPContent::FTPContent( const Reference< XMultiServiceFactory >& rxSMgr,
+ FTPContentProvider* pProvider,
+ const Reference< XContentIdentifier >& Identifier,
+ const ContentInfo& Info)
+ : ContentImplHelper(rxSMgr,pProvider,Identifier),
+ m_pFCP(pProvider),
+ m_aFTPURL(Identifier->getContentIdentifier(),
+ pProvider),
+ m_bInserted(true),
+ m_bTitleSet(false),
+ m_aInfo(Info)
+{
+}
+
+
+
+//=========================================================================
+
+FTPContent::~FTPContent()
+{
+}
+
+
+//=========================================================================
+//
+// XInterface methods.
+//
+//=========================================================================
+
+XINTERFACE_IMPL_6( FTPContent,
+ XTypeProvider,
+ XServiceInfo,
+ XContent,
+ XCommandProcessor,
+ XContentCreator,
+ XChild);
+
+//=========================================================================
+//
+// XTypeProvider methods.
+//
+//=========================================================================
+
+XTYPEPROVIDER_IMPL_6( FTPContent,
+ XTypeProvider,
+ XServiceInfo,
+ XContent,
+ XCommandProcessor,
+ XContentCreator,
+ XChild);
+
+//=========================================================================
+//
+// XServiceInfo methods.
+//
+//=========================================================================
+
+// needed, because the service shall not be creatable!!
+#undef XSERVICEINFO_CREATE_INSTANCE_IMPL
+#define XSERVICEINFO_CREATE_INSTANCE_IMPL( Class )
+
+XSERVICEINFO_IMPL_1( FTPContent,
+ rtl::OUString::createFromAscii(
+ "com.sun.star.comp.FTPContent"),
+ rtl::OUString::createFromAscii(
+ "com.sun.star.ucb.FTPContent"));
+
+
+
+//=========================================================================
+//
+// XContent methods.
+//
+//=========================================================================
+
+// virtual
+rtl::OUString SAL_CALL FTPContent::getContentType()
+ throw( RuntimeException )
+{
+ return rtl::OUString::createFromAscii(FTP_CONTENT_TYPE);
+}
+
+
+//=========================================================================
+//
+// XCommandProcessor methods.
+//
+//=========================================================================
+
+
+//virtual
+void SAL_CALL FTPContent::abort( sal_Int32 /*CommandId*/ )
+ throw( RuntimeException )
+{
+}
+
+
+
+/***************************************************************************/
+/* */
+/* Internal implementation class. */
+/* */
+/***************************************************************************/
+
+
+class ResultSetFactoryI
+ : public ResultSetFactory
+{
+public:
+
+ ResultSetFactoryI(const Reference<XMultiServiceFactory >& xSMgr,
+ const Reference<XContentProvider >& xProvider,
+ sal_Int32 nOpenMode,
+ const Sequence<Property>& seq,
+ const Sequence<NumberedSortingInfo>& seqSort,
+ const std::vector<FTPDirentry>& dirvec)
+ : m_xSMgr(xSMgr),
+ m_xProvider(xProvider),
+ m_nOpenMode(nOpenMode),
+ m_seq(seq),
+ m_seqSort(seqSort),
+ m_dirvec(dirvec)
+ {
+ }
+
+ virtual ResultSetBase* createResultSet()
+ {
+ return new ResultSetI(m_xSMgr,
+ m_xProvider,
+ m_nOpenMode,
+ m_seq,
+ m_seqSort,
+ m_dirvec);
+ }
+
+public:
+
+ Reference< XMultiServiceFactory > m_xSMgr;
+ Reference< XContentProvider > m_xProvider;
+ sal_Int32 m_nOpenMode;
+ Sequence< Property > m_seq;
+ Sequence< NumberedSortingInfo > m_seqSort;
+ std::vector<FTPDirentry> m_dirvec;
+};
+
+
+
+//=========================================================================
+//
+// XCommandProcessor methods.
+//
+//=========================================================================
+
+enum ACTION { NOACTION,
+ THROWAUTHENTICATIONREQUEST,
+ THROWACCESSDENIED,
+ THROWINTERACTIVECONNECT,
+ THROWRESOLVENAME,
+ THROWQUOTE,
+ THROWNOFILE,
+ THROWGENERAL };
+
+
+// virtual
+Any SAL_CALL FTPContent::execute(
+ const Command& aCommand,
+ sal_Int32 /*CommandId*/,
+ const Reference<
+ XCommandEnvironment >& Environment
+)
+ throw(
+ Exception,
+ CommandAbortedException,
+ RuntimeException
+ )
+{
+ ACTION action(NOACTION);
+ Any aRet;
+
+ while(true)
+ try {
+ if(action == THROWAUTHENTICATIONREQUEST) {
+ // try to get a continuation first
+ rtl::OUString aRealm,aPassword,aAccount;
+ m_pFCP->forHost(m_aFTPURL.host(),
+ m_aFTPURL.port(),
+ m_aFTPURL.username(),
+ aPassword,
+ aAccount);
+ rtl::Reference<ucbhelper::SimpleAuthenticationRequest>
+ p( new ucbhelper::SimpleAuthenticationRequest(
+ m_aFTPURL.ident(false, false),
+ m_aFTPURL.host(), // ServerName
+ ucbhelper::SimpleAuthenticationRequest::ENTITY_NA,
+ aRealm,
+ ucbhelper::SimpleAuthenticationRequest
+ ::ENTITY_FIXED,
+ m_aFTPURL.username(),
+ ucbhelper::SimpleAuthenticationRequest
+ ::ENTITY_MODIFY,
+ aPassword));
+
+ Reference<XInteractionHandler> xInteractionHandler;
+ if(Environment.is())
+ xInteractionHandler =
+ Environment->getInteractionHandler();
+
+ if( xInteractionHandler.is()) {
+ xInteractionHandler->handle(p.get());
+
+ Reference<XInterface> xSelection(
+ p->getSelection().get());
+
+ if(Reference<XInteractionRetry>(
+ xSelection,UNO_QUERY).is())
+ action = NOACTION;
+ else if(Reference<XInteractionSupplyAuthentication>(
+ xSelection,UNO_QUERY).is()) {
+ m_pFCP->setHost(
+ m_aFTPURL.host(),
+ m_aFTPURL.port(),
+ m_aFTPURL.username(),
+ p->getAuthenticationSupplier()->getPassword(),
+ aAccount);
+ action = NOACTION;
+ }
+ }
+ aRet = p->getRequest();
+ }
+
+// if(aCommand.Name.compareToAscii(
+// "getPropertyValues") == 0 &&
+// action != NOACTION) {
+// // It is not allowed to throw if
+// // command is getPropertyValues
+// rtl::Reference<ucbhelper::PropertyValueSet> xRow =
+// new ucbhelper::PropertyValueSet(m_xSMgr);
+// Sequence<Property> Properties;
+// aCommand.Argument >>= Properties;
+// for(int i = 0; i < Properties.getLength(); ++i)
+// xRow->appendVoid(Properties[i]);
+// aRet <<= Reference<XRow>(xRow.get());
+// return aRet;
+// }
+
+ switch (action)
+ {
+ case NOACTION:
+ break;
+
+ case THROWAUTHENTICATIONREQUEST:
+ ucbhelper::cancelCommandExecution(
+ aRet,
+ Reference<XCommandEnvironment>(0));
+ break;
+
+ case THROWACCESSDENIED:
+ {
+ Sequence<Any> seq(1);
+ PropertyValue value;
+ value.Name = rtl::OUString::createFromAscii("Uri");
+ value.Handle = -1;
+ value.Value <<= m_aFTPURL.ident(false,false);
+ value.State = PropertyState_DIRECT_VALUE;
+ seq[0] <<= value;
+ ucbhelper::cancelCommandExecution(
+ IOErrorCode_ACCESS_DENIED,
+ seq,
+ Environment);
+ break;
+ }
+ case THROWINTERACTIVECONNECT:
+ {
+ InteractiveNetworkConnectException excep;
+ excep.Server = m_aFTPURL.host();
+ aRet <<= excep;
+ ucbhelper::cancelCommandExecution(
+ aRet,
+ Environment);
+ break;
+ }
+ case THROWRESOLVENAME:
+ {
+ InteractiveNetworkResolveNameException excep;
+ excep.Server = m_aFTPURL.host();
+ aRet <<= excep;
+ ucbhelper::cancelCommandExecution(
+ aRet,
+ Environment);
+ break;
+ }
+ case THROWNOFILE:
+ {
+ Sequence<Any> seq(1);
+ PropertyValue value;
+ value.Name = rtl::OUString::createFromAscii("Uri");
+ value.Handle = -1;
+ value.Value <<= m_aFTPURL.ident(false,false);
+ value.State = PropertyState_DIRECT_VALUE;
+ seq[0] <<= value;
+ ucbhelper::cancelCommandExecution(
+ IOErrorCode_NO_FILE,
+ seq,
+ Environment);
+ break;
+ }
+ case THROWQUOTE:
+ case THROWGENERAL:
+ ucbhelper::cancelCommandExecution(
+ IOErrorCode_GENERAL,
+ Sequence<Any>(0),
+ Environment);
+ break;
+ }
+
+ if(aCommand.Name.compareToAscii("getPropertyValues") == 0) {
+ Sequence<Property> Properties;
+ if(!(aCommand.Argument >>= Properties))
+ {
+ aRet <<= IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >(this),
+ -1);
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+
+ aRet <<= getPropertyValues(Properties,Environment);
+ }
+ else if(aCommand.Name.compareToAscii("setPropertyValues") == 0)
+ {
+ Sequence<PropertyValue> propertyValues;
+
+ if( ! ( aCommand.Argument >>= propertyValues ) ) {
+ aRet <<= IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >(this),
+ -1);
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+
+ aRet <<= setPropertyValues(propertyValues);
+ }
+ else if(aCommand.Name.compareToAscii("getCommandInfo") == 0) {
+ // Note: Implemented by base class.
+ aRet <<= getCommandInfo(Environment);
+ }
+ else if(aCommand.Name.compareToAscii("getPropertySetInfo") == 0) {
+ // Note: Implemented by base class.
+ aRet <<= getPropertySetInfo(Environment);
+ }
+ else if(aCommand.Name.compareToAscii( "insert" ) == 0)
+ {
+ InsertCommandArgument aInsertArgument;
+ if ( ! ( aCommand.Argument >>= aInsertArgument ) ) {
+ aRet <<= IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >(this),
+ -1);
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+ insert(aInsertArgument,Environment);
+ }
+ else if(aCommand.Name.compareToAscii("delete") == 0) {
+ m_aFTPURL.del();
+ deleted();
+ }
+ else if(aCommand.Name.compareToAscii( "open" ) == 0) {
+ OpenCommandArgument2 aOpenCommand;
+ if ( !( aCommand.Argument >>= aOpenCommand ) ) {
+ aRet <<= IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >(this),
+ -1);
+
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+
+ if(aOpenCommand.Mode == OpenMode::DOCUMENT) {
+ // Open as a document
+ Reference<XActiveDataSink>
+ xActiveDataSink(aOpenCommand.Sink,UNO_QUERY);
+ Reference< XOutputStream >
+ xOutputStream(aOpenCommand.Sink,UNO_QUERY);
+
+ if(xActiveDataSink.is()) {
+ xActiveDataSink->setInputStream(
+ new FTPInputStream(m_aFTPURL.open()));
+ }
+ else if(xOutputStream.is()) {
+ Reference<XInputStream> xStream(
+ new FTPInputStream(m_aFTPURL.open()));
+ Sequence<sal_Int8> byte_seq(4096);
+ sal_Int32 n = 1000; // value does not matter here
+ for (;;) {
+ n = xStream->readBytes(byte_seq,4096);
+ if (n == 0) {
+ break;
+ }
+ try {
+ if(byte_seq.getLength() != n)
+ byte_seq.realloc(n);
+ xOutputStream->writeBytes(byte_seq);
+ } catch(const NotConnectedException&) {
+
+ } catch(const BufferSizeExceededException&) {
+
+ } catch(const IOException&) {
+
+ }
+ }
+ if(n) {
+ Sequence<Any> seq(1);
+ PropertyValue value;
+ value.Name =
+ rtl::OUString::createFromAscii("Uri");
+ value.Handle = -1;
+ value.Value <<= m_aFTPURL.ident(false,false);
+ value.State = PropertyState_DIRECT_VALUE;
+ seq[0] <<= value;
+ ucbhelper::cancelCommandExecution(
+ IOErrorCode_UNKNOWN,
+ seq,
+ Environment);
+ }
+ }
+ else {
+ aRet <<= UnsupportedDataSinkException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >(this),
+ aOpenCommand.Sink);
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+ }
+ else if(aOpenCommand.Mode == OpenMode::ALL ||
+ aOpenCommand.Mode == OpenMode::DOCUMENTS ||
+ aOpenCommand.Mode == OpenMode::FOLDERS ) {
+ std::vector<FTPDirentry> resvec =
+ m_aFTPURL.list(sal_Int16(aOpenCommand.Mode));
+ Reference< XDynamicResultSet > xSet
+ = new DynamicResultSet(
+ m_xSMgr,
+ this,
+ aOpenCommand,
+ Environment,
+ new ResultSetFactoryI(m_xSMgr,
+ m_xProvider.get(),
+ aOpenCommand.Mode,
+ aOpenCommand.Properties,
+ aOpenCommand.SortingInfo,
+ resvec));
+ aRet <<= xSet;
+ }
+ else if(aOpenCommand.Mode ==
+ OpenMode::DOCUMENT_SHARE_DENY_NONE ||
+ aOpenCommand.Mode ==
+ OpenMode::DOCUMENT_SHARE_DENY_WRITE) {
+ // Unsupported OpenMode
+ aRet <<= UnsupportedOpenModeException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >(this),
+ static_cast< sal_Int16 >(aOpenCommand.Mode));
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+ else {
+ aRet <<= IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Unexpected OpenMode!" ),
+ static_cast< cppu::OWeakObject * >(this),
+ -1);
+
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+ } else if(aCommand.Name.compareToAscii("createNewContent") == 0) {
+ ContentInfo aArg;
+ if (!(aCommand.Argument >>= aArg)) {
+ ucbhelper::cancelCommandExecution(
+ makeAny(
+ IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >(this),
+ -1)),
+ Environment);
+ // Unreachable
+ }
+ aRet <<= createNewContent(aArg);
+ } else {
+ aRet <<= UnsupportedCommandException(
+ aCommand.Name,
+ static_cast< cppu::OWeakObject * >(this));
+ ucbhelper::cancelCommandExecution(aRet,Environment);
+ }
+
+ return aRet;
+ } catch(const curl_exception& e) {
+ if(e.code() == CURLE_COULDNT_CONNECT)
+ action = THROWINTERACTIVECONNECT;
+ else if(e.code() == CURLE_COULDNT_RESOLVE_HOST )
+ action = THROWRESOLVENAME;
+ else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT ||
+ e.code() == CURLE_LOGIN_DENIED ||
+ e.code() == CURLE_BAD_PASSWORD_ENTERED ||
+ e.code() == CURLE_FTP_WEIRD_PASS_REPLY)
+ action = THROWAUTHENTICATIONREQUEST;
+ else if(e.code() == CURLE_FTP_ACCESS_DENIED)
+ action = THROWACCESSDENIED;
+ else if(e.code() == CURLE_FTP_QUOTE_ERROR)
+ action = THROWQUOTE;
+ else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE)
+ action = THROWNOFILE;
+ else
+ // nothing known about the cause of the error
+ action = THROWGENERAL;
+ }
+}
+
+#define FTP_FILE rtl::OUString::createFromAscii( \
+ "application/" \
+ "vnd.sun.staroffice.ftp-file")
+
+#define FTP_FOLDER rtl::OUString::createFromAscii( \
+ "application/" \
+ "vnd.sun.staroffice.ftp-folder")
+
+Sequence<ContentInfo > SAL_CALL
+FTPContent::queryCreatableContentsInfo( )
+ throw (RuntimeException)
+{
+ return queryCreatableContentsInfo_Static();
+}
+
+// static
+Sequence<ContentInfo >
+FTPContent::queryCreatableContentsInfo_Static( )
+ throw (RuntimeException)
+{
+ Sequence< ContentInfo > seq(2);
+
+ seq[0].Type = FTP_FILE;
+ seq[0].Attributes = ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
+ | ContentInfoAttribute::KIND_DOCUMENT;
+ Sequence< Property > props( 1 );
+ props[0] = Property(
+ rtl::OUString::createFromAscii( "Title" ),
+ -1,
+ getCppuType( static_cast< rtl::OUString* >( 0 ) ),
+ PropertyAttribute::MAYBEVOID
+ | PropertyAttribute::BOUND );
+ seq[0].Properties = props;
+
+ // folder
+ seq[1].Type = FTP_FOLDER;
+ seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER;
+ seq[1].Properties = props;
+
+ return seq;
+}
+
+Reference<XContent > SAL_CALL
+FTPContent::createNewContent( const ContentInfo& Info )
+ throw (RuntimeException)
+{
+ if(Info.Type.equalsAscii("application/"
+ "vnd.sun.staroffice.ftp-file") ||
+ Info.Type.equalsAscii("application/"
+ "vnd.sun.staroffice.ftp-folder"))
+ return new FTPContent(m_xSMgr,
+ m_pFCP,
+ m_xIdentifier,Info);
+ else
+ return Reference<XContent>(0);
+}
+
+
+
+
+Reference<XInterface > SAL_CALL
+FTPContent::getParent( )
+ throw (RuntimeException)
+{
+ Reference<XContentIdentifier>
+ xIdent(new FTPContentIdentifier(m_aFTPURL.parent(false)));
+ Reference<XContent> xContent(m_xProvider->queryContent(xIdent));
+ return Reference<XInterface>(xContent,UNO_QUERY);
+}
+
+
+void SAL_CALL
+FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
+ throw (NoSupportException,
+ RuntimeException)
+{
+ throw NoSupportException();
+}
+
+
+
+rtl::OUString FTPContent::getParentURL()
+{
+ return m_aFTPURL.parent();
+}
+
+
+class InsertData
+ : public CurlInput {
+
+public:
+
+ InsertData(const Reference<XInputStream>& xInputStream)
+ : m_xInputStream(xInputStream) { }
+ virtual ~InsertData() {}
+
+ // returns the number of bytes actually read
+ virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested);
+
+private:
+
+ Reference<XInputStream> m_xInputStream;
+};
+
+
+
+sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
+{
+ sal_Int32 m = 0;
+
+ if(m_xInputStream.is()) {
+ Sequence<sal_Int8> seq(nBytesRequested);
+ m = m_xInputStream->readBytes(seq,nBytesRequested);
+ rtl_copyMemory(dest,seq.getConstArray(),m);
+ }
+ return m;
+}
+
+
+void FTPContent::insert(const InsertCommandArgument& aInsertCommand,
+ const Reference<XCommandEnvironment>& Env)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if(m_bInserted && !m_bTitleSet) {
+ MissingPropertiesException excep;
+ excep.Properties.realloc(1);
+ excep.Properties[0] = rtl::OUString::createFromAscii("Title");
+ Any aAny; aAny <<= excep;
+ ucbhelper::cancelCommandExecution(aAny,Env);
+ }
+
+ if(m_bInserted &&
+ m_aInfo.Type == FTP_FILE &&
+ !aInsertCommand.Data.is())
+ {
+ MissingInputStreamException excep;
+ Any aAny; aAny <<= excep;
+ ucbhelper::cancelCommandExecution(aAny,Env);
+ }
+
+ bool bReplace(aInsertCommand.ReplaceExisting);
+
+ retry:
+ try {
+ if(m_aInfo.Type == FTP_FILE) {
+ InsertData data(aInsertCommand.Data);
+ m_aFTPURL.insert(bReplace,&data);
+ } else if(m_aInfo.Type == FTP_FOLDER)
+ m_aFTPURL.mkdir(bReplace);
+ } catch(const curl_exception& e) {
+ if(e.code() == FILE_EXIST_DURING_INSERT ||
+ e.code() == FOLDER_EXIST_DURING_INSERT) {
+ // Deprecated, not used anymore:
+ NameClashException excep;
+ excep.Name = m_aFTPURL.child();
+ Any aAny;
+ aAny <<= excep;
+ ucbhelper::cancelCommandExecution(aAny,Env);
+ } else if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT ||
+ e.code() == FILE_MIGHT_EXIST_DURING_INSERT) {
+ // Interact
+ Reference<XInteractionHandler> xInt;
+ if(Env.is())
+ xInt = Env->getInteractionHandler();
+
+ UnsupportedNameClashException excep;
+ excep.NameClash = 0; //NameClash::ERROR;
+
+ if(!xInt.is()) {
+ Any aAny;
+ aAny <<= excep;
+ ucbhelper::cancelCommandExecution(aAny,Env);
+ }
+
+ XInteractionRequestImpl* p =
+ new XInteractionRequestImpl(m_aFTPURL.child());
+ Reference<XInteractionRequest> req(p);
+ xInt->handle(req);
+ if(p->approved()) {
+ bReplace = true;
+ goto retry;
+ }
+ else
+ throw excep;
+ }
+ else
+ throw;
+ }
+
+ // May not be reached, because both mkdir and insert can throw curl-
+ // exceptions
+ m_bInserted = false;
+ inserted();
+}
+
+
+
+Reference< XRow > FTPContent::getPropertyValues(
+ const Sequence< Property >& seqProp,
+ const Reference<XCommandEnvironment>& /*environment*/
+)
+{
+ rtl::Reference<ucbhelper::PropertyValueSet> xRow =
+ new ucbhelper::PropertyValueSet(m_xSMgr);
+
+ FTPDirentry aDirEntry = m_aFTPURL.direntry();
+
+ for(sal_Int32 i = 0; i < seqProp.getLength(); ++i) {
+ const rtl::OUString& Name = seqProp[i].Name;
+ if(Name.compareToAscii("Title") == 0)
+ xRow->appendString(seqProp[i],aDirEntry.m_aName);
+ else if(Name.compareToAscii("CreatableContentsInfo") == 0)
+ xRow->appendObject(seqProp[i],
+ makeAny(queryCreatableContentsInfo()));
+ else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) {
+ if(Name.compareToAscii("ContentType") == 0)
+ xRow->appendString(seqProp[i],
+ aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR
+ ? FTP_FOLDER
+ : FTP_FILE );
+ else if(Name.compareToAscii("IsReadOnly") == 0)
+ xRow->appendBoolean(seqProp[i],
+ aDirEntry.m_nMode
+ & INETCOREFTP_FILEMODE_WRITE
+ ? 0
+ : 1 );
+ else if(Name.compareToAscii("IsDocument") == 0)
+ xRow->appendBoolean(seqProp[i],
+ ! sal_Bool(aDirEntry.m_nMode &
+ INETCOREFTP_FILEMODE_ISDIR));
+ else if(Name.compareToAscii("IsFolder") == 0)
+ xRow->appendBoolean(seqProp[i],
+ sal_Bool(aDirEntry.m_nMode &
+ INETCOREFTP_FILEMODE_ISDIR));
+ else if(Name.compareToAscii("Size") == 0)
+ xRow->appendLong(seqProp[i],
+ aDirEntry.m_nSize);
+ else if(Name.compareToAscii("DateCreated") == 0)
+ xRow->appendTimestamp(seqProp[i],
+ aDirEntry.m_aDate);
+ else
+ xRow->appendVoid(seqProp[i]);
+ } else
+ xRow->appendVoid(seqProp[i]);
+ }
+
+ return Reference<XRow>(xRow.get());
+}
+
+
+
+Sequence<Any> FTPContent::setPropertyValues(
+ const Sequence<PropertyValue>& seqPropVal)
+{
+ Sequence<Any> ret(seqPropVal.getLength());
+ Sequence<PropertyChangeEvent > evt;
+
+ osl::MutexGuard aGuard(m_aMutex);
+ for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
+ if(seqPropVal[i].Name.equalsAscii("Title")) {
+ rtl::OUString Title;
+ if(!(seqPropVal[i].Value >>= Title)) {
+ ret[i] <<= IllegalTypeException();
+ continue;
+ } else if(!Title.getLength()) {
+ ret[i] <<= IllegalArgumentException();
+ continue;
+ }
+
+ if(m_bInserted) {
+ m_aFTPURL.child(Title);
+ m_xIdentifier =
+ new FTPContentIdentifier(m_aFTPURL.ident(false,false));
+ m_bTitleSet = true;
+ } else
+ try {
+ rtl::OUString OldTitle = m_aFTPURL.ren(Title);
+ evt.realloc(1);
+ evt[0].PropertyName =
+ rtl::OUString::createFromAscii("Title");
+ evt[0].Further = false;
+ evt[0].PropertyHandle = -1;
+ evt[0].OldValue <<= OldTitle;
+ evt[0].NewValue <<= Title;
+ } catch(const curl_exception&) {
+ InteractiveIOException excep;
+ // any better possibility here?
+ // ( the error code is always CURLE_FTP_QUOTE_ERROR )
+ excep.Code = IOErrorCode_ACCESS_DENIED;
+ ret[i] <<= excep;
+ }
+ } else {
+ Sequence<Property> props =
+ getProperties(Reference<XCommandEnvironment>(0));
+
+ // either unknown or read-only
+ ret[i] <<= UnknownPropertyException();
+ for(sal_Int32 j = 0; j < props.getLength(); ++j)
+ if(props[j].Name == seqPropVal[i].Name) {
+ ret[i] <<= IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!"),
+ //props[j].Attributes & PropertyAttribute::READONLY
+ // ? "Property is read-only!"
+ // : "Access denied!"),
+ static_cast< cppu::OWeakObject * >( this ));
+ break;
+ }
+ }
+ }
+
+ if(evt.getLength()) {
+ // title has changed
+ notifyPropertiesChange(evt);
+ exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
+ }
+
+ return ret;
+}