diff options
-rw-r--r-- | filter/CppunitTest_filter_textfilterdetect.mk | 7 | ||||
-rw-r--r-- | filter/Library_textfd.mk | 1 | ||||
-rw-r--r-- | filter/qa/unit/data/empty.pptx | 0 | ||||
-rw-r--r-- | filter/qa/unit/textfilterdetect.cxx | 68 | ||||
-rw-r--r-- | filter/source/textfilterdetect/filterdetect.cxx | 32 | ||||
-rw-r--r-- | include/tools/stream.hxx | 6 | ||||
-rw-r--r-- | sfx2/source/doc/objstor.cxx | 6 | ||||
-rw-r--r-- | tools/source/stream/stream.cxx | 20 |
8 files changed, 111 insertions, 29 deletions
diff --git a/filter/CppunitTest_filter_textfilterdetect.mk b/filter/CppunitTest_filter_textfilterdetect.mk index dfcaee9ce16a..49cd09fd79b4 100644 --- a/filter/CppunitTest_filter_textfilterdetect.mk +++ b/filter/CppunitTest_filter_textfilterdetect.mk @@ -34,12 +34,7 @@ $(eval $(call gb_CppunitTest_use_ure,filter_textfilterdetect)) $(eval $(call gb_CppunitTest_use_vcl,filter_textfilterdetect)) -$(eval $(call gb_CppunitTest_use_components,filter_textfilterdetect,\ - configmgr/source/configmgr \ - filter/source/textfilterdetect/textfd \ - ucb/source/core/ucb1 \ - ucb/source/ucp/file/ucpfile1 \ -)) +$(eval $(call gb_CppunitTest_use_rdb,filter_textfilterdetect,services)) $(eval $(call gb_CppunitTest_use_configuration,filter_textfilterdetect)) diff --git a/filter/Library_textfd.mk b/filter/Library_textfd.mk index e6d3889410af..c6155f1e9876 100644 --- a/filter/Library_textfd.mk +++ b/filter/Library_textfd.mk @@ -23,6 +23,7 @@ $(eval $(call gb_Library_use_libraries,textfd,\ cppuhelper \ cppu \ sal \ + sfx \ tl \ utl \ svt \ diff --git a/filter/qa/unit/data/empty.pptx b/filter/qa/unit/data/empty.pptx new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/filter/qa/unit/data/empty.pptx diff --git a/filter/qa/unit/textfilterdetect.cxx b/filter/qa/unit/textfilterdetect.cxx index 3711c416c2c5..cc86fe04c3d5 100644 --- a/filter/qa/unit/textfilterdetect.cxx +++ b/filter/qa/unit/textfilterdetect.cxx @@ -7,49 +7,60 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> + #include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> #include <comphelper/processfactory.hxx> #include <comphelper/propertyvalue.hxx> -#include <test/bootstrapfixture.hxx> #include <unotools/mediadescriptor.hxx> #include <unotools/streamwrap.hxx> +#include <tools/stream.hxx> -namespace com -{ -namespace sun -{ -namespace star -{ -namespace io +namespace com::sun::star::io { class XInputStream; } -} -} -} using namespace com::sun::star; namespace { /// Test class for PlainTextFilterDetect. -class TextFilterDetectTest : public test::BootstrapFixture +class TextFilterDetectTest : public test::BootstrapFixture, public unotest::MacrosTest { -public: - void testTdf114428(); + uno::Reference<uno::XComponentContext> mxComponentContext; + uno::Reference<lang::XComponent> mxComponent; - CPPUNIT_TEST_SUITE(TextFilterDetectTest); - CPPUNIT_TEST(testTdf114428); - CPPUNIT_TEST_SUITE_END(); +public: + void setUp() override; + void tearDown() override; + uno::Reference<lang::XComponent>& getComponent() { return mxComponent; } }; +void TextFilterDetectTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory())); + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void TextFilterDetectTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); +} + char const DATA_DIRECTORY[] = "/filter/qa/unit/data/"; -void TextFilterDetectTest::testTdf114428() +CPPUNIT_TEST_FIXTURE(TextFilterDetectTest, testTdf114428) { - uno::Reference<uno::XComponentContext> xComponentContext - = comphelper::getComponentContext(getMultiServiceFactory()); uno::Reference<document::XExtendedFilterDetection> xDetect( getMultiServiceFactory()->createInstance("com.sun.star.comp.filters.PlainTextFilterDetect"), uno::UNO_QUERY); @@ -68,7 +79,22 @@ void TextFilterDetectTest::testTdf114428() CPPUNIT_ASSERT_EQUAL(OUString("HTML (StarWriter)"), aFilterName); } -CPPUNIT_TEST_SUITE_REGISTRATION(TextFilterDetectTest); +CPPUNIT_TEST_FIXTURE(TextFilterDetectTest, testEmptyFile) +{ + // Given an empty file, with a pptx extension + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "empty.pptx"; + + // When loading the file + getComponent() = loadFromDesktop(aURL); + + // Then make sure it is opened in Impress. + uno::Reference<lang::XServiceInfo> xServiceInfo(getComponent(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xServiceInfo.is()); + + // Without the accompanying fix in place, this test would have failed, as it was opened in + // Writer instead. + CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.presentation.PresentationDocument")); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/filter/source/textfilterdetect/filterdetect.cxx b/filter/source/textfilterdetect/filterdetect.cxx index cb0055c34565..c18751c0e66c 100644 --- a/filter/source/textfilterdetect/filterdetect.cxx +++ b/filter/source/textfilterdetect/filterdetect.cxx @@ -21,6 +21,8 @@ #include <com/sun/star/io/XInputStream.hpp> #include <cppuhelper/supportsservice.hxx> #include <memory> +#include <sfx2/fcontnr.hxx> +#include <sfx2/docfilt.hxx> #define WRITER_TEXT_FILTER "Text" #define CALC_TEXT_FILTER "Text - txt - csv (StarCalc)" @@ -129,6 +131,34 @@ bool IsHTMLStream( const uno::Reference<io::XInputStream>& xInStream ) return GetHTMLToken( OStringToOUString( aToken.toAsciiLowerCase(), RTL_TEXTENCODING_ASCII_US ) ) != HtmlTokenId::NONE; } +/** + * Given an (empty) file URL in rMediaDesc and rExt, looks up the best filter type for it and + * writes the type name to rType, the filter name to rMediaDesc. + */ +bool HandleEmptyFileUrlByExtension(MediaDescriptor& rMediaDesc, const OUString& rExt, + OUString& rType) +{ + OUString aURL = rMediaDesc.getUnpackedValueOrDefault(MediaDescriptor::PROP_URL(), OUString()); + if (!tools::isEmptyFileUrl(aURL)) + { + return false; + } + + if (rExt.isEmpty()) + { + return false; + } + + std::shared_ptr<const SfxFilter> pFilter(SfxFilterMatcher().GetFilter4Extension(rExt)); + if (!pFilter) + { + return false; + } + + rMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= pFilter->GetFilterName(); + rType = pFilter->GetTypeName(); + return true; +} } PlainTextFilterDetect::PlainTextFilterDetect() {} @@ -194,7 +224,7 @@ OUString SAL_CALL PlainTextFilterDetect::detect(uno::Sequence<beans::PropertyVal aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= OUString(WRITER_TEXT_FILTER); else if (aExt == "csv" || aExt == "tsv" || aExt == "tab" || aExt == "xls" || aName.endsWith(".csv.gz")) aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= OUString(CALC_TEXT_FILTER); - else + else if (!HandleEmptyFileUrlByExtension(aMediaDesc, aExt, aType)) aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= OUString(WRITER_TEXT_FILTER); } diff --git a/include/tools/stream.hxx b/include/tools/stream.hxx index 370372aba454..c258425cdd0c 100644 --- a/include/tools/stream.hxx +++ b/include/tools/stream.hxx @@ -568,6 +568,12 @@ inline std::size_t write_uInt16_lenPrefixed_uInt8s_FromOUString(SvStream& rStrm, SAL_WARN_UNUSED_RESULT TOOLS_DLLPUBLIC bool checkSeek(SvStream &rSt, sal_uInt64 nOffset); +namespace tools +{ +/// Is rUrl a file:// URL with no contents? +TOOLS_DLLPUBLIC bool isEmptyFileUrl(const OUString& rUrl); +} + // FileStream class TOOLS_DLLPUBLIC SvFileStream : public SvStream diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx index 66ec9a8d16f6..50ec51f7e546 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -2220,7 +2220,11 @@ bool SfxObjectShell::ImportFrom(SfxMedium& rMedium, // #i119492# During loading, some OLE objects like chart will be set // modified flag, so needs to reset the flag to false after loading - bool bRtn = xLoader->filter( aArgs ); + bool bRtn = true; + if (!tools::isEmptyFileUrl(rMedium.GetName())) + { + bRtn = xLoader->filter(aArgs); + } uno::Sequence < OUString > aNames = GetEmbeddedObjectContainer().GetObjectNames(); for ( sal_Int32 n = 0; n < aNames.getLength(); ++n ) { diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx index ea9f533b3af3..49ebb1ba7512 100644 --- a/tools/source/stream/stream.cxx +++ b/tools/source/stream/stream.cxx @@ -33,6 +33,7 @@ #include <sal/log.hxx> #include <comphelper/fileformat.h> +#include <comphelper/fileurl.hxx> static void swapNibbles(unsigned char &c) { @@ -1408,6 +1409,25 @@ bool checkSeek(SvStream &rSt, sal_uInt64 nOffset) return (nOffset <= nMaxSeek && rSt.Seek(nOffset) == nOffset); } +namespace tools +{ +bool isEmptyFileUrl(const OUString& rUrl) +{ + if (!comphelper::isFileUrl(rUrl)) + { + return false; + } + + SvFileStream aStream(rUrl, StreamMode::READ); + if (!aStream.IsOpen()) + { + return false; + } + + return aStream.remainingSize() == 0; +} +} + //STREAM_SEEK_TO_END in some of the Seek backends is special cased to be //efficient, in others e.g. SotStorageStream it's really horribly slow, and in //those this should be overridden |