Mercurial > pidgin.yaz
comparison libpurple/protocols/msn/cmdproc.c @ 31292:47b6eda87723
propagate from branch 'im.pidgin.pidgin' (head 07d0765c444a097af45c2650f54323afb900a07b)
to branch 'im.pidgin.soc.2010.msn-tlc' (head f3998422a4724ab424e4e2328f58fc0504856557)
author | masca@cpw.pidgin.im |
---|---|
date | Mon, 19 Jul 2010 21:11:32 +0000 |
parents | 230caecf5435 |
children | 4bc5b483699e |
comparison
equal
deleted
inserted
replaced
30698:e874875a74a7 | 31292:47b6eda87723 |
---|---|
19 * | 19 * |
20 * You should have received a copy of the GNU General Public License | 20 * You should have received a copy of the GNU General Public License |
21 * along with this program; if not, write to the Free Software | 21 * along with this program; if not, write to the Free Software |
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA | 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
23 */ | 23 */ |
24 #include "msn.h" | 24 |
25 #include "internal.h" | |
26 #include "debug.h" | |
27 | |
25 #include "cmdproc.h" | 28 #include "cmdproc.h" |
29 #include "error.h" | |
26 | 30 |
27 MsnCmdProc * | 31 MsnCmdProc * |
28 msn_cmdproc_new(MsnSession *session) | 32 msn_cmdproc_new(MsnSession *session) |
29 { | 33 { |
30 MsnCmdProc *cmdproc; | 34 MsnCmdProc *cmdproc; |
120 if (!servconn->connected) { | 124 if (!servconn->connected) { |
121 /* TODO: Need to free trans */ | 125 /* TODO: Need to free trans */ |
122 return; | 126 return; |
123 } | 127 } |
124 | 128 |
125 msn_history_add(cmdproc->history, trans); | 129 if (trans->saveable) |
130 msn_history_add(cmdproc->history, trans); | |
126 | 131 |
127 data = msn_transaction_to_string(trans); | 132 data = msn_transaction_to_string(trans); |
128 | 133 |
129 len = strlen(data); | 134 len = strlen(data); |
130 | 135 |
153 | 158 |
154 g_free(data); | 159 g_free(data); |
155 } | 160 } |
156 | 161 |
157 void | 162 void |
158 msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command, | |
159 const char *format, ...) | |
160 { | |
161 MsnServConn *servconn; | |
162 char *data; | |
163 char *params = NULL; | |
164 va_list arg; | |
165 size_t len; | |
166 | |
167 g_return_if_fail(cmdproc != NULL); | |
168 g_return_if_fail(command != NULL); | |
169 | |
170 servconn = cmdproc->servconn; | |
171 | |
172 if (!servconn->connected) | |
173 return; | |
174 | |
175 if (format != NULL) | |
176 { | |
177 va_start(arg, format); | |
178 params = g_strdup_vprintf(format, arg); | |
179 va_end(arg); | |
180 } | |
181 | |
182 if (params != NULL) | |
183 data = g_strdup_printf("%s %s\r\n", command, params); | |
184 else | |
185 data = g_strdup_printf("%s\r\n", command); | |
186 | |
187 g_free(params); | |
188 | |
189 len = strlen(data); | |
190 | |
191 show_debug_cmd(cmdproc, FALSE, data); | |
192 | |
193 msn_servconn_write(servconn, data, len); | |
194 | |
195 g_free(data); | |
196 } | |
197 | |
198 void | |
199 msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command, | |
200 const char *format, ...) | |
201 { | |
202 MsnTransaction *trans; | |
203 va_list arg; | |
204 | |
205 g_return_if_fail(cmdproc != NULL); | |
206 g_return_if_fail(command != NULL); | |
207 | |
208 if (!cmdproc->servconn->connected) | |
209 return; | |
210 | |
211 trans = g_new0(MsnTransaction, 1); | |
212 | |
213 trans->cmdproc = cmdproc; | |
214 trans->command = g_strdup(command); | |
215 | |
216 if (format != NULL) | |
217 { | |
218 va_start(arg, format); | |
219 trans->params = g_strdup_vprintf(format, arg); | |
220 va_end(arg); | |
221 } | |
222 | |
223 msn_cmdproc_send_trans(cmdproc, trans); | |
224 } | |
225 | |
226 void | |
227 msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload, | 163 msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload, |
228 int payload_len) | 164 int payload_len) |
229 { | 165 { |
230 MsnCommand *last; | 166 MsnCommand *last; |
231 | 167 |
241 | 177 |
242 void | 178 void |
243 msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) | 179 msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) |
244 { | 180 { |
245 MsnMsgTypeCb cb; | 181 MsnMsgTypeCb cb; |
246 const char *messageId = NULL; | 182 const char *message_id = NULL; |
247 | 183 |
248 /* Multi-part messages */ | 184 /* Multi-part messages */ |
249 if ((messageId = msn_message_get_attr(msg, "Message-ID")) != NULL) { | 185 message_id = msn_message_get_header_value(msg, "Message-ID"); |
250 const char *chunk_text = msn_message_get_attr(msg, "Chunks"); | 186 if (message_id != NULL) { |
187 /* This is the first in a series of chunks */ | |
188 | |
189 const char *chunk_text = msn_message_get_header_value(msg, "Chunks"); | |
251 guint chunk; | 190 guint chunk; |
252 if (chunk_text != NULL) { | 191 if (chunk_text != NULL) { |
253 chunk = strtol(chunk_text, NULL, 10); | 192 chunk = strtol(chunk_text, NULL, 10); |
254 /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent | 193 /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent |
255 some random client causing pidgin to hog a ton of memory. | 194 some random client causing pidgin to hog a ton of memory. |
256 Probably should figure out the maximum that the official client | 195 Probably should figure out the maximum that the official client |
257 actually supports, though. */ | 196 actually supports, though. */ |
258 if (chunk > 0 && chunk < 1024) { | 197 if (chunk > 0 && chunk < 1024) { |
259 msg->total_chunks = chunk; | 198 msg->total_chunks = chunk; |
260 msg->received_chunks = 1; | 199 msg->received_chunks = 1; |
261 g_hash_table_insert(cmdproc->multiparts, (gpointer)messageId, msn_message_ref(msg)); | 200 g_hash_table_insert(cmdproc->multiparts, (gpointer)message_id, msn_message_ref(msg)); |
262 purple_debug_info("msn", "Received chunked message, messageId: '%s', total chunks: %d\n", | 201 purple_debug_info("msn", "Received chunked message, message_id: '%s', total chunks: %d\n", |
263 messageId, chunk); | 202 message_id, chunk); |
264 } else { | 203 } else { |
265 purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", messageId, chunk); | 204 purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", message_id, chunk); |
266 } | 205 } |
267 return; | 206 return; |
268 } else { | 207 } else { |
269 chunk_text = msn_message_get_attr(msg, "Chunk"); | 208 chunk_text = msn_message_get_header_value(msg, "Chunk"); |
270 if (chunk_text != NULL) { | 209 if (chunk_text != NULL) { |
271 MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, messageId); | 210 /* This is one chunk in a series of chunks */ |
211 | |
212 MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, message_id); | |
272 chunk = strtol(chunk_text, NULL, 10); | 213 chunk = strtol(chunk_text, NULL, 10); |
273 if (first == NULL) { | 214 if (first == NULL) { |
274 purple_debug_error("msn", | 215 purple_debug_error("msn", |
275 "Unable to find first chunk of messageId '%s' to correspond with chunk %d.\n", | 216 "Unable to find first chunk of message_id '%s' to correspond with chunk %d.\n", |
276 messageId, chunk+1); | 217 message_id, chunk + 1); |
277 } else if (first->received_chunks == chunk) { | 218 } else if (first->received_chunks != chunk) { |
278 /* Chunk is from 1 to total-1 (doesn't count first one) */ | 219 /* |
279 purple_debug_info("msn", "Received chunk %d of %d, messageId: '%s'\n", | 220 * We received an out of order chunk number (i.e. not the |
280 chunk+1, first->total_chunks, messageId); | 221 * next one in the sequence). Not sure if this can happen |
281 first->body = g_realloc(first->body, first->body_len + msg->body_len); | 222 * legitimately, but we definitely don't handle it right |
282 memcpy(first->body + first->body_len, msg->body, msg->body_len); | 223 * now. |
283 first->body_len += msg->body_len; | 224 */ |
284 first->received_chunks++; | 225 g_hash_table_remove(cmdproc->multiparts, message_id); |
285 if (first->received_chunks != first->total_chunks) | |
286 return; | |
287 else | |
288 /* We're done! Send it along... The caller takes care of | |
289 freeing the old one. */ | |
290 msg = first; | |
291 } else { | |
292 /* TODO: Can you legitimately receive chunks out of order? */ | |
293 g_hash_table_remove(cmdproc->multiparts, messageId); | |
294 return; | 226 return; |
295 } | 227 } |
228 | |
229 /* Chunk is from 1 to total-1 (doesn't count first one) */ | |
230 purple_debug_info("msn", "Received chunk %d of %d, message_id: '%s'\n", | |
231 chunk + 1, first->total_chunks, message_id); | |
232 first->body = g_realloc(first->body, first->body_len + msg->body_len); | |
233 memcpy(first->body + first->body_len, msg->body, msg->body_len); | |
234 first->body_len += msg->body_len; | |
235 first->received_chunks++; | |
236 if (first->received_chunks != first->total_chunks) | |
237 /* We're waiting for more chunks */ | |
238 return; | |
239 | |
240 /* | |
241 * We have all the chunks for this message, great! Send | |
242 * it along... The caller takes care of freeing the old one. | |
243 */ | |
244 msg = first; | |
296 } else { | 245 } else { |
297 purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", messageId); | 246 purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", message_id); |
298 } | 247 } |
299 } | 248 } |
300 } | 249 } |
301 | 250 |
302 if (msn_message_get_content_type(msg) == NULL) | 251 if (msn_message_get_content_type(msg) == NULL) |
312 cb(cmdproc, msg); | 261 cb(cmdproc, msg); |
313 else | 262 else |
314 purple_debug_warning("msn", "Unhandled content-type '%s'\n", | 263 purple_debug_warning("msn", "Unhandled content-type '%s'\n", |
315 msn_message_get_content_type(msg)); | 264 msn_message_get_content_type(msg)); |
316 | 265 |
317 if (messageId != NULL) | 266 if (message_id != NULL) |
318 g_hash_table_remove(cmdproc->multiparts, messageId); | 267 g_hash_table_remove(cmdproc->multiparts, message_id); |
319 } | 268 } |
320 | 269 |
321 void | 270 void |
322 msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) | 271 msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) |
323 { | 272 { |