fastlib 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +1 -1
- data/lib/fastlib.rb +132 -38
- metadata +4 -4
data/README.markdown
CHANGED
@@ -8,7 +8,7 @@ This is similar to capabilities like zip/ziprequire, except that it provides wor
|
|
8
8
|
|
9
9
|
$ apt-get install fastlib
|
10
10
|
|
11
|
-
$ \`gem env gemdir\`/gems/fastlib
|
11
|
+
$ \`gem env gemdir\`/gems/fastlib-\*/lib/fastlib.rb dump lib/myarchive.fastlib lib/ lib/\*
|
12
12
|
|
13
13
|
$ ruby -r rubygems -r fastlib -I lib/myarchive.fastlib application.rb
|
14
14
|
|
data/lib/fastlib.rb
CHANGED
@@ -20,6 +20,7 @@
|
|
20
20
|
|
21
21
|
require "find"
|
22
22
|
|
23
|
+
|
23
24
|
#
|
24
25
|
# Copyright (C) 2011 Rapid7. You can redistribute it and/or
|
25
26
|
# modify it under the terms of the ruby license.
|
@@ -98,9 +99,22 @@ end
|
|
98
99
|
#
|
99
100
|
class FastLib
|
100
101
|
|
101
|
-
VERSION = "0.0.
|
102
|
+
VERSION = "0.0.5"
|
102
103
|
|
104
|
+
FLAG_COMPRESS = 0x01
|
105
|
+
FLAG_ENCRYPT = 0x02
|
106
|
+
|
103
107
|
@@cache = {}
|
108
|
+
@@has_zlib = false
|
109
|
+
|
110
|
+
#
|
111
|
+
# Load zlib support if possible
|
112
|
+
#
|
113
|
+
begin
|
114
|
+
require 'zlib'
|
115
|
+
@@has_zlib = true
|
116
|
+
rescue ::LoadError
|
117
|
+
end
|
104
118
|
|
105
119
|
#
|
106
120
|
# This method returns the version of the fastlib library
|
@@ -128,7 +142,7 @@ class FastLib
|
|
128
142
|
@@cache[lib][:fastlib_header][1] +
|
129
143
|
@@cache[lib][name][0]
|
130
144
|
)
|
131
|
-
data =
|
145
|
+
data = fastlib_filter_decode( @@cache[lib][:fastlib_flags], fd.read(@@cache[lib][name][1] ))
|
132
146
|
end
|
133
147
|
|
134
148
|
# Return the contents in raw or processed form
|
@@ -140,50 +154,102 @@ class FastLib
|
|
140
154
|
#
|
141
155
|
def self.load_cache(lib)
|
142
156
|
return if @@cache[lib]
|
143
|
-
|
157
|
+
@@cache[lib] = {}
|
158
|
+
|
159
|
+
return if not ::File.exists?(lib)
|
160
|
+
|
144
161
|
::File.open(lib, 'rb') do |fd|
|
162
|
+
dict = {}
|
145
163
|
head = fd.read(4)
|
146
164
|
return if head != "FAST"
|
147
165
|
hlen = fd.read(4).unpack("N")[0]
|
148
|
-
|
166
|
+
flag = fd.read(4).unpack("N")[0]
|
167
|
+
|
168
|
+
@@cache[lib][:fastlib_header] = [12, hlen, fd.stat.mtime.utc.to_i ]
|
169
|
+
@@cache[lib][:fastlib_flags] = flag
|
149
170
|
|
150
|
-
nlen, doff, dlen = fd.read(
|
171
|
+
nlen, doff, dlen, tims = fd.read(16).unpack("N*")
|
151
172
|
|
152
173
|
while nlen > 0
|
153
|
-
name =
|
154
|
-
dict[name] = [doff, dlen]
|
174
|
+
name = fastlib_filter_decode( lib, fd.read(nlen) )
|
175
|
+
dict[name] = [doff, dlen, tims]
|
155
176
|
|
156
|
-
nlen, doff, dlen = fd.read(
|
177
|
+
nlen, doff, dlen, tims = fd.read(16).unpack("N*")
|
157
178
|
end
|
158
|
-
|
179
|
+
|
180
|
+
@@cache[lib].merge!(dict)
|
159
181
|
end
|
182
|
+
|
160
183
|
end
|
161
184
|
|
162
185
|
#
|
163
|
-
# This method provides
|
164
|
-
#
|
165
|
-
# used to provide encryption or compression.
|
186
|
+
# This method provides compression and encryption capabilities
|
187
|
+
# for the fastlib archive format.
|
166
188
|
#
|
167
|
-
def self.
|
168
|
-
|
189
|
+
def self.fastlib_filter_decode(lib, buff)
|
190
|
+
|
191
|
+
if (@@cache[lib][:fastlib_flags] & FLAG_ENCRYPT) != 0
|
192
|
+
|
193
|
+
@@cache[lib][:fastlib_decrypt] ||= ::Proc.new do |data|
|
194
|
+
stub = "decrypt_%.8x" % ( @@cache[lib][:fastlib_flags] & 0xfffffff0 )
|
195
|
+
FastLib.send(stub, data)
|
196
|
+
end
|
197
|
+
|
198
|
+
buff = @@cache[lib][:fastlib_decrypt].call( buff )
|
199
|
+
end
|
200
|
+
|
201
|
+
if (@@cache[lib][:fastlib_flags] & FLAG_COMPRESS) != 0
|
202
|
+
if not @@has_zlib
|
203
|
+
raise ::RuntimeError, "zlib is required to open this archive"
|
204
|
+
end
|
205
|
+
|
206
|
+
z = Zlib::Inflate.new
|
207
|
+
buff = z.inflate(buff)
|
208
|
+
buff << z.finish
|
209
|
+
z.close
|
210
|
+
end
|
211
|
+
|
212
|
+
buff
|
169
213
|
end
|
170
214
|
|
171
215
|
#
|
172
|
-
# This method provides
|
173
|
-
#
|
174
|
-
#
|
175
|
-
|
176
|
-
|
177
|
-
|
216
|
+
# This method provides compression and encryption capabilities
|
217
|
+
# for the fastlib archive format.
|
218
|
+
#
|
219
|
+
def self.fastlib_filter_encode(lib, buff)
|
220
|
+
|
221
|
+
if (@@cache[lib][:fastlib_flags] & FLAG_COMPRESS) != 0
|
222
|
+
if not @@has_zlib
|
223
|
+
raise ::RuntimeError, "zlib is required to open this archive"
|
224
|
+
end
|
225
|
+
|
226
|
+
z = Zlib::Deflate.new
|
227
|
+
buff = z.deflate(buff)
|
228
|
+
buff << z.finish
|
229
|
+
z.close
|
230
|
+
end
|
231
|
+
|
232
|
+
if (@@cache[lib][:fastlib_flags] & FLAG_ENCRYPT) != 0
|
233
|
+
|
234
|
+
@@cache[lib][:fastlib_encrypt] ||= ::Proc.new do |data|
|
235
|
+
stub = "encrypt_%.8x" % ( @@cache[lib][:fastlib_flags] & 0xfffffff0 )
|
236
|
+
FastLib.send(stub, data)
|
237
|
+
end
|
238
|
+
|
239
|
+
buff = @@cache[lib][:fastlib_encrypt].call( buff )
|
240
|
+
end
|
241
|
+
|
242
|
+
buff
|
178
243
|
end
|
179
244
|
|
245
|
+
|
180
246
|
#
|
181
247
|
# This method provides a way to create a FASTLIB archive programatically,
|
182
248
|
# the key arguments are the name of the destination archive, the base
|
183
249
|
# directory that should be excluded from the archived path, and finally
|
184
250
|
# the list of specific files and directories to include in the archive.
|
185
251
|
#
|
186
|
-
def self.dump(lib, bdir, *dirs)
|
252
|
+
def self.dump(lib, flag, bdir, *dirs)
|
187
253
|
head = ""
|
188
254
|
data = ""
|
189
255
|
hidx = 0
|
@@ -192,20 +258,26 @@ class FastLib
|
|
192
258
|
bdir = bdir.gsub(/\/$/, '')
|
193
259
|
brex = /^#{Regexp.escape(bdir)}\//
|
194
260
|
|
261
|
+
@@cache[lib] = {
|
262
|
+
:fastlib_flags => flag.to_i(16)
|
263
|
+
}
|
264
|
+
|
195
265
|
dirs.each do |dir|
|
196
266
|
::Find.find(dir).each do |path|
|
197
267
|
next if not ::File.file?(path)
|
198
|
-
name =
|
268
|
+
name = fastlib_filter_encode( lib, path.sub( brex, "" ) )
|
269
|
+
|
199
270
|
buff = ""
|
200
271
|
::File.open(path, "rb") do |fd|
|
201
|
-
buff = fd.read(fd.stat.size)
|
272
|
+
buff = fastlib_filter_encode(lib, fd.read(fd.stat.size))
|
202
273
|
end
|
203
|
-
|
204
|
-
|
274
|
+
|
275
|
+
|
276
|
+
head << [ name.length, didx, buff.length, ::File.stat(path).mtime.utc.to_i ].pack("NNNN")
|
205
277
|
head << name
|
206
|
-
hidx = hidx +
|
278
|
+
hidx = hidx + 16 + name.length
|
207
279
|
|
208
|
-
data <<
|
280
|
+
data << buff
|
209
281
|
didx = didx + buff.length
|
210
282
|
end
|
211
283
|
end
|
@@ -214,7 +286,7 @@ class FastLib
|
|
214
286
|
|
215
287
|
::File.open(lib, "wb") do |fd|
|
216
288
|
fd.write("FAST")
|
217
|
-
fd.write( [ head.length ].pack("
|
289
|
+
fd.write( [ head.length, flag.to_i(16) ].pack("NN") )
|
218
290
|
fd.write( head )
|
219
291
|
fd.write( data )
|
220
292
|
end
|
@@ -226,7 +298,7 @@ class FastLib
|
|
226
298
|
#
|
227
299
|
def self.list(lib)
|
228
300
|
load_cache(lib)
|
229
|
-
( @@cache[lib] || {} ).keys.map{|x| x.to_s }.sort
|
301
|
+
( @@cache[lib] || {} ).keys.map{|x| x.to_s }.sort.select{ |x| @@cache[lib][x] }
|
230
302
|
end
|
231
303
|
|
232
304
|
#
|
@@ -237,6 +309,24 @@ class FastLib
|
|
237
309
|
data.gsub('__FILE__', "'#{ ::File.expand_path(::File.join(::File.dirname(lib), name)) }'")
|
238
310
|
end
|
239
311
|
|
312
|
+
#
|
313
|
+
# This is a stub crypto handler that performs a basic XOR
|
314
|
+
# operation against a fixed one byte key
|
315
|
+
#
|
316
|
+
def self.encrypt_12345600(data)
|
317
|
+
data.unpack("C*").map{ |c| c ^ 0x90 }.pack("C*")
|
318
|
+
end
|
319
|
+
|
320
|
+
def self.decrypt_12345600(data)
|
321
|
+
encrypt_12345600(data)
|
322
|
+
end
|
323
|
+
|
324
|
+
def self.cache
|
325
|
+
@@cache
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
|
240
330
|
end
|
241
331
|
|
242
332
|
|
@@ -246,32 +336,35 @@ end
|
|
246
336
|
#
|
247
337
|
if __FILE__ == $0
|
248
338
|
cmd = ARGV.shift
|
249
|
-
unless ["
|
339
|
+
unless ["store", "list", "version"].include?(cmd)
|
250
340
|
$stderr.puts "Usage: #{$0} [dump|list|version] <arguments>"
|
251
341
|
exit(0)
|
252
342
|
end
|
253
343
|
|
254
344
|
case cmd
|
255
|
-
when "
|
345
|
+
when "store"
|
256
346
|
dst = ARGV.shift
|
347
|
+
flg = ARGV.shift
|
257
348
|
dir = ARGV.shift
|
258
349
|
src = ARGV
|
259
350
|
unless dst and dir and src.length > 0
|
260
|
-
$stderr.puts "Usage: #{$0}
|
351
|
+
$stderr.puts "Usage: #{$0} store destination.fastlib flags base_dir src1 src2 ... src99"
|
261
352
|
exit(0)
|
262
353
|
end
|
263
|
-
FastLib.dump(dst, dir, *src)
|
354
|
+
FastLib.dump(dst, flg, dir, *src)
|
264
355
|
|
265
356
|
when "list"
|
266
357
|
src = ARGV.shift
|
267
358
|
unless src
|
268
|
-
$stderr.puts "Usage: #{$0} list
|
359
|
+
$stderr.puts "Usage: #{$0} list"
|
269
360
|
exit(0)
|
270
361
|
end
|
271
362
|
$stdout.puts "Library: #{src}"
|
272
363
|
$stdout.puts "====================================================="
|
273
364
|
FastLib.list(src).each do |name|
|
274
|
-
|
365
|
+
fsize = FastLib.cache[src][name][1]
|
366
|
+
ftime = ::Time.at(FastLib.cache[src][name][2]).strftime("%Y-%m-%d %H:%M:%S")
|
367
|
+
$stdout.puts sprintf("%9d\t%20s\t%s\n", fsize, ftime, name)
|
275
368
|
end
|
276
369
|
$stdout.puts ""
|
277
370
|
|
@@ -289,10 +382,10 @@ end
|
|
289
382
|
|
290
383
|
* All integers are 32-bit and in network byte order (big endian / BE)
|
291
384
|
* The file signature is 0x46415354 (big endian, use htonl() if necessary)
|
292
|
-
* The header is always
|
293
|
-
* The data section is always
|
385
|
+
* The header is always 12 bytes into the archive (magic + header length)
|
386
|
+
* The data section is always 12 + header length into the archive
|
294
387
|
* The header entries always start with 'fastlib_header'
|
295
|
-
* The header entries always consist of
|
388
|
+
* The header entries always consist of 16 bytes + name length (no alignment)
|
296
389
|
* The header name data may be encoded, compressed, or transformed
|
297
390
|
* The data entries may be encoded, compressed, or transformed too
|
298
391
|
|
@@ -303,6 +396,7 @@ end
|
|
303
396
|
4 bytes: name length (0 = End of Names)
|
304
397
|
4 bytes: data offset
|
305
398
|
4 bytes: data length
|
399
|
+
4 bytes: timestamp
|
306
400
|
]
|
307
401
|
[ Raw Data ]
|
308
402
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- HD Moore
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-11-
|
18
|
+
date: 2011-11-23 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|