1# $Id$
2
3if {![cequal $::interface tk]} return
4
5package require base64
6package require sha1
7
8namespace eval ::avatar {
9    set options(announce) 0
10    set options(share) 0
11}
12
13##############################################################################
14
15proc ::avatar::setup_menu {} {
16    catch {
17	#set m [.mainframe getmenu services]
18	#for {set ind [$m index end]} {$ind > 0} {incr ind -1} {
19	#    if {[$m type $ind] == "separator"} {
20	#	break
21	#    }
22	#}
23	set m [.mainframe getmenu plugins]
24
25	set mm .avatar_menu
26	menu $mm -tearoff $ifacetk::options(show_tearoffs)
27	$mm add checkbutton -label [::msgcat::mc "Announce"] \
28	    -variable avatar::options(announce)
29	$mm add checkbutton -label [::msgcat::mc "Allow downloading"] \
30	    -variable avatar::options(share)
31	$mm add command -label [::msgcat::mc "Send to server"] \
32	    -command {avatar::store_on_server}
33
34	$m add cascade -label [::msgcat::mc "Avatar"] \
35	    -menu $mm
36    }
37}
38
39hook::add finload_hook ::avatar::setup_menu
40
41##############################################################################
42
43proc ::avatar::load_file {filename} {
44    variable avatar
45    variable options
46
47    image create photo user_avatar -file $filename
48    set f [open $filename]
49    fconfigure $f -translation binary
50    set data [read $f]
51    close $f
52
53    set avatar(userhash) [sha1::sha1 $data]
54    set avatar(userdata) [base64::encode $data]
55
56    set options(announce) 1
57    set options(share) 1
58}
59
60##############################################################################
61
62proc ::avatar::get_presence_x {varname xlib status} {
63    variable avatar
64    variable options
65    upvar 2 $varname var
66
67    if {$options(announce) && [info exists avatar(userhash)]} {
68	lappend var [::xmpp::xml::create x \
69			 -xmlns $::NS(xavatar) \
70			 -subelement [::xmpp::xml::create hash \
71					    -cdata $avatar(userhash)]]
72
73    }
74    return
75}
76
77hook::add presence_xlist_hook ::avatar::get_presence_x
78
79##############################################################################
80
81proc ::avatar::process_presence {xlib from type x args} {
82    switch -- $type {
83	available -
84	unavailable {
85	    foreach xs $x {
86		::xmpp::xml::split $xs tag xmlns attrs cdata subels
87		if {$xmlns == $::NS(xavatar)} {
88		    set_hash $xlib $from $subels
89		    break
90		}
91	    }
92	}
93    }
94}
95
96hook::add client_presence_hook ::avatar::process_presence
97
98##############################################################################
99
100proc ::avatar::insert_userinfo {tab xlib jid editable} {
101    if {$editable} return
102
103    set avatar_img [get_image $xlib [get_jid_of_user $xlib $jid]]
104    if {$avatar_img != ""} {
105	set avatar [$tab insert end avatar -text [::msgcat::mc "Avatar"]]
106
107	set av [userinfo::pack_frame $avatar.avatar [::msgcat::mc "Avatar"]]
108	label $av.a -image $avatar_img
109	pack $av.a -expand yes -fill both
110    }
111}
112
113hook::add userinfo_hook ::avatar::insert_userinfo 40
114
115##############################################################################
116
117proc ::avatar::set_hash {xlib jid children} {
118    variable avatar
119
120    debugmsg avatar "set hash $xlib $jid $children"
121    foreach child $children {
122	::xmpp::xml::split $child tag xmlns attrs cdata subels
123	if {$tag == "hash"} {
124	    set hash $cdata
125	}
126    }
127    if {[info exists hash]} {
128	if {![info exists avatar(hash,$xlib,$jid)] || \
129		$hash != $avatar(hash,$xlib,$jid)} {
130	    set avatar(hash,$xlib,$jid) $hash
131	    set avatar(needupdate,$xlib,$jid) 1
132	}
133    }
134}
135
136##############################################################################
137
138proc ::avatar::get_image {xlib jid} {
139    variable avatar
140
141    debugmsg avatar "$jid; [array name avatar]"
142    if {[info exists avatar(hash,$xlib,$jid)]} {
143	if {![info exists avatar(data,$xlib,$jid)]} {
144	    image create photo avatar$xlib@$jid
145	    get $xlib $jid
146	} elseif {$avatar(needupdate,$xlib,$jid)} {
147	    get $xlib $jid
148	}
149	return avatar$xlib@$jid
150    } else {
151	return ""
152    }
153}
154
155##############################################################################
156
157proc ::avatar::get {xlib jid} {
158    variable avatar
159
160    set avatar(needupdate,$xlib,$jid) 0
161
162    ::xmpp::sendIQ $xlib get \
163	-query [::xmpp::xml::create query \
164			-xmlns $::NS(iqavatar)] \
165	-to $jid -command [list avatar::recv $xlib $jid]
166}
167
168proc ::avatar::recv {xlib jid res child} {
169    variable avatar
170
171    if {![string equal $res ok]} {
172	::xmpp::sendIQ $xlib get \
173	    -query [::xmpp::xml::create query \
174			       -xmlns storage:client:avatar] \
175	    -to [::xmpp::jid::stripResource $jid] \
176	    -command [list avatar::recv_from_serv $xlib $jid]
177
178	return
179    }
180
181    ::xmpp::xml::split $child tag xmlns attrs cdata subels
182    foreach subel $subels {
183	::xmpp::xml::split $subel stag sxmlns sattrs scdata ssubels
184	if {$stag == "data"} {
185	    catch {
186		set avatar(data,$xlib,$jid) [base64::decode $scdata]
187		avatar$xlib@$jid put $scdata
188	    }
189	}
190    }
191}
192
193proc ::avatar::recv_from_serv {xlib jid res child} {
194    variable avatar
195
196    if {![string equal $res ok]} {
197	# TODO
198	return
199    }
200
201    ::xmpp::xml::split $child tag xmlns attrs cdata subels
202    foreach subel $subels {
203	::xmpp::xml::split $subel stag sxmlns sattrs scdata ssubels
204	if {$stag == "data"} {
205	    catch {
206		set avatar(data,$xlib,$jid) [base64::decode $scdata]
207		avatar$xlib@$jid put $scdata
208	    }
209	}
210    }
211}
212
213##############################################################################
214
215proc ::avatar::store_on_server {{xlib ""}} {
216    variable avatar
217
218    if {[llength [connections]] == 0} return
219
220    if {$xlib == ""} {
221	set xlib [lindex [connections] 0]
222    }
223
224    if {![info exists avatar(userdata)]} {
225	MessageDlg .avatar_error -aspect 50000 -icon error \
226		-message [::msgcat::mc "No avatar to store"] -type user \
227		-buttons ok -default 0 -cancel 0
228	return
229    }
230
231    ::xmpp::sendIQ $xlib set \
232	-query [::xmpp::xml::create query \
233			-xmlns storage:client:avatar \
234			-subelement [::xmpp::xml::create data \
235					    -cdata $avatar(userdata)]]
236}
237
238##############################################################################
239
240proc ::avatar::iq_reply {xlib from child args} {
241    variable avatar
242    variable options
243
244    if {$options(share) && [info exists avatar(userdata)]} {
245	set res [::xmpp::xml::create query \
246			-xmlns $::NS(iqavatar) \
247			-subelement [::xmpp::xml::create data \
248					    -cdata $avatar(userdata)]]
249	return [list result $res]
250    } else {
251	return [list error cancel service-unavailable]
252    }
253}
254
255::xmpp::iq::register get query $::NS(iqavatar) ::avatar::iq_reply
256
257##############################################################################
258
259