gtk2passwordapp 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|