Esempio n. 1
0
static void _callback_foreach_buddy_groupchat(gpointer rosterdata, void *param)
{
  LmMessageNode *field, *option;
  const char *room_jid, *nickname;
  char *desc;

  room_jid = buddy_getjid(rosterdata);
  if (!room_jid) return;
  nickname = buddy_getnickname(rosterdata);
  if (!nickname) return;
  field = param;

  option = lm_message_node_add_child(field, "option", NULL);
  lm_message_node_add_child(option, "value", room_jid);
  desc = g_strdup_printf("%s on %s", nickname, room_jid);
  lm_message_node_set_attribute(option, "label", desc);
  g_free(desc);
}
Esempio n. 2
0
void roompresence(gpointer room, void *presencedata)
{
  const char *bjid;
  const char *nickname;
  char *to;
  struct T_presence *pres = presencedata;

  if (!buddy_getinsideroom(room))
    return;

  bjid = buddy_getjid(room);
  if (!bjid) return;
  nickname = buddy_getnickname(room);
  if (!nickname) return;

  to = g_strdup_printf("%s/%s", bjid, nickname);
  xmpp_setstatus(pres->st, to, pres->msg, TRUE);
  g_free(to);
}
Esempio n. 3
0
void handle_muc_presence(const char *from, LmMessageNode *xmldata,
                         const char *roomjid, const char *rname,
                         enum imstatus ust, const char *ustmsg,
                         time_t usttime, char bpprio)
{
  char *mbuf;
  const char *ournick;
  enum imrole mbrole = role_none;
  enum imaffiliation mbaffil = affil_none;
  enum room_printstatus printstatus;
  enum room_autowhois autowhois;
  enum room_flagjoins flagjoins;
  const char *mbjid = NULL, *mbnick = NULL;
  const char *reason = NULL;
  char *actor = NULL;
  bool new_member = FALSE; // True if somebody else joins the room (not us)
  bool our_presence = FALSE; // True if this presence is from us (i.e. bears
                             // code 110)
  guint statuscode = 0;
  guint nickchange = 0;
  GSList *room_elt;
  int log_muc_conf;
  guint msgflags;

  log_muc_conf = settings_opt_get_int("log_muc_conf");

  room_elt = roster_find(roomjid, jidsearch, 0);
  if (!room_elt) {
    // Add room if it doesn't already exist
    // It shouldn't happen, there is probably something wrong (server or
    // network issue?)
    room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM,
                               sub_none, -1);
    scr_LogPrint(LPRINT_LOGNORM, "Strange MUC presence message");
  } else {
    // Make sure this is a room (it can be a conversion user->room)
    buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
  }

  // Get room member's information
  muc_get_item_info(from, xmldata, &mbrole, &mbaffil, &mbjid, &mbnick,
                    &actor, &reason);

  // Get our room nickname
  ournick = buddy_getnickname(room_elt->data);

  if (!ournick) {
    // It shouldn't happen, probably a server issue
    const gchar msg[] = "Unexpected groupchat packet!";
    scr_LogPrint(LPRINT_LOGNORM, msg);
    scr_WriteIncomingMessage(roomjid, msg, 0, HBB_PREFIX_INFO, 0);
    // Send back an unavailable packet
    xmpp_setstatus(offline, roomjid, "", TRUE);
    scr_draw_roster();
    return;
  }

#define SETSTATUSCODE(VALUE)                                              \
{                                                                         \
  if (G_UNLIKELY(statuscode))                                             \
    scr_LogPrint(LPRINT_DEBUG, "handle_muc_presence: WARNING: "           \
                 "replacing status code %u with %u.", statuscode, VALUE); \
  statuscode = VALUE;                                                     \
}

  { // Get the status code
    LmMessageNode *node;
    for (node = xmldata -> children; node; node = node -> next) {
      if (!g_strcmp0(node -> name, "status")) {
        const char *codestr = lm_message_node_get_attribute(node, "code");
        if (codestr) {
          const char *mesg = NULL;
          switch (atoi(codestr)) {
            // initial
            case 100:
                    mesg = "The room is not anonymous.";
                    break;
            case 110: // It is our presence
                    our_presence = TRUE;
                    break;
            // initial
            case 170:
                    mesg = "The room is logged.";
                    break;
            // initial
            case 201: // Room created
                    SETSTATUSCODE(201);
                    break;
            // initial
            case 210: // Your nick change (on join)
                    // FIXME: print nick
                    mesg = "The room has changed your nick!";
                    buddy_setnickname(room_elt->data, rname);
                    ournick = rname;
                    break;
            case 301: // User banned
                    SETSTATUSCODE(301);
                    break;
            case 303: // Nick change
                    SETSTATUSCODE(303);
                    break;
            case 307: // User kicked
                    SETSTATUSCODE(307);
                    break;
                    // XXX (next three)
            case 321:
                    mesg = "User leaves room due to affilation change.";
                    break;
            case 322:
                    mesg = "User leaves room, as room is only for members now.";
                    break;
            case 332:
                    mesg = "User leaves room due to system shutdown.";
                    break;
            default:
                    scr_LogPrint(LPRINT_DEBUG,
                           "handle_muc_presence: Unknown MUC status code: %s.",
                           codestr);
                    break;
          }
          if (mesg) {
            scr_WriteIncomingMessage(roomjid, mesg, usttime,
                                     HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
            if (log_muc_conf)
              hlog_write_message(roomjid, 0, -1, mesg);
          }
        }
      }
    }
  }

#undef SETSTATUSCODE

  if (!our_presence)
    if (ournick && !strcmp(ournick, rname))
      our_presence = TRUE;

  // Get the room's "print_status" settings
  printstatus = buddy_getprintstatus(room_elt->data);
  if (printstatus == status_default) {
    printstatus = (guint) settings_opt_get_int("muc_print_status");
    if (printstatus > 3)
      printstatus = status_default;
  }

  // A new room has been created; accept MUC default config
  if (statuscode == 201)
    xmpp_room_unlock(roomjid);

  // Check for nickname change
  if (statuscode == 303 && mbnick) {
    mbuf = g_strdup_printf("%s is now known as %s", rname, mbnick);
    scr_WriteIncomingMessage(roomjid, mbuf, usttime,
                             HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
    if (log_muc_conf)
      hlog_write_message(roomjid, 0, -1, mbuf);
    g_free(mbuf);
    buddy_resource_setname(room_elt->data, rname, mbnick);
    // Maybe it's _our_ nickname...
    if (our_presence)
      buddy_setnickname(room_elt->data, mbnick);
    nickchange = TRUE;
  }

  autowhois = buddy_getautowhois(room_elt->data);
  if (autowhois == autowhois_default)
    autowhois = (settings_opt_get_int("muc_auto_whois") ?
                 autowhois_on : autowhois_off);

  // Check for departure/arrival
  if (statuscode != 303 && ust == offline) {
    // Somebody is leaving
    enum { leave=0, kick, ban } how = leave;

    if (statuscode == 307)
      how = kick;
    else if (statuscode == 301)
      how = ban;

    // If this is a leave, check if it is ourself
    if (our_presence) {
      buddy_setinsideroom(room_elt->data, FALSE);
      buddy_setnickname(room_elt->data, NULL);
      buddy_del_all_resources(room_elt->data);
      buddy_settopic(room_elt->data, NULL);
      scr_update_chat_status(FALSE);
      update_roster = TRUE;
    }

    // The message depends on _who_ left, and _how_
    if (how) {
      gchar *mbuf_end;
      gchar *reason_msg = NULL;
      // Forced leave
      if (actor) {
        mbuf_end = g_strdup_printf("%s from %s by %s",
                                   (how == ban ? "banned" : "kicked"),
                                   roomjid, actor);
      } else {
        mbuf_end = g_strdup_printf("%s from %s",
                                   (how == ban ? "banned" : "kicked"),
                                   roomjid);
      }
      if (reason)
        reason_msg = g_strdup_printf("\nReason: %s", reason);
      if (our_presence)
        mbuf = g_strdup_printf("You have been %s%s", mbuf_end,
                               reason_msg ? reason_msg : "");
      else
        mbuf = g_strdup_printf("%s has been %s%s", rname, mbuf_end,
                               reason_msg ? reason_msg : "");

      g_free(reason_msg);
      g_free(mbuf_end);
    } else {
      // Natural leave
      if (our_presence) {
        LmMessageNode *destroynode = lm_message_node_find_child(xmldata,
                                                                "destroy");
        if (destroynode) {
          reason = lm_message_node_get_child_value(destroynode, "reason");
          if (reason && *reason) {
            mbuf = g_strdup_printf("You have left %s, "
                                   "the room has been destroyed: %s",
                                   roomjid, reason);
          } else {
            mbuf = g_strdup_printf("You have left %s, "
                                   "the room has been destroyed", roomjid);
          }
        } else {
          mbuf = g_strdup_printf("You have left %s", roomjid);
        }
      } else {
        if (ust != offline) {
          // This can happen when a network failure occurs,
          // this isn't an official leave but the user isn't there anymore.
          mbuf = g_strdup_printf("%s has disappeared!", rname);
          ust = offline;
        } else {
          if (ustmsg)
            mbuf = g_strdup_printf("%s has left: %s", rname, ustmsg);
          else
            mbuf = g_strdup_printf("%s has left", rname);
        }
      }
    }

    g_free(actor);

    // Display the mbuf message if we're concerned
    // or if the print_status isn't set to none.
    if (our_presence || printstatus != status_none) {
      msgflags = HBB_PREFIX_INFO;
      flagjoins = buddy_getflagjoins(room_elt->data);
      if (flagjoins == flagjoins_default &&
          settings_opt_get_int("muc_flag_joins") == 2)
	flagjoins = flagjoins_all;
      if (!our_presence && flagjoins != flagjoins_all)
        msgflags |= HBB_PREFIX_NOFLAG;
      //silent message if someone else joins, and we care about noone
      scr_WriteIncomingMessage(roomjid, mbuf, usttime, msgflags, 0);
    }

    if (log_muc_conf)
      hlog_write_message(roomjid, 0, -1, mbuf);

    if (our_presence) {
      scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf);
      g_free(mbuf);
      return;
    }
    g_free(mbuf);
  } else {
    enum imstatus old_ust = buddy_getstatus(room_elt->data, rname);
    if (old_ust == offline && ust != offline) {
      // Somebody is joining
      new_member = muc_handle_join(room_elt, rname, roomjid, ournick,
                                   printstatus, usttime, log_muc_conf,
                                   autowhois, mbjid);
    } else {
      // This is a simple member status change

      if (printstatus == status_all && !nickchange) {
        const char *old_ustmsg = buddy_getstatusmsg(room_elt->data, rname);
        if (old_ust != ust || g_strcmp0(old_ustmsg, ustmsg)) {
          mbuf = g_strdup_printf("%s [%c>%c] %s", rname, imstatus2char[old_ust],
                                 imstatus2char[ust], ((ustmsg) ? ustmsg : ""));
          scr_WriteIncomingMessage(roomjid, mbuf, usttime,
                                 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
          g_free(mbuf);
        }
      }
    }
  }

  // Sanity check, shouldn't happen...
  if (!rname)
    return;

  // Update room member status
  roster_setstatus(roomjid, rname, bpprio, ust, ustmsg, usttime,
                   mbrole, mbaffil, mbjid);

  if (new_member && autowhois == autowhois_on) {
    cmd_room_whois(room_elt->data, rname, FALSE);
  }

  scr_draw_roster();
}