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