Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : /**************************************************************************
22 : TODO
23 : **************************************************************************
24 :
25 : *************************************************************************/
26 : #include <com/sun/star/beans/PropertyAttribute.hpp>
27 :
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 "ftpcfunc.hxx"
36 : #include "ftpstrcont.hxx"
37 : #include "ftpintreq.hxx"
38 :
39 : #include <memory>
40 : #include <vector>
41 : #include <string.h>
42 : #include "curl.hxx"
43 : #include <curl/easy.h>
44 : #include <comphelper/processfactory.hxx>
45 : #include <ucbhelper/cancelcommandexecution.hxx>
46 : #include <ucbhelper/contentidentifier.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/ucb/ContentInfoAttribute.hpp>
52 : #include <com/sun/star/beans/UnknownPropertyException.hpp>
53 : #include <com/sun/star/beans/Property.hpp>
54 : #include <com/sun/star/beans/PropertyValue.hpp>
55 : #include <com/sun/star/ucb/XCommandInfo.hpp>
56 : #include <com/sun/star/io/XActiveDataSink.hpp>
57 : #include <com/sun/star/io/XOutputStream.hpp>
58 : #include <com/sun/star/io/XActiveDataStreamer.hpp>
59 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
60 : #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
61 : #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
62 : #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
63 : #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
64 : #include <com/sun/star/ucb/InteractiveIOException.hpp>
65 : #include <com/sun/star/ucb/MissingPropertiesException.hpp>
66 : #include <com/sun/star/ucb/MissingInputStreamException.hpp>
67 : #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
68 : #include <com/sun/star/ucb/NameClashException.hpp>
69 : #include <com/sun/star/ucb/OpenMode.hpp>
70 : #include <com/sun/star/ucb/IOErrorCode.hpp>
71 :
72 : using namespace ftp;
73 : using namespace com::sun::star::task;
74 : using namespace com::sun::star::container;
75 : using namespace com::sun::star::lang;
76 : using namespace com::sun::star::uno;
77 : using namespace com::sun::star::ucb;
78 : using namespace com::sun::star::beans;
79 : using namespace com::sun::star::io;
80 : using namespace com::sun::star::sdbc;
81 :
82 :
83 : // Content Implementation.
84 :
85 2 : FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
86 : FTPContentProvider* pProvider,
87 : const Reference< XContentIdentifier >& Identifier,
88 : const FTPURL& aFTPURL)
89 : : ContentImplHelper(rxContext,pProvider,Identifier)
90 : , m_pFCP(pProvider)
91 : , m_aFTPURL(aFTPURL)
92 : , m_bInserted(false)
93 2 : , m_bTitleSet(false)
94 : {
95 2 : }
96 :
97 0 : FTPContent::FTPContent( const Reference< XComponentContext >& rxContext,
98 : FTPContentProvider* pProvider,
99 : const Reference< XContentIdentifier >& Identifier,
100 : const ContentInfo& Info)
101 : : ContentImplHelper(rxContext,pProvider,Identifier)
102 : , m_pFCP(pProvider)
103 0 : , m_aFTPURL(Identifier->getContentIdentifier(), pProvider)
104 : , m_bInserted(true)
105 : , m_bTitleSet(false)
106 0 : , m_aInfo(Info)
107 : {
108 0 : }
109 :
110 4 : FTPContent::~FTPContent()
111 : {
112 4 : }
113 :
114 : // XInterface methods.
115 :
116 17 : void SAL_CALL FTPContent::acquire()
117 : throw()
118 : {
119 17 : OWeakObject::acquire();
120 17 : }
121 :
122 17 : void SAL_CALL FTPContent::release()
123 : throw()
124 : {
125 17 : OWeakObject::release();
126 17 : }
127 :
128 6 : css::uno::Any SAL_CALL FTPContent::queryInterface( const css::uno::Type & rType )
129 : throw( css::uno::RuntimeException, std::exception )
130 : {
131 : css::uno::Any aRet = cppu::queryInterface( rType,
132 : (static_cast< XTypeProvider* >(this)),
133 : (static_cast< XServiceInfo* >(this)),
134 : (static_cast< XContent* >(this)),
135 : (static_cast< XCommandProcessor* >(this)),
136 : (static_cast< XContentCreator* >(this)),
137 : (static_cast< XChild* >(this))
138 6 : );
139 6 : return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
140 : }
141 :
142 : // XTypeProvider methods.
143 :
144 0 : css::uno::Sequence< sal_Int8 > SAL_CALL FTPContent::getImplementationId()
145 : throw( css::uno::RuntimeException,
146 : std::exception )
147 : {
148 0 : return css::uno::Sequence<sal_Int8>();
149 : }
150 :
151 0 : css::uno::Sequence< css::uno::Type > SAL_CALL FTPContent::getTypes()
152 : throw( css::uno::RuntimeException,
153 : std::exception )
154 : {
155 : static cppu::OTypeCollection* pCollection = NULL;
156 0 : if ( !pCollection )
157 : {
158 0 : osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
159 0 : if ( !pCollection )
160 : {
161 : static cppu::OTypeCollection collection(
162 0 : cppu::UnoType<XTypeProvider>::get(),
163 0 : cppu::UnoType<XServiceInfo>::get(),
164 0 : cppu::UnoType<XContent>::get(),
165 0 : cppu::UnoType<XCommandProcessor>::get(),
166 0 : cppu::UnoType<XContentCreator>::get(),
167 0 : cppu::UnoType<XChild>::get()
168 0 : );
169 0 : pCollection = &collection;
170 0 : }
171 : }
172 0 : return (*pCollection).getTypes();
173 : }
174 :
175 :
176 :
177 : // XServiceInfo methods.
178 :
179 0 : OUString SAL_CALL FTPContent::getImplementationName()
180 : throw( css::uno::RuntimeException, std::exception )
181 : {
182 0 : return getImplementationName_Static();
183 : }
184 :
185 0 : OUString FTPContent::getImplementationName_Static()
186 : {
187 0 : return OUString( "com.sun.star.comp.FTPContent");
188 : }
189 :
190 0 : sal_Bool SAL_CALL FTPContent::supportsService( const OUString& ServiceName )
191 : throw( css::uno::RuntimeException, std::exception )
192 : {
193 0 : return cppu::supportsService( this, ServiceName );
194 : }
195 :
196 0 : css::uno::Sequence< OUString > SAL_CALL FTPContent::getSupportedServiceNames()
197 : throw( css::uno::RuntimeException, std::exception )
198 : {
199 0 : return getSupportedServiceNames_Static();
200 : }
201 :
202 0 : css::uno::Sequence< OUString > FTPContent::getSupportedServiceNames_Static()
203 : {
204 0 : css::uno::Sequence< OUString > aSNS( 1 );
205 0 : aSNS.getArray()[ 0 ] = "com.sun.star.ucb.FTPContent";
206 0 : return aSNS;
207 : }
208 :
209 :
210 :
211 :
212 :
213 : // XContent methods.
214 :
215 : // virtual
216 0 : OUString SAL_CALL FTPContent::getContentType()
217 : throw( RuntimeException, std::exception )
218 : {
219 0 : return OUString(FTP_CONTENT_TYPE);
220 : }
221 :
222 : // XCommandProcessor methods.
223 :
224 : //virtual
225 0 : void SAL_CALL FTPContent::abort( sal_Int32 /*CommandId*/ )
226 : throw( RuntimeException, std::exception )
227 : {
228 0 : }
229 :
230 : /***************************************************************************/
231 : /* */
232 : /* Internal implementation class. */
233 : /* */
234 : /***************************************************************************/
235 :
236 0 : class ResultSetFactoryI : public ResultSetFactory
237 : {
238 : public:
239 :
240 0 : ResultSetFactoryI(const Reference<XComponentContext >& rxContext,
241 : const Reference<XContentProvider >& xProvider,
242 : sal_Int32 nOpenMode,
243 : const Sequence<Property>& seq,
244 : const Sequence<NumberedSortingInfo>& seqSort,
245 : const std::vector<FTPDirentry>& dirvec)
246 : : m_xContext(rxContext),
247 : m_xProvider(xProvider),
248 : m_nOpenMode(nOpenMode),
249 : m_seq(seq),
250 : m_seqSort(seqSort),
251 0 : m_dirvec(dirvec)
252 : {
253 0 : }
254 :
255 0 : virtual ResultSetBase* createResultSet() SAL_OVERRIDE
256 : {
257 : return new ResultSetI(m_xContext,
258 : m_xProvider,
259 : m_nOpenMode,
260 : m_seq,
261 : m_seqSort,
262 0 : m_dirvec);
263 : }
264 :
265 : public:
266 :
267 : Reference< XComponentContext > m_xContext;
268 : Reference< XContentProvider > m_xProvider;
269 : sal_Int32 m_nOpenMode;
270 : Sequence< Property > m_seq;
271 : Sequence< NumberedSortingInfo > m_seqSort;
272 : std::vector<FTPDirentry> m_dirvec;
273 : };
274 :
275 : // XCommandProcessor methods.
276 :
277 : enum ACTION { NOACTION,
278 : THROWAUTHENTICATIONREQUEST,
279 : THROWACCESSDENIED,
280 : THROWINTERACTIVECONNECT,
281 : THROWRESOLVENAME,
282 : THROWQUOTE,
283 : THROWNOFILE,
284 : THROWGENERAL };
285 :
286 : // virtual
287 1 : Any SAL_CALL FTPContent::execute( const Command& aCommand,
288 : sal_Int32 /*CommandId*/,
289 : const Reference<
290 : XCommandEnvironment >& Environment)
291 : throw( Exception,
292 : CommandAbortedException,
293 : RuntimeException,
294 : std::exception)
295 : {
296 1 : ACTION action(NOACTION);
297 1 : Any aRet;
298 :
299 : while(true)
300 : {
301 : try
302 : {
303 2 : if(action == THROWAUTHENTICATIONREQUEST)
304 : {
305 : // try to get a continuation first
306 0 : OUString aRealm,aPassword,aAccount;
307 : m_pFCP->forHost(m_aFTPURL.host(),
308 : m_aFTPURL.port(),
309 : m_aFTPURL.username(),
310 : aPassword,
311 0 : aAccount);
312 : rtl::Reference<ucbhelper::SimpleAuthenticationRequest>
313 : p( new ucbhelper::SimpleAuthenticationRequest(
314 : m_aFTPURL.ident(false, false),
315 : m_aFTPURL.host(), // ServerName
316 : ucbhelper::SimpleAuthenticationRequest::ENTITY_NA,
317 : aRealm,
318 : ucbhelper::SimpleAuthenticationRequest
319 : ::ENTITY_FIXED,
320 : m_aFTPURL.username(),
321 : ucbhelper::SimpleAuthenticationRequest
322 : ::ENTITY_MODIFY,
323 0 : aPassword));
324 :
325 0 : Reference<XInteractionHandler> xInteractionHandler;
326 0 : if(Environment.is())
327 0 : xInteractionHandler =
328 0 : Environment->getInteractionHandler();
329 :
330 0 : if( xInteractionHandler.is()) {
331 0 : xInteractionHandler->handle(p.get());
332 :
333 : Reference<XInterface> xSelection(
334 0 : p->getSelection().get());
335 :
336 0 : if(Reference<XInteractionRetry>(
337 0 : xSelection,UNO_QUERY).is())
338 0 : action = NOACTION;
339 0 : else if(Reference<XInteractionSupplyAuthentication>(
340 0 : xSelection,UNO_QUERY).is()) {
341 : m_pFCP->setHost(
342 : m_aFTPURL.host(),
343 : m_aFTPURL.port(),
344 : m_aFTPURL.username(),
345 0 : p->getAuthenticationSupplier()->getPassword(),
346 0 : aAccount);
347 0 : action = NOACTION;
348 0 : }
349 : }
350 0 : aRet = p->getRequest();
351 : }
352 :
353 : // if(aCommand.Name.equalsAscii(
354 : // "getPropertyValues") &&
355 : // action != NOACTION) {
356 : // // It is not allowed to throw if
357 : // // command is getPropertyValues
358 : // rtl::Reference<ucbhelper::PropertyValueSet> xRow =
359 : // new ucbhelper::PropertyValueSet(m_xSMgr);
360 : // Sequence<Property> Properties;
361 : // aCommand.Argument >>= Properties;
362 : // for(int i = 0; i < Properties.getLength(); ++i)
363 : // xRow->appendVoid(Properties[i]);
364 : // aRet <<= Reference<XRow>(xRow.get());
365 : // return aRet;
366 : // }
367 :
368 2 : switch (action)
369 : {
370 : case NOACTION:
371 1 : break;
372 :
373 : case THROWAUTHENTICATIONREQUEST:
374 : ucbhelper::cancelCommandExecution(
375 : aRet,
376 0 : Reference<XCommandEnvironment>(0));
377 0 : break;
378 :
379 : case THROWACCESSDENIED:
380 : {
381 0 : Sequence<Any> seq(1);
382 0 : PropertyValue value;
383 0 : value.Name = "Uri";
384 0 : value.Handle = -1;
385 0 : value.Value <<= m_aFTPURL.ident(false,false);
386 0 : value.State = PropertyState_DIRECT_VALUE;
387 0 : seq[0] <<= value;
388 : ucbhelper::cancelCommandExecution(
389 : IOErrorCode_ACCESS_DENIED,
390 : seq,
391 0 : Environment);
392 0 : break;
393 : }
394 : case THROWINTERACTIVECONNECT:
395 : {
396 0 : InteractiveNetworkConnectException excep;
397 0 : excep.Server = m_aFTPURL.host();
398 0 : aRet <<= excep;
399 : ucbhelper::cancelCommandExecution(
400 : aRet,
401 0 : Environment);
402 0 : break;
403 : }
404 : case THROWRESOLVENAME:
405 : {
406 1 : InteractiveNetworkResolveNameException excep;
407 1 : excep.Server = m_aFTPURL.host();
408 1 : aRet <<= excep;
409 : ucbhelper::cancelCommandExecution(
410 : aRet,
411 1 : Environment);
412 1 : break;
413 : }
414 : case THROWNOFILE:
415 : {
416 0 : Sequence<Any> seq(1);
417 0 : PropertyValue value;
418 0 : value.Name = "Uri";
419 0 : value.Handle = -1;
420 0 : value.Value <<= m_aFTPURL.ident(false,false);
421 0 : value.State = PropertyState_DIRECT_VALUE;
422 0 : seq[0] <<= value;
423 : ucbhelper::cancelCommandExecution(
424 : IOErrorCode_NO_FILE,
425 : seq,
426 0 : Environment);
427 0 : break;
428 : }
429 : case THROWQUOTE:
430 : case THROWGENERAL:
431 : ucbhelper::cancelCommandExecution(
432 : IOErrorCode_GENERAL,
433 : Sequence<Any>(0),
434 0 : Environment);
435 0 : break;
436 : }
437 :
438 1 : if(aCommand.Name == "getPropertyValues") {
439 0 : Sequence<Property> Properties;
440 0 : if(!(aCommand.Argument >>= Properties))
441 : {
442 0 : aRet <<= IllegalArgumentException(
443 : OUString( "Wrong argument type!" ),
444 : static_cast< cppu::OWeakObject * >(this),
445 0 : -1);
446 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
447 : }
448 :
449 0 : aRet <<= getPropertyValues(Properties,Environment);
450 : }
451 1 : else if(aCommand.Name == "setPropertyValues")
452 : {
453 0 : Sequence<PropertyValue> propertyValues;
454 :
455 0 : if( ! ( aCommand.Argument >>= propertyValues ) ) {
456 0 : aRet <<= IllegalArgumentException(
457 : OUString( "Wrong argument type!" ),
458 : static_cast< cppu::OWeakObject * >(this),
459 0 : -1);
460 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
461 : }
462 :
463 0 : aRet <<= setPropertyValues(propertyValues);
464 : }
465 1 : else if(aCommand.Name == "getCommandInfo") {
466 : // Note: Implemented by base class.
467 0 : aRet <<= getCommandInfo(Environment);
468 : }
469 1 : else if(aCommand.Name == "getPropertySetInfo") {
470 : // Note: Implemented by base class.
471 0 : aRet <<= getPropertySetInfo(Environment);
472 : }
473 1 : else if(aCommand.Name == "insert")
474 : {
475 0 : InsertCommandArgument aInsertArgument;
476 0 : if ( ! ( aCommand.Argument >>= aInsertArgument ) ) {
477 0 : aRet <<= IllegalArgumentException(
478 : OUString( "Wrong argument type!" ),
479 : static_cast< cppu::OWeakObject * >(this),
480 0 : -1);
481 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
482 : }
483 0 : insert(aInsertArgument,Environment);
484 : }
485 1 : else if(aCommand.Name == "delete") {
486 0 : m_aFTPURL.del();
487 0 : deleted();
488 : }
489 1 : else if(aCommand.Name == "open") {
490 1 : OpenCommandArgument2 aOpenCommand;
491 1 : if ( !( aCommand.Argument >>= aOpenCommand ) ) {
492 0 : aRet <<= IllegalArgumentException(
493 : OUString( "Wrong argument type!" ),
494 : static_cast< cppu::OWeakObject * >(this),
495 0 : -1);
496 :
497 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
498 : }
499 :
500 1 : if(aOpenCommand.Mode == OpenMode::DOCUMENT) {
501 : // Open as a document
502 : Reference<XActiveDataSink>
503 0 : xActiveDataSink(aOpenCommand.Sink,UNO_QUERY);
504 : Reference< XOutputStream >
505 0 : xOutputStream(aOpenCommand.Sink,UNO_QUERY);
506 :
507 0 : if(xActiveDataSink.is()) {
508 0 : xActiveDataSink->setInputStream(
509 0 : new ucbhelper::FdInputStream(m_aFTPURL.open()));
510 : }
511 0 : else if(xOutputStream.is()) {
512 : Reference<XInputStream> xStream(
513 0 : new ucbhelper::FdInputStream(m_aFTPURL.open()));
514 0 : Sequence<sal_Int8> byte_seq(4096);
515 0 : sal_Int32 n = 1000; // value does not matter here
516 : for (;;) {
517 0 : n = xStream->readBytes(byte_seq,4096);
518 0 : if (n == 0) {
519 0 : break;
520 : }
521 : try {
522 0 : if(byte_seq.getLength() != n)
523 0 : byte_seq.realloc(n);
524 0 : xOutputStream->writeBytes(byte_seq);
525 0 : } catch(const NotConnectedException&) {
526 :
527 0 : } catch(const BufferSizeExceededException&) {
528 :
529 0 : } catch(const IOException&) {
530 :
531 : }
532 0 : }
533 0 : if(n) {
534 0 : Sequence<Any> seq(1);
535 0 : PropertyValue value;
536 0 : value.Name = "Uri";
537 0 : value.Handle = -1;
538 0 : value.Value <<= m_aFTPURL.ident(false,false);
539 0 : value.State = PropertyState_DIRECT_VALUE;
540 0 : seq[0] <<= value;
541 : ucbhelper::cancelCommandExecution(
542 : IOErrorCode_UNKNOWN,
543 : seq,
544 0 : Environment);
545 0 : }
546 : }
547 : else {
548 0 : aRet <<= UnsupportedDataSinkException(
549 : OUString(),
550 : static_cast< cppu::OWeakObject * >(this),
551 0 : aOpenCommand.Sink);
552 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
553 0 : }
554 : }
555 1 : else if(aOpenCommand.Mode == OpenMode::ALL ||
556 0 : aOpenCommand.Mode == OpenMode::DOCUMENTS ||
557 0 : aOpenCommand.Mode == OpenMode::FOLDERS ) {
558 : std::vector<FTPDirentry> resvec =
559 1 : m_aFTPURL.list(sal_Int16(aOpenCommand.Mode));
560 : Reference< XDynamicResultSet > xSet
561 : = new DynamicResultSet(
562 : m_xContext,
563 : this,
564 : aOpenCommand,
565 : Environment,
566 : new ResultSetFactoryI(m_xContext,
567 0 : m_xProvider.get(),
568 : aOpenCommand.Mode,
569 : aOpenCommand.Properties,
570 : aOpenCommand.SortingInfo,
571 0 : resvec));
572 0 : aRet <<= xSet;
573 : }
574 0 : else if(aOpenCommand.Mode ==
575 0 : OpenMode::DOCUMENT_SHARE_DENY_NONE ||
576 0 : aOpenCommand.Mode ==
577 : OpenMode::DOCUMENT_SHARE_DENY_WRITE) {
578 : // Unsupported OpenMode
579 0 : aRet <<= UnsupportedOpenModeException(
580 : OUString(),
581 : static_cast< cppu::OWeakObject * >(this),
582 0 : static_cast< sal_Int16 >(aOpenCommand.Mode));
583 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
584 : }
585 : else {
586 0 : aRet <<= IllegalArgumentException(
587 : OUString( "Unexpected OpenMode!" ),
588 : static_cast< cppu::OWeakObject * >(this),
589 0 : -1);
590 :
591 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
592 1 : }
593 0 : } else if(aCommand.Name == "createNewContent") {
594 0 : ContentInfo aArg;
595 0 : if (!(aCommand.Argument >>= aArg)) {
596 : ucbhelper::cancelCommandExecution(
597 : makeAny(
598 : IllegalArgumentException(
599 : OUString( "Wrong argument type!" ),
600 : static_cast< cppu::OWeakObject * >(this),
601 : -1)),
602 0 : Environment);
603 : // Unreachable
604 : }
605 0 : aRet <<= createNewContent(aArg);
606 : } else {
607 0 : aRet <<= UnsupportedCommandException(
608 : aCommand.Name,
609 0 : static_cast< cppu::OWeakObject * >(this));
610 0 : ucbhelper::cancelCommandExecution(aRet,Environment);
611 : }
612 :
613 0 : return aRet;
614 : }
615 2 : catch(const curl_exception& e)
616 : {
617 1 : if(e.code() == CURLE_COULDNT_CONNECT)
618 0 : action = THROWINTERACTIVECONNECT;
619 1 : else if(e.code() == CURLE_COULDNT_RESOLVE_HOST )
620 1 : action = THROWRESOLVENAME;
621 0 : else if(e.code() == CURLE_FTP_USER_PASSWORD_INCORRECT ||
622 0 : e.code() == CURLE_LOGIN_DENIED ||
623 0 : e.code() == CURLE_BAD_PASSWORD_ENTERED ||
624 0 : e.code() == CURLE_FTP_WEIRD_PASS_REPLY)
625 0 : action = THROWAUTHENTICATIONREQUEST;
626 0 : else if(e.code() == CURLE_FTP_ACCESS_DENIED)
627 0 : action = THROWACCESSDENIED;
628 0 : else if(e.code() == CURLE_FTP_QUOTE_ERROR)
629 0 : action = THROWQUOTE;
630 0 : else if(e.code() == CURLE_FTP_COULDNT_RETR_FILE)
631 0 : action = THROWNOFILE;
632 : else
633 : // nothing known about the cause of the error
634 0 : action = THROWGENERAL;
635 : }
636 : }
637 : }
638 :
639 : #define FTP_FILE "application/vnd.sun.staroffice.ftp-file"
640 :
641 : #define FTP_FOLDER "application/vnd.sun.staroffice.ftp-folder"
642 :
643 : Sequence<ContentInfo > SAL_CALL
644 0 : FTPContent::queryCreatableContentsInfo( )
645 : throw (RuntimeException, std::exception)
646 : {
647 0 : return queryCreatableContentsInfo_Static();
648 : }
649 :
650 : // static
651 : Sequence<ContentInfo >
652 0 : FTPContent::queryCreatableContentsInfo_Static( )
653 : throw (RuntimeException)
654 : {
655 0 : Sequence< ContentInfo > seq(2);
656 :
657 0 : seq[0].Type = FTP_FILE;
658 0 : seq[0].Attributes = ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
659 0 : | ContentInfoAttribute::KIND_DOCUMENT;
660 0 : Sequence< Property > props( 1 );
661 0 : props[0] = Property(
662 : OUString("Title"),
663 : -1,
664 0 : cppu::UnoType<OUString>::get(),
665 : PropertyAttribute::MAYBEVOID
666 0 : | PropertyAttribute::BOUND );
667 0 : seq[0].Properties = props;
668 :
669 : // folder
670 0 : seq[1].Type = FTP_FOLDER;
671 0 : seq[1].Attributes = ContentInfoAttribute::KIND_FOLDER;
672 0 : seq[1].Properties = props;
673 :
674 0 : return seq;
675 : }
676 :
677 : Reference<XContent > SAL_CALL
678 0 : FTPContent::createNewContent( const ContentInfo& Info )
679 : throw (RuntimeException, std::exception)
680 : {
681 0 : if( Info.Type =="application/vnd.sun.staroffice.ftp-file" || Info.Type == "application/vnd.sun.staroffice.ftp-folder" )
682 : return new FTPContent(m_xContext,
683 : m_pFCP,
684 0 : m_xIdentifier,Info);
685 : else
686 0 : return Reference<XContent>(0);
687 : }
688 :
689 :
690 :
691 :
692 : Reference<XInterface > SAL_CALL
693 0 : FTPContent::getParent( )
694 : throw (RuntimeException, std::exception)
695 : {
696 : Reference<XContentIdentifier>
697 0 : xIdent(new FTPContentIdentifier(m_aFTPURL.parent(false)));
698 0 : return Reference<XInterface>( m_xProvider->queryContent(xIdent), UNO_QUERY );
699 : }
700 :
701 :
702 : void SAL_CALL
703 0 : FTPContent::setParent(const Reference<XInterface >& /*Parent*/ )
704 : throw (NoSupportException,
705 : RuntimeException, std::exception)
706 : {
707 0 : throw NoSupportException();
708 : }
709 :
710 :
711 :
712 0 : OUString FTPContent::getParentURL()
713 : {
714 0 : return m_aFTPURL.parent();
715 : }
716 :
717 :
718 : class InsertData
719 : : public CurlInput {
720 :
721 : public:
722 :
723 0 : explicit InsertData(const Reference<XInputStream>& xInputStream)
724 0 : : m_xInputStream(xInputStream) { }
725 0 : virtual ~InsertData() {}
726 :
727 : // returns the number of bytes actually read
728 : virtual sal_Int32 read(sal_Int8 *dest,sal_Int32 nBytesRequested) SAL_OVERRIDE;
729 :
730 : private:
731 :
732 : Reference<XInputStream> m_xInputStream;
733 : };
734 :
735 :
736 :
737 0 : sal_Int32 InsertData::read(sal_Int8 *dest,sal_Int32 nBytesRequested)
738 : {
739 0 : sal_Int32 m = 0;
740 :
741 0 : if(m_xInputStream.is()) {
742 0 : Sequence<sal_Int8> seq(nBytesRequested);
743 0 : m = m_xInputStream->readBytes(seq,nBytesRequested);
744 0 : memcpy(dest,seq.getConstArray(),m);
745 : }
746 0 : return m;
747 : }
748 :
749 :
750 0 : void FTPContent::insert(const InsertCommandArgument& aInsertCommand,
751 : const Reference<XCommandEnvironment>& Env)
752 : {
753 0 : osl::MutexGuard aGuard(m_aMutex);
754 :
755 0 : if(m_bInserted && !m_bTitleSet) {
756 0 : MissingPropertiesException excep;
757 0 : excep.Properties.realloc(1);
758 0 : excep.Properties[0] = "Title";
759 0 : Any aAny; aAny <<= excep;
760 0 : ucbhelper::cancelCommandExecution(aAny,Env);
761 : }
762 :
763 0 : if(m_bInserted &&
764 0 : m_aInfo.Type == FTP_FILE &&
765 0 : !aInsertCommand.Data.is())
766 : {
767 0 : MissingInputStreamException excep;
768 0 : Any aAny; aAny <<= excep;
769 0 : ucbhelper::cancelCommandExecution(aAny,Env);
770 : }
771 :
772 0 : bool bReplace(aInsertCommand.ReplaceExisting);
773 :
774 : retry:
775 : try {
776 0 : if(m_aInfo.Type == FTP_FILE) {
777 0 : InsertData data(aInsertCommand.Data);
778 0 : m_aFTPURL.insert(bReplace,&data);
779 0 : } else if(m_aInfo.Type == FTP_FOLDER)
780 0 : m_aFTPURL.mkdir(bReplace);
781 0 : } catch(const curl_exception& e) {
782 0 : if(e.code() == FILE_EXIST_DURING_INSERT ||
783 0 : e.code() == FOLDER_EXIST_DURING_INSERT) {
784 : // Deprecated, not used anymore:
785 0 : NameClashException excep;
786 0 : excep.Name = m_aFTPURL.child();
787 0 : Any aAny;
788 0 : aAny <<= excep;
789 0 : ucbhelper::cancelCommandExecution(aAny,Env);
790 0 : } else if(e.code() == FOLDER_MIGHT_EXIST_DURING_INSERT ||
791 0 : e.code() == FILE_MIGHT_EXIST_DURING_INSERT) {
792 : // Interact
793 0 : Reference<XInteractionHandler> xInt;
794 0 : if(Env.is())
795 0 : xInt = Env->getInteractionHandler();
796 :
797 0 : UnsupportedNameClashException excep;
798 0 : excep.NameClash = 0; //NameClash::ERROR;
799 :
800 0 : if(!xInt.is()) {
801 0 : Any aAny;
802 0 : aAny <<= excep;
803 0 : ucbhelper::cancelCommandExecution(aAny,Env);
804 : }
805 :
806 0 : XInteractionRequestImpl* p = new XInteractionRequestImpl;
807 0 : Reference<XInteractionRequest> req(p);
808 0 : xInt->handle(req);
809 0 : if(p->approved()) {
810 0 : bReplace = true;
811 0 : goto retry;
812 : }
813 : else
814 0 : throw excep;
815 : }
816 : else
817 0 : throw;
818 0 : }
819 :
820 : // May not be reached, because both mkdir and insert can throw curl-
821 : // exceptions
822 0 : m_bInserted = false;
823 0 : inserted();
824 0 : }
825 :
826 :
827 :
828 0 : Reference< XRow > FTPContent::getPropertyValues(
829 : const Sequence< Property >& seqProp,
830 : const Reference<XCommandEnvironment>& /*environment*/
831 : )
832 : {
833 : rtl::Reference<ucbhelper::PropertyValueSet> xRow =
834 0 : new ucbhelper::PropertyValueSet(m_xContext);
835 :
836 0 : FTPDirentry aDirEntry = m_aFTPURL.direntry();
837 :
838 0 : for(sal_Int32 i = 0; i < seqProp.getLength(); ++i) {
839 0 : const OUString& Name = seqProp[i].Name;
840 0 : if(Name == "Title")
841 0 : xRow->appendString(seqProp[i],aDirEntry.m_aName);
842 0 : else if(Name == "CreatableContentsInfo")
843 0 : xRow->appendObject(seqProp[i],
844 0 : makeAny(queryCreatableContentsInfo()));
845 0 : else if(aDirEntry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) {
846 0 : if(Name == "ContentType")
847 0 : xRow->appendString(seqProp[i],
848 0 : aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR
849 : ? OUString(FTP_FOLDER)
850 0 : : OUString(FTP_FILE) );
851 0 : else if(Name == "IsReadOnly")
852 0 : xRow->appendBoolean(seqProp[i],
853 : (aDirEntry.m_nMode
854 0 : & INETCOREFTP_FILEMODE_WRITE) == 0 );
855 0 : else if(Name == "IsDocument")
856 0 : xRow->appendBoolean(seqProp[i],
857 0 : (aDirEntry.m_nMode &
858 0 : INETCOREFTP_FILEMODE_ISDIR) != INETCOREFTP_FILEMODE_ISDIR);
859 0 : else if(Name == "IsFolder")
860 0 : xRow->appendBoolean(seqProp[i],
861 0 : (aDirEntry.m_nMode &
862 0 : INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR);
863 0 : else if(Name == "Size")
864 0 : xRow->appendLong(seqProp[i],
865 0 : aDirEntry.m_nSize);
866 0 : else if(Name == "DateCreated")
867 0 : xRow->appendTimestamp(seqProp[i],
868 0 : aDirEntry.m_aDate);
869 : else
870 0 : xRow->appendVoid(seqProp[i]);
871 : } else
872 0 : xRow->appendVoid(seqProp[i]);
873 : }
874 :
875 0 : return Reference<XRow>(xRow.get());
876 : }
877 :
878 :
879 :
880 0 : Sequence<Any> FTPContent::setPropertyValues(
881 : const Sequence<PropertyValue>& seqPropVal)
882 : {
883 0 : Sequence<Any> ret(seqPropVal.getLength());
884 0 : Sequence<PropertyChangeEvent > evt;
885 :
886 0 : osl::MutexGuard aGuard(m_aMutex);
887 0 : for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
888 0 : if ( seqPropVal[i].Name == "Title" ) {
889 0 : OUString Title;
890 0 : if(!(seqPropVal[i].Value >>= Title)) {
891 0 : ret[i] <<= IllegalTypeException();
892 0 : continue;
893 0 : } else if(Title.isEmpty()) {
894 0 : ret[i] <<= IllegalArgumentException();
895 0 : continue;
896 : }
897 :
898 0 : if(m_bInserted) {
899 0 : m_aFTPURL.child(Title);
900 0 : m_xIdentifier =
901 0 : new FTPContentIdentifier(m_aFTPURL.ident(false,false));
902 0 : m_bTitleSet = true;
903 : } else
904 : try {
905 0 : OUString OldTitle = m_aFTPURL.ren(Title);
906 0 : evt.realloc(1);
907 0 : evt[0].PropertyName = "Title";
908 0 : evt[0].Further = false;
909 0 : evt[0].PropertyHandle = -1;
910 0 : evt[0].OldValue <<= OldTitle;
911 0 : evt[0].NewValue <<= Title;
912 0 : } catch(const curl_exception&) {
913 0 : InteractiveIOException excep;
914 : // any better possibility here?
915 : // ( the error code is always CURLE_FTP_QUOTE_ERROR )
916 0 : excep.Code = IOErrorCode_ACCESS_DENIED;
917 0 : ret[i] <<= excep;
918 0 : }
919 : } else {
920 : Sequence<Property> props =
921 0 : getProperties(Reference<XCommandEnvironment>(0));
922 :
923 : // either unknown or read-only
924 0 : ret[i] <<= UnknownPropertyException();
925 0 : for(sal_Int32 j = 0; j < props.getLength(); ++j)
926 0 : if(props[j].Name == seqPropVal[i].Name) {
927 0 : ret[i] <<= IllegalAccessException(
928 : OUString( "Property is read-only!"),
929 : //props[j].Attributes & PropertyAttribute::READONLY
930 : // ? "Property is read-only!"
931 : // : "Access denied!"),
932 0 : static_cast< cppu::OWeakObject * >( this ));
933 0 : break;
934 0 : }
935 : }
936 : }
937 :
938 0 : if(evt.getLength()) {
939 : // title has changed
940 0 : notifyPropertiesChange(evt);
941 0 : (void)exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
942 : }
943 :
944 0 : return ret;
945 : }
946 :
947 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|