gtk2passwordapp 4.3.0 → 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 +15 -119
- data/lib/gtk2passwordapp.rb +50 -14
- data/lib/gtk2passwordapp/account.rb +5 -5
- data/lib/gtk2passwordapp/accounts.rb +7 -6
- data/lib/gtk2passwordapp/cli.rb +35 -0
- data/lib/gtk2passwordapp/config.rb +197 -145
- data/lib/gtk2passwordapp/gui.rb +314 -0
- metadata +41 -80
- data/README.rdoc +0 -75
- data/data/VERSION +0 -1
- data/lib/gtk2passwordapp/gtk2passwordapp.rb +0 -453
- data/lib/gtk2passwordapp/such_parts.rb +0 -22
- data/lib/gtk2passwordapp/version.rb +0 -3
metadata
CHANGED
@@ -1,117 +1,105 @@
|
|
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
|
-
name:
|
14
|
+
name: yaml_zlib_blowfish
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
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
|
-
name:
|
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
|
-
name:
|
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
|
-
name:
|
74
|
+
name: base32
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
76
76
|
requirements:
|
77
|
-
- -
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: '0.0'
|
80
|
-
- - ">="
|
77
|
+
- - '='
|
81
78
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
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
|
-
- -
|
84
|
+
- - '='
|
88
85
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
90
|
-
- - ">="
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
version: 0.0.1
|
86
|
+
version: 0.3.4
|
93
87
|
- !ruby/object:Gem::Dependency
|
94
|
-
name:
|
88
|
+
name: totp
|
95
89
|
requirement: !ruby/object:Gem::Requirement
|
96
90
|
requirements:
|
97
|
-
- -
|
91
|
+
- - '='
|
98
92
|
- !ruby/object:Gem::Version
|
99
|
-
version:
|
100
|
-
- - ">="
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
version: 0.2.0
|
93
|
+
version: 1.0.0
|
103
94
|
type: :runtime
|
104
95
|
prerelease: false
|
105
96
|
version_requirements: !ruby/object:Gem::Requirement
|
106
97
|
requirements:
|
107
|
-
- -
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0.2'
|
110
|
-
- - ">="
|
98
|
+
- - '='
|
111
99
|
- !ruby/object:Gem::Version
|
112
|
-
version: 0.
|
100
|
+
version: 1.0.0
|
113
101
|
- !ruby/object:Gem::Dependency
|
114
|
-
name:
|
102
|
+
name: super_random
|
115
103
|
requirement: !ruby/object:Gem::Requirement
|
116
104
|
requirements:
|
117
105
|
- - "~>"
|
@@ -119,7 +107,7 @@ dependencies:
|
|
119
107
|
version: '2.0'
|
120
108
|
- - ">="
|
121
109
|
- !ruby/object:Gem::Version
|
122
|
-
version: 2.0.
|
110
|
+
version: 2.0.210126
|
123
111
|
type: :runtime
|
124
112
|
prerelease: false
|
125
113
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -129,58 +117,33 @@ dependencies:
|
|
129
117
|
version: '2.0'
|
130
118
|
- - ">="
|
131
119
|
- !ruby/object:Gem::Version
|
132
|
-
version: 2.0.
|
133
|
-
- !ruby/object:Gem::Dependency
|
134
|
-
name: helpema
|
135
|
-
requirement: !ruby/object:Gem::Requirement
|
136
|
-
requirements:
|
137
|
-
- - "~>"
|
138
|
-
- !ruby/object:Gem::Version
|
139
|
-
version: '0.2'
|
140
|
-
- - ">="
|
141
|
-
- !ruby/object:Gem::Version
|
142
|
-
version: 0.2.0
|
143
|
-
type: :runtime
|
144
|
-
prerelease: false
|
145
|
-
version_requirements: !ruby/object:Gem::Requirement
|
146
|
-
requirements:
|
147
|
-
- - "~>"
|
148
|
-
- !ruby/object:Gem::Version
|
149
|
-
version: '0.2'
|
150
|
-
- - ">="
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 0.2.0
|
120
|
+
version: 2.0.210126
|
153
121
|
description: |
|
154
122
|
Ruby-Gnome Password Manager.
|
155
123
|
|
156
124
|
Uses Blowfish to encrypt the datafile.
|
157
|
-
Features random password generator
|
125
|
+
Features random password generator, clipboard use, and TOTP.
|
158
126
|
email: carlosjhr64@gmail.com
|
159
127
|
executables:
|
160
128
|
- gtk2passwordapp
|
161
129
|
extensions: []
|
162
|
-
extra_rdoc_files:
|
163
|
-
- README.rdoc
|
130
|
+
extra_rdoc_files: []
|
164
131
|
files:
|
165
|
-
- README.
|
132
|
+
- README.md
|
166
133
|
- bin/gtk2passwordapp
|
167
|
-
- data/VERSION
|
168
134
|
- data/logo.png
|
169
135
|
- lib/gtk2passwordapp.rb
|
170
136
|
- lib/gtk2passwordapp/account.rb
|
171
137
|
- lib/gtk2passwordapp/accounts.rb
|
138
|
+
- lib/gtk2passwordapp/cli.rb
|
172
139
|
- lib/gtk2passwordapp/config.rb
|
173
|
-
- lib/gtk2passwordapp/
|
174
|
-
- lib/gtk2passwordapp/such_parts.rb
|
175
|
-
- lib/gtk2passwordapp/version.rb
|
140
|
+
- lib/gtk2passwordapp/gui.rb
|
176
141
|
homepage: https://github.com/carlosjhr64/gtk2passwordapp
|
177
142
|
licenses:
|
178
143
|
- MIT
|
179
144
|
metadata: {}
|
180
|
-
post_install_message:
|
181
|
-
rdoc_options:
|
182
|
-
- "--main"
|
183
|
-
- README.rdoc
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
184
147
|
require_paths:
|
185
148
|
- lib
|
186
149
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -194,11 +157,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
157
|
- !ruby/object:Gem::Version
|
195
158
|
version: '0'
|
196
159
|
requirements:
|
197
|
-
- 'ruby: ruby
|
198
|
-
|
199
|
-
|
200
|
-
rubygems_version: 2.5.2
|
201
|
-
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:
|
202
163
|
specification_version: 4
|
203
164
|
summary: Ruby-Gnome Password Manager.
|
204
165
|
test_files: []
|
data/README.rdoc
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
= Gtk2passwordapp
|
2
|
-
|
3
|
-
{<img src="https://badge.fury.io/rb/gtk2passwordapp.svg" alt="Gem Version" />}[http://badge.fury.io/rb/gtk2passwordapp]
|
4
|
-
|
5
|
-
== DESCRIPTION:
|
6
|
-
|
7
|
-
Ruby-Gnome Password Manager.
|
8
|
-
|
9
|
-
Uses Blowfish to encrypt the datafile.
|
10
|
-
Features random password generator and clipboard use.
|
11
|
-
|
12
|
-
== INSTALL:
|
13
|
-
|
14
|
-
Note that you'll need gtk3app installed:
|
15
|
-
|
16
|
-
sudo gem install gtk3app
|
17
|
-
sudo gem install gtk2passwordapp
|
18
|
-
|
19
|
-
== HELP:
|
20
|
-
|
21
|
-
Usage:
|
22
|
-
gtk3app gtk2passwordapp [--help] [--version]
|
23
|
-
gtk2passwordapp [--no-gui [--dump [--verbose]]] [account]
|
24
|
-
|
25
|
-
== MORE:
|
26
|
-
|
27
|
-
"Mouse Left Click" on window to get the application menu.
|
28
|
-
Anything I thought could be customized I made configurable.
|
29
|
-
See:
|
30
|
-
|
31
|
-
~/.config/gtk3app/gtk2passwordapp/config-?.?.yml
|
32
|
-
|
33
|
-
You may want to change the following settings:
|
34
|
-
|
35
|
-
[Help] Add any notes to yourself you want.
|
36
|
-
[SharedSecretFile] You may prefer it to be a file in some removable media.
|
37
|
-
[BackupFile] Although the GUI allows you to specify the file, this gives a default.
|
38
|
-
[TooOld] I have this set for a year (in seconds).
|
39
|
-
[CustomDigits] I have this as "ABC...XYZ" for CAPS.
|
40
|
-
[Custom] I have this as CAPS. Describes CustomDigits.
|
41
|
-
|
42
|
-
If you're updating from a previous version,
|
43
|
-
you may need to edit the new config file to match you're previously edited changes.
|
44
|
-
Also, double check the requirements to ensure the versions of ruby and gems being used
|
45
|
-
(gtk3app, etc...) are compatible.
|
46
|
-
|
47
|
-
If you use a qrcode to enter your password, and
|
48
|
-
the result is a multiline string,
|
49
|
-
gtk2passwordapp will assume you want the qgraph-sha256-digest.
|
50
|
-
See gtk2passwordapp/gtk2passwordapp.rb's #process_pwd_entries to see how that's done.
|
51
|
-
|
52
|
-
== LICENSE:
|
53
|
-
|
54
|
-
(The MIT License)
|
55
|
-
|
56
|
-
Copyright (c) 2017
|
57
|
-
|
58
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
59
|
-
a copy of this software and associated documentation files (the
|
60
|
-
'Software'), to deal in the Software without restriction, including
|
61
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
62
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
63
|
-
permit persons to whom the Software is furnished to do so, subject to
|
64
|
-
the following conditions:
|
65
|
-
|
66
|
-
The above copyright notice and this permission notice shall be
|
67
|
-
included in all copies or substantial portions of the Software.
|
68
|
-
|
69
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
70
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
71
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
72
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
73
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
74
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
75
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
4.3.0
|
@@ -1,453 +0,0 @@
|
|
1
|
-
module Gtk2passwordapp
|
2
|
-
using Rafini::Exception
|
3
|
-
using Rafini::Array
|
4
|
-
|
5
|
-
RND = SuperRandom.new
|
6
|
-
H2Q = BaseConvert::FromTo.new(:hex, :qgraph)
|
7
|
-
H2W = BaseConvert::FromTo.new(:hex, :word)
|
8
|
-
|
9
|
-
def self.options=(opts)
|
10
|
-
@@options=opts
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.options
|
14
|
-
@@options
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.run(program)
|
18
|
-
Gtk2PasswordApp.new(program)
|
19
|
-
end
|
20
|
-
|
21
|
-
class DeleteDialog < Gtk3App::Dialog::CancelOk
|
22
|
-
def initialize(parent)
|
23
|
-
super([parent: parent], :delete_dialog)
|
24
|
-
label :delete_label!
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class BackupDialog < Such::FileChooserDialog
|
29
|
-
def initialize(parent)
|
30
|
-
super([parent: parent], :backup_dialog)
|
31
|
-
set_action Gtk::FileChooser::Action::SAVE
|
32
|
-
add_button(Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL)
|
33
|
-
add_button(Gtk::Stock::OPEN, Gtk::ResponseType::ACCEPT)
|
34
|
-
if CONFIG[:BackupFile]
|
35
|
-
set_filename CONFIG[:BackupFile]
|
36
|
-
set_current_name File.basename CONFIG[:BackupFile]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def runs
|
41
|
-
show_all
|
42
|
-
value = nil
|
43
|
-
if run == Gtk::ResponseType::ACCEPT
|
44
|
-
value = filename
|
45
|
-
end
|
46
|
-
destroy
|
47
|
-
return value
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
class ErrorDialog < Such::MessageDialog
|
52
|
-
def initialize(parent)
|
53
|
-
super([parent: parent, flags: :modal, type: :error, buttons_type: :close], :error_dialog)
|
54
|
-
end
|
55
|
-
|
56
|
-
def runs
|
57
|
-
set_secondary_text $!.message
|
58
|
-
run
|
59
|
-
destroy
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class Gtk2PasswordApp
|
64
|
-
|
65
|
-
def initialize(program)
|
66
|
-
@program = program
|
67
|
-
@names = @combo = nil
|
68
|
-
|
69
|
-
@blue = Gdk::RGBA.parse(CONFIG[:Blue])
|
70
|
-
@red = Gdk::RGBA.parse(CONFIG[:Red])
|
71
|
-
@black = Gdk::RGBA.parse(CONFIG[:Black])
|
72
|
-
|
73
|
-
_ = CONFIG[:CustomDigits]
|
74
|
-
@h2c = BaseConvert::FromTo.new(:hex, _.length)
|
75
|
-
@h2c.to_digits = _
|
76
|
-
|
77
|
-
if CONFIG[:SwitchClipboard]
|
78
|
-
@clipboard = Gtk::Clipboard.get(Gdk::Selection::PRIMARY)
|
79
|
-
@primary = Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
|
80
|
-
else
|
81
|
-
@primary = Gtk::Clipboard.get(Gdk::Selection::PRIMARY)
|
82
|
-
@clipboard = Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
|
83
|
-
end
|
84
|
-
|
85
|
-
@current, @previous = [], []
|
86
|
-
|
87
|
-
window = program.window
|
88
|
-
@page = Such::Box.new window, :vbox!
|
89
|
-
@accounts = Accounts.new(CONFIG[:PwdFile])
|
90
|
-
password_page((@accounts.exist?)? :load : :init)
|
91
|
-
window.show
|
92
|
-
|
93
|
-
# Because accounts are editable from the main window,
|
94
|
-
# minime's menu needs to be updated each time.
|
95
|
-
destroy_menu_items
|
96
|
-
program.mini.signal_connect('show'){generate_menu_items}
|
97
|
-
program.mini.signal_connect('hide'){destroy_menu_items}
|
98
|
-
end
|
99
|
-
|
100
|
-
def copy2clipboard(pwd, user)
|
101
|
-
@primary.text = pwd
|
102
|
-
@clipboard.text = user
|
103
|
-
GLib::Timeout.add_seconds(CONFIG[:ClipboardTimeout]) do
|
104
|
-
if @primary.wait_for_text == pwd
|
105
|
-
@primary.text = ''
|
106
|
-
if @clipboard.wait_for_text == user
|
107
|
-
@clipboard.text = ''
|
108
|
-
end
|
109
|
-
end
|
110
|
-
false
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def color_code(selected)
|
115
|
-
@current.unshift selected; @current.uniq!
|
116
|
-
if @current.length > CONFIG[:Recent]
|
117
|
-
popped = @current.pop
|
118
|
-
popped.override_color :normal, @black
|
119
|
-
end
|
120
|
-
selected.override_color :normal, @blue
|
121
|
-
end
|
122
|
-
|
123
|
-
def generate_menu_items
|
124
|
-
now = Time.now.to_i
|
125
|
-
@accounts.names.sort{|a,b|a.upcase<=>b.upcase}.each do |name|
|
126
|
-
account = @accounts.get name
|
127
|
-
pwd, user, updated = account.password, account.username, account.updated
|
128
|
-
selected = Such::MenuItem.new([name], 'activate') do
|
129
|
-
color_code selected
|
130
|
-
@combo.set_active @names.index name if @combo
|
131
|
-
copy2clipboard pwd, user
|
132
|
-
@program.mini_menu.reorder_child(selected,0)
|
133
|
-
end
|
134
|
-
if @previous.include? name
|
135
|
-
@current[@previous.index(name)] = selected
|
136
|
-
selected.override_color :normal, @blue
|
137
|
-
elsif ((now - updated) > CONFIG[:TooOld])
|
138
|
-
selected.override_color :normal, @red
|
139
|
-
end
|
140
|
-
@program.mini_menu.append selected
|
141
|
-
selected.show
|
142
|
-
end
|
143
|
-
@current.delete_if{|a|a.nil?}
|
144
|
-
@previous.clear
|
145
|
-
end
|
146
|
-
|
147
|
-
def destroy_menu_items
|
148
|
-
@current.each{|item| @previous.push item.label}
|
149
|
-
@current.clear
|
150
|
-
@program.mini_menu.each{|item|item.destroy}
|
151
|
-
end
|
152
|
-
|
153
|
-
def clear_page
|
154
|
-
@page.each{|w|w.destroy}
|
155
|
-
end
|
156
|
-
|
157
|
-
def process_pwd_entries(entry1, entry2)
|
158
|
-
begin
|
159
|
-
pwd1 = entry1.text.strip
|
160
|
-
if pwd1 == '' and pwd = Helpema::ZBar.qrcode(CONFIG[:QrcTimeOut])
|
161
|
-
if pwd.include?("\n")
|
162
|
-
pwd1 = BaseConvert::FromTo.new(:hex, :qgraph).convert Digest::SHA256.hexdigest pwd
|
163
|
-
else
|
164
|
-
pwd1 = pwd
|
165
|
-
end
|
166
|
-
end
|
167
|
-
raise 'No password given.' if pwd1 == ''
|
168
|
-
if entry2
|
169
|
-
raise 'Passwords did not match' unless entry2.text.strip==pwd1
|
170
|
-
@accounts.save pwd1
|
171
|
-
else
|
172
|
-
if pwd1=~/^\d+\-[\dabcdef]+$/ # then we probably have a shared secret...
|
173
|
-
if File.exist? CONFIG[:SharedSecretFile] # and looks like we really do...
|
174
|
-
pwd0 = File.read(CONFIG[:SharedSecretFile]).strip
|
175
|
-
pwd = Helpema::SSSS.combine(pwd0, pwd1)
|
176
|
-
pwd1 = pwd unless pwd=='' # but maybe not.
|
177
|
-
end
|
178
|
-
end
|
179
|
-
@accounts.load pwd1
|
180
|
-
end
|
181
|
-
true
|
182
|
-
rescue StandardError
|
183
|
-
$!.puts
|
184
|
-
entry1.text = ''
|
185
|
-
entry2.text = '' if entry2
|
186
|
-
false
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def backup
|
191
|
-
if filename = BackupDialog.new(@program.window).runs
|
192
|
-
begin
|
193
|
-
FileUtils.cp CONFIG[:PwdFile], filename
|
194
|
-
rescue
|
195
|
-
$!.puts
|
196
|
-
ErrorDialog.new(@program.window).runs
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
# mode can be :init, :load, or :reset
|
202
|
-
def password_page(mode)
|
203
|
-
clear_page
|
204
|
-
|
205
|
-
password_label = Such::Label.new @page, :password_label!
|
206
|
-
password_entry1 = Such::Entry.new @page, :password_entry!
|
207
|
-
password_entry2 = (mode==:load)? nil : Such::Entry.new(@page, :password_entry!)
|
208
|
-
|
209
|
-
action = Such::AbButtons.new(@page, :hbox!) do |button, *_|
|
210
|
-
case button
|
211
|
-
when action.a_Button # Cancel
|
212
|
-
(mode==:reset)? view_page : @program.quit!
|
213
|
-
when action.b_Button # Go
|
214
|
-
if process_pwd_entries password_entry1, password_entry2
|
215
|
-
unless mode==:reset
|
216
|
-
@program.app_menu.append_menu_item(:reset!){password_page(:reset)}
|
217
|
-
@program.app_menu.append_menu_item(:backup!){backup}
|
218
|
-
end
|
219
|
-
view_page
|
220
|
-
else
|
221
|
-
password_label.text = CONFIG[:ReTry]
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
action.labels :Cancel, :Go
|
226
|
-
|
227
|
-
password_entry1.signal_connect('activate') do
|
228
|
-
if password_entry2
|
229
|
-
password_entry2.grab_focus
|
230
|
-
else
|
231
|
-
action.b_Button.clicked
|
232
|
-
end
|
233
|
-
end
|
234
|
-
if password_entry2
|
235
|
-
password_entry2.signal_connect('activate') do
|
236
|
-
action.b_Button.clicked
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
@page.show_all
|
241
|
-
end
|
242
|
-
|
243
|
-
def create_combo
|
244
|
-
combo = Such::PromptedCombo.new @page, :hbox!
|
245
|
-
combo.prompt_Label.text = CONFIG[:Name]
|
246
|
-
@combo= combo.prompted_ComboBoxText
|
247
|
-
@names = @accounts.names.sort{|a,b|a.upcase<=>b.upcase}
|
248
|
-
@names.each{|name|@combo.append_text name}
|
249
|
-
@combo.set_active @names.index(@account.name)
|
250
|
-
@combo.signal_connect('destroy'){@names = @combo = nil}
|
251
|
-
end
|
252
|
-
|
253
|
-
def create_entries
|
254
|
-
entries = {}
|
255
|
-
CONFIG[:FIELDS].each do |field, text|
|
256
|
-
entry = Such::PromptedLabel.new @page, :hbox!
|
257
|
-
entry.prompt_Label.text = text
|
258
|
-
entry.prompted_Label.text = @account.method(field).call
|
259
|
-
entry.prompted_Label.set_alignment(*CONFIG[:FIELD_ALIGNMENT])
|
260
|
-
entries[field] = entry
|
261
|
-
end
|
262
|
-
return entries
|
263
|
-
end
|
264
|
-
|
265
|
-
def any_name
|
266
|
-
names = @accounts.names
|
267
|
-
if name = ARGV.shift
|
268
|
-
unless names.include? name
|
269
|
-
like = Regexp.new name
|
270
|
-
name = names.which{|nm|nm=~like}
|
271
|
-
end
|
272
|
-
end
|
273
|
-
name = names.sample unless name
|
274
|
-
return name
|
275
|
-
end
|
276
|
-
|
277
|
-
def view_page
|
278
|
-
if @accounts.data.length == 0
|
279
|
-
edit_page(:add)
|
280
|
-
return
|
281
|
-
end
|
282
|
-
@account ||= @accounts.get any_name
|
283
|
-
|
284
|
-
clear_page
|
285
|
-
|
286
|
-
Such::Label.new @page, :view_label!
|
287
|
-
create_combo
|
288
|
-
entries = create_entries
|
289
|
-
|
290
|
-
label, hidden = entries[:password].prompted_Label, CONFIG[:HiddenPwd]
|
291
|
-
label.text = hidden
|
292
|
-
|
293
|
-
@combo.signal_connect('changed') do
|
294
|
-
@account = @accounts.get @combo.active_text
|
295
|
-
CONFIG[:FIELDS].each do |field, _|
|
296
|
-
entries[field].prompted_Label.text = @account.method(field).call
|
297
|
-
end
|
298
|
-
label.text = hidden
|
299
|
-
end
|
300
|
-
|
301
|
-
clip_box = Such::AbcButtons.new(@page, :hbox!) do |button, *_|
|
302
|
-
case button
|
303
|
-
when clip_box.a_Button # Current
|
304
|
-
copy2clipboard @account.password, @account.username
|
305
|
-
when clip_box.b_Button # Previous
|
306
|
-
copy2clipboard @account.previous, @account.password
|
307
|
-
when clip_box.c_Button # Show
|
308
|
-
label.text == hidden ?
|
309
|
-
label.text = @account.password :
|
310
|
-
label.text = hidden
|
311
|
-
end
|
312
|
-
end
|
313
|
-
clip_box.labels :Current, :Previous, :Show
|
314
|
-
|
315
|
-
edit_box = Such::AbcButtons.new(@page, :hbox!) do |button, *_|
|
316
|
-
case button
|
317
|
-
when edit_box.a_Button then edit_page
|
318
|
-
when edit_box.b_Button then edit_page(:add)
|
319
|
-
when edit_box.c_Button
|
320
|
-
system("#{Gtk3App::CONFIG[:Open]} '#{@account.url}'") if @account.url.length > 0
|
321
|
-
end
|
322
|
-
end
|
323
|
-
edit_box.labels :Edit, :Add, :Goto
|
324
|
-
|
325
|
-
@page.show_all
|
326
|
-
end
|
327
|
-
|
328
|
-
def edit_page(mode=:edit)
|
329
|
-
clear_page
|
330
|
-
|
331
|
-
edited = false
|
332
|
-
previous = @account ? @account.name : nil
|
333
|
-
name = nil
|
334
|
-
|
335
|
-
case mode
|
336
|
-
when :add
|
337
|
-
Such::Label.new @page, :add_label!
|
338
|
-
name = Such::PromptedEntryLabel.new @page, :hbox!
|
339
|
-
name.prompt_Label.text = CONFIG[:Name]
|
340
|
-
when :edit
|
341
|
-
Such::Label.new @page, :edit_label!
|
342
|
-
name = Such::PromptedLabel.new @page, :hbox!
|
343
|
-
name.prompt_Label.text = CONFIG[:Name]
|
344
|
-
name.prompted_Label.text = @account.name
|
345
|
-
end
|
346
|
-
name.prompted_Label.set_alignment(*CONFIG[:FIELD_ALIGNMENT])
|
347
|
-
|
348
|
-
entries = {}
|
349
|
-
CONFIG[:FIELDS].each do |field, text|
|
350
|
-
entry = Such::PromptedEntry.new @page, :hbox!
|
351
|
-
entry.prompt_Label.text = text
|
352
|
-
entry.prompted_Entry.text = @account.method(field).call if mode==:edit
|
353
|
-
entries[field] = entry
|
354
|
-
end
|
355
|
-
|
356
|
-
# cb and sb will be a CheckButton and SpinButton respectively.
|
357
|
-
cb = sb = nil
|
358
|
-
password = @account ? @account.password : ''
|
359
|
-
truncate = Proc.new do |p|
|
360
|
-
password = p
|
361
|
-
if cb.active?
|
362
|
-
n = sb.value.to_i
|
363
|
-
p = p[-n..-1] if p.length > n
|
364
|
-
end
|
365
|
-
p
|
366
|
-
end
|
367
|
-
|
368
|
-
pwd = entries[:password].prompted_Entry
|
369
|
-
pwd.set_visibility false
|
370
|
-
pwd.signal_connect('focus-in-event' ){pwd.set_visibility true}
|
371
|
-
pwd.signal_connect('focus-out-event'){pwd.set_visibility false}
|
372
|
-
|
373
|
-
generators = Such::AbcButtons.new(@page, :hbox!) do |button,*e,s|
|
374
|
-
hex = RND.hexadecimal
|
375
|
-
case button
|
376
|
-
when generators.a_Button
|
377
|
-
pwd.text = truncate.call H2Q.convert hex
|
378
|
-
when generators.b_Button
|
379
|
-
pwd.text = truncate.call H2W.convert hex
|
380
|
-
when generators.c_Button
|
381
|
-
pwd.text = truncate.call @h2c.convert hex
|
382
|
-
end
|
383
|
-
end
|
384
|
-
generators.labels :Random, :AlphaNumeric, :Custom
|
385
|
-
|
386
|
-
cb = Such::CheckButton.new(generators, :pwd_size_check!, 'toggled') do
|
387
|
-
pwd.text = (cb.active?) ? truncate.call(password) : password
|
388
|
-
end
|
389
|
-
sb = Such::SpinButton.new(generators, :pwd_size_spin!, 'value-changed') do
|
390
|
-
pwd.text = truncate.call password if cb.active?
|
391
|
-
end
|
392
|
-
|
393
|
-
action = Such::AbcButtons.new(@page, :hbox!) do |button, *_|
|
394
|
-
case button
|
395
|
-
when action.a_Button # Cancel
|
396
|
-
if edited
|
397
|
-
@accounts.load
|
398
|
-
@account = previous ? @accounts.get(previous) : nil
|
399
|
-
end
|
400
|
-
view_page
|
401
|
-
when action.b_Button # Delete
|
402
|
-
dialog = DeleteDialog.new(@program.window)
|
403
|
-
dialog.set_title @account.name
|
404
|
-
if dialog.runs
|
405
|
-
@accounts.delete @account.name
|
406
|
-
@accounts.save
|
407
|
-
@account = nil
|
408
|
-
view_page
|
409
|
-
end
|
410
|
-
when action.c_Button # Save
|
411
|
-
edited = true
|
412
|
-
begin
|
413
|
-
if mode==:add
|
414
|
-
@account = @accounts.add(name.prompted_Entry.text.strip)
|
415
|
-
name.prompted_Label.text = @account.name
|
416
|
-
name.prompted_Entry.hide
|
417
|
-
name.prompted_Label.show
|
418
|
-
name.prompt_Label.override_color :normal, @blue
|
419
|
-
mode = :edit
|
420
|
-
end
|
421
|
-
errors = false
|
422
|
-
entries.each do |field, entry|
|
423
|
-
begin
|
424
|
-
@account.method("#{field}=".to_sym).call(entry.prompted_Entry.text.strip)
|
425
|
-
entry.prompt_Label.override_color :normal, @blue
|
426
|
-
rescue RuntimeError
|
427
|
-
$!.puts
|
428
|
-
errors ||= true
|
429
|
-
entry.prompt_Label.override_color :normal, @red
|
430
|
-
end
|
431
|
-
end
|
432
|
-
unless errors
|
433
|
-
@accounts.save
|
434
|
-
view_page
|
435
|
-
end
|
436
|
-
rescue RuntimeError
|
437
|
-
$!.puts
|
438
|
-
name.prompt_Label.override_color :normal, @red
|
439
|
-
end
|
440
|
-
end
|
441
|
-
end
|
442
|
-
action.labels :Cancel, :Delete, :Save
|
443
|
-
|
444
|
-
@page.show_all
|
445
|
-
if mode==:add
|
446
|
-
name.prompted_Label.hide
|
447
|
-
action.b_Button.hide
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
end
|
452
|
-
|
453
|
-
end
|