Mercurial > pidgin
annotate src/protocols/yahoo/yahoo.c @ 10209:9e0b98c458b1
[gaim-migrate @ 11331]
gaim_notify_uri now needs trusted parameter to indicate whether
the source of the uri is trusted. This helps us avoid the security risks
involved in blindly executing untrusted local file URIs in windows. This
fixes the MSN open mail bug on windows.
committer: Tailor Script <tailor@pidgin.im>
author | Herman Bloggs <hermanator12002@yahoo.com> |
---|---|
date | Fri, 19 Nov 2004 20:18:14 +0000 |
parents | fa4973f356a1 |
children | 95ca0db2d01d |
rev | line source |
---|---|
2681 | 1 /* |
2 * gaim | |
3 * | |
8046 | 4 * Gaim is the legal property of its developers, whose names are too numerous |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
2681 | 7 * |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 * | |
22 */ | |
9369 | 23 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
24 #include "internal.h" |
2681 | 25 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
26 #include "account.h" |
5638
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5590
diff
changeset
|
27 #include "accountopt.h" |
6760 | 28 #include "blist.h" |
10119 | 29 #include "cmds.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
30 #include "debug.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
31 #include "notify.h" |
6760 | 32 #include "privacy.h" |
2681 | 33 #include "prpl.h" |
34 #include "proxy.h" | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
35 #include "request.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
36 #include "server.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
37 #include "util.h" |
9943 | 38 #include "version.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
39 |
6986 | 40 #include "sha.h" |
6513 | 41 #include "yahoo.h" |
9278 | 42 #include "yahoo_friend.h" |
6729 | 43 #include "yahoochat.h" |
9376 | 44 #include "ycht.h" |
8349 | 45 #include "yahoo_auth.h" |
7651 | 46 #include "yahoo_filexfer.h" |
9306 | 47 #include "yahoo_picture.h" |
3147 | 48 #include "md5.h" |
2681 | 49 |
5583 | 50 extern char *yahoo_crypt(const char *, const char *); |
2795
536bb833fdeb
[gaim-migrate @ 2808]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2786
diff
changeset
|
51 |
5493
3e8487580024
[gaim-migrate @ 5889]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
52 /* #define YAHOO_DEBUG */ |
2681 | 53 |
9285 | 54 static void yahoo_add_buddy(GaimConnection *gc, GaimBuddy *, GaimGroup *); |
9410 | 55 static void yahoo_login_page_cb(void *user_data, const char *buf, size_t len); |
9306 | 56 |
6784 | 57 |
6729 | 58 struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id) |
2681 | 59 { |
60 struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1); | |
61 | |
62 pkt->service = service; | |
63 pkt->status = status; | |
64 pkt->id = id; | |
65 | |
66 return pkt; | |
67 } | |
68 | |
6729 | 69 void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value) |
2681 | 70 { |
71 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); | |
72 pair->key = key; | |
73 pair->value = g_strdup(value); | |
74 pkt->hash = g_slist_append(pkt->hash, pair); | |
75 } | |
76 | |
7651 | 77 int yahoo_packet_length(struct yahoo_packet *pkt) |
2681 | 78 { |
79 GSList *l; | |
80 | |
81 int len = 0; | |
82 | |
83 l = pkt->hash; | |
84 while (l) { | |
85 struct yahoo_pair *pair = l->data; | |
86 int tmp = pair->key; | |
87 do { | |
88 tmp /= 10; | |
89 len++; | |
90 } while (tmp); | |
91 len += 2; | |
92 len += strlen(pair->value); | |
93 len += 2; | |
94 l = l->next; | |
95 } | |
96 | |
97 return len; | |
98 } | |
99 | |
100 static void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len) | |
101 { | |
102 int pos = 0; | |
103 | |
104 while (pos + 1 < len) { | |
6629 | 105 char key[64], *value = NULL, *esc; |
2724
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
106 int accept; |
2681 | 107 int x; |
108 | |
109 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); | |
110 | |
9329 | 111 /* this is weird, and in one of the chat packets, and causes us |
112 * think all the values are keys and all the keys are values after | |
113 * this point if we don't handle it */ | |
114 if (data[pos] == '\0') { | |
115 while (pos + 1 < len) { | |
116 if (data[pos] == 0xc0 && data[pos + 1] == 0x80) | |
117 break; | |
118 pos++; | |
119 } | |
120 pos += 2; | |
121 g_free(pair); | |
122 continue; | |
123 } | |
124 | |
2681 | 125 x = 0; |
126 while (pos + 1 < len) { | |
127 if (data[pos] == 0xc0 && data[pos + 1] == 0x80) | |
128 break; | |
8118 | 129 if (x >= sizeof(key)-1) { |
130 x++; | |
8357 | 131 pos++; |
8118 | 132 continue; |
133 } | |
2681 | 134 key[x++] = data[pos++]; |
135 } | |
8118 | 136 if (x >= sizeof(key)-1) { |
137 x = 0; | |
138 } | |
2681 | 139 key[x] = 0; |
140 pos += 2; | |
141 pair->key = strtol(key, NULL, 10); | |
2724
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
142 accept = x; /* if x is 0 there was no key, so don't accept it */ |
2681 | 143 |
3996
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
144 if (len - pos + 1 <= 0) { |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
145 /* Truncated. Garbage or something. */ |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
146 accept = 0; |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
147 } |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
148 |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
149 if (accept) { |
2724
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
150 value = g_malloc(len - pos + 1); |
3996
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
151 x = 0; |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
152 while (pos + 1 < len) { |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
153 if (data[pos] == 0xc0 && data[pos + 1] == 0x80) |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
154 break; |
2724
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
155 value[x++] = data[pos++]; |
3996
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
156 } |
2724
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
157 value[x] = 0; |
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
158 pair->value = g_strdup(value); |
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
159 g_free(value); |
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
160 pkt->hash = g_slist_append(pkt->hash, pair); |
6629 | 161 esc = g_strescape(pair->value, NULL); |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
162 gaim_debug(GAIM_DEBUG_MISC, "yahoo", |
6629 | 163 "Key: %d \tValue: %s\n", pair->key, esc); |
164 g_free(esc); | |
2724
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
165 } else { |
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
166 g_free(pair); |
7f3f4aa114ad
[gaim-migrate @ 2737]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2723
diff
changeset
|
167 } |
3996
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
168 pos += 2; |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
169 |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
170 /* Skip over garbage we've noticed in the mail notifications */ |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
171 if (data[0] == '9' && data[pos] == 0x01) |
3fdfe7872118
[gaim-migrate @ 4191]
Christian Hammond <chipx86@chipx86.com>
parents:
3768
diff
changeset
|
172 pos++; |
2681 | 173 } |
174 } | |
175 | |
7651 | 176 void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data) |
2681 | 177 { |
178 GSList *l = pkt->hash; | |
179 int pos = 0; | |
180 | |
181 while (l) { | |
182 struct yahoo_pair *pair = l->data; | |
183 guchar buf[100]; | |
184 | |
185 g_snprintf(buf, sizeof(buf), "%d", pair->key); | |
186 strcpy(data + pos, buf); | |
187 pos += strlen(buf); | |
188 data[pos++] = 0xc0; | |
189 data[pos++] = 0x80; | |
190 | |
191 strcpy(data + pos, pair->value); | |
192 pos += strlen(pair->value); | |
193 data[pos++] = 0xc0; | |
194 data[pos++] = 0x80; | |
195 | |
196 l = l->next; | |
197 } | |
198 } | |
199 | |
200 static void yahoo_packet_dump(guchar *data, int len) | |
201 { | |
202 #ifdef YAHOO_DEBUG | |
203 int i; | |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
204 |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
205 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
206 |
2681 | 207 for (i = 0; i + 1 < len; i += 2) { |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
208 if ((i % 16 == 0) && i) { |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
209 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
210 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
211 } |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
212 |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
213 gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x%02x ", data[i], data[i + 1]); |
2681 | 214 } |
215 if (i < len) | |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
216 gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x", data[i]); |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
217 |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
218 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
219 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
220 |
2681 | 221 for (i = 0; i < len; i++) { |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
222 if ((i % 16 == 0) && i) { |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
223 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
224 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
225 } |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
226 |
6686 | 227 if (g_ascii_isprint(data[i])) |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
228 gaim_debug(GAIM_DEBUG_MISC, NULL, "%c ", data[i]); |
2681 | 229 else |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
230 gaim_debug(GAIM_DEBUG_MISC, NULL, ". "); |
2681 | 231 } |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
232 |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
233 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); |
2681 | 234 #endif |
235 } | |
236 | |
6729 | 237 int yahoo_send_packet(struct yahoo_data *yd, struct yahoo_packet *pkt) |
2681 | 238 { |
239 int pktlen = yahoo_packet_length(pkt); | |
240 int len = YAHOO_PACKET_HDRLEN + pktlen; | |
241 int ret; | |
242 | |
243 guchar *data; | |
244 int pos = 0; | |
245 | |
246 if (yd->fd < 0) | |
247 return -1; | |
248 | |
249 data = g_malloc0(len + 1); | |
250 | |
251 memcpy(data + pos, "YMSG", 4); pos += 4; | |
9371 | 252 |
253 if (yd->wm) | |
254 pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER); | |
255 else | |
256 pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); | |
257 | |
2681 | 258 pos += yahoo_put16(data + pos, 0x0000); |
259 pos += yahoo_put16(data + pos, pktlen); | |
260 pos += yahoo_put16(data + pos, pkt->service); | |
261 pos += yahoo_put32(data + pos, pkt->status); | |
262 pos += yahoo_put32(data + pos, pkt->id); | |
263 | |
264 yahoo_packet_write(pkt, data + pos); | |
265 | |
266 yahoo_packet_dump(data, len); | |
267 ret = write(yd->fd, data, len); | |
9329 | 268 if (ret != len) |
269 gaim_debug_warning("yahoo", "Only wrote %d of %d bytes!", ret, len); | |
2681 | 270 g_free(data); |
271 | |
272 return ret; | |
273 } | |
274 | |
9306 | 275 int yahoo_send_packet_special(int fd, struct yahoo_packet *pkt, int pad) |
276 { | |
277 int pktlen = yahoo_packet_length(pkt); | |
278 int len = YAHOO_PACKET_HDRLEN + pktlen; | |
279 int ret; | |
280 | |
281 guchar *data; | |
282 int pos = 0; | |
283 | |
284 if (fd < 0) | |
285 return -1; | |
286 | |
287 data = g_malloc0(len + 1); | |
288 | |
289 memcpy(data + pos, "YMSG", 4); pos += 4; | |
9371 | 290 |
9306 | 291 pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); |
9371 | 292 |
9306 | 293 pos += yahoo_put16(data + pos, 0x0000); |
294 pos += yahoo_put16(data + pos, pktlen + pad); | |
295 pos += yahoo_put16(data + pos, pkt->service); | |
296 pos += yahoo_put32(data + pos, pkt->status); | |
297 pos += yahoo_put32(data + pos, pkt->id); | |
298 | |
299 yahoo_packet_write(pkt, data + pos); | |
300 | |
301 ret = write(fd, data, len); | |
302 g_free(data); | |
303 | |
304 return ret; | |
305 } | |
306 | |
6729 | 307 void yahoo_packet_free(struct yahoo_packet *pkt) |
2681 | 308 { |
309 while (pkt->hash) { | |
310 struct yahoo_pair *pair = pkt->hash->data; | |
311 g_free(pair->value); | |
312 g_free(pair); | |
313 pkt->hash = g_slist_remove(pkt->hash, pair); | |
314 } | |
315 g_free(pkt); | |
316 } | |
317 | |
9278 | 318 static void yahoo_update_status(GaimConnection *gc, const char *name, YahooFriend *f) |
6784 | 319 { |
9927 | 320 gboolean online = TRUE; |
9983 | 321 char *status = NULL; |
6840 | 322 |
6784 | 323 if (!gc || !name || !f || !gaim_find_buddy(gaim_connection_get_account(gc), name)) |
324 return; | |
325 | |
6840 | 326 if (f->status == YAHOO_STATUS_OFFLINE) |
9927 | 327 online = FALSE; |
6840 | 328 |
9983 | 329 switch (f->status) { |
330 case YAHOO_STATUS_AVAILABLE: | |
331 status = "available"; | |
332 break; | |
333 case YAHOO_STATUS_BRB: | |
334 status = "brb"; | |
335 break; | |
336 case YAHOO_STATUS_BUSY: | |
337 status = "busy"; | |
338 break; | |
339 case YAHOO_STATUS_NOTATHOME: | |
340 status = "notathome"; | |
341 break; | |
342 case YAHOO_STATUS_NOTATDESK: | |
343 status = "notatdesk"; | |
344 break; | |
345 case YAHOO_STATUS_NOTINOFFICE: | |
346 status = "notinoffice"; | |
347 break; | |
348 case YAHOO_STATUS_ONPHONE: | |
349 status = "onphone"; | |
350 break; | |
351 case YAHOO_STATUS_ONVACATION: | |
352 status = "onvacation"; | |
353 break; | |
354 case YAHOO_STATUS_OUTTOLUNCH: | |
355 status = "outtolunch"; | |
356 break; | |
357 case YAHOO_STATUS_STEPPEDOUT: | |
358 status = "steppedout"; | |
359 break; | |
360 case YAHOO_STATUS_INVISIBLE: /* this should never happen? */ | |
361 status = "invisible"; | |
362 break; | |
363 case YAHOO_STATUS_CUSTOM: | |
364 if (!f->away) | |
365 status = "avaiablewm"; | |
366 else | |
367 status = "away"; | |
368 break; | |
10141 | 369 case YAHOO_STATUS_IDLE: |
9983 | 370 break; |
371 default: | |
372 gaim_debug_warning("yahoo", "Warning, unknown status %d\n", f->status); | |
373 break; | |
374 } | |
375 | |
376 if (status) { | |
377 if (f->status == YAHOO_STATUS_CUSTOM) | |
378 gaim_prpl_got_user_status(gaim_connection_get_account(gc), name, status, "message", | |
379 yahoo_friend_get_status_message(f), NULL); | |
380 else | |
381 gaim_prpl_got_user_status(gaim_connection_get_account(gc), name, status, NULL); | |
382 } | |
383 | |
10141 | 384 if (f->idle != 0) |
385 gaim_prpl_got_user_idle(gaim_connection_get_account(gc), name, TRUE, f->idle); | |
386 else | |
387 gaim_prpl_got_user_idle(gaim_connection_get_account(gc), name, FALSE, 0); | |
6784 | 388 } |
389 | |
5583 | 390 static void yahoo_process_status(GaimConnection *gc, struct yahoo_packet *pkt) |
2681 | 391 { |
9983 | 392 GaimAccount *account = gaim_connection_get_account(gc); |
2681 | 393 struct yahoo_data *yd = gc->proto_data; |
394 GSList *l = pkt->hash; | |
9278 | 395 YahooFriend *f = NULL; |
2681 | 396 char *name = NULL; |
6784 | 397 |
7892 | 398 if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { |
8383 | 399 gc->wants_to_die = TRUE; |
7892 | 400 gaim_connection_error(gc, _("You have been logged off as you have logged in on a different machine or device.")); |
401 return; | |
402 } | |
6686 | 403 |
2681 | 404 while (l) { |
405 struct yahoo_pair *pair = l->data; | |
406 | |
407 switch (pair->key) { | |
408 case 0: /* we won't actually do anything with this */ | |
409 break; | |
410 case 1: /* we don't get the full buddy list here. */ | |
2805
9b3c7d2a6e9a
[gaim-migrate @ 2818]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2795
diff
changeset
|
411 if (!yd->logged_in) { |
7664 | 412 gaim_connection_set_display_name(gc, pair->value); |
5583 | 413 gaim_connection_set_state(gc, GAIM_CONNECTED); |
2805
9b3c7d2a6e9a
[gaim-migrate @ 2818]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2795
diff
changeset
|
414 serv_finish_login(gc); |
9b3c7d2a6e9a
[gaim-migrate @ 2818]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2795
diff
changeset
|
415 yd->logged_in = TRUE; |
9306 | 416 if (yd->picture_upload_todo) { |
417 yahoo_buddy_icon_upload(gc, yd->picture_upload_todo); | |
418 yd->picture_upload_todo = NULL; | |
419 } | |
2681 | 420 |
3147 | 421 /* this requests the list. i have a feeling that this is very evil |
422 * | |
6686 | 423 * scs.yahoo.com sends you the list before this packet without it being |
3147 | 424 * requested |
425 * | |
426 * do_import(gc, NULL); | |
427 * newpkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YAHOO_STATUS_OFFLINE, 0); | |
428 * yahoo_send_packet(yd, newpkt); | |
429 * yahoo_packet_free(newpkt); | |
430 */ | |
431 | |
432 } | |
2681 | 433 break; |
434 case 8: /* how many online buddies we have */ | |
435 break; | |
436 case 7: /* the current buddy */ | |
437 name = pair->value; | |
9886 | 438 if (name && g_utf8_validate(name, -1, NULL)) |
439 f = yahoo_friend_find_or_new(gc, name); | |
9888 | 440 else { |
441 f = NULL; | |
442 name = NULL; | |
443 } | |
2681 | 444 break; |
445 case 10: /* state */ | |
6784 | 446 if (!f) |
447 break; | |
448 | |
449 f->status = strtol(pair->value, NULL, 10); | |
450 if ((f->status >= YAHOO_STATUS_BRB) && (f->status <= YAHOO_STATUS_STEPPEDOUT)) | |
451 f->away = 1; | |
452 else | |
453 f->away = 0; | |
10141 | 454 |
455 if (f->status == YAHOO_STATUS_IDLE) { | |
456 /* Idle may have already been set in a more precise way in case 137 */ | |
457 if (f->idle == 0) | |
458 f->idle = time(NULL); | |
459 } else | |
6804 | 460 f->idle = 0; |
10141 | 461 |
9283 | 462 if (f->status != YAHOO_STATUS_CUSTOM) |
463 yahoo_friend_set_status_message(f, NULL); | |
6847 | 464 |
465 f->sms = 0; | |
2681 | 466 break; |
467 case 19: /* custom message */ | |
9283 | 468 if (f) |
469 yahoo_friend_set_status_message(f, yahoo_string_decode(gc, pair->value, FALSE)); | |
2681 | 470 break; |
6686 | 471 case 11: /* this is the buddy's session id */ |
2681 | 472 break; |
473 case 17: /* in chat? */ | |
474 break; | |
6784 | 475 case 47: /* is custom status away or not? 2=idle*/ |
476 if (!f) | |
477 break; | |
8441 | 478 |
479 /* I have no idea what it means when this is | |
480 * set when someone's available, but it doesn't | |
481 * mean idle. */ | |
482 if (f->status == YAHOO_STATUS_AVAILABLE) | |
483 break; | |
10141 | 484 |
6784 | 485 f->away = strtol(pair->value, NULL, 10); |
10141 | 486 if (f->away == 2) { |
487 /* Idle may have already been set in a more precise way in case 137 */ | |
488 if (f->idle == 0) | |
489 f->idle = time(NULL); | |
490 } | |
491 | |
6686 | 492 break; |
6784 | 493 case 138: /* either we're not idle, or we are but won't say how long */ |
494 if (!f) | |
495 break; | |
496 | |
497 if (f->idle) | |
498 f->idle = -1; | |
499 break; | |
500 case 137: /* usually idle time in seconds, sometimes login time */ | |
501 if (!f) | |
502 break; | |
503 | |
504 if (f->status != YAHOO_STATUS_AVAILABLE) | |
505 f->idle = time(NULL) - strtol(pair->value, NULL, 10); | |
6686 | 506 break; |
507 case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ | |
6784 | 508 if (strtol(pair->value, NULL, 10) == 0) { |
509 if (f) | |
510 f->status = YAHOO_STATUS_OFFLINE; | |
9983 | 511 gaim_prpl_got_user_status(account, name, "offline", NULL); |
2807
f01e6a425136
[gaim-migrate @ 2820]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2805
diff
changeset
|
512 break; |
2805
9b3c7d2a6e9a
[gaim-migrate @ 2818]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2795
diff
changeset
|
513 } |
6784 | 514 |
515 if (f) | |
516 yahoo_update_status(gc, name, f); | |
517 break; | |
518 case 60: /* SMS */ | |
519 if (f) { | |
520 f->sms = strtol(pair->value, NULL, 10); | |
521 yahoo_update_status(gc, name, f); | |
2771
450f4f9d2f23
[gaim-migrate @ 2784]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2741
diff
changeset
|
522 } |
450f4f9d2f23
[gaim-migrate @ 2784]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2741
diff
changeset
|
523 break; |
9292 | 524 case 197: /* Avatars */ |
9277 | 525 { |
526 char *decoded, *tmp; | |
527 guint len; | |
528 | |
529 if (pair->value) { | |
530 gaim_base64_decode(pair->value, &decoded, &len); | |
531 if (len) { | |
532 tmp = gaim_str_binary_to_ascii(decoded, len); | |
533 gaim_debug_info("yahoo", "Got key 197, value = %s\n", tmp); | |
534 g_free(tmp); | |
535 } | |
536 g_free(decoded); | |
537 } | |
538 break; | |
539 } | |
9292 | 540 case 192: /* Pictures, aka Buddy Icons, checksum */ |
541 { | |
542 int cksum = strtol(pair->value, NULL, 10); | |
543 GaimBuddy *b; | |
544 | |
545 if (!name) | |
546 break; | |
547 | |
9325 | 548 b = gaim_find_buddy(gc->account, name); |
549 | |
9292 | 550 if (!cksum || (cksum == -1)) { |
9325 | 551 if (f) |
552 yahoo_friend_set_buddy_icon_need_request(f, TRUE); | |
9292 | 553 gaim_buddy_icons_set_for_user(gc->account, name, NULL, 0); |
9325 | 554 if (b) |
555 gaim_blist_node_remove_setting((GaimBlistNode *)b, YAHOO_ICON_CHECKSUM_KEY); | |
9292 | 556 break; |
557 } | |
558 | |
559 if (!f) | |
560 break; | |
9325 | 561 |
9292 | 562 yahoo_friend_set_buddy_icon_need_request(f, FALSE); |
563 if (cksum != gaim_blist_node_get_int((GaimBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY)) | |
9310 | 564 yahoo_send_picture_request(gc, name); |
9292 | 565 |
566 break; | |
567 } | |
2979 | 568 case 16: /* Custom error message */ |
7827 | 569 { |
570 char *tmp = yahoo_string_decode(gc, pair->value, TRUE); | |
571 gaim_notify_error(gc, NULL, tmp, NULL); | |
572 g_free(tmp); | |
573 } | |
2951 | 574 break; |
2681 | 575 default: |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
576 gaim_debug(GAIM_DEBUG_ERROR, "yahoo", |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
577 "Unknown status key %d\n", pair->key); |
2681 | 578 break; |
579 } | |
580 | |
581 l = l->next; | |
582 } | |
583 } | |
584 | |
9285 | 585 static void yahoo_do_group_check(GaimAccount *account, GHashTable *ht, const char *name, const char *group) |
6820 | 586 { |
587 GaimBuddy *b; | |
588 GaimGroup *g; | |
589 GSList *list, *i; | |
590 gboolean onlist = 0; | |
591 char *oname = NULL; | |
592 | |
9015 | 593 char **oname_p = &oname; |
594 GSList **list_p = &list; | |
595 | |
596 if (!g_hash_table_lookup_extended(ht, gaim_normalize(account, name), (gpointer *) oname_p, (gpointer *) list_p)) | |
6820 | 597 list = gaim_find_buddies(account, name); |
598 else | |
599 g_hash_table_steal(ht, name); | |
600 | |
601 for (i = list; i; i = i->next) { | |
602 b = i->data; | |
603 g = gaim_find_buddys_group(b); | |
604 if (!gaim_utf8_strcasecmp(group, g->name)) { | |
605 gaim_debug(GAIM_DEBUG_MISC, "yahoo", | |
606 "Oh good, %s is in the right group (%s).\n", name, group); | |
607 list = g_slist_delete_link(list, i); | |
608 onlist = 1; | |
609 break; | |
610 } | |
611 } | |
612 | |
613 if (!onlist) { | |
614 gaim_debug(GAIM_DEBUG_MISC, "yahoo", | |
615 "Uhoh, %s isn't on the list (or not in this group), adding him to group %s.\n", name, group); | |
616 if (!(g = gaim_find_group(group))) { | |
617 g = gaim_group_new(group); | |
618 gaim_blist_add_group(g, NULL); | |
619 } | |
620 b = gaim_buddy_new(account, name, NULL); | |
621 gaim_blist_add_buddy(b, NULL, g, NULL); | |
622 } | |
623 | |
624 if (list) { | |
625 if (!oname) | |
7823 | 626 oname = g_strdup(gaim_normalize(account, name)); |
6820 | 627 g_hash_table_insert(ht, oname, list); |
628 } else if (oname) | |
629 g_free(oname); | |
630 } | |
631 | |
632 static void yahoo_do_group_cleanup(gpointer key, gpointer value, gpointer user_data) | |
633 { | |
634 char *name = key; | |
635 GSList *list = value, *i; | |
636 GaimBuddy *b; | |
637 GaimGroup *g; | |
638 | |
639 for (i = list; i; i = i->next) { | |
640 b = i->data; | |
641 g = gaim_find_buddys_group(b); | |
642 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "Deleting Buddy %s from group %s.\n", name, g->name); | |
643 gaim_blist_remove_buddy(b); | |
644 } | |
645 } | |
646 | |
7651 | 647 static char *_getcookie(char *rawcookie) |
648 { | |
649 char *cookie = NULL; | |
650 char *tmpcookie; | |
651 char *cookieend; | |
652 | |
653 if (strlen(rawcookie) < 2) | |
654 return NULL; | |
655 tmpcookie = g_strdup(rawcookie+2); | |
656 cookieend = strchr(tmpcookie, ';'); | |
657 | |
658 if (cookieend) | |
659 *cookieend = '\0'; | |
660 | |
661 cookie = g_strdup(tmpcookie); | |
662 g_free(tmpcookie); | |
663 | |
664 return cookie; | |
665 } | |
666 | |
667 static void yahoo_process_cookie(struct yahoo_data *yd, char *c) | |
668 { | |
669 if (c[0] == 'Y') { | |
670 if (yd->cookie_y) | |
671 g_free(yd->cookie_y); | |
672 yd->cookie_y = _getcookie(c); | |
673 } else if (c[0] == 'T') { | |
674 if (yd->cookie_t) | |
675 g_free(yd->cookie_t); | |
676 yd->cookie_t = _getcookie(c); | |
677 } | |
678 } | |
679 | |
5583 | 680 static void yahoo_process_list(GaimConnection *gc, struct yahoo_packet *pkt) |
2681 | 681 { |
682 GSList *l = pkt->hash; | |
683 gboolean export = FALSE; | |
6760 | 684 gboolean got_serv_list = FALSE; |
6695 | 685 GaimBuddy *b; |
686 GaimGroup *g; | |
9278 | 687 YahooFriend *f = NULL; |
6820 | 688 GaimAccount *account = gaim_connection_get_account(gc); |
6784 | 689 struct yahoo_data *yd = gc->proto_data; |
6820 | 690 GHashTable *ht; |
6784 | 691 |
692 char **lines; | |
693 char **split; | |
694 char **buddies; | |
7823 | 695 char **tmp, **bud, *norm_bud; |
7827 | 696 char *grp = NULL; |
2681 | 697 |
7651 | 698 if (pkt->id) |
699 yd->session_id = pkt->id; | |
700 | |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
701 while (l) { |
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
702 struct yahoo_pair *pair = l->data; |
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
703 l = l->next; |
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
704 |
6760 | 705 switch (pair->key) { |
706 case 87: | |
6784 | 707 if (!yd->tmp_serv_blist) |
708 yd->tmp_serv_blist = g_string_new(pair->value); | |
709 else | |
710 g_string_append(yd->tmp_serv_blist, pair->value); | |
6760 | 711 break; |
712 case 88: | |
6784 | 713 if (!yd->tmp_serv_ilist) |
714 yd->tmp_serv_ilist = g_string_new(pair->value); | |
715 else | |
716 g_string_append(yd->tmp_serv_ilist, pair->value); | |
6760 | 717 break; |
7651 | 718 case 59: /* cookies, yum */ |
719 yahoo_process_cookie(yd, pair->value); | |
720 break; | |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
721 } |
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
722 } |
2681 | 723 |
6784 | 724 if (pkt->status != 0) |
725 return; | |
726 | |
727 if (yd->tmp_serv_blist) { | |
6820 | 728 ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free); |
729 | |
6784 | 730 lines = g_strsplit(yd->tmp_serv_blist->str, "\n", -1); |
731 for (tmp = lines; *tmp; tmp++) { | |
732 split = g_strsplit(*tmp, ":", 2); | |
733 if (!split) | |
734 continue; | |
735 if (!split[0] || !split[1]) { | |
736 g_strfreev(split); | |
737 continue; | |
738 } | |
7827 | 739 grp = yahoo_string_decode(gc, split[0], FALSE); |
6784 | 740 buddies = g_strsplit(split[1], ",", -1); |
741 for (bud = buddies; bud && *bud; bud++) { | |
7823 | 742 norm_bud = g_strdup(gaim_normalize(account, *bud)); |
9279 | 743 f = yahoo_friend_find_or_new(gc, norm_bud); |
744 | |
7827 | 745 if (!(b = gaim_find_buddy(account, norm_bud))) { |
746 if (!(g = gaim_find_group(grp))) { | |
747 g = gaim_group_new(grp); | |
6784 | 748 gaim_blist_add_group(g, NULL); |
749 } | |
7823 | 750 b = gaim_buddy_new(account, norm_bud, NULL); |
6784 | 751 gaim_blist_add_buddy(b, NULL, g, NULL); |
752 export = TRUE; | |
6820 | 753 } |
6784 | 754 |
9285 | 755 yahoo_do_group_check(account, ht, norm_bud, grp); |
7823 | 756 g_free(norm_bud); |
6784 | 757 } |
758 g_strfreev(buddies); | |
759 g_strfreev(split); | |
7827 | 760 g_free(grp); |
6784 | 761 } |
762 g_strfreev(lines); | |
763 | |
764 g_string_free(yd->tmp_serv_blist, TRUE); | |
765 yd->tmp_serv_blist = NULL; | |
9285 | 766 g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL); |
6820 | 767 g_hash_table_destroy(ht); |
6784 | 768 } |
769 | |
770 | |
771 if (yd->tmp_serv_ilist) { | |
772 buddies = g_strsplit(yd->tmp_serv_ilist->str, ",", -1); | |
773 for (bud = buddies; bud && *bud; bud++) { | |
774 /* The server is already ignoring the user */ | |
775 got_serv_list = TRUE; | |
776 gaim_privacy_deny_add(gc->account, *bud, 1); | |
777 } | |
778 g_strfreev(buddies); | |
779 | |
780 g_string_free(yd->tmp_serv_ilist, TRUE); | |
781 yd->tmp_serv_ilist = NULL; | |
782 } | |
783 | |
784 if (got_serv_list) { | |
785 gc->account->perm_deny = 4; | |
786 serv_set_permit_deny(gc); | |
787 } | |
2681 | 788 } |
789 | |
5583 | 790 static void yahoo_process_notify(GaimConnection *gc, struct yahoo_packet *pkt) |
2993 | 791 { |
792 char *msg = NULL; | |
793 char *from = NULL; | |
3019 | 794 char *stat = NULL; |
795 char *game = NULL; | |
9278 | 796 YahooFriend *f = NULL; |
2993 | 797 GSList *l = pkt->hash; |
6784 | 798 |
2993 | 799 while (l) { |
800 struct yahoo_pair *pair = l->data; | |
801 if (pair->key == 4) | |
802 from = pair->value; | |
803 if (pair->key == 49) | |
804 msg = pair->value; | |
3001 | 805 if (pair->key == 13) |
3019 | 806 stat = pair->value; |
807 if (pair->key == 14) | |
808 game = pair->value; | |
2993 | 809 l = l->next; |
810 } | |
3640 | 811 |
6784 | 812 if (!from || !msg) |
3640 | 813 return; |
6686 | 814 |
4793 | 815 if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING"))) { |
3019 | 816 if (*stat == '1') |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
817 serv_got_typing(gc, from, 0, GAIM_TYPING); |
3019 | 818 else |
819 serv_got_typing_stopped(gc, from); | |
4793 | 820 } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) { |
6695 | 821 GaimBuddy *bud = gaim_find_buddy(gc->account, from); |
6784 | 822 |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
823 if (!bud) { |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
824 gaim_debug(GAIM_DEBUG_WARNING, "yahoo", |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
825 "%s is playing a game, and doesn't want " |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
826 "you to know.\n", from); |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
827 } |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
828 |
9279 | 829 f = yahoo_friend_find(gc, from); |
6784 | 830 if (!f) |
831 return; /* if they're not on the list, don't bother */ | |
832 | |
9283 | 833 yahoo_friend_set_game(f, NULL); |
6784 | 834 |
3019 | 835 if (*stat == '1') { |
9283 | 836 yahoo_friend_set_game(f, game); |
3020 | 837 if (bud) |
6784 | 838 yahoo_update_status(gc, from, f); |
3019 | 839 } |
840 } | |
2993 | 841 } |
842 | |
7827 | 843 |
844 struct _yahoo_im { | |
845 char *from; | |
846 int time; | |
847 int utf8; | |
9284 | 848 int buddy_icon; |
7827 | 849 char *msg; |
850 }; | |
851 | |
5583 | 852 static void yahoo_process_message(GaimConnection *gc, struct yahoo_packet *pkt) |
2681 | 853 { |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
854 GSList *l = pkt->hash; |
7827 | 855 GSList *list = NULL; |
856 struct _yahoo_im *im = NULL; | |
6069 | 857 |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
858 if (pkt->status <= 1 || pkt->status == 5) { |
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
859 while (l) { |
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
860 struct yahoo_pair *pair = l->data; |
7827 | 861 if (pair->key == 4) { |
862 im = g_new0(struct _yahoo_im, 1); | |
863 list = g_slist_append(list, im); | |
864 im->from = pair->value; | |
865 im->time = time(NULL); | |
866 } | |
867 if (pair->key == 97) | |
868 if (im) | |
869 im->utf8 = strtol(pair->value, NULL, 10); | |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
870 if (pair->key == 15) |
7827 | 871 if (im) |
872 im->time = strtol(pair->value, NULL, 10); | |
9284 | 873 if (pair->key == 206) |
874 if (im) | |
875 im->buddy_icon = strtol(pair->value, NULL, 10); | |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
876 if (pair->key == 14) { |
7827 | 877 if (im) |
878 im->msg = pair->value; | |
6687 | 879 } |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
880 l = l->next; |
6687 | 881 } |
2681 | 882 } else if (pkt->status == 2) { |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5367
diff
changeset
|
883 gaim_notify_error(gc, NULL, |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5367
diff
changeset
|
884 _("Your Yahoo! message did not get sent."), NULL); |
2681 | 885 } |
7827 | 886 |
887 for (l = list; l; l = l->next) { | |
9306 | 888 YahooFriend *f; |
7827 | 889 char *m, *m2; |
890 im = l->data; | |
891 | |
892 if (!im->from || !im->msg) { | |
893 g_free(im); | |
894 continue; | |
895 } | |
896 | |
897 m = yahoo_string_decode(gc, im->msg, im->utf8); | |
898 gaim_str_strip_cr(m); | |
8375 | 899 |
900 if (!strcmp(m, "<ding>")) { | |
901 GaimConversation *c = gaim_conversation_new(GAIM_CONV_IM, | |
902 gaim_connection_get_account(gc), im->from); | |
903 gaim_conv_im_write(GAIM_CONV_IM(c), "", _("Buzz!!"), GAIM_MESSAGE_NICK|GAIM_MESSAGE_RECV, | |
904 im->time); | |
905 g_free(m); | |
906 g_free(im); | |
907 continue; | |
908 } | |
909 | |
7827 | 910 m2 = yahoo_codes_to_html(m); |
911 g_free(m); | |
912 serv_got_im(gc, im->from, m2, 0, im->time); | |
913 g_free(m2); | |
9284 | 914 |
915 if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) { | |
916 if (yahoo_friend_get_buddy_icon_need_request(f)) { | |
9310 | 917 yahoo_send_picture_request(gc, im->from); |
9284 | 918 yahoo_friend_set_buddy_icon_need_request(f, FALSE); |
919 } | |
920 } | |
921 | |
7827 | 922 g_free(im); |
923 } | |
924 g_slist_free(list); | |
2681 | 925 } |
926 | |
7865 | 927 static void yahoo_process_sysmessage(GaimConnection *gc, struct yahoo_packet *pkt) |
928 { | |
929 GSList *l = pkt->hash; | |
10070 | 930 char *prim, *me = NULL, *msg = NULL, *escmsg = NULL; |
7865 | 931 |
932 while (l) { | |
933 struct yahoo_pair *pair = l->data; | |
934 | |
935 if (pair->key == 5) | |
936 me = pair->value; | |
937 if (pair->key == 14) | |
938 msg = pair->value; | |
939 | |
940 l = l->next; | |
941 } | |
942 | |
10070 | 943 if (!msg || !g_utf8_validate(msg, -1, NULL)) |
7865 | 944 return; |
945 | |
10070 | 946 escmsg = gaim_escape_html(msg); |
947 | |
7865 | 948 prim = g_strdup_printf(_("Yahoo! system message for %s:"), |
949 me?me:gaim_connection_get_display_name(gc)); | |
10070 | 950 gaim_notify_info(NULL, NULL, prim, escmsg); |
7865 | 951 g_free(prim); |
10070 | 952 g_free(escmsg); |
7865 | 953 } |
954 | |
6686 | 955 static void yahoo_buddy_added_us(GaimConnection *gc, struct yahoo_packet *pkt) { |
2681 | 956 char *id = NULL; |
957 char *who = NULL; | |
7827 | 958 char *msg = NULL, *tmpmsg = NULL; |
2681 | 959 GSList *l = pkt->hash; |
960 | |
961 while (l) { | |
962 struct yahoo_pair *pair = l->data; | |
6686 | 963 |
964 switch (pair->key) { | |
965 case 1: | |
2681 | 966 id = pair->value; |
6686 | 967 break; |
968 case 3: | |
2681 | 969 who = pair->value; |
6686 | 970 break; |
971 case 15: /* time, for when they add us and we're offline */ | |
972 break; | |
973 case 14: | |
2681 | 974 msg = pair->value; |
6686 | 975 break; |
976 } | |
2681 | 977 l = l->next; |
978 } | |
979 | |
7827 | 980 if (id) { |
981 if (msg) | |
982 tmpmsg = yahoo_string_decode(gc, msg, FALSE); | |
983 gaim_account_notify_added(gc->account, id, who, NULL, tmpmsg); | |
984 if (tmpmsg) | |
985 g_free(tmpmsg); | |
986 } | |
6686 | 987 } |
988 | |
989 static void yahoo_buddy_denied_our_add(GaimConnection *gc, struct yahoo_packet *pkt) | |
990 { | |
991 char *who = NULL; | |
992 char *msg = NULL; | |
993 GSList *l = pkt->hash; | |
994 GString *buf = NULL; | |
6784 | 995 struct yahoo_data *yd = gc->proto_data; |
6686 | 996 |
997 while (l) { | |
998 struct yahoo_pair *pair = l->data; | |
999 | |
1000 switch (pair->key) { | |
1001 case 3: | |
1002 who = pair->value; | |
1003 break; | |
1004 case 14: | |
1005 msg = pair->value; | |
1006 break; | |
1007 } | |
1008 l = l->next; | |
1009 } | |
1010 | |
1011 if (who) { | |
7827 | 1012 char *msg2; |
6686 | 1013 buf = g_string_sized_new(0); |
7827 | 1014 if (!msg) { |
6686 | 1015 g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list."), who); |
7827 | 1016 } else { |
1017 msg2 = yahoo_string_decode(gc, msg, FALSE); | |
1018 g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2); | |
1019 g_free(msg2); | |
1020 } | |
6840 | 1021 gaim_notify_info(gc, NULL, _("Add buddy rejected"), buf->str); |
6686 | 1022 g_string_free(buf, TRUE); |
6784 | 1023 g_hash_table_remove(yd->friends, who); |
9983 | 1024 gaim_prpl_got_user_status(gaim_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */ |
6686 | 1025 } |
1026 } | |
1027 | |
1028 static void yahoo_process_contact(GaimConnection *gc, struct yahoo_packet *pkt) | |
1029 { | |
1030 | |
1031 | |
1032 switch (pkt->status) { | |
1033 case 1: | |
1034 yahoo_process_status(gc, pkt); | |
1035 return; | |
1036 case 3: | |
1037 yahoo_buddy_added_us(gc, pkt); | |
1038 break; | |
1039 case 7: | |
1040 yahoo_buddy_denied_our_add(gc, pkt); | |
1041 break; | |
1042 default: | |
1043 break; | |
2683
4836eae8dd8c
[gaim-migrate @ 2696]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2682
diff
changeset
|
1044 } |
2681 | 1045 } |
1046 | |
7747 | 1047 #define OUT_CHARSET "utf-8" |
1048 | |
1049 static char *yahoo_decode(const char *text) | |
1050 { | |
9221 | 1051 char *converted = NULL; |
8125 | 1052 char *n, *new; |
1053 const char *end, *p; | |
8616 | 1054 int i, k; |
8125 | 1055 |
7771 | 1056 n = new = g_malloc(strlen (text) + 1); |
8118 | 1057 end = text + strlen(text); |
1058 | |
8125 | 1059 for (p = text; p < end; p++, n++) { |
7747 | 1060 if (*p == '\\') { |
9064 | 1061 if (p[1] >= '0' && p[1] <= '7') { |
1062 p += 1; | |
1063 for (i = 0, k = 0; k < 3; k += 1) { | |
1064 char c = p[k]; | |
9065 | 1065 if (c < '0' || c > '7') break; |
9064 | 1066 i *= 8; |
1067 i += c - '0'; | |
1068 } | |
1069 *n = i; | |
1070 p += k - 1; | |
1071 } else { /* bug 959248 */ | |
1072 /* If we see a \ not followed by an octal number, | |
1073 * it means that it is actually a \\ with one \ | |
1074 * already eaten by some unknown function. | |
1075 * This is arguably broken. | |
1076 * | |
1077 * I think wing is wrong here, there is no function | |
1078 * called that I see that could have done it. I guess | |
1079 * it is just really sending single \'s. That's yahoo | |
1080 * for you. | |
1081 */ | |
1082 *n = *p; | |
1083 } | |
7747 | 1084 } |
1085 else | |
1086 *n = *p; | |
1087 } | |
1088 | |
1089 *n = '\0'; | |
8125 | 1090 |
9221 | 1091 if (strstr(text, "\033$B")) |
1092 converted = g_convert(new, n - new, OUT_CHARSET, "iso-2022-jp", NULL, NULL, NULL); | |
1093 if (!converted) | |
1094 converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL); | |
7747 | 1095 g_free(new); |
1096 | |
1097 return converted; | |
1098 } | |
1099 | |
5583 | 1100 static void yahoo_process_mail(GaimConnection *gc, struct yahoo_packet *pkt) |
2681 | 1101 { |
5583 | 1102 GaimAccount *account = gaim_connection_get_account(gc); |
9221 | 1103 struct yahoo_data *yd = gc->proto_data; |
2681 | 1104 char *who = NULL; |
1105 char *email = NULL; | |
1106 char *subj = NULL; | |
9221 | 1107 char *yahoo_mail_url = (yd->jp? YAHOOJP_MAIL_URL: YAHOO_MAIL_URL); |
2681 | 1108 int count = 0; |
1109 GSList *l = pkt->hash; | |
1110 | |
5583 | 1111 if (!gaim_account_get_check_mail(account)) |
5521
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1112 return; |
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1113 |
2681 | 1114 while (l) { |
1115 struct yahoo_pair *pair = l->data; | |
1116 if (pair->key == 9) | |
1117 count = strtol(pair->value, NULL, 10); | |
1118 else if (pair->key == 43) | |
1119 who = pair->value; | |
1120 else if (pair->key == 42) | |
1121 email = pair->value; | |
1122 else if (pair->key == 18) | |
1123 subj = pair->value; | |
1124 l = l->next; | |
1125 } | |
1126 | |
4001 | 1127 if (who && subj && email && *email) { |
7747 | 1128 char *dec_who = yahoo_decode(who); |
1129 char *dec_subj = yahoo_decode(subj); | |
1130 char *from = g_strdup_printf("%s (%s)", dec_who, email); | |
1131 | |
1132 gaim_notify_email(gc, dec_subj, from, gaim_account_get_username(account), | |
9221 | 1133 yahoo_mail_url, NULL, NULL); |
5521
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1134 |
7747 | 1135 g_free(dec_who); |
1136 g_free(dec_subj); | |
2850
cbe6a1e63a72
[gaim-migrate @ 2863]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2813
diff
changeset
|
1137 g_free(from); |
5521
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1138 } else if (count > 0) { |
5583 | 1139 const char *to = gaim_account_get_username(account); |
9221 | 1140 const char *url = yahoo_mail_url; |
5521
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1141 |
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1142 gaim_notify_emails(gc, count, FALSE, NULL, NULL, &to, &url, |
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1143 NULL, NULL); |
76ec14ba51d7
[gaim-migrate @ 5921]
Christian Hammond <chipx86@chipx86.com>
parents:
5498
diff
changeset
|
1144 } |
2681 | 1145 } |
3147 | 1146 /* This is the y64 alphabet... it's like base64, but has a . and a _ */ |
1147 char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._"; | |
1148 | |
1149 /* This is taken from Sylpheed by Hiroyuki Yamamoto. We have our own tobase64 function | |
1150 * in util.c, but it has a bug I don't feel like finding right now ;) */ | |
1151 void to_y64(unsigned char *out, const unsigned char *in, int inlen) | |
1152 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */ | |
1153 { | |
1154 for (; inlen >= 3; inlen -= 3) | |
1155 { | |
1156 *out++ = base64digits[in[0] >> 2]; | |
1157 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)]; | |
1158 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; | |
1159 *out++ = base64digits[in[2] & 0x3f]; | |
1160 in += 3; | |
1161 } | |
1162 if (inlen > 0) | |
1163 { | |
1164 unsigned char fragment; | |
1165 | |
1166 *out++ = base64digits[in[0] >> 2]; | |
1167 fragment = (in[0] << 4) & 0x30; | |
1168 if (inlen > 1) | |
1169 fragment |= in[1] >> 4; | |
1170 *out++ = base64digits[fragment]; | |
1171 *out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c]; | |
1172 *out++ = '-'; | |
1173 } | |
1174 *out = '\0'; | |
1175 } | |
1176 | |
6986 | 1177 static void yahoo_process_auth_old(GaimConnection *gc, const char *seed) |
1178 { | |
1179 struct yahoo_packet *pack; | |
1180 GaimAccount *account = gaim_connection_get_account(gc); | |
7261 | 1181 const char *name = gaim_normalize(account, gaim_account_get_username(account)); |
6986 | 1182 const char *pass = gaim_account_get_password(account); |
1183 struct yahoo_data *yd = gc->proto_data; | |
1184 | |
1185 /* So, Yahoo has stopped supporting its older clients in India, and undoubtedly | |
1186 * will soon do so in the rest of the world. | |
1187 * | |
1188 * The new clients use this authentication method. I warn you in advance, it's | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8713
diff
changeset
|
1189 * bizarre, convoluted, inordinately complicated. It's also no more secure than |
6986 | 1190 * crypt() was. The only purpose this scheme could serve is to prevent third |
1191 * part clients from connecting to their servers. | |
1192 * | |
1193 * Sorry, Yahoo. | |
1194 */ | |
9277 | 1195 |
6986 | 1196 md5_byte_t result[16]; |
1197 md5_state_t ctx; | |
9277 | 1198 |
6986 | 1199 char *crypt_result; |
1200 char password_hash[25]; | |
1201 char crypt_hash[25]; | |
1202 char *hash_string_p = g_malloc(50 + strlen(name)); | |
1203 char *hash_string_c = g_malloc(50 + strlen(name)); | |
9277 | 1204 |
6986 | 1205 char checksum; |
9277 | 1206 |
6986 | 1207 int sv; |
9277 | 1208 |
6986 | 1209 char result6[25]; |
1210 char result96[25]; | |
1211 | |
1212 sv = seed[15]; | |
1213 sv = sv % 8; | |
1214 | |
1215 md5_init(&ctx); | |
1216 md5_append(&ctx, pass, strlen(pass)); | |
1217 md5_finish(&ctx, result); | |
1218 to_y64(password_hash, result, 16); | |
9277 | 1219 |
6986 | 1220 md5_init(&ctx); |
9277 | 1221 crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$"); |
6986 | 1222 md5_append(&ctx, crypt_result, strlen(crypt_result)); |
1223 md5_finish(&ctx, result); | |
1224 to_y64(crypt_hash, result, 16); | |
1225 | |
1226 switch (sv) { | |
1227 case 1: | |
1228 case 6: | |
1229 checksum = seed[seed[9] % 16]; | |
1230 g_snprintf(hash_string_p, strlen(name) + 50, | |
1231 "%c%s%s%s", checksum, name, seed, password_hash); | |
1232 g_snprintf(hash_string_c, strlen(name) + 50, | |
1233 "%c%s%s%s", checksum, name, seed, crypt_hash); | |
1234 break; | |
1235 case 2: | |
1236 case 7: | |
1237 checksum = seed[seed[15] % 16]; | |
1238 g_snprintf(hash_string_p, strlen(name) + 50, | |
1239 "%c%s%s%s", checksum, seed, password_hash, name); | |
1240 g_snprintf(hash_string_c, strlen(name) + 50, | |
1241 "%c%s%s%s", checksum, seed, crypt_hash, name); | |
1242 break; | |
1243 case 3: | |
1244 checksum = seed[seed[1] % 16]; | |
1245 g_snprintf(hash_string_p, strlen(name) + 50, | |
1246 "%c%s%s%s", checksum, name, password_hash, seed); | |
1247 g_snprintf(hash_string_c, strlen(name) + 50, | |
1248 "%c%s%s%s", checksum, name, crypt_hash, seed); | |
1249 break; | |
1250 case 4: | |
1251 checksum = seed[seed[3] % 16]; | |
1252 g_snprintf(hash_string_p, strlen(name) + 50, | |
1253 "%c%s%s%s", checksum, password_hash, seed, name); | |
1254 g_snprintf(hash_string_c, strlen(name) + 50, | |
1255 "%c%s%s%s", checksum, crypt_hash, seed, name); | |
1256 break; | |
1257 case 0: | |
1258 case 5: | |
1259 checksum = seed[seed[7] % 16]; | |
1260 g_snprintf(hash_string_p, strlen(name) + 50, | |
1261 "%c%s%s%s", checksum, password_hash, name, seed); | |
1262 g_snprintf(hash_string_c, strlen(name) + 50, | |
1263 "%c%s%s%s", checksum, crypt_hash, name, seed); | |
1264 break; | |
1265 } | |
9277 | 1266 |
1267 md5_init(&ctx); | |
6986 | 1268 md5_append(&ctx, hash_string_p, strlen(hash_string_p)); |
1269 md5_finish(&ctx, result); | |
1270 to_y64(result6, result, 16); | |
9277 | 1271 |
1272 md5_init(&ctx); | |
6986 | 1273 md5_append(&ctx, hash_string_c, strlen(hash_string_c)); |
1274 md5_finish(&ctx, result); | |
1275 to_y64(result96, result, 16); | |
1276 | |
1277 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); | |
1278 yahoo_packet_hash(pack, 0, name); | |
1279 yahoo_packet_hash(pack, 6, result6); | |
1280 yahoo_packet_hash(pack, 96, result96); | |
1281 yahoo_packet_hash(pack, 1, name); | |
9277 | 1282 |
6986 | 1283 yahoo_send_packet(yd, pack); |
9277 | 1284 |
6986 | 1285 g_free(hash_string_p); |
1286 g_free(hash_string_c); | |
9277 | 1287 |
6986 | 1288 yahoo_packet_free(pack); |
9277 | 1289 |
6986 | 1290 } |
1291 | |
6998 | 1292 /* I'm dishing out some uber-mad props to Cerulean Studios for cracking this |
1293 * and sending the fix! Thanks guys. */ | |
1294 | |
6986 | 1295 static void yahoo_process_auth_new(GaimConnection *gc, const char *seed) |
1296 { | |
1297 struct yahoo_packet *pack = NULL; | |
1298 GaimAccount *account = gaim_connection_get_account(gc); | |
7261 | 1299 const char *name = gaim_normalize(account, gaim_account_get_username(account)); |
6986 | 1300 const char *pass = gaim_account_get_password(account); |
1301 struct yahoo_data *yd = gc->proto_data; | |
9277 | 1302 |
8349 | 1303 md5_byte_t result[16]; |
1304 md5_state_t ctx; | |
9277 | 1305 |
8349 | 1306 SHA_CTX ctx1; |
1307 SHA_CTX ctx2; | |
9277 | 1308 |
8349 | 1309 char *alphabet1 = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ"; |
1310 char *alphabet2 = "F0E1D2C3B4A59687abcdefghijklmnop"; | |
1311 | |
1312 char *challenge_lookup = "qzec2tb3um1olpar8whx4dfgijknsvy5"; | |
1313 char *operand_lookup = "+|&%/*^-"; | |
1314 char *delimit_lookup = ",;"; | |
1315 | |
1316 char *password_hash = (char *)g_malloc(25); | |
1317 char *crypt_hash = (char *)g_malloc(25); | |
1318 char *crypt_result = NULL; | |
1319 | |
1320 char pass_hash_xor1[64]; | |
1321 char pass_hash_xor2[64]; | |
1322 char crypt_hash_xor1[64]; | |
1323 char crypt_hash_xor2[64]; | |
1324 char resp_6[100]; | |
1325 char resp_96[100]; | |
1326 | |
1327 unsigned char digest1[20]; | |
1328 unsigned char digest2[20]; | |
1329 unsigned char comparison_src[20]; | |
1330 unsigned char magic_key_char[4]; | |
8375 | 1331 const unsigned char *magic_ptr; |
8349 | 1332 |
1333 unsigned int magic[64]; | |
1334 unsigned int magic_work = 0; | |
1335 unsigned int magic_4 = 0; | |
1336 | |
1337 int x; | |
1338 int y; | |
1339 int cnt = 0; | |
1340 int magic_cnt = 0; | |
1341 int magic_len; | |
1342 | |
1343 memset(password_hash, 0, 25); | |
1344 memset(crypt_hash, 0, 25); | |
6986 | 1345 memset(&pass_hash_xor1, 0, 64); |
1346 memset(&pass_hash_xor2, 0, 64); | |
1347 memset(&crypt_hash_xor1, 0, 64); | |
1348 memset(&crypt_hash_xor2, 0, 64); | |
1349 memset(&digest1, 0, 20); | |
1350 memset(&digest2, 0, 20); | |
1351 memset(&magic, 0, 64); | |
1352 memset(&resp_6, 0, 100); | |
1353 memset(&resp_96, 0, 100); | |
1354 memset(&magic_key_char, 0, 4); | |
8349 | 1355 memset(&comparison_src, 0, 20); |
6986 | 1356 |
1357 /* | |
8349 | 1358 * Magic: Phase 1. Generate what seems to be a 30 byte value (could change if base64 |
1359 * ends up differently? I don't remember and I'm tired, so use a 64 byte buffer. | |
6986 | 1360 */ |
9277 | 1361 |
6986 | 1362 magic_ptr = seed; |
8375 | 1363 |
6986 | 1364 while (*magic_ptr != (int)NULL) { |
8349 | 1365 char *loc; |
6986 | 1366 |
8349 | 1367 /* Ignore parentheses. |
1368 */ | |
6986 | 1369 |
1370 if (*magic_ptr == '(' || *magic_ptr == ')') { | |
1371 magic_ptr++; | |
1372 continue; | |
1373 } | |
1374 | |
8349 | 1375 /* Characters and digits verify against the challenge lookup. |
1376 */ | |
6986 | 1377 |
1378 if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) { | |
1379 loc = strchr(challenge_lookup, *magic_ptr); | |
1380 if (!loc) { | |
8349 | 1381 /* SME XXX Error - disconnect here */ |
6986 | 1382 } |
1383 | |
8349 | 1384 /* Get offset into lookup table and shl 3. |
1385 */ | |
6986 | 1386 |
1387 magic_work = loc - challenge_lookup; | |
1388 magic_work <<= 3; | |
1389 | |
1390 magic_ptr++; | |
1391 continue; | |
1392 } else { | |
8349 | 1393 unsigned int local_store; |
6986 | 1394 |
1395 loc = strchr(operand_lookup, *magic_ptr); | |
1396 if (!loc) { | |
8349 | 1397 /* SME XXX Disconnect */ |
6986 | 1398 } |
1399 | |
1400 local_store = loc - operand_lookup; | |
8349 | 1401 |
1402 /* Oops; how did this happen? | |
1403 */ | |
1404 | |
6986 | 1405 if (magic_cnt >= 64) |
1406 break; | |
8349 | 1407 |
6986 | 1408 magic[magic_cnt++] = magic_work | local_store; |
1409 magic_ptr++; | |
1410 continue; | |
1411 } | |
8349 | 1412 } |
6986 | 1413 |
1414 magic_len = magic_cnt; | |
1415 magic_cnt = 0; | |
1416 | |
8349 | 1417 /* Magic: Phase 2. Take generated magic value and sprinkle fairy dust on the values. |
1418 */ | |
1419 | |
6986 | 1420 for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) { |
8349 | 1421 unsigned char byte1; |
1422 unsigned char byte2; | |
6986 | 1423 |
1424 /* Bad. Abort. | |
1425 */ | |
8349 | 1426 |
1427 if ((magic_cnt + 1 > magic_len) || (magic_cnt > magic_len)) | |
6986 | 1428 break; |
1429 | |
1430 byte1 = magic[magic_cnt]; | |
1431 byte2 = magic[magic_cnt+1]; | |
8349 | 1432 |
6986 | 1433 byte1 *= 0xcd; |
1434 byte1 ^= byte2; | |
1435 | |
1436 magic[magic_cnt+1] = byte1; | |
8349 | 1437 } |
1438 | |
1439 /* | |
1440 * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic | |
1441 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key | |
1442 * plus 3 bytes. The 3 bytes are found by looping, and they represent the offsets | |
1443 * into particular functions we'll later call to potentially alter the magic key. | |
1444 * | |
1445 * %-) | |
1446 */ | |
1447 | |
1448 magic_cnt = 1; | |
1449 x = 0; | |
1450 | |
1451 do { | |
1452 unsigned int bl = 0; | |
1453 unsigned int cl = magic[magic_cnt++]; | |
1454 | |
1455 if (magic_cnt >= magic_len) | |
1456 break; | |
1457 | |
1458 if (cl > 0x7F) { | |
1459 if (cl < 0xe0) | |
1460 bl = cl = (cl & 0x1f) << 6; | |
1461 else { | |
1462 bl = magic[magic_cnt++]; | |
1463 cl = (cl & 0x0f) << 6; | |
1464 bl = ((bl & 0x3f) + cl) << 6; | |
1465 } | |
9277 | 1466 |
8349 | 1467 cl = magic[magic_cnt++]; |
1468 bl = (cl & 0x3f) + bl; | |
1469 } else | |
1470 bl = cl; | |
1471 | |
1472 comparison_src[x++] = (bl & 0xff00) >> 8; | |
1473 comparison_src[x++] = bl & 0xff; | |
1474 } while (x < 20); | |
1475 | |
1476 /* First four bytes are magic key. | |
1477 */ | |
1478 | |
1479 memcpy(&magic_key_char[0], comparison_src, 4); | |
8482 | 1480 magic_4 = magic_key_char[0] | (magic_key_char[1]<<8) | (magic_key_char[2]<<16) | (magic_key_char[3]<<24); |
8349 | 1481 |
1482 /* | |
1483 * Magic: Phase 4. Determine what function to use later by getting outside/inside | |
1484 * loop values until we match our previous buffer. | |
1485 */ | |
1486 | |
1487 for (x = 0; x < 65535; x++) { | |
1488 int leave = 0; | |
1489 | |
1490 for (y = 0; y < 5; y++) { | |
1491 md5_byte_t result[16]; | |
1492 md5_state_t ctx; | |
1493 | |
1494 unsigned char test[3]; | |
1495 | |
1496 memset(&result, 0, 16); | |
1497 memset(&test, 0, 3); | |
1498 | |
1499 /* Calculate buffer. | |
1500 */ | |
1501 | |
1502 test[0] = x; | |
1503 test[1] = x >> 8; | |
1504 test[2] = y; | |
1505 | |
1506 md5_init(&ctx); | |
1507 md5_append(&ctx, magic_key_char, 4); | |
1508 md5_append(&ctx, test, 3); | |
1509 md5_finish(&ctx, result); | |
1510 | |
1511 if (!memcmp(result, comparison_src+4, 16)) { | |
1512 leave = 1; | |
1513 break; | |
1514 } | |
1515 } | |
1516 | |
1517 if (leave == 1) | |
1518 break; | |
6986 | 1519 } |
1520 | |
8349 | 1521 /* If y != 0, we need some help. |
1522 */ | |
6986 | 1523 |
8349 | 1524 if (y != 0) { |
1525 unsigned int updated_key; | |
6986 | 1526 |
8349 | 1527 /* Update magic stuff. Call it twice because Yahoo's encryption is super bad ass. |
1528 */ | |
7127 | 1529 |
8349 | 1530 updated_key = yahoo_auth_finalCountdown(magic_4, 0x60, y, x); |
1531 updated_key = yahoo_auth_finalCountdown(updated_key, 0x60, y, x); | |
6986 | 1532 |
8482 | 1533 magic_key_char[0] = updated_key & 0xff; |
1534 magic_key_char[1] = (updated_key >> 8) & 0xff; | |
1535 magic_key_char[2] = (updated_key >> 16) & 0xff; | |
1536 magic_key_char[3] = (updated_key >> 24) & 0xff; | |
8349 | 1537 } |
7127 | 1538 |
8349 | 1539 /* Get password and crypt hashes as per usual. |
1540 */ | |
1541 | |
6986 | 1542 md5_init(&ctx); |
8349 | 1543 md5_append(&ctx, pass, strlen(pass)); |
6986 | 1544 md5_finish(&ctx, result); |
1545 to_y64(password_hash, result, 16); | |
1546 | |
1547 md5_init(&ctx); | |
1548 crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$"); | |
1549 md5_append(&ctx, crypt_result, strlen(crypt_result)); | |
1550 md5_finish(&ctx, result); | |
1551 to_y64(crypt_hash, result, 16); | |
8349 | 1552 |
1553 /* Our first authentication response is based off of the password hash. | |
1554 */ | |
6986 | 1555 |
1556 for (x = 0; x < (int)strlen(password_hash); x++) | |
1557 pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36; | |
1558 | |
1559 if (cnt < 64) | |
1560 memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt); | |
8349 | 1561 |
6986 | 1562 cnt = 0; |
1563 | |
1564 for (x = 0; x < (int)strlen(password_hash); x++) | |
1565 pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c; | |
1566 | |
1567 if (cnt < 64) | |
1568 memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt); | |
1569 | |
1570 shaInit(&ctx1); | |
1571 shaInit(&ctx2); | |
1572 | |
8349 | 1573 /* |
1574 * The first context gets the password hash XORed with 0x36 plus a magic value | |
1575 * which we previously extrapolated from our challenge. | |
1576 */ | |
6986 | 1577 |
1578 shaUpdate(&ctx1, pass_hash_xor1, 64); | |
9382 | 1579 if (y >= 3) |
1580 ctx1.sizeLo = 0x1ff; | |
6986 | 1581 shaUpdate(&ctx1, magic_key_char, 4); |
1582 shaFinal(&ctx1, digest1); | |
1583 | |
8349 | 1584 /* |
1585 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest | |
1586 * of the first context. | |
1587 */ | |
6986 | 1588 |
1589 shaUpdate(&ctx2, pass_hash_xor2, 64); | |
1590 shaUpdate(&ctx2, digest1, 20); | |
1591 shaFinal(&ctx2, digest2); | |
1592 | |
8349 | 1593 /* |
1594 * Now that we have digest2, use it to fetch characters from an alphabet to construct | |
1595 * our first authentication response. | |
1596 */ | |
1597 | |
6986 | 1598 for (x = 0; x < 20; x += 2) { |
8349 | 1599 unsigned int val = 0; |
1600 unsigned int lookup = 0; | |
6986 | 1601 |
8349 | 1602 char byte[6]; |
1603 | |
6986 | 1604 memset(&byte, 0, 6); |
8349 | 1605 |
1606 /* First two bytes of digest stuffed together. | |
6986 | 1607 */ |
9277 | 1608 |
6986 | 1609 val = digest2[x]; |
1610 val <<= 8; | |
1611 val += digest2[x+1]; | |
1612 | |
1613 lookup = (val >> 0x0b); | |
1614 lookup &= 0x1f; | |
1615 if (lookup >= strlen(alphabet1)) | |
1616 break; | |
1617 sprintf(byte, "%c", alphabet1[lookup]); | |
1618 strcat(resp_6, byte); | |
1619 strcat(resp_6, "="); | |
8349 | 1620 |
6986 | 1621 lookup = (val >> 0x06); |
1622 lookup &= 0x1f; | |
1623 if (lookup >= strlen(alphabet2)) | |
1624 break; | |
1625 sprintf(byte, "%c", alphabet2[lookup]); | |
1626 strcat(resp_6, byte); | |
1627 | |
1628 lookup = (val >> 0x01); | |
1629 lookup &= 0x1f; | |
1630 if (lookup >= strlen(alphabet2)) | |
1631 break; | |
1632 sprintf(byte, "%c", alphabet2[lookup]); | |
1633 strcat(resp_6, byte); | |
8349 | 1634 |
6986 | 1635 lookup = (val & 0x01); |
1636 if (lookup >= strlen(delimit_lookup)) | |
1637 break; | |
1638 sprintf(byte, "%c", delimit_lookup[lookup]); | |
1639 strcat(resp_6, byte); | |
1640 } | |
1641 | |
8349 | 1642 /* Our second authentication response is based off of the crypto hash. |
1643 */ | |
6986 | 1644 |
1645 cnt = 0; | |
1646 memset(&digest1, 0, 20); | |
1647 memset(&digest2, 0, 20); | |
1648 | |
1649 for (x = 0; x < (int)strlen(crypt_hash); x++) | |
1650 crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36; | |
1651 | |
1652 if (cnt < 64) | |
1653 memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt); | |
8349 | 1654 |
6986 | 1655 cnt = 0; |
1656 | |
1657 for (x = 0; x < (int)strlen(crypt_hash); x++) | |
1658 crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c; | |
1659 | |
1660 if (cnt < 64) | |
1661 memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt); | |
1662 | |
1663 shaInit(&ctx1); | |
1664 shaInit(&ctx2); | |
1665 | |
8349 | 1666 /* |
1667 * The first context gets the password hash XORed with 0x36 plus a magic value | |
1668 * which we previously extrapolated from our challenge. | |
1669 */ | |
6986 | 1670 |
1671 shaUpdate(&ctx1, crypt_hash_xor1, 64); | |
9382 | 1672 if (y >= 3) |
1673 ctx1.sizeLo = 0x1ff; | |
6986 | 1674 shaUpdate(&ctx1, magic_key_char, 4); |
1675 shaFinal(&ctx1, digest1); | |
1676 | |
8349 | 1677 /* |
1678 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest | |
1679 * of the first context. | |
1680 */ | |
6986 | 1681 |
1682 shaUpdate(&ctx2, crypt_hash_xor2, 64); | |
1683 shaUpdate(&ctx2, digest1, 20); | |
1684 shaFinal(&ctx2, digest2); | |
1685 | |
8349 | 1686 /* |
1687 * Now that we have digest2, use it to fetch characters from an alphabet to construct | |
1688 * our first authentication response. | |
1689 */ | |
6986 | 1690 |
1691 for (x = 0; x < 20; x += 2) { | |
8349 | 1692 unsigned int val = 0; |
1693 unsigned int lookup = 0; | |
6986 | 1694 |
8349 | 1695 char byte[6]; |
6986 | 1696 |
1697 memset(&byte, 0, 6); | |
1698 | |
8349 | 1699 /* First two bytes of digest stuffed together. |
1700 */ | |
6986 | 1701 |
1702 val = digest2[x]; | |
1703 val <<= 8; | |
1704 val += digest2[x+1]; | |
8349 | 1705 |
6986 | 1706 lookup = (val >> 0x0b); |
1707 lookup &= 0x1f; | |
1708 if (lookup >= strlen(alphabet1)) | |
1709 break; | |
1710 sprintf(byte, "%c", alphabet1[lookup]); | |
1711 strcat(resp_96, byte); | |
1712 strcat(resp_96, "="); | |
1713 | |
1714 lookup = (val >> 0x06); | |
1715 lookup &= 0x1f; | |
1716 if (lookup >= strlen(alphabet2)) | |
1717 break; | |
1718 sprintf(byte, "%c", alphabet2[lookup]); | |
1719 strcat(resp_96, byte); | |
1720 | |
1721 lookup = (val >> 0x01); | |
1722 lookup &= 0x1f; | |
1723 if (lookup >= strlen(alphabet2)) | |
1724 break; | |
1725 sprintf(byte, "%c", alphabet2[lookup]); | |
1726 strcat(resp_96, byte); | |
1727 | |
1728 lookup = (val & 0x01); | |
1729 if (lookup >= strlen(delimit_lookup)) | |
1730 break; | |
1731 sprintf(byte, "%c", delimit_lookup[lookup]); | |
1732 strcat(resp_96, byte); | |
1733 } | |
1734 | |
1735 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); | |
1736 yahoo_packet_hash(pack, 0, name); | |
1737 yahoo_packet_hash(pack, 6, resp_6); | |
1738 yahoo_packet_hash(pack, 96, resp_96); | |
1739 yahoo_packet_hash(pack, 1, name); | |
9888 | 1740 yahoo_packet_hash(pack, 135, "6,0,0,1710"); |
9306 | 1741 if (yd->picture_checksum) { |
1742 char *cksum = g_strdup_printf("%d", yd->picture_checksum); | |
1743 yahoo_packet_hash(pack, 192, cksum); | |
1744 g_free(cksum); | |
1745 } | |
6986 | 1746 yahoo_send_packet(yd, pack); |
1747 yahoo_packet_free(pack); | |
1748 | |
7424 | 1749 g_free(password_hash); |
1750 g_free(crypt_hash); | |
6986 | 1751 } |
1752 | |
5583 | 1753 static void yahoo_process_auth(GaimConnection *gc, struct yahoo_packet *pkt) |
3147 | 1754 { |
1755 char *seed = NULL; | |
1756 char *sn = NULL; | |
1757 GSList *l = pkt->hash; | |
7010 | 1758 int m = 0; |
9277 | 1759 gchar *buf; |
1760 | |
1761 | |
3147 | 1762 while (l) { |
1763 struct yahoo_pair *pair = l->data; | |
1764 if (pair->key == 94) | |
1765 seed = pair->value; | |
1766 if (pair->key == 1) | |
1767 sn = pair->value; | |
6986 | 1768 if (pair->key == 13) |
1769 m = atoi(pair->value); | |
3147 | 1770 l = l->next; |
1771 } | |
9277 | 1772 |
3147 | 1773 if (seed) { |
6986 | 1774 switch (m) { |
1775 case 0: | |
1776 yahoo_process_auth_old(gc, seed); | |
1777 break; | |
3147 | 1778 case 1: |
6986 | 1779 yahoo_process_auth_new(gc, seed); |
3147 | 1780 break; |
6986 | 1781 default: |
7043 | 1782 buf = g_strdup_printf(_("The Yahoo server has requested the use of an unrecognized " |
7129 | 1783 "authentication method. This version of Gaim will likely not be able " |
7043 | 1784 "to successfully sign on to Yahoo. Check %s for updates."), GAIM_WEBSITE); |
6986 | 1785 gaim_notify_error(gc, "", _("Failed Yahoo! Authentication"), |
7043 | 1786 buf); |
1787 g_free(buf); | |
6986 | 1788 yahoo_process_auth_new(gc, seed); /* Can't hurt to try it anyway. */ |
3147 | 1789 } |
1790 } | |
1791 } | |
2681 | 1792 |
9285 | 1793 static void ignore_buddy(GaimBuddy *buddy) { |
1794 GaimGroup *group; | |
1795 GaimConversation *conv; | |
6760 | 1796 GaimAccount *account; |
1797 gchar *name; | |
1798 | |
9285 | 1799 if (!buddy) |
6792 | 1800 return; |
6760 | 1801 |
9285 | 1802 group = gaim_find_buddys_group(buddy); |
1803 name = g_strdup(buddy->name); | |
1804 account = buddy->account; | |
6760 | 1805 |
6792 | 1806 gaim_debug(GAIM_DEBUG_INFO, "blist", |
9285 | 1807 "Removing '%s' from buddy list.\n", buddy->name); |
1808 serv_remove_buddy(account->gc, buddy, group); | |
1809 gaim_blist_remove_buddy(buddy); | |
6760 | 1810 |
6792 | 1811 serv_add_deny(account->gc, name); |
9285 | 1812 |
1813 conv = gaim_find_conversation_with_account(name, account); | |
1814 | |
1815 if (conv != NULL) | |
1816 gaim_conversation_update(conv, GAIM_CONV_UPDATE_REMOVE); | |
6760 | 1817 |
1818 g_free(name); | |
1819 } | |
1820 | |
1821 static void keep_buddy(GaimBuddy *b) { | |
1822 gaim_privacy_deny_remove(b->account, b->name, 1); | |
1823 } | |
1824 | |
1825 static void yahoo_process_ignore(GaimConnection *gc, struct yahoo_packet *pkt) { | |
1826 GaimBuddy *b; | |
1827 GSList *l; | |
1828 gchar *who = NULL; | |
1829 gchar *sn = NULL; | |
1830 gchar buf[BUF_LONG]; | |
1831 gint ignore = 0; | |
1832 gint status = 0; | |
1833 | |
1834 for (l = pkt->hash; l; l = l->next) { | |
1835 struct yahoo_pair *pair = l->data; | |
1836 switch (pair->key) { | |
1837 case 0: | |
1838 who = pair->value; | |
1839 break; | |
1840 case 1: | |
1841 sn = pair->value; | |
1842 break; | |
1843 case 13: | |
1844 ignore = strtol(pair->value, NULL, 10); | |
1845 break; | |
1846 case 66: | |
1847 status = strtol(pair->value, NULL, 10); | |
1848 break; | |
1849 default: | |
1850 break; | |
1851 } | |
1852 } | |
1853 | |
1854 switch (status) { | |
1855 case 12: | |
1856 b = gaim_find_buddy(gc->account, who); | |
1857 g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the " | |
1858 "user is on your buddy list. Clicking \"Yes\" " | |
1859 "will remove and ignore the buddy."), who); | |
1860 gaim_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0, b, | |
1861 G_CALLBACK(ignore_buddy), | |
1862 G_CALLBACK(keep_buddy)); | |
1863 break; | |
1864 case 2: | |
1865 case 3: | |
1866 case 0: | |
1867 default: | |
1868 break; | |
1869 } | |
1870 } | |
1871 | |
6761 | 1872 static void yahoo_process_authresp(GaimConnection *gc, struct yahoo_packet *pkt) |
1873 { | |
9410 | 1874 struct yahoo_data *yd = gc->proto_data; |
6761 | 1875 GSList *l = pkt->hash; |
1876 int err = 0; | |
1877 char *msg; | |
7865 | 1878 char *url = NULL; |
1879 char *fullmsg; | |
6761 | 1880 |
1881 while (l) { | |
1882 struct yahoo_pair *pair = l->data; | |
1883 | |
1884 if (pair->key == 66) | |
1885 err = strtol(pair->value, NULL, 10); | |
7865 | 1886 if (pair->key == 20) |
1887 url = pair->value; | |
6761 | 1888 |
1889 l = l->next; | |
1890 } | |
1891 | |
1892 switch (err) { | |
1893 case 3: | |
7865 | 1894 msg = g_strdup(_("Invalid username.")); |
6761 | 1895 break; |
1896 case 13: | |
9410 | 1897 if (!yd->wm) { |
1898 yd->wm = TRUE; | |
1899 if (yd->fd >= 0) | |
1900 close(yd->fd); | |
1901 if (gc->inpa) | |
1902 gaim_input_remove(gc->inpa); | |
1903 gaim_url_fetch(WEBMESSENGER_URL, TRUE, "Gaim/" VERSION, FALSE, | |
1904 yahoo_login_page_cb, gc); | |
9835 | 1905 gaim_notify_warning(gc, NULL, _("Normal authentication failed!"), |
1906 _("The normal authentication method has failed. " | |
9410 | 1907 "This means either your password is incorrect, " |
9835 | 1908 "or Yahoo!'s authentication scheme has changed. " |
9410 | 1909 "Gaim will now attempt to log in using Web " |
9835 | 1910 "Messenger authentication, which will result " |
9410 | 1911 "in reduced functionality and features.")); |
1912 return; | |
1913 } | |
7865 | 1914 msg = g_strdup(_("Incorrect password.")); |
1915 break; | |
1916 case 14: | |
9280 | 1917 msg = g_strdup(_("Your account is locked, please log in to the Yahoo! website.")); |
6761 | 1918 break; |
1919 default: | |
9280 | 1920 msg = g_strdup_printf(_("Unknown error number %d. Logging into the Yahoo! website may fix this."), err); |
6761 | 1921 } |
7865 | 1922 |
1923 if (url) | |
1924 fullmsg = g_strdup_printf("%s\n%s", msg, url); | |
1925 else | |
1926 fullmsg = g_strdup(msg); | |
1927 | |
9280 | 1928 gc->wants_to_die = TRUE; |
7865 | 1929 gaim_connection_error(gc, fullmsg); |
1930 g_free(msg); | |
1931 g_free(fullmsg); | |
6761 | 1932 } |
1933 | |
6840 | 1934 static void yahoo_process_addbuddy(GaimConnection *gc, struct yahoo_packet *pkt) |
1935 { | |
1936 int err = 0; | |
1937 char *who = NULL; | |
1938 char *group = NULL; | |
7827 | 1939 char *decoded_group; |
6840 | 1940 char *buf; |
9278 | 1941 YahooFriend *f; |
6840 | 1942 GSList *l = pkt->hash; |
1943 | |
1944 while (l) { | |
1945 struct yahoo_pair *pair = l->data; | |
1946 | |
1947 switch (pair->key) { | |
1948 case 66: | |
1949 err = strtol(pair->value, NULL, 10); | |
1950 break; | |
1951 case 7: | |
1952 who = pair->value; | |
1953 break; | |
1954 case 65: | |
1955 group = pair->value; | |
1956 break; | |
1957 } | |
1958 | |
1959 l = l->next; | |
1960 } | |
1961 | |
1962 if (!who) | |
1963 return; | |
1964 if (!group) | |
1965 group = ""; | |
1966 | |
1967 if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */ | |
9279 | 1968 f = yahoo_friend_find_or_new(gc, who); |
1969 yahoo_update_status(gc, who, f); | |
6840 | 1970 return; |
1971 } | |
1972 | |
7827 | 1973 decoded_group = yahoo_string_decode(gc, group, FALSE); |
6840 | 1974 buf = g_strdup_printf(_("Could not add buddy %s to group %s to the server list on account %s."), |
7827 | 1975 who, decoded_group, gaim_connection_get_display_name(gc)); |
9637 | 1976 if (!gaim_conv_present_error(who, gaim_connection_get_account(gc), buf)) |
1977 gaim_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); | |
6840 | 1978 g_free(buf); |
7827 | 1979 g_free(decoded_group); |
6840 | 1980 } |
1981 | |
9062 | 1982 static void yahoo_process_p2p(GaimConnection *gc, struct yahoo_packet *pkt) |
1983 { | |
1984 GSList *l = pkt->hash; | |
1985 char *who = NULL; | |
1986 char *base64 = NULL; | |
9277 | 1987 char *decoded; |
9062 | 1988 int len; |
1989 | |
1990 while (l) { | |
1991 struct yahoo_pair *pair = l->data; | |
1992 | |
1993 switch (pair->key) { | |
1994 case 5: | |
1995 /* our identity */ | |
1996 break; | |
1997 case 4: | |
1998 who = pair->value; | |
1999 break; | |
2000 case 1: | |
2001 /* who again, the master identity this time? */ | |
2002 break; | |
2003 case 12: | |
2004 base64 = pair->value; | |
2005 /* so, this is an ip address. in base64. decoded it's in ascii. | |
2006 after strtol, it's in reversed byte order. Who thought this up?*/ | |
2007 break; | |
2008 /* | |
2009 TODO: figure these out | |
2010 yahoo: Key: 61 Value: 0 | |
2011 yahoo: Key: 2 Value: | |
2012 yahoo: Key: 13 Value: 0 | |
2013 yahoo: Key: 49 Value: PEERTOPEER | |
2014 yahoo: Key: 140 Value: 1 | |
2015 yahoo: Key: 11 Value: -1786225828 | |
2016 */ | |
2017 | |
2018 } | |
2019 | |
2020 l = l->next; | |
2021 } | |
2022 | |
9277 | 2023 if (base64) { |
9281 | 2024 guint32 ip; |
2025 char *tmp2; | |
2026 YahooFriend *f; | |
2027 | |
9062 | 2028 gaim_base64_decode(base64, &decoded, &len); |
9277 | 2029 if (len) { |
2030 char *tmp = gaim_str_binary_to_ascii(decoded, len); | |
2031 gaim_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); | |
2032 g_free(tmp); | |
2033 } | |
9281 | 2034 |
2035 tmp2 = g_strndup(decoded, len); /* so its \0 terminated...*/ | |
2036 ip = strtol(tmp2, NULL, 10); | |
2037 g_free(tmp2); | |
9062 | 2038 g_free(decoded); |
9281 | 2039 tmp2 = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, |
2040 (ip >> 24) & 0xff); | |
2041 f = yahoo_friend_find(gc, who); | |
2042 if (f) | |
2043 yahoo_friend_set_ip(f, tmp2); | |
2044 g_free(tmp2); | |
9062 | 2045 } |
2046 } | |
2047 | |
9604 | 2048 static void yahoo_process_audible(GaimConnection *gc, struct yahoo_packet *pkt) |
2049 { | |
2050 char *who = NULL, *msg = NULL; | |
2051 GSList *l = pkt->hash; | |
2052 | |
2053 while (l) { | |
2054 struct yahoo_pair *pair = l->data; | |
2055 | |
2056 switch (pair->key) { | |
2057 case 4: | |
2058 who = pair->value; | |
2059 break; | |
2060 case 5: | |
2061 /* us */ | |
2062 break; | |
2063 case 230: | |
2064 /* the audible, in foo.bar.baz format */ | |
2065 break; | |
2066 case 231: | |
2067 /* the text of the audible */ | |
2068 msg = pair->value; | |
2069 break; | |
2070 case 232: | |
2071 /* weird number (md5 hash?), like 8ebab9094156135f5dcbaccbeee662a5c5fd1420 */ | |
2072 break; | |
2073 } | |
2074 | |
2075 l = l->next; | |
2076 } | |
2077 | |
2078 if (!who || !msg) | |
2079 return; | |
2080 if (!g_utf8_validate(msg, -1, NULL)) { | |
2081 gaim_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n"); | |
2082 return; | |
2083 } | |
2084 | |
2085 serv_got_im(gc, who, msg, 0, time(NULL)); | |
2086 } | |
2087 | |
5583 | 2088 static void yahoo_packet_process(GaimConnection *gc, struct yahoo_packet *pkt) |
2681 | 2089 { |
6760 | 2090 switch (pkt->service) { |
2681 | 2091 case YAHOO_SERVICE_LOGON: |
2771
450f4f9d2f23
[gaim-migrate @ 2784]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2741
diff
changeset
|
2092 case YAHOO_SERVICE_LOGOFF: |
2681 | 2093 case YAHOO_SERVICE_ISAWAY: |
2737
f61c1f3a6afa
[gaim-migrate @ 2750]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2724
diff
changeset
|
2094 case YAHOO_SERVICE_ISBACK: |
3019 | 2095 case YAHOO_SERVICE_GAMELOGON: |
2096 case YAHOO_SERVICE_GAMELOGOFF: | |
6686 | 2097 case YAHOO_SERVICE_CHATLOGON: |
2098 case YAHOO_SERVICE_CHATLOGOFF: | |
9409 | 2099 case YAHOO_SERVICE_YAHOO6_STATUS_UPDATE: |
2681 | 2100 yahoo_process_status(gc, pkt); |
2101 break; | |
3019 | 2102 case YAHOO_SERVICE_NOTIFY: |
2103 yahoo_process_notify(gc, pkt); | |
2993 | 2104 break; |
2681 | 2105 case YAHOO_SERVICE_MESSAGE: |
2786
318f846120e2
[gaim-migrate @ 2799]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2772
diff
changeset
|
2106 case YAHOO_SERVICE_GAMEMSG: |
5939 | 2107 case YAHOO_SERVICE_CHATMSG: |
2681 | 2108 yahoo_process_message(gc, pkt); |
2109 break; | |
7865 | 2110 case YAHOO_SERVICE_SYSMESSAGE: |
2111 yahoo_process_sysmessage(gc, pkt); | |
2112 break; | |
2681 | 2113 case YAHOO_SERVICE_NEWMAIL: |
2114 yahoo_process_mail(gc, pkt); | |
2115 break; | |
2116 case YAHOO_SERVICE_NEWCONTACT: | |
2117 yahoo_process_contact(gc, pkt); | |
2118 break; | |
6784 | 2119 case YAHOO_SERVICE_AUTHRESP: |
2120 yahoo_process_authresp(gc, pkt); | |
2121 break; | |
2681 | 2122 case YAHOO_SERVICE_LIST: |
2123 yahoo_process_list(gc, pkt); | |
2124 break; | |
3147 | 2125 case YAHOO_SERVICE_AUTH: |
2126 yahoo_process_auth(gc, pkt); | |
2127 break; | |
6840 | 2128 case YAHOO_SERVICE_ADDBUDDY: |
2129 yahoo_process_addbuddy(gc, pkt); | |
2130 break; | |
6760 | 2131 case YAHOO_SERVICE_IGNORECONTACT: |
2132 yahoo_process_ignore(gc, pkt); | |
2133 break; | |
6729 | 2134 case YAHOO_SERVICE_CONFINVITE: |
2135 case YAHOO_SERVICE_CONFADDINVITE: | |
2136 yahoo_process_conference_invite(gc, pkt); | |
2137 break; | |
2138 case YAHOO_SERVICE_CONFDECLINE: | |
2139 yahoo_process_conference_decline(gc, pkt); | |
2140 break; | |
2141 case YAHOO_SERVICE_CONFLOGON: | |
2142 yahoo_process_conference_logon(gc, pkt); | |
2143 break; | |
2144 case YAHOO_SERVICE_CONFLOGOFF: | |
2145 yahoo_process_conference_logoff(gc, pkt); | |
2146 break; | |
2147 case YAHOO_SERVICE_CONFMSG: | |
2148 yahoo_process_conference_message(gc, pkt); | |
2149 break; | |
2150 case YAHOO_SERVICE_CHATONLINE: | |
2151 yahoo_process_chat_online(gc, pkt); | |
2152 break; | |
2153 case YAHOO_SERVICE_CHATLOGOUT: | |
2154 yahoo_process_chat_logout(gc, pkt); | |
2155 break; | |
2156 case YAHOO_SERVICE_CHATGOTO: | |
2157 yahoo_process_chat_goto(gc, pkt); | |
2158 break; | |
2159 case YAHOO_SERVICE_CHATJOIN: | |
2160 yahoo_process_chat_join(gc, pkt); | |
2161 break; | |
2162 case YAHOO_SERVICE_CHATLEAVE: /* XXX is this right? */ | |
2163 case YAHOO_SERVICE_CHATEXIT: | |
2164 yahoo_process_chat_exit(gc, pkt); | |
2165 break; | |
2166 case YAHOO_SERVICE_CHATINVITE: /* XXX never seen this one, might not do it right */ | |
2167 case YAHOO_SERVICE_CHATADDINVITE: | |
2168 yahoo_process_chat_addinvite(gc, pkt); | |
2169 break; | |
2170 case YAHOO_SERVICE_COMMENT: | |
2171 yahoo_process_chat_message(gc, pkt); | |
2172 break; | |
7651 | 2173 case YAHOO_SERVICE_P2PFILEXFER: |
2174 case YAHOO_SERVICE_FILETRANSFER: | |
2175 yahoo_process_filetransfer(gc, pkt); | |
2176 break; | |
9062 | 2177 case YAHOO_SERVICE_PEEPTOPEER: |
2178 yahoo_process_p2p(gc, pkt); | |
2179 break; | |
9284 | 2180 case YAHOO_SERVICE_PICTURE: |
2181 yahoo_process_picture(gc, pkt); | |
2182 break; | |
9292 | 2183 case YAHOO_SERVICE_PICTURE_UPDATE: |
2184 yahoo_process_picture_update(gc, pkt); | |
2185 break; | |
2186 case YAHOO_SERVICE_PICTURE_CHECKSUM: | |
2187 yahoo_process_picture_checksum(gc, pkt); | |
2188 break; | |
9306 | 2189 case YAHOO_SERVICE_PICTURE_UPLOAD: |
2190 yahoo_process_picture_upload(gc, pkt); | |
2191 break; | |
9604 | 2192 case YAHOO_SERVICE_AUDIBLE: |
2193 yahoo_process_audible(gc, pkt); | |
2681 | 2194 default: |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
2195 gaim_debug(GAIM_DEBUG_ERROR, "yahoo", |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2196 "Unhandled service 0x%02x\n", pkt->service); |
2681 | 2197 break; |
2198 } | |
2199 } | |
2200 | |
2201 static void yahoo_pending(gpointer data, gint source, GaimInputCondition cond) | |
2202 { | |
5583 | 2203 GaimConnection *gc = data; |
2681 | 2204 struct yahoo_data *yd = gc->proto_data; |
2205 char buf[1024]; | |
2206 int len; | |
2207 | |
2208 len = read(yd->fd, buf, sizeof(buf)); | |
2209 | |
2210 if (len <= 0) { | |
6321 | 2211 gaim_connection_error(gc, _("Unable to read")); |
2681 | 2212 return; |
2213 } | |
2214 | |
2215 yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen); | |
2216 memcpy(yd->rxqueue + yd->rxlen, buf, len); | |
2217 yd->rxlen += len; | |
2218 | |
2219 while (1) { | |
2220 struct yahoo_packet *pkt; | |
2221 int pos = 0; | |
2222 int pktlen; | |
2223 | |
2224 if (yd->rxlen < YAHOO_PACKET_HDRLEN) | |
2225 return; | |
2226 | |
2227 pos += 4; /* YMSG */ | |
2228 pos += 2; | |
2229 pos += 2; | |
2230 | |
2231 pktlen = yahoo_get16(yd->rxqueue + pos); pos += 2; | |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
2232 gaim_debug(GAIM_DEBUG_MISC, "yahoo", |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2233 "%d bytes to read, rxlen is %d\n", pktlen, yd->rxlen); |
2681 | 2234 |
2235 if (yd->rxlen < (YAHOO_PACKET_HDRLEN + pktlen)) | |
2236 return; | |
2237 | |
2238 yahoo_packet_dump(yd->rxqueue, YAHOO_PACKET_HDRLEN + pktlen); | |
2239 | |
2240 pkt = yahoo_packet_new(0, 0, 0); | |
2241 | |
2242 pkt->service = yahoo_get16(yd->rxqueue + pos); pos += 2; | |
3021 | 2243 pkt->status = yahoo_get32(yd->rxqueue + pos); pos += 4; |
5220
7b9d78fa051e
[gaim-migrate @ 5590]
Christian Hammond <chipx86@chipx86.com>
parents:
5216
diff
changeset
|
2244 gaim_debug(GAIM_DEBUG_MISC, "yahoo", |
5216
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2245 "Yahoo Service: 0x%02x Status: %d\n", |
00bd3019749e
[gaim-migrate @ 5586]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2246 pkt->service, pkt->status); |
2681 | 2247 pkt->id = yahoo_get32(yd->rxqueue + pos); pos += 4; |
2248 | |
2249 yahoo_packet_read(pkt, yd->rxqueue + pos, pktlen); | |
2250 | |
2251 yd->rxlen -= YAHOO_PACKET_HDRLEN + pktlen; | |
2252 if (yd->rxlen) { | |
2253 char *tmp = g_memdup(yd->rxqueue + YAHOO_PACKET_HDRLEN + pktlen, yd->rxlen); | |
2254 g_free(yd->rxqueue); | |
2255 yd->rxqueue = tmp; | |
2256 } else { | |
2257 g_free(yd->rxqueue); | |
2258 yd->rxqueue = NULL; | |
2259 } | |
2260 | |
2261 yahoo_packet_process(gc, pkt); | |
2262 | |
2263 yahoo_packet_free(pkt); | |
2264 } | |
2265 } | |
2266 | |
2267 static void yahoo_got_connected(gpointer data, gint source, GaimInputCondition cond) | |
2268 { | |
5583 | 2269 GaimConnection *gc = data; |
2681 | 2270 struct yahoo_data *yd; |
2271 struct yahoo_packet *pkt; | |
2272 | |
5590
011a0a975060
[gaim-migrate @ 5994]
Christian Hammond <chipx86@chipx86.com>
parents:
5583
diff
changeset
|
2273 if (!g_list_find(gaim_connections_get_all(), gc)) { |
2681 | 2274 close(source); |
2275 return; | |
2276 } | |
2277 | |
2278 if (source < 0) { | |
8057 | 2279 gaim_connection_error(gc, _("Unable to connect.")); |
2681 | 2280 return; |
2281 } | |
2282 | |
2283 yd = gc->proto_data; | |
2284 yd->fd = source; | |
2285 | |
3147 | 2286 pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, 0); |
2681 | 2287 |
7261 | 2288 yahoo_packet_hash(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc)))); |
2681 | 2289 yahoo_send_packet(yd, pkt); |
2290 | |
2291 yahoo_packet_free(pkt); | |
2292 | |
2293 gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc); | |
2294 } | |
9370 | 2295 |
7134 | 2296 static void yahoo_got_web_connected(gpointer data, gint source, GaimInputCondition cond) |
2297 { | |
2298 GaimConnection *gc = data; | |
2299 struct yahoo_data *yd; | |
2300 struct yahoo_packet *pkt; | |
2301 | |
2302 if (!g_list_find(gaim_connections_get_all(), gc)) { | |
2303 close(source); | |
2304 return; | |
2305 } | |
2306 | |
2307 if (source < 0) { | |
8057 | 2308 gaim_connection_error(gc, _("Unable to connect.")); |
7134 | 2309 return; |
2310 } | |
2311 | |
2312 yd = gc->proto_data; | |
2313 yd->fd = source; | |
2314 | |
2315 pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, 0); | |
2316 | |
7261 | 2317 yahoo_packet_hash(pkt, 0, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc)))); |
2318 yahoo_packet_hash(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc)))); | |
7134 | 2319 yahoo_packet_hash(pkt, 6, yd->auth); |
2320 yahoo_send_packet(yd, pkt); | |
2321 | |
2322 yahoo_packet_free(pkt); | |
2323 g_free(yd->auth); | |
2324 gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc); | |
2325 } | |
2326 | |
2327 static void yahoo_web_pending(gpointer data, gint source, GaimInputCondition cond) | |
2328 { | |
2329 GaimConnection *gc = data; | |
2330 GaimAccount *account = gaim_connection_get_account(gc); | |
2331 struct yahoo_data *yd = gc->proto_data; | |
8243 | 2332 char buf[2048], *i = buf; |
8161 | 2333 int len; |
2334 GString *s; | |
7134 | 2335 |
8118 | 2336 len = read(source, buf, sizeof(buf)-1); |
8216
dcace041cfb8
[gaim-migrate @ 8939]
Christian Hammond <chipx86@chipx86.com>
parents:
8212
diff
changeset
|
2337 if (len <= 0 || (strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) && |
dcace041cfb8
[gaim-migrate @ 8939]
Christian Hammond <chipx86@chipx86.com>
parents:
8212
diff
changeset
|
2338 strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) { |
7134 | 2339 gaim_connection_error(gc, _("Unable to read")); |
2340 return; | |
2341 } | |
8161 | 2342 |
2343 s = g_string_sized_new(len); | |
8118 | 2344 buf[sizeof(buf)-1] = '\0'; |
8161 | 2345 |
2346 while ((i = strstr(i, "Set-Cookie: "))) { | |
2347 i += strlen("Set-Cookie: "); | |
8243 | 2348 for (;*i != ';' && *i != '\0'; i++) |
8161 | 2349 g_string_append_c(s, *i); |
2350 | |
2351 g_string_append(s, "; "); | |
7134 | 2352 } |
8161 | 2353 |
2354 yd->auth = g_string_free(s, FALSE); | |
7134 | 2355 gaim_input_remove(gc->inpa); |
2356 close(source); | |
2357 /* Now we have our cookies to login with. I'll go get the milk. */ | |
8045 | 2358 if (gaim_proxy_connect(account, "wcs2.msg.dcn.yahoo.com", |
7134 | 2359 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), |
2360 yahoo_got_web_connected, gc) != 0) { | |
2361 gaim_connection_error(gc, _("Connection problem")); | |
2362 return; | |
2363 } | |
2364 } | |
2365 | |
2366 static void yahoo_got_cookies(gpointer data, gint source, GaimInputCondition cond) | |
2367 { | |
2368 GaimConnection *gc = data; | |
2369 struct yahoo_data *yd = gc->proto_data; | |
2370 if (source < 0) { | |
8057 | 2371 gaim_connection_error(gc, _("Unable to connect.")); |
7134 | 2372 return; |
2373 } | |
2374 write(source, yd->auth, strlen(yd->auth)); | |
2375 g_free(yd->auth); | |
2376 gc->inpa = gaim_input_add(source, GAIM_INPUT_READ, yahoo_web_pending, gc); | |
2377 } | |
2378 | |
2379 static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url) | |
2380 { | |
2381 if (!strcmp(key, "passwd")) | |
2382 return; | |
2383 url = g_string_append_c(url, '&'); | |
2384 url = g_string_append(url, key); | |
2385 url = g_string_append_c(url, '='); | |
2386 if (!strcmp(key, ".save") || !strcmp(key, ".js")) | |
2387 url = g_string_append_c(url, '1'); | |
2388 else if (!strcmp(key, ".challenge")) | |
2389 url = g_string_append(url, val); | |
2390 else | |
2391 url = g_string_append(url, gaim_url_encode(val)); | |
2392 } | |
2393 | |
2394 static GHashTable *yahoo_login_page_hash(const char *buf, size_t len) | |
2395 { | |
2396 GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
7138
f189f8ccaa98
[gaim-migrate @ 7705]
Christian Hammond <chipx86@chipx86.com>
parents:
7134
diff
changeset
|
2397 const char *c = buf; |
f189f8ccaa98
[gaim-migrate @ 7705]
Christian Hammond <chipx86@chipx86.com>
parents:
7134
diff
changeset
|
2398 char *d; |
7134 | 2399 char name[64], value[64]; |
8118 | 2400 int count = sizeof(name)-1; |
7134 | 2401 while ((c < (buf + len)) && (c = strstr(c, "<input "))) { |
2402 c = strstr(c, "name=\"") + strlen("name=\""); | |
8118 | 2403 for (d = name; *c!='"' && count; c++, d++, count--) |
7134 | 2404 *d = *c; |
2405 *d = '\0'; | |
8118 | 2406 count = sizeof(value)-1; |
7134 | 2407 d = strstr(c, "value=\"") + strlen("value=\""); |
2408 if (strchr(c, '>') < d) | |
2409 break; | |
8118 | 2410 for (c = d, d = value; *c!='"' && count; c++, d++, count--) |
7134 | 2411 *d = *c; |
2412 *d = '\0'; | |
2413 g_hash_table_insert(hash, g_strdup(name), g_strdup(value)); | |
2414 } | |
2415 return hash; | |
2416 } | |
2417 | |
7138
f189f8ccaa98
[gaim-migrate @ 7705]
Christian Hammond <chipx86@chipx86.com>
parents:
7134
diff
changeset
|
2418 static void yahoo_login_page_cb(void *user_data, const char *buf, size_t len) |
7134 | 2419 { |
7138
f189f8ccaa98
[gaim-migrate @ 7705]
Christian Hammond <chipx86@chipx86.com>
parents:
7134
diff
changeset
|
2420 GaimConnection *gc = (GaimConnection *)user_data; |
7134 | 2421 GaimAccount *account = gaim_connection_get_account(gc); |
2422 struct yahoo_data *yd = gc->proto_data; | |
2423 const char *sn = gaim_account_get_username(account); | |
2424 const char *pass = gaim_account_get_password(account); | |
2425 GHashTable *hash = yahoo_login_page_hash(buf, len); | |
2426 GString *url = g_string_new("GET /config/login?login="); | |
2427 char md5[33], *hashp = md5, *chal; | |
2428 int i; | |
2429 md5_byte_t result[16]; | |
2430 md5_state_t ctx; | |
7191
4bd3892cded3
[gaim-migrate @ 7760]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7161
diff
changeset
|
2431 |
4bd3892cded3
[gaim-migrate @ 7760]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7161
diff
changeset
|
2432 url = g_string_append(url, sn); |
4bd3892cded3
[gaim-migrate @ 7760]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7161
diff
changeset
|
2433 url = g_string_append(url, "&passwd="); |
4bd3892cded3
[gaim-migrate @ 7760]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7161
diff
changeset
|
2434 |
7134 | 2435 md5_init(&ctx); |
2436 md5_append(&ctx, pass, strlen(pass)); | |
2437 md5_finish(&ctx, result); | |
2438 for (i = 0; i < 16; ++i) { | |
2439 g_snprintf(hashp, 3, "%02x", result[i]); | |
2440 hashp += 2; | |
2441 } | |
2442 chal = g_strconcat(md5, g_hash_table_lookup(hash, ".challenge"), NULL); | |
2443 md5_init(&ctx); | |
2444 md5_append(&ctx, chal, strlen(chal)); | |
2445 md5_finish(&ctx, result); | |
2446 hashp = md5; | |
2447 for (i = 0; i < 16; ++i) { | |
2448 g_snprintf(hashp, 3, "%02x", result[i]); | |
2449 hashp += 2; | |
2450 } | |
2451 /* | |
2452 md5_init(&ctx); | |
2453 md5_append(&ctx, md5, strlen(md5)); | |
2454 md5_finish(&ctx, result); | |
2455 hashp = md5; | |
2456 for (i = 0; i < 16; ++i) { | |
2457 g_snprintf(hashp, 3, "%02x", result[i]); | |
2458 hashp += 2; | |
2459 } | |
2460 */ | |
2461 g_free(chal); | |
2462 | |
2463 url = g_string_append(url, md5); | |
7138
f189f8ccaa98
[gaim-migrate @ 7705]
Christian Hammond <chipx86@chipx86.com>
parents:
7134
diff
changeset
|
2464 g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url); |
7134 | 2465 |
2466 url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n" | |
2467 "Host: login.yahoo.com\r\n\r\n"); | |
2468 g_hash_table_destroy(hash); | |
2469 yd->auth = g_string_free(url, FALSE); | |
2470 if (gaim_proxy_connect(account, "login.yahoo.com", 80, yahoo_got_cookies, gc) != 0) { | |
2471 gaim_connection_error(gc, _("Connection problem")); | |
2472 return; | |
2473 } | |
2474 } | |
2475 | |
7883 | 2476 static void yahoo_server_check(GaimAccount *account) |
2477 { | |
2478 const char *server; | |
2479 | |
2480 server = gaim_account_get_string(account, "server", YAHOO_PAGER_HOST); | |
2481 | |
2482 if (strcmp(server, "scs.yahoo.com") == 0) | |
2483 gaim_account_set_string(account, "server", YAHOO_PAGER_HOST); | |
2484 } | |
9306 | 2485 |
2486 static void yahoo_picture_check(GaimAccount *account) | |
2487 { | |
2488 GaimConnection *gc = gaim_account_get_connection(account); | |
2489 const char *buddyicon; | |
2490 | |
2491 buddyicon = gaim_account_get_buddy_icon(account); | |
2492 yahoo_set_buddy_icon(gc, buddyicon); | |
2493 } | |
2494 | |
7883 | 2495 |
5583 | 2496 static void yahoo_login(GaimAccount *account) { |
2497 GaimConnection *gc = gaim_account_get_connection(account); | |
2681 | 2498 struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1); |
2499 | |
9041 | 2500 gc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_NO_BGCOLOR | GAIM_CONNECTION_NO_URLDESC; |
6629 | 2501 |
5583 | 2502 gaim_connection_update_progress(gc, _("Connecting"), 1, 2); |
2681 | 2503 |
8235 | 2504 gaim_connection_set_display_name(gc, gaim_account_get_username(account)); |
2505 | |
2681 | 2506 yd->fd = -1; |
6784 | 2507 yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); |
6729 | 2508 yd->confs = NULL; |
2509 yd->conf_id = 2; | |
2681 | 2510 |
7883 | 2511 yahoo_server_check(account); |
9306 | 2512 yahoo_picture_check(account); |
7883 | 2513 |
9164 | 2514 if (gaim_account_get_bool(account, "yahoojp", FALSE)) { |
2515 yd->jp = TRUE; | |
2516 if (gaim_proxy_connect(account, | |
2517 gaim_account_get_string(account, "serverjp", YAHOOJP_PAGER_HOST), | |
2518 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), | |
2519 yahoo_got_connected, gc) != 0) | |
2520 { | |
2521 gaim_connection_error(gc, _("Connection problem")); | |
2522 return; | |
2523 } | |
2524 } else { | |
2525 yd->jp = FALSE; | |
2526 if (gaim_proxy_connect(account, | |
2527 gaim_account_get_string(account, "server", YAHOO_PAGER_HOST), | |
2528 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), | |
2529 yahoo_got_connected, gc) != 0) | |
2530 { | |
2531 gaim_connection_error(gc, _("Connection problem")); | |
2532 return; | |
2533 } | |
2681 | 2534 } |
9370 | 2535 |
2681 | 2536 |
2537 } | |
2538 | |
5583 | 2539 static void yahoo_close(GaimConnection *gc) { |
2681 | 2540 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; |
9782 | 2541 GSList *l; |
2542 | |
2543 for (l = yd->confs; l; l = l->next) { | |
2544 GaimConversation *conv = l->data; | |
2545 | |
2546 yahoo_conf_leave(yd, gaim_conversation_get_name(conv), | |
2547 gaim_connection_get_display_name(gc), | |
2548 gaim_conv_chat_get_users(GAIM_CONV_CHAT(conv))); | |
2549 } | |
2550 g_slist_free(yd->confs); | |
6729 | 2551 |
6784 | 2552 g_hash_table_destroy(yd->friends); |
2553 if (yd->chat_name) | |
2554 g_free(yd->chat_name); | |
6729 | 2555 |
7651 | 2556 if (yd->cookie_y) |
2557 g_free(yd->cookie_y); | |
2558 if (yd->cookie_t) | |
2559 g_free(yd->cookie_t); | |
2560 | |
2681 | 2561 if (yd->fd >= 0) |
2562 close(yd->fd); | |
3720
34c95669952f
[gaim-migrate @ 3853]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3642
diff
changeset
|
2563 |
2681 | 2564 if (yd->rxqueue) |
2565 g_free(yd->rxqueue); | |
2687
2d544f48146d
[gaim-migrate @ 2700]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2686
diff
changeset
|
2566 yd->rxlen = 0; |
9306 | 2567 if (yd->picture_url) |
2568 g_free(yd->picture_url); | |
2569 if (yd->picture_upload_todo) | |
2570 yahoo_buddy_icon_upload_data_free(yd->picture_upload_todo); | |
9376 | 2571 if (yd->ycht) |
2572 ycht_connection_close(yd->ycht); | |
2681 | 2573 if (gc->inpa) |
2574 gaim_input_remove(gc->inpa); | |
2575 g_free(yd); | |
2576 } | |
2577 | |
6695 | 2578 static const char *yahoo_list_icon(GaimAccount *a, GaimBuddy *b) |
2681 | 2579 { |
4687 | 2580 return "yahoo"; |
2681 | 2581 } |
4916 | 2582 |
9972 | 2583 static void yahoo_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne) |
4916 | 2584 { |
2585 int i = 0; | |
2586 char *emblems[4] = {NULL,NULL,NULL,NULL}; | |
6784 | 2587 GaimAccount *account; |
2588 GaimConnection *gc; | |
2589 struct yahoo_data *yd; | |
9278 | 2590 YahooFriend *f; |
10126 | 2591 GaimPresence *presence; |
2592 GaimStatus *status; | |
2593 const char *status_id; | |
6784 | 2594 |
2595 if (!b || !(account = b->account) || !(gc = gaim_account_get_connection(account)) || | |
2596 !(yd = gc->proto_data)) | |
2597 return; | |
2598 | |
9279 | 2599 f = yahoo_friend_find(gc, b->name); |
6784 | 2600 if (!f) { |
2601 *se = "notauthorized"; | |
2602 return; | |
2603 } | |
2604 | |
10126 | 2605 presence = gaim_buddy_get_presence(b); |
2606 status = gaim_presence_get_active_status(presence); | |
2607 status_id = gaim_status_get_id(status); | |
2608 | |
2609 if (gaim_presence_is_online(presence) == FALSE) { | |
4916 | 2610 *se = "offline"; |
2611 return; | |
2612 } else { | |
6784 | 2613 if (f->away) |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
2614 emblems[i++] = "away"; |
6784 | 2615 if (f->sms) |
2616 emblems[i++] = "wireless"; | |
9283 | 2617 if (yahoo_friend_get_game(f)) |
4916 | 2618 emblems[i++] = "game"; |
2619 } | |
2620 *se = emblems[0]; | |
2621 *sw = emblems[1]; | |
2622 *nw = emblems[2]; | |
2623 *ne = emblems[3]; | |
2624 } | |
2681 | 2625 |
2626 static char *yahoo_get_status_string(enum yahoo_status a) | |
2627 { | |
2628 switch (a) { | |
2629 case YAHOO_STATUS_BRB: | |
4596 | 2630 return _("Be Right Back"); |
2681 | 2631 case YAHOO_STATUS_BUSY: |
4596 | 2632 return _("Busy"); |
2681 | 2633 case YAHOO_STATUS_NOTATHOME: |
4596 | 2634 return _("Not At Home"); |
2681 | 2635 case YAHOO_STATUS_NOTATDESK: |
4596 | 2636 return _("Not At Desk"); |
2681 | 2637 case YAHOO_STATUS_NOTINOFFICE: |
4596 | 2638 return _("Not In Office"); |
2681 | 2639 case YAHOO_STATUS_ONPHONE: |
4606 | 2640 return _("On The Phone"); |
2681 | 2641 case YAHOO_STATUS_ONVACATION: |
4596 | 2642 return _("On Vacation"); |
2681 | 2643 case YAHOO_STATUS_OUTTOLUNCH: |
4596 | 2644 return _("Out To Lunch"); |
2681 | 2645 case YAHOO_STATUS_STEPPEDOUT: |
4596 | 2646 return _("Stepped Out"); |
2873
26be84883f91
[gaim-migrate @ 2886]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2856
diff
changeset
|
2647 case YAHOO_STATUS_INVISIBLE: |
4596 | 2648 return _("Invisible"); |
4730 | 2649 case YAHOO_STATUS_IDLE: |
2650 return _("Idle"); | |
6784 | 2651 case YAHOO_STATUS_OFFLINE: |
2652 return _("Offline"); | |
2879
5fc5123b7098
[gaim-migrate @ 2892]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2878
diff
changeset
|
2653 default: |
4596 | 2654 return _("Online"); |
2681 | 2655 } |
2656 } | |
2657 | |
9030 | 2658 static void yahoo_initiate_conference(GaimBlistNode *node, gpointer data) { |
2659 | |
2660 GaimBuddy *buddy; | |
2661 GaimConnection *gc; | |
2662 | |
6729 | 2663 GHashTable *components; |
2664 struct yahoo_data *yd; | |
2665 int id; | |
2666 | |
9030 | 2667 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
2668 | |
2669 buddy = (GaimBuddy *) node; | |
2670 gc = gaim_account_get_connection(buddy->account); | |
6729 | 2671 yd = gc->proto_data; |
2672 id = yd->conf_id; | |
2673 | |
2674 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
2675 g_hash_table_replace(components, g_strdup("room"), | |
2676 g_strdup_printf("%s-%d", gaim_connection_get_display_name(gc), id)); | |
2677 g_hash_table_replace(components, g_strdup("topic"), g_strdup("Join my conference...")); | |
2678 g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference")); | |
2679 yahoo_c_join(gc, components); | |
2680 g_hash_table_destroy(components); | |
2681 | |
9030 | 2682 yahoo_c_invite(gc, id, "Join my conference...", buddy->name); |
6729 | 2683 } |
2684 | |
9030 | 2685 static void yahoo_game(GaimBlistNode *node, gpointer data) { |
2686 | |
2687 GaimBuddy *buddy; | |
2688 GaimConnection *gc; | |
2689 | |
2690 struct yahoo_data *yd; | |
9283 | 2691 const char *game; |
2692 char *game2; | |
3019 | 2693 char *t; |
2694 char url[256]; | |
9278 | 2695 YahooFriend *f; |
3019 | 2696 |
9030 | 2697 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
2698 | |
2699 buddy = (GaimBuddy *) node; | |
2700 gc = gaim_account_get_connection(buddy->account); | |
2701 yd = (struct yahoo_data *) gc->proto_data; | |
2702 | |
9279 | 2703 f = yahoo_friend_find(gc, buddy->name); |
6784 | 2704 if (!f) |
2705 return; | |
2706 | |
9283 | 2707 game = yahoo_friend_get_game(f); |
3019 | 2708 if (!game) |
2709 return; | |
6784 | 2710 |
9283 | 2711 t = game2 = g_strdup(strstr(game, "ante?room=")); |
2712 while (*t && *t != '\t') | |
3019 | 2713 t++; |
2714 *t = 0; | |
9283 | 2715 g_snprintf(url, sizeof url, "http://games.yahoo.com/games/%s", game2); |
10209
9e0b98c458b1
[gaim-migrate @ 11331]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
10195
diff
changeset
|
2716 gaim_notify_uri(gc, url, TRUE); |
9283 | 2717 g_free(game2); |
3019 | 2718 } |
4722 | 2719 |
6695 | 2720 static char *yahoo_status_text(GaimBuddy *b) |
4722 | 2721 { |
9278 | 2722 YahooFriend *f = NULL; |
9283 | 2723 const char *msg; |
6691
306790891ce7
[gaim-migrate @ 7217]
Christian Hammond <chipx86@chipx86.com>
parents:
6687
diff
changeset
|
2724 |
9279 | 2725 f = yahoo_friend_find(b->account->gc, b->name); |
6784 | 2726 if (!f) |
2727 return g_strdup(_("Not on server list")); | |
2728 | |
2729 switch (f->status) { | |
2730 case YAHOO_STATUS_AVAILABLE: | |
2731 return NULL; | |
2732 case YAHOO_STATUS_IDLE: | |
2733 if (f->idle == -1) | |
2734 return g_strdup(yahoo_get_status_string(f->status)); | |
2735 return NULL; | |
2736 case YAHOO_STATUS_CUSTOM: | |
9283 | 2737 if (!(msg = yahoo_friend_get_status_message(f))) |
6784 | 2738 return NULL; |
9283 | 2739 return g_markup_escape_text(msg, strlen(msg)); |
9224 | 2740 |
6784 | 2741 default: |
2742 return g_strdup(yahoo_get_status_string(f->status)); | |
2743 } | |
4722 | 2744 } |
2745 | |
9220 | 2746 char *yahoo_tooltip_text(GaimBuddy *b) |
4724 | 2747 { |
9278 | 2748 YahooFriend *f; |
6784 | 2749 char *escaped, *status, *ret; |
2750 | |
9279 | 2751 f = yahoo_friend_find(b->account->gc, b->name); |
6784 | 2752 if (!f) |
8591 | 2753 status = g_strdup_printf("\n%s", _("Not on server list")); |
6784 | 2754 else |
2755 switch (f->status) { | |
2756 case YAHOO_STATUS_IDLE: | |
2757 if (f->idle == -1) { | |
2758 status = g_strdup(yahoo_get_status_string(f->status)); | |
2759 break; | |
2760 } | |
2761 return NULL; | |
2762 case YAHOO_STATUS_CUSTOM: | |
9283 | 2763 if (!yahoo_friend_get_status_message(f)) |
6784 | 2764 return NULL; |
9283 | 2765 status = g_strdup(yahoo_friend_get_status_message(f)); |
6784 | 2766 break; |
2767 default: | |
2768 status = g_strdup(yahoo_get_status_string(f->status)); | |
2769 break; | |
4745 | 2770 } |
6784 | 2771 |
2772 escaped = g_markup_escape_text(status, strlen(status)); | |
8591 | 2773 ret = g_strdup_printf(_("\n<b>%s:</b> %s"), _("Status"), escaped); |
6784 | 2774 g_free(status); |
2775 g_free(escaped); | |
2776 | |
2777 return ret; | |
4729 | 2778 } |
2779 | |
9030 | 2780 static void yahoo_addbuddyfrommenu_cb(GaimBlistNode *node, gpointer data) |
2781 { | |
2782 GaimBuddy *buddy; | |
2783 GaimConnection *gc; | |
2784 | |
2785 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
2786 | |
2787 buddy = (GaimBuddy *) node; | |
2788 gc = gaim_account_get_connection(buddy->account); | |
2789 | |
9285 | 2790 yahoo_add_buddy(gc, buddy, NULL); |
9030 | 2791 } |
2792 | |
2793 | |
2794 static void yahoo_chat_goto_menu(GaimBlistNode *node, gpointer data) | |
6796 | 2795 { |
9030 | 2796 GaimBuddy *buddy; |
2797 GaimConnection *gc; | |
2798 | |
2799 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
2800 | |
2801 buddy = (GaimBuddy *) node; | |
2802 gc = gaim_account_get_connection(buddy->account); | |
2803 | |
2804 yahoo_chat_goto(gc, buddy->name); | |
6796 | 2805 } |
2806 | |
9030 | 2807 |
2808 static GList *yahoo_buddy_menu(GaimBuddy *buddy) | |
2681 | 2809 { |
2810 GList *m = NULL; | |
9030 | 2811 GaimBlistNodeAction *act; |
2812 | |
2813 GaimConnection *gc = gaim_account_get_connection(buddy->account); | |
9370 | 2814 struct yahoo_data *yd = gc->proto_data; |
3019 | 2815 static char buf2[1024]; |
9278 | 2816 YahooFriend *f; |
6784 | 2817 |
9279 | 2818 f = yahoo_friend_find(gc, buddy->name); |
6784 | 2819 |
9370 | 2820 if (!f && !yd->wm) { |
9030 | 2821 act = gaim_blist_node_action_new(_("Add Buddy"), |
2822 yahoo_addbuddyfrommenu_cb, NULL); | |
2823 m = g_list_append(m, act); | |
6784 | 2824 |
2825 return m; | |
9030 | 2826 |
2827 } else if (f->status == YAHOO_STATUS_OFFLINE) { | |
6784 | 2828 return NULL; |
9030 | 2829 } |
2830 | |
9370 | 2831 if (!yd->wm) { |
2832 act = gaim_blist_node_action_new(_("Join in Chat"), | |
2833 yahoo_chat_goto_menu, NULL); | |
2834 m = g_list_append(m, act); | |
2835 } | |
9030 | 2836 |
2837 act = gaim_blist_node_action_new(_("Initiate Conference"), | |
2838 yahoo_initiate_conference, NULL); | |
2839 m = g_list_append(m, act); | |
6729 | 2840 |
9283 | 2841 if (yahoo_friend_get_game(f)) { |
2842 const char *game = yahoo_friend_get_game(f); | |
3019 | 2843 char *room; |
6784 | 2844 char *t; |
2845 | |
2846 if (!(room = strstr(game, "&follow="))) /* skip ahead to the url */ | |
2847 return m; | |
2848 while (*room && *room != '\t') /* skip to the tab */ | |
2849 room++; | |
2850 t = room++; /* room as now at the name */ | |
2851 while (*t != '\n') | |
2852 t++; /* replace the \n with a space */ | |
2853 *t = ' '; | |
2854 g_snprintf(buf2, sizeof buf2, "%s", room); | |
9030 | 2855 |
2856 act = gaim_blist_node_action_new(buf2, yahoo_game, NULL); | |
2857 m = g_list_append(m, act); | |
3019 | 2858 } |
6729 | 2859 |
2681 | 2860 return m; |
2861 } | |
2862 | |
9030 | 2863 |
2864 static GList *yahoo_blist_node_menu(GaimBlistNode *node) | |
2865 { | |
2866 if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
2867 return yahoo_buddy_menu((GaimBuddy *) node); | |
2868 } else { | |
2869 return NULL; | |
2870 } | |
2871 } | |
2872 | |
2873 | |
5583 | 2874 static void yahoo_act_id(GaimConnection *gc, const char *entry) |
2681 | 2875 { |
2876 struct yahoo_data *yd = gc->proto_data; | |
2877 | |
2878 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, 0); | |
2879 yahoo_packet_hash(pkt, 3, entry); | |
2880 yahoo_send_packet(yd, pkt); | |
2881 yahoo_packet_free(pkt); | |
2882 | |
5583 | 2883 gaim_connection_set_display_name(gc, entry); |
2681 | 2884 } |
2885 | |
9015 | 2886 static void yahoo_show_act_id(GaimPluginAction *action) |
2681 | 2887 { |
9015 | 2888 GaimConnection *gc = (GaimConnection *) action->context; |
5493
3e8487580024
[gaim-migrate @ 5889]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
2889 gaim_request_input(gc, NULL, _("Active which ID?"), NULL, |
8697 | 2890 gaim_connection_get_display_name(gc), FALSE, FALSE, NULL, |
5493
3e8487580024
[gaim-migrate @ 5889]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
2891 _("OK"), G_CALLBACK(yahoo_act_id), |
3e8487580024
[gaim-migrate @ 5889]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
2892 _("Cancel"), NULL, gc); |
2681 | 2893 } |
2894 | |
9015 | 2895 static void yahoo_show_chat_goto(GaimPluginAction *action) |
7878 | 2896 { |
9015 | 2897 GaimConnection *gc = (GaimConnection *) action->context; |
7878 | 2898 gaim_request_input(gc, NULL, _("Join who in chat?"), NULL, |
8697 | 2899 "", FALSE, FALSE, NULL, |
7878 | 2900 _("OK"), G_CALLBACK(yahoo_chat_goto), |
2901 _("Cancel"), NULL, gc); | |
2902 } | |
2903 | |
9015 | 2904 static GList *yahoo_actions(GaimPlugin *plugin, gpointer context) { |
2681 | 2905 GList *m = NULL; |
9015 | 2906 GaimPluginAction *act; |
2907 | |
2908 act = gaim_plugin_action_new(_("Activate ID..."), | |
2909 yahoo_show_act_id); | |
2910 m = g_list_append(m, act); | |
2911 | |
2912 act = gaim_plugin_action_new(_("Join user in chat..."), | |
2913 yahoo_show_chat_goto); | |
2914 m = g_list_append(m, act); | |
7878 | 2915 |
2681 | 2916 return m; |
2917 } | |
2918 | |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
7112
diff
changeset
|
2919 static int yahoo_send_im(GaimConnection *gc, const char *who, const char *what, GaimConvImFlags flags) |
2681 | 2920 { |
2921 struct yahoo_data *yd = gc->proto_data; | |
2922 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0); | |
6629 | 2923 char *msg = yahoo_html_to_codes(what); |
7827 | 2924 char *msg2; |
2925 gboolean utf8 = TRUE; | |
9828 | 2926 int ret = 1; |
7827 | 2927 |
2928 msg2 = yahoo_string_encode(gc, msg, &utf8); | |
2681 | 2929 |
5583 | 2930 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); |
2681 | 2931 yahoo_packet_hash(pkt, 5, who); |
7827 | 2932 if (utf8) |
2933 yahoo_packet_hash(pkt, 97, "1"); | |
2934 yahoo_packet_hash(pkt, 14, msg2); | |
2935 | |
9280 | 2936 yahoo_packet_hash(pkt, 63, ";0"); /* IMvironment */ |
2937 yahoo_packet_hash(pkt, 64, "0"); /* no idea */ | |
9062 | 2938 yahoo_packet_hash(pkt, 1002, "1"); /* no idea, Yahoo 6 or later only it seems */ |
9306 | 2939 if (!yd->picture_url) |
2940 yahoo_packet_hash(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */ | |
2941 else | |
2942 yahoo_packet_hash(pkt, 206, "2"); | |
2681 | 2943 |
9828 | 2944 /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */ |
2945 if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) | |
2946 yahoo_send_packet(yd, pkt); | |
2947 else | |
2948 ret = -E2BIG; | |
2681 | 2949 |
2950 yahoo_packet_free(pkt); | |
6629 | 2951 |
2952 g_free(msg); | |
7827 | 2953 g_free(msg2); |
6629 | 2954 |
9828 | 2955 return ret; |
2681 | 2956 } |
2957 | |
6059 | 2958 int yahoo_send_typing(GaimConnection *gc, const char *who, int typ) |
2993 | 2959 { |
2960 struct yahoo_data *yd = gc->proto_data; | |
3019 | 2961 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, 0); |
2993 | 2962 yahoo_packet_hash(pkt, 49, "TYPING"); |
5583 | 2963 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); |
2993 | 2964 yahoo_packet_hash(pkt, 14, " "); |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
2965 yahoo_packet_hash(pkt, 13, typ == GAIM_TYPING ? "1" : "0"); |
2993 | 2966 yahoo_packet_hash(pkt, 5, who); |
2967 yahoo_packet_hash(pkt, 1002, "1"); | |
2968 | |
2969 yahoo_send_packet(yd, pkt); | |
2970 | |
2971 yahoo_packet_free(pkt); | |
2972 | |
3001 | 2973 return 0; |
2993 | 2974 } |
2975 | |
9984 | 2976 static void yahoo_set_status(GaimAccount *account, GaimStatus *status) |
2681 | 2977 { |
9984 | 2978 GaimConnection *gc = gaim_account_get_connection(account); |
2681 | 2979 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; |
2980 struct yahoo_packet *pkt; | |
2772
f9227268db25
[gaim-migrate @ 2785]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2771
diff
changeset
|
2981 int service; |
2681 | 2982 char s[4]; |
9984 | 2983 const char *id; |
7827 | 2984 char *conv_msg = NULL; |
8503 | 2985 char *conv_msg2 = NULL; |
9984 | 2986 gboolean away = FALSE; /* only for YAHOO_STATUS_CUSTOM */ |
2987 | |
2988 id = gaim_status_get_id(status); | |
2989 | |
2990 if (!strcmp(id, "available")) { | |
2991 yd->current_status = YAHOO_STATUS_AVAILABLE; | |
2992 } else if (!strcmp(id, "berightback")) { | |
2993 yd->current_status = YAHOO_STATUS_BRB; | |
2994 } else if (!strcmp(id, "busy")) { | |
2995 yd->current_status = YAHOO_STATUS_BUSY; | |
2996 } else if (!strcmp(id, "notathome")) { | |
2997 yd->current_status = YAHOO_STATUS_NOTATHOME; | |
2998 } else if (!strcmp(id,"notatdesk")) { | |
2999 yd->current_status = YAHOO_STATUS_NOTATDESK; | |
3000 } else if (!strcmp(id, "notinoffice")) { | |
3001 yd->current_status = YAHOO_STATUS_NOTINOFFICE; | |
3002 } else if (!strcmp(id, "onthephone")) { | |
3003 yd->current_status = YAHOO_STATUS_ONPHONE; | |
3004 } else if (!strcmp(id, "onvacation")) { | |
3005 yd->current_status = YAHOO_STATUS_ONVACATION; | |
3006 } else if (!strcmp(id, "outtolunch")) { | |
3007 yd->current_status = YAHOO_STATUS_OUTTOLUNCH; | |
3008 } else if (!strcmp(id, "steppedout")) { | |
3009 yd->current_status = YAHOO_STATUS_STEPPEDOUT; | |
3010 } else if (!strcmp(id, "invisible")) { | |
3011 yd->current_status = YAHOO_STATUS_INVISIBLE; | |
3012 } else if (!strcmp(id, "away")) { | |
2681 | 3013 yd->current_status = YAHOO_STATUS_CUSTOM; |
9984 | 3014 away = TRUE; |
3015 } else if (!strcmp(id, "avaiablewm")) { | |
3016 yd->current_status = YAHOO_STATUS_CUSTOM; | |
3017 away = FALSE; | |
3018 } else if (gc->is_idle) { /* i think this is broken */ | |
2681 | 3019 yd->current_status = YAHOO_STATUS_IDLE; |
3020 } else { | |
3021 yd->current_status = YAHOO_STATUS_AVAILABLE; | |
3022 } | |
3023 | |
9984 | 3024 if (yd->current_status == YAHOO_STATUS_AVAILABLE || |
3025 ((yd->current_status == YAHOO_STATUS_CUSTOM) && !away)) | |
2772
f9227268db25
[gaim-migrate @ 2785]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2771
diff
changeset
|
3026 service = YAHOO_SERVICE_ISBACK; |
f9227268db25
[gaim-migrate @ 2785]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2771
diff
changeset
|
3027 else |
f9227268db25
[gaim-migrate @ 2785]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2771
diff
changeset
|
3028 service = YAHOO_SERVICE_ISAWAY; |
6847 | 3029 |
3030 pkt = yahoo_packet_new(service, YAHOO_STATUS_AVAILABLE, 0); | |
2681 | 3031 g_snprintf(s, sizeof(s), "%d", yd->current_status); |
3032 yahoo_packet_hash(pkt, 10, s); | |
6847 | 3033 |
9984 | 3034 if (yd->current_status == YAHOO_STATUS_CUSTOM) { |
3035 const char *msg = gaim_status_get_attr_string(status, "message"); | |
10195 | 3036 |
3037 if (msg == NULL) { | |
3038 gaim_debug_info("yahoo", "Attempted to set a NULL status message.\n"); | |
3039 msg = ""; | |
3040 } | |
3041 | |
9984 | 3042 conv_msg = yahoo_string_encode(gc, msg, NULL); |
3043 conv_msg2 = gaim_markup_strip_html(conv_msg); | |
8503 | 3044 yahoo_packet_hash(pkt, 19, conv_msg2); |
9984 | 3045 |
6784 | 3046 if (gc->is_idle) |
3047 yahoo_packet_hash(pkt, 47, "2"); | |
9984 | 3048 else if (away) |
3049 yahoo_packet_hash(pkt, 47, "1"); | |
6784 | 3050 else |
9984 | 3051 yahoo_packet_hash(pkt, 47, "0"); |
3052 } else if (gc->is_idle) { | |
3053 yahoo_packet_hash(pkt, 47, "2"); | |
6686 | 3054 } |
2681 | 3055 |
3056 yahoo_send_packet(yd, pkt); | |
3057 yahoo_packet_free(pkt); | |
9984 | 3058 |
3059 g_free(conv_msg); | |
3060 g_free(conv_msg2); | |
2681 | 3061 } |
3062 | |
5583 | 3063 static void yahoo_set_idle(GaimConnection *gc, int idle) |
2681 | 3064 { |
9984 | 3065 #if 0 |
3066 /* this is complicated, since it interacts with other statuses */ | |
2681 | 3067 struct yahoo_data *yd = gc->proto_data; |
3068 struct yahoo_packet *pkt = NULL; | |
8503 | 3069 char *msg = NULL, *msg2 = NULL; |
2681 | 3070 |
3071 if (idle && yd->current_status == YAHOO_STATUS_AVAILABLE) { | |
6847 | 3072 pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_AVAILABLE, 0); |
2681 | 3073 yd->current_status = YAHOO_STATUS_IDLE; |
3074 } else if (!idle && yd->current_status == YAHOO_STATUS_IDLE) { | |
3075 pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_AVAILABLE, 0); | |
3076 yd->current_status = YAHOO_STATUS_AVAILABLE; | |
6847 | 3077 } else { |
6784 | 3078 pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_AVAILABLE, 0); |
2681 | 3079 } |
3080 | |
3081 if (pkt) { | |
3082 char buf[4]; | |
3083 g_snprintf(buf, sizeof(buf), "%d", yd->current_status); | |
3084 yahoo_packet_hash(pkt, 10, buf); | |
6784 | 3085 if (gc->away && yd->current_status == YAHOO_STATUS_CUSTOM) { |
7827 | 3086 msg = yahoo_string_encode(gc, gc->away, NULL); |
8503 | 3087 msg2 = gaim_unescape_html(msg); |
3088 yahoo_packet_hash(pkt, 19, msg2); | |
6784 | 3089 if (idle) |
3090 yahoo_packet_hash(pkt, 47, "2"); | |
3091 else | |
3092 yahoo_packet_hash(pkt, 47, "1"); /* fixme when available messages are possible */ | |
6847 | 3093 } else if (idle && (yd->current_status != YAHOO_STATUS_AVAILABLE) && |
3094 (yd->current_status != YAHOO_STATUS_IDLE)) { | |
3095 yahoo_packet_hash(pkt, 47, "2"); | |
3096 } else if (!idle && (yd->current_status != YAHOO_STATUS_AVAILABLE) && | |
3097 (yd->current_status != YAHOO_STATUS_IDLE)) { | |
3098 yahoo_packet_hash(pkt, 47, "1"); | |
6784 | 3099 } |
6847 | 3100 |
2681 | 3101 yahoo_send_packet(yd, pkt); |
3102 yahoo_packet_free(pkt); | |
3103 } | |
7827 | 3104 if (msg) |
3105 g_free(msg); | |
8503 | 3106 if (msg2) |
3107 g_free(msg2); | |
9984 | 3108 #endif |
2681 | 3109 } |
3110 | |
9979 | 3111 static GList *yahoo_status_types(GaimAccount *account) |
2681 | 3112 { |
9979 | 3113 GaimConnection *gc = gaim_account_get_connection(account); |
3114 struct yahoo_data *yd = NULL; | |
3115 GaimStatusType *type; | |
3116 GList *types = NULL; | |
3117 | |
3118 if (gc) | |
3119 yd = gc->proto_data; | |
3120 | |
3121 type = gaim_status_type_new(GAIM_STATUS_OFFLINE, "offline", _("Offline"), FALSE); | |
3122 types = g_list_append(types, type); | |
3123 | |
3124 type = gaim_status_type_new(GAIM_STATUS_ONLINE, "online", _("Online"), FALSE); | |
3125 types = g_list_append(types, type); | |
3126 | |
3127 type = gaim_status_type_new(GAIM_STATUS_AVAILABLE, "available", _("Available"), TRUE); | |
3128 types = g_list_append(types, type); | |
3129 | |
3130 if (!yd || !yd->wm) { | |
3131 type = gaim_status_type_new_with_attrs(GAIM_STATUS_AVAILABLE, "available-wm", | |
3132 "Available With Message", TRUE, TRUE, FALSE, | |
3133 "message", _("Message"), | |
10009 | 3134 gaim_value_new(GAIM_TYPE_STRING), NULL); |
9979 | 3135 types = g_list_append(types, type); |
3136 | |
3137 | |
3138 type = gaim_status_type_new(GAIM_STATUS_AWAY, "brb", _("Be Right Back"), TRUE); | |
3139 types = g_list_append(types, type); | |
3140 | |
3141 type = gaim_status_type_new(GAIM_STATUS_AWAY, "busy", _("Busy"), TRUE); | |
3142 types = g_list_append(types, type); | |
3143 | |
3144 type = gaim_status_type_new(GAIM_STATUS_AWAY, "notathome", _("Not At Home"), TRUE); | |
3145 types = g_list_append(types, type); | |
3146 | |
3147 type = gaim_status_type_new(GAIM_STATUS_AWAY, "notatdesk", _("Not At Desk"), TRUE); | |
3148 types = g_list_append(types, type); | |
3149 | |
3150 type = gaim_status_type_new(GAIM_STATUS_AWAY, "notinoffice", _("Not In Office"), TRUE); | |
3151 types = g_list_append(types, type); | |
3152 | |
3153 type = gaim_status_type_new(GAIM_STATUS_AWAY, "onthephone", _("On The Phone"), TRUE); | |
3154 types = g_list_append(types, type); | |
3155 | |
3156 type = gaim_status_type_new(GAIM_STATUS_AWAY, "onvacation", _("On Vacation"), TRUE); | |
3157 types = g_list_append(types, type); | |
3158 | |
3159 type = gaim_status_type_new(GAIM_STATUS_AWAY, "outtolunch", _("Out To Lunch"), TRUE); | |
3160 types = g_list_append(types, type); | |
3161 | |
3162 type = gaim_status_type_new(GAIM_STATUS_AWAY, "steppedout", _("Stepped Out"), TRUE); | |
3163 types = g_list_append(types, type); | |
3164 | |
3165 type = gaim_status_type_new_with_attrs(GAIM_STATUS_AWAY, "away", | |
10195 | 3166 _("Away"), TRUE, TRUE, FALSE, |
9979 | 3167 "message", _("Message"), |
10009 | 3168 gaim_value_new(GAIM_TYPE_STRING), NULL); |
9979 | 3169 types = g_list_append(types, type); |
9370 | 3170 } |
9979 | 3171 type = gaim_status_type_new(GAIM_STATUS_HIDDEN, "invisible", _("Invisible"), TRUE); |
3172 types = g_list_append(types, type); | |
3173 | |
3174 | |
3175 return types; | |
2681 | 3176 } |
3177 | |
5583 | 3178 static void yahoo_keepalive(GaimConnection *gc) |
2681 | 3179 { |
3180 struct yahoo_data *yd = gc->proto_data; | |
3181 struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, 0); | |
3182 yahoo_send_packet(yd, pkt); | |
3183 yahoo_packet_free(pkt); | |
6729 | 3184 |
3185 if (!yd->chat_online) | |
3186 return; | |
3187 | |
9376 | 3188 if (yd->wm) { |
3189 ycht_chat_send_keepalive(yd->ycht); | |
3190 return; | |
3191 } | |
3192 | |
6729 | 3193 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, 0); |
3194 yahoo_packet_hash(pkt, 109, gaim_connection_get_display_name(gc)); | |
3195 yahoo_send_packet(yd, pkt); | |
3196 yahoo_packet_free(pkt); | |
2681 | 3197 } |
3198 | |
9285 | 3199 /* XXX - What's the deal with GaimGroup *foo? */ |
3200 static void yahoo_add_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *foo) | |
2681 | 3201 { |
3202 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; | |
3203 struct yahoo_packet *pkt; | |
6695 | 3204 GaimGroup *g; |
2681 | 3205 char *group = NULL; |
7829 | 3206 char *group2 = NULL; |
2681 | 3207 |
3208 if (!yd->logged_in) | |
3209 return; | |
3210 | |
6840 | 3211 if (foo) |
3212 group = foo->name; | |
3213 if (!group) { | |
9285 | 3214 g = gaim_find_buddys_group(gaim_find_buddy(gc->account, buddy->name)); |
6840 | 3215 if (g) |
3216 group = g->name; | |
3217 else | |
3218 group = "Buddies"; | |
3219 } | |
2681 | 3220 |
7829 | 3221 group2 = yahoo_string_encode(gc, group, NULL); |
2681 | 3222 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); |
5583 | 3223 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); |
9285 | 3224 yahoo_packet_hash(pkt, 7, buddy->name); |
7829 | 3225 yahoo_packet_hash(pkt, 65, group2); |
6820 | 3226 yahoo_packet_hash(pkt, 14, ""); |
2681 | 3227 yahoo_send_packet(yd, pkt); |
3228 yahoo_packet_free(pkt); | |
7829 | 3229 g_free(group2); |
2681 | 3230 } |
3231 | |
9285 | 3232 static void yahoo_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) |
2681 | 3233 { |
3234 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; | |
9278 | 3235 YahooFriend *f; |
6795
40ba19133882
[gaim-migrate @ 7334]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
6793
diff
changeset
|
3236 struct yahoo_packet *pkt; |
6840 | 3237 GSList *buddies, *l; |
3238 GaimGroup *g; | |
3239 gboolean remove = TRUE; | |
7827 | 3240 char *cg; |
6784 | 3241 |
9285 | 3242 if (!(f = yahoo_friend_find(gc, buddy->name))) |
6784 | 3243 return; |
3244 | |
9285 | 3245 buddies = gaim_find_buddies(gaim_connection_get_account(gc), buddy->name); |
6840 | 3246 for (l = buddies; l; l = l->next) { |
3247 g = gaim_find_buddys_group(l->data); | |
9285 | 3248 if (gaim_utf8_strcasecmp(group->name, g->name)) { |
6840 | 3249 remove = FALSE; |
3250 break; | |
3251 } | |
3252 } | |
3253 | |
3254 g_slist_free(buddies); | |
3255 | |
3256 if (remove) | |
9285 | 3257 g_hash_table_remove(yd->friends, buddy->name); |
3258 | |
3259 cg = yahoo_string_encode(gc, group->name, NULL); | |
6795
40ba19133882
[gaim-migrate @ 7334]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
6793
diff
changeset
|
3260 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); |
5583 | 3261 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); |
9285 | 3262 yahoo_packet_hash(pkt, 7, buddy->name); |
7827 | 3263 yahoo_packet_hash(pkt, 65, cg); |
2681 | 3264 yahoo_send_packet(yd, pkt); |
3265 yahoo_packet_free(pkt); | |
7827 | 3266 g_free(cg); |
2681 | 3267 } |
3268 | |
6760 | 3269 static void yahoo_add_deny(GaimConnection *gc, const char *who) { |
3270 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; | |
3271 struct yahoo_packet *pkt; | |
3272 | |
3273 if (!yd->logged_in) | |
3274 return; | |
8057 | 3275 /* It seems to work better without this */ |
3276 | |
8113 | 3277 /* if (gc->account->perm_deny != 4) |
3278 return; */ | |
3279 | |
3280 if (!who || who[0] == '\0') | |
3281 return; | |
3282 | |
6760 | 3283 pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, 0); |
3284 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); | |
3285 yahoo_packet_hash(pkt, 7, who); | |
3286 yahoo_packet_hash(pkt, 13, "1"); | |
3287 yahoo_send_packet(yd, pkt); | |
3288 yahoo_packet_free(pkt); | |
3289 } | |
3290 | |
3291 static void yahoo_rem_deny(GaimConnection *gc, const char *who) { | |
3292 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; | |
3293 struct yahoo_packet *pkt; | |
3294 | |
3295 if (!yd->logged_in) | |
3296 return; | |
3297 | |
3298 if (!who || who[0] == '\0') | |
3299 return; | |
3300 | |
3301 pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, 0); | |
3302 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); | |
3303 yahoo_packet_hash(pkt, 7, who); | |
3304 yahoo_packet_hash(pkt, 13, "2"); | |
3305 yahoo_send_packet(yd, pkt); | |
3306 yahoo_packet_free(pkt); | |
3307 } | |
3308 | |
3309 static void yahoo_set_permit_deny(GaimConnection *gc) { | |
3310 GaimAccount *acct; | |
3311 GSList *deny; | |
3312 | |
3313 acct = gc->account; | |
3314 | |
3315 switch (acct->perm_deny) { | |
10105 | 3316 /* privacy 1 */ |
3317 case GAIM_PRIVACY_ALLOW_ALL: | |
10143 | 3318 for (deny = acct->deny;deny;deny = deny->next) |
3319 yahoo_rem_deny(gc, deny->data); | |
3320 break; | |
10105 | 3321 /* privacy 3 */ |
3322 case GAIM_PRIVACY_ALLOW_USERS: | |
6760 | 3323 for (deny = acct->deny;deny;deny = deny->next) |
3324 yahoo_rem_deny(gc, deny->data); | |
3325 break; | |
10105 | 3326 /* privacy 5 */ |
3327 case GAIM_PRIVACY_ALLOW_BUDDYLIST: | |
3328 /* privacy 4 */ | |
3329 case GAIM_PRIVACY_DENY_USERS: | |
6760 | 3330 for (deny = acct->deny;deny;deny = deny->next) |
3331 yahoo_add_deny(gc, deny->data); | |
3332 break; | |
10105 | 3333 /* privacy 2 */ |
3334 case GAIM_PRIVACY_DENY_ALL: | |
6760 | 3335 default: |
3336 break; | |
3337 } | |
3338 } | |
3339 | |
6513 | 3340 static gboolean yahoo_unload_plugin(GaimPlugin *plugin) |
3341 { | |
3342 yahoo_dest_colorht(); | |
3343 return TRUE; | |
3344 } | |
3345 | |
6793 | 3346 static void yahoo_change_buddys_group(GaimConnection *gc, const char *who, |
3347 const char *old_group, const char *new_group) | |
3348 { | |
3349 struct yahoo_data *yd = gc->proto_data; | |
3350 struct yahoo_packet *pkt; | |
7827 | 3351 char *gpn, *gpo; |
6793 | 3352 |
3353 /* Step 0: If they aren't on the server list anyway, | |
3354 * don't bother letting the server know. | |
3355 */ | |
9279 | 3356 if (!yahoo_friend_find(gc, who)) |
6793 | 3357 return; |
3358 | |
7827 | 3359 /* If old and new are the same, we would probably |
3360 * end up deleting the buddy, which would be bad. | |
3361 * This might happen because of the charset conversation. | |
3362 */ | |
3363 gpn = yahoo_string_encode(gc, new_group, NULL); | |
3364 gpo = yahoo_string_encode(gc, old_group, NULL); | |
3365 if (!strcmp(gpn, gpo)) { | |
3366 g_free(gpn); | |
3367 g_free(gpo); | |
3368 return; | |
3369 } | |
3370 | |
6793 | 3371 /* Step 1: Add buddy to new group. */ |
3372 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); | |
3373 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); | |
3374 yahoo_packet_hash(pkt, 7, who); | |
7827 | 3375 yahoo_packet_hash(pkt, 65, gpn); |
6793 | 3376 yahoo_packet_hash(pkt, 14, ""); |
3377 yahoo_send_packet(yd, pkt); | |
3378 yahoo_packet_free(pkt); | |
3379 | |
3380 /* Step 2: Remove buddy from old group */ | |
3381 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); | |
3382 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); | |
3383 yahoo_packet_hash(pkt, 7, who); | |
7827 | 3384 yahoo_packet_hash(pkt, 65, gpo); |
6793 | 3385 yahoo_send_packet(yd, pkt); |
3386 yahoo_packet_free(pkt); | |
7827 | 3387 g_free(gpn); |
3388 g_free(gpo); | |
6793 | 3389 } |
3390 | |
9285 | 3391 static void yahoo_rename_group(GaimConnection *gc, const char *old_name, |
3392 GaimGroup *group, GList *moved_buddies) | |
6793 | 3393 { |
3394 struct yahoo_data *yd = gc->proto_data; | |
3395 struct yahoo_packet *pkt; | |
7827 | 3396 char *gpn, *gpo; |
3397 | |
9285 | 3398 gpn = yahoo_string_encode(gc, group->name, NULL); |
3399 gpo = yahoo_string_encode(gc, old_name, NULL); | |
7827 | 3400 if (!strcmp(gpn, gpo)) { |
3401 g_free(gpn); | |
3402 g_free(gpo); | |
3403 return; | |
3404 } | |
6793 | 3405 |
3406 pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, YAHOO_STATUS_AVAILABLE, 0); | |
3407 yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); | |
7827 | 3408 yahoo_packet_hash(pkt, 65, gpo); |
3409 yahoo_packet_hash(pkt, 67, gpn); | |
6793 | 3410 yahoo_send_packet(yd, pkt); |
3411 yahoo_packet_free(pkt); | |
7827 | 3412 g_free(gpn); |
3413 g_free(gpo); | |
6793 | 3414 } |
3415 | |
10119 | 3416 static GaimCmdRet |
3417 yahoogaim_cmd_buzz(GaimConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data) { | |
3418 | |
3419 GaimAccount *account = gaim_conversation_get_account(c); | |
3420 const char *username = gaim_account_get_username(account); | |
3421 | |
3422 if (*args && args[0]) | |
3423 return GAIM_CMD_RET_FAILED; | |
3424 | |
3425 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | |
3426 "Sending <ding> on account %s to buddy %s.\n", username, c->name); | |
3427 gaim_conv_im_send(GAIM_CONV_IM(c), "<ding>"); | |
3428 gaim_conv_im_write(GAIM_CONV_IM(c), "", _("Buzz!!"), GAIM_MESSAGE_NICK|GAIM_MESSAGE_RECV, time(NULL)); | |
3429 return GAIM_CMD_RET_OK; | |
3430 } | |
3431 | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3432 static GaimPlugin *my_protocol = NULL; |
2681 | 3433 |
10119 | 3434 /********************************* Commands **********************************/ |
3435 | |
3436 static GaimCmdRet | |
3437 yahoogaim_cmd_chat_join(GaimConversation *conv, const char *cmd, | |
3438 char **args, char **error, void *data) | |
3439 { | |
3440 GHashTable *comp; | |
3441 GaimConnection *gc; | |
3442 struct yahoo_data *yd; | |
3443 int id; | |
3444 | |
3445 if (!args || !args[0]) | |
3446 return GAIM_CMD_RET_FAILED; | |
3447 | |
3448 gc = gaim_conversation_get_gc(conv); | |
3449 yd = gc->proto_data; | |
3450 id = yd->conf_id; | |
3451 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | |
3452 "Trying to join %s \n", args[0]); | |
3453 | |
3454 comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
3455 g_hash_table_replace(comp, g_strdup("room"), | |
3456 g_strdup_printf("%s", g_ascii_strdown(args[0], strlen(args[0])))); | |
3457 g_hash_table_replace(comp, g_strdup("type"), g_strdup("Chat")); | |
3458 | |
3459 yahoo_c_join(gc, comp); | |
3460 | |
3461 g_hash_table_destroy(comp); | |
3462 return GAIM_CMD_RET_OK; | |
3463 } | |
3464 /************************** Plugin Initialization ****************************/ | |
3465 static void | |
3466 yahoogaim_register_commands(void) | |
3467 { | |
3468 gaim_cmd_register("join", "s", GAIM_CMD_P_PRPL, | |
3469 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT | | |
3470 GAIM_CMD_FLAG_PRPL_ONLY, | |
3471 "prpl-yahoo", yahoogaim_cmd_chat_join, | |
3472 _("join <room>: Join a chat room on the Yahoo network"), NULL); | |
10121 | 3473 gaim_cmd_register("buzz", "", GAIM_CMD_P_PRPL, |
10119 | 3474 GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_PRPL_ONLY, |
3475 "prpl-yahoo", yahoogaim_cmd_buzz, | |
3476 _("buzz: Buzz a contact to get their attention"), NULL); | |
3477 } | |
3478 | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3479 static GaimPluginProtocolInfo prpl_info = |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3480 { |
9308 | 3481 OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC, |
6729 | 3482 NULL, /* user_splits */ |
3483 NULL, /* protocol_options */ | |
9318 | 3484 {"png", 96, 96, 96, 96, GAIM_ICON_SCALE_SEND}, |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3485 yahoo_list_icon, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3486 yahoo_list_emblems, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3487 yahoo_status_text, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3488 yahoo_tooltip_text, |
9979 | 3489 yahoo_status_types, |
9030 | 3490 yahoo_blist_node_menu, |
6729 | 3491 yahoo_c_info, |
9768 | 3492 yahoo_c_info_defaults, |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3493 yahoo_login, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3494 yahoo_close, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3495 yahoo_send_im, |
6729 | 3496 NULL, /* set info */ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3497 yahoo_send_typing, |
6514 | 3498 yahoo_get_info, |
9984 | 3499 yahoo_set_status, |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3500 yahoo_set_idle, |
6729 | 3501 NULL, /* change_passwd*/ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3502 yahoo_add_buddy, |
6729 | 3503 NULL, /* add_buddies */ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3504 yahoo_remove_buddy, |
6729 | 3505 NULL, /*remove_buddies */ |
3506 NULL, /* add_permit */ | |
6760 | 3507 yahoo_add_deny, |
6729 | 3508 NULL, /* rem_permit */ |
6760 | 3509 yahoo_rem_deny, |
3510 yahoo_set_permit_deny, | |
6729 | 3511 NULL, /* warn */ |
3512 yahoo_c_join, | |
8562 | 3513 NULL, /* reject chat invite */ |
9917 | 3514 yahoo_get_chat_name, |
6729 | 3515 yahoo_c_invite, |
3516 yahoo_c_leave, | |
3517 NULL, /* chat whisper */ | |
3518 yahoo_c_send, | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3519 yahoo_keepalive, |
6729 | 3520 NULL, /* register_user */ |
3521 NULL, /* get_cb_info */ | |
3522 NULL, /* get_cb_away */ | |
3523 NULL, /* alias_buddy */ | |
6793 | 3524 yahoo_change_buddys_group, |
3525 yahoo_rename_group, | |
6729 | 3526 NULL, /* buddy_free */ |
3527 NULL, /* convo_closed */ | |
3528 NULL, /* normalize */ | |
9306 | 3529 yahoo_set_buddy_icon, |
7651 | 3530 NULL, /* void (*remove_group)(GaimConnection *gc, const char *group);*/ |
3531 NULL, /* char *(*get_cb_real_name)(GaimConnection *gc, int id, const char *who); */ | |
9475 | 3532 NULL, /* set_chat_topic */ |
3533 NULL, /* find_blist_chat */ | |
8113 | 3534 yahoo_roomlist_get_list, |
3535 yahoo_roomlist_cancel, | |
9466 | 3536 yahoo_roomlist_expand_category, |
9475 | 3537 NULL, /* can_receive_file */ |
9466 | 3538 yahoo_send_file |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3539 }; |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3540 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3541 static GaimPluginInfo info = |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3542 { |
9943 | 3543 GAIM_PLUGIN_MAGIC, |
3544 GAIM_MAJOR_VERSION, | |
3545 GAIM_MINOR_VERSION, | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3546 GAIM_PLUGIN_PROTOCOL, /**< type */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3547 NULL, /**< ui_requirement */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3548 0, /**< flags */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3549 NULL, /**< dependencies */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3550 GAIM_PRIORITY_DEFAULT, /**< priority */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3551 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3552 "prpl-yahoo", /**< id */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3553 "Yahoo", /**< name */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3554 VERSION, /**< version */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3555 /** summary */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3556 N_("Yahoo Protocol Plugin"), |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3557 /** description */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3558 N_("Yahoo Protocol Plugin"), |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3559 NULL, /**< author */ |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3560 GAIM_WEBSITE, /**< homepage */ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3561 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3562 NULL, /**< load */ |
6513 | 3563 yahoo_unload_plugin, /**< unload */ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3564 NULL, /**< destroy */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3565 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3566 NULL, /**< ui_info */ |
8993 | 3567 &prpl_info, /**< extra_info */ |
3568 NULL, | |
9015 | 3569 yahoo_actions |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3570 }; |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3571 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3572 static void |
5920
7d385de2f9cd
[gaim-migrate @ 6360]
Christian Hammond <chipx86@chipx86.com>
parents:
5872
diff
changeset
|
3573 init_plugin(GaimPlugin *plugin) |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3574 { |
5638
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5590
diff
changeset
|
3575 GaimAccountOption *option; |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3576 |
9164 | 3577 option = gaim_account_option_bool_new(_("Yahoo Japan"), "yahoojp", FALSE); |
3578 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3579 | |
7827 | 3580 option = gaim_account_option_string_new(_("Pager host"), "server", YAHOO_PAGER_HOST); |
3581 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3582 | |
9164 | 3583 option = gaim_account_option_string_new(_("Japan Pager host"), "serverjp", YAHOOJP_PAGER_HOST); |
3584 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3585 | |
7827 | 3586 option = gaim_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT); |
3587 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
7651 | 3588 |
3589 option = gaim_account_option_string_new(_("File transfer host"), "xfer_host", YAHOO_XFER_HOST); | |
3590 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3591 | |
9164 | 3592 option = gaim_account_option_string_new(_("Japan File transfer host"), "xferjp_host", YAHOOJP_XFER_HOST); |
3593 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3594 | |
7651 | 3595 option = gaim_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT); |
3596 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3597 | |
8113 | 3598 option = gaim_account_option_string_new(_("Chat Room List Url"), "room_list", YAHOO_ROOMLIST_URL); |
3599 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
9376 | 3600 #if 0 |
3601 option = gaim_account_option_string_new(_("YCHT Host"), "ycht-server", YAHOO_YCHT_HOST); | |
3602 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3603 | |
3604 option = gaim_account_option_int_new(_("YCHT Port"), "ycht-port", YAHOO_YCHT_PORT); | |
3605 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
3606 #endif | |
3607 | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3608 my_protocol = plugin; |
10119 | 3609 yahoogaim_register_commands(); |
6513 | 3610 yahoo_init_colorht(); |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3611 } |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5136
diff
changeset
|
3612 |
5920
7d385de2f9cd
[gaim-migrate @ 6360]
Christian Hammond <chipx86@chipx86.com>
parents:
5872
diff
changeset
|
3613 GAIM_INIT_PLUGIN(yahoo, init_plugin, info); |