diff --git a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs index 3b1ac31..834ff27 100644 --- a/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs +++ b/src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs @@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine { internal partial class CommandInvoker { - public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20221111"; + public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20221112"; [GeneratedRegex("((best|worst)\\d*|all)")] private static partial Regex ForStrRegex(); diff --git a/src/N_m3u8DL-RE/Downloader/SimpleDownloader.cs b/src/N_m3u8DL-RE/Downloader/SimpleDownloader.cs index b37fdf3..1225b25 100644 --- a/src/N_m3u8DL-RE/Downloader/SimpleDownloader.cs +++ b/src/N_m3u8DL-RE/Downloader/SimpleDownloader.cs @@ -60,6 +60,12 @@ namespace N_m3u8DL_RE.Downloader { //throw new NotSupportedException("SAMPLE-AES-CTR"); } + + //Image头处理 + if (dResult.ImageHeader) + { + await ImageHeaderUtil.ProcessAsync(dResult.ActualFilePath); + } } return dResult; } diff --git a/src/N_m3u8DL-RE/Entity/DownloadResult.cs b/src/N_m3u8DL-RE/Entity/DownloadResult.cs index e12870f..66929cb 100644 --- a/src/N_m3u8DL-RE/Entity/DownloadResult.cs +++ b/src/N_m3u8DL-RE/Entity/DownloadResult.cs @@ -12,6 +12,7 @@ namespace N_m3u8DL_RE.Entity public bool Success { get => (ActualContentLength != null && RespContentLength != null) ? (RespContentLength == ActualContentLength) : (ActualContentLength == null ? false : true); } public long? RespContentLength { get; set; } public long? ActualContentLength { get; set; } + public bool ImageHeader { get; set; } = false; //图片伪装 public required string ActualFilePath { get; set; } } } diff --git a/src/N_m3u8DL-RE/Program.cs b/src/N_m3u8DL-RE/Program.cs index bb8eb9b..1ea28f6 100644 --- a/src/N_m3u8DL-RE/Program.cs +++ b/src/N_m3u8DL-RE/Program.cs @@ -187,6 +187,8 @@ namespace N_m3u8DL_RE //url = "https://theater.kktv.com.tw/98/04000198010001_584b26392f7f7f11fc62299214a55fb7/16113081449d8d5e9960_sub_dash.mpd"; //MPD+VTT //url = "https://vsl.play.kakao.com/vod/rvty90n7btua6u9oebr97i8zl/dash/vhs/cenc/adaptive.mpd?e=1658297362&p=71&h=53766bdde112d59da2b2514e8ab41e81"; //需要补params //url = "https://a38avoddashs3ww-a.akamaihd.net/ondemand/iad_2/8e91/f2f2/ec5a/430f-bd7a-0779f4a0189d/685cda75-609c-41c1-86bb-688f4cdb5521_corrected.mpd"; + //url = "http://ht.grelighting.cn/m3u8/OEtYNVNjMFF5N1g2VzNkZ2lwbWEvd1ZtTGJ0dlZXOEk=.m3u8"; //特殊的图片伪装 + //url = "https://ali6.a.yximgs.com/udata/music/music_295e59bdb3084def8158873ad6f5c8250.jpg"; //PNG图片伪装 //url = ""; if (!string.IsNullOrEmpty(option.Input)) diff --git a/src/N_m3u8DL-RE/Util/ImageHeaderUtil.cs b/src/N_m3u8DL-RE/Util/ImageHeaderUtil.cs new file mode 100644 index 0000000..c9d1ef7 --- /dev/null +++ b/src/N_m3u8DL-RE/Util/ImageHeaderUtil.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace N_m3u8DL_RE.Util +{ + internal class ImageHeaderUtil + { + public static bool IsImageHeader(byte[] bArr) + { + var size = bArr.Length; + //PNG HEADER检测 + if (size > 3 && 137 == bArr[0] && 80 == bArr[1] && 78 == bArr[2] && 71 == bArr[3]) + return true; + //GIF HEADER检测 + else if (size > 3 && 0x47 == bArr[0] && 0x49 == bArr[1] && 0x46 == bArr[2] && 0x38 == bArr[3]) + return true; + //BMP HEADER检测 + else if (size > 10 && 0x42 == bArr[0] && 0x4D == bArr[1] && 0x00 == bArr[5] && 0x00 == bArr[6] && 0x00 == bArr[7] && 0x00 == bArr[8]) + return true; + return false; + } + + public static async Task ProcessAsync(string sourcePath) + { + var sourceData = await File.ReadAllBytesAsync(sourcePath); + + //PNG HEADER + if (137 == sourceData[0] && 80 == sourceData[1] && 78 == sourceData[2] && 71 == sourceData[3]) + { + if (sourceData.Length > 120 && 137 == sourceData[0] && 80 == sourceData[1] && 78 == sourceData[2] && 71 == sourceData[3] && 96 == sourceData[118] && 130 == sourceData[119]) + sourceData = sourceData[120..]; + else if (sourceData.Length > 6102 && 137 == sourceData[0] && 80 == sourceData[1] && 78 == sourceData[2] && 71 == sourceData[3] && 96 == sourceData[6100] && 130 == sourceData[6101]) + sourceData = sourceData[6102..]; + else if (sourceData.Length > 69 && 137 == sourceData[0] && 80 == sourceData[1] && 78 == sourceData[2] && 71 == sourceData[3] && 96 == sourceData[67] && 130 == sourceData[68]) + sourceData = sourceData[69..]; + else if (sourceData.Length > 771 && 137 == sourceData[0] && 80 == sourceData[1] && 78 == sourceData[2] && 71 == sourceData[3] && 96 == sourceData[769] && 130 == sourceData[770]) + sourceData = sourceData[771..]; + else + { + //确定是PNG但是需要手动查询结尾标记 0x47 出现两次 + int skip = 0; + for (int i = 4; i < sourceData.Length - 188 * 2 - 4; i++) + { + if (sourceData[i] == 0x47 && sourceData[i + 188] == 0x47 && sourceData[i + 188 + 188] == 0x47) + { + skip = i; + break; + } + } + sourceData = sourceData[skip..]; + } + } + //GIF HEADER + else if (0x47 == sourceData[0] && 0x49 == sourceData[1] && 0x46 == sourceData[2] && 0x38 == sourceData[3]) + { + sourceData = sourceData[42..]; + } + //BMP HEADER + else if (0x42 == sourceData[0] && 0x4D == sourceData[1] && 0x00 == sourceData[5] && 0x00 == sourceData[6] && 0x00 == sourceData[7] && 0x00 == sourceData[8]) + { + sourceData = sourceData[0x3E..]; + } + + await File.WriteAllBytesAsync(sourcePath, sourceData); + } + } +}