plugins/zephyr/zephyr.c

changeset 1700
45175fd73d3f
child 1719
faf919a930fb
equal deleted inserted replaced
1699:671e6c5cfb20 1700:45175fd73d3f
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 /*
3 * gaim
4 *
5 * Copyright (C) 1998-2001, Mark Spencer <markster@marko.net>
6 * Some code borrowed from GtkZephyr, by
7 * Jag/Sean Dilda <agrajag@linuxpower.org>/<smdilda@unity.ncsu.edu>
8 * http://gtkzephyr.linuxpower.org/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <gtk/gtk.h>
31 #include <string.h>
32 #include "gaim.h"
33 #include "prpl.h"
34 #include "zephyr/zephyr.h"
35
36 char *name()
37 {
38 return "Zephyr";
39 }
40
41 char *description()
42 {
43 return "Allows gaim to use the Zephyr protocol";
44 }
45
46 static char *zephyr_name()
47 {
48 return "Zephyr";
49 }
50
51 #define z_call(func) if (func != ZERR_NONE)\
52 return;
53 #define z_call_r(func) if (func != ZERR_NONE)\
54 return TRUE;
55 #define z_call_s(func, err) if (func != ZERR_NONE) {\
56 hide_login_progress(zgc, err);\
57 signoff(zgc);\
58 return;\
59 }
60
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. */
63 static guint32 nottimer = 0;
64 static guint32 loctimer = 0;
65 struct gaim_connection *zgc = NULL;
66
67 /* just for debugging
68 static void handle_unknown(ZNotice_t notice)
69 {
70 g_print("z_packet: %s\n", notice.z_packet);
71 g_print("z_version: %s\n", notice.z_version);
72 g_print("z_kind: %d\n", notice.z_kind);
73 g_print("z_class: %s\n", notice.z_class);
74 g_print("z_class_inst: %s\n", notice.z_class_inst);
75 g_print("z_opcode: %s\n", notice.z_opcode);
76 g_print("z_sender: %s\n", notice.z_sender);
77 g_print("z_recipient: %s\n", notice.z_recipient);
78 g_print("z_message: %s\n", notice.z_message);
79 g_print("z_message_len: %d\n", notice.z_message_len);
80 g_print("\n");
81 }
82 */
83
84 static void handle_message(ZNotice_t notice, struct sockaddr_in from)
85 {
86 if (!g_strcasecmp(notice.z_class, LOGIN_CLASS)) {
87 /* well, we'll be updating in 2 seconds anyway, might as well ignore this. */
88 } else if (!g_strcasecmp(notice.z_class, LOCATE_CLASS)) {
89 if (!g_strcasecmp(notice.z_opcode, LOCATE_LOCATE)) {
90 int nlocs;
91 char *user;
92 struct buddy *b;
93
94 if (ZParseLocations(&notice, NULL, &nlocs, &user) != ZERR_NONE)
95 return;
96 if ((b = find_buddy(zgc, user)) == NULL) {
97 char *e = strchr(user, '@');
98 if (e) *e = '\0';
99 b = find_buddy(zgc, user);
100 }
101 if (!b) {
102 free(user);
103 return;
104 }
105 serv_got_update(zgc, b->name, nlocs, 0, 0, 0, 0, 0);
106
107 free(user);
108 }
109 } else if (!g_strcasecmp(notice.z_class, "MESSAGE")) {
110 char buf[BUF_LONG];
111 char *ptr = notice.z_message + strlen(notice.z_message) + 1;
112 int len = notice.z_message_len - (ptr - notice.z_message);
113 if (len > 0) {
114 g_snprintf(buf, len + 1, "%s", ptr);
115 g_strchomp(buf);
116 serv_got_im(zgc, notice.z_sender, buf, 0);
117 }
118 } else {
119 /* yes. */
120 }
121 }
122
123 static gint check_notify(gpointer data)
124 {
125 while (ZPending()) {
126 ZNotice_t notice;
127 struct sockaddr_in from;
128 z_call_r(ZReceiveNotice(&notice, &from));
129
130 switch (notice.z_kind) {
131 case UNSAFE:
132 case UNACKED:
133 case ACKED:
134 handle_message(notice, from);
135 break;
136 default:
137 /* we'll just ignore things for now */
138 debug_printf("ZEPHYR: Unhandled Notice\n");
139 break;
140 }
141
142 ZFreeNotice(&notice);
143 }
144
145 return TRUE;
146 }
147
148 static gint check_loc(gpointer data)
149 {
150 GSList *gr, *m;
151 ZAsyncLocateData_t ald;
152
153 ald.user = NULL;
154 memset(&(ald.uid), 0, sizeof(ZUnique_Id_t));
155 ald.version = NULL;
156
157 gr = zgc->groups;
158 while (gr) {
159 struct group *g = gr->data;
160 m = g->members;
161 while (m) {
162 struct buddy *b = m->data;
163 char *chk;
164 if (!strchr(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 */
169 ZRequestLocations(chk, &ald, UNACKED, ZAUTH);
170 g_free(chk);
171 m = m->next;
172 }
173 gr = gr->next;
174 }
175
176 return TRUE;
177 }
178
179 static char *get_exposure_level()
180 {
181 char *exposure = ZGetVariable("exposure");
182
183 if (!exposure)
184 return EXPOSE_REALMVIS;
185 if (!g_strcasecmp(exposure, EXPOSE_NONE))
186 return EXPOSE_NONE;
187 if (!g_strcasecmp(exposure, EXPOSE_OPSTAFF))
188 return EXPOSE_OPSTAFF;
189 if (!g_strcasecmp(exposure, EXPOSE_REALMANN))
190 return EXPOSE_REALMANN;
191 if (!g_strcasecmp(exposure, EXPOSE_NETVIS))
192 return EXPOSE_NETVIS;
193 if (!g_strcasecmp(exposure, EXPOSE_NETANN))
194 return EXPOSE_NETANN;
195 return EXPOSE_REALMVIS;
196 }
197
198 static void strip_comments(char *str)
199 {
200 char *tmp = strchr(str, '#');
201 if (tmp)
202 *tmp = '\0';
203 g_strchug(str);
204 g_strchomp(str);
205 }
206
207 static void process_anyone()
208 {
209 FILE *fd;
210 gchar buff[BUFSIZ], *filename;
211
212 filename = g_strconcat(g_get_home_dir(), "/.anyone", NULL);
213 if ((fd = fopen(filename, "r")) != NULL) {
214 while (fgets(buff, BUFSIZ, fd)) {
215 strip_comments(buff);
216 if (buff[0])
217 add_buddy(zgc, "Anyone", buff, buff);
218 }
219 fclose(fd);
220 }
221 g_free(filename);
222 }
223
224 static void zephyr_login(struct aim_user *user)
225 {
226 ZSubscription_t sub;
227
228 if (zgc) {
229 do_error_dialog("Already logged in with Zephyr", "Zephyr");
230 return;
231 }
232
233 zgc = new_gaim_conn(user);
234
235 z_call_s(ZInitialize(), "Couldn't initialize zephyr");
236 z_call_s(ZOpenPort(NULL), "Couldn't open port");
237 z_call_s(ZSetLocation(get_exposure_level()), "Couldn't set location");
238
239 sub.zsub_class = "MESSAGE";
240 sub.zsub_classinst = "PERSONAL";
241 sub.zsub_recipient = ZGetSender();
242
243 /* we don't care if this fails. i'm lying right now. */
244 ZSubscribeTo(&sub, 1, 0);
245
246 account_online(zgc);
247 serv_finish_login(zgc);
248
249 if (bud_list_cache_exists(zgc))
250 do_import(NULL, zgc);
251 process_anyone();
252 /* should also process .zephyr.subs */
253
254 nottimer = gtk_timeout_add(100, check_notify, NULL);
255 loctimer = gtk_timeout_add(2000, check_loc, NULL);
256 }
257
258 static void zephyr_close(struct gaim_connection *gc)
259 {
260 /* should probably write .anyone, but eh. we all use gaim exclusively, right? :-P */
261 if (nottimer)
262 gtk_timeout_remove(nottimer);
263 nottimer = 0;
264 if (loctimer)
265 gtk_timeout_remove(loctimer);
266 loctimer = 0;
267 zgc = NULL;
268 z_call(ZCancelSubscriptions(0));
269 z_call(ZUnsetLocation());
270 z_call(ZClosePort());
271 }
272
273 static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { }
274 static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { }
275
276 static void zephyr_send_im(struct gaim_connection *gc, char *who, char *im, int away) {
277 ZNotice_t notice;
278
279 bzero((char *)&notice, sizeof(notice));
280 notice.z_kind = ACKED;
281 notice.z_port = 0;
282 notice.z_opcode = "";
283 notice.z_class = "MESSAGE";
284 notice.z_class_inst = "PERSONAL";
285 notice.z_sender = 0;
286 notice.z_recipient = who;
287 notice.z_default_format =
288 "Class $class, Instance $instance:\nTo: @bold($recipient) at $time $date\n$message";
289 notice.z_message_len = strlen(im) + 1;
290 notice.z_message = im;
291 ZSendNotice(&notice, ZAUTH);
292 }
293
294 static struct prpl *my_protocol = NULL;
295
296 void zephyr_init(struct prpl *ret)
297 {
298 ret->protocol = PROTO_ZEPHYR;
299 ret->name = zephyr_name;
300 ret->login = zephyr_login;
301 ret->close = zephyr_close;
302 ret->add_buddy = zephyr_add_buddy;
303 ret->remove_buddy = zephyr_remove_buddy;
304 ret->send_im = zephyr_send_im;
305
306 my_protocol = ret;
307 }
308
309 char *gaim_plugin_init(GModule *handle)
310 {
311 load_protocol(zephyr_init, sizeof(struct prpl));
312 return NULL;
313 }
314
315 void gaim_plugin_remove()
316 {
317 struct prpl *p = find_prpl(PROTO_ZEPHYR);
318 if (p == my_protocol)
319 unload_protocol(p);
320 }

mercurial