Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / ucp / ftp / ftpcontent.cxx
blob65e2b86f8f21c6829d3a6d60dadfab136ce93c7a
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 <utility>
39 #include <vector>
40 #include <string.h>
41 #include "curl.hxx"
42 #include <comphelper/propertysequence.hxx>
43 #include <cppuhelper/queryinterface.hxx>
44 #include <cppuhelper/supportsservice.hxx>
45 #include <cppuhelper/typeprovider.hxx>
46 #include <ucbhelper/cancelcommandexecution.hxx>
47 #include <ucbhelper/fd_inputstream.hxx>
48 #include <ucbhelper/propertyvalueset.hxx>
49 #include <ucbhelper/simpleauthenticationrequest.hxx>
50 #include <com/sun/star/lang/IllegalAccessException.hpp>
51 #include <com/sun/star/lang/NoSupportException.hpp>
52 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
53 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
54 #include <com/sun/star/beans/IllegalTypeException.hpp>
55 #include <com/sun/star/beans/UnknownPropertyException.hpp>
56 #include <com/sun/star/beans/Property.hpp>
57 #include <com/sun/star/ucb/XCommandInfo.hpp>
58 #include <com/sun/star/io/BufferSizeExceededException.hpp>
59 #include <com/sun/star/io/IOException.hpp>
60 #include <com/sun/star/io/NotConnectedException.hpp>
61 #include <com/sun/star/io/XActiveDataSink.hpp>
62 #include <com/sun/star/io/XOutputStream.hpp>
63 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
64 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
65 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
66 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
67 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
68 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
69 #include <com/sun/star/ucb/InteractiveIOException.hpp>
70 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
71 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
72 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
73 #include <com/sun/star/ucb/OpenMode.hpp>
74 #include <com/sun/star/ucb/IOErrorCode.hpp>
76 using namespace ftp;
77 using namespace com::sun::star::task;
78 using namespace com::sun::star::container;
79 using namespace com::sun::star::lang;
80 using namespace com::sun::star::uno;
81 using namespace com::sun::star::ucb;
82 using namespace com::sun::star::beans;
83 using namespace com::sun::star::io;
84 using namespace com::sun::star::sdbc;
87 // Content Implementation.
89 FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
90 FTPContentProvider* pProvider,
91 const Reference< XContentIdentifier >& Identifier,
92 const FTPURL& aFTPURL)
93 : ContentImplHelper(rxContext,pProvider,Identifier)
94 , m_pFCP(pProvider)
95 , m_aFTPURL(aFTPURL)
96 , m_bInserted(false)
97 , m_bTitleSet(false)
101 FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
102 FTPContentProvider* pProvider,
103 const Reference< XContentIdentifier >& Identifier,
104 ContentInfo Info)
105 : ContentImplHelper(rxContext,pProvider,Identifier)
106 , m_pFCP(pProvider)
107 , m_aFTPURL(Identifier->getContentIdentifier(), pProvider)
108 , m_bInserted(true)
109 , m_bTitleSet(false)
110 , m_aInfo(std::move(Info))
114 FTPContent::~FTPContent()
118 // XInterface methods.
120 void SAL_CALL FTPContent::acquire()
121 noexcept
123 OWeakObject::acquire();
126 void SAL_CALL FTPContent::release()
127 noexcept
129 OWeakObject::release();
132 css::uno::Any SAL_CALL FTPContent::queryInterface( const css::uno::Type & rType )
134 css::uno::Any aRet = cppu::queryInterface( rType,
135 static_cast< XTypeProvider* >(this),
136 static_cast< XServiceInfo* >(this),
137 static_cast< XContent* >(this),
138 static_cast< XCommandProcessor* >(this),
139 static_cast< XContentCreator* >(this),
140 static_cast< XChild* >(this)
142 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
145 // XTypeProvider methods.
147 css::uno::Sequence< sal_Int8 > SAL_CALL FTPContent::getImplementationId()
149 return css::uno::Sequence<sal_Int8>();
152 css::uno::Sequence< css::uno::Type > SAL_CALL FTPContent::getTypes()
154 static cppu::OTypeCollection s_aCollection(
155 cppu::UnoType<XTypeProvider>::get(),
156 cppu::UnoType<XServiceInfo>::get(),
157 cppu::UnoType<XContent>::get(),
158 cppu::UnoType<XCommandProcessor>::get(),
159 cppu::UnoType<XContentCreator>::get(),
160 cppu::UnoType<XChild>::get()
163 return s_aCollection.getTypes();
167 // XServiceInfo methods.
169 OUString SAL_CALL FTPContent::getImplementationName()
171 return "com.sun.star.comp.FTPContent";
174 sal_Bool SAL_CALL FTPContent::supportsService( const OUString& ServiceName )
176 return cppu::supportsService( this, ServiceName );
179 css::uno::Sequence< OUString > SAL_CALL FTPContent::getSupportedServiceNames()
181 return { "com.sun.star.ucb.FTPContent" };
185 // XContent methods.
187 // virtual
188 OUString SAL_CALL FTPContent::getContentType()
190 return FTP_CONTENT_TYPE;
193 // XCommandProcessor methods.
195 //virtual
196 void SAL_CALL FTPContent::abort( sal_Int32 /*CommandId*/ )
201 ResultSetFactory::ResultSetFactory(const Reference<XComponentContext >& rxContext,
202 const Reference<XContentProvider >& xProvider,
203 const Sequence<Property>& seq,
204 std::vector<FTPDirentry>&& dirvec)
205 : m_xContext(rxContext),
206 m_xProvider(xProvider),
207 m_seq(seq),
208 m_dirvec(std::move(dirvec))
213 rtl::Reference<ResultSetBase> ResultSetFactory::createResultSet()
215 return new ResultSetI(m_xContext,
216 m_xProvider,
217 m_seq,
218 m_dirvec);
222 // XCommandProcessor methods.
224 namespace {
226 enum ACTION { NOACTION,
227 THROWAUTHENTICATIONREQUEST,
228 THROWACCESSDENIED,
229 THROWINTERACTIVECONNECT,
230 THROWMALFORMED,
231 THROWRESOLVENAME,
232 THROWQUOTE,
233 THROWNOFILE,
234 THROWGENERAL };
238 // virtual
239 Any SAL_CALL FTPContent::execute( const Command& aCommand,
240 sal_Int32 /*CommandId*/,
241 const Reference<
242 XCommandEnvironment >& Environment)
244 ACTION action(NOACTION);
245 Any aRet;
247 while(true)
251 if(action == THROWAUTHENTICATIONREQUEST)
253 // try to get a continuation first
254 OUString aPassword,aAccount;
255 m_pFCP->forHost(m_aFTPURL.host(),
256 m_aFTPURL.port(),
257 m_aFTPURL.username(),
258 aPassword,
259 aAccount);
260 rtl::Reference<ucbhelper::SimpleAuthenticationRequest>
261 p( new ucbhelper::SimpleAuthenticationRequest(
262 m_aFTPURL.ident(false, false),
263 m_aFTPURL.host(), // ServerName
264 ucbhelper::SimpleAuthenticationRequest::ENTITY_NA,
265 OUString(),
266 ucbhelper::SimpleAuthenticationRequest
267 ::ENTITY_FIXED,
268 m_aFTPURL.username(),
269 ucbhelper::SimpleAuthenticationRequest
270 ::ENTITY_MODIFY,
271 aPassword));
273 Reference<XInteractionHandler> xInteractionHandler;
274 if(Environment.is())
275 xInteractionHandler =
276 Environment->getInteractionHandler();
278 if( xInteractionHandler.is()) {
279 xInteractionHandler->handle(p);
281 Reference<XInterface> xSelection(
282 p->getSelection());
284 if(Reference<XInteractionRetry>(
285 xSelection,UNO_QUERY).is())
286 action = NOACTION;
287 else if(Reference<XInteractionSupplyAuthentication>(
288 xSelection,UNO_QUERY).is()) {
289 m_pFCP->setHost(
290 m_aFTPURL.host(),
291 m_aFTPURL.port(),
292 m_aFTPURL.username(),
293 p->getAuthenticationSupplier()->getPassword(),
294 aAccount);
295 action = NOACTION;
298 aRet = p->getRequest();
301 // if(aCommand.Name.equalsAscii(
302 // "getPropertyValues") &&
303 // action != NOACTION) {
304 // // It is not allowed to throw if
305 // // command is getPropertyValues
306 // rtl::Reference<ucbhelper::PropertyValueSet> xRow =
307 // new ucbhelper::PropertyValueSet(m_xSMgr);
308 // Sequence<Property> Properties;
309 // aCommand.Argument >>= Properties;
310 // for(int i = 0; i < Properties.getLength(); ++i)
311 // xRow->appendVoid(Properties[i]);
312 // aRet <<= Reference<XRow>(xRow.get());
313 // return aRet;
314 // }
316 switch (action)
318 case NOACTION:
319 break;
321 case THROWAUTHENTICATIONREQUEST:
322 ucbhelper::cancelCommandExecution(
323 aRet,
324 Reference<XCommandEnvironment>(nullptr));
325 break;
327 case THROWACCESSDENIED:
329 Sequence<Any> seq(comphelper::InitAnyPropertySequence(
331 {"Uri", Any(m_aFTPURL.ident(false,false))}
332 }));
333 ucbhelper::cancelCommandExecution(
334 IOErrorCode_ACCESS_DENIED,
335 seq,
336 Environment);
337 break;
339 case THROWINTERACTIVECONNECT:
341 InteractiveNetworkConnectException excep;
342 excep.Server = m_aFTPURL.host();
343 aRet <<= excep;
344 ucbhelper::cancelCommandExecution(
345 aRet,
346 Environment);
347 break;
349 case THROWMALFORMED:
351 IllegalIdentifierException ex;
352 aRet <<= ex;
353 ucbhelper::cancelCommandExecution(
354 aRet,
355 Environment);
356 break;
358 case THROWRESOLVENAME:
360 InteractiveNetworkResolveNameException excep;
361 excep.Server = m_aFTPURL.host();
362 aRet <<= excep;
363 ucbhelper::cancelCommandExecution(
364 aRet,
365 Environment);
366 break;
368 case THROWNOFILE:
370 Sequence<Any> seq(comphelper::InitAnyPropertySequence(
372 {"Uri", Any(m_aFTPURL.ident(false,false))}
373 }));
374 ucbhelper::cancelCommandExecution(
375 IOErrorCode_NO_FILE,
376 seq,
377 Environment);
378 break;
380 case THROWQUOTE:
381 case THROWGENERAL:
382 ucbhelper::cancelCommandExecution(
383 IOErrorCode_GENERAL,
384 Sequence<Any>(0),
385 Environment);
386 break;
389 if(aCommand.Name == "getPropertyValues") {
390 Sequence<Property> Properties;
391 if(!(aCommand.Argument >>= Properties))
393 aRet <<= IllegalArgumentException(
394 "Wrong argument type!",
395 static_cast< cppu::OWeakObject * >(this),
396 -1);
397 ucbhelper::cancelCommandExecution(aRet,Environment);
400 aRet <<= getPropertyValues(Properties);
402 else if(aCommand.Name == "setPropertyValues")
404 Sequence<PropertyValue> propertyValues;
406 if( ! ( aCommand.Argument >>= propertyValues ) ) {
407 aRet <<= IllegalArgumentException(
408 "Wrong argument type!",
409 static_cast< cppu::OWeakObject * >(this),
410 -1);
411 ucbhelper::cancelCommandExecution(aRet,Environment);
414 aRet <<= setPropertyValues(propertyValues);
416 else if(aCommand.Name == "getCommandInfo") {
417 // Note: Implemented by base class.
418 aRet <<= getCommandInfo(Environment);
420 else if(aCommand.Name == "getPropertySetInfo") {
421 // Note: Implemented by base class.
422 aRet <<= getPropertySetInfo(Environment);
424 else if(aCommand.Name == "insert")
426 InsertCommandArgument aInsertArgument;
427 if ( ! ( aCommand.Argument >>= aInsertArgument ) ) {
428 aRet <<= IllegalArgumentException(
429 "Wrong argument type!",
430 static_cast< cppu::OWeakObject * >(this),
431 -1);
432 ucbhelper::cancelCommandExecution(aRet,Environment);
434 insert(aInsertArgument,Environment);
436 else if(aCommand.Name == "delete") {
437 m_aFTPURL.del();
438 deleted();
440 else if(aCommand.Name == "open") {
441 OpenCommandArgument2 aOpenCommand;
442 if ( !( aCommand.Argument >>= aOpenCommand ) ) {
443 aRet <<= IllegalArgumentException(
444 "Wrong argument type!",
445 static_cast< cppu::OWeakObject * >(this),
446 -1);
448 ucbhelper::cancelCommandExecution(aRet,Environment);
451 if(aOpenCommand.Mode == OpenMode::DOCUMENT) {
452 // Open as a document
453 Reference<XActiveDataSink>
454 xActiveDataSink(aOpenCommand.Sink,UNO_QUERY);
455 Reference< XOutputStream >
456 xOutputStream(aOpenCommand.Sink,UNO_QUERY);
458 if(xActiveDataSink.is()) {
459 xActiveDataSink->setInputStream(
460 new ucbhelper::FdInputStream(m_aFTPURL.open()));
462 else if(xOutputStream.is()) {
463 Reference<XInputStream> xStream(
464 new ucbhelper::FdInputStream(m_aFTPURL.open()));
465 for (;;) {
466 Sequence<sal_Int8> byte_seq(4096);
467 sal_Int32 n = xStream->readBytes(byte_seq, 4096);
468 if (n == 0) {
469 break;
471 try {
472 if(byte_seq.getLength() != n)
473 byte_seq.realloc(n);
474 xOutputStream->writeBytes(byte_seq);
475 } catch(const NotConnectedException&) {
477 } catch(const BufferSizeExceededException&) {
479 } catch(const IOException&) {
484 else {
485 aRet <<= UnsupportedDataSinkException(
486 OUString(),
487 static_cast< cppu::OWeakObject * >(this),
488 aOpenCommand.Sink);
489 ucbhelper::cancelCommandExecution(aRet,Environment);
492 else if(aOpenCommand.Mode == OpenMode::ALL ||
493 aOpenCommand.Mode == OpenMode::DOCUMENTS ||
494 aOpenCommand.Mode == OpenMode::FOLDERS ) {
495 std::vector<FTPDirentry> resvec =
496 m_aFTPURL.list(sal_Int16(aOpenCommand.Mode));
497 Reference< XDynamicResultSet > xSet
498 = new DynamicResultSet(
499 m_xContext,
500 aOpenCommand,
501 std::make_unique<ResultSetFactory>(m_xContext,
502 m_xProvider.get(),
503 aOpenCommand.Properties,
504 std::move(resvec)));
505 aRet <<= xSet;
507 else if(aOpenCommand.Mode ==
508 OpenMode::DOCUMENT_SHARE_DENY_NONE ||
509 aOpenCommand.Mode ==
510 OpenMode::DOCUMENT_SHARE_DENY_WRITE) {
511 // Unsupported OpenMode
512 aRet <<= UnsupportedOpenModeException(
513 OUString(),
514 static_cast< cppu::OWeakObject * >(this),
515 static_cast< sal_Int16 >(aOpenCommand.Mode));
516 ucbhelper::cancelCommandExecution(aRet,Environment);
518 else {
519 aRet <<= IllegalArgumentException(
520 "Unexpected OpenMode!",
521 static_cast< cppu::OWeakObject * >(this),
522 -1);
524 ucbhelper::cancelCommandExecution(aRet,Environment);
526 } else if(aCommand.Name == "createNewContent") {
527 ContentInfo aArg;
528 if (!(aCommand.Argument >>= aArg)) {
529 ucbhelper::cancelCommandExecution(
530 Any(
531 IllegalArgumentException(
532 "Wrong argument type!",
533 static_cast< cppu::OWeakObject * >(this),
534 -1)),
535 Environment);
536 // Unreachable
538 aRet <<= createNewContent(aArg);
539 } else {
540 aRet <<= UnsupportedCommandException(
541 aCommand.Name,
542 static_cast< cppu::OWeakObject * >(this));
543 ucbhelper::cancelCommandExecution(aRet,Environment);
546 return aRet;
548 catch(const curl_exception& e)
550 if(e.code() == CURLE_COULDNT_CONNECT)
551 action = THROWINTERACTIVECONNECT;
552 else if (e.code() == CURLE_URL_MALFORMAT)
554 action = THROWMALFORMED;
556 else if(e.code() == CURLE_COULDNT_RESOLVE_HOST )
557 action = THROWRESOLVENAME;
558 else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT ||
559 e.code() == CURLE_LOGIN_DENIED ||
560 e.code() == CURLE_BAD_PASSWORD_ENTERED ||
561 e.code() == CURLE_FTP_WEIRD_PASS_REPLY)
562 action = THROWAUTHENTICATIONREQUEST;
563 else if(e.code() == CURLE_FTP_ACCESS_DENIED)
564 action = THROWACCESSDENIED;
565 else if(e.code() == CURLE_FTP_QUOTE_ERROR)
566 action = THROWQUOTE;
567 else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE)
568 action = THROWNOFILE;
569 else
570 // nothing known about the cause of the error
571 action = THROWGENERAL;
576 constexpr OUStringLiteral FTP_FILE = u"application/vnd.sun.staroffice.ftp-file";
578 constexpr OUStringLiteral FTP_FOLDER = u"application/vnd.sun.staroffice.ftp-folder";
580 Sequence<ContentInfo > SAL_CALL
581 FTPContent::queryCreatableContentsInfo( )
583 return queryCreatableContentsInfo_Static();
586 // static
587 Sequence<ContentInfo >
588 FTPContent::queryCreatableContentsInfo_Static( )
590 Sequence< Property > props{ Property(
591 "Title",
593 cppu::UnoType<OUString>::get(),
594 PropertyAttribute::MAYBEVOID
595 | PropertyAttribute::BOUND ) };
596 return
598 { FTP_FILE, ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | ContentInfoAttribute::KIND_DOCUMENT, props },
599 { FTP_FOLDER, ContentInfoAttribute::KIND_FOLDER, props }
603 Reference<XContent > SAL_CALL
604 FTPContent::createNewContent( const ContentInfo& Info )
606 if( Info.Type =="application/vnd.sun.staroffice.ftp-file" || Info.Type == "application/vnd.sun.staroffice.ftp-folder" )
607 return new FTPContent(m_xContext,
608 m_pFCP,
609 m_xIdentifier,Info);
610 else
611 return Reference<XContent>(nullptr);
615 Reference<XInterface > SAL_CALL
616 FTPContent::getParent( )
618 Reference<XContentIdentifier>
619 xIdent(new FTPContentIdentifier(m_aFTPURL.parent()));
620 return Reference<XInterface>( m_xProvider->queryContent(xIdent), UNO_QUERY );
624 void SAL_CALL
625 FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
627 throw NoSupportException();
631 OUString FTPContent::getParentURL()
633 return m_aFTPURL.parent();
636 namespace {
638 class InsertData
639 : public CurlInput {
641 public:
643 explicit InsertData(const Reference<XInputStream>& xInputStream)
644 : m_xInputStream(xInputStream) { }
645 virtual ~InsertData() {}
647 // returns the number of bytes actually read
648 virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested) override;
650 private:
652 Reference<XInputStream> m_xInputStream;
657 sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
659 sal_Int32 m = 0;
661 if(m_xInputStream.is()) {
662 Sequence<sal_Int8> seq(nBytesRequested);
663 m = m_xInputStream->readBytes(seq,nBytesRequested);
664 memcpy(dest,seq.getConstArray(),m);
666 return m;
670 void FTPContent::insert(const InsertCommandArgument& aInsertCommand,
671 const Reference<XCommandEnvironment>& Env)
673 osl::MutexGuard aGuard(m_aMutex);
675 if(m_bInserted && !m_bTitleSet) {
676 MissingPropertiesException excep;
677 excep.Properties = { "Title" };
678 ucbhelper::cancelCommandExecution(Any(excep), Env);
681 if(m_bInserted &&
682 m_aInfo.Type == FTP_FILE &&
683 !aInsertCommand.Data.is())
685 MissingInputStreamException excep;
686 ucbhelper::cancelCommandExecution(Any(excep), Env);
689 bool bReplace(aInsertCommand.ReplaceExisting);
691 retry:
692 try {
693 if(m_aInfo.Type == FTP_FILE) {
694 InsertData data(aInsertCommand.Data);
695 m_aFTPURL.insert(bReplace,&data);
696 } else if(m_aInfo.Type == FTP_FOLDER)
697 m_aFTPURL.mkdir(bReplace);
698 } catch(const curl_exception& e) {
699 if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT ||
700 e.code() == FILE_MIGHT_EXIST_DURING_INSERT) {
701 // Interact
702 Reference<XInteractionHandler> xInt;
703 if(Env.is())
704 xInt = Env->getInteractionHandler();
706 UnsupportedNameClashException excep;
707 excep.NameClash = 0; //NameClash::ERROR;
709 if(!xInt.is()) {
710 ucbhelper::cancelCommandExecution(Any(excep), Env);
713 XInteractionRequestImpl request;
714 const Reference<XInteractionRequest>& xReq(request.getRequest());
715 xInt->handle(xReq);
716 if (request.approved()) {
717 bReplace = true;
718 goto retry;
720 else
721 throw excep;
723 else
724 throw;
727 // May not be reached, because both mkdir and insert can throw curl-
728 // exceptions
729 m_bInserted = false;
730 inserted();
734 Reference< XRow > FTPContent::getPropertyValues(
735 const Sequence< Property >& seqProp
738 rtl::Reference<ucbhelper::PropertyValueSet> xRow =
739 new ucbhelper::PropertyValueSet(m_xContext);
741 FTPDirentry aDirEntry = m_aFTPURL.direntry();
743 for(const auto& rProp : seqProp) {
744 const OUString& Name = rProp.Name;
745 if(Name == "Title")
746 xRow->appendString(rProp,aDirEntry.m_aName);
747 else if(Name == "CreatableContentsInfo")
748 xRow->appendObject(rProp,
749 Any(queryCreatableContentsInfo()));
750 else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) {
751 if(Name == "ContentType")
752 xRow->appendString(rProp,
753 (aDirEntry.m_nMode & INETCOREFTP_FILEMODE_ISDIR)
754 ? OUString(FTP_FOLDER)
755 : OUString(FTP_FILE) );
756 else if(Name == "IsReadOnly")
757 xRow->appendBoolean(rProp,
758 (aDirEntry.m_nMode
759 & INETCOREFTP_FILEMODE_WRITE) == 0 );
760 else if(Name == "IsDocument")
761 xRow->appendBoolean(rProp,
762 (aDirEntry.m_nMode &
763 INETCOREFTP_FILEMODE_ISDIR) != INETCOREFTP_FILEMODE_ISDIR);
764 else if(Name == "IsFolder")
765 xRow->appendBoolean(rProp,
766 (aDirEntry.m_nMode &
767 INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR);
768 else if(Name == "Size")
769 xRow->appendLong(rProp,
770 aDirEntry.m_nSize);
771 else if(Name == "DateCreated")
772 xRow->appendTimestamp(rProp,
773 aDirEntry.m_aDate);
774 else
775 xRow->appendVoid(rProp);
776 } else
777 xRow->appendVoid(rProp);
780 return xRow;
784 Sequence<Any> FTPContent::setPropertyValues(
785 const Sequence<PropertyValue>& seqPropVal)
787 Sequence<Any> ret(seqPropVal.getLength());
788 auto retRange = asNonConstRange(ret);
789 Sequence<PropertyChangeEvent > evt;
791 osl::MutexGuard aGuard(m_aMutex);
792 for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
793 if ( seqPropVal[i].Name == "Title" ) {
794 OUString Title;
795 if(!(seqPropVal[i].Value >>= Title)) {
796 retRange[i] <<= IllegalTypeException();
797 continue;
798 } else if(Title.isEmpty()) {
799 retRange[i] <<= IllegalArgumentException();
800 continue;
803 if(m_bInserted) {
804 m_aFTPURL.child(Title);
805 m_xIdentifier =
806 new FTPContentIdentifier(m_aFTPURL.ident(false,false));
807 m_bTitleSet = true;
808 } else
809 try {
810 OUString OldTitle = m_aFTPURL.ren(Title);
811 evt = { { /* Source */ {},
812 /* PropertyName */ "Title",
813 /* Further */ false,
814 /* PropertyHandle */ -1,
815 /* OldValue */ Any(OldTitle),
816 /* NewValue */ Any(Title) } };
817 } catch(const curl_exception&) {
818 InteractiveIOException excep;
819 // any better possibility here?
820 // ( the error code is always CURLE_FTP_QUOTE_ERROR )
821 excep.Code = IOErrorCode_ACCESS_DENIED;
822 retRange[i] <<= excep;
824 } else {
825 const Sequence<Property> props =
826 getProperties(Reference<XCommandEnvironment>(nullptr));
828 // either unknown or read-only
829 retRange[i] <<= UnknownPropertyException();
830 const auto& rName = seqPropVal[i].Name;
831 auto pProp = std::find_if(props.begin(), props.end(),
832 [&rName](const Property& rProp) { return rProp.Name == rName; });
833 if (pProp != props.end()) {
834 retRange[i] <<= IllegalAccessException(
835 "Property is read-only!",
836 //props[j].Attributes & PropertyAttribute::READONLY
837 // ? "Property is read-only!"
838 // : "Access denied!"),
839 static_cast< cppu::OWeakObject * >( this ));
844 if(evt.hasElements()) {
845 // title has changed
846 notifyPropertiesChange(evt);
847 (void)exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
850 return ret;
853 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */