shredder 0.1.1 → 3.0.210928

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 79cdefe01e4a370cbeabff63ec4e641945d62b239aef721050257e0a9bcf0119
4
+ data.tar.gz: d5290e49de44088fbb83a3615cea8ee7af5781b162fe3c49d202bfbe8e9a1779
5
+ SHA512:
6
+ metadata.gz: 28b6169312efdfaed3e1cc5365b866d177d09cbea1085d12eea12e63dc61f05a4561a8ea986e8f3ddd6e8e820656340d01f4f5f1e325a59b63f47bd3cb33d7fe
7
+ data.tar.gz: ad2d383ac37cd98d80676026e9d10f8c3092e3bb5f504404938809733a1e31e9e7ab4328afd596b63f83a35b04d48212e90f327446ef047deb04dce1187645f6
data/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # Shredder
2
+
3
+ * [VERSION 3.0.210928](https://github.com/carlosjhr64/shredder/releases)
4
+ * [github](https://github.com/carlosjhr64/shredder)
5
+ * [rubygems](https://rubygems.org/gems/shredder)
6
+
7
+ ## DESCRIPTION:
8
+
9
+ Shred a file into file fragments, and join fragments back into a restored file.
10
+
11
+ ## INSTALL:
12
+ ```console
13
+ $ gem install shredder
14
+ ```
15
+ ## HELP:
16
+ ```console
17
+ $ shredder --help
18
+ Usage:
19
+ shredder shred [:options+] <shreds=FILENAME>+
20
+ shredder sew [:options+] <shreds=FILENAME>+
21
+ Options:
22
+ --n=INTEGER Number of shreds
23
+ Types:
24
+ FILENAME /^[[:print:]]+$/
25
+ INTEGER /^[2-9]\d*$/
26
+ # Examples:
27
+ # shredder shred file.1 file.2 < file.txt
28
+ # shredder shred --n=2 file < file.txt
29
+ # shredder sew file.1 file.2 > file.txt
30
+ # shredder shred --n=2 file > file.txt
31
+ ```
32
+ ## SYNOPSIS:
33
+
34
+ ### Library
35
+ ```ruby
36
+ require 'shredder'
37
+ ```
38
+ #### Shredder::Streams
39
+ ```ruby
40
+ require 'stringio'
41
+
42
+ sewn = StringIO.new("This is a test String: 1, 2, 3.")
43
+ sewn.string.length #=> 31
44
+ shreds = [StringIO.new, StringIO.new]
45
+
46
+ shredder = Shredder::Streams.new(sewn, shreds)
47
+ shredder.shred #=> 31
48
+
49
+ shreds[0].string
50
+ #=> "T\u0001S\u001AAT\u0016T'\e\t\u001A\u001D\u0012\f\u001D"
51
+ shreds[0].string.length #=> 16
52
+
53
+ shreds[1].string
54
+ #=> "<\u001AISA\u0011\as\u0006\a]\u0011\f\u001E\u0013"
55
+ shreds[1].string.length #=> 15
56
+
57
+ restored = StringIO.new
58
+ shreds.each{|_|_.rewind}
59
+
60
+ shredder = Shredder::Streams.new(restored, shreds)
61
+ shredder.sew #=> 31
62
+
63
+ restored.string #=> "This is a test String: 1, 2, 3."
64
+ ```
65
+ #### Shredder::Files
66
+ ```ruby
67
+ sewn = './test/sewn.txt'
68
+ shreds = './tmp/shreds'
69
+ restored = './tmp/restored.txt'
70
+
71
+ File.read(sewn).chomp #=> "This is a test file: 1, 2, 3."
72
+ File.size(sewn) #=> 30
73
+
74
+ shredder = Shredder::Files.new(sewn, shreds, 3)
75
+ shredder.shreds
76
+ #=> ["./tmp/shreds.1", "./tmp/shreds.2", "./tmp/shreds.3"]
77
+ shredder.shred #=> 30
78
+
79
+ File.read(shreds+'.1') #=> "T\u001A\u001AA\u0016F\t\u0011\u0012\u0013"
80
+ File.read(shreds+'.2') #=> "<SST\a\u000F_\u001D\u001E\u001D"
81
+ File.read(shreds+'.3') #=> "\u0001IA\u0011T\u0005\u001A\f\f$"
82
+ File.size(shreds+'.3') #=> 10
83
+
84
+ shredder = Shredder::Files.new(restored, shreds, 3)
85
+ shredder.sewn #=> "./tmp/restored.txt"
86
+ shredder.sew #=> 30
87
+ File.read(restored).chomp #=> "This is a test file: 1, 2, 3."
88
+ ```
89
+ ## LICENSE:
90
+
91
+ (The MIT License)
92
+
93
+ Copyright (c) 2021 CarlosJHR64
94
+
95
+ Permission is hereby granted, free of charge, to any person obtaining
96
+ a copy of this software and associated documentation files (the
97
+ 'Software'), to deal in the Software without restriction, including
98
+ without limitation the rights to use, copy, modify, merge, publish,
99
+ distribute, sublicense, and/or sell copies of the Software, and to
100
+ permit persons to whom the Software is furnished to do so, subject to
101
+ the following conditions:
102
+
103
+ The above copyright notice and this permission notice shall be
104
+ included in all copies or substantial portions of the Software.
105
+
106
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
107
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
108
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
109
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
110
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
111
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
112
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/shredder CHANGED
@@ -1,73 +1,51 @@
1
1
  #!/usr/bin/env ruby
2
+ require 'help_parser'
2
3
  require 'shredder'
3
- raise "Need Shredder version ~> 0.1" if Shredder::VERSION < '0.1'
4
4
 
5
- # Command line utility
6
- class ShredderCommandLine
7
- def self.version
8
- puts Shredder::VERSION
9
- exit(0)
10
- end
11
-
12
- def self.help
13
- puts <<EOT
14
- shredder --shred sewed_file shred_file1 shred_file2... # shred a file to shreds
15
- shredder --io --shred shred_file1 shred_file2... # shred stdin to shreds
16
- shredder --sew sewed_file shred_file1 shred_file2... # sew shreds back to file
17
- shredder --io --sew shred_file1 shred_file2... # sew shreds out to stdout
18
- EOT
19
- print "VERSION: "
20
- ShredderCommandLine.version
21
- end
22
-
23
- def self.parse_argv
24
- options = ''
25
- while ARGV[0]=~/^-/ do
26
- options += ARGV.shift
27
- end
28
- ShredderCommandLine.version if options =~ /-v\b/ || options =~ /--version\b/ # need to allow verbose below.
29
- ShredderCommandLine.help if ARGV.length==0 || options =~ /-h/
30
- $verbose = (options=~/--verbose\b/)? true : false
31
- # validate
32
- raise "--sew or --shred ?" if !(options=~/--sew\b/) && !(options=~/--shred\b/)
33
- length = ARGV.length
34
- raise "Expected sew shred1 shred2 ..." if length < 2 && !(options=~/--io\b/)
35
- raise "Expected shred1 shred2..." if length < 1
36
- return options
37
- end
5
+ OPTIONS = HelpParser[Shredder::VERSION, <<HELP]
6
+ Usage:
7
+ shredder shred [:options+] <shreds=FILENAME>+
8
+ shredder sew [:options+] <shreds=FILENAME>+
9
+ Options:
10
+ --n=INTEGER \t Number of shreds
11
+ Types:
12
+ FILENAME /^[[:print:]]+$/
13
+ INTEGER /^[2-9]\\d*$/
14
+ # Examples:
15
+ # shredder shred file.1 file.2 < file.txt
16
+ # shredder shred --n=2 file < file.txt
17
+ # shredder sew file.1 file.2 > file.txt
18
+ # shredder shred --n=2 file > file.txt
19
+ HELP
20
+ HelpParser.int?(:n)
38
21
 
39
- def initialize
40
- options = ShredderCommandLine.parse_argv
41
- @shredding = (options=~/--shred/)? true : false
42
- if options=~/--io/ then
43
- if @shredding then
44
- @sew = $stdin
45
- @shreds = ARGV.map{|filename| File.open(filename,'w')} # WRITE SHREDS
46
- else
47
- @sew = $stdout
48
- @shreds = ARGV.map{|filename| File.open(filename,'r')} # READ SHREDS
49
- end
50
- else
51
- @sew = ARGV.shift
52
- @shreds = ARGV
53
- end
54
- end
55
-
56
- def execute
57
- shredder = (@sew.class == String)? Shredder::Files.new(@sew,@shreds): Shredder::Streams.new(@sew,@shreds)
58
- begin
59
- (@shredding)? shredder.shred : shredder.sew
60
- rescue StandardError
61
- $stderr.puts $!
62
- ensure
63
- @shreds.each{|filehandle| filehandle.close} if !(@sew.class == String)
64
- end
22
+ shreds = OPTIONS.shreds
23
+ count = shreds.length
24
+ if n = OPTIONS.n?
25
+ if count == 1
26
+ count = n
27
+ shreds = shreds.first
28
+ elsif count != n
29
+ $stderr.puts "shred count(#{count}) not equal to n(#{n})."
30
+ exit 64
65
31
  end
66
32
  end
33
+ unless count > 1
34
+ $stderr.puts "shred count must be at least 2"
35
+ exit 64
36
+ end
67
37
 
68
- begin
69
- ShredderCommandLine.new.execute
70
- rescue StandardError
71
- $stderr.puts $!
72
- $stderr.puts $!.backtrace if $verbose
38
+ shredder = Shredder::StdIO.new(shreds, count)
39
+ case OPTIONS[1]
40
+ when 'shred'
41
+ shredder.shred
42
+ when 'sew'
43
+ begin
44
+ shredder.sew
45
+ rescue Errno::ENOENT
46
+ # Common expected type of error,
47
+ # user tries to sew non-existing shreds.
48
+ $stderr.puts $!.message
49
+ exit 65
50
+ end
73
51
  end
@@ -1,45 +1,36 @@
1
1
  module Shredder
2
2
  class Files
3
- # this one takes filenames
4
- def initialize(sew,shreds,limit=0)
5
- @sew = sew
6
- @shreds = shreds
7
- @limit = limit
3
+ include Shredder
4
+ # this one takes filenames
5
+ def initialize(sewn, shreds=sewn, m=2, n: m)
6
+ @sewn = sewn
7
+ @shreds = shred_files(shreds, n)
8
+ raise "Need at least 2 shreds" unless @shreds.length > 1
8
9
  end
9
10
 
10
- def shred(limit=@limit)
11
- reader = File.open(@sew,'r')
12
- writers = []
13
- @shreds.each{|shred| writers.push( File.open(shred,'wb') ) }
14
-
15
- count = nil
11
+ def shred(limit=0)
12
+ reader = writers = count = nil
16
13
  begin
17
- count = Shredder.shred( reader, writers, limit )
18
- rescue Exception
19
- raise $!
14
+ reader = File.open(@sewn, 'r')
15
+ writers = @shreds.map{File.open _1, 'wb'}
16
+ count = Streams.new(reader, writers).shred(limit: limit)
20
17
  ensure
21
- writers.each{|writer| writer.close}
22
- reader.close
23
- end
24
-
18
+ writers.each{_1.close} if writers
19
+ reader.close if reader
20
+ end
25
21
  return count
26
22
  end
27
23
 
28
- def sew(limit=@limit)
29
- writer = File.open(@sew,'wb')
30
- readers = []
31
- @shreds.each{|shred| readers.push( File.open(shred,'r') ) }
32
-
33
- count = nil
24
+ def sew(limit=0)
25
+ writer = readers = count = nil
34
26
  begin
35
- count = Shredder.sew( writer, readers, limit )
36
- rescue Exception
37
- raise $!
27
+ writer = File.open(@sewn, 'wb')
28
+ readers = @shreds.map{File.open(_1, 'r')}
29
+ count = Streams.new(writer, readers).sew(limit: limit)
38
30
  ensure
39
- writer.close
40
- readers.each{|reader| reader.close}
31
+ writer.close if writer
32
+ readers.each{_1.close} if readers
41
33
  end
42
-
43
34
  return count
44
35
  end
45
36
  end
@@ -0,0 +1,40 @@
1
+ module Shredder
2
+ attr_accessor :sewn, :shreds
3
+
4
+ # note that these are streams
5
+ def shred(sewn=(@sewn or $stdin), shreds=@shreds,
6
+ writers: shreds, reader: sewn, limit: 0, xor: 0)
7
+ shreds,count = writers.length,0
8
+ while byte = reader.getbyte do
9
+ writers[count%shreds].putc(xor^(xor=byte))
10
+ count += 1 # note that 0 is skipped
11
+ break if count == limit
12
+ end
13
+ return count
14
+ end
15
+
16
+ # note that these are streams
17
+ def sew(shreds=@shreds, sewn=(@sewn or $stdout),
18
+ readers: shreds, writer: sewn, limit: 0, xor: 0)
19
+ shreds,count = readers.length,0
20
+ while byte = readers[count%shreds].getbyte do
21
+ writer.putc(xor=(byte^xor))
22
+ count += 1 # note that 0 is skipped
23
+ break if count == limit
24
+ end
25
+ return count
26
+ end
27
+
28
+ def shred_files(b=nil, m=2, basename: b, n: m)
29
+ case basename
30
+ when Array
31
+ basename
32
+ when String
33
+ (1..n).map{|i| "#{basename}.#{i}"}
34
+ when Integer
35
+ (1..basename).map{|i| "#{@sewn or 'shred'}.#{i}"}
36
+ else
37
+ raise "Expected basename Array|String|Integer"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ module Shredder
2
+ class StdIO
3
+ include Shredder
4
+ # this one takes shred filenames and uses $stdin or $stdout appropriately.
5
+ def initialize(*args)
6
+ @shreds = shred_files(*args)
7
+ end
8
+
9
+ def shred(limit=0)
10
+ writers = count = nil
11
+ begin
12
+ writers = @shreds.map{File.open _1, 'wb'}
13
+ count = Streams.new($stdin, writers).shred(limit: limit)
14
+ ensure
15
+ writers.each{_1.close} if writers
16
+ end
17
+ return count
18
+ end
19
+
20
+ def sew(limit=0)
21
+ readers = count = nil
22
+ begin
23
+ readers = @shreds.map{File.open _1, 'r'}
24
+ count = Streams.new($stdout, readers).sew(limit: limit)
25
+ ensure
26
+ readers.each{_1.close} if readers
27
+ end
28
+ return count
29
+ end
30
+ end
31
+ end
@@ -1,18 +1,10 @@
1
1
  module Shredder
2
2
  class Streams
3
+ include Shredder
3
4
  # this one takes streams
4
- def initialize(sew,shreds,limit=0)
5
- @sew = sew
5
+ def initialize(sewn, shreds)
6
+ @sewn = sewn
6
7
  @shreds = shreds
7
- @limit = limit
8
- end
9
-
10
- def shred(limit=@limit)
11
- Shredder.shred(@sew,@shreds,limit)
12
- end
13
-
14
- def sew(limit=@limit)
15
- Shredder.sew(@sew,@shreds,limit)
16
8
  end
17
9
  end
18
10
  end
data/lib/shredder.rb CHANGED
@@ -1,35 +1,9 @@
1
1
  module Shredder
2
- VERSION = '0.1.1'
3
-
4
- # note that these are streams
5
- def self.shred(reader,writers,limit=0)
6
- shreds = writers.length
7
- xor = count = 0
8
- while byte = reader.getbyte do
9
- writers[ count % shreds ].putc byte^xor
10
- xor = byte
11
- count += 1
12
- # note: will not break if limit is zero
13
- break if count == limit
14
- end
15
- return count
16
- end
17
-
18
- # note that these are streams
19
- def self.sew(writer,readers,limit=0)
20
- shreds = readers.length
21
- xor = count = 0
22
- while byte = readers[ count % shreds ].getbyte do
23
- chr = byte^xor
24
- xor = chr
25
- writer.putc chr
26
- count += 1
27
- # note: will not break if limit is zero
28
- break if count == limit
29
- end
30
- return count
31
- end
32
-
33
- autoload :Files, 'shredder/files'
34
- autoload :Streams, 'shredder/streams'
2
+ VERSION = '3.0.210928'
3
+ require 'shredder/shredder'
4
+ autoload :Streams, 'shredder/streams'
5
+ autoload :StdIO, 'shredder/stdio'
6
+ autoload :Files, 'shredder/files'
35
7
  end
8
+ # Requires:
9
+ #`ruby`
metadata CHANGED
@@ -1,73 +1,75 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: shredder
3
- version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.0.210928
11
5
  platform: ruby
12
- authors:
13
- - carlosjhr64@gmail.com
14
- autorequire:
6
+ authors:
7
+ - CarlosJHR64
8
+ autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
11
+ date: 2021-09-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: help_parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '8.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 8.0.210917
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '8.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 8.0.210917
33
+ description: 'Shred a file into file fragments, and join fragments back into a restored
34
+ file.
17
35
 
18
- date: 2011-06-21 00:00:00 Z
19
- dependencies: []
20
-
21
- description: |
22
- The idea is to disperse file shreds in separate depositories
23
- such that no one depository has the entire file.
24
- Note: These are not file segments, they're shreds.
25
-
36
+ '
26
37
  email: carlosjhr64@gmail.com
27
- executables:
38
+ executables:
28
39
  - shredder
29
40
  extensions: []
30
-
31
41
  extra_rdoc_files: []
32
-
33
- files:
34
- - ./lib/shredder/streams.rb
35
- - ./lib/shredder/files.rb
36
- - ./lib/shredder.rb
37
- - ./README.txt
42
+ files:
43
+ - README.md
38
44
  - bin/shredder
39
- homepage: https://sites.google.com/site/carlosjhr64/rubygems/shredder
40
- licenses: []
41
-
42
- post_install_message:
45
+ - lib/shredder.rb
46
+ - lib/shredder/files.rb
47
+ - lib/shredder/shredder.rb
48
+ - lib/shredder/stdio.rb
49
+ - lib/shredder/streams.rb
50
+ homepage: https://github.com/carlosjhr64/shredder
51
+ licenses:
52
+ - MIT
53
+ metadata: {}
54
+ post_install_message:
43
55
  rdoc_options: []
44
-
45
- require_paths:
56
+ require_paths:
46
57
  - lib
47
- required_ruby_version: !ruby/object:Gem::Requirement
48
- none: false
49
- requirements:
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
50
60
  - - ">="
51
- - !ruby/object:Gem::Version
52
- hash: 3
53
- segments:
54
- - 0
55
- version: "0"
56
- required_rubygems_version: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
59
65
  - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
65
- requirements: []
66
-
67
- rubyforge_project:
68
- rubygems_version: 1.8.4
69
- signing_key:
70
- specification_version: 3
71
- summary: Shred a file into file fragments, and join fragments back into a restored file.
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements:
69
+ - 'ruby: ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]'
70
+ rubygems_version: 3.2.22
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Shred a file into file fragments, and join fragments back into a restored
74
+ file.
72
75
  test_files: []
73
-
data/README.txt DELETED
@@ -1,28 +0,0 @@
1
- ### SYNOPSIS ###
2
-
3
- require 'shredder'
4
-
5
- # Shreds text.txt into test.f.1, test.f.2, test.f.3
6
- Shredder::Files.new('test.txt', ['test.f.1','test.f.2','test.f.3'] ).shred
7
-
8
- # Sews test.f.1, test.f.2, test.f.3 into restored.f.txt
9
- Shredder::Files.new('restored.f.txt', ['test.f.1','test.f.2','test.f.3'] ).sew
10
-
11
- # or #
12
-
13
- # shred streams #
14
- reader = File.open('test.txt','r')
15
- writers = []; ['test.s.1','test.s.2','test.s.3'].each{|writer| writers.push(File.open(writer,'wb'))}
16
- Shredder::Streams.new(reader,writers).shred
17
- reader.close
18
- writers.each{|writer| writer.close}
19
-
20
- # sew streams
21
- writer = File.open('restored.s.txt','wb')
22
- readers = []; ['test.s.1','test.s.2','test.s.3'].each{|writer| readers.push(File.open(writer,'r'))}
23
- Shredder::Streams.new(writer,readers).sew
24
- writer.close
25
- readers.each{|reader| reader.close}
26
-
27
- # Also available, Shredder.shred( writer, readers) and Shredder.sew( reader, writers )
28
- # and a command line utility, shredder (run shredder --help for more info).