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