Simplify type detectors
Change-Id: Ic731c1c4c76d8d6779868d7e3e4c02cb3cadc844 Reviewed-on: https://gerrit.libreoffice.org/9222 Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com> Tested-by: Maxim Monastirsky <momonasmon@gmail.com>
This commit is contained in:
@@ -77,6 +77,7 @@ $(eval $(call gb_CppunitTest_use_components,chart2_export,\
|
||||
embeddedobj/util/embobj \
|
||||
eventattacher/source/evtatt \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
forms/util/frm \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
|
@@ -80,6 +80,7 @@ $(eval $(call gb_CppunitTest_use_components,chart2_import,\
|
||||
embeddedobj/util/embobj \
|
||||
eventattacher/source/evtatt \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
forms/util/frm \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
|
@@ -71,6 +71,7 @@ $(eval $(call gb_CppunitTest_use_components,sc_html_export_test,\
|
||||
configmgr/source/configmgr \
|
||||
dbaccess/util/dba \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
forms/util/frm \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
|
@@ -27,12 +27,8 @@ $(eval $(call gb_Library_use_libraries,scd,\
|
||||
sal \
|
||||
sfx \
|
||||
sot \
|
||||
svl \
|
||||
svt \
|
||||
tl \
|
||||
ucbhelper \
|
||||
utl \
|
||||
vcl \
|
||||
$(gb_UWINAPI) \
|
||||
))
|
||||
|
||||
|
@@ -21,55 +21,17 @@
|
||||
|
||||
#include <sal/macros.h>
|
||||
|
||||
#include <framework/interaction.hxx>
|
||||
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
||||
#include <com/sun/star/beans/PropertyValue.hpp>
|
||||
#include <com/sun/star/frame/XFrame.hpp>
|
||||
#include <com/sun/star/frame/XModel.hpp>
|
||||
#include <com/sun/star/awt/XWindow.hpp>
|
||||
#include <com/sun/star/lang/XUnoTunnel.hpp>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <comphelper/string.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <com/sun/star/container/XNameAccess.hpp>
|
||||
#include <com/sun/star/io/XInputStream.hpp>
|
||||
#include <com/sun/star/task/XInteractionHandler.hpp>
|
||||
#include <com/sun/star/ucb/CommandAbortedException.hpp>
|
||||
#include <com/sun/star/ucb/InteractiveAppException.hpp>
|
||||
#include <com/sun/star/ucb/XContent.hpp>
|
||||
#include <com/sun/star/packages/zip/ZipIOException.hpp>
|
||||
|
||||
#include <toolkit/helper/vclunohelper.hxx>
|
||||
#include <ucbhelper/simpleinteractionrequest.hxx>
|
||||
|
||||
#include <svtools/parhtml.hxx>
|
||||
#include <rtl/ustring.h>
|
||||
#include <svl/itemset.hxx>
|
||||
#include <vcl/window.hxx>
|
||||
#include <svl/eitem.hxx>
|
||||
#include <svl/stritem.hxx>
|
||||
#include <tools/urlobj.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
#include <svtools/sfxecode.hxx>
|
||||
#include <svtools/ehdl.hxx>
|
||||
#include <sot/storinfo.hxx>
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <sfx2/sfxsids.hrc>
|
||||
#include <sfx2/request.hxx>
|
||||
#include <unotools/mediadescriptor.hxx>
|
||||
#include <sfx2/docfile.hxx>
|
||||
#include <sfx2/docfilt.hxx>
|
||||
#include <sfx2/fcontnr.hxx>
|
||||
#include <sfx2/app.hxx>
|
||||
#include <sfx2/brokenpackageint.hxx>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
using namespace ::com::sun::star::uno;
|
||||
using namespace ::com::sun::star::io;
|
||||
using namespace ::com::sun::star::frame;
|
||||
using namespace ::com::sun::star::task;
|
||||
using namespace ::com::sun::star::beans;
|
||||
using namespace ::com::sun::star::lang;
|
||||
using namespace ::com::sun::star::ucb;
|
||||
using utl::MediaDescriptor;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -285,359 +247,68 @@ static bool lcl_MayBeDBase( SvStream& rStream )
|
||||
OUString SAL_CALL ScFilterDetect::detect( uno::Sequence<beans::PropertyValue>& lDescriptor )
|
||||
throw( uno::RuntimeException, std::exception )
|
||||
{
|
||||
uno::Reference< XInputStream > xStream;
|
||||
uno::Reference< XContent > xContent;
|
||||
uno::Reference< XInteractionHandler > xInteraction;
|
||||
OUString aURL;
|
||||
OUString sTemp;
|
||||
OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
|
||||
OUString aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action)
|
||||
MediaDescriptor aMediaDesc( lDescriptor );
|
||||
OUString aTypeName = aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_TYPENAME(), OUString() );
|
||||
uno::Reference< io::XInputStream > xStream ( aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM()], uno::UNO_QUERY );
|
||||
if ( !xStream.is() )
|
||||
return OUString();
|
||||
|
||||
OUString aDocumentTitle; // interesting only if set in this method
|
||||
SfxMedium aMedium;
|
||||
aMedium.UseInteractionHandler( false );
|
||||
aMedium.setStreamToLoadFrom( xStream, true );
|
||||
|
||||
// opening as template is done when a parameter tells to do so and a template filter can be detected
|
||||
// (otherwise no valid filter would be found) or if the detected filter is a template filter and
|
||||
// there is no parameter that forbids to open as template
|
||||
bool bOpenAsTemplate = false;
|
||||
bool bWasReadOnly = false, bReadOnly = false;
|
||||
SvStream* pStream = aMedium.GetInStream();
|
||||
if ( !pStream || pStream->GetError() )
|
||||
// No stream, no detection.
|
||||
return OUString();
|
||||
|
||||
bool bRepairPackage = false;
|
||||
bool bRepairAllowed = false;
|
||||
bool bDeepDetection = false;
|
||||
|
||||
// now some parameters that can already be in the array, but may be overwritten or new inserted here
|
||||
// remember their indices in the case new values must be added to the array
|
||||
sal_Int32 nPropertyCount = lDescriptor.getLength();
|
||||
sal_Int32 nIndexOfFilterName = -1;
|
||||
sal_Int32 nIndexOfInputStream = -1;
|
||||
sal_Int32 nIndexOfContent = -1;
|
||||
sal_Int32 nIndexOfReadOnlyFlag = -1;
|
||||
sal_Int32 nIndexOfTemplateFlag = -1;
|
||||
sal_Int32 nIndexOfDocumentTitle = -1;
|
||||
|
||||
for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
|
||||
const char* pSearchFilterName = NULL;
|
||||
if (aTypeName == "calc_Lotus")
|
||||
{
|
||||
// extract properties
|
||||
if ( lDescriptor[nProperty].Name == "URL" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if( aURL.isEmpty() && lDescriptor[nProperty].Name == "FileName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "TypeName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aTypeName = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "FilterName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aPreselectedFilterName = sTemp;
|
||||
if (!detectThisFormat(*pStream, pLotus) && !detectThisFormat(*pStream, pLotusNew) && !detectThisFormat(*pStream, pLotus2))
|
||||
return OUString();
|
||||
|
||||
// if the preselected filter name is not correct, it must be erased after detection
|
||||
// remember index of property to get access to it later
|
||||
nIndexOfFilterName = nProperty;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "InputStream" )
|
||||
nIndexOfInputStream = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "ReadOnly" )
|
||||
nIndexOfReadOnlyFlag = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "UCBContent" )
|
||||
nIndexOfContent = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "AsTemplate" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= bOpenAsTemplate;
|
||||
nIndexOfTemplateFlag = nProperty;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "InteractionHandler" )
|
||||
lDescriptor[nProperty].Value >>= xInteraction;
|
||||
else if ( lDescriptor[nProperty].Name == "RepairPackage" )
|
||||
lDescriptor[nProperty].Value >>= bRepairPackage;
|
||||
else if ( lDescriptor[nProperty].Name == "DocumentTitle" )
|
||||
nIndexOfDocumentTitle = nProperty;
|
||||
else if (lDescriptor[nProperty].Name == "DeepDetection")
|
||||
bDeepDetection = lDescriptor[nProperty].Value.get<sal_Bool>();
|
||||
pSearchFilterName = pFilterLotus;
|
||||
}
|
||||
|
||||
// can't check the type for external filters, so set the "dont" flag accordingly
|
||||
SolarMutexGuard aGuard;
|
||||
//SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED;
|
||||
|
||||
SfxAllItemSet *pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
|
||||
TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
|
||||
SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, false );
|
||||
|
||||
bWasReadOnly = pItem && pItem->GetValue();
|
||||
|
||||
const SfxFilter* pFilter = 0;
|
||||
OUString aPrefix = "private:factory/";
|
||||
if( aURL.startsWith( aPrefix ) )
|
||||
else if (aTypeName == "calc_QPro")
|
||||
{
|
||||
OUString aPattern = aPrefix + "scalc";
|
||||
if ( aURL.startsWith( aPattern ) )
|
||||
pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
|
||||
if (!detectThisFormat(*pStream, pQPro))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterQPro6;
|
||||
}
|
||||
else if (aTypeName == "calc_SYLK")
|
||||
{
|
||||
if (!detectThisFormat(*pStream, pSylk))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterSylk;
|
||||
}
|
||||
else if (aTypeName == "calc_DIF")
|
||||
{
|
||||
if (!detectThisFormat(*pStream, pDIF1) && !detectThisFormat(*pStream, pDIF2))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterDif;
|
||||
}
|
||||
else if (aTypeName == "calc_dBase")
|
||||
{
|
||||
if (!lcl_MayBeDBase(*pStream))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterDBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
// container for Calc filters
|
||||
SfxFilterMatcher aMatcher("scalc");
|
||||
if ( !aPreselectedFilterName.isEmpty() )
|
||||
pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
|
||||
else if( !aTypeName.isEmpty() )
|
||||
pFilter = aMatcher.GetFilter4EA( aTypeName );
|
||||
return OUString();
|
||||
|
||||
// ctor of SfxMedium uses owner transition of ItemSet
|
||||
SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
|
||||
aMedium.UseInteractionHandler( true );
|
||||
|
||||
bool bIsStorage = aMedium.IsStorage();
|
||||
if ( aMedium.GetErrorCode() == ERRCODE_NONE )
|
||||
{
|
||||
// remember input stream and content and put them into the descriptor later
|
||||
// should be done here since later the medium can switch to a version
|
||||
xStream.set(aMedium.GetInputStream());
|
||||
xContent.set(aMedium.GetContent());
|
||||
bReadOnly = aMedium.IsReadOnly();
|
||||
|
||||
// maybe that IsStorage() already created an error!
|
||||
if ( bIsStorage )
|
||||
{
|
||||
uno::Reference < embed::XStorage > xStorage(aMedium.GetStorage( false ));
|
||||
if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
|
||||
{
|
||||
// error during storage creation means _here_ that the medium
|
||||
// is broken, but we can not handle it in medium since unpossibility
|
||||
// to create a storage does not _always_ means that the medium is broken
|
||||
aMedium.SetError(aMedium.GetLastStorageCreationState(), OUString(OSL_LOG_PREFIX));
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
OUString empty;
|
||||
try
|
||||
{
|
||||
InteractiveAppException xException( empty,
|
||||
uno::Reference< XInterface >(),
|
||||
InteractionClassification_ERROR,
|
||||
aMedium.GetError() );
|
||||
|
||||
uno::Reference< XInteractionRequest > xRequest(
|
||||
new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
|
||||
ucbhelper::CONTINUATION_APPROVE ) );
|
||||
xInteraction->handle( xRequest );
|
||||
}
|
||||
catch ( Exception & ) {};
|
||||
}
|
||||
}
|
||||
else if ( xStorage.is() )
|
||||
{
|
||||
try
|
||||
{
|
||||
OUString aFilterName;
|
||||
if ( pFilter )
|
||||
aFilterName = pFilter->GetName();
|
||||
aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsOwnTemplateFormat() : false, &aFilterName );
|
||||
}
|
||||
catch( const lang::WrappedTargetException& aWrap )
|
||||
{
|
||||
if (!bDeepDetection)
|
||||
// Bail out early unless it's a deep detection.
|
||||
return OUString();
|
||||
|
||||
packages::zip::ZipIOException aZipException;
|
||||
|
||||
// repairing is done only if this type is requested from outside
|
||||
if ( ( aWrap.TargetException >>= aZipException ) && !aTypeName.isEmpty() )
|
||||
{
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
// the package is broken one
|
||||
aDocumentTitle = aMedium.GetURLObject().getName(
|
||||
INetURLObject::LAST_SEGMENT,
|
||||
true,
|
||||
INetURLObject::DECODE_WITH_CHARSET );
|
||||
|
||||
if ( !bRepairPackage )
|
||||
{
|
||||
// ask the user whether he wants to try to repair
|
||||
RequestPackageReparation aRequest( aDocumentTitle );
|
||||
xInteraction->handle( aRequest.GetRequest() );
|
||||
bRepairAllowed = aRequest.isApproved();
|
||||
}
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
{
|
||||
// repair either not allowed or not successful
|
||||
NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
|
||||
xInteraction->handle( aNotifyRequest.GetRequest() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
aTypeName = "";
|
||||
}
|
||||
}
|
||||
catch( uno::RuntimeException& )
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch( uno::Exception& )
|
||||
{
|
||||
aTypeName = "";
|
||||
}
|
||||
|
||||
if ( !aTypeName.isEmpty() )
|
||||
pFilter = SfxFilterMatcher("scalc").GetFilter4EA( aTypeName );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-storage format.
|
||||
|
||||
if (aTypeName == "calc8_template" ||
|
||||
aTypeName == "calc8" ||
|
||||
aTypeName == "calc_StarOffice_XML_Calc" ||
|
||||
aTypeName == "calc_StarOffice_XML_Calc_Template")
|
||||
// These types require storage. Bail out.
|
||||
return OUString();
|
||||
|
||||
SvStream* pStream = aMedium.GetInStream();
|
||||
if (!pStream)
|
||||
// No stream, no detection.
|
||||
return OUString();
|
||||
|
||||
pFilter = NULL;
|
||||
|
||||
const char* pSearchFilterName = NULL;
|
||||
if (aTypeName == "calc_Lotus")
|
||||
{
|
||||
if (!detectThisFormat(*pStream, pLotus) && !detectThisFormat(*pStream, pLotusNew) && !detectThisFormat(*pStream, pLotus2))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterLotus;
|
||||
}
|
||||
else if (aTypeName == "calc_QPro")
|
||||
{
|
||||
if (!detectThisFormat(*pStream, pQPro))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterQPro6;
|
||||
}
|
||||
else if (aTypeName == "calc_SYLK")
|
||||
{
|
||||
if (!detectThisFormat(*pStream, pSylk))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterSylk;
|
||||
}
|
||||
else if (aTypeName == "calc_DIF")
|
||||
{
|
||||
if (!detectThisFormat(*pStream, pDIF1) && !detectThisFormat(*pStream, pDIF2))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterDif;
|
||||
}
|
||||
else if (aTypeName == "calc_dBase")
|
||||
{
|
||||
if (!lcl_MayBeDBase(*pStream))
|
||||
return OUString();
|
||||
|
||||
pSearchFilterName = pFilterDBase;
|
||||
}
|
||||
|
||||
if (!pSearchFilterName)
|
||||
return OUString();
|
||||
|
||||
pFilter = aMatcher.GetFilter4FilterName(OUString::createFromAscii(pSearchFilterName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( nIndexOfInputStream == -1 && xStream.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "InputStream";
|
||||
lDescriptor[nPropertyCount].Value <<= xStream;
|
||||
nPropertyCount++;
|
||||
}
|
||||
|
||||
if ( nIndexOfContent == -1 && xContent.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "UCBContent";
|
||||
lDescriptor[nPropertyCount].Value <<= xContent;
|
||||
nPropertyCount++;
|
||||
}
|
||||
|
||||
if ( bReadOnly != bWasReadOnly )
|
||||
{
|
||||
if ( nIndexOfReadOnlyFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "ReadOnly";
|
||||
lDescriptor[nPropertyCount].Value <<= bReadOnly;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
|
||||
}
|
||||
|
||||
if ( !bRepairPackage && bRepairAllowed )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "RepairPackage";
|
||||
lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
|
||||
nPropertyCount++;
|
||||
|
||||
bOpenAsTemplate = true;
|
||||
|
||||
// TODO/LATER: set progress bar that should be used
|
||||
}
|
||||
|
||||
if ( bOpenAsTemplate )
|
||||
{
|
||||
if ( nIndexOfTemplateFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "AsTemplate";
|
||||
lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
|
||||
}
|
||||
|
||||
if ( !aDocumentTitle.isEmpty() )
|
||||
{
|
||||
// the title was set here
|
||||
if ( nIndexOfDocumentTitle == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "DocumentTitle";
|
||||
lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
|
||||
}
|
||||
SfxFilterMatcher aMatcher("scalc");
|
||||
const SfxFilter* pFilter = aMatcher.GetFilter4FilterName(OUString::createFromAscii(pSearchFilterName));
|
||||
|
||||
if (!pFilter)
|
||||
return OUString();
|
||||
|
||||
if (nIndexOfFilterName == -1)
|
||||
{
|
||||
lDescriptor.realloc(nPropertyCount + 1);
|
||||
lDescriptor[nPropertyCount].Name = "FilterName";
|
||||
lDescriptor[nPropertyCount].Value <<= pFilter->GetName();
|
||||
++nPropertyCount;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfFilterName].Value <<= pFilter->GetName();
|
||||
|
||||
aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= pFilter->GetName();
|
||||
aMediaDesc >> lDescriptor;
|
||||
return aTypeName;
|
||||
}
|
||||
|
||||
|
@@ -19,16 +19,13 @@ $(eval $(call gb_Library_use_external,sdd,boost_headers))
|
||||
$(eval $(call gb_Library_use_sdk_api,sdd))
|
||||
|
||||
$(eval $(call gb_Library_use_libraries,sdd,\
|
||||
comphelper \
|
||||
cppu \
|
||||
cppuhelper \
|
||||
sal \
|
||||
sfx \
|
||||
sot \
|
||||
svl \
|
||||
svt \
|
||||
svxcore \
|
||||
tl \
|
||||
ucbhelper \
|
||||
utl \
|
||||
vcl \
|
||||
$(gb_UWINAPI) \
|
||||
|
@@ -17,83 +17,29 @@
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
|
||||
#include "sddetect.hxx"
|
||||
|
||||
#include <framework/interaction.hxx>
|
||||
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
||||
#include <com/sun/star/beans/PropertyValue.hpp>
|
||||
#include <com/sun/star/frame/XFrame.hpp>
|
||||
#include <com/sun/star/frame/XModel.hpp>
|
||||
#include <com/sun/star/awt/XWindow.hpp>
|
||||
#include <com/sun/star/lang/XUnoTunnel.hpp>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <com/sun/star/container/XNameAccess.hpp>
|
||||
#include <com/sun/star/io/XInputStream.hpp>
|
||||
#include <com/sun/star/task/XInteractionHandler.hpp>
|
||||
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
|
||||
#include <com/sun/star/ucb/CommandAbortedException.hpp>
|
||||
#include <com/sun/star/ucb/InteractiveAppException.hpp>
|
||||
#include <com/sun/star/ucb/XContent.hpp>
|
||||
#include <com/sun/star/packages/zip/ZipIOException.hpp>
|
||||
#include <toolkit/helper/vclunohelper.hxx>
|
||||
#include <ucbhelper/simpleinteractionrequest.hxx>
|
||||
#include <vcl/graphicfilter.hxx>
|
||||
#include <rtl/ustring.h>
|
||||
#include <rtl/logfile.hxx>
|
||||
#include <svl/itemset.hxx>
|
||||
#include <vcl/window.hxx>
|
||||
#include <svl/eitem.hxx>
|
||||
#include <svl/stritem.hxx>
|
||||
#include <tools/urlobj.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
#include <svtools/sfxecode.hxx>
|
||||
#include <svtools/ehdl.hxx>
|
||||
#include <sot/storinfo.hxx>
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <sfx2/app.hxx>
|
||||
#include <sfx2/sfxsids.hrc>
|
||||
#include <sfx2/request.hxx>
|
||||
#include <sfx2/docfile.hxx>
|
||||
#include <sfx2/docfilt.hxx>
|
||||
#include <sfx2/fcontnr.hxx>
|
||||
#include <sfx2/brokenpackageint.hxx>
|
||||
#include <vcl/FilterConfigItem.hxx>
|
||||
#include <sot/storage.hxx>
|
||||
#include <unotools/moduleoptions.hxx>
|
||||
|
||||
#include "strmname.h"
|
||||
#include <unotools/mediadescriptor.hxx>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
using namespace ::com::sun::star::uno;
|
||||
using namespace ::com::sun::star::io;
|
||||
using namespace ::com::sun::star::frame;
|
||||
using namespace ::com::sun::star::task;
|
||||
using namespace ::com::sun::star::beans;
|
||||
using namespace ::com::sun::star::lang;
|
||||
using namespace ::com::sun::star::ucb;
|
||||
|
||||
namespace {
|
||||
|
||||
bool isZipStorageType(const OUString& rTypeName)
|
||||
{
|
||||
if (rTypeName == "impress8" || rTypeName == "impress8_template")
|
||||
return true;
|
||||
|
||||
if (rTypeName == "draw8" || rTypeName == "draw8_template")
|
||||
return true;
|
||||
|
||||
if (rTypeName == "impress_StarOffice_XML_Impress" || rTypeName == "impress_StarOffice_XML_Impress_Template")
|
||||
return true;
|
||||
|
||||
if (rTypeName == "draw_StarOffice_XML_Draw" || rTypeName == "draw_StarOffice_XML_Draw_Template")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
using utl::MediaDescriptor;
|
||||
|
||||
SdFilterDetect::SdFilterDetect( const Reference < XMultiServiceFactory >& )
|
||||
{
|
||||
@@ -105,423 +51,79 @@ SdFilterDetect::~SdFilterDetect()
|
||||
|
||||
OUString SAL_CALL SdFilterDetect::detect( Sequence< beans::PropertyValue >& lDescriptor ) throw( RuntimeException, std::exception )
|
||||
{
|
||||
Reference< XInputStream > xStream;
|
||||
Reference< XContent > xContent;
|
||||
Reference< XInteractionHandler > xInteraction;
|
||||
OUString aURL;
|
||||
OUString sTemp;
|
||||
OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
|
||||
OUString aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action)
|
||||
MediaDescriptor aMediaDesc( lDescriptor );
|
||||
OUString aTypeName = aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_TYPENAME(), OUString() );
|
||||
uno::Reference< io::XInputStream > xInStream ( aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM()], uno::UNO_QUERY );
|
||||
if ( !xInStream.is() )
|
||||
return OUString();
|
||||
|
||||
OUString aDocumentTitle; // interesting only if set in this method
|
||||
SfxMedium aMedium;
|
||||
aMedium.UseInteractionHandler( false );
|
||||
aMedium.setStreamToLoadFrom( xInStream, true );
|
||||
|
||||
// opening as template is done when a parameter tells to do so and a template filter can be detected
|
||||
// (otherwise no valid filter would be found) or if the detected filter is a template filter and
|
||||
// there is no parameter that forbids to open as template
|
||||
bool bOpenAsTemplate = false;
|
||||
bool bWasReadOnly = false, bReadOnly = false;
|
||||
SvStream *pInStrm = aMedium.GetInStream();
|
||||
if ( !pInStrm || pInStrm->GetError() )
|
||||
return OUString();
|
||||
|
||||
bool bRepairPackage = false;
|
||||
bool bRepairAllowed = false;
|
||||
bool bDeepDetection = false;
|
||||
|
||||
// now some parameters that can already be in the array, but may be overwritten or new inserted here
|
||||
// remember their indices in the case new values must be added to the array
|
||||
sal_Int32 nPropertyCount = lDescriptor.getLength();
|
||||
sal_Int32 nIndexOfInputStream = -1;
|
||||
sal_Int32 nIndexOfContent = -1;
|
||||
sal_Int32 nIndexOfReadOnlyFlag = -1;
|
||||
sal_Int32 nIndexOfTemplateFlag = -1;
|
||||
sal_Int32 nIndexOfDocumentTitle = -1;
|
||||
|
||||
for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
|
||||
if ( aTypeName.startsWith( "impress_MS_PowerPoint_97" ) )
|
||||
{
|
||||
// extract properties
|
||||
if ( lDescriptor[nProperty].Name == "URL" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if( aURL.isEmpty() && lDescriptor[nProperty].Name == "FileName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "TypeName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aTypeName = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "FilterName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aPreselectedFilterName = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "InputStream" )
|
||||
nIndexOfInputStream = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "ReadOnly" )
|
||||
nIndexOfReadOnlyFlag = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "UCBContent" )
|
||||
nIndexOfContent = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "AsTemplate" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= bOpenAsTemplate;
|
||||
nIndexOfTemplateFlag = nProperty;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "InteractionHandler" )
|
||||
lDescriptor[nProperty].Value >>= xInteraction;
|
||||
else if ( lDescriptor[nProperty].Name == "RepairPackage" )
|
||||
lDescriptor[nProperty].Value >>= bRepairPackage;
|
||||
else if ( lDescriptor[nProperty].Name == "DocumentTitle" )
|
||||
nIndexOfDocumentTitle = nProperty;
|
||||
else if (lDescriptor[nProperty].Name == "DeepDetection")
|
||||
bDeepDetection = lDescriptor[nProperty].Value.get<sal_Bool>();
|
||||
}
|
||||
// Do not attempt to create an SotStorage on a
|
||||
// 0-length stream as that would create the compound
|
||||
// document header on the stream and effectively write to
|
||||
// disk!
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
if ( pInStrm->remainingSize() == 0 )
|
||||
return OUString();
|
||||
|
||||
// can't check the type for external filters, so set the "dont" flag accordingly
|
||||
SolarMutexGuard aGuard;
|
||||
//SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED;
|
||||
|
||||
SfxApplication* pApp = SFX_APP();
|
||||
SfxAllItemSet *pSet = new SfxAllItemSet( pApp->GetPool() );
|
||||
TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
|
||||
SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, false );
|
||||
|
||||
bWasReadOnly = pItem && pItem->GetValue();
|
||||
|
||||
const SfxFilter* pFilter = 0;
|
||||
OUString aPrefix = "private:factory/";
|
||||
if( aURL.startsWith( aPrefix ) )
|
||||
{
|
||||
if( SvtModuleOptions().IsImpress() )
|
||||
{
|
||||
OUString aPattern( aPrefix );
|
||||
aPattern += "simpress";
|
||||
if ( aURL.startsWith( aPattern ) )
|
||||
pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
|
||||
}
|
||||
|
||||
if( !pFilter && SvtModuleOptions().IsDraw() )
|
||||
{
|
||||
OUString aPattern( aPrefix );
|
||||
aPattern += "sdraw";
|
||||
if ( aURL.startsWith( aPattern ) )
|
||||
pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
|
||||
}
|
||||
SotStorageRef aStorage = new SotStorage( pInStrm, false );
|
||||
if ( !aStorage->GetError() && aStorage->IsStream( "PowerPoint Document" ) )
|
||||
return aTypeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ctor of SfxMedium uses owner transition of ItemSet
|
||||
SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
|
||||
aMedium.UseInteractionHandler( true );
|
||||
if ( !aPreselectedFilterName.isEmpty() )
|
||||
pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
|
||||
else if (!aTypeName.isEmpty())
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
|
||||
const OUString aFileName( aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL(), OUString() ) );
|
||||
GraphicDescriptor aDesc( *pInStrm, &aFileName );
|
||||
if( !aDesc.Detect( false ) )
|
||||
{
|
||||
SfxFilterMatcher aMatch;
|
||||
pFilter = aMatch.GetFilter4EA( aTypeName );
|
||||
}
|
||||
|
||||
if ( aMedium.GetErrorCode() == ERRCODE_NONE )
|
||||
{
|
||||
// remember input stream and content and put them into the descriptor later
|
||||
// should be done here since later the medium can switch to a version
|
||||
xStream = aMedium.GetInputStream();
|
||||
xContent = aMedium.GetContent();
|
||||
bReadOnly = aMedium.IsReadOnly();
|
||||
bool bIsZipStorage = aMedium.IsStorage();
|
||||
|
||||
if (aMedium.GetError() == SVSTREAM_OK)
|
||||
INetURLObject aCheckURL( aFileName );
|
||||
if( aCheckURL.getExtension().equalsIgnoreAsciiCase("cgm") )
|
||||
{
|
||||
if (bIsZipStorage)
|
||||
{
|
||||
// PowerPoint needs to be detected via StreamName, all other storage based formats are our own and can
|
||||
// be detected by the ClipboardId, so except for the PPT filter all filters must have a ClipboardId set
|
||||
Reference < embed::XStorage > xStorage = aMedium.GetStorage( false );
|
||||
|
||||
//TODO/LATER: move error handling to central place! (maybe even complete own filters)
|
||||
if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
|
||||
{
|
||||
// error during storage creation means _here_ that the medium
|
||||
// is broken, but we can not handle it in medium since unpossibility
|
||||
// to create a storage does not _always_ means that the medium is broken
|
||||
aMedium.SetError( aMedium.GetLastStorageCreationState(), OSL_LOG_PREFIX );
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
OUString empty;
|
||||
try
|
||||
{
|
||||
InteractiveAppException xException( empty,
|
||||
Reference< XInterface >(),
|
||||
InteractionClassification_ERROR,
|
||||
aMedium.GetError() );
|
||||
|
||||
Reference< XInteractionRequest > xRequest(
|
||||
new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
|
||||
ucbhelper::CONTINUATION_APPROVE ) );
|
||||
xInteraction->handle( xRequest );
|
||||
}
|
||||
catch ( Exception & ) {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pFilter && !pFilter->GetFormat() )
|
||||
// preselected Filter has no ClipboardId -> doesn't match (see comment above)
|
||||
pFilter = 0;
|
||||
|
||||
// the storage must be checked even if filter is already found, since it is deep type detection
|
||||
// the storage can be corrupted and it will be detected here
|
||||
try
|
||||
{
|
||||
OUString sFilterName;
|
||||
if ( pFilter )
|
||||
sFilterName = pFilter->GetName();
|
||||
aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter && pFilter->IsOwnTemplateFormat(), &sFilterName );
|
||||
}
|
||||
catch( const WrappedTargetException& aWrap )
|
||||
{
|
||||
if (!bDeepDetection)
|
||||
// Bail out early unless it's a deep detection.
|
||||
return OUString();
|
||||
|
||||
packages::zip::ZipIOException aZipException;
|
||||
if ((aWrap.TargetException >>= aZipException) && !aTypeName.isEmpty())
|
||||
{
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
// the package is broken one
|
||||
aDocumentTitle = aMedium.GetURLObject().getName(
|
||||
INetURLObject::LAST_SEGMENT,
|
||||
true,
|
||||
INetURLObject::DECODE_WITH_CHARSET );
|
||||
|
||||
if ( !bRepairPackage )
|
||||
{
|
||||
// ask the user whether he wants to try to repair
|
||||
RequestPackageReparation aRequest( aDocumentTitle );
|
||||
xInteraction->handle( aRequest.GetRequest() );
|
||||
bRepairAllowed = aRequest.isApproved();
|
||||
}
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
{
|
||||
// repair either not allowed or not successful
|
||||
NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
|
||||
xInteraction->handle( aNotifyRequest.GetRequest() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
{
|
||||
aTypeName = "";
|
||||
pFilter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( RuntimeException& )
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch( Exception& )
|
||||
{
|
||||
aTypeName = "";
|
||||
pFilter = 0;
|
||||
}
|
||||
|
||||
if (!pFilter && !aTypeName.isEmpty())
|
||||
{
|
||||
//TODO/LATER: using this method impress is always preferred if no flat detecion has been made
|
||||
// this should been discussed!
|
||||
if ( SvtModuleOptions().IsImpress() )
|
||||
pFilter = SfxFilterMatcher( OUString("simpress") ).GetFilter4EA( aTypeName );
|
||||
else if ( SvtModuleOptions().IsDraw() )
|
||||
pFilter = SfxFilterMatcher( OUString("sdraw") ).GetFilter4EA( aTypeName );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isZipStorageType(aTypeName))
|
||||
// This stream is a not zip archive, but a zip archive type is specified.
|
||||
pFilter = NULL;
|
||||
|
||||
SvStream* pStm = NULL;
|
||||
if (pFilter)
|
||||
{
|
||||
pStm = aMedium.GetInStream();
|
||||
if (!pStm)
|
||||
pFilter = NULL;
|
||||
else
|
||||
{
|
||||
pStm->Seek(STREAM_SEEK_TO_END);
|
||||
const sal_Size nSize = pStm->Tell();
|
||||
pStm->Seek(STREAM_SEEK_TO_BEGIN);
|
||||
|
||||
// Do not attempt to create an SotStorage on a
|
||||
// 0-length stream as that would create the compound
|
||||
// document header on the stream and effectively write to
|
||||
// disk!
|
||||
if (!nSize)
|
||||
pFilter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pFilter && pStm)
|
||||
{
|
||||
SotStorageRef aStorage = new SotStorage ( pStm, false );
|
||||
if ( !aStorage->GetError() )
|
||||
{
|
||||
OUString aStreamName("PowerPoint Document");
|
||||
if ( aStorage->IsStream( aStreamName ) && SvtModuleOptions().IsImpress() )
|
||||
{
|
||||
OUString aFileName(aMedium.GetName());
|
||||
aFileName = aFileName.toAsciiUpperCase();
|
||||
|
||||
if( aFileName.indexOf( ".POT" ) != -1 )
|
||||
pFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97Template );
|
||||
else if( aFileName.indexOf( ".PPS" ) != -1 )
|
||||
pFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97AutoPlay );
|
||||
else
|
||||
pFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFilter = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// vector graphic?
|
||||
pStm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
|
||||
const OUString aFileName( aMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
|
||||
GraphicDescriptor aDesc( *pStm, &aFileName );
|
||||
if( !aDesc.Detect( false ) )
|
||||
{
|
||||
pFilter = 0;
|
||||
if( SvtModuleOptions().IsImpress() )
|
||||
{
|
||||
INetURLObject aCheckURL( aFileName );
|
||||
if( aCheckURL.getExtension().equalsIgnoreAsciiCase("cgm") )
|
||||
{
|
||||
sal_uInt8 n8;
|
||||
pStm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
pStm->ReadUChar( n8 );
|
||||
if ( ( n8 & 0xf0 ) == 0 ) // we are supporting binary cgm format only, so
|
||||
{ // this is a small test to exclude cgm text
|
||||
SfxFilterMatcher aMatch(OUString("simpress"));
|
||||
pFilter = aMatch.GetFilter4FilterName(OUString("CGM - Computer Graphics Metafile"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OUString aShortName( aDesc.GetImportFormatShortName( aDesc.GetFileFormat() ) );
|
||||
GraphicFilter &rGrfFilter = GraphicFilter::GetGraphicFilter();
|
||||
const OUString aName( rGrfFilter.GetImportFormatTypeName( rGrfFilter.GetImportFormatNumberForShortName( aShortName ) ) );
|
||||
|
||||
if ( pFilter && aShortName.equalsIgnoreAsciiCase( "PCD" ) ) // there is a multiple pcd selection possible
|
||||
{
|
||||
sal_Int32 nBase = 2; // default Base0
|
||||
OUString aFilterTypeName( pFilter->GetRealTypeName() );
|
||||
if ( aFilterTypeName == "pcd_Photo_CD_Base4" )
|
||||
nBase = 1;
|
||||
else if ( aFilterTypeName == "pcd_Photo_CD_Base16" )
|
||||
nBase = 0;
|
||||
FilterConfigItem aFilterConfigItem( "Office.Common/Filter/Graphic/Import/PCD" );
|
||||
aFilterConfigItem.WriteInt32( "Resolution" , nBase );
|
||||
}
|
||||
|
||||
SfxFilterMatcher aMatch(OUString("sdraw"));
|
||||
pFilter = aMatch.GetFilter4FilterName( aName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pFilter = 0;
|
||||
sal_uInt8 n8;
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
pInStrm->ReadUChar( n8 );
|
||||
if ( ( n8 & 0xf0 ) == 0 )
|
||||
// we are supporting binary cgm format only, so
|
||||
// this is a small test to exclude cgm text
|
||||
return OUString("impress_CGM_Computer_Graphics_Metafile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( nIndexOfInputStream == -1 && xStream.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "InputStream";
|
||||
lDescriptor[nPropertyCount].Value <<= xStream;
|
||||
nPropertyCount++;
|
||||
}
|
||||
|
||||
if ( nIndexOfContent == -1 && xContent.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "UCBContent";
|
||||
lDescriptor[nPropertyCount].Value <<= xContent;
|
||||
nPropertyCount++;
|
||||
}
|
||||
|
||||
if ( bReadOnly != bWasReadOnly )
|
||||
{
|
||||
if ( nIndexOfReadOnlyFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "ReadOnly";
|
||||
lDescriptor[nPropertyCount].Value <<= bReadOnly;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
|
||||
}
|
||||
|
||||
if ( !bRepairPackage && bRepairAllowed )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "RepairPackage";
|
||||
lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
|
||||
nPropertyCount++;
|
||||
|
||||
bOpenAsTemplate = true;
|
||||
|
||||
// TODO/LATER: set progress bar that should be used
|
||||
}
|
||||
|
||||
if ( bOpenAsTemplate )
|
||||
{
|
||||
if ( nIndexOfTemplateFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "AsTemplate";
|
||||
lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
|
||||
nPropertyCount++;
|
||||
OUString aShortName( aDesc.GetImportFormatShortName( aDesc.GetFileFormat() ) );
|
||||
GraphicFilter &rGrfFilter = GraphicFilter::GetGraphicFilter();
|
||||
const OUString aName( rGrfFilter.GetImportFormatTypeName( rGrfFilter.GetImportFormatNumberForShortName( aShortName ) ) );
|
||||
|
||||
if ( aShortName.equalsIgnoreAsciiCase( "PCD" ) ) // there is a multiple pcd selection possible
|
||||
{
|
||||
sal_Int32 nBase = 2; // default Base0
|
||||
if ( aTypeName == "pcd_Photo_CD_Base4" )
|
||||
nBase = 1;
|
||||
else if ( aTypeName == "pcd_Photo_CD_Base16" )
|
||||
nBase = 0;
|
||||
FilterConfigItem aFilterConfigItem( "Office.Common/Filter/Graphic/Import/PCD" );
|
||||
aFilterConfigItem.WriteInt32( "Resolution" , nBase );
|
||||
}
|
||||
|
||||
SfxFilterMatcher aMatch("sdraw");
|
||||
const SfxFilter* pFilter = aMatch.GetFilter4FilterName( aName );
|
||||
if ( pFilter )
|
||||
return pFilter->GetRealTypeName();
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
|
||||
}
|
||||
|
||||
if ( !aDocumentTitle.isEmpty() )
|
||||
{
|
||||
// the title was set here
|
||||
if ( nIndexOfDocumentTitle == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "DocumentTitle";
|
||||
lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
|
||||
}
|
||||
|
||||
if (!pFilter)
|
||||
aTypeName = "";
|
||||
|
||||
return aTypeName;
|
||||
return OUString();
|
||||
}
|
||||
|
||||
// XServiceInfo
|
||||
@@ -529,7 +131,7 @@ OUString SAL_CALL SdFilterDetect::getImplementationName() throw( RuntimeExceptio
|
||||
{
|
||||
return impl_getStaticImplementationName();
|
||||
}
|
||||
\
|
||||
|
||||
// XServiceInfo
|
||||
sal_Bool SAL_CALL SdFilterDetect::supportsService( const OUString& sServiceName ) throw( RuntimeException, std::exception )
|
||||
{
|
||||
|
@@ -21,16 +21,14 @@ $(eval $(call gb_Library_use_external,smd,boost_headers))
|
||||
$(eval $(call gb_Library_use_sdk_api,smd))
|
||||
|
||||
$(eval $(call gb_Library_use_libraries,smd,\
|
||||
comphelper \
|
||||
cppu \
|
||||
cppuhelper \
|
||||
sal \
|
||||
sfx \
|
||||
sot \
|
||||
svl \
|
||||
svt \
|
||||
tl \
|
||||
ucbhelper \
|
||||
vcl \
|
||||
utl \
|
||||
$(gb_UWINAPI) \
|
||||
))
|
||||
|
||||
|
@@ -17,56 +17,23 @@
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
|
||||
#include "smdetect.hxx"
|
||||
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
||||
#include <com/sun/star/beans/PropertyValue.hpp>
|
||||
#include <com/sun/star/frame/XFrame.hpp>
|
||||
#include <com/sun/star/frame/XModel.hpp>
|
||||
#include <com/sun/star/awt/XWindow.hpp>
|
||||
#include <com/sun/star/lang/XUnoTunnel.hpp>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <com/sun/star/io/XInputStream.hpp>
|
||||
#include <com/sun/star/task/XInteractionHandler.hpp>
|
||||
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
|
||||
#include <com/sun/star/ucb/CommandAbortedException.hpp>
|
||||
#include <com/sun/star/ucb/InteractiveAppException.hpp>
|
||||
#include <com/sun/star/ucb/XContent.hpp>
|
||||
#include <com/sun/star/packages/zip/ZipIOException.hpp>
|
||||
#include <toolkit/helper/vclunohelper.hxx>
|
||||
#include <ucbhelper/simpleinteractionrequest.hxx>
|
||||
#include <rtl/ustring.h>
|
||||
#include <rtl/logfile.hxx>
|
||||
#include <svl/itemset.hxx>
|
||||
#include <vcl/window.hxx>
|
||||
#include <svl/eitem.hxx>
|
||||
#include <svl/stritem.hxx>
|
||||
#include <tools/urlobj.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
#include <svtools/sfxecode.hxx>
|
||||
#include <svtools/ehdl.hxx>
|
||||
#include <sot/storinfo.hxx>
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <sfx2/app.hxx>
|
||||
#include <sfx2/sfxsids.hrc>
|
||||
#include <sfx2/request.hxx>
|
||||
#include <sfx2/docfile.hxx>
|
||||
#include <sfx2/docfilt.hxx>
|
||||
#include <sfx2/fcontnr.hxx>
|
||||
#include <sfx2/brokenpackageint.hxx>
|
||||
#include <unotools/mediadescriptor.hxx>
|
||||
|
||||
#include "document.hxx"
|
||||
#include "eqnolefilehdr.hxx"
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
using namespace ::com::sun::star::uno;
|
||||
using namespace ::com::sun::star::io;
|
||||
using namespace ::com::sun::star::frame;
|
||||
using namespace ::com::sun::star::task;
|
||||
using namespace ::com::sun::star::beans;
|
||||
using namespace ::com::sun::star::lang;
|
||||
using namespace ::com::sun::star::ucb;
|
||||
using utl::MediaDescriptor;
|
||||
|
||||
SmFilterDetect::SmFilterDetect( const Reference < XMultiServiceFactory >& /*xFactory*/ )
|
||||
{
|
||||
@@ -78,368 +45,67 @@ SmFilterDetect::~SmFilterDetect()
|
||||
|
||||
OUString SAL_CALL SmFilterDetect::detect( Sequence< PropertyValue >& lDescriptor ) throw( RuntimeException, std::exception )
|
||||
{
|
||||
Reference< XInputStream > xStream;
|
||||
Reference< XContent > xContent;
|
||||
Reference< XInteractionHandler > xInteraction;
|
||||
OUString aURL;
|
||||
OUString sTemp;
|
||||
OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
|
||||
OUString aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action)
|
||||
MediaDescriptor aMediaDesc( lDescriptor );
|
||||
uno::Reference< io::XInputStream > xInStream ( aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM()], uno::UNO_QUERY );
|
||||
if ( !xInStream.is() )
|
||||
return OUString();
|
||||
|
||||
OUString aDocumentTitle; // interesting only if set in this method
|
||||
SfxMedium aMedium;
|
||||
aMedium.UseInteractionHandler( false );
|
||||
aMedium.setStreamToLoadFrom( xInStream, true );
|
||||
|
||||
// opening as template is done when a parameter tells to do so and a template filter can be detected
|
||||
// (otherwise no valid filter would be found) or if the detected filter is a template filter and
|
||||
// there is no parameter that forbids to open as template
|
||||
bool bOpenAsTemplate = false;
|
||||
bool bWasReadOnly = false, bReadOnly = false;
|
||||
SvStream *pInStrm = aMedium.GetInStream();
|
||||
if ( !pInStrm || pInStrm->GetError() )
|
||||
return OUString();
|
||||
|
||||
bool bRepairPackage = false;
|
||||
bool bRepairAllowed = false;
|
||||
bool bDeepDetection = false;
|
||||
// Do not attempt to create an SotStorage on a
|
||||
// 0-length stream as that would create the compound
|
||||
// document header on the stream and effectively write to
|
||||
// disk!
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
if ( pInStrm->remainingSize() == 0 )
|
||||
return OUString();
|
||||
|
||||
// now some parameters that can already be in the array, but may be overwritten or new inserted here
|
||||
// remember their indices in the case new values must be added to the array
|
||||
sal_Int32 nPropertyCount = lDescriptor.getLength();
|
||||
sal_Int32 nIndexOfInputStream = -1;
|
||||
sal_Int32 nIndexOfContent = -1;
|
||||
sal_Int32 nIndexOfReadOnlyFlag = -1;
|
||||
sal_Int32 nIndexOfTemplateFlag = -1;
|
||||
sal_Int32 nIndexOfDocumentTitle = -1;
|
||||
|
||||
for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
|
||||
SotStorageRef aStorage = new SotStorage( pInStrm, false );
|
||||
if ( !aStorage->GetError() )
|
||||
{
|
||||
// extract properties
|
||||
if( lDescriptor[nProperty].Name == "URL" )
|
||||
if ( aStorage->IsStream("Equation Native") )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if( aURL.isEmpty() && lDescriptor[nProperty].Name == "FileName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if( lDescriptor[nProperty].Name == "TypeName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aTypeName = sTemp;
|
||||
}
|
||||
else if( lDescriptor[nProperty].Name == "FilterName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aPreselectedFilterName = sTemp;
|
||||
}
|
||||
else if( lDescriptor[nProperty].Name == "InputStream" )
|
||||
nIndexOfInputStream = nProperty;
|
||||
else if( lDescriptor[nProperty].Name == "ReadOnly" )
|
||||
nIndexOfReadOnlyFlag = nProperty;
|
||||
else if( lDescriptor[nProperty].Name == "UCBContent" )
|
||||
nIndexOfContent = nProperty;
|
||||
else if( lDescriptor[nProperty].Name == "AsTemplate" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= bOpenAsTemplate;
|
||||
nIndexOfTemplateFlag = nProperty;
|
||||
}
|
||||
else if( lDescriptor[nProperty].Name == "InteractionHandler" )
|
||||
lDescriptor[nProperty].Value >>= xInteraction;
|
||||
else if( lDescriptor[nProperty].Name == "RepairPackage" )
|
||||
lDescriptor[nProperty].Value >>= bRepairPackage;
|
||||
else if( lDescriptor[nProperty].Name == "DocumentTitle" )
|
||||
nIndexOfDocumentTitle = nProperty;
|
||||
else if (lDescriptor[nProperty].Name == "DeepDetection")
|
||||
bDeepDetection = lDescriptor[nProperty].Value.get<sal_Bool>();
|
||||
}
|
||||
|
||||
// can't check the type for external filters, so set the "dont" flag accordingly
|
||||
SolarMutexGuard aGuard;
|
||||
|
||||
SfxApplication* pApp = SFX_APP();
|
||||
SfxAllItemSet *pSet = new SfxAllItemSet( pApp->GetPool() );
|
||||
TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
|
||||
SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, false );
|
||||
|
||||
bWasReadOnly = pItem && pItem->GetValue();
|
||||
|
||||
OUString aFilterName;
|
||||
OUString aPrefix( "private:factory/" );
|
||||
if( aURL.startsWith( aPrefix ) )
|
||||
{
|
||||
const SfxFilter* pFilter = 0;
|
||||
OUString aPattern( aPrefix );
|
||||
aPattern += "smath";
|
||||
if ( aURL.startsWith( aPattern ) )
|
||||
{
|
||||
pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
|
||||
aTypeName = pFilter->GetTypeName();
|
||||
aFilterName = pFilter->GetName();
|
||||
sal_uInt8 nVersion;
|
||||
if ( GetMathTypeVersion( aStorage, nVersion ) && nVersion <=3 )
|
||||
return OUString("math_MathType_3x");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ctor of SfxMedium uses owner transition of ItemSet
|
||||
SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
|
||||
aMedium.UseInteractionHandler( true );
|
||||
|
||||
bool bIsStorage = aMedium.IsStorage();
|
||||
if ( aMedium.GetErrorCode() == ERRCODE_NONE )
|
||||
// 200 should be enough for the XML
|
||||
// version, encoding and !DOCTYPE
|
||||
// stuff I hope?
|
||||
const sal_uInt16 nBufferSize = 200;
|
||||
char aBuffer[nBufferSize+1];
|
||||
aBuffer[nBufferSize] = 0;
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
pInStrm->StartReadingUnicodeText( RTL_TEXTENCODING_DONTKNOW ); // avoid BOM marker
|
||||
sal_uLong nBytesRead = pInStrm->Read( aBuffer, nBufferSize );
|
||||
if (nBytesRead >= 6)
|
||||
{
|
||||
// remember input stream and content and put them into the descriptor later
|
||||
// should be done here since later the medium can switch to a version
|
||||
xStream = aMedium.GetInputStream();
|
||||
xContent = aMedium.GetContent();
|
||||
bReadOnly = aMedium.IsReadOnly();
|
||||
|
||||
if ( bIsStorage )
|
||||
{
|
||||
//TODO/LATER: factor this out!
|
||||
Reference < embed::XStorage > xStorage = aMedium.GetStorage( false );
|
||||
if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
|
||||
{
|
||||
// error during storage creation means _here_ that the medium
|
||||
// is broken, but we can not handle it in medium since unpossibility
|
||||
// to create a storage does not _always_ means that the medium is broken
|
||||
aMedium.SetError( aMedium.GetLastStorageCreationState(), OSL_LOG_PREFIX );
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
OUString empty;
|
||||
try
|
||||
{
|
||||
InteractiveAppException xException( empty,
|
||||
Reference< XInterface >(),
|
||||
InteractionClassification_ERROR,
|
||||
aMedium.GetError() );
|
||||
|
||||
Reference< XInteractionRequest > xRequest(
|
||||
new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
|
||||
ucbhelper::CONTINUATION_APPROVE ) );
|
||||
xInteraction->handle( xRequest );
|
||||
}
|
||||
catch ( Exception & ) {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aFilterName = OUString();
|
||||
|
||||
try
|
||||
{
|
||||
const SfxFilter* pFilter = !aPreselectedFilterName.isEmpty() ?
|
||||
SfxFilterMatcher().GetFilter4FilterName( aPreselectedFilterName ) : !aTypeName.isEmpty() ?
|
||||
SfxFilterMatcher( "smath" ).GetFilter4EA( aTypeName ) : 0;
|
||||
OUString aTmpFilterName;
|
||||
if ( pFilter )
|
||||
aTmpFilterName = pFilter->GetName();
|
||||
aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter && pFilter->IsAllowedAsTemplate(), &aTmpFilterName );
|
||||
}
|
||||
catch( const WrappedTargetException& aWrap )
|
||||
{
|
||||
if (!bDeepDetection)
|
||||
// Bail out early unless it's a deep detection.
|
||||
return OUString();
|
||||
|
||||
packages::zip::ZipIOException aZipException;
|
||||
|
||||
// repairing is done only if this type is requested from outside
|
||||
if ( ( aWrap.TargetException >>= aZipException ) && !aTypeName.isEmpty() )
|
||||
{
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
// the package is broken one
|
||||
aDocumentTitle = aMedium.GetURLObject().getName(
|
||||
INetURLObject::LAST_SEGMENT,
|
||||
true,
|
||||
INetURLObject::DECODE_WITH_CHARSET );
|
||||
|
||||
if ( !bRepairPackage )
|
||||
{
|
||||
// ask the user whether he wants to try to repair
|
||||
RequestPackageReparation aRequest( aDocumentTitle );
|
||||
xInteraction->handle( aRequest.GetRequest() );
|
||||
bRepairAllowed = aRequest.isApproved();
|
||||
}
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
{
|
||||
// repair either not allowed or not successful
|
||||
NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
|
||||
xInteraction->handle( aNotifyRequest.GetRequest() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
aTypeName = OUString();
|
||||
}
|
||||
}
|
||||
catch( RuntimeException& )
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch( Exception& )
|
||||
{
|
||||
aTypeName = OUString();
|
||||
}
|
||||
|
||||
if ( !aTypeName.isEmpty() )
|
||||
{
|
||||
const SfxFilter* pFilter =
|
||||
SfxFilterMatcher( "smath" ).GetFilter4EA( aTypeName );
|
||||
if ( pFilter )
|
||||
aFilterName = pFilter->GetName();
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bIsMathType = false;
|
||||
if (0 == strncmp( "<?xml", aBuffer, 5))
|
||||
bIsMathType = (strstr( aBuffer, "<math>" ) ||
|
||||
strstr( aBuffer, "<math " ) ||
|
||||
strstr( aBuffer, "<math:math " ));
|
||||
else
|
||||
{
|
||||
//Test to see if this begins with xml and if so run it through
|
||||
//the MathML filter. There are all sorts of things wrong with
|
||||
//this approach, to be fixed at a better level than here
|
||||
SvStream *pStrm = aMedium.GetInStream();
|
||||
aTypeName = OUString();
|
||||
// this is the old <math tag to MathML in the beginning of the XML file
|
||||
bIsMathType = (0 == strncmp( "<math ", aBuffer, 6) ||
|
||||
0 == strncmp( "<math> ", aBuffer, 7) ||
|
||||
0 == strncmp( "<math:math> ", aBuffer, 12));
|
||||
|
||||
sal_Size nSize = 0;
|
||||
if ( pStrm && !pStrm->GetError() )
|
||||
{
|
||||
pStrm->Seek( STREAM_SEEK_TO_END );
|
||||
nSize = pStrm->Tell();
|
||||
pStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
}
|
||||
|
||||
// Do not attempt to create an SotStorage on a
|
||||
// 0-length stream as that would create the compound
|
||||
// document header on the stream and effectively write to
|
||||
// disk!
|
||||
if ( nSize > 0 )
|
||||
{
|
||||
SotStorageRef aStorage = new SotStorage ( pStrm, false );
|
||||
if ( !aStorage->GetError() )
|
||||
{
|
||||
if (aStorage->IsStream("Equation Native"))
|
||||
{
|
||||
sal_uInt8 nVersion;
|
||||
if (GetMathTypeVersion( aStorage, nVersion ) && nVersion <=3)
|
||||
aTypeName = "math_MathType_3x";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 200 should be enough for the XML
|
||||
// version, encoding and !DOCTYPE
|
||||
// stuff I hope?
|
||||
const sal_uInt16 nBufferSize = 200;
|
||||
sal_Char aBuffer[nBufferSize+1];
|
||||
aBuffer[nBufferSize] = 0;
|
||||
pStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
pStrm->StartReadingUnicodeText(RTL_TEXTENCODING_DONTKNOW); // avoid BOM marker
|
||||
sal_uLong nBytesRead = pStrm->Read( aBuffer, nBufferSize );
|
||||
if (nBytesRead >= 6)
|
||||
{
|
||||
bool bIsMathType = false;
|
||||
if (0 == strncmp( "<?xml", aBuffer, 5))
|
||||
{
|
||||
if (strstr( aBuffer, "<math>" ) ||
|
||||
strstr( aBuffer, "<math " ) ||
|
||||
strstr( aBuffer, "<math:math " ))
|
||||
bIsMathType = true;
|
||||
}
|
||||
// this is the old <math tag to MathML in the beginning of the XML file
|
||||
else if (0 == strncmp( "<math ", aBuffer, 6) ||
|
||||
0 == strncmp( "<math> ", aBuffer, 7) ||
|
||||
0 == strncmp( "<math:math> ", aBuffer, 12))
|
||||
bIsMathType = true;
|
||||
|
||||
if (bIsMathType){
|
||||
aFilterName = OUString( MATHML_XML );
|
||||
aTypeName = "math_MathML_XML_Math";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !aTypeName.isEmpty() )
|
||||
{
|
||||
const SfxFilter* pFilt = SfxFilterMatcher( "smath" ).GetFilter4EA( aTypeName );
|
||||
if ( pFilt )
|
||||
aFilterName = pFilt->GetName();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bIsMathType )
|
||||
return OUString("math_MathML_XML_Math");
|
||||
}
|
||||
}
|
||||
|
||||
if ( nIndexOfInputStream == -1 && xStream.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "InputStream";
|
||||
lDescriptor[nPropertyCount].Value <<= xStream;
|
||||
nPropertyCount++;
|
||||
}
|
||||
|
||||
if ( nIndexOfContent == -1 && xContent.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "UCBContent";
|
||||
lDescriptor[nPropertyCount].Value <<= xContent;
|
||||
nPropertyCount++;
|
||||
}
|
||||
|
||||
if ( bReadOnly != bWasReadOnly )
|
||||
{
|
||||
if ( nIndexOfReadOnlyFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "ReadOnly";
|
||||
lDescriptor[nPropertyCount].Value <<= bReadOnly;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
|
||||
}
|
||||
|
||||
if ( !bRepairPackage && bRepairAllowed )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "RepairPackage";
|
||||
lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
|
||||
nPropertyCount++;
|
||||
|
||||
bOpenAsTemplate = true;
|
||||
|
||||
// TODO/LATER: set progress bar that should be used
|
||||
}
|
||||
|
||||
if ( bOpenAsTemplate )
|
||||
{
|
||||
if ( nIndexOfTemplateFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "AsTemplate";
|
||||
lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
|
||||
}
|
||||
|
||||
if ( !aDocumentTitle.isEmpty() )
|
||||
{
|
||||
// the title was set here
|
||||
if ( nIndexOfDocumentTitle == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "DocumentTitle";
|
||||
lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
|
||||
}
|
||||
|
||||
if ( aFilterName.isEmpty() )
|
||||
aTypeName = OUString();
|
||||
|
||||
return aTypeName;
|
||||
return OUString();
|
||||
}
|
||||
|
||||
/* XServiceInfo */
|
||||
@@ -447,7 +113,7 @@ OUString SAL_CALL SmFilterDetect::getImplementationName() throw( RuntimeExceptio
|
||||
{
|
||||
return impl_getStaticImplementationName();
|
||||
}
|
||||
\
|
||||
|
||||
/* XServiceInfo */
|
||||
sal_Bool SAL_CALL SmFilterDetect::supportsService( const OUString& sServiceName ) throw( RuntimeException, std::exception )
|
||||
{
|
||||
|
@@ -56,6 +56,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_htmlexport,\
|
||||
configmgr/source/configmgr \
|
||||
embeddedobj/util/embobj \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
filter/source/textfilterdetect/textfd \
|
||||
forms/util/frm \
|
||||
framework/util/fwk \
|
||||
|
@@ -54,6 +54,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_odfexport,\
|
||||
configmgr/source/configmgr \
|
||||
embeddedobj/util/embobj \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
linguistic/source/lng \
|
||||
|
@@ -56,6 +56,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_odfimport,\
|
||||
configmgr/source/configmgr \
|
||||
embeddedobj/util/embobj \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
lingucomponent/source/languageguessing/guesslang \
|
||||
|
@@ -42,6 +42,7 @@ $(eval $(call gb_CppunitTest_use_ure,sw_ooxmlexport))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_components,sw_ooxmlexport,\
|
||||
$(sw_ooxmlexport_components) \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_configuration,sw_ooxmlexport))
|
||||
|
@@ -42,6 +42,7 @@ $(eval $(call gb_CppunitTest_use_ure,sw_ooxmlsdrexport))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_components,sw_ooxmlsdrexport,\
|
||||
$(sw_ooxmlexport_components) \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_configuration,sw_ooxmlsdrexport))
|
||||
|
@@ -53,6 +53,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_rtfexport,\
|
||||
configmgr/source/configmgr \
|
||||
embeddedobj/util/embobj \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
linguistic/source/lng \
|
||||
|
@@ -56,6 +56,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_rtfimport,\
|
||||
configmgr/source/configmgr \
|
||||
embeddedobj/util/embobj \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
linguistic/source/lng \
|
||||
|
@@ -56,6 +56,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_uiwriter,\
|
||||
configmgr/source/configmgr \
|
||||
embeddedobj/util/embobj \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
linguistic/source/lng \
|
||||
|
@@ -55,6 +55,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_ww8export,\
|
||||
dbaccess/util/dba \
|
||||
embeddedobj/util/embobj \
|
||||
filter/source/config/cache/filterconfig1 \
|
||||
filter/source/storagefilterdetect/storagefd \
|
||||
forms/util/frm \
|
||||
framework/util/fwk \
|
||||
i18npool/util/i18npool \
|
||||
|
@@ -43,12 +43,9 @@ $(eval $(call gb_Library_use_libraries,swd,\
|
||||
sal \
|
||||
sfx \
|
||||
sot \
|
||||
svl \
|
||||
svt \
|
||||
tl \
|
||||
ucbhelper \
|
||||
utl \
|
||||
vcl \
|
||||
$(gb_UWINAPI) \
|
||||
))
|
||||
|
||||
|
@@ -19,52 +19,20 @@
|
||||
|
||||
#include "swdetect.hxx"
|
||||
|
||||
#include <framework/interaction.hxx>
|
||||
#include <com/sun/star/frame/XFrame.hpp>
|
||||
#include <com/sun/star/frame/XModel.hpp>
|
||||
#include <com/sun/star/lang/XUnoTunnel.hpp>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <cppuhelper/supportsservice.hxx>
|
||||
#include <com/sun/star/container/XNameAccess.hpp>
|
||||
#include <com/sun/star/io/XInputStream.hpp>
|
||||
#include <com/sun/star/task/XInteractionHandler.hpp>
|
||||
#include <com/sun/star/ucb/CommandAbortedException.hpp>
|
||||
#include <com/sun/star/ucb/InteractiveAppException.hpp>
|
||||
#include <com/sun/star/ucb/XContent.hpp>
|
||||
#include <com/sun/star/packages/zip/ZipIOException.hpp>
|
||||
#include <toolkit/helper/vclunohelper.hxx>
|
||||
#include <ucbhelper/simpleinteractionrequest.hxx>
|
||||
#include <rtl/ustring.h>
|
||||
#include <svl/itemset.hxx>
|
||||
#include <vcl/window.hxx>
|
||||
#include <svl/eitem.hxx>
|
||||
#include <svl/stritem.hxx>
|
||||
#include <tools/urlobj.hxx>
|
||||
#include <osl/mutex.hxx>
|
||||
#include <svtools/sfxecode.hxx>
|
||||
#include <svtools/ehdl.hxx>
|
||||
#include <sot/storinfo.hxx>
|
||||
#include <vcl/svapp.hxx>
|
||||
#include <sfx2/app.hxx>
|
||||
#include <sfx2/sfxsids.hrc>
|
||||
#include <sfx2/request.hxx>
|
||||
#include <sfx2/docfile.hxx>
|
||||
#include <sfx2/docfilt.hxx>
|
||||
#include <sfx2/fcontnr.hxx>
|
||||
#include <sfx2/brokenpackageint.hxx>
|
||||
#include <vcl/FilterConfigItem.hxx>
|
||||
#include <unotools/moduleoptions.hxx>
|
||||
#include <comphelper/ihwrapnofilter.hxx>
|
||||
#include <iodetect.hxx>
|
||||
#include <sot/storage.hxx>
|
||||
#include <unotools/mediadescriptor.hxx>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
using namespace ::com::sun::star::uno;
|
||||
using namespace ::com::sun::star::io;
|
||||
using namespace ::com::sun::star::frame;
|
||||
using namespace ::com::sun::star::task;
|
||||
using namespace ::com::sun::star::beans;
|
||||
using namespace ::com::sun::star::lang;
|
||||
using namespace ::com::sun::star::ucb;
|
||||
using utl::MediaDescriptor;
|
||||
|
||||
SwFilterDetect::SwFilterDetect( const Reference < XMultiServiceFactory >& /*xFactory*/ )
|
||||
{
|
||||
@@ -76,379 +44,61 @@ SwFilterDetect::~SwFilterDetect()
|
||||
|
||||
OUString SAL_CALL SwFilterDetect::detect( Sequence< PropertyValue >& lDescriptor ) throw( RuntimeException, std::exception )
|
||||
{
|
||||
Reference< XInputStream > xStream;
|
||||
Reference< XContent > xContent;
|
||||
Reference< XInteractionHandler > xInteraction;
|
||||
OUString aURL;
|
||||
OUString sTemp;
|
||||
OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
|
||||
OUString aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action)
|
||||
MediaDescriptor aMediaDesc( lDescriptor );
|
||||
OUString aTypeName = aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_TYPENAME(), OUString() );
|
||||
uno::Reference< io::XInputStream > xInStream ( aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM()], uno::UNO_QUERY );
|
||||
if ( !xInStream.is() )
|
||||
return OUString();
|
||||
|
||||
OUString aDocumentTitle; // interesting only if set in this method
|
||||
SfxMedium aMedium;
|
||||
aMedium.UseInteractionHandler( false );
|
||||
aMedium.setStreamToLoadFrom( xInStream, true );
|
||||
|
||||
// opening as template is done when a parameter tells to do so and a template filter can be detected
|
||||
// (otherwise no valid filter would be found) or if the detected filter is a template filter and
|
||||
// there is no parameter that forbids to open as template
|
||||
bool bOpenAsTemplate = false;
|
||||
bool bWasReadOnly = false, bReadOnly = false;
|
||||
SvStream *pInStrm = aMedium.GetInStream();
|
||||
if ( !pInStrm || pInStrm->GetError() )
|
||||
return OUString();
|
||||
|
||||
bool bRepairPackage = false;
|
||||
bool bRepairAllowed = false;
|
||||
bool bDeepDetection = false;
|
||||
bool bIsDetected = false;
|
||||
|
||||
// now some parameters that can already be in the array, but may be overwritten or new inserted here
|
||||
// remember their indices in the case new values must be added to the array
|
||||
sal_Int32 nPropertyCount = lDescriptor.getLength();
|
||||
sal_Int32 nIndexOfInputStream = -1;
|
||||
sal_Int32 nIndexOfContent = -1;
|
||||
sal_Int32 nIndexOfReadOnlyFlag = -1;
|
||||
sal_Int32 nIndexOfTemplateFlag = -1;
|
||||
sal_Int32 nIndexOfDocumentTitle = -1;
|
||||
sal_Int32 nIndexOfInteractionHandler = -1;
|
||||
|
||||
for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
|
||||
if ( aTypeName == "writer_Rich_Text_Format" )
|
||||
{
|
||||
// extract properties
|
||||
if ( lDescriptor[nProperty].Name == "URL" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if( aURL.isEmpty() && lDescriptor[nProperty].Name == "FileName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aURL = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "TypeName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aTypeName = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "FilterName" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= sTemp;
|
||||
aPreselectedFilterName = sTemp;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "InputStream" )
|
||||
nIndexOfInputStream = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "ReadOnly" )
|
||||
nIndexOfReadOnlyFlag = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "UCBContent" )
|
||||
nIndexOfContent = nProperty;
|
||||
else if ( lDescriptor[nProperty].Name == "AsTemplate" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= bOpenAsTemplate;
|
||||
nIndexOfTemplateFlag = nProperty;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "InteractionHandler" )
|
||||
{
|
||||
lDescriptor[nProperty].Value >>= xInteraction;
|
||||
nIndexOfInteractionHandler = nProperty;
|
||||
}
|
||||
else if ( lDescriptor[nProperty].Name == "RepairPackage" )
|
||||
lDescriptor[nProperty].Value >>= bRepairPackage;
|
||||
else if ( lDescriptor[nProperty].Name == "DocumentTitle" )
|
||||
nIndexOfDocumentTitle = nProperty;
|
||||
else if (lDescriptor[nProperty].Name == "DeepDetection")
|
||||
bDeepDetection = lDescriptor[nProperty].Value.get<sal_Bool>();
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
bIsDetected = ( read_uInt8s_ToOString( *pInStrm, 5 ) == "{\\rtf" );
|
||||
}
|
||||
|
||||
SolarMutexGuard aGuard;
|
||||
|
||||
SfxApplication* pApp = SFX_APP();
|
||||
SfxAllItemSet *pSet = new SfxAllItemSet( pApp->GetPool() );
|
||||
TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
|
||||
SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, false );
|
||||
|
||||
bWasReadOnly = pItem && pItem->GetValue();
|
||||
|
||||
const SfxFilter* pFilter = 0;
|
||||
OUString aPrefix = "private:factory/";
|
||||
if( aURL.startsWith( aPrefix ) )
|
||||
else if ( aTypeName == "writer_MS_WinWord_5" )
|
||||
{
|
||||
if( SvtModuleOptions().IsWriter() )
|
||||
{
|
||||
OUString aPattern = aPrefix + "swriter";
|
||||
if ( aURL.startsWith( aPattern ) )
|
||||
return aTypeName;
|
||||
}
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
const sal_uInt8 nBufSize = 3;
|
||||
sal_uInt8 nBuffer[ nBufSize ];
|
||||
if ( pInStrm->Read( nBuffer, nBufSize ) < nBufSize )
|
||||
return OUString();
|
||||
|
||||
bIsDetected = ( nBuffer[0] == 0xDB && nBuffer[1] == 0xA5 && nBuffer[2] == 0x2D ) // WinWord 2.0 file
|
||||
|| ( nBuffer[0] == 0xDC && nBuffer[1] == 0xA5 && nBuffer[2] == 0x65 ); // WinWord 6.0/95, as a single stream file
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
// Do not attempt to create an SotStorage on a
|
||||
// 0-length stream as that would create the compound
|
||||
// document header on the stream and effectively write to
|
||||
// disk!
|
||||
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
|
||||
if ( pInStrm->remainingSize() == 0 )
|
||||
return OUString();
|
||||
|
||||
SotStorageRef aStorage = new SotStorage ( pInStrm, false );
|
||||
if ( !aStorage->GetError() )
|
||||
{
|
||||
// ctor of SfxMedium uses owner transition of ItemSet
|
||||
SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
|
||||
aMedium.UseInteractionHandler( true );
|
||||
if ( aMedium.GetErrorCode() == ERRCODE_NONE )
|
||||
{
|
||||
// remember input stream and content and put them into the descriptor later
|
||||
// should be done here since later the medium can switch to a version
|
||||
xStream = aMedium.GetInputStream();
|
||||
xContent = aMedium.GetContent();
|
||||
bReadOnly = aMedium.IsReadOnly();
|
||||
|
||||
bool bIsStorage = aMedium.IsStorage();
|
||||
if ( bIsStorage )
|
||||
{
|
||||
Reference< embed::XStorage > xStorage = aMedium.GetStorage( false );
|
||||
if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
|
||||
{
|
||||
// error during storage creation means _here_ that the medium
|
||||
// is broken, but we can not handle it in medium since impossibility
|
||||
// to create a storage does not _always_ means that the medium is broken
|
||||
aMedium.SetError( aMedium.GetLastStorageCreationState(), OUString( OSL_LOG_PREFIX ) );
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
OUString empty;
|
||||
try
|
||||
{
|
||||
InteractiveAppException xException( empty,
|
||||
Reference< XInterface >(),
|
||||
InteractionClassification_ERROR,
|
||||
aMedium.GetError() );
|
||||
|
||||
Reference< XInteractionRequest > xRequest(
|
||||
new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
|
||||
ucbhelper::CONTINUATION_APPROVE ) );
|
||||
xInteraction->handle( xRequest );
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OSL_ENSURE( xStorage.is(), "At this point storage must exist!" );
|
||||
|
||||
try
|
||||
{
|
||||
const SfxFilter* pPreFilter = !aPreselectedFilterName.isEmpty() ?
|
||||
SfxFilterMatcher().GetFilter4FilterName( aPreselectedFilterName ) : !aTypeName.isEmpty() ?
|
||||
SfxFilterMatcher(OUString("swriter")).GetFilter4EA( aTypeName ) : 0;
|
||||
if (!pPreFilter)
|
||||
pPreFilter = SfxFilterMatcher(OUString("sweb")).GetFilter4EA( aTypeName );
|
||||
OUString aFilterName;
|
||||
if ( pPreFilter )
|
||||
{
|
||||
aFilterName = pPreFilter->GetName();
|
||||
aTypeName = pPreFilter->GetTypeName();
|
||||
}
|
||||
|
||||
aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pPreFilter && pPreFilter->IsOwnTemplateFormat(), &aFilterName );
|
||||
}
|
||||
catch (const WrappedTargetException& aWrap)
|
||||
{
|
||||
if (!bDeepDetection)
|
||||
// Bail out early unless it's a deep detection.
|
||||
return OUString();
|
||||
|
||||
packages::zip::ZipIOException aZipException;
|
||||
|
||||
// repairing is done only if this type is requested from outside
|
||||
// we don't do any type detection on broken packages (f.e. because it might be impossible), so any requested
|
||||
// type will be accepted if the user allows to repair the file
|
||||
if ( ( aWrap.TargetException >>= aZipException ) && ( !aTypeName.isEmpty() || !aPreselectedFilterName.isEmpty() ) )
|
||||
{
|
||||
if ( xInteraction.is() )
|
||||
{
|
||||
// the package is a broken one
|
||||
aDocumentTitle = aMedium.GetURLObject().getName(
|
||||
INetURLObject::LAST_SEGMENT,
|
||||
true,
|
||||
INetURLObject::DECODE_WITH_CHARSET );
|
||||
|
||||
if ( !bRepairPackage )
|
||||
{
|
||||
// ask the user whether he wants to try to repair
|
||||
RequestPackageReparation aRequest( aDocumentTitle );
|
||||
xInteraction->handle( aRequest.GetRequest() );
|
||||
bRepairAllowed = aRequest.isApproved();
|
||||
}
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
{
|
||||
// repair either not allowed or not successful
|
||||
// repair either not allowed or not successful
|
||||
NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
|
||||
xInteraction->handle( aNotifyRequest.GetRequest() );
|
||||
|
||||
Reference< ::comphelper::OIHWrapNoFilterDialog > xHandler = new ::comphelper::OIHWrapNoFilterDialog( xInteraction );
|
||||
if ( nIndexOfInteractionHandler != -1 )
|
||||
lDescriptor[nIndexOfInteractionHandler].Value <<= Reference< XInteractionHandler >( static_cast< XInteractionHandler* >( xHandler.get() ) );
|
||||
|
||||
aMedium.SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
// no interaction, error handling as usual
|
||||
aMedium.SetError( ERRCODE_IO_BROKENPACKAGE, OUString( OSL_LOG_PREFIX ) );
|
||||
|
||||
if ( !bRepairAllowed )
|
||||
{
|
||||
aTypeName = "";
|
||||
aPreselectedFilterName = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aMedium.GetInStream();
|
||||
if ( aMedium.GetErrorCode() == ERRCODE_NONE )
|
||||
{
|
||||
if ( !aPreselectedFilterName.isEmpty() )
|
||||
pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
|
||||
else
|
||||
pFilter = SfxFilterMatcher().GetFilter4EA( aTypeName );
|
||||
|
||||
bool bTestWriter = !pFilter || pFilter->GetServiceName() == "com.sun.star.text.TextDocument" ||
|
||||
pFilter->GetServiceName() == "com.sun.star.text.WebDocument";
|
||||
bool bTestGlobal = !pFilter || pFilter->GetServiceName() == "com.sun.star.text.GlobalDocument";
|
||||
|
||||
const SfxFilter* pOrigFilter = NULL;
|
||||
if ( !bTestWriter && !bTestGlobal && pFilter )
|
||||
{
|
||||
// cross filter; now this should be a type detection only, not a filter detection
|
||||
// we can simulate it by preserving the preselected filter if the type matches
|
||||
// example: HTML filter for Calc
|
||||
pOrigFilter = pFilter;
|
||||
pFilter = SfxFilterMatcher().GetFilter4EA( pFilter->GetTypeName() );
|
||||
bTestWriter = true;
|
||||
}
|
||||
|
||||
sal_uLong nErr = ERRCODE_NONE;
|
||||
if ( pFilter || bTestWriter )
|
||||
nErr = DetectFilter( aMedium, &pFilter );
|
||||
if ( nErr != ERRCODE_NONE )
|
||||
pFilter = NULL;
|
||||
else if ( pOrigFilter && pFilter && pFilter->GetTypeName() == pOrigFilter->GetTypeName() )
|
||||
// cross filter, see above
|
||||
pFilter = pOrigFilter;
|
||||
}
|
||||
|
||||
if ( pFilter )
|
||||
aTypeName = pFilter->GetTypeName();
|
||||
else
|
||||
aTypeName = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const RuntimeException&)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
aTypeName = "";
|
||||
aPreselectedFilterName = "";
|
||||
bIsDetected = aStorage->IsContained( "WordDocument" );
|
||||
if ( bIsDetected && aTypeName.startsWith( "writer_MS_Word_97" ) )
|
||||
bIsDetected = ( aStorage->IsContained("0Table") || aStorage->IsContained("1Table") );
|
||||
}
|
||||
}
|
||||
|
||||
if ( nIndexOfInputStream == -1 && xStream.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "InputStream";
|
||||
lDescriptor[nPropertyCount].Value <<= xStream;
|
||||
nPropertyCount++;
|
||||
}
|
||||
if ( bIsDetected )
|
||||
return aTypeName;
|
||||
|
||||
if ( nIndexOfContent == -1 && xContent.is() )
|
||||
{
|
||||
// if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "UCBContent";
|
||||
lDescriptor[nPropertyCount].Value <<= xContent;
|
||||
nPropertyCount++;
|
||||
}
|
||||
|
||||
if ( bReadOnly != bWasReadOnly )
|
||||
{
|
||||
if ( nIndexOfReadOnlyFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "ReadOnly";
|
||||
lDescriptor[nPropertyCount].Value <<= bReadOnly;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
|
||||
}
|
||||
|
||||
if ( !bRepairPackage && bRepairAllowed )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "RepairPackage";
|
||||
lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
|
||||
nPropertyCount++;
|
||||
bOpenAsTemplate = true;
|
||||
// TODO/LATER: set progress bar that should be used
|
||||
}
|
||||
|
||||
if ( bOpenAsTemplate )
|
||||
{
|
||||
if ( nIndexOfTemplateFlag == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "AsTemplate";
|
||||
lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
|
||||
}
|
||||
|
||||
if ( !aDocumentTitle.isEmpty() )
|
||||
{
|
||||
// the title was set here
|
||||
if ( nIndexOfDocumentTitle == -1 )
|
||||
{
|
||||
lDescriptor.realloc( nPropertyCount + 1 );
|
||||
lDescriptor[nPropertyCount].Name = "DocumentTitle";
|
||||
lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
|
||||
nPropertyCount++;
|
||||
}
|
||||
else
|
||||
lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
|
||||
}
|
||||
|
||||
return aTypeName;
|
||||
}
|
||||
|
||||
sal_uLong SwFilterDetect::DetectFilter( SfxMedium& rMedium, const SfxFilter** ppFilter )
|
||||
{
|
||||
sal_uLong nRet = ERRCODE_NONE;
|
||||
if( *ppFilter )
|
||||
{
|
||||
// verify the given filter
|
||||
OUString aPrefFlt = (*ppFilter)->GetUserData();
|
||||
|
||||
// detection for TextFilter needs an additional checking
|
||||
bool bDetected = SwIoSystem::IsFileFilter(rMedium, aPrefFlt);
|
||||
return bDetected ? nRet : ERRCODE_ABORT;
|
||||
}
|
||||
|
||||
// mba: without preselection there is no PrefFlt
|
||||
OUString aPrefFlt;
|
||||
const SfxFilter* pTmp = SwIoSystem::GetFileFilter( rMedium.GetPhysicalName(), aPrefFlt, &rMedium );
|
||||
if( !pTmp )
|
||||
return ERRCODE_ABORT;
|
||||
|
||||
else
|
||||
{
|
||||
//Bug 41417: JP 09.07.97: HTML documents should be loaded by WebWriter
|
||||
SfxFilterContainer aFilterContainer( OUString("swriter/web") );
|
||||
if( !pTmp->GetUserData().equals(sHTML) ||
|
||||
pTmp->GetServiceName() == "com.sun.star.text.WebDocument" ||
|
||||
0 == ( (*ppFilter) = SwIoSystem::GetFilterOfFormat( OUString(sHTML),
|
||||
&aFilterContainer ) ) )
|
||||
*ppFilter = pTmp;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
return OUString();
|
||||
}
|
||||
|
||||
/* XServiceInfo */
|
||||
@@ -456,7 +106,7 @@ OUString SAL_CALL SwFilterDetect::getImplementationName() throw( RuntimeExceptio
|
||||
{
|
||||
return impl_getStaticImplementationName();
|
||||
}
|
||||
\
|
||||
|
||||
/* XServiceInfo */
|
||||
sal_Bool SAL_CALL SwFilterDetect::supportsService( const OUString& sServiceName ) throw( RuntimeException, std::exception )
|
||||
{
|
||||
|
@@ -57,8 +57,6 @@ class SfxFilter;
|
||||
|
||||
class SwFilterDetect : public ::cppu::WeakImplHelper2< css::document::XExtendedFilterDetection, css::lang::XServiceInfo >
|
||||
{
|
||||
static sal_uLong DetectFilter( SfxMedium& rMedium, const SfxFilter** ppFilter );
|
||||
static sal_uLong GlobDetectFilter( SfxMedium& rMedium, const SfxFilter** ppFilter );
|
||||
public:
|
||||
SwFilterDetect( const css::uno::Reference < css::lang::XMultiServiceFactory >& xFactory );
|
||||
virtual ~SwFilterDetect();
|
||||
|
Reference in New Issue
Block a user