Mercurial > pidgin
annotate src/protocols/zephyr/ZParseNot.c @ 13967:99b9b58b19dd
[gaim-migrate @ 16523]
Fix a crazy MSN crash. Basically it's possible to have more than one
slplink associated with a given switchboard, but our code did not
allow for that. I think it happens when you're in a multi-user
chat and you do stuff with multiple users that involves slplinks.
Like maybe file transfer and buddy icon related stuff.
Tracking this down took an ungodly amount of time, but thanks to
Meebo for letting me do it :-)
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 20 Jul 2006 07:31:15 +0000 |
parents | 64895571248f |
children |
rev | line source |
---|---|
2086 | 1 /* This file is part of the Project Athena Zephyr Notification System. |
2 * It contains source for the ZParseNotice function. | |
3 * | |
4 * Created by: Robert French | |
5 * | |
6 * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology. | |
7 * For copying and distribution information, see the file | |
8 * "mit-copyright.h". | |
9 */ | |
10 | |
8792
43d6c08d7e96
[gaim-migrate @ 9554]
Christian Hammond <chipx86@chipx86.com>
parents:
7475
diff
changeset
|
11 #include "internal.h" |
2086 | 12 |
13 /* Assume that strlen is efficient on this machine... */ | |
14 #define next_field(ptr) ptr += strlen (ptr) + 1 | |
15 | |
16 #if defined (__GNUC__) && defined (__vax__) | |
17 #undef next_field | |
18 static __inline__ char * Istrend (char *str) { | |
19 /* | |
20 * This should be faster on VAX models outside the 2 series. Don't | |
21 * use it if you are using MicroVAX 2 servers. If you are using a | |
22 * VS2 server, use something like | |
23 * #define next_field(ptr) while(*ptr++) | |
24 * instead of this code. | |
25 * | |
26 * This requires use of GCC to get the optimized code, but | |
27 * everybody uses GCC, don't they? :-) | |
28 */ | |
29 register char *str2 asm ("r1"); | |
30 /* Assumes that no field is longer than 64K.... */ | |
31 asm ("locc $0,$65535,(%1)" : "=r" (str2) : "r" (str) : "r0"); | |
32 return str2; | |
33 } | |
34 #define next_field(ptr) ptr = Istrend (ptr) + 1 | |
35 #endif | |
36 | |
37 #ifdef mips | |
38 #undef next_field | |
39 /* | |
40 * The compiler doesn't optimize this macro as well as it does the | |
41 * following function. | |
42 */ | |
43 #define next_fieldXXX(ptr) do{register unsigned c1,c2;c1= *ptr; \ | |
44 while((ptr++,c2= *ptr,c1)&&(ptr++,c1= *ptr,c2));}while(0) | |
45 static char *next_field_1 (s) char *s; { | |
46 /* | |
47 * Calling overhead is still present, but this routine is faster | |
48 * than strlen, and doesn't bother with some of the other math | |
49 * that we'd just have to undo later anyways. | |
50 */ | |
51 register unsigned c1 = *s, c2; | |
52 while (1) { | |
53 s++; c2 = *s; if (c1 == 0) break; | |
54 s++; c1 = *s; if (c2 == 0) break; | |
55 s++; c2 = *s; if (c1 == 0) break; | |
56 s++; c1 = *s; if (c2 == 0) break; | |
57 } | |
58 return s; | |
59 } | |
60 #define next_field(ptr) ptr=next_field_1(ptr) | |
61 #endif | |
62 | |
63 Code_t ZParseNotice(buffer, len, notice) | |
64 char *buffer; | |
65 int len; | |
66 ZNotice_t *notice; | |
67 { | |
68 char *ptr, *end; | |
69 unsigned long temp; | |
70 int maj, numfields, i; | |
71 | |
72 #ifdef __LINE__ | |
73 int lineno; | |
74 /* Note: This definition of BAD eliminates lint and compiler | |
75 * complains about the "while (0)", but require that the macro not | |
76 * be used as the "then" part of an "if" statement that also has | |
77 * an "else" clause. | |
78 */ | |
79 #define BAD_PACKET {lineno=__LINE__;goto badpkt;} | |
80 /* This one gets lint/compiler complaints. */ | |
81 /*#define BAD do{lineno=__LINE__;goto badpkt;}while(0)*/ | |
82 #else | |
83 #define BAD_PACKET goto badpkt | |
84 #endif | |
85 | |
86 (void) memset((char *)notice, 0, sizeof(ZNotice_t)); | |
87 | |
88 ptr = buffer; | |
89 end = buffer+len; | |
90 | |
91 notice->z_packet = buffer; | |
92 | |
93 notice->z_version = ptr; | |
94 if (strncmp(ptr, ZVERSIONHDR, sizeof(ZVERSIONHDR) - 1)) | |
95 return (ZERR_VERS); | |
96 ptr += sizeof(ZVERSIONHDR) - 1; | |
97 if (!*ptr) { | |
98 #ifdef Z_DEBUG | |
99 Z_debug ("ZParseNotice: null version string"); | |
100 #endif | |
101 return ZERR_BADPKT; | |
102 } | |
103 maj = atoi(ptr); | |
104 if (maj != ZVERSIONMAJOR) | |
105 return (ZERR_VERS); | |
106 next_field (ptr); | |
107 | |
108 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) | |
109 BAD_PACKET; | |
110 numfields = temp; | |
111 next_field (ptr); | |
112 | |
113 /*XXX 3 */ | |
114 numfields -= 2; /* numfields, version, and checksum */ | |
115 if (numfields < 0) { | |
116 #ifdef __LINE__ | |
117 lineno = __LINE__; | |
118 badpkt: | |
119 #ifdef Z_DEBUG | |
120 Z_debug ("ZParseNotice: bad packet from %s/%d (line %d)", | |
121 inet_ntoa (notice->z_uid.zuid_addr.s_addr), | |
122 notice->z_port, lineno); | |
123 #endif | |
124 #else | |
125 badpkt: | |
126 #ifdef Z_DEBUG | |
127 Z_debug ("ZParseNotice: bad packet from %s/%d", | |
128 inet_ntoa (notice->z_uid.zuid_addr.s_addr), | |
129 notice->z_port); | |
130 #endif | |
131 #endif | |
132 return ZERR_BADPKT; | |
133 } | |
134 | |
135 if (numfields) { | |
136 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) | |
137 BAD_PACKET; | |
138 notice->z_kind = temp; | |
139 numfields--; | |
140 next_field (ptr); | |
141 } | |
142 else | |
143 BAD_PACKET; | |
144 | |
145 if (numfields) { | |
146 if (ZReadAscii(ptr, end-ptr, (unsigned char *)¬ice->z_uid, | |
147 sizeof(ZUnique_Id_t)) == ZERR_BADFIELD) | |
148 BAD_PACKET; | |
7475 | 149 notice->z_time.tv_sec = ntohl((unsigned long) notice->z_uid.tv.tv_sec); |
150 notice->z_time.tv_usec = ntohl((unsigned long) notice->z_uid.tv.tv_usec); | |
2086 | 151 numfields--; |
152 next_field (ptr); | |
153 } | |
154 else | |
155 BAD_PACKET; | |
156 | |
157 if (numfields) { | |
158 if (ZReadAscii16(ptr, end-ptr, ¬ice->z_port) == ZERR_BADFIELD) | |
159 BAD_PACKET; | |
160 notice->z_port = htons(notice->z_port); | |
161 numfields--; | |
162 next_field (ptr); | |
163 } | |
164 else | |
165 BAD_PACKET; | |
166 | |
167 if (numfields) { | |
168 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) | |
169 BAD_PACKET; | |
170 notice->z_auth = temp; | |
171 numfields--; | |
172 next_field (ptr); | |
173 } | |
174 else | |
175 BAD_PACKET; | |
176 notice->z_checked_auth = ZAUTH_UNSET; | |
177 | |
178 if (numfields) { | |
179 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) | |
180 BAD_PACKET; | |
181 notice->z_authent_len = temp; | |
182 numfields--; | |
183 next_field (ptr); | |
184 } | |
185 else | |
186 BAD_PACKET; | |
187 | |
188 if (numfields) { | |
189 notice->z_ascii_authent = ptr; | |
190 numfields--; | |
191 next_field (ptr); | |
192 } | |
193 else | |
194 BAD_PACKET; | |
195 | |
196 if (numfields) { | |
197 notice->z_class = ptr; | |
198 numfields--; | |
199 next_field (ptr); | |
200 } | |
201 else | |
202 notice->z_class = ""; | |
203 | |
204 if (numfields) { | |
205 notice->z_class_inst = ptr; | |
206 numfields--; | |
207 next_field (ptr); | |
208 } | |
209 else | |
210 notice->z_class_inst = ""; | |
211 | |
212 if (numfields) { | |
213 notice->z_opcode = ptr; | |
214 numfields--; | |
215 next_field (ptr); | |
216 } | |
217 else | |
218 notice->z_opcode = ""; | |
219 | |
220 if (numfields) { | |
221 notice->z_sender = ptr; | |
222 numfields--; | |
223 next_field (ptr); | |
224 } | |
225 else | |
226 notice->z_sender = ""; | |
227 | |
228 if (numfields) { | |
229 notice->z_recipient = ptr; | |
230 numfields--; | |
231 next_field (ptr); | |
232 } | |
233 else | |
234 notice->z_recipient = ""; | |
235 | |
236 if (numfields) { | |
237 notice->z_default_format = ptr; | |
238 numfields--; | |
239 next_field (ptr); | |
240 } | |
241 else | |
242 notice->z_default_format = ""; | |
243 | |
244 /*XXX*/ | |
245 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) | |
246 BAD_PACKET; | |
247 notice->z_checksum = temp; | |
248 numfields--; | |
249 next_field (ptr); | |
250 | |
251 if (numfields) { | |
252 notice->z_multinotice = ptr; | |
253 numfields--; | |
254 next_field (ptr); | |
255 } | |
256 else | |
257 notice->z_multinotice = ""; | |
258 | |
259 if (numfields) { | |
260 if (ZReadAscii(ptr, end-ptr, (unsigned char *)¬ice->z_multiuid, | |
261 sizeof(ZUnique_Id_t)) == ZERR_BADFIELD) | |
262 BAD_PACKET; | |
7475 | 263 notice->z_time.tv_sec = ntohl((unsigned long) notice->z_multiuid.tv.tv_sec); |
264 notice->z_time.tv_usec = ntohl((unsigned long) notice->z_multiuid.tv.tv_usec); | |
2086 | 265 numfields--; |
266 next_field (ptr); | |
267 } | |
268 else | |
269 notice->z_multiuid = notice->z_uid; | |
270 | |
271 for (i=0;i<Z_MAXOTHERFIELDS && numfields;i++,numfields--) { | |
272 notice->z_other_fields[i] = ptr; | |
273 next_field (ptr); | |
274 } | |
275 notice->z_num_other_fields = i; | |
276 | |
277 for (i=0;i<numfields;i++) | |
278 next_field (ptr); | |
279 | |
7475 | 280 notice->z_message = (void *)ptr; |
2086 | 281 notice->z_message_len = len-(ptr-buffer); |
282 | |
283 return (ZERR_NONE); | |
284 } |