Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/mediadescriptor.hxx>
21 : #include <comphelper/namedvaluecollection.hxx>
22 : #include <comphelper/stillreadwriteinteraction.hxx>
23 :
24 : #include <com/sun/star/ucb/XContent.hpp>
25 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
26 : #include <com/sun/star/task/XInteractionHandler.hpp>
27 : #include <com/sun/star/io/XStream.hpp>
28 : #include <com/sun/star/io/XActiveDataSink.hpp>
29 : #include <com/sun/star/io/XSeekable.hpp>
30 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
32 : #include <com/sun/star/util/XURLTransformer.hpp>
33 : #include <com/sun/star/ucb/InteractiveIOException.hpp>
34 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
35 : #include <com/sun/star/ucb/CommandFailedException.hpp>
36 : #include <com/sun/star/task/XInteractionAbort.hpp>
37 : #include <com/sun/star/uri/UriReferenceFactory.hpp>
38 : #include <com/sun/star/uri/XUriReference.hpp>
39 : #include <com/sun/star/ucb/PostCommandArgument2.hpp>
40 : #include <com/sun/star/container/XNameAccess.hpp>
41 : #include <officecfg/Office/Common.hxx>
42 : #include <ucbhelper/interceptedinteraction.hxx>
43 : #include <ucbhelper/content.hxx>
44 : #include <ucbhelper/commandenvironment.hxx>
45 : #include <ucbhelper/activedatasink.hxx>
46 : #include <comphelper/processfactory.hxx>
47 :
48 : namespace comphelper{
49 :
50 236 : const OUString& MediaDescriptor::PROP_ABORTED()
51 : {
52 236 : static const OUString sProp("Aborted");
53 236 : return sProp;
54 : }
55 :
56 918 : const OUString& MediaDescriptor::PROP_ASTEMPLATE()
57 : {
58 918 : static const OUString sProp("AsTemplate");
59 918 : return sProp;
60 : }
61 :
62 1 : const OUString& MediaDescriptor::PROP_COMPONENTDATA()
63 : {
64 1 : static const OUString sProp("ComponentData");
65 1 : return sProp;
66 : }
67 :
68 2209 : const OUString& MediaDescriptor::PROP_DOCUMENTSERVICE()
69 : {
70 2209 : static const OUString sProp("DocumentService");
71 2209 : return sProp;
72 : }
73 :
74 0 : const OUString& MediaDescriptor::PROP_ENCRYPTIONDATA()
75 : {
76 0 : static const OUString sProp("EncryptionData");
77 0 : return sProp;
78 : }
79 :
80 1108 : const OUString& MediaDescriptor::PROP_FILENAME()
81 : {
82 1108 : static const OUString sProp("FileName");
83 1108 : return sProp;
84 : }
85 :
86 6305 : const OUString& MediaDescriptor::PROP_FILTERNAME()
87 : {
88 6305 : static const OUString sProp("FilterName");
89 6305 : return sProp;
90 : }
91 :
92 0 : const OUString& MediaDescriptor::PROP_FILTERPROVIDER()
93 : {
94 0 : static const OUString aProp("FilterProvider");
95 0 : return aProp;
96 : }
97 :
98 0 : const OUString& MediaDescriptor::PROP_FILTEROPTIONS()
99 : {
100 0 : static const OUString sProp("FilterOptions");
101 0 : return sProp;
102 : }
103 :
104 352 : const OUString& MediaDescriptor::PROP_FRAME()
105 : {
106 352 : static const OUString sProp("Frame");
107 352 : return sProp;
108 : }
109 :
110 1108 : const OUString& MediaDescriptor::PROP_FRAMENAME()
111 : {
112 1108 : static const OUString sProp("FrameName");
113 1108 : return sProp;
114 : }
115 :
116 2664 : const OUString& MediaDescriptor::PROP_HIDDEN()
117 : {
118 2664 : static const OUString sProp("Hidden");
119 2664 : return sProp;
120 : }
121 :
122 22843 : const OUString& MediaDescriptor::PROP_INPUTSTREAM()
123 : {
124 22843 : static const OUString sProp("InputStream");
125 22843 : return sProp;
126 : }
127 :
128 4352 : const OUString& MediaDescriptor::PROP_INTERACTIONHANDLER()
129 : {
130 4352 : static const OUString sProp("InteractionHandler");
131 4352 : return sProp;
132 : }
133 :
134 0 : const OUString& MediaDescriptor::PROP_JUMPMARK()
135 : {
136 0 : static const OUString sProp("JumpMark");
137 0 : return sProp;
138 : }
139 :
140 1777 : const OUString& MediaDescriptor::PROP_MACROEXECUTIONMODE()
141 : {
142 1777 : static const OUString sProp("MacroExecutionMode");
143 1777 : return sProp;
144 : }
145 :
146 16 : const OUString& MediaDescriptor::PROP_MEDIATYPE()
147 : {
148 16 : static const OUString sProp("MediaType");
149 16 : return sProp;
150 : }
151 :
152 2216 : const OUString& MediaDescriptor::PROP_MINIMIZED()
153 : {
154 2216 : static const OUString sProp("Minimized");
155 2216 : return sProp;
156 : }
157 :
158 0 : const OUString& MediaDescriptor::PROP_NOAUTOSAVE()
159 : {
160 0 : static const OUString sProp("NoAutoSave");
161 0 : return sProp;
162 : }
163 :
164 874 : const OUString& MediaDescriptor::PROP_OPENNEWVIEW()
165 : {
166 874 : static const OUString sProp("OpenNewView");
167 874 : return sProp;
168 : }
169 :
170 0 : const OUString& MediaDescriptor::PROP_OUTPUTSTREAM()
171 : {
172 0 : static const OUString sProp("OutputStream");
173 0 : return sProp;
174 : }
175 :
176 1977 : const OUString& MediaDescriptor::PROP_POSTDATA()
177 : {
178 1977 : static const OUString sProp("PostData");
179 1977 : return sProp;
180 : }
181 :
182 2218 : const OUString& MediaDescriptor::PROP_PREVIEW()
183 : {
184 2218 : static const OUString sProp("Preview");
185 2218 : return sProp;
186 : }
187 :
188 18783 : const OUString& MediaDescriptor::PROP_READONLY()
189 : {
190 18783 : static const OUString sProp("ReadOnly");
191 18783 : return sProp;
192 : }
193 :
194 0 : const OUString& MediaDescriptor::PROP_REFERRER()
195 : {
196 0 : static const OUString sProp("Referer");
197 0 : return sProp;
198 : }
199 :
200 2548 : const OUString& MediaDescriptor::PROP_STATUSINDICATOR()
201 : {
202 2548 : static const OUString sProp("StatusIndicator");
203 2548 : return sProp;
204 : }
205 :
206 2129 : const OUString& MediaDescriptor::PROP_STREAM()
207 : {
208 2129 : static const OUString sProp("Stream");
209 2129 : return sProp;
210 : }
211 :
212 101 : const OUString& MediaDescriptor::PROP_STREAMFOROUTPUT()
213 : {
214 101 : static const OUString sProp("StreamForOutput");
215 101 : return sProp;
216 : }
217 :
218 0 : const OUString& MediaDescriptor::PROP_TEMPLATENAME()
219 : {
220 0 : static const OUString sProp("TemplateName");
221 0 : return sProp;
222 : }
223 :
224 15263 : const OUString& MediaDescriptor::PROP_TYPENAME()
225 : {
226 15263 : static const OUString sProp("TypeName");
227 15263 : return sProp;
228 : }
229 :
230 1927 : const OUString& MediaDescriptor::PROP_UCBCONTENT()
231 : {
232 1927 : static const OUString sProp("UCBContent");
233 1927 : return sProp;
234 : }
235 :
236 2207 : const OUString& MediaDescriptor::PROP_UPDATEDOCMODE()
237 : {
238 2207 : static const OUString sProp("UpdateDocMode");
239 2207 : return sProp;
240 : }
241 :
242 12660 : const OUString& MediaDescriptor::PROP_URL()
243 : {
244 12660 : static const OUString sProp("URL");
245 12660 : return sProp;
246 : }
247 :
248 437 : const OUString& MediaDescriptor::PROP_VERSION()
249 : {
250 437 : static const OUString sProp("Version");
251 437 : return sProp;
252 : }
253 :
254 0 : const OUString& MediaDescriptor::PROP_DOCUMENTTITLE()
255 : {
256 0 : static const OUString sProp("DocumentTitle");
257 0 : return sProp;
258 : }
259 :
260 1139 : const OUString& MediaDescriptor::PROP_MODEL()
261 : {
262 1139 : static const OUString sProp("Model");
263 1139 : return sProp;
264 : }
265 :
266 0 : const OUString& MediaDescriptor::PROP_PASSWORD()
267 : {
268 0 : static const OUString sProp("Password");
269 0 : return sProp;
270 : }
271 :
272 0 : const OUString& MediaDescriptor::PROP_TITLE()
273 : {
274 0 : static const OUString sProp("Title");
275 0 : return sProp;
276 : }
277 :
278 0 : const OUString& MediaDescriptor::PROP_SALVAGEDFILE()
279 : {
280 0 : static const OUString sProp("SalvagedFile");
281 0 : return sProp;
282 : }
283 :
284 0 : const OUString& MediaDescriptor::PROP_VIEWONLY()
285 : {
286 0 : static const OUString sProp("ViewOnly");
287 0 : return sProp;
288 : }
289 :
290 4 : const OUString& MediaDescriptor::PROP_DOCUMENTBASEURL()
291 : {
292 4 : static const OUString sProp("DocumentBaseURL");
293 4 : return sProp;
294 : }
295 :
296 0 : const OUString& MediaDescriptor::PROP_DEEPDETECTION()
297 : {
298 0 : static const OUString aProp("DeepDetection");
299 0 : return aProp;
300 : }
301 :
302 1247 : MediaDescriptor::MediaDescriptor()
303 1247 : : SequenceAsHashMap()
304 : {
305 1247 : }
306 :
307 4910 : MediaDescriptor::MediaDescriptor(const css::uno::Sequence< css::beans::PropertyValue >& lSource)
308 4910 : : SequenceAsHashMap(lSource)
309 : {
310 4910 : }
311 :
312 4 : sal_Bool MediaDescriptor::isStreamReadOnly() const
313 : {
314 4 : static OUString CONTENTSCHEME_FILE( "file" );
315 4 : static OUString CONTENTPROP_ISREADONLY( "IsReadOnly" );
316 : static sal_Bool READONLY_FALLBACK = sal_False;
317 :
318 4 : sal_Bool bReadOnly = READONLY_FALLBACK;
319 :
320 : // check for explicit readonly state
321 4 : const_iterator pIt = find(MediaDescriptor::PROP_READONLY());
322 4 : if (pIt != end())
323 : {
324 4 : pIt->second >>= bReadOnly;
325 4 : return bReadOnly;
326 : }
327 :
328 : // streams based on post data are readonly by definition
329 0 : pIt = find(MediaDescriptor::PROP_POSTDATA());
330 0 : if (pIt != end())
331 0 : return sal_True;
332 :
333 : // A XStream capsulate XInputStream and XOutputStream ...
334 : // If it exists - the file must be open in read/write mode!
335 0 : pIt = find(MediaDescriptor::PROP_STREAM());
336 0 : if (pIt != end())
337 0 : return sal_False;
338 :
339 : // Only file system content provider is able to provide XStream
340 : // so for this content impossibility to create XStream triggers
341 : // switch to readonly mode.
342 : try
343 : {
344 0 : css::uno::Reference< css::ucb::XContent > xContent = getUnpackedValueOrDefault(MediaDescriptor::PROP_UCBCONTENT(), css::uno::Reference< css::ucb::XContent >());
345 0 : if (xContent.is())
346 : {
347 0 : css::uno::Reference< css::ucb::XContentIdentifier > xId(xContent->getIdentifier(), css::uno::UNO_QUERY);
348 0 : OUString aScheme;
349 0 : if (xId.is())
350 0 : aScheme = xId->getContentProviderScheme();
351 :
352 0 : if (aScheme.equalsIgnoreAsciiCase(CONTENTSCHEME_FILE))
353 0 : bReadOnly = sal_True;
354 : else
355 : {
356 0 : ::ucbhelper::Content aContent(xContent, css::uno::Reference< css::ucb::XCommandEnvironment >(), getProcessComponentContext());
357 0 : aContent.getPropertyValue(CONTENTPROP_ISREADONLY) >>= bReadOnly;
358 0 : }
359 0 : }
360 : }
361 0 : catch(const css::uno::RuntimeException& )
362 0 : { throw; }
363 0 : catch(const css::uno::Exception&)
364 : {}
365 :
366 0 : return bReadOnly;
367 : }
368 :
369 : // ----------------------------------------------------------------------------
370 :
371 0 : css::uno::Any MediaDescriptor::getComponentDataEntry( const OUString& rName ) const
372 : {
373 0 : css::uno::Any aEntry;
374 0 : SequenceAsHashMap::const_iterator aPropertyIter = find( PROP_COMPONENTDATA() );
375 0 : if( aPropertyIter != end() )
376 0 : return NamedValueCollection( aPropertyIter->second ).get( rName );
377 0 : return css::uno::Any();
378 : }
379 :
380 1 : void MediaDescriptor::setComponentDataEntry( const OUString& rName, const css::uno::Any& rValue )
381 : {
382 1 : if( rValue.hasValue() )
383 : {
384 : // get or create the 'ComponentData' property entry
385 1 : css::uno::Any& rCompDataAny = operator[]( PROP_COMPONENTDATA() );
386 : // insert the value (retain sequence type, create NamedValue elements by default)
387 1 : bool bHasNamedValues = !rCompDataAny.hasValue() || rCompDataAny.has< css::uno::Sequence< css::beans::NamedValue > >();
388 1 : bool bHasPropValues = rCompDataAny.has< css::uno::Sequence< css::beans::PropertyValue > >();
389 : OSL_ENSURE( bHasNamedValues || bHasPropValues, "MediaDescriptor::setComponentDataEntry - incompatible 'ComponentData' property in media descriptor" );
390 1 : if( bHasNamedValues || bHasPropValues )
391 : {
392 : // insert or overwrite the passed value
393 1 : SequenceAsHashMap aCompDataMap( rCompDataAny );
394 1 : aCompDataMap[ rName ] = rValue;
395 : // write back the sequence (restore sequence with correct element type)
396 1 : rCompDataAny = aCompDataMap.getAsConstAny( bHasPropValues );
397 : }
398 : }
399 : else
400 : {
401 : // if an empty Any is passed, clear the entry
402 0 : clearComponentDataEntry( rName );
403 : }
404 1 : }
405 :
406 0 : void MediaDescriptor::clearComponentDataEntry( const OUString& rName )
407 : {
408 0 : SequenceAsHashMap::iterator aPropertyIter = find( PROP_COMPONENTDATA() );
409 0 : if( aPropertyIter != end() )
410 : {
411 0 : css::uno::Any& rCompDataAny = aPropertyIter->second;
412 0 : bool bHasNamedValues = rCompDataAny.has< css::uno::Sequence< css::beans::NamedValue > >();
413 0 : bool bHasPropValues = rCompDataAny.has< css::uno::Sequence< css::beans::PropertyValue > >();
414 : OSL_ENSURE( bHasNamedValues || bHasPropValues, "MediaDescriptor::clearComponentDataEntry - incompatible 'ComponentData' property in media descriptor" );
415 0 : if( bHasNamedValues || bHasPropValues )
416 : {
417 : // remove the value with the passed name
418 0 : SequenceAsHashMap aCompDataMap( rCompDataAny );
419 0 : aCompDataMap.erase( rName );
420 : // write back the sequence, or remove it completely if it is empty
421 0 : if( aCompDataMap.empty() )
422 0 : erase( aPropertyIter );
423 : else
424 0 : rCompDataAny = aCompDataMap.getAsConstAny( bHasPropValues );
425 : }
426 : }
427 0 : }
428 :
429 1566 : sal_Bool MediaDescriptor::addInputStream()
430 : {
431 1566 : return impl_addInputStream( sal_True );
432 : }
433 :
434 : /*-----------------------------------------------*/
435 8169 : sal_Bool MediaDescriptor::addInputStreamOwnLock()
436 : {
437 : return impl_addInputStream(
438 8169 : officecfg::Office::Common::Misc::UseDocumentSystemFileLocking::get());
439 : }
440 :
441 : /*-----------------------------------------------*/
442 9735 : sal_Bool MediaDescriptor::impl_addInputStream( sal_Bool bLockFile )
443 : {
444 : // check for an already existing stream item first
445 9735 : const_iterator pIt = find(MediaDescriptor::PROP_INPUTSTREAM());
446 9735 : if (pIt != end())
447 7758 : return sal_True;
448 :
449 : try
450 : {
451 : // No stream available - create a new one
452 : // a) data comes as PostData ...
453 1977 : pIt = find(MediaDescriptor::PROP_POSTDATA());
454 1977 : if (pIt != end())
455 : {
456 0 : const css::uno::Any& rPostData = pIt->second;
457 0 : css::uno::Reference< css::io::XInputStream > xPostData;
458 0 : rPostData >>= xPostData;
459 :
460 0 : return impl_openStreamWithPostData( xPostData );
461 : }
462 :
463 : // b) ... or we must get it from the given URL
464 1977 : OUString sURL = getUnpackedValueOrDefault(MediaDescriptor::PROP_URL(), OUString());
465 1977 : if (sURL.isEmpty())
466 : throw css::uno::Exception("Found no URL.",
467 1 : css::uno::Reference< css::uno::XInterface >());
468 :
469 : // Parse URL! Only the main part has to be used further. E.g. a jumpmark can make trouble
470 3952 : OUString sNormalizedURL = impl_normalizeURL( sURL );
471 3953 : return impl_openStreamWithURL( sNormalizedURL, bLockFile );
472 : }
473 2 : catch(const css::uno::Exception& ex)
474 : {
475 : SAL_WARN(
476 : "comphelper", "invalid MediaDescriptor detected: " << ex.Message);
477 1 : return false;
478 : }
479 : }
480 :
481 0 : sal_Bool MediaDescriptor::impl_openStreamWithPostData( const css::uno::Reference< css::io::XInputStream >& _rxPostData )
482 : throw(::com::sun::star::uno::RuntimeException)
483 : {
484 0 : if ( !_rxPostData.is() )
485 : throw css::lang::IllegalArgumentException("Found invalid PostData.",
486 0 : css::uno::Reference< css::uno::XInterface >(), 1);
487 :
488 : // PostData can't be used in read/write mode!
489 0 : (*this)[MediaDescriptor::PROP_READONLY()] <<= sal_True;
490 :
491 : // prepare the environment
492 : css::uno::Reference< css::task::XInteractionHandler > xInteraction = getUnpackedValueOrDefault(
493 0 : MediaDescriptor::PROP_INTERACTIONHANDLER(),
494 0 : css::uno::Reference< css::task::XInteractionHandler >());
495 0 : css::uno::Reference< css::ucb::XProgressHandler > xProgress;
496 0 : ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
497 0 : css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
498 :
499 : // media type
500 0 : OUString sMediaType = getUnpackedValueOrDefault(MediaDescriptor::PROP_MEDIATYPE(), OUString());
501 0 : if (sMediaType.isEmpty())
502 : {
503 0 : sMediaType = "application/x-www-form-urlencoded";
504 0 : (*this)[MediaDescriptor::PROP_MEDIATYPE()] <<= sMediaType;
505 : }
506 :
507 : // url
508 0 : OUString sURL( getUnpackedValueOrDefault( PROP_URL(), OUString() ) );
509 :
510 0 : css::uno::Reference< css::io::XInputStream > xResultStream;
511 : try
512 : {
513 : // seek PostData stream to the beginning
514 0 : css::uno::Reference< css::io::XSeekable > xSeek( _rxPostData, css::uno::UNO_QUERY );
515 0 : if ( xSeek.is() )
516 0 : xSeek->seek( 0 );
517 :
518 : // a content for the URL
519 0 : ::ucbhelper::Content aContent( sURL, xCommandEnv, getProcessComponentContext() );
520 :
521 : // use post command
522 0 : css::ucb::PostCommandArgument2 aPostArgument;
523 0 : aPostArgument.Source = _rxPostData;
524 0 : css::uno::Reference< css::io::XActiveDataSink > xSink( new ucbhelper::ActiveDataSink );
525 0 : aPostArgument.Sink = xSink;
526 0 : aPostArgument.MediaType = sMediaType;
527 0 : aPostArgument.Referer = getUnpackedValueOrDefault( PROP_REFERRER(), OUString() );
528 :
529 0 : OUString sCommandName( "post" );
530 0 : aContent.executeCommand( sCommandName, css::uno::makeAny( aPostArgument ) );
531 :
532 : // get result
533 0 : xResultStream = xSink->getInputStream();
534 : }
535 0 : catch( const css::uno::Exception& )
536 : {
537 : }
538 :
539 : // success?
540 0 : if ( !xResultStream.is() )
541 : {
542 : OSL_FAIL( "no valid reply to the HTTP-Post" );
543 0 : return sal_False;
544 : }
545 :
546 0 : (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xResultStream;
547 0 : return sal_True;
548 : }
549 :
550 : /*-----------------------------------------------*/
551 1976 : sal_Bool MediaDescriptor::impl_openStreamWithURL( const OUString& sURL, sal_Bool bLockFile )
552 : throw(::com::sun::star::uno::RuntimeException)
553 : {
554 : // prepare the environment
555 : css::uno::Reference< css::task::XInteractionHandler > xOrgInteraction = getUnpackedValueOrDefault(
556 1976 : MediaDescriptor::PROP_INTERACTIONHANDLER(),
557 3952 : css::uno::Reference< css::task::XInteractionHandler >());
558 :
559 1976 : StillReadWriteInteraction* pInteraction = new StillReadWriteInteraction(xOrgInteraction);
560 3952 : css::uno::Reference< css::task::XInteractionHandler > xInteraction(static_cast< css::task::XInteractionHandler* >(pInteraction), css::uno::UNO_QUERY);
561 :
562 3952 : css::uno::Reference< css::ucb::XProgressHandler > xProgress;
563 1976 : ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
564 3952 : css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
565 :
566 : // try to create the content
567 : // no content -> no stream => return immediately with FALSE
568 3952 : ::ucbhelper::Content aContent;
569 3952 : css::uno::Reference< css::ucb::XContent > xContent;
570 : try
571 : {
572 1976 : aContent = ::ucbhelper::Content(sURL, xCommandEnv, getProcessComponentContext());
573 1976 : xContent = aContent.get();
574 : }
575 0 : catch(const css::uno::RuntimeException&)
576 0 : { throw; }
577 0 : catch(const css::ucb::ContentCreationException&)
578 0 : { return sal_False; } // TODO error handling
579 0 : catch(const css::uno::Exception&)
580 0 : { return sal_False; } // TODO error handling
581 :
582 : // try to open the file in read/write mode
583 : // (if its allowed to do so).
584 : // But handle errors in a "hidden mode". Because
585 : // we try it readonly later - if read/write isnt an option.
586 3952 : css::uno::Reference< css::io::XStream > xStream ;
587 3952 : css::uno::Reference< css::io::XInputStream > xInputStream;
588 :
589 1976 : sal_Bool bReadOnly = sal_False;
590 1976 : sal_Bool bModeRequestedExplicitly = sal_False;
591 1976 : const_iterator pIt = find(MediaDescriptor::PROP_READONLY());
592 1976 : if (pIt != end())
593 : {
594 857 : pIt->second >>= bReadOnly;
595 857 : bModeRequestedExplicitly = sal_True;
596 : }
597 :
598 1976 : if ( !bReadOnly && bLockFile )
599 : {
600 : try
601 : {
602 : // TODO: use "special" still interaction to supress error messages
603 675 : xStream = aContent.openWriteableStream();
604 667 : if (xStream.is())
605 667 : xInputStream = xStream->getInputStream();
606 : }
607 0 : catch(const css::uno::RuntimeException&)
608 0 : { throw; }
609 16 : catch(const css::uno::Exception&)
610 : {
611 : // ignore exception, if reason was problem reasoned on
612 : // open it in WRITEABLE mode! Then we try it READONLY
613 : // later a second time.
614 : // All other errors must be handled as real error an
615 : // break this method.
616 8 : if (!pInteraction->wasWriteError() || bModeRequestedExplicitly)
617 0 : return sal_False;
618 8 : xStream.clear();
619 8 : xInputStream.clear();
620 8 : }
621 : }
622 :
623 : // If opening of the stream in read/write mode wasnt allowed
624 : // or failed by an error - we must try it in readonly mode.
625 1976 : if (!xInputStream.is())
626 : {
627 1309 : OUString aScheme;
628 :
629 : try
630 : {
631 : css::uno::Reference< css::ucb::XContentIdentifier > xContId(
632 1309 : aContent.get().is() ? aContent.get()->getIdentifier() : 0 );
633 :
634 1309 : if ( xContId.is() )
635 1309 : aScheme = xContId->getContentProviderScheme();
636 :
637 : // Only file system content provider is able to provide XStream
638 : // so for this content impossibility to create XStream triggers
639 : // switch to readonly mode in case of opening with locking on
640 1309 : if( bLockFile && aScheme.equalsIgnoreAsciiCase("file") )
641 829 : bReadOnly = sal_True;
642 : else
643 : {
644 480 : sal_Bool bRequestReadOnly = bReadOnly;
645 504 : aContent.getPropertyValue("IsReadOnly") >>= bReadOnly;
646 456 : if ( bReadOnly && !bRequestReadOnly && bModeRequestedExplicitly )
647 0 : return sal_False; // the document is explicitly requested with WRITEABLE mode
648 1309 : }
649 : }
650 0 : catch(const css::uno::RuntimeException&)
651 0 : { throw; }
652 24 : catch(const css::uno::Exception&)
653 : { /* no error handling if IsReadOnly property does not exist for UCP */ }
654 :
655 1309 : if ( bReadOnly )
656 853 : (*this)[MediaDescriptor::PROP_READONLY()] <<= bReadOnly;
657 :
658 1309 : pInteraction->resetInterceptions();
659 1309 : pInteraction->resetErrorStates();
660 : try
661 : {
662 : // all the contents except file-URLs should be opened as usual
663 1309 : if ( bLockFile || !aScheme.equalsIgnoreAsciiCase("file") )
664 829 : xInputStream = aContent.openStream();
665 : else
666 480 : xInputStream = aContent.openStreamNoLock();
667 : }
668 0 : catch(const css::uno::RuntimeException&)
669 0 : { throw; }
670 98 : catch(const css::uno::Exception&)
671 1309 : { return sal_False; }
672 : }
673 :
674 : // add streams to the descriptor
675 1927 : if (xContent.is())
676 1927 : (*this)[MediaDescriptor::PROP_UCBCONTENT()] <<= xContent;
677 1927 : if (xStream.is())
678 667 : (*this)[MediaDescriptor::PROP_STREAM()] <<= xStream;
679 1927 : if (xInputStream.is())
680 1927 : (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xInputStream;
681 :
682 : // At least we need an input stream. The r/w stream is optional ...
683 3903 : return xInputStream.is();
684 : }
685 :
686 1976 : OUString MediaDescriptor::impl_normalizeURL(const OUString& sURL)
687 : {
688 : /* Remove Jumpmarks (fragments) of an URL only here.
689 : They are not part of any URL and as a result may be
690 : no ucb content can be created then.
691 : On the other side arguments must exists ... because
692 : they are part of an URL.
693 :
694 : Do not use the URLTransformer service here. Because
695 : it parses the URL in another way. It's main part isnt enough
696 : and it's complete part contains the jumpmark (fragment) parameter ...
697 : */
698 :
699 : try
700 : {
701 1976 : css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
702 1976 : css::uno::Reference< css::uri::XUriReferenceFactory > xUriFactory = css::uri::UriReferenceFactory::create(xContext);;
703 1976 : css::uno::Reference< css::uri::XUriReference > xUriRef = xUriFactory->parse(sURL);
704 1976 : if (xUriRef.is())
705 : {
706 1976 : xUriRef->clearFragment();
707 1976 : return xUriRef->getUriReference();
708 0 : }
709 : }
710 0 : catch(const css::uno::RuntimeException&)
711 0 : { throw; }
712 0 : catch(const css::uno::Exception&)
713 : {}
714 :
715 : // If an error ocurred ... return the original URL.
716 : // It's a try .-)
717 0 : return sURL;
718 : }
719 :
720 : } // namespace comphelper
721 :
722 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|