1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_unotools.hxx"
30 
31 #include <unotools/ucblockbytes.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <salhelper/condition.hxx>
34 #ifndef _OSL_THREAD_HXX_
35 #include <osl/thread.hxx>
36 #endif
37 #include <tools/urlobj.hxx>
38 #include <ucbhelper/interactionrequest.hxx>
39 #include <com/sun/star/task/XInteractionAbort.hpp>
40 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
41 #include <com/sun/star/ucb/CommandFailedException.hpp>
42 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
43 #ifndef _COM_SUN_STAR_UCB_INTERACTIVEIODEXCEPTION_HPP_
44 #include <com/sun/star/ucb/InteractiveIOException.hpp>
45 #endif
46 #include <com/sun/star/io/XActiveDataStreamer.hpp>
47 #include <com/sun/star/ucb/DocumentHeaderField.hpp>
48 #include <com/sun/star/ucb/XCommandInfo.hpp>
49 #include <com/sun/star/ucb/XCommandProcessor.hpp>
50 #include <com/sun/star/task/XInteractionHandler.hpp>
51 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
52 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
53 #include <com/sun/star/ucb/OpenMode.hpp>
54 #include <com/sun/star/beans/Property.hpp>
55 #include <com/sun/star/beans/PropertyValue.hpp>
56 #include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
57 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
58 #include <com/sun/star/sdbc/XRow.hpp>
59 #include <com/sun/star/io/XActiveDataSink.hpp>
60 #include <com/sun/star/io/XActiveDataControl.hpp>
61 #include <com/sun/star/io/XSeekable.hpp>
62 #include <cppuhelper/implbase1.hxx>
63 #include <cppuhelper/implbase2.hxx>
64 #include <tools/inetmsg.hxx>
65 #include <com/sun/star/io/XTruncate.hpp>
66 #include <com/sun/star/lang/IllegalArgumentException.hpp>
67 
68 #include <comphelper/storagehelper.hxx>
69 
70 #include <ucbhelper/contentbroker.hxx>
71 #include <ucbhelper/content.hxx>
72 
73 using namespace ::com::sun::star::uno;
74 using namespace ::com::sun::star::io;
75 using namespace ::com::sun::star::uno;
76 using namespace ::com::sun::star::ucb;
77 using namespace ::com::sun::star::task;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::beans;
80 
81 
82 namespace utl
83 {
84 
85 /**
86     Helper class for getting a XInputStream when opening a content
87  */
88 class UcbDataSink_Impl : public ::cppu::WeakImplHelper2< XActiveDataControl, XActiveDataSink >
89 {
90 	UcbLockBytesRef         m_xLockBytes;
91 
92 public:
93 							UcbDataSink_Impl( UcbLockBytes* pLockBytes )
94 								: m_xLockBytes( pLockBytes )
95 							{}
96 
97 	SvLockBytes*            getLockBytes (void)
98 							{ return m_xLockBytes; }
99 
100 	// XActiveDataControl.
101     virtual void SAL_CALL   addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
102     virtual void SAL_CALL   removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
103     virtual void SAL_CALL   start (void) throw(RuntimeException) {}
104     virtual void SAL_CALL   terminate (void) throw(RuntimeException)
105                             { m_xLockBytes->terminate_Impl(); }
106 
107 	// XActiveDataSink.
108     virtual void SAL_CALL   setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException)
109                             { m_xLockBytes->setInputStream_Impl (rxInputStream); }
110     virtual Reference<XInputStream> SAL_CALL getInputStream (void) throw(RuntimeException)
111                             { return m_xLockBytes->getInputStream_Impl(); }
112 };
113 
114 /**
115     Helper class for getting a XStream when opening a content
116  */
117 class UcbStreamer_Impl : public ::cppu::WeakImplHelper2< XActiveDataStreamer, XActiveDataControl >
118 {
119     Reference < XStream >   m_xStream;
120     UcbLockBytesRef         m_xLockBytes;
121 
122 public:
123 
124                             UcbStreamer_Impl( UcbLockBytes* pLockBytes )
125                                 : m_xLockBytes( pLockBytes )
126                             {}
127 
128 	// XActiveDataControl.
129     virtual void SAL_CALL   addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
130     virtual void SAL_CALL   removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
131     virtual void SAL_CALL   start (void) throw(RuntimeException) {}
132     virtual void SAL_CALL   terminate (void) throw(RuntimeException)
133                             { m_xLockBytes->terminate_Impl(); }
134 
135     // XActiveDataStreamer
136     virtual void SAL_CALL   setStream( const Reference< XStream >& aStream ) throw(RuntimeException)
137                             { m_xStream = aStream; m_xLockBytes->setStream_Impl( aStream ); }
138     virtual Reference< XStream > SAL_CALL getStream() throw(RuntimeException)
139                             { return m_xStream; }
140 };
141 
142 /**
143     Helper class for progress handling while executing UCB commands
144  */
145 class ProgressHandler_Impl: public ::cppu::WeakImplHelper1< XProgressHandler >
146 {
147     Link                    m_aProgress;
148 
149 public:
150                             ProgressHandler_Impl( const Link& rLink )
151                                 : m_aProgress( rLink )
152                             {}
153     // XProgressHandler
154     virtual void SAL_CALL   push(const Any & /*rStatus*/) throw (RuntimeException) {}
155     virtual void SAL_CALL   pop() throw (RuntimeException) {}
156     virtual void SAL_CALL   update(const Any & /*rStatus*/) throw (RuntimeException)
157                             { if ( m_aProgress.IsSet() ) m_aProgress.Call( 0 ); }
158 };
159 
160 /**
161     Helper class for managing interactions and progress when executing UCB commands
162  */
163 class UcbTaskEnvironment : public ::cppu::WeakImplHelper1< XCommandEnvironment >
164 {
165     Reference< XInteractionHandler >                m_xInteractionHandler;
166     Reference< XProgressHandler >                   m_xProgressHandler;
167 
168 public:
169                             UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler,
170                                                 const Reference< XProgressHandler>& rxProgressHandler )
171                                 : m_xInteractionHandler( rxInteractionHandler )
172                                 , m_xProgressHandler( rxProgressHandler )
173                             {}
174 
175 
176     virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException)
177 	{ return m_xInteractionHandler; }
178 
179     virtual Reference<XProgressHandler> SAL_CALL    getProgressHandler() throw (RuntimeException)
180 	{ return m_xProgressHandler; }
181 };
182 
183 
184 /**
185     Helper class for property change notifies when executing UCB commands
186 */
187 class UcbPropertiesChangeListener_Impl : public ::cppu::WeakImplHelper1< XPropertiesChangeListener >
188 {
189 public:
190     UcbLockBytesRef         m_xLockBytes;
191 
192                             UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef )
193                                 : m_xLockBytes( rRef )
194                             {}
195 
196     virtual void SAL_CALL   disposing ( const EventObject &/*rEvent*/) throw(RuntimeException) {}
197     virtual void SAL_CALL   propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException);
198 };
199 
200 void SAL_CALL UcbPropertiesChangeListener_Impl::propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException)
201 {
202 	sal_Int32 i, n = rEvent.getLength();
203 	for (i = 0; i < n; i++)
204 	{
205 		PropertyChangeEvent evt (rEvent[i]);
206         if (evt.PropertyName == ::rtl::OUString::createFromAscii ("DocumentHeader"))
207 		{
208 			Sequence<DocumentHeaderField> aHead;
209 			if (evt.NewValue >>= aHead)
210 			{
211                 sal_Int32 k, m = aHead.getLength();
212                 for (k = 0; k < m; k++)
213                 {
214                     String aName( aHead[k].Name );
215                     String aValue( aHead[k].Value );
216 
217                     if (aName.CompareIgnoreCaseToAscii("Expires") == COMPARE_EQUAL)
218                     {
219                         DateTime aExpires (0, 0);
220                         if (INetRFC822Message::ParseDateField (aValue, aExpires))
221                         {
222                             aExpires.ConvertToLocalTime();
223                             m_xLockBytes->SetExpireDate_Impl( aExpires );
224                         }
225                     }
226                 }
227 			}
228 
229             m_xLockBytes->SetStreamValid_Impl();
230 		}
231         else if (evt.PropertyName == rtl::OUString::createFromAscii ("PresentationURL"))
232 		{
233             ::rtl::OUString aUrl;
234 			if (evt.NewValue >>= aUrl)
235 			{
236                 ::rtl::OUString aBad (::rtl::OUString::createFromAscii ("private:"));
237 				if (!(aUrl.compareTo (aBad, aBad.getLength()) == 0))
238 				{
239 					// URL changed (Redirection).
240                     m_xLockBytes->SetRealURL_Impl( aUrl );
241 				}
242 			}
243 		}
244         else if (evt.PropertyName == ::rtl::OUString::createFromAscii ("MediaType"))
245         {
246             ::rtl::OUString aContentType;
247             if (evt.NewValue >>= aContentType)
248                 m_xLockBytes->SetContentType_Impl( aContentType );
249         }
250 	}
251 }
252 
253 
254 
255 class Moderator
256 	: public osl::Thread
257 {
258 	// usage restriction:
259 	// It might be possible, that the call to the interactionhandler and/or
260 	// progresshandler is done asynchrounsly, while the 'execute' simply
261 	// returns. This would imply that these class must be refcounted !!!
262 
263 public:
264 
265 	Moderator(
266 		Reference < XContent >& xContent,
267 		Reference < XInteractionHandler >& xInteract,
268 		Reference < XProgressHandler >& xProgress,
269 		const Command& rArg
270     )
271         throw(
272             ContentCreationException,
273             RuntimeException
274         );
275 
276 	~Moderator();
277 
278 
279 	enum ResultType {
280 		NORESULT,
281 
282 		INTERACTIONREQUEST,    // reply expected
283 
284 		PROGRESSPUSH,
285 		PROGRESSUPDATE,
286 		PROGRESSPOP,
287 
288         INPUTSTREAM,
289         STREAM,
290 
291 		RESULT,
292 		TIMEDOUT,
293 		COMMANDABORTED,
294 		COMMANDFAILED,
295 		INTERACTIVEIO,
296 		UNSUPPORTED,
297 		GENERAL
298 	};
299 
300 
301 	class ConditionRes
302 		: public salhelper::Condition
303 	{
304 	public:
305 
306 		ConditionRes(osl::Mutex& aMutex,Moderator& aModerator)
307 			: salhelper::Condition(aMutex),
308               m_aModerator(aModerator)
309 		{
310 		}
311 
312 	protected:
313 
314 		bool applies() const {
315 			return m_aModerator.m_aResultType != NORESULT;
316 		}
317 
318 	private:
319 
320 		Moderator& m_aModerator;
321 	};
322 
323 
324 	struct Result {
325 		ResultType        type;
326 		Any               result;
327 		sal_Int32         ioErrorCode;
328 	};
329 
330 
331 	Result getResult(const sal_uInt32 milliSec);
332 
333 
334 	enum ReplyType {
335 		NOREPLY,
336 		EXIT,
337 		RETRY,
338 		REQUESTHANDLED
339 	};
340 
341 
342 	class ConditionRep
343 		: public salhelper::Condition
344 	{
345 	public:
346 
347 		ConditionRep(osl::Mutex& aMutex,Moderator& aModerator)
348 			: salhelper::Condition(aMutex),
349               m_aModerator(aModerator)
350 		{
351 		}
352 
353 	protected:
354 
355 		bool applies() const {
356 			return m_aModerator.m_aReplyType != NOREPLY;
357 		}
358 
359 	private:
360 
361 		Moderator& m_aModerator;
362 	};
363 
364 	void setReply(ReplyType);
365 
366 
367 	void handle( const Reference<XInteractionRequest >& Request );
368 
369 	void push( const Any& Status );
370 
371 	void update( const Any& Status );
372 
373 	void pop(  );
374 
375     void setStream(const Reference< XStream >& aStream);
376 
377     void setInputStream(const Reference<XInputStream> &rxInputStream);
378 
379 
380 protected:
381 
382 	virtual void SAL_CALL run();
383 
384 	virtual void SAL_CALL onTerminated();
385 
386 private:
387 
388     osl::Mutex        m_aMutex;
389 
390     friend class ConditionRes;
391 
392 	ConditionRes      m_aRes;
393 	ResultType        m_aResultType;
394 	sal_Int32         m_nIOErrorCode;
395 	Any               m_aResult;
396 
397     friend class ConditionRep;
398 
399 	ConditionRep      m_aRep;
400 	ReplyType         m_aReplyType;
401 
402     Command                           m_aArg;
403 	::ucbhelper::Content              m_aContent;
404 };
405 
406 
407 class ModeratorsActiveDataStreamer
408 	: public ::cppu::WeakImplHelper1<XActiveDataStreamer>
409 {
410 public:
411 
412 	ModeratorsActiveDataStreamer(Moderator &theModerator);
413 
414 	~ModeratorsActiveDataStreamer();
415 
416     // XActiveDataStreamer
417     virtual void SAL_CALL
418     setStream(
419         const Reference< XStream >& aStream
420     )
421         throw(
422             RuntimeException
423         );
424 
425     virtual Reference<XStream> SAL_CALL
426     getStream (
427         void
428     ) throw(
429         RuntimeException
430     )
431     {
432         osl::MutexGuard aGuard(m_aMutex);
433         return m_xStream;
434     }
435 
436 
437 private:
438 
439     Moderator& m_aModerator;
440 
441     osl::Mutex m_aMutex;
442     Reference<XStream> m_xStream;
443 };
444 
445 
446 
447 class ModeratorsActiveDataSink
448 	: public ::cppu::WeakImplHelper1<XActiveDataSink>
449 {
450 public:
451 
452 	ModeratorsActiveDataSink(Moderator &theModerator);
453 
454 	~ModeratorsActiveDataSink();
455 
456 	// XActiveDataSink.
457     virtual void SAL_CALL
458     setInputStream (
459         const Reference<XInputStream> &rxInputStream
460     )
461         throw(
462             RuntimeException
463         );
464 
465     virtual Reference<XInputStream> SAL_CALL
466     getInputStream (
467         void
468     ) throw(
469         RuntimeException
470     )
471     {
472         osl::MutexGuard aGuard(m_aMutex);
473         return m_xStream;
474     }
475 
476 
477 private:
478 
479 	Moderator& m_aModerator;
480     osl::Mutex m_aMutex;
481     Reference<XInputStream> m_xStream;
482 };
483 
484 
485 
486 ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator)
487     : m_aModerator(theModerator)
488 {
489 }
490 
491 
492 ModeratorsActiveDataSink::~ModeratorsActiveDataSink()
493 {
494 }
495 
496 // XActiveDataSink.
497 void SAL_CALL
498 ModeratorsActiveDataSink::setInputStream (
499     const Reference<XInputStream> &rxInputStream
500 )
501     throw(
502         RuntimeException
503     )
504 {
505     m_aModerator.setInputStream(rxInputStream);
506     osl::MutexGuard aGuard(m_aMutex);
507     m_xStream = rxInputStream;
508 }
509 
510 
511 ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer(
512     Moderator &theModerator
513 )
514     : m_aModerator(theModerator)
515 {
516 }
517 
518 
519 ModeratorsActiveDataStreamer::~ModeratorsActiveDataStreamer()
520 {
521 }
522 
523 // XActiveDataStreamer.
524 void SAL_CALL
525 ModeratorsActiveDataStreamer::setStream (
526     const Reference<XStream> &rxStream
527 )
528     throw(
529         RuntimeException
530     )
531 {
532     m_aModerator.setStream(rxStream);
533     osl::MutexGuard aGuard(m_aMutex);
534     m_xStream = rxStream;
535 }
536 
537 
538 
539 class ModeratorsInteractionHandler
540 	: public ::cppu::WeakImplHelper1<XInteractionHandler>
541 {
542 public:
543 
544 	ModeratorsInteractionHandler(Moderator &theModerator);
545 
546 	~ModeratorsInteractionHandler();
547 
548 	virtual void SAL_CALL
549 	handle( const Reference<XInteractionRequest >& Request )
550 		throw (RuntimeException);
551 
552 private:
553 
554 	Moderator& m_aModerator;
555 };
556 
557 
558 class ModeratorsProgressHandler
559 	: public ::cppu::WeakImplHelper1<XProgressHandler>
560 {
561 public:
562 
563 	ModeratorsProgressHandler(Moderator &theModerator);
564 
565 	~ModeratorsProgressHandler();
566 
567 	virtual void SAL_CALL push( const Any& Status )
568 		throw (
569 			RuntimeException);
570 
571     virtual void SAL_CALL update( const Any& Status )
572 		throw (RuntimeException);
573 
574     virtual void SAL_CALL pop(  )
575 		throw (RuntimeException);
576 
577 
578 private:
579 
580 	Moderator& m_aModerator;
581 };
582 
583 
584 ModeratorsProgressHandler::ModeratorsProgressHandler(Moderator &theModerator)
585 	: m_aModerator(theModerator)
586 {
587 }
588 
589 ModeratorsProgressHandler::~ModeratorsProgressHandler()
590 {
591 }
592 
593 
594 void SAL_CALL ModeratorsProgressHandler::push( const Any& Status )
595 	throw (
596 		RuntimeException)
597 {
598 	m_aModerator.push(Status);
599 }
600 
601 
602 void SAL_CALL ModeratorsProgressHandler::update( const Any& Status )
603 	throw (RuntimeException)
604 {
605 	m_aModerator.update(Status);
606 }
607 
608 
609 void SAL_CALL ModeratorsProgressHandler::pop(  )
610 	throw (RuntimeException)
611 {
612 	m_aModerator.pop();
613 }
614 
615 
616 
617 
618 ModeratorsInteractionHandler::ModeratorsInteractionHandler(
619 	Moderator &aModerator)
620 	: m_aModerator(aModerator)
621 {
622 }
623 
624 
625 ModeratorsInteractionHandler::~ModeratorsInteractionHandler()
626 {
627 }
628 
629 
630 void SAL_CALL
631 ModeratorsInteractionHandler::handle(
632 	const Reference<XInteractionRequest >& Request
633 )
634 	throw (
635 		RuntimeException
636 	)
637 {
638 	// wakes up the mainthread
639 	m_aModerator.handle(Request);
640 }
641 
642 
643 
644 
645 Moderator::Moderator(
646 	Reference < XContent >& xContent,
647 	Reference < XInteractionHandler >& xInteract,
648 	Reference < XProgressHandler >& xProgress,
649 	const Command& rArg
650 )
651     throw(
652         ::com::sun::star::ucb::ContentCreationException,
653         ::com::sun::star::uno::RuntimeException
654     )
655 	: m_aMutex(),
656 
657       m_aRes(m_aMutex,*this),
658 	  m_aResultType(NORESULT),
659 	  m_nIOErrorCode(0),
660 	  m_aResult(),
661 
662 	  m_aRep(m_aMutex,*this),
663 	  m_aReplyType(NOREPLY),
664 
665 	  m_aArg(rArg),
666       m_aContent(
667           xContent,
668           new UcbTaskEnvironment(
669               xInteract.is() ? new ModeratorsInteractionHandler(*this) : 0,
670               xProgress.is() ? new ModeratorsProgressHandler(*this) : 0
671           ))
672 {
673     // now exchange the whole data sink stuff
674     // with a thread safe version
675 
676     Reference<XInterface> *pxSink = NULL;
677 
678     PostCommandArgument2 aPostArg;
679     OpenCommandArgument2 aOpenArg;
680 
681     int dec(2);
682     if(m_aArg.Argument >>= aPostArg) {
683         pxSink = &aPostArg.Sink;
684         dec = 0;
685     }
686     else if(m_aArg.Argument >>= aOpenArg) {
687         pxSink = &aOpenArg.Sink;
688         dec = 1;
689     }
690 
691     if(dec ==2)
692         throw ContentCreationException();
693 
694     Reference < XActiveDataSink > xActiveSink(*pxSink,UNO_QUERY);
695     if(xActiveSink.is())
696         *pxSink = Reference<XInterface>(
697             (cppu::OWeakObject*)new ModeratorsActiveDataSink(*this));
698 
699     Reference<XActiveDataStreamer> xStreamer( *pxSink, UNO_QUERY );
700     if ( xStreamer.is() )
701         *pxSink = Reference<XInterface>(
702             (cppu::OWeakObject*)new ModeratorsActiveDataStreamer(*this));
703 
704     if(dec == 0)
705         m_aArg.Argument <<= aPostArg;
706     else if(dec == 1)
707         m_aArg.Argument <<= aOpenArg;
708 }
709 
710 
711 Moderator::~Moderator()
712 {
713 }
714 
715 
716 Moderator::Result Moderator::getResult(const sal_uInt32 milliSec)
717 {
718 	Result ret;
719 	try {
720         salhelper::ConditionWaiter aWaiter(m_aRes,milliSec);
721         ret.type = m_aResultType;
722         ret.result = m_aResult;
723         ret.ioErrorCode = m_nIOErrorCode;
724 
725         // reset
726         m_aResultType = NORESULT;
727 	}
728 	catch(const salhelper::ConditionWaiter::timedout&)
729 	{
730 		ret.type = TIMEDOUT;
731 	}
732 
733 	return ret;
734 }
735 
736 
737 void Moderator::setReply(ReplyType aReplyType )
738 {
739 	salhelper::ConditionModifier aMod(m_aRep);
740 	m_aReplyType = aReplyType;
741 }
742 
743 
744 void Moderator::handle( const Reference<XInteractionRequest >& Request )
745 {
746 	ReplyType aReplyType;
747 
748 	do {
749 		{
750 			salhelper::ConditionModifier aMod(m_aRes);
751 			m_aResultType = INTERACTIONREQUEST;
752 			m_aResult <<= Request;
753 		}
754 
755 		{
756 			salhelper::ConditionWaiter aWait(m_aRep);
757 			aReplyType = m_aReplyType;
758 
759 			// reset
760 			m_aReplyType = NOREPLY;
761 		}
762 
763 		if(aReplyType == EXIT) {
764 			Sequence<Reference<XInteractionContinuation> > aSeq(
765 				Request->getContinuations());
766 			for(sal_Int32 i = 0; i < aSeq.getLength(); ++i) {
767 				Reference<XInteractionAbort> aRef(aSeq[i],UNO_QUERY);
768 				if(aRef.is()) {
769 					aRef->select();
770 				}
771 			}
772 
773 			// resignal the exitcondition
774 			setReply(EXIT);
775 			break;
776 		}
777 	} while(aReplyType != REQUESTHANDLED);
778 }
779 
780 
781 
782 void Moderator::push( const Any& Status )
783 {
784     {
785         salhelper::ConditionModifier aMod(m_aRes);
786         m_aResultType = PROGRESSPUSH;
787         m_aResult = Status;
788     }
789 	ReplyType aReplyType;
790     {
791         salhelper::ConditionWaiter aWait(m_aRep);
792 		aReplyType = m_aReplyType;
793 		m_aReplyType = NOREPLY;
794     }
795 	if(aReplyType == EXIT)
796 		setReply(EXIT);
797 }
798 
799 
800 void Moderator::update( const Any& Status )
801 {
802 	{
803         salhelper::ConditionModifier aMod(m_aRes);
804         m_aResultType = PROGRESSUPDATE;
805         m_aResult = Status;
806     }
807 	ReplyType aReplyType;
808     {
809         salhelper::ConditionWaiter aWait(m_aRep);
810 		aReplyType = m_aReplyType;
811 		m_aReplyType = NOREPLY;
812     }
813 	if(aReplyType == EXIT)
814 		setReply(EXIT);
815 }
816 
817 
818 void Moderator::pop(  )
819 {
820     {
821         salhelper::ConditionModifier aMod(m_aRes);
822         m_aResultType = PROGRESSPOP;
823     }
824 	ReplyType aReplyType;
825     {
826         salhelper::ConditionWaiter aWait(m_aRep);
827 		aReplyType = m_aReplyType;
828 		m_aReplyType = NOREPLY;
829 	}
830 	if(aReplyType == EXIT)
831 		setReply(EXIT);
832 }
833 
834 
835 void Moderator::setStream(const Reference< XStream >& aStream)
836 {
837     {
838         salhelper::ConditionModifier aMod(m_aRes);
839         m_aResultType = STREAM;
840         m_aResult <<= aStream;
841     }
842 	ReplyType aReplyType;
843     {
844         salhelper::ConditionWaiter aWait(m_aRep);
845 		aReplyType = m_aReplyType;
846         m_aReplyType = NOREPLY;
847     }
848 	if(aReplyType == EXIT)
849 		setReply(EXIT);
850 }
851 
852 
853 void Moderator::setInputStream(const Reference<XInputStream> &rxInputStream)
854 {
855     {
856         salhelper::ConditionModifier aMod(m_aRes);
857         m_aResultType = INPUTSTREAM;
858         m_aResult <<= rxInputStream;
859     }
860 	ReplyType aReplyType;
861     {
862         salhelper::ConditionWaiter aWait(m_aRep);
863 		aReplyType = m_aReplyType;
864         m_aReplyType = NOREPLY;
865     }
866 	if(aReplyType == EXIT)
867 		setReply(EXIT);
868 }
869 
870 
871 
872 void SAL_CALL Moderator::run()
873 {
874 	ResultType aResultType;
875 	Any        aResult;
876 	sal_Int32  nIOErrorCode = 0;
877 
878     try
879     {
880 		aResult = m_aContent.executeCommand(m_aArg.Name,m_aArg.Argument);
881 		aResultType = RESULT;
882     }
883     catch ( CommandAbortedException )
884     {
885 		aResultType = COMMANDABORTED;
886     }
887     catch ( CommandFailedException )
888     {
889 		aResultType = COMMANDFAILED;
890     }
891     catch ( InteractiveIOException& r )
892     {
893 		nIOErrorCode = r.Code;
894 		aResultType = INTERACTIVEIO;
895     }
896     catch ( UnsupportedDataSinkException& )
897     {
898 		aResultType = UNSUPPORTED;
899     }
900     catch ( Exception )
901     {
902 		aResultType = GENERAL;
903     }
904 
905 	{
906 		salhelper::ConditionModifier aMod(m_aRes);
907 		m_aResultType = aResultType;
908 		m_aResult = aResult;
909 		m_nIOErrorCode = nIOErrorCode;
910 	}
911 }
912 
913 
914 
915 void SAL_CALL Moderator::onTerminated()
916 {
917     {
918         salhelper::ConditionWaiter aWaiter(m_aRep);
919     }
920  	delete this;
921 }
922 
923 
924 /**
925    Function for opening UCB contents synchronously,
926    but with handled timeout;
927 */
928 
929 static sal_Bool _UCBOpenContentSync(
930 	UcbLockBytesRef xLockBytes,
931 	Reference < XContent > xContent,
932 	const Command& rArg,
933 	Reference < XInterface > xSink,
934 	Reference < XInteractionHandler > xInteract,
935 	Reference < XProgressHandler > xProgress,
936 	UcbLockBytesHandlerRef xHandler );
937 
938 
939 static sal_Bool UCBOpenContentSync(
940 	UcbLockBytesRef xLockBytes,
941 	Reference < XContent > xContent,
942 	const Command& rArg,
943 	Reference < XInterface > xSink,
944 	Reference < XInteractionHandler > xInteract,
945 	Reference < XProgressHandler > xProgress,
946 	UcbLockBytesHandlerRef xHandler )
947 {
948     // http protocol must be handled in a special way:
949 	//        during the opening process the input stream may change
950     //        only the last inputstream after notifying the document
951 	//        headers is valid
952 
953 	Reference<XContentIdentifier> xContId(
954 		xContent.is() ? xContent->getIdentifier() : 0 );
955 
956 	rtl::OUString aScheme;
957 	if(xContId.is())
958 		aScheme = xContId->getContentProviderScheme();
959 
960     // now determine wether we use a timeout or not;
961     if( ! aScheme.equalsIgnoreAsciiCaseAscii("http")                &&
962 		! aScheme.equalsIgnoreAsciiCaseAscii("https")                &&
963         ! aScheme.equalsIgnoreAsciiCaseAscii("vnd.sun.star.webdav") &&
964         ! aScheme.equalsIgnoreAsciiCaseAscii("ftp"))
965 		return _UCBOpenContentSync(
966 			xLockBytes,xContent,rArg,xSink,xInteract,xProgress,xHandler);
967 
968     if ( (aScheme.compareToAscii( "http" ) != COMPARE_EQUAL) ||
969 		 (aScheme.compareToAscii( "https" ) != COMPARE_EQUAL) )
970         xLockBytes->SetStreamValid_Impl();
971 
972     Reference< XPropertiesChangeListener > xListener;
973 	Reference< XPropertiesChangeNotifier > xProps(xContent,UNO_QUERY);
974     if(xProps.is()) {
975 		xListener =
976 			new UcbPropertiesChangeListener_Impl(xLockBytes);
977         xProps->addPropertiesChangeListener(
978 			Sequence< ::rtl::OUString >(),
979 			xListener);
980 	}
981 
982     Any aResult;
983     bool bException(false);
984     bool bAborted(false);
985     bool bResultAchieved(false);
986 
987     Moderator* pMod = 0;
988     try {
989         pMod = new Moderator(xContent,xInteract,xProgress,rArg);
990         pMod->create();
991     } catch(const ContentCreationException&) {
992         bResultAchieved = bException = true;
993         xLockBytes->SetError( ERRCODE_IO_GENERAL );
994     }
995 
996     sal_uInt32 nTimeout(5000); // initially 5000 milliSec
997 	while(!bResultAchieved) {
998 
999         Moderator::Result res;
1000 		// try to get the result for with timeout
1001 		res = pMod->getResult(nTimeout);
1002 
1003 		switch(res.type) {
1004         case Moderator::PROGRESSPUSH:
1005 			{
1006 				if(xProgress.is())
1007 					xProgress->push(res.result);
1008 				pMod->setReply(Moderator::REQUESTHANDLED);
1009 				break;
1010 			}
1011         case Moderator::PROGRESSUPDATE:
1012 			{
1013 				if(xProgress.is())
1014 					xProgress->update(res.result);
1015 				pMod->setReply(Moderator::REQUESTHANDLED);
1016 				break;
1017 			}
1018         case Moderator::PROGRESSPOP:
1019 			{
1020 				if(xProgress.is())
1021 					xProgress->pop();
1022 				pMod->setReply(Moderator::REQUESTHANDLED);
1023 				break;
1024 			}
1025         case Moderator::STREAM:
1026             {
1027                 Reference<XStream> result;
1028                 if(res.result >>= result) {
1029                     Reference < XActiveDataStreamer > xStreamer(
1030                         xSink, UNO_QUERY
1031                     );
1032 
1033                     if(xStreamer.is())
1034                         xStreamer->setStream(result);
1035                 }
1036 				pMod->setReply(Moderator::REQUESTHANDLED);
1037                 break;
1038             }
1039         case Moderator::INPUTSTREAM:
1040             {
1041 				Reference<XInputStream> result;
1042 				res.result >>= result;
1043                 Reference < XActiveDataSink > xActiveSink(
1044                     xSink, UNO_QUERY
1045                 );
1046 
1047                 if(xActiveSink.is())
1048                     xActiveSink->setInputStream(result);
1049 				pMod->setReply(Moderator::REQUESTHANDLED);
1050                 break;
1051             }
1052         case Moderator::TIMEDOUT:
1053 			{
1054 				Reference<XInteractionRetry> xRet;
1055 				if(xInteract.is()) {
1056 					InteractiveNetworkConnectException aExcep;
1057 					INetURLObject aURL(
1058 						xContId.is() ?
1059 						xContId->getContentIdentifier() :
1060 						rtl::OUString() );
1061 					aExcep.Server = aURL.GetHost();
1062 					aExcep.Classification = InteractionClassification_ERROR;
1063 					aExcep.Message =
1064 						rtl::OUString(
1065 							RTL_CONSTASCII_USTRINGPARAM(
1066 								"server not responding after five seconds"));
1067 					Any request;
1068 					request <<= aExcep;
1069 					ucbhelper::InteractionRequest *ir =
1070 						new ucbhelper::InteractionRequest(request);
1071 					Reference<XInteractionRequest> xIR(ir);
1072 					Sequence<Reference<XInteractionContinuation> > aSeq(2);
1073 					ucbhelper::InteractionRetry *retryP =
1074 						new ucbhelper::InteractionRetry(ir);
1075 					aSeq[0] = retryP;
1076 					ucbhelper::InteractionAbort *abortP =
1077 						new ucbhelper::InteractionAbort(ir);
1078 					aSeq[1] = abortP;
1079 
1080 					ir->setContinuations(aSeq);
1081 					xInteract->handle(xIR);
1082 					rtl::Reference< ucbhelper::InteractionContinuation > ref
1083 						= ir->getSelection();
1084 					if(ref.is()) {
1085 						Reference<XInterface> xInt(ref.get());
1086 						xRet = Reference<XInteractionRetry>(xInt,UNO_QUERY);
1087 					}
1088 				}
1089 
1090 				if(!xRet.is()) {
1091 					bAborted = true;
1092 					xLockBytes->SetError(ERRCODE_ABORT);
1093 				}
1094 
1095 				break;
1096 			}
1097         case Moderator::INTERACTIONREQUEST:
1098 			{
1099 				Reference<XInteractionRequest> Request;
1100 				res.result >>= Request;
1101 				xInteract->handle(Request);
1102 				pMod->setReply(Moderator::REQUESTHANDLED);
1103 				break;
1104 			}
1105         case Moderator::RESULT:
1106 			{
1107 				bResultAchieved = true;
1108 				aResult = res.result;
1109 				break;
1110 			}
1111         case Moderator::COMMANDABORTED:
1112 			{
1113 				bAborted = true;
1114 				xLockBytes->SetError( ERRCODE_ABORT );
1115 				break;
1116 			}
1117         case Moderator::COMMANDFAILED:
1118 			{
1119 				bAborted = true;
1120 				xLockBytes->SetError( ERRCODE_ABORT );
1121 				break;
1122 			}
1123         case Moderator::INTERACTIVEIO:
1124 			{
1125 				bException = true;
1126 				if ( res.ioErrorCode == IOErrorCode_ACCESS_DENIED ||
1127 					 res.ioErrorCode == IOErrorCode_LOCKING_VIOLATION )
1128 					xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
1129 				else if ( res.ioErrorCode == IOErrorCode_NOT_EXISTING )
1130 					xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
1131 				else if ( res.ioErrorCode == IOErrorCode_CANT_READ )
1132 					xLockBytes->SetError( ERRCODE_IO_CANTREAD );
1133 				else
1134 					xLockBytes->SetError( ERRCODE_IO_GENERAL );
1135 				break;
1136 			}
1137         case Moderator::UNSUPPORTED:
1138 			{
1139 				bException = true;
1140 				xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
1141 				break;
1142 			}
1143         default:
1144 			{
1145 				bException = true;
1146 				xLockBytes->SetError( ERRCODE_IO_GENERAL );
1147 				break;
1148 			}
1149 		}
1150 
1151 		bResultAchieved |= bException;
1152 		bResultAchieved |= bAborted;
1153         if(nTimeout == 5000) nTimeout *= 2;
1154     }
1155 
1156     if(pMod) pMod->setReply(Moderator::EXIT);
1157 
1158     if ( bAborted || bException )
1159     {
1160         if( xHandler.Is() )
1161             xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes );
1162 
1163         Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
1164         if ( xActiveSink.is() )
1165             xActiveSink->setInputStream( Reference < XInputStream >() );
1166 
1167         Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
1168         if ( xStreamer.is() )
1169             xStreamer->setStream( Reference < XStream >() );
1170     }
1171 
1172     Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
1173     if ( xControl.is() )
1174         xControl->terminate();
1175 
1176     if ( xProps.is() )
1177         xProps->removePropertiesChangeListener(
1178 			Sequence< ::rtl::OUString >(),
1179 			xListener );
1180 
1181     return ( bAborted || bException );
1182 }
1183 
1184 /**
1185     Function for opening UCB contents synchronously
1186  */
1187 static sal_Bool _UCBOpenContentSync(
1188 	UcbLockBytesRef xLockBytes,
1189 	Reference < XContent > xContent,
1190 	const Command& rArg,
1191 	Reference < XInterface > xSink,
1192 	Reference < XInteractionHandler > xInteract,
1193 	Reference < XProgressHandler > xProgress,
1194 	UcbLockBytesHandlerRef xHandler )
1195 {
1196     ::ucbhelper::Content aContent( xContent, new UcbTaskEnvironment( xInteract, xProgress ) );
1197     Reference < XContentIdentifier > xIdent = xContent->getIdentifier();
1198     ::rtl::OUString aScheme = xIdent->getContentProviderScheme();
1199 
1200     // http protocol must be handled in a special way: during the opening process the input stream may change
1201     // only the last inputstream after notifying the document headers is valid
1202     if ( aScheme.compareToAscii("http") != COMPARE_EQUAL )
1203         xLockBytes->SetStreamValid_Impl();
1204 
1205     Reference< XPropertiesChangeListener > xListener = new UcbPropertiesChangeListener_Impl( xLockBytes );
1206     Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY );
1207     if ( xProps.is() )
1208         xProps->addPropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener );
1209 
1210     Any aResult;
1211     bool bException = false;
1212     bool bAborted = false;
1213 
1214     try
1215     {
1216         aResult = aContent.executeCommand( rArg.Name, rArg.Argument );
1217     }
1218     catch ( CommandAbortedException )
1219     {
1220         bAborted = true;
1221 		xLockBytes->SetError( ERRCODE_ABORT );
1222     }
1223     catch ( CommandFailedException )
1224     {
1225         bAborted = true;
1226 		xLockBytes->SetError( ERRCODE_ABORT );
1227     }
1228     catch ( InteractiveIOException& r )
1229     {
1230 		bException = true;
1231         if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
1232 			xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
1233 		else if ( r.Code == IOErrorCode_NOT_EXISTING )
1234 			xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
1235 		else if ( r.Code == IOErrorCode_CANT_READ )
1236 			xLockBytes->SetError( ERRCODE_IO_CANTREAD );
1237 		else
1238 			xLockBytes->SetError( ERRCODE_IO_GENERAL );
1239     }
1240     catch ( UnsupportedDataSinkException& )
1241     {
1242 		bException = true;
1243         xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
1244     }
1245     catch ( Exception )
1246     {
1247         bException = true;
1248 		xLockBytes->SetError( ERRCODE_IO_GENERAL );
1249     }
1250 
1251     if ( bAborted || bException )
1252     {
1253         if( xHandler.Is() )
1254             xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes );
1255 
1256         Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
1257         if ( xActiveSink.is() )
1258             xActiveSink->setInputStream( Reference < XInputStream >() );
1259 
1260         Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
1261         if ( xStreamer.is() )
1262             xStreamer->setStream( Reference < XStream >() );
1263     }
1264 
1265     Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
1266     if ( xControl.is() )
1267         xControl->terminate();
1268 
1269 
1270     if ( xProps.is() )
1271         xProps->removePropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener );
1272 
1273     return ( bAborted || bException );
1274 }
1275 
1276 
1277 //----------------------------------------------------------------------------
1278 UcbLockBytes::UcbLockBytes( UcbLockBytesHandler* pHandler )
1279     : m_xInputStream (NULL)
1280     , m_pCommandThread( NULL )
1281     , m_xHandler( pHandler )
1282     , m_nError( ERRCODE_NONE )
1283     , m_bTerminated  (sal_False)
1284     , m_bDontClose( sal_False )
1285     , m_bStreamValid  (sal_False)
1286 {
1287     SetSynchronMode( sal_True );
1288 }
1289 
1290 //----------------------------------------------------------------------------
1291 UcbLockBytes::~UcbLockBytes()
1292 {
1293     if ( !m_bDontClose )
1294     {
1295         if ( m_xInputStream.is() )
1296         {
1297 			try
1298 			{
1299 				m_xInputStream->closeInput();
1300 			}
1301 			catch ( RuntimeException const & )
1302 			{}
1303 			catch ( IOException const & )
1304 			{}
1305         }
1306     }
1307 
1308     if ( !m_xInputStream.is() && m_xOutputStream.is() )
1309     {
1310         try
1311         {
1312             m_xOutputStream->closeOutput();
1313         }
1314         catch ( RuntimeException const & )
1315         {}
1316         catch ( IOException const & )
1317         {}
1318     }
1319 }
1320 
1321 Reference < XInputStream > UcbLockBytes::getInputStream()
1322 {
1323 	vos::OClearableGuard aGuard( m_aMutex );
1324     m_bDontClose = sal_True;
1325     return m_xInputStream;
1326 }
1327 
1328 Reference < XStream > UcbLockBytes::getStream()
1329 {
1330 	vos::OClearableGuard aGuard( m_aMutex );
1331 	Reference < XStream > xStream( m_xSeekable, UNO_QUERY );
1332 	if ( xStream.is() )
1333     	m_bDontClose = sal_True;
1334     return xStream;
1335 }
1336 
1337 //----------------------------------------------------------------------------
1338 
1339 sal_Bool UcbLockBytes::setStream_Impl( const Reference<XStream>& aStream )
1340 {
1341 	vos::OClearableGuard aGuard( m_aMutex );
1342     if ( aStream.is() )
1343     {
1344         m_xOutputStream = aStream->getOutputStream();
1345         setInputStream_Impl( aStream->getInputStream(), sal_False );
1346         m_xSeekable = Reference < XSeekable > ( aStream, UNO_QUERY );
1347     }
1348     else
1349     {
1350         m_xOutputStream = Reference < XOutputStream >();
1351         setInputStream_Impl( Reference < XInputStream >() );
1352     }
1353 
1354     return m_xInputStream.is();
1355 }
1356 
1357 sal_Bool UcbLockBytes::setInputStream_Impl( const Reference<XInputStream> &rxInputStream, sal_Bool bSetXSeekable )
1358 {
1359 	sal_Bool bRet = sal_False;
1360 
1361 	try
1362 	{
1363 		vos::OClearableGuard aGuard( m_aMutex );
1364 
1365 		if ( !m_bDontClose && m_xInputStream.is() )
1366 			m_xInputStream->closeInput();
1367 
1368 		m_xInputStream = rxInputStream;
1369 
1370 		if( bSetXSeekable )
1371 		{
1372     		m_xSeekable = Reference < XSeekable > ( rxInputStream, UNO_QUERY );
1373 			if( !m_xSeekable.is() && rxInputStream.is() )
1374 			{
1375             	Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
1376 				Reference< XOutputStream > rxTempOut = Reference < XOutputStream > (
1377 									xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
1378 									UNO_QUERY );
1379 
1380 				if( rxTempOut.is() )
1381 				{
1382 					::comphelper::OStorageHelper::CopyInputToOutput( rxInputStream, rxTempOut );
1383 					m_xInputStream = Reference< XInputStream >( rxTempOut, UNO_QUERY );
1384         			m_xSeekable = Reference < XSeekable > ( rxTempOut, UNO_QUERY );
1385 				}
1386 			}
1387 		}
1388 
1389 		bRet = m_xInputStream.is();
1390 		// aGuard.clear();
1391 	}
1392 	catch( Exception& )
1393 	{}
1394 
1395     if ( m_bStreamValid && m_xInputStream.is() )
1396         m_aInitialized.set();
1397 
1398 	return bRet;
1399 }
1400 
1401 void UcbLockBytes::SetStreamValid_Impl()
1402 {
1403     m_bStreamValid = sal_True;
1404     if ( m_xInputStream.is() )
1405         m_aInitialized.set();
1406 }
1407 
1408 //----------------------------------------------------------------------------
1409 void UcbLockBytes::terminate_Impl()
1410 {
1411 	m_bTerminated = sal_True;
1412 	m_aInitialized.set();
1413 	m_aTerminated.set();
1414 
1415     if ( GetError() == ERRCODE_NONE && !m_xInputStream.is() )
1416 	{
1417 		DBG_ERROR("No InputStream, but no error set!" );
1418         SetError( ERRCODE_IO_NOTEXISTS );
1419 	}
1420 
1421     if ( m_xHandler.Is() )
1422         m_xHandler->Handle( UcbLockBytesHandler::DONE, this );
1423 }
1424 
1425 //----------------------------------------------------------------------------
1426 void UcbLockBytes::SetSynchronMode (sal_Bool bSynchron)
1427 {
1428 	SvLockBytes::SetSynchronMode (bSynchron);
1429 }
1430 
1431 //----------------------------------------------------------------------------
1432 ErrCode UcbLockBytes::ReadAt ( sal_uLong nPos, void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const
1433 {
1434 	if ( IsSynchronMode() )
1435     {
1436         UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
1437         pThis->m_aInitialized.wait();
1438     }
1439 
1440     Reference <XInputStream> xStream = getInputStream_Impl();
1441 	if ( !xStream.is() )
1442 	{
1443 		if ( m_bTerminated )
1444 			return ERRCODE_IO_CANTREAD;
1445 		else
1446 			return ERRCODE_IO_PENDING;
1447 	}
1448 
1449 	if ( pRead )
1450 		*pRead = 0;
1451 
1452     Reference <XSeekable> xSeekable = getSeekable_Impl();
1453     if ( !xSeekable.is() )
1454 		return ERRCODE_IO_CANTREAD;
1455 
1456 	try
1457 	{
1458         xSeekable->seek( nPos );
1459 	}
1460 	catch ( IOException )
1461 	{
1462 		return ERRCODE_IO_CANTSEEK;
1463 	}
1464 	catch (com::sun::star::lang::IllegalArgumentException)
1465 	{
1466 		return ERRCODE_IO_CANTSEEK;
1467 	}
1468 
1469 	Sequence<sal_Int8> aData;
1470 	sal_Int32          nSize;
1471 
1472 	nCount = VOS_MIN(nCount, 0x7FFFFFFF);
1473 	try
1474 	{
1475 		if ( !m_bTerminated && !IsSynchronMode() )
1476 		{
1477             sal_uInt64 nLen = xSeekable->getLength();
1478 			if ( nPos + nCount > nLen )
1479 				return ERRCODE_IO_PENDING;
1480 		}
1481 
1482 		nSize = xStream->readBytes( aData, sal_Int32(nCount) );
1483 	}
1484 	catch (IOException)
1485 	{
1486 		return ERRCODE_IO_CANTREAD;
1487 	}
1488 
1489 	rtl_copyMemory (pBuffer, aData.getConstArray(), nSize);
1490 	if (pRead)
1491 		*pRead = sal_uLong(nSize);
1492 
1493 	return ERRCODE_NONE;
1494 }
1495 
1496 //----------------------------------------------------------------------------
1497 ErrCode UcbLockBytes::WriteAt ( sal_uLong nPos, const void *pBuffer, sal_uLong nCount, sal_uLong *pWritten)
1498 {
1499 	if ( pWritten )
1500 		*pWritten = 0;
1501 
1502     DBG_ASSERT( IsSynchronMode(), "Writing is only possible in SynchronMode!" );
1503     DBG_ASSERT( m_aInitialized.check(), "Writing bevor stream is ready!" );
1504 
1505     Reference <XSeekable> xSeekable = getSeekable_Impl();
1506     Reference <XOutputStream> xOutputStream = getOutputStream_Impl();
1507     if ( !xOutputStream.is() || !xSeekable.is() )
1508         return ERRCODE_IO_CANTWRITE;
1509 
1510 	try
1511 	{
1512         xSeekable->seek( nPos );
1513 	}
1514 	catch ( IOException )
1515 	{
1516 		return ERRCODE_IO_CANTSEEK;
1517 	}
1518 
1519     sal_Int8* pData = (sal_Int8*) pBuffer;
1520     Sequence<sal_Int8> aData( pData, nCount );
1521 	try
1522 	{
1523         xOutputStream->writeBytes( aData );
1524         if ( pWritten )
1525             *pWritten = nCount;
1526 	}
1527     catch ( Exception )
1528 	{
1529         return ERRCODE_IO_CANTWRITE;
1530 	}
1531 
1532 	return ERRCODE_NONE;
1533 }
1534 
1535 //----------------------------------------------------------------------------
1536 ErrCode UcbLockBytes::Flush() const
1537 {
1538     Reference <XOutputStream > xOutputStream = getOutputStream_Impl();
1539     if ( !xOutputStream.is() )
1540         return ERRCODE_IO_CANTWRITE;
1541 
1542     try
1543     {
1544         xOutputStream->flush();
1545     }
1546     catch( Exception )
1547     {
1548         return ERRCODE_IO_CANTWRITE;
1549     }
1550 
1551     return ERRCODE_NONE;
1552 }
1553 
1554 //----------------------------------------------------------------------------
1555 ErrCode UcbLockBytes::SetSize (sal_uLong nNewSize)
1556 {
1557     SvLockBytesStat aStat;
1558     Stat( &aStat, (SvLockBytesStatFlag) 0 );
1559     sal_uLong nSize = aStat.nSize;
1560 
1561     if ( nSize > nNewSize )
1562     {
1563         Reference < XTruncate > xTrunc( getOutputStream_Impl(), UNO_QUERY );
1564         if ( xTrunc.is() )
1565         {
1566             xTrunc->truncate();
1567             nSize = 0;
1568         }
1569         else {
1570             DBG_WARNING("Not truncatable!");
1571         }
1572     }
1573 
1574     if ( nSize < nNewSize )
1575     {
1576         sal_uLong nDiff = nNewSize-nSize, nCount=0;
1577         sal_uInt8* pBuffer = new sal_uInt8[ nDiff ];
1578         memset(pBuffer, 0, nDiff); // initialize for enhanced security
1579         WriteAt( nSize, pBuffer, nDiff, &nCount );
1580         delete[] pBuffer;
1581         if ( nCount != nDiff )
1582             return ERRCODE_IO_CANTWRITE;
1583     }
1584 
1585     return ERRCODE_NONE;
1586 }
1587 
1588 //----------------------------------------------------------------------------
1589 ErrCode UcbLockBytes::Stat( SvLockBytesStat *pStat, SvLockBytesStatFlag) const
1590 {
1591 	if ( IsSynchronMode() )
1592     {
1593         UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
1594         pThis->m_aInitialized.wait();
1595     }
1596 
1597 	if (!pStat)
1598 		return ERRCODE_IO_INVALIDPARAMETER;
1599 
1600     Reference <XInputStream> xStream = getInputStream_Impl();
1601     Reference <XSeekable> xSeekable = getSeekable_Impl();
1602 
1603     if ( !xStream.is() )
1604     {
1605 		if ( m_bTerminated )
1606             return ERRCODE_IO_INVALIDACCESS;
1607 		else
1608 			return ERRCODE_IO_PENDING;
1609     }
1610     else if( !xSeekable.is() )
1611 		return ERRCODE_IO_CANTTELL;
1612 
1613 	try
1614 	{
1615         pStat->nSize = sal_uLong(xSeekable->getLength());
1616 	}
1617 	catch (IOException)
1618 	{
1619 		return ERRCODE_IO_CANTTELL;
1620 	}
1621 
1622     return ERRCODE_NONE;
1623 }
1624 
1625 //----------------------------------------------------------------------------
1626 void UcbLockBytes::Cancel()
1627 {
1628 	// is alive only for compatibility reasons
1629 	OSL_ENSURE( m_bTerminated, "UcbLockBytes is not thread safe so it can be used only syncronously!\n" );
1630 }
1631 
1632 //----------------------------------------------------------------------------
1633 IMPL_LINK( UcbLockBytes, DataAvailHdl, void*, EMPTYARG )
1634 {
1635     if ( hasInputStream_Impl() && m_xHandler.Is() )
1636         m_xHandler->Handle( UcbLockBytesHandler::DATA_AVAILABLE, this );
1637 
1638 	return 0;
1639 }
1640 
1641 UcbLockBytesRef UcbLockBytes::CreateInputLockBytes( const Reference< XInputStream >& xInputStream )
1642 {
1643     if( !xInputStream.is() )
1644 		return NULL;;
1645 
1646     UcbLockBytesRef xLockBytes = new UcbLockBytes();
1647     xLockBytes->setDontClose_Impl();
1648     xLockBytes->setInputStream_Impl( xInputStream );
1649     xLockBytes->terminate_Impl();
1650     return xLockBytes;
1651 }
1652 
1653 UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference< XStream >& xStream )
1654 {
1655     if( !xStream.is() )
1656 		return NULL;;
1657 
1658     UcbLockBytesRef xLockBytes = new UcbLockBytes();
1659     xLockBytes->setDontClose_Impl();
1660     xLockBytes->setStream_Impl( xStream );
1661     xLockBytes->terminate_Impl();
1662     return xLockBytes;
1663 }
1664 
1665 UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const ::rtl::OUString& rReferer, const ::rtl::OUString& rMediaType,
1666         const Reference < XInputStream >& xPostData, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler )
1667 {
1668 	if( !xContent.is() )
1669 		return NULL;;
1670 
1671     UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler );
1672     xLockBytes->SetSynchronMode( !pHandler );
1673     Reference< XActiveDataControl > xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes );
1674 
1675     PostCommandArgument2 aArgument;
1676 	aArgument.Source = xPostData;
1677     aArgument.Sink = xSink;
1678     aArgument.MediaType = rMediaType;
1679     aArgument.Referer = rReferer;
1680 
1681     Command aCommand;
1682     aCommand.Name = ::rtl::OUString::createFromAscii ("post");
1683     aCommand.Argument <<= aArgument;
1684 
1685     Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) );
1686 
1687 	sal_Bool bError = UCBOpenContentSync( xLockBytes,
1688 										  xContent,
1689 										  aCommand,
1690 										  xSink,
1691 										  xInteractionHandler,
1692 										  xProgressHdl,
1693 										  pHandler );
1694 
1695    	if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) )
1696 	{
1697 		DBG_ERROR("No InputStream, but no error set!" );
1698        	xLockBytes->SetError( ERRCODE_IO_GENERAL );
1699 	}
1700 
1701     return xLockBytes;
1702 }
1703 
1704 UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const Sequence < PropertyValue >& rProps,
1705         StreamMode eOpenMode, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler )
1706 {
1707 	if( !xContent.is() )
1708 		return NULL;;
1709 
1710     UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler );
1711     xLockBytes->SetSynchronMode( !pHandler );
1712     Reference< XActiveDataControl > xSink;
1713     if ( eOpenMode & STREAM_WRITE )
1714         xSink = (XActiveDataControl*) new UcbStreamer_Impl( xLockBytes );
1715     else
1716         xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes );
1717 
1718     if ( rProps.getLength() )
1719     {
1720         Reference < XCommandProcessor > xProcessor( xContent, UNO_QUERY );
1721         Command aCommand;
1722         aCommand.Name     = ::rtl::OUString::createFromAscii("setPropertyValues");
1723         aCommand.Handle   = -1; /* unknown */
1724         aCommand.Argument <<= rProps;
1725         xProcessor->execute( aCommand, 0, Reference < XCommandEnvironment >() );
1726     }
1727 
1728 	OpenCommandArgument2 aArgument;
1729     aArgument.Sink = xSink;
1730 	aArgument.Mode = OpenMode::DOCUMENT;
1731 
1732     Command aCommand;
1733 	aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("open") );
1734 	aCommand.Argument <<= aArgument;
1735 
1736     Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) );
1737 
1738     sal_Bool bError = UCBOpenContentSync( xLockBytes,
1739 										  xContent,
1740 										  aCommand,
1741 										  xSink,
1742 										  xInteractionHandler,
1743 										  xProgressHdl,
1744 										  pHandler );
1745 
1746     if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) )
1747 	{
1748 		DBG_ERROR("No InputStream, but no error set!" );
1749        	xLockBytes->SetError( ERRCODE_IO_GENERAL );
1750 	}
1751 
1752     return xLockBytes;
1753 }
1754 
1755 }
1756