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 4 : 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 4 : , m_bTitleSet(false)
94 : {
95 4 : }
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 8 : FTPContent::~FTPContent()
111 : {
112 8 : }
113 :
114 : // XInterface methods.
115 :
116 34 : void SAL_CALL FTPContent::acquire()
117 : throw()
118 : {
119 34 : OWeakObject::acquire();
120 34 : }
121 :
122 34 : void SAL_CALL FTPContent::release()
123 : throw()
124 : {
125 34 : OWeakObject::release();
126 34 : }
127 :
128 12 : 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 12 : );
139 12 : 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 ] = OUString( "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 2 : 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 2 : ACTION action(NOACTION);
297 2 : Any aRet;
298 :
299 : while(true)
300 : {
301 : try
302 : {
303 4 : 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 4 : switch (action)
369 : {
370 : case NOACTION:
371 2 : 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 2 : InteractiveNetworkResolveNameException excep;
407 2 : excep.Server = m_aFTPURL.host();
408 2 : aRet <<= excep;
409 : ucbhelper::cancelCommandExecution(
410 : aRet,
411 2 : Environment);
412 2 : 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 2 : if(aCommand.Name.equalsAscii("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 2 : else if(aCommand.Name.equalsAscii("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 2 : else if(aCommand.Name.equalsAscii("getCommandInfo")) {
466 : // Note: Implemented by base class.
467 0 : aRet <<= getCommandInfo(Environment);
468 : }
469 2 : else if(aCommand.Name.equalsAscii("getPropertySetInfo")) {
470 : // Note: Implemented by base class.
471 0 : aRet <<= getPropertySetInfo(Environment);
472 : }
473 2 : else if(aCommand.Name.equalsAscii( "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 2 : else if(aCommand.Name.equalsAscii("delete")) {
486 0 : m_aFTPURL.del();
487 0 : deleted();
488 : }
489 2 : else if(aCommand.Name.equalsAscii( "open" )) {
490 2 : OpenCommandArgument2 aOpenCommand;
491 2 : 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 2 : 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 2 : else if(aOpenCommand.Mode == OpenMode::ALL ||
556 0 : aOpenCommand.Mode == OpenMode::DOCUMENTS ||
557 0 : aOpenCommand.Mode == OpenMode::FOLDERS ) {
558 : std::vector<FTPDirentry> resvec =
559 2 : 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 2 : }
593 0 : } else if(aCommand.Name.equalsAscii("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 4 : catch(const curl_exception& e)
616 : {
617 2 : if(e.code() == CURLE_COULDNT_CONNECT)
618 0 : action = THROWINTERACTIVECONNECT;
619 2 : else if(e.code() == CURLE_COULDNT_RESOLVE_HOST )
620 2 : 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 OUString( "application/vnd.sun.staroffice.ftp-file")
640 :
641 : #define FTP_FOLDER OUString( "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 : 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.equalsAscii("Title"))
841 0 : xRow->appendString(seqProp[i],aDirEntry.m_aName);
842 0 : else if(Name.equalsAscii("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.equalsAscii("ContentType"))
847 0 : xRow->appendString(seqProp[i],
848 0 : aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR
849 : ? FTP_FOLDER
850 0 : : FTP_FILE );
851 0 : else if(Name.equalsAscii("IsReadOnly"))
852 0 : xRow->appendBoolean(seqProp[i],
853 : aDirEntry.m_nMode
854 0 : & INETCOREFTP_FILEMODE_WRITE
855 : ? 0
856 0 : : 1 );
857 0 : else if(Name.equalsAscii("IsDocument"))
858 0 : xRow->appendBoolean(seqProp[i],
859 0 : (aDirEntry.m_nMode &
860 0 : INETCOREFTP_FILEMODE_ISDIR) != INETCOREFTP_FILEMODE_ISDIR);
861 0 : else if(Name.equalsAscii("IsFolder"))
862 0 : xRow->appendBoolean(seqProp[i],
863 0 : (aDirEntry.m_nMode &
864 0 : INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR);
865 0 : else if(Name.equalsAscii("Size"))
866 0 : xRow->appendLong(seqProp[i],
867 0 : aDirEntry.m_nSize);
868 0 : else if(Name.equalsAscii("DateCreated"))
869 0 : xRow->appendTimestamp(seqProp[i],
870 0 : aDirEntry.m_aDate);
871 : else
872 0 : xRow->appendVoid(seqProp[i]);
873 : } else
874 0 : xRow->appendVoid(seqProp[i]);
875 : }
876 :
877 0 : return Reference<XRow>(xRow.get());
878 : }
879 :
880 :
881 :
882 0 : Sequence<Any> FTPContent::setPropertyValues(
883 : const Sequence<PropertyValue>& seqPropVal)
884 : {
885 0 : Sequence<Any> ret(seqPropVal.getLength());
886 0 : Sequence<PropertyChangeEvent > evt;
887 :
888 0 : osl::MutexGuard aGuard(m_aMutex);
889 0 : for(sal_Int32 i = 0; i < ret.getLength(); ++i) {
890 0 : if ( seqPropVal[i].Name == "Title" ) {
891 0 : OUString Title;
892 0 : if(!(seqPropVal[i].Value >>= Title)) {
893 0 : ret[i] <<= IllegalTypeException();
894 0 : continue;
895 0 : } else if(Title.isEmpty()) {
896 0 : ret[i] <<= IllegalArgumentException();
897 0 : continue;
898 : }
899 :
900 0 : if(m_bInserted) {
901 0 : m_aFTPURL.child(Title);
902 0 : m_xIdentifier =
903 0 : new FTPContentIdentifier(m_aFTPURL.ident(false,false));
904 0 : m_bTitleSet = true;
905 : } else
906 : try {
907 0 : OUString OldTitle = m_aFTPURL.ren(Title);
908 0 : evt.realloc(1);
909 0 : evt[0].PropertyName =
910 0 : OUString("Title");
911 0 : evt[0].Further = false;
912 0 : evt[0].PropertyHandle = -1;
913 0 : evt[0].OldValue <<= OldTitle;
914 0 : evt[0].NewValue <<= Title;
915 0 : } catch(const curl_exception&) {
916 0 : InteractiveIOException excep;
917 : // any better possibility here?
918 : // ( the error code is always CURLE_FTP_QUOTE_ERROR )
919 0 : excep.Code = IOErrorCode_ACCESS_DENIED;
920 0 : ret[i] <<= excep;
921 0 : }
922 : } else {
923 : Sequence<Property> props =
924 0 : getProperties(Reference<XCommandEnvironment>(0));
925 :
926 : // either unknown or read-only
927 0 : ret[i] <<= UnknownPropertyException();
928 0 : for(sal_Int32 j = 0; j < props.getLength(); ++j)
929 0 : if(props[j].Name == seqPropVal[i].Name) {
930 0 : ret[i] <<= IllegalAccessException(
931 : OUString( "Property is read-only!"),
932 : //props[j].Attributes & PropertyAttribute::READONLY
933 : // ? "Property is read-only!"
934 : // : "Access denied!"),
935 0 : static_cast< cppu::OWeakObject * >( this ));
936 0 : break;
937 0 : }
938 : }
939 : }
940 :
941 0 : if(evt.getLength()) {
942 : // title has changed
943 0 : notifyPropertiesChange(evt);
944 0 : (void)exchange(new FTPContentIdentifier(m_aFTPURL.ident(false,false)));
945 : }
946 :
947 0 : return ret;
948 : }
949 :
950 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|