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