comparison plugins/zephyr/zephyr.c @ 1808:6a89897c8658

[gaim-migrate @ 1818] nsanch's patch for zephyr subscriptions. the only changes i made to it were slight style changes, so if there's anything broken, blame him, not me ;) committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sat, 05 May 2001 11:22:31 +0000
parents 60b3fd819cce
children b012f6b9095b
comparison
equal deleted inserted replaced
1807:ba8f463744c0 1808:6a89897c8658
32 #include "gaim.h" 32 #include "gaim.h"
33 #include "prpl.h" 33 #include "prpl.h"
34 #include "zephyr/zephyr.h" 34 #include "zephyr/zephyr.h"
35 35
36 typedef struct _zframe zframe; 36 typedef struct _zframe zframe;
37 typedef struct _zephyr_triple zephyr_triple;
37 38
38 /* struct I need for zephyr_to_html */ 39 /* struct I need for zephyr_to_html */
39 struct _zframe { 40 struct _zframe {
40 /* true for everything but @color, since inside the parens of that one is 41 /* true for everything but @color, since inside the parens of that one is
41 * the color. */ 42 * the color. */
45 /* text including the opening html thingie. */ 46 /* text including the opening html thingie. */
46 GString *text; 47 GString *text;
47 struct _zframe *enclosing; 48 struct _zframe *enclosing;
48 }; 49 };
49 50
51 struct _zephyr_triple {
52 char *class;
53 char *instance;
54 char *recipient;
55 char *name;
56 gboolean open;
57 int id;
58 };
59
50 char *name() 60 char *name()
51 { 61 {
52 return "Zephyr"; 62 return "Zephyr";
53 } 63 }
54 64
78 * wouldn't do this. but it is so i will. */ 88 * wouldn't do this. but it is so i will. */
79 static guint32 nottimer = 0; 89 static guint32 nottimer = 0;
80 static guint32 loctimer = 0; 90 static guint32 loctimer = 0;
81 struct gaim_connection *zgc = NULL; 91 struct gaim_connection *zgc = NULL;
82 static GList *pending_zloc_names = NULL; 92 static GList *pending_zloc_names = NULL;
93 static GSList *subscrips = NULL;
94 static int last_id = 0;
95 static GtkWidget *class_entry;
96 static GtkWidget *inst_entry;
97 static GtkWidget *recip_entry;
83 98
84 /* just for debugging 99 /* just for debugging
85 static void handle_unknown(ZNotice_t notice) 100 static void handle_unknown(ZNotice_t notice)
86 { 101 {
87 g_print("z_packet: %s\n", notice.z_packet); 102 g_print("z_packet: %s\n", notice.z_packet);
95 g_print("z_message: %s\n", notice.z_message); 110 g_print("z_message: %s\n", notice.z_message);
96 g_print("z_message_len: %d\n", notice.z_message_len); 111 g_print("z_message_len: %d\n", notice.z_message_len);
97 g_print("\n"); 112 g_print("\n");
98 } 113 }
99 */ 114 */
115
116 static zephyr_triple *new_triple(char *c, char *i, char *r)
117 {
118 zephyr_triple *zt;
119 zt = g_new0(zephyr_triple, 1);
120 zt->class = g_strdup(c);
121 zt->instance = g_strdup(i);
122 zt->recipient = g_strdup(r);
123 zt->name = g_strdup_printf("%s,%s,%s", c, i, r);
124 zt->id = ++last_id;
125 zt->open = FALSE;
126 return zt;
127 }
128
129 static void free_triple(zephyr_triple *zt)
130 {
131 g_free(zt->class);
132 g_free(zt->instance);
133 g_free(zt->recipient);
134 g_free(zt->name);
135 g_free(zt);
136 }
137
138 /* returns true if zt1 is a subset of zt2, i.e. zt2 has the same thing or
139 * wildcards in each field of zt1. */
140 static gboolean triple_subset(zephyr_triple *zt1, zephyr_triple *zt2)
141 {
142 if (g_strcasecmp(zt2->class, zt1->class) &&
143 g_strcasecmp(zt2->class, "*")) {
144 return FALSE;
145 }
146 if (g_strcasecmp(zt2->instance, zt1->instance) &&
147 g_strcasecmp(zt2->instance, "*")) {
148 return FALSE;
149 }
150 if (g_strcasecmp(zt2->recipient, zt1->recipient) &&
151 g_strcasecmp(zt2->recipient, "*")) {
152 return FALSE;
153 }
154 return TRUE;
155 }
156
157 static zephyr_triple *find_sub_by_triple(zephyr_triple *zt)
158 {
159 zephyr_triple *curr_t;
160 GSList *curr = subscrips;
161 while (curr) {
162 curr_t = curr->data;
163 if (triple_subset(zt, curr_t))
164 return curr_t;
165 curr = curr->next;
166 }
167 return NULL;
168 }
169
170 static zephyr_triple *find_sub_by_id(int id)
171 {
172 zephyr_triple *zt;
173 GSList *curr = subscrips;
174 while (curr) {
175 zt = curr->data;
176 if (zt->id == id)
177 return zt;
178 curr = curr->next;
179 }
180 return NULL;
181 }
100 182
101 /* utility macros that are useful for zephyr_to_html */ 183 /* utility macros that are useful for zephyr_to_html */
102 184
103 #define IS_OPENER(c) ((c == '{') || (c == '[') || (c == '(') || (c == '<')) 185 #define IS_OPENER(c) ((c == '{') || (c == '[') || (c == '(') || (c == '<'))
104 #define IS_CLOSER(c) ((c == '}') || (c == ']') || (c == ')') || (c == '>')) 186 #define IS_CLOSER(c) ((c == '}') || (c == ']') || (c == ')') || (c == '>'))
302 len = MAX(BUF_LONG, strlen(buf2)); 384 len = MAX(BUF_LONG, strlen(buf2));
303 buf = g_malloc(len + 1); 385 buf = g_malloc(len + 1);
304 g_snprintf(buf, len + 1, "%s", buf2); 386 g_snprintf(buf, len + 1, "%s", buf2);
305 serv_got_im(zgc, notice.z_sender, buf, 0, time((time_t)NULL)); 387 serv_got_im(zgc, notice.z_sender, buf, 0, time((time_t)NULL));
306 g_free(buf); 388 g_free(buf);
389 } else {
390 zephyr_triple *zt1, *zt2;
391 zt1 = new_triple(notice.z_class, notice.z_class_inst,
392 notice.z_recipient);
393 zt2 = find_sub_by_triple(zt1);
394 if (!zt2) {
395 /* we shouldn't be subscribed to this message. ignore. */
396 } else {
397 len = MAX(BUF_LONG, strlen(buf2));
398 buf = g_malloc(len + 1);
399 g_snprintf(buf, len + 1, "%s", buf2);
400 if (!zt2->open) {
401 zt2->open = TRUE;
402 serv_got_joined_chat(zgc, zt2->id, zt2->name);
403 }
404 serv_got_chat_in(zgc, zt2->id, notice.z_sender, FALSE,
405 buf, time((time_t)NULL));
406 g_free(buf);
407 }
408 free_triple(zt1);
307 } 409 }
308 g_free(buf2); 410 g_free(buf2);
309 } 411 }
310 } 412 }
311 } 413 }
427 sub.zsub_class, 529 sub.zsub_class,
428 sub.zsub_classinst, 530 sub.zsub_classinst,
429 sub.zsub_recipient); 531 sub.zsub_recipient);
430 } 532 }
431 g_free(recip); 533 g_free(recip);
534 subscrips = g_slist_append(subscrips,
535 new_triple(triple[0], triple[1], recip));
432 } 536 }
433 g_strfreev(triple); 537 g_strfreev(triple);
434 } 538 }
435 } 539 }
436 } 540 }
481 serv_finish_login(zgc); 585 serv_finish_login(zgc);
482 586
483 if (bud_list_cache_exists(zgc)) 587 if (bud_list_cache_exists(zgc))
484 do_import(NULL, zgc); 588 do_import(NULL, zgc);
485 process_anyone(); 589 process_anyone();
486 /* call process_zsubs to subscribe. still commented out since I don't know 590 process_zsubs();
487 * how you want to handle incoming msgs from subs.
488 process_zsubs(); */
489 591
490 nottimer = gtk_timeout_add(100, check_notify, NULL); 592 nottimer = gtk_timeout_add(100, check_notify, NULL);
491 loctimer = gtk_timeout_add(2000, check_loc, NULL); 593 loctimer = gtk_timeout_add(2000, check_loc, NULL);
594 }
595
596 static void write_zsubs()
597 {
598 GSList *s = subscrips;
599 zephyr_triple *zt;
600 FILE *fd;
601 char *fname;
602
603 fname = g_strdup_printf("%s/.zephyr.subs", g_get_home_dir());
604 fd = fopen(fname, "w");
605
606 if (!fd) {
607 g_free(fname);
608 return;
609 }
610
611 while (s) {
612 zt = s->data;
613 fprintf(fd, "%s\n", zt->name);
614 s = s->next;
615 }
616 g_free(fname);
617 fclose(fd);
492 } 618 }
493 619
494 static void write_anyone() 620 static void write_anyone()
495 { 621 {
496 GSList *gr, *m; 622 GSList *gr, *m;
526 g_free(fname); 652 g_free(fname);
527 } 653 }
528 654
529 static void zephyr_close(struct gaim_connection *gc) 655 static void zephyr_close(struct gaim_connection *gc)
530 { 656 {
531 g_list_foreach(pending_zloc_names, (GFunc)g_free, NULL); 657 GList *l;
658 GSList *s;
659 l = pending_zloc_names;
660 while (l) {
661 g_free((char*)l->data);
662 l = l->next;
663 }
532 g_list_free(pending_zloc_names); 664 g_list_free(pending_zloc_names);
665
533 write_anyone(); 666 write_anyone();
667 write_zsubs();
668
669 s = subscrips;
670 while (s) {
671 free_triple((zephyr_triple*)s->data);
672 s = s->next;
673 }
674 g_slist_free(subscrips);
675
534 if (nottimer) 676 if (nottimer)
535 gtk_timeout_remove(nottimer); 677 gtk_timeout_remove(nottimer);
536 nottimer = 0; 678 nottimer = 0;
537 if (loctimer) 679 if (loctimer)
538 gtk_timeout_remove(loctimer); 680 gtk_timeout_remove(loctimer);
543 z_call(ZClosePort()); 685 z_call(ZClosePort());
544 } 686 }
545 687
546 static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { } 688 static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { }
547 static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { } 689 static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { }
690
691 static void zephyr_chat_send(struct gaim_connection *gc, int id, char *im)
692 {
693 ZNotice_t notice;
694 zephyr_triple *zt;
695 char *buf;
696 char *sig;
697
698 zt = find_sub_by_id(id);
699 if (!zt)
700 /* this should never happen. */
701 return;
702
703 sig = ZGetVariable("zwrite-signature");
704 if (!sig) {
705 sig = g_get_real_name();
706 }
707 buf = g_strdup_printf("%s%c%s", sig, '\0', im);
708
709 bzero((char *)&notice, sizeof(notice));
710 notice.z_kind = ACKED;
711 notice.z_port = 0;
712 notice.z_opcode = "";
713 notice.z_class = zt->class;
714 notice.z_class_inst = zt->instance;
715 if (!g_strcasecmp(zt->recipient, "*"))
716 notice.z_recipient = zephyr_normalize("");
717 else
718 notice.z_recipient = zephyr_normalize(zt->recipient);
719 notice.z_sender = 0;
720 notice.z_default_format =
721 "Class $class, Instance $instance:\n"
722 "To: @bold($recipient) at $time $date\n"
723 "From: @bold($1) <$sender>\n\n$2";
724 notice.z_message_len = strlen(im) + strlen(sig) + 4;
725 notice.z_message = buf;
726 ZSendNotice(&notice, ZAUTH);
727 g_free(buf);
728 }
548 729
549 static void zephyr_send_im(struct gaim_connection *gc, char *who, char *im, int away) { 730 static void zephyr_send_im(struct gaim_connection *gc, char *who, char *im, int away) {
550 ZNotice_t notice; 731 ZNotice_t notice;
551 char *buf; 732 char *buf;
552 char *sig; 733 char *sig;
641 m = g_list_append(m, "Hidden"); 822 m = g_list_append(m, "Hidden");
642 823
643 return m; 824 return m;
644 } 825 }
645 826
827 static void zephyr_draw_jc(struct gaim_connection *gc, GtkWidget *vbox) {
828 GtkWidget *label;
829 GtkWidget *rowbox;
830
831 rowbox = gtk_hbox_new(FALSE, 5);
832 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
833
834 label = gtk_label_new(_("Class:"));
835 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 5);
836 gtk_widget_show(label);
837
838 class_entry = gtk_entry_new();
839 gtk_box_pack_end(GTK_BOX(rowbox), class_entry, FALSE, FALSE, 5);
840 gtk_widget_show(class_entry);
841
842 gtk_widget_show(rowbox);
843
844 rowbox = gtk_hbox_new(FALSE, 5);
845 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
846
847 label = gtk_label_new(_("Instance:"));
848 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 5);
849 gtk_widget_show(label);
850
851 inst_entry = gtk_entry_new();
852 gtk_box_pack_end(GTK_BOX(rowbox), inst_entry, FALSE, FALSE, 5);
853 gtk_widget_show(inst_entry);
854
855 gtk_widget_show(rowbox);
856
857 rowbox = gtk_hbox_new(FALSE, 5);
858 gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
859
860 label = gtk_label_new(_("Recipient:"));
861 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 5);
862 gtk_widget_show(label);
863
864 recip_entry = gtk_entry_new();
865 gtk_box_pack_end(GTK_BOX(rowbox), recip_entry, FALSE, FALSE, 5);
866 gtk_widget_show(recip_entry);
867
868 gtk_widget_show(rowbox);
869 }
870
871 static void zephyr_join_chat(struct gaim_connection *gc, int id, char *nm)
872 {
873 ZSubscription_t sub;
874 zephyr_triple *zt1, *zt2;
875 char *classname;
876 char *instname;
877 char *recip;
878 char **splitted;
879
880 if (!nm) {
881 splitted = NULL;
882 classname = gtk_entry_get_text(GTK_ENTRY(class_entry));
883 instname = gtk_entry_get_text(GTK_ENTRY(inst_entry));
884 recip = gtk_entry_get_text(GTK_ENTRY(recip_entry));
885 if (!g_strcasecmp(recip, "%me%"))
886 recip = g_getenv("USER");
887 } else {
888 splitted = g_strsplit(nm, ",", 3);
889 if (!splitted[0] || !splitted[1] || !splitted[2]) {
890 g_strfreev(splitted);
891 return;
892 }
893 classname = g_strstrip(splitted[0]);
894 instname = g_strstrip(splitted[1]);
895 recip = g_strstrip(splitted[2]);
896 }
897
898 zt1 = new_triple(classname, instname, recip);
899 if (splitted)
900 g_strfreev(splitted);
901 zt2 = find_sub_by_triple(zt1);
902 if (zt2) {
903 free_triple(zt1);
904 if (!zt2->open)
905 serv_got_joined_chat(gc, zt2->id, zt2->name);
906 return;
907 }
908
909 sub.zsub_class = zt1->class;
910 sub.zsub_classinst = zt1->instance;
911 sub.zsub_recipient = zt1->recipient;
912
913 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) {
914 free_triple(zt1);
915 return;
916 }
917
918 subscrips = g_slist_append(subscrips, zt1);
919 zt1->open = TRUE;
920 serv_got_joined_chat(gc, zt1->id, zt1->name);
921 }
922
923 static void zephyr_chat_leave(struct gaim_connection *gc, int id)
924 {
925 zephyr_triple *zt;
926 zt = find_sub_by_id(id);
927 if (zt) {
928 zt->open = FALSE;
929 zt->id = ++last_id;
930 }
931 }
932
646 static struct prpl *my_protocol = NULL; 933 static struct prpl *my_protocol = NULL;
647 934
648 void zephyr_init(struct prpl *ret) 935 void zephyr_init(struct prpl *ret)
649 { 936 {
650 ret->protocol = PROTO_ZEPHYR; 937 ret->protocol = PROTO_ZEPHYR;
657 ret->get_info = zephyr_zloc; 944 ret->get_info = zephyr_zloc;
658 ret->normalize = zephyr_normalize; 945 ret->normalize = zephyr_normalize;
659 ret->buddy_menu = zephyr_buddy_menu; 946 ret->buddy_menu = zephyr_buddy_menu;
660 ret->away_states = zephyr_away_states; 947 ret->away_states = zephyr_away_states;
661 ret->set_away = zephyr_set_away; 948 ret->set_away = zephyr_set_away;
949 ret->draw_join_chat = zephyr_draw_jc;
950 ret->join_chat = zephyr_join_chat;
951 ret->chat_send = zephyr_chat_send;
952 ret->chat_leave = zephyr_chat_leave;
662 953
663 my_protocol = ret; 954 my_protocol = ret;
664 } 955 }
665 956
666 char *gaim_plugin_init(GModule *handle) 957 char *gaim_plugin_init(GModule *handle)