-
Notifications
You must be signed in to change notification settings - Fork 24
/
checkthumbswdx.lua
179 lines (168 loc) · 4.43 KB
/
checkthumbswdx.lua
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
-- checkthumbswdx.lua (cross-platform)
-- 2022.12.15
--[[
Getting some information from thumbnails files:
created by Double Commander (Windows or Linux)
or the system generator of thumbnails (Linux).
Supported fields: see table "fields".
GetDouble() based on struct.unpack(): Copyright (c) 2015-2020 Iryont <https://github.com/iryont/lua-struct>
URL-decode: http://lua-users.org/wiki/StringRecipes
]]
local fields = {
{"Original file name", 8},
{"Modification date", 8},
{"Obsolete", 6},
{"Not found", 6}
}
local tunpack = table.unpack or _G.unpack
local ar = {}
function ContentGetSupportedField(FieldIndex)
if fields[FieldIndex + 1] ~= nil then
return fields[FieldIndex + 1][1], "", fields[FieldIndex + 1][2]
end
return "", "", 0
end
function ContentGetDefaultSortOrder(FieldIndex)
return 1; --or -1
end
function ContentGetDetectString()
return '(EXT="PNG")|(EXT="JPG")'
end
function ContentGetValue(FileName, FieldIndex, UnitIndex, flags)
if FieldIndex >= #fields then return nil end
local at = SysUtils.FileGetAttr(FileName)
if at < 0 then return nil end
if math.floor(at / 0x00000010) % 2 ~= 0 then return nil end
local h = io.open(FileName, 'rb')
if h == nil then return nil end
local tn, tt
at = h:seek('end')
h:seek('set', at - 4)
local d = h:read(4)
local n = BinToNumLE(d, 1, 4)
if n < at then
h:seek('set', n)
d = h:read(8)
if (d ~= nil) and (string.byte(d, 1) == 0x00) and (string.byte(d, 2) == 0x00) and (string.sub(d, 3, 8) == '#THUMB') then
-- Double Commander
d = h:read(4)
n = BinToNumLE(d, 1, 4)
d = h:read(n)
tn = string.sub(d, 9, -1)
h:seek('cur', 8)
d = h:read(8)
-- Lua 5.3+ only:
--at = string.unpack('<d', d)
at = GetDouble(d)
tt = math.floor((at - 25569) * 86400)
end
end
if tn == nil then
-- Linux
h:seek('set', 0)
d = h:read(8)
n = BinToNumBE(d, 1, 4)
at = BinToNumBE(d, 5, 8)
if (n == 0x89504e47) and (at == 0x0d0a1a0a) then
h:seek('cur', 4)
d = h:read(4)
if d ~= 'IHDR' then
h:close()
return nil
end
h:seek('cur', 17)
local i = 0
local t
while i ~= 2 do
d = h:read(4)
at = BinToNumBE(d, 1, 4)
d = h:read(4)
if d == 'IDAT' then break end
if d == 'tEXt' then
d = h:read(at)
t = string.sub(d, 1, 10)
if t == 'Thumb::URI' then
tn = string.sub(d, 19, at)
i = i + 1
elseif t == 'Thumb::MTi' then
tt = tonumber(string.sub(d, 14, at), 10)
i = i + 1
end
h:seek('cur', 4)
else
h:seek('cur', at + 4)
end
end
end
end
h:close()
if tn == nil then return nil end
if string.sub(tn, 2, 3) == ':/' then tn = string.gsub(tn, '/', '\\') end
ar[1] = string.gsub(tn, "%%(%x%x)", function(h)
return string.char(tonumber(h, 16))
end)
at = CheckAndGetFileTime(ar[1])
if at == nil then
ar[3] = true
ar[4] = true
else
if at ~= tt then ar[3] = true else ar[3] = false end
ar[4] = false
end
if tt ~= nil then ar[2] = os.date('%Y.%m.%d %H:%M:%S', tt) else ar[2] = '' end
if ar[FieldIndex + 1] == '' then
return nil
else
return ar[FieldIndex + 1]
end
end
function BinToNumBE(d, n1, n2)
local r = ''
for i = n1, n2 do
r = r .. string.format('%02x', string.byte(d, i))
end
return tonumber('0x' .. r)
end
function BinToNumLE(d, n1, n2)
local r = ''
for i = n1, n2 do
r = string.format('%02x', string.byte(d, i)) .. r
end
return tonumber('0x' .. r)
end
function GetDouble(x)
local vars = {}
local sign = 1
local mantissa = string.byte(x, 7) % 16
for i = 6, 1, -1 do
mantissa = mantissa * (2 ^ 8) + string.byte(x, i)
end
if string.byte(x, 8) > 127 then
sign = -1
end
local exponent = (string.byte(x, 8) % 128) * 16 + math.floor(string.byte(x, 7) / 16)
if exponent == 0 then
table.insert(vars, 0.0)
else
mantissa = (math.ldexp(mantissa, -52) + 1) * sign
table.insert(vars, math.ldexp(mantissa, exponent - 1023))
end
return tunpack(vars)
end
function CheckAndGetFileTime(s)
local fn = SysUtils.ExtractFileName(s)
local ft = nil
local fr = nil
local h, fd = SysUtils.FindFirst(s)
if h ~= nil then
repeat
if fd.Name == fn then
ft = fd.Time
break
end
fr, fd = SysUtils.FindNext(h)
until fr == nil
SysUtils.FindClose(h)
end
return ft
end