From 9aef56a9737808c74ff6898d77b162be9fa6e032 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 15 Jan 2023 11:27:08 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=A0=B9=E6=8D=AEfile=20magi?= =?UTF-8?q?c=20number=E5=88=A4=E6=96=AD=E6=96=87=E4=BB=B6=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 + .../cn/hutool/core/io/FileMagicNumber.java | 535 +++++++++--------- 2 files changed, 272 insertions(+), 265 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 003c25b7e..9aaee2adc 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,11 @@ ### 🐣新特性 * 【core 】 XmlUtil.readObjectFromXml增加注入漏洞的警告注释,并标识为废弃(issue#2857@Github) * 【http 】 HttpGlobalConfig.allowPatch()调用时忽略错误(issue#2832@Github) +* 【core 】 重构根据file magic number判断文件类型(pr#2834@Github) ### 🐞Bug修复 * 【core 】 修复HexUtil.isHexNumber()对"-"的判断问题(issue#2857@Github) +* 【core 】 修复FileTypeUtil判断wav后缀的录音文件类型不能匹配问题(pr#2834@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileMagicNumber.java b/hutool-core/src/main/java/cn/hutool/core/io/FileMagicNumber.java index ab8051391..c6d142075 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileMagicNumber.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileMagicNumber.java @@ -6,17 +6,23 @@ import java.math.BigInteger; import java.util.Arrays; import java.util.Objects; +/** + * 文件类型魔数封装 + * + * @author CherryRum + * @since 5.8.12 + */ public enum FileMagicNumber { UNKNOWN(null, null) { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return false; } }, //image start--------------------------------------------- JPEG("image/jpeg", "jpg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0xff) && Objects.equals(bytes[1], (byte) 0xd8) @@ -25,7 +31,7 @@ public enum FileMagicNumber { }, JXR("image/vnd.ms-photo", "jxr") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { //file magic number https://www.iana.org/assignments/media-types/image/jxr return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x49) @@ -35,8 +41,8 @@ public enum FileMagicNumber { }, APNG("image/apng", "apng") { @Override - public boolean match(byte[] bytes) { - boolean b = bytes.length > 8 + public boolean match(final byte[] bytes) { + final boolean b = bytes.length > 8 && Objects.equals(bytes[0], (byte) 0x89) && Objects.equals(bytes[1], (byte) 0x50) && Objects.equals(bytes[2], (byte) 0x4e) @@ -50,10 +56,10 @@ public enum FileMagicNumber { int i = 8; while (i < bytes.length) { try { - int dataLength = new BigInteger(1, Arrays.copyOfRange(bytes, i, i + 4)).intValue(); + final int dataLength = new BigInteger(1, Arrays.copyOfRange(bytes, i, i + 4)).intValue(); i += 4; - byte[] bytes1 = Arrays.copyOfRange(bytes, i, i + 4); - String chunkType = new String(bytes1); + final byte[] bytes1 = Arrays.copyOfRange(bytes, i, i + 4); + final String chunkType = new String(bytes1); i += 4; if (Objects.equals(chunkType, "IDAT") || Objects.equals(chunkType, "IEND")) { return false; @@ -61,7 +67,7 @@ public enum FileMagicNumber { return true; } i += dataLength + 4; - }catch (Exception e){ + } catch (final Exception e) { return false; } } @@ -71,7 +77,7 @@ public enum FileMagicNumber { }, PNG("image/png", "png") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x89) && Objects.equals(bytes[1], (byte) 0x50) @@ -81,7 +87,7 @@ public enum FileMagicNumber { }, GIF("image/gif", "gif") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x47) && Objects.equals(bytes[1], (byte) 0x49) @@ -90,7 +96,7 @@ public enum FileMagicNumber { }, BMP("image/bmp", "bmp") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 1 && Objects.equals(bytes[0], (byte) 0x42) && Objects.equals(bytes[1], (byte) 0x4d); @@ -98,15 +104,15 @@ public enum FileMagicNumber { }, TIFF("image/tiff", "tiff") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 4) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x49) && Objects.equals(bytes[2], (byte) 0x2a) && Objects.equals(bytes[3], (byte) 0x00); - boolean flag2 = (Objects.equals(bytes[0], (byte) 0x4d) + final boolean flag2 = (Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x4d) && Objects.equals(bytes[2], (byte) 0x00) && Objects.equals(bytes[3], (byte) 0x2a)); @@ -117,7 +123,7 @@ public enum FileMagicNumber { DWG("image/vnd.dwg", "dwg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 10 && Objects.equals(bytes[0], (byte) 0x41) && Objects.equals(bytes[1], (byte) 0x43) @@ -128,7 +134,7 @@ public enum FileMagicNumber { WEBP("image/webp", "webp") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[8], (byte) 0x57) && Objects.equals(bytes[9], (byte) 0x45) @@ -138,7 +144,7 @@ public enum FileMagicNumber { }, PSD("image/vnd.adobe.photoshop", "psd") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x38) && Objects.equals(bytes[1], (byte) 0x42) @@ -148,7 +154,7 @@ public enum FileMagicNumber { }, ICO("image/x-icon", "ico") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x00) @@ -158,7 +164,7 @@ public enum FileMagicNumber { }, XCF("image/x-xcf", "xcf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 9 && Objects.equals(bytes[0], (byte) 0x67) && Objects.equals(bytes[1], (byte) 0x69) @@ -178,7 +184,7 @@ public enum FileMagicNumber { WAV("audio/x-wav", "wav") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x52) && Objects.equals(bytes[1], (byte) 0x49) @@ -192,7 +198,7 @@ public enum FileMagicNumber { }, MIDI("audio/midi", "midi") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x54) @@ -202,20 +208,20 @@ public enum FileMagicNumber { }, MP3("audio/mpeg", "mp3") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 2) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x44) && Objects.equals(bytes[2], (byte) 0x33); - boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xFB); - boolean flag3 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF3); - boolean flag4 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF2); - return flag1 || flag2 || flag3 || flag4; + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x44) && Objects.equals(bytes[2], (byte) 0x33); + final boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xFB); + final boolean flag3 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF3); + final boolean flag4 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF2); + return flag1 || flag2 || flag3 || flag4; } }, OGG("audio/ogg", "ogg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4f) && Objects.equals(bytes[1], (byte) 0x67) @@ -225,7 +231,7 @@ public enum FileMagicNumber { }, FLAC("audio/x-flac", "flac") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x66) && Objects.equals(bytes[1], (byte) 0x4c) @@ -235,7 +241,7 @@ public enum FileMagicNumber { }, M4A("audio/mp4", "m4a") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return (bytes.length > 10 && Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) @@ -252,30 +258,30 @@ public enum FileMagicNumber { }, AAC("audio/aac", "aac") { @Override - public boolean match(byte[] bytes) { - if (bytes.length <1) { + public boolean match(final byte[] bytes) { + if (bytes.length < 1) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF1); - boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF9); - return flag1 || flag2; + final boolean flag1 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF1); + final boolean flag2 = Objects.equals(bytes[0], (byte) 0xFF) && Objects.equals(bytes[1], (byte) 0xF9); + return flag1 || flag2; } }, AMR("audio/amr", "amr") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { //single-channel - if (bytes.length < 11){ + if (bytes.length < 11) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x23) + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x23) && Objects.equals(bytes[1], (byte) 0x21) && Objects.equals(bytes[2], (byte) 0x41) && Objects.equals(bytes[3], (byte) 0x4d) && Objects.equals(bytes[4], (byte) 0x52) && Objects.equals(bytes[5], (byte) 0x0A); //multi-channel: - boolean flag2 = Objects.equals(bytes[0], (byte) 0x23) + final boolean flag2 = Objects.equals(bytes[0], (byte) 0x23) && Objects.equals(bytes[1], (byte) 0x21) && Objects.equals(bytes[2], (byte) 0x41) && Objects.equals(bytes[3], (byte) 0x4d) @@ -287,12 +293,12 @@ public enum FileMagicNumber { && Objects.equals(bytes[9], (byte) 0x2e) && Objects.equals(bytes[10], (byte) 0x30) && Objects.equals(bytes[11], (byte) 0x0a); - return flag1 || flag2; + return flag1 || flag2; } }, AC3("audio/ac3", "ac3") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x0b) && Objects.equals(bytes[1], (byte) 0x77); @@ -300,7 +306,7 @@ public enum FileMagicNumber { }, AIFF("audio/x-aiff", "aiff") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x46) && Objects.equals(bytes[1], (byte) 0x4f) @@ -318,20 +324,20 @@ public enum FileMagicNumber { // The existing registration "application/font-woff" is deprecated in favor of "font/woff". WOFF("font/woff", "woff") { @Override - public boolean match(byte[] bytes) { - boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) + public boolean match(final byte[] bytes) { + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) && Objects.equals(bytes[1], (byte) 0x4f) && Objects.equals(bytes[2], (byte) 0x46) && Objects.equals(bytes[3], (byte) 0x46); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) && Objects.equals(bytes[5], (byte) 0x01) && Objects.equals(bytes[6], (byte) 0x00) && Objects.equals(bytes[7], (byte) 0x00); - boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) + final boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) && Objects.equals(bytes[5], (byte) 0x54) && Objects.equals(bytes[6], (byte) 0x54) && Objects.equals(bytes[7], (byte) 0x4f); - boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) + final boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x75) && Objects.equals(bytes[7], (byte) 0x65); @@ -341,20 +347,20 @@ public enum FileMagicNumber { }, WOFF2("font/woff2", "woff2") { @Override - public boolean match(byte[] bytes) { - boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) + public boolean match(final byte[] bytes) { + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x77) && Objects.equals(bytes[1], (byte) 0x4f) && Objects.equals(bytes[2], (byte) 0x46) && Objects.equals(bytes[3], (byte) 0x32); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x00) && Objects.equals(bytes[5], (byte) 0x01) && Objects.equals(bytes[6], (byte) 0x00) && Objects.equals(bytes[7], (byte) 0x00); - boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) + final boolean flag3 = Objects.equals(bytes[4], (byte) 0x4f) && Objects.equals(bytes[5], (byte) 0x54) && Objects.equals(bytes[6], (byte) 0x54) && Objects.equals(bytes[7], (byte) 0x4f); - boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) + final boolean flag4 = Objects.equals(bytes[4], (byte) 0x74) && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x75) && Objects.equals(bytes[7], (byte) 0x65); @@ -364,7 +370,7 @@ public enum FileMagicNumber { }, TTF("font/ttf", "ttf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x01) @@ -375,7 +381,7 @@ public enum FileMagicNumber { }, OTF("font/otf", "otf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x4f) && Objects.equals(bytes[1], (byte) 0x54) @@ -390,10 +396,10 @@ public enum FileMagicNumber { //archive start----------------------------------------- EPUB("application/epub+zip", "epub") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 58 - && Objects.equals(bytes[0], (byte) 0x50) && Objects.equals(bytes[1], (byte) 0x4b) - && Objects.equals(bytes[2], (byte) 0x03) && Objects.equals(bytes[3], (byte) 0x04) + && Objects.equals(bytes[0], (byte) 0x50) && Objects.equals(bytes[1], (byte) 0x4b) + && Objects.equals(bytes[2], (byte) 0x03) && Objects.equals(bytes[3], (byte) 0x04) && Objects.equals(bytes[30], (byte) 0x6d) && Objects.equals(bytes[31], (byte) 0x69) && Objects.equals(bytes[32], (byte) 0x6d) && Objects.equals(bytes[33], (byte) 0x65) && Objects.equals(bytes[34], (byte) 0x74) && Objects.equals(bytes[35], (byte) 0x79) @@ -412,19 +418,19 @@ public enum FileMagicNumber { }, ZIP("application/zip", "zip") { @Override - public boolean match(byte[] bytes) { - if (bytes.length <4) { + public boolean match(final byte[] bytes) { + if (bytes.length < 4) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x50) && Objects.equals(bytes[1], (byte) 0x4b); - boolean flag2 = Objects.equals(bytes[2], (byte) 0x03) || Objects.equals(bytes[2], (byte) 0x05) || Objects.equals(bytes[2], (byte) 0x07); - boolean flag3 = Objects.equals(bytes[3], (byte) 0x04) || Objects.equals(bytes[3], (byte) 0x06) || Objects.equals(bytes[3], (byte) 0x08); + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x50) && Objects.equals(bytes[1], (byte) 0x4b); + final boolean flag2 = Objects.equals(bytes[2], (byte) 0x03) || Objects.equals(bytes[2], (byte) 0x05) || Objects.equals(bytes[2], (byte) 0x07); + final boolean flag3 = Objects.equals(bytes[3], (byte) 0x04) || Objects.equals(bytes[3], (byte) 0x06) || Objects.equals(bytes[3], (byte) 0x08); return flag1 && flag2 && flag3; } }, TAR("application/x-tar", "tar") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 261 && Objects.equals(bytes[257], (byte) 0x75) && Objects.equals(bytes[258], (byte) 0x73) @@ -435,7 +441,7 @@ public enum FileMagicNumber { }, RAR("application/x-rar-compressed", "rar") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 6 && Objects.equals(bytes[0], (byte) 0x52) && Objects.equals(bytes[1], (byte) 0x61) @@ -448,7 +454,7 @@ public enum FileMagicNumber { }, GZ("application/gzip", "gz") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x1f) && Objects.equals(bytes[1], (byte) 0x8b) @@ -457,7 +463,7 @@ public enum FileMagicNumber { }, BZ2("application/x-bzip2", "bz2") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 && Objects.equals(bytes[0], (byte) 0x42) && Objects.equals(bytes[1], (byte) 0x5a) @@ -466,7 +472,7 @@ public enum FileMagicNumber { }, SevenZ("application/x-7z-compressed", "7z") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 6 && Objects.equals(bytes[0], (byte) 0x37) && Objects.equals(bytes[1], (byte) 0x7a) @@ -494,7 +500,7 @@ public enum FileMagicNumber { }, EXE("application/x-msdownload", "exe") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 1 && Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x5a); @@ -502,16 +508,16 @@ public enum FileMagicNumber { }, SWF("application/x-shockwave-flash", "swf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 2 - && (Objects.equals(bytes[0],0x43) || Objects.equals(bytes[0], (byte) 0x46)) + && (Objects.equals(bytes[0], 0x43) || Objects.equals(bytes[0], (byte) 0x46)) && Objects.equals(bytes[1], (byte) 0x57) && Objects.equals(bytes[2], (byte) 0x53); } }, RTF("application/rtf", "rtf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x7b) && Objects.equals(bytes[1], (byte) 0x5c) @@ -522,7 +528,7 @@ public enum FileMagicNumber { }, NES("application/x-nintendo-nes-rom", "nes") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4e) && Objects.equals(bytes[1], (byte) 0x45) @@ -532,7 +538,7 @@ public enum FileMagicNumber { }, CRX("application/x-google-chrome-extension", "crx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x43) && Objects.equals(bytes[1], (byte) 0x72) @@ -542,20 +548,20 @@ public enum FileMagicNumber { }, CAB("application/vnd.ms-cab-compressed", "cab") { @Override - public boolean match(byte[] bytes) { - if ( bytes.length < 4){ + public boolean match(final byte[] bytes) { + if (bytes.length < 4) { return false; } - boolean flag1 = Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x53) + final boolean flag1 = Objects.equals(bytes[0], (byte) 0x4d) && Objects.equals(bytes[1], (byte) 0x53) && Objects.equals(bytes[2], (byte) 0x43) && Objects.equals(bytes[3], (byte) 0x46); - boolean flag2 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x53) + final boolean flag2 = Objects.equals(bytes[0], (byte) 0x49) && Objects.equals(bytes[1], (byte) 0x53) && Objects.equals(bytes[2], (byte) 0x63) && Objects.equals(bytes[3], (byte) 0x28); - return flag1||flag2; + return flag1 || flag2; } }, PS("application/postscript", "ps") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 1 && Objects.equals(bytes[0], (byte) 0x25) && Objects.equals(bytes[1], (byte) 0x21); @@ -563,7 +569,7 @@ public enum FileMagicNumber { }, XZ("application/x-xz", "xz") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 5 && Objects.equals(bytes[0], (byte) 0xFD) && Objects.equals(bytes[1], (byte) 0x37) @@ -575,13 +581,13 @@ public enum FileMagicNumber { }, SQLITE("application/x-sqlite3", "sqlite") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 15 - && Objects.equals(bytes[0], (byte) 0x53) && Objects.equals(bytes[1], (byte) 0x51) - && Objects.equals(bytes[2], (byte) 0x4c) && Objects.equals(bytes[3], (byte) 0x69) - && Objects.equals(bytes[4], (byte) 0x74) && Objects.equals(bytes[5], (byte) 0x65) - && Objects.equals(bytes[6], (byte) 0x20) && Objects.equals(bytes[7], (byte) 0x66) - && Objects.equals(bytes[8], (byte) 0x6f) && Objects.equals(bytes[9], (byte) 0x72) + && Objects.equals(bytes[0], (byte) 0x53) && Objects.equals(bytes[1], (byte) 0x51) + && Objects.equals(bytes[2], (byte) 0x4c) && Objects.equals(bytes[3], (byte) 0x69) + && Objects.equals(bytes[4], (byte) 0x74) && Objects.equals(bytes[5], (byte) 0x65) + && Objects.equals(bytes[6], (byte) 0x20) && Objects.equals(bytes[7], (byte) 0x66) + && Objects.equals(bytes[8], (byte) 0x6f) && Objects.equals(bytes[9], (byte) 0x72) && Objects.equals(bytes[10], (byte) 0x6d) && Objects.equals(bytes[11], (byte) 0x61) && Objects.equals(bytes[12], (byte) 0x74) && Objects.equals(bytes[13], (byte) 0x20) && Objects.equals(bytes[14], (byte) 0x33) && Objects.equals(bytes[15], (byte) 0x00); @@ -589,13 +595,13 @@ public enum FileMagicNumber { }, DEB("application/x-deb", "deb") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 20 - && Objects.equals(bytes[0], (byte) 0x21) && Objects.equals(bytes[1], (byte) 0x3c) - && Objects.equals(bytes[2], (byte) 0x61) && Objects.equals(bytes[3], (byte) 0x72) - && Objects.equals(bytes[4], (byte) 0x63) && Objects.equals(bytes[5], (byte) 0x68) - && Objects.equals(bytes[6], (byte) 0x3e) && Objects.equals(bytes[7], (byte) 0x0a) - && Objects.equals(bytes[8], (byte) 0x64) && Objects.equals(bytes[9], (byte) 0x65) + && Objects.equals(bytes[0], (byte) 0x21) && Objects.equals(bytes[1], (byte) 0x3c) + && Objects.equals(bytes[2], (byte) 0x61) && Objects.equals(bytes[3], (byte) 0x72) + && Objects.equals(bytes[4], (byte) 0x63) && Objects.equals(bytes[5], (byte) 0x68) + && Objects.equals(bytes[6], (byte) 0x3e) && Objects.equals(bytes[7], (byte) 0x0a) + && Objects.equals(bytes[8], (byte) 0x64) && Objects.equals(bytes[9], (byte) 0x65) && Objects.equals(bytes[10], (byte) 0x62) && Objects.equals(bytes[11], (byte) 0x69) && Objects.equals(bytes[12], (byte) 0x61) && Objects.equals(bytes[13], (byte) 0x6e) && Objects.equals(bytes[14], (byte) 0x2d) && Objects.equals(bytes[15], (byte) 0x62) @@ -606,7 +612,7 @@ public enum FileMagicNumber { }, AR("application/x-unix-archive", "ar") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 6 && Objects.equals(bytes[0], (byte) 0x21) && Objects.equals(bytes[1], (byte) 0x3c) @@ -619,7 +625,7 @@ public enum FileMagicNumber { }, LZOP("application/x-lzop", "lzo") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 7 && Objects.equals(bytes[0], (byte) 0x89) && Objects.equals(bytes[1], (byte) 0x4c) @@ -633,7 +639,7 @@ public enum FileMagicNumber { }, LZ("application/x-lzip", "lz") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x4c) && Objects.equals(bytes[1], (byte) 0x5a) @@ -643,7 +649,7 @@ public enum FileMagicNumber { }, ELF("application/x-executable", "elf") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 52 && Objects.equals(bytes[0], (byte) 0x7f) && Objects.equals(bytes[1], (byte) 0x45) @@ -653,7 +659,7 @@ public enum FileMagicNumber { }, LZ4("application/x-lz4", "lz4") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x04) && Objects.equals(bytes[1], (byte) 0x22) @@ -664,7 +670,7 @@ public enum FileMagicNumber { //https://github.com/madler/brotli/blob/master/br-format-v3.txt,brotli 没有固定的file magic number,所以此处只是参考 BR("application/x-brotli", "br") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0xce) && Objects.equals(bytes[1], (byte) 0xb2) @@ -674,7 +680,7 @@ public enum FileMagicNumber { }, DCM("application/x-dicom", "dcm") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 128 && Objects.equals(bytes[128], (byte) 0x44) && Objects.equals(bytes[129], (byte) 0x49) @@ -684,7 +690,7 @@ public enum FileMagicNumber { }, RPM("application/x-rpm", "rpm") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0xed) && Objects.equals(bytes[1], (byte) 0xab) @@ -694,13 +700,13 @@ public enum FileMagicNumber { }, ZSTD("application/x-zstd", "zst") { @Override - public boolean match(byte[] bytes) { - int length = bytes.length; + public boolean match(final byte[] bytes) { + final int length = bytes.length; if (length < 5) { return false; } - byte[] buf1 = new byte[]{(byte)0x22,(byte)0x23,(byte)0x24,(byte)0x25,(byte)0x26,(byte)0x27,(byte) 0x28}; - boolean flag1 = ArrayUtil.contains(buf1, bytes[0]) + final byte[] buf1 = new byte[]{(byte) 0x22, (byte) 0x23, (byte) 0x24, (byte) 0x25, (byte) 0x26, (byte) 0x27, (byte) 0x28}; + final boolean flag1 = ArrayUtil.contains(buf1, bytes[0]) && Objects.equals(bytes[1], (byte) 0xb5) && Objects.equals(bytes[2], (byte) 0x2f) && Objects.equals(bytes[3], (byte) 0xfd); @@ -717,32 +723,32 @@ public enum FileMagicNumber { //video start------------------------------------------------------------ MP4("video/mp4", "mp4") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 13) { return false; } - boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) - && Objects.equals(bytes[5], (byte) 0x74) - && Objects.equals(bytes[6], (byte) 0x79) - && Objects.equals(bytes[7], (byte) 0x70) - && Objects.equals(bytes[8], (byte) 0x4d) - && Objects.equals(bytes[9], (byte) 0x53) + final boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) + && Objects.equals(bytes[5], (byte) 0x74) + && Objects.equals(bytes[6], (byte) 0x79) + && Objects.equals(bytes[7], (byte) 0x70) + && Objects.equals(bytes[8], (byte) 0x4d) + && Objects.equals(bytes[9], (byte) 0x53) && Objects.equals(bytes[10], (byte) 0x4e) && Objects.equals(bytes[11], (byte) 0x56); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) - && Objects.equals(bytes[5], (byte) 0x74) - && Objects.equals(bytes[6], (byte) 0x79) - && Objects.equals(bytes[7], (byte) 0x70) - && Objects.equals(bytes[8], (byte) 0x69) - && Objects.equals(bytes[9], (byte) 0x73) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) + && Objects.equals(bytes[5], (byte) 0x74) + && Objects.equals(bytes[6], (byte) 0x79) + && Objects.equals(bytes[7], (byte) 0x70) + && Objects.equals(bytes[8], (byte) 0x69) + && Objects.equals(bytes[9], (byte) 0x73) && Objects.equals(bytes[10], (byte) 0x6f) && Objects.equals(bytes[11], (byte) 0x6d); - return flag1||flag2; + return flag1 || flag2; } }, AVI("video/x-msvideo", "avi") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x52) && Objects.equals(bytes[1], (byte) 0x49) @@ -756,7 +762,7 @@ public enum FileMagicNumber { }, WMV("video/x-ms-wmv", "wmv") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 9 && Objects.equals(bytes[0], (byte) 0x30) && Objects.equals(bytes[1], (byte) 0x26) @@ -772,32 +778,32 @@ public enum FileMagicNumber { }, M4V("video/x-m4v", "m4v") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 12) { return false; } - boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) - && Objects.equals(bytes[5], (byte) 0x74) - && Objects.equals(bytes[6], (byte) 0x79) - && Objects.equals(bytes[7], (byte) 0x70) - && Objects.equals(bytes[8], (byte) 0x4d) - && Objects.equals(bytes[9], (byte) 0x34) + final boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) + && Objects.equals(bytes[5], (byte) 0x74) + && Objects.equals(bytes[6], (byte) 0x79) + && Objects.equals(bytes[7], (byte) 0x70) + && Objects.equals(bytes[8], (byte) 0x4d) + && Objects.equals(bytes[9], (byte) 0x34) && Objects.equals(bytes[10], (byte) 0x56) && Objects.equals(bytes[11], (byte) 0x20); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) - && Objects.equals(bytes[5], (byte) 0x74) - && Objects.equals(bytes[6], (byte) 0x79) - && Objects.equals(bytes[7], (byte) 0x70) - && Objects.equals(bytes[8], (byte) 0x6d) - && Objects.equals(bytes[9], (byte) 0x70) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x66) + && Objects.equals(bytes[5], (byte) 0x74) + && Objects.equals(bytes[6], (byte) 0x79) + && Objects.equals(bytes[7], (byte) 0x70) + && Objects.equals(bytes[8], (byte) 0x6d) + && Objects.equals(bytes[9], (byte) 0x70) && Objects.equals(bytes[10], (byte) 0x34) && Objects.equals(bytes[11], (byte) 0x32); - return flag1||flag2; + return flag1 || flag2; } }, FLV("video/x-flv", "flv") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x46) && Objects.equals(bytes[1], (byte) 0x4c) @@ -807,9 +813,9 @@ public enum FileMagicNumber { }, MKV("video/x-matroska", "mkv") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { //0x42 0x82 0x88 0x6d 0x61 0x74 0x72 0x6f 0x73 0x6b 0x61 - boolean flag1 = bytes.length > 11 + final boolean flag1 = bytes.length > 11 && Objects.equals(bytes[0], (byte) 0x1a) && Objects.equals(bytes[1], (byte) 0x45) && Objects.equals(bytes[2], (byte) 0xdf) @@ -817,8 +823,8 @@ public enum FileMagicNumber { if (flag1) { //此处需要判断是否是'\x42\x82\x88matroska',算法类似kmp判断 - byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x6d, (byte) 0x61, (byte) 0x74, (byte) 0x72, (byte) 0x6f, (byte) 0x73, (byte) 0x6b, (byte) 0x61}; - int index = FileMagicNumber.indexOf(bytes, bytes1); + final byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x6d, (byte) 0x61, (byte) 0x74, (byte) 0x72, (byte) 0x6f, (byte) 0x73, (byte) 0x6b, (byte) 0x61}; + final int index = FileMagicNumber.indexOf(bytes, bytes1); return index > 0; } return false; @@ -827,16 +833,16 @@ public enum FileMagicNumber { WEBM("video/webm", "webm") { @Override - public boolean match(byte[] bytes) { - boolean flag1 = bytes.length > 8 + public boolean match(final byte[] bytes) { + final boolean flag1 = bytes.length > 8 && Objects.equals(bytes[0], (byte) 0x1a) && Objects.equals(bytes[1], (byte) 0x45) && Objects.equals(bytes[2], (byte) 0xdf) && Objects.equals(bytes[3], (byte) 0xa3); if (flag1) { //此处需要判断是否是'\x42\x82\x88webm',算法类似kmp判断 - byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x77, (byte) 0x65, (byte) 0x62, (byte) 0x6d}; - int index = FileMagicNumber.indexOf(bytes, bytes1); + final byte[] bytes1 = {(byte) 0x42, (byte) 0x82, (byte) 0x88, (byte) 0x77, (byte) 0x65, (byte) 0x62, (byte) 0x6d}; + final int index = FileMagicNumber.indexOf(bytes, bytes1); return index > 0; } return false; @@ -845,11 +851,11 @@ public enum FileMagicNumber { //此文件签名非常复杂,只判断常见的几种 MOV("video/quicktime", "mov") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 12) { return false; } - boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag1 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x74) && Objects.equals(bytes[6], (byte) 0x79) && Objects.equals(bytes[7], (byte) 0x70) @@ -857,27 +863,27 @@ public enum FileMagicNumber { && Objects.equals(bytes[9], (byte) 0x74) && Objects.equals(bytes[10], (byte) 0x20) && Objects.equals(bytes[11], (byte) 0x20); - boolean flag2 = Objects.equals(bytes[4], (byte) 0x6D) + final boolean flag2 = Objects.equals(bytes[4], (byte) 0x6D) && Objects.equals(bytes[5], (byte) 0x6F) && Objects.equals(bytes[6], (byte) 0x6F) && Objects.equals(bytes[7], (byte) 0x76); - boolean flag3 = Objects.equals(bytes[4], (byte) 0x66) + final boolean flag3 = Objects.equals(bytes[4], (byte) 0x66) && Objects.equals(bytes[5], (byte) 0x72) && Objects.equals(bytes[6], (byte) 0x65) && Objects.equals(bytes[7], (byte) 0x65); - boolean flag4 = Objects.equals(bytes[4], (byte) 0x6D) + final boolean flag4 = Objects.equals(bytes[4], (byte) 0x6D) && Objects.equals(bytes[5], (byte) 0x64) && Objects.equals(bytes[6], (byte) 0x61) && Objects.equals(bytes[7], (byte) 0x74); - boolean flag5 = Objects.equals(bytes[4], (byte) 0x77) + final boolean flag5 = Objects.equals(bytes[4], (byte) 0x77) && Objects.equals(bytes[5], (byte) 0x69) && Objects.equals(bytes[6], (byte) 0x64) && Objects.equals(bytes[7], (byte) 0x65); - boolean flag6 = Objects.equals(bytes[4], (byte) 0x70) + final boolean flag6 = Objects.equals(bytes[4], (byte) 0x70) && Objects.equals(bytes[5], (byte) 0x6E) && Objects.equals(bytes[6], (byte) 0x6F) && Objects.equals(bytes[7], (byte) 0x74); - boolean flag7 = Objects.equals(bytes[4], (byte) 0x73) + final boolean flag7 = Objects.equals(bytes[4], (byte) 0x73) && Objects.equals(bytes[5], (byte) 0x6B) && Objects.equals(bytes[6], (byte) 0x69) && Objects.equals(bytes[7], (byte) 0x70); @@ -886,7 +892,7 @@ public enum FileMagicNumber { }, MPEG("video/mpeg", "mpg") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 3 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x00) @@ -896,7 +902,7 @@ public enum FileMagicNumber { }, RMVB("video/vnd.rn-realvideo", "rmvb") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 4 && Objects.equals(bytes[0], (byte) 0x2E) && Objects.equals(bytes[1], (byte) 0x52) @@ -906,14 +912,14 @@ public enum FileMagicNumber { }, M3GP("video/3gpp", "3gp") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 10 - && Objects.equals(bytes[4], (byte) 0x66) - && Objects.equals(bytes[5], (byte) 0x74) - && Objects.equals(bytes[6], (byte) 0x79) - && Objects.equals(bytes[7], (byte) 0x70) - && Objects.equals(bytes[8], (byte) 0x33) - && Objects.equals(bytes[9], (byte) 0x67) + && Objects.equals(bytes[4], (byte) 0x66) + && Objects.equals(bytes[5], (byte) 0x74) + && Objects.equals(bytes[6], (byte) 0x79) + && Objects.equals(bytes[7], (byte) 0x70) + && Objects.equals(bytes[8], (byte) 0x33) + && Objects.equals(bytes[9], (byte) 0x67) && Objects.equals(bytes[10], (byte) 0x70); } }, @@ -921,18 +927,18 @@ public enum FileMagicNumber { //document start ---------------------------------------------------------- DOC("application/msword", "doc") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xd0,(byte) 0xcf,(byte) 0x11,(byte) 0xe0,(byte) 0xa1,(byte) 0xb1,(byte) 0x1a,(byte) 0xe1}; - boolean flag1 = bytes.length > 515 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; + final boolean flag1 = bytes.length > 515 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); if (flag1) { - byte[] byte2 = new byte[]{(byte) 0xec,(byte) 0xa5,(byte) 0xc1,(byte) 0x00}; - boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2); - byte[] byte3 = new byte[]{(byte) 0x00,(byte) 0x0a,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x4d,(byte) 0x53,(byte) 0x57,(byte) 0x6f,(byte) 0x72,(byte) 0x64 - ,(byte) 0x44,(byte) 0x6f,(byte) 0x63,(byte) 0x00,(byte) 0x10,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x57,(byte) 0x6f,(byte) 0x72, (byte) 0x64, - (byte) 0x2e,(byte) 0x44,(byte) 0x6f,(byte) 0x63,(byte) 0x75, (byte) 0x6d,(byte) 0x65,(byte) 0x6e,(byte) 0x74,(byte) 0x2e,(byte) 0x38,(byte) 0x00, - (byte) 0xf4,(byte) 0x39,(byte) 0xb2,(byte) 0x71}; - byte[] range = Arrays.copyOfRange(bytes, 2075, 2142); - boolean flag3 = bytes.length > 2142 && FileMagicNumber.indexOf(range, byte3) > 0; + final byte[] byte2 = new byte[]{(byte) 0xec, (byte) 0xa5, (byte) 0xc1, (byte) 0x00}; + final boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2); + final byte[] byte3 = new byte[]{(byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x4d, (byte) 0x53, (byte) 0x57, (byte) 0x6f, (byte) 0x72, (byte) 0x64 + , (byte) 0x44, (byte) 0x6f, (byte) 0x63, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x57, (byte) 0x6f, (byte) 0x72, (byte) 0x64, + (byte) 0x2e, (byte) 0x44, (byte) 0x6f, (byte) 0x63, (byte) 0x75, (byte) 0x6d, (byte) 0x65, (byte) 0x6e, (byte) 0x74, (byte) 0x2e, (byte) 0x38, (byte) 0x00, + (byte) 0xf4, (byte) 0x39, (byte) 0xb2, (byte) 0x71}; + final byte[] range = Arrays.copyOfRange(bytes, 2075, 2142); + final boolean flag3 = bytes.length > 2142 && FileMagicNumber.indexOf(range, byte3) > 0; return flag2 || flag3; } return false; @@ -941,62 +947,61 @@ public enum FileMagicNumber { XLS("application/vnd.ms-excel", "xls") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xd0,(byte) 0xcf,(byte) 0x11,(byte) 0xe0,(byte) 0xa1,(byte) 0xb1,(byte) 0x1a,(byte) 0xe1}; - boolean flag1 = bytes.length > 520 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; + final boolean flag1 = bytes.length > 520 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); if (flag1) { - byte[] byte2 = new byte[]{(byte) 0xfd,(byte) 0xff,(byte) 0xff,(byte) 0xff}; - boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2) && (bytes[518] == 0x00 || bytes[518] == 0x02); - byte[] byte3 = new byte[]{(byte) 0x09,(byte) 0x08,(byte) 0x10,(byte) 0x00,(byte) 0x00,(byte) 0x06,(byte) 0x05,(byte) 0x00}; - boolean flag3 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 520), byte3); - byte[] byte4 = new byte[]{(byte) 0xe2,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x5c,(byte) 0x00,(byte) 0x70,(byte) 0x00,(byte) 0x04,(byte) 0x00,(byte) 0x00,(byte) 0x43,(byte) 0x61,(byte) 0x6c,(byte) 0x63}; - boolean flag4 = bytes.length > 2095 && Arrays.equals(Arrays.copyOfRange(bytes, 1568, 2095), byte4); + final byte[] byte2 = new byte[]{(byte) 0xfd, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + final boolean flag2 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 516), byte2) && (bytes[518] == 0x00 || bytes[518] == 0x02); + final byte[] byte3 = new byte[]{(byte) 0x09, (byte) 0x08, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x05, (byte) 0x00}; + final boolean flag3 = Arrays.equals(Arrays.copyOfRange(bytes, 512, 520), byte3); + final byte[] byte4 = new byte[]{(byte) 0xe2, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x5c, (byte) 0x00, (byte) 0x70, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x43, (byte) 0x61, (byte) 0x6c, (byte) 0x63}; + final boolean flag4 = bytes.length > 2095 && Arrays.equals(Arrays.copyOfRange(bytes, 1568, 2095), byte4); return flag2 || flag3 || flag4; } - return false; + return false; } }, PPT("application/vnd.ms-powerpoint", "ppt") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xd0,(byte) 0xcf,(byte) 0x11,(byte) 0xe0,(byte) 0xa1,(byte) 0xb1,(byte) 0x1a,(byte) 0xe1}; - boolean flag1 = bytes.length > 524 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; + final boolean flag1 = bytes.length > 524 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte1); if (flag1) { - byte[] byte2 = new byte[]{(byte) 0xa0,(byte) 0x46,(byte) 0x1d,(byte) 0xf0}; - byte[] byteRange = Arrays.copyOfRange(bytes, 512, 516); - boolean flag2 = Arrays.equals(byteRange, byte2); - byte[] byte3 = new byte[]{(byte) 0x00,(byte) 0x6e,(byte) 0x1e,(byte) 0xf0}; - boolean flag3 = Arrays.equals(byteRange, byte3); - byte[] byte4 = new byte[]{(byte) 0x0f,(byte) 0x00,(byte) 0xe8,(byte) 0x03}; - boolean flag4 = Arrays.equals(byteRange, byte4); - byte[] byte5 = new byte[]{(byte) 0xfd,(byte) 0xff,(byte) 0xff,(byte) 0xff}; - boolean flag5 = Arrays.equals(byteRange, byte5) && bytes[522] == 0x00 && bytes[523] == 0x00; - byte[] byte6 = new byte[]{(byte) 0x00,(byte) 0xb9,(byte) 0x29,(byte) 0xe8,(byte) 0x11,(byte) 0x00,(byte) 0x00,(byte) 0x00, - (byte) 0x4d,(byte) 0x53,(byte) 0x20,(byte) 0x50,(byte) 0x6f,(byte) 0x77,(byte) 0x65,(byte) 0x72,(byte) 0x50,(byte) - 0x6f,(byte) 0x69,(byte) 0x6e,(byte) 0x74,(byte) 0x20,(byte) 0x39,(byte) 0x37}; - boolean flag6 = bytes.length > 2096 && Arrays.equals(Arrays.copyOfRange(bytes, 2072, 2096), byte6); + final byte[] byte2 = new byte[]{(byte) 0xa0, (byte) 0x46, (byte) 0x1d, (byte) 0xf0}; + final byte[] byteRange = Arrays.copyOfRange(bytes, 512, 516); + final boolean flag2 = Arrays.equals(byteRange, byte2); + final byte[] byte3 = new byte[]{(byte) 0x00, (byte) 0x6e, (byte) 0x1e, (byte) 0xf0}; + final boolean flag3 = Arrays.equals(byteRange, byte3); + final byte[] byte4 = new byte[]{(byte) 0x0f, (byte) 0x00, (byte) 0xe8, (byte) 0x03}; + final boolean flag4 = Arrays.equals(byteRange, byte4); + final byte[] byte5 = new byte[]{(byte) 0xfd, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + final boolean flag5 = Arrays.equals(byteRange, byte5) && bytes[522] == 0x00 && bytes[523] == 0x00; + final byte[] byte6 = new byte[]{(byte) 0x00, (byte) 0xb9, (byte) 0x29, (byte) 0xe8, (byte) 0x11, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x4d, (byte) 0x53, (byte) 0x20, (byte) 0x50, (byte) 0x6f, (byte) 0x77, (byte) 0x65, (byte) 0x72, (byte) 0x50, (byte) + 0x6f, (byte) 0x69, (byte) 0x6e, (byte) 0x74, (byte) 0x20, (byte) 0x39, (byte) 0x37}; + final boolean flag6 = bytes.length > 2096 && Arrays.equals(Arrays.copyOfRange(bytes, 2072, 2096), byte6); return flag2 || flag3 || flag4 || flag5 || flag6; - } - return false; } + return false; } - , + }, DOCX("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return Objects.equals(FileMagicNumber.matchDocument(bytes), DOCX); } }, PPTX("application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return Objects.equals(FileMagicNumber.matchDocument(bytes), PPTX); } }, XLSX("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return Objects.equals(FileMagicNumber.matchDocument(bytes), XLSX); } }, @@ -1005,7 +1010,7 @@ public enum FileMagicNumber { //other start ------------------------------------------------------------- WASM("application/wasm", "wasm") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 7 && Objects.equals(bytes[0], (byte) 0x00) && Objects.equals(bytes[1], (byte) 0x61) @@ -1020,46 +1025,46 @@ public enum FileMagicNumber { // https://source.android.com/devices/tech/dalvik/dex-format#dex-file-magic DEX("application/vnd.android.dex", "dex") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 36 && Objects.equals(bytes[0], (byte) 0x64) && Objects.equals(bytes[1], (byte) 0x65) && Objects.equals(bytes[2], (byte) 0x78) && Objects.equals(bytes[3], (byte) 0x0A) - && Objects.equals(bytes[36],(byte) 0x70); + && Objects.equals(bytes[36], (byte) 0x70); } }, DEY("application/vnd.android.dey", "dey") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { return bytes.length > 100 && Objects.equals(bytes[0], (byte) 0x64) && Objects.equals(bytes[1], (byte) 0x65) && Objects.equals(bytes[2], (byte) 0x79) - && Objects.equals(bytes[3], (byte) 0x0A)&& + && Objects.equals(bytes[3], (byte) 0x0A) && DEX.match(Arrays.copyOfRange(bytes, 40, 100)); } }, EML("message/rfc822", "eml") { @Override - public boolean match(byte[] bytes) { + public boolean match(final byte[] bytes) { if (bytes.length < 8) { return false; } - byte[] byte1 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x20, (byte) 0x20}; - byte[] byte2 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x3F, (byte) 0x3F, (byte) 0x3F}; - byte[] byte3 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x3A, (byte) 0x20}; - byte[] byte4 = new byte[]{(byte) 0x52, (byte) 0x65, (byte) 0x74, (byte) 0x75, (byte) 0x72, (byte) 0x6E, (byte) 0x2D, (byte) 0x50, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x3A, (byte) 0x20}; + final byte[] byte1 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x20, (byte) 0x20}; + final byte[] byte2 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x20, (byte) 0x3F, (byte) 0x3F, (byte) 0x3F}; + final byte[] byte3 = new byte[]{(byte) 0x46, (byte) 0x72, (byte) 0x6F, (byte) 0x6D, (byte) 0x3A, (byte) 0x20}; + final byte[] byte4 = new byte[]{(byte) 0x52, (byte) 0x65, (byte) 0x74, (byte) 0x75, (byte) 0x72, (byte) 0x6E, (byte) 0x2D, (byte) 0x50, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x3A, (byte) 0x20}; return Arrays.equals(Arrays.copyOfRange(bytes, 0, 7), byte1) || Arrays.equals(Arrays.copyOfRange(bytes, 0, 8), byte2) || Arrays.equals(Arrays.copyOfRange(bytes, 0, 6), byte3) - || bytes.length>13 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 13), byte4); + || bytes.length > 13 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 13), byte4); } }, MDB("application/vnd.ms-access", "mdb") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x6E, (byte) 0x64, + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x6E, (byte) 0x64, (byte) 0x61, (byte) 0x72, (byte) 0x64, (byte) 0x20, (byte) 0x4A, (byte) 0x65, (byte) 0x74, (byte) 0x20, (byte) 0x44, (byte) 0x42}; return bytes.length > 18 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 18), byte1); } @@ -1067,52 +1072,52 @@ public enum FileMagicNumber { //CHM 49 54 53 46 CHM("application/vnd.ms-htmlhelp", "chm") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x49, (byte) 0x54, (byte) 0x53, (byte) 0x46}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x49, (byte) 0x54, (byte) 0x53, (byte) 0x46}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, //class CA FE BA BE CLASS("application/java-vm", "class") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, //torrent 64 38 3A 61 6E 6E 6F 75 6E 63 65 TORRENT("application/x-bittorrent", "torrent") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x64, (byte) 0x38, (byte) 0x3A, (byte) 0x61, (byte) 0x6E, (byte) 0x6E, (byte) 0x6F, (byte) 0x75, (byte) 0x6E, (byte) 0x63, (byte) 0x65}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x64, (byte) 0x38, (byte) 0x3A, (byte) 0x61, (byte) 0x6E, (byte) 0x6E, (byte) 0x6F, (byte) 0x75, (byte) 0x6E, (byte) 0x63, (byte) 0x65}; return bytes.length > 11 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 11), byte1); } }, WPD("application/vnd.wordperfect", "wpd") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xFF, (byte) 0x57, (byte) 0x50, (byte) 0x43}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xFF, (byte) 0x57, (byte) 0x50, (byte) 0x43}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, DBX("", "dbx") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0xCF, (byte) 0xAD, (byte) 0x12, (byte) 0xFE}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0xCF, (byte) 0xAD, (byte) 0x12, (byte) 0xFE}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, PST("application/vnd.ms-outlook-pst", "pst") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x21, (byte) 0x42, (byte) 0x44, (byte) 0x4E}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x21, (byte) 0x42, (byte) 0x44, (byte) 0x4E}; return bytes.length > 4 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 4), byte1); } }, RAM("audio/x-pn-realaudio", "ram") { @Override - public boolean match(byte[] bytes) { - byte[] byte1 = new byte[]{(byte) 0x2E, (byte) 0x72, (byte) 0x61, (byte) 0xFD, (byte) 0x00}; + public boolean match(final byte[] bytes) { + final byte[] byte1 = new byte[]{(byte) 0x2E, (byte) 0x72, (byte) 0x61, (byte) 0xFD, (byte) 0x00}; return bytes.length > 5 && Arrays.equals(Arrays.copyOfRange(bytes, 0, 5), byte1); } } @@ -1121,18 +1126,18 @@ public enum FileMagicNumber { private final String mimeType; private final String extension; - FileMagicNumber(String mimeType, String extension) { + FileMagicNumber(final String mimeType, final String extension) { this.mimeType = mimeType; this.extension = extension; } - public static FileMagicNumber getMagicNumber(byte[] bytes) { - FileMagicNumber number = Arrays.stream(values()) + public static FileMagicNumber getMagicNumber(final byte[] bytes) { + final FileMagicNumber number = Arrays.stream(values()) .filter(fileMagicNumber -> fileMagicNumber.match(bytes)) .findFirst() .orElse(UNKNOWN); - if (number.equals(FileMagicNumber.ZIP)){ - FileMagicNumber fn = FileMagicNumber.matchDocument(bytes); + if (number.equals(FileMagicNumber.ZIP)) { + final FileMagicNumber fn = FileMagicNumber.matchDocument(bytes); return fn == UNKNOWN ? ZIP : fn; } return number; @@ -1146,7 +1151,7 @@ public enum FileMagicNumber { return extension; } - private static int indexOf(byte[] array, byte[] target) { + private static int indexOf(final byte[] array, final byte[] target) { if (array == null || target == null || array.length < target.length) { return -1; } @@ -1154,8 +1159,8 @@ public enum FileMagicNumber { return 0; } else { label1: - for(int i = 0; i < array.length - target.length + 1; ++i) { - for(int j = 0; j < target.length; ++j) { + for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { if (array[i + j] != target[j]) { continue label1; } @@ -1167,19 +1172,19 @@ public enum FileMagicNumber { } //处理 Open XML 类型的文件 - private static boolean compareBytes(byte[] buf, byte[] slice, int startOffset) { - int sl = slice.length; + private static boolean compareBytes(final byte[] buf, final byte[] slice, final int startOffset) { + final int sl = slice.length; if (startOffset + sl > buf.length) { return false; } - byte[] sub = Arrays.copyOfRange(buf, startOffset, startOffset + sl); + final byte[] sub = Arrays.copyOfRange(buf, startOffset, startOffset + sl); return Arrays.equals(sub, slice); } - private static FileMagicNumber matchOpenXmlMime(byte[] bytes,int offset) { - byte[] word = new byte[]{'w','o','r','d','/'}; - byte[] ppt = new byte[]{ 'p','p','t','/'}; - byte[] xl = new byte[]{'x','l','/'}; + private static FileMagicNumber matchOpenXmlMime(final byte[] bytes, final int offset) { + final byte[] word = new byte[]{'w', 'o', 'r', 'd', '/'}; + final byte[] ppt = new byte[]{'p', 'p', 't', '/'}; + final byte[] xl = new byte[]{'x', 'l', '/'}; if (FileMagicNumber.compareBytes(bytes, word, offset)) { return FileMagicNumber.DOCX; } @@ -1189,45 +1194,45 @@ public enum FileMagicNumber { if (FileMagicNumber.compareBytes(bytes, xl, offset)) { return FileMagicNumber.XLSX; } - return FileMagicNumber.UNKNOWN; + return FileMagicNumber.UNKNOWN; } - private static FileMagicNumber matchDocument(byte[] bytes) { - FileMagicNumber fileMagicNumber = FileMagicNumber.matchOpenXmlMime(bytes, (byte) 0x1e); - if (false== fileMagicNumber.equals(UNKNOWN)){ + private static FileMagicNumber matchDocument(final byte[] bytes) { + final FileMagicNumber fileMagicNumber = FileMagicNumber.matchOpenXmlMime(bytes, (byte) 0x1e); + if (false == fileMagicNumber.equals(UNKNOWN)) { return fileMagicNumber; } - byte[] bytes1 = new byte[]{0x5B,0x43,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x54,0x79,0x70,0x65,0x73,0x5D,0x2E,0x78,0x6D,0x6C}; - byte[] bytes2 = new byte[]{0x5F,0x72,0x65,0x6C,0x73,0x2F,0x2E,0x72,0x65,0x6C,0x73}; - byte[] bytes3 = new byte[]{0x64,0x6F,0x63,0x50,0x72,0x6F,0x70,0x73}; - boolean flag1 = FileMagicNumber.compareBytes(bytes, bytes1, (byte) 0x1e); - boolean flag2 = FileMagicNumber.compareBytes(bytes, bytes2, (byte) 0x1e); - boolean flag3 = FileMagicNumber.compareBytes(bytes, bytes3, (byte) 0x1e); - if (false==(flag1 || flag2 || flag3)){ + final byte[] bytes1 = new byte[]{0x5B, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x5F, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5D, 0x2E, 0x78, 0x6D, 0x6C}; + final byte[] bytes2 = new byte[]{0x5F, 0x72, 0x65, 0x6C, 0x73, 0x2F, 0x2E, 0x72, 0x65, 0x6C, 0x73}; + final byte[] bytes3 = new byte[]{0x64, 0x6F, 0x63, 0x50, 0x72, 0x6F, 0x70, 0x73}; + final boolean flag1 = FileMagicNumber.compareBytes(bytes, bytes1, (byte) 0x1e); + final boolean flag2 = FileMagicNumber.compareBytes(bytes, bytes2, (byte) 0x1e); + final boolean flag3 = FileMagicNumber.compareBytes(bytes, bytes3, (byte) 0x1e); + if (false == (flag1 || flag2 || flag3)) { return UNKNOWN; } int index = 0; for (int i = 0; i < 4; i++) { - index = searchSignature(bytes, index+4,6000); + index = searchSignature(bytes, index + 4, 6000); if (index == -1) { continue; } - FileMagicNumber fn = FileMagicNumber.matchOpenXmlMime(bytes, index +30); - if (false==fn.equals(UNKNOWN)) { + final FileMagicNumber fn = FileMagicNumber.matchOpenXmlMime(bytes, index + 30); + if (false == fn.equals(UNKNOWN)) { return fn; } } return UNKNOWN; } - private static int searchSignature(byte[] bytes,int start,int rangeNum) { - byte[] signature = new byte[]{0x50,0x4B,0x03,0x04}; - int length = bytes.length; + private static int searchSignature(final byte[] bytes, final int start, final int rangeNum) { + final byte[] signature = new byte[]{0x50, 0x4B, 0x03, 0x04}; + final int length = bytes.length; int end = start + rangeNum; - if (end> length){ + if (end > length) { end = length; } - int index = FileMagicNumber.indexOf(Arrays.copyOfRange(bytes, start, end), signature); + final int index = FileMagicNumber.indexOf(Arrays.copyOfRange(bytes, start, end), signature); return (index == -1) ? -1 : (start + index);