Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / ucb / source / ucp / ftp / ftpcontent.cxx
blob92c3639bebf08c74083c7d4dfb622c04e31a1432
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 throw()
121 OWeakObject::acquire();
124 void SAL_CALL FTPContent::release()
125 throw()
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 ResultSetBase* ResultSetFactory::createResultSet()
213 return new ResultSetI(m_xContext,
214 m_xProvider,
215 m_seq,
216 m_dirvec);
220 // XCommandProcessor methods.
222 enum ACTION { NOACTION,
223 THROWAUTHENTICATIONREQUEST,
224 THROWACCESSDENIED,
225 THROWINTERACTIVECONNECT,
226 THROWRESOLVENAME,
227 THROWQUOTE,
228 THROWNOFILE,
229 THROWGENERAL };
231 // virtual
232 Any SAL_CALL FTPContent::execute( const Command& aCommand,
233 sal_Int32 /*CommandId*/,
234 const Reference<
235 XCommandEnvironment >& Environment)
237 ACTION action(NOACTION);
238 Any aRet;
240 while(true)
244 if(action == THROWAUTHENTICATIONREQUEST)
246 // try to get a continuation first
247 OUString aPassword,aAccount;
248 m_pFCP->forHost(m_aFTPURL.host(),
249 m_aFTPURL.port(),
250 m_aFTPURL.username(),
251 aPassword,
252 aAccount);
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,
258 OUString(),
259 ucbhelper::SimpleAuthenticationRequest
260 ::ENTITY_FIXED,
261 m_aFTPURL.username(),
262 ucbhelper::SimpleAuthenticationRequest
263 ::ENTITY_MODIFY,
264 aPassword));
266 Reference<XInteractionHandler> xInteractionHandler;
267 if(Environment.is())
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())
279 action = NOACTION;
280 else if(Reference<XInteractionSupplyAuthentication>(
281 xSelection,UNO_QUERY).is()) {
282 m_pFCP->setHost(
283 m_aFTPURL.host(),
284 m_aFTPURL.port(),
285 m_aFTPURL.username(),
286 p->getAuthenticationSupplier()->getPassword(),
287 aAccount);
288 action = NOACTION;
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());
306 // return aRet;
307 // }
309 switch (action)
311 case NOACTION:
312 break;
314 case THROWAUTHENTICATIONREQUEST:
315 ucbhelper::cancelCommandExecution(
316 aRet,
317 Reference<XCommandEnvironment>(nullptr));
318 break;
320 case THROWACCESSDENIED:
322 Sequence<Any> seq(comphelper::InitAnyPropertySequence(
324 {"Uri", Any(m_aFTPURL.ident(false,false))}
325 }));
326 ucbhelper::cancelCommandExecution(
327 IOErrorCode_ACCESS_DENIED,
328 seq,
329 Environment);
330 break;
332 case THROWINTERACTIVECONNECT:
334 InteractiveNetworkConnectException excep;
335 excep.Server = m_aFTPURL.host();
336 aRet <<= excep;
337 ucbhelper::cancelCommandExecution(
338 aRet,
339 Environment);
340 break;
342 case THROWRESOLVENAME:
344 InteractiveNetworkResolveNameException excep;
345 excep.Server = m_aFTPURL.host();
346 aRet <<= excep;
347 ucbhelper::cancelCommandExecution(
348 aRet,
349 Environment);
350 break;
352 case THROWNOFILE:
354 Sequence<Any> seq(comphelper::InitAnyPropertySequence(
356 {"Uri", Any(m_aFTPURL.ident(false,false))}
357 }));
358 ucbhelper::cancelCommandExecution(
359 IOErrorCode_NO_FILE,
360 seq,
361 Environment);
362 break;
364 case THROWQUOTE:
365 case THROWGENERAL:
366 ucbhelper::cancelCommandExecution(
367 IOErrorCode_GENERAL,
368 Sequence<Any>(0),
369 Environment);
370 break;
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),
380 -1);
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),
394 -1);
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),
415 -1);
416 ucbhelper::cancelCommandExecution(aRet,Environment);
418 insert(aInsertArgument,Environment);
420 else if(aCommand.Name == "delete") {
421 m_aFTPURL.del();
422 deleted();
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),
430 -1);
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()));
449 for (;;) {
450 Sequence<sal_Int8> byte_seq(4096);
451 sal_Int32 n = xStream->readBytes(byte_seq, 4096);
452 if (n == 0) {
453 break;
455 try {
456 if(byte_seq.getLength() != n)
457 byte_seq.realloc(n);
458 xOutputStream->writeBytes(byte_seq);
459 } catch(const NotConnectedException&) {
461 } catch(const BufferSizeExceededException&) {
463 } catch(const IOException&) {
468 else {
469 aRet <<= UnsupportedDataSinkException(
470 OUString(),
471 static_cast< cppu::OWeakObject * >(this),
472 aOpenCommand.Sink);
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(
483 m_xContext,
484 aOpenCommand,
485 std::make_unique<ResultSetFactory>(m_xContext,
486 m_xProvider.get(),
487 aOpenCommand.Properties,
488 resvec));
489 aRet <<= xSet;
491 else if(aOpenCommand.Mode ==
492 OpenMode::DOCUMENT_SHARE_DENY_NONE ||
493 aOpenCommand.Mode ==
494 OpenMode::DOCUMENT_SHARE_DENY_WRITE) {
495 // Unsupported OpenMode
496 aRet <<= UnsupportedOpenModeException(
497 OUString(),
498 static_cast< cppu::OWeakObject * >(this),
499 static_cast< sal_Int16 >(aOpenCommand.Mode));
500 ucbhelper::cancelCommandExecution(aRet,Environment);
502 else {
503 aRet <<= IllegalArgumentException(
504 "Unexpected OpenMode!",
505 static_cast< cppu::OWeakObject * >(this),
506 -1);
508 ucbhelper::cancelCommandExecution(aRet,Environment);
510 } else if(aCommand.Name == "createNewContent") {
511 ContentInfo aArg;
512 if (!(aCommand.Argument >>= aArg)) {
513 ucbhelper::cancelCommandExecution(
514 makeAny(
515 IllegalArgumentException(
516 "Wrong argument type!",
517 static_cast< cppu::OWeakObject * >(this),
518 -1)),
519 Environment);
520 // Unreachable
522 aRet <<= createNewContent(aArg);
523 } else {
524 aRet <<= UnsupportedCommandException(
525 aCommand.Name,
526 static_cast< cppu::OWeakObject * >(this));
527 ucbhelper::cancelCommandExecution(aRet,Environment);
530 return aRet;
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)
546 action = THROWQUOTE;
547 else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE)
548 action = THROWNOFILE;
549 else
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();
566 // 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 );
576 props[0] = Property(
577 "Title",
579 cppu::UnoType<OUString>::get(),
580 PropertyAttribute::MAYBEVOID
581 | PropertyAttribute::BOUND );
582 seq[0].Properties = props;
584 // folder
585 seq[1].Type = FTP_FOLDER;
586 seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER;
587 seq[1].Properties = props;
589 return seq;
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,
597 m_pFCP,
598 m_xIdentifier,Info);
599 else
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 );
613 void SAL_CALL
614 FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
616 throw NoSupportException();
620 OUString FTPContent::getParentURL()
622 return m_aFTPURL.parent();
626 class InsertData
627 : public CurlInput {
629 public:
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;
638 private:
640 Reference<XInputStream> m_xInputStream;
644 sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
646 sal_Int32 m = 0;
648 if(m_xInputStream.is()) {
649 Sequence<sal_Int8> seq(nBytesRequested);
650 m = m_xInputStream->readBytes(seq,nBytesRequested);
651 memcpy(dest,seq.getConstArray(),m);
653 return 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);
669 if(m_bInserted &&
670 m_aInfo.Type == FTP_FILE &&
671 !aInsertCommand.Data.is())
673 MissingInputStreamException excep;
674 ucbhelper::cancelCommandExecution(Any(excep), Env);
677 bool bReplace(aInsertCommand.ReplaceExisting);
679 retry:
680 try {
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) {
689 // Interact
690 Reference<XInteractionHandler> xInt;
691 if(Env.is())
692 xInt = Env->getInteractionHandler();
694 UnsupportedNameClashException excep;
695 excep.NameClash = 0; //NameClash::ERROR;
697 if(!xInt.is()) {
698 ucbhelper::cancelCommandExecution(Any(excep), Env);
701 XInteractionRequestImpl request;
702 const Reference<XInteractionRequest>& xReq(request.getRequest());
703 xInt->handle(xReq);
704 if (request.approved()) {
705 bReplace = true;
706 goto retry;
708 else
709 throw excep;
711 else
712 throw;
715 // May not be reached, because both mkdir and insert can throw curl-
716 // exceptions
717 m_bInserted = false;
718 inserted();
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;
733 if(Name == "Title")
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,
746 (aDirEntry.m_nMode
747 & INETCOREFTP_FILEMODE_WRITE) == 0 );
748 else if(Name == "IsDocument")
749 xRow->appendBoolean(rProp,
750 (aDirEntry.m_nMode &
751 INETCOREFTP_FILEMODE_ISDIR) != INETCOREFTP_FILEMODE_ISDIR);
752 else if(Name == "IsFolder")
753 xRow->appendBoolean(rProp,
754 (aDirEntry.m_nMode &
755 INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR);
756 else if(Name == "Size")
757 xRow->appendLong(rProp,
758 aDirEntry.m_nSize);
759 else if(Name == "DateCreated")
760 xRow->appendTimestamp(rProp,
761 aDirEntry.m_aDate);
762 else
763 xRow->appendVoid(rProp);
764 } else
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" ) {
781 OUString Title;
782 if(!(seqPropVal[i].Value >>= Title)) {
783 ret[i] <<= IllegalTypeException();
784 continue;
785 } else if(Title.isEmpty()) {
786 ret[i] <<= IllegalArgumentException();
787 continue;
790 if(m_bInserted) {
791 m_aFTPURL.child(Title);
792 m_xIdentifier =
793 new FTPContentIdentifier(m_aFTPURL.ident(false,false));
794 m_bTitleSet = true;
795 } else
796 try {
797 OUString OldTitle = m_aFTPURL.ren(Title);
798 evt.realloc(1);
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;
809 ret[i] <<= excep;
811 } else {
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()) {
832 // title has changed
833 notifyPropertiesChange(evt);
834 (void)exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
837 return ret;
840 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */