Mercurial > pidgin
annotate src/protocols/zephyr/zephyr.c @ 10038:eb8ccdd6f5f2
[gaim-migrate @ 10997]
" Fix Philip Mucci's bug (reported to gaim-devel on the
16th), where malformed (visibility) strings, caused
users to be unmessageable and hidden, by normalizing
them, and using sane defaults.
Fixes CraigD's bug IRC reported on IRC (non-kerberized
zephyr users always have the realm "local-realm"), by
adding a user-specified "Realm" option string.
Also added two new preferences (import from .anyone and
import from .zephyr.subs) to go with (export to .anyone
and "export to .zephyr.subs"). Since one can now use
multiple accounts, most people wouldn't want to use the
same buddy lists and chat room lists for both accounts.
Added a /topic command to make zephyr use the same
command name as the other protocols which have topics." --Arun A Tharuvai
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Sat, 18 Sep 2004 22:25:12 +0000 |
parents | c124bef68132 |
children | 8490f2e292a6 |
rev | line source |
---|---|
2086 | 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 | |
7084
0909ebf6fb28
[gaim-migrate @ 7649]
Christian Hammond <chipx86@chipx86.com>
parents:
7070
diff
changeset
|
7 * Jag/Sean Dilda <agrajag@linuxpower.org>/<smdilda@unity.ncsu.edu> |
0909ebf6fb28
[gaim-migrate @ 7649]
Christian Hammond <chipx86@chipx86.com>
parents:
7070
diff
changeset
|
8 * http://gtkzephyr.linuxpower.org/ |
2086 | 9 * |
9896 | 10 * Some code borrowed from kzephyr, by |
11 * Chris Colohan <colohan+@cs.cmu.edu> | |
12 * | |
2086 | 13 * This program is free software; you can redistribute it and/or modify |
14 * it under the terms of the GNU General Public License as published by | |
15 * the Free Software Foundation; either version 2 of the License, or | |
16 * (at your option) any later version. | |
17 * | |
18 * This program is distributed in the hope that it will be useful, | |
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9896 | 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2086 | 21 * GNU General Public License for more details. |
22 * | |
23 * You should have received a copy of the GNU General Public License | |
24 * along with this program; if not, write to the Free Software | |
9896 | 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
2086 | 26 * |
9896 | 27 |
28 */ | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
29 /* XXX eww */ |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
30 #include "src/internal.h" |
2086 | 31 |
8212 | 32 #include "accountopt.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
33 #include "debug.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
34 #include "notify.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
35 #include "prpl.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
36 #include "server.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
37 #include "util.h" |
9434 | 38 #include "cmds.h" |
9896 | 39 #include "privacy.h" |
9943 | 40 #include "version.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
41 |
9896 | 42 #include "zephyr.h" |
9478 | 43 #include "internal.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5717
diff
changeset
|
44 |
8386 | 45 #include <strings.h> |
46 | |
8560 | 47 #define ZEPHYR_FALLBACK_CHARSET "ISO-8859-1" |
48 | |
9478 | 49 /* these are deliberately high, since most people don't send multiple "PING"s */ |
50 #define ZEPHYR_TYPING_SEND_TIMEOUT 15 | |
51 #define ZEPHYR_TYPING_RECV_TIMEOUT 10 | |
9896 | 52 #define ZEPHYR_FD_READ 0 |
53 #define ZEPHYR_FD_WRITE 1 | |
9478 | 54 |
2086 | 55 extern Code_t ZGetLocations(ZLocations_t *, int *); |
56 extern Code_t ZSetLocation(char *); | |
57 extern Code_t ZUnsetLocation(); | |
9478 | 58 extern Code_t ZGetSubscriptions(ZSubscription_t *, int*); |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
59 extern char __Zephyr_realm[]; |
2086 | 60 typedef struct _zframe zframe; |
61 typedef struct _zephyr_triple zephyr_triple; | |
9610 | 62 typedef struct _zephyr_account zephyr_account; |
9896 | 63 typedef struct _parse_tree parse_tree; |
2086 | 64 |
9896 | 65 typedef enum { |
66 GAIM_ZEPHYR_NONE, /* Non-kerberized ZEPH0.2 */ | |
67 GAIM_ZEPHYR_KRB4, /* ZEPH0.2 w/ KRB4 support */ | |
68 GAIM_ZEPHYR_TZC, /* tzc executable proxy */ | |
69 GAIM_ZEPHYR_INTERGALACTIC_KRB4, /* Kerberized ZEPH0.3 */ | |
70 } zephyr_connection_type; | |
9610 | 71 |
72 struct _zephyr_account { | |
9896 | 73 GaimAccount* account; |
74 char *username; | |
75 char *realm; | |
76 char *encoding; | |
77 char* galaxy; /* not yet useful */ | |
78 char* krbtkfile; /* not yet useful */ | |
79 guint32 nottimer; | |
80 guint32 loctimer; | |
81 GList *pending_zloc_names; | |
82 GSList *subscrips; | |
83 int last_id; | |
84 unsigned short port; | |
85 char ourhost[HOST_NAME_MAX + 1]; | |
86 char ourhostcanon[HOST_NAME_MAX + 1]; | |
87 zephyr_connection_type connection_type; | |
88 int totzc[2]; | |
89 int fromtzc[2]; | |
90 char *exposure; | |
9986 | 91 pid_t tzc_pid; |
92 gchar *away; | |
9610 | 93 }; |
9478 | 94 |
9896 | 95 #define MAXCHILDREN 20 |
96 | |
97 struct _parse_tree { | |
98 gchar* contents; | |
99 parse_tree *children[MAXCHILDREN]; | |
100 int num_children; | |
101 }; | |
102 | |
103 parse_tree null_parse_tree = { | |
104 "", | |
105 {}, | |
106 0, | |
107 }; | |
108 | |
109 #define use_none(zephyr) ((zephyr->connection_type == GAIM_ZEPHYR_NONE)?1:0) | |
110 #define use_krb4(zephyr) ((zephyr->connection_type == GAIM_ZEPHYR_KRB4)?1:0) | |
111 #define use_tzc(zephyr) ((zephyr->connection_type == GAIM_ZEPHYR_TZC)?1:0) | |
112 | |
113 #define use_zeph02(zephyr) ( (zephyr->connection_type == GAIM_ZEPHYR_NONE)?1: ((zephyr->connection_type == GAIM_ZEPHYR_KRB4)?1:0)) | |
114 | |
2086 | 115 /* struct I need for zephyr_to_html */ |
116 struct _zframe { | |
117 /* true for everything but @color, since inside the parens of that one is | |
8644 | 118 * the color. */ |
2086 | 119 gboolean has_closer; |
120 /* </i>, </font>, </b>, etc. */ | |
121 char *closing; | |
122 /* text including the opening html thingie. */ | |
123 GString *text; | |
124 struct _zframe *enclosing; | |
125 }; | |
126 | |
127 struct _zephyr_triple { | |
128 char *class; | |
129 char *instance; | |
130 char *recipient; | |
131 char *name; | |
132 gboolean open; | |
133 int id; | |
134 }; | |
135 | |
136 #define z_call(func) if (func != ZERR_NONE)\ | |
137 return; | |
138 #define z_call_r(func) if (func != ZERR_NONE)\ | |
139 return TRUE; | |
9896 | 140 |
2086 | 141 #define z_call_s(func, err) if (func != ZERR_NONE) {\ |
9610 | 142 gaim_connection_error(gc, err);\ |
2086 | 143 return;\ |
144 } | |
145 | |
9896 | 146 |
147 Code_t zephyr_subscribe_to(zephyr_account* zephyr, char* class, char *instance, char *recipient, char* galaxy) { | |
9328 | 148 |
9896 | 149 if (use_tzc(zephyr)) { |
150 /* ((tzcfodder . subscribe) ("class" "instance" "recipient")) */ | |
151 gchar *zsubstr = g_strdup_printf("((tzcfodder . subscribe) (\"%s\" \"%s\" \"%s\"))\n",class,instance,recipient); | |
152 write(zephyr->totzc[ZEPHYR_FD_WRITE],zsubstr,strlen(zsubstr)); | |
153 g_free(zsubstr); | |
154 return ZERR_NONE; | |
155 } | |
156 else { | |
157 if (use_zeph02(zephyr)) { | |
158 ZSubscription_t sub; | |
159 sub.zsub_class = class; | |
160 sub.zsub_classinst = instance; | |
161 sub.zsub_recipient = recipient; | |
162 return ZSubscribeTo(&sub,1,0); | |
163 } else { | |
164 /* This should not happen */ | |
165 return -1; | |
166 } | |
167 } | |
168 return -1; | |
169 } | |
170 | |
171 char *local_zephyr_normalize(zephyr_account* zephyr,const char *); | |
172 static const char *zephyr_normalize(const GaimAccount *, const char *); | |
173 static void zephyr_chat_set_topic(GaimConnection * gc, int id, const char *topic); | |
174 char* zephyr_tzc_deescape_str(const char *message); | |
175 | |
9912 | 176 char *zephyr_strip_local_realm(zephyr_account* zephyr,const char* user){ |
9896 | 177 /* |
178 Takes in a username of the form username or username@realm | |
179 and returns: | |
180 username, if there is no realm, or the realm is the local realm | |
181 or: | |
182 username@realm if there is a realm and it is foreign | |
183 */ | |
9328 | 184 char *tmp = g_strdup(user); |
185 char *at = strchr(tmp,'@'); | |
9896 | 186 if (at && !g_ascii_strcasecmp(at+1,zephyr->realm)) { |
9328 | 187 /* We're passed in a username of the form user@users-realm */ |
188 char* tmp2; | |
189 *at = '\0'; | |
190 tmp2 = g_strdup(tmp); | |
191 g_free(tmp); | |
192 return tmp2; | |
193 } | |
194 else { | |
195 /* We're passed in a username of the form user or user@foreign-realm */ | |
196 return tmp; | |
197 } | |
198 } | |
2086 | 199 |
200 /* this is so bad, and if Zephyr weren't so fucked up to begin with I | |
201 * wouldn't do this. but it is so i will. */ | |
9610 | 202 |
9328 | 203 /* just for debugging */ |
2086 | 204 static void handle_unknown(ZNotice_t notice) |
205 { | |
9328 | 206 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_packet: %s\n", notice.z_packet); |
207 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_version: %s\n", notice.z_version); | |
208 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_kind: %d\n", (int)(notice.z_kind)); | |
209 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_class: %s\n", notice.z_class); | |
210 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_class_inst: %s\n", notice.z_class_inst); | |
211 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_opcode: %s\n", notice.z_opcode); | |
212 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_sender: %s\n", notice.z_sender); | |
213 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_recipient: %s\n", notice.z_recipient); | |
214 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_message: %s\n", notice.z_message); | |
215 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_message_len: %d\n", notice.z_message_len); | |
2086 | 216 } |
9328 | 217 |
2086 | 218 |
9610 | 219 static zephyr_triple *new_triple(zephyr_account *zephyr,const char *c, const char *i, const char *r) |
2086 | 220 { |
221 zephyr_triple *zt; | |
8644 | 222 |
2086 | 223 zt = g_new0(zephyr_triple, 1); |
224 zt->class = g_strdup(c); | |
225 zt->instance = g_strdup(i); | |
226 zt->recipient = g_strdup(r); | |
9610 | 227 zt->name = g_strdup_printf("%s,%s,%s", c, i?i:"", r?r:""); |
228 zt->id = ++(zephyr->last_id); | |
2086 | 229 zt->open = FALSE; |
230 return zt; | |
231 } | |
232 | |
8644 | 233 static void free_triple(zephyr_triple * zt) |
2086 | 234 { |
235 g_free(zt->class); | |
236 g_free(zt->instance); | |
237 g_free(zt->recipient); | |
238 g_free(zt->name); | |
239 g_free(zt); | |
240 } | |
241 | |
9328 | 242 /* returns true if zt1 is a subset of zt2. This function is used to |
243 determine whether a zephyr sent to zt1 should be placed in the chat | |
244 with triple zt2 | |
245 | |
246 zt1 is a subset of zt2 | |
247 iff. the classnames are identical ignoring case | |
248 AND. the instance names are identical (ignoring case), or zt2->instance is *. | |
249 AND. the recipient names are identical | |
250 */ | |
251 | |
8644 | 252 static gboolean triple_subset(zephyr_triple * zt1, zephyr_triple * zt2) |
2086 | 253 { |
9896 | 254 |
255 if (!zt2) | |
256 gaim_debug_error("zephyr","zt2 doesn't exist\n"); | |
257 if (!zt1) | |
258 gaim_debug_error("zephyr","zt1 doesn't exist\n"); | |
259 if (!(zt1->class)) | |
260 gaim_debug_error("zephyr","zt1c doesn't exist\n"); | |
261 if (!(zt1->instance)) | |
262 gaim_debug_error("zephyr","zt1i doesn't exist\n"); | |
263 if (!(zt1->recipient)) | |
264 gaim_debug_error("zephyr","zt1r doesn't exist\n"); | |
265 if (!(zt2->class)) | |
266 gaim_debug_error("zephyr","zt2c doesn't exist\n"); | |
267 if (!(zt2->recipient)) | |
268 gaim_debug_error("zephyr","zt2r doesn't exist\n"); | |
269 if (!(zt2->instance)) | |
270 gaim_debug_error("zephyr","zt2i doesn't exist\n"); | |
271 | |
272 | |
9328 | 273 if (g_ascii_strcasecmp(zt2->class, zt1->class)) { |
2086 | 274 return FALSE; |
275 } | |
8644 | 276 if (g_ascii_strcasecmp(zt2->instance, zt1->instance) && g_ascii_strcasecmp(zt2->instance, "*")) { |
2086 | 277 return FALSE; |
278 } | |
9328 | 279 if (g_ascii_strcasecmp(zt2->recipient, zt1->recipient)) { |
2086 | 280 return FALSE; |
281 } | |
9896 | 282 gaim_debug_info("zephyr","<%s,%s,%s> is in <%s,%s,%s>\n",zt1->class,zt1->instance,zt1->recipient,zt2->class,zt2->instance,zt2->recipient); |
2086 | 283 return TRUE; |
284 } | |
285 | |
9610 | 286 static zephyr_triple *find_sub_by_triple(zephyr_account *zephyr,zephyr_triple * zt) |
2086 | 287 { |
288 zephyr_triple *curr_t; | |
9610 | 289 GSList *curr = zephyr->subscrips; |
8644 | 290 |
2086 | 291 while (curr) { |
292 curr_t = curr->data; | |
293 if (triple_subset(zt, curr_t)) | |
294 return curr_t; | |
295 curr = curr->next; | |
296 } | |
297 return NULL; | |
298 } | |
299 | |
9610 | 300 static zephyr_triple *find_sub_by_id(zephyr_account *zephyr,int id) |
2086 | 301 { |
302 zephyr_triple *zt; | |
9610 | 303 GSList *curr = zephyr->subscrips; |
8644 | 304 |
2086 | 305 while (curr) { |
306 zt = curr->data; | |
307 if (zt->id == id) | |
308 return zt; | |
309 curr = curr->next; | |
310 } | |
311 return NULL; | |
312 } | |
313 | |
9328 | 314 /* |
9434 | 315 Converts strings to utf-8 if necessary using user specified encoding |
9328 | 316 */ |
317 | |
9610 | 318 static gchar *zephyr_recv_convert(GaimConnection *gc,gchar *string, int len) |
8560 | 319 { |
320 gchar *utf8; | |
321 GError *err = NULL; | |
9896 | 322 zephyr_account *zephyr = gc->proto_data; |
8644 | 323 if (g_utf8_validate(string, len, NULL)) { |
8568 | 324 return g_strdup(string); |
325 } else { | |
9896 | 326 utf8 = g_convert(string, len, "UTF-8", zephyr->encoding, NULL, NULL, &err); |
8568 | 327 if (err) { |
328 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "recv conversion error: %s\n", err->message); | |
9896 | 329 utf8 = g_strdup(_("(There was an error converting this message. Check the 'Encoding' option in the Account Editor)")); |
8954 | 330 g_error_free(err); |
8568 | 331 } |
332 | |
333 return utf8; | |
334 } | |
8560 | 335 } |
336 | |
2086 | 337 /* utility macros that are useful for zephyr_to_html */ |
338 | |
339 #define IS_OPENER(c) ((c == '{') || (c == '[') || (c == '(') || (c == '<')) | |
340 #define IS_CLOSER(c) ((c == '}') || (c == ']') || (c == ')') || (c == '>')) | |
341 | |
8451 | 342 /* This parses HTML formatting (put out by one of the gtkimhtml widgets |
343 And converts it to zephyr formatting. | |
344 It currently deals properly with <b>, <br>, <i>, <font face=...>, <font color=...>, | |
345 It ignores <font back=...> | |
346 It does | |
347 <font size = "1 or 2" -> @small | |
348 3 or 4 @medium() | |
349 5,6, or 7 @large() | |
350 <a href is dealt with by ignoring the description and outputting the link | |
351 */ | |
352 | |
353 static char *html_to_zephyr(const char *message) | |
354 { | |
8644 | 355 int len, cnt, retcount; |
356 char *ret; | |
357 | |
358 len = strlen(message); | |
9478 | 359 if (!len) |
360 return g_strdup(""); | |
361 | |
8644 | 362 ret = g_new0(char, len * 3); |
363 | |
364 bzero(ret, len * 3); | |
365 retcount = 0; | |
366 cnt = 0; | |
9896 | 367 gaim_debug_info("zephyr","html received %s\n",message); |
8644 | 368 while (cnt <= len) { |
369 if (message[cnt] == '<') { | |
370 if (!g_ascii_strncasecmp(message + cnt + 1, "i>", 2)) { | |
371 strncpy(ret + retcount, "@i(", 3); | |
372 cnt += 3; | |
373 retcount += 3; | |
374 } else if (!g_ascii_strncasecmp(message + cnt + 1, "b>", 2)) { | |
375 strncpy(ret + retcount, "@b(", 3); | |
376 cnt += 3; | |
377 retcount += 3; | |
378 } else if (!g_ascii_strncasecmp(message + cnt + 1, "br>", 3)) { | |
379 strncpy(ret + retcount, "\n", 1); | |
380 cnt += 4; | |
381 retcount += 1; | |
9896 | 382 } else if (!g_ascii_strncasecmp(message + cnt + 1, "a href=\"mailto:", 15)) { |
383 cnt += 16; | |
384 while (g_ascii_strncasecmp(message + cnt, "\">", 2) != 0) { | |
385 ret[retcount] = message[cnt]; | |
386 retcount++; | |
387 cnt++; | |
388 } | |
389 cnt += 2; | |
390 /* ignore descriptive string */ | |
391 while (g_ascii_strncasecmp(message + cnt, "</a>", 4) != 0) { | |
392 cnt++; | |
393 } | |
394 cnt += 4; | |
8644 | 395 } else if (!g_ascii_strncasecmp(message + cnt + 1, "a href=\"", 8)) { |
396 cnt += 9; | |
397 while (g_ascii_strncasecmp(message + cnt, "\">", 2) != 0) { | |
398 ret[retcount] = message[cnt]; | |
399 retcount++; | |
400 cnt++; | |
401 } | |
402 cnt += 2; | |
403 /* ignore descriptive string */ | |
404 while (g_ascii_strncasecmp(message + cnt, "</a>", 4) != 0) { | |
405 cnt++; | |
406 } | |
407 cnt += 4; | |
408 } else if (!g_ascii_strncasecmp(message + cnt + 1, "font", 4)) { | |
409 cnt += 5; | |
410 while (!g_ascii_strncasecmp(message + cnt, " ", 1)) | |
411 cnt++; | |
412 if (!g_ascii_strncasecmp(message + cnt, "color=\"", 7)) { | |
413 cnt += 7; | |
414 strncpy(ret + retcount, "@color(", 7); | |
415 retcount += 7; | |
416 while (g_ascii_strncasecmp(message + cnt, "\">", 2) != 0) { | |
417 ret[retcount] = message[cnt]; | |
418 retcount++; | |
419 cnt++; | |
420 } | |
421 ret[retcount] = ')'; | |
422 retcount++; | |
423 cnt += 2; | |
424 } else if (!g_ascii_strncasecmp(message + cnt, "face=\"", 6)) { | |
425 cnt += 6; | |
426 strncpy(ret + retcount, "@font(", 6); | |
427 retcount += 6; | |
428 while (g_ascii_strncasecmp(message + cnt, "\">", 2) != 0) { | |
429 ret[retcount] = message[cnt]; | |
430 retcount++; | |
431 cnt++; | |
432 } | |
433 ret[retcount] = ')'; | |
434 retcount++; | |
435 cnt += 2; | |
436 } else if (!g_ascii_strncasecmp(message + cnt, "size=\"", 6)) { | |
437 cnt += 6; | |
438 if ((message[cnt] == '1') || (message[cnt] == '2')) { | |
439 strncpy(ret + retcount, "@small(", 7); | |
440 retcount += 7; | |
441 } else if ((message[cnt] == '3') | |
9896 | 442 || (message[cnt] == '4')) { |
8644 | 443 strncpy(ret + retcount, "@medium(", 8); |
444 retcount += 8; | |
445 } else if ((message[cnt] == '5') | |
9896 | 446 || (message[cnt] == '6') |
447 || (message[cnt] == '7')) { | |
8644 | 448 strncpy(ret + retcount, "@large(", 7); |
449 retcount += 7; | |
450 } | |
451 cnt += 3; | |
452 } else { | |
453 /* Drop all unrecognized/misparsed font tags */ | |
454 while (g_ascii_strncasecmp(message + cnt, "\">", 2) != 0) { | |
455 cnt++; | |
456 } | |
457 cnt += 2; | |
458 } | |
459 } else if (!g_ascii_strncasecmp(message + cnt + 1, "/i>", 3) | |
9896 | 460 || !g_ascii_strncasecmp(message + cnt + 1, "/b>", 3)) { |
8644 | 461 cnt += 4; |
462 ret[retcount] = ')'; | |
463 retcount++; | |
464 } else if (!g_ascii_strncasecmp(message + cnt + 1, "/font>", 6)) { | |
465 cnt += 7; | |
466 strncpy(ret + retcount, "@font(fixed)", 12); | |
467 retcount += 12; | |
468 } else { | |
469 /* Catch all for all unrecognized/misparsed <foo> tage */ | |
470 while (g_ascii_strncasecmp(message + cnt, ">", 1) != 0) { | |
471 ret[retcount] = message[cnt]; | |
472 retcount++; | |
473 cnt++; | |
474 } | |
475 } | |
476 } else { | |
477 /* Duh */ | |
478 ret[retcount] = message[cnt]; | |
479 retcount++; | |
480 cnt++; | |
481 } | |
482 } | |
9896 | 483 gaim_debug_info("zephyr","zephyr outputted %s\n",ret); |
8644 | 484 return ret; |
8451 | 485 } |
486 | |
2086 | 487 /* this parses zephyr formatting and converts it to html. For example, if |
488 * you pass in "@{@color(blue)@i(hello)}" you should get out | |
489 * "<font color=blue><i>hello</i></font>". */ | |
490 static char *zephyr_to_html(char *message) | |
491 { | |
492 int len, cnt; | |
493 zframe *frames, *curr; | |
494 char *ret; | |
495 | |
496 frames = g_new(zframe, 1); | |
497 frames->text = g_string_new(""); | |
498 frames->enclosing = NULL; | |
499 frames->closing = ""; | |
500 frames->has_closer = FALSE; | |
501 | |
502 len = strlen(message); | |
503 cnt = 0; | |
504 while (cnt <= len) { | |
505 if (message[cnt] == '@') { | |
506 zframe *new_f; | |
507 char *buf; | |
508 int end; | |
8644 | 509 |
510 for (end = 1; (cnt + end) <= len && !IS_OPENER(message[cnt + end]) | |
9896 | 511 && !IS_CLOSER(message[cnt + end]); end++); |
2086 | 512 buf = g_new0(char, end); |
8644 | 513 |
2086 | 514 if (end) { |
8644 | 515 g_snprintf(buf, end, "%s", message + cnt + 1); |
2086 | 516 } |
8644 | 517 if (!g_ascii_strcasecmp(buf, "italic") || !g_ascii_strcasecmp(buf, "i")) { |
2086 | 518 new_f = g_new(zframe, 1); |
519 new_f->enclosing = frames; | |
520 new_f->text = g_string_new("<i>"); | |
521 new_f->closing = "</i>"; | |
522 new_f->has_closer = TRUE; | |
523 frames = new_f; | |
8644 | 524 cnt += end + 1; /* cnt points to char after opener */ |
525 } else if (!g_ascii_strcasecmp(buf, "small")) { | |
526 new_f = g_new(zframe, 1); | |
527 new_f->enclosing = frames; | |
528 new_f->text = g_string_new("<font size=\"1\">"); | |
529 new_f->closing = "</font>"; | |
530 frames = new_f; | |
531 cnt += end + 1; | |
532 } else if (!g_ascii_strcasecmp(buf, "medium")) { | |
533 new_f = g_new(zframe, 1); | |
534 new_f->enclosing = frames; | |
535 new_f->text = g_string_new("<font size=\"3\">"); | |
536 new_f->closing = "</font>"; | |
537 frames = new_f; | |
538 cnt += end + 1; | |
539 } else if (!g_ascii_strcasecmp(buf, "large")) { | |
540 new_f = g_new(zframe, 1); | |
541 new_f->enclosing = frames; | |
542 new_f->text = g_string_new("<font size=\"7\">"); | |
543 new_f->closing = "</font>"; | |
544 frames = new_f; | |
545 cnt += end + 1; | |
546 } else if (!g_ascii_strcasecmp(buf, "bold") | |
9896 | 547 || !g_ascii_strcasecmp(buf, "b")) { |
2086 | 548 new_f = g_new(zframe, 1); |
549 new_f->enclosing = frames; | |
550 new_f->text = g_string_new("<b>"); | |
551 new_f->closing = "</b>"; | |
552 new_f->has_closer = TRUE; | |
553 frames = new_f; | |
8644 | 554 cnt += end + 1; |
555 } else if (!g_ascii_strcasecmp(buf, "font")) { | |
556 cnt += end + 1; | |
8451 | 557 new_f = g_new(zframe, 1); |
558 new_f->enclosing = frames; | |
559 new_f->text = g_string_new("<font face="); | |
560 for (; (cnt <= len) && !IS_CLOSER(message[cnt]); cnt++) { | |
561 g_string_append_c(new_f->text, message[cnt]); | |
562 } | |
8644 | 563 cnt++; /* point to char after closer */ |
8451 | 564 g_string_append_c(new_f->text, '>'); |
565 new_f->closing = "</font>"; | |
566 new_f->has_closer = FALSE; | |
567 frames = new_f; | |
8568 | 568 } else if (!g_ascii_strcasecmp(buf, "color")) { |
8644 | 569 cnt += end + 1; |
2086 | 570 new_f = g_new(zframe, 1); |
571 new_f->enclosing = frames; | |
572 new_f->text = g_string_new("<font color="); | |
573 for (; (cnt <= len) && !IS_CLOSER(message[cnt]); cnt++) { | |
574 g_string_append_c(new_f->text, message[cnt]); | |
575 } | |
8644 | 576 cnt++; /* point to char after closer */ |
2086 | 577 g_string_append_c(new_f->text, '>'); |
578 new_f->closing = "</font>"; | |
579 new_f->has_closer = FALSE; | |
580 frames = new_f; | |
4793 | 581 } else if (!g_ascii_strcasecmp(buf, "")) { |
2086 | 582 new_f = g_new(zframe, 1); |
583 new_f->enclosing = frames; | |
584 new_f->text = g_string_new(""); | |
585 new_f->closing = ""; | |
586 new_f->has_closer = TRUE; | |
587 frames = new_f; | |
8644 | 588 cnt += end + 1; /* cnt points to char after opener */ |
2086 | 589 } else { |
8644 | 590 if ((cnt + end) > len) { |
2086 | 591 g_string_append_c(frames->text, '@'); |
592 cnt++; | |
8644 | 593 } else if (IS_CLOSER(message[cnt + end])) { |
594 /* We have @chars..closer . This is | |
595 merely a sequence of chars that isn't a formatting tag | |
9896 | 596 */ |
8644 | 597 int tmp = cnt; |
598 | |
599 while (tmp <= cnt + end) { | |
600 g_string_append_c(frames->text, message[tmp]); | |
601 tmp++; | |
602 } | |
603 cnt += end + 1; | |
604 } else { | |
2086 | 605 /* unrecognized thingie. act like it's not there, but we |
606 * still need to take care of the corresponding closer, | |
607 * make a frame that does nothing. */ | |
608 new_f = g_new(zframe, 1); | |
609 new_f->enclosing = frames; | |
610 new_f->text = g_string_new(""); | |
611 new_f->closing = ""; | |
612 new_f->has_closer = TRUE; | |
613 frames = new_f; | |
8644 | 614 cnt += end + 1; /* cnt points to char after opener */ |
2086 | 615 } |
616 } | |
617 } else if (IS_CLOSER(message[cnt])) { | |
618 zframe *popped; | |
619 gboolean last_had_closer; | |
8644 | 620 |
2086 | 621 if (frames->enclosing) { |
622 do { | |
623 popped = frames; | |
624 frames = frames->enclosing; | |
625 g_string_append(frames->text, popped->text->str); | |
626 g_string_append(frames->text, popped->closing); | |
627 g_string_free(popped->text, TRUE); | |
628 last_had_closer = popped->has_closer; | |
629 g_free(popped); | |
630 } while (frames && frames->enclosing && !last_had_closer); | |
631 } else { | |
632 g_string_append_c(frames->text, message[cnt]); | |
633 } | |
634 cnt++; | |
635 } else if (message[cnt] == '\n') { | |
636 g_string_append(frames->text, "<br>"); | |
637 cnt++; | |
638 } else { | |
639 g_string_append_c(frames->text, message[cnt++]); | |
640 } | |
641 } | |
642 /* go through all the stuff that they didn't close */ | |
643 while (frames->enclosing) { | |
644 curr = frames; | |
645 g_string_append(frames->enclosing->text, frames->text->str); | |
646 g_string_append(frames->enclosing->text, frames->closing); | |
647 g_string_free(frames->text, TRUE); | |
648 frames = frames->enclosing; | |
649 g_free(curr); | |
650 } | |
651 ret = frames->text->str; | |
652 g_string_free(frames->text, FALSE); | |
653 g_free(frames); | |
654 return ret; | |
655 } | |
656 | |
9610 | 657 static gboolean pending_zloc(zephyr_account *zephyr,char *who) |
2086 | 658 { |
659 GList *curr; | |
8644 | 660 |
9610 | 661 for (curr = zephyr->pending_zloc_names; curr != NULL; curr = curr->next) { |
9896 | 662 char* normalized_who = local_zephyr_normalize(zephyr,who); |
9328 | 663 if (!g_ascii_strcasecmp(normalized_who, (char *)curr->data)) { |
8644 | 664 g_free((char *)curr->data); |
9610 | 665 zephyr->pending_zloc_names = g_list_remove(zephyr->pending_zloc_names, curr->data); |
2086 | 666 return TRUE; |
667 } | |
668 } | |
669 return FALSE; | |
670 } | |
671 | |
9328 | 672 /* Called when the server notifies us a message couldn't get sent */ |
673 | |
9610 | 674 static void message_failed(GaimConnection *gc, ZNotice_t notice, struct sockaddr_in from) |
8559 | 675 { |
8644 | 676 if (g_ascii_strcasecmp(notice.z_class, "message")) { |
9328 | 677 gchar* chat_failed = g_strdup_printf(_("Unable send to chat %s,%s,%s"),notice.z_class,notice.z_class_inst,notice.z_recipient); |
9610 | 678 gaim_notify_error(gc,"",chat_failed,NULL); |
9328 | 679 g_free(chat_failed); |
8644 | 680 } else { |
9610 | 681 gaim_notify_error(gc, notice.z_recipient, _("User is offline"), NULL); |
8644 | 682 } |
8559 | 683 } |
684 | |
9610 | 685 static void handle_message(GaimConnection *gc,ZNotice_t notice, struct sockaddr_in from) |
2086 | 686 { |
9896 | 687 zephyr_account* zephyr = gc->proto_data; |
688 | |
4793 | 689 if (!g_ascii_strcasecmp(notice.z_class, LOGIN_CLASS)) { |
3277 | 690 /* well, we'll be updating in 20 seconds anyway, might as well ignore this. */ |
4793 | 691 } else if (!g_ascii_strcasecmp(notice.z_class, LOCATE_CLASS)) { |
692 if (!g_ascii_strcasecmp(notice.z_opcode, LOCATE_LOCATE)) { | |
2086 | 693 int nlocs; |
694 char *user; | |
6695 | 695 GaimBuddy *b; |
9478 | 696 /* XXX add real error reporting */ |
2086 | 697 if (ZParseLocations(¬ice, NULL, &nlocs, &user) != ZERR_NONE) |
698 return; | |
8435 | 699 |
9610 | 700 if ((b = gaim_find_buddy(gc->account, user)) == NULL) { |
9986 | 701 char* stripped_user = zephyr_strip_local_realm(zephyr,user); |
702 b = gaim_find_buddy(gc->account,stripped_user); | |
703 g_free(stripped_user); | |
8644 | 704 } |
9896 | 705 if ((b && pending_zloc(zephyr,b->name)) || pending_zloc(zephyr,user)) { |
2086 | 706 ZLocations_t locs; |
707 int one = 1; | |
708 GString *str = g_string_new(""); | |
8644 | 709 |
710 g_string_append_printf(str, _("<b>User:</b> %s<br>"), b ? b->name : user); | |
8435 | 711 if (b && b->alias) |
5132 | 712 g_string_append_printf(str, _("<b>Alias:</b> %s<br>"), b->alias); |
2086 | 713 if (!nlocs) { |
5132 | 714 g_string_append_printf(str, _("<br>Hidden or not logged-in")); |
2086 | 715 } |
716 for (; nlocs > 0; nlocs--) { | |
9478 | 717 /* XXX add real error reporting */ |
2086 | 718 ZGetLocations(&locs, &one); |
8644 | 719 g_string_append_printf(str, _("<br>At %s since %s"), locs.host, locs.time); |
2086 | 720 } |
9797 | 721 gaim_notify_userinfo(gc, b ? b->name : user, NULL, _("Buddy Information"), NULL, |
9896 | 722 str->str, NULL, NULL); |
2086 | 723 g_string_free(str, TRUE); |
9986 | 724 } else { |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
725 if (nlocs>0) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
726 gaim_prpl_got_user_status(gc->account,b->name,"online",NULL); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
727 else |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
728 gaim_prpl_got_user_status(gc->account,b->name,"offline",NULL); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
729 } |
2086 | 730 |
9434 | 731 g_free(user); |
2086 | 732 } |
733 } else { | |
8560 | 734 char *buf, *buf2, *buf3; |
2804
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
735 char *send_inst; |
8644 | 736 GaimConversation *gconv1; |
737 GaimConvChat *gcc; | |
2086 | 738 char *ptr = notice.z_message + strlen(notice.z_message) + 1; |
9478 | 739 int len; |
9896 | 740 char *sendertmp = g_strdup_printf("%s", zephyr->username); |
9478 | 741 int signature_length = strlen(notice.z_message); |
742 int message_has_no_body = 0; | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
7084
diff
changeset
|
743 GaimConvImFlags flags = 0; |
9896 | 744 gchar *tmpescape; |
8560 | 745 |
9478 | 746 /* Need to deal with 0 length messages to handle typing notification (OPCODE) ping messages */ |
747 /* One field zephyrs would have caused gaim to crash */ | |
748 if ( (notice.z_message_len == 0) || (signature_length >= notice.z_message_len - 1)) { | |
749 message_has_no_body = 1; | |
750 len = 0; | |
751 gaim_debug_info("zephyr","message_size %d %d %d\n",len,notice.z_message_len,signature_length); | |
752 buf3 = g_strdup(""); | |
753 | |
754 } else { | |
755 len = notice.z_message_len - ( signature_length +1); | |
756 gaim_debug_info("zephyr","message_size %d %d %d\n",len,notice.z_message_len,signature_length); | |
8644 | 757 buf = g_malloc(len + 1); |
758 g_snprintf(buf, len + 1, "%s", ptr); | |
759 g_strchomp(buf); | |
760 tmpescape = gaim_escape_html(buf); | |
9478 | 761 g_free(buf); |
8644 | 762 buf2 = zephyr_to_html(tmpescape); |
9610 | 763 buf3 = zephyr_recv_convert(gc,buf2, strlen(buf2)); |
8644 | 764 g_free(buf2); |
765 g_free(tmpescape); | |
9478 | 766 } |
8644 | 767 |
9896 | 768 if (!g_ascii_strcasecmp(notice.z_class, "MESSAGE") && !g_ascii_strcasecmp(notice.z_class_inst, "PERSONAL") |
769 && !g_ascii_strcasecmp(notice.z_recipient,zephyr->username)) { | |
770 gchar* stripped_sender; | |
771 if (!g_ascii_strcasecmp(notice.z_message, "Automated reply:")) | |
772 flags |= GAIM_CONV_IM_AUTO_RESP; | |
9912 | 773 stripped_sender = zephyr_strip_local_realm(zephyr,notice.z_sender); |
9896 | 774 |
9478 | 775 if (!g_ascii_strcasecmp(notice.z_opcode,"PING")) |
9610 | 776 serv_got_typing(gc,stripped_sender,ZEPHYR_TYPING_RECV_TIMEOUT, GAIM_TYPING); |
9896 | 777 else { |
778 /* Based on the values of | |
779 account->permit_deny, | |
780 account->permit, account>deny , and | |
781 the buddylist */ | |
782 | |
783 GSList* l; | |
784 gboolean in_deny; | |
9478 | 785 |
9896 | 786 switch (gc->account->perm_deny) { |
787 case GAIM_PRIVACY_ALLOW_ALL: | |
788 in_deny = 0; break; | |
789 case GAIM_PRIVACY_DENY_ALL: | |
790 in_deny = 1; break; | |
791 case GAIM_PRIVACY_ALLOW_USERS: /* See if stripped_sender is in gc->account->permit and allow appropriately */ | |
792 in_deny = 1; | |
793 for(l=gc->account->permit;l!=NULL;l=l->next) { | |
794 if (!gaim_utf8_strcasecmp(stripped_sender, gaim_normalize(gc->account, (char *)l->data))) { | |
795 in_deny=0; | |
796 break; | |
797 } | |
798 } | |
799 break; | |
800 case GAIM_PRIVACY_DENY_USERS: /* See if stripped_sender is in gc->account->deny and deny if so */ | |
801 in_deny = 0; | |
802 for(l=gc->account->deny;l!=NULL;l=l->next) { | |
803 if (!gaim_utf8_strcasecmp(stripped_sender, gaim_normalize(gc->account, (char *)l->data))) { | |
804 in_deny=1; | |
805 break; | |
806 } | |
807 } | |
808 break; | |
809 case GAIM_PRIVACY_ALLOW_BUDDYLIST: | |
810 in_deny = 1; | |
811 if (gaim_find_buddy(gc->account,stripped_sender)!=NULL) { | |
812 in_deny = 0; | |
813 } | |
814 break; | |
815 default: | |
816 in_deny=0; break; | |
817 } | |
818 | |
819 if (!in_deny) { | |
820 serv_got_im(gc, stripped_sender, buf3, flags, time(NULL)); | |
821 } | |
822 } | |
823 | |
824 g_free(stripped_sender); | |
825 } else { | |
826 zephyr_triple *zt1, *zt2; | |
827 gchar *send_inst_utf8; | |
828 zephyr_account *zephyr = gc->proto_data; | |
829 zt1 = new_triple(gc->proto_data,notice.z_class, notice.z_class_inst, notice.z_recipient); | |
830 zt2 = find_sub_by_triple(gc->proto_data,zt1); | |
831 if (!zt2) { | |
832 /* This is a server supplied subscription */ | |
833 zephyr->subscrips = g_slist_append(zephyr->subscrips, new_triple(zephyr,zt1->class,zt1->instance,zt1->recipient)); | |
9610 | 834 zt2 = find_sub_by_triple(gc->proto_data,zt1); |
9896 | 835 } |
836 | |
837 if (!zt2->open) { | |
838 zt2->open = TRUE; | |
839 serv_got_joined_chat(gc, zt2->id, zt2->name); | |
840 zephyr_chat_set_topic(gc,zt2->id,notice.z_class_inst); | |
841 } | |
842 g_free(sendertmp); /* fix memory leak? */ | |
843 /* If the person is in the default Realm, then strip the | |
844 Realm from the sender field */ | |
9912 | 845 sendertmp = zephyr_strip_local_realm(zephyr,notice.z_sender); |
9896 | 846 send_inst = g_strdup_printf("%s %s",sendertmp,notice.z_class_inst); |
847 send_inst_utf8 = zephyr_recv_convert(gc,send_inst, strlen(send_inst)); | |
848 if (!send_inst_utf8) { | |
849 gaim_debug(GAIM_DEBUG_ERROR, "zephyr","send_inst %s became null\n", send_inst); | |
850 send_inst_utf8 = "malformed instance"; | |
2086 | 851 } |
9912 | 852 |
9896 | 853 serv_got_chat_in(gc, zt2->id, send_inst_utf8, 0, buf3, time(NULL)); |
854 g_free(send_inst); | |
855 gconv1 = gaim_find_conversation_with_account(zt2->name, gc->account); | |
856 gcc = gaim_conversation_get_chat_data(gconv1); | |
9912 | 857 |
9896 | 858 if (!gaim_conv_chat_find_user(gcc, sendertmp)) { |
859 /* force interpretation in network byte order */ | |
860 unsigned char *addrs = (unsigned char *)&(notice.z_sender_addr.s_addr); | |
861 gchar* ipaddr = g_strdup_printf("%hhd.%hhd.%hhd.%hhd", (unsigned char)addrs[0], | |
862 (unsigned char)addrs[1], (unsigned char)addrs[2], | |
863 (unsigned char) addrs[3]); | |
864 | |
865 gaim_conv_chat_add_user(gcc, sendertmp, ipaddr, GAIM_CBFLAGS_NONE, TRUE); | |
866 g_free(ipaddr); /* fix memory leak? */ | |
867 | |
868 } | |
869 g_free(sendertmp); | |
870 g_free(send_inst_utf8); | |
871 | |
872 free_triple(zt1); | |
873 } | |
874 g_free(buf3); | |
9478 | 875 |
2086 | 876 } |
877 } | |
9896 | 878 int free_parse_tree(parse_tree* tree) { |
879 if (!tree) { | |
880 return 0; | |
881 } | |
882 else { | |
883 int i; | |
884 if (tree->children) { | |
885 for(i=0;i<tree->num_children;i++){ | |
886 if (tree->children[i]) { | |
887 free_parse_tree(tree->children[i]); | |
888 g_free(tree->children[i]); | |
889 } | |
890 } | |
891 } | |
892 if ((tree != &null_parse_tree) && (tree->contents != NULL)) | |
893 g_free(tree->contents); | |
2086 | 894 |
9896 | 895 } |
896 return 0; | |
897 } | |
898 | |
899 parse_tree *tree_child(parse_tree* tree,int index) { | |
900 if (index < tree->num_children) { | |
901 return tree->children[index]; | |
902 } else { | |
903 return &null_parse_tree; | |
904 } | |
905 } | |
906 | |
907 parse_tree *find_node(parse_tree* ptree,gchar* key) | |
908 { | |
909 gchar* tc = tree_child(ptree,0)->contents; | |
910 | |
911 if (!ptree || ! key) | |
912 return &null_parse_tree; | |
913 | |
914 if (ptree->num_children > 0 && tc && !strcasecmp(tc, key)) { | |
915 return ptree; | |
916 } else { | |
917 parse_tree *result = &null_parse_tree; | |
918 int i; | |
919 for(i = 0; i < ptree->num_children; i++) { | |
920 result = find_node(ptree->children[i],key); | |
921 if(result != &null_parse_tree) { | |
922 break; | |
923 } | |
924 } | |
925 return result; | |
926 } | |
927 } | |
928 | |
929 parse_tree *parse_buffer(gchar* source, gboolean do_parse) { | |
930 | |
931 parse_tree *ptree = g_new0(parse_tree,1); | |
932 ptree->contents = NULL; | |
933 ptree->num_children=0; | |
934 if (do_parse) { | |
935 unsigned int p = 0; | |
936 while(p < strlen(source)) { | |
937 unsigned int end; | |
9986 | 938 gchar *newstr; |
9896 | 939 |
940 /* Eat white space: */ | |
941 if(g_ascii_isspace(source[p]) || source[p] == '\001') { | |
942 p++; | |
943 continue; | |
944 } | |
945 | |
946 /* Skip comments */ | |
947 if(source[p] == ';') { | |
948 while(source[p] != '\n' && p < strlen(source)) { | |
949 p++; | |
950 } | |
951 continue; | |
952 } | |
953 | |
954 if(source[p] == '(') { | |
955 int nesting = 0; | |
956 gboolean in_quote = FALSE; | |
957 gboolean escape_next = FALSE; | |
958 p++; | |
959 end = p; | |
960 while(!(source[end] == ')' && nesting == 0 && !in_quote) && end < strlen(source)) { | |
961 if(!escape_next) { | |
962 if(source[end] == '\\') { | |
963 escape_next = TRUE; | |
964 } | |
965 if(!in_quote) { | |
966 if(source[end] == '(') { | |
967 nesting++; | |
968 } | |
969 if(source[end] == ')') { | |
970 nesting--; | |
971 } | |
972 } | |
973 if(source[end] == '"') { | |
974 in_quote = !in_quote; | |
975 } | |
976 } else { | |
977 escape_next = FALSE; | |
978 } | |
979 end++; | |
980 } | |
981 do_parse = TRUE; | |
982 | |
983 } else { | |
984 gchar end_char; | |
985 if(source[p] == '"') { | |
986 end_char = '"'; | |
987 p++; | |
988 } else { | |
989 end_char = ' '; | |
990 } | |
991 do_parse = FALSE; | |
992 | |
993 end = p; | |
994 while(source[end] != end_char && end < strlen(source)) { | |
995 if(source[end] == '\\') | |
996 end++; | |
997 end++; | |
998 } | |
999 } | |
1000 newstr = g_new0(gchar, end+1-p); | |
1001 strncpy(newstr,source+p,end-p); | |
1002 if (ptree->num_children < MAXCHILDREN) { | |
1003 /* In case we surpass maxchildren, ignore this */ | |
1004 ptree->children[ptree->num_children++] = parse_buffer( newstr, do_parse); | |
1005 } else { | |
1006 gaim_debug_error("zephyr","too many children in tzc output. skipping\n"); | |
1007 } | |
1008 g_free(newstr); | |
1009 p = end + 1; | |
1010 } | |
1011 return ptree; | |
1012 } else { | |
1013 /* XXX does this have to be strdup'd */ | |
1014 ptree->contents = g_strdup(source); | |
1015 return ptree; | |
1016 } | |
1017 } | |
1018 | |
1019 parse_tree *read_from_tzc(zephyr_account* zephyr){ | |
1020 struct timeval tv; | |
1021 fd_set rfds; | |
1022 int bufsize = 2048; | |
1023 char *buf = (char *)calloc(bufsize, 1); | |
1024 char *bufcur = buf; | |
1025 int selected = 0; | |
9986 | 1026 parse_tree *incoming_msg; |
9896 | 1027 |
1028 FD_ZERO(&rfds); | |
1029 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); | |
1030 tv.tv_sec = 0; | |
1031 tv.tv_usec = 0; | |
9986 | 1032 incoming_msg=NULL; |
9896 | 1033 |
1034 while (select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, &tv)) { | |
1035 selected = 1; | |
1036 read(zephyr->fromtzc[ZEPHYR_FD_READ], bufcur, 1); | |
1037 bufcur++; | |
1038 if ((bufcur - buf) > (bufsize - 1)) { | |
1039 if ((buf = realloc(buf, bufsize * 2)) == NULL) { | |
1040 gaim_debug_error("zephyr","Ran out of memory"); | |
1041 exit(-1); | |
1042 } else { | |
1043 bufcur = buf + bufsize; | |
1044 bufsize *= 2; | |
1045 } | |
1046 } | |
1047 } | |
1048 *bufcur = '\0'; | |
1049 | |
1050 if (selected) { | |
1051 incoming_msg = parse_buffer(buf,TRUE); | |
1052 } | |
1053 free(buf); | |
1054 return incoming_msg; | |
1055 } | |
1056 | |
1057 static gint check_notify_tzc(gpointer data) | |
1058 { | |
1059 GaimConnection *gc = (GaimConnection *)data; | |
1060 zephyr_account* zephyr = gc->proto_data; | |
1061 parse_tree *newparsetree = read_from_tzc(zephyr); | |
1062 struct sockaddr_in from; | |
1063 if (newparsetree != NULL) { | |
1064 gchar *spewtype; | |
1065 if ( (spewtype = tree_child(find_node(newparsetree,"tzcspew"),2)->contents) ) { | |
1066 if (!g_ascii_strncasecmp(spewtype,"message",7)) { | |
1067 ZNotice_t notice; | |
1068 parse_tree *msgnode = tree_child(find_node(newparsetree,"message"),2); | |
1069 parse_tree *bodynode = tree_child(msgnode,1); | |
1070 /* char *zsig = g_strdup(" "); */ /* gaim doesn't care about zsigs */ | |
1071 char *msg = zephyr_tzc_deescape_str(bodynode->contents); | |
1072 size_t bufsize = strlen(msg) + 3; | |
1073 char *buf = g_new0(char,bufsize); | |
1074 g_snprintf(buf,1+strlen(msg)+2," %c%s",'\0',msg); | |
1075 bzero((char *)¬ice, sizeof(notice)); | |
1076 notice.z_kind = ACKED; | |
1077 notice.z_port = 0; | |
1078 notice.z_opcode = tree_child(find_node(newparsetree,"opcode"),2)->contents; | |
1079 notice.z_class = zephyr_tzc_deescape_str(tree_child(find_node(newparsetree,"class"),2)->contents); | |
1080 notice.z_class_inst = tree_child(find_node(newparsetree,"instance"),2)->contents; | |
1081 notice.z_recipient = local_zephyr_normalize(zephyr,tree_child(find_node(newparsetree,"recipient"),2)->contents); | |
1082 notice.z_sender = local_zephyr_normalize(zephyr,tree_child(find_node(newparsetree,"sender"),2)->contents); | |
1083 notice.z_default_format = "Class $class, Instance $instance:\n" "To: @bold($recipient) at $time $date\n" "From: @bold($1) <$sender>\n\n$2"; | |
1084 notice.z_message_len = strlen(msg) + 3; | |
1085 notice.z_message = buf; | |
1086 handle_message(gc,notice,from); | |
1087 g_free(msg); | |
1088 /* g_free(zsig); */ | |
1089 g_free(buf); | |
1090 /* free_parse_tree(msgnode); | |
1091 free_parse_tree(bodynode); | |
1092 g_free(msg); | |
1093 g_free(zsig); | |
1094 g_free(buf); | |
1095 */ | |
1096 } | |
1097 else if (!g_ascii_strncasecmp(spewtype,"zlocation",9)) { | |
1098 /* check_loc or zephyr_zloc respectively */ | |
1099 /* XXX fix */ | |
1100 char *user; | |
1101 GaimBuddy *b; | |
1102 int nlocs = 0; | |
9912 | 1103 parse_tree *locations; |
1104 gchar *locval; | |
9896 | 1105 user = tree_child(find_node(newparsetree,"user"),2)->contents; |
1106 | |
1107 if ((b = gaim_find_buddy(gc->account, user)) == NULL) { | |
9986 | 1108 gchar *stripped_user = zephyr_strip_local_realm(zephyr,user); |
9912 | 1109 b = gaim_find_buddy(gc->account, stripped_user); |
9986 | 1110 g_free(stripped_user); |
9896 | 1111 } |
1112 locations = find_node(newparsetree,"locations"); | |
1113 locval = tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents; | |
1114 | |
1115 if (!locval || !g_ascii_strcasecmp(locval," ") || (strlen(locval) == 0)) { | |
1116 nlocs = 0; | |
1117 } else { | |
1118 nlocs = 1; | |
1119 } | |
1120 | |
1121 if ((b && pending_zloc(zephyr,b->name)) || pending_zloc(zephyr,user) || pending_zloc(zephyr,local_zephyr_normalize(zephyr,user))){ | |
1122 GString *str = g_string_new(""); | |
1123 | |
1124 g_string_append_printf(str, _("<b>User:</b> %s<br>"), b ? b->name : user); | |
1125 if (b && b->alias) | |
1126 g_string_append_printf(str, _("<b>Alias:</b> %s<br>"), b->alias); | |
1127 | |
1128 if (!nlocs) { | |
1129 g_string_append_printf(str, _("<br>Hidden or not logged-in")); | |
1130 } else { | |
1131 g_string_append_printf(str, _("<br>At %s since %s"), | |
1132 tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents, | |
1133 tree_child(tree_child(tree_child(tree_child(locations,2),0),2),2)->contents); | |
1134 } | |
1135 | |
1136 gaim_notify_userinfo(gc, b ? b->name : user, NULL, _("Buddy Information"), NULL, | |
1137 str->str, NULL, NULL); | |
1138 g_string_free(str, TRUE); | |
1139 } else { | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1140 if (nlocs>0) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1141 gaim_prpl_got_user_status(gc->account,b->name,"online",NULL); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1142 else |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1143 gaim_prpl_got_user_status(gc->account,b->name,"offline",NULL); |
9896 | 1144 } |
1145 } | |
1146 else if (!g_ascii_strncasecmp(spewtype,"subscribed",10)) { | |
1147 } | |
1148 else if (!g_ascii_strncasecmp(spewtype,"start",5)) { | |
1149 } | |
1150 else if (!g_ascii_strncasecmp(spewtype,"error",5)) { | |
1151 /* XXX handle */ | |
1152 } | |
1153 } else { | |
1154 } | |
1155 } else { | |
1156 } | |
1157 | |
1158 free_parse_tree(newparsetree); | |
1159 return TRUE; | |
1160 } | |
1161 | |
1162 static gint check_notify_zeph02(gpointer data) | |
2086 | 1163 { |
9478 | 1164 /* XXX add real error reporting */ |
9896 | 1165 GaimConnection *gc = (GaimConnection*) data; |
2086 | 1166 while (ZPending()) { |
1167 ZNotice_t notice; | |
1168 struct sockaddr_in from; | |
9478 | 1169 /* XXX add real error reporting */ |
8644 | 1170 |
2086 | 1171 z_call_r(ZReceiveNotice(¬ice, &from)); |
1172 | |
1173 switch (notice.z_kind) { | |
1174 case UNSAFE: | |
1175 case UNACKED: | |
1176 case ACKED: | |
9610 | 1177 handle_message(gc,notice, from); |
2086 | 1178 break; |
8644 | 1179 case SERVACK: |
1180 if (!(g_ascii_strcasecmp(notice.z_message, ZSRVACK_NOTSENT))) { | |
9610 | 1181 message_failed(gc,notice, from); |
8644 | 1182 } |
1183 break; | |
9328 | 1184 case CLIENTACK: |
9478 | 1185 gaim_debug_error("zephyr", "Client ack received\n"); |
2086 | 1186 default: |
1187 /* we'll just ignore things for now */ | |
9328 | 1188 handle_unknown(notice); |
9478 | 1189 gaim_debug_error("zephyr", "Unhandled notice.\n"); |
2086 | 1190 break; |
1191 } | |
9478 | 1192 /* XXX add real error reporting */ |
2086 | 1193 ZFreeNotice(¬ice); |
1194 } | |
1195 | |
1196 return TRUE; | |
1197 } | |
1198 | |
1199 static gint check_loc(gpointer data) | |
1200 { | |
6695 | 1201 GaimBlistNode *gnode, *cnode, *bnode; |
2086 | 1202 ZAsyncLocateData_t ald; |
9896 | 1203 GaimConnection *gc = (GaimConnection *)data; |
1204 zephyr_account *zephyr = gc->proto_data; | |
2086 | 1205 |
9896 | 1206 if (use_zeph02(zephyr)) { |
1207 ald.user = NULL; | |
1208 memset(&(ald.uid), 0, sizeof(ZUnique_Id_t)); | |
1209 ald.version = NULL; | |
1210 } | |
2086 | 1211 |
8644 | 1212 for (gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { |
1213 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
4785 | 1214 continue; |
8644 | 1215 for (cnode = gnode->child; cnode; cnode = cnode->next) { |
1216 if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) | |
4785 | 1217 continue; |
8644 | 1218 for (bnode = cnode->child; bnode; bnode = bnode->next) { |
1219 GaimBuddy *b = (GaimBuddy *) bnode; | |
1220 | |
1221 if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) | |
6695 | 1222 continue; |
9610 | 1223 if (b->account->gc == gc) { |
7261 | 1224 const char *chk; |
8644 | 1225 |
9896 | 1226 chk = local_zephyr_normalize(zephyr,b->name); |
1227 gaim_debug_info("zephyr","chk: %s b->name %s\n",chk,b->name); | |
9478 | 1228 /* XXX add real error reporting */ |
6695 | 1229 /* doesn't matter if this fails or not; we'll just move on to the next one */ |
9896 | 1230 if (use_zeph02(zephyr)) { |
1231 #ifdef WIN32 | |
9986 | 1232 int numlocs; |
1233 int one=1; | |
1234 ZLocateUser(chk,&numlocs,ZAUTH); | |
1235 if (numlocs) { | |
1236 int i; | |
1237 for(i=0;i<numlocs;i++) { | |
1238 ZGetLocations(&locations,&one); | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1239 if (nlocs>0) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1240 gaim_prpl_got_user_status(gc->account,b->name,"online",NULL); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1241 else |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1242 gaim_prpl_got_user_status(gc->account,b->name,"offline",NULL); |
9986 | 1243 } |
1244 } | |
9896 | 1245 #else |
1246 ZRequestLocations(chk, &ald, UNACKED, ZAUTH); | |
1247 g_free(ald.user); | |
1248 g_free(ald.version); | |
1249 #endif /* WIN32 */ | |
1250 } else | |
1251 if (use_tzc(zephyr)) { | |
1252 gchar *zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n",chk); | |
1253 write(zephyr->totzc[ZEPHYR_FD_WRITE],zlocstr,strlen(zlocstr)); | |
1254 g_free(zlocstr); | |
1255 } | |
6695 | 1256 } |
4349 | 1257 } |
2086 | 1258 } |
1259 } | |
9896 | 1260 |
2086 | 1261 return TRUE; |
1262 } | |
1263 | |
1264 static char *get_exposure_level() | |
1265 { | |
9478 | 1266 /* XXX add real error reporting */ |
2086 | 1267 char *exposure = ZGetVariable("exposure"); |
1268 | |
1269 if (!exposure) | |
1270 return EXPOSE_REALMVIS; | |
4793 | 1271 if (!g_ascii_strcasecmp(exposure, EXPOSE_NONE)) |
2086 | 1272 return EXPOSE_NONE; |
4793 | 1273 if (!g_ascii_strcasecmp(exposure, EXPOSE_OPSTAFF)) |
2086 | 1274 return EXPOSE_OPSTAFF; |
4793 | 1275 if (!g_ascii_strcasecmp(exposure, EXPOSE_REALMANN)) |
2086 | 1276 return EXPOSE_REALMANN; |
4793 | 1277 if (!g_ascii_strcasecmp(exposure, EXPOSE_NETVIS)) |
2086 | 1278 return EXPOSE_NETVIS; |
4793 | 1279 if (!g_ascii_strcasecmp(exposure, EXPOSE_NETANN)) |
2086 | 1280 return EXPOSE_NETANN; |
1281 return EXPOSE_REALMVIS; | |
1282 } | |
1283 | |
1284 static void strip_comments(char *str) | |
1285 { | |
1286 char *tmp = strchr(str, '#'); | |
8644 | 1287 |
2086 | 1288 if (tmp) |
1289 *tmp = '\0'; | |
1290 g_strchug(str); | |
1291 g_strchomp(str); | |
1292 } | |
1293 | |
9896 | 1294 static void zephyr_inithosts(zephyr_account *zephyr) |
9478 | 1295 { |
1296 /* XXX This code may not be Win32 clean */ | |
1297 struct hostent *hent; | |
1298 | |
9802 | 1299 if (gethostname(zephyr->ourhost, sizeof(zephyr->ourhost)) == -1) { |
9478 | 1300 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "unable to retrieve hostname, %%host%% and %%canon%% will be wrong in subscriptions and have been set to unknown\n"); |
9802 | 1301 g_strlcpy(zephyr->ourhost, "unknown", sizeof(zephyr->ourhost)); |
9803 | 1302 g_strlcpy(zephyr->ourhostcanon, "unknown", sizeof(zephyr->ourhostcanon)); |
9478 | 1303 return; |
1304 } | |
1305 | |
9610 | 1306 if (!(hent = gethostbyname(zephyr->ourhost))) { |
1307 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "unable to resolve hostname, %%canon%% will be wrong in subscriptions.and has been set to the value of %%host%%, %s\n",zephyr->ourhost); | |
9803 | 1308 g_strlcpy(zephyr->ourhostcanon, zephyr->ourhost, sizeof(zephyr->ourhostcanon)); |
9478 | 1309 return; |
1310 } | |
9802 | 1311 |
1312 g_strlcpy(zephyr->ourhostcanon, hent->h_name, sizeof(zephyr->ourhostcanon)); | |
1313 | |
9478 | 1314 return; |
1315 } | |
1316 | |
9610 | 1317 static void process_zsubs(zephyr_account *zephyr) |
2086 | 1318 { |
9802 | 1319 /* Loads zephyr chats "(subscriptions) from ~/.zephyr.subs, and |
1320 registers (subscribes to) them on the server */ | |
9434 | 1321 |
9802 | 1322 /* XXX deal with unsubscriptions */ |
1323 /* XXX deal with punts */ | |
9434 | 1324 |
2086 | 1325 FILE *f; |
1326 gchar *fname; | |
1327 gchar buff[BUFSIZ]; | |
8644 | 1328 |
3630 | 1329 fname = g_strdup_printf("%s/.zephyr.subs", gaim_home_dir()); |
2086 | 1330 f = fopen(fname, "r"); |
1331 if (f) { | |
1332 char **triple; | |
1333 char *recip; | |
9478 | 1334 char *z_class; |
1335 char *z_instance; | |
9896 | 1336 char *z_galaxy = NULL; |
8644 | 1337 |
2086 | 1338 while (fgets(buff, BUFSIZ, f)) { |
1339 strip_comments(buff); | |
1340 if (buff[0]) { | |
1341 triple = g_strsplit(buff, ",", 3); | |
8644 | 1342 if (triple[0] && triple[1]) { |
9896 | 1343 char *tmp = g_strdup_printf("%s", zephyr->username); |
2804
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1344 char *atptr; |
8644 | 1345 |
9896 | 1346 z_class = triple[0]; |
1347 z_instance = triple[1]; | |
8644 | 1348 if (triple[2] == NULL) { |
3277 | 1349 recip = g_malloc0(1); |
4793 | 1350 } else if (!g_ascii_strcasecmp(triple[2], "%me%")) { |
9896 | 1351 recip = g_strdup_printf("%s", zephyr->username); |
4793 | 1352 } else if (!g_ascii_strcasecmp(triple[2], "*")) { |
2804
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1353 /* wildcard |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1354 * form of class,instance,* */ |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1355 recip = g_malloc0(1); |
4793 | 1356 } else if (!g_ascii_strcasecmp(triple[2], tmp)) { |
2804
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1357 /* form of class,instance,aatharuv@ATHENA.MIT.EDU */ |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1358 recip = g_strdup(triple[2]); |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1359 } else if ((atptr = strchr(triple[2], '@')) != NULL) { |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1360 /* form of class,instance,*@ANDREW.CMU.EDU |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1361 * class,instance,@ANDREW.CMU.EDU |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1362 * If realm is local realm, blank recipient, else |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1363 * @REALM-NAME |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1364 */ |
9896 | 1365 char *realmat = g_strdup_printf("@%s",zephyr->realm); |
8644 | 1366 |
4793 | 1367 if (!g_ascii_strcasecmp(atptr, realmat)) |
2804
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1368 recip = g_malloc0(1); |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1369 else |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1370 recip = g_strdup(atptr); |
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1371 g_free(realmat); |
2086 | 1372 } else { |
1373 recip = g_strdup(triple[2]); | |
1374 } | |
2804
1648c703ddc2
[gaim-migrate @ 2817]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2791
diff
changeset
|
1375 g_free(tmp); |
9478 | 1376 |
1377 if (!g_ascii_strcasecmp(triple[0],"%host%")) { | |
9610 | 1378 z_class = g_strdup(zephyr->ourhost); |
9478 | 1379 } else if (!g_ascii_strcasecmp(triple[0],"%canon%")) { |
9610 | 1380 z_class = g_strdup(zephyr->ourhostcanon); |
9478 | 1381 } else { |
1382 z_class = g_strdup(triple[0]); | |
1383 } | |
1384 | |
1385 if (!g_ascii_strcasecmp(triple[1],"%host%")) { | |
9610 | 1386 z_instance = g_strdup(zephyr->ourhost); |
9478 | 1387 } else if (!g_ascii_strcasecmp(triple[1],"%canon%")) { |
9610 | 1388 z_instance = g_strdup(zephyr->ourhostcanon); |
9478 | 1389 } else { |
1390 z_instance = g_strdup(triple[1]); | |
1391 } | |
1392 | |
1393 /* There should be some sort of error report listing classes that couldn't be subbed to. | |
1394 Not important right now though */ | |
1395 | |
9896 | 1396 if (zephyr_subscribe_to(zephyr,z_class, z_instance, recip,z_galaxy) != ZERR_NONE) { |
9478 | 1397 |
9896 | 1398 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "Couldn't subscribe to %s, %s, %s\n", z_class,z_instance,recip); |
2086 | 1399 } |
9478 | 1400 |
9896 | 1401 zephyr->subscrips = g_slist_append(zephyr->subscrips, new_triple(zephyr,z_class,z_instance,recip)); |
9478 | 1402 /* g_hash_table_destroy(sub_hash_table); */ |
1403 g_free(z_instance); | |
1404 g_free(z_class); | |
2086 | 1405 g_free(recip); |
1406 } | |
1407 g_strfreev(triple); | |
1408 } | |
1409 } | |
1410 } | |
1411 } | |
1412 | |
9610 | 1413 static void process_anyone(GaimConnection *gc) |
2086 | 1414 { |
1415 FILE *fd; | |
1416 gchar buff[BUFSIZ], *filename; | |
6695 | 1417 GaimGroup *g; |
1418 GaimBuddy *b; | |
4775 | 1419 |
1420 if (!(g = gaim_find_group(_("Anyone")))) { | |
1421 g = gaim_group_new(_("Anyone")); | |
1422 gaim_blist_add_group(g, NULL); | |
1423 } | |
6695 | 1424 |
3630 | 1425 filename = g_strconcat(gaim_home_dir(), "/.anyone", NULL); |
2086 | 1426 if ((fd = fopen(filename, "r")) != NULL) { |
1427 while (fgets(buff, BUFSIZ, fd)) { | |
1428 strip_comments(buff); | |
4687 | 1429 if (buff[0]) { |
9610 | 1430 if (!(b = gaim_find_buddy(gc->account, buff))) { |
9986 | 1431 char *stripped_user = zephyr_strip_local_realm(gc->proto_data,buff); |
1432 gaim_debug_info("zephyr","stripped_user %s\n",stripped_user); | |
1433 if (!(b = gaim_find_buddy(gc->account,stripped_user))){ | |
1434 b = gaim_buddy_new(gc->account, stripped_user, NULL); | |
1435 gaim_blist_add_buddy(b, NULL, g, NULL); | |
1436 } | |
1437 g_free(stripped_user); | |
8644 | 1438 } |
1439 } | |
2086 | 1440 } |
1441 fclose(fd); | |
1442 } | |
1443 g_free(filename); | |
1444 } | |
1445 | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1446 static char* normalize_zephyr_exposure(const char* exposure) { |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1447 char *exp2 = g_strstrip(g_ascii_strup(exposure,-1)); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1448 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1449 if (!exp2) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1450 return EXPOSE_REALMVIS; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1451 if (!g_ascii_strcasecmp(exp2, EXPOSE_NONE)) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1452 return EXPOSE_NONE; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1453 if (!g_ascii_strcasecmp(exp2, EXPOSE_OPSTAFF)) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1454 return EXPOSE_OPSTAFF; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1455 if (!g_ascii_strcasecmp(exp2, EXPOSE_REALMANN)) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1456 return EXPOSE_REALMANN; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1457 if (!g_ascii_strcasecmp(exp2, EXPOSE_NETVIS)) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1458 return EXPOSE_NETVIS; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1459 if (!g_ascii_strcasecmp(exp2, EXPOSE_NETANN)) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1460 return EXPOSE_NETANN; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1461 return EXPOSE_REALMVIS; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1462 } |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1463 |
8644 | 1464 static void zephyr_login(GaimAccount * account) |
2086 | 1465 { |
9896 | 1466 GaimConnection *gc; |
1467 zephyr_account *zephyr; | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1468 gboolean read_anyone; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1469 gboolean read_zsubs; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1470 gchar *exposure; |
9427 | 1471 |
9610 | 1472 gc = gaim_account_get_connection(account); |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1473 read_anyone = gaim_account_get_bool(gc->account,"read_anyone",TRUE); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1474 read_zsubs = gaim_account_get_bool(gc->account,"read_zsubs",TRUE); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1475 exposure = (gchar *)gaim_account_get_string(gc->account, "exposure_level", EXPOSE_REALMVIS); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1476 |
9610 | 1477 gc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_NO_BGCOLOR | GAIM_CONNECTION_NO_URLDESC; |
9896 | 1478 gc->proto_data = zephyr=g_new0(zephyr_account,1); |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1479 |
9896 | 1480 zephyr->account = account; |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1481 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1482 /* Make sure that the exposure (visibility) is set to a sane value */ |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1483 zephyr->exposure=g_strdup(normalize_zephyr_exposure(exposure)); |
2086 | 1484 |
9896 | 1485 if (gaim_account_get_bool(gc->account,"use_tzc",0)) { |
1486 zephyr->connection_type = GAIM_ZEPHYR_TZC; | |
1487 } else { | |
1488 zephyr->connection_type = GAIM_ZEPHYR_KRB4; | |
1489 } | |
1490 | |
1491 zephyr->encoding = (char *)gaim_account_get_string(gc->account, "encoding", ZEPHYR_FALLBACK_CHARSET); | |
9610 | 1492 gaim_connection_update_progress(gc, _("Connecting"), 0, 8); |
9478 | 1493 |
1494 /* XXX z_call_s should actually try to report the com_err determined error */ | |
9896 | 1495 if (use_tzc(zephyr)) { |
1496 pid_t pid; | |
1497 /* gaim_connection_error(gc,"tzc not supported yet"); */ | |
1498 if ((pipe(zephyr->totzc) != 0) || (pipe(zephyr->fromtzc) != 0)) { | |
1499 gaim_debug_error("zephyr", "pipe creation failed. killing\n"); | |
1500 exit(-1); | |
1501 } | |
1502 | |
1503 pid = fork(); | |
1504 | |
1505 if (pid == -1) { | |
1506 gaim_debug_error("zephyr", "forking failed\n"); | |
1507 exit(-1); | |
1508 } | |
1509 if (pid == 0) { | |
1510 unsigned int i=0; | |
1511 gboolean found_ps = FALSE; | |
1512 gchar ** tzc_cmd_array = g_strsplit(gaim_account_get_string(gc->account,"tzc_command","/usr/bin/tzc -e %s")," ",0); | |
1513 if (close(1) == -1) { | |
1514 gaim_debug_error("zephyr", "stdout couldn't be closed. dying\n"); | |
1515 exit(-1); | |
1516 } | |
1517 if (dup2(zephyr->fromtzc[1], 1) == -1) { | |
1518 gaim_debug_error("zephyr", "dup2 of stdout failed \n"); | |
1519 exit(-1); | |
1520 } | |
1521 if (close(zephyr->fromtzc[1]) == -1) { | |
1522 gaim_debug_error("zephyr", "closing of piped stdout failed\n"); | |
1523 exit(-1); | |
1524 } | |
1525 if (close(0) == -1) { | |
1526 gaim_debug_error("zephyr", "stdin couldn't be closed. dying\n"); | |
1527 exit(-1); | |
1528 } | |
1529 if (dup2(zephyr->totzc[0], 0) == -1) { | |
1530 gaim_debug_error("zephyr", "dup2 of stdin failed \n"); | |
1531 exit(-1); | |
1532 } | |
1533 if (close(zephyr->totzc[0]) == -1) { | |
1534 gaim_debug_error("zephyr", "closing of piped stdin failed\n"); | |
1535 exit(-1); | |
1536 } | |
1537 /* tzc_command should really be of the form | |
1538 path/to/tzc -e %s | |
1539 or | |
1540 ssh username@hostname pathtotzc -e %s | |
1541 -- this should not require a password, and ideally should be kerberized ssh -- | |
1542 or | |
1543 fsh username@hostname pathtotzc -e %s | |
1544 */ | |
1545 while(tzc_cmd_array[i] != NULL){ | |
1546 if (!g_strncasecmp(tzc_cmd_array[i],"%s",2)) { | |
9986 | 1547 /* fprintf(stderr,"replacing %%s with %s\n",zephyr->exposure); */ |
9896 | 1548 tzc_cmd_array[i] = g_strdup(zephyr->exposure); |
1549 found_ps = TRUE; | |
1550 | |
1551 } else { | |
9986 | 1552 /* fprintf(stderr,"keeping %s\n",tzc_cmd_array[i]); */ |
9896 | 1553 } |
1554 i++; | |
1555 } | |
8645 | 1556 |
9896 | 1557 if (!found_ps) { |
1558 gaim_connection_error(gc,"Tzc command needs %s to set the exposure\n"); | |
1559 return; | |
1560 } | |
1561 | |
1562 execvp(tzc_cmd_array[0], tzc_cmd_array); | |
1563 } | |
1564 else { | |
1565 fd_set rfds; | |
1566 int bufsize = 2048; | |
1567 char *buf = (char *)calloc(bufsize, 1); | |
1568 char *bufcur = buf; | |
1569 struct timeval tv; | |
1570 char *ptr; | |
1571 int parenlevel=0; | |
1572 char* tempstr; | |
1573 int tempstridx; | |
1574 | |
9986 | 1575 zephyr->tzc_pid = pid; |
9896 | 1576 /* wait till we have data to read from ssh */ |
1577 FD_ZERO(&rfds); | |
1578 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); | |
1579 | |
1580 tv.tv_sec = 10; | |
1581 tv.tv_usec = 0; | |
1582 | |
1583 gaim_debug_info("zephyr", "about to read from tzc\n"); | |
1584 | |
1585 select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, NULL); | |
1586 | |
1587 FD_ZERO(&rfds); | |
1588 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); | |
1589 while (select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, &tv)) { | |
1590 read(zephyr->fromtzc[ZEPHYR_FD_READ], bufcur, 1); | |
1591 bufcur++; | |
1592 if ((bufcur - buf) > (bufsize - 1)) { | |
1593 if ((buf = realloc(buf, bufsize * 2)) == NULL) { | |
1594 exit(-1); | |
1595 } else { | |
1596 bufcur = buf + bufsize; | |
1597 bufsize *= 2; | |
1598 } | |
1599 } | |
1600 FD_ZERO(&rfds); | |
1601 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); | |
1602 tv.tv_sec = 10; | |
1603 tv.tv_usec = 0; | |
2086 | 1604 |
9896 | 1605 } |
9986 | 1606 /* fprintf(stderr, "read from tzc\n"); */ |
9896 | 1607 *bufcur = '\0'; |
1608 ptr = buf; | |
1609 | |
1610 /* ignore all tzcoutput till we've received the first (*/ | |
1611 while (ptr < bufcur && (*ptr !='(')) { | |
1612 ptr++; | |
1613 } | |
1614 if (ptr >=bufcur) { | |
1615 gaim_connection_error(gc,"invalid output by tzc (or bad parsing code)"); | |
1616 return; | |
1617 } | |
9427 | 1618 |
9896 | 1619 while(ptr < bufcur) { |
1620 if (*ptr == '(') { | |
1621 parenlevel++; | |
1622 } | |
1623 else if (*ptr == ')') { | |
1624 parenlevel--; | |
1625 } | |
1626 gaim_debug_info("zephyr","tzc parenlevel is %d\n",parenlevel); | |
1627 switch (parenlevel) { | |
1628 case 0: | |
1629 break; | |
1630 case 1: | |
1631 /* Search for next beginning (, or for the ending */ | |
1632 ptr++; | |
1633 while((*ptr != '(') && (*ptr != ')') && (ptr <bufcur)) | |
1634 ptr++; | |
1635 if (ptr >= bufcur) | |
1636 gaim_debug_error("zephyr","tzc parsing error\n"); | |
1637 break; | |
1638 case 2: | |
1639 /* You are probably at | |
1640 (foo . bar ) or (foo . "bar") or (foo . chars) or (foo . numbers) or (foo . () ) | |
1641 Parse all the data between the first and last f, and move past ) | |
1642 */ | |
1643 tempstr = g_malloc0(20000); | |
1644 tempstridx=0; | |
1645 while(parenlevel >1) { | |
1646 ptr++; | |
1647 if (*ptr == '(') | |
1648 parenlevel++; | |
1649 if (*ptr == ')') | |
1650 parenlevel--; | |
1651 if (parenlevel > 1) { | |
1652 tempstr[tempstridx++]=*ptr; | |
1653 } else { | |
1654 ptr++; | |
1655 } | |
1656 } | |
1657 gaim_debug_info("zephyr","tempstr parsed\n"); | |
1658 /* tempstr should now be a tempstridx length string containing all characters | |
1659 from that after the first ( to the one before the last paren ). */ | |
1660 /* We should have the following possible lisp strings but we don't care | |
1661 (tzcspew . start) (version . "something") (pid . number)*/ | |
1662 /* We care about 'zephyrid . "username@REALM.NAME"' and 'exposure . "SOMETHING"' */ | |
1663 tempstridx=0; | |
1664 if (!g_ascii_strncasecmp(tempstr,"zephyrid",8)) { | |
1665 gchar* username = g_malloc0(100); | |
1666 int username_idx=0; | |
1667 char *realm; | |
1668 gaim_debug_info("zephyr","zephyrid found\n"); | |
1669 tempstridx+=8; | |
1670 while(tempstr[tempstridx] !='"' && tempstridx < 20000) | |
1671 tempstridx++; | |
1672 tempstridx++; | |
1673 while(tempstr[tempstridx] !='"' && tempstridx < 20000) | |
1674 username[username_idx++]=tempstr[tempstridx++]; | |
1675 | |
1676 zephyr->username = g_strdup_printf("%s",username); | |
1677 if ((realm = strchr(username,'@'))) | |
1678 zephyr->realm = g_strdup_printf("%s",realm+1); | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1679 else { |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1680 realm = (gchar *)gaim_account_get_string(gc->account,"realm",""); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1681 if (!g_strcasecmp(realm,"")) { |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1682 realm = "local-realm"; |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1683 } |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1684 zephyr->realm = g_strdup(realm); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1685 g_strlcpy(__Zephyr_realm, (const char*)zephyr->realm, REALM_SZ-1); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1686 } |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1687 /* else { |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1688 zephyr->realm = g_strdup("local-realm"); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1689 }*/ |
9896 | 1690 |
1691 g_free(username); | |
1692 } else { | |
1693 gaim_debug_info("zephyr", "something that's not zephyr id found %s\n",tempstr); | |
1694 } | |
1695 | |
1696 /* We don't care about anything else yet */ | |
1697 g_free(tempstr); | |
1698 break; | |
1699 default: | |
1700 gaim_debug_info("zephyr","parenlevel is not 1 or 2\n"); | |
1701 /* This shouldn't be happening */ | |
1702 break; | |
1703 } | |
1704 if (parenlevel==0) | |
1705 break; | |
1706 } /* while (ptr < bufcur) { */ | |
1707 gaim_debug_info("zephyr", "tzc startup done\n"); | |
1708 } | |
1709 } | |
1710 else if ( use_zeph02(zephyr)) { | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1711 gchar* realm; |
9896 | 1712 z_call_s(ZInitialize(), "Couldn't initialize zephyr"); |
1713 z_call_s(ZOpenPort(&(zephyr->port)), "Couldn't open port"); | |
1714 z_call_s(ZSetLocation((char *)zephyr->exposure), "Couldn't set location"); | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1715 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1716 realm = (gchar *)gaim_account_get_string(gc->account,"realm",""); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1717 if (!g_strcasecmp(realm,"")) { |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1718 realm = ZGetRealm(); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1719 } |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1720 zephyr->realm = g_strdup(realm); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1721 g_strlcpy(__Zephyr_realm, (const char*)zephyr->realm, REALM_SZ-1); |
9896 | 1722 zephyr->username = g_strdup(ZGetSender()); |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1723 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1724 /* zephyr->realm = g_strdup(ZGetRealm()); */ |
9896 | 1725 gaim_debug_info("zephyr","realm: %s\n",zephyr->realm); |
1726 } | |
1727 else { | |
1728 gaim_connection_error(gc,"Only ZEPH0.2 supported currently"); | |
1729 return; | |
1730 } | |
1731 gaim_debug_info("zephyr","does it get here\n"); | |
1732 gaim_debug_info("zephyr"," realm: %s username:%s\n", zephyr->realm, zephyr->username); | |
1733 | |
1734 /* For now */ | |
1735 zephyr->galaxy = NULL; | |
1736 zephyr->krbtkfile = NULL; | |
1737 zephyr_inithosts(zephyr); | |
1738 | |
1739 if (zephyr_subscribe_to(zephyr,"MESSAGE","PERSONAL",zephyr->username,NULL) != ZERR_NONE) { | |
9478 | 1740 /* XXX don't translate this yet. It could be written better */ |
1741 /* XXX error messages could be handled with more detail */ | |
1742 gaim_notify_error(account->gc, NULL, | |
1743 "Unable to subscribe to messages", "Unable to subscribe to initial messages"); | |
1744 return; | |
2086 | 1745 } |
1746 | |
9610 | 1747 gaim_connection_set_state(gc, GAIM_CONNECTED); |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1748 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1749 if (read_anyone) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1750 process_anyone(gc); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1751 if (read_zsubs) |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1752 process_zsubs(zephyr); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
1753 |
9610 | 1754 serv_finish_login(gc); |
2086 | 1755 |
9896 | 1756 if (use_zeph02(zephyr)) { |
1757 zephyr->nottimer = gaim_timeout_add(100, check_notify_zeph02, gc); | |
1758 } else if (use_tzc(zephyr)) { | |
1759 zephyr->nottimer = gaim_timeout_add(100, check_notify_tzc, gc); | |
1760 } | |
1761 zephyr->loctimer = gaim_timeout_add(20000, check_loc, gc); | |
2086 | 1762 |
1763 } | |
1764 | |
9610 | 1765 static void write_zsubs(zephyr_account *zephyr) |
2086 | 1766 { |
9896 | 1767 /* Exports subscription (chat) list back to |
1768 * .zephyr.subs | |
1769 * XXX deal with %host%, %canon%, unsubscriptions, and negative subscriptions (punts?) | |
1770 */ | |
9434 | 1771 |
9610 | 1772 GSList *s = zephyr->subscrips; |
2086 | 1773 zephyr_triple *zt; |
1774 FILE *fd; | |
1775 char *fname; | |
1776 | |
8644 | 1777 char **triple; |
1778 | |
3630 | 1779 fname = g_strdup_printf("%s/.zephyr.subs", gaim_home_dir()); |
2086 | 1780 fd = fopen(fname, "w"); |
8644 | 1781 |
2086 | 1782 if (!fd) { |
1783 g_free(fname); | |
1784 return; | |
1785 } | |
8644 | 1786 |
2086 | 1787 while (s) { |
9478 | 1788 char *zclass, *zinst, *zrecip; |
2086 | 1789 zt = s->data; |
8644 | 1790 triple = g_strsplit(zt->name, ",", 3); |
9478 | 1791 |
1792 /* deal with classes */ | |
9610 | 1793 if (!g_ascii_strcasecmp(triple[0],zephyr->ourhost)) { |
9775 | 1794 zclass = g_strdup("%host%"); |
9610 | 1795 } else if (!g_ascii_strcasecmp(triple[0],zephyr->ourhostcanon)) { |
9775 | 1796 zclass = g_strdup("%canon%"); |
9478 | 1797 } else { |
1798 zclass = g_strdup(triple[0]); | |
1799 } | |
1800 | |
1801 /* deal with instances */ | |
1802 | |
9610 | 1803 if (!g_ascii_strcasecmp(triple[1],zephyr->ourhost)) { |
9775 | 1804 zinst = g_strdup("%host%"); |
9610 | 1805 } else if (!g_ascii_strcasecmp(triple[1],zephyr->ourhostcanon)) { |
9896 | 1806 zinst = g_strdup("%canon%");; |
1807 } else { | |
9478 | 1808 zinst = g_strdup(triple[1]); |
9896 | 1809 } |
9478 | 1810 |
1811 /* deal with recipients */ | |
1812 if (triple[2] == NULL) { | |
1813 zrecip = g_strdup("*"); | |
1814 } else if (!g_ascii_strcasecmp(triple[2],"")){ | |
1815 zrecip = g_strdup("*"); | |
9896 | 1816 } else if (!g_ascii_strcasecmp(triple[2], zephyr->username)) { |
9478 | 1817 zrecip = g_strdup("%me%"); |
3277 | 1818 } else { |
9478 | 1819 zrecip = g_strdup(triple[2]); |
3277 | 1820 } |
9478 | 1821 |
1822 fprintf(fd, "%s,%s,%s\n",zclass,zinst,zrecip); | |
1823 | |
1824 g_free(zclass); | |
1825 g_free(zinst); | |
1826 g_free(zrecip); | |
3277 | 1827 g_free(triple); |
2086 | 1828 s = s->next; |
1829 } | |
1830 g_free(fname); | |
1831 fclose(fd); | |
1832 } | |
1833 | |
9610 | 1834 static void write_anyone(GaimConnection *gc) |
2086 | 1835 { |
6695 | 1836 GaimBlistNode *gnode, *cnode, *bnode; |
1837 GaimBuddy *b; | |
9912 | 1838 char *fname; |
2086 | 1839 FILE *fd; |
9896 | 1840 zephyr_account* zephyr = gc->proto_data; |
3630 | 1841 fname = g_strdup_printf("%s/.anyone", gaim_home_dir()); |
2086 | 1842 fd = fopen(fname, "w"); |
1843 if (!fd) { | |
1844 g_free(fname); | |
1845 return; | |
1846 } | |
1847 | |
8644 | 1848 for (gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { |
1849 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
4785 | 1850 continue; |
8644 | 1851 for (cnode = gnode->child; cnode; cnode = cnode->next) { |
1852 if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) | |
4785 | 1853 continue; |
8644 | 1854 for (bnode = cnode->child; bnode; bnode = bnode->next) { |
1855 if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) | |
6695 | 1856 continue; |
8644 | 1857 b = (GaimBuddy *) bnode; |
9610 | 1858 if (b->account == gc->account) { |
9986 | 1859 gchar *stripped_user = zephyr_strip_local_realm(zephyr,b->name); |
9912 | 1860 fprintf(fd, "%s\n", stripped_user); |
9986 | 1861 g_free(stripped_user); |
3277 | 1862 } |
1863 } | |
2086 | 1864 } |
1865 } | |
1866 | |
1867 fclose(fd); | |
1868 g_free(fname); | |
1869 } | |
1870 | |
8644 | 1871 static void zephyr_close(GaimConnection * gc) |
2086 | 1872 { |
1873 GList *l; | |
1874 GSList *s; | |
9896 | 1875 zephyr_account *zephyr = gc->proto_data; |
9986 | 1876 pid_t tzc_pid = zephyr->tzc_pid; |
8644 | 1877 |
9610 | 1878 l = zephyr->pending_zloc_names; |
2086 | 1879 while (l) { |
8644 | 1880 g_free((char *)l->data); |
2086 | 1881 l = l->next; |
1882 } | |
9610 | 1883 g_list_free(zephyr->pending_zloc_names); |
8644 | 1884 |
9610 | 1885 if (gaim_account_get_bool(gc->account, "write_anyone", FALSE)) |
1886 write_anyone(gc); | |
8644 | 1887 |
9610 | 1888 if (gaim_account_get_bool(gc->account, "write_zsubs", FALSE)) |
1889 write_zsubs(gc->proto_data); | |
8644 | 1890 |
9610 | 1891 s = zephyr->subscrips; |
2086 | 1892 while (s) { |
8644 | 1893 free_triple((zephyr_triple *) s->data); |
2086 | 1894 s = s->next; |
1895 } | |
9610 | 1896 g_slist_free(zephyr->subscrips); |
8644 | 1897 |
9610 | 1898 if (zephyr->nottimer) |
1899 gaim_timeout_remove(zephyr->nottimer); | |
1900 zephyr->nottimer = 0; | |
1901 if (zephyr->loctimer) | |
1902 gaim_timeout_remove(zephyr->loctimer); | |
1903 zephyr->loctimer = 0; | |
1904 gc = NULL; | |
9896 | 1905 if (use_zeph02(zephyr)) { |
1906 z_call(ZCancelSubscriptions(0)); | |
1907 z_call(ZUnsetLocation()); | |
1908 z_call(ZClosePort()); | |
1909 } else { | |
1910 /* assume tzc */ | |
9986 | 1911 if (kill(tzc_pid,SIGTERM) == -1) { |
1912 int err=errno; | |
1913 if (err==EINVAL) { | |
1914 gaim_debug_error("zephyr","An invalid signal was specified when killing tzc\n"); | |
1915 } | |
1916 else if (err==ESRCH) { | |
1917 gaim_debug_error("zephyr","Tzc's pid didn't exist while killing tzc\n"); | |
1918 } | |
1919 else if (err==EPERM) { | |
1920 gaim_debug_error("zephyr","gaim didn't have permission to kill tzc\n"); | |
1921 } | |
1922 else { | |
1923 gaim_debug_error("zephyr","miscellaneous error while attempting to close tzc\n"); | |
1924 } | |
1925 } | |
9896 | 1926 } |
2086 | 1927 } |
1928 | |
9896 | 1929 static int zephyr_send_message(zephyr_account *zephyr,char* zclass, char* instance, char* recipient, const char *im, |
9478 | 1930 const char *sig, char *opcode) ; |
9434 | 1931 |
1932 const char * zephyr_get_signature() | |
1933 { | |
9478 | 1934 /* XXX add zephyr error reporting */ |
1935 const char * sig =ZGetVariable("zwrite-signature"); | |
9896 | 1936 if (!sig) { |
1937 sig = g_get_real_name(); | |
1938 } | |
1939 return sig; | |
9434 | 1940 } |
1941 | |
8644 | 1942 static int zephyr_chat_send(GaimConnection * gc, int id, const char *im) |
2086 | 1943 { |
1944 zephyr_triple *zt; | |
1945 const char *sig; | |
8644 | 1946 GaimConversation *gconv1; |
1947 GaimConvChat *gcc; | |
1948 char *inst; | |
9896 | 1949 char *recipient; |
1950 zephyr_account *zephyr = gc->proto_data; | |
2086 | 1951 |
9610 | 1952 zt = find_sub_by_id(gc->proto_data,id); |
2086 | 1953 if (!zt) |
1954 /* this should never happen. */ | |
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
1955 return -EINVAL; |
8644 | 1956 |
9896 | 1957 sig = zephyr_get_signature(); |
2086 | 1958 |
9610 | 1959 gconv1 = gaim_find_conversation_with_account(zt->name, gc->account); |
8644 | 1960 gcc = gaim_conversation_get_chat_data(gconv1); |
8212 | 1961 |
8644 | 1962 if (!(inst = (char *)gaim_conv_chat_get_topic(gcc))) |
9434 | 1963 inst = g_strdup("PERSONAL"); |
8644 | 1964 |
4793 | 1965 if (!g_ascii_strcasecmp(zt->recipient, "*")) |
9896 | 1966 recipient = local_zephyr_normalize(zephyr,""); |
2086 | 1967 else |
9896 | 1968 recipient = local_zephyr_normalize(zephyr,zt->recipient); |
8451 | 1969 |
9896 | 1970 zephyr_send_message(zephyr,zt->class,inst,recipient,im,sig,""); |
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
1971 return 0; |
2086 | 1972 } |
1973 | |
9434 | 1974 |
8644 | 1975 static int zephyr_send_im(GaimConnection * gc, const char *who, const char *im, GaimConvImFlags flags) |
1976 { | |
2086 | 1977 const char *sig; |
9896 | 1978 zephyr_account *zephyr = gc->proto_data; |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
7084
diff
changeset
|
1979 if (flags & GAIM_CONV_IM_AUTO_RESP) |
2086 | 1980 sig = "Automated reply:"; |
1981 else { | |
9434 | 1982 sig = zephyr_get_signature(); |
2086 | 1983 } |
9896 | 1984 zephyr_send_message(zephyr,"MESSAGE","PERSONAL",local_zephyr_normalize(zephyr,who),im,sig,""); |
9434 | 1985 |
1986 return 1; | |
1987 } | |
2086 | 1988 |
9896 | 1989 /* Munge the outgoing zephyr so that any quotes or backslashes are |
1990 escaped and do not confuse tzc: */ | |
1991 | |
1992 char* zephyr_tzc_escape_msg(const char *message) | |
1993 { | |
1994 int pos = 0; | |
1995 int pos2 = 0; | |
1996 char *newmsg; | |
1997 | |
1998 if (message && (strlen(message) > 0)) { | |
1999 newmsg = g_new0(char,1+strlen(message)*2); | |
2000 while(pos < strlen(message)) { | |
2001 if (message[pos]=='\\') { | |
2002 newmsg[pos2]='\\'; | |
2003 newmsg[pos2+1]='\\'; | |
2004 pos2+=2; | |
2005 } | |
2006 else if (message[pos]=='"') { | |
2007 newmsg[pos2]='\\'; | |
2008 newmsg[pos2+1]='"'; | |
2009 pos2+=2; | |
2010 } | |
2011 else { | |
2012 newmsg[pos2] = message[pos]; | |
2013 pos2++; | |
2014 } | |
2015 pos++; | |
2016 } | |
2017 } else { | |
2018 newmsg = g_strdup(""); | |
2019 } | |
9986 | 2020 /* fprintf(stderr,"newmsg %s message %s\n",newmsg,message); */ |
9896 | 2021 return newmsg; |
2022 } | |
2023 | |
2024 char* zephyr_tzc_deescape_str(const char *message) | |
2025 { | |
2026 int pos = 0; | |
2027 int pos2 = 0; | |
2028 char *newmsg; | |
2029 | |
2030 if (message && (strlen(message) > 0)) { | |
2031 newmsg = g_new0(char,strlen(message)+1); | |
2032 while(pos < strlen(message)) { | |
2033 if (message[pos]=='\\') { | |
2034 pos++; | |
2035 } | |
2036 newmsg[pos2] = message[pos]; | |
2037 pos++;pos2++; | |
2038 } | |
2039 newmsg[pos2]='\0'; | |
2040 } else { | |
2041 newmsg = g_strdup(""); | |
2042 } | |
2043 | |
2044 return newmsg; | |
2045 } | |
2046 | |
2047 static int zephyr_send_message(zephyr_account *zephyr,char* zclass, char* instance, char* recipient, const char *im, | |
9478 | 2048 const char *sig, char *opcode) |
9434 | 2049 { |
8451 | 2050 |
9896 | 2051 /* (From the tzc source) |
2052 * emacs sends something of the form: | |
2053 * ((class . "MESSAGE") | |
2054 * (auth . t) | |
2055 * (recipients ("PERSONAL" . "bovik") ("test" . "")) | |
2056 * (sender . "bovik") | |
2057 * (message . ("Harry Bovik" "my zgram")) | |
2058 * ) | |
2059 */ | |
2060 char *html_buf; | |
2061 char *html_buf2; | |
2062 html_buf = html_to_zephyr(im); | |
2063 html_buf2 = gaim_unescape_html(html_buf); | |
9434 | 2064 |
9896 | 2065 if(use_tzc(zephyr)) { |
2066 char* zsendstr; | |
2067 /* CMU cclub tzc doesn't grok opcodes for now */ | |
2068 char* tzc_sig = zephyr_tzc_escape_msg(sig); | |
2069 char *tzc_body = zephyr_tzc_escape_msg(html_buf2); | |
2070 zsendstr = g_strdup_printf("((tzcfodder . send) (class . \"%s\") (auth . t) (recipients (\"%s\" . \"%s\")) (message . (\"%s\" \"%s\")) ) \n", | |
9986 | 2071 zclass, instance, recipient, tzc_sig, tzc_body); |
2072 /* fprintf(stderr,"zsendstr = %s\n",zsendstr); */ | |
9896 | 2073 write(zephyr->totzc[ZEPHYR_FD_WRITE],zsendstr,strlen(zsendstr)); |
2074 g_free(zsendstr); | |
2075 } else if (use_zeph02(zephyr)) { | |
2076 ZNotice_t notice; | |
2077 char *buf = g_strdup_printf("%s%c%s", sig, '\0', html_buf2); | |
2078 bzero((char *)¬ice, sizeof(notice)); | |
2079 | |
2080 notice.z_kind = ACKED; | |
2081 notice.z_port = 0; | |
2082 notice.z_opcode = ""; | |
2083 notice.z_class = zclass; | |
2084 notice.z_class_inst = instance; | |
2085 notice.z_recipient = recipient; | |
2086 notice.z_sender = 0; | |
2087 notice.z_default_format = "Class $class, Instance $instance:\n" "To: @bold($recipient) at $time $date\n" "From: @bold($1) <$sender>\n\n$2"; | |
2088 notice.z_message_len = strlen(html_buf2) + strlen(sig) + 2; | |
2089 notice.z_message = buf; | |
2090 notice.z_opcode = g_strdup(opcode); | |
2091 gaim_debug_info("zephyr","About to send notice"); | |
2092 if (! ZSendNotice(¬ice, ZAUTH) == ZERR_NONE) { | |
2093 /* XXX handle errors here */ | |
2094 return 0; | |
2095 } | |
2096 gaim_debug_info("zephyr","notice sent"); | |
2097 g_free(buf); | |
9478 | 2098 } |
2099 | |
8644 | 2100 g_free(html_buf2); |
2101 g_free(html_buf); | |
8451 | 2102 |
9896 | 2103 return 1; |
2086 | 2104 } |
2105 | |
8644 | 2106 static const char *zephyr_normalize(const GaimAccount * account, const char *orig) |
2086 | 2107 { |
9328 | 2108 /* returns the string you gave it. Maybe this function shouldn't be here */ |
9896 | 2109 char * buf = g_malloc0(80); |
2110 /* gaim_debug_error("zephyr","entering zephyr_normalize\n"); */ | |
8644 | 2111 |
7126 | 2112 if (!g_ascii_strcasecmp(orig, "")) { |
2113 buf[0] = '\0'; | |
2114 return buf; | |
8354 | 2115 } else { |
8644 | 2116 g_snprintf(buf, 80, "%s", orig); |
2117 } | |
9896 | 2118 /* gaim_debug_error("zephyr","leaving zephyr_normalize\n"); */ |
2119 | |
8644 | 2120 return buf; |
8354 | 2121 } |
2122 | |
2123 | |
9896 | 2124 char *local_zephyr_normalize(zephyr_account *zephyr,const char *orig) |
8354 | 2125 { |
9328 | 2126 /* |
9912 | 2127 Basically the inverse of zephyr_strip_local_realm |
9896 | 2128 */ |
2129 char* buf; | |
2130 | |
8354 | 2131 if (!g_ascii_strcasecmp(orig, "")) { |
9896 | 2132 return g_strdup(""); |
7126 | 2133 } |
8644 | 2134 |
9896 | 2135 if (strchr(orig,'@')) { |
2136 buf = g_strdup_printf("%s",orig); | |
2086 | 2137 } else { |
9896 | 2138 buf = g_strdup_printf("%s@%s",orig,zephyr->realm); |
2139 } | |
2086 | 2140 return buf; |
2141 } | |
2142 | |
9030 | 2143 static void zephyr_zloc(GaimConnection *gc, const char *who) |
2086 | 2144 { |
2145 ZAsyncLocateData_t ald; | |
9896 | 2146 zephyr_account *zephyr = gc->proto_data; |
2147 gchar* normalized_who = local_zephyr_normalize(zephyr,who); | |
2148 | |
2149 if (use_zeph02(zephyr)) { | |
2150 if (ZRequestLocations(normalized_who, &ald, UNACKED, ZAUTH) == ZERR_NONE) { | |
2151 zephyr->pending_zloc_names = g_list_append(zephyr->pending_zloc_names, | |
2152 g_strdup(normalized_who)); | |
2153 } else { | |
2154 /* XXX deal with errors somehow */ | |
2155 } | |
2156 } else if (use_tzc(zephyr)) { | |
2157 char* zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n",normalized_who); | |
2158 zephyr->pending_zloc_names = g_list_append(zephyr->pending_zloc_names, g_strdup(normalized_who)); | |
2159 write(zephyr->totzc[ZEPHYR_FD_WRITE],zlocstr,strlen(zlocstr)); | |
2160 g_free(zlocstr); | |
2086 | 2161 } |
2162 } | |
2163 | |
9986 | 2164 static void zephyr_set_status(GaimAccount *account, GaimStatus *status) { |
2165 zephyr_account *zephyr = gaim_account_get_connection(account)->proto_data; | |
2166 const char *status_id = gaim_status_get_id(status); | |
2167 | |
2168 if (zephyr->away) { | |
2169 g_free(zephyr->away); | |
2170 zephyr->away=NULL; | |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
3867
diff
changeset
|
2171 } |
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
3867
diff
changeset
|
2172 |
9986 | 2173 if (!strcmp(status_id,"away")) { |
2174 zephyr->away = g_strdup(gaim_status_get_attr_string(status,"message")); | |
2175 } | |
2176 else if (!strcmp(status_id,"online")) { | |
2177 if (use_zeph02(zephyr)) { | |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2178 ZSetLocation(zephyr->exposure); |
9986 | 2179 } |
2180 else { | |
2181 char *zexpstr = g_strdup_printf("((tzcfodder . set-location) (hostname . \"%s\") (exposure . \"%s\"))\n",zephyr->ourhost,zephyr->exposure); | |
2182 write(zephyr->totzc[ZEPHYR_FD_WRITE],zexpstr,strlen(zexpstr)); | |
2183 g_free(zexpstr); | |
2184 } | |
2185 } | |
2186 else if (!strcmp(status_id,"hidden")) { | |
9478 | 2187 /* XXX handle errors */ |
9896 | 2188 if (use_zeph02(zephyr)) { |
2189 ZSetLocation(EXPOSE_OPSTAFF); | |
2190 } else { | |
2191 char *zexpstr = g_strdup_printf("((tzcfodder . set-location) (hostname . \"%s\") (exposure . \"%s\"))\n",zephyr->ourhost,EXPOSE_OPSTAFF); | |
2192 write(zephyr->totzc[ZEPHYR_FD_WRITE],zexpstr,strlen(zexpstr)); | |
2193 g_free(zexpstr); | |
2194 } | |
9478 | 2195 } |
2086 | 2196 } |
2197 | |
9986 | 2198 static GList *zephyr_status_types(GaimAccount *account) |
2086 | 2199 { |
9986 | 2200 GaimStatusType *type; |
2201 GList *types = NULL; | |
2202 | |
2203 /* zephyr has several exposures | |
2204 NONE (where you are hidden, and zephyrs to you are in practice silently dropped -- yes this is wrong) | |
2205 OPSTAFF "hidden" | |
2206 REALM-VISIBLE visible to people in local realm | |
2207 REALM-ANNOUNCED REALM-VISIBLE+ plus your logins/logouts are announced to <login,username,*> | |
2208 NET-VISIBLE REALM-ANNOUNCED, plus visible to people in foreign realm | |
2209 NET-ANNOUNCED NET-VISIBLE, plus logins/logouts are announced to <login,username,*> | |
2210 | |
2211 Online will set the user to the exposure they have in their options (defaulting to REALM-VISIBLE), | |
2212 Hidden, will set the user's exposure to OPSTAFF | |
2086 | 2213 |
9986 | 2214 Away won't change their exposure but will set an auto away message (for IMs only) |
2215 */ | |
2216 | |
2217 type = gaim_status_type_new(GAIM_STATUS_ONLINE, "online", _("Online"), FALSE); | |
2218 types = g_list_append(types,type); | |
2086 | 2219 |
9986 | 2220 type = gaim_status_type_new(GAIM_STATUS_HIDDEN, "hidden", _("Hidden"), FALSE); |
2221 types = g_list_append(types,type); | |
2222 | |
2223 type = gaim_status_type_new_with_attrs( | |
2224 GAIM_STATUS_AWAY, "away", _("Away"), TRUE, TRUE, FALSE, | |
10009 | 2225 "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); |
9986 | 2226 types = g_list_append(types, type); |
2227 | |
2228 return types; | |
2086 | 2229 } |
2230 | |
8644 | 2231 static GList *zephyr_chat_info(GaimConnection * gc) |
2232 { | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2233 GList *m = NULL; |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2234 struct proto_chat_entry *pce; |
2086 | 2235 |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2236 pce = g_new0(struct proto_chat_entry, 1); |
8644 | 2237 |
7841 | 2238 pce->label = _("_Class:"); |
5234 | 2239 pce->identifier = "class"; |
3158 | 2240 m = g_list_append(m, pce); |
2086 | 2241 |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2242 pce = g_new0(struct proto_chat_entry, 1); |
8644 | 2243 |
7841 | 2244 pce->label = _("_Instance:"); |
5234 | 2245 pce->identifier = "instance"; |
3158 | 2246 m = g_list_append(m, pce); |
2086 | 2247 |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2248 pce = g_new0(struct proto_chat_entry, 1); |
8644 | 2249 |
7841 | 2250 pce->label = _("_Recipient:"); |
5234 | 2251 pce->identifier = "recipient"; |
3158 | 2252 m = g_list_append(m, pce); |
2086 | 2253 |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2254 return m; |
2086 | 2255 } |
2256 | |
9478 | 2257 /* Called when the server notifies us a message couldn't get sent */ |
2258 | |
9896 | 2259 static void zephyr_subscribe_failed(GaimConnection *gc,char * z_class, char *z_instance, char * z_recipient, char* z_galaxy) |
9478 | 2260 { |
9896 | 2261 gchar* subscribe_failed = g_strdup_printf(_("Attempt to subscribe to %s,%s,%s failed"), z_class, z_instance,z_recipient); |
9610 | 2262 gaim_notify_error(gc,"", subscribe_failed, NULL); |
9478 | 2263 g_free(subscribe_failed); |
2264 } | |
2265 | |
9921 | 2266 static char *zephyr_get_chat_name(GHashTable *data) { |
9922 | 2267 gchar* zclass = g_hash_table_lookup(data,"class"); |
2268 gchar* inst = g_hash_table_lookup(data,"instance"); | |
2269 gchar* recipient = g_hash_table_lookup(data, "recipient"); | |
2270 if (!zclass) /* This should never happen */ | |
2271 zclass = ""; | |
2272 if (!inst) | |
2273 inst = "*"; | |
2274 if (!recipient) | |
2275 recipient = ""; | |
2276 return g_strdup_printf("%s,%s,%s",zclass,inst,recipient); | |
9917 | 2277 } |
2278 | |
9922 | 2279 |
8644 | 2280 static void zephyr_join_chat(GaimConnection * gc, GHashTable * data) |
2086 | 2281 { |
9896 | 2282 /* ZSubscription_t sub; */ |
2086 | 2283 zephyr_triple *zt1, *zt2; |
2284 const char *classname; | |
2285 const char *instname; | |
2286 const char *recip; | |
9896 | 2287 zephyr_account *zephyr=gc->proto_data; |
5234 | 2288 classname = g_hash_table_lookup(data, "class"); |
2289 instname = g_hash_table_lookup(data, "instance"); | |
2290 recip = g_hash_table_lookup(data, "recipient"); | |
2291 | |
9478 | 2292 |
9328 | 2293 if (!classname) |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2294 return; |
9478 | 2295 |
2296 if (!g_ascii_strcasecmp(classname,"%host%")) | |
9896 | 2297 classname = g_strdup(zephyr->ourhost); |
9478 | 2298 if (!g_ascii_strcasecmp(classname,"%canon%")) |
9896 | 2299 classname = g_strdup(zephyr->ourhostcanon); |
9478 | 2300 |
9328 | 2301 if (!instname || !strlen(instname)) |
2302 instname = "*"; | |
9478 | 2303 |
2304 if (!g_ascii_strcasecmp(instname,"%host%")) | |
9896 | 2305 instname = g_strdup(zephyr->ourhost); |
9478 | 2306 if (!g_ascii_strcasecmp(instname,"%canon%")) |
9896 | 2307 instname = g_strdup(zephyr->ourhostcanon); |
9478 | 2308 |
9328 | 2309 if (!recip || (*recip == '*')) |
2310 recip = ""; | |
4793 | 2311 if (!g_ascii_strcasecmp(recip, "%me%")) |
9896 | 2312 recip = zephyr->username; |
2086 | 2313 |
9610 | 2314 zt1 = new_triple(gc->proto_data,classname, instname, recip); |
2315 zt2 = find_sub_by_triple(gc->proto_data,zt1); | |
2086 | 2316 if (zt2) { |
2317 free_triple(zt1); | |
9328 | 2318 if (!zt2->open) { |
2319 if (!g_ascii_strcasecmp(instname,"*")) | |
2320 instname = "PERSONAL"; | |
9434 | 2321 serv_got_joined_chat(gc, zt2->id, zt2->name); |
9896 | 2322 zephyr_chat_set_topic(gc,zt2->id,instname); |
9328 | 2323 zt2->open = TRUE; |
2324 } | |
2086 | 2325 return; |
2326 } | |
9896 | 2327 |
2328 /* sub.zsub_class = zt1->class; | |
2329 sub.zsub_classinst = zt1->instance; | |
2330 sub.zsub_recipient = zt1->recipient; */ | |
2331 | |
2332 if (zephyr_subscribe_to(zephyr,zt1->class,zt1->instance,zt1->recipient,NULL) != ZERR_NONE) { | |
9478 | 2333 /* XXX output better subscription information */ |
9896 | 2334 zephyr_subscribe_failed(gc,zt1->class,zt1->instance,zt1->recipient,NULL); |
2086 | 2335 free_triple(zt1); |
2336 return; | |
2337 } | |
2338 | |
9610 | 2339 zephyr->subscrips = g_slist_append(zephyr->subscrips, zt1); |
2086 | 2340 zt1->open = TRUE; |
2341 serv_got_joined_chat(gc, zt1->id, zt1->name); | |
9328 | 2342 if (!g_ascii_strcasecmp(instname,"*")) |
2343 instname = "PERSONAL"; | |
9896 | 2344 zephyr_chat_set_topic(gc,zt1->id,instname); |
2086 | 2345 } |
2346 | |
8644 | 2347 static void zephyr_chat_leave(GaimConnection * gc, int id) |
2086 | 2348 { |
2349 zephyr_triple *zt; | |
9896 | 2350 zephyr_account *zephyr = gc->proto_data; |
9610 | 2351 zt = find_sub_by_id(zephyr,id); |
9896 | 2352 |
2086 | 2353 if (zt) { |
2354 zt->open = FALSE; | |
9610 | 2355 zt->id = ++(zephyr->last_id); |
2086 | 2356 } |
2357 } | |
2358 | |
9478 | 2359 static GaimChat *zephyr_find_blist_chat(GaimAccount *account, const char *name) |
2360 { | |
2361 GaimBlistNode *gnode, *cnode; | |
2362 | |
2363 /* XXX needs to be %host%,%canon%, and %me% clean */ | |
2364 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { | |
2365 for(cnode = gnode->child; cnode; cnode = cnode->next) { | |
2366 GaimChat *chat = (GaimChat*)cnode; | |
2367 char *zclass, *inst, *recip; | |
2368 char** triple; | |
2369 if(!GAIM_BLIST_NODE_IS_CHAT(cnode)) | |
2370 continue; | |
2371 if(chat->account !=account) | |
2372 continue; | |
2373 if(!(zclass = g_hash_table_lookup(chat->components, "class"))) | |
2374 continue; | |
2375 if(!(inst = g_hash_table_lookup(chat->components, "instance"))) | |
2376 inst = g_strdup(""); | |
2377 if(!(recip = g_hash_table_lookup(chat->components, "recipient"))) | |
2378 recip = g_strdup(""); | |
9896 | 2379 /* gaim_debug_info("zephyr","in zephyr_find_blist_chat name: %s\n",name?name:""); */ |
9478 | 2380 triple = g_strsplit(name,",",3); |
2381 if (!g_ascii_strcasecmp(triple[0],zclass) && !g_ascii_strcasecmp(triple[1],inst) && !g_ascii_strcasecmp(triple[2],recip)) | |
2382 return chat; | |
2383 | |
2384 } | |
2385 } | |
2386 return NULL; | |
2387 } | |
8644 | 2388 static const char *zephyr_list_icon(GaimAccount * a, GaimBuddy * b) |
5202 | 2389 { |
2390 return "zephyr"; | |
2391 } | |
2392 | |
9478 | 2393 static int zephyr_send_typing(GaimConnection *gc, const char *who, int typing) { |
2394 gchar *recipient; | |
9896 | 2395 zephyr_account *zephyr = gc->proto_data; |
2396 if (use_tzc(zephyr)) | |
2397 return 0; | |
2398 | |
9478 | 2399 if (!typing) |
2400 return 0; | |
2401 /* XXX We probably should care if this fails. Or maybe we don't want to */ | |
2402 if (!who) { | |
2403 gaim_debug_info("zephyr", "who is null\n"); | |
9896 | 2404 recipient = local_zephyr_normalize(zephyr,""); |
9478 | 2405 } else { |
9896 | 2406 /* Don't ping broadcast (chat) recipients */ |
2407 /* The strrchr case finds a realm-stripped broadcast subscription | |
2408 e.g. comma is the last character in the string */ | |
2409 if ((strrchr(who, ',') && ((strrchr(who, ',') == (who+strlen(who)-1)) || ((char *)(strrchr(who, ',')[1] == '@'))))) | |
2410 return 0; | |
2411 | |
2412 recipient = local_zephyr_normalize(zephyr,who); | |
9478 | 2413 } |
2414 | |
9896 | 2415 gaim_debug_info("zephyr","about to send typing notification to %s\n",recipient); |
2416 zephyr_send_message(zephyr,"MESSAGE","PERSONAL",recipient,"","","PING"); | |
2417 gaim_debug_info("zephyr","sent typing notification\n"); | |
9478 | 2418 return ZEPHYR_TYPING_SEND_TIMEOUT; |
2419 } | |
8212 | 2420 |
9434 | 2421 |
2422 | |
8644 | 2423 static void zephyr_chat_set_topic(GaimConnection * gc, int id, const char *topic) |
2424 { | |
2425 zephyr_triple *zt; | |
2426 GaimConversation *gconv; | |
2427 GaimConvChat *gcc; | |
9896 | 2428 gchar *topic_utf8; |
2429 zephyr_account* zephyr = gc->proto_data; | |
2430 char *sender = (char *)zephyr->username; | |
8212 | 2431 |
9610 | 2432 zt = find_sub_by_id(gc->proto_data,id); |
9986 | 2433 /* find_sub_by_id can return NULL */ |
2434 if (!zt) | |
2435 return; | |
9610 | 2436 gconv = gaim_find_conversation_with_account(zt->name, gc->account); |
8644 | 2437 gcc = gaim_conversation_get_chat_data(gconv); |
9434 | 2438 |
9896 | 2439 topic_utf8 = zephyr_recv_convert(gc,(gchar *)topic,strlen(topic)); |
2440 gaim_conv_chat_set_topic(gcc,sender,topic_utf8); | |
2441 g_free(topic_utf8); | |
2442 return; | |
9434 | 2443 } |
2444 | |
2445 /* commands */ | |
2446 | |
2447 static GaimCmdRet zephyr_gaim_cmd_msg(GaimConversation *conv, | |
9896 | 2448 const char *cmd, char **args, char **error, void *data) |
9434 | 2449 { |
9896 | 2450 char *recipient; |
2451 zephyr_account *zephyr = gaim_conversation_get_gc(conv)->proto_data; | |
2452 if (!g_ascii_strcasecmp(args[0],"*")) | |
2453 return GAIM_CMD_RET_FAILED; /* "*" is not a valid argument */ | |
2454 else | |
2455 recipient = local_zephyr_normalize(zephyr,args[0]); | |
9434 | 2456 |
9896 | 2457 if (strlen(recipient) < 1) |
2458 return GAIM_CMD_RET_FAILED; /* a null recipient is a chat message, not an IM */ | |
9478 | 2459 |
9896 | 2460 if (zephyr_send_message(zephyr,"MESSAGE","PERSONAL",recipient,args[1],zephyr_get_signature(),"")) |
2461 return GAIM_CMD_RET_OK; | |
2462 else | |
2463 return GAIM_CMD_RET_FAILED; | |
9434 | 2464 } |
2465 | |
2466 static GaimCmdRet zephyr_gaim_cmd_zlocate(GaimConversation *conv, | |
9896 | 2467 const char *cmd, char **args, char **error, void *data) |
9434 | 2468 { |
9896 | 2469 zephyr_zloc(gaim_conversation_get_gc(conv),args[0]); |
2470 return GAIM_CMD_RET_OK; | |
9434 | 2471 } |
2472 | |
2473 static GaimCmdRet zephyr_gaim_cmd_instance(GaimConversation *conv, | |
9896 | 2474 const char *cmd, char **args, char **error, void *data) |
9434 | 2475 { |
9896 | 2476 /* Currently it sets the instance with leading spaces and |
2477 * all. This might not be the best thing to do, though having | |
2478 * one word isn't ideal either. */ | |
9434 | 2479 |
9896 | 2480 GaimConvChat *gcc = gaim_conversation_get_chat_data(conv); |
2481 int id = gcc->id; | |
2482 const char* instance = args[0]; | |
2483 zephyr_chat_set_topic(gaim_conversation_get_gc(conv),id,instance); | |
2484 return GAIM_CMD_RET_OK; | |
9434 | 2485 } |
2486 | |
2487 static GaimCmdRet zephyr_gaim_cmd_joinchat_cir(GaimConversation *conv, | |
9896 | 2488 const char *cmd, char **args, char **error, void *data) |
9434 | 2489 { |
9896 | 2490 /* Join a new zephyr chat */ |
2491 GHashTable *triple = g_hash_table_new(NULL,NULL); | |
2492 g_hash_table_insert(triple,"class",args[0]); | |
2493 g_hash_table_insert(triple,"instance",args[1]); | |
2494 g_hash_table_insert(triple,"recipient",args[2]); | |
2495 zephyr_join_chat(gaim_conversation_get_gc(conv),triple); | |
2496 return GAIM_CMD_RET_OK; | |
9434 | 2497 } |
2498 | |
2499 static GaimCmdRet zephyr_gaim_cmd_zi(GaimConversation *conv, | |
9896 | 2500 const char *cmd, char **args, char **error, void *data) |
9434 | 2501 { |
9896 | 2502 /* args = instance, message */ |
2503 zephyr_account *zephyr = gaim_conversation_get_gc(conv)->proto_data; | |
2504 if ( zephyr_send_message(zephyr,"message",args[0],"",args[1],zephyr_get_signature(),"")) | |
2505 return GAIM_CMD_RET_OK; | |
2506 else | |
2507 return GAIM_CMD_RET_FAILED; | |
9434 | 2508 } |
2509 | |
2510 static GaimCmdRet zephyr_gaim_cmd_zci(GaimConversation *conv, | |
9896 | 2511 const char *cmd, char **args, char **error, void *data) |
9434 | 2512 { |
9896 | 2513 /* args = class, instance, message */ |
2514 zephyr_account *zephyr = gaim_conversation_get_gc(conv)->proto_data; | |
2515 if ( zephyr_send_message(zephyr,args[0],args[1],"",args[2],zephyr_get_signature(),"")) | |
2516 return GAIM_CMD_RET_OK; | |
2517 else | |
2518 return GAIM_CMD_RET_FAILED; | |
9434 | 2519 } |
8644 | 2520 |
9434 | 2521 static GaimCmdRet zephyr_gaim_cmd_zcir(GaimConversation *conv, |
9896 | 2522 const char *cmd, char **args, char **error, void *data) |
9434 | 2523 { |
9896 | 2524 /* args = class, instance, recipient, message */ |
2525 zephyr_account *zephyr = gaim_conversation_get_gc(conv)->proto_data; | |
2526 if ( zephyr_send_message(zephyr,args[0],args[1],args[2],args[3],zephyr_get_signature(),"")) | |
2527 return GAIM_CMD_RET_OK; | |
2528 else | |
2529 return GAIM_CMD_RET_FAILED; | |
8212 | 2530 } |
2531 | |
9434 | 2532 static GaimCmdRet zephyr_gaim_cmd_zir(GaimConversation *conv, |
9896 | 2533 const char *cmd, char **args, char **error, void *data) |
9434 | 2534 { |
9896 | 2535 /* args = instance, recipient, message */ |
2536 zephyr_account *zephyr = gaim_conversation_get_gc(conv)->proto_data; | |
2537 if ( zephyr_send_message(zephyr,"message",args[0],args[1],args[2],zephyr_get_signature(),"")) | |
2538 return GAIM_CMD_RET_OK; | |
2539 else | |
2540 return GAIM_CMD_RET_FAILED; | |
9434 | 2541 } |
2542 | |
2543 static GaimCmdRet zephyr_gaim_cmd_zc(GaimConversation *conv, | |
9896 | 2544 const char *cmd, char **args, char **error, void *data) |
9434 | 2545 { |
9896 | 2546 /* args = class, message */ |
2547 zephyr_account *zephyr = gaim_conversation_get_gc(conv)->proto_data; | |
2548 if ( zephyr_send_message(zephyr,args[0],"PERSONAL","",args[1],zephyr_get_signature(),"")) | |
2549 return GAIM_CMD_RET_OK; | |
2550 else | |
2551 return GAIM_CMD_RET_FAILED; | |
9434 | 2552 } |
2553 | |
9597 | 2554 static void zephyr_register_slash_commands() |
9434 | 2555 { |
2556 | |
9896 | 2557 gaim_cmd_register("msg","ws", GAIM_CMD_P_PRPL, |
2558 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2559 "prpl-zephyr", | |
2560 zephyr_gaim_cmd_msg, _("msg <nick> <message>: Send a private message to a user"), NULL); | |
9434 | 2561 |
9896 | 2562 gaim_cmd_register("zlocate","w", GAIM_CMD_P_PRPL, |
2563 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2564 "prpl-zephyr", | |
2565 zephyr_gaim_cmd_zlocate, _("zlocate <nick>: Locate user"), NULL); | |
9434 | 2566 |
9896 | 2567 gaim_cmd_register("zl","w", GAIM_CMD_P_PRPL, |
2568 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2569 "prpl-zephyr", | |
2570 zephyr_gaim_cmd_zlocate, _("zl <nick>: Locate user"), NULL); | |
9434 | 2571 |
9896 | 2572 gaim_cmd_register("instance","s", GAIM_CMD_P_PRPL, |
2573 GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2574 "prpl-zephyr", | |
2575 zephyr_gaim_cmd_instance, _("instance <instance>: Set the instance to be used on this class"), NULL); | |
9434 | 2576 |
9896 | 2577 gaim_cmd_register("inst","s", GAIM_CMD_P_PRPL, |
2578 GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2579 "prpl-zephyr", | |
2580 zephyr_gaim_cmd_instance, _("inst <instance>: Set the instance to be used on this class"), NULL); | |
9434 | 2581 |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2582 gaim_cmd_register("topic","s", GAIM_CMD_P_PRPL, |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2583 GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2584 "prpl-zephyr", |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2585 zephyr_gaim_cmd_instance, _("topic <instance>: Set the instance to be used on this class"), NULL); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2586 |
9896 | 2587 gaim_cmd_register("sub", "www", GAIM_CMD_P_PRPL, |
2588 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2589 "prpl-zephyr", | |
2590 zephyr_gaim_cmd_joinchat_cir, | |
2591 _("sub <class> <instance> <recipient>: Join a new chat"), NULL); | |
9434 | 2592 |
9896 | 2593 gaim_cmd_register("zi","ws", GAIM_CMD_P_PRPL, |
2594 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2595 "prpl-zephyr", | |
2596 zephyr_gaim_cmd_zi, _("zi <instance>: Send a message to <message,<i>instance</i>,*>"), NULL); | |
9434 | 2597 |
9896 | 2598 gaim_cmd_register("zci","wws",GAIM_CMD_P_PRPL, |
2599 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2600 "prpl-zephyr", | |
2601 zephyr_gaim_cmd_zci, | |
2602 _("zci <class> <instance>: Send a message to <<i>class</i>,<i>instance</i>,*>"), NULL); | |
9434 | 2603 |
9896 | 2604 gaim_cmd_register("zcir","wwws",GAIM_CMD_P_PRPL, |
2605 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2606 "prpl-zephyr", | |
2607 zephyr_gaim_cmd_zcir, | |
2608 _("zcir <class> <instance> <recipient>: Send a message to <<i>class</i>,<i>instance</i>,<i>recipient</i>>"), NULL); | |
9434 | 2609 |
9896 | 2610 gaim_cmd_register("zir","wws",GAIM_CMD_P_PRPL, |
2611 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2612 "prpl-zephyr", | |
2613 zephyr_gaim_cmd_zir, | |
2614 _("zir <instance> <recipient>: Send a message to <MESSAGE,<i>instance</i>,<i>recipient</i>>"), NULL); | |
9434 | 2615 |
9896 | 2616 gaim_cmd_register("zc","ws", GAIM_CMD_P_PRPL, |
2617 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, | |
2618 "prpl-zephyr", | |
2619 zephyr_gaim_cmd_zc, _("zc <class>: Send a message to <<i>class</i>,PERSONAL,*>"), NULL); | |
9597 | 2620 |
9434 | 2621 } |
2622 | |
2623 | |
9896 | 2624 static void |
2625 zephyr_add_deny(GaimConnection *gc, const char *who) | |
2626 { | |
2627 gaim_privacy_deny_add(gc->account,who,1); | |
2628 } | |
2629 | |
2630 static void | |
2631 zephyr_remove_deny(GaimConnection *gc, const char *who) | |
2632 { | |
2633 gaim_privacy_deny_remove(gc->account,who,1); | |
2634 } | |
2635 | |
2636 static void | |
2637 zephyr_add_permit(GaimConnection *gc, const char *who) | |
2638 { | |
2639 gaim_privacy_permit_add(gc->account,who,1); | |
2640 } | |
2641 | |
2642 static void | |
2643 zephyr_remove_permit(GaimConnection *gc, const char *who) | |
2644 { | |
2645 gaim_privacy_permit_remove(gc->account,who,1); | |
2646 } | |
2647 | |
2648 static void | |
2649 zephyr_set_permit_deny(GaimConnection *gc) | |
2650 { | |
2651 /* This doesn't have to do anything, since really, we can just check account->perm_deny when deciding whether to di */ | |
2652 return; | |
2653 } | |
9427 | 2654 static int zephyr_resubscribe(GaimConnection *gc) |
2655 { | |
9896 | 2656 /* Resubscribe to the in-memory list of subscriptions and also |
2657 unsubscriptions*/ | |
2658 zephyr_account *zephyr = gc->proto_data; | |
2659 GSList *s = zephyr->subscrips; | |
2660 zephyr_triple *zt; | |
2661 while (s) { | |
2662 zt = s->data; | |
2663 /* XXX We really should care if this fails */ | |
2664 zephyr_subscribe_to(zephyr,zt->class,zt->instance,zt->recipient,NULL); | |
2665 s = s->next; | |
2666 } | |
2667 /* XXX handle unsubscriptions */ | |
2668 return 1; | |
9427 | 2669 } |
2670 | |
9434 | 2671 |
9427 | 2672 static void zephyr_action_resubscribe(GaimPluginAction *action) |
2673 { | |
2674 | |
9896 | 2675 GaimConnection *gc = (GaimConnection *) action->context; |
2676 zephyr_resubscribe(gc); | |
9427 | 2677 } |
2678 | |
2679 | |
9478 | 2680 static void zephyr_action_get_subs_from_server(GaimPluginAction *action) |
2681 { | |
2682 GaimConnection *gc = (GaimConnection *) action->context; | |
9896 | 2683 zephyr_account *zephyr = gc->proto_data; |
9478 | 2684 gchar *title; |
2685 int retval, nsubs, one,i; | |
2686 ZSubscription_t subs; | |
9896 | 2687 if (use_zeph02(zephyr)) { |
2688 GString* subout = g_string_new("Subscription list<br>"); | |
2689 | |
2690 title = g_strdup_printf("Server subscriptions for %s", zephyr->username); | |
2691 | |
2692 if (zephyr->port == 0) { | |
2693 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "error while retrieving port"); | |
2694 return; | |
2695 } | |
2696 if ((retval = ZRetrieveSubscriptions(zephyr->port,&nsubs)) != ZERR_NONE) { | |
9478 | 2697 /* XXX better error handling */ |
9896 | 2698 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "error while retrieving subscriptions from server"); |
9478 | 2699 return; |
2700 } | |
9896 | 2701 for(i=0;i<nsubs;i++) { |
2702 one = 1; | |
2703 if ((retval = ZGetSubscriptions(&subs,&one)) != ZERR_NONE) { | |
2704 /* XXX better error handling */ | |
2705 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "error while retrieving individual subscription"); | |
2706 return; | |
2707 } | |
2708 g_string_append_printf(subout, "Class %s Instance %s Recipient %s<br>", | |
2709 subs.zsub_class, subs.zsub_classinst, | |
2710 subs.zsub_recipient); | |
2711 } | |
2712 gaim_notify_formatted(gc, title, title, NULL, subout->str, NULL, NULL); | |
2713 } else { | |
2714 /* XXX fix */ | |
2715 gaim_notify_error(gc,"","tzc doesn't support this action",NULL); | |
9478 | 2716 } |
2717 } | |
2718 | |
2719 | |
9427 | 2720 static GList *zephyr_actions(GaimPlugin *plugin, gpointer context) |
2721 { | |
2722 GList *list = NULL; | |
2723 GaimPluginAction *act = NULL; | |
2724 | |
2725 act = gaim_plugin_action_new(_("Resubscribe"), zephyr_action_resubscribe); | |
2726 list = g_list_append(list, act); | |
2727 | |
9478 | 2728 act = gaim_plugin_action_new(_("Retrieve subscriptions from server"), zephyr_action_get_subs_from_server); |
2729 list = g_list_append(list,act); | |
2730 | |
9427 | 2731 return list; |
2732 } | |
2733 | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2734 static GaimPlugin *my_protocol = NULL; |
2086 | 2735 |
8644 | 2736 static GaimPluginProtocolInfo prpl_info = { |
2737 OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD, | |
9478 | 2738 NULL, /* ??? user_splits */ |
2739 NULL, /* ??? protocol_options */ | |
2740 NO_BUDDY_ICONS, | |
2741 zephyr_list_icon, | |
2742 NULL, /* ??? list_emblems */ | |
2743 NULL, /* ??? status_text */ | |
2744 NULL, /* ??? tooltip_text */ | |
9986 | 2745 zephyr_status_types, /* status_types */ |
9478 | 2746 NULL, /* ??? blist_node_menu - probably all useful actions are already handled*/ |
9475 | 2747 zephyr_chat_info, /* chat_info */ |
9754 | 2748 NULL, /* chat_info_defaults */ |
9475 | 2749 zephyr_login, /* login */ |
2750 zephyr_close, /* close */ | |
2751 zephyr_send_im, /* send_im */ | |
9478 | 2752 NULL, /* XXX set info (Location?) */ |
2753 zephyr_send_typing, /* send_typing */ | |
9475 | 2754 zephyr_zloc, /* get_info */ |
9986 | 2755 zephyr_set_status, /* set_status */ |
9478 | 2756 NULL, /* ??? set idle */ |
2757 NULL, /* change password */ | |
9475 | 2758 NULL, /* add_buddy */ |
2759 NULL, /* add_buddies */ | |
2760 NULL, /* remove_buddy */ | |
2761 NULL, /* remove_buddies */ | |
9896 | 2762 zephyr_add_permit, /* add_permit */ |
2763 zephyr_add_deny, /* add_deny */ | |
2764 zephyr_remove_permit, /* remove_permit */ | |
2765 zephyr_remove_deny, /* remove_deny */ | |
2766 zephyr_set_permit_deny, /* set_permit_deny */ | |
2767 NULL, /* warn -- not supported in zephyr */ | |
2768 zephyr_join_chat, /* join_chat */ | |
2769 NULL, /* reject_chat -- No chat invites*/ | |
9917 | 2770 zephyr_get_chat_name, /* get_chat_name */ |
9896 | 2771 NULL, /* chat_invite -- No chat invites*/ |
2772 zephyr_chat_leave, /* chat_leave */ | |
2773 NULL, /* chat_whisper -- No "whispering"*/ | |
2774 zephyr_chat_send, /* chat_send */ | |
2775 NULL, /* keepalive -- Not necessary*/ | |
2776 NULL, /* register_user -- Not supported*/ | |
2777 NULL, /* XXX get_cb_info */ | |
9475 | 2778 NULL, /* get_cb_away */ |
2779 NULL, /* alias_buddy */ | |
2780 NULL, /* group_buddy */ | |
2781 NULL, /* rename_group */ | |
9896 | 2782 NULL, /* buddy_free */ |
9475 | 2783 NULL, /* convo_closed */ |
9896 | 2784 zephyr_normalize, /* normalize */ |
2785 NULL, /* XXX set_buddy_icon */ | |
9475 | 2786 NULL, /* remove_group */ |
9896 | 2787 NULL, /* XXX get_cb_real_name */ |
2788 zephyr_chat_set_topic, /* set_chat_topic */ | |
2789 zephyr_find_blist_chat, /* find_blist_chat */ | |
9475 | 2790 NULL, /* roomlist_get_list */ |
2791 NULL, /* roomlist_cancel */ | |
9896 | 2792 NULL, /* roomlist_expand_category */ |
9475 | 2793 NULL, /* can_receive_file */ |
2794 NULL /* send_file */ | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2795 }; |
2086 | 2796 |
8644 | 2797 static GaimPluginInfo info = { |
9943 | 2798 GAIM_PLUGIN_MAGIC, |
2799 GAIM_MAJOR_VERSION, | |
2800 GAIM_MINOR_VERSION, | |
9896 | 2801 GAIM_PLUGIN_PROTOCOL, /**< type */ |
8644 | 2802 NULL, /**< ui_requirement */ |
9896 | 2803 0, /**< flags */ |
8644 | 2804 NULL, /**< dependencies */ |
9896 | 2805 GAIM_PRIORITY_DEFAULT, /**< priority */ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2806 |
9896 | 2807 "prpl-zephyr", /**< id */ |
2808 "Zephyr", /**< name */ | |
2809 VERSION, /**< version */ | |
2810 /** summary */ | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2811 N_("Zephyr Protocol Plugin"), |
9896 | 2812 /** description */ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2813 N_("Zephyr Protocol Plugin"), |
9896 | 2814 NULL, /**< author */ |
2815 GAIM_WEBSITE, /**< homepage */ | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2816 |
9896 | 2817 NULL, /**< load */ |
2818 NULL, /**< unload */ | |
2819 NULL, /**< destroy */ | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2820 |
9896 | 2821 NULL, /**< ui_info */ |
8993 | 2822 &prpl_info, /**< extra_info */ |
2823 NULL, | |
9427 | 2824 zephyr_actions |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2825 }; |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2826 |
8644 | 2827 static void init_plugin(GaimPlugin * plugin) |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2828 { |
8212 | 2829 GaimAccountOption *option; |
8644 | 2830 char *tmp = get_exposure_level(); |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2831 |
9896 | 2832 option = gaim_account_option_bool_new("Use tzc", "use_tzc", FALSE); |
2833 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
2834 | |
2835 option = gaim_account_option_string_new("tzc command", "tzc_command", "/usr/bin/tzc -e %s"); | |
2836 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
2837 | |
8644 | 2838 option = gaim_account_option_bool_new(_("Export to .anyone"), "write_anyone", FALSE); |
2839 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
8212 | 2840 |
8644 | 2841 option = gaim_account_option_bool_new(_("Export to .zephyr.subs"), "write_zsubs", FALSE); |
2842 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
8212 | 2843 |
10038
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2844 option = gaim_account_option_bool_new(_("Import from .anyone"), "read_anyone", TRUE); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2845 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2846 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2847 option = gaim_account_option_bool_new(_("Import from .zephyr.subs"), "read_zsubs", TRUE); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2848 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2849 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2850 option = gaim_account_option_string_new(_("Realm"), "realm", ""); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2851 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2852 |
eb8ccdd6f5f2
[gaim-migrate @ 10997]
Luke Schierer <lschiere@pidgin.im>
parents:
10009
diff
changeset
|
2853 option = gaim_account_option_string_new(_("Exposure"), "exposure_level", tmp?tmp: EXPOSE_REALMVIS); |
8644 | 2854 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
8212 | 2855 |
8644 | 2856 option = gaim_account_option_string_new(_("Encoding"), "encoding", ZEPHYR_FALLBACK_CHARSET); |
2857 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
8560 | 2858 |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5202
diff
changeset
|
2859 my_protocol = plugin; |
9896 | 2860 zephyr_register_slash_commands(); |
2086 | 2861 } |
2862 | |
5920
7d385de2f9cd
[gaim-migrate @ 6360]
Christian Hammond <chipx86@chipx86.com>
parents:
5872
diff
changeset
|
2863 GAIM_INIT_PLUGIN(zephyr, init_plugin, info); |