xref: /trunk/main/comphelper/source/misc/mediadescriptor.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 {
635     if ( !_rxPostData.is() )
636         throw css::lang::IllegalArgumentException(
637                 ::rtl::OUString::createFromAscii("Found invalid PostData."),
638                 css::uno::Reference< css::uno::XInterface >(), 1);
639 
640     // PostData can't be used in read/write mode!
641     (*this)[MediaDescriptor::PROP_READONLY()] <<= sal_True;
642 
643     // prepare the environment
644     css::uno::Reference< css::task::XInteractionHandler > xInteraction = getUnpackedValueOrDefault(
645         MediaDescriptor::PROP_INTERACTIONHANDLER(),
646         css::uno::Reference< css::task::XInteractionHandler >());
647     css::uno::Reference< css::ucb::XProgressHandler > xProgress;
648     ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
649     css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
650 
651     // media type
652     ::rtl::OUString sMediaType = getUnpackedValueOrDefault(MediaDescriptor::PROP_MEDIATYPE(), ::rtl::OUString());
653     if ( sMediaType.isEmpty() )
654     {
655         sMediaType = ::rtl::OUString::createFromAscii("application/x-www-form-urlencoded");
656         (*this)[MediaDescriptor::PROP_MEDIATYPE()] <<= sMediaType;
657     }
658 
659     // url
660     ::rtl::OUString sURL( getUnpackedValueOrDefault( PROP_URL(), ::rtl::OUString() ) );
661 
662     css::uno::Reference< css::io::XInputStream > xResultStream;
663     try
664     {
665         // seek PostData stream to the beginning
666         css::uno::Reference< css::io::XSeekable > xSeek( _rxPostData, css::uno::UNO_QUERY );
667         if ( xSeek.is() )
668             xSeek->seek( 0 );
669 
670         // a content for the URL
671         ::ucbhelper::Content aContent( sURL, xCommandEnv );
672 
673         // use post command
674         css::ucb::PostCommandArgument2 aPostArgument;
675         aPostArgument.Source = _rxPostData;
676         css::uno::Reference< css::io::XActiveDataSink > xSink( new ucbhelper::ActiveDataSink );
677         aPostArgument.Sink = xSink;
678         aPostArgument.MediaType = sMediaType;
679         aPostArgument.Referer = getUnpackedValueOrDefault( PROP_REFERRER(), ::rtl::OUString() );
680 
681         ::rtl::OUString sCommandName( RTL_CONSTASCII_USTRINGPARAM( "post" ) );
682         aContent.executeCommand( sCommandName, css::uno::makeAny( aPostArgument ) );
683 
684         // get result
685         xResultStream = xSink->getInputStream();
686     }
687     catch( const css::uno::Exception& )
688     {
689     }
690 
691     // success?
692     if ( !xResultStream.is() )
693     {
694         OSL_ENSURE( false, "no valid reply to the HTTP-Post" );
695         return sal_False;
696     }
697 
698     (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xResultStream;
699     return sal_True;
700 }
701 
702 /*-----------------------------------------------*/
703 
704 /*-----------------------------------------------
705     25.03.2004 12:29
706 -----------------------------------------------*/
impl_openStreamWithURL(const::rtl::OUString & sURL,sal_Bool bLockFile)707 sal_Bool MediaDescriptor::impl_openStreamWithURL( const ::rtl::OUString& sURL, sal_Bool bLockFile )
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     css::uno::Reference< css::task::XInteractionHandler > xAuthenticationInteraction = getUnpackedValueOrDefault(
714         MediaDescriptor::PROP_AUTHENTICATIONHANDLER(),
715         css::uno::Reference< css::task::XInteractionHandler >());
716 
717     StillReadWriteInteraction* pInteraction = new StillReadWriteInteraction(xOrgInteraction, xAuthenticationInteraction);
718     css::uno::Reference< css::task::XInteractionHandler > xInteraction(static_cast< css::task::XInteractionHandler* >(pInteraction), css::uno::UNO_QUERY);
719 
720     css::uno::Reference< css::ucb::XProgressHandler > xProgress;
721     ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
722     css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
723 
724     // try to create the content
725     // no content -> no stream => return immediately with FALSE
726     ::ucbhelper::Content                        aContent;
727     css::uno::Reference< css::ucb::XContent >   xContent;
728     try
729     {
730         aContent = ::ucbhelper::Content(sURL, xCommandEnv);
731         xContent = aContent.get();
732     }
733     catch(const css::uno::RuntimeException&)
734         { throw; }
735     catch(const css::ucb::ContentCreationException&)
736         { return sal_False; } // TODO error handling
737     catch(const css::uno::Exception&)
738         { return sal_False; } // TODO error handling
739 
740     // try to open the file in read/write mode
741     // (if its allowed to do so).
742     // But handle errors in a "hidden mode". Because
743     // we try it readonly later - if read/write isn't an option.
744     css::uno::Reference< css::io::XStream >         xStream     ;
745     css::uno::Reference< css::io::XInputStream >    xInputStream;
746 
747     sal_Bool bReadOnly = sal_False;
748     //bModeRequestedExplicitly means 'read/write mode requested explicitly'
749     sal_Bool bModeRequestedExplicitly = sal_False;
750     // MediaDescriptor::PROP_READONLY is present only if the mediadescriptor was used at least one time
751     // that is, it exists if the file was changed from readonly mode to read/write using the GUI interface
752     const_iterator pIt = find(MediaDescriptor::PROP_READONLY());
753     if (pIt != end())
754     {
755         pIt->second >>= bReadOnly;
756         // TODO: thinking a different way: we enable the switch to r/o even though the file
757         // 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
758         // according to GUI request) instead of returning an error
759         bModeRequestedExplicitly = sal_True;
760     }
761 
762     if ( !bReadOnly && bLockFile )
763     {
764         try
765         {
766             // TODO: use "special" still interaction to suppress error messages
767             xStream = aContent.openWriteableStream();
768             if (xStream.is())
769                 xInputStream = xStream->getInputStream();
770         }
771         catch(const css::uno::RuntimeException&)
772             { throw; }
773         catch(const css::uno::Exception&)
774             {
775                 // ignore exception, if reason was problem reasoned on
776                 // open it in WRITEABLE mode! Then we try it READONLY
777                 // later a second time.
778                 // All other errors must be handled as real error and
779                 // break this method.
780                 if (!pInteraction->wasWriteError() || bModeRequestedExplicitly)
781                 {
782                     //-> i126305
783                     // If the protocol is webdav, then we need to treat the stream as readonly, even if the
784                     // operation was requested as read/write explicitly (the WebDAV UCB implementation is monodirectional
785                     // read or write not both at the same time).
786                     rtl::OUString aScheme;
787                     css::uno::Reference< css::ucb::XContentIdentifier > xContId(
788                         aContent.get().is() ? aContent.get()->getIdentifier() : 0 );
789                     if ( xContId.is() )
790                         aScheme = xContId->getContentProviderScheme();
791                     if(!aScheme.equalsIgnoreAsciiCaseAscii( "http" ) && !aScheme.equalsIgnoreAsciiCaseAscii( "https" ))
792                         return sal_False;
793                     //<- i126305
794                 }
795 
796                 xStream.clear();
797                 xInputStream.clear();
798             }
799     }
800 
801     // If opening of the stream in read/write mode wasn't allowed
802     // or failed by an error - we must try it in readonly mode.
803     if (!xInputStream.is())
804     {
805         rtl::OUString aScheme;
806 
807         try
808         {
809             css::uno::Reference< css::ucb::XContentIdentifier > xContId(
810                 aContent.get().is() ? aContent.get()->getIdentifier() : 0 );
811 
812             if ( xContId.is() )
813                 aScheme = xContId->getContentProviderScheme();
814 
815             // Only file system content provider is able to provide XStream
816             // so for this content impossibility to create XStream triggers
817             // switch to readonly mode in case of opening with locking on
818             if( bLockFile && aScheme.equalsIgnoreAsciiCaseAscii( "file" ) )
819                 bReadOnly = sal_True;
820             else
821             {
822                 sal_Bool bRequestReadOnly = bReadOnly;
823                 aContent.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bReadOnly;
824                 if ( bReadOnly && !bRequestReadOnly && bModeRequestedExplicitly )
825                         return sal_False; // the document is explicitly requested with WRITEABLE mode
826             }
827         }
828         catch(const css::uno::RuntimeException&)
829             { throw; }
830         catch(const css::uno::Exception&)
831             { /* no error handling if IsReadOnly property does not exist for UCP */ }
832 
833         if ( bReadOnly )
834             (*this)[MediaDescriptor::PROP_READONLY()] <<= bReadOnly;
835 
836         pInteraction->resetInterceptions();
837         pInteraction->resetErrorStates();
838         try
839         {
840             // all the contents except file-URLs should be opened as usual
841             if ( bLockFile || !aScheme.equalsIgnoreAsciiCaseAscii( "file" ) )
842                 xInputStream = aContent.openStream();
843             else
844                 xInputStream = aContent.openStreamNoLock();
845         }
846         catch(const css::uno::RuntimeException&)
847             { throw; }
848         catch(const css::uno::Exception&)
849             { return sal_False; }
850     }
851 
852     // add streams to the descriptor
853     if (xContent.is())
854         (*this)[MediaDescriptor::PROP_UCBCONTENT()] <<= xContent;
855     if (xStream.is())
856         (*this)[MediaDescriptor::PROP_STREAM()] <<= xStream;
857     if (xInputStream.is())
858         (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xInputStream;
859 
860     // At least we need an input stream. The r/w stream is optional ...
861     return xInputStream.is();
862 }
863 
864 /*-----------------------------------------------
865     10.09.2004 10:51
866 -----------------------------------------------*/
impl_normalizeURL(const::rtl::OUString & sURL)867 ::rtl::OUString MediaDescriptor::impl_normalizeURL(const ::rtl::OUString& sURL)
868 {
869     /* Remove Jumpmarks (fragments) of an URL only here.
870        They are not part of any URL and as a result may be
871        no ucb content can be created then.
872        On the other side arguments must exists ... because
873        they are part of an URL.
874 
875        Do not use the URLTransformer service here. Because
876        it parses the URL in another way. It's main part isn't enough
877        and it's complete part contains the jumpmark (fragment) parameter ...
878     */
879     static ::rtl::OUString SERVICENAME_URIREFERENCEFACTORY = ::rtl::OUString::createFromAscii("com.sun.star.uri.UriReferenceFactory");
880 
881     try
882     {
883         css::uno::Reference< css::lang::XMultiServiceFactory >  xSMGR   = ::comphelper::getProcessServiceFactory();
884         css::uno::Reference< css::uri::XUriReferenceFactory >   xUriFactory(xSMGR->createInstance(SERVICENAME_URIREFERENCEFACTORY), css::uno::UNO_QUERY_THROW);
885         css::uno::Reference< css::uri::XUriReference >          xUriRef = xUriFactory->parse(sURL);
886         if (xUriRef.is())
887         {
888             xUriRef->clearFragment();
889             return xUriRef->getUriReference();
890         }
891     }
892     catch(const css::uno::RuntimeException& exRun)
893         { throw exRun; }
894     catch(const css::uno::Exception&)
895         {}
896 
897     // If an error occurred ... return the original URL.
898     // It's a try .-)
899     return sURL;
900 }
901 
902 } // namespace comphelper
903