fastlib 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.markdown +1 -1
  2. data/lib/fastlib.rb +132 -38
  3. 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-*/lib/fastlib.rb dump lib/myarchive.fastlib lib/ lib/*
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.3"
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 = fastlib_filter( fd.read(@@cache[lib][name][1] ))
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
- dict = {}
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
- dict[:fastlib_header] = [8, hlen]
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(12).unpack("N*")
171
+ nlen, doff, dlen, tims = fd.read(16).unpack("N*")
151
172
 
152
173
  while nlen > 0
153
- name = fastlib_filter_name( fd.read(nlen) )
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(12).unpack("N*")
177
+ nlen, doff, dlen, tims = fd.read(16).unpack("N*")
157
178
  end
158
- @@cache[lib] = dict
179
+
180
+ @@cache[lib].merge!(dict)
159
181
  end
182
+
160
183
  end
161
184
 
162
185
  #
163
- # This method provides a way to hook the translation of file names
164
- # from the dictionary in the file to the final string. This can be
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.fastlib_filter_name(name)
168
- name
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 a way to hook the translation of file content
173
- # from the archive to the final content. This can be used to provide
174
- # encryption or compression.
175
- #
176
- def self.fastlib_filter(data)
177
- data
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 = fastlib_filter_name( path.sub( brex, "" ) )
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
- head << [ name.length, didx, buff.length ].pack("NNN")
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 + 12 + name.length
278
+ hidx = hidx + 16 + name.length
207
279
 
208
- data << fastlib_filter( buff )
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("N") )
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 ["dump", "list", "version"].include?(cmd)
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 "dump"
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} dump destination.fastlib base_dir src1 src2 ... src99"
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 src_lib "
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
- $stdout.puts " - #{name}"
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 8 bytes into the archive (magic + header length)
293
- * The data section is always 8 + header length into the archive
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 12 bytes + name length (no alignment)
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: 25
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
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-20 00:00:00 -06:00
18
+ date: 2011-11-23 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies: []
21
21