ModValidate.vb 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. '提供不同的输入验证方法,名称以 Validate 开头
  2. ''' <summary>
  3. ''' 输入验证规则基类。要查看所有的输入验证规则,可在输入 Validate 后查看自动补全。
  4. ''' </summary>
  5. Public MustInherit Class Validate
  6. ''' <summary>
  7. ''' 验证某字符串是否符合验证要求。若符合,返回空字符串;若不符合,返回错误原因。
  8. ''' </summary>
  9. Public MustOverride Function Validate(Str As String) As String
  10. End Class
  11. ''' <summary>
  12. ''' 若为空则直接通过检查。
  13. ''' </summary>
  14. Public Class ValidateNullable
  15. Inherits Validate
  16. Public Overrides Function Validate(Str As String) As String
  17. If IsNothing(Str) OrElse String.IsNullOrEmpty(Str) Then Return Nothing
  18. Return ""
  19. End Function
  20. End Class
  21. ''' <summary>
  22. ''' 不能为 Nothing 或空字符串(不包括全空格检查)。
  23. ''' </summary>
  24. Public Class ValidateNullOrEmpty
  25. Inherits Validate
  26. Public Overrides Function Validate(Str As String) As String
  27. If IsNothing(Str) OrElse String.IsNullOrEmpty(Str) Then Return "输入内容不能为空!"
  28. Return ""
  29. End Function
  30. End Class
  31. ''' <summary>
  32. ''' 不能为 Nothing 或空字符串(包括全空格检查)。
  33. ''' </summary>
  34. Public Class ValidateNullOrWhiteSpace
  35. Inherits Validate
  36. Public Overrides Function Validate(Str As String) As String
  37. If IsNothing(Str) OrElse String.IsNullOrWhiteSpace(Str) Then Return "输入内容不能为空!"
  38. Return ""
  39. End Function
  40. End Class
  41. ''' <summary>
  42. ''' 必须满足正则表达式。
  43. ''' </summary>
  44. Public Class ValidateRegex
  45. Inherits Validate
  46. Public Property Regex As String
  47. Public Property ErrorDescription As String = ""
  48. Public Sub New()
  49. End Sub '用于 XAML 初始化
  50. Public Sub New(Regex As String, Optional ErrorDescription As String = "")
  51. Me.Regex = Regex
  52. Me.ErrorDescription = ErrorDescription
  53. End Sub
  54. Public Overrides Function Validate(Str As String) As String
  55. If Not RegexCheck(Str, Regex) Then Return ErrorDescription
  56. Return ""
  57. End Function
  58. End Class
  59. ''' <summary>
  60. ''' 必须是一个完整网址。
  61. ''' </summary>
  62. Public Class ValidateHttp
  63. Inherits Validate
  64. Public Sub New()
  65. End Sub '用于 XAML 初始化
  66. Public Overrides Function Validate(Str As String) As String
  67. If Str.EndsWith("/") Then Str = Str.Substring(0, Str.Length - 1)
  68. If Not RegexCheck(Str, "^(http[s]?)\://") Then Return "输入的网址无效!"
  69. Return ""
  70. End Function
  71. End Class
  72. ''' <summary>
  73. ''' 必须为整数。
  74. ''' </summary>
  75. Public Class ValidateInteger
  76. Inherits Validate
  77. Public Property Min As Integer
  78. Public Property Max As Integer = Integer.MaxValue
  79. Public Sub New()
  80. End Sub '用于 XAML 初始化
  81. Public Sub New(Min As Integer, Max As Integer)
  82. Me.Min = Min
  83. Me.Max = Max
  84. End Sub
  85. Public Overrides Function Validate(Str As String) As String
  86. If Str.Length > 9 Then Return "请输入一个大小合理的数字!"
  87. Dim Valed As Integer = Val(Str)
  88. If Valed.ToString <> Str Then Return "请输入一个整数!"
  89. If Val(Str) > Max Then Return "不可超过 " & Max & "!"
  90. If Val(Str) < Min Then Return "不可低于 " & Min & "!"
  91. Return ""
  92. End Function
  93. End Class
  94. ''' <summary>
  95. ''' 长度限制。
  96. ''' </summary>
  97. Public Class ValidateLength
  98. Inherits Validate
  99. Public Property Min As Integer = 0
  100. Public Property Max As Integer = Integer.MaxValue
  101. Public Sub New()
  102. End Sub '用于 XAML 初始化
  103. Public Sub New(Min As Integer, Optional Max As Integer = Integer.MaxValue)
  104. Me.Min = Min
  105. Me.Max = Max
  106. End Sub
  107. Public Overrides Function Validate(Str As String) As String
  108. If Len(Str) <> Max AndAlso Max = Min Then Return "长度必须为 " & Max & " 个字符!"
  109. If Len(Str) > Max Then Return "长度最长为 " & Max & " 个字符!"
  110. If Len(Str) < Min Then Return "长度至少需 " & Min & " 个字符!"
  111. Return ""
  112. End Function
  113. End Class
  114. ''' <summary>
  115. ''' 不能包含某些特定字符串。忽略大小写。
  116. ''' </summary>
  117. Public Class ValidateExcept
  118. Inherits Validate
  119. Public Property Excepts As ObjectModel.Collection(Of String) = New ObjectModel.Collection(Of String)
  120. Public Property ErrorMessage As String
  121. Public Sub New()
  122. ErrorMessage = "输入内容不能包含 %!"
  123. End Sub '用于 XAML 初始化
  124. Public Sub New(Excepts As ObjectModel.Collection(Of String), Optional ErrorMessage As String = "输入内容不能包含 %!")
  125. Me.Excepts = Excepts
  126. Me.ErrorMessage = ErrorMessage
  127. End Sub
  128. Public Sub New(Excepts As IEnumerable, Optional ErrorMessage As String = "输入内容不能包含 %!")
  129. Me.Excepts = New ObjectModel.Collection(Of String)
  130. Me.ErrorMessage = ErrorMessage
  131. For Each Data As String In Excepts
  132. Me.Excepts.Add(Data)
  133. Next
  134. End Sub
  135. Public Overrides Function Validate(Str As String) As String
  136. For Each Ch As String In Excepts
  137. If Str.IndexOf(Ch, StringComparison.OrdinalIgnoreCase) >= 0 Then
  138. If IsNothing(ErrorMessage) Then ErrorMessage = ""
  139. Return ErrorMessage.Replace("%", Ch)
  140. End If
  141. Next
  142. Return ""
  143. End Function
  144. End Class
  145. ''' <summary>
  146. ''' 不能与某些特定字符串相同。
  147. ''' </summary>
  148. Public Class ValidateExceptSame
  149. Inherits Validate
  150. Public Property Excepts As ObjectModel.Collection(Of String) = New ObjectModel.Collection(Of String)
  151. Public Property ErrorMessage As String
  152. Public Property IgnoreCase As Boolean = False
  153. Public Sub New(Excepts As ObjectModel.Collection(Of String), Optional ErrorMessage As String = "输入内容不能为 %!", Optional IgnoreCase As Boolean = False)
  154. Me.Excepts = Excepts
  155. Me.ErrorMessage = ErrorMessage
  156. Me.IgnoreCase = IgnoreCase
  157. End Sub
  158. Public Sub New(Excepts As IEnumerable, Optional ErrorMessage As String = "输入内容不能为 %!", Optional IgnoreCase As Boolean = False)
  159. Me.Excepts = New ObjectModel.Collection(Of String)
  160. For Each Data As String In Excepts
  161. Me.Excepts.Add(Data)
  162. Next
  163. Me.ErrorMessage = ErrorMessage
  164. Me.IgnoreCase = IgnoreCase
  165. End Sub
  166. Public Overrides Function Validate(Str As String) As String
  167. If Str Is Nothing Then Return ErrorMessage.Replace("%", "null")
  168. For Each Ch As String In Excepts
  169. If IgnoreCase Then
  170. If Str.ToLower = Ch.ToLower Then Return ErrorMessage.Replace("%", Ch)
  171. Else
  172. If Str.Equals(Ch) Then Return ErrorMessage.Replace("%", Ch) '使用 = 不确定是否会忽略大小写
  173. End If
  174. Next
  175. Return ""
  176. End Function
  177. End Class
  178. ''' <summary>
  179. ''' 对文件夹名的粗略的特化检测。
  180. ''' </summary>
  181. Public Class ValidateFolderName
  182. Inherits Validate
  183. Public Property Path As String
  184. Public Property UseMinecraftCharCheck As Boolean = True
  185. Public Property IgnoreCase As Boolean = True
  186. Private ReadOnly PathIgnore As IEnumerable(Of DirectoryInfo)
  187. Public Sub New(Path As String, Optional UseMinecraftCharCheck As Boolean = True, Optional IgnoreCase As Boolean = True)
  188. Me.Path = Path
  189. Me.IgnoreCase = IgnoreCase
  190. Me.UseMinecraftCharCheck = UseMinecraftCharCheck
  191. On Error Resume Next
  192. PathIgnore = New DirectoryInfo(Path).EnumerateDirectories
  193. End Sub
  194. Public Overrides Function Validate(Str As String) As String
  195. Try
  196. '检查是否为空
  197. Dim LengthCheck As String = New ValidateNullOrWhiteSpace().Validate(Str)
  198. If Not LengthCheck = "" Then Return LengthCheck
  199. '检查空格
  200. If Str.StartsWith(" ") Then Return "文件夹名不能以空格开头!"
  201. If Str.EndsWith(" ") Then Return "文件夹名不能以空格结尾!"
  202. '检查长度
  203. LengthCheck = New ValidateLength(1, 100).Validate(Str)
  204. If Not LengthCheck = "" Then Return LengthCheck
  205. '检查尾部小数点
  206. If Str.EndsWith(".") Then Return "文件夹名不能以小数点结尾!"
  207. '检查特殊字符
  208. Dim CharactCheck As String = New ValidateExcept(IO.Path.GetInvalidFileNameChars() & If(UseMinecraftCharCheck, "!;", ""), "文件夹名不可包含 % 字符!").Validate(Str)
  209. If Not CharactCheck = "" Then Return CharactCheck
  210. '检查特殊字符串
  211. 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(Str)
  212. If Not InvalidStrCheck = "" Then Return InvalidStrCheck
  213. '检查文件夹重名
  214. Dim Arr As New List(Of String)
  215. If PathIgnore IsNot Nothing Then
  216. For Each Folder As DirectoryInfo In PathIgnore
  217. Arr.Add(Folder.Name)
  218. Next
  219. End If
  220. Dim SameNameCheck = New ValidateExceptSame(Arr, "不可与现有文件夹重名!", IgnoreCase).Validate(Str)
  221. If Not SameNameCheck = "" Then Return SameNameCheck
  222. Return ""
  223. Catch ex As Exception
  224. Log(ex, "检查文件夹名出错")
  225. Return "错误:" & ex.Message
  226. End Try
  227. End Function
  228. End Class
  229. ''' <summary>
  230. ''' 要求输入一个可用的文件夹路径。
  231. ''' </summary>
  232. Public Class ValidateFolderPath
  233. Inherits Validate
  234. Public Property UseMinecraftCharCheck As Boolean = True
  235. Public Sub New()
  236. End Sub
  237. Public Sub New(UseMinecraftCharCheck As Boolean)
  238. Me.UseMinecraftCharCheck = UseMinecraftCharCheck
  239. End Sub
  240. Public Overrides Function Validate(Str As String) As String
  241. '去除尾部斜线,统一为 \
  242. Str = Str.Replace("/", "\")
  243. If Not Str.TrimEnd("\").EndsWith(":") Then Str = Str.TrimEnd("\")
  244. '检查是否为空
  245. Dim LengthCheck As String = New ValidateNullOrWhiteSpace().Validate(Str)
  246. If Not LengthCheck = "" Then Return LengthCheck
  247. '检查长度
  248. LengthCheck = New ValidateLength(1, 254).Validate(Str)
  249. If Not LengthCheck = "" Then Return LengthCheck
  250. '检查开头
  251. If Str.StartsWith("\\Mac\") Then GoTo Fin
  252. For Each Drive As DriveInfo In My.Computer.FileSystem.Drives
  253. If Str.ToUpper = Drive.Name Then Return ""
  254. If Str.ToUpper.StartsWith(Drive.Name) Then GoTo Fin
  255. Next
  256. Return "文件夹路径头存在错误!"
  257. Fin:
  258. '对首层以外的路径检查
  259. For i = If(Str.StartsWith("\\Mac\"), 2, 1) To Str.Split("\").Count - 1
  260. Dim SubStr As String = Str.Split("\")(i)
  261. '检查是否为空
  262. Dim SubLengthCheck As String = New ValidateNullOrWhiteSpace().Validate(SubStr)
  263. If Not SubLengthCheck = "" Then Return "文件夹路径存在错误!"
  264. '检查特殊字符
  265. Dim CharactCheck As String = New ValidateExcept(IO.Path.GetInvalidFileNameChars() & If(UseMinecraftCharCheck, "!;", ""), "路径中存在无效字符!").Validate(SubStr)
  266. If Not CharactCheck = "" Then Return CharactCheck
  267. '检查头部空格
  268. If SubStr.StartsWith(" ") Then Return "文件夹名不能以空格开头!"
  269. If SubStr.EndsWith(" ") Then Return "文件夹名不能以空格结尾!"
  270. '检查尾部小数点
  271. If SubStr.EndsWith(".") Then Return "文件夹名不能以小数点结尾!"
  272. '检查特殊字符串
  273. 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)
  274. If Not InvalidStrCheck = "" Then Return InvalidStrCheck
  275. Next
  276. Return ""
  277. End Function
  278. End Class
  279. ''' <summary>
  280. ''' 敏感词过滤。
  281. ''' </summary>
  282. Public Class ValidateFilter
  283. Inherits Validate
  284. Private Shared Excepts As String() = SecretDecrypt(SecretSensitiveWordsRaw).Split("|")
  285. Public Sub New()
  286. End Sub '用于 XAML 初始化
  287. Public Overrides Function Validate(Str As String) As String
  288. '提取无间隔符的字符串
  289. Dim RealStr As String = ""
  290. For Each St In If(Str, "").ToLower
  291. If String.IsNullOrWhiteSpace(St.ToString) OrElse ("!@#$%^&*()_+-={}[]|\;':"",./<>? ~ ·!¥…()—,。、《》?‘;:【】{}" & vbLQ & vbRQ).ToCharArray.Contains(St) Then Continue For
  292. RealStr += St
  293. Next
  294. '检查
  295. For Each Except In Excepts
  296. If RealStr.Contains(Except) Then Return "存在敏感内容!"
  297. Next
  298. Return ""
  299. End Function
  300. End Class