gtk2passwordapp 1.5.0 → 1.6.0
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/bin/gtk2passwordapp +4 -57
- data/lib/gtk2passwordapp/appconfig.rb +31 -13
- data/lib/gtk2passwordapp/iocrypt.rb +2 -1
- data/lib/gtk2passwordapp/passwords.rb +9 -7
- data/lib/gtk2passwordapp/passwords_data.rb +33 -25
- data/lib/gtk2passwordapp.rb +241 -204
- metadata +10 -10
data/bin/gtk2passwordapp
CHANGED
@@ -1,67 +1,14 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'rubygems'
|
3
|
-
gem 'gtk2applib', '~>
|
3
|
+
gem 'gtk2applib', '~> 15.3'
|
4
4
|
require 'gtk2applib'
|
5
|
+
require 'gtk2passwordapp'
|
5
6
|
|
6
|
-
|
7
|
-
program = Program.new( {
|
8
|
-
'name' => 'Ruby-Gnome Password Manager',
|
9
|
-
'authors' => ['carlosjhr64@gmail.com'],
|
10
|
-
'website' => 'https://sites.google.com/site/gtk2applib/home/gtk2applib-applications/gtk2passwordapp',
|
11
|
-
'website-label' => 'Ruby-Gnome Password Manager',
|
12
|
-
'license' => 'GPL',
|
13
|
-
'copyright' => '2011-03-07 17:05:39',
|
14
|
-
} )
|
7
|
+
program = Gtk2AppLib::Program.new( Gtk2Password::ABOUT )
|
15
8
|
|
16
9
|
begin
|
17
|
-
|
18
|
-
|
19
|
-
passwords = Gtk2PasswordApp::Passwords.new
|
20
|
-
Gtk2PasswordApp.build_menu(program,passwords)
|
21
|
-
|
22
|
-
modified = false
|
23
|
-
program.window do |window|
|
24
|
-
Gtk2AppLib::Configuration::PARAMETERS[:Account_ComboBoxEntry][0] = passwords.accounts
|
25
|
-
Gtk2AppLib::Dialogs::DIALOG[:Window] = window
|
26
|
-
gui = Gtk2PasswordApp::Component::Gui.new(window) do |is,signal,*emits|
|
27
|
-
$stderr.puts "#{is},#{signal}:\t#{emits}" if $trace
|
28
|
-
Gtk2PasswordApp.method(signal).call(is,passwords) do |action|
|
29
|
-
case action
|
30
|
-
when :modified then modified ||= true
|
31
|
-
when :save
|
32
|
-
if modified then
|
33
|
-
Gtk2PasswordApp.save(program,passwords)
|
34
|
-
modified = false
|
35
|
-
else
|
36
|
-
Gtk2AppLib::DIALOGS.quick_message(*Gtk2PasswordApp::Configuration::NO_UPDATES)
|
37
|
-
end
|
38
|
-
when :close
|
39
|
-
if !modified || Gtk2AppLib::DIALOGS.question?(*Gtk2PasswordApp::Configuration::ARE_YOU_SURE) then
|
40
|
-
passwords.load # revert
|
41
|
-
modified = false
|
42
|
-
program.close
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
Gtk2PasswordApp::Component::SHARED[:Password_SpinButton].value = Gtk2PasswordApp::Configuration::DEFAULT_PASSWORD_LENGTH
|
48
|
-
Gtk2PasswordApp::Component::SHARED[:Account_ComboBoxEntry].active = Gtk2PasswordApp.index
|
49
|
-
window.signal_connect('destroy') do
|
50
|
-
if modified then
|
51
|
-
if Gtk2AppLib::DIALOGS.question?(*Gtk2PasswordApp::Configuration::WANT_TO_SAVE) then
|
52
|
-
Gtk2PasswordApp.save(program,passwords)
|
53
|
-
modified = false
|
54
|
-
end
|
55
|
-
end
|
56
|
-
if modified then
|
57
|
-
passwords.load # revert
|
58
|
-
modified = false
|
59
|
-
end
|
60
|
-
end
|
61
|
-
window.show_all
|
62
|
-
end
|
10
|
+
Gtk2Password::App.new(program)
|
63
11
|
rescue Exception
|
64
|
-
$verbose = true
|
65
12
|
$!.puts_bang!
|
66
13
|
ensure
|
67
14
|
program.finalize
|
@@ -15,8 +15,7 @@ module Configuration
|
|
15
15
|
check = 20
|
16
16
|
|
17
17
|
if HILDON then
|
18
|
-
|
19
|
-
FONT[:Normal] = FONT[:Large] = Pango::FontDescription.new( 'Arial 18' )
|
18
|
+
FONT[:NORMAL] = FONT[:LARGE] = Pango::FontDescription.new( 'Arial 18' )
|
20
19
|
go = 75
|
21
20
|
label = 150
|
22
21
|
entry = 500
|
@@ -30,12 +29,13 @@ module Configuration
|
|
30
29
|
WINDOW_DEFAULT_SIZE[0],WINDOW_DEFAULT_SIZE[1] = 100,100
|
31
30
|
MENU[:close] = '_Close'
|
32
31
|
end
|
32
|
+
MENU[:help] = '_Help'
|
33
33
|
|
34
34
|
wrap = {:wrap= => true}
|
35
35
|
label_width = {:width_request= => label, :wrap= => true}
|
36
36
|
entry_width = {:width_request= => entry}
|
37
|
-
|
38
|
-
|
37
|
+
shorten_a = {:width_request= => entry - go - 2*padding}
|
38
|
+
shorten_b = {:width_request= => entry - spin - check - 4*padding, :visibility= => false}
|
39
39
|
go_width = {:width_request= => go}
|
40
40
|
check_width = {:width_request= => check, :active= => true}
|
41
41
|
spin_width = {:width_request= => spin, :set_range => [3,30]}
|
@@ -46,7 +46,7 @@ module Configuration
|
|
46
46
|
PARAMETERS[:Account_ComboBoxEntry] = [nil,entry_width,'changed'] # catching changed signal
|
47
47
|
|
48
48
|
PARAMETERS[:Url_Label] = ['Url:',label_width]
|
49
|
-
PARAMETERS[:Url_Entry] = [
|
49
|
+
PARAMETERS[:Url_Entry] = [shorten_a]
|
50
50
|
PARAMETERS[:Url_Button] = ['Go!',go_width,clicked]
|
51
51
|
|
52
52
|
PARAMETERS[:Note_Label] = ['Note:',label_width]
|
@@ -56,7 +56,7 @@ module Configuration
|
|
56
56
|
PARAMETERS[:Username_Entry] = [entry_width]
|
57
57
|
|
58
58
|
PARAMETERS[:Password_Label] = ['Password:',label_width]
|
59
|
-
PARAMETERS[:Password_Entry] = [
|
59
|
+
PARAMETERS[:Password_Entry] = [shorten_b]
|
60
60
|
PARAMETERS[:Password_CheckButton] = [check_width,'toggled']
|
61
61
|
PARAMETERS[:Password_SpinButton] = [spin_width]
|
62
62
|
|
@@ -78,7 +78,7 @@ module Configuration
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
module
|
81
|
+
module Gtk2Password
|
82
82
|
module Configuration
|
83
83
|
# Note that the passwords data file name is auto generated, but...
|
84
84
|
# You can place your passwords data file in a directory other than ~/gtk2passwordapp-*
|
@@ -90,11 +90,29 @@ module Configuration
|
|
90
90
|
DEFAULT_PASSWORD_LENGTH = 7
|
91
91
|
EXPIRED_COLOR = Gtk2AppLib::Color[:Red]
|
92
92
|
|
93
|
-
BAD_URL = ['Need url like http://www.site.com/page.html',{:
|
94
|
-
ARE_YOU_SURE = ['Changes will lost, are you sure you want to close?',{:
|
95
|
-
WANT_TO_SAVE = ['Would you like to save your changes?',{:
|
96
|
-
NO_UPDATES = ["You've not updated any accounts yet.",{:
|
97
|
-
UPDATED = ["Updated!",{:
|
93
|
+
BAD_URL = ['Need url like http://www.site.com/page.html',{:TITLE => 'Error: Bad Url',:SCROLLED_WINDOW => false}]
|
94
|
+
ARE_YOU_SURE = ['Changes will lost, are you sure you want to close?',{:TITLE => 'Are you sure?'}]
|
95
|
+
WANT_TO_SAVE = ['Would you like to save your changes?',{:TITLE => 'Save?'}]
|
96
|
+
NO_UPDATES = ["You've not updated any accounts yet.",{:TITLE => 'Not Modified',:SCROLLED_WINDOW => false}]
|
97
|
+
UPDATED = ["Updated!",{:TITLE => 'Updated!',:SCROLLED_WINDOW => false}]
|
98
|
+
|
99
|
+
updates = [:Delete_Button,:Update_Button,:Save_Button]
|
100
|
+
updates.unshift(:Cancel_Button) if Gtk2AppLib::Configuration::MENU[:close]
|
101
|
+
vbox = 'Gtk2AppLib::Widgets::VBox'
|
102
|
+
hbox = 'Gtk2AppLib::Widgets::HBox'
|
103
|
+
GUI = [
|
104
|
+
['Gui', vbox, [:Account_Component,:Url_Component,:Note_Component,:Username_Component,:Password_Component,:Buttons_Component]],
|
105
|
+
['Account', hbox, [:Account_Label,:Account_ComboBoxEntry]],
|
106
|
+
['Url', hbox, [:Url_Label,:Url_Entry,:Url_Button]],
|
107
|
+
['Note', hbox, [:Note_Label,:Note_Entry]],
|
108
|
+
['Username', hbox, [:Username_Label,:Username_Entry]],
|
109
|
+
['Password', hbox, [:Password_Label,:Password_Entry,:Password_CheckButton,:Password_SpinButton]],
|
110
|
+
['Buttons', vbox, [:Generators_Component,:Updates_Component,:Datafile_Component,:Clip_Component]],
|
111
|
+
['Generators', hbox, [:Random_Button,:Alpha_Button,:Numeric_Button,:Letters_Button,:Caps_Button]],
|
112
|
+
['Updates', hbox, updates],
|
113
|
+
['Datafile', hbox, [:Datafile_Button]],
|
114
|
+
['Clip', hbox, [:Current_Button,:Previous_Button]],
|
115
|
+
]
|
98
116
|
end
|
99
117
|
|
100
118
|
def self.passwords_updated(dumpfile)
|
@@ -111,6 +129,6 @@ end
|
|
111
129
|
# end
|
112
130
|
# end
|
113
131
|
# Gtk2AppLib::DIALOGS.quick_message("Warning: Could not create backup on 192.168.1.123")
|
114
|
-
Gtk2AppLib::DIALOGS.quick_message("Passwords Data Saved.",{:
|
132
|
+
Gtk2AppLib::DIALOGS.quick_message("Passwords Data Saved.",{:TITLE => 'Saved',:SCROLLED_WINDOW => false})
|
115
133
|
end
|
116
134
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'gtk2passwordapp/passwords_data.rb'
|
2
|
-
module
|
2
|
+
module Gtk2Password
|
3
|
+
# Passwords subclasses PasswordsData :P
|
3
4
|
class Passwords < PasswordsData
|
4
5
|
|
5
6
|
def _create_passphrase
|
@@ -18,11 +19,12 @@ class Passwords < PasswordsData
|
|
18
19
|
passphrase = ''
|
19
20
|
|
20
21
|
@pfile = Gtk2AppLib::USERDIR+'/passphrase.txt'
|
22
|
+
exists = File.exist?(@pfile)
|
21
23
|
if mv then
|
22
|
-
File.rename(@pfile, @pfile+'.bak') if
|
24
|
+
File.rename(@pfile, @pfile+'.bak') if exists
|
23
25
|
passphrase = _create_passphrase
|
24
26
|
else
|
25
|
-
if
|
27
|
+
if exists then
|
26
28
|
File.open(@pfile,'r'){|fh| passphrase = fh.read }
|
27
29
|
else
|
28
30
|
passphrase = _create_passphrase
|
@@ -43,7 +45,7 @@ class Passwords < PasswordsData
|
|
43
45
|
end
|
44
46
|
|
45
47
|
def self._get_salt(prompt)
|
46
|
-
(ret =
|
48
|
+
(ret = Gtk2Password.get_salt(prompt,'Salt')) || exit
|
47
49
|
ret.strip
|
48
50
|
end
|
49
51
|
|
@@ -82,7 +84,9 @@ class Passwords < PasswordsData
|
|
82
84
|
end
|
83
85
|
|
84
86
|
def save(pwd=nil)
|
85
|
-
if pwd then
|
87
|
+
if pwd.nil? then
|
88
|
+
super()
|
89
|
+
else
|
86
90
|
pfbak = self.pfile + '.bak'
|
87
91
|
pph = get_passphrase(true) # new passphrase
|
88
92
|
dfbak = self.dumpfile + '.bak'
|
@@ -91,8 +95,6 @@ class Passwords < PasswordsData
|
|
91
95
|
@pph = pph
|
92
96
|
File.unlink(pfbak) if File.exist?(pfbak)
|
93
97
|
File.unlink(dfbak) if File.exist?(dfbak)
|
94
|
-
else
|
95
|
-
super()
|
96
98
|
end
|
97
99
|
return self.dumpfile
|
98
100
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'gtk2passwordapp/iocrypt'
|
2
2
|
require 'digest/md5'
|
3
3
|
|
4
|
-
module
|
4
|
+
module Gtk2Password
|
5
|
+
# PasswordsData maitains passwords
|
5
6
|
class PasswordsData
|
6
7
|
include Configuration
|
7
8
|
attr_accessor :account
|
@@ -30,7 +31,7 @@ class PasswordsData
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def load(passphrase = nil)
|
33
|
-
_reset(passphrase) if passphrase
|
34
|
+
_reset(passphrase) if !passphrase.nil?
|
34
35
|
iocrypt = IOCrypt.new(@passphrase)
|
35
36
|
@data = iocrypt.load(@dumpfile)
|
36
37
|
end
|
@@ -38,7 +39,7 @@ class PasswordsData
|
|
38
39
|
def save(passphrase = nil)
|
39
40
|
# just in case, keep a backup
|
40
41
|
File.rename(@dumpfile, @dumpfile+'.bak') if File.exist?(@dumpfile)
|
41
|
-
_reset(passphrase) if passphrase
|
42
|
+
_reset(passphrase) if !passphrase.nil?
|
42
43
|
iocrypt = IOCrypt.new(@passphrase)
|
43
44
|
iocrypt.dump(@dumpfile, @data)
|
44
45
|
File.chmod(0600, @dumpfile)
|
@@ -46,7 +47,7 @@ class PasswordsData
|
|
46
47
|
|
47
48
|
def add(account)
|
48
49
|
raise "Pre-existing" if @data[account]
|
49
|
-
raise "Can't have nil account" if
|
50
|
+
raise "Can't have nil account" if account.nil?
|
50
51
|
@data[account] = ['','','','','']
|
51
52
|
end
|
52
53
|
|
@@ -68,43 +69,50 @@ class PasswordsData
|
|
68
69
|
end
|
69
70
|
|
70
71
|
def url_of(account, url=nil)
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
data_account = @data[account]
|
73
|
+
raise "#{account} not found" if data_account.nil?
|
74
|
+
data_account[URL] = url if !url.nil?
|
75
|
+
return data_account[URL] || ''
|
74
76
|
end
|
75
77
|
|
76
78
|
def expired?(account)
|
77
|
-
|
78
|
-
|
79
|
+
data_account = @data[account]
|
80
|
+
raise "#{account} not found" if data_account.nil?
|
81
|
+
last_update = data_account[LAST_UPDATE]
|
82
|
+
return true if last_update.nil? || ((Time.now.to_i - last_update) > PASSWORD_EXPIRED)
|
79
83
|
return false
|
80
84
|
end
|
81
85
|
|
82
|
-
def password_of(account,
|
83
|
-
|
84
|
-
if
|
85
|
-
|
86
|
-
|
87
|
-
|
86
|
+
def password_of(account, password=nil)
|
87
|
+
data_account = @data[account]
|
88
|
+
raise "#{account} not found" if data_account.nil?
|
89
|
+
if !password.nil? then
|
90
|
+
data_account[PREVIOUS] = data_account[PASSWORD]
|
91
|
+
data_account[PASSWORD] = password
|
92
|
+
data_account[LAST_UPDATE] = Time.now.to_i
|
88
93
|
end
|
89
|
-
return
|
94
|
+
return data_account[PASSWORD] || ''
|
90
95
|
end
|
91
96
|
|
92
97
|
# previous password
|
93
98
|
def previous_password_of(account)
|
94
|
-
|
95
|
-
|
99
|
+
data_account = @data[account]
|
100
|
+
raise "#{account} not found" if data_account.nil?
|
101
|
+
return data_account[PREVIOUS] || ''
|
96
102
|
end
|
97
103
|
|
98
|
-
def note_of(account,
|
99
|
-
|
100
|
-
|
101
|
-
|
104
|
+
def note_of(account, note=nil)
|
105
|
+
data_account = @data[account]
|
106
|
+
raise "#{account} not found" if data_account.nil?
|
107
|
+
data_account[NOTE] = note if !note.nil?
|
108
|
+
return data_account[NOTE] || ''
|
102
109
|
end
|
103
110
|
|
104
111
|
def username_of(account, usr=nil)
|
105
|
-
|
106
|
-
|
107
|
-
|
112
|
+
data_account = @data[account]
|
113
|
+
raise "#{account} not found" if data_account.nil?
|
114
|
+
data_account[USERNAME] = usr if !usr.nil?
|
115
|
+
return data_account[USERNAME] || ''
|
108
116
|
end
|
109
117
|
end
|
110
118
|
end
|
data/lib/gtk2passwordapp.rb
CHANGED
@@ -1,249 +1,286 @@
|
|
1
1
|
require 'gtk2passwordapp/passwords'
|
2
|
-
module
|
2
|
+
module Gtk2Password
|
3
|
+
|
4
|
+
ABOUT = {
|
5
|
+
'name' => 'Ruby-Gnome Password Manager',
|
6
|
+
'authors' => ['carlosjhr64@gmail.com'],
|
7
|
+
'website' => 'https://sites.google.com/site/gtk2applib/home/gtk2applib-applications/gtk2passwordapp',
|
8
|
+
'website-label' => 'Ruby-Gnome Password Manager',
|
9
|
+
'license' => 'GPL',
|
10
|
+
'copyright' => '2011-04-26 13:57:20',
|
11
|
+
}
|
3
12
|
|
4
13
|
PRIMARY = Gtk::Clipboard.get((Configuration::SWITCH_CLIPBOARDS)? Gdk::Selection::CLIPBOARD: Gdk::Selection::PRIMARY)
|
5
14
|
CLIPBOARD = Gtk::Clipboard.get((Configuration::SWITCH_CLIPBOARDS)? Gdk::Selection::PRIMARY: Gdk::Selection::CLIPBOARD)
|
6
15
|
|
7
|
-
|
8
|
-
|
9
|
-
@@index
|
10
|
-
end
|
11
|
-
def self.build_menu(program,passwords)
|
12
|
-
if program.icon? then
|
13
|
-
program.clear_dock_menu
|
14
|
-
program.append_dock_menu(Gtk::SeparatorMenuItem.new)
|
15
|
-
passwords.accounts.each do |account|
|
16
|
-
item = program.append_dock_menu(account) do
|
17
|
-
@@index = passwords.accounts.index(account)
|
18
|
-
PRIMARY.text = passwords.password_of(account)
|
19
|
-
CLIPBOARD.text = passwords.username_of(account)
|
20
|
-
end
|
21
|
-
item.child.modify_fg(Gtk::STATE_NORMAL, Configuration::EXPIRED_COLOR) if passwords.expired?(account)
|
22
|
-
end
|
23
|
-
end
|
16
|
+
def self.get_salt(prompt,title=prompt)
|
17
|
+
Gtk2AppLib::DIALOGS.entry( prompt, {:TITLE=>title, :Entry => [{:visibility= => false},'activate']} )
|
24
18
|
end
|
25
19
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
20
|
+
Configuration::GUI.each do |clss,spr,keys|
|
21
|
+
code = Gtk2AppLib::Component.define(clss,spr,keys)
|
22
|
+
$stderr.puts "<<<START CODE EVAL>>>\n#{code}\n<<<END CODE EVAL>>>" if $trace && $verbose
|
23
|
+
eval( code )
|
30
24
|
end
|
31
25
|
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
# App is an App is an App...
|
27
|
+
class App
|
28
|
+
@@index = 0
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
def initialize(program)
|
31
|
+
@program = program
|
32
|
+
@passwords = Gtk2Password::Passwords.new
|
33
|
+
@modified = false
|
34
|
+
self.build_menu
|
35
|
+
program.window do |window|
|
36
|
+
@window = window
|
37
|
+
self.pre_gui
|
38
|
+
@gui = self.build_gui
|
39
|
+
self.post_gui
|
40
|
+
end
|
41
|
+
end
|
40
42
|
|
41
|
-
|
43
|
+
def menu_item(account)
|
44
|
+
item = @program.append_dock_menu(account) do
|
45
|
+
@@index = @passwords.accounts.index(account)
|
46
|
+
PRIMARY.text = @passwords.password_of(account)
|
47
|
+
CLIPBOARD.text = @passwords.username_of(account)
|
48
|
+
end
|
49
|
+
item.child.modify_fg(Gtk::STATE_NORMAL, Configuration::EXPIRED_COLOR) if @passwords.expired?(account)
|
50
|
+
end
|
42
51
|
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
def build_menu
|
53
|
+
if @program.icon? then
|
54
|
+
@program.clear_dock_menu
|
55
|
+
@program.append_dock_menu(Gtk::SeparatorMenuItem.new)
|
56
|
+
@passwords.accounts.each{|account| menu_item(account)}
|
57
|
+
end
|
58
|
+
end
|
46
59
|
|
47
|
-
|
60
|
+
def _save
|
61
|
+
dumpfile = @passwords.save
|
62
|
+
Gtk2Password.passwords_updated(dumpfile)
|
63
|
+
build_menu
|
64
|
+
end
|
48
65
|
|
49
|
-
|
50
|
-
|
51
|
-
|
66
|
+
def save
|
67
|
+
if @modified then
|
68
|
+
_save
|
69
|
+
@modified = false
|
70
|
+
else
|
71
|
+
Gtk2AppLib::DIALOGS.quick_message(*Gtk2Password::Configuration::NO_UPDATES)
|
72
|
+
end
|
73
|
+
end
|
52
74
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
75
|
+
def finalyze
|
76
|
+
if @modified then
|
77
|
+
if Gtk2AppLib::DIALOGS.question?(*Gtk2Password::Configuration::WANT_TO_SAVE) then
|
78
|
+
save
|
79
|
+
@modified = false
|
80
|
+
end
|
57
81
|
end
|
58
|
-
|
82
|
+
if @modified then
|
83
|
+
@passwords.load # revert
|
84
|
+
@modified = false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def post_gui
|
89
|
+
@gui[:password_spinbutton].value = Gtk2Password::Configuration::DEFAULT_PASSWORD_LENGTH
|
90
|
+
@gui[:account_comboboxentry].active = @@index
|
91
|
+
@window.signal_connect('destroy'){ finalyze }
|
92
|
+
@window.show_all
|
93
|
+
end
|
94
|
+
|
95
|
+
def pre_gui
|
96
|
+
Gtk2AppLib::Configuration::PARAMETERS[:Account_ComboBoxEntry][0] = @passwords.accounts
|
97
|
+
Gtk2AppLib::Dialogs::DIALOG[:Window] = @window
|
98
|
+
end
|
59
99
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
100
|
+
def close
|
101
|
+
if !@modified || Gtk2AppLib::DIALOGS.question?(*Gtk2Password::Configuration::ARE_YOU_SURE) then
|
102
|
+
@passwords.load # revert
|
103
|
+
@modified = false
|
104
|
+
@program.close
|
65
105
|
end
|
66
|
-
|
106
|
+
end
|
67
107
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
108
|
+
def method_call(is,signal)
|
109
|
+
self.method(signal).call(is) do |action|
|
110
|
+
case action
|
111
|
+
when :modified then @modified ||= true
|
112
|
+
when :save then save
|
113
|
+
when :close then close
|
114
|
+
end
|
73
115
|
end
|
74
|
-
|
116
|
+
end
|
75
117
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
suggestion += chr if chr =~/[A-Z]/i
|
118
|
+
def build_gui
|
119
|
+
Gtk2Password::Gui.new(@window) do |is,signal,*emits|
|
120
|
+
$stderr.puts "#{is},#{signal}:\t#{emits}" if $trace
|
121
|
+
method_call(is,signal)
|
81
122
|
end
|
82
|
-
|
123
|
+
end
|
83
124
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
suggestion += chr
|
125
|
+
def self.get_account(account)
|
126
|
+
if !account.nil? then
|
127
|
+
account.strip!
|
128
|
+
account = nil if account.length<1
|
89
129
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
130
|
+
return account
|
131
|
+
end
|
132
|
+
def get_account
|
133
|
+
App.get_account( @gui[:account_comboboxentry].active_text )
|
134
|
+
end
|
135
|
+
|
136
|
+
def clicked(is)
|
137
|
+
|
138
|
+
pwdlength = @gui[:password_spinbutton]
|
139
|
+
account = get_account
|
140
|
+
|
141
|
+
case is
|
142
|
+
|
143
|
+
when @gui[:url_button]
|
144
|
+
url = @gui[:url_entry].text.strip
|
145
|
+
Gtk2AppLib.run(url) if url =~ Configuration::URL_PATTERN
|
146
|
+
|
147
|
+
when @gui[:random_button]
|
148
|
+
suggestion = ''
|
149
|
+
pwdlength.value.to_i.times do
|
150
|
+
suggestion += (rand(94)+33).chr
|
101
151
|
end
|
102
|
-
|
152
|
+
@gui[:password_entry].text = suggestion
|
103
153
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
154
|
+
when @gui[:alpha_button]
|
155
|
+
suggestion = ''
|
156
|
+
while suggestion.length < pwdlength.value.to_i do
|
157
|
+
chr = (rand(75)+48).chr
|
158
|
+
suggestion += chr if chr =~/\w/
|
159
|
+
end
|
160
|
+
@gui[:password_entry].text = suggestion
|
161
|
+
|
162
|
+
when @gui[:numeric_button]
|
163
|
+
suggestion = ''
|
164
|
+
pwdlength.value.to_i.times do
|
165
|
+
chr = (rand(10)+48).chr
|
166
|
+
suggestion += chr
|
167
|
+
end
|
168
|
+
@gui[:password_entry].text = suggestion
|
169
|
+
|
170
|
+
when @gui[:letters_button]
|
171
|
+
suggestion = ''
|
172
|
+
while suggestion.length < pwdlength.value.to_i do
|
173
|
+
chr = (rand(58)+65).chr
|
174
|
+
suggestion += chr if chr =~/[A-Z]/i
|
175
|
+
end
|
176
|
+
@gui[:password_entry].text = suggestion
|
177
|
+
|
178
|
+
when @gui[:caps_button]
|
179
|
+
suggestion = ''
|
180
|
+
pwdlength.value.to_i.times do
|
181
|
+
chr = (rand(26)+65).chr
|
182
|
+
suggestion += chr
|
183
|
+
end
|
184
|
+
@gui[:password_entry].text = suggestion
|
185
|
+
|
186
|
+
when @gui[:delete_button]
|
187
|
+
# MODIFIES!!!
|
188
|
+
if account then
|
189
|
+
i = @passwords.accounts.index(account)
|
190
|
+
if i then
|
191
|
+
@passwords.delete(account)
|
192
|
+
@gui[:account_comboboxentry].remove_text(i)
|
193
|
+
@@index = (@gui[:account_comboboxentry].active = (i > 0)? i - 1: 0)
|
194
|
+
yield(:modified)
|
114
195
|
end
|
115
|
-
passwords.url_of(account, url)
|
116
|
-
passwords.note_of(account, shared[:Note_Entry].text.strip)
|
117
|
-
passwords.username_of(account, shared[:Username_Entry].text.strip)
|
118
|
-
password = shared[:Password_Entry].text.strip
|
119
|
-
passwords.password_of(account, password) if !passwords.verify?(account, password)
|
120
|
-
Gtk2AppLib::DIALOGS.quick_message(*Configuration::UPDATED)
|
121
|
-
else
|
122
|
-
Gtk2AppLib::DIALOGS.quick_message(*Configuration::BAD_URL)
|
123
196
|
end
|
124
|
-
end
|
125
197
|
|
126
|
-
|
127
|
-
|
128
|
-
if
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
198
|
+
when @gui[:update_button]
|
199
|
+
# MODIFIES!!!
|
200
|
+
if account then
|
201
|
+
url = @gui[:url_entry].text.strip
|
202
|
+
if url.length == 0 || url =~ Configuration::URL_PATTERN then
|
203
|
+
yield(:modified)
|
204
|
+
if !@passwords.include?(account) then
|
205
|
+
@passwords.add(account)
|
206
|
+
@@index = i = @passwords.accounts.index(account)
|
207
|
+
@gui[:account_comboboxentry].insert_text(i,account)
|
208
|
+
end
|
209
|
+
@passwords.url_of(account, url)
|
210
|
+
@passwords.note_of(account, @gui[:note_entry].text.strip)
|
211
|
+
@passwords.username_of(account, @gui[:username_entry].text.strip)
|
212
|
+
password = @gui[:password_entry].text.strip
|
213
|
+
@passwords.password_of(account, password) if !@passwords.verify?(account, password)
|
214
|
+
Gtk2AppLib::DIALOGS.quick_message(*Configuration::UPDATED)
|
215
|
+
else
|
216
|
+
Gtk2AppLib::DIALOGS.quick_message(*Configuration::BAD_URL)
|
134
217
|
end
|
135
|
-
dumpfile = passwords.save(pwd1)
|
136
|
-
Gtk2PasswordApp.passwords_updated(dumpfile)
|
137
218
|
end
|
138
|
-
end
|
139
219
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
220
|
+
when @gui[:datafile_button]
|
221
|
+
if pwd1 = Gtk2Password.get_salt('New Password') then
|
222
|
+
if pwd2 = Gtk2Password.get_salt('Verify') then
|
223
|
+
while !(pwd1==pwd2) do
|
224
|
+
pwd1 = Gtk2Password.get_salt('Try again!')
|
225
|
+
return if !pwd1
|
226
|
+
pwd2 = Gtk2Password.get_salt('Verify')
|
227
|
+
return if !pwd2
|
228
|
+
end
|
229
|
+
dumpfile = @passwords.save(pwd1)
|
230
|
+
Gtk2Password.passwords_updated(dumpfile)
|
231
|
+
end
|
232
|
+
end
|
145
233
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
234
|
+
when @gui[:current_button]
|
235
|
+
if account then
|
236
|
+
PRIMARY.text = @passwords.password_of(account)
|
237
|
+
CLIPBOARD.text = @passwords.username_of(account)
|
238
|
+
end
|
239
|
+
|
240
|
+
when @gui[:previous_button]
|
241
|
+
if account then
|
242
|
+
PRIMARY.text = @passwords.previous_password_of(account)
|
243
|
+
CLIPBOARD.text = @passwords.username_of(account)
|
244
|
+
end
|
245
|
+
|
246
|
+
when @gui[:save_button] then yield(:save)
|
247
|
+
when @gui[:cancel_button] then yield(:close)
|
248
|
+
else $stderr.puts "What? #{is} in #{is.parent.class}."
|
150
249
|
end
|
151
250
|
|
152
|
-
when shared[:Save_Button] then yield(:save)
|
153
|
-
when shared[:Cancel_Button] then yield(:close)
|
154
|
-
else $stderr.puts "What? #{is} in #{is.parent.class}."
|
155
251
|
end
|
156
252
|
|
157
|
-
|
253
|
+
def _changed_clear
|
254
|
+
@gui[:url_entry].text = ''
|
255
|
+
@gui[:note_entry].text = ''
|
256
|
+
@gui[:username_entry].text = ''
|
257
|
+
end
|
158
258
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
if account then
|
165
|
-
shared[:Password_Entry].text = ''
|
166
|
-
if passwords.include?(account) then
|
167
|
-
shared[:Url_Entry].text = passwords.url_of(account)
|
168
|
-
shared[:Note_Entry].text = passwords.note_of(account)
|
169
|
-
shared[:Username_Entry].text = passwords.username_of(account)
|
170
|
-
shared[:Password_Entry].text = passwords.password_of(account)
|
171
|
-
else
|
172
|
-
shared[:Url_Entry].text = ''
|
173
|
-
shared[:Note_Entry].text = ''
|
174
|
-
shared[:Username_Entry].text = ''
|
175
|
-
end
|
176
|
-
@@index = is.active
|
177
|
-
$stderr.puts "Index: #{@@index}" if $trace
|
178
|
-
end
|
179
|
-
else
|
180
|
-
$stderr.puts "What? Expected #{shared[:Account_ComboBoxEntry]}, got #{is}."
|
259
|
+
def _changed_set(account)
|
260
|
+
@gui[:url_entry].text = @passwords.url_of(account)
|
261
|
+
@gui[:note_entry].text = @passwords.note_of(account)
|
262
|
+
@gui[:username_entry].text = @passwords.username_of(account)
|
263
|
+
@gui[:password_entry].text = @passwords.password_of(account)
|
181
264
|
end
|
182
|
-
end
|
183
265
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
266
|
+
def _changed(is,account)
|
267
|
+
@gui[:password_entry].text = ''
|
268
|
+
(@passwords.include?(account))? _changed_set(account) : _changed_clear
|
269
|
+
@@index = is.active
|
270
|
+
$stderr.puts "Index: #{@@index}" if $trace
|
271
|
+
end
|
188
272
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
updates = [:Delete_Button,:Update_Button,:Save_Button]
|
193
|
-
updates.unshift(:Cancel_Button) if Gtk2AppLib::Configuration::MENU[:close]
|
194
|
-
|
195
|
-
vbox = 'Gtk2AppLib::Widgets::VBox'
|
196
|
-
hbox = 'Gtk2AppLib::Widgets::HBox'
|
197
|
-
classes = [
|
198
|
-
['Gui', vbox, [:Account_Component,:Url_Component,:Note_Component,:Username_Component,:Password_Component,:Buttons_Component]],
|
199
|
-
['Account', hbox, [:Account_Label,:Account_ComboBoxEntry]],
|
200
|
-
['Url', hbox, [:Url_Label,:Url_Entry,:Url_Button]],
|
201
|
-
['Note', hbox, [:Note_Label,:Note_Entry]],
|
202
|
-
['Username', hbox, [:Username_Label,:Username_Entry]],
|
203
|
-
['Password', hbox, [:Password_Label,:Password_Entry,:Password_CheckButton,:Password_SpinButton]],
|
204
|
-
['Buttons', vbox, [:Generators_Component,:Updates_Component,:Datafile_Component,:Clip_Component]],
|
205
|
-
['Generators', hbox, [:Random_Button,:Alpha_Button,:Numeric_Button,:Letters_Button,:Caps_Button]],
|
206
|
-
['Updates', hbox, updates],
|
207
|
-
['Datafile', hbox, [:Datafile_Button]],
|
208
|
-
['Clip', hbox, [:Current_Button,:Previous_Button]],
|
209
|
-
]
|
210
|
-
classes.each do |clss,spr,keys|
|
211
|
-
code = Gtk2AppLib::Component.define(clss,spr,keys)
|
212
|
-
$stderr.puts "<<<START CODE EVAL>>>\n#{code}\n<<<END CODE EVAL>>>" if $trace && $verbose
|
213
|
-
eval( code )
|
214
|
-
end
|
215
|
-
|
216
|
-
def self.init_code(clss,keys)
|
217
|
-
code = <<-EOT
|
218
|
-
class #{clss}
|
219
|
-
def _init(block)
|
220
|
-
EOT
|
221
|
-
keys.each do |key|
|
222
|
-
code += <<-EOT
|
223
|
-
SHARED[:#{key}] = self.#{key.to_s.downcase}
|
224
|
-
EOT
|
273
|
+
def changed(is)
|
274
|
+
if account = get_account then
|
275
|
+
_changed(is,account)
|
225
276
|
end
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
# Regardless of where in the gui they are...
|
234
|
-
[ ['Account', [:Account_ComboBoxEntry]],
|
235
|
-
['Url', [:Url_Entry,:Url_Button]],
|
236
|
-
['Note', [:Note_Entry]],
|
237
|
-
['Username', [:Username_Entry]],
|
238
|
-
['Password', [:Password_Entry,:Password_SpinButton]],
|
239
|
-
['Generators', [:Random_Button,:Alpha_Button,:Numeric_Button,:Letters_Button,:Caps_Button]],
|
240
|
-
['Updates', updates],
|
241
|
-
['Datafile', [:Datafile_Button]],
|
242
|
-
['Clip', [:Current_Button,:Previous_Button]],
|
243
|
-
].each do |clss,keys|
|
244
|
-
code = Component.init_code(clss,keys)
|
245
|
-
$stderr.puts "<<<START CODE EVAL>>>\n#{code}\n<<<END CODE EVAL>>>" if $trace && $verbose
|
246
|
-
eval( code )
|
277
|
+
end
|
278
|
+
|
279
|
+
def self.toggled(pwd)
|
280
|
+
pwd.visibility = !pwd.visibility?
|
281
|
+
end
|
282
|
+
def toggled(is)
|
283
|
+
App.toggled(@gui[:password_entry])
|
247
284
|
end
|
248
285
|
|
249
286
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gtk2passwordapp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 6
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.6.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- carlosjhr64@gmail.com
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-04-26 00:00:00 -07:00
|
19
19
|
default_executable: gtk2passwordapp
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -41,11 +41,11 @@ dependencies:
|
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
hash:
|
44
|
+
hash: 49
|
45
45
|
segments:
|
46
|
-
-
|
47
|
-
-
|
48
|
-
version: "
|
46
|
+
- 15
|
47
|
+
- 3
|
48
|
+
version: "15.3"
|
49
49
|
type: :runtime
|
50
50
|
version_requirements: *id002
|
51
51
|
description: |
|
@@ -70,7 +70,7 @@ files:
|
|
70
70
|
- ./pngs/icon.png
|
71
71
|
- README.txt
|
72
72
|
- bin/gtk2passwordapp
|
73
|
-
has_rdoc:
|
73
|
+
has_rdoc: false
|
74
74
|
homepage: https://sites.google.com/site/gtk2applib/home/gtk2applib-applications/gtk2passwordapp
|
75
75
|
licenses: []
|
76
76
|
|
@@ -99,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
99
|
version: "0"
|
100
100
|
requirements:
|
101
101
|
- gtk2
|
102
|
-
rubyforge_project:
|
102
|
+
rubyforge_project:
|
103
103
|
rubygems_version: 1.5.2
|
104
104
|
signing_key:
|
105
105
|
specification_version: 3
|