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/docpasswordhelper.hxx>
21 : #include <sal/log.hxx>
22 : #include <unotools/mediadescriptor.hxx>
23 : #include <unotools/securityoptions.hxx>
24 : #include <comphelper/namedvaluecollection.hxx>
25 : #include <comphelper/stillreadwriteinteraction.hxx>
26 :
27 : #include <com/sun/star/ucb/XContent.hpp>
28 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
29 : #include <com/sun/star/task/XInteractionHandler.hpp>
30 : #include <com/sun/star/io/XStream.hpp>
31 : #include <com/sun/star/io/XActiveDataSink.hpp>
32 : #include <com/sun/star/io/XSeekable.hpp>
33 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
35 : #include <com/sun/star/util/XURLTransformer.hpp>
36 : #include <com/sun/star/ucb/InteractiveIOException.hpp>
37 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
38 : #include <com/sun/star/ucb/CommandFailedException.hpp>
39 : #include <com/sun/star/task/XInteractionAbort.hpp>
40 : #include <com/sun/star/uri/UriReferenceFactory.hpp>
41 : #include <com/sun/star/uri/XUriReference.hpp>
42 : #include <com/sun/star/ucb/PostCommandArgument2.hpp>
43 : #include <com/sun/star/container/XNameAccess.hpp>
44 : #include <officecfg/Office/Common.hxx>
45 : #include <ucbhelper/interceptedinteraction.hxx>
46 : #include <ucbhelper/content.hxx>
47 : #include <ucbhelper/commandenvironment.hxx>
48 : #include <ucbhelper/activedatasink.hxx>
49 : #include <comphelper/processfactory.hxx>
50 : #include <osl/diagnose.h>
51 :
52 : namespace utl {
53 :
54 : namespace {
55 :
56 6990 : OUString removeFragment(OUString const & uri) {
57 : css::uno::Reference< css::uri::XUriReference > ref(
58 : css::uri::UriReferenceFactory::create(
59 20970 : comphelper::getProcessComponentContext())->
60 13980 : parse(uri));
61 6990 : if (ref.is()) {
62 6990 : ref->clearFragment();
63 6990 : return ref->getUriReference();
64 : } else {
65 : SAL_WARN("unotools.misc", "cannot parse <" << uri << ">");
66 0 : return uri;
67 6990 : }
68 : }
69 :
70 : }
71 :
72 3479 : const OUString& MediaDescriptor::PROP_ABORTED()
73 : {
74 3479 : static const OUString sProp("Aborted");
75 3479 : return sProp;
76 : }
77 :
78 4992 : const OUString& MediaDescriptor::PROP_ASTEMPLATE()
79 : {
80 4992 : static const OUString sProp("AsTemplate");
81 4992 : return sProp;
82 : }
83 :
84 1690 : const OUString& MediaDescriptor::PROP_COMPONENTDATA()
85 : {
86 1690 : static const OUString sProp("ComponentData");
87 1690 : return sProp;
88 : }
89 :
90 6488 : const OUString& MediaDescriptor::PROP_DOCUMENTSERVICE()
91 : {
92 6488 : static const OUString sProp("DocumentService");
93 6488 : return sProp;
94 : }
95 :
96 1207 : const OUString& MediaDescriptor::PROP_ENCRYPTIONDATA()
97 : {
98 1207 : static const OUString sProp("EncryptionData");
99 1207 : return sProp;
100 : }
101 :
102 3300 : const OUString& MediaDescriptor::PROP_FILENAME()
103 : {
104 3300 : static const OUString sProp("FileName");
105 3300 : return sProp;
106 : }
107 :
108 32971 : const OUString& MediaDescriptor::PROP_FILTERNAME()
109 : {
110 32971 : static const OUString sProp("FilterName");
111 32971 : return sProp;
112 : }
113 :
114 0 : const OUString& MediaDescriptor::PROP_FILTERPROVIDER()
115 : {
116 0 : static const OUString aProp("FilterProvider");
117 0 : return aProp;
118 : }
119 :
120 0 : const OUString& MediaDescriptor::PROP_FILTEROPTIONS()
121 : {
122 0 : static const OUString sProp("FilterOptions");
123 0 : return sProp;
124 : }
125 :
126 3036 : const OUString& MediaDescriptor::PROP_FRAME()
127 : {
128 3036 : static const OUString sProp("Frame");
129 3036 : return sProp;
130 : }
131 :
132 3298 : const OUString& MediaDescriptor::PROP_FRAMENAME()
133 : {
134 3298 : static const OUString sProp("FrameName");
135 3298 : return sProp;
136 : }
137 :
138 9054 : const OUString& MediaDescriptor::PROP_HIDDEN()
139 : {
140 9054 : static const OUString sProp("Hidden");
141 9054 : return sProp;
142 : }
143 :
144 171100 : const OUString& MediaDescriptor::PROP_INPUTSTREAM()
145 : {
146 171100 : static const OUString sProp("InputStream");
147 171100 : return sProp;
148 : }
149 :
150 16196 : const OUString& MediaDescriptor::PROP_INTERACTIONHANDLER()
151 : {
152 16196 : static const OUString sProp("InteractionHandler");
153 16196 : return sProp;
154 : }
155 :
156 0 : const OUString& MediaDescriptor::PROP_JUMPMARK()
157 : {
158 0 : static const OUString sProp("JumpMark");
159 0 : return sProp;
160 : }
161 :
162 4214 : const OUString& MediaDescriptor::PROP_MACROEXECUTIONMODE()
163 : {
164 4214 : static const OUString sProp("MacroExecutionMode");
165 4214 : return sProp;
166 : }
167 :
168 16 : const OUString& MediaDescriptor::PROP_MEDIATYPE()
169 : {
170 16 : static const OUString sProp("MediaType");
171 16 : return sProp;
172 : }
173 :
174 6588 : const OUString& MediaDescriptor::PROP_MINIMIZED()
175 : {
176 6588 : static const OUString sProp("Minimized");
177 6588 : return sProp;
178 : }
179 :
180 0 : const OUString& MediaDescriptor::PROP_NOAUTOSAVE()
181 : {
182 0 : static const OUString sProp("NoAutoSave");
183 0 : return sProp;
184 : }
185 :
186 4845 : const OUString& MediaDescriptor::PROP_OPENNEWVIEW()
187 : {
188 4845 : static const OUString sProp("OpenNewView");
189 4845 : return sProp;
190 : }
191 :
192 0 : const OUString& MediaDescriptor::PROP_OUTPUTSTREAM()
193 : {
194 0 : static const OUString sProp("OutputStream");
195 0 : return sProp;
196 : }
197 :
198 6996 : const OUString& MediaDescriptor::PROP_POSTDATA()
199 : {
200 6996 : static const OUString sProp("PostData");
201 6996 : return sProp;
202 : }
203 :
204 6552 : const OUString& MediaDescriptor::PROP_PREVIEW()
205 : {
206 6552 : static const OUString sProp("Preview");
207 6552 : return sProp;
208 : }
209 :
210 123762 : const OUString& MediaDescriptor::PROP_READONLY()
211 : {
212 123762 : static const OUString sProp("ReadOnly");
213 123762 : return sProp;
214 : }
215 :
216 7002 : const OUString& MediaDescriptor::PROP_REFERRER()
217 : {
218 7002 : static const OUString sProp("Referer");
219 7002 : return sProp;
220 : }
221 :
222 11054 : const OUString& MediaDescriptor::PROP_STATUSINDICATOR()
223 : {
224 11054 : static const OUString sProp("StatusIndicator");
225 11054 : return sProp;
226 : }
227 :
228 7379 : const OUString& MediaDescriptor::PROP_STREAM()
229 : {
230 7379 : static const OUString sProp("Stream");
231 7379 : return sProp;
232 : }
233 :
234 741 : const OUString& MediaDescriptor::PROP_STREAMFOROUTPUT()
235 : {
236 741 : static const OUString sProp("StreamForOutput");
237 741 : return sProp;
238 : }
239 :
240 0 : const OUString& MediaDescriptor::PROP_TEMPLATENAME()
241 : {
242 0 : static const OUString sProp("TemplateName");
243 0 : return sProp;
244 : }
245 :
246 97599 : const OUString& MediaDescriptor::PROP_TYPENAME()
247 : {
248 97599 : static const OUString sProp("TypeName");
249 97599 : return sProp;
250 : }
251 :
252 6612 : const OUString& MediaDescriptor::PROP_UCBCONTENT()
253 : {
254 6612 : static const OUString sProp("UCBContent");
255 6612 : return sProp;
256 : }
257 :
258 6583 : const OUString& MediaDescriptor::PROP_UPDATEDOCMODE()
259 : {
260 6583 : static const OUString sProp("UpdateDocMode");
261 6583 : return sProp;
262 : }
263 :
264 77910 : const OUString& MediaDescriptor::PROP_URL()
265 : {
266 77910 : static const OUString sProp("URL");
267 77910 : return sProp;
268 : }
269 :
270 2436 : const OUString& MediaDescriptor::PROP_VERSION()
271 : {
272 2436 : static const OUString sProp("Version");
273 2436 : return sProp;
274 : }
275 :
276 0 : const OUString& MediaDescriptor::PROP_DOCUMENTTITLE()
277 : {
278 0 : static const OUString sProp("DocumentTitle");
279 0 : return sProp;
280 : }
281 :
282 3399 : const OUString& MediaDescriptor::PROP_MODEL()
283 : {
284 3399 : static const OUString sProp("Model");
285 3399 : return sProp;
286 : }
287 :
288 0 : const OUString& MediaDescriptor::PROP_PASSWORD()
289 : {
290 0 : static const OUString sProp("Password");
291 0 : return sProp;
292 : }
293 :
294 0 : const OUString& MediaDescriptor::PROP_TITLE()
295 : {
296 0 : static const OUString sProp("Title");
297 0 : return sProp;
298 : }
299 :
300 0 : const OUString& MediaDescriptor::PROP_SALVAGEDFILE()
301 : {
302 0 : static const OUString sProp("SalvagedFile");
303 0 : return sProp;
304 : }
305 :
306 0 : const OUString& MediaDescriptor::PROP_VIEWONLY()
307 : {
308 0 : static const OUString sProp("ViewOnly");
309 0 : return sProp;
310 : }
311 :
312 4 : const OUString& MediaDescriptor::PROP_DOCUMENTBASEURL()
313 : {
314 4 : static const OUString sProp("DocumentBaseURL");
315 4 : return sProp;
316 : }
317 :
318 5632 : MediaDescriptor::MediaDescriptor()
319 5632 : : SequenceAsHashMap()
320 : {
321 5632 : }
322 :
323 48967 : MediaDescriptor::MediaDescriptor(const css::uno::Sequence< css::beans::PropertyValue >& lSource)
324 48967 : : SequenceAsHashMap(lSource)
325 : {
326 48967 : }
327 :
328 4 : bool MediaDescriptor::isStreamReadOnly() const
329 : {
330 : static const char CONTENTSCHEME_FILE[] = "file";
331 : static const char CONTENTPROP_ISREADONLY[] = "IsReadOnly";
332 : static bool READONLY_FALLBACK = false;
333 :
334 4 : bool bReadOnly = READONLY_FALLBACK;
335 :
336 : // check for explicit readonly state
337 4 : const_iterator pIt = find(MediaDescriptor::PROP_READONLY());
338 4 : if (pIt != end())
339 : {
340 0 : pIt->second >>= bReadOnly;
341 0 : return bReadOnly;
342 : }
343 :
344 : // streams based on post data are readonly by definition
345 4 : pIt = find(MediaDescriptor::PROP_POSTDATA());
346 4 : if (pIt != end())
347 0 : return true;
348 :
349 : // A XStream capsulate XInputStream and XOutputStream ...
350 : // If it exists - the file must be open in read/write mode!
351 4 : pIt = find(MediaDescriptor::PROP_STREAM());
352 4 : if (pIt != end())
353 4 : return false;
354 :
355 : // Only file system content provider is able to provide XStream
356 : // so for this content impossibility to create XStream triggers
357 : // switch to readonly mode.
358 : try
359 : {
360 0 : css::uno::Reference< css::ucb::XContent > xContent = getUnpackedValueOrDefault(MediaDescriptor::PROP_UCBCONTENT(), css::uno::Reference< css::ucb::XContent >());
361 0 : if (xContent.is())
362 : {
363 0 : css::uno::Reference< css::ucb::XContentIdentifier > xId(xContent->getIdentifier(), css::uno::UNO_QUERY);
364 0 : OUString aScheme;
365 0 : if (xId.is())
366 0 : aScheme = xId->getContentProviderScheme();
367 :
368 0 : if (aScheme.equalsIgnoreAsciiCase(CONTENTSCHEME_FILE))
369 0 : bReadOnly = true;
370 : else
371 : {
372 0 : ::ucbhelper::Content aContent(xContent, css::uno::Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext());
373 0 : aContent.getPropertyValue(CONTENTPROP_ISREADONLY) >>= bReadOnly;
374 0 : }
375 0 : }
376 : }
377 0 : catch(const css::uno::RuntimeException& )
378 0 : { throw; }
379 0 : catch(const css::uno::Exception&)
380 : {}
381 :
382 0 : return bReadOnly;
383 : }
384 :
385 1689 : css::uno::Any MediaDescriptor::getComponentDataEntry( const OUString& rName ) const
386 : {
387 1689 : comphelper::SequenceAsHashMap::const_iterator aPropertyIter = find( PROP_COMPONENTDATA() );
388 1689 : if( aPropertyIter != end() )
389 0 : return comphelper::NamedValueCollection( aPropertyIter->second ).get( rName );
390 1689 : return css::uno::Any();
391 : }
392 :
393 1 : void MediaDescriptor::setComponentDataEntry( const OUString& rName, const css::uno::Any& rValue )
394 : {
395 1 : if( rValue.hasValue() )
396 : {
397 : // get or create the 'ComponentData' property entry
398 1 : css::uno::Any& rCompDataAny = operator[]( PROP_COMPONENTDATA() );
399 : // insert the value (retain sequence type, create NamedValue elements by default)
400 1 : bool bHasNamedValues = !rCompDataAny.hasValue() || rCompDataAny.has< css::uno::Sequence< css::beans::NamedValue > >();
401 1 : bool bHasPropValues = rCompDataAny.has< css::uno::Sequence< css::beans::PropertyValue > >();
402 : OSL_ENSURE( bHasNamedValues || bHasPropValues, "MediaDescriptor::setComponentDataEntry - incompatible 'ComponentData' property in media descriptor" );
403 1 : if( bHasNamedValues || bHasPropValues )
404 : {
405 : // insert or overwrite the passed value
406 1 : comphelper::SequenceAsHashMap aCompDataMap( rCompDataAny );
407 1 : aCompDataMap[ rName ] = rValue;
408 : // write back the sequence (restore sequence with correct element type)
409 1 : rCompDataAny = aCompDataMap.getAsConstAny( bHasPropValues );
410 : }
411 : }
412 : else
413 : {
414 : // if an empty Any is passed, clear the entry
415 0 : clearComponentDataEntry( rName );
416 : }
417 1 : }
418 :
419 0 : void MediaDescriptor::clearComponentDataEntry( const OUString& rName )
420 : {
421 0 : comphelper::SequenceAsHashMap::iterator aPropertyIter = find( PROP_COMPONENTDATA() );
422 0 : if( aPropertyIter != end() )
423 : {
424 0 : css::uno::Any& rCompDataAny = aPropertyIter->second;
425 0 : bool bHasNamedValues = rCompDataAny.has< css::uno::Sequence< css::beans::NamedValue > >();
426 0 : bool bHasPropValues = rCompDataAny.has< css::uno::Sequence< css::beans::PropertyValue > >();
427 : OSL_ENSURE( bHasNamedValues || bHasPropValues, "MediaDescriptor::clearComponentDataEntry - incompatible 'ComponentData' property in media descriptor" );
428 0 : if( bHasNamedValues || bHasPropValues )
429 : {
430 : // remove the value with the passed name
431 0 : comphelper::SequenceAsHashMap aCompDataMap( rCompDataAny );
432 0 : aCompDataMap.erase( rName );
433 : // write back the sequence, or remove it completely if it is empty
434 0 : if( aCompDataMap.empty() )
435 0 : erase( aPropertyIter );
436 : else
437 0 : rCompDataAny = aCompDataMap.getAsConstAny( bHasPropValues );
438 : }
439 : }
440 0 : }
441 :
442 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > MediaDescriptor::requestAndVerifyDocPassword(
443 : comphelper::IDocPasswordVerifier& rVerifier,
444 : comphelper::DocPasswordRequestType eRequestType,
445 : const ::std::vector< OUString >* pDefaultPasswords )
446 : {
447 : css::uno::Sequence< css::beans::NamedValue > aMediaEncData = getUnpackedValueOrDefault(
448 0 : PROP_ENCRYPTIONDATA(), css::uno::Sequence< css::beans::NamedValue >() );
449 : OUString aMediaPassword = getUnpackedValueOrDefault(
450 0 : PROP_PASSWORD(), OUString() );
451 : css::uno::Reference< css::task::XInteractionHandler > xInteractHandler = getUnpackedValueOrDefault(
452 0 : PROP_INTERACTIONHANDLER(), css::uno::Reference< css::task::XInteractionHandler >() );
453 : OUString aDocumentName = getUnpackedValueOrDefault(
454 0 : PROP_URL(), OUString() );
455 :
456 0 : bool bIsDefaultPassword = false;
457 : css::uno::Sequence< css::beans::NamedValue > aEncryptionData = comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
458 0 : rVerifier, aMediaEncData, aMediaPassword, xInteractHandler, aDocumentName, eRequestType, pDefaultPasswords, &bIsDefaultPassword );
459 :
460 0 : erase( PROP_PASSWORD() );
461 0 : erase( PROP_ENCRYPTIONDATA() );
462 :
463 : // insert valid password into media descriptor (but not a default password)
464 0 : if( (aEncryptionData.getLength() > 0) && !bIsDefaultPassword )
465 0 : (*this)[ PROP_ENCRYPTIONDATA() ] <<= aEncryptionData;
466 :
467 0 : return aEncryptionData;
468 : }
469 :
470 10321 : bool MediaDescriptor::addInputStream()
471 : {
472 10321 : return impl_addInputStream( true );
473 : }
474 :
475 : /*-----------------------------------------------*/
476 57328 : bool MediaDescriptor::addInputStreamOwnLock()
477 : {
478 : return impl_addInputStream(
479 57328 : officecfg::Office::Common::Misc::UseDocumentSystemFileLocking::get());
480 : }
481 :
482 : /*-----------------------------------------------*/
483 67649 : bool MediaDescriptor::impl_addInputStream( bool bLockFile )
484 : {
485 : // check for an already existing stream item first
486 67649 : const_iterator pIt = find(MediaDescriptor::PROP_INPUTSTREAM());
487 67649 : if (pIt != end())
488 60657 : return true;
489 :
490 : try
491 : {
492 : // No stream available - create a new one
493 : // a) data comes as PostData ...
494 6992 : pIt = find(MediaDescriptor::PROP_POSTDATA());
495 6992 : if (pIt != end())
496 : {
497 0 : const css::uno::Any& rPostData = pIt->second;
498 0 : css::uno::Reference< css::io::XInputStream > xPostData;
499 0 : rPostData >>= xPostData;
500 :
501 0 : return impl_openStreamWithPostData( xPostData );
502 : }
503 :
504 : // b) ... or we must get it from the given URL
505 6992 : OUString sURL = getUnpackedValueOrDefault(MediaDescriptor::PROP_URL(), OUString());
506 6992 : if (sURL.isEmpty())
507 : throw css::uno::Exception("Found no URL.",
508 2 : css::uno::Reference< css::uno::XInterface >());
509 :
510 6990 : return impl_openStreamWithURL( removeFragment(sURL), bLockFile );
511 : }
512 4 : catch(const css::uno::Exception& ex)
513 : {
514 : SAL_WARN(
515 : "unotools.misc",
516 : "invalid MediaDescriptor detected: " << ex.Message);
517 2 : return false;
518 : }
519 : }
520 :
521 0 : bool MediaDescriptor::impl_openStreamWithPostData( const css::uno::Reference< css::io::XInputStream >& _rxPostData )
522 : throw(::com::sun::star::uno::RuntimeException)
523 : {
524 0 : if ( !_rxPostData.is() )
525 : throw css::lang::IllegalArgumentException("Found invalid PostData.",
526 0 : css::uno::Reference< css::uno::XInterface >(), 1);
527 :
528 : // PostData can't be used in read/write mode!
529 0 : (*this)[MediaDescriptor::PROP_READONLY()] <<= sal_True;
530 :
531 : // prepare the environment
532 : css::uno::Reference< css::task::XInteractionHandler > xInteraction = getUnpackedValueOrDefault(
533 0 : MediaDescriptor::PROP_INTERACTIONHANDLER(),
534 0 : css::uno::Reference< css::task::XInteractionHandler >());
535 0 : css::uno::Reference< css::ucb::XProgressHandler > xProgress;
536 0 : ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
537 0 : css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
538 :
539 : // media type
540 0 : OUString sMediaType = getUnpackedValueOrDefault(MediaDescriptor::PROP_MEDIATYPE(), OUString());
541 0 : if (sMediaType.isEmpty())
542 : {
543 0 : sMediaType = "application/x-www-form-urlencoded";
544 0 : (*this)[MediaDescriptor::PROP_MEDIATYPE()] <<= sMediaType;
545 : }
546 :
547 : // url
548 0 : OUString sURL( getUnpackedValueOrDefault( PROP_URL(), OUString() ) );
549 :
550 0 : css::uno::Reference< css::io::XInputStream > xResultStream;
551 : try
552 : {
553 : // seek PostData stream to the beginning
554 0 : css::uno::Reference< css::io::XSeekable > xSeek( _rxPostData, css::uno::UNO_QUERY );
555 0 : if ( xSeek.is() )
556 0 : xSeek->seek( 0 );
557 :
558 : // a content for the URL
559 0 : ::ucbhelper::Content aContent( sURL, xCommandEnv, comphelper::getProcessComponentContext() );
560 :
561 : // use post command
562 0 : css::ucb::PostCommandArgument2 aPostArgument;
563 0 : aPostArgument.Source = _rxPostData;
564 0 : css::uno::Reference< css::io::XActiveDataSink > xSink( new ucbhelper::ActiveDataSink );
565 0 : aPostArgument.Sink = xSink;
566 0 : aPostArgument.MediaType = sMediaType;
567 0 : aPostArgument.Referer = getUnpackedValueOrDefault( PROP_REFERRER(), OUString() );
568 :
569 0 : OUString sCommandName( "post" );
570 0 : aContent.executeCommand( sCommandName, css::uno::makeAny( aPostArgument ) );
571 :
572 : // get result
573 0 : xResultStream = xSink->getInputStream();
574 : }
575 0 : catch( const css::uno::Exception& )
576 : {
577 : }
578 :
579 : // success?
580 0 : if ( !xResultStream.is() )
581 : {
582 : OSL_FAIL( "no valid reply to the HTTP-Post" );
583 0 : return false;
584 : }
585 :
586 0 : (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xResultStream;
587 0 : return true;
588 : }
589 :
590 : /*-----------------------------------------------*/
591 6990 : bool MediaDescriptor::impl_openStreamWithURL( const OUString& sURL, bool bLockFile )
592 : throw(::com::sun::star::uno::RuntimeException)
593 : {
594 6990 : OUString referer(getUnpackedValueOrDefault(PROP_REFERRER(), OUString()));
595 6990 : if (SvtSecurityOptions().isUntrustedReferer(referer)) {
596 0 : return false;
597 : }
598 :
599 : // prepare the environment
600 : css::uno::Reference< css::task::XInteractionHandler > xOrgInteraction = getUnpackedValueOrDefault(
601 6990 : MediaDescriptor::PROP_INTERACTIONHANDLER(),
602 20970 : css::uno::Reference< css::task::XInteractionHandler >());
603 :
604 6990 : comphelper::StillReadWriteInteraction* pInteraction = new comphelper::StillReadWriteInteraction(xOrgInteraction);
605 13980 : css::uno::Reference< css::task::XInteractionHandler > xInteraction(static_cast< css::task::XInteractionHandler* >(pInteraction), css::uno::UNO_QUERY);
606 :
607 13980 : css::uno::Reference< css::ucb::XProgressHandler > xProgress;
608 6990 : ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress);
609 13980 : css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY);
610 :
611 : // try to create the content
612 : // no content -> no stream => return immediately with FALSE
613 13980 : ::ucbhelper::Content aContent;
614 13980 : css::uno::Reference< css::ucb::XContent > xContent;
615 : try
616 : {
617 6990 : aContent = ::ucbhelper::Content(sURL, xCommandEnv, comphelper::getProcessComponentContext());
618 6982 : xContent = aContent.get();
619 : }
620 0 : catch(const css::uno::RuntimeException&)
621 0 : { throw; }
622 16 : catch(const css::ucb::ContentCreationException& e)
623 : {
624 : SAL_WARN(
625 : "unotools.misc",
626 : "caught ContentCreationException \"" << e.Message
627 : << "\" while opening <" << sURL << ">");
628 8 : return false; // TODO error handling
629 : }
630 0 : catch(const css::uno::Exception& e)
631 : {
632 : SAL_WARN(
633 : "unotools.misc",
634 : "caught Exception \"" << e.Message << "\" while opening <"
635 : << sURL << ">");
636 0 : return false; // TODO error handling
637 : }
638 :
639 : // try to open the file in read/write mode
640 : // (if its allowed to do so).
641 : // But handle errors in a "hidden mode". Because
642 : // we try it readonly later - if read/write is not an option.
643 13964 : css::uno::Reference< css::io::XStream > xStream;
644 13964 : css::uno::Reference< css::io::XInputStream > xInputStream;
645 :
646 6982 : bool bReadOnly = false;
647 6982 : bool bModeRequestedExplicitly = false;
648 6982 : const_iterator pIt = find(MediaDescriptor::PROP_READONLY());
649 6982 : if (pIt != end())
650 : {
651 1547 : pIt->second >>= bReadOnly;
652 1547 : bModeRequestedExplicitly = true;
653 : }
654 :
655 6982 : if ( !bReadOnly && bLockFile )
656 : {
657 : try
658 : {
659 : // TODO: use "special" still interaction to suppress error messages
660 2925 : xStream = aContent.openWriteableStream();
661 2924 : if (xStream.is())
662 2924 : xInputStream = xStream->getInputStream();
663 : }
664 0 : catch(const css::uno::RuntimeException&)
665 0 : { throw; }
666 2 : catch(const css::uno::Exception& e)
667 : {
668 : // ignore exception, if reason was problem reasoned on
669 : // open it in WRITEABLE mode! Then we try it READONLY
670 : // later a second time.
671 : // All other errors must be handled as real error an
672 : // break this method.
673 1 : if (!pInteraction->wasWriteError() || bModeRequestedExplicitly)
674 : {
675 : SAL_WARN(
676 : "unotools.misc",
677 : "caught Exception \"" << e.Message
678 : << "\" while opening <" << sURL << ">");
679 0 : return false;
680 : }
681 1 : xStream.clear();
682 1 : xInputStream.clear();
683 1 : }
684 : }
685 :
686 : // If opening of the stream in read/write mode was not allowed
687 : // or failed by an error - we must try it in readonly mode.
688 6982 : if (!xInputStream.is())
689 : {
690 4058 : OUString aScheme;
691 :
692 : try
693 : {
694 : css::uno::Reference< css::ucb::XContentIdentifier > xContId(
695 4058 : aContent.get().is() ? aContent.get()->getIdentifier() : 0 );
696 :
697 4058 : if ( xContId.is() )
698 4058 : aScheme = xContId->getContentProviderScheme();
699 :
700 : // Only file system content provider is able to provide XStream
701 : // so for this content impossibility to create XStream triggers
702 : // switch to readonly mode in case of opening with locking on
703 4058 : if( bLockFile && aScheme.equalsIgnoreAsciiCase("file") )
704 549 : bReadOnly = true;
705 : else
706 : {
707 3509 : bool bRequestReadOnly = bReadOnly;
708 3862 : aContent.getPropertyValue("IsReadOnly") >>= bReadOnly;
709 3156 : if ( bReadOnly && !bRequestReadOnly && bModeRequestedExplicitly )
710 0 : return false; // the document is explicitly requested with WRITEABLE mode
711 4058 : }
712 : }
713 0 : catch(const css::uno::RuntimeException&)
714 0 : { throw; }
715 353 : catch(const css::uno::Exception&)
716 : { /* no error handling if IsReadOnly property does not exist for UCP */ }
717 :
718 4058 : if ( bReadOnly )
719 897 : (*this)[MediaDescriptor::PROP_READONLY()] <<= bReadOnly;
720 :
721 4058 : pInteraction->resetInterceptions();
722 4058 : pInteraction->resetErrorStates();
723 : try
724 : {
725 : // all the contents except file-URLs should be opened as usual
726 4058 : if ( bLockFile || !aScheme.equalsIgnoreAsciiCase("file") )
727 549 : xInputStream = aContent.openStream();
728 : else
729 3509 : xInputStream = aContent.openStreamNoLock();
730 : }
731 0 : catch(const css::uno::RuntimeException&)
732 0 : { throw; }
733 740 : catch(const css::uno::Exception& e)
734 : {
735 : SAL_WARN(
736 : "unotools.misc",
737 : "caught Exception \"" << e.Message << "\" while opening <"
738 : << sURL << ">");
739 370 : return false;
740 3688 : }
741 : }
742 :
743 : // add streams to the descriptor
744 6612 : if (xContent.is())
745 6612 : (*this)[MediaDescriptor::PROP_UCBCONTENT()] <<= xContent;
746 6612 : if (xStream.is())
747 2924 : (*this)[MediaDescriptor::PROP_STREAM()] <<= xStream;
748 6612 : if (xInputStream.is())
749 6612 : (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xInputStream;
750 :
751 : // At least we need an input stream. The r/w stream is optional ...
752 13602 : return xInputStream.is();
753 : }
754 :
755 : } // namespace comphelper
756 :
757 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|