Mercurial > pidgin
annotate src/protocols/jabber/message.c @ 7104:7700a28929bd
[gaim-migrate @ 7669]
When retrieving user info for an MSN user, the prpl checks if the info is
empty. If so, it displays an error dialog indicating so. Otherwise, it
displays the info.
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Wed, 01 Oct 2003 05:42:40 +0000 |
| parents | c8bf2da398e3 |
| children | bf630f7dfdcd |
| rev | line source |
|---|---|
| 7014 | 1 /* |
| 2 * gaim - Jabber Protocol Plugin | |
| 3 * | |
| 4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
| 5 * | |
| 6 * This program is free software; you can redistribute it and/or modify | |
| 7 * it under the terms of the GNU General Public License as published by | |
| 8 * the Free Software Foundation; either version 2 of the License, or | |
| 9 * (at your option) any later version. | |
| 10 * | |
| 11 * This program is distributed in the hope that it will be useful, | |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 * GNU General Public License for more details. | |
| 15 * | |
| 16 * You should have received a copy of the GNU General Public License | |
| 17 * along with this program; if not, write to the Free Software | |
| 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 * | |
| 20 */ | |
| 21 #include "internal.h" | |
| 22 | |
| 23 #include "debug.h" | |
| 24 #include "notify.h" | |
| 25 #include "server.h" | |
|
7095
c8bf2da398e3
[gaim-migrate @ 7660]
Christian Hammond <chipx86@chipx86.com>
parents:
7014
diff
changeset
|
26 #include "util.h" |
| 7014 | 27 |
| 28 #include "buddy.h" | |
| 29 #include "chat.h" | |
| 30 #include "message.h" | |
| 31 #include "xmlnode.h" | |
| 32 | |
| 33 #define JABBER_TYPING_NOTIFY_INT 15 | |
| 34 | |
| 35 void jabber_message_free(JabberMessage *jm) | |
| 36 { | |
| 37 if(jm->from) | |
| 38 g_free(jm->from); | |
| 39 if(jm->to) | |
| 40 g_free(jm->to); | |
| 41 if(jm->subject) | |
| 42 g_free(jm->subject); | |
| 43 if(jm->body) | |
| 44 g_free(jm->body); | |
| 45 if(jm->xhtml) | |
| 46 g_free(jm->xhtml); | |
| 47 if(jm->password) | |
| 48 g_free(jm->password); | |
| 49 | |
| 50 g_free(jm); | |
| 51 } | |
| 52 | |
| 53 void handle_chat(JabberMessage *jm) | |
| 54 { | |
| 55 JabberID *jid = jabber_id_new(jm->from); | |
| 56 char *from; | |
| 57 | |
| 58 JabberBuddy *jb; | |
| 59 JabberBuddyResource *jbr; | |
| 60 | |
| 61 jb = jabber_buddy_find(jm->js, jm->from, TRUE); | |
| 62 jbr = jabber_buddy_find_resource(jb, jabber_get_resource(jm->from)); | |
| 63 | |
| 64 if(gaim_find_conversation_with_account(jm->from, jm->js->gc->account)) | |
| 65 from = g_strdup(jm->from); | |
| 66 else if(jid->node) | |
| 67 from = g_strdup_printf("%s@%s", jid->node, jid->domain); | |
| 68 else | |
| 69 from = g_strdup(jid->domain); | |
| 70 | |
| 71 if(!jm->xhtml && !jm->body) { | |
| 72 if(jm->events & JABBER_MESSAGE_EVENT_COMPOSING) | |
| 73 serv_got_typing(jm->js->gc, from, 0, GAIM_TYPING); | |
| 74 else | |
| 75 serv_got_typing_stopped(jm->js->gc, from); | |
| 76 } else { | |
| 77 if(jbr && jm->events & JABBER_MESSAGE_EVENT_COMPOSING) | |
| 78 jbr->capabilities |= JABBER_CAP_COMPOSING; | |
| 79 serv_got_im(jm->js->gc, from, jm->xhtml ? jm->xhtml : jm->body, 0, | |
| 80 jm->sent); | |
| 81 } | |
| 82 | |
| 83 g_free(from); | |
| 84 jabber_id_free(jid); | |
| 85 } | |
| 86 | |
| 87 void handle_groupchat(JabberMessage *jm) | |
| 88 { | |
| 89 JabberID *jid = jabber_id_new(jm->from); | |
| 90 JabberChat *chat = jabber_chat_find(jm->js, jid->node, jid->domain); | |
| 91 | |
| 92 if(!chat) | |
| 93 return; | |
| 94 | |
| 95 if(jm->subject) | |
| 96 gaim_chat_set_topic(GAIM_CHAT(chat->conv), jid->resource, jm->subject); | |
| 97 | |
| 98 serv_got_chat_in(jm->js->gc, chat->id, jabber_get_resource(jm->from), | |
| 99 0, jm->xhtml ? jm->xhtml : jm->body, jm->sent); | |
| 100 jabber_id_free(jid); | |
| 101 } | |
| 102 | |
| 103 void handle_groupchat_invite(JabberMessage *jm) | |
| 104 { | |
| 105 GHashTable *components = g_hash_table_new_full(g_str_hash, g_str_equal, | |
| 106 g_free, g_free); | |
| 107 JabberID *jid = jabber_id_new(jm->to); | |
| 108 | |
| 109 g_hash_table_replace(components, g_strdup("room"), jid->node); | |
| 110 g_hash_table_replace(components, g_strdup("server"), jid->node); | |
| 111 g_hash_table_replace(components, g_strdup("handle"), jm->js->user->node); | |
| 112 g_hash_table_replace(components, g_strdup("password"), jm->password); | |
| 113 | |
| 114 jabber_id_free(jid); | |
| 115 serv_got_chat_invite(jm->js->gc, jm->to, jm->from, jm->body, components); | |
| 116 } | |
| 117 | |
| 118 void handle_error(JabberMessage *jm) | |
| 119 { | |
| 120 char *buf; | |
| 121 | |
| 122 if(!jm->body) | |
| 123 return; | |
| 124 | |
| 125 buf = g_strdup_printf(_("Message delivery to %s failed: %s"), | |
| 126 jm->from, jm->error); | |
| 127 | |
| 128 gaim_notify_error(jm->js->gc, _("Jabber Message Error"), buf, jm->body); | |
| 129 | |
| 130 g_free(buf); | |
| 131 } | |
| 132 | |
| 133 void jabber_message_parse(JabberStream *js, xmlnode *packet) | |
| 134 { | |
| 135 JabberMessage *jm; | |
| 136 const char *type; | |
| 137 xmlnode *child; | |
| 138 | |
| 139 if(strcmp(packet->name, "message")) | |
| 140 return; | |
| 141 | |
| 142 jm = g_new0(JabberMessage, 1); | |
| 143 jm->js = js; | |
| 144 jm->sent = time(NULL); | |
| 145 | |
| 146 type = xmlnode_get_attrib(packet, "type"); | |
| 147 | |
| 148 if(type) { | |
| 149 if(!strcmp(type, "normal")) | |
| 150 jm->type = JABBER_MESSAGE_NORMAL; | |
| 151 else if(!strcmp(type, "chat")) | |
| 152 jm->type = JABBER_MESSAGE_CHAT; | |
| 153 else if(!strcmp(type, "groupchat")) | |
| 154 jm->type = JABBER_MESSAGE_GROUPCHAT; | |
| 155 else if(!strcmp(type, "headline")) | |
| 156 jm->type = JABBER_MESSAGE_HEADLINE; | |
| 157 else if(!strcmp(type, "error")) | |
| 158 jm->type = JABBER_MESSAGE_ERROR; | |
| 159 else | |
| 160 jm->type = JABBER_MESSAGE_OTHER; | |
| 161 } else { | |
| 162 jm->type = JABBER_MESSAGE_NORMAL; | |
| 163 } | |
| 164 | |
| 165 jm->from = g_strdup(xmlnode_get_attrib(packet, "from")); | |
| 166 jm->to = g_strdup(xmlnode_get_attrib(packet, "to")); | |
| 167 | |
| 168 for(child = packet->child; child; child = child->next) { | |
| 169 if(child->type != NODE_TYPE_TAG) | |
| 170 continue; | |
| 171 | |
| 172 if(!strcmp(child->name, "subject")) { | |
| 173 if(!jm->subject) | |
| 174 jm->subject = xmlnode_get_data(child); | |
| 175 } else if(!strcmp(child->name, "body")) { | |
| 176 if(!jm->body) | |
| 177 jm->body = xmlnode_get_data(child); | |
| 178 } else if(!strcmp(child->name, "html") && child->child) { | |
| 179 /* check to see if the <html> actually contains anything, | |
| 180 * otherwise we'll ignore it */ | |
| 181 char *txt = xmlnode_get_data(child); | |
| 182 if(!jm->xhtml && txt) | |
| 183 jm->xhtml = xmlnode_to_str(child); | |
| 184 g_free(txt); | |
| 185 } else if(!strcmp(child->name, "error")) { | |
| 186 const char *code = xmlnode_get_attrib(child, "code"); | |
| 187 char *code_txt = NULL; | |
| 188 char *text = xmlnode_get_data(child); | |
| 189 | |
| 190 if(code) | |
| 191 code_txt = g_strdup_printf(_(" (Code %s)"), code); | |
| 192 | |
| 193 if(!jm->error) | |
| 194 jm->error = g_strdup_printf("%s%s", text ? text : "", | |
| 195 code_txt ? code_txt : ""); | |
| 196 | |
| 197 g_free(code_txt); | |
| 198 g_free(text); | |
| 199 } else if(!strcmp(child->name, "x")) { | |
| 200 const char *xmlns = xmlnode_get_attrib(child, "xmlns"); | |
| 201 if(xmlns && !strcmp(xmlns, "jabber:x:event")) { | |
| 202 if(xmlnode_get_child(child, "composing")) | |
| 203 jm->events |= JABBER_MESSAGE_EVENT_COMPOSING; | |
| 204 } else if(xmlns && !strcmp(xmlns, "jabber:x:delay")) { | |
| 205 const char *timestamp = xmlnode_get_attrib(child, "stamp"); | |
| 206 if(timestamp) | |
| 207 jm->sent = str_to_time(timestamp); | |
| 208 } else if(xmlns && !strcmp(xmlns, "jabber:x:conference") && | |
| 209 jm->type != JABBER_MESSAGE_GROUPCHAT_INVITE) { | |
| 210 const char *jid = xmlnode_get_attrib(child, "jid"); | |
| 211 if(jid) { | |
| 212 jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; | |
| 213 g_free(jm->to); | |
| 214 jm->to = g_strdup(jid); | |
| 215 } | |
| 216 } else if(xmlns && !strcmp(xmlns, | |
| 217 "http://jabber.org/protocol/muc#user")) { | |
| 218 xmlnode *invite = xmlnode_get_child(child, "invite"); | |
| 219 if(invite) { | |
| 220 xmlnode *reason, *password; | |
| 221 const char *jid = xmlnode_get_attrib(child, "from"); | |
| 222 g_free(jm->to); | |
| 223 jm->to = jm->from; | |
| 224 jm->from = g_strdup(jid); | |
| 225 if((reason = xmlnode_get_child(invite, "reason"))) { | |
| 226 g_free(jm->body); | |
| 227 jm->body = xmlnode_get_data(reason); | |
| 228 } | |
| 229 if((password = xmlnode_get_child(invite, "password"))) | |
| 230 jm->password = xmlnode_get_data(password); | |
| 231 | |
| 232 jm->type = JABBER_MESSAGE_GROUPCHAT_INVITE; | |
| 233 } | |
| 234 } | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 switch(jm->type) { | |
| 239 case JABBER_MESSAGE_NORMAL: | |
| 240 case JABBER_MESSAGE_CHAT: | |
| 241 case JABBER_MESSAGE_HEADLINE: | |
| 242 handle_chat(jm); | |
| 243 break; | |
| 244 case JABBER_MESSAGE_GROUPCHAT: | |
| 245 handle_groupchat(jm); | |
| 246 break; | |
| 247 case JABBER_MESSAGE_GROUPCHAT_INVITE: | |
| 248 handle_groupchat_invite(jm); | |
| 249 break; | |
| 250 case JABBER_MESSAGE_ERROR: | |
| 251 handle_error(jm); | |
| 252 break; | |
| 253 case JABBER_MESSAGE_OTHER: | |
| 254 gaim_debug(GAIM_DEBUG_INFO, "jabber", | |
| 255 "Received message of unknown type: %s\n", type); | |
| 256 break; | |
| 257 } | |
| 258 jabber_message_free(jm); | |
| 259 } | |
| 260 | |
| 261 void jabber_message_send(JabberMessage *jm) | |
| 262 { | |
| 263 xmlnode *message, *child; | |
| 264 const char *type = NULL; | |
| 265 | |
| 266 message = xmlnode_new("message"); | |
| 267 | |
| 268 switch(jm->type) { | |
| 269 case JABBER_MESSAGE_NORMAL: | |
| 270 type = "normal"; | |
| 271 break; | |
| 272 case JABBER_MESSAGE_CHAT: | |
| 273 case JABBER_MESSAGE_GROUPCHAT_INVITE: | |
| 274 type = "chat"; | |
| 275 break; | |
| 276 case JABBER_MESSAGE_HEADLINE: | |
| 277 type = "headline"; | |
| 278 break; | |
| 279 case JABBER_MESSAGE_GROUPCHAT: | |
| 280 type = "groupchat"; | |
| 281 break; | |
| 282 case JABBER_MESSAGE_ERROR: | |
| 283 type = "error"; | |
| 284 break; | |
| 285 case JABBER_MESSAGE_OTHER: | |
| 286 type = NULL; | |
| 287 break; | |
| 288 } | |
| 289 | |
| 290 if(type) | |
| 291 xmlnode_set_attrib(message, "type", type); | |
| 292 | |
| 293 xmlnode_set_attrib(message, "to", jm->to); | |
| 294 | |
| 295 if(jm->events || (!jm->body && !jm->xhtml)) { | |
| 296 child = xmlnode_new_child(message, "x"); | |
| 297 xmlnode_set_attrib(child, "xmlns", "jabber:x:event"); | |
| 298 if(jm->events & JABBER_MESSAGE_EVENT_COMPOSING) | |
| 299 xmlnode_new_child(child, "composing"); | |
| 300 } | |
| 301 | |
| 302 if(jm->subject) { | |
| 303 child = xmlnode_new_child(message, "subject"); | |
| 304 xmlnode_insert_data(child, jm->subject, -1); | |
| 305 } | |
| 306 | |
| 307 if(jm->body) { | |
| 308 child = xmlnode_new_child(message, "body"); | |
| 309 xmlnode_insert_data(child, jm->body, -1); | |
| 310 } | |
| 311 | |
| 312 if(jm->xhtml) { | |
| 313 child = xmlnode_from_str(jm->xhtml, -1); | |
| 314 if(child) { | |
| 315 xmlnode_insert_child(message, child); | |
| 316 } else { | |
| 317 gaim_debug(GAIM_DEBUG_ERROR, "jabber", | |
| 318 "XHTML translation/validation failed, returning: %s\n", | |
| 319 jm->xhtml); | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 jabber_send(jm->js, message); | |
| 324 | |
| 325 xmlnode_free(message); | |
| 326 } | |
| 327 | |
| 328 int jabber_message_send_im(GaimConnection *gc, const char *who, const char *msg, | |
| 329 GaimImFlags flags) | |
| 330 { | |
| 331 JabberMessage *jm; | |
| 332 JabberBuddy *jb; | |
| 333 JabberBuddyResource *jbr; | |
| 334 char *buf; | |
| 335 char *xhtml, *plain; | |
| 336 | |
| 337 if(!who || !msg) | |
| 338 return 0; | |
| 339 | |
| 340 jb = jabber_buddy_find(gc->proto_data, who, TRUE); | |
| 341 jbr = jabber_buddy_find_resource(jb, jabber_get_resource(who)); | |
| 342 | |
| 343 jm = g_new0(JabberMessage, 1); | |
| 344 jm->js = gc->proto_data; | |
| 345 jm->type = JABBER_MESSAGE_CHAT; | |
| 346 jm->events = JABBER_MESSAGE_EVENT_COMPOSING; | |
| 347 jm->to = g_strdup(who); | |
| 348 | |
| 349 buf = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body>%s</body></html>", msg); | |
| 350 | |
|
7095
c8bf2da398e3
[gaim-migrate @ 7660]
Christian Hammond <chipx86@chipx86.com>
parents:
7014
diff
changeset
|
351 gaim_markup_html_to_xhtml(buf, &xhtml, &plain); |
| 7014 | 352 g_free(buf); |
| 353 | |
| 354 jm->body = plain; | |
| 355 if(!jbr || jbr->capabilities & JABBER_CAP_XHTML) | |
| 356 jm->xhtml = xhtml; | |
| 357 else | |
| 358 g_free(xhtml); | |
| 359 | |
| 360 jabber_message_send(jm); | |
| 361 jabber_message_free(jm); | |
| 362 return 1; | |
| 363 } | |
| 364 | |
| 365 int jabber_message_send_chat(GaimConnection *gc, int id, const char *message) | |
| 366 { | |
| 367 JabberChat *chat; | |
| 368 JabberMessage *jm; | |
| 369 JabberStream *js = gc->proto_data; | |
| 370 | |
| 371 if(!message) | |
| 372 return 0; | |
| 373 | |
| 374 chat = jabber_chat_find_by_id(js, id); | |
| 375 | |
| 376 jm = g_new0(JabberMessage, 1); | |
| 377 jm->js = gc->proto_data; | |
| 378 jm->type = JABBER_MESSAGE_CHAT; | |
| 379 jm->to = g_strdup_printf("%s@%s", chat->room, chat->server); | |
| 380 | |
|
7095
c8bf2da398e3
[gaim-migrate @ 7660]
Christian Hammond <chipx86@chipx86.com>
parents:
7014
diff
changeset
|
381 gaim_markup_html_to_xhtml(message, NULL, &jm->body); |
| 7014 | 382 |
| 383 jabber_message_send(jm); | |
| 384 jabber_message_free(jm); | |
| 385 return 1; | |
| 386 } | |
| 387 | |
| 388 int jabber_send_typing(GaimConnection *gc, const char *who, int typing) | |
| 389 { | |
| 390 JabberMessage *jm; | |
| 391 JabberBuddy *jb; | |
| 392 JabberBuddyResource *jbr; | |
| 393 | |
| 394 jb = jabber_buddy_find(gc->proto_data, who, TRUE); | |
| 395 jbr = jabber_buddy_find_resource(jb, jabber_get_resource(who)); | |
| 396 | |
| 397 if(jbr && !(jbr->capabilities & JABBER_CAP_COMPOSING)) | |
| 398 return 0; | |
| 399 | |
| 400 jm = g_new0(JabberMessage, 1); | |
| 401 jm->js = gc->proto_data; | |
| 402 jm->type = JABBER_MESSAGE_CHAT; | |
| 403 jm->to = g_strdup(who); | |
| 404 | |
| 405 if(typing == GAIM_TYPING) | |
| 406 jm->events = JABBER_MESSAGE_EVENT_COMPOSING; | |
| 407 | |
| 408 jabber_message_send(jm); | |
| 409 jabber_message_free(jm); | |
| 410 | |
| 411 return JABBER_TYPING_NOTIFY_INT; | |
| 412 } | |
| 413 |
