fastlib 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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