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