shh 0.1.6 → 0.1.7

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.
data/MIT-LICENSE CHANGED
@@ -1,20 +1,20 @@
1
- Copyright (c) 2009 Mark Ryall
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2009 Mark Ryall
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -1,113 +1,110 @@
1
- = SHH
2
-
3
- Secret Squirrel
4
-
5
- This is a command line utility for managing secure information such as accounts, passwords as individual files so that they can be easily managed in a version control repository.
6
-
7
- You won't be hiding anything from the NSA with this level of encryption so it isn't recommended that you make your repository publicly accessible.
8
-
9
- Now with more tab completion and multi line editing!
10
-
11
- = Usage
12
-
13
- Here you sit expectantly in front of a computer at the command line.
14
-
15
- == Install
16
-
17
- gem install shh
18
-
19
- (you may need to install gemcutter first)
20
-
21
- == Launch
22
-
23
- Open all 'secrets' stored in ~/.secret
24
-
25
- > shh
26
-
27
- Opens all 'secrets' stored in foo/.secret
28
-
29
- > shh foo
30
-
31
- == Authenticate
32
-
33
- Enter your passphrase
34
-
35
- This passphrase will be used to encrypt and decrypt all of your secrets so don't make it too obvious.
36
-
37
- == Listing mode
38
-
39
- This mode allows you to view and edit 'entries' (which are encrypted hashes stored in files)
40
-
41
- > list
42
-
43
- bitbucket (260f34de-6779-4367-af2a-44184dec1cc1)
44
- amazon (291a3e6c-2c7b-4960-a146-1f6635d9a74e)
45
- yahoo (2fe408e7-7f2b-4dc0-854a-c92c21f131ae)
46
- evernote (41ad0a21-eafc-4f70-9b0d-0251be207b9e)
47
- gmail (8b35c1f2-851d-40fc-bd12-c2aad12c370a)
48
- rememberthemilk (a499f612-d034-4e49-82a8-6967d29653a1)
49
-
50
- * list - list entries
51
- * edit <name> - edit or create entry
52
- * view <name> - view entry
53
- * quit
54
-
55
- == Viewing mode
56
-
57
- This mode allows you to view (but not edit) an existing entry
58
-
59
- > view bitbucket
60
- (bitbucket) > list
61
- id,name,password,username
62
- (bitbucket) > view username
63
- markryall
64
-
65
- list keys, show key, copy key or quit? c password
66
-
67
- * list - show entry keys
68
- * view <key> - view entry value on screen
69
- * copy <key> - copy entry value to clipboard
70
- * launch <key> - launch entry value in default browser (available if it starts with http)
71
- * run <key> - execute ruby script (available if it starts with #!/usr/bin/env ruby)
72
- * quit
73
-
74
- == Editing mode
75
-
76
- This mode is viewing mode plus some editing commands
77
-
78
- > edit bitbucket
79
- (bitbucket) > set foo
80
- Enter new value for foo
81
- bar
82
- (bitbucket) > delete foo
83
-
84
- * edit <key> - edit or create key using text editor (notepad or EDITOR)
85
- * set <key> - edit or create key from prompt
86
- * delete <key> - remove a key
87
-
88
- == Quitting mode
89
-
90
- You don't want to be a quitter
91
-
92
- == Scripting
93
-
94
- In a script the following objects are available:
95
-
96
- * splat.clipboard = <text> - allows content to be copied to the clipboard
97
- * splat.browser - a watir compatible browser
98
- * hash - the current selected entry
99
-
100
- Example:
101
-
102
- browser = splat.browser
103
- browser.goto 'http://www.github.com/login'
104
- browser.text_field(:id, 'login_field').set hash['username']
105
- browser.text_field(:id, 'password').set hash['password']
106
- browser.button(:name, 'commit').click
107
-
108
- = Future plans for world domination
109
-
110
- * Add some color
111
- * Add help
112
- * add some source control (hg/git) commands
113
- * add commands for displaying history of entries
1
+ = SHH
2
+
3
+ Secret Squirrel
4
+
5
+ This is a command line utility for managing secure information such as accounts, passwords as individual files so that they can be easily managed in a version control repository.
6
+
7
+ You won't be hiding anything from the NSA with this level of encryption so it isn't recommended that you make your repository publicly accessible.
8
+
9
+ Now with more tab completion and multi line editing!
10
+
11
+ = Usage
12
+
13
+ Here you sit expectantly in front of a computer at the command line.
14
+
15
+ == Install
16
+
17
+ gem install shh
18
+
19
+ == Launch
20
+
21
+ Open all 'secrets' stored in ~/.secret
22
+
23
+ > shh
24
+
25
+ Opens all 'secrets' stored in foo/.secret
26
+
27
+ > shh foo
28
+
29
+ == Authenticate
30
+
31
+ Enter your passphrase
32
+
33
+ This passphrase will be used to encrypt and decrypt all of your secrets so don't make it too obvious.
34
+
35
+ == Listing mode
36
+
37
+ This mode allows you to view and edit 'entries' (which are encrypted hashes stored in files)
38
+
39
+ > list
40
+
41
+ bitbucket (260f34de-6779-4367-af2a-44184dec1cc1)
42
+ amazon (291a3e6c-2c7b-4960-a146-1f6635d9a74e)
43
+ yahoo (2fe408e7-7f2b-4dc0-854a-c92c21f131ae)
44
+ evernote (41ad0a21-eafc-4f70-9b0d-0251be207b9e)
45
+ gmail (8b35c1f2-851d-40fc-bd12-c2aad12c370a)
46
+ rememberthemilk (a499f612-d034-4e49-82a8-6967d29653a1)
47
+
48
+ * list - list entries
49
+ * edit <name> - edit or create entry
50
+ * view <name> - view entry
51
+ * quit
52
+
53
+ == Viewing mode
54
+
55
+ This mode allows you to view (but not edit) an existing entry
56
+
57
+ > view bitbucket
58
+ (bitbucket) > list
59
+ id,name,password,username
60
+ (bitbucket) > view username
61
+ markryall
62
+
63
+ list keys, show key, copy key or quit? c password
64
+
65
+ * list - show entry keys
66
+ * view <key> - view entry value on screen
67
+ * copy <key> - copy entry value to clipboard
68
+ * launch <key> - launch entry value in default browser (available if it starts with http)
69
+ * run <key> - execute ruby script (available if it starts with #!/usr/bin/env ruby)
70
+ * quit
71
+
72
+ == Editing mode
73
+
74
+ This mode is viewing mode plus some editing commands
75
+
76
+ > edit bitbucket
77
+ (bitbucket) > set foo
78
+ Enter new value for foo
79
+ bar
80
+ (bitbucket) > delete foo
81
+
82
+ * edit <key> - edit or create key using text editor (notepad or EDITOR)
83
+ * set <key> - edit or create key from prompt
84
+ * delete <key> - remove a key
85
+
86
+ == Quitting mode
87
+
88
+ You don't want to be a quitter
89
+
90
+ == Scripting
91
+
92
+ In a script the following objects are available:
93
+
94
+ * splat.clipboard = <text> - allows content to be copied to the clipboard
95
+ * splat.browser - a watir compatible browser
96
+ * hash - the current selected entry
97
+
98
+ Example:
99
+
100
+ browser = 'http://www.github.com/login'.to_browser
101
+ browser.text_field(:id, 'login_field').set hash['username']
102
+ browser.text_field(:id, 'password').set hash['password']
103
+ browser.button(:name, 'commit').click
104
+
105
+ = Future plans for world domination
106
+
107
+ * Add some color
108
+ * Add help
109
+ * add some source control (hg/git) commands
110
+ * add commands for displaying history of entries
data/bin/shh CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift File.dirname(__FILE__)+'/../lib'
4
- require 'shh/cli'
5
- Shh::Cli.execute(*ARGV)
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__)+'/../lib'
4
+ require 'shh/cli'
5
+ Shh::Cli.execute(*ARGV)
data/lib/shh/cli.rb CHANGED
@@ -1,16 +1,16 @@
1
- require 'rubygems'
2
- require 'shh/repository'
3
- require 'shh/prompt'
4
- require 'shh/entries_menu'
5
-
6
- module Shh
7
- class Cli
8
- def self.execute *args
9
- prompt = Prompt.new
10
- passphrase = prompt.get('Enter your passphrase', :silent => true)
11
- path = args.shift || ('~')
12
-
13
- EntriesMenu.new(prompt, Repository.new(passphrase, path)).main_loop
14
- end
15
- end
16
- end
1
+ require 'rubygems'
2
+ require 'shh/repository'
3
+ require 'shh/prompt'
4
+ require 'shh/entries_menu'
5
+
6
+ module Shh
7
+ class Cli
8
+ def self.execute *args
9
+ prompt = Prompt.new
10
+ passphrase = prompt.ask('Enter your passphrase', :silent => true)
11
+ path = args.shift || ('~')
12
+
13
+ EntriesMenu.new(prompt, Repository.new(passphrase, path)).push
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ require 'shh/commands'
2
+ require 'shh/command/key_command'
3
+ require 'splat'
4
+
5
+ class Shh::Command::CopyKey
6
+ include Shh::Command::KeyCommand
7
+
8
+ def help
9
+ "Copies the value associated with the specified key to the clipboard"
10
+ end
11
+
12
+ def execute key=nil
13
+ (@entry[key] || '').to_clipboard
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'shh/command/key_command'
2
+ require 'splat'
3
+
4
+ class Shh::Command::EditKey
5
+ include Shh::Command::KeyCommand
6
+
7
+ def help
8
+ "Launches an external editor (specified by EDITOR environment variable) to edit the value associated with the specified key"
9
+ end
10
+
11
+ def execute key=nil
12
+ new_value = (@entry[key] || '').to_editor
13
+ @entry[key] = new_value if new_value.length > 0
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require 'shh/command/key_command'
2
+
3
+ class Shh::Command::ExecuteKey
4
+ include Shh::Command::KeyCommand
5
+
6
+ def help
7
+ "Executes the contents (ruby code) associated with the specified key\nNote that the entire entry is available as a hash called 'entry'"
8
+ end
9
+
10
+ def execute key=nil
11
+ begin
12
+ entry = @entry
13
+ eval @entry[key]
14
+ rescue Exception => e
15
+ @io.say e.message
16
+ e.backtrace.each {|t| @io.say " > #{t}" }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module Shh::Command::KeyCommand
2
+ def initialize entry, io
3
+ @entry, @io = entry, io
4
+ end
5
+
6
+ def usage
7
+ "<key name>"
8
+ end
9
+
10
+ def completion text
11
+ @entry.keys.grep(/^#{text}/).sort || []
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ require 'shh/command/key_command'
2
+ require 'splat'
3
+
4
+ class Shh::Command::LaunchKey
5
+ include Shh::Command::KeyCommand
6
+
7
+ def help
8
+ "Launches the value (usually a url) associated with the specified key using default application"
9
+ end
10
+
11
+ def execute key=nil
12
+ (@entry[key] || '').to_launcher
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ class Shh::Command::ListEntries
2
+ attr_reader :usage, :help
3
+
4
+ def initialize repository, io
5
+ @repository, @io = repository, io
6
+ @usage = "(<substring>)"
7
+ @help = "Lists all entries or those with a name including the specified substring"
8
+ end
9
+
10
+ def execute text=nil
11
+ @repository.each do |entry|
12
+ next if text and !(entry['name'] =~ /#{text}/)
13
+ @io.say "#{entry['name']} (#{entry['id']})"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ class Shh::Command::ListKeys
2
+ attr_reader :usage, :help
3
+
4
+ def initialize entry, io
5
+ @entry, @io = entry, io
6
+ @usage = "(<substring>)"
7
+ @help = "Lists all keys for the entry or those including the specified substring"
8
+ end
9
+
10
+ def execute text=nil
11
+ @entry.each_key do |key|
12
+ next if text and !(key =~ /#{text}/)
13
+ @io.say key
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ require 'uuidtools'
2
+ require 'shh/entry_menu'
3
+
4
+ class Shh::Command::OpenEntry
5
+ attr_reader :usage, :help
6
+
7
+ def initialize repository, io
8
+ @repository, @io = repository, io
9
+ @usage = "<entry name>"
10
+ @help = "Enters a subshell for editing the specifed entry"
11
+ end
12
+
13
+ def completion text
14
+ @repository.map{|entry| entry['name']}.grep(/^#{text}/).sort || []
15
+ end
16
+
17
+ def execute name=nil
18
+ entry = @repository.find_by_name(name)
19
+ entry ||= {'name' => name, 'id' => UUIDTools::UUID.random_create.to_s}
20
+ Shh::EntryMenu.new(@io, entry).push
21
+ @repository.persist entry
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ require 'shh/command/key_command'
2
+
3
+ class Shh::Command::RemoveKey
4
+ include Shh::Command::KeyCommand
5
+
6
+ def help
7
+ "Removes the specified key from the entry"
8
+ end
9
+
10
+ def execute key=nil
11
+ @entry.delete(key)
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ require 'shh/command/key_command'
2
+
3
+ class Shh::Command::SetKey
4
+ include Shh::Command::KeyCommand
5
+
6
+ def help
7
+ "Prompts for a new value for the specified key\nKeys with a name including 'pass' (eg. password, passphrase) will not echo input"
8
+ end
9
+
10
+ def execute key=nil
11
+ new_value = @io.ask("Enter new value for #{key}", :silent => (key =~ /pass/))
12
+ @entry[key] = new_value if new_value.length > 0
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'shh/command/key_command'
2
+
3
+ class Shh::Command::ShowKey
4
+ include Shh::Command::KeyCommand
5
+
6
+ def help
7
+ "Displays the value associated with the specified key"
8
+ end
9
+
10
+ def execute key=nil
11
+ @io.say @entry[key]
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ require 'active_support/inflector'
2
+
3
+ module Shh
4
+ module Command
5
+ def load_command name, *args
6
+ require "shh/command/#{name}"
7
+ Command.const_get(name.to_s.camelize).new(*args)
8
+ end
9
+ end
10
+ end
data/lib/shh/crypt.rb CHANGED
@@ -1,25 +1,25 @@
1
- require 'crypt/blowfish'
2
-
3
- module Shh
4
- class Crypt
5
- def initialize passphrase
6
- @blowfish = ::Crypt::Blowfish.new(passphrase)
7
- end
8
-
9
- def encrypt text, out_io
10
- in_io = StringIO.new(text)
11
- while l = in_io.read(8) do
12
- while l.size < 8 do l += "\0" end
13
- out_io.print @blowfish.encrypt_block(l)
14
- end
15
- end
16
-
17
- def decrypt in_io
18
- out_io = StringIO.new
19
- while l = in_io.read(8) do
20
- out_io.print @blowfish.decrypt_block(l)
21
- end
22
- out_io.string.gsub("\0",'')
23
- end
24
- end
25
- end
1
+ require 'crypt/blowfish'
2
+
3
+ module Shh
4
+ class Crypt
5
+ def initialize passphrase
6
+ @blowfish = ::Crypt::Blowfish.new(passphrase)
7
+ end
8
+
9
+ def encrypt text, out_io
10
+ in_io = StringIO.new(text)
11
+ while l = in_io.read(8) do
12
+ while l.size < 8 do l += "\0" end
13
+ out_io.print @blowfish.encrypt_block(l)
14
+ end
15
+ end
16
+
17
+ def decrypt in_io
18
+ out_io = StringIO.new
19
+ while l = in_io.read(8) do
20
+ out_io.print @blowfish.decrypt_block(l)
21
+ end
22
+ out_io.string.gsub("\0",'')
23
+ end
24
+ end
25
+ end
@@ -1,64 +1,16 @@
1
- require 'uuidtools'
2
- require 'readline'
3
- require 'shh/entry_menu'
4
-
5
- module Shh
6
- class EntriesMenu
7
- def initialize prompt, repository
8
- @prompt, @repository = prompt, repository
9
- refresh
10
- end
11
-
12
- def main_loop
13
- prompt_text = 'shh > '
14
-
15
- begin
16
- while line = Readline.readline(prompt_text, true)
17
- line.strip!
18
- case line
19
- when 'quit'
20
- return
21
- when 'refresh'
22
- refresh
23
- when 'list'
24
- @entries.sort.each {|entry| say entry }
25
- when /^view (.*)/
26
- view $1
27
- when /^edit (.*)/
28
- edit $1
29
- end
30
- puts
31
- end
32
- rescue Interrupt => e
33
- exit
34
- end
35
- puts
36
- end
37
-
38
- def refresh
39
- commands = ['list', 'refresh', 'quit']
40
- @entries = []
41
- @repository.each_entry do |entry|
42
- @entries << "#{entry['name']} (#{entry['id']})"
43
- commands << "edit #{entry['name']}"
44
- commands << "view #{entry['name']}"
45
- end
46
- Readline.completion_proc = lambda do |text|
47
- commands.grep( /^#{Regexp.escape(text)}/ ).sort
48
- end
49
- Readline.completer_word_break_characters = ''
50
- end
51
-
52
- def edit name
53
- entry = @repository.find_entry(name)
54
- entry ||= {'name' => name, 'id' => UUIDTools::UUID.random_create.to_s}
55
- @repository.persist_entry EntryMenu.new(@prompt, entry).main_loop
56
- refresh
57
- end
58
-
59
- def view name
60
- EntryMenu.new(@prompt, @repository.find_entry(name), true).main_loop
61
- refresh
62
- end
63
- end
64
- end
1
+ require 'shell_shock/context'
2
+ require 'shh/commands'
3
+
4
+ class Shh::EntriesMenu
5
+ include Shh::Command
6
+ include ShellShock::Context
7
+
8
+ def initialize io, repository
9
+ @io, @repository = io, repository
10
+ @prompt_text = 'shh > '
11
+ @commands = {
12
+ 'ls' => load_command(:list_entries, @repository, @io),
13
+ 'cd' => load_command(:open_entry, @repository, @io)
14
+ }
15
+ end
16
+ end
@@ -1,141 +1,25 @@
1
- require 'splat'
2
-
3
- module Shh
4
- class EntryMenu
5
- def initialize prompt, hash, read_only=false
6
- @prompt, @hash, @read_only = prompt, hash, read_only
7
- @splat = Splat.new
8
- refresh
9
- end
10
-
11
- def main_loop
12
- prompt_text = "shh:#{@hash['name']} > "
13
-
14
- begin
15
- while line = Readline.readline(prompt_text, true)
16
- line.strip!
17
- case line
18
- when 'quit'
19
- return @hash
20
- when 'list'
21
- say(@hash.keys.sort.join(','))
22
- when /^set (.*)/
23
- set $1
24
- when /^edit (.*)/
25
- edit $1
26
- when /^copy (.*)/
27
- copy $1
28
- when /^launch (.*)/
29
- launch $1
30
- when /^delete (.*)/
31
- delete $1
32
- when /^view (.*)/
33
- view $1
34
- when /^run (.*)/
35
- run $1
36
- else
37
- puts "I can't imagine what you mean by that"
38
- end
39
- end
40
- rescue Interrupt => e
41
- exit
42
- end
43
-
44
- puts
45
- @hash
46
- end
47
-
48
- private
49
- def can_edit?
50
- !@read_only
51
- end
52
-
53
- def can_launch? key
54
- @splat.supported? and @hash[key] =~ /^http/
55
- end
56
-
57
- def can_run? key
58
- @splat.supported? and @hash[key] =~ /^#!\/usr\/bin\/env ruby/
59
- end
60
-
61
- def view key
62
- say(@hash[key]) if @hash[key]
63
- end
64
-
65
- def copy key
66
- @splat.clipboard = @hash[key]
67
- end
68
-
69
- def run key
70
- begin
71
- hash = @hash
72
- splat = @splat
73
- eval @hash[key]
74
- rescue Exception => e
75
- puts e.message
76
- e.backtrace.each {|t| puts " > #{t}" }
77
- end
78
- end
79
-
80
- def set key
81
- if can_edit?
82
- set_value key
83
- refresh
84
- end
85
- end
86
-
87
- def edit key
88
- if can_edit?
89
- edit_value key
90
- refresh
91
- end
92
- end
93
-
94
- def delete key
95
- if can_edit?
96
- @hash.delete(key)
97
- refresh
98
- end
99
- end
100
-
101
- def launch key
102
- @splat.launch @hash[key] if can_launch?(key)
103
- end
104
-
105
- def refresh
106
- commands = ['list', 'quit']
107
- @hash.keys.each do |key|
108
- commands << "edit #{key}" if can_edit?
109
- commands << "set #{key}" if can_edit?
110
- commands << "delete #{key}" if can_edit?
111
- commands << "view #{key}"
112
- commands << "copy #{key}" if @splat.supported?
113
- commands << "launch #{key}" if can_launch?(key)
114
- commands << "run #{key}" if can_run?(key)
115
- end
116
- Readline.completion_proc = lambda do |text|
117
- commands.grep( /^#{Regexp.escape(text)}/ ).sort
118
- end
119
- Readline.completer_word_break_characters = ''
120
- end
121
-
122
- def set_value key
123
- new_value = @prompt.get("Enter new value for #{key}", :silent => (key =~ /pass/))
124
- @hash[key] = new_value if new_value.length > 0
125
- end
126
-
127
- def edit_value key
128
- tmp_file = Pathname.new("key.tmp")
129
- begin
130
- tmp_file.open('w') { |out| out.print @hash[key] }
131
- editor = ENV["EDITOR"] || "notepad"
132
- system("#{editor} key.tmp")
133
- return unless $?.to_i == 0
134
- new_value = tmp_file.read
135
- @hash[key] = new_value if new_value.length > 0
136
- ensure
137
- tmp_file.unlink
138
- end
139
- end
140
- end
141
- end
1
+ require 'shell_shock/context'
2
+ require 'shh/commands'
3
+
4
+ class Shh::EntryMenu
5
+ include Shh::Command
6
+ include ShellShock::Context
7
+
8
+ def initialize io, entry
9
+ @io, @entry = io, entry
10
+ @commands = {
11
+ 'ls' => load_command(:list_keys, entry, io),
12
+ 'set' => load_command(:set_key, entry, io),
13
+ 'edit' => load_command(:edit_key, entry, io),
14
+ 'cat' => load_command(:show_key, entry, io),
15
+ 'cp' => load_command(:copy_key, entry, io),
16
+ 'launch' => load_command(:launch_key, entry, io),
17
+ 'rm' => load_command(:remove_key, entry, io),
18
+ 'exec' => load_command(:execute_key, entry, io)
19
+ }
20
+ end
21
+
22
+ def refresh_commands
23
+ @prompt_text = "shh:#{@entry['name']} > "
24
+ end
25
+ end
data/lib/shh/prompt.rb CHANGED
@@ -1,11 +1,14 @@
1
- require 'highline/import'
2
-
3
- module Shh
4
- class Prompt
5
- def get text, params={}
6
- return params[:value] if params[:value] and params[:value].size > 0
7
- echo = params[:silent] ? false : true
8
- ask(text) { |q| q.echo = echo }
9
- end
10
- end
11
- end
1
+ require 'highline/import'
2
+
3
+ module Shh
4
+ class Prompt
5
+ def ask text, params={}
6
+ echo = params[:silent] ? false : true
7
+ Kernel.ask(text) { |q| q.echo = echo }
8
+ end
9
+
10
+ def say text=''
11
+ puts text
12
+ end
13
+ end
14
+ end
@@ -1,39 +1,44 @@
1
- require 'yaml'
2
- require 'shh/crypt'
3
- require 'fileutils'
4
-
5
- module Shh
6
- class Repository
7
- attr_reader :folder
8
-
9
- def initialize passphrase, path
10
- @folder = Pathname.new(File.expand_path(path)) + '.secret'
11
- FileUtils.mkdir_p @folder.to_s
12
- @crypt = Crypt.new(passphrase)
13
- end
14
-
15
- def each_entry
16
- @folder.children.each do |child|
17
- entry = load_entry(child)
18
- yield entry if entry
19
- end
20
- end
21
-
22
- def find_entry name
23
- each_entry {|e| return e if e['name'] == name}
24
- nil
25
- end
26
-
27
- def load_entry path
28
- return nil if path.directory?
29
- yaml = path.open('rb') {|io| @crypt.decrypt(io) }
30
- entry = YAML::load(yaml)
31
- return nil unless entry
32
- path.basename.to_s == entry['id'] ? entry : nil
33
- end
34
-
35
- def persist_entry entry
36
- (@folder + entry['id']).open('wb') {|io| @crypt.encrypt(entry.to_yaml, io) }
37
- end
38
- end
39
- end
1
+ require 'yaml'
2
+ require 'shh/crypt'
3
+ require 'fileutils'
4
+
5
+ module Shh
6
+ class Repository
7
+ include Enumerable
8
+
9
+ attr_reader :folder
10
+
11
+ def initialize passphrase, path
12
+ @folder = Pathname.new(File.expand_path(path)) + '.secret'
13
+ @folder.mkpath
14
+ @crypt = Crypt.new(passphrase)
15
+ end
16
+
17
+ def each
18
+ @folder.children.each do |child|
19
+ entry = load(child)
20
+ yield entry if entry
21
+ end
22
+ end
23
+
24
+ def find_by_name name
25
+ each {|e| return e if e['name'] == name}
26
+ nil
27
+ end
28
+
29
+ def load path
30
+ return nil if path.directory?
31
+ yaml = path.open('rb') {|io| @crypt.decrypt(io) }
32
+ entry = YAML::load(yaml)
33
+ unless entry and path.basename.to_s == entry['id']
34
+ $stderr.puts "failed to deserialise #{path}"
35
+ return nil
36
+ end
37
+ entry
38
+ end
39
+
40
+ def persist entry
41
+ (@folder + entry['id']).open('wb') {|io| @crypt.encrypt(entry.to_yaml, io) }
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 6
9
- version: 0.1.6
8
+ - 7
9
+ version: 0.1.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Mark Ryall
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-07 00:00:00 +10:00
17
+ date: 2010-06-15 00:00:00 +10:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -27,8 +27,8 @@ dependencies:
27
27
  segments:
28
28
  - 1
29
29
  - 5
30
- - 1
31
- version: 1.5.1
30
+ - 2
31
+ version: 1.5.2
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
@@ -68,11 +68,67 @@ dependencies:
68
68
  - !ruby/object:Gem::Version
69
69
  segments:
70
70
  - 0
71
+ - 1
71
72
  - 0
72
- - 2
73
- version: 0.0.2
73
+ version: 0.1.0
74
74
  type: :runtime
75
75
  version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: shell_shock
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
85
+ - 0
86
+ - 3
87
+ version: 0.0.3
88
+ type: :runtime
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ name: rake
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ~>
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ - 8
100
+ - 7
101
+ version: 0.8.7
102
+ type: :development
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
105
+ name: gemesis
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ segments:
112
+ - 0
113
+ - 0
114
+ - 3
115
+ version: 0.0.3
116
+ type: :development
117
+ version_requirements: *id007
118
+ - !ruby/object:Gem::Dependency
119
+ name: orangutan
120
+ prerelease: false
121
+ requirement: &id008 !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ segments:
126
+ - 0
127
+ - 0
128
+ - 7
129
+ version: 0.0.7
130
+ type: :development
131
+ version_requirements: *id008
76
132
  description: |
77
133
  A command line utility that manages accounts and passwords as individual encypted files
78
134
 
@@ -85,6 +141,18 @@ extra_rdoc_files: []
85
141
 
86
142
  files:
87
143
  - lib/shh/cli.rb
144
+ - lib/shh/command/copy_key.rb
145
+ - lib/shh/command/edit_key.rb
146
+ - lib/shh/command/execute_key.rb
147
+ - lib/shh/command/key_command.rb
148
+ - lib/shh/command/launch_key.rb
149
+ - lib/shh/command/list_entries.rb
150
+ - lib/shh/command/list_keys.rb
151
+ - lib/shh/command/open_entry.rb
152
+ - lib/shh/command/remove_key.rb
153
+ - lib/shh/command/set_key.rb
154
+ - lib/shh/command/show_key.rb
155
+ - lib/shh/commands.rb
88
156
  - lib/shh/crypt.rb
89
157
  - lib/shh/entries_menu.rb
90
158
  - lib/shh/entry_menu.rb