2.8.9
This commit is contained in:
@@ -12,13 +12,13 @@ Public Module ModBase
|
||||
#Region "声明"
|
||||
|
||||
'下列版本信息由更新器自动修改
|
||||
Public Const VersionBaseName As String = "2.8.8" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.8.8." & VersionBranchCode '标准格式的四段式版本号
|
||||
Public Const VersionBaseName As String = "2.8.9" '不含分支前缀的显示用版本名
|
||||
Public Const VersionStandardCode As String = "2.8.9." & VersionBranchCode '标准格式的四段式版本号
|
||||
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
|
||||
#If BETA Then
|
||||
Public Const VersionCode As Integer = 340 'Release
|
||||
#Else
|
||||
Public Const VersionCode As Integer = 339 'Snapshot
|
||||
Public Const VersionCode As Integer = 341 'Snapshot
|
||||
#End If
|
||||
'自动生成的版本信息
|
||||
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
|
||||
@@ -176,9 +176,9 @@ Public Module ModBase
|
||||
''' </summary>
|
||||
Public Const IconButtonOffline As String = "M533.293176 788.841412a60.235294 60.235294 0 1 1 85.202824 85.202823l-42.616471 42.586353c-129.355294 129.385412-339.124706 129.385412-468.510117 0-129.385412-129.385412-129.385412-339.124706 0-468.510117l42.586353-42.616471a60.235294 60.235294 0 1 1 85.202823 85.202824l-42.61647 42.586352a210.823529 210.823529 0 1 0 298.164706 298.164706l42.586352-42.61647z m255.548236-255.548236l42.61647-42.586352a210.823529 210.823529 0 1 0-298.164706-298.164706l-42.586352 42.61647a60.235294 60.235294 0 1 1-85.202824-85.202823l42.616471-42.586353c129.355294-129.385412 339.124706-129.385412 468.510117 0 129.385412 129.385412 129.385412 339.124706 0 468.510117l-42.586353 42.616471a60.235294 60.235294 0 1 1-85.202823-85.202824zM192.542118 192.542118a60.235294 60.235294 0 0 1 85.202823 0l553.712941 553.712941a60.235294 60.235294 0 0 1-85.202823 85.202823L192.542118 277.744941a60.235294 60.235294 0 0 1 0-85.202823z"
|
||||
''' <summary>
|
||||
''' 图标,音符,1x
|
||||
''' 图标,服务端,1x
|
||||
''' </summary>
|
||||
Public Const IconButtonServer As String = "M640 725.333333a42.666667 42.666667 0 1 0 0 85.333334 42.666667 42.666667 0 0 0 0-85.333334z m-256 0H256a42.666667 42.666667 0 0 0 0 85.333334h128a42.666667 42.666667 0 1 0 0-85.333334z m384 0a42.666667 42.666667 0 1 0 0 85.333334 42.666667 42.666667 0 0 0 0-85.333334z m-128-256a42.666667 42.666667 0 1 0 0 85.333334 42.666667 42.666667 0 0 0 0-85.333334z m-256 0H256a42.666667 42.666667 0 1 0 0 85.333334h128a42.666667 42.666667 0 1 0 0-85.333334z m384-256a42.666667 42.666667 0 1 0 0 85.333334 42.666667 42.666667 0 0 0 0-85.333334z m0 256a42.666667 42.666667 0 1 0 0 85.333334 42.666667 42.666667 0 0 0 0-85.333334z m170.666667-256a128 128 0 0 0-128-128H213.333333a128 128 0 0 0-128 128v85.333334a128 128 0 0 0 33.28 85.333333A128 128 0 0 0 85.333333 469.333333v85.333334a128 128 0 0 0 33.28 85.333333A128 128 0 0 0 85.333333 725.333333v85.333334a128 128 0 0 0 128 128h597.333334a128 128 0 0 0 128-128v-85.333334a128 128 0 0 0-33.28-85.333333 128 128 0 0 0 33.28-85.333333v-85.333334a128 128 0 0 0-33.28-85.333333A128 128 0 0 0 938.666667 298.666667V213.333333z m-85.333334 597.333334a42.666667 42.666667 0 0 1-42.666666 42.666666H213.333333a42.666667 42.666667 0 0 1-42.666666-42.666666v-85.333334a42.666667 42.666667 0 0 1 42.666666-42.666666h597.333334a42.666667 42.666667 0 0 1 42.666666 42.666666v85.333334z m0-256a42.666667 42.666667 0 0 1-42.666666 42.666666H213.333333a42.666667 42.666667 0 0 1-42.666666-42.666666v-85.333334a42.666667 42.666667 0 0 1 42.666666-42.666666h597.333334a42.666667 42.666667 0 0 1 42.666666 42.666666v85.333334z m0-256a42.666667 42.666667 0 0 1-42.666666 42.666666H213.333333a42.666667 42.666667 0 0 1-42.666666-42.666666V213.333333a42.666667 42.666667 0 0 1 42.666666-42.666666h597.333334a42.666667 42.666667 0 0 1 42.666666 42.666666v85.333334z m-213.333333-85.333334a42.666667 42.666667 0 1 0 0 85.333334 42.666667 42.666667 0 0 0 0-85.333334zM384 213.333333H256a42.666667 42.666667 0 1 0 0 85.333334h128a42.666667 42.666667 0 1 0 0-85.333334z"
|
||||
Public Const IconButtonServer As String = "M224 160a64 64 0 0 0-64 64v576a64 64 0 0 0 64 64h576a64 64 0 0 0 64-64V224a64 64 0 0 0-64-64H224z m0 384h576v256H224v-256z m192 96v64h320v-64H416z m-128 0v64h64v-64H288zM224 224h576v256H224V224z m192 96v64h320v-64H416z m-128 0v64h64v-64H288z"
|
||||
''' <summary>
|
||||
''' 图标,音符,1x
|
||||
''' </summary>
|
||||
@@ -1348,8 +1348,8 @@ RetryDir:
|
||||
|
||||
'常见错误(记得同时修改下面的)
|
||||
Dim CommonReason As String = Nothing
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。"
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is BadImageFormatException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。若无法安装,请先卸载较新版本的 .NET Framework,然后再尝试安装。"
|
||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
||||
CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
|
||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
||||
@@ -1368,7 +1368,7 @@ RetryDir:
|
||||
If CommonReason Is Nothing Then
|
||||
Return Desc & Stack & TypeDesc
|
||||
Else
|
||||
Dim Result As String = DescList.First & vbCrLf & CommonReason & vbCrLf & "————————————" & vbCrLf
|
||||
Dim Result As String = CommonReason & vbCrLf & DescList.First & vbCrLf & "————————————" & vbCrLf
|
||||
DescList(0) = "详细错误信息:"
|
||||
Return Result & Join(DescList, vbCrLf & "→ ") & Stack & TypeDesc
|
||||
End If
|
||||
@@ -1396,8 +1396,8 @@ RetryDir:
|
||||
|
||||
'常见错误(记得同时修改上面的)
|
||||
Dim CommonReason As String = Nothing
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。"
|
||||
If TypeOf InnerEx Is TypeLoadException OrElse TypeOf InnerEx Is BadImageFormatException OrElse TypeOf InnerEx Is MissingMethodException OrElse TypeOf InnerEx Is NotImplementedException OrElse TypeOf InnerEx Is TypeInitializationException Then
|
||||
CommonReason = "PCL 的运行环境存在问题。请尝试重新安装 .NET Framework 4.6.2 然后再试。若无法安装,请先卸载较新版本的 .NET Framework,然后再尝试安装。"
|
||||
ElseIf TypeOf InnerEx Is UnauthorizedAccessException Then
|
||||
CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
|
||||
ElseIf TypeOf InnerEx Is OutOfMemoryException Then
|
||||
@@ -1411,7 +1411,7 @@ RetryDir:
|
||||
|
||||
'构造输出信息
|
||||
If CommonReason IsNot Nothing Then
|
||||
Return DescList.First & ":" & CommonReason
|
||||
Return CommonReason & "详细错误:" & DescList.First
|
||||
Else
|
||||
DescList.Reverse() '让最深层错误在最左边
|
||||
Return Join(DescList, " → ")
|
||||
@@ -1721,16 +1721,6 @@ RetryDir:
|
||||
Public Function RegexReplaceEach(Input As String, Replacement As MatchEvaluator, Regex As String, Optional options As RegexOptions = RegularExpressions.RegexOptions.None) As String
|
||||
Return RegularExpressions.Regex.Replace(Input, Regex, Replacement, options)
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 检查传入字符串会不会引发 Issue #4505
|
||||
''' </summary>
|
||||
Public Function Ntfs83NameCheck(name As String) As Boolean
|
||||
Dim regex As New Regex("(.*)~(\d*)")
|
||||
Dim namePart As Byte() = Encoding.UTF8.GetBytes(regex.Match(name).Groups(1).Value)
|
||||
Dim numPart As Integer = regex.Match(name).Groups(2).Value.Length
|
||||
|
||||
Return namePart.Length >= 6 AndAlso numPart = 1
|
||||
End Function
|
||||
|
||||
#End Region
|
||||
|
||||
@@ -1822,10 +1812,10 @@ RetryDir:
|
||||
'进行搜索,获取相似信息
|
||||
For Each Entry In Entries
|
||||
Entry.Similarity = SearchSimilarityWeighted(Entry.SearchSource, Query)
|
||||
Entry.AbsoluteRight = False
|
||||
For Each Pair In Entry.SearchSource
|
||||
If Pair.Key.Replace(" ", "").ContainsF(Query.Replace(" ", ""), True) Then Entry.AbsoluteRight = True
|
||||
Next
|
||||
Entry.AbsoluteRight =
|
||||
Query.Split(" ").All( '对于按空格分割的每一段
|
||||
Function(QueryPart) Entry.SearchSource.Any( '若与任意一个搜索源完全匹配,则标记为完全匹配项
|
||||
Function(Source) Source.Key.Replace(" ", "").ContainsF(QueryPart, True)))
|
||||
Next
|
||||
'按照相似度进行排序
|
||||
Entries = Sort(Entries,
|
||||
@@ -1854,10 +1844,26 @@ RetryDir:
|
||||
|
||||
#Region "系统"
|
||||
|
||||
''' <summary>
|
||||
''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
|
||||
''' </summary>
|
||||
Public PathPure As String = GetPureASCIIDir()
|
||||
Private Function GetPureASCIIDir() As String
|
||||
If (Path & "PCL").IsASCII() Then
|
||||
Return Path & "PCL\"
|
||||
ElseIf PathAppdata.IsASCII() Then
|
||||
Return PathAppdata
|
||||
ElseIf PathTemp.IsASCII() Then
|
||||
Return PathTemp
|
||||
Else
|
||||
Return OsDrive & "ProgramData\PCL\"
|
||||
End If
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 指示接取到这个异常的函数进行重试。
|
||||
''' </summary>
|
||||
Public Class RetryException
|
||||
Public Class RestartException
|
||||
Inherits Exception
|
||||
End Class
|
||||
|
||||
|
||||
@@ -939,7 +939,6 @@ RequestFinished:
|
||||
Dim StartPosition As Long, StartSource As NetSource = Nothing
|
||||
Dim Th As Thread, ThreadInfo As NetThread
|
||||
SyncLock LockChain
|
||||
|
||||
'获取线程起点与下载源
|
||||
'不分割
|
||||
If IsNoSplit Then GoTo Capture
|
||||
@@ -1049,6 +1048,15 @@ StartThread:
|
||||
If ModeDebug AndAlso HttpResponse.ResponseUri.OriginalString <> Info.Source.Url Then
|
||||
Log($"[Download] {LocalName} {Info.Uuid}#:重定向至 {HttpResponse.ResponseUri.OriginalString}")
|
||||
End If
|
||||
''从响应头获取文件名
|
||||
'If Info.IsFirstThread Then
|
||||
' Dim FileName As String = GetFileNameFromResponse(HttpResponse)
|
||||
' If ModeDebug Then Log($"[Download] {LocalName} {Info.Uuid}#:远程文件名:{If(FileName, "未提供")}")
|
||||
' If FileName IsNot Nothing AndAlso LocalName = "待定" Then
|
||||
' LocalName = FileName
|
||||
' Log($"[Download] {LocalName} {Info.Uuid}#:从响应头获取到文件名")
|
||||
' End If
|
||||
'End If
|
||||
'文件大小校验
|
||||
ContentLength = HttpResponse.ContentLength
|
||||
If ContentLength = -1 Then
|
||||
@@ -1133,7 +1141,7 @@ NotSupportRange:
|
||||
If NetTaskSpeedLimitHigh > 0 Then NetTaskSpeedLimitLeft -= RealDataCount
|
||||
End SyncLock
|
||||
Dim DeltaTime = GetTimeTick() - Info.LastReceiveTime
|
||||
If DeltaTime > 1000000 Then DeltaTime = 0 '时间刻反转导致出现极大值
|
||||
If DeltaTime > 1000000 Then DeltaTime = 1 '时间刻反转导致出现极大值
|
||||
If RealDataCount > 0 Then
|
||||
'有数据
|
||||
If Info.DownloadDone = 0 Then
|
||||
@@ -1174,7 +1182,7 @@ NotSupportRange:
|
||||
ResultStream.Write(HttpData, 0, RealDataCount)
|
||||
End If
|
||||
'检查速度是否过慢
|
||||
If DeltaTime > 1000 AndAlso DeltaTime > RealDataCount Then '数据包间隔大于 1s,且速度小于 1K/s
|
||||
If DeltaTime > 1500 AndAlso DeltaTime > RealDataCount Then '数据包间隔大于 1.5s,且速度小于 1.5K/s
|
||||
Throw New TimeoutException("由于速度过慢断开链接,下载 " & RealDataCount & " B,消耗 " & DeltaTime & " ms。")
|
||||
End If
|
||||
Info.LastReceiveTime = GetTimeTick()
|
||||
@@ -1286,6 +1294,17 @@ Wrong:
|
||||
If ((FileSize >= 0 AndAlso DownloadDone >= FileSize) OrElse (FileSize = -1 AndAlso DownloadDone > 0)) AndAlso State < NetState.Merge Then Merge()
|
||||
End Try
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' 从 HTTP 响应头中获取文件名。
|
||||
''' 如果没有,返回 Nothing。
|
||||
''' </summary>
|
||||
Private Function GetFileNameFromResponse(response As HttpWebResponse) As String
|
||||
Dim header As String = response.Headers("Content-Disposition")
|
||||
If String.IsNullOrEmpty(header) Then Return Nothing
|
||||
'attachment; filename="filename.ext"
|
||||
If Not header.Contains("filename=") Then Return Nothing
|
||||
Return header.After("filename=").Trim(""""c, " "c).Before(";")
|
||||
End Function
|
||||
|
||||
'下载文件的最终收束事件
|
||||
''' <summary>
|
||||
|
||||
@@ -233,8 +233,8 @@ Public Class ValidateFolderName
|
||||
'检查特殊字符串
|
||||
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件夹名不可为 %!", True).Validate(Str)
|
||||
If Not InvalidStrCheck = "" Then Return InvalidStrCheck
|
||||
'检查 NTFS 8.3 (issue #4505)
|
||||
If Ntfs83NameCheck(Str) Then Return "文件夹名不能是一个有效的 NTFS 8.3 文件名!"
|
||||
'检查 NTFS 8.3 文件名(#4505)
|
||||
If RegexCheck(Str, ".{2,}~\d") Then Return "文件夹名不能包含这一特殊格式!"
|
||||
'检查文件夹重名
|
||||
Dim Arr As New List(Of String)
|
||||
If PathIgnore IsNot Nothing Then
|
||||
@@ -288,8 +288,8 @@ Public Class ValidateFileName
|
||||
'检查特殊字符串
|
||||
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件名不可为 %!", True).Validate(Str)
|
||||
If Not InvalidStrCheck = "" Then Return InvalidStrCheck
|
||||
'检查 NTFS 8.3 (issue #4505)
|
||||
If Ntfs83NameCheck(Str) Then Return "文件名不能是一个有效的 NTFS 8.3 文件名!"
|
||||
'检查 NTFS 8.3 文件名(#4505)
|
||||
If RegexCheck(Str, ".{2,}~\d") Then Return "文件名不能包含这一特殊格式!"
|
||||
'检查文件重名
|
||||
If ParentFolder IsNot Nothing Then
|
||||
Dim DirInfo As New DirectoryInfo(ParentFolder)
|
||||
@@ -355,9 +355,9 @@ Fin:
|
||||
'检查特殊字符串
|
||||
Dim InvalidStrCheck As String = New ValidateExceptSame({"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}, "文件夹名不可为 %!").Validate(SubStr)
|
||||
If Not InvalidStrCheck = "" Then Return InvalidStrCheck
|
||||
'检查 NTFS 8.3 (issue #4505)
|
||||
If Ntfs83NameCheck(Str) Then Return "文件夹名不能是一个有效的 NTFS 8.3 文件名!"
|
||||
'检查 NTFS 8.3 文件名(#4505)
|
||||
If RegexCheck(Str, ".{2,}~\d") Then Return "文件夹名不能包含这一特殊格式!"
|
||||
Next
|
||||
Return ""
|
||||
End Function
|
||||
End Class
|
||||
End Class
|
||||
|
||||
@@ -7,7 +7,7 @@ Public Class MyBitmap
|
||||
''' <summary>
|
||||
''' 位图缓存。
|
||||
''' </summary>
|
||||
Public Shared BitmapCache As New Dictionary(Of String, MyBitmap)
|
||||
Public Shared BitmapCache As New Concurrent.ConcurrentDictionary(Of String, MyBitmap)
|
||||
|
||||
''' <summary>
|
||||
''' 存储的图片
|
||||
@@ -61,7 +61,7 @@ Public Class MyBitmap
|
||||
Pic = BitmapCache(FilePathOrResourceName).Pic
|
||||
Else
|
||||
Pic = New MyBitmap(CType((New ImageSourceConverter).ConvertFromString(FilePathOrResourceName), ImageSource))
|
||||
BitmapCache.Add(FilePathOrResourceName, Pic)
|
||||
BitmapCache.TryAdd(FilePathOrResourceName, Pic)
|
||||
End If
|
||||
Else
|
||||
'使用这种自己接管 FileStream 的方法加载才能解除文件占用
|
||||
@@ -72,11 +72,9 @@ Public Class MyBitmap
|
||||
InputStream.Seek(0, SeekOrigin.Begin)
|
||||
If Header(0) = 82 AndAlso Header(1) = 73 Then
|
||||
'读取 WebP
|
||||
If Is32BitSystem Then Throw New Exception("不支持在 32 位系统下加载 WebP 图片。")
|
||||
Dim FileBytes(InputStream.Length - 1) As Byte
|
||||
InputStream.Read(FileBytes, 0, FileBytes.Length)
|
||||
Dim Decoder As New Imazen.WebP.SimpleDecoder()
|
||||
Pic = Decoder.DecodeFromBytes(FileBytes, FileBytes.Length)
|
||||
Pic = WebPDecoder.DecodeFromBytes(FileBytes) '将代码隔离在另外一个类中,这样只要不走进这个分支就不会加载 Imazen.WebP.dll
|
||||
Else
|
||||
Pic = New System.Drawing.Bitmap(InputStream)
|
||||
End If
|
||||
@@ -86,10 +84,9 @@ Public Class MyBitmap
|
||||
Pic = My.Application.TryFindResource(FilePathOrResourceName)
|
||||
If Pic Is Nothing Then
|
||||
Pic = New System.Drawing.Bitmap(1, 1)
|
||||
Log(ex, $"加载位图失败({FilePathOrResourceName})")
|
||||
Throw
|
||||
Throw New Exception($"加载 MyBitmap 失败({FilePathOrResourceName})", ex)
|
||||
Else
|
||||
Log(ex, $"指定类型有误的位图加载({FilePathOrResourceName})", LogLevel.Developer)
|
||||
Log(ex, $"指定类型有误的 MyBitmap 加载({FilePathOrResourceName})", LogLevel.Developer)
|
||||
Exit Try
|
||||
End If
|
||||
End Try
|
||||
@@ -116,6 +113,13 @@ Public Class MyBitmap
|
||||
Pic = New System.Drawing.Bitmap(MS)
|
||||
End Using
|
||||
End Sub
|
||||
Private Class WebPDecoder '将代码隔离在另外一个类中,这样只要不调用这个方法就不会加载 Imazen.WebP.dll
|
||||
Public Shared Function DecodeFromBytes(Bytes As Byte()) As System.Drawing.Bitmap
|
||||
If Is32BitSystem Then Throw New Exception("不支持在 32 位系统下加载 WebP 图片。")
|
||||
Dim Decoder As New Imazen.WebP.SimpleDecoder()
|
||||
Return Decoder.DecodeFromBytes(Bytes, Bytes.Length)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' 获取裁切的图片,这个方法不会导致原对象改变且会返回一个新的对象。
|
||||
@@ -152,4 +156,4 @@ Public Class MyBitmap
|
||||
End Using
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
End Class
|
||||
|
||||
Reference in New Issue
Block a user