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 immediately 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 isn't 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 suppress 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 wasn't 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 isn't 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 occurred ... return the original URL.
900 	// It's a try .-)
901 	return sURL;
902 }
903 
904 } // namespace comphelper
905