change type detection to use GraphicFormatDetector
ImpPeekGraphicFormat now uses GraphicFormatDetector for type
detection.
Change-Id: I4ef2c3c57f72466fcb8c56c64a30f00ad6421d25
Reviewed-on: https://gerrit.libreoffice.org/72137
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index ecc9001..b5090fa 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -246,13 +246,6 @@ bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension, bool b
if (!aDetector.detect())
return false;
sal_uInt8* sFirstBytes = aDetector.maFirstBytes.data();
sal_uLong nFirstLong = aDetector.mnFirstLong;
sal_uLong nSecondLong = aDetector.mnSecondLong;
sal_uLong nStreamPos = aDetector.mnStreamPosition;
sal_uLong nStreamLen = aDetector.mnStreamLength;
// The following variable is used when bTest == true. It remains false
// if the format (rFormatExtension) has not yet been set.
bool bSomethingTested = false;
@@ -264,446 +257,236 @@ bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension, bool b
// Therefore, in the case of a format check (bTest == true) we only test *exactly* this
// format. Everything else could have fatal consequences, for example if the user says it is
// a BMP file (and it is a BMP) file, and the file would go through the MET test ...
//--------------------------- MET ------------------------------------
if( !bTest || rFormatExtension.startsWith( "MET" ) )
{
bSomethingTested=true;
if( sFirstBytes[2] == 0xd3 )
{
rStream.SetEndian( SvStreamEndian::BIG );
rStream.Seek( nStreamPos );
sal_uInt16 nFieldSize;
sal_uInt8 nMagic;
bool bOK=true;
rStream.ReadUInt16( nFieldSize ).ReadUChar( nMagic );
for (int i=0; i<3; i++) {
if (nFieldSize<6) { bOK=false; break; }
if (nStreamLen < rStream.Tell() + nFieldSize ) { bOK=false; break; }
rStream.SeekRel(nFieldSize-3);
rStream.ReadUInt16( nFieldSize ).ReadUChar( nMagic );
if (nMagic!=0xd3) { bOK=false; break; }
}
rStream.SetEndian( SvStreamEndian::LITTLE );
if (bOK && !rStream.GetError()) {
rFormatExtension = "MET";
return true;
}
}
}
//--------------------------- BMP ------------------------------------
if( !bTest || rFormatExtension.startsWith( "BMP" ) )
{
sal_uInt8 nOffs;
bSomethingTested=true;
// We're possibly also able to read an OS/2 bitmap array
// ('BA'), therefore we must adjust the offset to discover the
// first bitmap in the array
if ( sFirstBytes[0] == 0x42 && sFirstBytes[1] == 0x41 )
nOffs = 14;
else
nOffs = 0;
// Now we initially test on 'BM'
if ( sFirstBytes[0+nOffs]==0x42 && sFirstBytes[1+nOffs]==0x4d )
{
// OS/2 can set the Reserved flags to a value other than 0
// (which they really should not do...);
// In this case we test the size of the BmpInfoHeaders
if ( ( sFirstBytes[6+nOffs]==0x00 &&
sFirstBytes[7+nOffs]==0x00 &&
sFirstBytes[8+nOffs]==0x00 &&
sFirstBytes[9+nOffs]==0x00 ) ||
sFirstBytes[14+nOffs] == 0x28 ||
sFirstBytes[14+nOffs] == 0x0c )
{
rFormatExtension = "BMP";
return true;
}
}
}
//--------------------------- WMF/EMF ------------------------------------
if( !bTest ||
rFormatExtension.startsWith( "WMF" ) ||
rFormatExtension.startsWith( "EMF" ) )
if (!bTest || rFormatExtension.startsWith("MET"))
{
bSomethingTested = true;
if ( nFirstLong==0xd7cdc69a || nFirstLong==0x01000900 )
if (aDetector.checkMET())
{
rFormatExtension = "WMF";
return true;
}
else if( nFirstLong == 0x01000000 && sFirstBytes[ 40 ] == 0x20 && sFirstBytes[ 41 ] == 0x45 &&
sFirstBytes[ 42 ] == 0x4d && sFirstBytes[ 43 ] == 0x46 )
{
rFormatExtension = "EMF";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
//--------------------------- PCX ------------------------------------
if( !bTest || rFormatExtension.startsWith( "PCX" ) )
{
bSomethingTested=true;
if (sFirstBytes[0]==0x0a)
{
sal_uInt8 nVersion=sFirstBytes[1];
sal_uInt8 nEncoding=sFirstBytes[2];
if( ( nVersion==0 || nVersion==2 || nVersion==3 || nVersion==5 ) && nEncoding<=1 )
{
rFormatExtension = "PCX";
return true;
}
}
}
//--------------------------- TIF ------------------------------------
if( !bTest || rFormatExtension.startsWith( "TIF" ) )
{
bSomethingTested=true;
if ( nFirstLong==0x49492a00 || nFirstLong==0x4d4d002a )
{
rFormatExtension = "TIF";
return true;
}
}
//--------------------------- GIF ------------------------------------
if( !bTest || rFormatExtension.startsWith( "GIF" ) )
{
bSomethingTested=true;
if ( nFirstLong==0x47494638 && (sFirstBytes[4]==0x37 || sFirstBytes[4]==0x39) && sFirstBytes[5]==0x61 )
{
rFormatExtension = "GIF";
return true;
}
}
//--------------------------- PNG ------------------------------------
if( !bTest || rFormatExtension.startsWith( "PNG" ) )
{
bSomethingTested=true;
if (nFirstLong==0x89504e47 && nSecondLong==0x0d0a1a0a)
{
rFormatExtension = "PNG";
return true;
}
}
//--------------------------- JPG ------------------------------------
if( !bTest || rFormatExtension.startsWith( "JPG" ) )
{
bSomethingTested=true;
if ( ( nFirstLong==0xffd8ffe0 && sFirstBytes[6]==0x4a && sFirstBytes[7]==0x46 && sFirstBytes[8]==0x49 && sFirstBytes[9]==0x46 ) ||
( nFirstLong==0xffd8fffe ) || ( 0xffd8ff00 == ( nFirstLong & 0xffffff00 ) ) )
{
rFormatExtension = "JPG";
return true;
}
}
//--------------------------- SVM ------------------------------------
if( !bTest || rFormatExtension.startsWith( "SVM" ) )
{
bSomethingTested=true;
if( nFirstLong==0x53564744 && sFirstBytes[4]==0x49 )
{
rFormatExtension = "SVM";
return true;
}
else if( sFirstBytes[0]==0x56 && sFirstBytes[1]==0x43 && sFirstBytes[2]==0x4C &&
sFirstBytes[3]==0x4D && sFirstBytes[4]==0x54 && sFirstBytes[5]==0x46 )
{
rFormatExtension = "SVM";
return true;
}
}
//--------------------------- PCD ------------------------------------
if( !bTest || rFormatExtension.startsWith( "PCD" ) )
if (!bTest || rFormatExtension.startsWith("BMP"))
{
bSomethingTested = true;
if( nStreamLen >= 2055 )
if (aDetector.checkBMP())
{
char sBuf[8];
rStream.Seek( nStreamPos + 2048 );
rStream.ReadBytes( sBuf, 7 );
if( strncmp( sBuf, "PCD_IPI", 7 ) == 0 )
{
rFormatExtension = "PCD";
return true;
}
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
//--------------------------- PSD ------------------------------------
if( !bTest || rFormatExtension.startsWith( "PSD" ) )
if (!bTest ||
rFormatExtension.startsWith("WMF") ||
rFormatExtension.startsWith("EMF"))
{
bSomethingTested = true;
if ( ( nFirstLong == 0x38425053 ) && ( (nSecondLong >> 16 ) == 1 ) )
if (aDetector.checkWMForEMF())
{
rFormatExtension = "PSD";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
//--------------------------- EPS ------------------------------------
if( !bTest || rFormatExtension.startsWith( "EPS" ) )
if (!bTest || rFormatExtension.startsWith("PCX"))
{
bSomethingTested = true;
if ( ( nFirstLong == 0xC5D0D3C6 ) || ( ImplSearchEntry( sFirstBytes, reinterpret_cast<sal_uInt8 const *>("%!PS-Adobe"), 10, 10 ) &&
ImplSearchEntry( &sFirstBytes[15], reinterpret_cast<sal_uInt8 const *>("EPS"), 3, 3 ) ) )
if (aDetector.checkPCX())
{
rFormatExtension = "EPS";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
//--------------------------- DXF ------------------------------------
if( !bTest || rFormatExtension.startsWith( "DXF" ) )
{
// Binary DXF File Format
if( strncmp( reinterpret_cast<char*>(sFirstBytes), "AutoCAD Binary DXF", 18 ) == 0 )
{
rFormatExtension = "DXF";
return true;
}
// ASCII DXF File Format
int i=0;
while (i<256 && sFirstBytes[i]<=32)
++i;
if (i<256 && sFirstBytes[i]=='0')
{
++i;
// only now do we have sufficient data to make a judgement
// based on a '0' + 'SECTION' == DXF argument
bSomethingTested=true;
while( i<256 && sFirstBytes[i]<=32 )
++i;
if (i+7<256 && (strncmp(reinterpret_cast<char*>(sFirstBytes+i),"SECTION",7)==0))
{
rFormatExtension = "DXF";
return true;
}
}
}
//--------------------------- PCT ------------------------------------
if( !bTest || rFormatExtension.startsWith( "PCT" ) )
if (!bTest || rFormatExtension.startsWith("TIF"))
{
bSomethingTested = true;
if (isPCT(rStream, nStreamPos, nStreamLen))
if (aDetector.checkTIF())
{
rFormatExtension = "PCT";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
//------------------------- PBM + PGM + PPM ---------------------------
if( !bTest ||
rFormatExtension.startsWith( "PBM" ) ||
rFormatExtension.startsWith( "PGM" ) ||
rFormatExtension.startsWith( "PPM" ) )
{
bSomethingTested=true;
if ( sFirstBytes[ 0 ] == 'P' )
{
switch( sFirstBytes[ 1 ] )
{
case '1' :
case '4' :
rFormatExtension = "PBM";
return true;
case '2' :
case '5' :
rFormatExtension = "PGM";
return true;
case '3' :
case '6' :
rFormatExtension = "PPM";
return true;
}
}
}
//--------------------------- RAS( SUN RasterFile )------------------
if( !bTest || rFormatExtension.startsWith( "RAS" ) )
{
bSomethingTested=true;
if( nFirstLong == 0x59a66a95 )
{
rFormatExtension = "RAS";
return true;
}
}
//--------------------------- XPM ------------------------------------
if( !bTest )
if (!bTest || rFormatExtension.startsWith("GIF"))
{
bSomethingTested = true;
if( ImplSearchEntry( sFirstBytes, reinterpret_cast<sal_uInt8 const *>("/* XPM */"), 256, 9 ) )
if (aDetector.checkGIF())
{
rFormatExtension = "XPM";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
else if( rFormatExtension.startsWith( "XPM" ) )
if (!bTest || rFormatExtension.startsWith("PNG"))
{
bSomethingTested = true;
if (aDetector.checkPNG())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("JPG"))
{
bSomethingTested = true;
if (aDetector.checkJPG())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("SVM"))
{
bSomethingTested = true;
if (aDetector.checkSVM())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("PCD"))
{
bSomethingTested = true;
if (aDetector.checkPCD())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("PSD"))
{
bSomethingTested = true;
if (aDetector.checkPSD())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("EPS"))
{
bSomethingTested = true;
if (aDetector.checkEPS())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("DXF"))
{
if (aDetector.checkDXF())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("PCT"))
{
bSomethingTested = true;
if (aDetector.checkPCT())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest ||
rFormatExtension.startsWith("PBM") ||
rFormatExtension.startsWith("PGM") ||
rFormatExtension.startsWith("PPM"))
{
bSomethingTested = true;
if (aDetector.checkPBMorPGMorPPM())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("RAS"))
{
bSomethingTested = true;
if (aDetector.checkRAS())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest)
{
bSomethingTested = true;
if (aDetector.checkXPM())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
else if (rFormatExtension.startsWith("XPM"))
{
return true;
}
//--------------------------- XBM ------------------------------------
if( !bTest )
if (!bTest)
{
sal_uLong nSize = std::min<sal_uLong>( nStreamLen, 2048 );
std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8 [ nSize ]);
rStream.Seek( nStreamPos );
rStream.ReadBytes( pBuf.get(), nSize );
sal_uInt8* pPtr = ImplSearchEntry( pBuf.get(), reinterpret_cast<sal_uInt8 const *>("#define"), nSize, 7 );
if( pPtr )
if (aDetector.checkXBM())
{
if( ImplSearchEntry( pPtr, reinterpret_cast<sal_uInt8 const *>("_width"), pBuf.get() + nSize - pPtr, 6 ) )
{
rFormatExtension = "XBM";
return true;
}
}
}
else if( rFormatExtension.startsWith( "XBM" ) )
{
return true;
}
//--------------------------- SVG ------------------------------------
if( !bTest )
{
sal_uInt8* pCheckArray = sFirstBytes;
sal_uLong nCheckSize = std::min<sal_uLong>(nStreamLen, 256);
sal_uInt8 sExtendedOrDecompressedFirstBytes[2048];
sal_uLong nDecompressedSize = nCheckSize;
bool bIsGZip(false);
// check if it is gzipped -> svgz
if(sFirstBytes[0] == 0x1F && sFirstBytes[1] == 0x8B)
{
ZCodec aCodec;
rStream.Seek(nStreamPos);
aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, false, true);
nDecompressedSize = aCodec.Read(rStream, sExtendedOrDecompressedFirstBytes, 2048);
nCheckSize = std::min<sal_uLong>(nDecompressedSize, 256);
aCodec.EndCompression();
pCheckArray = sExtendedOrDecompressedFirstBytes;
bIsGZip = true;
}
bool bIsSvg(false);
// check for Xml
// #119176# SVG files which have no xml header at all have shown up this is optional
if( ImplSearchEntry(pCheckArray, reinterpret_cast<sal_uInt8 const *>("<?xml"), nCheckSize, 5 ) // is it xml
&& ImplSearchEntry(pCheckArray, reinterpret_cast<sal_uInt8 const *>("version"), nCheckSize, 7 )) // does it have a version (required for xml)
{
// check for DOCTYPE svg combination
if( ImplSearchEntry(pCheckArray, reinterpret_cast<sal_uInt8 const *>("DOCTYPE"), nCheckSize, 7 ) // 'DOCTYPE' is there
&& ImplSearchEntry(pCheckArray, reinterpret_cast<sal_uInt8 const *>("svg"), nCheckSize, 3 )) // 'svg' is there
{
bIsSvg = true;
}
}
// check for svg element in 1st 256 bytes
if(!bIsSvg && ImplSearchEntry(pCheckArray, reinterpret_cast<sal_uInt8 const *>("<svg"), nCheckSize, 4 )) // '<svg'
{
bIsSvg = true;
}
// extended search for svg element
if(!bIsSvg)
{
// it's a xml, look for '<svg' in full file. Should not happen too
// often since the tests above will handle most cases, but can happen
// with Svg files containing big comment headers or Svg as the host
// language
pCheckArray = sExtendedOrDecompressedFirstBytes;
if (bIsGZip)
{
nCheckSize = std::min<sal_uLong>(nDecompressedSize, 2048);
}
else
{
nCheckSize = std::min<sal_uLong>(nStreamLen, 2048);
rStream.Seek(nStreamPos);
nCheckSize = rStream.ReadBytes(sExtendedOrDecompressedFirstBytes, nCheckSize);
}
if(ImplSearchEntry(pCheckArray, reinterpret_cast<sal_uInt8 const *>("<svg"), nCheckSize, 4)) // '<svg'
{
bIsSvg = true;
}
}
if(bIsSvg)
{
rFormatExtension = "SVG";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
else if( rFormatExtension.startsWith( "SVG" ) )
else if (rFormatExtension.startsWith("XBM"))
{
return true;
}
//--------------------------- TGA ------------------------------------
if( !bTest || rFormatExtension.startsWith( "TGA" ) )
if (!bTest)
{
if (aDetector.checkSVG())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
else if (rFormatExtension.startsWith("SVG"))
{
return true;
}
if (!bTest || rFormatExtension.startsWith("TGA"))
{
bSomethingTested = true;
// just a simple test for the extension
if( rFormatExtension.startsWith( "TGA" ) )
if (aDetector.checkTGA())
{
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if(!bTest || rFormatExtension.startsWith( "MOV" ))
if (!bTest || rFormatExtension.startsWith("MOV"))
{
if ((sFirstBytes[ 4 ] == 'f' && sFirstBytes[ 5 ] == 't' && sFirstBytes[ 6 ] == 'y' &&
sFirstBytes[ 7 ] == 'p' && sFirstBytes[ 8 ] == 'q' && sFirstBytes[ 9 ] == 't') ||
(sFirstBytes[ 4 ] == 'm' && sFirstBytes[ 5 ] == 'o' && sFirstBytes[ 6 ] == 'o' &&
sFirstBytes[ 7 ] == 'v' && sFirstBytes[ 11 ] == 'l' && sFirstBytes[ 12 ] == 'm'))
if (aDetector.checkMOV())
{
rFormatExtension = "MOV";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}
if (!bTest || rFormatExtension.startsWith("PDF"))
{
if (sFirstBytes[0] == '%' && sFirstBytes[1] == 'P' && sFirstBytes[2] == 'D' &&
sFirstBytes[3] == 'F' && sFirstBytes[4] == '-')
if (aDetector.checkPDF())
{
rFormatExtension = "PDF";
rFormatExtension = aDetector.msDetectedFormat;
return true;
}
}