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