expletive 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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