diff --git a/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java b/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java index 3ce2421..d804202 100644 --- a/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java +++ b/parser/src/main/java/cn/qaiu/parser/PanDomainTemplate.java @@ -68,8 +68,8 @@ public enum PanDomainTemplate { t-is.cn */ LZ("蓝奏云", - compile("https://(?:[a-zA-Z\\d-]+\\.)?(" + - "lanzoul|" + + compile("https://(?:[a-zA-Z\\d-]+\\.)?(?:" + + "(?:lanzoul|" + "lanzouh|" + "lanosso|" + "lanpv|" + @@ -95,14 +95,16 @@ public enum PanDomainTemplate { "lanzv|" + "dmpdmp|" + "lanrar|" + + "webgetstore|" + "lanzb|" + "lanzoux|" + "lanzout|" + "lanzouc|" + "lanzoui|" + "lanzoug|" + - "lanzoum" + - ")\\.com/(?.+)"), + "lanzoum)\\.com" + + "|t-is\\.cn" + + ")/(?.+)"), "https://w1.lanzn.com/{shareKey}", LzTool.class), @@ -115,7 +117,7 @@ public enum PanDomainTemplate { // https://lecloud.lenovo.com/share/ LE("联想乐云", - compile("https://lecloud?\\.lenovo\\.com/share/(?.+)"), + compile("https://lecloud\\.lenovo\\.com/share/(?.+)"), "https://lecloud.lenovo.com/share/{shareKey}", LeTool.class), @@ -241,7 +243,7 @@ public enum PanDomainTemplate { EcTool.class), // https://cowtransfer.com/s/ COW("奶牛快传", - compile("https://(.*)cowtransfer\\.com/s/(?.+)"), + compile("https://(?:[a-zA-Z\\d-]+\\.)?cowtransfer\\.com/s/(?.+)"), "https://cowtransfer.com/s/{shareKey}", CowTool.class), CT("城通网盘", @@ -264,7 +266,7 @@ public enum PanDomainTemplate { PodTool.class), // 404网盘 https://drive.google.com/file/d/xxx/view?usp=sharing PGD("GoogleDrive", - compile("https://drive\\.google\\.com/file/d/(?.+)/view(\\?usp=(sharing|drive_link))?"), + compile("https://(?:[a-zA-Z\\d-]+\\.)?drive\\.google\\.com/file/d/(?.+)/view(\\?usp=(sharing|drive_link))?"), "https://drive.google.com/file/d/{shareKey}/view?usp=sharing", PgdTool.class), // iCloud https://www.icloud.com.cn/iclouddrive/xxx#fonts @@ -274,11 +276,11 @@ public enum PanDomainTemplate { PicTool.class), // https://www.dropbox.com/scl/fi/cwnbms1yn8u6rcatzyta7/emqx-5.0.26-el7-amd64.tar.gz?rlkey=3uoi4bxz5mv93jmlaws0nlol1&e=8&st=fe0lclc2&dl=0 PDB("dropbox", - compile("https://www.dropbox.com/scl/fi/(?\\w+)/.+?rlkey=(?\\w+).*"), + compile("https://www\\.dropbox\\.com/scl/fi/(?\\w+)/.+?rlkey=(?\\w+).*"), "https://www.dropbox.com/scl/fi/{shareKey}/?rlkey={pwd}&dl=0", PdbTool.class), P115("115网盘", - compile("https://(115|anxia).com/s/(?\\w+)(\\?password=(?\\w+))?([&#].*)?"), + compile("https://(115|anxia)\\.com/s/(?\\w+)(\\?password=(?\\w+))?([&#].*)?"), "https://115.com/s/{shareKey}?password={pwd}", P115Tool.class), // 链接:https://www.yunpan.com/surl_yD7wz4VgU9v(提取码:fc70) @@ -319,7 +321,7 @@ public enum PanDomainTemplate { MnesTool.class), // https://music.163.com/#/song?id=xxx MNE("网易云音乐歌曲详情", - compile("https://(y.)?music\\.163\\.com/(#|m/)?song\\?id=(?.+)(&.*)?"), + compile("https://(y\\.)?music\\.163\\.com/(?:#/|m/)?song\\?id=(?.+)(&.*)?"), "https://music.163.com/#/song?id={shareKey}", MnesTool.MneTool.class), // https://c6.y.qq.com/base/fcgi-bin/u?__=xxx @@ -340,7 +342,7 @@ public enum PanDomainTemplate { MkgsTool.class), // https://www.kugou.com/share/2bi8Fe9CSV3.html?id=2bi8Fe9CSV3#6ed9gna4" MKGS2("酷狗音乐分享2", - compile("https://(?:[a-zA-Z\\d-]+\\.)?kugou\\.com/share/(?.+).html.*"), + compile("https://(?:[a-zA-Z\\d-]+\\.)?kugou\\.com/share/(?.+)\\.html.*"), "https://www.kugou.com/share/{shareKey}.html", MkgsTool.Mkgs2Tool.class), // https://www.kugou.com/mixsong/2bi8Fe9CSV3 diff --git a/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java b/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java index 4370cb9..1ced9bf 100644 --- a/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java +++ b/parser/src/test/java/cn/qaiu/parser/PanDomainTemplateTest.java @@ -129,15 +129,126 @@ public class PanDomainTemplateTest { wsPattern.matcher("https://www.evil.com/f/abc123").matches()); } + @Test + public void testLzPatternWebgetstore() { + Pattern lzPattern = PanDomainTemplate.LZ.getPattern(); + + // webgetstore.com 以前遗漏,现已补入 + Matcher m1 = lzPattern.matcher("https://webgetstore.com/somekey"); + assertTrue("LZ should match webgetstore.com", m1.find()); + assertEquals("somekey", m1.group("KEY")); + + Matcher m2 = lzPattern.matcher("https://www.webgetstore.com/somekey"); + assertTrue("LZ should match www.webgetstore.com", m2.find()); + assertEquals("somekey", m2.group("KEY")); + + // t-is.cn 以前遗漏,现已补入 + Matcher m3 = lzPattern.matcher("https://t-is.cn/somekey"); + assertTrue("LZ should match t-is.cn", m3.find()); + assertEquals("somekey", m3.group("KEY")); + + Matcher m4 = lzPattern.matcher("https://www.t-is.cn/somekey"); + assertTrue("LZ should match www.t-is.cn", m4.find()); + assertEquals("somekey", m4.group("KEY")); + + // 已有域名仍然正常匹配 + Matcher m5 = lzPattern.matcher("https://www.lanzoul.com/somekey"); + assertTrue("LZ should match existing domain lanzoul.com", m5.find()); + assertEquals("somekey", m5.group("KEY")); + } + + @Test + public void testLePatternFix() { + Pattern lePattern = PanDomainTemplate.LE.getPattern(); + + // lecloud.lenovo.com 应匹配 + Matcher m1 = lePattern.matcher("https://lecloud.lenovo.com/share/abc123"); + assertTrue("LE should match lecloud.lenovo.com", m1.find()); + assertEquals("abc123", m1.group("KEY")); + + // leclou.lenovo.com (去掉'd') 不应匹配(原 lecloud? 的 bug) + assertFalse("LE should NOT match leclou.lenovo.com", + lePattern.matcher("https://leclou.lenovo.com/share/abc123").find()); + } + + @Test + public void testCowPatternFix() { + Pattern cowPattern = PanDomainTemplate.COW.getPattern(); + + // 正常域名 + Matcher m1 = cowPattern.matcher("https://cowtransfer.com/s/abc123"); + assertTrue("COW should match cowtransfer.com", m1.find()); + assertEquals("abc123", m1.group("KEY")); + + Matcher m2 = cowPattern.matcher("https://share.cowtransfer.com/s/abc123"); + assertTrue("COW should match share.cowtransfer.com", m2.find()); + assertEquals("abc123", m2.group("KEY")); + + // 潜在的URL注入攻击(修复前 (.*) 能匹配此类URL) + assertFalse("COW should NOT match redirect URLs", + cowPattern.matcher("https://evil.com/redirect/cowtransfer.com/s/abc").find()); + } + + @Test + public void testMnePatternFix() { + Pattern mnePattern = PanDomainTemplate.MNE.getPattern(); + + // 带 #/ 前缀的完整网页链接(修复前因 (y.) 未转义而存在 bug) + Matcher m1 = mnePattern.matcher("https://music.163.com/#/song?id=12345"); + assertTrue("MNE should match #/song format", m1.find()); + assertEquals("12345", m1.group("KEY")); + + // 带 m/ 前缀的移动端链接 + Matcher m2 = mnePattern.matcher("https://music.163.com/m/song?id=12345"); + assertTrue("MNE should match m/song format", m2.find()); + assertEquals("12345", m2.group("KEY")); + + // y.music.163.com 子域名 + Matcher m3 = mnePattern.matcher("https://y.music.163.com/song?id=12345"); + assertTrue("MNE should match y.music.163.com", m3.find()); + assertEquals("12345", m3.group("KEY")); + + // 原 (y.) 未转义时 yXmusic.163.com 会被误匹配(现已修复) + assertFalse("MNE should NOT match yXmusic.163.com", + mnePattern.matcher("https://yXmusic.163.com/song?id=12345").find()); + } + + @Test + public void testP115PatternFix() { + Pattern p115Pattern = PanDomainTemplate.P115.getPattern(); + + // 正常匹配 + Matcher m1 = p115Pattern.matcher("https://115.com/s/abc123"); + assertTrue("P115 should match 115.com", m1.find()); + assertEquals("abc123", m1.group("KEY")); + + Matcher m2 = p115Pattern.matcher("https://anxia.com/s/abc123"); + assertTrue("P115 should match anxia.com", m2.find()); + assertEquals("abc123", m2.group("KEY")); + + // 原 .com 未转义时 115Xcom 会被误匹配(现已修复) + assertFalse("P115 should NOT match 115Xcom", + p115Pattern.matcher("https://115Xcom/s/abc123").find()); + } + + @Test + public void testPgdSubdomain() { + Pattern pgdPattern = PanDomainTemplate.PGD.getPattern(); + + // 标准链接 + Matcher m1 = pgdPattern.matcher("https://drive.google.com/file/d/abc123/view?usp=sharing"); + assertTrue("PGD should match standard drive.google.com", m1.find()); + assertEquals("abc123", m1.group("KEY")); + + // 带子域名的链接(修复后支持) + Matcher m2 = pgdPattern.matcher("https://adsd.drive.google.com/file/d/151bR-nk-tOBm9QAFaozJIVt2WYyCMkoz/view"); + assertTrue("PGD should match subdomain.drive.google.com", m2.find()); + assertEquals("151bR-nk-tOBm9QAFaozJIVt2WYyCMkoz", m2.group("KEY")); + } + @Test public void verifyDuplicates() { - Matcher matcher = compile("https://(?:[a-zA-Z\\d-]+\\.)?drive\\.google\\.com/file/d/(?.+)/view(\\?usp=(sharing|drive_link))?") - .matcher("https://adsd.drive.google.com/file/d/151bR-nk-tOBm9QAFaozJIVt2WYyCMkoz/view"); - if (matcher.find()) { - System.out.println(matcher.group()); - System.out.println(matcher.group("KEY")); - } // 校验重复 Set collect = Arrays.stream(PanDomainTemplate.values()).map(PanDomainTemplate::getRegex).collect(Collectors.toSet());