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