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