s7 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +311 -0
- data/LICENCE +24 -0
- data/README +56 -0
- data/Rakefile +128 -0
- data/VERSION +1 -0
- data/bin/s7cli +27 -0
- data/lib/gettext.rb +28 -0
- data/lib/s7.rb +12 -0
- data/lib/s7/action.rb +7 -0
- data/lib/s7/attribute.rb +226 -0
- data/lib/s7/cipher.rb +110 -0
- data/lib/s7/configuration.rb +41 -0
- data/lib/s7/entry.rb +106 -0
- data/lib/s7/entry_collection.rb +44 -0
- data/lib/s7/entry_template.rb +10 -0
- data/lib/s7/exception.rb +116 -0
- data/lib/s7/file.rb +77 -0
- data/lib/s7/gpass_file.rb +202 -0
- data/lib/s7/key.rb +83 -0
- data/lib/s7/message_catalog.rb +5 -0
- data/lib/s7/s7_file.rb +47 -0
- data/lib/s7/s7cli.rb +213 -0
- data/lib/s7/s7cli/attribute_command.rb +69 -0
- data/lib/s7/s7cli/command.rb +210 -0
- data/lib/s7/s7cli/entry_collection_command.rb +63 -0
- data/lib/s7/s7cli/entry_command.rb +728 -0
- data/lib/s7/s7cli/option.rb +101 -0
- data/lib/s7/secret_generator.rb +30 -0
- data/lib/s7/undo_stack.rb +7 -0
- data/lib/s7/unicode_data.rb +29 -0
- data/lib/s7/utils.rb +37 -0
- data/lib/s7/world.rb +150 -0
- data/setup.rb +1585 -0
- data/test/s7/attribute_test.rb +45 -0
- data/test/s7/gpass_file_test.rb +169 -0
- data/test/s7/gpass_file_test/passwords.gps.empty +1 -0
- data/test/s7/gpass_file_test/passwords.gps.one_entry +2 -0
- data/test/s7/gpass_file_test/passwords.gps.three_entries +3 -0
- data/test/s7/gpass_file_test/passwords.gps.with_folders +0 -0
- data/test/s7/secret_generator_test.rb +29 -0
- data/test/s7/unicode_data_test.rb +28 -0
- data/test/s7/world_test.rb +35 -0
- data/test/test_helper.rb +19 -0
- metadata +108 -0
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/s7cli
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/ruby1.9
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# Ruby 1.9 で Ruby-GetText-Package を使用するのはまだ時間がかかるようだ。
|
5
|
+
# そのため、LANG=C にして様子を見る。
|
6
|
+
ENV["LANG"] = "C"
|
7
|
+
|
8
|
+
$:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
|
9
|
+
|
10
|
+
require "gettext"
|
11
|
+
|
12
|
+
require "s7"
|
13
|
+
require "s7/s7cli"
|
14
|
+
|
15
|
+
path = File.expand_path("../data/locale/", File.dirname(__FILE__))
|
16
|
+
GetText.bindtextdomain("s7", :path => path)
|
17
|
+
begin
|
18
|
+
S7::S7Cli.run(ARGV)
|
19
|
+
rescue S7::ApplicationError => e
|
20
|
+
puts(e.message)
|
21
|
+
puts("----- back trace -----")
|
22
|
+
raise e
|
23
|
+
end
|
24
|
+
|
25
|
+
# Local Variables:
|
26
|
+
# mode: ruby
|
27
|
+
# End:
|
data/lib/gettext.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# gettext のモック
|
4
|
+
module GetText
|
5
|
+
def self.included(mod)
|
6
|
+
class << mod
|
7
|
+
def _(s)
|
8
|
+
return s
|
9
|
+
end
|
10
|
+
|
11
|
+
def N_(s)
|
12
|
+
return s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def _(s)
|
18
|
+
return s
|
19
|
+
end
|
20
|
+
|
21
|
+
def N_(s)
|
22
|
+
return s
|
23
|
+
end
|
24
|
+
|
25
|
+
def bindtextdomain(*args)
|
26
|
+
end
|
27
|
+
module_function :bindtextdomain
|
28
|
+
end
|
data/lib/s7.rb
ADDED
data/lib/s7/action.rb
ADDED
data/lib/s7/attribute.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require "gettext"
|
5
|
+
|
6
|
+
module S7
|
7
|
+
# 属性を表現する。
|
8
|
+
class Attribute
|
9
|
+
include GetText
|
10
|
+
|
11
|
+
# サポートしている属性のクラス。
|
12
|
+
@@attribute_classes = {}
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def create_instance(type, options)
|
16
|
+
return @@attribute_classes[type].new(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# 属性の型名の配列を返す。
|
20
|
+
def types
|
21
|
+
return @@attribute_classes.keys
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def type(name)
|
27
|
+
@@attribute_classes[name] = self
|
28
|
+
self.const_set("TYPE", name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# 名前。
|
33
|
+
attr_accessor :name
|
34
|
+
|
35
|
+
# 機密情報かどうか。true であれば機密情報、false であればそうでない。
|
36
|
+
attr_accessor :secret
|
37
|
+
|
38
|
+
# 値を編集できるかどうか。true であれば編集でき、false であれ
|
39
|
+
# ばそうでない。
|
40
|
+
attr_accessor :editabled
|
41
|
+
|
42
|
+
# 削除できるかどうか。true であれば削除できず、false であれ
|
43
|
+
# ばそうでない。
|
44
|
+
attr_accessor :protected
|
45
|
+
|
46
|
+
def initialize(options)
|
47
|
+
self.name = options["name"]
|
48
|
+
self.value = options["value"]
|
49
|
+
self.secret = options["secret"] ? true : false
|
50
|
+
if options.key?("editabled")
|
51
|
+
self.editabled = options["editabled"] ? true : false
|
52
|
+
else
|
53
|
+
self.editabled = true
|
54
|
+
end
|
55
|
+
self.protected = options["protected"] ? true : false
|
56
|
+
end
|
57
|
+
|
58
|
+
# value を取得する。
|
59
|
+
def value
|
60
|
+
if @value.nil?
|
61
|
+
return nil
|
62
|
+
else
|
63
|
+
return get_value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# value を設定する。
|
68
|
+
def value=(val)
|
69
|
+
if val.nil?
|
70
|
+
@value = val
|
71
|
+
else
|
72
|
+
set_value(val)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# 属性の型を取得する。
|
77
|
+
def type
|
78
|
+
return self.class.const_get("TYPE")
|
79
|
+
end
|
80
|
+
|
81
|
+
# 機密情報かどうかを取得する。
|
82
|
+
# 機密情報の場合、true を返す。そうでなれば false を返す。
|
83
|
+
def secret?
|
84
|
+
return secret ? true : false
|
85
|
+
end
|
86
|
+
|
87
|
+
# ユーザによる値の編集ができるかどうかを取得する。
|
88
|
+
# 編集できる場合、true を返す。そうでなければ true を返す。
|
89
|
+
def editable?
|
90
|
+
return editabled ? true : false
|
91
|
+
end
|
92
|
+
|
93
|
+
# ユーザによる削除ができるかどうかを取得する。
|
94
|
+
# 削除できる場合、true を返す。そうでなければ true を返す。
|
95
|
+
def protected?
|
96
|
+
return protected ? true : false
|
97
|
+
end
|
98
|
+
|
99
|
+
# value を表示するために文字列に変換する。
|
100
|
+
# このとき、 secret が true であれば「*」でマスクする。
|
101
|
+
def display_value(secret = @secret)
|
102
|
+
if secret
|
103
|
+
return "*" * value.to_s.length
|
104
|
+
else
|
105
|
+
return value.to_s
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def get_value
|
112
|
+
return @value
|
113
|
+
end
|
114
|
+
|
115
|
+
def set_value(val)
|
116
|
+
@value = val
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# 文字列の属性を表現する。
|
121
|
+
class TextAttribute < Attribute
|
122
|
+
type("text")
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def get_value
|
127
|
+
return @value.to_s.force_encoding("utf-8")
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_value(val)
|
131
|
+
@value = val.to_s.force_encoding("utf-8")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# 数値の属性を表現する。
|
136
|
+
class NumericAttribute < Attribute
|
137
|
+
type("numeric")
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def get_value
|
142
|
+
return @value.to_i
|
143
|
+
end
|
144
|
+
|
145
|
+
def set_value(val)
|
146
|
+
@value = val.to_i
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# 真偽値の属性を表現する。
|
151
|
+
class BooleanAttribute < Attribute
|
152
|
+
type("boolean")
|
153
|
+
|
154
|
+
# value を表示するために文字列に変換する。
|
155
|
+
# secret が true であれば「*」を返す。
|
156
|
+
# そうでなければ、Yes か No を返す。
|
157
|
+
def display_value(secret = @secret)
|
158
|
+
if secret
|
159
|
+
return "*"
|
160
|
+
else
|
161
|
+
return value ? _("Yes") : _("No")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def get_value
|
168
|
+
return @value ? true : false
|
169
|
+
end
|
170
|
+
|
171
|
+
def set_value(val)
|
172
|
+
@value = val ? true : false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# 日時の属性を表現する。
|
177
|
+
class DateTimeAttribute < Attribute
|
178
|
+
type("datetime")
|
179
|
+
|
180
|
+
# value を表示するために文字列に変換する。
|
181
|
+
# secret が true であれば「*」を返す。
|
182
|
+
# そうでなければ、「%Y/%m/%d %H:%M:%S」でフォーマットした文字列を返す。
|
183
|
+
# また、時分秒が全て0の場合は「%Y/%m/%d」でフォーマットする。
|
184
|
+
def display_value(secret = @secret)
|
185
|
+
if secret
|
186
|
+
return "*"
|
187
|
+
else
|
188
|
+
format = "%Y/%m/%d"
|
189
|
+
if value.hour != 0 || value.min != 0 || value.sec != 0
|
190
|
+
format << " %H:%M:%S"
|
191
|
+
end
|
192
|
+
return value.strftime(format)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def get_value
|
199
|
+
return @value.to_datetime
|
200
|
+
end
|
201
|
+
|
202
|
+
def set_value(val)
|
203
|
+
case val
|
204
|
+
when Time, DateTime, Date
|
205
|
+
@value = val.to_datetime
|
206
|
+
else
|
207
|
+
@value = DateTime.parse(val.to_s)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# ファイルの属性を表現する。
|
213
|
+
class FileAttribute < Attribute
|
214
|
+
type("file")
|
215
|
+
end
|
216
|
+
|
217
|
+
# 画像の属性を表現する。
|
218
|
+
class FigureAttribute < FileAttribute
|
219
|
+
type("figure")
|
220
|
+
end
|
221
|
+
|
222
|
+
# 不明な属性を表現する。
|
223
|
+
class UnknownAttribute < Attribute
|
224
|
+
type("unknown")
|
225
|
+
end
|
226
|
+
end
|
data/lib/s7/cipher.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require "openssl"
|
4
|
+
|
5
|
+
module S7
|
6
|
+
# 秘密鍵暗号化方式を用いた暗号化処理を表現する。
|
7
|
+
class Cipher
|
8
|
+
@@cipher_classes = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def create_instance(type, options)
|
12
|
+
return @@cipher_classes[type].new(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def cipher_type(name)
|
18
|
+
if @@cipher_classes.nil?
|
19
|
+
@@cipher_classes = {}
|
20
|
+
end
|
21
|
+
@@cipher_classes[name] = self
|
22
|
+
self.const_set("CIPHER_TYPE", name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_accessor :options
|
27
|
+
|
28
|
+
def initialize(options)
|
29
|
+
self.options = options
|
30
|
+
end
|
31
|
+
|
32
|
+
# io で指定した IO からデータを読み込み、復号する。
|
33
|
+
def decrypt(io)
|
34
|
+
begin
|
35
|
+
cipher = create_cipher
|
36
|
+
cipher.decrypt
|
37
|
+
parse_options(cipher, options)
|
38
|
+
s = ""
|
39
|
+
while d = io.read(cipher.block_size)
|
40
|
+
s << cipher.update(d)
|
41
|
+
end
|
42
|
+
s << cipher.final
|
43
|
+
rescue OpenSSL::Cipher::CipherError
|
44
|
+
raise InvalidPassphrase
|
45
|
+
end
|
46
|
+
return s
|
47
|
+
end
|
48
|
+
|
49
|
+
# io で指定した IO からデータを読み込み、暗号化する。
|
50
|
+
def encrypt(io)
|
51
|
+
cipher = create_cipher
|
52
|
+
cipher.encrypt
|
53
|
+
parse_options(cipher, options)
|
54
|
+
s = ""
|
55
|
+
while d = io.read(cipher.block_size)
|
56
|
+
s << cipher.update(d)
|
57
|
+
end
|
58
|
+
s << cipher.final
|
59
|
+
return s
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def create_cipher
|
65
|
+
cipher_type = self.class.const_get("CIPHER_TYPE")
|
66
|
+
return OpenSSL::Cipher::Cipher.new(cipher_type)
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_options(cipher, options)
|
70
|
+
if options.key?(:passphrase)
|
71
|
+
cipher.pkcs5_keyivgen(options[:passphrase])
|
72
|
+
elsif options.key?(:key)
|
73
|
+
cipher.key_len = options[:key].length
|
74
|
+
cipher.key = options[:key].key
|
75
|
+
if options.key?(:iv)
|
76
|
+
cipher.iv = options[:iv]
|
77
|
+
end
|
78
|
+
else
|
79
|
+
raise ArgumentError, "too few options: :passphrase or :key"
|
80
|
+
end
|
81
|
+
if options.key?(:padding)
|
82
|
+
cipher.padding = options[:padding]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# 秘密鍵方式の一つ AES を用いて暗号化処理を行うクラスを表現する。
|
88
|
+
class Aes256CbcCipher < Cipher
|
89
|
+
cipher_type "AES-256-CBC"
|
90
|
+
end
|
91
|
+
|
92
|
+
# 秘密鍵方式の一つ Blowfish を用いて暗号化処理を行うクラスを表現する。
|
93
|
+
class BfCbcCipher < Cipher
|
94
|
+
cipher_type "BF-CBC"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Cipher クラスと同じインタフェースを持つが、暗号化しないクラスを表現
|
98
|
+
# する。
|
99
|
+
class PlainCipher < Cipher
|
100
|
+
cipher_type "plain"
|
101
|
+
|
102
|
+
def encrypt(io)
|
103
|
+
return io.read
|
104
|
+
end
|
105
|
+
|
106
|
+
def decrypt(io)
|
107
|
+
return io.read
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
module S7
|
6
|
+
# 設定を表現する。
|
7
|
+
class Configuration
|
8
|
+
# デフォルトの秘密鍵暗号方式。
|
9
|
+
DEFAULT_CIPHER_TYPE = "AES-256-CBC"
|
10
|
+
|
11
|
+
# World オブジェクト。
|
12
|
+
attr_accessor :world
|
13
|
+
|
14
|
+
# 秘密鍵暗号方式。
|
15
|
+
attr_accessor :cipher_type
|
16
|
+
|
17
|
+
def initialize(world)
|
18
|
+
@world = world
|
19
|
+
@cipher_type = DEFAULT_CIPHER_TYPE
|
20
|
+
end
|
21
|
+
|
22
|
+
# 設定をファイルに書き出す。
|
23
|
+
def save(path)
|
24
|
+
hash = {
|
25
|
+
"cipher_type" => @cipher_type,
|
26
|
+
}
|
27
|
+
FileUtils.touch(path)
|
28
|
+
File.open(path, "wb") do |f|
|
29
|
+
f.write(hash.to_yaml)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# 設定をファイルから読み込む。
|
34
|
+
def load(path)
|
35
|
+
File.open(path, "rb") do |f|
|
36
|
+
hash = YAML.load(f.read)
|
37
|
+
@cipher_type = hash["cipher_type"]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|