1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 /**************************************************************************
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 "ftpintreq.hxx"
41 #include <comphelper/propertysequence.hxx>
42 #include <cppuhelper/queryinterface.hxx>
43 #include <cppuhelper/supportsservice.hxx>
44 #include <cppuhelper/typeprovider.hxx>
45 #include <ucbhelper/cancelcommandexecution.hxx>
46 #include <ucbhelper/fd_inputstream.hxx>
47 #include <ucbhelper/propertyvalueset.hxx>
48 #include <ucbhelper/simpleauthenticationrequest.hxx>
49 #include <com/sun/star/lang/IllegalAccessException.hpp>
50 #include <com/sun/star/lang/NoSupportException.hpp>
51 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
52 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
53 #include <com/sun/star/beans/IllegalTypeException.hpp>
54 #include <com/sun/star/beans/UnknownPropertyException.hpp>
55 #include <com/sun/star/beans/Property.hpp>
56 #include <com/sun/star/ucb/XCommandInfo.hpp>
57 #include <com/sun/star/io/BufferSizeExceededException.hpp>
58 #include <com/sun/star/io/IOException.hpp>
59 #include <com/sun/star/io/NotConnectedException.hpp>
60 #include <com/sun/star/io/XActiveDataSink.hpp>
61 #include <com/sun/star/io/XOutputStream.hpp>
62 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
63 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
64 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
65 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
66 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
67 #include <com/sun/star/ucb/InteractiveIOException.hpp>
68 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
69 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
70 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
71 #include <com/sun/star/ucb/OpenMode.hpp>
72 #include <com/sun/star/ucb/IOErrorCode.hpp>
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
;
85 // Content Implementation.
87 FTPContent::FTPContent( const Reference
< XComponentContext
>& rxContext
,
88 FTPContentProvider
* pProvider
,
89 const Reference
< XContentIdentifier
>& Identifier
,
90 const FTPURL
& aFTPURL
)
91 : ContentImplHelper(rxContext
,pProvider
,Identifier
)
99 FTPContent::FTPContent( const Reference
< XComponentContext
>& rxContext
,
100 FTPContentProvider
* pProvider
,
101 const Reference
< XContentIdentifier
>& Identifier
,
102 const ContentInfo
& Info
)
103 : ContentImplHelper(rxContext
,pProvider
,Identifier
)
105 , m_aFTPURL(Identifier
->getContentIdentifier(), pProvider
)
112 FTPContent::~FTPContent()
116 // XInterface methods.
118 void SAL_CALL
FTPContent::acquire()
121 OWeakObject::acquire();
124 void SAL_CALL
FTPContent::release()
127 OWeakObject::release();
130 css::uno::Any SAL_CALL
FTPContent::queryInterface( const css::uno::Type
& rType
)
132 css::uno::Any aRet
= cppu::queryInterface( rType
,
133 static_cast< XTypeProvider
* >(this),
134 static_cast< XServiceInfo
* >(this),
135 static_cast< XContent
* >(this),
136 static_cast< XCommandProcessor
* >(this),
137 static_cast< XContentCreator
* >(this),
138 static_cast< XChild
* >(this)
140 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
143 // XTypeProvider methods.
145 css::uno::Sequence
< sal_Int8
> SAL_CALL
FTPContent::getImplementationId()
147 return css::uno::Sequence
<sal_Int8
>();
150 css::uno::Sequence
< css::uno::Type
> SAL_CALL
FTPContent::getTypes()
152 static cppu::OTypeCollection
s_aCollection(
153 cppu::UnoType
<XTypeProvider
>::get(),
154 cppu::UnoType
<XServiceInfo
>::get(),
155 cppu::UnoType
<XContent
>::get(),
156 cppu::UnoType
<XCommandProcessor
>::get(),
157 cppu::UnoType
<XContentCreator
>::get(),
158 cppu::UnoType
<XChild
>::get()
161 return s_aCollection
.getTypes();
165 // XServiceInfo methods.
167 OUString SAL_CALL
FTPContent::getImplementationName()
169 return "com.sun.star.comp.FTPContent";
172 sal_Bool SAL_CALL
FTPContent::supportsService( const OUString
& ServiceName
)
174 return cppu::supportsService( this, ServiceName
);
177 css::uno::Sequence
< OUString
> SAL_CALL
FTPContent::getSupportedServiceNames()
179 return { "com.sun.star.ucb.FTPContent" };
186 OUString SAL_CALL
FTPContent::getContentType()
188 return FTP_CONTENT_TYPE
;
191 // XCommandProcessor methods.
194 void SAL_CALL
FTPContent::abort( sal_Int32
/*CommandId*/ )
199 ResultSetFactory::ResultSetFactory(const Reference
<XComponentContext
>& rxContext
,
200 const Reference
<XContentProvider
>& xProvider
,
201 const Sequence
<Property
>& seq
,
202 const std::vector
<FTPDirentry
>& dirvec
)
203 : m_xContext(rxContext
),
204 m_xProvider(xProvider
),
211 ResultSetBase
* ResultSetFactory::createResultSet()
213 return new ResultSetI(m_xContext
,
220 // XCommandProcessor methods.
222 enum ACTION
{ NOACTION
,
223 THROWAUTHENTICATIONREQUEST
,
225 THROWINTERACTIVECONNECT
,
232 Any SAL_CALL
FTPContent::execute( const Command
& aCommand
,
233 sal_Int32
/*CommandId*/,
235 XCommandEnvironment
>& Environment
)
237 ACTION
action(NOACTION
);
244 if(action
== THROWAUTHENTICATIONREQUEST
)
246 // try to get a continuation first
247 OUString aPassword
,aAccount
;
248 m_pFCP
->forHost(m_aFTPURL
.host(),
250 m_aFTPURL
.username(),
253 rtl::Reference
<ucbhelper::SimpleAuthenticationRequest
>
254 p( new ucbhelper::SimpleAuthenticationRequest(
255 m_aFTPURL
.ident(false, false),
256 m_aFTPURL
.host(), // ServerName
257 ucbhelper::SimpleAuthenticationRequest::ENTITY_NA
,
259 ucbhelper::SimpleAuthenticationRequest
261 m_aFTPURL
.username(),
262 ucbhelper::SimpleAuthenticationRequest
266 Reference
<XInteractionHandler
> xInteractionHandler
;
268 xInteractionHandler
=
269 Environment
->getInteractionHandler();
271 if( xInteractionHandler
.is()) {
272 xInteractionHandler
->handle(p
.get());
274 Reference
<XInterface
> xSelection(
275 p
->getSelection().get());
277 if(Reference
<XInteractionRetry
>(
278 xSelection
,UNO_QUERY
).is())
280 else if(Reference
<XInteractionSupplyAuthentication
>(
281 xSelection
,UNO_QUERY
).is()) {
285 m_aFTPURL
.username(),
286 p
->getAuthenticationSupplier()->getPassword(),
291 aRet
= p
->getRequest();
294 // if(aCommand.Name.equalsAscii(
295 // "getPropertyValues") &&
296 // action != NOACTION) {
297 // // It is not allowed to throw if
298 // // command is getPropertyValues
299 // rtl::Reference<ucbhelper::PropertyValueSet> xRow =
300 // new ucbhelper::PropertyValueSet(m_xSMgr);
301 // Sequence<Property> Properties;
302 // aCommand.Argument >>= Properties;
303 // for(int i = 0; i < Properties.getLength(); ++i)
304 // xRow->appendVoid(Properties[i]);
305 // aRet <<= Reference<XRow>(xRow.get());
314 case THROWAUTHENTICATIONREQUEST
:
315 ucbhelper::cancelCommandExecution(
317 Reference
<XCommandEnvironment
>(nullptr));
320 case THROWACCESSDENIED
:
322 Sequence
<Any
> seq(comphelper::InitAnyPropertySequence(
324 {"Uri", Any(m_aFTPURL
.ident(false,false))}
326 ucbhelper::cancelCommandExecution(
327 IOErrorCode_ACCESS_DENIED
,
332 case THROWINTERACTIVECONNECT
:
334 InteractiveNetworkConnectException excep
;
335 excep
.Server
= m_aFTPURL
.host();
337 ucbhelper::cancelCommandExecution(
342 case THROWRESOLVENAME
:
344 InteractiveNetworkResolveNameException excep
;
345 excep
.Server
= m_aFTPURL
.host();
347 ucbhelper::cancelCommandExecution(
354 Sequence
<Any
> seq(comphelper::InitAnyPropertySequence(
356 {"Uri", Any(m_aFTPURL
.ident(false,false))}
358 ucbhelper::cancelCommandExecution(
366 ucbhelper::cancelCommandExecution(
373 if(aCommand
.Name
== "getPropertyValues") {
374 Sequence
<Property
> Properties
;
375 if(!(aCommand
.Argument
>>= Properties
))
377 aRet
<<= IllegalArgumentException(
378 "Wrong argument type!",
379 static_cast< cppu::OWeakObject
* >(this),
381 ucbhelper::cancelCommandExecution(aRet
,Environment
);
384 aRet
<<= getPropertyValues(Properties
);
386 else if(aCommand
.Name
== "setPropertyValues")
388 Sequence
<PropertyValue
> propertyValues
;
390 if( ! ( aCommand
.Argument
>>= propertyValues
) ) {
391 aRet
<<= IllegalArgumentException(
392 "Wrong argument type!",
393 static_cast< cppu::OWeakObject
* >(this),
395 ucbhelper::cancelCommandExecution(aRet
,Environment
);
398 aRet
<<= setPropertyValues(propertyValues
);
400 else if(aCommand
.Name
== "getCommandInfo") {
401 // Note: Implemented by base class.
402 aRet
<<= getCommandInfo(Environment
);
404 else if(aCommand
.Name
== "getPropertySetInfo") {
405 // Note: Implemented by base class.
406 aRet
<<= getPropertySetInfo(Environment
);
408 else if(aCommand
.Name
== "insert")
410 InsertCommandArgument aInsertArgument
;
411 if ( ! ( aCommand
.Argument
>>= aInsertArgument
) ) {
412 aRet
<<= IllegalArgumentException(
413 "Wrong argument type!",
414 static_cast< cppu::OWeakObject
* >(this),
416 ucbhelper::cancelCommandExecution(aRet
,Environment
);
418 insert(aInsertArgument
,Environment
);
420 else if(aCommand
.Name
== "delete") {
424 else if(aCommand
.Name
== "open") {
425 OpenCommandArgument2 aOpenCommand
;
426 if ( !( aCommand
.Argument
>>= aOpenCommand
) ) {
427 aRet
<<= IllegalArgumentException(
428 "Wrong argument type!",
429 static_cast< cppu::OWeakObject
* >(this),
432 ucbhelper::cancelCommandExecution(aRet
,Environment
);
435 if(aOpenCommand
.Mode
== OpenMode::DOCUMENT
) {
436 // Open as a document
437 Reference
<XActiveDataSink
>
438 xActiveDataSink(aOpenCommand
.Sink
,UNO_QUERY
);
439 Reference
< XOutputStream
>
440 xOutputStream(aOpenCommand
.Sink
,UNO_QUERY
);
442 if(xActiveDataSink
.is()) {
443 xActiveDataSink
->setInputStream(
444 new ucbhelper::FdInputStream(m_aFTPURL
.open()));
446 else if(xOutputStream
.is()) {
447 Reference
<XInputStream
> xStream(
448 new ucbhelper::FdInputStream(m_aFTPURL
.open()));
450 Sequence
<sal_Int8
> byte_seq(4096);
451 sal_Int32 n
= xStream
->readBytes(byte_seq
, 4096);
456 if(byte_seq
.getLength() != n
)
458 xOutputStream
->writeBytes(byte_seq
);
459 } catch(const NotConnectedException
&) {
461 } catch(const BufferSizeExceededException
&) {
463 } catch(const IOException
&) {
469 aRet
<<= UnsupportedDataSinkException(
471 static_cast< cppu::OWeakObject
* >(this),
473 ucbhelper::cancelCommandExecution(aRet
,Environment
);
476 else if(aOpenCommand
.Mode
== OpenMode::ALL
||
477 aOpenCommand
.Mode
== OpenMode::DOCUMENTS
||
478 aOpenCommand
.Mode
== OpenMode::FOLDERS
) {
479 std::vector
<FTPDirentry
> resvec
=
480 m_aFTPURL
.list(sal_Int16(aOpenCommand
.Mode
));
481 Reference
< XDynamicResultSet
> xSet
482 = new DynamicResultSet(
485 std::make_unique
<ResultSetFactory
>(m_xContext
,
487 aOpenCommand
.Properties
,
491 else if(aOpenCommand
.Mode
==
492 OpenMode::DOCUMENT_SHARE_DENY_NONE
||
494 OpenMode::DOCUMENT_SHARE_DENY_WRITE
) {
495 // Unsupported OpenMode
496 aRet
<<= UnsupportedOpenModeException(
498 static_cast< cppu::OWeakObject
* >(this),
499 static_cast< sal_Int16
>(aOpenCommand
.Mode
));
500 ucbhelper::cancelCommandExecution(aRet
,Environment
);
503 aRet
<<= IllegalArgumentException(
504 "Unexpected OpenMode!",
505 static_cast< cppu::OWeakObject
* >(this),
508 ucbhelper::cancelCommandExecution(aRet
,Environment
);
510 } else if(aCommand
.Name
== "createNewContent") {
512 if (!(aCommand
.Argument
>>= aArg
)) {
513 ucbhelper::cancelCommandExecution(
515 IllegalArgumentException(
516 "Wrong argument type!",
517 static_cast< cppu::OWeakObject
* >(this),
522 aRet
<<= createNewContent(aArg
);
524 aRet
<<= UnsupportedCommandException(
526 static_cast< cppu::OWeakObject
* >(this));
527 ucbhelper::cancelCommandExecution(aRet
,Environment
);
532 catch(const curl_exception
& e
)
534 if(e
.code() == CURLE_COULDNT_CONNECT
)
535 action
= THROWINTERACTIVECONNECT
;
536 else if(e
.code() == CURLE_COULDNT_RESOLVE_HOST
)
537 action
= THROWRESOLVENAME
;
538 else if(e
.code() == CURLE_FTP_USER_PASSWORD_INCORRECT
||
539 e
.code() == CURLE_LOGIN_DENIED
||
540 e
.code() == CURLE_BAD_PASSWORD_ENTERED
||
541 e
.code() == CURLE_FTP_WEIRD_PASS_REPLY
)
542 action
= THROWAUTHENTICATIONREQUEST
;
543 else if(e
.code() == CURLE_FTP_ACCESS_DENIED
)
544 action
= THROWACCESSDENIED
;
545 else if(e
.code() == CURLE_FTP_QUOTE_ERROR
)
547 else if(e
.code() == CURLE_FTP_COULDNT_RETR_FILE
)
548 action
= THROWNOFILE
;
550 // nothing known about the cause of the error
551 action
= THROWGENERAL
;
556 #define FTP_FILE "application/vnd.sun.staroffice.ftp-file"
558 #define FTP_FOLDER "application/vnd.sun.staroffice.ftp-folder"
560 Sequence
<ContentInfo
> SAL_CALL
561 FTPContent::queryCreatableContentsInfo( )
563 return queryCreatableContentsInfo_Static();
567 Sequence
<ContentInfo
>
568 FTPContent::queryCreatableContentsInfo_Static( )
570 Sequence
< ContentInfo
> seq(2);
572 seq
[0].Type
= FTP_FILE
;
573 seq
[0].Attributes
= ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
574 | ContentInfoAttribute::KIND_DOCUMENT
;
575 Sequence
< Property
> props( 1 );
579 cppu::UnoType
<OUString
>::get(),
580 PropertyAttribute::MAYBEVOID
581 | PropertyAttribute::BOUND
);
582 seq
[0].Properties
= props
;
585 seq
[1].Type
= FTP_FOLDER
;
586 seq
[1].Attributes
= ContentInfoAttribute::KIND_FOLDER
;
587 seq
[1].Properties
= props
;
592 Reference
<XContent
> SAL_CALL
593 FTPContent::createNewContent( const ContentInfo
& Info
)
595 if( Info
.Type
=="application/vnd.sun.staroffice.ftp-file" || Info
.Type
== "application/vnd.sun.staroffice.ftp-folder" )
596 return new FTPContent(m_xContext
,
600 return Reference
<XContent
>(nullptr);
604 Reference
<XInterface
> SAL_CALL
605 FTPContent::getParent( )
607 Reference
<XContentIdentifier
>
608 xIdent(new FTPContentIdentifier(m_aFTPURL
.parent()));
609 return Reference
<XInterface
>( m_xProvider
->queryContent(xIdent
), UNO_QUERY
);
614 FTPContent::setParent(const Reference
<XInterface
>& /*Parent*/ )
616 throw NoSupportException();
620 OUString
FTPContent::getParentURL()
622 return m_aFTPURL
.parent();
631 explicit InsertData(const Reference
<XInputStream
>& xInputStream
)
632 : m_xInputStream(xInputStream
) { }
633 virtual ~InsertData() {}
635 // returns the number of bytes actually read
636 virtual sal_Int32
read(sal_Int8
*dest
,sal_Int32 nBytesRequested
) override
;
640 Reference
<XInputStream
> m_xInputStream
;
644 sal_Int32
InsertData::read(sal_Int8
*dest
,sal_Int32 nBytesRequested
)
648 if(m_xInputStream
.is()) {
649 Sequence
<sal_Int8
> seq(nBytesRequested
);
650 m
= m_xInputStream
->readBytes(seq
,nBytesRequested
);
651 memcpy(dest
,seq
.getConstArray(),m
);
657 void FTPContent::insert(const InsertCommandArgument
& aInsertCommand
,
658 const Reference
<XCommandEnvironment
>& Env
)
660 osl::MutexGuard
aGuard(m_aMutex
);
662 if(m_bInserted
&& !m_bTitleSet
) {
663 MissingPropertiesException excep
;
664 excep
.Properties
.realloc(1);
665 excep
.Properties
[0] = "Title";
666 ucbhelper::cancelCommandExecution(Any(excep
), Env
);
670 m_aInfo
.Type
== FTP_FILE
&&
671 !aInsertCommand
.Data
.is())
673 MissingInputStreamException excep
;
674 ucbhelper::cancelCommandExecution(Any(excep
), Env
);
677 bool bReplace(aInsertCommand
.ReplaceExisting
);
681 if(m_aInfo
.Type
== FTP_FILE
) {
682 InsertData
data(aInsertCommand
.Data
);
683 m_aFTPURL
.insert(bReplace
,&data
);
684 } else if(m_aInfo
.Type
== FTP_FOLDER
)
685 m_aFTPURL
.mkdir(bReplace
);
686 } catch(const curl_exception
& e
) {
687 if(e
.code() == FOLDER_MIGHT_EXIST_DURING_INSERT
||
688 e
.code() == FILE_MIGHT_EXIST_DURING_INSERT
) {
690 Reference
<XInteractionHandler
> xInt
;
692 xInt
= Env
->getInteractionHandler();
694 UnsupportedNameClashException excep
;
695 excep
.NameClash
= 0; //NameClash::ERROR;
698 ucbhelper::cancelCommandExecution(Any(excep
), Env
);
701 XInteractionRequestImpl request
;
702 const Reference
<XInteractionRequest
>& xReq(request
.getRequest());
704 if (request
.approved()) {
715 // May not be reached, because both mkdir and insert can throw curl-
722 Reference
< XRow
> FTPContent::getPropertyValues(
723 const Sequence
< Property
>& seqProp
726 rtl::Reference
<ucbhelper::PropertyValueSet
> xRow
=
727 new ucbhelper::PropertyValueSet(m_xContext
);
729 FTPDirentry aDirEntry
= m_aFTPURL
.direntry();
731 for(const auto& rProp
: seqProp
) {
732 const OUString
& Name
= rProp
.Name
;
734 xRow
->appendString(rProp
,aDirEntry
.m_aName
);
735 else if(Name
== "CreatableContentsInfo")
736 xRow
->appendObject(rProp
,
737 makeAny(queryCreatableContentsInfo()));
738 else if(aDirEntry
.m_nMode
!= INETCOREFTP_FILEMODE_UNKNOWN
) {
739 if(Name
== "ContentType")
740 xRow
->appendString(rProp
,
741 (aDirEntry
.m_nMode
& INETCOREFTP_FILEMODE_ISDIR
)
742 ? OUString(FTP_FOLDER
)
743 : OUString(FTP_FILE
) );
744 else if(Name
== "IsReadOnly")
745 xRow
->appendBoolean(rProp
,
747 & INETCOREFTP_FILEMODE_WRITE
) == 0 );
748 else if(Name
== "IsDocument")
749 xRow
->appendBoolean(rProp
,
751 INETCOREFTP_FILEMODE_ISDIR
) != INETCOREFTP_FILEMODE_ISDIR
);
752 else if(Name
== "IsFolder")
753 xRow
->appendBoolean(rProp
,
755 INETCOREFTP_FILEMODE_ISDIR
) == INETCOREFTP_FILEMODE_ISDIR
);
756 else if(Name
== "Size")
757 xRow
->appendLong(rProp
,
759 else if(Name
== "DateCreated")
760 xRow
->appendTimestamp(rProp
,
763 xRow
->appendVoid(rProp
);
765 xRow
->appendVoid(rProp
);
768 return Reference
<XRow
>(xRow
.get());
772 Sequence
<Any
> FTPContent::setPropertyValues(
773 const Sequence
<PropertyValue
>& seqPropVal
)
775 Sequence
<Any
> ret(seqPropVal
.getLength());
776 Sequence
<PropertyChangeEvent
> evt
;
778 osl::MutexGuard
aGuard(m_aMutex
);
779 for(sal_Int32 i
= 0; i
< ret
.getLength(); ++i
) {
780 if ( seqPropVal
[i
].Name
== "Title" ) {
782 if(!(seqPropVal
[i
].Value
>>= Title
)) {
783 ret
[i
] <<= IllegalTypeException();
785 } else if(Title
.isEmpty()) {
786 ret
[i
] <<= IllegalArgumentException();
791 m_aFTPURL
.child(Title
);
793 new FTPContentIdentifier(m_aFTPURL
.ident(false,false));
797 OUString OldTitle
= m_aFTPURL
.ren(Title
);
799 evt
[0].PropertyName
= "Title";
800 evt
[0].Further
= false;
801 evt
[0].PropertyHandle
= -1;
802 evt
[0].OldValue
<<= OldTitle
;
803 evt
[0].NewValue
<<= Title
;
804 } catch(const curl_exception
&) {
805 InteractiveIOException excep
;
806 // any better possibility here?
807 // ( the error code is always CURLE_FTP_QUOTE_ERROR )
808 excep
.Code
= IOErrorCode_ACCESS_DENIED
;
812 Sequence
<Property
> props
=
813 getProperties(Reference
<XCommandEnvironment
>(nullptr));
815 // either unknown or read-only
816 ret
[i
] <<= UnknownPropertyException();
817 const auto& rName
= seqPropVal
[i
].Name
;
818 auto pProp
= std::find_if(props
.begin(), props
.end(),
819 [&rName
](const Property
& rProp
) { return rProp
.Name
== rName
; });
820 if (pProp
!= props
.end()) {
821 ret
[i
] <<= IllegalAccessException(
822 "Property is read-only!",
823 //props[j].Attributes & PropertyAttribute::READONLY
824 // ? "Property is read-only!"
825 // : "Access denied!"),
826 static_cast< cppu::OWeakObject
* >( this ));
831 if(evt
.hasElements()) {
833 notifyPropertiesChange(evt
);
834 (void)exchange(new FTPContentIdentifier(m_aFTPURL
.ident(false,false)));
840 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */