mcabber/mcabber/xmpp.c
changeset 2345 462f4359391c
parent 2335 72543547c646
child 2346 7921c8d671c8
equal deleted inserted replaced
2344:1579ed96d501 2345:462f4359391c
   987     buddylist_defer_build();
   987     buddylist_defer_build();
   988     scr_update_roster();
   988     scr_update_roster();
   989     goto gotmessage_return;
   989     goto gotmessage_return;
   990   }
   990   }
   991 
   991 
       
   992   if (subject && LM_MESSAGE_SUB_TYPE_GROUPCHAT == type) {
       
   993     // Room topic
       
   994     GSList *roombuddy;
       
   995     gchar *mbuf;
       
   996     // Set the new topic
       
   997     roombuddy = roster_find(bjid, jidsearch, 0);
       
   998     if (roombuddy)
       
   999       buddy_settopic(roombuddy->data, subject);
       
  1000     // Display inside the room window
       
  1001     if (!rname) {
       
  1002       // No specific resource (this is certainly history)
       
  1003       if (*subject)
       
  1004         mbuf = g_strdup_printf("The topic has been set to: %s", subject);
       
  1005       else
       
  1006         mbuf = g_strdup_printf("The topic has been cleared");
       
  1007     } else {
       
  1008       if (*subject)
       
  1009         mbuf = g_strdup_printf("%s has set the topic to: %s", rname, subject);
       
  1010       else
       
  1011         mbuf = g_strdup_printf("%s has cleared the topic", rname);
       
  1012     }
       
  1013     scr_WriteIncomingMessage(bjid, mbuf, timestamp,
       
  1014                              HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
       
  1015     if (settings_opt_get_int("log_muc_conf"))
       
  1016       hlog_write_message(bjid, 0, -1, mbuf);
       
  1017     g_free(mbuf);
       
  1018     // The topic is displayed in the chat status line, so refresh now.
       
  1019     scr_update_chat_status(TRUE);
       
  1020   }
       
  1021 
   992   // We don't call the message_in hook if 'block_unsubscribed' is true and
  1022   // We don't call the message_in hook if 'block_unsubscribed' is true and
   993   // this is a regular message from an unsubscribed user.
  1023   // this is a regular message from an unsubscribed user.
   994   // System messages (from our server) are allowed.
  1024   // System messages (from our server) are allowed.
   995   if (settings_opt_get_int("block_unsubscribed") &&
  1025   if (settings_opt_get_int("block_unsubscribed") &&
   996       (roster_gettype(bjid) != ROSTER_TYPE_ROOM) &&
  1026       (roster_gettype(bjid) != ROSTER_TYPE_ROOM) &&
  1050 
  1080 
  1051 static LmHandlerResult handle_messages(LmMessageHandler *handler,
  1081 static LmHandlerResult handle_messages(LmMessageHandler *handler,
  1052                                        LmConnection *connection,
  1082                                        LmConnection *connection,
  1053                                        LmMessage *m, gpointer user_data)
  1083                                        LmMessage *m, gpointer user_data)
  1054 {
  1084 {
  1055   const char *p, *from=lm_message_get_from(m);
  1085   const char *from = lm_message_get_from(m);
  1056   char *bjid, *res;
  1086   char *bjid, *res;
  1057   LmMessageNode *x;
  1087   LmMessageNode *x;
  1058   const char *body = NULL;
  1088   const char *body = NULL;
  1059   const char *enc = NULL;
  1089   const char *enc = NULL;
  1060   const char *subject = NULL;
  1090   const char *subject = NULL;
  1061   time_t timestamp = 0L;
  1091   time_t timestamp = 0L;
  1062   LmMessageSubType mstype;
  1092   LmMessageSubType mstype;
  1063   gboolean skip_process = FALSE;
       
  1064   LmMessageNode *ns_signed = NULL;
  1093   LmMessageNode *ns_signed = NULL;
  1065 
  1094 
  1066   mstype = lm_message_get_sub_type(m);
  1095   if (!from) {
  1067 
  1096     scr_LogPrint(LPRINT_DEBUG, "handle_messages: message with missing from attribute");
  1068   body = lm_message_node_get_child_value(m->node, "body");
  1097     return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
  1069 
  1098   }
  1070   x = lm_message_node_find_xmlns(m->node, NS_ENCRYPTED);
       
  1071   if (x && (p = lm_message_node_get_value(x)) != NULL)
       
  1072     enc = p;
       
  1073 
       
  1074   // Get the bare-JID/room (bjid) and the resource/nickname (res)
  1099   // Get the bare-JID/room (bjid) and the resource/nickname (res)
  1075   bjid = g_strdup(lm_message_get_from(m));
  1100   bjid = g_strdup(from);
  1076   res = strchr(bjid, JID_RESOURCE_SEPARATOR);
  1101   res = strchr(bjid, JID_RESOURCE_SEPARATOR);
  1077   if (res) *res++ = 0;
  1102   if (res) *res++ = 0;
  1078 
  1103 
       
  1104   mstype = lm_message_get_sub_type(m);
  1079   // Timestamp?
  1105   // Timestamp?
  1080   timestamp = lm_message_node_get_timestamp(m->node);
  1106   timestamp = lm_message_node_get_timestamp(m->node);
  1081 
       
  1082   p = lm_message_node_get_child_value(m->node, "subject");
       
  1083   if (p != NULL) {
       
  1084     if (mstype != LM_MESSAGE_SUB_TYPE_GROUPCHAT) {
       
  1085       // Chat message
       
  1086       subject = p;
       
  1087     } else {
       
  1088       // Room topic
       
  1089       GSList *roombuddy;
       
  1090       gchar *mbuf;
       
  1091       const gchar *subj = p;
       
  1092       // Set the new topic
       
  1093       roombuddy = roster_find(bjid, jidsearch, 0);
       
  1094       if (roombuddy)
       
  1095         buddy_settopic(roombuddy->data, subj);
       
  1096       // Display inside the room window
       
  1097       if (!res) {
       
  1098         // No specific resource (this is certainly history)
       
  1099         if (*subj)
       
  1100           mbuf = g_strdup_printf("The topic has been set to: %s", subj);
       
  1101         else
       
  1102           mbuf = g_strdup_printf("The topic has been cleared");
       
  1103       } else {
       
  1104         if (*subj)
       
  1105           mbuf = g_strdup_printf("%s has set the topic to: %s", res, subj);
       
  1106         else
       
  1107           mbuf = g_strdup_printf("%s has cleared the topic", res);
       
  1108       }
       
  1109       scr_WriteIncomingMessage(bjid, mbuf, timestamp,
       
  1110                                HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
       
  1111       if (settings_opt_get_int("log_muc_conf"))
       
  1112         hlog_write_message(bjid, 0, -1, mbuf);
       
  1113       g_free(mbuf);
       
  1114       // The topic is displayed in the chat status line, so refresh now.
       
  1115       scr_update_chat_status(TRUE);
       
  1116     }
       
  1117   }
       
  1118 
  1107 
  1119   if (mstype == LM_MESSAGE_SUB_TYPE_ERROR) {
  1108   if (mstype == LM_MESSAGE_SUB_TYPE_ERROR) {
  1120     x = lm_message_node_get_child(m->node, "error");
  1109     x = lm_message_node_get_child(m->node, "error");
  1121     display_server_error(x, from);
  1110     display_server_error(x, from);
  1122 #ifdef XEP0085
  1111 #ifdef XEP0085
  1152                    "Could not read carbon message!  Please file a bug.");
  1141                    "Could not read carbon message!  Please file a bug.");
  1153       goto handle_messages_return;
  1142       goto handle_messages_return;
  1154     }
  1143     }
  1155 
  1144 
  1156     xenc = lm_message_node_find_xmlns(x, NS_ENCRYPTED);
  1145     xenc = lm_message_node_find_xmlns(x, NS_ENCRYPTED);
  1157     if (xenc && (p = lm_message_node_get_value(xenc)) != NULL)
  1146     if (xenc)
  1158       enc = p;
  1147       enc = lm_message_node_get_value(xenc);
  1159 
  1148 
  1160     body = lm_message_node_get_child_value(x, "body");
  1149     body = lm_message_node_get_child_value(x, "body");
  1161     subject = lm_message_node_get_child_value(x, "subject");
  1150     subject = lm_message_node_get_child_value(x, "subject");
  1162     if (body && *body && !subject)
  1151     ns_signed = lm_message_node_find_xmlns(x, NS_SIGNED);
  1163       ns_signed = lm_message_node_find_xmlns(x, NS_SIGNED);
       
  1164     else
       
  1165       skip_process = TRUE;
       
  1166 
  1152 
  1167     // Parse a message that is send to one of our other resources
  1153     // Parse a message that is send to one of our other resources
  1168     if (!g_strcmp0(carbon_name, "received")) {
  1154     if (!g_strcmp0(carbon_name, "received")) {
  1169       from = lm_message_node_get_attribute(x, "from");
  1155       from = lm_message_node_get_attribute(x, "from");
  1170       if (!from) {
  1156       if (!from) {
  1184     } else if (!g_strcmp0(carbon_name, "sent")) {
  1170     } else if (!g_strcmp0(carbon_name, "sent")) {
  1185 #ifdef HAVE_GPGME
  1171 #ifdef HAVE_GPGME
  1186       char *decrypted_pgp = NULL;
  1172       char *decrypted_pgp = NULL;
  1187 #endif
  1173 #endif
  1188       guint encrypted = 0;
  1174       guint encrypted = 0;
  1189       const char *to= lm_message_node_get_attribute(x, "to");
  1175       const char *to = lm_message_node_get_attribute(x, "to");
  1190       if (!to) {
  1176       if (!to) {
  1191         scr_LogPrint(LPRINT_LOGNORM, "Malformed carbon copy!");
  1177         scr_LogPrint(LPRINT_LOGNORM, "Malformed carbon copy!");
  1192         goto handle_messages_return;
  1178         goto handle_messages_return;
  1193       }
  1179       }
  1194       g_free(bjid);
  1180       g_free(bjid);
  1221       g_free(decrypted_pgp);
  1207       g_free(decrypted_pgp);
  1222 #endif
  1208 #endif
  1223       goto handle_messages_return;
  1209       goto handle_messages_return;
  1224     }
  1210     }
  1225   } else { // Not a Carbon
  1211   } else { // Not a Carbon
       
  1212     subject = lm_message_node_get_child_value(m->node, "subject");
       
  1213     body = lm_message_node_get_child_value(m->node, "body");
       
  1214     x = lm_message_node_find_xmlns(m->node, NS_ENCRYPTED);
       
  1215     if (x)
       
  1216       enc = lm_message_node_get_value(x);
  1226     ns_signed = lm_message_node_find_xmlns(m->node, NS_SIGNED);
  1217     ns_signed = lm_message_node_find_xmlns(m->node, NS_SIGNED);
  1227   }
  1218   }
  1228 
  1219 
  1229   // Do not process the message if some fields are missing
  1220   // Only process messages that have a body or a subject
  1230   if (!from || (!body && !subject))
  1221   if (body || subject) {
  1231     skip_process = TRUE;
       
  1232 
       
  1233   if (!skip_process) {
       
  1234     gotmessage(mstype, from, body, enc, subject, timestamp,
  1222     gotmessage(mstype, from, body, enc, subject, timestamp,
  1235                ns_signed, carbons);
  1223                ns_signed, carbons);
  1236   }
  1224   }
  1237 
  1225 
  1238   // We're done if it was a Carbon forwarded message
  1226   // Handle XEP 184
  1239   if (carbons)
  1227   {
  1240     goto handle_messages_return;
  1228     LmMessageNode *xep184 = lm_message_node_find_xmlns(m->node, NS_RECEIPTS);
  1241 
  1229     if (xep184) {
  1242   // Report received message if message delivery receipt was requested
  1230       if(!g_strcmp0("request", xep184->name) &&
  1243   if (lm_message_node_get_child(m->node, "request") &&
  1231          (roster_getsubscription(bjid) & sub_from)) {
  1244       (roster_getsubscription(bjid) & sub_from)) {
  1232         // Report received message if message delivery receipt was requested
  1245     const gchar *mid;
  1233         const gchar *mid;
  1246     LmMessageNode *y;
  1234         LmMessageNode *y;
  1247     LmMessage *rcvd = lm_message_new(from, LM_MESSAGE_TYPE_MESSAGE);
  1235         LmMessage *rcvd = lm_message_new(from, LM_MESSAGE_TYPE_MESSAGE);
  1248     mid = lm_message_get_id(m);
  1236         mid = lm_message_get_id(m);
  1249     // For backward compatibility (XEP184 < v.1.1):
  1237         // For backward compatibility (XEP184 < v.1.1):
  1250     lm_message_node_set_attribute(rcvd->node, "id", mid);
  1238         lm_message_node_set_attribute(rcvd->node, "id", mid);
  1251     y = lm_message_node_add_child(rcvd->node, "received", NULL);
  1239         y = lm_message_node_add_child(rcvd->node, "received", NULL);
  1252     lm_message_node_set_attribute(y, "xmlns", NS_RECEIPTS);
  1240         lm_message_node_set_attribute(y, "xmlns", NS_RECEIPTS);
  1253     lm_message_node_set_attribute(y, "id", mid);
  1241         lm_message_node_set_attribute(y, "id", mid);
  1254     lm_connection_send(connection, rcvd, NULL);
  1242         lm_connection_send(connection, rcvd, NULL);
  1255     lm_message_unref(rcvd);
  1243         lm_message_unref(rcvd);
  1256   }
  1244       } else if(!g_strcmp0("received", xep184->name)) {
  1257 
  1245         // receipt acknowledged
  1258   { // xep184 receipt confirmation
  1246         const char *id  = lm_message_node_get_attribute(xep184, "id");
  1259     LmMessageNode *received = lm_message_node_get_child(m->node, "received");
  1247         // This is for backward compatibility; if the remote client didn't add
  1260     if (received && !g_strcmp0(lm_message_node_get_attribute(received, "xmlns"),
  1248         // the id as an attribute of the 'received' tag, we use the message id:
  1261                                NS_RECEIPTS)) {
  1249         if (!id)
  1262       char       *jid = jidtodisp(from);
  1250           id = lm_message_get_id(m);
  1263       const char *id  = lm_message_node_get_attribute(received, "id");
  1251         scr_remove_receipt_flag(bjid, id);
  1264       // This is for backward compatibility; if the remote client didn't add
       
  1265       // the id as an attribute of the 'received' tag, we use the message id:
       
  1266       if (!id)
       
  1267         id = lm_message_get_id(m);
       
  1268       scr_remove_receipt_flag(jid, id);
       
  1269       g_free(jid);
       
  1270 
  1252 
  1271 #ifdef MODULES_ENABLE
  1253 #ifdef MODULES_ENABLE
  1272       {
  1254         {
  1273         hk_arg_t args[] = {
  1255           hk_arg_t args[] = {
  1274           { "jid", from },
  1256             { "jid", from },
  1275           { NULL, NULL },
  1257             { NULL, NULL },
  1276         };
  1258           };
  1277         hk_run_handlers("hook-mdr-received", args);
  1259           hk_run_handlers("hook-mdr-received", args);
       
  1260         }
       
  1261 #endif
  1278       }
  1262       }
  1279 #endif
  1263     }
  1280     }
  1264   }
  1281   }
  1265 
  1282 
  1266   {
  1283   if (from) {
  1267     LmMessageNode *muc_message = lm_message_node_find_xmlns(m->node, NS_MUC_USER);
  1284     x = lm_message_node_find_xmlns(m->node, NS_MUC_USER);
  1268     if (muc_message && !strcmp(muc_message->name, "x"))
  1285     if (x && !strcmp(x->name, "x"))
  1269       got_muc_message(from, muc_message, timestamp);
  1286       got_muc_message(from, x, timestamp);
  1270   }
  1287 
  1271 
  1288     x = lm_message_node_find_xmlns(m->node, NS_X_CONFERENCE);
  1272   {
  1289 
  1273     LmMessageNode *muc_invite = lm_message_node_find_xmlns(m->node, NS_X_CONFERENCE);
  1290     if (x && !strcmp(x->name, "x")) {
  1274 
  1291       const char *jid = lm_message_node_get_attribute(x, "jid");
  1275     if (muc_invite && !strcmp(muc_invite->name, "x")) {
       
  1276       const char *jid = lm_message_node_get_attribute(muc_invite, "jid");
  1292       if (jid) {
  1277       if (jid) {
  1293         const char *reason = lm_message_node_get_attribute(x, "reason");
  1278         const char *reason = lm_message_node_get_attribute(muc_invite, "reason");
  1294         const char *password = lm_message_node_get_attribute(x, "password");
  1279         const char *password = lm_message_node_get_attribute(muc_invite, "password");
  1295         // We won't send decline stanzas as it is a Direct Invitation
  1280         // We won't send decline stanzas as it is a Direct Invitation
  1296         got_invite(from, jid, reason, password, FALSE);
  1281         got_invite(from, jid, reason, password, FALSE);
  1297       }
  1282       }
  1298     }
  1283     }
  1299   }
  1284   }