Mercurial > pidgin
annotate src/protocols/msn/cmdproc.c @ 9175:3e2ea5b69605
[gaim-migrate @ 9970]
W and S are now implemented for /cmds in core.
This means you can do /me with colors again.
This was probably the hardest part of cmds that was left to do. So the rest
should be fairly easy. Hopefully there's no major bugs in this. There's
some inconsist use of g_utf8_isspace vs strchr(s, ' ') I want to clean up
yet that will cause some oddness if you use a tab instead of a space as
your argument separater.
committer: Tailor Script <tailor@pidgin.im>
| author | Tim Ringenbach <marv@pidgin.im> |
|---|---|
| date | Sat, 05 Jun 2004 07:33:58 +0000 |
| parents | c30d81b4dd22 |
| children | 502707ca1836 |
| 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; | |
|
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
123 gsize len; |
| 8810 | 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); | |
|
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
132 |
| 8810 | 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 | |
|
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
170 if (format != NULL) |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
171 { |
|
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
172 va_start(arg, format); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
173 params = g_strdup_vprintf(format, arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
174 va_end(arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
175 } |
| 8810 | 176 |
| 177 if (params != NULL) | |
| 178 data = g_strdup_printf("%s %s\r\n", command, params); | |
| 179 else | |
| 180 data = g_strdup_printf("%s\r\n", command); | |
| 181 | |
| 182 g_free(params); | |
| 183 | |
| 184 len = strlen(data); | |
| 185 | |
| 186 show_debug_cmd(cmdproc, FALSE, data); | |
| 187 | |
| 188 msn_servconn_write(servconn, data, len); | |
| 189 | |
| 190 g_free(data); | |
| 191 } | |
| 192 | |
| 193 void | |
| 194 msn_cmdproc_send(MsnCmdProc *cmdproc, const char *command, | |
| 195 const char *format, ...) | |
| 196 { | |
| 197 MsnTransaction *trans; | |
| 198 va_list arg; | |
| 199 | |
| 200 g_return_if_fail(cmdproc != NULL); | |
| 201 g_return_if_fail(command != NULL); | |
| 202 | |
| 203 trans = g_new0(MsnTransaction, 1); | |
| 204 | |
| 205 trans->command = g_strdup(command); | |
| 206 | |
|
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
207 if (format != NULL) |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
208 { |
|
8830
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
209 va_start(arg, format); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
210 trans->params = g_strdup_vprintf(format, arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
211 va_end(arg); |
|
f8038b1f7449
[gaim-migrate @ 9594]
Christian Hammond <chipx86@chipx86.com>
parents:
8810
diff
changeset
|
212 } |
| 8810 | 213 |
| 214 msn_cmdproc_send_trans(cmdproc, trans); | |
| 215 } | |
| 216 | |
| 217 void | |
|
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
218 msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload, |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
219 int payload_len) |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
220 { |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
221 g_return_if_fail(cmdproc != NULL); |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
222 g_return_if_fail(cmdproc->payload_cb != NULL); |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
223 |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
224 cmdproc->payload_cb(cmdproc, payload, payload_len); |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
225 } |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
226 |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
227 void |
| 8810 | 228 msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg) |
| 229 { | |
| 230 MsnServConn *servconn; | |
| 231 MsnMsgCb cb; | |
| 232 | |
| 233 servconn = cmdproc->servconn; | |
| 234 | |
| 235 cb = g_hash_table_lookup(cmdproc->cbs_table->msgs, | |
| 236 msn_message_get_content_type(msg)); | |
| 237 | |
| 238 if (cb == NULL) | |
| 239 { | |
|
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
240 gaim_debug_warning("msn", "Unhandled content-type '%s'\n", |
|
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
241 msn_message_get_content_type(msg)); |
| 8810 | 242 |
| 243 return; | |
| 244 } | |
| 245 | |
| 246 cb(cmdproc, msg); | |
| 247 } | |
| 248 | |
| 249 void | |
| 250 msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) | |
| 251 { | |
| 252 MsnSession *session; | |
| 253 MsnServConn *servconn; | |
| 254 MsnTransaction *trans = NULL; | |
| 255 MsnTransCb cb = NULL; | |
| 256 GSList *l, *l_next = NULL; | |
| 257 | |
| 258 session = cmdproc->session; | |
| 259 servconn = cmdproc->servconn; | |
| 260 | |
| 261 if (cmd->trId) | |
| 262 trans = msn_history_find(cmdproc->history, cmd->trId); | |
| 263 | |
| 264 if (g_ascii_isdigit(cmd->command[0])) | |
| 265 { | |
| 266 if (trans != NULL) | |
| 267 { | |
| 268 MsnErrorCb error_cb = NULL; | |
| 269 int error; | |
| 270 | |
| 271 error = atoi(cmd->command); | |
| 272 if (cmdproc->cbs_table->errors != NULL) | |
| 273 error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command); | |
| 274 | |
| 275 if (error_cb != NULL) | |
| 276 error_cb(cmdproc, trans, error); | |
| 277 else | |
| 278 { | |
| 279 #if 1 | |
| 280 msn_error_handle(cmdproc->session, error); | |
| 281 #else | |
| 282 gaim_debug_warning("msn", "Unhandled error '%s'\n", | |
| 283 cmd->command); | |
| 284 #endif | |
| 285 } | |
| 286 | |
| 287 return; | |
| 288 } | |
| 289 } | |
| 290 | |
| 291 if (cmdproc->cbs_table->async != NULL) | |
| 292 cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command); | |
| 293 | |
| 294 if (cb == NULL && cmd->trId) | |
| 295 { | |
| 296 if (trans != NULL) | |
| 297 { | |
| 298 cmd->trans = trans; | |
| 299 | |
| 300 if (trans->callbacks) | |
| 301 cb = g_hash_table_lookup(trans->callbacks, cmd->command); | |
| 302 } | |
| 303 } | |
| 304 | |
| 305 if (cb != NULL) | |
| 306 cb(cmdproc, cmd); | |
| 307 else | |
| 308 { | |
| 309 gaim_debug_warning("msn", "Unhandled command '%s'\n", | |
|
9158
c30d81b4dd22
[gaim-migrate @ 9942]
Christian Hammond <chipx86@chipx86.com>
parents:
8830
diff
changeset
|
310 cmd->command); |
| 8810 | 311 |
| 312 return; | |
| 313 } | |
| 314 | |
| 315 if (g_list_find(session->servconns, servconn) == NULL) | |
| 316 return; | |
| 317 | |
| 318 /* Process all queued messages that are waiting on this command. */ | |
| 319 for (l = cmdproc->msg_queue; l != NULL; l = l_next) | |
| 320 { | |
| 321 MsnQueueEntry *entry = l->data; | |
| 322 MsnMessage *msg; | |
| 323 | |
| 324 l_next = l->next; | |
| 325 | |
| 326 if (entry->command == NULL || | |
| 327 !g_ascii_strcasecmp(entry->command, cmd->command)) | |
| 328 { | |
| 329 msg = entry->msg; | |
| 330 | |
| 331 msn_message_ref(msg); | |
| 332 | |
| 333 msn_cmdproc_process_msg(cmdproc, msg); | |
| 334 | |
| 335 msn_cmdproc_unqueue_message(cmdproc, entry->msg); | |
| 336 | |
| 337 msn_message_destroy(msg); | |
| 338 entry->msg = NULL; | |
| 339 } | |
| 340 } | |
| 341 } | |
| 342 | |
| 343 void | |
| 344 msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command) | |
| 345 { | |
| 346 show_debug_cmd(cmdproc, TRUE, command); | |
| 347 | |
| 348 if (cmdproc->last_cmd != NULL) | |
| 349 msn_command_destroy(cmdproc->last_cmd); | |
| 350 | |
| 351 cmdproc->last_cmd = msn_command_from_string(command); | |
| 352 | |
| 353 msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd); | |
| 354 } | |
| 355 | |
| 356 void | |
| 357 msn_cmdproc_queue_message(MsnCmdProc *cmdproc, const char *command, | |
| 358 MsnMessage *msg) | |
| 359 { | |
| 360 MsnQueueEntry *entry; | |
| 361 | |
| 362 g_return_if_fail(cmdproc != NULL); | |
| 363 g_return_if_fail(msg != NULL); | |
| 364 | |
| 365 entry = g_new0(MsnQueueEntry, 1); | |
| 366 entry->msg = msg; | |
| 367 entry->command = (command == NULL ? NULL : g_strdup(command)); | |
| 368 | |
| 369 cmdproc->msg_queue = g_slist_append(cmdproc->msg_queue, entry); | |
| 370 | |
| 371 msn_message_ref(msg); | |
| 372 } | |
| 373 | |
| 374 void | |
| 375 msn_cmdproc_unqueue_message(MsnCmdProc *cmdproc, MsnMessage *msg) | |
| 376 { | |
| 377 MsnQueueEntry *entry = NULL; | |
| 378 GSList *l; | |
| 379 | |
| 380 g_return_if_fail(cmdproc != NULL); | |
| 381 g_return_if_fail(msg != NULL); | |
| 382 | |
| 383 for (l = cmdproc->msg_queue; l != NULL; l = l->next) | |
| 384 { | |
| 385 entry = l->data; | |
| 386 | |
| 387 if (entry->msg == msg) | |
| 388 break; | |
| 389 | |
| 390 entry = NULL; | |
| 391 } | |
| 392 | |
| 393 g_return_if_fail(entry != NULL); | |
| 394 | |
| 395 msn_message_unref(msg); | |
| 396 | |
| 397 cmdproc->msg_queue = g_slist_remove(cmdproc->msg_queue, entry); | |
| 398 | |
| 399 if (entry->command != NULL) | |
| 400 g_free(entry->command); | |
| 401 | |
| 402 g_free(entry); | |
| 403 } |
