gtk2passwordapp 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -5,45 +5,23 @@ Uses crypt-tea's Tiny Encryption Algorithm to encrypt the datafile.
5
5
  Features random password generator and clipboard use.
6
6
 
7
7
 
8
- To add an account, enter the new account name in the "Account:" entry/combo box.
9
- For the account, write the associated url, a note about the accout, and the username
10
- in the appropriate entry boxes.
11
-
12
- To set a new password, either enter the password in the "New:" entry box, or
13
- generate it by pressing "Random", "Alpha-Numeric", "Numeric", "Letters", or
14
- "All-Caps". One can set the password length generated with the spin-box.
15
- To make the password generated visible, un-check the check button.
16
-
17
- Once one has edited the account, clicking the "Update Account" button finalizes the record.
18
- Note, however, that the change is not yet permanent and saved on disk.
19
- To delete an account, select the account in the entry/combo box, and
20
- the press the "Delete Account" button.
21
- Once one is done with all updates, one then needs to press "Save To Disk".
22
- "Cancel All Changes" or closing the window without "Save To Disk" will ignore all of the sessions updates.
23
-
24
- The "Clip Current Password" button copies the current password to the primary clipboard.
25
- The "Clip Previous Password" button copies the previous (old) password to the primary clipboard.
26
-
27
- The "Change Data File Password" button will allow one the change
28
- the master password. Do not forget the master password!
29
-
30
- Right click most anywhere on the app's window for the main menu.
31
- "Close" will dock the app and has the same effect as "Cancel All Changes".
32
-
33
- Left click on the docked icon to bring back the editor window.
34
- Right click on the docked icon to select one of the accounts to load
35
- the password and username to the clipboard.
36
- The password is copied to the primary clipboard and will paste on
37
- middle mouse button click.
38
- Right click on an entry box to paste the username (via the clipboard's menu).
8
+ To add an account, enter the new account name in the "Account:" entry/combo box. For the account, write the associated url, a note about the account, and the username in the appropriate entry boxes.
9
+
10
+ To set a new password, either enter the password in the "New:" entry box, or generate it by pressing "Random", "Alpha-Numeric", "Numeric", "Letters", or "All-Caps". One can set the password length generated with the spin-box. To make the password generated visible, un-check the check button.
11
+
12
+ Once one has edited the account, clicking the "Update Account" button finalizes the record. Note, however, that the change is not yet permanent and saved on disk. To delete an account, select the account in the entry/combo box, and the press the "Delete Account" button. Once one is done with all updates, one then needs to press "Save To Disk". Clicking the "Close" button or closing the window without "Save To Disk" will ignore all of the sessions updates.
13
+
14
+ The "Clip Current Password" button copies the current password to the primary clipboard. The "Clip Previous Password" button copies the previous (old) password to the primary clipboard. The "Change Data File Password" button will allow one the change the master password. Do not forget the master password!
15
+
16
+ Right click most anywhere on the app's window for the main menu. "Close" will dock the app and has the same effect as the "Close" button.
17
+
18
+ Left click on the docked icon to bring back the editor window. Right click on the docked icon to select one of the accounts to load the password and username to the clipboard. The password is copied to the primary clipboard and will paste on middle mouse button click. Right click on an entry box to paste the username (via the clipboard's menu).
39
19
 
40
20
  Lastly, do not edit
41
21
  ~/.gtk2passwordapp-1/passphrase.txt
42
- It's used to "salt" the password... without it,
43
- one will not be able to decrypt the datafile.
22
+ It's used to "salt" the password... without it, one will not be able to decrypt the datafile.
44
23
 
45
24
  For full documentation and comments, see
46
-
47
- http://ruby-gnome-apps.blogspot.com/search/label/Passwords
25
+ https://sites.google.com/site/gtk2applib/home/gtk2applib-applications/gtk2passwordapp
48
26
 
49
27
  carlosjhr64@gmail.com
data/bin/gtk2passwordapp CHANGED
@@ -1,38 +1,69 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  require 'rubygems'
4
- gem 'gtk2applib', '~> 7'
3
+ gem 'gtk2applib', '~> 13.0'
5
4
  require 'gtk2applib'
6
5
 
7
6
  include Gtk2AppLib
8
- PROGRAM = Program.new( {
9
- :name => 'Ruby-Gnome Password Manager',
10
- :tooltip => 'Password Manager',
11
- :icon_name => 'Passwords',
12
- :FILE => __FILE__,
13
- :lock => "Proceed anyways?",
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
14
  } )
15
15
 
16
16
  begin
17
17
  require 'gtk2passwordapp'
18
- passwords = Gtk2PasswordApp::Passwords.new
19
- Gtk2PasswordApp.build_menu(passwords)
20
18
 
21
- about = {
22
- :authors => ['carlosjhr64@gmail.com'],
23
- :website => 'http://ruby-gnome-apps.blogspot.com/search/label/Passwords',
24
- :website_label => 'Ruby-Gnome Password Manager',
25
- :license => 'GPL',
26
- :copyright => '2010-08-17 19:00:27',
27
- }
19
+ passwords = Gtk2PasswordApp::Passwords.new
20
+ Gtk2PasswordApp.build_menu(program,passwords)
28
21
 
29
- PROGRAM.window(about) do |window|
30
- Gtk2PasswordApp.edit(window,passwords)
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
31
62
  end
32
63
  rescue Exception
33
64
  $verbose = true
34
- Gtk2AppLib.puts_bang!
65
+ $!.puts_bang!
35
66
  ensure
36
- PROGRAM.finalize
67
+ program.finalize
37
68
  end
38
69
 
@@ -1,275 +1,250 @@
1
1
  require 'gtk2passwordapp/passwords'
2
2
  module Gtk2PasswordApp
3
- include Configuration
4
- PRIMARY = Gtk::Clipboard.get((SWITCH_CLIPBOARDS)? Gdk::Selection::CLIPBOARD: Gdk::Selection::PRIMARY)
5
- CLIPBOARD = Gtk::Clipboard.get((SWITCH_CLIPBOARDS)? Gdk::Selection::PRIMARY: Gdk::Selection::CLIPBOARD)
6
3
 
7
- @@index = nil
8
- def self.build_menu(passwords)
9
- passwords.accounts.each {|account|
10
- item = PROGRAM.dock_menu.append_menu_item(account){
11
- @@index = passwords.accounts.index(account)
12
- PRIMARY.text = passwords.password_of(account)
13
- CLIPBOARD.text = passwords.username_of(account)
14
- }
15
- item.child.modify_fg(Gtk::STATE_NORMAL, COLOR[:red]) if passwords.expired?(account)
16
- }
17
- PROGRAM.dock_menu.show_all
18
- end
19
- def self.rebuild_menu(passwords)
20
- items = PROGRAM.dock_menu.children
21
- 3.times{ items.shift } # shift out Quit, Run, and Spacer
22
- while item = items.shift do
23
- PROGRAM.dock_menu.remove(item)
24
- item.destroy
25
- end
26
- Gtk2PasswordApp.build_menu(passwords)
27
- end
4
+ PRIMARY = Gtk::Clipboard.get((Configuration::SWITCH_CLIPBOARDS)? Gdk::Selection::CLIPBOARD: Gdk::Selection::PRIMARY)
5
+ CLIPBOARD = Gtk::Clipboard.get((Configuration::SWITCH_CLIPBOARDS)? Gdk::Selection::PRIMARY: Gdk::Selection::CLIPBOARD)
28
6
 
29
- def self.get_salt(prompt,title=prompt)
30
- Gtk2AppLib::DIALOGS.entry(prompt,{:title=>title,:visibility=>false})
31
- end
32
-
33
- EDITOR_LABELS = [
34
- :account,
35
- :url,
36
- :note,
37
- :username,
38
- :password,
39
- ]
40
-
41
-
42
- EDITOR_BUTTONS = [
43
- [ :random, :alphanum, :num, :alpha, :caps, ],
44
- [ :cancel, :delete, :update, :save, ],
45
- [ :cpwd ],
46
- [ :current, :previous, ],
47
- ]
48
-
49
- TEXT = {
50
- # Labels
51
- :account => 'Account',
52
- :note => 'Note',
53
- :password => 'New',
54
- # Buttons
55
- :username => 'Username',
56
- :current => 'Clip Current Password',
57
- :url => 'Url',
58
- :note => 'Note',
59
- :edit => 'Edit',
60
- :update => 'Update Account',
61
- :alphanum => 'Alpha-Numeric',
62
- :num => 'Numeric',
63
- :alpha => 'Letters',
64
- :caps => 'All-Caps',
65
- :random => 'Random',
66
- :previous => 'Clip Previous Password',
67
- :quit => 'Quit',
68
- :cancel => 'Cancel All Changes',
69
- :save => 'Save To Disk',
70
- :cpwd => 'Change Data File Password',
71
- :delete => 'Delete Account',
72
- }
73
-
74
- def self.edit(window, passwords)
75
- dialog_options = {:window=>window}
76
- updated = false # only saves data if data updated
7
+ @@index = 0
8
+ def self.index
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
24
+ end
77
25
 
78
- vbox = Gtk2AppLib::VBox.new(window)
79
-
80
- goto_url = pwdlength = visibility = nil
81
-
82
- widget = {}
83
- EDITOR_LABELS.each {|s|
84
- hbox = Gtk2AppLib::HBox.new(vbox)
85
- label = Gtk2AppLib::Label.new(TEXT[s]+':',hbox,{:label_width=>LABEL_WIDTH})
86
- dx = ((s == :password)? (SPIN_BUTTON_LENGTH+2*PADDING+30): ((s == :url)? (GO_BUTTON_LENGTH+2*PADDING): 0))
87
- width = ENTRY_WIDTH - dx
88
- widget[s] = (s==:account)?
89
- Gtk2AppLib::ComboBoxEntry.new(passwords.accounts,hbox,{:comboboxentry_width=>width}) :
90
- Gtk2AppLib::Entry.new('',hbox,{:entry_width=>width})
26
+ def self.save(program,passwords)
27
+ dumpfile = passwords.save
28
+ Gtk2PasswordApp.passwords_updated(dumpfile)
29
+ Gtk2PasswordApp.build_menu(program,passwords)
30
+ end
91
31
 
92
- if s == :password then
93
- visibility = Gtk2AppLib::CheckButton.new(hbox,{:active=>true})
94
- pwdlength = Gtk2AppLib::SpinButton.new(hbox)
95
- pwdlength.value = DEFAULT_PASSWORD_LENGTH
96
- elsif s == :url then
97
- goto_url = Gtk2AppLib::Button.new('Go',hbox,{:button_width=>GO_BUTTON_LENGTH}){
98
- # The go button opens the url in a browser
99
- system("#{APP[:browser]} #{widget[:url].text} > /dev/null 2> /dev/null &")
100
- }
101
- end
102
- }
32
+ def self.get_salt(prompt,title=prompt)
33
+ Gtk2AppLib::DIALOGS.entry( prompt, {:Title=>title, :Entry => [{:visibility= => false},'activate']} )
34
+ end
103
35
 
104
- EDITOR_BUTTONS.each{|row|
105
- hbox = Gtk2AppLib::HBox.new(vbox)
106
- row.each {|s| widget[s] = Gtk2AppLib::Button.new(TEXT[s],hbox) }
107
- }
108
-
109
- widget[:account].active = @@index if @@index
110
- account_changed = proc {
111
- account = (widget[:account].active_text)? widget[:account].active_text.strip: ''
112
- if account.length > 0 then
113
- widget[:password].text = ''
114
- if passwords.include?(account) then
115
- widget[:url].text = passwords.url_of(account)
116
- widget[:note].text = passwords.note_of(account)
117
- widget[:username].text = passwords.username_of(account)
118
- else
119
- widget[:url].text = ''
120
- widget[:note].text = ''
121
- widget[:username].text = ''
122
- end
123
- @@index = widget[:account].active
124
- end
125
- }
126
- account_changed.call
127
- widget[:account].signal_connect('changed'){
128
- account_changed.call
129
- }
130
-
131
- # New Password
132
- widget[:password].visibility = false
133
-
134
- # Update
135
- widget[:update].signal_connect('clicked'){
136
- url = widget[:url].text.strip
137
- if url.length == 0 || url =~ URL_PATTERN then
138
- account = (widget[:account].active_text)? widget[:account].active_text.strip: ''
139
- if account.length > 0 then
140
- updated = true if !updated
141
- if !passwords.include?(account) then
142
- passwords.add(account)
143
- @@index = i = passwords.accounts.index(account)
144
- widget[:account].insert_text(i,account)
145
- end
146
- passwords.url_of(account, url)
147
- passwords.note_of(account, widget[:note].text.strip)
148
- passwords.username_of(account, widget[:username].text.strip)
149
- password = widget[:password].text.strip
150
- if password.length > 0 then
151
- passwords.password_of(account, password) if !passwords.verify?(account, password)
152
- widget[:password].text = ''
153
- end
154
- end
155
- else
156
- Gtk2AppLib::DIALOGS.quick_message('Need url like http://www.site.com/page.html', dialog_options)
157
- end
158
- }
159
-
160
- # Random
161
- widget[:random].signal_connect('clicked'){
162
- suggestion = ''
163
- pwdlength.value.to_i.times do
164
- suggestion += (rand(94)+33).chr
165
- end
166
- widget[:password].text = suggestion
167
- }
168
- # Alpha-Numeric
169
- widget[:alphanum].signal_connect('clicked'){
170
- suggestion = ''
171
- while suggestion.length < pwdlength.value.to_i do
172
- chr = (rand(75)+48).chr
173
- suggestion += chr if chr =~/\w/
174
- end
175
- widget[:password].text = suggestion
176
- }
177
- # Numeric
178
- widget[:num].signal_connect('clicked'){
179
- suggestion = ''
180
- pwdlength.value.to_i.times do
181
- chr = (rand(10)+48).chr
182
- suggestion += chr
183
- end
184
- widget[:password].text = suggestion
185
- }
186
- # Letters
187
- widget[:alpha].signal_connect('clicked'){
188
- suggestion = ''
189
- while suggestion.length < pwdlength.value.to_i do
190
- chr = (rand(58)+65).chr
191
- suggestion += chr if chr =~/[A-Z]/i
192
- end
193
- widget[:password].text = suggestion
194
- }
195
- # Caps
196
- widget[:caps].signal_connect('clicked'){
197
- suggestion = ''
198
- pwdlength.value.to_i.times do
199
- chr = (rand(26)+65).chr
200
- suggestion += chr
201
- end
202
- widget[:password].text = suggestion
203
- }
204
-
205
- # Visibility
206
- visibility.signal_connect('clicked'){
207
- widget[:password].visibility = !widget[:password].visibility?
208
- }
209
-
210
- # Current
211
- widget[:current].signal_connect('clicked'){
212
- account = (widget[:account].active_text)? widget[:account].active_text.strip: ''
213
- PRIMARY.text = passwords.password_of(account)
214
- CLIPBOARD.text = passwords.username_of(account)
215
- }
216
-
217
- # Previous
218
- widget[:previous].signal_connect('clicked'){
219
- account = (widget[:account].active_text)? widget[:account].active_text.strip: ''
220
- PRIMARY.text = passwords.previous_password_of(account)
221
- CLIPBOARD.text = passwords.username_of(account)
222
- }
223
-
224
- # Change Password
225
- widget[:cpwd].signal_connect('clicked'){
226
- if pwd1 = Gtk2PasswordApp.get_salt('New Password') then
227
- if pwd2 = Gtk2PasswordApp.get_salt('Verify') then
228
- while !(pwd1==pwd2) do
229
- pwd1 = Gtk2PasswordApp.get_salt('Try again!')
230
- return if !pwd1
231
- pwd2 = Gtk2PasswordApp.get_salt('Verify')
232
- return if !pwd2
233
- end
234
- Gtk2AppLib.passwords_updated( passwords.save(pwd1) )
235
- end
236
- end
237
- }
238
-
239
- # Save
240
- widget[:save].signal_connect('clicked'){
241
- if updated then
242
- Gtk2AppLib.passwords_updated( passwords.save )
243
- updated = false
244
- Gtk2PasswordApp.rebuild_menu(passwords)
245
- end
246
- PROGRAM.close
247
- }
248
-
249
- # Delete
250
- widget[:delete].signal_connect('clicked'){
251
- account = (widget[:account].active_text)? widget[:account].active_text.strip: nil
252
- if account then
253
- i = passwords.accounts.index(account)
254
- if i then
255
- passwords.delete(account)
256
- widget[:account].remove_text(i)
257
- @@index = (widget[:account].active = (i > 0)? i - 1: 0)
258
- updated = true
259
- Gtk2AppLib::DIALOGS.quick_message("#{account} deleted.", dialog_options)
260
- end
261
- end
262
- }
36
+ def self.account( shared = Component::SHARED )
37
+ account = (shared[:Account_ComboBoxEntry].active_text)? shared[:Account_ComboBoxEntry].active_text.strip: ''
38
+ (account.length>0)? account: nil
39
+ end
263
40
 
264
- # Cancel
265
- widget[:cancel].signal_connect('clicked'){ PROGRAM.close }
266
- window.signal_connect('destroy'){
267
- if updated then
268
- passwords.load # revert
269
- updated = false
270
- end
271
- }
272
-
273
- window.show_all
274
- end
41
+ def self.clicked(is,passwords)
42
+
43
+ shared = Component::SHARED
44
+ pwdlength = shared[:Password_SpinButton]
45
+ account = Gtk2PasswordApp.account
46
+
47
+ case is
48
+
49
+ when shared[:Url_Button]
50
+ url = shared[:Url_Entry].text.strip
51
+ Gtk2AppLib.run(url) if url =~ Configuration::URL_PATTERN
52
+
53
+ when shared[:Random_Button]
54
+ suggestion = ''
55
+ pwdlength.value.to_i.times do
56
+ suggestion += (rand(94)+33).chr
57
+ end
58
+ shared[:Password_Entry].text = suggestion
59
+
60
+ when shared[:Alpha_Button]
61
+ suggestion = ''
62
+ while suggestion.length < pwdlength.value.to_i do
63
+ chr = (rand(75)+48).chr
64
+ suggestion += chr if chr =~/\w/
65
+ end
66
+ shared[:Password_Entry].text = suggestion
67
+
68
+ when shared[:Numeric_Button]
69
+ suggestion = ''
70
+ pwdlength.value.to_i.times do
71
+ chr = (rand(10)+48).chr
72
+ suggestion += chr
73
+ end
74
+ shared[:Password_Entry].text = suggestion
75
+
76
+ when shared[:Letters_Button]
77
+ suggestion = ''
78
+ while suggestion.length < pwdlength.value.to_i do
79
+ chr = (rand(58)+65).chr
80
+ suggestion += chr if chr =~/[A-Z]/i
81
+ end
82
+ shared[:Password_Entry].text = suggestion
83
+
84
+ when shared[:Caps_Button]
85
+ suggestion = ''
86
+ pwdlength.value.to_i.times do
87
+ chr = (rand(26)+65).chr
88
+ suggestion += chr
89
+ end
90
+ shared[:Password_Entry].text = suggestion
91
+
92
+ when shared[:Delete_Button]
93
+ # MODIFIES!!!
94
+ if account then
95
+ i = passwords.accounts.index(account)
96
+ if i then
97
+ passwords.delete(account)
98
+ shared[:Account_ComboBoxEntry].remove_text(i)
99
+ @@index = (shared[:Account_ComboBoxEntry].active = (i > 0)? i - 1: 0)
100
+ yield(:modified)
101
+ end
102
+ end
103
+
104
+ when shared[:Update_Button]
105
+ # MODIFIES!!!
106
+ if account then
107
+ url = shared[:Url_Entry].text.strip
108
+ if url.length == 0 || url =~ Configuration::URL_PATTERN then
109
+ yield(:modified)
110
+ if !passwords.include?(account) then
111
+ passwords.add(account)
112
+ @@index = i = passwords.accounts.index(account)
113
+ shared[:Account_ComboBoxEntry].insert_text(i,account)
114
+ 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
+ end
124
+ end
125
+
126
+ when shared[:Datafile_Button]
127
+ if pwd1 = Gtk2PasswordApp.get_salt('New Password') then
128
+ if pwd2 = Gtk2PasswordApp.get_salt('Verify') then
129
+ while !(pwd1==pwd2) do
130
+ pwd1 = Gtk2PasswordApp.get_salt('Try again!')
131
+ return if !pwd1
132
+ pwd2 = Gtk2PasswordApp.get_salt('Verify')
133
+ return if !pwd2
134
+ end
135
+ dumpfile = passwords.save(pwd1)
136
+ Gtk2PasswordApp.passwords_updated(dumpfile)
137
+ end
138
+ end
139
+
140
+ when shared[:Current_Button]
141
+ if account then
142
+ PRIMARY.text = passwords.password_of(account)
143
+ CLIPBOARD.text = passwords.username_of(account)
144
+ end
145
+
146
+ when shared[:Previous_Button]
147
+ if account then
148
+ PRIMARY.text = passwords.previous_password_of(account)
149
+ CLIPBOARD.text = passwords.username_of(account)
150
+ end
151
+
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
+ end
156
+
157
+ end
158
+
159
+ def self.changed(is,passwords)
160
+ shared = Component::SHARED
161
+ account = Gtk2PasswordApp.account
162
+ case is
163
+ when shared[:Account_ComboBoxEntry]
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}."
181
+ end
182
+ end
183
+
184
+ def self.toggled(is,passwords)
185
+ pwd = Component::SHARED[:Password_Entry]
186
+ pwd.visibility = !pwd.visibility?
187
+ end
188
+
189
+ module Component
190
+ SHARED = {}
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
225
+ end
226
+ code += <<-EOT
227
+ end
228
+ end
229
+ EOT
230
+ code
231
+ end
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 )
247
+ end
248
+
249
+ end
275
250
  end
@@ -2,47 +2,115 @@
2
2
  # Do not edit or delete passphrase, or you'll loose your passwords data.
3
3
 
4
4
  module Gtk2AppLib
5
+ # Only one gtk2passwordapp will be allowed to run.
6
+ # Will kill a duplicate proccess...
7
+ Lock.lock_mode
5
8
  module Configuration
6
- # Note that the passwords data file name is auto generated, but...
7
- # You can place your passwords data file in a directory other than ~/gtk2passwordapp-*
8
- PASSWORDS_DATA_DIR = UserSpace::DIRECTORY
9
9
 
10
- HILDON = (WRAPPER.to_s =~ /HildonWrapper/)? true: false
10
+ padding = Widgets::WIDGET[:Widgets][:pack_start].last
11
+ go = 50
12
+ label = 75
13
+ entry = 300
14
+ spin = 60
15
+ check = 20
11
16
 
12
- GO_BUTTON_LENGTH = 50
13
- SPIN_BUTTON_LENGTH = 60
14
- PADDING = 2
15
- ENTRY_WIDTH = (HILDON)? 600: 300
16
- LABEL_WIDTH = 75
17
+ if HILDON then
18
+ # WIDGET_OPTIONS[:font] =
19
+ FONT[:Normal] = FONT[:Large] = Pango::FontDescription.new( 'Arial 18' )
20
+ go = 75
21
+ label = 150
22
+ entry = 500
23
+ spin = 75
24
+ check = 25
25
+ if Gtk2AppLib::Configuration::OSTYPE == 'Internet Tablet OS: maemo Linux based OS2008' then
26
+ # Icon works on N800, but not N800 (Maemo 5)
27
+ MENU[:close] = '_Close'
28
+ end
29
+ else
30
+ WINDOW_DEFAULT_SIZE[0],WINDOW_DEFAULT_SIZE[1] = 100,100
31
+ MENU[:close] = '_Close'
32
+ end
17
33
 
34
+ wrap = {:wrap= => true}
35
+ label_width = {:width_request= => label, :wrap= => true}
36
+ entry_width = {:width_request= => entry}
37
+ entry_shorten = {:width_request= => entry - go - 2*padding}
38
+ entry_shorten2 = {:width_request= => entry - spin - check - 4*padding, :visibility= => false}
39
+ go_width = {:width_request= => go}
40
+ check_width = {:width_request= => check, :active= => true}
41
+ spin_width = {:width_request= => spin, :set_range => [3,30]}
42
+ clicked = 'clicked'
18
43
 
19
- # Switches the roles of PRIMARY and CLIPBOARD when true
20
- SWITCH_CLIPBOARDS = HILDON
44
+ PARAMETERS[:Account_Label] = ['Account:',label_width]
45
+ # nil needs to be set to the accounts list in bin/gtk2passwordapp
46
+ PARAMETERS[:Account_ComboBoxEntry] = [nil,entry_width,'changed'] # catching changed signal
21
47
 
22
- PASSWORD_EXPIRED = 60*60*24*30*3 # 3 months
48
+ PARAMETERS[:Url_Label] = ['Url:',label_width]
49
+ PARAMETERS[:Url_Entry] = [entry_shorten]
50
+ PARAMETERS[:Url_Button] = ['Go!',go_width,clicked]
23
51
 
24
- URL_PATTERN = Regexp.new('^https?:\/\/[^\s\']+$')
52
+ PARAMETERS[:Note_Label] = ['Note:',label_width]
53
+ PARAMETERS[:Note_Entry] = [entry_width]
25
54
 
26
- if HILDON then
27
- WIDGET_OPTIONS[:font] = FONT[:normal] = FONT[:large] = Pango::FontDescription.new( 'Arial 18' )
28
- end
55
+ PARAMETERS[:Username_Label] = ['Username:',label_width]
56
+ PARAMETERS[:Username_Entry] = [entry_width]
57
+
58
+ PARAMETERS[:Password_Label] = ['Password:',label_width]
59
+ PARAMETERS[:Password_Entry] = [entry_shorten2]
60
+ PARAMETERS[:Password_CheckButton] = [check_width,'toggled']
61
+ PARAMETERS[:Password_SpinButton] = [spin_width]
29
62
 
30
- MENU[:close] = '_Close'
63
+ PARAMETERS[:Random_Button] = ['Random',clicked]
64
+ PARAMETERS[:Alpha_Button] = ['Alpha-Numeric',clicked]
65
+ PARAMETERS[:Numeric_Button] = ['Numeric',clicked]
66
+ PARAMETERS[:Letters_Button] = ['Letters',clicked]
67
+ PARAMETERS[:Caps_Button] = ['All-Caps',clicked]
31
68
 
32
- WINDOW_DEFAULT_SIZE[0],WINDOW_DEFAULT_SIZE[1] = 100,100
69
+ PARAMETERS[:Cancel_Button] = ['Close',clicked]
70
+ PARAMETERS[:Delete_Button] = ['Delete Account',clicked]
71
+ PARAMETERS[:Update_Button] = ['Update Account',clicked]
72
+ PARAMETERS[:Save_Button] = ['Save To Disk',clicked]
33
73
 
34
- WIDGET_OPTIONS[:max] = 20 # MAX PASSWORD LENGTH
35
- WIDGET_OPTIONS[:min] = 3 # MIN PASSWORD LENGTH
74
+ PARAMETERS[:Datafile_Button] = ['Change Data File Password',clicked]
75
+
76
+ PARAMETERS[:Current_Button] = ['Clip Current Password',clicked]
77
+ PARAMETERS[:Previous_Button] = ['Clip Previous Password',clicked]
78
+ end
79
+ end
80
+
81
+ module Gtk2PasswordApp
82
+ module Configuration
83
+ # Note that the passwords data file name is auto generated, but...
84
+ # You can place your passwords data file in a directory other than ~/gtk2passwordapp-*
85
+ PASSWORDS_DATA_DIR = Gtk2AppLib::USERDIR
86
+ # Switches the roles of PRIMARY and CLIPBOARD when true
87
+ SWITCH_CLIPBOARDS = (Gtk2AppLib::HILDON || !Gtk2AppLib::Configuration::X)? true: false
88
+ PASSWORD_EXPIRED = 60*60*24*30*3 # 3 months
89
+ URL_PATTERN = Regexp.new('^https?:\/\/[^\s\']+$')
36
90
  DEFAULT_PASSWORD_LENGTH = 7
91
+ EXPIRED_COLOR = Gtk2AppLib::Color[:Red]
37
92
 
38
- WIDGET_OPTIONS[:spinbutton_width] = SPIN_BUTTON_LENGTH
39
- WIDGET_OPTIONS[:padding] = PADDING
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}]
40
98
  end
41
99
 
42
100
  def self.passwords_updated(dumpfile)
43
- # After the password files are saved, you have the option here to backup or mirror the files elsewhere....
44
- #fn = File.basename(dumpfile)
45
- #system( "scp #{dumpfile} user@192.168.1.123:.gtk2passwordapp-1/#{fn}")
46
- #system( "scp #{Configuration::PASSWORDS_DATA_DIR}/passphrase.txt user@192.168.1.123:.gtk2passwordapp-1/passphrase.txt")
101
+ ## After the password files are saved, you have the option here to backup or mirror the files elsewhere.
102
+ ## Here's an example:
103
+ # system( "ssh user@192.168.1.123 mv .gtk2passwordapp-1/*.dat .gtk2passwordapp-1/bak/")
104
+ # system( "ssh user@192.168.1.123 cp .gtk2passwordapp-1/passphrase.txt .gtk2passwordapp-1/bak/passphrase.txt") # you might choose not too.
105
+ # fn = File.basename(dumpfile)
106
+ # if system( "scp #{dumpfile} user@192.168.1.123:.gtk2passwordapp-1/#{fn}") then
107
+ # # again, you might choose not to distribute passphrase (reduces cracking to your short password)
108
+ # if system( "scp #{Configuration::PASSWORDS_DATA_DIR}/passphrase.txt user@192.168.1.123:.gtk2passwordapp-1/passphrase.txt") then
109
+ # Gtk2AppLib::DIALOGS.quick_message("Passwords saved on 192.168.1.101 and 102")
110
+ # return
111
+ # end
112
+ # end
113
+ # Gtk2AppLib::DIALOGS.quick_message("Warning: Could not create backup on 192.168.1.123")
114
+ Gtk2AppLib::DIALOGS.quick_message("Passwords Data Saved.",{:Title => 'Saved',:Scrolled_Window => false})
47
115
  end
48
116
  end
@@ -17,7 +17,7 @@ class Passwords < PasswordsData
17
17
  def get_passphrase(mv=false)
18
18
  passphrase = ''
19
19
 
20
- @pfile = UserSpace::DIRECTORY+'/passphrase.txt'
20
+ @pfile = Gtk2AppLib::USERDIR+'/passphrase.txt'
21
21
  if mv then
22
22
  File.rename(@pfile, @pfile+'.bak') if File.exist?(@pfile)
23
23
  passphrase = _create_passphrase
@@ -33,8 +33,8 @@ class Passwords < PasswordsData
33
33
  end
34
34
 
35
35
  def has_datafile?
36
- Find.find(UserSpace::DIRECTORY){|fn|
37
- Find.prune if !(fn==UserSpace::DIRECTORY) && File.directory?(fn)
36
+ Find.find(Gtk2AppLib::USERDIR){|fn|
37
+ Find.prune if !(fn==Gtk2AppLib::USERDIR) && File.directory?(fn)
38
38
  if fn =~/[0123456789abcdef]{32}\.dat$/ then
39
39
  return true
40
40
  end
@@ -74,6 +74,8 @@ class Passwords < PasswordsData
74
74
  pwd = Passwords._get_salt('Try again!')
75
75
  @pwd = Passwords._get_salt('Verify New Password')
76
76
  end
77
+ super(@pwd+@pph)
78
+ self.save
77
79
  end
78
80
  end
79
81
  # Off to the races...
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: 7
5
- prerelease: false
4
+ hash: 3
5
+ prerelease:
6
6
  segments:
7
7
  - 1
8
- - 4
8
+ - 5
9
9
  - 0
10
- version: 1.4.0
10
+ version: 1.5.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: 2010-08-17 00:00:00 -07:00
18
+ date: 2011-03-07 00:00:00 -08:00
19
19
  default_executable: gtk2passwordapp
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -26,12 +26,11 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 27
29
+ hash: 9
30
30
  segments:
31
31
  - 1
32
32
  - 3
33
- - 0
34
- version: 1.3.0
33
+ version: "1.3"
35
34
  type: :runtime
36
35
  version_requirements: *id001
37
36
  - !ruby/object:Gem::Dependency
@@ -42,10 +41,11 @@ dependencies:
42
41
  requirements:
43
42
  - - ~>
44
43
  - !ruby/object:Gem::Version
45
- hash: 13
44
+ hash: 63
46
45
  segments:
47
- - 7
48
- version: "7"
46
+ - 13
47
+ - 0
48
+ version: "13.0"
49
49
  type: :runtime
50
50
  version_requirements: *id002
51
51
  description: |
@@ -71,7 +71,7 @@ files:
71
71
  - README.txt
72
72
  - bin/gtk2passwordapp
73
73
  has_rdoc: true
74
- homepage: http://ruby-gnome-apps.blogspot.com/search/label/Passwords
74
+ homepage: https://sites.google.com/site/gtk2applib/home/gtk2applib-applications/gtk2passwordapp
75
75
  licenses: []
76
76
 
77
77
  post_install_message:
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - gtk2
102
102
  rubyforge_project: gtk2passwordapp
103
- rubygems_version: 1.3.7
103
+ rubygems_version: 1.5.2
104
104
  signing_key:
105
105
  specification_version: 3
106
106
  summary: Ruby-Gnome Password Manager