-
Notifications
You must be signed in to change notification settings - Fork 0
/
7zip.ahk
149 lines (139 loc) · 5.21 KB
/
7zip.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
SevenZip (7Zip) Parser
-----------------------
Uses 7z.exe to parse a zip file (.7z)
License: https://www.7-zip.org/license.txt
(c) 2022-2024 Ken Verdadero
2022-06-02
*/
#Include ./Run.ahk
#Include ./Path.ahk
#Include ./Arrays.ahk
/**
* A simple archive wrapper.
*
* This uses 7z.exe to parse an archive file.
*
* @param {String} zip The zip file to parse
* @param {String} password The password for the zip file
* @param {String} bin The path to 7z.exe
* @param {String} dll The path to 7z.dll
* @returns {Object} SevenZip
* @throws {Error} If 7z.exe or 7z.dll is not found
* @example
* zip := new SevenZip("C:\path\to\file.7z")
* zip := new SevenZip("C:\path\to\file.7z", "password")
* zip := new SevenZip("C:\path\to\file.7z", "password", "C:\path\to\7z.exe")
*/
Class SevenZip {
__New(zip, password := '', bin := 'bin\7z.exe', dll := 'bin\7z.dll') {
bin := (!InStr(bin, '.exe') ? bin '.exe' : bin)
if !FileExist(bin) {
Throw Error('Binary 7z was not found: ' bin, , bin)
}
if !FileExist(dll) {
Throw Error('7z.dll was not found: ' dll, , dll)
}
this.ZIP := zip
this.BIN := bin
this.DLL := dll
this.PW := password
this.META := this._ParseZip()
this.ZIP_SIZE := this.META.ZIP.SIZE
this.PATHS := this.META.PATH
this.SIZES := this.META.SIZE
this.MODIFIEDS := this.META.MODIFIED
this.CRCS := this.META.CRC
this.METHODS := this.META.METHOD
}
/**
* Parses the whole 7zip file
* @returns {Object} meta
*/
_ParseZip() {
SplitPath(this.BIN)
command := Format('{1} l "{2}" -slt {3}',
this.BIN, this.ZIP, (StrLen(this.PW) ? '-p"' this.PW '"' : '')
)
zip := StrSplit(RunWaitOne(command), '`n')
meta := Object()
for prop in ['Path', 'Size', 'Modified', 'Attributes', 'CRC', 'Method'] { ;; File properties
meta.DefineProp(prop, { value: Array() })
}
meta.Zip := { ;; Metadata for the target zip
Size: 0 ;; Size of the zip in bytes
}
for line in zip {
line := Trim(line, ' `t`r`n')
if !StrLen(line) {
continue
}
if InStr(line, "Codec Load Error") {
return 1
}
key := StrSplit(line, ' ')[1] ;; Property key
val := Trim(ArrayAsStr(ArrayTrunc(StrSplit(line, ' '), 3), ' ', , false), ;; Trimmed value
' `t`r`n')
switch key {
case '1': meta.Zip.Size := StrSplit(val, ' ')[1]
case 'Path': meta.Path.Push(val)
case 'Size': meta.Size.Push(val)
case 'Modified': meta.Modified.Push(val)
case 'Attributes': meta.Attributes.Push(val)
case 'CRC': meta.CRC.Push(val)
case 'Method': meta.Method.Push(val)
}
}
return meta
}
/**
* Extracts a file from the zip
* @param filename The file to extract
* @param {String} destination Destination directory
* @param {Integer} overwrite Overwrite existing file
* @returns {Integer} 0 if successful, 1 if file not found, 2 if file exists and overwrite is false
*/
Extract(filename, destination := '', overwrite := false) {
filename := StrReplace(filename, '/', '\')
destination := (StrLen(destination) ? destination : A_WorkingDir) ;; Set destination to working directory if not specified
destination := StrReplace(destination, '/', '\') ;; Convert all forward slashes to a backslash
if !ArrayMatch(filename, this.PATHS) { ;; Verify if the filename is in archive
return 1
}
if FileExist(PathJoin(destination, PathSplit(filename)[2])) and !overwrite {
return 2
}
if !FileExist(this.BIN) {
throw Error('Binary 7z was not found: ' this.BIN, , "Binary")
}
if !FileExist(this.DLL) {
throw Error('7z.dll was not found: ' this.DLL, , "Library")
}
switchs := (overwrite ? '-aoa' : '')
command := Format(
'{1} e "{2}" "{3}" -o"{4}" -p"{5}" {6}',
this.BIN, this.ZIP, filename, destination, this.PW, switchs
)
RunWaitOne(command)
return 0
}
/**
* Returns the file info of the specified file
* @param filename The file to get info from
* @returns {Integer|Object} 1 if file not found, Object if file is found
*/
GetInfo(filename) {
filename := StrReplace(filename, '/', '\')
if !ArrayMatch(filename, this.PATHS) {
return 1
}
idx := ArrayFind(filename, this.PATHS)
return {
Path: filename,
Size: this.SIZES[idx],
Modified: this.MODIFIEDS[idx],
CRC: this.CRCS[idx],
Method: this.METHODS[idx]
}
}
}