Mercurial > pidgin.yaz
comparison libpurple/protocols/silc/silc.c @ 17806:980a104267da
Patch from Pekka Riikonen to update the SILC protocol plugin to work with
SILC Toolkit 1.1
I added the fallback to SILC Toolkit 1.0 support (silc10 protocol
directory) and configure.ac adjustments, any problems with this are 100%
my fault.
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Sat, 09 Jun 2007 17:31:28 +0000 |
parents | 0f4a562b38d1 |
children | b142c090eaf7 |
comparison
equal
deleted
inserted
replaced
17805:ba1b50f114f6 | 17806:980a104267da |
---|---|
2 | 2 |
3 silcpurple.c | 3 silcpurple.c |
4 | 4 |
5 Author: Pekka Riikonen <priikone@silcnet.org> | 5 Author: Pekka Riikonen <priikone@silcnet.org> |
6 | 6 |
7 Copyright (C) 2004 - 2005 Pekka Riikonen | 7 Copyright (C) 2004 - 2007 Pekka Riikonen |
8 | 8 |
9 This program is free software; you can redistribute it and/or modify | 9 This program is free software; you can redistribute it and/or modify |
10 it under the terms of the GNU General Public License as published by | 10 it under the terms of the GNU General Public License as published by |
11 the Free Software Foundation; version 2 of the License. | 11 the Free Software Foundation; version 2 of the License. |
12 | 12 |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 GNU General Public License for more details. | 16 GNU General Public License for more details. |
17 | 17 |
18 */ | 18 */ |
19 | 19 |
20 #include "silcincludes.h" | 20 #include "silc.h" |
21 #include "silcclient.h" | 21 #include "silcclient.h" |
22 #include "silcpurple.h" | 22 #include "silcpurple.h" |
23 #include "version.h" | 23 #include "version.h" |
24 #include "wb.h" | 24 #include "wb.h" |
25 | 25 |
26 extern SilcClientOperations ops; | 26 extern SilcClientOperations ops; |
27 static PurplePlugin *silc_plugin = NULL; | 27 static PurplePlugin *silc_plugin = NULL; |
28 | |
29 /* Error log message callback */ | |
30 | |
31 static SilcBool silcpurple_log_error(SilcLogType type, char *message, | |
32 void *context) | |
33 { | |
34 silc_say(NULL, NULL, SILC_CLIENT_MESSAGE_ERROR, message); | |
35 return TRUE; | |
36 } | |
28 | 37 |
29 static const char * | 38 static const char * |
30 silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b) | 39 silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b) |
31 { | 40 { |
32 return (const char *)"silc"; | 41 return (const char *)"silc"; |
100 | 109 |
101 /* Send UMODE */ | 110 /* Send UMODE */ |
102 idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT); | 111 idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT); |
103 SILC_PUT32_MSB(mode, mb); | 112 SILC_PUT32_MSB(mode, mb); |
104 silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE, | 113 silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE, |
105 ++sg->conn->cmd_ident, 2, | 114 silcpurple_command_reply, NULL, 2, |
106 1, idp->data, idp->len, | 115 1, idp->data, silc_buffer_len(idp), |
107 2, mb, sizeof(mb)); | 116 2, mb, sizeof(mb)); |
108 silc_buffer_free(idp); | 117 silc_buffer_free(idp); |
109 } | 118 } |
110 | 119 |
111 | 120 |
113 | 122 |
114 static void | 123 static void |
115 silcpurple_keepalive(PurpleConnection *gc) | 124 silcpurple_keepalive(PurpleConnection *gc) |
116 { | 125 { |
117 SilcPurple sg = gc->proto_data; | 126 SilcPurple sg = gc->proto_data; |
118 silc_client_send_packet(sg->client, sg->conn, SILC_PACKET_HEARTBEAT, | 127 silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0, |
119 NULL, 0); | 128 NULL, 0); |
120 } | 129 } |
121 | 130 |
122 static gboolean | 131 static gboolean |
123 silcpurple_scheduler(gpointer *context) | 132 silcpurple_scheduler(gpointer *context) |
124 { | 133 { |
125 SilcPurple sg = (SilcPurple)context; | 134 SilcClient client = (SilcClient)context; |
126 silc_client_run_one(sg->client); | 135 silc_client_run_one(client); |
127 return TRUE; | 136 return TRUE; |
128 } | 137 } |
129 | 138 |
130 static void | 139 static void |
131 silcpurple_nickname_parse(const char *nickname, | 140 silcpurple_connect_cb(SilcClient client, SilcClientConnection conn, |
132 char **ret_nickname) | 141 SilcClientConnectionStatus status, SilcStatus error, |
133 { | 142 const char *message, void *context) |
134 silc_parse_userfqdn(nickname, ret_nickname, NULL); | 143 { |
135 } | 144 PurpleConnection *gc = context; |
136 | |
137 static void | |
138 silcpurple_login_connected(gpointer data, gint source, const gchar *error_message) | |
139 { | |
140 PurpleConnection *gc = data; | |
141 SilcPurple sg; | 145 SilcPurple sg; |
142 SilcClient client; | 146 gboolean reject_watch, block_invites, block_ims; |
143 SilcClientConnection conn; | |
144 PurpleAccount *account; | |
145 SilcClientConnectionParams params; | |
146 const char *dfile; | |
147 | |
148 g_return_if_fail(gc != NULL); | |
149 | 147 |
150 sg = gc->proto_data; | 148 sg = gc->proto_data; |
151 | 149 |
152 if (source < 0) { | 150 switch (status) { |
153 purple_connection_error(gc, _("Connection failed")); | 151 case SILC_CLIENT_CONN_SUCCESS: |
154 return; | 152 case SILC_CLIENT_CONN_SUCCESS_RESUME: |
155 } | 153 sg->conn = conn; |
156 | 154 |
157 client = sg->client; | 155 /* Connection created successfully */ |
158 account = sg->account; | 156 purple_connection_set_state(gc, PURPLE_CONNECTED); |
159 | 157 |
160 /* Get session detachment data, if available */ | 158 /* Send the server our buddy list */ |
161 memset(¶ms, 0, sizeof(params)); | 159 silcpurple_send_buddylist(gc); |
162 dfile = silcpurple_session_file(purple_account_get_username(sg->account)); | 160 |
163 params.detach_data = (unsigned char *)silc_file_readfile(dfile, ¶ms.detach_data_len); | 161 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); |
164 if (params.detach_data) | 162 |
165 params.detach_data[params.detach_data_len] = 0; | 163 /* Send any UMODEs configured for account */ |
166 | 164 reject_watch = purple_account_get_bool(sg->account, "reject-watch", FALSE); |
167 /* Add connection to SILC client library */ | 165 block_invites = purple_account_get_bool(sg->account, "block-invites", FALSE); |
168 conn = silc_client_add_connection( | 166 block_ims = purple_account_get_bool(sg->account, "block-ims", FALSE); |
169 sg->client, ¶ms, | 167 if (reject_watch || block_invites || block_ims) { |
170 (char *)purple_account_get_string(account, "server", | 168 char m[5]; |
171 "silc.silcnet.org"), | 169 g_snprintf(m, sizeof(m), "+%s%s%s", |
172 purple_account_get_int(account, "port", 706), sg); | 170 reject_watch ? "w" : "", |
173 if (!conn) { | 171 block_invites ? "I" : "", |
174 purple_connection_error(gc, _("Cannot initialize SILC Client connection")); | 172 block_ims ? "P" : ""); |
175 gc->proto_data = NULL; | 173 silc_client_command_call(sg->client, sg->conn, NULL, |
176 return; | 174 "UMODE", m, NULL); |
177 } | 175 } |
178 sg->conn = conn; | 176 |
179 | 177 /* Set default attributes */ |
180 /* Progress */ | 178 if (!purple_account_get_bool(sg->account, "reject-attrs", FALSE)) { |
181 if (params.detach_data) { | 179 SilcUInt32 mask; |
182 purple_connection_update_progress(gc, _("Resuming session"), 2, 5); | 180 char tz[16]; |
183 sg->resuming = TRUE; | |
184 } else { | |
185 purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5); | |
186 } | |
187 | |
188 /* Perform SILC Key Exchange. The "silc_connected" will be called | |
189 eventually. */ | |
190 silc_client_start_key_exchange(sg->client, sg->conn, source); | |
191 | |
192 /* Set default attributes */ | |
193 if (!purple_account_get_bool(account, "reject-attrs", FALSE)) { | |
194 SilcUInt32 mask; | |
195 const char *tmp; | |
196 #ifdef SILC_ATTRIBUTE_USER_ICON | 181 #ifdef SILC_ATTRIBUTE_USER_ICON |
197 PurpleStoredImage *img; | 182 PurpleStoredImage *img; |
198 #endif | 183 #endif |
199 #ifdef HAVE_SYS_UTSNAME_H | 184 #ifdef HAVE_SYS_UTSNAME_H |
200 struct utsname u; | 185 struct utsname u; |
201 #endif | 186 #endif |
202 | 187 |
203 mask = SILC_ATTRIBUTE_MOOD_NORMAL; | 188 mask = SILC_ATTRIBUTE_MOOD_NORMAL; |
204 silc_client_attribute_add(client, conn, | 189 silc_client_attribute_add(client, conn, |
205 SILC_ATTRIBUTE_STATUS_MOOD, | 190 SILC_ATTRIBUTE_STATUS_MOOD, |
206 SILC_32_TO_PTR(mask), | 191 SILC_32_TO_PTR(mask), |
207 sizeof(SilcUInt32)); | 192 sizeof(SilcUInt32)); |
208 mask = SILC_ATTRIBUTE_CONTACT_CHAT; | 193 mask = SILC_ATTRIBUTE_CONTACT_CHAT; |
209 silc_client_attribute_add(client, conn, | 194 silc_client_attribute_add(client, conn, |
210 SILC_ATTRIBUTE_PREFERRED_CONTACT, | 195 SILC_ATTRIBUTE_PREFERRED_CONTACT, |
211 SILC_32_TO_PTR(mask), | 196 SILC_32_TO_PTR(mask), |
212 sizeof(SilcUInt32)); | 197 sizeof(SilcUInt32)); |
213 #ifdef HAVE_SYS_UTSNAME_H | 198 #ifdef HAVE_SYS_UTSNAME_H |
214 if (!uname(&u)) { | 199 if (!uname(&u)) { |
215 SilcAttributeObjDevice dev; | 200 SilcAttributeObjDevice dev; |
216 memset(&dev, 0, sizeof(dev)); | 201 memset(&dev, 0, sizeof(dev)); |
217 dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; | 202 dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; |
218 dev.version = u.release; | 203 dev.version = u.release; |
219 dev.model = u.sysname; | 204 dev.model = u.sysname; |
220 silc_client_attribute_add(client, conn, | 205 silc_client_attribute_add(client, conn, |
221 SILC_ATTRIBUTE_DEVICE_INFO, | 206 SILC_ATTRIBUTE_DEVICE_INFO, |
222 (void *)&dev, sizeof(dev)); | 207 (void *)&dev, sizeof(dev)); |
208 } | |
209 #endif | |
210 silc_timezone(tz, sizeof(tz)); | |
211 silc_client_attribute_add(client, conn, | |
212 SILC_ATTRIBUTE_TIMEZONE, | |
213 (void *)tz, strlen(tz)); | |
214 | |
215 #ifdef SILC_ATTRIBUTE_USER_ICON | |
216 /* Set our buddy icon */ | |
217 img = purple_buddy_icons_find_account_icon(sg->account); | |
218 silcpurple_buddy_set_icon(gc, img); | |
219 purple_imgstore_unref(img); | |
220 #endif | |
223 } | 221 } |
224 #endif | 222 |
225 #ifdef _WIN32 | 223 return; |
226 tmp = _tzname[0]; | 224 break; |
227 #else | 225 |
228 tmp = tzname[0]; | 226 case SILC_CLIENT_CONN_DISCONNECTED: |
229 #endif | 227 /* Disconnected */ |
230 silc_client_attribute_add(client, conn, | 228 if (sg->resuming && !sg->detaching) |
231 SILC_ATTRIBUTE_TIMEZONE, | 229 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); |
232 (void *)tmp, strlen(tmp)); | 230 |
233 | 231 /* Close the connection */ |
234 #ifdef SILC_ATTRIBUTE_USER_ICON | 232 if (!sg->detaching) |
235 /* Set our buddy icon */ | 233 purple_connection_error(gc, _("Disconnected by server")); |
236 img = purple_buddy_icons_find_account_icon(account); | 234 else |
237 silcpurple_buddy_set_icon(gc, img); | 235 /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */ |
238 purple_imgstore_unref(img); | 236 purple_account_disconnect(purple_connection_get_account(gc)); |
239 #endif | 237 break; |
240 } | 238 |
241 | 239 case SILC_CLIENT_CONN_ERROR: |
242 silc_free(params.detach_data); | 240 purple_connection_error(gc, _("Error during connecting to SILC Server")); |
243 } | 241 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); |
244 | 242 break; |
245 static void | 243 |
246 silcpurple_login(PurpleAccount *account) | 244 case SILC_CLIENT_CONN_ERROR_KE: |
247 { | 245 purple_connection_error(gc, _("Key Exchange failed")); |
246 break; | |
247 | |
248 case SILC_CLIENT_CONN_ERROR_AUTH: | |
249 purple_connection_error(gc, _("Authentication failed")); | |
250 break; | |
251 | |
252 case SILC_CLIENT_CONN_ERROR_RESUME: | |
253 purple_connection_error(gc, | |
254 _("Resuming detached session failed. " | |
255 "Press Reconnect to create new connection.")); | |
256 g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); | |
257 break; | |
258 | |
259 case SILC_CLIENT_CONN_ERROR_TIMEOUT: | |
260 purple_connection_error(gc, _("Connection Timeout")); | |
261 break; | |
262 } | |
263 | |
264 /* Error */ | |
265 sg->conn = NULL; | |
266 } | |
267 | |
268 static void | |
269 silcpurple_stream_created(SilcSocketStreamStatus status, SilcStream stream, | |
270 void *context) | |
271 { | |
272 PurpleConnection *gc = context; | |
248 SilcPurple sg; | 273 SilcPurple sg; |
249 SilcClient client; | 274 SilcClient client; |
275 SilcClientConnectionParams params; | |
276 const char *dfile; | |
277 | |
278 sg = gc->proto_data; | |
279 | |
280 if (status != SILC_SOCKET_OK) { | |
281 purple_connection_error(gc, _("Connection failed")); | |
282 silc_pkcs_public_key_free(sg->public_key); | |
283 silc_pkcs_private_key_free(sg->private_key); | |
284 silc_free(sg); | |
285 gc->proto_data = NULL; | |
286 return; | |
287 } | |
288 | |
289 client = sg->client; | |
290 | |
291 /* Progress */ | |
292 if (params.detach_data) { | |
293 purple_connection_update_progress(gc, _("Resuming session"), 2, 5); | |
294 sg->resuming = TRUE; | |
295 } else { | |
296 purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5); | |
297 } | |
298 | |
299 /* Get session detachment data, if available */ | |
300 memset(¶ms, 0, sizeof(params)); | |
301 dfile = silcpurple_session_file(purple_account_get_username(sg->account)); | |
302 params.detach_data = (unsigned char *)silc_file_readfile(dfile, ¶ms.detach_data_len); | |
303 if (params.detach_data) | |
304 params.detach_data[params.detach_data_len] = 0; | |
305 params.ignore_requested_attributes = | |
306 purple_account_get_bool(sg->account, "reject-attrs", FALSE); | |
307 params.pfs = purple_account_get_bool(sg->account, "pfs", FALSE); | |
308 | |
309 /* Perform SILC Key Exchange. */ | |
310 silc_client_key_exchange(sg->client, ¶ms, sg->public_key, | |
311 sg->private_key, stream, SILC_CONN_SERVER, | |
312 silcpurple_connect_cb, gc); | |
313 | |
314 silc_free(params.detach_data); | |
315 } | |
316 | |
317 static void | |
318 silcpurple_login_connected(gpointer data, gint source, const gchar *error_message) | |
319 { | |
320 PurpleConnection *gc = data; | |
321 SilcPurple sg; | |
322 | |
323 g_return_if_fail(gc != NULL); | |
324 | |
325 sg = gc->proto_data; | |
326 | |
327 if (source < 0) { | |
328 purple_connection_error(gc, _("Connection failed")); | |
329 silc_pkcs_public_key_free(sg->public_key); | |
330 silc_pkcs_private_key_free(sg->private_key); | |
331 silc_free(sg); | |
332 gc->proto_data = NULL; | |
333 return; | |
334 } | |
335 | |
336 /* Wrap socket to TCP stream */ | |
337 silc_socket_tcp_stream_create(source, TRUE, FALSE, | |
338 sg->client->schedule, | |
339 silcpurple_stream_created, gc); | |
340 } | |
341 | |
342 static void silcpurple_running(SilcClient client, void *context) | |
343 { | |
344 PurpleAccount *account = context; | |
345 PurpleConnection *gc = account->gc; | |
346 SilcPurple sg; | |
347 char pkd[256], prd[256]; | |
348 | |
349 sg = silc_calloc(1, sizeof(*sg)); | |
350 if (!sg) | |
351 return; | |
352 memset(sg, 0, sizeof(*sg)); | |
353 sg->client = client; | |
354 sg->gc = gc; | |
355 sg->account = account; | |
356 sg->scheduler = SILC_PTR_TO_32(gc->proto_data); | |
357 gc->proto_data = sg; | |
358 | |
359 /* Progress */ | |
360 purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); | |
361 | |
362 /* Load SILC key pair */ | |
363 g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); | |
364 g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); | |
365 if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd), | |
366 (char *)purple_account_get_string(account, "private-key", prd), | |
367 (gc->password == NULL) ? "" : gc->password, | |
368 &sg->public_key, &sg->private_key)) { | |
369 g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair")); | |
370 purple_connection_error(gc, pkd); | |
371 gc->proto_data = NULL; | |
372 silc_free(sg); | |
373 return; | |
374 } | |
375 | |
376 /* Connect to the SILC server */ | |
377 if (purple_proxy_connect(gc, account, | |
378 purple_account_get_string(account, "server", | |
379 "silc.silcnet.org"), | |
380 purple_account_get_int(account, "port", 706), | |
381 silcpurple_login_connected, gc) == NULL) | |
382 { | |
383 purple_connection_error(gc, _("Unable to create connection")); | |
384 gc->proto_data = NULL; | |
385 silc_free(sg); | |
386 return; | |
387 } | |
388 } | |
389 | |
390 static void | |
391 silcpurple_login(PurpleAccount *account) | |
392 { | |
393 SilcClient client; | |
394 PurpleConnection *gc; | |
250 SilcClientParams params; | 395 SilcClientParams params; |
251 PurpleConnection *gc; | |
252 char pkd[256], prd[256]; | |
253 const char *cipher, *hmac; | 396 const char *cipher, *hmac; |
254 char *realname; | 397 char *username, *hostname, *realname, **up; |
398 guint scheduler; | |
255 int i; | 399 int i; |
256 | 400 |
257 gc = account->gc; | 401 gc = account->gc; |
258 if (!gc) | 402 if (!gc) |
259 return; | 403 return; |
260 gc->proto_data = NULL; | 404 gc->proto_data = NULL; |
261 | 405 |
262 memset(¶ms, 0, sizeof(params)); | 406 memset(¶ms, 0, sizeof(params)); |
263 strcat(params.nickname_format, "%n@%h%a"); | 407 strcat(params.nickname_format, "%n#a"); |
264 params.nickname_parse = silcpurple_nickname_parse; | |
265 params.ignore_requested_attributes = | |
266 purple_account_get_bool(account, "reject-attrs", FALSE); | |
267 | 408 |
268 /* Allocate SILC client */ | 409 /* Allocate SILC client */ |
269 client = silc_client_alloc(&ops, ¶ms, gc, NULL); | 410 client = silc_client_alloc(&ops, ¶ms, gc, NULL); |
270 if (!client) { | 411 if (!client) { |
271 purple_connection_error(gc, _("Out of memory")); | 412 purple_connection_error(gc, _("Out of memory")); |
272 return; | 413 return; |
273 } | 414 } |
274 | 415 |
275 /* Get username, real name and local hostname for SILC library */ | 416 /* Get username, real name and local hostname for SILC library */ |
276 if (purple_account_get_username(account)) { | 417 if (!purple_account_get_username(account)) |
277 const char *u = purple_account_get_username(account); | 418 purple_account_set_username(account, silc_get_username()); |
278 char **up = g_strsplit(u, "@", 2); | 419 |
279 client->username = strdup(up[0]); | 420 username = (char *)purple_account_get_username(account); |
280 g_strfreev(up); | 421 up = g_strsplit(username, "@", 2); |
281 } else { | 422 username = strdup(up[0]); |
282 client->username = silc_get_username(); | 423 g_strfreev(up); |
283 purple_account_set_username(account, client->username); | 424 |
284 } | 425 if (!purple_account_get_user_info(account)) { |
285 realname = silc_get_real_name(); | 426 purple_account_set_user_info(account, silc_get_real_name()); |
286 if (purple_account_get_user_info(account)) { | 427 if (!purple_account_get_user_info(account)) |
287 client->realname = strdup(purple_account_get_user_info(account)); | 428 purple_account_set_user_info(account, |
288 free(realname); | 429 "John T. Noname"); |
289 } else if ((silc_get_real_name() != NULL) && (*realname != '\0')) { | 430 } |
290 client->realname = realname; | 431 realname = (char *)purple_account_get_user_info(account); |
291 purple_account_set_user_info(account, client->realname); | 432 hostname = silc_net_localhost(); |
292 } else { | 433 |
293 free(realname); | 434 purple_connection_set_display_name(gc, username); |
294 client->realname = strdup(_("John Noname")); | |
295 } | |
296 client->hostname = silc_net_localhost(); | |
297 | |
298 purple_connection_set_display_name(gc, client->username); | |
299 | 435 |
300 /* Register requested cipher and HMAC */ | 436 /* Register requested cipher and HMAC */ |
301 cipher = purple_account_get_string(account, "cipher", SILC_DEFAULT_CIPHER); | 437 cipher = purple_account_get_string(account, "cipher", |
438 SILC_DEFAULT_CIPHER); | |
302 for (i = 0; silc_default_ciphers[i].name; i++) | 439 for (i = 0; silc_default_ciphers[i].name; i++) |
303 if (!strcmp(silc_default_ciphers[i].name, cipher)) { | 440 if (!strcmp(silc_default_ciphers[i].name, cipher)) { |
304 silc_cipher_register(&(silc_default_ciphers[i])); | 441 silc_cipher_register(&(silc_default_ciphers[i])); |
305 break; | 442 break; |
306 } | 443 } |
310 silc_hmac_register(&(silc_default_hmacs[i])); | 447 silc_hmac_register(&(silc_default_hmacs[i])); |
311 break; | 448 break; |
312 } | 449 } |
313 | 450 |
314 /* Init SILC client */ | 451 /* Init SILC client */ |
315 if (!silc_client_init(client)) { | 452 if (!silc_client_init(client, username, hostname, realname, |
453 silcpurple_running, account)) { | |
316 gc->wants_to_die = TRUE; | 454 gc->wants_to_die = TRUE; |
317 purple_connection_error(gc, _("Cannot initialize SILC protocol")); | 455 purple_connection_error(gc, _("Cannot initialize SILC protocol")); |
318 return; | 456 return; |
319 } | 457 } |
320 | 458 |
321 /* Check the ~/.silc dir and create it, and new key pair if necessary. */ | 459 /* Check the ~/.silc dir and create it, and new key pair if necessary. */ |
322 if (!silcpurple_check_silc_dir(gc)) { | 460 if (!silcpurple_check_silc_dir(gc)) { |
323 gc->wants_to_die = TRUE; | 461 gc->wants_to_die = TRUE; |
324 purple_connection_error(gc, _("Cannot find/access ~/.silc directory")); | 462 purple_connection_error(gc, _("Error loading SILC key pair")); |
325 return; | |
326 } | |
327 | |
328 /* Progress */ | |
329 purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); | |
330 | |
331 /* Load SILC key pair */ | |
332 g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); | |
333 g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); | |
334 if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd), | |
335 (char *)purple_account_get_string(account, "private-key", prd), | |
336 (gc->password == NULL) ? "" : gc->password, &client->pkcs, | |
337 &client->public_key, &client->private_key)) { | |
338 g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair: %s"), strerror(errno)); | |
339 purple_connection_error(gc, pkd); | |
340 return; | |
341 } | |
342 | |
343 sg = silc_calloc(1, sizeof(*sg)); | |
344 if (!sg) | |
345 return; | |
346 memset(sg, 0, sizeof(*sg)); | |
347 sg->client = client; | |
348 sg->gc = gc; | |
349 sg->account = account; | |
350 gc->proto_data = sg; | |
351 | |
352 /* Connect to the SILC server */ | |
353 if (purple_proxy_connect(gc, account, | |
354 purple_account_get_string(account, "server", | |
355 "silc.silcnet.org"), | |
356 purple_account_get_int(account, "port", 706), | |
357 silcpurple_login_connected, gc) == NULL) | |
358 { | |
359 purple_connection_error(gc, _("Unable to create connection")); | |
360 return; | 463 return; |
361 } | 464 } |
362 | 465 |
363 /* Schedule SILC using Glib's event loop */ | 466 /* Schedule SILC using Glib's event loop */ |
364 sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg); | 467 scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client); |
468 gc->proto_data = SILC_32_TO_PTR(scheduler); | |
365 } | 469 } |
366 | 470 |
367 static int | 471 static int |
368 silcpurple_close_final(gpointer *context) | 472 silcpurple_close_final(gpointer *context) |
369 { | 473 { |
370 SilcPurple sg = (SilcPurple)context; | 474 SilcPurple sg = (SilcPurple)context; |
371 silc_client_stop(sg->client); | 475 silc_client_stop(sg->client, NULL, NULL); |
372 silc_client_free(sg->client); | 476 silc_client_free(sg->client); |
373 #ifdef HAVE_SILCMIME_H | 477 #ifdef HAVE_SILCMIME_H |
374 if (sg->mimeass) | 478 if (sg->mimeass) |
375 silc_mime_assembler_free(sg->mimeass); | 479 silc_mime_assembler_free(sg->mimeass); |
376 #endif | 480 #endif |
385 | 489 |
386 g_return_if_fail(sg != NULL); | 490 g_return_if_fail(sg != NULL); |
387 | 491 |
388 /* Send QUIT */ | 492 /* Send QUIT */ |
389 silc_client_command_call(sg->client, sg->conn, NULL, | 493 silc_client_command_call(sg->client, sg->conn, NULL, |
390 "QUIT", "Download this: " PURPLE_WEBSITE, NULL); | 494 "QUIT", "Download Pidgin: " PURPLE_WEBSITE, NULL); |
391 | 495 |
392 if (sg->conn) | 496 if (sg->conn) |
393 silc_client_close_connection(sg->client, sg->conn); | 497 silc_client_close_connection(sg->client, sg->conn); |
394 | 498 |
395 purple_timeout_remove(sg->scheduler); | 499 purple_timeout_remove(sg->scheduler); |
593 minvincible = FALSE, minlove = FALSE, msleepy = FALSE, | 697 minvincible = FALSE, minlove = FALSE, msleepy = FALSE, |
594 mbored = FALSE, mexcited = FALSE, manxious = FALSE; | 698 mbored = FALSE, mexcited = FALSE, manxious = FALSE; |
595 gboolean cemail = FALSE, ccall = FALSE, csms = FALSE, | 699 gboolean cemail = FALSE, ccall = FALSE, csms = FALSE, |
596 cmms = FALSE, cchat = TRUE, cvideo = FALSE; | 700 cmms = FALSE, cchat = TRUE, cvideo = FALSE; |
597 gboolean device = TRUE; | 701 gboolean device = TRUE; |
598 char status[1024]; | 702 char status[1024], tz[16]; |
599 | 703 |
600 sg = gc->proto_data; | 704 sg = gc->proto_data; |
601 if (!sg) | 705 if (!sg) |
602 return; | 706 return; |
603 | 707 |
720 g = purple_request_field_group_new(NULL); | 824 g = purple_request_field_group_new(NULL); |
721 f = purple_request_field_string_new("vcard", _("Your VCard File"), | 825 f = purple_request_field_string_new("vcard", _("Your VCard File"), |
722 purple_account_get_string(sg->account, "vcard", ""), | 826 purple_account_get_string(sg->account, "vcard", ""), |
723 FALSE); | 827 FALSE); |
724 purple_request_field_group_add_field(g, f); | 828 purple_request_field_group_add_field(g, f); |
725 #ifdef _WIN32 | 829 |
726 f = purple_request_field_string_new("timezone", _("Timezone"), _tzname[0], FALSE); | 830 silc_timezone(tz, sizeof(tz)); |
727 #else | 831 f = purple_request_field_string_new("timezone", _("Timezone (UTC)"), tz, FALSE); |
728 f = purple_request_field_string_new("timezone", _("Timezone"), tzname[0], FALSE); | |
729 #endif | |
730 purple_request_field_group_add_field(g, f); | 832 purple_request_field_group_add_field(g, f); |
731 purple_request_fields_add_group(fields, g); | 833 purple_request_fields_add_group(fields, g); |
732 | 834 |
733 purple_request_fields(gc, _("User Online Status Attributes"), | 835 purple_request_fields(gc, _("User Online Status Attributes"), |
734 _("User Online Status Attributes"), | 836 _("User Online Status Attributes"), |
859 o = purple_request_field_string_get_value(f); | 961 o = purple_request_field_string_get_value(f); |
860 f = purple_request_fields_get_field(fields, "c"); | 962 f = purple_request_fields_get_field(fields, "c"); |
861 if (f) | 963 if (f) |
862 c = purple_request_field_string_get_value(f); | 964 c = purple_request_field_string_get_value(f); |
863 | 965 |
864 identifier = silc_pkcs_encode_identifier((char *)un, (char *)hn, | 966 identifier = silc_pkcs_silc_encode_identifier((char *)un, (char *)hn, |
865 (char *)rn, (char *)e, (char *)o, (char *)c); | 967 (char *)rn, (char *)e, |
968 (char *)o, (char *)c, | |
969 NULL); | |
866 | 970 |
867 /* Create the key pair */ | 971 /* Create the key pair */ |
868 if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile, | 972 if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile, |
869 identifier, pass1, NULL, &public_key, NULL, | 973 identifier, pass1, &public_key, NULL, |
870 FALSE)) { | 974 FALSE)) { |
871 purple_notify_error( | 975 purple_notify_error( |
872 gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL); | 976 gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL); |
873 return; | 977 return; |
874 } | 978 } |
939 purple_request_field_string_set_masked(f, TRUE); | 1043 purple_request_field_string_set_masked(f, TRUE); |
940 purple_request_field_group_add_field(g, f); | 1044 purple_request_field_group_add_field(g, f); |
941 purple_request_fields_add_group(fields, g); | 1045 purple_request_fields_add_group(fields, g); |
942 | 1046 |
943 purple_request_fields(gc, _("Create New SILC Key Pair"), | 1047 purple_request_fields(gc, _("Create New SILC Key Pair"), |
944 _("Create New SILC Key Pair"), NULL, fields, | 1048 _("Create New SILC Key Pair"), NULL, fields, |
945 _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), | 1049 _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), |
946 _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), | 1050 _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), |
947 gc->account, NULL, NULL, gc); | 1051 gc->account, NULL, NULL, gc); |
948 | 1052 |
949 g_strfreev(u); | 1053 g_strfreev(u); |
950 silc_free(hostname); | 1054 silc_free(hostname); |
951 } | 1055 } |
952 | 1056 |
961 silcpurple_change_passwd(PurpleConnection *gc, const char *old, const char *new) | 1065 silcpurple_change_passwd(PurpleConnection *gc, const char *old, const char *new) |
962 { | 1066 { |
963 char prd[256]; | 1067 char prd[256]; |
964 g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir()); | 1068 g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir()); |
965 silc_change_private_key_passphrase(purple_account_get_string(gc->account, | 1069 silc_change_private_key_passphrase(purple_account_get_string(gc->account, |
966 "private-key", | 1070 "private-key", |
967 prd), old, new); | 1071 prd), old, new); |
968 } | 1072 } |
969 | 1073 |
970 static void | 1074 static void |
971 silcpurple_show_set_info(PurplePluginAction *action) | 1075 silcpurple_show_set_info(PurplePluginAction *action) |
972 { | 1076 { |
1026 PurpleMessageFlags gflags; | 1130 PurpleMessageFlags gflags; |
1027 } *SilcPurpleIM; | 1131 } *SilcPurpleIM; |
1028 | 1132 |
1029 static void | 1133 static void |
1030 silcpurple_send_im_resolved(SilcClient client, | 1134 silcpurple_send_im_resolved(SilcClient client, |
1031 SilcClientConnection conn, | 1135 SilcClientConnection conn, |
1032 SilcClientEntry *clients, | 1136 SilcStatus status, |
1033 SilcUInt32 clients_count, | 1137 SilcDList clients, |
1034 void *context) | 1138 void *context) |
1035 { | 1139 { |
1036 PurpleConnection *gc = client->application; | 1140 PurpleConnection *gc = client->application; |
1037 SilcPurple sg = gc->proto_data; | 1141 SilcPurple sg = gc->proto_data; |
1038 SilcPurpleIM im = context; | 1142 SilcPurpleIM im = context; |
1039 PurpleConversation *convo; | 1143 PurpleConversation *convo; |
1040 char tmp[256], *nickname = NULL; | 1144 char tmp[256]; |
1041 SilcClientEntry client_entry; | 1145 SilcClientEntry client_entry; |
1042 #ifdef HAVE_SILCMIME_H | 1146 #ifdef HAVE_SILCMIME_H |
1043 SilcDList list; | 1147 SilcDList list; |
1044 #endif | 1148 #endif |
1045 | 1149 |
1046 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick, | 1150 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick, |
1047 sg->account); | 1151 sg->account); |
1048 if (!convo) | 1152 if (!convo) |
1049 return; | 1153 return; |
1050 | 1154 |
1051 if (!clients) | 1155 if (!clients) |
1052 goto err; | 1156 goto err; |
1053 | 1157 |
1054 if (clients_count > 1) { | 1158 if (silc_dlist_count(clients) > 1) { |
1055 silc_parse_userfqdn(im->nick, &nickname, NULL); | |
1056 | |
1057 /* Find the correct one. The im->nick might be a formatted nick | 1159 /* Find the correct one. The im->nick might be a formatted nick |
1058 so this will find the correct one. */ | 1160 so this will find the correct one. */ |
1059 clients = silc_client_get_clients_local(client, conn, | 1161 clients = silc_client_get_clients_local(client, conn, |
1060 nickname, im->nick, | 1162 im->nick, FALSE); |
1061 &clients_count); | |
1062 if (!clients) | 1163 if (!clients) |
1063 goto err; | 1164 goto err; |
1064 client_entry = clients[0]; | 1165 } |
1065 silc_free(clients); | 1166 |
1066 } else { | 1167 silc_dlist_start(clients); |
1067 client_entry = clients[0]; | 1168 client_entry = silc_dlist_get(clients); |
1068 } | |
1069 | 1169 |
1070 #ifdef HAVE_SILCMIME_H | 1170 #ifdef HAVE_SILCMIME_H |
1071 /* Check for images */ | 1171 /* Check for images */ |
1072 if (im->gflags & PURPLE_MESSAGE_IMAGES) { | 1172 if (im->gflags & PURPLE_MESSAGE_IMAGES) { |
1073 list = silcpurple_image_message(im->message, (SilcUInt32 *)&im->flags); | 1173 list = silcpurple_image_message(im->message, |
1174 (SilcUInt32 *)(void *)&im->flags); | |
1074 if (list) { | 1175 if (list) { |
1075 /* Send one or more MIME message. If more than one, they | 1176 /* Send one or more MIME message. If more than one, they |
1076 are MIME fragments due to over large message */ | 1177 are MIME fragments due to over large message */ |
1077 SilcBuffer buf; | 1178 SilcBuffer buf; |
1078 | 1179 |
1079 silc_dlist_start(list); | 1180 silc_dlist_start(list); |
1080 while ((buf = silc_dlist_get(list)) != SILC_LIST_END) | 1181 while ((buf = silc_dlist_get(list)) != SILC_LIST_END) |
1081 silc_client_send_private_message(client, conn, | 1182 silc_client_send_private_message(client, conn, |
1082 client_entry, im->flags, | 1183 client_entry, im->flags, NULL, |
1083 buf->data, buf->len, | 1184 buf->data, |
1084 TRUE); | 1185 silc_buffer_len(buf)); |
1085 silc_mime_partial_free(list); | 1186 silc_mime_partial_free(list); |
1086 purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, | 1187 purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, |
1087 im->message, 0, time(NULL)); | 1188 im->message, 0, time(NULL)); |
1088 goto out; | 1189 goto out; |
1089 } | 1190 } |
1090 } | 1191 } |
1091 #endif | 1192 #endif |
1092 | 1193 |
1093 /* Send the message */ | 1194 /* Send the message */ |
1094 silc_client_send_private_message(client, conn, client_entry, im->flags, | 1195 silc_client_send_private_message(client, conn, client_entry, im->flags, |
1095 (unsigned char *)im->message, im->message_len, TRUE); | 1196 NULL, (unsigned char *)im->message, im->message_len); |
1096 purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, | 1197 purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, |
1097 im->message, 0, time(NULL)); | 1198 im->message, 0, time(NULL)); |
1098 goto out; | 1199 goto out; |
1099 | 1200 |
1100 err: | 1201 err: |
1101 g_snprintf(tmp, sizeof(tmp), | 1202 g_snprintf(tmp, sizeof(tmp), |
1102 _("User <I>%s</I> is not present in the network"), im->nick); | 1203 _("User <I>%s</I> is not present in the network"), im->nick); |
1104 | 1205 |
1105 out: | 1206 out: |
1106 g_free(im->nick); | 1207 g_free(im->nick); |
1107 g_free(im->message); | 1208 g_free(im->message); |
1108 silc_free(im); | 1209 silc_free(im); |
1109 silc_free(nickname); | |
1110 } | 1210 } |
1111 | 1211 |
1112 static int | 1212 static int |
1113 silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message, | 1213 silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message, |
1114 PurpleMessageFlags flags) | 1214 PurpleMessageFlags flags) |
1115 { | 1215 { |
1116 SilcPurple sg = gc->proto_data; | 1216 SilcPurple sg = gc->proto_data; |
1117 SilcClient client = sg->client; | 1217 SilcClient client = sg->client; |
1118 SilcClientConnection conn = sg->conn; | 1218 SilcClientConnection conn = sg->conn; |
1119 SilcClientEntry *clients; | 1219 SilcDList clients; |
1120 SilcUInt32 clients_count, mflags; | 1220 SilcClientEntry client_entry; |
1121 char *nickname, *msg, *tmp; | 1221 SilcUInt32 mflags; |
1222 char *msg, *tmp; | |
1122 int ret = 0; | 1223 int ret = 0; |
1123 gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); | 1224 gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); |
1124 #ifdef HAVE_SILCMIME_H | 1225 #ifdef HAVE_SILCMIME_H |
1125 SilcDList list; | 1226 SilcDList list; |
1126 #endif | 1227 #endif |
1139 return 0; | 1240 return 0; |
1140 } | 1241 } |
1141 mflags |= SILC_MESSAGE_FLAG_ACTION; | 1242 mflags |= SILC_MESSAGE_FLAG_ACTION; |
1142 } else if (strlen(msg) > 1 && msg[0] == '/') { | 1243 } else if (strlen(msg) > 1 && msg[0] == '/') { |
1143 if (!silc_client_command_call(client, conn, msg + 1)) | 1244 if (!silc_client_command_call(client, conn, msg + 1)) |
1144 purple_notify_error(gc, _("Call Command"), _("Cannot call command"), | 1245 purple_notify_error(gc, _("Call Command"), |
1145 _("Unknown command")); | 1246 _("Cannot call command"), |
1247 _("Unknown command")); | |
1146 g_free(tmp); | 1248 g_free(tmp); |
1147 return 0; | 1249 return 0; |
1148 } | 1250 } |
1149 | 1251 |
1150 | |
1151 if (!silc_parse_userfqdn(who, &nickname, NULL)) { | |
1152 g_free(tmp); | |
1153 return 0; | |
1154 } | |
1155 | |
1156 if (sign) | 1252 if (sign) |
1157 mflags |= SILC_MESSAGE_FLAG_SIGNED; | 1253 mflags |= SILC_MESSAGE_FLAG_SIGNED; |
1158 | 1254 |
1159 /* Find client entry */ | 1255 /* Find client entry */ |
1160 clients = silc_client_get_clients_local(client, conn, nickname, who, | 1256 clients = silc_client_get_clients_local(client, conn, who, FALSE); |
1161 &clients_count); | |
1162 if (!clients) { | 1257 if (!clients) { |
1163 /* Resolve unknown user */ | 1258 /* Resolve unknown user */ |
1164 SilcPurpleIM im = silc_calloc(1, sizeof(*im)); | 1259 SilcPurpleIM im = silc_calloc(1, sizeof(*im)); |
1165 if (!im) { | 1260 if (!im) { |
1166 g_free(tmp); | 1261 g_free(tmp); |
1169 im->nick = g_strdup(who); | 1264 im->nick = g_strdup(who); |
1170 im->message = g_strdup(message); | 1265 im->message = g_strdup(message); |
1171 im->message_len = strlen(im->message); | 1266 im->message_len = strlen(im->message); |
1172 im->flags = mflags; | 1267 im->flags = mflags; |
1173 im->gflags = flags; | 1268 im->gflags = flags; |
1174 silc_client_get_clients(client, conn, nickname, NULL, | 1269 silc_client_get_clients(client, conn, who, NULL, |
1175 silcpurple_send_im_resolved, im); | 1270 silcpurple_send_im_resolved, im); |
1176 silc_free(nickname); | |
1177 g_free(tmp); | 1271 g_free(tmp); |
1178 return 0; | 1272 return 0; |
1179 } | 1273 } |
1274 | |
1275 silc_dlist_start(clients); | |
1276 client_entry = silc_dlist_get(clients); | |
1180 | 1277 |
1181 #ifdef HAVE_SILCMIME_H | 1278 #ifdef HAVE_SILCMIME_H |
1182 /* Check for images */ | 1279 /* Check for images */ |
1183 if (flags & PURPLE_MESSAGE_IMAGES) { | 1280 if (flags & PURPLE_MESSAGE_IMAGES) { |
1184 list = silcpurple_image_message(message, &mflags); | 1281 list = silcpurple_image_message(message, &mflags); |
1189 | 1286 |
1190 silc_dlist_start(list); | 1287 silc_dlist_start(list); |
1191 while ((buf = silc_dlist_get(list)) != SILC_LIST_END) | 1288 while ((buf = silc_dlist_get(list)) != SILC_LIST_END) |
1192 ret = | 1289 ret = |
1193 silc_client_send_private_message(client, conn, | 1290 silc_client_send_private_message(client, conn, |
1194 clients[0], mflags, | 1291 client_entry, mflags, NULL, |
1195 buf->data, buf->len, | 1292 buf->data, |
1196 TRUE); | 1293 silc_buffer_len(buf)); |
1197 silc_mime_partial_free(list); | 1294 silc_mime_partial_free(list); |
1198 g_free(tmp); | 1295 g_free(tmp); |
1199 silc_free(nickname); | 1296 silc_client_list_free(client, conn, clients); |
1200 silc_free(clients); | |
1201 return ret; | 1297 return ret; |
1202 } | 1298 } |
1203 } | 1299 } |
1204 #endif | 1300 #endif |
1205 | 1301 |
1206 /* Send private message directly */ | 1302 /* Send private message directly */ |
1207 ret = silc_client_send_private_message(client, conn, clients[0], | 1303 ret = silc_client_send_private_message(client, conn, client_entry, |
1208 mflags, | 1304 mflags, NULL, |
1209 (unsigned char *)msg, | 1305 (unsigned char *)msg, |
1210 strlen(msg), TRUE); | 1306 strlen(msg)); |
1211 | 1307 |
1212 g_free(tmp); | 1308 g_free(tmp); |
1213 silc_free(nickname); | 1309 silc_client_list_free(client, conn, clients); |
1214 silc_free(clients); | |
1215 return ret; | 1310 return ret; |
1216 } | 1311 } |
1217 | 1312 |
1218 | 1313 |
1219 static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) { | 1314 static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) { |
1220 /* split this single menu building function back into the two | 1315 /* split this single menu building function back into the two |
1221 original: one for buddies and one for chats */ | 1316 original: one for buddies and one for chats */ |
1222 | |
1223 if(PURPLE_BLIST_NODE_IS_CHAT(node)) { | 1317 if(PURPLE_BLIST_NODE_IS_CHAT(node)) { |
1224 return silcpurple_chat_menu((PurpleChat *) node); | 1318 return silcpurple_chat_menu((PurpleChat *) node); |
1225 } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { | 1319 } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { |
1226 return silcpurple_buddy_menu((PurpleBuddy *) node); | 1320 return silcpurple_buddy_menu((PurpleBuddy *) node); |
1227 } else { | 1321 } else { |
1546 | 1640 |
1547 if (sg == NULL) | 1641 if (sg == NULL) |
1548 return PURPLE_CMD_RET_FAILED; | 1642 return PURPLE_CMD_RET_FAILED; |
1549 | 1643 |
1550 silc_client_command_call(sg->client, sg->conn, NULL, | 1644 silc_client_command_call(sg->client, sg->conn, NULL, |
1551 "QUIT", (args && args[0]) ? args[0] : "Download this: " PURPLE_WEBSITE, NULL); | 1645 "QUIT", (args && args[0]) ? args[0] : "Download Pidgin: " PURPLE_WEBSITE, NULL); |
1552 | 1646 |
1553 return PURPLE_CMD_RET_OK; | 1647 return PURPLE_CMD_RET_OK; |
1554 } | 1648 } |
1555 | 1649 |
1556 static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv, | 1650 static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv, |
1727 OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE, | 1821 OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE, |
1728 #else | 1822 #else |
1729 OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | | 1823 OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | |
1730 OPT_PROTO_PASSWORD_OPTIONAL, | 1824 OPT_PROTO_PASSWORD_OPTIONAL, |
1731 #endif | 1825 #endif |
1732 NULL, /* user_splits */ | 1826 NULL, /* user_splits */ |
1733 NULL, /* protocol_options */ | 1827 NULL, /* protocol_options */ |
1734 #ifdef SILC_ATTRIBUTE_USER_ICON | 1828 #ifdef SILC_ATTRIBUTE_USER_ICON |
1735 {"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ | 1829 {"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ |
1736 #else | 1830 #else |
1737 NO_BUDDY_ICONS, | 1831 NO_BUDDY_ICONS, |
1738 #endif | 1832 #endif |
1739 silcpurple_list_icon, /* list_icon */ | 1833 silcpurple_list_icon, /* list_icon */ |
1740 NULL, /* list_emblems */ | 1834 NULL, /* list_emblems */ |
1741 silcpurple_status_text, /* status_text */ | 1835 silcpurple_status_text, /* status_text */ |
1742 silcpurple_tooltip_text, /* tooltip_text */ | 1836 silcpurple_tooltip_text, /* tooltip_text */ |
1743 silcpurple_away_states, /* away_states */ | 1837 silcpurple_away_states, /* away_states */ |
1744 silcpurple_blist_node_menu, /* blist_node_menu */ | 1838 silcpurple_blist_node_menu, /* blist_node_menu */ |
1745 silcpurple_chat_info, /* chat_info */ | 1839 silcpurple_chat_info, /* chat_info */ |
1746 silcpurple_chat_info_defaults,/* chat_info_defaults */ | 1840 silcpurple_chat_info_defaults, /* chat_info_defaults */ |
1747 silcpurple_login, /* login */ | 1841 silcpurple_login, /* login */ |
1748 silcpurple_close, /* close */ | 1842 silcpurple_close, /* close */ |
1749 silcpurple_send_im, /* send_im */ | 1843 silcpurple_send_im, /* send_im */ |
1750 silcpurple_set_info, /* set_info */ | 1844 silcpurple_set_info, /* set_info */ |
1751 NULL, /* send_typing */ | 1845 NULL, /* send_typing */ |
1752 silcpurple_get_info, /* get_info */ | 1846 silcpurple_get_info, /* get_info */ |
1753 silcpurple_set_status, /* set_status */ | 1847 silcpurple_set_status, /* set_status */ |
1754 silcpurple_idle_set, /* set_idle */ | 1848 silcpurple_idle_set, /* set_idle */ |
1755 silcpurple_change_passwd, /* change_passwd */ | 1849 silcpurple_change_passwd, /* change_passwd */ |
1756 silcpurple_add_buddy, /* add_buddy */ | 1850 silcpurple_add_buddy, /* add_buddy */ |
1757 NULL, /* add_buddies */ | 1851 NULL, /* add_buddies */ |
1758 silcpurple_remove_buddy, /* remove_buddy */ | 1852 silcpurple_remove_buddy, /* remove_buddy */ |
1759 NULL, /* remove_buddies */ | 1853 NULL, /* remove_buddies */ |
1760 NULL, /* add_permit */ | 1854 NULL, /* add_permit */ |
1761 NULL, /* add_deny */ | 1855 NULL, /* add_deny */ |
1762 NULL, /* rem_permit */ | 1856 NULL, /* rem_permit */ |
1763 NULL, /* rem_deny */ | 1857 NULL, /* rem_deny */ |
1764 NULL, /* set_permit_deny */ | 1858 NULL, /* set_permit_deny */ |
1765 silcpurple_chat_join, /* join_chat */ | 1859 silcpurple_chat_join, /* join_chat */ |
1766 NULL, /* reject_chat */ | 1860 NULL, /* reject_chat */ |
1767 silcpurple_get_chat_name, /* get_chat_name */ | 1861 silcpurple_get_chat_name, /* get_chat_name */ |
1768 silcpurple_chat_invite, /* chat_invite */ | 1862 silcpurple_chat_invite, /* chat_invite */ |
1769 silcpurple_chat_leave, /* chat_leave */ | 1863 silcpurple_chat_leave, /* chat_leave */ |
1770 NULL, /* chat_whisper */ | 1864 NULL, /* chat_whisper */ |
1771 silcpurple_chat_send, /* chat_send */ | 1865 silcpurple_chat_send, /* chat_send */ |
1772 silcpurple_keepalive, /* keepalive */ | 1866 silcpurple_keepalive, /* keepalive */ |
1773 NULL, /* register_user */ | 1867 NULL, /* register_user */ |
1774 NULL, /* get_cb_info */ | 1868 NULL, /* get_cb_info */ |
1775 NULL, /* get_cb_away */ | 1869 NULL, /* get_cb_away */ |
1776 NULL, /* alias_buddy */ | 1870 NULL, /* alias_buddy */ |
1777 NULL, /* group_buddy */ | 1871 NULL, /* group_buddy */ |
1778 NULL, /* rename_group */ | 1872 NULL, /* rename_group */ |
1779 NULL, /* buddy_free */ | 1873 NULL, /* buddy_free */ |
1780 NULL, /* convo_closed */ | 1874 NULL, /* convo_closed */ |
1781 NULL, /* normalize */ | 1875 NULL, /* normalize */ |
1782 #ifdef SILC_ATTRIBUTE_USER_ICON | 1876 #ifdef SILC_ATTRIBUTE_USER_ICON |
1783 silcpurple_buddy_set_icon, /* set_buddy_icon */ | 1877 silcpurple_buddy_set_icon, /* set_buddy_icon */ |
1784 #else | 1878 #else |
1785 NULL, | 1879 NULL, |
1786 #endif | 1880 #endif |
1787 NULL, /* remove_group */ | 1881 NULL, /* remove_group */ |
1788 NULL, /* get_cb_real_name */ | 1882 NULL, /* get_cb_real_name */ |
1789 silcpurple_chat_set_topic, /* set_chat_topic */ | 1883 silcpurple_chat_set_topic, /* set_chat_topic */ |
1790 NULL, /* find_blist_chat */ | 1884 NULL, /* find_blist_chat */ |
1791 silcpurple_roomlist_get_list, /* roomlist_get_list */ | 1885 silcpurple_roomlist_get_list, /* roomlist_get_list */ |
1792 silcpurple_roomlist_cancel, /* roomlist_cancel */ | 1886 silcpurple_roomlist_cancel, /* roomlist_cancel */ |
1793 NULL, /* roomlist_expand_category */ | 1887 NULL, /* roomlist_expand_category */ |
1794 NULL, /* can_receive_file */ | 1888 NULL, /* can_receive_file */ |
1795 silcpurple_ftp_send_file, /* send_file */ | 1889 silcpurple_ftp_send_file, /* send_file */ |
1796 silcpurple_ftp_new_xfer, /* new_xfer */ | 1890 silcpurple_ftp_new_xfer, /* new_xfer */ |
1797 NULL, /* offline_message */ | 1891 NULL, /* offline_message */ |
1798 &silcpurple_wb_ops, /* whiteboard_prpl_ops */ | 1892 &silcpurple_wb_ops, /* whiteboard_prpl_ops */ |
1799 NULL, /* send_raw */ | 1893 NULL, /* send_raw */ |
1800 NULL, /* roomlist_room_serialize */ | 1894 NULL, /* roomlist_room_serialize */ |
1801 | 1895 |
1802 /* padding */ | 1896 /* padding */ |
1803 NULL, | 1897 NULL, |
1804 NULL, | 1898 NULL, |
1805 NULL, | 1899 NULL, |
1809 static PurplePluginInfo info = | 1903 static PurplePluginInfo info = |
1810 { | 1904 { |
1811 PURPLE_PLUGIN_MAGIC, | 1905 PURPLE_PLUGIN_MAGIC, |
1812 PURPLE_MAJOR_VERSION, | 1906 PURPLE_MAJOR_VERSION, |
1813 PURPLE_MINOR_VERSION, | 1907 PURPLE_MINOR_VERSION, |
1814 PURPLE_PLUGIN_PROTOCOL, /**< type */ | 1908 PURPLE_PLUGIN_PROTOCOL, /**< type */ |
1815 NULL, /**< ui_requirement */ | 1909 NULL, /**< ui_requirement */ |
1816 0, /**< flags */ | 1910 0, /**< flags */ |
1817 NULL, /**< dependencies */ | 1911 NULL, /**< dependencies */ |
1818 PURPLE_PRIORITY_DEFAULT, /**< priority */ | 1912 PURPLE_PRIORITY_DEFAULT, /**< priority */ |
1819 | 1913 |
1820 "prpl-silc", /**< id */ | 1914 "prpl-silc", /**< id */ |
1821 "SILC", /**< name */ | 1915 "SILC", /**< name */ |
1822 "1.0", /**< version */ | 1916 "1.1", /**< version */ |
1823 /** summary */ | 1917 /** summary */ |
1824 N_("SILC Protocol Plugin"), | 1918 N_("SILC Protocol Plugin"), |
1825 /** description */ | 1919 /** description */ |
1826 N_("Secure Internet Live Conferencing (SILC) Protocol"), | 1920 N_("Secure Internet Live Conferencing (SILC) Protocol"), |
1827 "Pekka Riikonen", /**< author */ | 1921 "Pekka Riikonen", /**< author */ |
1828 "http://silcnet.org/", /**< homepage */ | 1922 "http://silcnet.org/", /**< homepage */ |
1829 | 1923 |
1830 NULL, /**< load */ | 1924 NULL, /**< load */ |
1831 NULL, /**< unload */ | 1925 NULL, /**< unload */ |
1832 NULL, /**< destroy */ | 1926 NULL, /**< destroy */ |
1833 | 1927 |
1834 NULL, /**< ui_info */ | 1928 NULL, /**< ui_info */ |
1835 &prpl_info, /**< extra_info */ | 1929 &prpl_info, /**< extra_info */ |
1836 NULL, /**< prefs_info */ | 1930 NULL, /**< prefs_info */ |
1837 silcpurple_actions, | 1931 silcpurple_actions, |
1838 | 1932 |
1839 /* padding */ | 1933 /* padding */ |
1840 NULL, | 1934 NULL, |
1841 NULL, | 1935 NULL, |
1858 split = purple_account_user_split_new(_("Network"), "silcnet.org", '@'); | 1952 split = purple_account_user_split_new(_("Network"), "silcnet.org", '@'); |
1859 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); | 1953 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); |
1860 | 1954 |
1861 /* Account options */ | 1955 /* Account options */ |
1862 option = purple_account_option_string_new(_("Connect server"), | 1956 option = purple_account_option_string_new(_("Connect server"), |
1863 "server", | 1957 "server", |
1864 "silc.silcnet.org"); | 1958 "silc.silcnet.org"); |
1865 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 1959 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1866 option = purple_account_option_int_new(_("Port"), "port", 706); | 1960 option = purple_account_option_int_new(_("Port"), "port", 706); |
1867 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 1961 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1868 g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); | 1962 g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); |
1869 option = purple_account_option_string_new(_("Public Key file"), | 1963 option = purple_account_option_string_new(_("Public Key file"), |
1870 "public-key", tmp); | 1964 "public-key", tmp); |
1871 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 1965 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1872 g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); | 1966 g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); |
1873 option = purple_account_option_string_new(_("Private Key file"), | 1967 option = purple_account_option_string_new(_("Private Key file"), |
1874 "private-key", tmp); | 1968 "private-key", tmp); |
1875 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 1969 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1876 | 1970 |
1877 for (i = 0; silc_default_ciphers[i].name; i++) { | 1971 for (i = 0; silc_default_ciphers[i].name; i++) { |
1878 kvp = g_new0(PurpleKeyValuePair, 1); | 1972 kvp = g_new0(PurpleKeyValuePair, 1); |
1879 kvp->key = g_strdup(silc_default_ciphers[i].name); | 1973 kvp->key = g_strdup(silc_default_ciphers[i].name); |
1891 list = g_list_append(list, kvp); | 1985 list = g_list_append(list, kvp); |
1892 } | 1986 } |
1893 option = purple_account_option_list_new(_("HMAC"), "hmac", list); | 1987 option = purple_account_option_list_new(_("HMAC"), "hmac", list); |
1894 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 1988 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1895 | 1989 |
1990 option = purple_account_option_bool_new(_("Use Perfect Forward Secrecy"), | |
1991 "pfs", FALSE); | |
1992 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
1993 | |
1896 option = purple_account_option_bool_new(_("Public key authentication"), | 1994 option = purple_account_option_bool_new(_("Public key authentication"), |
1897 "pubkey-auth", FALSE); | 1995 "pubkey-auth", FALSE); |
1898 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 1996 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1899 option = purple_account_option_bool_new(_("Reject watching by other users"), | 1997 option = purple_account_option_bool_new(_("Reject watching by other users"), |
1900 "reject-watch", FALSE); | 1998 "reject-watch", FALSE); |
1901 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 1999 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1902 option = purple_account_option_bool_new(_("Block invites"), | 2000 option = purple_account_option_bool_new(_("Block invites"), |
1903 "block-invites", FALSE); | 2001 "block-invites", FALSE); |
1904 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 2002 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1905 option = purple_account_option_bool_new(_("Block IMs without Key Exchange"), | 2003 option = purple_account_option_bool_new(_("Block IMs without Key Exchange"), |
1906 "block-ims", FALSE); | 2004 "block-ims", FALSE); |
1907 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 2005 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1908 option = purple_account_option_bool_new(_("Reject online status attribute requests"), | 2006 option = purple_account_option_bool_new(_("Reject online status attribute requests"), |
1909 "reject-attrs", FALSE); | 2007 "reject-attrs", FALSE); |
1910 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 2008 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1911 option = purple_account_option_bool_new(_("Block messages to whiteboard"), | 2009 option = purple_account_option_bool_new(_("Block messages to whiteboard"), |
1912 "block-wb", FALSE); | 2010 "block-wb", FALSE); |
1913 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 2011 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1914 option = purple_account_option_bool_new(_("Automatically open whiteboard"), | 2012 option = purple_account_option_bool_new(_("Automatically open whiteboard"), |
1915 "open-wb", FALSE); | 2013 "open-wb", FALSE); |
1916 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 2014 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1917 option = purple_account_option_bool_new(_("Digitally sign and verify all messages"), | 2015 option = purple_account_option_bool_new(_("Digitally sign and verify all messages"), |
1918 "sign-verify", FALSE); | 2016 "sign-verify", FALSE); |
1919 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | 2017 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
1920 | 2018 |
1921 purple_prefs_remove("/plugins/prpl/silc"); | 2019 purple_prefs_remove("/plugins/prpl/silc"); |
1922 | 2020 |
2021 silc_log_set_callback(SILC_LOG_ERROR, silcpurple_log_error, NULL); | |
1923 silcpurple_register_commands(); | 2022 silcpurple_register_commands(); |
2023 | |
2024 #if 0 | |
2025 silc_log_debug(TRUE); | |
2026 silc_log_set_debug_string("*client*"); | |
2027 #endif | |
1924 | 2028 |
1925 #ifdef _WIN32 | 2029 #ifdef _WIN32 |
1926 silc_net_win32_init(); | 2030 silc_net_win32_init(); |
1927 #endif | 2031 #endif |
1928 } | 2032 } |