xref: /AOO41X/main/comphelper/source/misc/mediadescriptor.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_comphelper.hxx"
30 #include <comphelper/mediadescriptor.hxx>
31 #include <comphelper/namedvaluecollection.hxx>
32 #include <comphelper/stillreadwriteinteraction.hxx>
33 
34 #include <com/sun/star/ucb/XContent.hpp>
35 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
36 #include <com/sun/star/task/XInteractionHandler.hpp>
37 #include <com/sun/star/io/XStream.hpp>
38 #include <com/sun/star/io/XActiveDataSink.hpp>
39 #include <com/sun/star/io/XSeekable.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/lang/IllegalArgumentException.hpp>
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/ucb/InteractiveIOException.hpp>
44 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
45 #include <com/sun/star/ucb/CommandFailedException.hpp>
46 #include <com/sun/star/task/XInteractionAbort.hpp>
47 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
48 #include <com/sun/star/uri/XUriReference.hpp>
49 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
50 #include <com/sun/star/container/XNameAccess.hpp>
51 
52 #include <ucbhelper/interceptedinteraction.hxx>
53 #include <ucbhelper/content.hxx>
54 #include <ucbhelper/commandenvironment.hxx>
55 #include <ucbhelper/activedatasink.hxx>
56 #include <comphelper/processfactory.hxx>
57 #include <comphelper/configurationhelper.hxx>
58 
59 #include <rtl/ustrbuf.hxx>
60 
61 //_______________________________________________
62 // namespace
63 
64 namespace comphelper{
65 
66 namespace css = ::com::sun::star;
67 
68 //_______________________________________________
69 // definitions
70 
71 /*-----------------------------------------------
72     10.03.2004 07:35
73 -----------------------------------------------*/
74 const ::rtl::OUString& MediaDescriptor::PROP_ABORTED()
75 {
76     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Aborted"));
77     return sProp;
78 }
79 
80 const ::rtl::OUString& MediaDescriptor::PROP_ASTEMPLATE()
81 {
82     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("AsTemplate"));
83     return sProp;
84 }
85 
86 const ::rtl::OUString& MediaDescriptor::PROP_CHARACTERSET()
87 {
88     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("CharacterSet"));
89     return sProp;
90 }
91 
92 const ::rtl::OUString& MediaDescriptor::PROP_COMPONENTDATA()
93 {
94     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ComponentData"));
95     return sProp;
96 }
97 
98 const ::rtl::OUString& MediaDescriptor::PROP_DEEPDETECTION()
99 {
100     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DeepDetection"));
101     return sProp;
102 }
103 
104 const ::rtl::OUString& MediaDescriptor::PROP_DETECTSERVICE()
105 {
106     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DetectService"));
107     return sProp;
108 }
109 
110 const ::rtl::OUString& MediaDescriptor::PROP_DOCUMENTSERVICE()
111 {
112     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DocumentService"));
113     return sProp;
114 }
115 
116 const ::rtl::OUString& MediaDescriptor::PROP_ENCRYPTIONDATA()
117 {
118     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("EncryptionData"));
119     return sProp;
120 }
121 
122 const ::rtl::OUString& MediaDescriptor::PROP_EXTENSION()
123 {
124     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Extension"));
125     return sProp;
126 }
127 
128 const ::rtl::OUString& MediaDescriptor::PROP_FILENAME()
129 {
130     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FileName"));
131     return sProp;
132 }
133 
134 const ::rtl::OUString& MediaDescriptor::PROP_FILTERNAME()
135 {
136     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FilterName"));
137     return sProp;
138 }
139 
140 const ::rtl::OUString& MediaDescriptor::PROP_FILTEROPTIONS()
141 {
142     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FilterOptions"));
143     return sProp;
144 }
145 
146 const ::rtl::OUString& MediaDescriptor::PROP_FORMAT()
147 {
148     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Format"));
149     return sProp;
150 }
151 
152 const ::rtl::OUString& MediaDescriptor::PROP_FRAME()
153 {
154     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Frame"));
155     return sProp;
156 }
157 
158 const ::rtl::OUString& MediaDescriptor::PROP_FRAMENAME()
159 {
160     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FrameName"));
161     return sProp;
162 }
163 
164 const ::rtl::OUString& MediaDescriptor::PROP_HIDDEN()
165 {
166     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Hidden"));
167     return sProp;
168 }
169 
170 const ::rtl::OUString& MediaDescriptor::PROP_INPUTSTREAM()
171 {
172     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("InputStream"));
173     return sProp;
174 }
175 
176 const ::rtl::OUString& MediaDescriptor::PROP_INTERACTIONHANDLER()
177 {
178     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("InteractionHandler"));
179     return sProp;
180 }
181 
182 const ::rtl::OUString& MediaDescriptor::PROP_JUMPMARK()
183 {
184     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("JumpMark"));
185     return sProp;
186 }
187 
188 const ::rtl::OUString& MediaDescriptor::PROP_MACROEXECUTIONMODE()
189 {
190     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("MacroExecutionMode"));
191     return sProp;
192 }
193 
194 const ::rtl::OUString& MediaDescriptor::PROP_MEDIATYPE()
195 {
196     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
197     return sProp;
198 }
199 
200 const ::rtl::OUString& MediaDescriptor::PROP_MINIMIZED()
201 {
202     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Minimized"));
203     return sProp;
204 }
205 
206 const ::rtl::OUString& MediaDescriptor::PROP_NOAUTOSAVE()
207 {
208     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("NoAutoSave"));
209     return sProp;
210 }
211 
212 const ::rtl::OUString& MediaDescriptor::PROP_OPENNEWVIEW()
213 {
214     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("OpenNewView"));
215     return sProp;
216 }
217 
218 const ::rtl::OUString& MediaDescriptor::PROP_OUTPUTSTREAM()
219 {
220     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("OutputStream"));
221     return sProp;
222 }
223 
224 const ::rtl::OUString& MediaDescriptor::PROP_PATTERN()
225 {
226     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Pattern"));
227     return sProp;
228 }
229 
230 const ::rtl::OUString& MediaDescriptor::PROP_POSSIZE()
231 {
232     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("PosSize"));
233     return sProp;
234 }
235 
236 const ::rtl::OUString& MediaDescriptor::PROP_POSTDATA()
237 {
238     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("PostData"));
239     return sProp;
240 }
241 
242 const ::rtl::OUString& MediaDescriptor::PROP_POSTSTRING()
243 {
244     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("PostString"));
245     return sProp;
246 }
247 
248 const ::rtl::OUString& MediaDescriptor::PROP_PREVIEW()
249 {
250     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Preview"));
251     return sProp;
252 }
253 
254 const ::rtl::OUString& MediaDescriptor::PROP_READONLY()
255 {
256     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
257     return sProp;
258 }
259 
260 const ::rtl::OUString& MediaDescriptor::PROP_REFERRER()
261 {
262     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Referer"));
263     return sProp;
264 }
265 
266 const ::rtl::OUString& MediaDescriptor::PROP_SILENT()
267 {
268     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Silent"));
269     return sProp;
270 }
271 
272 const ::rtl::OUString& MediaDescriptor::PROP_STATUSINDICATOR()
273 {
274     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("StatusIndicator"));
275     return sProp;
276 }
277 
278 const ::rtl::OUString& MediaDescriptor::PROP_STREAM()
279 {
280     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Stream"));
281     return sProp;
282 }
283 
284 const ::rtl::OUString& MediaDescriptor::PROP_STREAMFOROUTPUT()
285 {
286     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("StreamForOutput"));
287     return sProp;
288 }
289 
290 const ::rtl::OUString& MediaDescriptor::PROP_TEMPLATENAME()
291 {
292     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("TemplateName"));
293     return sProp;
294 }
295 
296 const ::rtl::OUString& MediaDescriptor::PROP_TEMPLATEREGIONNAME()
297 {
298     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("TemplateRegionName"));
299     return sProp;
300 }
301 
302 const ::rtl::OUString& MediaDescriptor::PROP_TYPENAME()
303 {
304     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("TypeName"));
305     return sProp;
306 }
307 
308 const ::rtl::OUString& MediaDescriptor::PROP_UCBCONTENT()
309 {
310     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("UCBContent"));
311     return sProp;
312 }
313 
314 const ::rtl::OUString& MediaDescriptor::PROP_UPDATEDOCMODE()
315 {
316     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("UpdateDocMode"));
317     return sProp;
318 }
319 
320 const ::rtl::OUString& MediaDescriptor::PROP_URL()
321 {
322     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("URL"));
323     return sProp;
324 }
325 
326 const ::rtl::OUString& MediaDescriptor::PROP_VERSION()
327 {
328     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Version"));
329     return sProp;
330 }
331 
332 const ::rtl::OUString& MediaDescriptor::PROP_VIEWID()
333 {
334     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ViewId"));
335     return sProp;
336 }
337 
338 const ::rtl::OUString& MediaDescriptor::PROP_REPAIRPACKAGE()
339 {
340     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("RepairPackage"));
341     return sProp;
342 }
343 
344 const ::rtl::OUString& MediaDescriptor::PROP_DOCUMENTTITLE()
345 {
346     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle"));
347     return sProp;
348 }
349 
350 const ::rtl::OUString& MediaDescriptor::PROP_MODEL()
351 {
352     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Model"));
353     return sProp;
354 }
355 
356 const ::rtl::OUString& MediaDescriptor::PROP_PASSWORD()
357 {
358     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Password"));
359     return sProp;
360 }
361 
362 const ::rtl::OUString& MediaDescriptor::PROP_TITLE()
363 {
364     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Title"));
365     return sProp;
366 }
367 
368 const ::rtl::OUString& MediaDescriptor::PROP_SALVAGEDFILE()
369 {
370     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("SalvagedFile"));
371     return sProp;
372 }
373 
374 const ::rtl::OUString& MediaDescriptor::PROP_VIEWONLY()
375 {
376     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ViewOnly"));
377     return sProp;
378 }
379 
380 const ::rtl::OUString& MediaDescriptor::PROP_DOCUMENTBASEURL()
381 {
382     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DocumentBaseURL"));
383     return sProp;
384 }
385 
386 const ::rtl::OUString& MediaDescriptor::PROP_VIEWCONTROLLERNAME()
387 {
388     static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ViewControllerName"));
389     return sProp;
390 }
391 /*-----------------------------------------------
392     10.03.2004 08:09
393 -----------------------------------------------*/
394 MediaDescriptor::MediaDescriptor()
395     : SequenceAsHashMap()
396 {
397 }
398 
399 /*-----------------------------------------------
400     10.03.2004 08:09
401 -----------------------------------------------*/
402 MediaDescriptor::MediaDescriptor(const css::uno::Any& aSource)
403     : SequenceAsHashMap(aSource)
404 {
405 }
406 
407 /*-----------------------------------------------
408     10.03.2004 08:09
409 -----------------------------------------------*/
410 MediaDescriptor::MediaDescriptor(const css::uno::Sequence< css::beans::PropertyValue >& lSource)
411     : SequenceAsHashMap(lSource)
412 {
413 }
414 
415 /*-----------------------------------------------
416     10.03.2004 08:09
417 -----------------------------------------------*/
418 MediaDescriptor::MediaDescriptor(const css::uno::Sequence< css::beans::NamedValue >& lSource)
419     : SequenceAsHashMap(lSource)
420 {
421 }
422 
423 /*-----------------------------------------------
424     18.11.2004 13:37
425 -----------------------------------------------*/
426 sal_Bool MediaDescriptor::isStreamReadOnly() const
427 {
428     static ::rtl::OUString CONTENTSCHEME_FILE     = ::rtl::OUString::createFromAscii("file");
429     static ::rtl::OUString CONTENTPROP_ISREADONLY = ::rtl::OUString::createFromAscii("IsReadOnly");
430     static sal_Bool        READONLY_FALLBACK      = sal_False;
431 
432     sal_Bool bReadOnly = READONLY_FALLBACK;
433 
434     // check for explicit readonly state
435     const_iterator pIt = find(MediaDescriptor::PROP_READONLY());
436     if (pIt != end())
437     {
438 		pIt->second >>= bReadOnly;
439         return bReadOnly;
440     }
441 
442     // streams based on post data are readonly by definition
443     pIt = find(MediaDescriptor::PROP_POSTDATA());
444     if (pIt != end())
445         return sal_True;
446 
447     // A XStream capsulate XInputStream and XOutputStream ...
448     // If it exists - the file must be open in read/write mode!
449     pIt = find(MediaDescriptor::PROP_STREAM());
450     if (pIt != end())
451         return sal_False;
452 
453     // Only file system content provider is able to provide XStream
454     // so for this content impossibility to create XStream triggers
455     // switch to readonly mode.
456     try
457     {
458         css::uno::Reference< css::ucb::XContent > xContent = getUnpackedValueOrDefault(MediaDescriptor::PROP_UCBCONTENT(), css::uno::Reference< css::ucb::XContent >());
459         if (xContent.is())
460         {
461             css::uno::Reference< css::ucb::XContentIdentifier > xId(xContent->getIdentifier(), css::uno::UNO_QUERY);
462             ::rtl::OUString aScheme;
463             if (xId.is())
464                 aScheme = xId->getContentProviderScheme();
465 
466             if (aScheme.equalsIgnoreAsciiCase(CONTENTSCHEME_FILE))
467                 bReadOnly = sal_True;
468             else
469             {
470                 ::ucbhelper::Content aContent(xContent, css::uno::Reference< css::ucb::XCommandEnvironment >());
471                 aContent.getPropertyValue(CONTENTPROP_ISREADONLY) >>= bReadOnly;
472             }
473         }
474     }
475     catch(const css::uno::RuntimeException& exRun)
476         { throw exRun; }
477     catch(const css::uno::Exception&)
478         {}
479 
480     return bReadOnly;
481 }
482 
483 // ----------------------------------------------------------------------------
484 
485 css::uno::Any MediaDescriptor::getComponentDataEntry( const ::rtl::OUString& rName ) const
486 {
487     css::uno::Any aEntry;
488     SequenceAsHashMap::const_iterator aPropertyIter = find( PROP_COMPONENTDATA() );
489     if( aPropertyIter != end() )
490         return NamedValueCollection( aPropertyIter->second ).get( rName );
491     return css::uno::Any();
492 }
493 
494 void MediaDescriptor::setComponentDataEntry( const ::rtl::OUString& rName, const css::uno::Any& rValue )
495 {
496     if( rValue.hasValue() )
497     {
498         // get or create the 'ComponentData' property entry
499         css::uno::Any& rCompDataAny = operator[]( PROP_COMPONENTDATA() );
500         // insert the value (retain sequence type, create NamedValue elements by default)
501         bool bHasNamedValues = !rCompDataAny.hasValue() || rCompDataAny.has< css::uno::Sequence< css::beans::NamedValue > >();
502         bool bHasPropValues = rCompDataAny.has< css::uno::Sequence< css::beans::PropertyValue > >();
503         OSL_ENSURE( bHasNamedValues || bHasPropValues, "MediaDescriptor::setComponentDataEntry - incompatible 'ComponentData' property in media descriptor" );
504         if( bHasNamedValues || bHasPropValues )
505         {
506             // insert or overwrite the passed value
507             SequenceAsHashMap aCompDataMap( rCompDataAny );
508             aCompDataMap[ rName ] = rValue;
509             // write back the sequence (restore sequence with correct element type)
510             rCompDataAny = aCompDataMap.getAsConstAny( bHasPropValues );
511         }
512     }
513     else
514     {
515         // if an empty Any is passed, clear the entry
516         clearComponentDataEntry( rName );
517     }
518 }
519 
520 void MediaDescriptor::clearComponentDataEntry( const ::rtl::OUString& rName )
521 {
522     SequenceAsHashMap::iterator aPropertyIter = find( PROP_COMPONENTDATA() );
523     if( aPropertyIter != end() )
524     {
525         css::uno::Any& rCompDataAny = aPropertyIter->second;
526         bool bHasNamedValues = rCompDataAny.has< css::uno::Sequence< css::beans::NamedValue > >();
527         bool bHasPropValues = rCompDataAny.has< css::uno::Sequence< css::beans::PropertyValue > >();
528         OSL_ENSURE( bHasNamedValues || bHasPropValues, "MediaDescriptor::clearComponentDataEntry - incompatible 'ComponentData' property in media descriptor" );
529         if( bHasNamedValues || bHasPropValues )
530         {
531             // remove the value with the passed name
532             SequenceAsHashMap aCompDataMap( rCompDataAny );
533             aCompDataMap.erase( rName );
534             // write back the sequence, or remove it completely if it is empty
535             if( aCompDataMap.empty() )
536                 erase( aPropertyIter );
537             else
538                 rCompDataAny = aCompDataMap.getAsConstAny( bHasPropValues );
539         }
540     }
541 }
542 
543 /*-----------------------------------------------
544     10.03.2004 09:02
545 -----------------------------------------------*/
546 sal_Bool MediaDescriptor::addInputStream()
547 {
548     return impl_addInputStream( sal_True );
549 }
550 
551 /*-----------------------------------------------*/
552 sal_Bool MediaDescriptor::addInputStreamOwnLock()
553 {
554     // Own lock file implementation
555 
556     sal_Bool bUseLock = sal_True; // the system file locking is used per default
557     try
558     {
559 
560 		css::uno::Reference< css::uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
561 							::comphelper::getProcessServiceFactory(),
562 							::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
563 							::comphelper::ConfigurationHelper::E_STANDARD );
564 		if ( !xCommonConfig.is() )
565 			throw css::uno::RuntimeException();
566 
567         ::comphelper::ConfigurationHelper::readRelativeKey(
568                 xCommonConfig,
569                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
570                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentSystemFileLocking" ) ) ) >>= bUseLock;
571     }
572     catch( const css::uno::Exception& )
573     {
574     }
575 
576     return impl_addInputStream( bUseLock );
577 }
578 
579 /*-----------------------------------------------*/
580 sal_Bool MediaDescriptor::impl_addInputStream( sal_Bool bLockFile )
581 {
582     // check for an already existing stream item first
583     const_iterator pIt = find(MediaDescriptor::PROP_INPUTSTREAM());
584     if (pIt != end())
585         return sal_True;
586 
587 	try
588 	{
589 		// No stream available - create a new one
590 		// a) data comes as PostData ...
591 		pIt = find(MediaDescriptor::PROP_POSTDATA());
592 		if (pIt != end())
593 		{
594 			const css::uno::Any& rPostData = pIt->second;
595 			css::uno::Reference< css::io::XInputStream > xPostData;
596 			rPostData >>= xPostData;
597 
598 			return impl_openStreamWithPostData( xPostData );
599 		}
600 
601 		// b) ... or we must get it from the given URL
602 		::rtl::OUString sURL = getUnpackedValueOrDefault(MediaDescriptor::PROP_URL(), ::rtl::OUString());
603 		if (!sURL.getLength())
604 			throw css::uno::Exception(
605 					::rtl::OUString::createFromAscii("Found no URL."),
606 					css::uno::Reference< css::uno::XInterface >());
607 
608         // Parse URL! Only the main part has to be used further. E.g. a jumpmark can make trouble
609         ::rtl::OUString sNormalizedURL = impl_normalizeURL( sURL );
610 		return impl_openStreamWithURL( sNormalizedURL, bLockFile );
611 	}
612 #if OSL_DEBUG_LEVEL>0
613 	catch(const css::uno::Exception& ex)
614 	{
615 		::rtl::OUStringBuffer sMsg(256);
616 		sMsg.appendAscii("Invalid MediaDescriptor detected:\n");
617 		sMsg.append		(ex.Message							  );
618 		OSL_ENSURE(sal_False, ::rtl::OUStringToOString(sMsg.makeStringAndClear(), RTL_TEXTENCODING_UTF8).getStr());
619 	}
620 #else
621 	catch(const css::uno::Exception&)
622 		{}
623 #endif
624 
625 	return sal_False;
626 }
627 
628 /*-----------------------------------------------
629     25.03.2004 12:38
630 -----------------------------------------------*/
631 sal_Bool MediaDescriptor::impl_openStreamWithPostData( const css::uno::Reference< css::io::XInputStream >& _rxPostData )
632     throw(::com::sun::star::uno::RuntimeException)
633 {
634 	if ( !_rxPostData.is() )
635 		throw css::lang::IllegalArgumentException(
636 				::rtl::OUString::createFromAscii("Found invalid PostData."),
637 				css::uno::Reference< css::uno::XInterface >(), 1);
638 
639 	// PostData can't be used in read/write mode!
640 	(*this)[MediaDescriptor::PROP_READONLY()] <<= sal_True;
641 
642     // prepare the environment
643 	css::uno::Reference< css::task::XInteractionHandler > xInteraction = getUnpackedValueOrDefault(
644 		MediaDescriptor::PROP_INTERACTIONHANDLER(),
645 		css::uno::Reference< css::task::XInteractionHandler >());
646 	css::uno::Reference< css::ucb::XProgressHandler > xProgress;
647     ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
648 	css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
649 
650     // media type
651 	::rtl::OUString sMediaType = getUnpackedValueOrDefault(MediaDescriptor::PROP_MEDIATYPE(), ::rtl::OUString());
652     if (!sMediaType.getLength())
653     {
654         sMediaType = ::rtl::OUString::createFromAscii("application/x-www-form-urlencoded");
655         (*this)[MediaDescriptor::PROP_MEDIATYPE()] <<= sMediaType;
656     }
657 
658     // url
659 	::rtl::OUString sURL( getUnpackedValueOrDefault( PROP_URL(), ::rtl::OUString() ) );
660 
661     css::uno::Reference< css::io::XInputStream > xResultStream;
662     try
663     {
664         // seek PostData stream to the beginning
665         css::uno::Reference< css::io::XSeekable > xSeek( _rxPostData, css::uno::UNO_QUERY );
666         if ( xSeek.is() )
667             xSeek->seek( 0 );
668 
669         // a content for the URL
670         ::ucbhelper::Content aContent( sURL, xCommandEnv );
671 
672         // use post command
673         css::ucb::PostCommandArgument2 aPostArgument;
674         aPostArgument.Source = _rxPostData;
675         css::uno::Reference< css::io::XActiveDataSink > xSink( new ucbhelper::ActiveDataSink );
676         aPostArgument.Sink = xSink;
677         aPostArgument.MediaType = sMediaType;
678         aPostArgument.Referer = getUnpackedValueOrDefault( PROP_REFERRER(), ::rtl::OUString() );
679 
680         ::rtl::OUString sCommandName( RTL_CONSTASCII_USTRINGPARAM( "post" ) );
681         aContent.executeCommand( sCommandName, css::uno::makeAny( aPostArgument ) );
682 
683         // get result
684         xResultStream = xSink->getInputStream();
685     }
686     catch( const css::uno::Exception& )
687     {
688     }
689 
690     // success?
691     if ( !xResultStream.is() )
692     {
693         OSL_ENSURE( false, "no valid reply to the HTTP-Post" );
694         return sal_False;
695     }
696 
697     (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xResultStream;
698     return sal_True;
699 }
700 
701 /*-----------------------------------------------*/
702 
703 /*-----------------------------------------------
704     25.03.2004 12:29
705 -----------------------------------------------*/
706 sal_Bool MediaDescriptor::impl_openStreamWithURL( const ::rtl::OUString& sURL, sal_Bool bLockFile )
707     throw(::com::sun::star::uno::RuntimeException)
708 {
709     // prepare the environment
710 	css::uno::Reference< css::task::XInteractionHandler > xOrgInteraction = getUnpackedValueOrDefault(
711 		MediaDescriptor::PROP_INTERACTIONHANDLER(),
712 		css::uno::Reference< css::task::XInteractionHandler >());
713 
714     StillReadWriteInteraction* pInteraction = new StillReadWriteInteraction(xOrgInteraction);
715 	css::uno::Reference< css::task::XInteractionHandler > xInteraction(static_cast< css::task::XInteractionHandler* >(pInteraction), css::uno::UNO_QUERY);
716 
717 	css::uno::Reference< css::ucb::XProgressHandler > xProgress;
718     ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
719 	css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
720 
721     // try to create the content
722 	// no content -> no stream => return immediatly with FALSE
723 	::ucbhelper::Content                      aContent;
724     css::uno::Reference< css::ucb::XContent > xContent;
725     try
726     {
727 		aContent = ::ucbhelper::Content(sURL, xCommandEnv);
728         xContent = aContent.get();
729     }
730     catch(const css::uno::RuntimeException&)
731         { throw; }
732     catch(const css::ucb::ContentCreationException&)
733         { return sal_False; } // TODO error handling
734 	catch(const css::uno::Exception&)
735         { return sal_False; } // TODO error handling
736 
737     // try to open the file in read/write mode
738     // (if its allowed to do so).
739     // But handle errors in a "hidden mode". Because
740     // we try it readonly later - if read/write isnt an option.
741     css::uno::Reference< css::io::XStream >      xStream     ;
742     css::uno::Reference< css::io::XInputStream > xInputStream;
743 
744     sal_Bool bReadOnly = sal_False;
745 	sal_Bool bModeRequestedExplicitly = sal_False;
746     const_iterator pIt = find(MediaDescriptor::PROP_READONLY());
747     if (pIt != end())
748 	{
749 		pIt->second >>= bReadOnly;
750 		bModeRequestedExplicitly = sal_True;
751 	}
752 
753     if ( !bReadOnly && bLockFile )
754     {
755         try
756         {
757             // TODO: use "special" still interaction to supress error messages
758             xStream = aContent.openWriteableStream();
759             if (xStream.is())
760                 xInputStream = xStream->getInputStream();
761         }
762         catch(const css::uno::RuntimeException&)
763             { throw; }
764         catch(const css::uno::Exception&)
765             {
766                 // ignore exception, if reason was problem reasoned on
767                 // open it in WRITEABLE mode! Then we try it READONLY
768                 // later a second time.
769                 // All other errors must be handled as real error an
770                 // break this method.
771                 if (!pInteraction->wasWriteError() || bModeRequestedExplicitly)
772                     return sal_False;
773                 xStream.clear();
774                 xInputStream.clear();
775             }
776     }
777 
778     // If opening of the stream in read/write mode wasnt allowed
779     // or failed by an error - we must try it in readonly mode.
780     if (!xInputStream.is())
781     {
782         rtl::OUString aScheme;
783 
784 		try
785 		{
786 			css::uno::Reference< css::ucb::XContentIdentifier > xContId(
787 				aContent.get().is() ? aContent.get()->getIdentifier() : 0 );
788 
789 			if ( xContId.is() )
790 				aScheme = xContId->getContentProviderScheme();
791 
792 			// Only file system content provider is able to provide XStream
793 			// so for this content impossibility to create XStream triggers
794 			// switch to readonly mode in case of opening with locking on
795     		if( bLockFile && aScheme.equalsIgnoreAsciiCaseAscii( "file" ) )
796         		bReadOnly = sal_True;
797 			else
798             {
799                 sal_Bool bRequestReadOnly = bReadOnly;
800 				aContent.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bReadOnly;
801                 if ( bReadOnly && !bRequestReadOnly && bModeRequestedExplicitly )
802                         return sal_False; // the document is explicitly requested with WRITEABLE mode
803             }
804 		}
805         catch(const css::uno::RuntimeException&)
806             { throw; }
807         catch(const css::uno::Exception&)
808             { /* no error handling if IsReadOnly property does not exist for UCP */ }
809 
810 		if ( bReadOnly )
811        		(*this)[MediaDescriptor::PROP_READONLY()] <<= bReadOnly;
812 
813         pInteraction->resetInterceptions();
814         pInteraction->resetErrorStates();
815         try
816         {
817             // all the contents except file-URLs should be opened as usual
818             if ( bLockFile || !aScheme.equalsIgnoreAsciiCaseAscii( "file" ) )
819                 xInputStream = aContent.openStream();
820             else
821                 xInputStream = aContent.openStreamNoLock();
822         }
823         catch(const css::uno::RuntimeException&)
824             { throw; }
825         catch(const css::uno::Exception&)
826             { return sal_False; }
827     }
828 
829     // add streams to the descriptor
830     if (xContent.is())
831         (*this)[MediaDescriptor::PROP_UCBCONTENT()] <<= xContent;
832     if (xStream.is())
833         (*this)[MediaDescriptor::PROP_STREAM()] <<= xStream;
834     if (xInputStream.is())
835         (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xInputStream;
836 
837     // At least we need an input stream. The r/w stream is optional ...
838     return xInputStream.is();
839 }
840 
841 /*-----------------------------------------------
842     10.09.2004 10:51
843 -----------------------------------------------*/
844 ::rtl::OUString MediaDescriptor::impl_normalizeURL(const ::rtl::OUString& sURL)
845 {
846     /* Remove Jumpmarks (fragments) of an URL only here.
847        They are not part of any URL and as a result may be
848        no ucb content can be created then.
849        On the other side arguments must exists ... because
850        they are part of an URL.
851 
852        Do not use the URLTransformer service here. Because
853        it parses the URL in another way. It's main part isnt enough
854        and it's complete part contains the jumpmark (fragment) parameter ...
855     */
856     static ::rtl::OUString SERVICENAME_URIREFERENCEFACTORY = ::rtl::OUString::createFromAscii("com.sun.star.uri.UriReferenceFactory");
857 
858     try
859     {
860         css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR      = ::comphelper::getProcessServiceFactory();
861         css::uno::Reference< css::uri::XUriReferenceFactory >  xUriFactory(xSMGR->createInstance(SERVICENAME_URIREFERENCEFACTORY), css::uno::UNO_QUERY_THROW);
862         css::uno::Reference< css::uri::XUriReference >         xUriRef    = xUriFactory->parse(sURL);
863         if (xUriRef.is())
864         {
865             xUriRef->clearFragment();
866             return xUriRef->getUriReference();
867         }
868     }
869     catch(const css::uno::RuntimeException& exRun)
870         { throw exRun; }
871     catch(const css::uno::Exception&)
872         {}
873 
874     // If an error ocurred ... return the original URL.
875     // It's a try .-)
876     return sURL;
877 }
878 
879 } // namespace comphelper
880 
881