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