nss: upgrade to release 3.73
[LibreOffice.git] / ucb / source / ucp / ftp / ftpcontent.cxx
blobe655c6cbe162e1d075983ec1ff6816ce634b4a7b
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 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.get());
278 Reference<XInterface> xSelection(
279 p->getSelection().get());
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< ContentInfo > seq(2);
576 seq[0].Type = FTP_FILE;
577 seq[0].Attributes = ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
578 | ContentInfoAttribute::KIND_DOCUMENT;
579 Sequence< Property > props( 1 );
580 props[0] = Property(
581 "Title",
583 cppu::UnoType<OUString>::get(),
584 PropertyAttribute::MAYBEVOID
585 | PropertyAttribute::BOUND );
586 seq[0].Properties = props;
588 // folder
589 seq[1].Type = FTP_FOLDER;
590 seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER;
591 seq[1].Properties = props;
593 return seq;
596 Reference<XContent > SAL_CALL
597 FTPContent::createNewContent( const ContentInfo& Info )
599 if( Info.Type =="application/vnd.sun.staroffice.ftp-file" || Info.Type == "application/vnd.sun.staroffice.ftp-folder" )
600 return new FTPContent(m_xContext,
601 m_pFCP,
602 m_xIdentifier,Info);
603 else
604 return Reference<XContent>(nullptr);
608 Reference<XInterface > SAL_CALL
609 FTPContent::getParent( )
611 Reference<XContentIdentifier>
612 xIdent(new FTPContentIdentifier(m_aFTPURL.parent()));
613 return Reference<XInterface>( m_xProvider->queryContent(xIdent), UNO_QUERY );
617 void SAL_CALL
618 FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
620 throw NoSupportException();
624 OUString FTPContent::getParentURL()
626 return m_aFTPURL.parent();
629 namespace {
631 class InsertData
632 : public CurlInput {
634 public:
636 explicit InsertData(const Reference<XInputStream>& xInputStream)
637 : m_xInputStream(xInputStream) { }
638 virtual ~InsertData() {}
640 // returns the number of bytes actually read
641 virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested) override;
643 private:
645 Reference<XInputStream> m_xInputStream;
650 sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
652 sal_Int32 m = 0;
654 if(m_xInputStream.is()) {
655 Sequence<sal_Int8> seq(nBytesRequested);
656 m = m_xInputStream->readBytes(seq,nBytesRequested);
657 memcpy(dest,seq.getConstArray(),m);
659 return m;
663 void FTPContent::insert(const InsertCommandArgument& aInsertCommand,
664 const Reference<XCommandEnvironment>& Env)
666 osl::MutexGuard aGuard(m_aMutex);
668 if(m_bInserted && !m_bTitleSet) {
669 MissingPropertiesException excep;
670 excep.Properties.realloc(1);
671 excep.Properties[0] = "Title";
672 ucbhelper::cancelCommandExecution(Any(excep), Env);
675 if(m_bInserted &&
676 m_aInfo.Type == FTP_FILE &&
677 !aInsertCommand.Data.is())
679 MissingInputStreamException excep;
680 ucbhelper::cancelCommandExecution(Any(excep), Env);
683 bool bReplace(aInsertCommand.ReplaceExisting);
685 retry:
686 try {
687 if(m_aInfo.Type == FTP_FILE) {
688 InsertData data(aInsertCommand.Data);
689 m_aFTPURL.insert(bReplace,&data);
690 } else if(m_aInfo.Type == FTP_FOLDER)
691 m_aFTPURL.mkdir(bReplace);
692 } catch(const curl_exception& e) {
693 if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT ||
694 e.code() == FILE_MIGHT_EXIST_DURING_INSERT) {
695 // Interact
696 Reference<XInteractionHandler> xInt;
697 if(Env.is())
698 xInt = Env->getInteractionHandler();
700 UnsupportedNameClashException excep;
701 excep.NameClash = 0; //NameClash::ERROR;
703 if(!xInt.is()) {
704 ucbhelper::cancelCommandExecution(Any(excep), Env);
707 XInteractionRequestImpl request;
708 const Reference<XInteractionRequest>& xReq(request.getRequest());
709 xInt->handle(xReq);
710 if (request.approved()) {
711 bReplace = true;
712 goto retry;
714 else
715 throw excep;
717 else
718 throw;
721 // May not be reached, because both mkdir and insert can throw curl-
722 // exceptions
723 m_bInserted = false;
724 inserted();
728 Reference< XRow > FTPContent::getPropertyValues(
729 const Sequence< Property >& seqProp
732 rtl::Reference<ucbhelper::PropertyValueSet> xRow =
733 new ucbhelper::PropertyValueSet(m_xContext);
735 FTPDirentry aDirEntry = m_aFTPURL.direntry();
737 for(const auto& rProp : seqProp) {
738 const OUString& Name = rProp.Name;
739 if(Name == "Title")
740 xRow->appendString(rProp,aDirEntry.m_aName);
741 else if(Name == "CreatableContentsInfo")
742 xRow->appendObject(rProp,
743 makeAny(queryCreatableContentsInfo()));
744 else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) {
745 if(Name == "ContentType")
746 xRow->appendString(rProp,
747 (aDirEntry.m_nMode & INETCOREFTP_FILEMODE_ISDIR)
748 ? OUString(FTP_FOLDER)
749 : OUString(FTP_FILE) );
750 else if(Name == "IsReadOnly")
751 xRow->appendBoolean(rProp,
752 (aDirEntry.m_nMode
753 & INETCOREFTP_FILEMODE_WRITE) == 0 );
754 else if(Name == "IsDocument")
755 xRow->appendBoolean(rProp,
756 (aDirEntry.m_nMode &
757 INETCOREFTP_FILEMODE_ISDIR) != INETCOREFTP_FILEMODE_ISDIR);
758 else if(Name == "IsFolder")
759 xRow->appendBoolean(rProp,
760 (aDirEntry.m_nMode &
761 INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR);
762 else if(Name == "Size")
763 xRow->appendLong(rProp,
764 aDirEntry.m_nSize);
765 else if(Name == "DateCreated")
766 xRow->appendTimestamp(rProp,
767 aDirEntry.m_aDate);
768 else
769 xRow->appendVoid(rProp);
770 } else
771 xRow->appendVoid(rProp);
774 return Reference<XRow>(xRow.get());
778 Sequence<Any> FTPContent::setPropertyValues(
779 const Sequence<PropertyValue>& seqPropVal)
781 Sequence<Any> ret(seqPropVal.getLength());
782 Sequence<PropertyChangeEvent > evt;
784 osl::MutexGuard aGuard(m_aMutex);
785 for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
786 if ( seqPropVal[i].Name == "Title" ) {
787 OUString Title;
788 if(!(seqPropVal[i].Value >>= Title)) {
789 ret[i] <<= IllegalTypeException();
790 continue;
791 } else if(Title.isEmpty()) {
792 ret[i] <<= IllegalArgumentException();
793 continue;
796 if(m_bInserted) {
797 m_aFTPURL.child(Title);
798 m_xIdentifier =
799 new FTPContentIdentifier(m_aFTPURL.ident(false,false));
800 m_bTitleSet = true;
801 } else
802 try {
803 OUString OldTitle = m_aFTPURL.ren(Title);
804 evt.realloc(1);
805 evt[0].PropertyName = "Title";
806 evt[0].Further = false;
807 evt[0].PropertyHandle = -1;
808 evt[0].OldValue <<= OldTitle;
809 evt[0].NewValue <<= Title;
810 } catch(const curl_exception&) {
811 InteractiveIOException excep;
812 // any better possibility here?
813 // ( the error code is always CURLE_FTP_QUOTE_ERROR )
814 excep.Code = IOErrorCode_ACCESS_DENIED;
815 ret[i] <<= excep;
817 } else {
818 Sequence<Property> props =
819 getProperties(Reference<XCommandEnvironment>(nullptr));
821 // either unknown or read-only
822 ret[i] <<= UnknownPropertyException();
823 const auto& rName = seqPropVal[i].Name;
824 auto pProp = std::find_if(props.begin(), props.end(),
825 [&rName](const Property& rProp) { return rProp.Name == rName; });
826 if (pProp != props.end()) {
827 ret[i] <<= IllegalAccessException(
828 "Property is read-only!",
829 //props[j].Attributes & PropertyAttribute::READONLY
830 // ? "Property is read-only!"
831 // : "Access denied!"),
832 static_cast< cppu::OWeakObject * >( this ));
837 if(evt.hasElements()) {
838 // title has changed
839 notifyPropertiesChange(evt);
840 (void)exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
843 return ret;
846 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */