obfus 0.1.2
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.
- checksums.yaml +7 -0
- data/.github/.gitkeep +0 -0
- data/.gitignore +85 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +35 -0
- data/Rakefile +27 -0
- data/bin/console +14 -0
- data/bin/obfus +5 -0
- data/bin/setup +8 -0
- data/build/obfus +257 -0
- data/lib/obfus/main.rb +253 -0
- data/lib/obfus/version.rb +3 -0
- data/lib/obfus.rb +5 -0
- data/license.txt +21 -0
- data/obfus.gemspec +37 -0
- data/readme.md +104 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 51e71e8417dd0832c1324a8d6cfcb8139d3862a1353e81bfb25ffd30cf89019d
|
4
|
+
data.tar.gz: 13ec0652fc092f92e922ea22454fdb2f4477fa93151ea74ca35ef9f10e5c814c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 309c4004e6c09cfe4b37a5706c0f2abd02d321d6f079950d9a1c9a6f3a8446a80ab50cd80728f9838b92cea5fce8fa188d2b4402a792e76cabe7622ae2e713e2
|
7
|
+
data.tar.gz: a14c98fc22b8b722af6a0f45e7d075dc7868e9b0c5edb2909016371512967c3f17e1d35a82f4c85c4b19253541205f367eb2255b7b82d957723d3956bfbb56e8
|
data/.github/.gitkeep
ADDED
File without changes
|
data/.gitignore
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# example folder
|
2
|
+
example/
|
3
|
+
|
4
|
+
|
5
|
+
# General
|
6
|
+
.DS_Store
|
7
|
+
.AppleDouble
|
8
|
+
.LSOverride
|
9
|
+
|
10
|
+
# Icon must end with two \r
|
11
|
+
Icon
|
12
|
+
|
13
|
+
|
14
|
+
# Thumbnails
|
15
|
+
._*
|
16
|
+
|
17
|
+
# Files that might appear in the root of a volume
|
18
|
+
.DocumentRevisions-V100
|
19
|
+
.fseventsd
|
20
|
+
.Spotlight-V100
|
21
|
+
.TemporaryItems
|
22
|
+
.Trashes
|
23
|
+
.VolumeIcon.icns
|
24
|
+
.com.apple.timemachine.donotpresent
|
25
|
+
|
26
|
+
# Directories potentially created on remote AFP share
|
27
|
+
.AppleDB
|
28
|
+
.AppleDesktop
|
29
|
+
Network Trash Folder
|
30
|
+
Temporary Items
|
31
|
+
.apdisk
|
32
|
+
|
33
|
+
*.gem
|
34
|
+
*.rbc
|
35
|
+
/.config
|
36
|
+
/coverage/
|
37
|
+
/InstalledFiles
|
38
|
+
/pkg/
|
39
|
+
/spec/reports/
|
40
|
+
/spec/examples.txt
|
41
|
+
/test/tmp/
|
42
|
+
/test/version_tmp/
|
43
|
+
/tmp/
|
44
|
+
|
45
|
+
# Used by dotenv library to load environment variables.
|
46
|
+
# .env
|
47
|
+
|
48
|
+
## Specific to RubyMotion:
|
49
|
+
.dat*
|
50
|
+
.repl_history
|
51
|
+
# build/
|
52
|
+
*.bridgesupport
|
53
|
+
build-iPhoneOS/
|
54
|
+
build-iPhoneSimulator/
|
55
|
+
|
56
|
+
## Specific to RubyMotion (use of CocoaPods):
|
57
|
+
#
|
58
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
59
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
60
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
61
|
+
#
|
62
|
+
# vendor/Pods/
|
63
|
+
|
64
|
+
## Documentation cache and generated files:
|
65
|
+
/_yardoc/
|
66
|
+
/.yardoc/
|
67
|
+
/_yardoc/
|
68
|
+
/doc/
|
69
|
+
/rdoc/
|
70
|
+
|
71
|
+
## Environment normalization:
|
72
|
+
/.bundle/
|
73
|
+
/vendor/bundle
|
74
|
+
/lib/bundler/man/
|
75
|
+
|
76
|
+
# for a library or gem, you might want to ignore these files since the code is
|
77
|
+
# intended to run in multiple environments; otherwise, check them in:
|
78
|
+
# Gemfile.lock
|
79
|
+
# .ruby-version
|
80
|
+
# .ruby-gemset
|
81
|
+
|
82
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
83
|
+
.rvmrc
|
84
|
+
# TODO: ignore rspec last status?
|
85
|
+
.rspec_status
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
obfus (0.1.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.3)
|
10
|
+
rake (10.5.0)
|
11
|
+
rspec (3.8.0)
|
12
|
+
rspec-core (~> 3.8.0)
|
13
|
+
rspec-expectations (~> 3.8.0)
|
14
|
+
rspec-mocks (~> 3.8.0)
|
15
|
+
rspec-core (3.8.0)
|
16
|
+
rspec-support (~> 3.8.0)
|
17
|
+
rspec-expectations (3.8.1)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.8.0)
|
20
|
+
rspec-mocks (3.8.0)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.8.0)
|
23
|
+
rspec-support (3.8.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
bundler (~> 1.16)
|
30
|
+
obfus!
|
31
|
+
rake (~> 10.0)
|
32
|
+
rspec (~> 3.0)
|
33
|
+
|
34
|
+
BUNDLED WITH
|
35
|
+
1.16.2
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
task :default => :test
|
4
|
+
|
5
|
+
desc 'Run the tests'
|
6
|
+
task :test do
|
7
|
+
sh 'rspec spec'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :standalone do
|
11
|
+
mkdir_p 'build'
|
12
|
+
File.open('build/obfus', 'w') do |f|
|
13
|
+
f.puts '#!/usr/bin/env ruby'
|
14
|
+
f.puts ''
|
15
|
+
f.puts File.read('bin/obfus').split("require 'obfus/main'\n")[1].prepend(File.read('lib/obfus/main.rb'))
|
16
|
+
end
|
17
|
+
|
18
|
+
sh 'chmod +x build/obfus'
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Install standalone script and man page.'
|
22
|
+
task :install => :standalone do
|
23
|
+
prefix = ENV['PREFIX'] || ENV['prefix'] || '/usr/local'
|
24
|
+
|
25
|
+
mkdir_p "#{prefix}/bin"
|
26
|
+
ln_s "build/obfus", "#{prefix}/bin/obfus"
|
27
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'obfus'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/obfus
ADDED
data/bin/setup
ADDED
data/build/obfus
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'open3'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
module Obfus
|
10
|
+
class << self
|
11
|
+
CONFIG_LOCATIONS = [
|
12
|
+
File.join(ENV['HOME'], '.config', 'obfus', '{.,}config*'),
|
13
|
+
File.join(ENV['HOME'], '.config', 'obfus', '.obfus{config*,rc}'),
|
14
|
+
File.join(ENV['HOME'], '.obfus{config*,rc}')
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
OPTIONS = {
|
18
|
+
mode: :compress,
|
19
|
+
preset: nil,
|
20
|
+
level: 9,
|
21
|
+
keep: true,
|
22
|
+
recipients: [],
|
23
|
+
verbosity: :normal
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
def find_config
|
27
|
+
list = []
|
28
|
+
CONFIG_LOCATIONS.each do |pattern|
|
29
|
+
list += Dir.glob pattern
|
30
|
+
end
|
31
|
+
|
32
|
+
if list.count < 1
|
33
|
+
# no config file detected
|
34
|
+
nil
|
35
|
+
elsif list.count > 1
|
36
|
+
# TODO: print warning (multiple config files: <list...>, reading from <path>)
|
37
|
+
puts 'error: encountered multiple configuration files:'
|
38
|
+
list.each do |l|
|
39
|
+
puts File.expand_path l
|
40
|
+
end
|
41
|
+
puts "reading from: #{File.expand_path list[0]}"
|
42
|
+
nil
|
43
|
+
else
|
44
|
+
list[0]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_config(file)
|
49
|
+
parsed = nil
|
50
|
+
File.open(file, 'r') do |f|
|
51
|
+
parsed = YAML.safe_load f.read
|
52
|
+
end
|
53
|
+
parsed
|
54
|
+
end
|
55
|
+
|
56
|
+
def apply_config(options)
|
57
|
+
file = find_config
|
58
|
+
opts = OpenStruct.new OPTIONS
|
59
|
+
config = nil
|
60
|
+
unless file.nil?
|
61
|
+
config = parse_config(file)
|
62
|
+
if options.preset.nil?
|
63
|
+
if config['default'].nil?
|
64
|
+
# use native defaults
|
65
|
+
else
|
66
|
+
# use config file
|
67
|
+
opts = OpenStruct.new config['default']
|
68
|
+
opts.preset = 'default'
|
69
|
+
end
|
70
|
+
else
|
71
|
+
# use preset
|
72
|
+
opts = OpenStruct.new config[options.preset]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# override
|
77
|
+
options.each_pair do |k, v|
|
78
|
+
opts[k] = v
|
79
|
+
end
|
80
|
+
|
81
|
+
opts['keep'] = true if opts['keep'].nil?
|
82
|
+
|
83
|
+
opts['config'] = file
|
84
|
+
|
85
|
+
opts
|
86
|
+
end
|
87
|
+
|
88
|
+
def ensure_file(name)
|
89
|
+
path = File.expand_path name
|
90
|
+
File.exist? path
|
91
|
+
end
|
92
|
+
|
93
|
+
def compress(files, options)
|
94
|
+
archive_name = 'Archive'
|
95
|
+
if files.count < 1
|
96
|
+
puts 'error: no files specified'
|
97
|
+
puts 'try `obfus --help`'
|
98
|
+
exit 1
|
99
|
+
elsif files.count == 1
|
100
|
+
# call it the name of the file
|
101
|
+
archive_name = File.basename files[0], '.*'
|
102
|
+
end
|
103
|
+
|
104
|
+
unless options.output.nil?
|
105
|
+
archive_name = options.output.strip
|
106
|
+
archive_name.gsub!(/^.*(\\|\/)/, '')
|
107
|
+
end
|
108
|
+
|
109
|
+
unless options.force
|
110
|
+
if ensure_file(archive_name)
|
111
|
+
# file already exists
|
112
|
+
puts "error: file #{archive_name} already exists"
|
113
|
+
puts 'to overwrite the file use `--force`'
|
114
|
+
exit 1
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
files.each do |file|
|
119
|
+
next if ensure_file(file)
|
120
|
+
# TODO: file <file> does not exist!
|
121
|
+
puts "error: #{file} does not exist"
|
122
|
+
exit 1
|
123
|
+
end
|
124
|
+
|
125
|
+
if options.recipients.count < 1
|
126
|
+
# TODO: throw error! no recipients specified
|
127
|
+
puts 'error: no recipients specified'
|
128
|
+
puts 'try `obfus --help`'
|
129
|
+
exit 1
|
130
|
+
end
|
131
|
+
|
132
|
+
if options.verbosity == :verbose
|
133
|
+
unless options.verbosity == :quiet
|
134
|
+
puts 'using config file: ' + options.config
|
135
|
+
puts 'using preset: ' + options.preset
|
136
|
+
puts 'keeping original files: ' + options.keep.to_s
|
137
|
+
puts 'compression quality: ' + options.level.to_s
|
138
|
+
puts 'compressing:'
|
139
|
+
files.each { |f| puts '- ' + f }
|
140
|
+
puts
|
141
|
+
puts 'recipients:'
|
142
|
+
options.recipients.each { |r| puts '- ' + r }
|
143
|
+
puts
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
File.open archive_name, 'w' do |f|
|
148
|
+
# add recipients `-r <recipient>`
|
149
|
+
recipients = []
|
150
|
+
|
151
|
+
options.recipients.each do |r|
|
152
|
+
recipients << '-r'
|
153
|
+
recipients << r
|
154
|
+
end
|
155
|
+
|
156
|
+
Open3.pipeline_r(
|
157
|
+
['tar', 'cf', '-', *files],
|
158
|
+
['brotli', '-cq', options.level.to_s],
|
159
|
+
['gpg', '-eq', *recipients]
|
160
|
+
) do |o, _ts|
|
161
|
+
# ts.each { |t| puts t.pid, t.status }
|
162
|
+
f.write o.read
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def decompress(file)
|
168
|
+
# TODO: iterate over files
|
169
|
+
unless ensure_file(file)
|
170
|
+
puts "error: file #{file} does not exist"
|
171
|
+
exit 1
|
172
|
+
end
|
173
|
+
|
174
|
+
Open3.pipeline_r(
|
175
|
+
['gpg', '-dq', file],
|
176
|
+
['brotli', '-dc'],
|
177
|
+
['tar', '-x']
|
178
|
+
) do |o, ts|
|
179
|
+
# ts.each { |t| puts t.pid, t.status }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def exec(args)
|
184
|
+
options = OpenStruct.new
|
185
|
+
|
186
|
+
opt_parser = OptionParser.new do |opts|
|
187
|
+
opts.banner = "\nUsage: obfus [options] <file...>"
|
188
|
+
opts.separator ''
|
189
|
+
opts.separator 'Operation Modes:'
|
190
|
+
opts.on('-z', '--compress', 'Compress operation mode (default)') do
|
191
|
+
options.mode = :compress
|
192
|
+
end
|
193
|
+
opts.on('-d', '--decompress', 'Decompress operation mode') do
|
194
|
+
options.mode = :decompress
|
195
|
+
end
|
196
|
+
|
197
|
+
opts.separator ''
|
198
|
+
opts.separator 'Options:'
|
199
|
+
opts.on('-o', '--output NAME', 'Specify the output file name') do |name|
|
200
|
+
options.output = name
|
201
|
+
end
|
202
|
+
opts.on('-f', '--force', 'Overwrites output file if conflicts with an existing one') do |v|
|
203
|
+
options.force = v
|
204
|
+
end
|
205
|
+
opts.on('-p', '--preset NAME', 'Use a configuration preset') do |name|
|
206
|
+
options.preset = name
|
207
|
+
end
|
208
|
+
opts.on('-l', '--level [0..9]', Integer, 'Specify compression level (defaults to 9)') do |v|
|
209
|
+
options.level = v
|
210
|
+
end
|
211
|
+
opts.on('-k', '--[no-]keep', 'Keep the original files') do |keep|
|
212
|
+
options.keep = keep
|
213
|
+
end
|
214
|
+
opts.on('-r', '--recipients x,y,z', Array, 'Add recipients list') do |list|
|
215
|
+
options.recipients = [] if options.recipient.nil?
|
216
|
+
options.recipients += list
|
217
|
+
end
|
218
|
+
|
219
|
+
opts.on('-v', '--verbose', 'Run verbosely') do
|
220
|
+
options.verbosity = :verbose
|
221
|
+
end
|
222
|
+
opts.on('-q', '--quiet', 'Suppress any output') do
|
223
|
+
options.verbosity = :quiet
|
224
|
+
end
|
225
|
+
|
226
|
+
opts.separator ''
|
227
|
+
opts.separator 'Other options:'
|
228
|
+
opts.on_tail('--version', 'Show the version number') do
|
229
|
+
puts Obfus::VERSION
|
230
|
+
exit
|
231
|
+
end
|
232
|
+
|
233
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
234
|
+
puts opts
|
235
|
+
exit
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
opt_parser.parse!(args)
|
240
|
+
|
241
|
+
options = apply_config(options)
|
242
|
+
|
243
|
+
if options.mode == :decompress
|
244
|
+
# decompress archive
|
245
|
+
decompress(ARGV[0])
|
246
|
+
else
|
247
|
+
# compress
|
248
|
+
compress(ARGV, options)
|
249
|
+
end
|
250
|
+
|
251
|
+
# puts options
|
252
|
+
# puts ARGV
|
253
|
+
end # exec()
|
254
|
+
end # class << self
|
255
|
+
end # module Obfus
|
256
|
+
|
257
|
+
Obfus.exec(ARGV)
|
data/lib/obfus/main.rb
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'open3'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module Obfus
|
8
|
+
class << self
|
9
|
+
CONFIG_LOCATIONS = [
|
10
|
+
File.join(ENV['HOME'], '.config', 'obfus', '{.,}config*'),
|
11
|
+
File.join(ENV['HOME'], '.config', 'obfus', '.obfus{config*,rc}'),
|
12
|
+
File.join(ENV['HOME'], '.obfus{config*,rc}')
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
OPTIONS = {
|
16
|
+
mode: :compress,
|
17
|
+
preset: nil,
|
18
|
+
level: 9,
|
19
|
+
keep: true,
|
20
|
+
recipients: [],
|
21
|
+
verbosity: :normal
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
def find_config
|
25
|
+
list = []
|
26
|
+
CONFIG_LOCATIONS.each do |pattern|
|
27
|
+
list += Dir.glob pattern
|
28
|
+
end
|
29
|
+
|
30
|
+
if list.count < 1
|
31
|
+
# no config file detected
|
32
|
+
nil
|
33
|
+
elsif list.count > 1
|
34
|
+
# TODO: print warning (multiple config files: <list...>, reading from <path>)
|
35
|
+
puts 'error: encountered multiple configuration files:'
|
36
|
+
list.each do |l|
|
37
|
+
puts File.expand_path l
|
38
|
+
end
|
39
|
+
puts "reading from: #{File.expand_path list[0]}"
|
40
|
+
nil
|
41
|
+
else
|
42
|
+
list[0]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_config(file)
|
47
|
+
parsed = nil
|
48
|
+
File.open(file, 'r') do |f|
|
49
|
+
parsed = YAML.safe_load f.read
|
50
|
+
end
|
51
|
+
parsed
|
52
|
+
end
|
53
|
+
|
54
|
+
def apply_config(options)
|
55
|
+
file = find_config
|
56
|
+
opts = OpenStruct.new OPTIONS
|
57
|
+
config = nil
|
58
|
+
unless file.nil?
|
59
|
+
config = parse_config(file)
|
60
|
+
if options.preset.nil?
|
61
|
+
if config['default'].nil?
|
62
|
+
# use native defaults
|
63
|
+
else
|
64
|
+
# use config file
|
65
|
+
opts = OpenStruct.new config['default']
|
66
|
+
opts.preset = 'default'
|
67
|
+
end
|
68
|
+
else
|
69
|
+
# use preset
|
70
|
+
opts = OpenStruct.new config[options.preset]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# override
|
75
|
+
options.each_pair do |k, v|
|
76
|
+
opts[k] = v
|
77
|
+
end
|
78
|
+
|
79
|
+
opts['keep'] = true if opts['keep'].nil?
|
80
|
+
|
81
|
+
opts['config'] = file
|
82
|
+
|
83
|
+
opts
|
84
|
+
end
|
85
|
+
|
86
|
+
def ensure_file(name)
|
87
|
+
path = File.expand_path name
|
88
|
+
File.exist? path
|
89
|
+
end
|
90
|
+
|
91
|
+
def compress(files, options)
|
92
|
+
archive_name = 'Archive'
|
93
|
+
if files.count < 1
|
94
|
+
puts 'error: no files specified'
|
95
|
+
puts 'try `obfus --help`'
|
96
|
+
exit 1
|
97
|
+
elsif files.count == 1
|
98
|
+
# call it the name of the file
|
99
|
+
archive_name = File.basename files[0], '.*'
|
100
|
+
end
|
101
|
+
|
102
|
+
unless options.output.nil?
|
103
|
+
archive_name = options.output.strip
|
104
|
+
archive_name.gsub!(/^.*(\\|\/)/, '')
|
105
|
+
end
|
106
|
+
|
107
|
+
unless options.force
|
108
|
+
if ensure_file(archive_name)
|
109
|
+
# file already exists
|
110
|
+
puts "error: file #{archive_name} already exists"
|
111
|
+
puts 'to overwrite the file use `--force`'
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
files.each do |file|
|
117
|
+
next if ensure_file(file)
|
118
|
+
# TODO: file <file> does not exist!
|
119
|
+
puts "error: #{file} does not exist"
|
120
|
+
exit 1
|
121
|
+
end
|
122
|
+
|
123
|
+
if options.recipients.count < 1
|
124
|
+
# TODO: throw error! no recipients specified
|
125
|
+
puts 'error: no recipients specified'
|
126
|
+
puts 'try `obfus --help`'
|
127
|
+
exit 1
|
128
|
+
end
|
129
|
+
|
130
|
+
if options.verbosity == :verbose
|
131
|
+
unless options.verbosity == :quiet
|
132
|
+
puts 'using config file: ' + options.config
|
133
|
+
puts 'using preset: ' + options.preset
|
134
|
+
puts 'keeping original files: ' + options.keep.to_s
|
135
|
+
puts 'compression quality: ' + options.level.to_s
|
136
|
+
puts 'compressing:'
|
137
|
+
files.each { |f| puts '- ' + f }
|
138
|
+
puts
|
139
|
+
puts 'recipients:'
|
140
|
+
options.recipients.each { |r| puts '- ' + r }
|
141
|
+
puts
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
File.open archive_name, 'w' do |f|
|
146
|
+
# add recipients `-r <recipient>`
|
147
|
+
recipients = []
|
148
|
+
|
149
|
+
options.recipients.each do |r|
|
150
|
+
recipients << '-r'
|
151
|
+
recipients << r
|
152
|
+
end
|
153
|
+
|
154
|
+
Open3.pipeline_r(
|
155
|
+
['tar', 'cf', '-', *files],
|
156
|
+
['brotli', '-cq', options.level.to_s],
|
157
|
+
['gpg', '-eq', *recipients]
|
158
|
+
) do |o, _ts|
|
159
|
+
# ts.each { |t| puts t.pid, t.status }
|
160
|
+
f.write o.read
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def decompress(file)
|
166
|
+
# TODO: iterate over files
|
167
|
+
unless ensure_file(file)
|
168
|
+
puts "error: file #{file} does not exist"
|
169
|
+
exit 1
|
170
|
+
end
|
171
|
+
|
172
|
+
Open3.pipeline_r(
|
173
|
+
['gpg', '-dq', file],
|
174
|
+
['brotli', '-dc'],
|
175
|
+
['tar', '-x']
|
176
|
+
) do |o, ts|
|
177
|
+
# ts.each { |t| puts t.pid, t.status }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def exec(args)
|
182
|
+
options = OpenStruct.new
|
183
|
+
|
184
|
+
opt_parser = OptionParser.new do |opts|
|
185
|
+
opts.banner = "\nUsage: obfus [options] <file...>"
|
186
|
+
opts.separator ''
|
187
|
+
opts.separator 'Operation Modes:'
|
188
|
+
opts.on('-z', '--compress', 'Compress operation mode (default)') do
|
189
|
+
options.mode = :compress
|
190
|
+
end
|
191
|
+
opts.on('-d', '--decompress', 'Decompress operation mode') do
|
192
|
+
options.mode = :decompress
|
193
|
+
end
|
194
|
+
|
195
|
+
opts.separator ''
|
196
|
+
opts.separator 'Options:'
|
197
|
+
opts.on('-o', '--output NAME', 'Specify the output file name') do |name|
|
198
|
+
options.output = name
|
199
|
+
end
|
200
|
+
opts.on('-f', '--force', 'Overwrites output file if conflicts with an existing one') do |v|
|
201
|
+
options.force = v
|
202
|
+
end
|
203
|
+
opts.on('-p', '--preset NAME', 'Use a configuration preset') do |name|
|
204
|
+
options.preset = name
|
205
|
+
end
|
206
|
+
opts.on('-l', '--level [0..9]', Integer, 'Specify compression level (defaults to 9)') do |v|
|
207
|
+
options.level = v
|
208
|
+
end
|
209
|
+
opts.on('-k', '--[no-]keep', 'Keep the original files') do |keep|
|
210
|
+
options.keep = keep
|
211
|
+
end
|
212
|
+
opts.on('-r', '--recipients x,y,z', Array, 'Add recipients list') do |list|
|
213
|
+
options.recipients = [] if options.recipient.nil?
|
214
|
+
options.recipients += list
|
215
|
+
end
|
216
|
+
|
217
|
+
opts.on('-v', '--verbose', 'Run verbosely') do
|
218
|
+
options.verbosity = :verbose
|
219
|
+
end
|
220
|
+
opts.on('-q', '--quiet', 'Suppress any output') do
|
221
|
+
options.verbosity = :quiet
|
222
|
+
end
|
223
|
+
|
224
|
+
opts.separator ''
|
225
|
+
opts.separator 'Other options:'
|
226
|
+
opts.on_tail('--version', 'Show the version number') do
|
227
|
+
puts Obfus::VERSION
|
228
|
+
exit
|
229
|
+
end
|
230
|
+
|
231
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
232
|
+
puts opts
|
233
|
+
exit
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
opt_parser.parse!(args)
|
238
|
+
|
239
|
+
options = apply_config(options)
|
240
|
+
|
241
|
+
if options.mode == :decompress
|
242
|
+
# decompress archive
|
243
|
+
decompress(ARGV[0])
|
244
|
+
else
|
245
|
+
# compress
|
246
|
+
compress(ARGV, options)
|
247
|
+
end
|
248
|
+
|
249
|
+
# puts options
|
250
|
+
# puts ARGV
|
251
|
+
end # exec()
|
252
|
+
end # class << self
|
253
|
+
end # module Obfus
|
data/lib/obfus.rb
ADDED
data/license.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 everdrone
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/obfus.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'obfus/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'obfus'
|
7
|
+
spec.version = Obfus::VERSION
|
8
|
+
spec.authors = ['everdrone']
|
9
|
+
spec.email = ['giorgiotropiano@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = 'File compression and encryption tool'
|
12
|
+
spec.description = 'With the top notch of both compression and encryption technology, `obfus` makes it easy to pack and back up sensitive data in a few keystrokes.'
|
13
|
+
spec.homepage = 'https://github.com/everdrone/obfus'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
20
|
+
else
|
21
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
22
|
+
'public gem pushes.'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Specify which files should be added to the gem when it is released.
|
26
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
27
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
28
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
29
|
+
end
|
30
|
+
spec.bindir = 'bin'
|
31
|
+
spec.executables = 'obfus'
|
32
|
+
spec.require_paths = ['lib']
|
33
|
+
|
34
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
36
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# obfus
|
2
|
+
> File compression and encryption tool
|
3
|
+
|
4
|
+
## Under development!
|
5
|
+
|
6
|
+
With the top notch of both compression and encryption technology, `obfus` makes it easy to pack and back up sensitive data in a few keystrokes.
|
7
|
+
|
8
|
+
### Requirements
|
9
|
+
- [Brotli](https://github.com/google/brotli)
|
10
|
+
- [GnuPG](https://github.com/gpg/gnupg)
|
11
|
+
|
12
|
+
## Install
|
13
|
+
|
14
|
+
```bash
|
15
|
+
brew install obfus
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
#### Archive
|
21
|
+
```bash
|
22
|
+
obfus readme.md src/**/*.rb -o backup.obfus
|
23
|
+
```
|
24
|
+
|
25
|
+
#### Unarchive
|
26
|
+
```bash
|
27
|
+
obfus -d backup.obfus
|
28
|
+
```
|
29
|
+
|
30
|
+
## Features
|
31
|
+
|
32
|
+
### Configuration file
|
33
|
+
Before each operation, `obfus` searches for a configuration file, usually located in `~/.config/obfus/` or in your home directory.
|
34
|
+
|
35
|
+
The config file can be both in `json` or `yaml` format.
|
36
|
+
|
37
|
+
Inside the configuration file you can define a list of presets that can be used when `obfus` archives data.
|
38
|
+
|
39
|
+
Example configuration file:
|
40
|
+
```yaml
|
41
|
+
# ~/.config/obfus/config.yml
|
42
|
+
|
43
|
+
default:
|
44
|
+
recipients:
|
45
|
+
- myself@mail.com
|
46
|
+
level: 9
|
47
|
+
keep: false
|
48
|
+
|
49
|
+
work:
|
50
|
+
recipients:
|
51
|
+
- coworker@company.com
|
52
|
+
- boss@company.com
|
53
|
+
level: 3
|
54
|
+
keep: true
|
55
|
+
verbosity: verbose
|
56
|
+
|
57
|
+
backup:
|
58
|
+
recipients:
|
59
|
+
- myself@mail.com
|
60
|
+
level: 11
|
61
|
+
verbosity: verbose
|
62
|
+
```
|
63
|
+
|
64
|
+
By default `obfus` uses the `default` preset if present, otherwise it will operate with the program's native defaults.
|
65
|
+
|
66
|
+
To specify a preset use the `-p` option:
|
67
|
+
|
68
|
+
```bash
|
69
|
+
obfus -p work ~/Documents/work/
|
70
|
+
```
|
71
|
+
|
72
|
+
The configuration file's sole purpose is to make it easier to pick the settings and apply them on the fly every time you need.
|
73
|
+
To ovveride the current preset settings or the default settings just pass more options as arguments.
|
74
|
+
|
75
|
+
For example, to add a recipient to the archive without altering the config file use the `-r` option:
|
76
|
+
|
77
|
+
```bash
|
78
|
+
obfus -p work ~/Documents/work/ -r mommy@mail.com,daddy@mail.com
|
79
|
+
```
|
80
|
+
|
81
|
+
#### Configuration file location
|
82
|
+
- `~/.config/obfus/config{,.json,.yaml,.yml}`
|
83
|
+
- `~/.obfus{rc,config}`
|
84
|
+
|
85
|
+
### Options
|
86
|
+
|
87
|
+
|Name|Shorthand|Functionality|Default|
|
88
|
+
|-|-|-|-|
|
89
|
+
|`--compress`|`-z`|Compress operation mode|yes|
|
90
|
+
|`--decompress`|`-d`|Decompress operation mode|no|
|
91
|
+
|`--output FILE`|`-o`|Specify the output file name||
|
92
|
+
|`--force`|`-f`|Force overwrite the output file if it already exists|`false`|
|
93
|
+
|`--preset NAME`|`-p`|Use a preset configuration from the config file|`default`|
|
94
|
+
|`--level [0..9]`|`-l`|Specify the compression level (as in brotli)|`9`|
|
95
|
+
|`--keep`|`-k`|Keep the original files|`true`|
|
96
|
+
|`--recipients X,Y,Z`|`-r`|Add recipients||
|
97
|
+
|`--verbose`|`-v`|Prints more stuff||
|
98
|
+
|`--quiet`|`-q`|Prints nothing but errors, if any||
|
99
|
+
|`--version`||Print the version and exit||
|
100
|
+
|`--help`|`-h`|Print the help message and exit||
|
101
|
+
|
102
|
+
> Options can be concatenated, like in many unix programs:
|
103
|
+
>
|
104
|
+
> `obfus files/* -zvr some@mail.com -fko output.obfus`
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: obfus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- everdrone
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: With the top notch of both compression and encryption technology, `obfus`
|
56
|
+
makes it easy to pack and back up sensitive data in a few keystrokes.
|
57
|
+
email:
|
58
|
+
- giorgiotropiano@gmail.com
|
59
|
+
executables:
|
60
|
+
- obfus
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- ".github/.gitkeep"
|
65
|
+
- ".gitignore"
|
66
|
+
- ".rspec"
|
67
|
+
- ".travis.yml"
|
68
|
+
- Gemfile
|
69
|
+
- Gemfile.lock
|
70
|
+
- Rakefile
|
71
|
+
- bin/console
|
72
|
+
- bin/obfus
|
73
|
+
- bin/setup
|
74
|
+
- build/obfus
|
75
|
+
- lib/obfus.rb
|
76
|
+
- lib/obfus/main.rb
|
77
|
+
- lib/obfus/version.rb
|
78
|
+
- license.txt
|
79
|
+
- obfus.gemspec
|
80
|
+
- readme.md
|
81
|
+
homepage: https://github.com/everdrone/obfus
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata:
|
85
|
+
allowed_push_host: https://rubygems.org
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 2.7.7
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: File compression and encryption tool
|
106
|
+
test_files: []
|