Mercurial > pidgin
annotate src/protocols/msn/cmdproc.c @ 8999:8f838ae3e710
[gaim-migrate @ 9774]
" This patch renames the existing received-*-msg signals
to receiving-*msg to fit the naming of other signals
where a pointer to the message is passed (writing,
sending, displaying)
It adds new received-*-msg signals which are emitted
after the receiving signals, in line with the other
conversation signals (wrote, sent, displayed)
This is necessary to allow plugins which depend on the
final received message to work alongside plugins which
may modify the message.
One known example of this is festival-gaim alongside
gaim-encryption - festival-gaim would try to "speak"
the encrypted text:
http://sf.net/tracker/?func=detail&aid=943216&group_id=89763&atid=591320
I've tested this with gaim-encryption and festival-gaim
(locally modified so gaim-encryption uses the receiving
signal and festival uses the received signal)
All in-tree users of received-*-msg are updated to use
receiving-*-msg if they do modify the message, the
conversation-signals documentation is updated, the
signals-test.c & signal-test.tcl plugins are also updated." --Stu Tomlinson
committer: Tailor Script <tailor@pidgin.im>
| author | Luke Schierer <lschiere@pidgin.im> |
|---|---|
| date | Fri, 21 May 2004 14:33:32 +0000 |
| parents | f8038b1f7449 |
| children | c30d81b4dd22 |
| rev | line source |
|---|---|
| 8810 | 1 /** |
| 2 * @file cmdproc.c MSN command processor functions | |
| 3 * | |
| 4 * gaim | |
| 5 * | |
| 6 * Copyright (C) 2003, Christian Hammond <chipx86@gnupdate.org> | |
| 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 #include "msn.h" | |
| 23 #include "cmdproc.h" | |
| 24 | |
| 25 typedef struct | |
| 26 { | |
| 27 char *command; | |
| 28 MsnMessage *msg; | |
| 29 | |
| 30 } MsnQueueEntry; | |
| 31 | |
| 32 MsnCmdProc * | |
| 33 msn_cmdproc_new(MsnSession *session) | |
| 34 { | |
| 35 MsnCmdProc *cmdproc; | |
| 36 | |
| 37 cmdproc = g_new0(MsnCmdProc, 1); | |
| 38 | |
| 39 cmdproc->session = session; | |
| 40 cmdproc->txqueue = g_queue_new(); | |
| 41 cmdproc->history = msn_history_new(); | |
| 42 | |
| 43 return cmdproc; | |
| 44 } | |
| 45 | |
| 46 void | |
| 47 msn_cmdproc_destroy(MsnCmdProc *cmdproc) | |
| 48 { | |
| 49 MsnTransaction *trans; | |
| 50 | |
| 51 if (cmdproc->last_trans != NULL) | |
| 52 g_free(cmdproc->last_trans); | |
| 53 | |
| 54 while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL) | |
| 55 msn_transaction_destroy(trans); | |
| 56 | |
| 57 g_queue_free(cmdproc->txqueue); | |
| 58 | |
| 59 while (cmdproc->msg_queue != NULL) | |
| 60 { | |
| 61 MsnQueueEntry *entry = cmdproc->msg_queue->data; | |
| 62 | |
| 63 msn_cmdproc_unqueue_message(cmdproc, entry->msg); | |
| 64 } | |
| 65 | |
| 66 msn_history_destroy(cmdproc->history); | |
| 67 } | |
| 68 | |
| 69 void | |
| 70 msn_cmdproc_process_queue(MsnCmdProc *cmdproc) | |
| 71 { | |
| 72 MsnTransaction *trans; | |
| 73 | |
| 74 while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL && | |
| 75 cmdproc->error == 0) | |
| 76 { | |
| 77 msn_cmdproc_send_trans(cmdproc, trans); | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 void | |
| 82 msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans) | |
| 83 { | |
| 84 g_return_if_fail(cmdproc != NULL); | |
| 85 g_return_if_fail(trans != NULL); | |
| 86 | |
| 87 gaim_debug_info("msn", "Appending command to queue.\n"); | |
| 88 | |
| 89 g_queue_push_tail(cmdproc->txqueue, trans); | |
| 90 } | |
| 91 | |
| 92 static void | |
| 93 show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command) | |
| 94 { | |
| 95 MsnServConn *servconn; | |
| 96 const char *names[] = { "NS", "SB" }; | |
| 97 char *show; | |
| 98 char tmp; | |
| 99 size_t len; | |
| 100 | |
| 101 servconn = cmdproc->servconn; | |
| 102 len = strlen(command); | |
| 103 show = g_strdup(command); | |
| 104 | |
| 105 tmp = (incoming) ? 'S' : 'C'; | |
| 106 | |
| 107 if ((show[len - 1] == '\n') && (show[len - 2] == '\r')) | |
| 108 { | |
| 109 show[len - 2] = '\0'; | |
| 110 } | |
| 111 | |
| 112 gaim_debug_misc("msn", "%c: %s %03d: %s\n", tmp, | |
| 113 names[servconn->type], servconn->num, show); | |
| 114 | |
| 115 g_free(show); | |
| 116 } | |
| 117 | |
| 118 void | |
| 119 msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans) | |
| 120 { | |
| 121 MsnServConn *servconn; | |
| 122 char *data; | |
| 123 size_t len; | |
| 124 | |
| 125 g_return_if_fail(cmdproc != NULL); | |
| 126 g_return_if_fail(trans != NULL); | |
| 127 | |
| 128 servconn = cmdproc->servconn; | |
| 129 msn_history_add(cmdproc->history, trans); | |
| 130 | |
| 131 data = msn_transaction_to_string(trans); | |
| 132 | |
| 133 cmdproc->last_trans = g_strdup(data); | |
| 134 | |
| 135 len = strlen(data); | |
| 136 | |
| 137 show_debug_cmd(cmdproc, FALSE, data); | |
| 138 | |
| 139 if (trans->callbacks == NULL) | |
| 140 trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds, | |
| 141 trans->command); | |
| 142 | |
| 143 if (trans->payload != NULL) | |
| 144 { | |
| 145 data = g_realloc(data, len + trans->payload_len); | |
| 146 memcpy(data + len, trans->payload, trans->payload_len); | |
| 147 len += trans->payload_len; | |
| 148 } | |
| 149 | |
| 150 msn_servconn_write(servconn, data, len); | |
| 151 | |
| 152 g_free(data); | |
| 153 } | |
| 154 | |
| 155 void | |
| 156 msn_cmdproc_send_quick(MsnCmdProc *cmdproc, const char *command, | |
| 157 const char *format, ...) | |
| 158 { | |
| 159 MsnServConn *servconn; | |
| 160 char *data; | |
|
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
161 char *params = NULL; |
| 8810 | 162 va_list arg; |
| 163 size_t len; | |
| 164 | |
| 165 g_return_if_fail(cmdproc != NULL); | |
| 166 g_return_if_fail(command != NULL); | |
| 167 | |
| 168 servconn = cmdproc->servconn; | |
| 169 | |
|
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
170 if (format != NULL) { |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
171 va_start(arg, format); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
172 params = g_strdup_vprintf(format, arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
173 va_end(arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
174 } |
| 8810 | 175 |
| 176 if (params != NULL) | |
| 177 data = g_strdup_printf("%s %s\r\n", command, params); | |
| 178 else | |
| 179 data = g_strdup_printf("%s\r\n", command); | |
| 180 | |
| 181 g_free(params); | |
| 182 | |
| 183 len = strlen(data); | |
| 184 | |
| 185 show_debug_cmd(cmdproc, FALSE, data); | |
| 186 | |
| 187 msn_servconn_write(servconn, data, len); | |
| 188 | |
| 189 g_free(data); | |
| 190 } | |
| 191 | |
| 192 void | |
| 193 msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command, | |
| 194 const char *format, ...) | |
| 195 { | |
| 196 MsnTransaction *trans; | |
| 197 va_list arg; | |
| 198 | |
| 199 g_return_if_fail(cmdproc != NULL); | |
| 200 g_return_if_fail(command != NULL); | |
| 201 | |
| 202 trans = g_new0(MsnTransaction, 1); | |
| 203 | |
| 204 trans->command = g_strdup(command); | |
| 205 | |
|
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
206 if (format != NULL) { |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
207 va_start(arg, format); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
208 trans->params = g_strdup_vprintf(format, arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
209 va_end(arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
210 } |
| 8810 | 211 |
| 212 msn_cmdproc_send_trans(cmdproc, trans); | |
| 213 } | |
| 214 | |
| 215 void | |
| 216 msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) | |
| 217 { | |
| 218 MsnServConn *servconn; | |
| 219 MsnMsgCb cb; | |
| 220 | |
| 221 servconn = cmdproc->servconn; | |
| 222 | |
| 223 cb = g_hash_table_lookup(cmdproc->cbs_table->msgs, | |
| 224 msn_message_get_content_type(msg)); | |
| 225 | |
| 226 if (cb == NULL) | |
| 227 { | |
| 228 gaim_debug_warning("msn", "Unhandled content-type '%s': %s\n", | |
| 229 msn_message_get_content_type(msg), | |
| 230 msn_message_get_body(msg)); | |
| 231 | |
| 232 return; | |
| 233 } | |
| 234 | |
| 235 cb(cmdproc, msg); | |
| 236 } | |
| 237 | |
| 238 void | |
| 239 msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload, int payload_len) | |
| 240 { | |
| 241 g_return_if_fail(cmdproc != NULL); | |
| 242 g_return_if_fail(cmdproc->payload_cb != NULL); | |
| 243 | |
| 244 cmdproc->payload_cb(cmdproc, payload, payload_len); | |
| 245 } | |
| 246 | |
| 247 void | |
| 248 msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) | |
| 249 { | |
| 250 MsnSession *session; | |
| 251 MsnServConn *servconn; | |
| 252 MsnTransaction *trans = NULL; | |
| 253 MsnTransCb cb = NULL; | |
| 254 GSList *l, *l_next = NULL; | |
| 255 | |
| 256 session = cmdproc->session; | |
| 257 servconn = cmdproc->servconn; | |
| 258 | |
| 259 if (cmd->trId) | |
| 260 trans = msn_history_find(cmdproc->history, cmd->trId); | |
| 261 | |
| 262 if (g_ascii_isdigit(cmd->command[0])) | |
| 263 { | |
| 264 if (trans != NULL) | |
| 265 { | |
| 266 MsnErrorCb error_cb = NULL; | |
| 267 int error; | |
| 268 | |
| 269 error = atoi(cmd->command); | |
| 270 if (cmdproc->cbs_table->errors != NULL) | |
| 271 error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command); | |
| 272 | |
| 273 if (error_cb != NULL) | |
| 274 error_cb(cmdproc, trans, error); | |
| 275 else | |
| 276 { | |
| 277 #if 1 | |
| 278 msn_error_handle(cmdproc->session, error); | |
| 279 #else | |
| 280 gaim_debug_warning("msn", "Unhandled error '%s'\n", | |
| 281 cmd->command); | |
| 282 #endif | |
| 283 } | |
| 284 | |
| 285 return; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 if (cmdproc->cbs_table->async != NULL) | |
| 290 cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command); | |
| 291 | |
| 292 if (cb == NULL && cmd->trId) | |
| 293 { | |
| 294 if (trans != NULL) | |
| 295 { | |
| 296 cmd->trans = trans; | |
| 297 | |
| 298 if (trans->callbacks) | |
| 299 cb = g_hash_table_lookup(trans->callbacks, cmd->command); | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 if (cb != NULL) | |
| 304 cb(cmdproc, cmd); | |
| 305 else | |
| 306 { | |
| 307 gaim_debug_warning("msn", "Unhandled command '%s'\n", | |
| 308 cmd->command); | |
| 309 | |
| 310 return; | |
| 311 } | |
| 312 | |
| 313 if (g_list_find(session->servconns, servconn) == NULL) | |
| 314 return; | |
| 315 | |
| 316 /* Process all queued messages that are waiting on this command. */ | |
| 317 for (l = cmdproc->msg_queue; l != NULL; l = l_next) | |
| 318 { | |
| 319 MsnQueueEntry *entry = l->data; | |
| 320 MsnMessage *msg; | |
| 321 | |
| 322 l_next = l->next; | |
| 323 | |
| 324 if (entry->command == NULL || | |
| 325 !g_ascii_strcasecmp(entry->command, cmd->command)) | |
| 326 { | |
| 327 msg = entry->msg; | |
| 328 | |
| 329 msn_message_ref(msg); | |
| 330 | |
| 331 msn_cmdproc_process_msg(cmdproc, msg); | |
| 332 | |
| 333 msn_cmdproc_unqueue_message(cmdproc, entry->msg); | |
| 334 | |
| 335 msn_message_destroy(msg); | |
| 336 entry->msg = NULL; | |
| 337 } | |
| 338 } | |
| 339 } | |
| 340 | |
| 341 void | |
| 342 msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command) | |
| 343 { | |
| 344 show_debug_cmd(cmdproc, TRUE, command); | |
| 345 | |
| 346 if (cmdproc->last_cmd != NULL) | |
| 347 msn_command_destroy(cmdproc->last_cmd); | |
| 348 | |
| 349 cmdproc->last_cmd = msn_command_from_string(command); | |
| 350 | |
| 351 msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd); | |
| 352 } | |
| 353 | |
| 354 void | |
| 355 msn_cmdproc_queue_message(MsnCmdProc *cmdproc, const char *command, | |
| 356 MsnMessage *msg) | |
| 357 { | |
| 358 MsnQueueEntry *entry; | |
| 359 | |
| 360 g_return_if_fail(cmdproc != NULL); | |
| 361 g_return_if_fail(msg != NULL); | |
| 362 | |
| 363 entry = g_new0(MsnQueueEntry, 1); | |
| 364 entry->msg = msg; | |
| 365 entry->command = (command == NULL ? NULL : g_strdup(command)); | |
| 366 | |
| 367 cmdproc->msg_queue = g_slist_append(cmdproc->msg_queue, entry); | |
| 368 | |
| 369 msn_message_ref(msg); | |
| 370 } | |
| 371 | |
| 372 void | |
| 373 msn_cmdproc_unqueue_message(MsnCmdProc *cmdproc, MsnMessage *msg) | |
| 374 { | |
| 375 MsnQueueEntry *entry = NULL; | |
| 376 GSList *l; | |
| 377 | |
| 378 g_return_if_fail(cmdproc != NULL); | |
| 379 g_return_if_fail(msg != NULL); | |
| 380 | |
| 381 for (l = cmdproc->msg_queue; l != NULL; l = l->next) | |
| 382 { | |
| 383 entry = l->data; | |
| 384 | |
| 385 if (entry->msg == msg) | |
| 386 break; | |
| 387 | |
| 388 entry = NULL; | |
| 389 } | |
| 390 | |
| 391 g_return_if_fail(entry != NULL); | |
| 392 | |
| 393 msn_message_unref(msg); | |
| 394 | |
| 395 cmdproc->msg_queue = g_slist_remove(cmdproc->msg_queue, entry); | |
| 396 | |
| 397 if (entry->command != NULL) | |
| 398 g_free(entry->command); | |
| 399 | |
| 400 g_free(entry); | |
| 401 } |
