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