bump product version to 7.2.5.1
[LibreOffice.git] / ucb / source / ucp / ftp / ftpcontent.cxx
blobca38f16ae08c804c486ebd1d943bd5c2b8e09532
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 "ftpintreq.hxx"
37 #include <memory>
38 #include <vector>
39 #include <string.h>
40 #include "curl.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>
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;
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)
92 , m_pFCP(pProvider)
93 , m_aFTPURL(aFTPURL)
94 , m_bInserted(false)
95 , m_bTitleSet(false)
99 FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
100 FTPContentProvider* pProvider,
101 const Reference< XContentIdentifier >& Identifier,
102 const ContentInfo& Info)
103 : ContentImplHelper(rxContext,pProvider,Identifier)
104 , m_pFCP(pProvider)
105 , m_aFTPURL(Identifier->getContentIdentifier(), pProvider)
106 , m_bInserted(true)
107 , m_bTitleSet(false)
108 , m_aInfo(Info)
112 FTPContent::~FTPContent()
116 // XInterface methods.
118 void SAL_CALL FTPContent::acquire()
119 noexcept
121 OWeakObject::acquire();
124 void SAL_CALL FTPContent::release()
125 noexcept
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" };
183 // XContent methods.
185 // virtual
186 OUString SAL_CALL FTPContent::getContentType()
188 return FTP_CONTENT_TYPE;
191 // XCommandProcessor methods.
193 //virtual
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),
205 m_seq(seq),
206 m_dirvec(dirvec)
211 rtl::Reference<ResultSetBase> ResultSetFactory::createResultSet()
213 return new ResultSetI(m_xContext,
214 m_xProvider,
215 m_seq,
216 m_dirvec);
220 // XCommandProcessor methods.
222 namespace {
224 enum ACTION { NOACTION,
225 THROWAUTHENTICATIONREQUEST,
226 THROWACCESSDENIED,
227 THROWINTERACTIVECONNECT,
228 THROWRESOLVENAME,
229 THROWQUOTE,
230 THROWNOFILE,
231 THROWGENERAL };
235 // virtual
236 Any SAL_CALL FTPContent::execute( const Command& aCommand,
237 sal_Int32 /*CommandId*/,
238 const Reference<
239 XCommandEnvironment >& Environment)
241 ACTION action(NOACTION);
242 Any aRet;
244 while(true)
248 if(action == THROWAUTHENTICATIONREQUEST)
250 // try to get a continuation first
251 OUString aPassword,aAccount;
252 m_pFCP->forHost(m_aFTPURL.host(),
253 m_aFTPURL.port(),
254 m_aFTPURL.username(),
255 aPassword,
256 aAccount);
257 rtl::Reference<ucbhelper::SimpleAuthenticationRequest>
258 p( new ucbhelper::SimpleAuthenticationRequest(
259 m_aFTPURL.ident(false, false),
260 m_aFTPURL.host(), // ServerName
261 ucbhelper::SimpleAuthenticationRequest::ENTITY_NA,
262 OUString(),
263 ucbhelper::SimpleAuthenticationRequest
264 ::ENTITY_FIXED,
265 m_aFTPURL.username(),
266 ucbhelper::SimpleAuthenticationRequest
267 ::ENTITY_MODIFY,
268 aPassword));
270 Reference<XInteractionHandler> xInteractionHandler;
271 if(Environment.is())
272 xInteractionHandler =
273 Environment->getInteractionHandler();
275 if( xInteractionHandler.is()) {
276 xInteractionHandler->handle(p);
278 Reference<XInterface> xSelection(
279 p->getSelection());
281 if(Reference<XInteractionRetry>(
282 xSelection,UNO_QUERY).is())
283 action = NOACTION;
284 else if(Reference<XInteractionSupplyAuthentication>(
285 xSelection,UNO_QUERY).is()) {
286 m_pFCP->setHost(
287 m_aFTPURL.host(),
288 m_aFTPURL.port(),
289 m_aFTPURL.username(),
290 p->getAuthenticationSupplier()->getPassword(),
291 aAccount);
292 action = NOACTION;
295 aRet = p->getRequest();
298 // if(aCommand.Name.equalsAscii(
299 // "getPropertyValues") &&
300 // action != NOACTION) {
301 // // It is not allowed to throw if
302 // // command is getPropertyValues
303 // rtl::Reference<ucbhelper::PropertyValueSet> xRow =
304 // new ucbhelper::PropertyValueSet(m_xSMgr);
305 // Sequence<Property> Properties;
306 // aCommand.Argument >>= Properties;
307 // for(int i = 0; i < Properties.getLength(); ++i)
308 // xRow->appendVoid(Properties[i]);
309 // aRet <<= Reference<XRow>(xRow.get());
310 // return aRet;
311 // }
313 switch (action)
315 case NOACTION:
316 break;
318 case THROWAUTHENTICATIONREQUEST:
319 ucbhelper::cancelCommandExecution(
320 aRet,
321 Reference<XCommandEnvironment>(nullptr));
322 break;
324 case THROWACCESSDENIED:
326 Sequence<Any> seq(comphelper::InitAnyPropertySequence(
328 {"Uri", Any(m_aFTPURL.ident(false,false))}
329 }));
330 ucbhelper::cancelCommandExecution(
331 IOErrorCode_ACCESS_DENIED,
332 seq,
333 Environment);
334 break;
336 case THROWINTERACTIVECONNECT:
338 InteractiveNetworkConnectException excep;
339 excep.Server = m_aFTPURL.host();
340 aRet <<= excep;
341 ucbhelper::cancelCommandExecution(
342 aRet,
343 Environment);
344 break;
346 case THROWRESOLVENAME:
348 InteractiveNetworkResolveNameException excep;
349 excep.Server = m_aFTPURL.host();
350 aRet <<= excep;
351 ucbhelper::cancelCommandExecution(
352 aRet,
353 Environment);
354 break;
356 case THROWNOFILE:
358 Sequence<Any> seq(comphelper::InitAnyPropertySequence(
360 {"Uri", Any(m_aFTPURL.ident(false,false))}
361 }));
362 ucbhelper::cancelCommandExecution(
363 IOErrorCode_NO_FILE,
364 seq,
365 Environment);
366 break;
368 case THROWQUOTE:
369 case THROWGENERAL:
370 ucbhelper::cancelCommandExecution(
371 IOErrorCode_GENERAL,
372 Sequence<Any>(0),
373 Environment);
374 break;
377 if(aCommand.Name == "getPropertyValues") {
378 Sequence<Property> Properties;
379 if(!(aCommand.Argument >>= Properties))
381 aRet <<= IllegalArgumentException(
382 "Wrong argument type!",
383 static_cast< cppu::OWeakObject * >(this),
384 -1);
385 ucbhelper::cancelCommandExecution(aRet,Environment);
388 aRet <<= getPropertyValues(Properties);
390 else if(aCommand.Name == "setPropertyValues")
392 Sequence<PropertyValue> propertyValues;
394 if( ! ( aCommand.Argument >>= propertyValues ) ) {
395 aRet <<= IllegalArgumentException(
396 "Wrong argument type!",
397 static_cast< cppu::OWeakObject * >(this),
398 -1);
399 ucbhelper::cancelCommandExecution(aRet,Environment);
402 aRet <<= setPropertyValues(propertyValues);
404 else if(aCommand.Name == "getCommandInfo") {
405 // Note: Implemented by base class.
406 aRet <<= getCommandInfo(Environment);
408 else if(aCommand.Name == "getPropertySetInfo") {
409 // Note: Implemented by base class.
410 aRet <<= getPropertySetInfo(Environment);
412 else if(aCommand.Name == "insert")
414 InsertCommandArgument aInsertArgument;
415 if ( ! ( aCommand.Argument >>= aInsertArgument ) ) {
416 aRet <<= IllegalArgumentException(
417 "Wrong argument type!",
418 static_cast< cppu::OWeakObject * >(this),
419 -1);
420 ucbhelper::cancelCommandExecution(aRet,Environment);
422 insert(aInsertArgument,Environment);
424 else if(aCommand.Name == "delete") {
425 m_aFTPURL.del();
426 deleted();
428 else if(aCommand.Name == "open") {
429 OpenCommandArgument2 aOpenCommand;
430 if ( !( aCommand.Argument >>= aOpenCommand ) ) {
431 aRet <<= IllegalArgumentException(
432 "Wrong argument type!",
433 static_cast< cppu::OWeakObject * >(this),
434 -1);
436 ucbhelper::cancelCommandExecution(aRet,Environment);
439 if(aOpenCommand.Mode == OpenMode::DOCUMENT) {
440 // Open as a document
441 Reference<XActiveDataSink>
442 xActiveDataSink(aOpenCommand.Sink,UNO_QUERY);
443 Reference< XOutputStream >
444 xOutputStream(aOpenCommand.Sink,UNO_QUERY);
446 if(xActiveDataSink.is()) {
447 xActiveDataSink->setInputStream(
448 new ucbhelper::FdInputStream(m_aFTPURL.open()));
450 else if(xOutputStream.is()) {
451 Reference<XInputStream> xStream(
452 new ucbhelper::FdInputStream(m_aFTPURL.open()));
453 for (;;) {
454 Sequence<sal_Int8> byte_seq(4096);
455 sal_Int32 n = xStream->readBytes(byte_seq, 4096);
456 if (n == 0) {
457 break;
459 try {
460 if(byte_seq.getLength() != n)
461 byte_seq.realloc(n);
462 xOutputStream->writeBytes(byte_seq);
463 } catch(const NotConnectedException&) {
465 } catch(const BufferSizeExceededException&) {
467 } catch(const IOException&) {
472 else {
473 aRet <<= UnsupportedDataSinkException(
474 OUString(),
475 static_cast< cppu::OWeakObject * >(this),
476 aOpenCommand.Sink);
477 ucbhelper::cancelCommandExecution(aRet,Environment);
480 else if(aOpenCommand.Mode == OpenMode::ALL ||
481 aOpenCommand.Mode == OpenMode::DOCUMENTS ||
482 aOpenCommand.Mode == OpenMode::FOLDERS ) {
483 std::vector<FTPDirentry> resvec =
484 m_aFTPURL.list(sal_Int16(aOpenCommand.Mode));
485 Reference< XDynamicResultSet > xSet
486 = new DynamicResultSet(
487 m_xContext,
488 aOpenCommand,
489 std::make_unique<ResultSetFactory>(m_xContext,
490 m_xProvider.get(),
491 aOpenCommand.Properties,
492 resvec));
493 aRet <<= xSet;
495 else if(aOpenCommand.Mode ==
496 OpenMode::DOCUMENT_SHARE_DENY_NONE ||
497 aOpenCommand.Mode ==
498 OpenMode::DOCUMENT_SHARE_DENY_WRITE) {
499 // Unsupported OpenMode
500 aRet <<= UnsupportedOpenModeException(
501 OUString(),
502 static_cast< cppu::OWeakObject * >(this),
503 static_cast< sal_Int16 >(aOpenCommand.Mode));
504 ucbhelper::cancelCommandExecution(aRet,Environment);
506 else {
507 aRet <<= IllegalArgumentException(
508 "Unexpected OpenMode!",
509 static_cast< cppu::OWeakObject * >(this),
510 -1);
512 ucbhelper::cancelCommandExecution(aRet,Environment);
514 } else if(aCommand.Name == "createNewContent") {
515 ContentInfo aArg;
516 if (!(aCommand.Argument >>= aArg)) {
517 ucbhelper::cancelCommandExecution(
518 makeAny(
519 IllegalArgumentException(
520 "Wrong argument type!",
521 static_cast< cppu::OWeakObject * >(this),
522 -1)),
523 Environment);
524 // Unreachable
526 aRet <<= createNewContent(aArg);
527 } else {
528 aRet <<= UnsupportedCommandException(
529 aCommand.Name,
530 static_cast< cppu::OWeakObject * >(this));
531 ucbhelper::cancelCommandExecution(aRet,Environment);
534 return aRet;
536 catch(const curl_exception& e)
538 if(e.code() == CURLE_COULDNT_CONNECT)
539 action = THROWINTERACTIVECONNECT;
540 else if(e.code() == CURLE_COULDNT_RESOLVE_HOST )
541 action = THROWRESOLVENAME;
542 else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT ||
543 e.code() == CURLE_LOGIN_DENIED ||
544 e.code() == CURLE_BAD_PASSWORD_ENTERED ||
545 e.code() == CURLE_FTP_WEIRD_PASS_REPLY)
546 action = THROWAUTHENTICATIONREQUEST;
547 else if(e.code() == CURLE_FTP_ACCESS_DENIED)
548 action = THROWACCESSDENIED;
549 else if(e.code() == CURLE_FTP_QUOTE_ERROR)
550 action = THROWQUOTE;
551 else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE)
552 action = THROWNOFILE;
553 else
554 // nothing known about the cause of the error
555 action = THROWGENERAL;
560 #define FTP_FILE "application/vnd.sun.staroffice.ftp-file"
562 #define FTP_FOLDER "application/vnd.sun.staroffice.ftp-folder"
564 Sequence<ContentInfo > SAL_CALL
565 FTPContent::queryCreatableContentsInfo( )
567 return queryCreatableContentsInfo_Static();
570 // static
571 Sequence<ContentInfo >
572 FTPContent::queryCreatableContentsInfo_Static( )
574 Sequence< Property > props( 1 );
575 props[0] = Property(
576 "Title",
578 cppu::UnoType<OUString>::get(),
579 PropertyAttribute::MAYBEVOID
580 | PropertyAttribute::BOUND );
581 return
583 { FTP_FILE, ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | ContentInfoAttribute::KIND_DOCUMENT, props },
584 { FTP_FOLDER, ContentInfoAttribute::KIND_FOLDER, props }
588 Reference<XContent > SAL_CALL
589 FTPContent::createNewContent( const ContentInfo& Info )
591 if( Info.Type =="application/vnd.sun.staroffice.ftp-file" || Info.Type == "application/vnd.sun.staroffice.ftp-folder" )
592 return new FTPContent(m_xContext,
593 m_pFCP,
594 m_xIdentifier,Info);
595 else
596 return Reference<XContent>(nullptr);
600 Reference<XInterface > SAL_CALL
601 FTPContent::getParent( )
603 Reference<XContentIdentifier>
604 xIdent(new FTPContentIdentifier(m_aFTPURL.parent()));
605 return Reference<XInterface>( m_xProvider->queryContent(xIdent), UNO_QUERY );
609 void SAL_CALL
610 FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
612 throw NoSupportException();
616 OUString FTPContent::getParentURL()
618 return m_aFTPURL.parent();
621 namespace {
623 class InsertData
624 : public CurlInput {
626 public:
628 explicit InsertData(const Reference<XInputStream>& xInputStream)
629 : m_xInputStream(xInputStream) { }
630 virtual ~InsertData() {}
632 // returns the number of bytes actually read
633 virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested) override;
635 private:
637 Reference<XInputStream> m_xInputStream;
642 sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
644 sal_Int32 m = 0;
646 if(m_xInputStream.is()) {
647 Sequence<sal_Int8> seq(nBytesRequested);
648 m = m_xInputStream->readBytes(seq,nBytesRequested);
649 memcpy(dest,seq.getConstArray(),m);
651 return m;
655 void FTPContent::insert(const InsertCommandArgument& aInsertCommand,
656 const Reference<XCommandEnvironment>& Env)
658 osl::MutexGuard aGuard(m_aMutex);
660 if(m_bInserted && !m_bTitleSet) {
661 MissingPropertiesException excep;
662 excep.Properties.realloc(1);
663 excep.Properties[0] = "Title";
664 ucbhelper::cancelCommandExecution(Any(excep), Env);
667 if(m_bInserted &&
668 m_aInfo.Type == FTP_FILE &&
669 !aInsertCommand.Data.is())
671 MissingInputStreamException excep;
672 ucbhelper::cancelCommandExecution(Any(excep), Env);
675 bool bReplace(aInsertCommand.ReplaceExisting);
677 retry:
678 try {
679 if(m_aInfo.Type == FTP_FILE) {
680 InsertData data(aInsertCommand.Data);
681 m_aFTPURL.insert(bReplace,&data);
682 } else if(m_aInfo.Type == FTP_FOLDER)
683 m_aFTPURL.mkdir(bReplace);
684 } catch(const curl_exception& e) {
685 if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT ||
686 e.code() == FILE_MIGHT_EXIST_DURING_INSERT) {
687 // Interact
688 Reference<XInteractionHandler> xInt;
689 if(Env.is())
690 xInt = Env->getInteractionHandler();
692 UnsupportedNameClashException excep;
693 excep.NameClash = 0; //NameClash::ERROR;
695 if(!xInt.is()) {
696 ucbhelper::cancelCommandExecution(Any(excep), Env);
699 XInteractionRequestImpl request;
700 const Reference<XInteractionRequest>& xReq(request.getRequest());
701 xInt->handle(xReq);
702 if (request.approved()) {
703 bReplace = true;
704 goto retry;
706 else
707 throw excep;
709 else
710 throw;
713 // May not be reached, because both mkdir and insert can throw curl-
714 // exceptions
715 m_bInserted = false;
716 inserted();
720 Reference< XRow > FTPContent::getPropertyValues(
721 const Sequence< Property >& seqProp
724 rtl::Reference<ucbhelper::PropertyValueSet> xRow =
725 new ucbhelper::PropertyValueSet(m_xContext);
727 FTPDirentry aDirEntry = m_aFTPURL.direntry();
729 for(const auto& rProp : seqProp) {
730 const OUString& Name = rProp.Name;
731 if(Name == "Title")
732 xRow->appendString(rProp,aDirEntry.m_aName);
733 else if(Name == "CreatableContentsInfo")
734 xRow->appendObject(rProp,
735 makeAny(queryCreatableContentsInfo()));
736 else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) {
737 if(Name == "ContentType")
738 xRow->appendString(rProp,
739 (aDirEntry.m_nMode & INETCOREFTP_FILEMODE_ISDIR)
740 ? OUString(FTP_FOLDER)
741 : OUString(FTP_FILE) );
742 else if(Name == "IsReadOnly")
743 xRow->appendBoolean(rProp,
744 (aDirEntry.m_nMode
745 & INETCOREFTP_FILEMODE_WRITE) == 0 );
746 else if(Name == "IsDocument")
747 xRow->appendBoolean(rProp,
748 (aDirEntry.m_nMode &
749 INETCOREFTP_FILEMODE_ISDIR) != INETCOREFTP_FILEMODE_ISDIR);
750 else if(Name == "IsFolder")
751 xRow->appendBoolean(rProp,
752 (aDirEntry.m_nMode &
753 INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR);
754 else if(Name == "Size")
755 xRow->appendLong(rProp,
756 aDirEntry.m_nSize);
757 else if(Name == "DateCreated")
758 xRow->appendTimestamp(rProp,
759 aDirEntry.m_aDate);
760 else
761 xRow->appendVoid(rProp);
762 } else
763 xRow->appendVoid(rProp);
766 return xRow;
770 Sequence<Any> FTPContent::setPropertyValues(
771 const Sequence<PropertyValue>& seqPropVal)
773 Sequence<Any> ret(seqPropVal.getLength());
774 Sequence<PropertyChangeEvent > evt;
776 osl::MutexGuard aGuard(m_aMutex);
777 for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
778 if ( seqPropVal[i].Name == "Title" ) {
779 OUString Title;
780 if(!(seqPropVal[i].Value >>= Title)) {
781 ret[i] <<= IllegalTypeException();
782 continue;
783 } else if(Title.isEmpty()) {
784 ret[i] <<= IllegalArgumentException();
785 continue;
788 if(m_bInserted) {
789 m_aFTPURL.child(Title);
790 m_xIdentifier =
791 new FTPContentIdentifier(m_aFTPURL.ident(false,false));
792 m_bTitleSet = true;
793 } else
794 try {
795 OUString OldTitle = m_aFTPURL.ren(Title);
796 evt.realloc(1);
797 evt[0].PropertyName = "Title";
798 evt[0].Further = false;
799 evt[0].PropertyHandle = -1;
800 evt[0].OldValue <<= OldTitle;
801 evt[0].NewValue <<= Title;
802 } catch(const curl_exception&) {
803 InteractiveIOException excep;
804 // any better possibility here?
805 // ( the error code is always CURLE_FTP_QUOTE_ERROR )
806 excep.Code = IOErrorCode_ACCESS_DENIED;
807 ret[i] <<= excep;
809 } else {
810 Sequence<Property> props =
811 getProperties(Reference<XCommandEnvironment>(nullptr));
813 // either unknown or read-only
814 ret[i] <<= UnknownPropertyException();
815 const auto& rName = seqPropVal[i].Name;
816 auto pProp = std::find_if(props.begin(), props.end(),
817 [&rName](const Property& rProp) { return rProp.Name == rName; });
818 if (pProp != props.end()) {
819 ret[i] <<= IllegalAccessException(
820 "Property is read-only!",
821 //props[j].Attributes & PropertyAttribute::READONLY
822 // ? "Property is read-only!"
823 // : "Access denied!"),
824 static_cast< cppu::OWeakObject * >( this ));
829 if(evt.hasElements()) {
830 // title has changed
831 notifyPropertiesChange(evt);
832 (void)exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
835 return ret;
838 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */