Mercurial > pidgin.yaz
comparison src/protocols/yahoo/yahoo_packet.c @ 10392:a8f9e5ce4f92
[gaim-migrate @ 11620]
a little bit of clean up and reorganization of the yahoo prpl.
I moved the packet functions to their own file, renamed a couple of them,
added a convience function and used it a lot. I plan on adding several
more convience functions.
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Thu, 16 Dec 2004 21:47:54 +0000 |
parents | |
children | 45a0a07e8b25 |
comparison
equal
deleted
inserted
replaced
10391:38256d3e8324 | 10392:a8f9e5ce4f92 |
---|---|
1 /* | |
2 * gaim | |
3 * | |
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. | |
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 */ | |
23 | |
24 #include "internal.h" | |
25 #include "debug.h" | |
26 | |
27 #include "yahoo.h" | |
28 #include "yahoo_packet.h" | |
29 | |
30 struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id) | |
31 { | |
32 struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1); | |
33 | |
34 pkt->service = service; | |
35 pkt->status = status; | |
36 pkt->id = id; | |
37 | |
38 return pkt; | |
39 } | |
40 | |
41 void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value) | |
42 { | |
43 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); | |
44 pair->key = key; | |
45 pair->value = g_strdup(value); | |
46 pkt->hash = g_slist_append(pkt->hash, pair); | |
47 } | |
48 | |
49 int yahoo_packet_length(struct yahoo_packet *pkt) | |
50 { | |
51 GSList *l; | |
52 | |
53 int len = 0; | |
54 | |
55 l = pkt->hash; | |
56 while (l) { | |
57 struct yahoo_pair *pair = l->data; | |
58 int tmp = pair->key; | |
59 do { | |
60 tmp /= 10; | |
61 len++; | |
62 } while (tmp); | |
63 len += 2; | |
64 len += strlen(pair->value); | |
65 len += 2; | |
66 l = l->next; | |
67 } | |
68 | |
69 return len; | |
70 } | |
71 | |
72 void yahoo_packet_read(struct yahoo_packet *pkt, guchar *data, int len) | |
73 { | |
74 int pos = 0; | |
75 | |
76 while (pos + 1 < len) { | |
77 char key[64], *value = NULL, *esc; | |
78 int accept; | |
79 int x; | |
80 | |
81 struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1); | |
82 | |
83 /* this is weird, and in one of the chat packets, and causes us | |
84 * think all the values are keys and all the keys are values after | |
85 * this point if we don't handle it */ | |
86 if (data[pos] == '\0') { | |
87 while (pos + 1 < len) { | |
88 if (data[pos] == 0xc0 && data[pos + 1] == 0x80) | |
89 break; | |
90 pos++; | |
91 } | |
92 pos += 2; | |
93 g_free(pair); | |
94 continue; | |
95 } | |
96 | |
97 x = 0; | |
98 while (pos + 1 < len) { | |
99 if (data[pos] == 0xc0 && data[pos + 1] == 0x80) | |
100 break; | |
101 if (x >= sizeof(key)-1) { | |
102 x++; | |
103 pos++; | |
104 continue; | |
105 } | |
106 key[x++] = data[pos++]; | |
107 } | |
108 if (x >= sizeof(key)-1) { | |
109 x = 0; | |
110 } | |
111 key[x] = 0; | |
112 pos += 2; | |
113 pair->key = strtol(key, NULL, 10); | |
114 accept = x; /* if x is 0 there was no key, so don't accept it */ | |
115 | |
116 if (len - pos + 1 <= 0) { | |
117 /* Truncated. Garbage or something. */ | |
118 accept = 0; | |
119 } | |
120 | |
121 if (accept) { | |
122 value = g_malloc(len - pos + 1); | |
123 x = 0; | |
124 while (pos + 1 < len) { | |
125 if (data[pos] == 0xc0 && data[pos + 1] == 0x80) | |
126 break; | |
127 value[x++] = data[pos++]; | |
128 } | |
129 value[x] = 0; | |
130 pair->value = g_strdup(value); | |
131 g_free(value); | |
132 pkt->hash = g_slist_append(pkt->hash, pair); | |
133 esc = g_strescape(pair->value, NULL); | |
134 gaim_debug(GAIM_DEBUG_MISC, "yahoo", | |
135 "Key: %d \tValue: %s\n", pair->key, esc); | |
136 g_free(esc); | |
137 } else { | |
138 g_free(pair); | |
139 } | |
140 pos += 2; | |
141 | |
142 /* Skip over garbage we've noticed in the mail notifications */ | |
143 if (data[0] == '9' && data[pos] == 0x01) | |
144 pos++; | |
145 } | |
146 } | |
147 | |
148 void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data) | |
149 { | |
150 GSList *l = pkt->hash; | |
151 int pos = 0; | |
152 | |
153 while (l) { | |
154 struct yahoo_pair *pair = l->data; | |
155 guchar buf[100]; | |
156 | |
157 g_snprintf(buf, sizeof(buf), "%d", pair->key); | |
158 strcpy(data + pos, buf); | |
159 pos += strlen(buf); | |
160 data[pos++] = 0xc0; | |
161 data[pos++] = 0x80; | |
162 | |
163 strcpy(data + pos, pair->value); | |
164 pos += strlen(pair->value); | |
165 data[pos++] = 0xc0; | |
166 data[pos++] = 0x80; | |
167 | |
168 l = l->next; | |
169 } | |
170 } | |
171 | |
172 void yahoo_packet_dump(guchar *data, int len) | |
173 { | |
174 #ifdef YAHOO_DEBUG | |
175 int i; | |
176 | |
177 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); | |
178 | |
179 for (i = 0; i + 1 < len; i += 2) { | |
180 if ((i % 16 == 0) && i) { | |
181 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); | |
182 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); | |
183 } | |
184 | |
185 gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x%02x ", data[i], data[i + 1]); | |
186 } | |
187 if (i < len) | |
188 gaim_debug(GAIM_DEBUG_MISC, NULL, "%02x", data[i]); | |
189 | |
190 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); | |
191 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); | |
192 | |
193 for (i = 0; i < len; i++) { | |
194 if ((i % 16 == 0) && i) { | |
195 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); | |
196 gaim_debug(GAIM_DEBUG_MISC, "yahoo", ""); | |
197 } | |
198 | |
199 if (g_ascii_isprint(data[i])) | |
200 gaim_debug(GAIM_DEBUG_MISC, NULL, "%c ", data[i]); | |
201 else | |
202 gaim_debug(GAIM_DEBUG_MISC, NULL, ". "); | |
203 } | |
204 | |
205 gaim_debug(GAIM_DEBUG_MISC, NULL, "\n"); | |
206 #endif | |
207 } | |
208 | |
209 int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd) | |
210 { | |
211 int pktlen = yahoo_packet_length(pkt); | |
212 int len = YAHOO_PACKET_HDRLEN + pktlen; | |
213 int ret; | |
214 | |
215 guchar *data; | |
216 int pos = 0; | |
217 | |
218 if (yd->fd < 0) | |
219 return -1; | |
220 | |
221 data = g_malloc0(len + 1); | |
222 | |
223 memcpy(data + pos, "YMSG", 4); pos += 4; | |
224 | |
225 if (yd->wm) | |
226 pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER); | |
227 else | |
228 pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); | |
229 | |
230 pos += yahoo_put16(data + pos, 0x0000); | |
231 pos += yahoo_put16(data + pos, pktlen); | |
232 pos += yahoo_put16(data + pos, pkt->service); | |
233 pos += yahoo_put32(data + pos, pkt->status); | |
234 pos += yahoo_put32(data + pos, pkt->id); | |
235 | |
236 yahoo_packet_write(pkt, data + pos); | |
237 | |
238 yahoo_packet_dump(data, len); | |
239 ret = write(yd->fd, data, len); | |
240 if (ret != len) | |
241 gaim_debug_warning("yahoo", "Only wrote %d of %d bytes!", ret, len); | |
242 g_free(data); | |
243 | |
244 return ret; | |
245 } | |
246 | |
247 int yahoo_packet_send_and_free(struct yahoo_packet *pkt, struct yahoo_data *yd) | |
248 { | |
249 int ret; | |
250 | |
251 ret = yahoo_packet_send(pkt, yd); | |
252 yahoo_packet_free(pkt); | |
253 return ret; | |
254 } | |
255 | |
256 int yahoo_packet_send_special(struct yahoo_packet *pkt, int fd, int pad) | |
257 { | |
258 int pktlen = yahoo_packet_length(pkt); | |
259 int len = YAHOO_PACKET_HDRLEN + pktlen; | |
260 int ret; | |
261 | |
262 guchar *data; | |
263 int pos = 0; | |
264 | |
265 if (fd < 0) | |
266 return -1; | |
267 | |
268 data = g_malloc0(len + 1); | |
269 | |
270 memcpy(data + pos, "YMSG", 4); pos += 4; | |
271 | |
272 pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); | |
273 | |
274 pos += yahoo_put16(data + pos, 0x0000); | |
275 pos += yahoo_put16(data + pos, pktlen + pad); | |
276 pos += yahoo_put16(data + pos, pkt->service); | |
277 pos += yahoo_put32(data + pos, pkt->status); | |
278 pos += yahoo_put32(data + pos, pkt->id); | |
279 | |
280 yahoo_packet_write(pkt, data + pos); | |
281 | |
282 ret = write(fd, data, len); | |
283 g_free(data); | |
284 | |
285 return ret; | |
286 } | |
287 | |
288 void yahoo_packet_free(struct yahoo_packet *pkt) | |
289 { | |
290 while (pkt->hash) { | |
291 struct yahoo_pair *pair = pkt->hash->data; | |
292 g_free(pair->value); | |
293 g_free(pair); | |
294 pkt->hash = g_slist_remove(pkt->hash, pair); | |
295 } | |
296 g_free(pkt); | |
297 } |