Detect WMF from header instead of extension

Change ImpDetectWMF function to detect a WMF file
from its header instead of just comparing the extension.

Change-Id: I5a31cfd52b5425ab94424c2edce842365db04e8c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134876
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/vcl/source/filter/graphicfilter2.cxx b/vcl/source/filter/graphicfilter2.cxx
index c02e9d5..fb001ee 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -30,9 +30,24 @@
#include "graphicfilter_internal.hxx"

#define DATA_SIZE           640
constexpr sal_uInt32 EMF_CHECK_SIZE    = 44;
constexpr sal_uInt32 EMR_HEADER        = 0x00000001;
constexpr sal_uInt32 ENHMETA_SIGNATURE = 0x464d4520;
constexpr sal_uInt32 EMF_CHECK_SIZE      = 44;
constexpr sal_uInt32 WMF_CHECK_SIZE      = 32;
constexpr sal_uInt32 EMR_HEADER          = 0x00000001;
constexpr sal_uInt32 ENHMETA_SIGNATURE   = 0x464d4520;
constexpr sal_uInt32 PLACEABLE_SIGNATURE = 0xd7cdc69a;
namespace
{
enum class MetafileType : sal_uInt16
{
    Memory = 0x0001,
    Disk   = 0x0002,
};
enum class MetafileVersion : sal_uInt16
{
    Version100 = 0x0100,
    Version300 = 0x0300,
};
}

GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
    pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ).release() ),
@@ -1081,12 +1096,49 @@ bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, bool bExtendedInfo )
    return bRet;
}

bool GraphicDescriptor::ImpDetectWMF( SvStream&, bool )
bool GraphicDescriptor::ImpDetectWMF(SvStream& rStm, bool)
{
    bool bRet = aPathExt.startsWith( "wmf" ) || aPathExt.startsWith( "wmz" );
    if (bRet)
    bool bRet = false;
    SvStream* aNewStream = &rStm;
    SvMemoryStream aMemStream;
    sal_uInt8 aUncompressedBuffer[WMF_CHECK_SIZE];
    if (ZCodec::IsZCompressed(rStm))
    {
        ZCodec aCodec;
        aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/ true);
        auto nDecompressLength = aCodec.Read(rStm, aUncompressedBuffer, WMF_CHECK_SIZE);
        aCodec.EndCompression();
        if (nDecompressLength != WMF_CHECK_SIZE)
            return false;
        aMemStream.SetBuffer(aUncompressedBuffer, WMF_CHECK_SIZE, WMF_CHECK_SIZE);
        aNewStream = &aMemStream;
    }
    sal_uInt32 nKey = 0;
    sal_Int32 nStmPos = rStm.Tell();
    aNewStream->SetEndian(SvStreamEndian::LITTLE);
    aNewStream->ReadUInt32(nKey);
    // Check if file is placeable WMF
    if (nKey == PLACEABLE_SIGNATURE)
    {
        nFormat = GraphicFileFormat::WMF;
        bRet = true;
    }
    else
    {
        sal_uInt16 nKeyLSW = nKey & 0xFFFF;
        sal_uInt16 nVersion = 0;
        aNewStream->ReadUInt16(nVersion);
        if ((nKeyLSW == static_cast<sal_uInt16>(MetafileType::Memory)
            || nKeyLSW == static_cast<sal_uInt16>(MetafileType::Disk))
            && (nVersion == static_cast<sal_uInt16>(MetafileVersion::Version100)
            || nVersion == static_cast<sal_uInt16>(MetafileVersion::Version300)))
        {
            nFormat = GraphicFileFormat::WMF;
            bRet = true;
        }
    }

    rStm.Seek(nStmPos);
    return bRet;
}