gnetvibes 0.1

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/gnetvibes ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $KCODE = "U"
4
+ require 'rubygems'
5
+
6
+ require 'fileutils'
7
+ require 'gtk2'
8
+
9
+ require 'gnetvibes/config'
10
+ require 'gnetvibes/gui'
11
+
12
+ FileUtils.mkdir_p(GNetvibes::CACHE) if not File.exists?(GNetvibes::CACHE)
13
+
14
+ gui = GNetvibes::GUI.new
15
+ gui.login_dialog.show_all
16
+ gui.login_dialog.run
17
+
18
+ Gtk.main
@@ -0,0 +1,117 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'cgi'
4
+ require 'digest/sha1'
5
+
6
+ module GNetvibes
7
+ class API
8
+
9
+ URL = {
10
+ :base => URI.parse('http://www.netvibes.com'),
11
+ :login => URI.parse('http://www.netvibes.com/user/signIn.php'),
12
+ :data => URI.parse('http://www.netvibes.com/get/userData.php'),
13
+ :save => URI.parse('http://www.netvibes.com/save/userData.php')
14
+ }
15
+
16
+ attr_reader :tabs, :modules
17
+
18
+ def initialize
19
+ @active_user_id = nil
20
+ @active_session_id = nil
21
+ @data = nil
22
+ @key = nil
23
+ end
24
+
25
+ def login(email, password)
26
+ res = Net::HTTP.post_form(URL[:login], {'email'=> email.strip, 'password' => password.strip})
27
+ if res.body.strip == 'success'
28
+ @key = Digest::SHA1.new(email + password).hexdigest
29
+ cookies = CGI::Cookie::parse(res['set-cookie'])
30
+ @active_user_id = cookies['activeUserID'].value
31
+ @active_session_id = cookies['activeSessionID'].value
32
+ refresh
33
+ true
34
+ else
35
+ false
36
+ end
37
+ end
38
+
39
+ def refresh(force = false)
40
+ if not force and File.exists?(DATA) and File.mtime(DATA) > Time.now - EXPIRE
41
+ @data = eval(crypt(File.read(DATA), @key))
42
+ else
43
+ res = Net::HTTP.start(URL[:data].host, URL[:data].port) do |http|
44
+ headers = {'Cookie' => "activeUserID=#{@active_user_id}; activeSessionID=#{@active_session_id}"}
45
+ http.request(Net::HTTP::Get.new(URL[:data].path, headers))
46
+ end
47
+ @data = json2ruby(unicode(res.body))
48
+ dump
49
+ end
50
+ @tabs = {}
51
+ @modules = {}
52
+ @data['tabs'].each { |t| @tabs[t['id'].to_i] = t }
53
+ @data['modules'].each { |m| @modules[m['id'].to_i] = m }
54
+ true
55
+ end
56
+
57
+ def each_modules_in_tab(tab)
58
+ @data['modules'].select{|m| m['tab'].to_i == tab.to_i}.each do |m|
59
+ yield m
60
+ end
61
+ end
62
+
63
+ def each_todo_list_item(mod)
64
+ raise "Module is not a TodoList" if @modules[mod.to_i]['name'] != 'TodoList'
65
+ list = []
66
+ data = @modules[mod.to_i]['data']
67
+ data.select{|k,v| k =~ /^tdval/}.each do |k,v|
68
+ id = k[/\d+$/].to_i
69
+ list[id] = { 'title' => v, 'checked' => data["tdchk_#{id}"].to_i == 1 }
70
+ end
71
+ list.each do |i|
72
+ yield i
73
+ end
74
+ end
75
+
76
+ def dump
77
+ File.open(DATA, 'w') do |fd|
78
+ fd.write crypt(@data.inspect, @key)
79
+ end
80
+ end
81
+
82
+ def download(uri)
83
+ if uri =~ /^\//
84
+ url = URL[:base] + uri
85
+ else
86
+ url = URI.parse(uri)
87
+ end
88
+ req = Net::HTTP::Get.new(url.path)
89
+ res = Net::HTTP.start(url.host, url.port) {|http| http.request(req) }
90
+ res.body
91
+ end
92
+
93
+ private
94
+
95
+ UNICODE_TABLE = {
96
+ 'u00b0' => '°', 'u00e0' => 'à', 'u00e2' => 'â', 'u00e7' => 'ç',
97
+ 'u00e8' => 'è', 'u00e9' => 'é', 'u00ea' => 'ê', 'u00ee' => 'î',
98
+ 'u00f4' => 'ô', 'u2019' => '\''
99
+ }
100
+
101
+ def unicode(s)
102
+ s.gsub(/u[a-f\d]{4}/) { |c| UNICODE_TABLE[c] }
103
+ end
104
+
105
+ def json2ruby(s)
106
+ eval(s.gsub(/":/, '"=>'))
107
+ end
108
+
109
+ def crypt(buf, key)
110
+ buf = buf.unpack("c*")
111
+ key = key.unpack("c*")
112
+ key *= buf.size / key.size + 1
113
+ buf.zip(key).collect{|c1,c2| c1^c2}.pack("c*")
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,72 @@
1
+ require 'gnetvibes/api'
2
+ require 'digest/sha1'
3
+
4
+ module GNetvibes
5
+ class GUI
6
+
7
+ def edit(obj, mod)
8
+ mod = @api.modules[mod.to_i]
9
+ @title.text = mod['title']
10
+ @buf.text = mod['data']['text'].strip
11
+ @txt.grab_focus
12
+ @edit_dialog.show_all
13
+ @edit_dialog.run
14
+ end
15
+
16
+ def save(obj, ev)
17
+ if ev == Gtk::Dialog::RESPONSE_ACCEPT
18
+ puts "save"
19
+ end
20
+ @edit_dialog.hide_on_delete
21
+ end
22
+
23
+ def login(obj, ev)
24
+ if (ev.is_a? Gdk::EventKey and (ev.keyval == Gdk::Keyval::GDK_KP_Enter or ev.keyval == Gdk::Keyval::GDK_Return)) or
25
+ (ev.is_a? Fixnum and ev == Gtk::Dialog::RESPONSE_ACCEPT)
26
+ if @api.login(@login.text, @password.text)
27
+ refresh
28
+ @login_dialog.destroy
29
+ else
30
+ raise "Login failed"
31
+ end
32
+ end
33
+
34
+ if (ev.is_a? Fixnum and ev == Gtk::Dialog::RESPONSE_REJECT)
35
+ exit!
36
+ end
37
+ end
38
+
39
+ def refresh
40
+ @tray.tooltip = "#{GNetvibes::NAME} refreshing...";
41
+
42
+ @api.tabs.each do |id, tab|
43
+ icon = File.join(CACHE, Digest::SHA1.new(tab['icon']).hexdigest)
44
+ if not File.exists?(icon)
45
+ File.open(icon, 'w') do |fd|
46
+ fd.puts @api.download(tab['icon'])
47
+ end
48
+ end
49
+
50
+ submenutitle = Gtk::ImageMenuItem.new(tab['title'])
51
+ submenutitle.image = Gtk::Image.new(icon)
52
+
53
+ submenu = Gtk::Menu.new
54
+ @api.each_modules_in_tab(id) do |mod|
55
+ case mod['name']
56
+ when 'PostIt'
57
+ item = Gtk::ImageMenuItem.new(mod['title'])
58
+ item.image = Gtk::Image.new(@icon_webnote)
59
+ item.signal_connect("activate", mod['id'], &method(:edit))
60
+ submenu.append(item)
61
+ end
62
+ end
63
+ submenutitle.submenu = submenu
64
+ @menu.prepend(submenutitle)
65
+ end
66
+
67
+ @menu.show_all
68
+ @tray.tooltip = GNetvibes::NAME;
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,15 @@
1
+ module GNetvibes
2
+ NAME = 'gNetvibes'
3
+ VERSION = '0.1'
4
+ COPYRIGHT = 'Copyright (C) 2007 Florent Solt'
5
+ DESC = 'Netvibes integration with the Gnome Desktop'
6
+ AUTHOR = 'Florent Solt'
7
+ EMAIL = 'florent@solt.biz'
8
+ HOMEPAGE = 'http://rubyforge.org/projects/gnetvibes/'
9
+
10
+ CACHE = File.join(ENV['HOME'], ".#{GNetvibes::NAME.downcase}", "cache")
11
+ DATA = File.join(ENV['HOME'], ".#{GNetvibes::NAME.downcase}", "data")
12
+ EXPIRE = 5 * 60
13
+ end
14
+
15
+
@@ -0,0 +1,109 @@
1
+ require 'gnetvibes/callback'
2
+
3
+ module GNetvibes
4
+ class GUI
5
+
6
+ attr_reader :login_dialog, :edit_dialog
7
+
8
+ def initialize
9
+ # API
10
+ @api = GNetvibes::API.new
11
+
12
+ # Icons
13
+ @icon = Gdk::Pixbuf.new(File.join(File.dirname(__FILE__), "ico.png"))
14
+ @icon_webnote = Gdk::Pixbuf.new(File.join(File.dirname(__FILE__), "webnote.gif"))
15
+
16
+ # Login Dialog
17
+ @login_dialog = Gtk::Dialog.new("#{GNetvibes::NAME} Authentification", nil, Gtk::Dialog::MODAL,
18
+ [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT],
19
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_REJECT])
20
+ @login_dialog.icon = @icon
21
+ @login_dialog.resizable = false
22
+
23
+ @login = Gtk::Entry.new
24
+ @password = Gtk::Entry.new
25
+
26
+ table = Gtk::Table.new(2, 3)
27
+ table.border_width = 5
28
+ image = Gtk::Image.new(Gtk::Stock::DIALOG_AUTHENTICATION, Gtk::IconSize::DIALOG)
29
+ table.attach(image, 0, 1, 0, 2, nil, nil, 10, 10)
30
+
31
+ table.attach_defaults(Gtk::Label.new("Login:"), 1, 2, 0, 1)
32
+ table.attach_defaults(@login, 2, 3, 0, 1)
33
+
34
+ table.attach_defaults(Gtk::Label.new("Password:"), 1, 2, 1, 2)
35
+ @password.visibility = false
36
+ @password.invisible_char = 0
37
+ table.attach_defaults(@password, 2, 3, 1, 2)
38
+ @login_dialog.vbox.pack_start(table)
39
+ @password.signal_connect("key_release_event", &method(:login))
40
+
41
+ if not ARGV.empty?
42
+ @login.editable = false
43
+ @login.text = ARGV.first
44
+ @password.grab_focus
45
+ else
46
+ @login.grab_focus
47
+ end
48
+
49
+ @login_dialog.signal_connect('response', &method(:login))
50
+
51
+ # Status Tray Icon
52
+ @tray = Gtk::StatusIcon.new
53
+ @tray.pixbuf = @icon
54
+
55
+ @menu = Gtk::Menu.new
56
+ @menu.append(Gtk::SeparatorMenuItem.new)
57
+
58
+ item = Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
59
+ item.signal_connect("activate", &method(:refresh))
60
+ @menu.append(item)
61
+
62
+ item = Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
63
+ item.signal_connect("activate") do
64
+ Gtk.main_quit
65
+ end
66
+ @menu.append(item)
67
+ @menu.show_all
68
+
69
+ @tray.signal_connect('popup-menu') do |w, button, time|
70
+ @menu.popup(nil, nil, button, time) do
71
+ @tray.position_menu(@menu)
72
+ end
73
+ end
74
+
75
+ # Text
76
+ @buf = Gtk::TextBuffer.new
77
+ @txt = Gtk::TextView.new(@buf)
78
+
79
+ @title = Gtk::Entry.new
80
+
81
+ # Edit Dialog
82
+ @edit_dialog = Gtk::Dialog.new(GNetvibes::NAME, nil, Gtk::Dialog::MODAL,
83
+ [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT],
84
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_REJECT])
85
+
86
+ scroll = Gtk::ScrolledWindow.new
87
+ scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
88
+ scroll.add(@txt)
89
+ scroll.border_width = 1
90
+
91
+ frame = Gtk::Frame.new
92
+ frame.add(scroll)
93
+
94
+ @edit_dialog.set_default_size(300, 300)
95
+ @edit_dialog.signal_connect("delete-event") do
96
+ @edit_dialog.hide_on_delete
97
+ end
98
+
99
+ @edit_dialog.title = GNetvibes::NAME
100
+ @edit_dialog.modal = true
101
+ @edit_dialog.border_width = 10
102
+ @edit_dialog.icon = @icon
103
+ @edit_dialog.vbox.pack_start(@title, false, false)
104
+ @edit_dialog.vbox.pack_start(frame, true, true, 10)
105
+ @edit_dialog.signal_connect('response', &method(:save))
106
+ end
107
+
108
+ end
109
+ end
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: gnetvibes
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2007-03-17 00:00:00 +01:00
8
+ summary: Netvibes integration with the Gnome Desktop
9
+ require_paths:
10
+ - lib
11
+ email: florent@solt.biz
12
+ homepage: http://rubyforge.org/projects/gnetvibes/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Florent Solt
31
+ files:
32
+ - lib/gnetvibes/callback.rb
33
+ - lib/gnetvibes/api.rb
34
+ - lib/gnetvibes/config.rb
35
+ - lib/gnetvibes/gui.rb
36
+ - lib/gnetvibes/ico.png
37
+ - lib/gnetvibes/webnote.gif
38
+ test_files: []
39
+
40
+ rdoc_options: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ executables:
45
+ - gnetvibes
46
+ extensions: []
47
+
48
+ requirements: []
49
+
50
+ dependencies: []
51
+