gtk2passwordapp 5.2.1 → 6.0.210202
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.
- checksums.yaml +5 -5
- data/README.md +107 -0
- data/bin/gtk2passwordapp +19 -0
- data/lib/gtk2passwordapp.rb +50 -14
- data/lib/gtk2passwordapp/account.rb +5 -5
- data/lib/gtk2passwordapp/accounts.rb +6 -4
- data/lib/gtk2passwordapp/cli.rb +35 -0
- data/lib/gtk2passwordapp/config.rb +197 -135
- data/lib/gtk2passwordapp/gui.rb +314 -0
- metadata +33 -50
- data/README.rdoc +0 -64
- data/bin/gtk2pwdV +0 -68
- data/data/VERSION +0 -1
- data/lib/gtk2passwordapp/gtk2pwdv.rb +0 -449
- data/lib/gtk2passwordapp/such_parts.rb +0 -22
@@ -0,0 +1,314 @@
|
|
1
|
+
class Gtk2PasswordApp
|
2
|
+
def initialize(stage, toolbar, options)
|
3
|
+
@primary = Gtk::Clipboard.get(Gdk::Selection::PRIMARY)
|
4
|
+
@clipboard = Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
|
5
|
+
@accounts = Accounts.new(CONFIG[:PwdFile])
|
6
|
+
@toolbox = Such::Box.new toolbar, :toolbox!
|
7
|
+
@pages = Such::Box.new stage, :pages!
|
8
|
+
@recent = []
|
9
|
+
@reset = false
|
10
|
+
@red,@green,@blue = [:Red,:Green,:Blue].map{Gdk::RGBA.parse(CONFIG[_1])}
|
11
|
+
@tools = @password_page = @add_page = @edit_page = @main_page = @menu = nil
|
12
|
+
build_password_page
|
13
|
+
build_logo_menu
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_logo_menu
|
17
|
+
Gtk3App.logo_press_event do |button|
|
18
|
+
next unless @main_page&.visible?
|
19
|
+
case button
|
20
|
+
when 1
|
21
|
+
popup_accounts_menu unless @accounts.data.empty?
|
22
|
+
when 2
|
23
|
+
reset_password
|
24
|
+
when 3
|
25
|
+
# Gets captured by Gtk3App's main menu
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset_password
|
31
|
+
ursure = Gtk3App::YesNoDialog.new :reset_ursure!
|
32
|
+
Gtk3App.transient ursure
|
33
|
+
if ursure.ok?
|
34
|
+
@reset = true
|
35
|
+
hide_main_page
|
36
|
+
@password_page.show
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def popup_accounts_menu
|
41
|
+
@menu = Such::Menu.new :main_menu!
|
42
|
+
@recent.each do |name| add_menu_item(name, @green) end
|
43
|
+
@accounts.data.keys.sort{|a,b|a.upcase<=>b.upcase}.each do |name| add_menu_item(name) end
|
44
|
+
@menu.show_all
|
45
|
+
@menu.popup_at_pointer
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_menu_item(name, color=nil)
|
49
|
+
menu_item = Such::MenuItem.new [label:name], :main_menu_item, 'activate' do selected_account(name) end
|
50
|
+
account = @accounts.get name
|
51
|
+
color = (Time.now.to_i - account.updated > CONFIG[:TooOld])? @red : @blue unless color
|
52
|
+
menu_item.override_color :normal, color
|
53
|
+
@menu.append menu_item
|
54
|
+
end
|
55
|
+
|
56
|
+
def selected_account(name)
|
57
|
+
@recent.unshift name; @recent.uniq!; @recent.pop if @recent.length>3
|
58
|
+
account = @accounts.get name
|
59
|
+
setup_main_page account
|
60
|
+
setup_edit_page account
|
61
|
+
copy2clipboard(account.password, account.username)
|
62
|
+
end
|
63
|
+
|
64
|
+
def copy2clipboard(pwd, user)
|
65
|
+
@primary.text, @clipboard.text = pwd, user
|
66
|
+
GLib::Timeout.add_seconds(CONFIG[:ClipboardTimeout]) do
|
67
|
+
@primary.text = '' if @primary.wait_for_text == pwd
|
68
|
+
@clipboard.text = '' if @clipboard.wait_for_text == user
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def view_row(page, label)
|
74
|
+
row = Such::Box.new page, :field_row!
|
75
|
+
Such::Label.new(row, label, :field_label)
|
76
|
+
Such::Label.new(row, :field_view!)
|
77
|
+
end
|
78
|
+
|
79
|
+
def field_row(page, label, entry=:field_entry!, &block)
|
80
|
+
row = Such::Box.new page, :field_row!
|
81
|
+
Such::Label.new(row, label, :field_label)
|
82
|
+
Such::Entry.new(row, entry, ((block)? 'activate' : ''), &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def show_main_page
|
86
|
+
@main_page.show_all
|
87
|
+
@toolbox.show_all
|
88
|
+
end
|
89
|
+
|
90
|
+
def hide_main_page
|
91
|
+
@main_page.hide
|
92
|
+
@toolbox.hide
|
93
|
+
end
|
94
|
+
|
95
|
+
def bootstrap_setups
|
96
|
+
names = @accounts.data.keys
|
97
|
+
account = (names.empty?)? nil : @accounts.get(names[rand(names.length)])
|
98
|
+
setup_edit_page(account) if account
|
99
|
+
setup_main_page(account)
|
100
|
+
end
|
101
|
+
|
102
|
+
def rehash(pwd)
|
103
|
+
pwd += CONFIG[:Salt] if pwd.length < CONFIG[:LongPwd]
|
104
|
+
pwd = Digest::SHA256.hexdigest(pwd).upcase
|
105
|
+
H2Q.convert pwd
|
106
|
+
end
|
107
|
+
|
108
|
+
def build_password_page
|
109
|
+
@password_page = Such::Box.new @pages, :page!
|
110
|
+
Such::Label.new @password_page, :PASSWORD_PAGE_LABEL, :page_label
|
111
|
+
error_label,previous = nil,'' # updates below
|
112
|
+
password_entry = field_row(@password_page, :PASSWORD, :password_entry!) do
|
113
|
+
pwd = password_entry.text.strip
|
114
|
+
password_entry.text = ''
|
115
|
+
raise CONFIG[:TooShort] if pwd.length < CONFIG[:MinPwdLen]
|
116
|
+
if not @reset and @accounts.exist?
|
117
|
+
@accounts.load rehash pwd
|
118
|
+
else
|
119
|
+
raise CONFIG[:Confirm] unless pwd==previous
|
120
|
+
@accounts.save rehash pwd
|
121
|
+
@reset = false
|
122
|
+
end
|
123
|
+
@password_page.hide
|
124
|
+
build_add_page unless @add_page
|
125
|
+
build_edit_page unless @edit_page
|
126
|
+
build_main_page unless @main_page
|
127
|
+
build_tools unless @tools
|
128
|
+
bootstrap_setups
|
129
|
+
show_main_page
|
130
|
+
rescue
|
131
|
+
error_label.text = $!.message
|
132
|
+
previous = pwd
|
133
|
+
end
|
134
|
+
error_label = Such::Label.new @password_page, :error_label!
|
135
|
+
end
|
136
|
+
|
137
|
+
def build_add_page
|
138
|
+
@add_page = Such::Box.new @pages, :page!
|
139
|
+
Such::Label.new @add_page, :ADD_PAGE_LABEL, :page_label
|
140
|
+
error_label = nil # updates below
|
141
|
+
add_account_entry = field_row(@add_page, :NAME) do
|
142
|
+
name = add_account_entry.text.strip
|
143
|
+
@accounts.add name
|
144
|
+
@accounts.save
|
145
|
+
account = @accounts.get name
|
146
|
+
setup_edit_page(account)
|
147
|
+
setup_main_page(account)
|
148
|
+
@add_page.hide
|
149
|
+
add_account_entry.text = ''
|
150
|
+
@edit_page.show_all
|
151
|
+
rescue
|
152
|
+
error_label.text = $!.message
|
153
|
+
end
|
154
|
+
Such::Button.new @add_page, :CANCEL, :tool_button do
|
155
|
+
@add_page.hide
|
156
|
+
add_account_entry.text = ''
|
157
|
+
show_main_page
|
158
|
+
end
|
159
|
+
error_label = Such::Label.new @add_page, :error_label!
|
160
|
+
end
|
161
|
+
|
162
|
+
def visibility_toggleling(entry)
|
163
|
+
entry.signal_connect('enter-notify-event') do
|
164
|
+
entry.set_visibility true unless entry.has_focus?
|
165
|
+
end
|
166
|
+
entry.signal_connect('leave-notify-event') do
|
167
|
+
entry.set_visibility false unless entry.has_focus?
|
168
|
+
end
|
169
|
+
entry.signal_connect('focus-in-event') do
|
170
|
+
entry.set_visibility true
|
171
|
+
end
|
172
|
+
entry.signal_connect('focus-out-event') do
|
173
|
+
entry.set_visibility false
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def show_toggleling(label)
|
178
|
+
label.signal_connect('button-press-event') do |_,e|
|
179
|
+
if e.button==1 and not (pwd=label.text).empty?
|
180
|
+
case pwd
|
181
|
+
when CONFIG[:HiddenPwd]
|
182
|
+
label.text = @accounts.get(@name.text).password
|
183
|
+
when TOTPx
|
184
|
+
label.text = TOTP.passwords(label.text)[1].to_s
|
185
|
+
else
|
186
|
+
label.text = CONFIG[:HiddenPwd]
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def build_edit_page
|
193
|
+
@edit_page = Such::Box.new @pages, :page!
|
194
|
+
Such::Label.new @edit_page, :EDIT_PAGE_LABEL, :page_label
|
195
|
+
|
196
|
+
@edit_name = view_row @edit_page, :NAME
|
197
|
+
@edit_url = field_row @edit_page, :URL
|
198
|
+
@edit_note = field_row @edit_page, :NOTE
|
199
|
+
@edit_username = field_row @edit_page, :USERNAME
|
200
|
+
@edit_password = field_row @edit_page, :PASSWORD, :password_entry!
|
201
|
+
|
202
|
+
visibility_toggleling @edit_password
|
203
|
+
|
204
|
+
generator = Such::Box.new @edit_page, :toolbox!
|
205
|
+
pwdlen=rndpwd=nil
|
206
|
+
Such::Button.new generator, :RAND, :tool_button do
|
207
|
+
rndpwd = H2Q.convert RND.hexadecimal
|
208
|
+
@edit_password.text = rndpwd[0...pwdlen.value]
|
209
|
+
end
|
210
|
+
pwdlen = Such::SpinButton.new generator, :pwdlen!, 'value-changed' do
|
211
|
+
@edit_password.text = rndpwd[0...pwdlen.value] if rndpwd
|
212
|
+
end
|
213
|
+
|
214
|
+
toolbox = Such::Box.new @edit_page, :toolbox!
|
215
|
+
error_label = Such::Label.new @edit_page, :error_label!
|
216
|
+
|
217
|
+
Such::Button.new toolbox, :SAVE, :tool_button do
|
218
|
+
account = @accounts.get @edit_name.text.strip
|
219
|
+
account.url = @edit_url.text.strip
|
220
|
+
account.note = @edit_note.text.strip
|
221
|
+
account.username = @edit_username.text.strip
|
222
|
+
account.password = @edit_password.text.strip
|
223
|
+
@accounts.save
|
224
|
+
rndpwd = nil
|
225
|
+
@edit_page.hide
|
226
|
+
setup_main_page(account)
|
227
|
+
show_main_page
|
228
|
+
rescue
|
229
|
+
error_label.text = $!.message
|
230
|
+
end
|
231
|
+
Such::Button.new toolbox, :CANCEL, :tool_button do
|
232
|
+
account = @accounts.get @edit_name.text
|
233
|
+
rndpwd = nil
|
234
|
+
@edit_page.hide
|
235
|
+
setup_edit_page(account) # restore values
|
236
|
+
show_main_page
|
237
|
+
end
|
238
|
+
Such::Button.new toolbox, :DELETE, :tool_button do
|
239
|
+
ursure = Gtk3App::YesNoDialog.new :delete_ursure!
|
240
|
+
Gtk3App.transient ursure
|
241
|
+
if ursure.ok?
|
242
|
+
@accounts.delete @edit_name.text
|
243
|
+
@accounts.save
|
244
|
+
rndpwd = nil
|
245
|
+
@edit_page.hide
|
246
|
+
bootstrap_setups
|
247
|
+
show_main_page
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def setup_edit_page(account)
|
253
|
+
@edit_name.text = account.name
|
254
|
+
@edit_url.text = account.url
|
255
|
+
@edit_note.text = account.note
|
256
|
+
@edit_username.text = account.username
|
257
|
+
@edit_password.text = account.password
|
258
|
+
end
|
259
|
+
|
260
|
+
def build_main_page
|
261
|
+
@main_page = Such::Box.new @pages, :page!
|
262
|
+
Such::Label.new @main_page, :MAIN_PAGE_LABEL, :page_label
|
263
|
+
|
264
|
+
@name = view_row @main_page, :NAME
|
265
|
+
@url = view_row @main_page, :URL
|
266
|
+
@note = view_row @main_page, :NOTE
|
267
|
+
@username = view_row @main_page, :USERNAME
|
268
|
+
@password = view_row @main_page, :PASSWORD
|
269
|
+
|
270
|
+
show_toggleling @password
|
271
|
+
end
|
272
|
+
|
273
|
+
def setup_main_page(account)
|
274
|
+
@name.text = account&.name || ''
|
275
|
+
@url.text = account&.url || ''
|
276
|
+
@note.text = account&.note || ''
|
277
|
+
@username.text = account&.username || ''
|
278
|
+
@password.text =(account&.password&.>'')? CONFIG[:HiddenPwd] : ''
|
279
|
+
end
|
280
|
+
|
281
|
+
def build_tools
|
282
|
+
@tools = true
|
283
|
+
Such::Button.new @toolbox, :ADD, :tool_button do
|
284
|
+
hide_main_page
|
285
|
+
@add_page.show_all
|
286
|
+
end
|
287
|
+
Such::Button.new @toolbox, :EDIT, :tool_button do
|
288
|
+
unless (name=@name.text).empty?
|
289
|
+
hide_main_page
|
290
|
+
@edit_page.show_all
|
291
|
+
end
|
292
|
+
end
|
293
|
+
Such::Button.new @toolbox, :GO, :tool_button do
|
294
|
+
unless (name=@name.text).empty?
|
295
|
+
url = @accounts.get(name).url
|
296
|
+
system(Gtk3App::CONFIG[:Open], url) unless url.empty?
|
297
|
+
end
|
298
|
+
end
|
299
|
+
Such::Button.new @toolbox, :CURRENT, :tool_button do
|
300
|
+
unless (name=@name.text).empty?
|
301
|
+
account = @accounts.get name
|
302
|
+
copy2clipboard(account.password, account.username)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
Such::Button.new @toolbox, :PREVIOUS, :tool_button do
|
306
|
+
unless (name=@name.text).empty?
|
307
|
+
account = @accounts.get name
|
308
|
+
copy2clipboard(account.previous, account.password)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def self.run = Gtk3App.run(klass:Gtk2PasswordApp)
|
314
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gtk2passwordapp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.210202
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- carlosjhr64
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yaml_zlib_blowfish
|
@@ -16,87 +16,78 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 2.0.210127
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '2.0'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
32
|
+
version: 2.0.210127
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: base_convert
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
39
|
+
version: '6.0'
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
42
|
+
version: 6.0.210201
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: '
|
49
|
+
version: '6.0'
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
52
|
+
version: 6.0.210201
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
name: gtk3app
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
57
|
- - "~>"
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: '
|
59
|
+
version: '5.0'
|
60
60
|
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
62
|
+
version: 5.0.210201
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '5.0'
|
70
70
|
- - ">="
|
71
71
|
- !ruby/object:Gem::Version
|
72
|
-
version:
|
72
|
+
version: 5.0.210201
|
73
73
|
- !ruby/object:Gem::Dependency
|
74
74
|
name: base32
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
76
76
|
requirements:
|
77
|
-
- - "~>"
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: '0.3'
|
80
77
|
- - '='
|
81
78
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.3.
|
79
|
+
version: 0.3.4
|
83
80
|
type: :runtime
|
84
81
|
prerelease: false
|
85
82
|
version_requirements: !ruby/object:Gem::Requirement
|
86
83
|
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0.3'
|
90
84
|
- - '='
|
91
85
|
- !ruby/object:Gem::Version
|
92
|
-
version: 0.3.
|
86
|
+
version: 0.3.4
|
93
87
|
- !ruby/object:Gem::Dependency
|
94
88
|
name: totp
|
95
89
|
requirement: !ruby/object:Gem::Requirement
|
96
90
|
requirements:
|
97
|
-
- - "~>"
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version: '1.0'
|
100
91
|
- - '='
|
101
92
|
- !ruby/object:Gem::Version
|
102
93
|
version: 1.0.0
|
@@ -104,9 +95,6 @@ dependencies:
|
|
104
95
|
prerelease: false
|
105
96
|
version_requirements: !ruby/object:Gem::Requirement
|
106
97
|
requirements:
|
107
|
-
- - "~>"
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '1.0'
|
110
98
|
- - '='
|
111
99
|
- !ruby/object:Gem::Version
|
112
100
|
version: 1.0.0
|
@@ -116,50 +104,46 @@ dependencies:
|
|
116
104
|
requirements:
|
117
105
|
- - "~>"
|
118
106
|
- !ruby/object:Gem::Version
|
119
|
-
version: '
|
107
|
+
version: '2.0'
|
120
108
|
- - ">="
|
121
109
|
- !ruby/object:Gem::Version
|
122
|
-
version:
|
110
|
+
version: 2.0.210126
|
123
111
|
type: :runtime
|
124
112
|
prerelease: false
|
125
113
|
version_requirements: !ruby/object:Gem::Requirement
|
126
114
|
requirements:
|
127
115
|
- - "~>"
|
128
116
|
- !ruby/object:Gem::Version
|
129
|
-
version: '
|
117
|
+
version: '2.0'
|
130
118
|
- - ">="
|
131
119
|
- !ruby/object:Gem::Version
|
132
|
-
version:
|
120
|
+
version: 2.0.210126
|
133
121
|
description: |
|
134
122
|
Ruby-Gnome Password Manager.
|
135
123
|
|
136
124
|
Uses Blowfish to encrypt the datafile.
|
137
|
-
Features random password generator
|
125
|
+
Features random password generator, clipboard use, and TOTP.
|
138
126
|
email: carlosjhr64@gmail.com
|
139
127
|
executables:
|
140
|
-
-
|
128
|
+
- gtk2passwordapp
|
141
129
|
extensions: []
|
142
|
-
extra_rdoc_files:
|
143
|
-
- README.rdoc
|
130
|
+
extra_rdoc_files: []
|
144
131
|
files:
|
145
|
-
- README.
|
146
|
-
- bin/
|
147
|
-
- data/VERSION
|
132
|
+
- README.md
|
133
|
+
- bin/gtk2passwordapp
|
148
134
|
- data/logo.png
|
149
135
|
- lib/gtk2passwordapp.rb
|
150
136
|
- lib/gtk2passwordapp/account.rb
|
151
137
|
- lib/gtk2passwordapp/accounts.rb
|
138
|
+
- lib/gtk2passwordapp/cli.rb
|
152
139
|
- lib/gtk2passwordapp/config.rb
|
153
|
-
- lib/gtk2passwordapp/
|
154
|
-
- lib/gtk2passwordapp/such_parts.rb
|
140
|
+
- lib/gtk2passwordapp/gui.rb
|
155
141
|
homepage: https://github.com/carlosjhr64/gtk2passwordapp
|
156
142
|
licenses:
|
157
143
|
- MIT
|
158
144
|
metadata: {}
|
159
|
-
post_install_message:
|
160
|
-
rdoc_options:
|
161
|
-
- "--main"
|
162
|
-
- README.rdoc
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
163
147
|
require_paths:
|
164
148
|
- lib
|
165
149
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -173,10 +157,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
157
|
- !ruby/object:Gem::Version
|
174
158
|
version: '0'
|
175
159
|
requirements:
|
176
|
-
- 'ruby: ruby
|
177
|
-
|
178
|
-
|
179
|
-
signing_key:
|
160
|
+
- 'ruby: ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]'
|
161
|
+
rubygems_version: 3.2.3
|
162
|
+
signing_key:
|
180
163
|
specification_version: 4
|
181
164
|
summary: Ruby-Gnome Password Manager.
|
182
165
|
test_files: []
|