Mercurial > pidgin
annotate src/protocols/zephyr/ZSubs.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 ZSubscribeTo, ZUnsubscribeTo, and | |
3 * ZCancelSubscriptions functions. | |
4 * | |
5 * Created by: Robert French | |
6 * | |
7 * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology. | |
8 * For copying and distribution information, see the file | |
9 * "mit-copyright.h". | |
10 */ | |
11 | |
8792
43d6c08d7e96
[gaim-migrate @ 9554]
Christian Hammond <chipx86@chipx86.com>
parents:
3277
diff
changeset
|
12 #include "internal.h" |
2086 | 13 |
14 static Code_t Z_Subscriptions __P((register ZSubscription_t *sublist, | |
15 int nitems, unsigned int port, | |
16 char *opcode, int authit)); | |
17 static Code_t subscr_sendoff __P((ZNotice_t *notice, char **lyst, int num, | |
18 int authit)); | |
19 | |
20 Code_t ZSubscribeTo(sublist, nitems, port) | |
21 ZSubscription_t *sublist; | |
22 int nitems; | |
23 unsigned int port; | |
24 { | |
25 return (Z_Subscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE, 1)); | |
26 } | |
27 | |
28 Code_t ZSubscribeToSansDefaults(sublist, nitems, port) | |
29 ZSubscription_t *sublist; | |
30 int nitems; | |
31 unsigned int port; | |
32 { | |
33 return (Z_Subscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE_NODEFS, | |
34 1)); | |
35 } | |
36 | |
37 Code_t ZUnsubscribeTo(sublist, nitems, port) | |
38 ZSubscription_t *sublist; | |
39 int nitems; | |
40 unsigned int port; | |
41 { | |
42 return (Z_Subscriptions(sublist, nitems, port, CLIENT_UNSUBSCRIBE, 1)); | |
43 } | |
44 | |
45 Code_t ZCancelSubscriptions(port) | |
46 unsigned int port; | |
47 { | |
48 return (Z_Subscriptions((ZSubscription_t *)0, 0, port, | |
49 CLIENT_CANCELSUB, 0)); | |
50 } | |
51 | |
52 /* | |
53 * This routine must do its own fragmentation. Subscriptions must | |
54 * not be broken across packet boundaries, or else the server will | |
55 * mis-interpret them. | |
56 */ | |
57 | |
58 static Code_t | |
59 Z_Subscriptions(sublist, nitems, port, opcode, authit) | |
60 register ZSubscription_t *sublist; | |
61 int nitems; | |
62 unsigned int port; | |
63 char *opcode; | |
64 int authit; | |
65 { | |
66 register int i, j; | |
67 int retval; | |
68 ZNotice_t notice; | |
69 char header[Z_MAXHEADERLEN]; | |
70 char **list; | |
3277 | 71 char *recip; |
2086 | 72 int hdrlen; |
73 int size_avail = Z_MAXPKTLEN-Z_FRAGFUDGE; /* space avail for data, | |
74 adjusted below */ | |
75 int size, start, numok; | |
76 | |
77 /* nitems = 0 means cancel all subscriptions; still need to allocate a */ | |
78 /* array for one item so we can cancel, however. */ | |
79 | |
80 list = (char **)malloc((unsigned)((nitems==0)?1:nitems)*3*sizeof(char *)); | |
81 if (!list) | |
82 return (ENOMEM); | |
83 | |
84 (void) memset((char *)¬ice, 0, sizeof(notice)); | |
85 notice.z_kind = ACKED; | |
86 notice.z_port = port; | |
87 notice.z_class = ZEPHYR_CTL_CLASS; | |
88 notice.z_class_inst = ZEPHYR_CTL_CLIENT; | |
89 notice.z_opcode = opcode; | |
90 notice.z_sender = 0; | |
91 notice.z_recipient = ""; | |
92 notice.z_default_format = ""; | |
93 notice.z_message_len = 0; | |
94 | |
95 /* format the header to figure out how long it is */ | |
96 retval = Z_FormatHeader(¬ice, header, sizeof(header), &hdrlen, ZAUTH); | |
97 if (retval != ZERR_NONE && !authit) | |
98 retval = Z_FormatHeader(¬ice, header, sizeof(header), | |
2419
7ba69b8e0de5
[gaim-migrate @ 2432]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
99 &hdrlen, ZNOAUTH); |
2086 | 100 if (retval != ZERR_NONE) { |
101 free((char *)list); | |
102 return(retval); | |
103 } | |
104 | |
105 /* compute amount of room left */ | |
106 size_avail -= hdrlen; | |
107 size = size_avail; | |
108 | |
109 /* assemble subs into an array of pointers */ | |
110 for (i=0;i<nitems;i++) { | |
111 list[i*3] = sublist[i].zsub_class; | |
112 list[i*3+1] = sublist[i].zsub_classinst; | |
3277 | 113 recip = sublist[i].zsub_recipient; |
114 if (recip && *recip == '*') | |
115 recip++; | |
116 if (!recip || (*recip != 0 && *recip != '@')) | |
117 recip = ZGetSender(); | |
118 list[i*3+2] = recip; | |
2086 | 119 } |
120 | |
121 start = -1; | |
122 i = 0; | |
123 numok = 0; | |
124 if (!nitems) { | |
125 /* there aren't really any, but we need to xmit anyway */ | |
126 retval = subscr_sendoff(¬ice, list, 0, authit); | |
127 free((char *)list); | |
128 return(retval); | |
129 } | |
130 while(i < nitems) { | |
131 if (start == -1) { | |
132 size = size_avail; | |
133 start = i; | |
134 numok = 0; | |
135 } | |
136 if ((j = strlen(list[i*3]) | |
137 + strlen(list[i*3+1]) | |
138 + strlen(list[i*3+2]) + 3) <= size) { | |
139 /* it will fit in this packet */ | |
140 size -= j; | |
141 numok++; | |
142 i++; | |
143 continue; | |
144 } | |
145 if (!numok) { /* a single subscription won't | |
146 fit into one packet */ | |
147 free((char *)list); | |
148 return(ZERR_FIELDLEN); | |
149 } | |
150 retval = subscr_sendoff(¬ice, &list[start*3], numok, authit); | |
151 if (retval) { | |
152 free((char *)list); | |
153 return(retval); | |
154 } | |
155 start = -1; | |
156 } | |
157 if (numok) | |
158 retval = subscr_sendoff(¬ice, &list[start*3], numok, authit); | |
159 free((char *)list); | |
160 return(retval); | |
161 } | |
162 | |
163 static Code_t | |
164 subscr_sendoff(notice, lyst, num, authit) | |
165 ZNotice_t *notice; | |
166 char **lyst; | |
167 int num; | |
168 int authit; | |
169 { | |
170 register Code_t retval; | |
171 ZNotice_t retnotice; | |
172 | |
173 retval = ZSendList(notice, lyst, num*3, ZAUTH); | |
174 if (retval != ZERR_NONE && !authit) | |
175 retval = ZSendList(notice, lyst, num*3, ZNOAUTH); | |
176 | |
177 if (retval != ZERR_NONE) | |
178 return (retval); | |
179 if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *)0, | |
180 ZCompareUIDPred, (char *)¬ice->z_uid)) != | |
181 ZERR_NONE) | |
182 return (retval); | |
183 if (retnotice.z_kind == SERVNAK) { | |
184 ZFreeNotice(&retnotice); | |
185 return (ZERR_SERVNAK); | |
186 } | |
187 if (retnotice.z_kind != SERVACK) { | |
188 ZFreeNotice(&retnotice); | |
189 return (ZERR_INTERNAL); | |
190 } | |
191 ZFreeNotice(&retnotice); | |
192 return (ZERR_NONE); | |
193 } |