expletive 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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 82f14df20cd14e764a80e8faa5d70419d4e748be
4
+ data.tar.gz: e4ef058f3e28c80be86145406c0fbc3bec3a89d2
5
+ SHA512:
6
+ metadata.gz: 8bb284dee6a30cccdb2da53d0286941c681cd41e6ed2981b5f7bacf0a4a72fa2356482145e8b17964ce0372a5010be2cf844c006371ed23eabc3cf2cedba5101
7
+ data.tar.gz: 4af5fd6d6a3ca6da5fe7b4eeeb7b807e60ae989f5e2a647b4b0a1aa2b3d43c74710d10eec178deccc5d5b0097c05ab68cd6065693c14f8adbbb5dc45d99ced9e
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ .ruby_version
8
+ README.html
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'minitest'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Russ Olsen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,162 @@
1
+ # Expletive
2
+
3
+
4
+ © 2015 Russ Olsen
5
+
6
+ **Expletive** is a simple pair of utilities that allow you to dump a file -- presumably a binary file -- into a
7
+ a plain text format that you can edit. The trick is that as long as you follow the expletive conventions as
8
+ you edit you can turn your plain text back into a binary file. So expletive has all the charm of your typical
9
+ hex editor, *without having to learn a new editor*. Just use vim or emacs or lightTable or any other editor
10
+ of your choice.
11
+
12
+ And the name... Well typically by the time I come to having to edit a binary file I'm usually muttering some bad words.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'expletive'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install expletive
27
+
28
+ ## Usage
29
+
30
+ Expletive is really just two commands, `exdump` and `exundump`. The `exdump` command will take your binary file and
31
+ turn it into something you can edit with an ordinary text editor. For example, if I wanted to
32
+ edit the `ls` command, I would do something like:
33
+
34
+ ```sh
35
+ $ dump < /bin/ls >ls.dump
36
+ ```
37
+
38
+ What you will end up with in `ls.dump` will be plain text, albeit somewhat intimidating plain text:
39
+
40
+ \cf\fa\ed\fe\07\00\00\01\03\00\00\80\02\00\00\00\13\00\00\00\18
41
+ \07\00\00\85\00 \00\00\00\00\00\19\00\00\00H\00\00\00__PAGEZE
42
+ RO\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01\00
43
+ \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00
44
+ \00\00\00\00\00\00\00\00\00\00\00\00\00\19\00\00\00(\02\00\00
45
+ __TEXT\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00
46
+
47
+
48
+ You can then edit the `ls.dump` file, making any changes you desire. Once you are
49
+ done you can turn your modified text back into binary with `exundump`.
50
+
51
+
52
+ ```sh
53
+ $ undump < ls.dump > ls.new
54
+ ```
55
+
56
+ ### The Dump File Format
57
+
58
+ The format of the dumped files is as simple as my small mind can make it:
59
+
60
+ * Backslashes get converted to double backslashes, so \ becomes \\\\.
61
+
62
+ * Newlines get converted to \n - that's a backslash character followed by an "n".
63
+
64
+ * Any byte that looks like a simple, human readable single byte character is written as is.
65
+
66
+ * Otherwise the byte is written as a backslash followed by a two digit hex number. Note
67
+ that this number is zero filled: It's always \03, never \3.
68
+
69
+ * The `exdump` command will periodically insert actual newlines into the output to make
70
+ it more readable. Actual newlines are ignored by `exundump`.
71
+
72
+ That's it!
73
+
74
+ ### An Example
75
+
76
+ Have you ever noticed that when you do `ls -l` in your terminal, `ls` prints
77
+ the total number of bytes at the top of the output?
78
+
79
+ ```shell
80
+ ~/projects/ruby/expletive: ls -l
81
+
82
+ total 304
83
+ -rw-r--r-- 1 russolsen staff 347 Jun 10 08:56 CHANGELOG.md
84
+ -rw-r--r-- 1 russolsen staff 55 Jun 10 09:20 Gemfile
85
+ -rw-r--r-- 1 russolsen staff 672 Jun 10 08:56 Gemfile.lock
86
+ -rw-r--r-- 1 russolsen staff 1067 Jun 10 08:56 LICENSE
87
+ ...
88
+ ```
89
+
90
+ Now imagine that for some obscure reason you wanted to make that
91
+ *total* show up as *YOOO!*. Nothing to it. First dump the contents
92
+ of the (very binary) `ls` command to some file:
93
+
94
+ ```shell
95
+ exdump </bin/ls >ls.dump
96
+ ```
97
+
98
+ Then edit the resulting dump file with the editor of your choice:
99
+
100
+ ```shell
101
+ vi ls.dump
102
+ ```
103
+
104
+ And look for the string *total*. Here is what I see when I do that:
105
+
106
+ llu\00%lu\00printscol\00/SourceCache/file_cmds/file_cmds-242/
107
+ ls/print.c\00dp\00total %qu\n\00%*llu \00%*qu \00%s%s %*u \00
108
+ %s%s %*u %-*s \00%s%s %*u %-*s %-*s \00%-*s \00%3d, 0x%08x
109
+ \00%3d, %3d \00%*s%*qu \00, \00printcol\00dp->list\00base <·
110
+
111
+ Notice the *total* on the second line. Now all you need to do is
112
+ change *total* to *YOOO!* or some other amusing string:
113
+
114
+ llu\00%lu\00printscol\00/SourceCache/file_cmds/file_cmds-242/
115
+ ls/print.c\00dp\00YOOO! %qu\n\00%*llu \00%*qu \00%s%s %*u \00
116
+ %s%s %*u %-*s \00%s%s %*u %-*s %-*s \00%-*s \00%3d, 0x%08x
117
+ \00%3d, %3d \00%*s%*qu \00, \00printcol\00dp->list\00base <·
118
+
119
+
120
+ Note that you need to make sure that your new string is the same length as the
121
+ old one (e.g. total) because executables contain counts and offsets
122
+ that you don't want to mess up.
123
+
124
+ Having made your change, you just need to convert your dump file back
125
+ to a binary. But don't overwrite your system's `ls` command!
126
+
127
+ ```shell
128
+ exundump <ls.dump >ls.new
129
+ ```
130
+
131
+ Make your new `ls.new` file executable:
132
+
133
+ ```shell
134
+ chmod +x ls.new
135
+ ```
136
+
137
+ And run your hacked binary:
138
+
139
+ ```shell
140
+ ./ls.new -l
141
+
142
+ YOOO! 312
143
+ -rw-r--r-- 1 russolsen staff 347 Jun 10 08:56 CHANGELOG.md
144
+ -rw-r--r-- 1 russolsen staff 55 Jun 10 09:20 Gemfile
145
+ -rw-r--r-- 1 russolsen staff 672 Jun 10 08:56 Gemfile.lock
146
+
147
+ ```
148
+
149
+ One final note: With the power to edit binaries, easily and with your favorite text editor,
150
+ comes great responsibility.
151
+
152
+ ## Contributors
153
+
154
+ * Russ Olsen (@russolsen)
155
+
156
+ ## Contributing
157
+
158
+ 1. Fork it
159
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
160
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
161
+ 4. Push to the branch (`git push origin my-new-feature`)
162
+ 5. Create new Pull Request
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = "spec/*_spec.rb"
8
+ end
9
+
10
+ task :clean do
11
+ rm_rf "pkg"
12
+ end
13
+
14
+ task :default => [:test, :build]
15
+
16
+ task :irb do
17
+ sh "irb -I lib -r expletive"
18
+ sh "reset"
19
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'expletive'
4
+
5
+ Expletive::Dump.new.run
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'expletive'
4
+
5
+ Expletive::Undump.new.run
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/expletive/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Russ Olsen"]
6
+ gem.email = ["russ@russolsen.com"]
7
+ gem.description = %q{'Handy scripts to convert binary files to and from an editable plaintext form.'}
8
+ gem.summary = gem.description
9
+ gem.homepage = "https://github.com/russolsen/expletive"
10
+ gem.license = "MIT"
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "expletive"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Expletive::VERSION
18
+
19
+ gem.add_development_dependency 'pry', '~> 0.9.10'
20
+ gem.add_development_dependency 'rspec', '~> 2.11.0'
21
+ gem.add_development_dependency 'rantly', '~> 0.3.1'
22
+ gem.add_development_dependency 'rake', '~> 10.0.3'
23
+ end
@@ -0,0 +1,3 @@
1
+ require 'expletive/version'
2
+ require 'expletive/filters'
3
+
@@ -0,0 +1,83 @@
1
+ module Expletive
2
+ SPACE = ' '.ord
3
+ TILDE = '~'.ord
4
+ NEWLINE = "\n".ord
5
+ BACKSLASH = "\\".ord
6
+
7
+ class Dump
8
+ def initialize(in_io=$stdin, out_io=$stdout)
9
+ @in = in_io
10
+ @out = out_io
11
+ @current_width = 0
12
+ end
13
+
14
+ def run
15
+ n = 0
16
+ until @in.eof?
17
+ byte = @in.readbyte
18
+ case
19
+ when byte == BACKSLASH
20
+ write_string "\\\\"
21
+ when byte == NEWLINE
22
+ write_string "\\n"
23
+ when human_readable?(byte)
24
+ write_string byte.chr
25
+ else
26
+ write_string "\\%02x" % byte
27
+ end
28
+ end
29
+ end
30
+
31
+ def start_new_line
32
+ @out.print("\n")
33
+ @current_width = 0
34
+ end
35
+
36
+ def write_string(s)
37
+ @out.print(s)
38
+ @current_width += s.size
39
+ start_new_line if @current_width > 60
40
+ end
41
+
42
+ def human_readable?(byte)
43
+ (byte >= SPACE) && (byte <= TILDE)
44
+ end
45
+ end
46
+
47
+ class Undump
48
+ def initialize(in_io=$stdin, out_io=$stdout)
49
+ @in = in_io
50
+ @out = out_io
51
+ end
52
+
53
+ def run
54
+ until @in.eof?
55
+ ch = @in.getc
56
+ if ch == "\n"
57
+ # do nothing
58
+ elsif ch != "\\"
59
+ @out.write ch.chr
60
+ else
61
+ handle_escape
62
+ end
63
+ end
64
+ end
65
+
66
+ def handle_escape
67
+ nextc = @in.getc
68
+ case
69
+ when nextc == '\\'
70
+ @out.write "\\"
71
+ when nextc == 'n'
72
+ @out.write "\n"
73
+ when nextc =~ /\h/
74
+ otherc = @in.getc
75
+ hex = nextc + otherc
76
+ @out.write hex.to_i(16).chr
77
+ else
78
+ raise "Dont know what to do with \\ #{nextc}"
79
+ end
80
+ end
81
+ end
82
+ end
83
+
@@ -0,0 +1,3 @@
1
+ module Expletive
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,36 @@
1
+ require 'minitest/autorun'
2
+ require 'expletive'
3
+ require 'stringio'
4
+
5
+ include Expletive
6
+
7
+ describe Dump do
8
+ def endump(input)
9
+ in_io = StringIO.new(input)
10
+ out_io = StringIO.new
11
+ Dump.new(in_io, out_io).run
12
+ out_io.string
13
+ end
14
+
15
+ describe "#dump" do
16
+ it "passes text unchanged" do
17
+ input = "hello world"
18
+ assert_equal input, endump(input)
19
+ end
20
+
21
+ it "encodes binary into hex" do
22
+ input = "\01\02\03xyz"
23
+ assert_equal '\\01\\02\\03xyz', endump(input)
24
+ end
25
+
26
+ it "escapes backslashes" do
27
+ input = 'abc\\def'
28
+ assert_equal 'abc\\\\def', endump(input)
29
+ end
30
+
31
+ it "escapes newlines" do
32
+ input = "abc\ndef"
33
+ assert_equal 'abc\\ndef', endump(input)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ require 'minitest/autorun'
2
+ require 'expletive'
3
+ require 'stringio'
4
+
5
+ include Expletive
6
+
7
+ describe Undump do
8
+ def dedump(input)
9
+ in_io = StringIO.new(input)
10
+ out_io = StringIO.new
11
+ Undump.new(in_io, out_io).run
12
+ out_io.string
13
+ end
14
+
15
+ describe "#run" do
16
+ it "passes text unchanged" do
17
+ input = "hello world"
18
+ assert_equal input, dedump(input)
19
+ end
20
+
21
+ it "decodes hex into equivalent binary" do
22
+ input = "\\01\\02\\03xyz"
23
+ output = "\01\02\03xyz"
24
+ assert_equal output, dedump(input)
25
+ end
26
+
27
+ it "turns backslash backslash into a single backslash" do
28
+ input = 'abc\\\\def'
29
+ output = 'abc\\def'
30
+ assert_equal output, dedump(input)
31
+ end
32
+
33
+ it "turns backslash n into a real newline" do
34
+ input = "abc\\ndef"
35
+ output = "abc\ndef"
36
+ assert_equal output, dedump(input)
37
+ end
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: expletive
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Russ Olsen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.10
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.10
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.11.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.11.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rantly
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.3.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.3.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 10.0.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 10.0.3
69
+ description: "'Handy scripts to convert binary files to and from an editable plaintext
70
+ form.'"
71
+ email:
72
+ - russ@russolsen.com
73
+ executables:
74
+ - exdump
75
+ - exundump
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - Gemfile
81
+ - LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - bin/exdump
85
+ - bin/exundump
86
+ - expletive.gemspec
87
+ - lib/expletive.rb
88
+ - lib/expletive/filters.rb
89
+ - lib/expletive/version.rb
90
+ - spec/dump_spec.rb
91
+ - spec/undump_spec.rb
92
+ homepage: https://github.com/russolsen/expletive
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.4.6
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: "'Handy scripts to convert binary files to and from an editable plaintext
116
+ form.'"
117
+ test_files:
118
+ - spec/dump_spec.rb
119
+ - spec/undump_spec.rb