ciphr 0.0.1

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.
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ciphr'
4
+ require 'slop'
5
+
6
+ Slop.parse do
7
+ banner "Usage: #{File.basename $0} [options] [spec]"
8
+ on :h, :help
9
+ on :v, :verbose
10
+ on :n, :'no-newline'
11
+ on :N, :'newline'
12
+ on :x, :'xargs-mode'
13
+ on :'0', :null
14
+
15
+ run do |opts, args|
16
+ Ciphr::FunctionRegistry.global.setup
17
+ if opts[:help] || args.size == 0
18
+ puts opts
19
+ if opts[:verbose]
20
+ puts "Available Functions: aliases ([args])"
21
+ Ciphr::FunctionRegistry.global.functions.flat_map{|c,vs| vs.map{|v| [c,v] }}.each{|a|
22
+ c,v = a
23
+ puts " #{v[0].map{|v|v.to_s}.join(", ")} (#{c.params.map{|p| p.to_s}.join(", ")})"
24
+ }
25
+ end
26
+ else
27
+ newline = opts[:newline] || opts[:'xargs-mode'] || STDOUT.tty? && ! opts[:'no-newline']
28
+ spec = args.join(" ")
29
+ begin
30
+ parsed = Ciphr::Parser.new.parse(spec)
31
+ if opts[:'xargs-mode']
32
+ delim = opts['null'] ? "\x00" : "\n"
33
+ $stdin.each_line(delim) do |line|
34
+ transformed = Ciphr::Transformer.new(StringIO.new(line.tr(delim,''))).apply(parsed)
35
+ $stdout.print transformed.read
36
+ puts if newline
37
+ end
38
+ else
39
+ transformed = Ciphr::Transformer.new($stdin).apply(parsed)
40
+ while (chunk = transformed.read(256)) && ! $stdout.closed?
41
+ begin
42
+ $stdout.print(chunk)
43
+ rescue Errno::EPIPE
44
+ break
45
+ end
46
+ end
47
+ puts if newline
48
+ end
49
+ rescue Parslet::ParseFailed => e
50
+ $stderr.puts e.cause
51
+ $stderr.puts spec
52
+ $stderr.puts " " * (e.cause.pos) + "^"
53
+ rescue Ciphr::FunctionRegistry::InvalidFunctionError => e
54
+ $stderr.puts "invalid function '#{e.name}'"
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+
61
+
62
+
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ciphr/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ciphr"
8
+ spec.version = Ciphr::VERSION
9
+ spec.authors = ["Chris Frohoff"]
10
+ spec.email = ["chris@frohoff.org"]
11
+ spec.description = ""
12
+ spec.summary = "gem for composing (en|de)coding, digest, cipher operations"
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = Dir['**/*']
17
+ spec.executables << 'ciphr'
18
+ spec.test_files = Dir['test/**/*', 'spec/**/*']
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake", "~> 10.5.0"
23
+ spec.add_development_dependency "rspec", "~> 3.4.0"
24
+ #spec.add_development_dependency 'coveralls'
25
+ #spec.add_development_dependency 'codeclimate-test-reporter'
26
+
27
+ spec.add_dependency "parslet", "~> 1.5.0"
28
+ spec.add_dependency "slop", "~> 3.6.0"
29
+ spec.add_dependency "base32", "~> 0.3.2"
30
+ #spec.add_dependency "base32-crockford"
31
+ #spec.add_dependency "zbase32"
32
+ end
@@ -0,0 +1,35 @@
1
+ require "ciphr/version"
2
+ require "ciphr/functions"
3
+ require "ciphr/stream"
4
+ require "ciphr/parser"
5
+
6
+ module Ciphr
7
+ @@init = false
8
+
9
+ def self.init()
10
+ @@init = true
11
+ Ciphr::FunctionRegistry.global.setup
12
+ end
13
+
14
+ def self.transform(spec, input = STDIN, output = STDOUT)
15
+ init if !@@init
16
+ if input.is_a? String
17
+ input = StringIO.new(input)
18
+ input.close_write
19
+ output = StringIO.new()
20
+ end
21
+
22
+ parsed = Ciphr::Parser.new.parse(spec)
23
+ transformed = Ciphr::Transformer.new(input).apply(parsed)
24
+
25
+ while chunk = transformed.read(256)
26
+ output.write chunk
27
+ end
28
+
29
+ if output.is_a? StringIO
30
+ output.string
31
+ else
32
+ nil
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,47 @@
1
+ module Ciphr
2
+ class FunctionRegistry
3
+ def initialize()
4
+ @function_classes = []
5
+ @functions = []
6
+ @function_aliases = {}
7
+ end
8
+
9
+ def register(klass)
10
+ @function_classes << klass
11
+ end
12
+
13
+ def setup(classes=@function_classes)
14
+ @functions = classes.map{|c| [c,c.variants]}.select{|a| a[1] && a[1].size > 0}.map{|a|
15
+ [a[0], a[1].map{|v| [[v[0]].flatten.uniq, v[1]]}]}
16
+ @function_aliases = Hash[@functions.map{|c,vs| vs.map{|v| [v[0]].flatten.map{|n| [n,[c, v[1]]]}}.flatten(1)}.flatten(1)]
17
+ end
18
+
19
+ def function_aliases
20
+ @function_aliases
21
+ end
22
+
23
+ def [](name)
24
+ @function_aliases[name] || (raise InvalidFunctionError.new(name))
25
+ end
26
+
27
+ def functions
28
+ @functions
29
+ end
30
+
31
+ # http://stackoverflow.com/questions/746207/ruby-design-pattern-how-to-make-an-extensible-factory-class
32
+ # global instance for load-time registration
33
+
34
+ @@global = FunctionRegistry.new()
35
+
36
+ def self.global
37
+ @@global
38
+ end
39
+
40
+ class InvalidFunctionError < StandardError
41
+ attr_reader :name
42
+ def initialize(name)
43
+ @name = name
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,62 @@
1
+
2
+ #require 'base32/crockford'
3
+ #require 'zbase32'
4
+ require_relative 'function_registry'
5
+
6
+ module Ciphr::Functions
7
+ class Function
8
+ def initialize(options, args)
9
+ @options = options
10
+ @args = args
11
+ @stream = Ciphr::Stream.new(self)
12
+ end
13
+ attr_accessor :options, :args #don't like that these are both writable, but c'est la vie
14
+
15
+ def self.variants
16
+ []
17
+ end
18
+
19
+ def self.inherited(subclass)
20
+ Ciphr::FunctionRegistry.global.register(subclass)
21
+ end
22
+
23
+ def self.params
24
+ []
25
+ end
26
+
27
+ def self.invertable?
28
+ false
29
+ end
30
+
31
+ def self.aligned
32
+ nil
33
+ end
34
+
35
+ def read(*args)
36
+ @stream.read(*args)
37
+ end
38
+
39
+ def prepend(*args)
40
+ @stream.prepend(*args)
41
+ end
42
+ end
43
+
44
+ class InvertibleFunction < Function
45
+ @invert = false
46
+ attr_accessor :invert
47
+
48
+ def self.invertable?
49
+ true
50
+ end
51
+ end
52
+ end
53
+
54
+ require_relative 'functions/openssl'
55
+ require_relative 'functions/base_radix'
56
+ require_relative 'functions/zlib'
57
+ require_relative 'functions/bitwise'
58
+ require_relative 'functions/reader'
59
+ require_relative 'functions/url'
60
+ require_relative 'functions/simple'
61
+ require_relative 'functions/crypto'
62
+
@@ -0,0 +1,205 @@
1
+ require 'base64'
2
+ require 'base32'
3
+
4
+ module Ciphr::Functions::Base
5
+ class Base < Ciphr::Functions::InvertibleFunction
6
+ def self.aligned
7
+ :left
8
+ end
9
+ end
10
+
11
+ class Base2 < Base
12
+ def self.variants
13
+ [[['b2','base2', 'bin','binary'], {}]]
14
+ end
15
+
16
+ def self.params
17
+ [:input]
18
+ end
19
+
20
+ def apply
21
+ input = @args[0]
22
+ if !invert
23
+ Proc.new do
24
+ chunk = input.read(1)
25
+ chunk && chunk.unpack("B*")[0]
26
+ end
27
+ else
28
+ Proc.new do
29
+ chunk = input.read(8)
30
+ chunk && [chunk].pack("B*")
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ class Base8 < Base
37
+ def self.variants
38
+ [[['b8','base8','oct','octal'], {}]]
39
+ end
40
+
41
+ def self.params
42
+ [:input]
43
+ end
44
+
45
+ def apply
46
+ input = @args[0]
47
+ if !invert
48
+ Proc.new do
49
+ chunk = input.read(3)
50
+ chunk = chunk && chunk + "\x00"*(3-chunk.size) #pad
51
+ chunk && chunk.unpack("B*")[0].bytes.to_a.each_slice(3).to_a.map{|a|a.pack("c*").to_i(2).to_s(8)}.join
52
+ end
53
+ else
54
+ Proc.new do
55
+ chunk = input.read(8)
56
+ chunk = chunk && chunk + "0"*(8-chunk.size) #pad
57
+ chunk && chunk.unpack("aaaaaaaa").map{|o| o.to_i.to_s(2).rjust(3,"0")}.join.unpack("a8a8a8").map{|b| b.to_i(2)}.pack("C*")
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ class Base16 < Base
64
+ def self.variants
65
+ [[['b16','base16','hex','hexidecimal'], {}]]
66
+ end
67
+
68
+ def self.params
69
+ [:input]
70
+ end
71
+
72
+ def apply
73
+ input = @args[0]
74
+ if !invert
75
+ Proc.new do
76
+ chunk = input.read(1)
77
+ chunk && chunk.unpack("H*")[0]
78
+ end
79
+ else
80
+ Proc.new do
81
+ chunk = input.read(2)
82
+ chunk && [chunk].pack("H*")
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+
89
+ class Base32 < Base
90
+ def self.variants
91
+ [
92
+ [['b32','base32','b32-std','base32-std'], {:object => ::Base32 }]#,
93
+ #broken
94
+ #[['b32-crockford','base32-crockford'], {:object => ::Base32::Crockford }],
95
+ #[['b32-z','base32-z'], {:object => ZBase32.new }]
96
+ ]
97
+ end
98
+
99
+ def self.params
100
+ [:input]
101
+ end
102
+
103
+ def apply
104
+ input = @args[0]
105
+ if !invert
106
+ Proc.new do
107
+ chunk = input.read(5)
108
+ chunk && options[:object].encode(chunk)
109
+ end
110
+ else
111
+ Proc.new do
112
+ chunk = input.read(8)
113
+ chunk && options[:object].decode(chunk)
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ class Base64 < Base
120
+ def self.aligned
121
+ nil # preserves alignment
122
+ end
123
+
124
+ def apply
125
+ input = @args[0]
126
+ if !invert
127
+ Proc.new do
128
+ chunk = input.read(3)
129
+ chunk && ::Base64.encode64(chunk).gsub(/\s/,'').tr("+/", options[:chars][0,2]).tr("=", options[:chars][2,3])
130
+ end
131
+ else
132
+ Proc.new do
133
+ chunk = input.read(4)
134
+ chunk = chunk && chunk + "="*(4-chunk.size) #pad
135
+ chunk && ::Base64.decode64(chunk.tr(options[:chars][0,2],"+/").tr(options[:chars][2,3],"=").ljust(4,"="))
136
+ end
137
+ end
138
+ end
139
+
140
+ def self.variants
141
+ chars = {"+"=>"p", "-"=>"h", "_"=>"u", ":"=>"c", "/"=>"s", "." => "d", "!"=>"x", "="=>"q"}
142
+ types = {"+/=" => ["std"], "+/" => "utf7", "+-" => "file", "-_" => "url", "._-" => "yui",
143
+ ".-" => "xml-name", "_:" => "xml-id", "_-" => "prog-id-1", "._" => "prog-id-2", "!-" => "regex"}
144
+ variants = types.map{|c,n| [["b64","base64"].product([c.chars.map{|c| chars[c] }.join,n]).map{|a| a.join("-")}, {:chars => c}]}
145
+ std = variants.select{|v| v[0].include? "b64-std"}[0] #add short aliases for standard
146
+ std[0] = ["b64","base64"].concat(std[0])
147
+ variants
148
+ end
149
+
150
+ def self.params
151
+ [:input]
152
+ end
153
+ end
154
+
155
+ end
156
+
157
+ module Ciphr::Functions::Radix
158
+
159
+
160
+ class Radix < Ciphr::Functions::InvertibleFunction
161
+ def self.aligned
162
+ :right
163
+ end
164
+
165
+ def self.variants
166
+ (2..36).map{|r| [["r#{r}","rad#{r}","radix#{r}"], {:radix => r}]}
167
+ end
168
+
169
+ def self.params
170
+ [:input]
171
+ end
172
+
173
+ def apply
174
+ radix = options[:radix]
175
+ input = @args[0]
176
+ if !invert
177
+ num = 0
178
+ while chunk = input.read(1)
179
+ num = (num << 8) + chunk.bytes.to_a[0]
180
+ end
181
+ Proc.new do
182
+ begin
183
+ num && num.to_s(radix)
184
+ ensure
185
+ num = nil
186
+ end
187
+ end
188
+ else
189
+ num = input.read().to_i(radix)
190
+ bytes = []
191
+ while num > 0
192
+ bytes.unshift(num & 0xff)
193
+ num = num >> 8
194
+ end
195
+ Proc.new do
196
+ begin
197
+ bytes && bytes.pack("c*")
198
+ ensure
199
+ bytes = nil
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end