| 61 /* this is so bad, and if Zephyr weren't so fucked up to begin with I |
61 /* this is so bad, and if Zephyr weren't so fucked up to begin with I |
| 62 * wouldn't do this. but it is so i will. */ |
62 * wouldn't do this. but it is so i will. */ |
| 63 static guint32 nottimer = 0; |
63 static guint32 nottimer = 0; |
| 64 static guint32 loctimer = 0; |
64 static guint32 loctimer = 0; |
| 65 struct gaim_connection *zgc = NULL; |
65 struct gaim_connection *zgc = NULL; |
| |
66 static GList *pending_zloc_names = NULL; |
| 66 |
67 |
| 67 /* just for debugging |
68 /* just for debugging |
| 68 static void handle_unknown(ZNotice_t notice) |
69 static void handle_unknown(ZNotice_t notice) |
| 69 { |
70 { |
| 70 g_print("z_packet: %s\n", notice.z_packet); |
71 g_print("z_packet: %s\n", notice.z_packet); |
| 79 g_print("z_message_len: %d\n", notice.z_message_len); |
80 g_print("z_message_len: %d\n", notice.z_message_len); |
| 80 g_print("\n"); |
81 g_print("\n"); |
| 81 } |
82 } |
| 82 */ |
83 */ |
| 83 |
84 |
| |
85 static char *zephyr_normalize(const char *orig) |
| |
86 { |
| |
87 static char buf[80]; |
| |
88 if (strchr(orig, '@')) { |
| |
89 g_snprintf(buf, 80, "%s", orig); |
| |
90 } else { |
| |
91 g_snprintf(buf, 80, "%s@%s", orig, ZGetRealm()); |
| |
92 } |
| |
93 return buf; |
| |
94 } |
| |
95 |
| |
96 static gboolean pending_zloc(char *who) |
| |
97 { |
| |
98 GList *curr; |
| |
99 for (curr = pending_zloc_names; curr != NULL; curr = curr->next) { |
| |
100 if (!g_strcasecmp(who, (char*)curr->data)) { |
| |
101 g_free((char*)curr->data); |
| |
102 pending_zloc_names = g_list_remove(pending_zloc_names, curr->data); |
| |
103 return TRUE; |
| |
104 } |
| |
105 } |
| |
106 return FALSE; |
| |
107 } |
| |
108 |
| |
109 static void zephyr_zloc(struct gaim_connection *gc, char *who) |
| |
110 { |
| |
111 ZAsyncLocateData_t ald; |
| |
112 |
| |
113 if (ZRequestLocations(zephyr_normalize(who), &ald, UNACKED, ZAUTH) |
| |
114 != ZERR_NONE) { |
| |
115 return; |
| |
116 } |
| |
117 pending_zloc_names = g_list_append(pending_zloc_names, |
| |
118 g_strdup(zephyr_normalize(who))); |
| |
119 } |
| |
120 |
| |
121 static void info_callback(GtkObject *obj, char *who) |
| |
122 { |
| |
123 zephyr_zloc(gtk_object_get_user_data(obj), who); |
| |
124 } |
| |
125 |
| |
126 static void zephyr_buddy_menu(GtkWidget *menu, struct gaim_connection *gc, char *who) |
| |
127 { |
| |
128 GtkWidget *button; |
| |
129 |
| |
130 button = gtk_menu_item_new_with_label(_("ZLocate")); |
| |
131 gtk_signal_connect(GTK_OBJECT(button), "activate", |
| |
132 GTK_SIGNAL_FUNC(info_callback), who); |
| |
133 gtk_object_set_user_data(GTK_OBJECT(button), gc); |
| |
134 gtk_menu_append(GTK_MENU(menu), button); |
| |
135 gtk_widget_show(button); |
| |
136 } |
| |
137 |
| 84 static void handle_message(ZNotice_t notice, struct sockaddr_in from) |
138 static void handle_message(ZNotice_t notice, struct sockaddr_in from) |
| 85 { |
139 { |
| 86 if (!g_strcasecmp(notice.z_class, LOGIN_CLASS)) { |
140 if (!g_strcasecmp(notice.z_class, LOGIN_CLASS)) { |
| 87 /* well, we'll be updating in 2 seconds anyway, might as well ignore this. */ |
141 /* well, we'll be updating in 2 seconds anyway, might as well ignore this. */ |
| 88 } else if (!g_strcasecmp(notice.z_class, LOCATE_CLASS)) { |
142 } else if (!g_strcasecmp(notice.z_class, LOCATE_CLASS)) { |
| 100 } |
154 } |
| 101 if (!b) { |
155 if (!b) { |
| 102 free(user); |
156 free(user); |
| 103 return; |
157 return; |
| 104 } |
158 } |
| |
159 if (pending_zloc(b->name)) { |
| |
160 ZLocations_t locs; |
| |
161 int one = 1; |
| |
162 GString *str = g_string_new(""); |
| |
163 g_string_sprintfa(str, "<b>User:</b> %s<br>" |
| |
164 "<b>Alias:</b> %s<br>", |
| |
165 b->name, b->show); |
| |
166 if (!nlocs) { |
| |
167 g_string_sprintfa(str, "<br>Hidden or not logged-in"); |
| |
168 } |
| |
169 for (; nlocs > 0; nlocs--) { |
| |
170 ZGetLocations(&locs, &one); |
| |
171 g_string_sprintfa(str, "<br>At %s since %s", locs.host, |
| |
172 locs.time); |
| |
173 } |
| |
174 g_show_info_text(str->str); |
| |
175 g_string_free(str, TRUE); |
| |
176 } |
| 105 serv_got_update(zgc, b->name, nlocs, 0, 0, 0, 0, 0); |
177 serv_got_update(zgc, b->name, nlocs, 0, 0, 0, 0, 0); |
| 106 |
178 |
| 107 free(user); |
179 free(user); |
| 108 } |
180 } |
| 109 } else if (!g_strcasecmp(notice.z_class, "MESSAGE")) { |
181 } else if (!g_strcasecmp(notice.z_class, "MESSAGE")) { |
| 159 struct group *g = gr->data; |
231 struct group *g = gr->data; |
| 160 m = g->members; |
232 m = g->members; |
| 161 while (m) { |
233 while (m) { |
| 162 struct buddy *b = m->data; |
234 struct buddy *b = m->data; |
| 163 char *chk; |
235 char *chk; |
| 164 if (!strchr(b->name, '@')) |
236 chk = g_strdup(zephyr_normalize(b->name)); |
| 165 chk = g_strdup_printf("%s@%s", b->name, ZGetRealm()); |
|
| 166 else |
|
| 167 chk = g_strdup(b->name); |
|
| 168 /* doesn't matter if this fails or not; we'll just move on to the next one */ |
237 /* doesn't matter if this fails or not; we'll just move on to the next one */ |
| 169 ZRequestLocations(chk, &ald, UNACKED, ZAUTH); |
238 ZRequestLocations(chk, &ald, UNACKED, ZAUTH); |
| 170 g_free(chk); |
239 g_free(chk); |
| 171 m = m->next; |
240 m = m->next; |
| 172 } |
241 } |
| 202 *tmp = '\0'; |
271 *tmp = '\0'; |
| 203 g_strchug(str); |
272 g_strchug(str); |
| 204 g_strchomp(str); |
273 g_strchomp(str); |
| 205 } |
274 } |
| 206 |
275 |
| |
276 static void process_zsubs() |
| |
277 { |
| |
278 FILE *f; |
| |
279 gchar *fname; |
| |
280 gchar buff[BUFSIZ]; |
| |
281 |
| |
282 fname = g_strdup_printf("%s/.zephyr.subs", g_getenv("HOME")); |
| |
283 f = fopen(fname, "r"); |
| |
284 if (f) { |
| |
285 char **triple; |
| |
286 ZSubscription_t sub; |
| |
287 char *recip; |
| |
288 while (fgets(buff, BUFSIZ, f)) { |
| |
289 strip_comments(buff); |
| |
290 if (buff[0]) { |
| |
291 triple = g_strsplit(buff, ",", 3); |
| |
292 if (triple[0] && triple[1] && triple[2]) { |
| |
293 sub.zsub_class = triple[0]; |
| |
294 sub.zsub_classinst = triple[1]; |
| |
295 if (!g_strcasecmp(triple[2], "%me%")) { |
| |
296 recip = g_strdup_printf("%s@%s", g_getenv("USER"), |
| |
297 ZGetRealm()); |
| |
298 } else if (!g_strcasecmp(triple[2], "*")) { |
| |
299 /* wildcard */ |
| |
300 recip = g_strdup_printf("@%s", ZGetRealm()); |
| |
301 } else { |
| |
302 recip = g_strdup(triple[2]); |
| |
303 } |
| |
304 sub.zsub_recipient = recip; |
| |
305 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { |
| |
306 debug_printf("Zephyr: Couldn't subscribe to %s, %s, " |
| |
307 "%s\n", |
| |
308 sub.zsub_class, |
| |
309 sub.zsub_classinst, |
| |
310 sub.zsub_recipient); |
| |
311 } |
| |
312 g_free(recip); |
| |
313 } |
| |
314 g_strfreev(triple); |
| |
315 } |
| |
316 } |
| |
317 } |
| |
318 } |
| |
319 |
| 207 static void process_anyone() |
320 static void process_anyone() |
| 208 { |
321 { |
| 209 FILE *fd; |
322 FILE *fd; |
| 210 gchar buff[BUFSIZ], *filename; |
323 gchar buff[BUFSIZ], *filename; |
| 211 |
324 |
| 239 sub.zsub_class = "MESSAGE"; |
352 sub.zsub_class = "MESSAGE"; |
| 240 sub.zsub_classinst = "PERSONAL"; |
353 sub.zsub_classinst = "PERSONAL"; |
| 241 sub.zsub_recipient = ZGetSender(); |
354 sub.zsub_recipient = ZGetSender(); |
| 242 |
355 |
| 243 /* we don't care if this fails. i'm lying right now. */ |
356 /* we don't care if this fails. i'm lying right now. */ |
| 244 ZSubscribeTo(&sub, 1, 0); |
357 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { |
| |
358 debug_printf("Zephyr: Couldn't subscribe to messages!\n"); |
| |
359 } |
| 245 |
360 |
| 246 account_online(zgc); |
361 account_online(zgc); |
| 247 serv_finish_login(zgc); |
362 serv_finish_login(zgc); |
| 248 |
363 |
| 249 if (bud_list_cache_exists(zgc)) |
364 if (bud_list_cache_exists(zgc)) |
| 250 do_import(NULL, zgc); |
365 do_import(NULL, zgc); |
| 251 process_anyone(); |
366 process_anyone(); |
| 252 /* should also process .zephyr.subs */ |
367 /* call process_zsubs to subscribe. still commented out since I don't know |
| |
368 * how you want to handle incoming msgs from subs. |
| |
369 process_zsubs(); */ |
| 253 |
370 |
| 254 nottimer = gtk_timeout_add(100, check_notify, NULL); |
371 nottimer = gtk_timeout_add(100, check_notify, NULL); |
| 255 loctimer = gtk_timeout_add(2000, check_loc, NULL); |
372 loctimer = gtk_timeout_add(2000, check_loc, NULL); |
| 256 } |
373 } |
| 257 |
374 |
| 258 static void zephyr_close(struct gaim_connection *gc) |
375 static void zephyr_close(struct gaim_connection *gc) |
| 259 { |
376 { |
| |
377 g_list_foreach(pending_zloc_names, (GFunc)g_free, NULL); |
| |
378 g_list_free(pending_zloc_names); |
| 260 /* should probably write .anyone, but eh. we all use gaim exclusively, right? :-P */ |
379 /* should probably write .anyone, but eh. we all use gaim exclusively, right? :-P */ |
| 261 if (nottimer) |
380 if (nottimer) |
| 262 gtk_timeout_remove(nottimer); |
381 gtk_timeout_remove(nottimer); |
| 263 nottimer = 0; |
382 nottimer = 0; |
| 264 if (loctimer) |
383 if (loctimer) |
| 273 static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { } |
392 static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { } |
| 274 static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { } |
393 static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { } |
| 275 |
394 |
| 276 static void zephyr_send_im(struct gaim_connection *gc, char *who, char *im, int away) { |
395 static void zephyr_send_im(struct gaim_connection *gc, char *who, char *im, int away) { |
| 277 ZNotice_t notice; |
396 ZNotice_t notice; |
| |
397 char *buf; |
| |
398 char *sig; |
| |
399 |
| |
400 sig = ZGetVariable("zwrite-signature"); |
| |
401 if (!sig) { |
| |
402 sig = g_get_real_name(); |
| |
403 } |
| |
404 buf = g_strdup_printf("%s%c%s", sig, '\0', im); |
| 278 |
405 |
| 279 bzero((char *)¬ice, sizeof(notice)); |
406 bzero((char *)¬ice, sizeof(notice)); |
| 280 notice.z_kind = ACKED; |
407 notice.z_kind = ACKED; |
| 281 notice.z_port = 0; |
408 notice.z_port = 0; |
| 282 notice.z_opcode = ""; |
409 notice.z_opcode = ""; |
| 283 notice.z_class = "MESSAGE"; |
410 notice.z_class = "MESSAGE"; |
| 284 notice.z_class_inst = "PERSONAL"; |
411 notice.z_class_inst = "PERSONAL"; |
| 285 notice.z_sender = 0; |
412 notice.z_sender = 0; |
| 286 notice.z_recipient = who; |
413 notice.z_recipient = who; |
| 287 notice.z_default_format = |
414 notice.z_default_format = |
| 288 "Class $class, Instance $instance:\nTo: @bold($recipient) at $time $date\n$message"; |
415 "Class $class, Instance $instance:\n" |
| 289 notice.z_message_len = strlen(im) + 1; |
416 "To: @bold($recipient) at $time $date\n" |
| 290 notice.z_message = im; |
417 "From: @bold($1) <$sender>\n\n$2"; |
| |
418 notice.z_message_len = strlen(im) + strlen(sig) + 4; |
| |
419 notice.z_message = buf; |
| 291 ZSendNotice(¬ice, ZAUTH); |
420 ZSendNotice(¬ice, ZAUTH); |
| |
421 g_free(buf); |
| 292 } |
422 } |
| 293 |
423 |
| 294 static struct prpl *my_protocol = NULL; |
424 static struct prpl *my_protocol = NULL; |
| 295 |
425 |
| 296 void zephyr_init(struct prpl *ret) |
426 void zephyr_init(struct prpl *ret) |
| 300 ret->login = zephyr_login; |
430 ret->login = zephyr_login; |
| 301 ret->close = zephyr_close; |
431 ret->close = zephyr_close; |
| 302 ret->add_buddy = zephyr_add_buddy; |
432 ret->add_buddy = zephyr_add_buddy; |
| 303 ret->remove_buddy = zephyr_remove_buddy; |
433 ret->remove_buddy = zephyr_remove_buddy; |
| 304 ret->send_im = zephyr_send_im; |
434 ret->send_im = zephyr_send_im; |
| |
435 ret->get_info = zephyr_zloc; |
| |
436 ret->normalize = zephyr_normalize; |
| |
437 ret->buddy_menu = zephyr_buddy_menu; |
| 305 |
438 |
| 306 my_protocol = ret; |
439 my_protocol = ret; |
| 307 } |
440 } |
| 308 |
441 |
| 309 char *gaim_plugin_init(GModule *handle) |
442 char *gaim_plugin_init(GModule *handle) |