VCS_IE_Functions.bas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. Option Compare Database
  2. Option Private Module
  3. Option Explicit
  4. Private Const AggressiveSanitize As Boolean = True
  5. Private Const StripPublishOption As Boolean = True
  6. ' Constants for Scripting.FileSystemObject API
  7. Public Const ForReading = 1, ForWriting = 2, ForAppending = 8
  8. Public Const TristateTrue = -1, TristateFalse = 0, TristateUseDefault = -2
  9. ' constants for names conversion
  10. Public Const ForbiddenCars = "34,42,47,58,60,62,63,92,124"
  11. ' Can we export without closing the form?
  12. ' Export a database object with optional UCS2-to-UTF-8 conversion.
  13. Public Sub ExportObject(ByVal obj_type_num As Integer, ByVal obj_name As String, _
  14. ByVal file_path As String, Optional ByVal Ucs2Convert As Boolean = False)
  15. VCS_Dir.MkDirIfNotExist Left$(file_path, InStrRev(file_path, "\"))
  16. If Ucs2Convert Then
  17. Dim tempFileName As String
  18. tempFileName = VCS_File.TempFile()
  19. Application.SaveAsText obj_type_num, obj_name, tempFileName
  20. VCS_File.ConvertUcs2Utf8 tempFileName, file_path
  21. Dim FSO As Object
  22. Set FSO = CreateObject("Scripting.FileSystemObject")
  23. FSO.DeleteFile tempFileName
  24. Else
  25. Application.SaveAsText obj_type_num, obj_name, file_path
  26. End If
  27. logger "ExportObject", "DEBUG", "Object of type " & obj_type_num & " named " & obj_name & " exported to " & file_path
  28. If obj_type_num <> acModule Then
  29. SanitizeFile file_path
  30. End If
  31. End Sub
  32. ' Import a database object with optional UTF-8-to-UCS2 conversion.
  33. Public Sub ImportObject(ByVal obj_type_num As Integer, ByVal obj_name As String, _
  34. ByVal file_path As String, Optional ByVal Ucs2Convert As Boolean = False)
  35. If Not VCS_Dir.FileExists(file_path) Then
  36. logger "ImportObject", "ERROR", "Can't find the file " & file_path
  37. Exit Sub
  38. End If
  39. On Error GoTo err
  40. If Ucs2Convert Then
  41. Dim tempFileName As String
  42. tempFileName = VCS_File.TempFile()
  43. VCS_File.ConvertUtf8Ucs2 file_path, tempFileName
  44. Application.LoadFromText obj_type_num, obj_name, tempFileName
  45. Dim FSO As Object
  46. Set FSO = CreateObject("Scripting.FileSystemObject")
  47. FSO.DeleteFile tempFileName
  48. Else
  49. Application.LoadFromText obj_type_num, obj_name, file_path
  50. End If
  51. logger "ImportObject", "DEBUG", "Object of type " & obj_type_num & " named " & obj_name & " imported from " & file_path
  52. Exit Sub
  53. err:
  54. logger "ImportObject", "CRITICAL", "Unable to import the object " & obj_name & " (" & obj_type_num & ")" & "[" & err.Description & "]"
  55. End Sub
  56. Public Sub SanitizeFile(ByVal filepath As String)
  57. ' cleans the file from unnecessary lines
  58. Dim FSO As Object
  59. Set FSO = CreateObject("Scripting.FileSystemObject")
  60. ' Setup Block matching Regex.
  61. Dim rxBlock As Object
  62. Set rxBlock = CreateObject("VBScript.RegExp")
  63. rxBlock.ignoreCase = False
  64. ' Match PrtDevNames / Mode with or without W
  65. Dim srchPattern As String
  66. srchPattern = "PrtDev(?:Names|Mode)[W]?"
  67. If (AggressiveSanitize = True) Then
  68. ' Add and group aggressive matches
  69. srchPattern = "(?:" & srchPattern
  70. srchPattern = srchPattern & "|GUID|""GUID""|NameMap|dbLongBinary ""DOL"""
  71. srchPattern = srchPattern & ")"
  72. End If
  73. ' Ensure that this is the begining of a block.
  74. srchPattern = srchPattern & " = Begin"
  75. rxBlock.Pattern = srchPattern
  76. ' Setup Line Matching Regex.
  77. Dim rxLine As Object
  78. Set rxLine = CreateObject("VBScript.RegExp")
  79. srchPattern = "^\s*(?:"
  80. srchPattern = srchPattern & "Checksum ="
  81. srchPattern = srchPattern & "|BaseInfo|NoSaveCTIWhenDisabled =1"
  82. If (StripPublishOption = True) Then
  83. srchPattern = srchPattern & "|dbByte ""PublishToWeb"" =""1"""
  84. srchPattern = srchPattern & "|PublishOption =1"
  85. End If
  86. srchPattern = srchPattern & ")"
  87. rxLine.Pattern = srchPattern
  88. Dim isReport As Boolean
  89. isReport = False
  90. ' Dim dir_name, file_name, obj_name As String
  91. '
  92. ' obj_name = Mid$(filename, 1, InStrRev(filename, ".") - 1)
  93. Dim InFile As Object
  94. Set InFile = FSO.OpenTextFile(filepath, iomode:=ForReading, Create:=False, Format:=TristateFalse)
  95. Dim OutFile As Object
  96. Set OutFile = FSO.CreateTextFile(filepath & ".sanitize", overwrite:=True, unicode:=False)
  97. Dim getLine As Boolean
  98. getLine = True
  99. Do Until InFile.AtEndOfStream
  100. DoEvents
  101. Dim txt As String
  102. '
  103. ' Check if we need to get a new line of text
  104. If getLine = True Then
  105. txt = InFile.readline
  106. Else
  107. getLine = True
  108. End If
  109. ' Skip lines starting with line pattern
  110. If rxLine.test(txt) Then
  111. Dim rxIndent As Object
  112. Set rxIndent = CreateObject("VBScript.RegExp")
  113. rxIndent.Pattern = "^(\s+)\S"
  114. '
  115. ' Get indentation level.
  116. Dim matches As Object
  117. Set matches = rxIndent.Execute(txt)
  118. '
  119. ' Setup pattern to match current indent
  120. Select Case matches.count
  121. Case 0
  122. rxIndent.Pattern = "^" & vbNullString
  123. Case Else
  124. rxIndent.Pattern = "^(\s{0," & Len(matches(0).SubMatches(0)) & "})"
  125. End Select
  126. rxIndent.Pattern = rxIndent.Pattern + "\S"
  127. '
  128. ' Skip lines with deeper indentation
  129. Do Until InFile.AtEndOfStream
  130. txt = InFile.readline
  131. If rxIndent.test(txt) Then Exit Do
  132. Loop
  133. ' We've moved on at least one line so do get a new one
  134. ' when starting the loop again.
  135. getLine = False
  136. '
  137. ' skip blocks of code matching block pattern
  138. ElseIf rxBlock.test(txt) Then
  139. Do Until InFile.AtEndOfStream
  140. txt = InFile.readline
  141. If InStr(txt, "End") Then Exit Do
  142. Loop
  143. ElseIf InStr(1, txt, "Begin Report") = 1 Then
  144. isReport = True
  145. OutFile.WriteLine txt
  146. ElseIf isReport = True And (InStr(1, txt, " Right =") Or InStr(1, txt, " Bottom =")) Then
  147. 'skip line
  148. If InStr(1, txt, " Bottom =") Then
  149. isReport = False
  150. End If
  151. Else
  152. OutFile.WriteLine txt
  153. End If
  154. Loop
  155. OutFile.Close
  156. InFile.Close
  157. FSO.DeleteFile (filepath)
  158. Dim thisFile As Object
  159. Set thisFile = FSO.GetFile(filepath & ".sanitize")
  160. thisFile.Move (filepath)
  161. logger "SanitizeFile", "DEBUG", "> File " & filepath & " sanitized"
  162. End Sub
  163. ' For each *.txt in `Path`, find and remove a number of problematic but
  164. ' unnecessary lines of VB code that are inserted automatically by the
  165. ' Access GUI and change often (we don't want these lines of code in
  166. ' version control).
  167. Public Sub SanitizeTextFiles(ByVal path As String, ByVal Ext As String)
  168. Dim FSO As Object
  169. Set FSO = CreateObject("Scripting.FileSystemObject")
  170. '
  171. ' Setup Block matching Regex.
  172. Dim rxBlock As Object
  173. Set rxBlock = CreateObject("VBScript.RegExp")
  174. rxBlock.ignoreCase = False
  175. '
  176. ' Match PrtDevNames / Mode with or without W
  177. Dim srchPattern As String
  178. srchPattern = "PrtDev(?:Names|Mode)[W]?"
  179. If (AggressiveSanitize = True) Then
  180. ' Add and group aggressive matches
  181. srchPattern = "(?:" & srchPattern
  182. srchPattern = srchPattern & "|GUID|""GUID""|NameMap|dbLongBinary ""DOL"""
  183. srchPattern = srchPattern & ")"
  184. End If
  185. ' Ensure that this is the begining of a block.
  186. srchPattern = srchPattern & " = Begin"
  187. 'Debug.Print srchPattern
  188. rxBlock.Pattern = srchPattern
  189. '
  190. ' Setup Line Matching Regex.
  191. Dim rxLine As Object
  192. Set rxLine = CreateObject("VBScript.RegExp")
  193. srchPattern = "^\s*(?:"
  194. srchPattern = srchPattern & "Checksum ="
  195. srchPattern = srchPattern & "|BaseInfo|NoSaveCTIWhenDisabled =1"
  196. If (StripPublishOption = True) Then
  197. srchPattern = srchPattern & "|dbByte ""PublishToWeb"" =""1"""
  198. srchPattern = srchPattern & "|PublishOption =1"
  199. End If
  200. srchPattern = srchPattern & ")"
  201. 'Debug.Print srchPattern
  202. rxLine.Pattern = srchPattern
  203. Dim filename As String
  204. filename = dir$(path & "*." & Ext)
  205. If Len(filename) = 0 Then
  206. logger "SanitizeTextFiles", "INFO", "> No file to sanitized"
  207. Exit Sub
  208. End If
  209. Dim isReport As Boolean
  210. isReport = False
  211. Do Until Len(filename) = 0
  212. DoEvents
  213. Dim obj_name As String
  214. obj_name = Mid$(filename, 1, InStrRev(filename, ".") - 1)
  215. Dim InFile As Object
  216. Set InFile = FSO.OpenTextFile(path & obj_name & "." & Ext, iomode:=ForReading, Create:=False, Format:=TristateFalse)
  217. Dim OutFile As Object
  218. Set OutFile = FSO.CreateTextFile(path & obj_name & ".sanitize", overwrite:=True, unicode:=False)
  219. Dim getLine As Boolean
  220. getLine = True
  221. Do Until InFile.AtEndOfStream
  222. DoEvents
  223. Dim txt As String
  224. '
  225. ' Check if we need to get a new line of text
  226. If getLine = True Then
  227. txt = InFile.readline
  228. Else
  229. getLine = True
  230. End If
  231. '
  232. ' Skip lines starting with line pattern
  233. If rxLine.test(txt) Then
  234. Dim rxIndent As Object
  235. Set rxIndent = CreateObject("VBScript.RegExp")
  236. rxIndent.Pattern = "^(\s+)\S"
  237. '
  238. ' Get indentation level.
  239. Dim matches As Object
  240. Set matches = rxIndent.Execute(txt)
  241. '
  242. ' Setup pattern to match current indent
  243. Select Case matches.count
  244. Case 0
  245. rxIndent.Pattern = "^" & vbNullString
  246. Case Else
  247. rxIndent.Pattern = "^(\s{0," & Len(matches(0).SubMatches(0)) & "})"
  248. End Select
  249. rxIndent.Pattern = rxIndent.Pattern + "\S"
  250. '
  251. ' Skip lines with deeper indentation
  252. Do Until InFile.AtEndOfStream
  253. txt = InFile.readline
  254. If rxIndent.test(txt) Then Exit Do
  255. Loop
  256. ' We've moved on at least one line so do get a new one
  257. ' when starting the loop again.
  258. getLine = False
  259. '
  260. ' skip blocks of code matching block pattern
  261. ElseIf rxBlock.test(txt) Then
  262. Do Until InFile.AtEndOfStream
  263. txt = InFile.readline
  264. If InStr(txt, "End") Then Exit Do
  265. Loop
  266. ElseIf InStr(1, txt, "Begin Report") = 1 Then
  267. isReport = True
  268. OutFile.WriteLine txt
  269. ElseIf isReport = True And (InStr(1, txt, " Right =") Or InStr(1, txt, " Bottom =")) Then
  270. 'skip line
  271. If InStr(1, txt, " Bottom =") Then
  272. isReport = False
  273. End If
  274. Else
  275. OutFile.WriteLine txt
  276. End If
  277. Loop
  278. OutFile.Close
  279. InFile.Close
  280. FSO.DeleteFile (path & filename)
  281. Dim thisFile As Object
  282. Set thisFile = FSO.GetFile(path & obj_name & ".sanitize")
  283. thisFile.Move (path & filename)
  284. logger "SanitizeTextFiles", "DEBUG", "> File " & path & filename & " sanitized"
  285. filename = dir$()
  286. Loop
  287. logger "SanitizeTextFiles", "INFO", "> Files " & path & "*." & Ext & " sanitized"
  288. End Sub
  289. Public Function to_filename(ByVal object_name As String) As String
  290. ' return a file name for the object's name
  291. ' 1- access does not accept brackets for object's names
  292. ' 2- file's names can not contain those caracters:
  293. ' \ [92]
  294. ' / [47]
  295. ' : [58]
  296. ' * [42]
  297. ' ? [63]
  298. ' " [34]
  299. ' < [60]
  300. ' > [62]
  301. ' | [124]
  302. '
  303. ' this function replaces caracters which are not allowed for file names by [x],
  304. 'where x is the ascii code of the character
  305. ' test: "test_\_/_:_*_?_""_<_>_|" should become test_[92]_[47]_[58]_[42]_[63]_[34]_[60]_[62]_[124]
  306. ' to convert back the string, use to_accessname
  307. Dim result As String
  308. Dim ascii_code As Variant
  309. result = object_name
  310. For Each ascii_code In Split(ForbiddenCars, ",")
  311. result = Replace(result, Chr(CInt(ascii_code)), "[" & ascii_code & "]")
  312. Next
  313. If result <> object_name Then
  314. logger "to_filename", "DEBUG", "> Object's name " & object_name & " transformed to " & result
  315. End If
  316. to_filename = result
  317. Exit Function
  318. err:
  319. Call logger("to_filename", "ERROR", "Unable to convert object's name " & object_name & " to file's name")
  320. to_filename = object_name
  321. End Function
  322. Public Function to_accessname(ByVal file_name As String) As String
  323. On Error GoTo err
  324. ' return an object name from a file's name
  325. ' see function 'to_filename' for more informations
  326. ' test: "test_[92]_[47]_[58]_[42]_[63]_[34]_[60]_[62]_[124]" should become test_\_/_:_*_?_"_<_>_|
  327. Dim result As String
  328. Dim ascii_code As Variant
  329. result = file_name
  330. For Each ascii_code In Split(ForbiddenCars, ",")
  331. result = Replace(result, "[" & ascii_code & "]", Chr(CInt(ascii_code)))
  332. Next
  333. If result <> file_name Then
  334. logger "to_accessname", "DEBUG", "> File's name " & file_name & " transformed to " & result
  335. End If
  336. to_accessname = result
  337. Exit Function
  338. err:
  339. Call logger("to_accessname", "ERROR", "Unable to convert file's name " & file_name & " to access object's name")
  340. to_accessname = file_name
  341. End Function