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 : #include <ucblockbytes.hxx>
21 :
22 : #include <sal/macros.h>
23 : #include <comphelper/processfactory.hxx>
24 : #include <salhelper/condition.hxx>
25 : #include <osl/thread.hxx>
26 : #include <osl/diagnose.h>
27 : #include <tools/urlobj.hxx>
28 : #include <ucbhelper/interactionrequest.hxx>
29 : #include <com/sun/star/task/XInteractionAbort.hpp>
30 : #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
31 : #include <com/sun/star/ucb/CommandFailedException.hpp>
32 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
33 : #include <com/sun/star/ucb/InteractiveIOException.hpp>
34 : #include <com/sun/star/io/XActiveDataStreamer.hpp>
35 : #include <com/sun/star/io/TempFile.hpp>
36 : #include <com/sun/star/ucb/DocumentHeaderField.hpp>
37 : #include <com/sun/star/ucb/XCommandInfo.hpp>
38 : #include <com/sun/star/ucb/XCommandProcessor.hpp>
39 : #include <com/sun/star/task/XInteractionHandler.hpp>
40 : #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
41 : #include <com/sun/star/ucb/PostCommandArgument2.hpp>
42 : #include <com/sun/star/ucb/OpenMode.hpp>
43 : #include <com/sun/star/beans/Property.hpp>
44 : #include <com/sun/star/beans/PropertyValue.hpp>
45 : #include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
46 : #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
47 : #include <com/sun/star/sdbc/XRow.hpp>
48 : #include <com/sun/star/io/XActiveDataSink.hpp>
49 : #include <com/sun/star/io/XActiveDataControl.hpp>
50 : #include <com/sun/star/io/XSeekable.hpp>
51 : #include <cppuhelper/implbase1.hxx>
52 : #include <cppuhelper/implbase2.hxx>
53 : #include <tools/inetmsg.hxx>
54 : #include <com/sun/star/io/XTruncate.hpp>
55 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
56 :
57 : #include <comphelper/storagehelper.hxx>
58 : #include <ucbhelper/content.hxx>
59 :
60 : using namespace ::com::sun::star::uno;
61 : using namespace ::com::sun::star::io;
62 : using namespace ::com::sun::star::ucb;
63 : using namespace ::com::sun::star::task;
64 : using namespace ::com::sun::star::lang;
65 : using namespace ::com::sun::star::beans;
66 :
67 : namespace utl
68 : {
69 :
70 : /**
71 : Helper class for getting a XInputStream when opening a content
72 : */
73 510 : class UcbDataSink_Impl : public ::cppu::WeakImplHelper2< XActiveDataControl, XActiveDataSink >
74 : {
75 : UcbLockBytesRef m_xLockBytes;
76 :
77 : public:
78 255 : explicit UcbDataSink_Impl( UcbLockBytes* pLockBytes )
79 255 : : m_xLockBytes( pLockBytes )
80 255 : {}
81 :
82 : // XActiveDataControl.
83 0 : virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException, std::exception) SAL_OVERRIDE {}
84 0 : virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException, std::exception) SAL_OVERRIDE {}
85 0 : virtual void SAL_CALL start() throw(RuntimeException, std::exception) SAL_OVERRIDE {}
86 255 : virtual void SAL_CALL terminate() throw(RuntimeException, std::exception) SAL_OVERRIDE
87 255 : { m_xLockBytes->terminate_Impl(); }
88 :
89 : // XActiveDataSink.
90 281 : virtual void SAL_CALL setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException, std::exception) SAL_OVERRIDE
91 281 : { m_xLockBytes->setInputStream_Impl (rxInputStream); }
92 0 : virtual Reference<XInputStream> SAL_CALL getInputStream() throw(RuntimeException, std::exception) SAL_OVERRIDE
93 0 : { return m_xLockBytes->getInputStream_Impl(); }
94 : };
95 :
96 : /**
97 : Helper class for getting a XStream when opening a content
98 : */
99 38828 : class UcbStreamer_Impl : public ::cppu::WeakImplHelper2< XActiveDataStreamer, XActiveDataControl >
100 : {
101 : Reference < XStream > m_xStream;
102 : UcbLockBytesRef m_xLockBytes;
103 :
104 : public:
105 19414 : explicit UcbStreamer_Impl( UcbLockBytes* pLockBytes )
106 19414 : : m_xLockBytes( pLockBytes )
107 19414 : {}
108 :
109 : // XActiveDataControl.
110 0 : virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException, std::exception) SAL_OVERRIDE {}
111 0 : virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException, std::exception) SAL_OVERRIDE {}
112 0 : virtual void SAL_CALL start() throw(RuntimeException, std::exception) SAL_OVERRIDE {}
113 19414 : virtual void SAL_CALL terminate() throw(RuntimeException, std::exception) SAL_OVERRIDE
114 19414 : { m_xLockBytes->terminate_Impl(); }
115 :
116 : // XActiveDataStreamer
117 19424 : virtual void SAL_CALL setStream( const Reference< XStream >& aStream ) throw(RuntimeException, std::exception) SAL_OVERRIDE
118 19424 : { m_xStream = aStream; m_xLockBytes->setStream_Impl( aStream ); }
119 0 : virtual Reference< XStream > SAL_CALL getStream() throw(RuntimeException, std::exception) SAL_OVERRIDE
120 0 : { return m_xStream; }
121 : };
122 :
123 : /**
124 : Helper class for managing interactions and progress when executing UCB commands
125 : */
126 39338 : class UcbTaskEnvironment : public ::cppu::WeakImplHelper1< XCommandEnvironment >
127 : {
128 : Reference< XInteractionHandler > m_xInteractionHandler;
129 : Reference< XProgressHandler > m_xProgressHandler;
130 :
131 : public:
132 19669 : UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler,
133 : const Reference< XProgressHandler>& rxProgressHandler )
134 : : m_xInteractionHandler( rxInteractionHandler )
135 19669 : , m_xProgressHandler( rxProgressHandler )
136 19669 : {}
137 :
138 85 : virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException, std::exception) SAL_OVERRIDE
139 85 : { return m_xInteractionHandler; }
140 :
141 0 : virtual Reference<XProgressHandler> SAL_CALL getProgressHandler() throw (RuntimeException, std::exception) SAL_OVERRIDE
142 0 : { return m_xProgressHandler; }
143 : };
144 :
145 : /**
146 : Helper class for property change notifies when executing UCB commands
147 : */
148 39338 : class UcbPropertiesChangeListener_Impl : public ::cppu::WeakImplHelper1< XPropertiesChangeListener >
149 : {
150 : public:
151 : UcbLockBytesRef m_xLockBytes;
152 :
153 19669 : explicit UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef )
154 19669 : : m_xLockBytes( rRef )
155 19669 : {}
156 :
157 0 : virtual void SAL_CALL disposing ( const EventObject &/*rEvent*/) throw(RuntimeException, std::exception) SAL_OVERRIDE {}
158 : virtual void SAL_CALL propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException, std::exception) SAL_OVERRIDE;
159 : };
160 :
161 0 : void SAL_CALL UcbPropertiesChangeListener_Impl::propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException, std::exception)
162 : {
163 0 : sal_Int32 i, n = rEvent.getLength();
164 0 : for (i = 0; i < n; i++)
165 : {
166 0 : PropertyChangeEvent evt (rEvent[i]);
167 0 : if (evt.PropertyName == "DocumentHeader")
168 : {
169 0 : Sequence<DocumentHeaderField> aHead;
170 0 : if (evt.NewValue >>= aHead)
171 : {
172 0 : sal_Int32 k, m = aHead.getLength();
173 0 : for (k = 0; k < m; k++)
174 : {
175 0 : OUString aName( aHead[k].Name );
176 0 : OUString aValue( aHead[k].Value );
177 :
178 0 : if (aName.compareToIgnoreAsciiCaseAscii("Expires") == 0)
179 : {
180 0 : DateTime aExpires (0, 0);
181 0 : if (INetMIMEMessage::ParseDateField (aValue, aExpires))
182 : {
183 0 : aExpires.ConvertToLocalTime();
184 0 : m_xLockBytes->SetExpireDate_Impl( aExpires );
185 : }
186 : }
187 0 : }
188 : }
189 :
190 0 : m_xLockBytes->SetStreamValid_Impl();
191 : }
192 0 : else if (evt.PropertyName == "PresentationURL")
193 : {
194 0 : OUString aUrl;
195 0 : if (evt.NewValue >>= aUrl)
196 : {
197 0 : OUString aBad ("private:");
198 0 : if (!aUrl.startsWith(aBad))
199 : {
200 : // URL changed (Redirection).
201 0 : m_xLockBytes->SetRealURL_Impl( aUrl );
202 0 : }
203 0 : }
204 : }
205 0 : else if (evt.PropertyName == "MediaType")
206 : {
207 0 : OUString aContentType;
208 0 : if (evt.NewValue >>= aContentType)
209 0 : m_xLockBytes->SetContentType_Impl( aContentType );
210 : }
211 0 : }
212 0 : }
213 :
214 : class Moderator
215 : : public osl::Thread
216 : {
217 : // usage restriction:
218 : // It might be possible, that the call to the interactionhandler and/or
219 : // progresshandler is done asynchrounsly, while the 'execute' simply
220 : // returns. This would imply that these class must be refcounted !!!
221 :
222 : public:
223 : Moderator(
224 : Reference < XContent >& xContent,
225 : Reference < XInteractionHandler >& xInteract,
226 : const Command& rArg
227 : )
228 : throw(
229 : ContentCreationException,
230 : RuntimeException
231 : );
232 :
233 : virtual ~Moderator();
234 :
235 : enum ResultType {
236 : NORESULT,
237 :
238 : INTERACTIONREQUEST, // reply expected
239 :
240 : PROGRESSPUSH,
241 : PROGRESSUPDATE,
242 : PROGRESSPOP,
243 :
244 : INPUTSTREAM,
245 : STREAM,
246 :
247 : RESULT,
248 : TIMEDOUT,
249 : COMMANDABORTED,
250 : COMMANDFAILED,
251 : INTERACTIVEIO,
252 : UNSUPPORTED,
253 : GENERAL
254 : };
255 :
256 0 : class ConditionRes
257 : : public salhelper::Condition
258 : {
259 : public:
260 0 : ConditionRes(osl::Mutex& aMutex,Moderator& aModerator)
261 : : salhelper::Condition(aMutex),
262 0 : m_aModerator(aModerator)
263 : {
264 0 : }
265 :
266 : protected:
267 0 : bool applies() const SAL_OVERRIDE {
268 0 : return m_aModerator.m_aResultType != NORESULT;
269 : }
270 :
271 : private:
272 : Moderator& m_aModerator;
273 : };
274 :
275 0 : struct Result {
276 : ResultType type;
277 : Any result;
278 : sal_Int32 ioErrorCode;
279 : };
280 :
281 : Result getResult(const sal_uInt32 milliSec);
282 :
283 : enum ReplyType {
284 : NOREPLY,
285 : EXIT,
286 : RETRY,
287 : REQUESTHANDLED
288 : };
289 :
290 0 : class ConditionRep
291 : : public salhelper::Condition
292 : {
293 : public:
294 0 : ConditionRep(osl::Mutex& aMutex,Moderator& aModerator)
295 : : salhelper::Condition(aMutex),
296 0 : m_aModerator(aModerator)
297 : {
298 0 : }
299 :
300 : protected:
301 0 : bool applies() const SAL_OVERRIDE {
302 0 : return m_aModerator.m_aReplyType != NOREPLY;
303 : }
304 :
305 : private:
306 : Moderator& m_aModerator;
307 : };
308 :
309 : void setReply(ReplyType);
310 :
311 : void handle( const Reference<XInteractionRequest >& Request );
312 :
313 : void setStream(const Reference< XStream >& aStream);
314 : void setInputStream(const Reference<XInputStream> &rxInputStream);
315 :
316 : protected:
317 : virtual void SAL_CALL run() SAL_OVERRIDE;
318 : virtual void SAL_CALL onTerminated() SAL_OVERRIDE;
319 :
320 : private:
321 : osl::Mutex m_aMutex;
322 :
323 : friend class ConditionRes;
324 :
325 : ConditionRes m_aRes;
326 : ResultType m_aResultType;
327 : sal_Int32 m_nIOErrorCode;
328 : Any m_aResult;
329 :
330 : friend class ConditionRep;
331 :
332 : ConditionRep m_aRep;
333 : ReplyType m_aReplyType;
334 :
335 : Command m_aArg;
336 : ::ucbhelper::Content m_aContent;
337 : };
338 :
339 : class ModeratorsActiveDataStreamer
340 : : public ::cppu::WeakImplHelper1<XActiveDataStreamer>
341 : {
342 : public:
343 :
344 : explicit ModeratorsActiveDataStreamer(Moderator &theModerator);
345 :
346 : virtual ~ModeratorsActiveDataStreamer();
347 :
348 : // XActiveDataStreamer
349 : virtual void SAL_CALL
350 : setStream(
351 : const Reference< XStream >& aStream
352 : )
353 : throw(
354 : RuntimeException, std::exception
355 : ) SAL_OVERRIDE;
356 :
357 : virtual Reference<XStream> SAL_CALL
358 0 : getStream (
359 : void
360 : ) throw(
361 : RuntimeException, std::exception
362 : ) SAL_OVERRIDE
363 : {
364 0 : osl::MutexGuard aGuard(m_aMutex);
365 0 : return m_xStream;
366 : }
367 :
368 : private:
369 : Moderator& m_aModerator;
370 :
371 : osl::Mutex m_aMutex;
372 : Reference<XStream> m_xStream;
373 : };
374 :
375 : class ModeratorsActiveDataSink
376 : : public ::cppu::WeakImplHelper1<XActiveDataSink>
377 : {
378 : public:
379 :
380 : explicit ModeratorsActiveDataSink(Moderator &theModerator);
381 :
382 : virtual ~ModeratorsActiveDataSink();
383 :
384 : // XActiveDataSink.
385 : virtual void SAL_CALL
386 : setInputStream (
387 : const Reference<XInputStream> &rxInputStream
388 : )
389 : throw(
390 : RuntimeException, std::exception
391 : ) SAL_OVERRIDE;
392 :
393 : virtual Reference<XInputStream> SAL_CALL
394 0 : getInputStream (
395 : void
396 : ) throw(
397 : RuntimeException, std::exception
398 : ) SAL_OVERRIDE
399 : {
400 0 : osl::MutexGuard aGuard(m_aMutex);
401 0 : return m_xStream;
402 : }
403 :
404 : private:
405 : Moderator& m_aModerator;
406 : osl::Mutex m_aMutex;
407 : Reference<XInputStream> m_xStream;
408 : };
409 :
410 0 : ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator)
411 0 : : m_aModerator(theModerator)
412 : {
413 0 : }
414 :
415 0 : ModeratorsActiveDataSink::~ModeratorsActiveDataSink()
416 : {
417 0 : }
418 :
419 : // XActiveDataSink.
420 : void SAL_CALL
421 0 : ModeratorsActiveDataSink::setInputStream (
422 : const Reference<XInputStream> &rxInputStream
423 : )
424 : throw(
425 : RuntimeException, std::exception
426 : )
427 : {
428 0 : m_aModerator.setInputStream(rxInputStream);
429 0 : osl::MutexGuard aGuard(m_aMutex);
430 0 : m_xStream = rxInputStream;
431 0 : }
432 :
433 0 : ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer(
434 : Moderator &theModerator
435 : )
436 0 : : m_aModerator(theModerator)
437 : {
438 0 : }
439 :
440 0 : ModeratorsActiveDataStreamer::~ModeratorsActiveDataStreamer()
441 : {
442 0 : }
443 :
444 : // XActiveDataStreamer.
445 : void SAL_CALL
446 0 : ModeratorsActiveDataStreamer::setStream (
447 : const Reference<XStream> &rxStream
448 : )
449 : throw(
450 : RuntimeException, std::exception
451 : )
452 : {
453 0 : m_aModerator.setStream(rxStream);
454 0 : osl::MutexGuard aGuard(m_aMutex);
455 0 : m_xStream = rxStream;
456 0 : }
457 :
458 : class ModeratorsInteractionHandler
459 : : public ::cppu::WeakImplHelper1<XInteractionHandler>
460 : {
461 : public:
462 :
463 : explicit ModeratorsInteractionHandler(Moderator &theModerator);
464 :
465 : virtual ~ModeratorsInteractionHandler();
466 :
467 : virtual void SAL_CALL
468 : handle( const Reference<XInteractionRequest >& Request )
469 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
470 :
471 : private:
472 :
473 : Moderator& m_aModerator;
474 : };
475 :
476 0 : ModeratorsInteractionHandler::ModeratorsInteractionHandler(
477 : Moderator &aModerator)
478 0 : : m_aModerator(aModerator)
479 : {
480 0 : }
481 :
482 0 : ModeratorsInteractionHandler::~ModeratorsInteractionHandler()
483 : {
484 0 : }
485 :
486 : void SAL_CALL
487 0 : ModeratorsInteractionHandler::handle(
488 : const Reference<XInteractionRequest >& Request
489 : )
490 : throw (
491 : RuntimeException, std::exception
492 : )
493 : {
494 : // wakes up the mainthread
495 0 : m_aModerator.handle(Request);
496 0 : }
497 :
498 0 : Moderator::Moderator(
499 : Reference < XContent >& xContent,
500 : Reference < XInteractionHandler >& xInteract,
501 : const Command& rArg
502 : )
503 : throw(
504 : ::com::sun::star::ucb::ContentCreationException,
505 : ::com::sun::star::uno::RuntimeException
506 : )
507 : : m_aMutex(),
508 :
509 : m_aRes(m_aMutex,*this),
510 : m_aResultType(NORESULT),
511 : m_nIOErrorCode(0),
512 : m_aResult(),
513 :
514 : m_aRep(m_aMutex,*this),
515 : m_aReplyType(NOREPLY),
516 :
517 : m_aArg(rArg),
518 : m_aContent(
519 : xContent,
520 : new UcbTaskEnvironment(
521 0 : xInteract.is() ? new ModeratorsInteractionHandler(*this) : 0,
522 0 : 0),
523 0 : comphelper::getProcessComponentContext())
524 : {
525 : // now exchange the whole data sink stuff
526 : // with a thread safe version
527 :
528 0 : Reference<XInterface> *pxSink = NULL;
529 :
530 0 : PostCommandArgument2 aPostArg;
531 0 : OpenCommandArgument2 aOpenArg;
532 :
533 0 : int dec(2);
534 0 : if(m_aArg.Argument >>= aPostArg) {
535 0 : pxSink = &aPostArg.Sink;
536 0 : dec = 0;
537 : }
538 0 : else if(m_aArg.Argument >>= aOpenArg) {
539 0 : pxSink = &aOpenArg.Sink;
540 0 : dec = 1;
541 : }
542 :
543 0 : if(dec ==2)
544 0 : throw ContentCreationException();
545 :
546 0 : Reference < XActiveDataSink > xActiveSink(*pxSink,UNO_QUERY);
547 0 : if(xActiveSink.is())
548 0 : *pxSink = Reference<XInterface>(
549 0 : static_cast<cppu::OWeakObject*>(new ModeratorsActiveDataSink(*this)));
550 :
551 0 : Reference<XActiveDataStreamer> xStreamer( *pxSink, UNO_QUERY );
552 0 : if ( xStreamer.is() )
553 0 : *pxSink = Reference<XInterface>(
554 0 : static_cast<cppu::OWeakObject*>(new ModeratorsActiveDataStreamer(*this)));
555 :
556 0 : if(dec == 0)
557 0 : m_aArg.Argument <<= aPostArg;
558 0 : else if(dec == 1)
559 0 : m_aArg.Argument <<= aOpenArg;
560 0 : }
561 :
562 0 : Moderator::~Moderator()
563 : {
564 0 : }
565 :
566 0 : Moderator::Result Moderator::getResult(const sal_uInt32 milliSec)
567 : {
568 0 : Result ret;
569 : try {
570 0 : salhelper::ConditionWaiter aWaiter(m_aRes,milliSec);
571 0 : ret.type = m_aResultType;
572 0 : ret.result = m_aResult;
573 0 : ret.ioErrorCode = m_nIOErrorCode;
574 :
575 : // reset
576 0 : m_aResultType = NORESULT;
577 : }
578 0 : catch (const salhelper::ConditionWaiter::timedout&)
579 : {
580 0 : ret.type = TIMEDOUT;
581 : }
582 :
583 0 : return ret;
584 : }
585 :
586 0 : void Moderator::setReply(ReplyType aReplyType )
587 : {
588 0 : salhelper::ConditionModifier aMod(m_aRep);
589 0 : m_aReplyType = aReplyType;
590 0 : }
591 :
592 0 : void Moderator::handle( const Reference<XInteractionRequest >& Request )
593 : {
594 : ReplyType aReplyType;
595 :
596 0 : do {
597 : {
598 0 : salhelper::ConditionModifier aMod(m_aRes);
599 0 : m_aResultType = INTERACTIONREQUEST;
600 0 : m_aResult <<= Request;
601 : }
602 :
603 : {
604 0 : salhelper::ConditionWaiter aWait(m_aRep);
605 0 : aReplyType = m_aReplyType;
606 :
607 : // reset
608 0 : m_aReplyType = NOREPLY;
609 : }
610 :
611 0 : if(aReplyType == EXIT) {
612 : Sequence<Reference<XInteractionContinuation> > aSeq(
613 0 : Request->getContinuations());
614 0 : for(sal_Int32 i = 0; i < aSeq.getLength(); ++i) {
615 0 : Reference<XInteractionAbort> aRef(aSeq[i],UNO_QUERY);
616 0 : if(aRef.is()) {
617 0 : aRef->select();
618 : }
619 0 : }
620 :
621 : // resignal the exitcondition
622 0 : setReply(EXIT);
623 0 : break;
624 : }
625 : } while(aReplyType != REQUESTHANDLED);
626 0 : }
627 :
628 0 : void Moderator::setStream(const Reference< XStream >& aStream)
629 : {
630 : {
631 0 : salhelper::ConditionModifier aMod(m_aRes);
632 0 : m_aResultType = STREAM;
633 0 : m_aResult <<= aStream;
634 : }
635 : ReplyType aReplyType;
636 : {
637 0 : salhelper::ConditionWaiter aWait(m_aRep);
638 0 : aReplyType = m_aReplyType;
639 0 : m_aReplyType = NOREPLY;
640 : }
641 0 : if(aReplyType == EXIT)
642 0 : setReply(EXIT);
643 0 : }
644 :
645 0 : void Moderator::setInputStream(const Reference<XInputStream> &rxInputStream)
646 : {
647 : {
648 0 : salhelper::ConditionModifier aMod(m_aRes);
649 0 : m_aResultType = INPUTSTREAM;
650 0 : m_aResult <<= rxInputStream;
651 : }
652 : ReplyType aReplyType;
653 : {
654 0 : salhelper::ConditionWaiter aWait(m_aRep);
655 0 : aReplyType = m_aReplyType;
656 0 : m_aReplyType = NOREPLY;
657 : }
658 0 : if(aReplyType == EXIT)
659 0 : setReply(EXIT);
660 0 : }
661 :
662 0 : void SAL_CALL Moderator::run()
663 : {
664 0 : osl_setThreadName("utl::Moderator");
665 :
666 : ResultType aResultType;
667 0 : Any aResult;
668 0 : sal_Int32 nIOErrorCode = 0;
669 :
670 : try
671 : {
672 0 : aResult = m_aContent.executeCommand(m_aArg.Name,m_aArg.Argument);
673 0 : aResultType = RESULT;
674 : }
675 0 : catch (const CommandAbortedException&)
676 : {
677 0 : aResultType = COMMANDABORTED;
678 : }
679 0 : catch (const CommandFailedException&)
680 : {
681 0 : aResultType = COMMANDFAILED;
682 : }
683 0 : catch (const InteractiveIOException& r)
684 : {
685 0 : nIOErrorCode = r.Code;
686 0 : aResultType = INTERACTIVEIO;
687 : }
688 0 : catch (const UnsupportedDataSinkException &)
689 : {
690 0 : aResultType = UNSUPPORTED;
691 : }
692 0 : catch (const Exception&)
693 : {
694 0 : aResultType = GENERAL;
695 : }
696 :
697 : {
698 0 : salhelper::ConditionModifier aMod(m_aRes);
699 0 : m_aResultType = aResultType;
700 0 : m_aResult = aResult;
701 0 : m_nIOErrorCode = nIOErrorCode;
702 0 : }
703 0 : }
704 :
705 0 : void SAL_CALL Moderator::onTerminated()
706 : {
707 : {
708 0 : salhelper::ConditionWaiter aWaiter(m_aRep);
709 : }
710 0 : delete this;
711 0 : }
712 :
713 : /**
714 : Function for opening UCB contents synchronously,
715 : but with handled timeout;
716 : */
717 : static bool _UCBOpenContentSync(
718 : UcbLockBytesRef xLockBytes,
719 : Reference < XContent > xContent,
720 : const Command& rArg,
721 : Reference < XInterface > xSink,
722 : Reference < XInteractionHandler > xInteract );
723 :
724 19669 : static bool UCBOpenContentSync(
725 : UcbLockBytesRef xLockBytes,
726 : Reference < XContent > xContent,
727 : const Command& rArg,
728 : Reference < XInterface > xSink,
729 : Reference < XInteractionHandler > xInteract )
730 : {
731 : // http protocol must be handled in a special way:
732 : // during the opening process the input stream may change
733 : // only the last inputstream after notifying the document
734 : // headers is valid
735 :
736 : Reference<XContentIdentifier> xContId(
737 19669 : xContent.is() ? xContent->getIdentifier() : 0 );
738 :
739 39338 : OUString aScheme;
740 19669 : if(xContId.is())
741 19669 : aScheme = xContId->getContentProviderScheme();
742 :
743 : // now determine whether we use a timeout or not;
744 59007 : if( ! aScheme.equalsIgnoreAsciiCase("http") &&
745 39338 : ! aScheme.equalsIgnoreAsciiCase("https") &&
746 59007 : ! aScheme.equalsIgnoreAsciiCase("vnd.sun.star.webdav") &&
747 19669 : ! aScheme.equalsIgnoreAsciiCase("ftp"))
748 : return _UCBOpenContentSync(
749 19669 : xLockBytes,xContent,rArg,xSink,xInteract);
750 :
751 0 : if ( !aScheme.equalsIgnoreAsciiCase( "http" ) &&
752 0 : !aScheme.equalsIgnoreAsciiCase( "https" ) )
753 0 : xLockBytes->SetStreamValid_Impl();
754 :
755 0 : Reference< XPropertiesChangeListener > xListener;
756 0 : Reference< XPropertiesChangeNotifier > xProps(xContent,UNO_QUERY);
757 0 : if(xProps.is()) {
758 0 : xListener =
759 0 : new UcbPropertiesChangeListener_Impl(xLockBytes);
760 0 : xProps->addPropertiesChangeListener(
761 : Sequence< OUString >(),
762 0 : xListener);
763 : }
764 :
765 0 : Any aResult;
766 0 : bool bException(false);
767 0 : bool bAborted(false);
768 0 : bool bResultAchieved(false);
769 :
770 0 : Moderator* pMod = 0;
771 : try
772 : {
773 0 : pMod = new Moderator(xContent,xInteract,rArg);
774 0 : pMod->create();
775 : }
776 0 : catch (const ContentCreationException&)
777 : {
778 0 : bResultAchieved = bException = true;
779 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
780 : }
781 :
782 0 : sal_uInt32 nTimeout(5000); // initially 5000 milliSec
783 0 : while(!bResultAchieved) {
784 :
785 0 : Moderator::Result res;
786 : // try to get the result for with timeout
787 0 : res = pMod->getResult(nTimeout);
788 :
789 0 : switch(res.type) {
790 : case Moderator::PROGRESSPUSH:
791 : {
792 0 : pMod->setReply(Moderator::REQUESTHANDLED);
793 0 : break;
794 : }
795 : case Moderator::PROGRESSUPDATE:
796 : {
797 0 : pMod->setReply(Moderator::REQUESTHANDLED);
798 0 : break;
799 : }
800 : case Moderator::PROGRESSPOP:
801 : {
802 0 : pMod->setReply(Moderator::REQUESTHANDLED);
803 0 : break;
804 : }
805 : case Moderator::STREAM:
806 : {
807 0 : Reference<XStream> result;
808 0 : if(res.result >>= result) {
809 : Reference < XActiveDataStreamer > xStreamer(
810 : xSink, UNO_QUERY
811 0 : );
812 :
813 0 : if(xStreamer.is())
814 0 : xStreamer->setStream(result);
815 : }
816 0 : pMod->setReply(Moderator::REQUESTHANDLED);
817 0 : break;
818 : }
819 : case Moderator::INPUTSTREAM:
820 : {
821 0 : Reference<XInputStream> result;
822 0 : res.result >>= result;
823 : Reference < XActiveDataSink > xActiveSink(
824 : xSink, UNO_QUERY
825 0 : );
826 :
827 0 : if(xActiveSink.is())
828 0 : xActiveSink->setInputStream(result);
829 0 : pMod->setReply(Moderator::REQUESTHANDLED);
830 0 : break;
831 : }
832 : case Moderator::TIMEDOUT:
833 : {
834 0 : Reference<XInteractionRetry> xRet;
835 0 : if(xInteract.is()) {
836 0 : InteractiveNetworkConnectException aExcep;
837 : INetURLObject aURL(
838 0 : xContId.is() ?
839 0 : xContId->getContentIdentifier() :
840 0 : OUString() );
841 0 : aExcep.Server = aURL.GetHost();
842 0 : aExcep.Classification = InteractionClassification_ERROR;
843 0 : aExcep.Message = "server not responding after five seconds";
844 0 : Any request;
845 0 : request <<= aExcep;
846 : ucbhelper::InteractionRequest *ir =
847 0 : new ucbhelper::InteractionRequest(request);
848 0 : Reference<XInteractionRequest> xIR(ir);
849 0 : Sequence<Reference<XInteractionContinuation> > aSeq(2);
850 : ucbhelper::InteractionRetry *retryP =
851 0 : new ucbhelper::InteractionRetry(ir);
852 0 : aSeq[0] = retryP;
853 : ucbhelper::InteractionAbort *abortP =
854 0 : new ucbhelper::InteractionAbort(ir);
855 0 : aSeq[1] = abortP;
856 :
857 0 : ir->setContinuations(aSeq);
858 0 : xInteract->handle(xIR);
859 : rtl::Reference< ucbhelper::InteractionContinuation > ref
860 0 : = ir->getSelection();
861 0 : if(ref.is()) {
862 0 : Reference<XInterface> xInt(ref.get());
863 0 : xRet = Reference<XInteractionRetry>(xInt,UNO_QUERY);
864 0 : }
865 : }
866 :
867 0 : if(!xRet.is()) {
868 0 : bAborted = true;
869 0 : xLockBytes->SetError(ERRCODE_ABORT);
870 : }
871 :
872 0 : break;
873 : }
874 : case Moderator::INTERACTIONREQUEST:
875 : {
876 0 : Reference<XInteractionRequest> Request;
877 0 : res.result >>= Request;
878 0 : xInteract->handle(Request);
879 0 : pMod->setReply(Moderator::REQUESTHANDLED);
880 0 : break;
881 : }
882 : case Moderator::RESULT:
883 : {
884 0 : bResultAchieved = true;
885 0 : aResult = res.result;
886 0 : break;
887 : }
888 : case Moderator::COMMANDABORTED:
889 : {
890 0 : bAborted = true;
891 0 : xLockBytes->SetError( ERRCODE_ABORT );
892 0 : break;
893 : }
894 : case Moderator::COMMANDFAILED:
895 : {
896 0 : bAborted = true;
897 0 : xLockBytes->SetError( ERRCODE_ABORT );
898 0 : break;
899 : }
900 : case Moderator::INTERACTIVEIO:
901 : {
902 0 : bException = true;
903 0 : if ( res.ioErrorCode == IOErrorCode_ACCESS_DENIED ||
904 0 : res.ioErrorCode == IOErrorCode_LOCKING_VIOLATION )
905 0 : xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
906 0 : else if ( res.ioErrorCode == IOErrorCode_NOT_EXISTING )
907 0 : xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
908 0 : else if ( res.ioErrorCode == IOErrorCode_CANT_READ )
909 0 : xLockBytes->SetError( ERRCODE_IO_CANTREAD );
910 : else
911 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
912 0 : break;
913 : }
914 : case Moderator::UNSUPPORTED:
915 : {
916 0 : bException = true;
917 0 : xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
918 0 : break;
919 : }
920 : default:
921 : {
922 0 : bException = true;
923 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
924 0 : break;
925 : }
926 : }
927 :
928 0 : bResultAchieved |= bException;
929 0 : bResultAchieved |= bAborted;
930 0 : if(nTimeout == 5000) nTimeout *= 2;
931 0 : }
932 :
933 0 : if(pMod) pMod->setReply(Moderator::EXIT);
934 :
935 0 : if ( bAborted || bException )
936 : {
937 0 : Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
938 0 : if ( xActiveSink.is() )
939 0 : xActiveSink->setInputStream( Reference < XInputStream >() );
940 :
941 0 : Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
942 0 : if ( xStreamer.is() )
943 0 : xStreamer->setStream( Reference < XStream >() );
944 : }
945 :
946 0 : Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
947 0 : if ( xControl.is() )
948 0 : xControl->terminate();
949 :
950 0 : if ( xProps.is() )
951 0 : xProps->removePropertiesChangeListener(
952 : Sequence< OUString >(),
953 0 : xListener );
954 :
955 19669 : return ( bAborted || bException );
956 : }
957 :
958 : /**
959 : Function for opening UCB contents synchronously
960 : */
961 19669 : static bool _UCBOpenContentSync(
962 : UcbLockBytesRef xLockBytes,
963 : Reference < XContent > xContent,
964 : const Command& rArg,
965 : Reference < XInterface > xSink,
966 : Reference < XInteractionHandler > xInteract )
967 : {
968 : ::ucbhelper::Content aContent(
969 19669 : xContent, new UcbTaskEnvironment( xInteract, 0 ),
970 39338 : comphelper::getProcessComponentContext() );
971 39338 : Reference < XContentIdentifier > xIdent = xContent->getIdentifier();
972 39338 : OUString aScheme = xIdent->getContentProviderScheme();
973 :
974 : // http protocol must be handled in a special way: during the opening process the input stream may change
975 : // only the last inputstream after notifying the document headers is valid
976 19669 : if ( !aScheme.equalsIgnoreAsciiCase("http") )
977 19669 : xLockBytes->SetStreamValid_Impl();
978 :
979 39338 : Reference< XPropertiesChangeListener > xListener = new UcbPropertiesChangeListener_Impl( xLockBytes );
980 39338 : Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY );
981 19669 : if ( xProps.is() )
982 19669 : xProps->addPropertiesChangeListener( Sequence< OUString >(), xListener );
983 :
984 39338 : Any aResult;
985 19669 : bool bException = false;
986 19669 : bool bAborted = false;
987 :
988 : try
989 : {
990 19669 : aResult = aContent.executeCommand( rArg.Name, rArg.Argument );
991 : }
992 0 : catch (const CommandAbortedException&)
993 : {
994 0 : bAborted = true;
995 0 : xLockBytes->SetError( ERRCODE_ABORT );
996 : }
997 0 : catch (const CommandFailedException&)
998 : {
999 0 : bAborted = true;
1000 0 : xLockBytes->SetError( ERRCODE_ABORT );
1001 : }
1002 170 : catch (const InteractiveIOException& r)
1003 : {
1004 85 : bException = true;
1005 85 : if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
1006 0 : xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
1007 85 : else if ( r.Code == IOErrorCode_NOT_EXISTING )
1008 85 : xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
1009 0 : else if ( r.Code == IOErrorCode_CANT_READ )
1010 0 : xLockBytes->SetError( ERRCODE_IO_CANTREAD );
1011 : else
1012 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1013 : }
1014 0 : catch (const UnsupportedDataSinkException&)
1015 : {
1016 0 : bException = true;
1017 0 : xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
1018 : }
1019 0 : catch (const Exception&)
1020 : {
1021 0 : bException = true;
1022 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1023 : }
1024 :
1025 19669 : if ( bAborted || bException )
1026 : {
1027 85 : Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
1028 85 : if ( xActiveSink.is() )
1029 75 : xActiveSink->setInputStream( Reference < XInputStream >() );
1030 :
1031 170 : Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
1032 85 : if ( xStreamer.is() )
1033 95 : xStreamer->setStream( Reference < XStream >() );
1034 : }
1035 :
1036 39338 : Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
1037 19669 : if ( xControl.is() )
1038 19669 : xControl->terminate();
1039 :
1040 19669 : if ( xProps.is() )
1041 19669 : xProps->removePropertiesChangeListener( Sequence< OUString >(), xListener );
1042 :
1043 39338 : return ( bAborted || bException );
1044 : }
1045 :
1046 46772 : UcbLockBytes::UcbLockBytes( UcbLockBytesHandler* pHandler )
1047 : : m_aExpireDate( DateTime::EMPTY )
1048 : , m_xInputStream (NULL)
1049 : , m_pCommandThread( NULL )
1050 : , m_xHandler( pHandler )
1051 : , m_nError( ERRCODE_NONE )
1052 : , m_bTerminated (false)
1053 : , m_bDontClose( false )
1054 46772 : , m_bStreamValid (false)
1055 : {
1056 46772 : SetSynchronMode( true );
1057 46772 : }
1058 :
1059 186880 : UcbLockBytes::~UcbLockBytes()
1060 : {
1061 46720 : if ( !m_bDontClose )
1062 : {
1063 69 : if ( m_xInputStream.is() )
1064 : {
1065 : try
1066 : {
1067 0 : m_xInputStream->closeInput();
1068 : }
1069 0 : catch (const RuntimeException&)
1070 : {
1071 : }
1072 0 : catch (const IOException&)
1073 : {
1074 : }
1075 : }
1076 : }
1077 :
1078 46720 : if ( !m_xInputStream.is() && m_xOutputStream.is() )
1079 : {
1080 : try
1081 : {
1082 0 : m_xOutputStream->closeOutput();
1083 : }
1084 0 : catch (const RuntimeException&)
1085 : {
1086 : }
1087 0 : catch (const IOException&)
1088 : {
1089 : }
1090 : }
1091 140160 : }
1092 :
1093 19584 : Reference < XInputStream > UcbLockBytes::getInputStream()
1094 : {
1095 19584 : osl::MutexGuard aGuard( m_aMutex );
1096 19584 : m_bDontClose = true;
1097 19584 : return m_xInputStream;
1098 : }
1099 :
1100 22915 : bool UcbLockBytes::setStream_Impl( const Reference<XStream>& aStream )
1101 : {
1102 22915 : osl::MutexGuard aGuard( m_aMutex );
1103 22915 : if ( aStream.is() )
1104 : {
1105 22895 : m_xOutputStream = aStream->getOutputStream();
1106 22895 : setInputStream_Impl( aStream->getInputStream(), false );
1107 22895 : m_xSeekable = Reference < XSeekable > ( aStream, UNO_QUERY );
1108 : }
1109 : else
1110 : {
1111 20 : m_xOutputStream.clear();
1112 20 : setInputStream_Impl( Reference < XInputStream >() );
1113 : }
1114 :
1115 22915 : return m_xInputStream.is();
1116 : }
1117 :
1118 46808 : bool UcbLockBytes::setInputStream_Impl( const Reference<XInputStream> &rxInputStream, bool bSetXSeekable )
1119 : {
1120 46808 : bool bRet = false;
1121 :
1122 : try
1123 : {
1124 46808 : osl::MutexGuard aGuard( m_aMutex );
1125 :
1126 46808 : if ( !m_bDontClose && m_xInputStream.is() )
1127 0 : m_xInputStream->closeInput();
1128 :
1129 46808 : m_xInputStream = rxInputStream;
1130 :
1131 46808 : if( bSetXSeekable )
1132 : {
1133 23913 : m_xSeekable = Reference < XSeekable > ( rxInputStream, UNO_QUERY );
1134 23913 : if( !m_xSeekable.is() && rxInputStream.is() )
1135 : {
1136 1328 : Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1137 2654 : Reference< XOutputStream > rxTempOut = Reference < XOutputStream > ( TempFile::create(xContext), UNO_QUERY_THROW );
1138 :
1139 1326 : ::comphelper::OStorageHelper::CopyInputToOutput( rxInputStream, rxTempOut );
1140 1326 : m_xInputStream = Reference< XInputStream >( rxTempOut, UNO_QUERY );
1141 2654 : m_xSeekable = Reference < XSeekable > ( rxTempOut, UNO_QUERY );
1142 : }
1143 : }
1144 :
1145 46808 : bRet = m_xInputStream.is();
1146 : }
1147 2 : catch (const Exception&)
1148 : {
1149 : }
1150 :
1151 46808 : if ( m_bStreamValid && m_xInputStream.is() )
1152 19584 : m_aInitialized.set();
1153 :
1154 46808 : return bRet;
1155 : }
1156 :
1157 19669 : void UcbLockBytes::SetStreamValid_Impl()
1158 : {
1159 19669 : m_bStreamValid = true;
1160 19669 : if ( m_xInputStream.is() )
1161 0 : m_aInitialized.set();
1162 19669 : }
1163 :
1164 46772 : void UcbLockBytes::terminate_Impl()
1165 : {
1166 46772 : m_bTerminated = true;
1167 46772 : m_aInitialized.set();
1168 46772 : m_aTerminated.set();
1169 :
1170 46772 : if ( GetError() == ERRCODE_NONE && !m_xInputStream.is() )
1171 : {
1172 : OSL_FAIL("No InputStream, but no error set!" );
1173 0 : SetError( ERRCODE_IO_NOTEXISTS );
1174 : }
1175 46772 : }
1176 :
1177 66568 : void UcbLockBytes::SetSynchronMode (bool bSynchron)
1178 : {
1179 66568 : SvLockBytes::SetSynchronMode (bSynchron);
1180 66568 : }
1181 :
1182 197383 : ErrCode UcbLockBytes::ReadAt(sal_uInt64 const nPos,
1183 : void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const
1184 : {
1185 197383 : if ( IsSynchronMode() )
1186 : {
1187 197383 : UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
1188 197383 : pThis->m_aInitialized.wait();
1189 : }
1190 :
1191 197383 : Reference <XInputStream> xStream = getInputStream_Impl();
1192 197383 : if ( !xStream.is() )
1193 : {
1194 0 : if ( m_bTerminated )
1195 0 : return ERRCODE_IO_CANTREAD;
1196 : else
1197 0 : return ERRCODE_IO_PENDING;
1198 : }
1199 :
1200 197383 : if ( pRead )
1201 197383 : *pRead = 0;
1202 :
1203 394766 : Reference <XSeekable> xSeekable = getSeekable_Impl();
1204 197383 : if ( !xSeekable.is() )
1205 0 : return ERRCODE_IO_CANTREAD;
1206 :
1207 : try
1208 : {
1209 197383 : xSeekable->seek( nPos );
1210 : }
1211 0 : catch (const IOException&)
1212 : {
1213 0 : return ERRCODE_IO_CANTSEEK;
1214 : }
1215 2 : catch (const com::sun::star::lang::IllegalArgumentException&)
1216 : {
1217 1 : return ERRCODE_IO_CANTSEEK;
1218 : }
1219 :
1220 394764 : Sequence<sal_Int8> aData;
1221 : sal_Int32 nSize;
1222 :
1223 197382 : if(nCount > 0x7FFFFFFF)
1224 : {
1225 0 : nCount = 0x7FFFFFFF;
1226 : }
1227 : try
1228 : {
1229 197382 : if ( !m_bTerminated && !IsSynchronMode() )
1230 : {
1231 0 : sal_uInt64 nLen = xSeekable->getLength();
1232 0 : if ( nPos + nCount > nLen )
1233 0 : return ERRCODE_IO_PENDING;
1234 : }
1235 :
1236 197382 : nSize = xStream->readBytes( aData, sal_Int32(nCount) );
1237 : }
1238 0 : catch (const IOException&)
1239 : {
1240 0 : return ERRCODE_IO_CANTREAD;
1241 : }
1242 :
1243 197382 : memcpy (pBuffer, aData.getConstArray(), nSize);
1244 197382 : if (pRead)
1245 197382 : *pRead = sal_uLong(nSize);
1246 :
1247 394765 : return ERRCODE_NONE;
1248 : }
1249 :
1250 45021 : ErrCode UcbLockBytes::WriteAt(sal_uInt64 const nPos, const void *pBuffer,
1251 : sal_uLong nCount, sal_uLong *pWritten)
1252 : {
1253 45021 : if ( pWritten )
1254 45021 : *pWritten = 0;
1255 :
1256 : DBG_ASSERT( IsSynchronMode(), "Writing is only possible in SynchronMode!" );
1257 : DBG_ASSERT( m_aInitialized.check(), "Writing bevor stream is ready!" );
1258 :
1259 45021 : Reference <XSeekable> xSeekable = getSeekable_Impl();
1260 90042 : Reference <XOutputStream> xOutputStream = getOutputStream_Impl();
1261 45021 : if ( !xOutputStream.is() || !xSeekable.is() )
1262 8 : return ERRCODE_IO_CANTWRITE;
1263 :
1264 : try
1265 : {
1266 45013 : xSeekable->seek( nPos );
1267 : }
1268 0 : catch (const IOException&)
1269 : {
1270 0 : return ERRCODE_IO_CANTSEEK;
1271 : }
1272 :
1273 45013 : sal_Int8 const * pData = static_cast<sal_Int8 const *>(pBuffer);
1274 90026 : Sequence<sal_Int8> aData( pData, nCount );
1275 : try
1276 : {
1277 45013 : xOutputStream->writeBytes( aData );
1278 45013 : if ( pWritten )
1279 45013 : *pWritten = nCount;
1280 : }
1281 0 : catch (const Exception&)
1282 : {
1283 0 : return ERRCODE_IO_CANTWRITE;
1284 : }
1285 :
1286 90034 : return ERRCODE_NONE;
1287 : }
1288 :
1289 50346 : ErrCode UcbLockBytes::Flush() const
1290 : {
1291 50346 : Reference <XOutputStream > xOutputStream = getOutputStream_Impl();
1292 50346 : if ( !xOutputStream.is() )
1293 23788 : return ERRCODE_IO_CANTWRITE;
1294 :
1295 : try
1296 : {
1297 26558 : xOutputStream->flush();
1298 : }
1299 2 : catch (const Exception&)
1300 : {
1301 1 : return ERRCODE_IO_CANTWRITE;
1302 : }
1303 :
1304 26557 : return ERRCODE_NONE;
1305 : }
1306 :
1307 3571 : ErrCode UcbLockBytes::SetSize (sal_uInt64 const nNewSize)
1308 : {
1309 3571 : SvLockBytesStat aStat;
1310 3571 : Stat( &aStat, (SvLockBytesStatFlag) 0 );
1311 3571 : sal_uLong nSize = aStat.nSize;
1312 :
1313 3571 : if ( nSize > nNewSize )
1314 : {
1315 0 : Reference < XTruncate > xTrunc( getOutputStream_Impl(), UNO_QUERY );
1316 0 : if ( xTrunc.is() )
1317 : {
1318 0 : xTrunc->truncate();
1319 0 : nSize = 0;
1320 : }
1321 : else {
1322 : DBG_WARNING("Not truncatable!");
1323 0 : }
1324 : }
1325 :
1326 3571 : if ( nSize < nNewSize )
1327 : {
1328 3571 : sal_uLong nDiff = nNewSize-nSize, nCount=0;
1329 3571 : sal_uInt8* pBuffer = new sal_uInt8[ nDiff ];
1330 3571 : memset(pBuffer, 0, nDiff); // initialize for enhanced security
1331 3571 : WriteAt( nSize, pBuffer, nDiff, &nCount );
1332 3571 : delete[] pBuffer;
1333 3571 : if ( nCount != nDiff )
1334 0 : return ERRCODE_IO_CANTWRITE;
1335 : }
1336 :
1337 3571 : return ERRCODE_NONE;
1338 : }
1339 :
1340 76201 : ErrCode UcbLockBytes::Stat( SvLockBytesStat *pStat, SvLockBytesStatFlag) const
1341 : {
1342 76201 : if ( IsSynchronMode() )
1343 : {
1344 76201 : UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
1345 76201 : pThis->m_aInitialized.wait();
1346 : }
1347 :
1348 76201 : if (!pStat)
1349 0 : return ERRCODE_IO_INVALIDPARAMETER;
1350 :
1351 76201 : Reference <XInputStream> xStream = getInputStream_Impl();
1352 152402 : Reference <XSeekable> xSeekable = getSeekable_Impl();
1353 :
1354 76201 : if ( !xStream.is() )
1355 : {
1356 0 : if ( m_bTerminated )
1357 0 : return ERRCODE_IO_INVALIDACCESS;
1358 : else
1359 0 : return ERRCODE_IO_PENDING;
1360 : }
1361 76201 : else if( !xSeekable.is() )
1362 4 : return ERRCODE_IO_CANTTELL;
1363 :
1364 : try
1365 : {
1366 76197 : pStat->nSize = sal_uLong(xSeekable->getLength());
1367 : }
1368 0 : catch (const IOException&)
1369 : {
1370 0 : return ERRCODE_IO_CANTTELL;
1371 : }
1372 :
1373 152398 : return ERRCODE_NONE;
1374 : }
1375 :
1376 23612 : UcbLockBytesRef UcbLockBytes::CreateInputLockBytes( const Reference< XInputStream >& xInputStream )
1377 : {
1378 23612 : if( !xInputStream.is() )
1379 0 : return NULL;
1380 :
1381 23612 : UcbLockBytesRef xLockBytes = new UcbLockBytes(nullptr);
1382 23612 : xLockBytes->setDontClose_Impl();
1383 23612 : xLockBytes->setInputStream_Impl( xInputStream );
1384 23612 : xLockBytes->terminate_Impl();
1385 23612 : return xLockBytes;
1386 : }
1387 :
1388 3491 : UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference< XStream >& xStream )
1389 : {
1390 3491 : if( !xStream.is() )
1391 0 : return NULL;
1392 :
1393 3491 : UcbLockBytesRef xLockBytes = new UcbLockBytes(nullptr);
1394 3491 : xLockBytes->setDontClose_Impl();
1395 3491 : xLockBytes->setStream_Impl( xStream );
1396 3491 : xLockBytes->terminate_Impl();
1397 3491 : return xLockBytes;
1398 : }
1399 :
1400 19669 : UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const Sequence < PropertyValue >& rProps,
1401 : StreamMode eOpenMode, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler )
1402 : {
1403 19669 : if( !xContent.is() )
1404 0 : return NULL;
1405 :
1406 19669 : UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler );
1407 19669 : xLockBytes->SetSynchronMode( !pHandler );
1408 39338 : Reference< XActiveDataControl > xSink;
1409 19669 : if ( eOpenMode & StreamMode::WRITE )
1410 19414 : xSink = static_cast<XActiveDataControl*>(new UcbStreamer_Impl( xLockBytes ));
1411 : else
1412 255 : xSink = static_cast<XActiveDataControl*>(new UcbDataSink_Impl( xLockBytes ));
1413 :
1414 19669 : if ( rProps.getLength() )
1415 : {
1416 0 : Reference < XCommandProcessor > xProcessor( xContent, UNO_QUERY );
1417 0 : Command aCommand;
1418 0 : aCommand.Name = "setPropertyValues";
1419 0 : aCommand.Handle = -1; /* unknown */
1420 0 : aCommand.Argument <<= rProps;
1421 0 : xProcessor->execute( aCommand, 0, Reference < XCommandEnvironment >() );
1422 : }
1423 :
1424 39338 : OpenCommandArgument2 aArgument;
1425 19669 : aArgument.Sink = xSink;
1426 19669 : aArgument.Mode = OpenMode::DOCUMENT;
1427 :
1428 39338 : Command aCommand;
1429 19669 : aCommand.Name = "open";
1430 19669 : aCommand.Argument <<= aArgument;
1431 :
1432 : bool bError = UCBOpenContentSync( xLockBytes,
1433 : xContent,
1434 : aCommand,
1435 : xSink,
1436 19669 : xInteractionHandler );
1437 :
1438 19669 : if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) )
1439 : {
1440 : OSL_FAIL("No InputStream, but no error set!" );
1441 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1442 : }
1443 :
1444 39338 : return xLockBytes;
1445 : }
1446 :
1447 : }
1448 :
1449 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|