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 {