コード例 #1
1
ファイル: xmpp_muc.c プロジェクト: Like-all/mcabber
//  got_invite(from, to, reason, passwd, reply)
// This function should be called when receiving an invitation from user
// "from", to enter the room "to".  Optional reason and room password can
// be provided.
void got_invite(const char* from, const char *to, const char* reason,
                const char* passwd, gboolean reply)
{
  GString *sbuf;
  char *barejid;
  GSList *room_elt;

  sbuf = g_string_new("");
  if (reason && reason[0]) {
    g_string_printf(sbuf,
                    "Received an invitation to <%s>, from <%s>, reason: %s",
                    to, from, reason);
  } else {
    g_string_printf(sbuf, "Received an invitation to <%s>, from <%s>",
                    to, from);
  }

  barejid = jidtodisp(from);
  scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
  scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);

  { // remove any equal older invites
    GSList *iel = invitations;
    while (iel) {
      event_muc_invitation *invitation = iel->data;
      iel = iel -> next;
      if (!g_strcmp0(to, invitation->to) &&
          !g_strcmp0(passwd, invitation->passwd)) {
        // found a previous invitation
        // We keep the old one, unless the current one is better and allows us
        // to send a reply.
        if (!reply || invitation->reply) {
          g_free(barejid);
          return;
        }
        scr_LogPrint(LPRINT_DEBUG, "Destroying previous invitation event %s.",
                     invitation->evid);
        evs_del(invitation->evid);
      }
    }
  }

  { // create event
    const char *id;
    char *desc = g_strdup_printf("<%s> invites you to %s", from, to);
    event_muc_invitation *invitation;

    invitation = g_new(event_muc_invitation, 1);
    invitation->to = g_strdup(to);
    invitation->from = g_strdup(from);
    invitation->passwd = g_strdup(passwd);
    invitation->reason = g_strdup(reason);
    invitation->reply = reply;
    invitation->evid = NULL;

    invitations = g_slist_append(invitations, invitation);

    id = evs_new(desc, NULL, 0, evscallback_invitation, invitation,
                 (GDestroyNotify)destroy_event_muc_invitation);
    g_free(desc);
    if (id) {
      invitation->evid = g_strdup(id);
      g_string_printf(sbuf, "Please use /event %s accept|reject", id);
    } else
      g_string_printf(sbuf, "Unable to create a new event!");
  }
  scr_WriteIncomingMessage(barejid, sbuf->str, 0, HBB_PREFIX_INFO, 0);
  scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
  g_string_free(sbuf, TRUE);
  g_free(barejid);

  // Make sure the MUC room barejid is a room in the roster
  barejid = jidtodisp(to);
  room_elt = roster_find(barejid, jidsearch, 0);
  if (room_elt)
    buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);

  g_free(barejid);
}
コード例 #2
0
ファイル: fifo_internal.c プロジェクト: weiss/mcabber
//  fifo_init_internal(path)
// If path is NULL, reopen existing fifo, else open anew.
static int fifo_init_internal(const char *fifo_path)
{
  if (fifo_path) {
    fifo_deinit();
    fifo_name = expand_filename(fifo_path);

    if (!check_fifo(fifo_name)) {
      scr_LogPrint(LPRINT_LOGNORM, "WARNING: Cannot create the FIFO. "
                   "%s already exists and is not a pipe", fifo_name);
      g_free(fifo_name);
      fifo_name = NULL;
      return -1;
    }
  } else if (fifo_name)
    g_source_remove_by_user_data(fifo_channel);
  else
    return -1;

  if (!attach_fifo(fifo_name)) {
    scr_LogPrint(LPRINT_LOGNORM, "Error: Cannot open fifo");
    return -1;
  }

  setenv(FIFO_ENV_NAME, fifo_name, 1);

  scr_LogPrint(LPRINT_LOGNORM, "FIFO initialized (%s)", fifo_path);
  return 1;
}
コード例 #3
0
ファイル: filetransfer.c プロジェクト: alkino/mcabber-jingle
static void _jft_info(char **args)
{
  GSList *el = info_list;

  if (!info_list)
    scr_LogPrint(LPRINT_LOGNORM, "JFT: no file");

  for (el = info_list; el; el = el->next) {
    JingleFTInfo *jftio = el->data;
    JingleFT *jft = jftio->jft;
    gchar *strsize = _convert_size(jft->size);
    const gchar *dir = (jft->dir == JINGLE_FT_INCOMING) ? "<==" : "-->";
    gfloat percent = (gfloat)jft->size ? 
                       ((gfloat)jft->transmit / (gfloat)jft->size) * 100 :
                       0;
    const gchar *state = strstate[jft->state];
    const gchar *desc = jft->desc ? jft->desc : "";
    const gchar *hash = "";
    if (jft->dir == JINGLE_FT_INCOMING &&
        jft->state == JINGLE_FT_ENDING) {
      if (_check_hash(jft->hash, jft->md5) == FALSE)
        hash = "corrupt";
      else
        hash = "checked";
    }

    scr_LogPrint(LPRINT_LOGNORM, "[%i]%s %s %s %.2f%%: %s %s %s", jftio->index, 
                 dir, jftio->jft->name, strsize, percent, desc, state, hash);
    g_free(strsize);
  }
}
コード例 #4
0
ファイル: xmpp_muc.c プロジェクト: Like-all/mcabber
// invitation event handler
// TODO: if event is accepted, check if other events to the same room exist and
// destroy them? (need invitation registry list for that)
static gboolean evscallback_invitation(guint evcontext, const char *arg, gpointer userdata)
{
  event_muc_invitation *invitation = userdata;

  // Sanity check
  if (G_UNLIKELY(!invitation)) {
    // Shouldn't happen.
    scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback.");
    return FALSE;
  }

  if (evcontext == EVS_CONTEXT_TIMEOUT) {
    scr_LogPrint(LPRINT_LOGNORM, "Invitation event %s timed out, cancelled.", invitation->to);
    return FALSE;
  }
  if (evcontext == EVS_CONTEXT_CANCEL) {
    scr_LogPrint(LPRINT_LOGNORM, "Invitation event %s cancelled.", invitation->to);
    return FALSE;
  }
  if (!(evcontext == EVS_CONTEXT_ACCEPT || evcontext == EVS_CONTEXT_REJECT))
    return FALSE;

  // Ok, let's work now
  if (evcontext == EVS_CONTEXT_ACCEPT) {
    char *nickname = default_muc_nickname(invitation->to);
    xmpp_room_join(invitation->to, nickname, invitation->passwd);
    g_free(nickname);
  } else {
    scr_LogPrint(LPRINT_LOGNORM, "Invitation to %s refused.", invitation->to);
    if (invitation->reply)
      decline_invitation(invitation, arg);
  }

  return FALSE;
}
コード例 #5
0
ファイル: filetransfer.c プロジェクト: alkino/mcabber-jingle
static JingleFT* _new(const gchar *name)
{
  struct stat fileinfo;
  GError *err = NULL;
  gchar *filename = expand_filename(name); // expand ~ to HOME
  JingleFT *jft = g_new0(JingleFT, 1);
  
  jft->desc = g_strdup(name);
  jft->type = JINGLE_FT_OFFER;
  jft->name = g_path_get_basename(filename);
  jft->transmit = 0;
  jft->hash = NULL;
  jft->md5 = NULL;
  jft->state = JINGLE_FT_PENDING;
  jft->dir = JINGLE_FT_OUTGOING;
  jft->date = 0;
  jft->size = 0;
  
  // Add the jft to the list
  JingleFTInfo *jftinf = g_new0(JingleFTInfo, 1);
  jftinf->index = _next_index();
  jftinf->jft = jft;
  info_list = g_slist_append(info_list, jftinf);

  if (g_stat(filename, &fileinfo) != 0) {
    scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: unable to stat %s",
                 filename);
    jft->state = JINGLE_FT_ERROR;
    return NULL;
  }

  if (!S_ISREG(fileinfo.st_mode) || S_ISLNK(fileinfo.st_mode)) {
    scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: File doesn't exist!");
    jft->state = JINGLE_FT_ERROR;
    return NULL;
  }

  jft->date = fileinfo.st_mtime;
  jft->size = fileinfo.st_size;
  
  jft->outfile = g_io_channel_new_file(filename, "r", &err);
  if (jft->outfile == NULL || err != NULL) {
    scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message,
                 name);
    g_error_free(err);
    jft->state = JINGLE_FT_ERROR;
    return NULL;
  }

  g_io_channel_set_encoding(jft->outfile, NULL, &err);
  if (jft->outfile == NULL || err != NULL) {
    scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message,
                 name);
    g_error_free(err);
    jft->state = JINGLE_FT_ERROR;
    return NULL;
  }
  
  return jft;
}
コード例 #6
0
ファイル: xmpp_muc.c プロジェクト: Like-all/mcabber
//  muc_get_item_info(...)
// Get room member's information from xmlndata.
// The variables must be initialized before calling this function,
// because they are not touched if the relevant information is missing.
// Note that *actor should be freed by the caller.
static void muc_get_item_info(const char *from, LmMessageNode *xmldata,
                              enum imrole *mbrole, enum imaffiliation *mbaffil,
                              const char **mbjid, const char **mbnick,
                              char **actor, const char **reason)
{
  LmMessageNode *y, *z;
  const char *p, *actorjid, *actornick;

  y = lm_message_node_find_child(xmldata, "item");
  if (!y)
    return;

  p = lm_message_node_get_attribute(y, "affiliation");
  if (p) {
    if (!strcmp(p, "owner"))        *mbaffil = affil_owner;
    else if (!strcmp(p, "admin"))   *mbaffil = affil_admin;
    else if (!strcmp(p, "member"))  *mbaffil = affil_member;
    else if (!strcmp(p, "outcast")) *mbaffil = affil_outcast;
    else if (!strcmp(p, "none"))    *mbaffil = affil_none;
    else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown affiliation \"%s\"",
                      from, p);
  }
  p = lm_message_node_get_attribute(y, "role");
  if (p) {
    if (!strcmp(p, "moderator"))        *mbrole = role_moderator;
    else if (!strcmp(p, "participant")) *mbrole = role_participant;
    else if (!strcmp(p, "visitor"))     *mbrole = role_visitor;
    else if (!strcmp(p, "none"))        *mbrole = role_none;
    else scr_LogPrint(LPRINT_LOGNORM, "<%s>: Unknown role \"%s\"",
                      from, p);
  }
  *mbjid = lm_message_node_get_attribute(y, "jid");
  *mbnick = lm_message_node_get_attribute(y, "nick");
  // For kick/ban, there can be actor and reason tags
  z = lm_message_node_find_child(y, "actor");
  if (z) {
    actornick = lm_message_node_get_attribute(z, "nick");
    actorjid  = lm_message_node_get_attribute(z, "jid");
    if (actorjid) {
      if (actornick) {
        // We have both the actor's jid and nick
        *actor = g_strdup_printf("%s <%s>", actornick, actorjid);
      } else {
        *actor = g_strdup(actorjid); // jid only
      }
    } else if (!actorjid && actornick) {
      // We only have the nickname
      *actor = g_strdup(actornick);
    }
  }

  *reason = lm_message_node_get_child_value(y, "reason");
  if (*reason && !**reason)
    *reason = NULL;
}
コード例 #7
0
ファイル: xmpp_muc.c プロジェクト: Like-all/mcabber
int xmpp_room_setattrib(const char *roomid, const char *fjid,
                        const char *nick, struct role_affil ra,
                        const char *reason)
{
  LmMessage *iq;
  LmMessageHandler *handler;
  LmMessageNode *query, *x;

  if (!xmpp_is_online() || !roomid)
    return 1;
  if (!fjid && !nick) return 1;

  if (check_jid_syntax((char*)roomid)) {
    scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", roomid);
    return 1;
  }
  if (fjid && check_jid_syntax((char*)fjid)) {
    scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", fjid);
    return 1;
  }

  if (ra.type == type_affil && ra.val.affil == affil_outcast && !fjid)
    return 1; // Shouldn't happen (jid mandatory when banning)

  iq = lm_message_new_with_sub_type(roomid, LM_MESSAGE_TYPE_IQ,
                                    LM_MESSAGE_SUB_TYPE_SET);
  query = lm_message_node_add_child(iq->node, "query", NULL);
  lm_message_node_set_attribute(query, "xmlns", NS_MUC_ADMIN);
  x = lm_message_node_add_child(query, "item", NULL);

  if (fjid) {
    lm_message_node_set_attribute(x, "jid", fjid);
  } else { // nickname
    lm_message_node_set_attribute(x, "nick", nick);
  }

  if (ra.type == type_affil)
    lm_message_node_set_attribute(x, "affiliation", straffil[ra.val.affil]);
  else if (ra.type == type_role)
    lm_message_node_set_attribute(x, "role", strrole[ra.val.role]);

  if (reason)
    lm_message_node_add_child(x, "reason", reason);

  handler = lm_message_handler_new(handle_iq_dummy, NULL, FALSE);
  lm_connection_send_with_reply(lconnection, iq, handler, NULL);
  lm_message_handler_unref(handler);
  lm_message_unref(iq);

  return 0;
}
コード例 #8
0
ファイル: xmpp_iq.c プロジェクト: weiss/mcabber
LmHandlerResult handle_iq_last(LmMessageHandler *h, LmConnection *c,
                               LmMessage *m, gpointer ud)
{
  LmMessage *r;
  LmMessageNode *query;
  char *seconds;

  if (!settings_opt_get_int("iq_hide_requests")) {
    scr_LogPrint(LPRINT_LOGNORM, "Received an IQ last time request from <%s>",
                 lm_message_get_from(m));
  }

  if (settings_opt_get_int("iq_last_disable") ||
      (settings_opt_get_int("iq_last_disable_when_notavail") &&
       xmpp_getstatus() == notavail))
  {
    send_iq_error(c, m, XMPP_ERROR_SERVICE_UNAVAILABLE);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT);
  query = lm_message_node_add_child(r->node, "query", NULL);
  lm_message_node_set_attribute(query, "xmlns", NS_LAST);
  seconds = g_strdup_printf("%.0f", seconds_since_last_use());
  lm_message_node_set_attribute(query, "seconds", seconds);
  g_free(seconds);

  lm_connection_send(c, r, NULL);
  lm_message_unref(r);
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #9
0
static guint mucignore_handle_message(const gchar *hookname, hk_arg_t *args,
    gpointer userdata)
{
    const gchar* bjid = 0;
    const gchar* resource = 0;
    const gchar* groupchat = 0;
    gchar* fullname = 0;
    guint result = HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;

    for (; args->name; ++args) {
        if (!bjid && !g_strcmp0(args->name, "jid")) {
            bjid = args->value;
        } else if (!resource && !g_strcmp0(args->name, "resource")) {
            resource = args->value;
        } else if (!groupchat && !g_strcmp0(args->name, "groupchat")) {
            groupchat = args->value;
        }
    }

    if (groupchat && bjid && resource && !g_strcmp0(groupchat, "true")) {
        fullname = g_strdup_printf("%s/%s", bjid, resource);
        if (g_regex_match(mucignore, fullname, 0, NULL)) {
            scr_LogPrint(LPRINT_NORMAL, "Message from %s ignored", fullname);
            result = HOOK_HANDLER_RESULT_NO_MORE_HANDLER_DROP_DATA;
        }
    }
    g_free(fullname);
    return result;
}
コード例 #10
0
ファイル: xmpp_iq.c プロジェクト: jbar/mcabber
// This function borrows some code from the Pidgin project
LmHandlerResult handle_iq_time202(LmMessageHandler *h, LmConnection *c,
                                  LmMessage *m, gpointer ud)
{
  LmMessage *r;
  LmMessageNode *query;
  char *buf, *utf8_buf;
  time_t now_t;
  struct tm *now;
  char const *sign;
  int diff = 0;

  time(&now_t);

  if (!settings_opt_get_int("iq_hide_requests")) {
    scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>",
                 lm_message_get_from(m));
  }

  buf = g_new0(char, 512);

  r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT);
  query = lm_message_node_add_child(r->node, "time", NULL);
  lm_message_node_set_attribute(query, "xmlns", NS_XMPP_TIME);

  now = localtime(&now_t);

  if (now->tm_isdst >= 0) {
#if defined HAVE_TM_GMTOFF
    diff = now->tm_gmtoff;
#elif defined HAVE_TIMEZONE
    tzset();
    diff = -timezone;
#endif
  }

  if (diff < 0) {
    sign = "-";
    diff = -diff;
  } else {
    sign = "+";
  }
  diff /= 60;
  snprintf(buf, 512, "%c%02d:%02d", *sign, diff / 60, diff % 60);
  if ((utf8_buf = to_utf8(buf))) {
    lm_message_node_add_child(query, "tzo", utf8_buf);
    g_free(utf8_buf);
  }

  now = gmtime(&now_t);

  strftime(buf, 512, "%Y-%m-%dT%TZ", now);
  lm_message_node_add_child(query, "utc", buf);

  lm_connection_send(c, r, NULL);
  lm_message_unref(r);
  g_free(buf);
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #11
0
ファイル: xmpp_iqrequest.c プロジェクト: capterin/mcabber
static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c,
                               LmMessage *m, gpointer user_data)
{
  LmMessageNode *ansqry;
  const char *bjid;
  char *buf, *tmp;

  // Check IQ result sender
  bjid = lm_message_get_from(m);
  if (!bjid)
    bjid = lm_connection_get_jid(lconnection); // No from means our JID...
  if (!bjid) {
    scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:vCard result (no sender name).");
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  // Check for error message
  if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
    scr_LogPrint(LPRINT_LOGNORM, "Received error IQ message (%s)", bjid);
    display_server_error(lm_message_node_get_child(m->node, "error"), NULL);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  buf = g_strdup_printf("Received IQ:vCard result from <%s>", bjid);
  scr_LogPrint(LPRINT_LOGNORM, "%s", buf);

  // Get the vCard node
  ansqry = lm_message_node_get_child(m->node, "vCard");
  if (!ansqry) {
    scr_LogPrint(LPRINT_LOGNORM, "Empty IQ:vCard result!");
    g_free(buf);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  // bjid should really be the "bare JID", let's strip the resource
  tmp = strchr(bjid, JID_RESOURCE_SEPARATOR);
  if (tmp) *tmp = '\0';

  scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
  g_free(buf);

  // Get result data...
  handle_vcard_node(bjid, ansqry);
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #12
0
ファイル: xmpp_iqrequest.c プロジェクト: stef/mcabber
static LmHandlerResult cb_storage_bookmarks(LmMessageHandler *h,
                                            LmConnection *c,
                                            LmMessage *m, gpointer user_data)
{
  LmMessageNode *x, *ansqry;
  char *p = NULL;

  if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
    LmMessageNode *error = lm_message_node_get_child(m->node, "error");
    // No server support, or no bookmarks?
    if (error && error->children)
      p = error->children->name;
    if (p && !strcmp(p, "item-not-found")) {
      // item-no-found means the server has Private Storage, but it's
      // currently empty.
      if (bookmarks)
        lm_message_node_unref(bookmarks);
      bookmarks = lm_message_node_new("storage", "storage:bookmarks");
      // We return 0 so that the IQ error message be
      // not displayed, as it isn't a real error.
    } else
      scr_LogPrint(LPRINT_LOGNORM, "Server does not support bookmarks storage.");
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  ansqry = lm_message_node_get_child(m->node, "query");
  ansqry = lm_message_node_get_child(ansqry, "storage");
  if (!ansqry) {
    scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! (storage:bookmarks)");
    return 0;
  }

  // Walk through the storage tags
  for (x = ansqry->children ; x; x = x->next) {
    // If the current node is a conference item, parse it and update the roster
    if (x->name && !strcmp(x->name, "conference"))
      storage_bookmarks_parse_conference(x);
  }
  // "Copy" the bookmarks node
  if (bookmarks)
    lm_message_node_unref(bookmarks);
  lm_message_node_deep_ref(ansqry);
  bookmarks = ansqry;
  return 0;
}
コード例 #13
0
ファイル: xmpp_iqrequest.c プロジェクト: capterin/mcabber
static LmHandlerResult cb_ping(LmMessageHandler *h, LmConnection *c,
                               LmMessage *m, gpointer user_data)
{
  struct timeval *timestamp = (struct timeval *)user_data;
  struct timeval now;
  time_t         dsec;
  suseconds_t    dusec;
  const gchar    *fjid;
  gchar          *bjid, *mesg = NULL;

  gettimeofday(&now, NULL);
  dsec = now.tv_sec - timestamp->tv_sec;
  if (now.tv_usec < timestamp->tv_usec) {
    dusec = now.tv_usec + 1000000 - timestamp->tv_usec;
    --dsec;
  } else
    dusec = now.tv_usec - timestamp->tv_usec;

  // Check IQ result sender
  fjid = lm_message_get_from(m);
  if (!fjid)
    fjid = lm_connection_get_jid(lconnection); // No from means our JID...
  if (!fjid) {
    scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result (no sender name).");
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  bjid  = jidtodisp(fjid);

  switch (lm_message_get_sub_type(m)) {
    case LM_MESSAGE_SUB_TYPE_RESULT:
        mesg = g_strdup_printf("Pong from <%s>: %d second%s %d ms.", fjid,
                               (int)dsec, dsec > 1 ? "s" : "",
                               (int)(dusec/1000L));
        break;

    case LM_MESSAGE_SUB_TYPE_ERROR:
        display_server_error(lm_message_node_get_child(m->node, "error"),
                             fjid);
        mesg = g_strdup_printf("Ping to <%s> failed.  "
                               "Response time: %d second%s %d ms.",
                               fjid, (int)dsec, dsec > 1 ? "s" : "",
                               (int)(dusec/1000L));
        break;

    default:
        g_free(bjid);
        return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
        break;
  }

  if (mesg)
    scr_WriteIncomingMessage(bjid, mesg, 0, HBB_PREFIX_INFO, 0);
  g_free(mesg);
  g_free(bjid);
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #14
0
ファイル: fifo_internal.c プロジェクト: weiss/mcabber
static guint fifo_callback(GIOChannel *channel,
                           GIOCondition condition,
                           gpointer data)
{
  if (condition & (G_IO_IN|G_IO_PRI)) {
    GIOStatus  chstat;
    gchar     *buf;
    gsize      endpos;

    chstat = g_io_channel_read_line(channel, &buf, NULL, &endpos, NULL);
    if (chstat == G_IO_STATUS_ERROR || chstat == G_IO_STATUS_EOF) {
      if (!attach_fifo(fifo_name))
        scr_LogPrint(LPRINT_LOGNORM,
                     "Reopening fifo failed! Fifo will not work from now!");
      return FALSE;
    }
    if (buf) {
      guint logflag;
      guint fifo_ignore = settings_opt_get_int("fifo_ignore");

      if (endpos)
        buf[endpos] = '\0';

      if (settings_opt_get_int("fifo_hide_commands"))
        logflag = LPRINT_LOG;
      else
        logflag = LPRINT_LOGNORM;
      scr_LogPrint(logflag, "%s FIFO command: %s",
                   (fifo_ignore ? "Ignoring" : "Executing"), buf);
      if (!fifo_ignore) {
        process_command(buf, TRUE);
      }

      g_free(buf);
    }
  } else if (condition & (G_IO_ERR|G_IO_NVAL|G_IO_HUP)) {
    if (!attach_fifo(fifo_name))
      scr_LogPrint(LPRINT_LOGNORM,
                   "Reopening fifo failed! Fifo will not work from now!");
    return FALSE;
  }
  return TRUE;
}
コード例 #15
0
ファイル: fifo_internal.c プロジェクト: weiss/mcabber
// Returns 1 in case of success, -1 on error
int fifo_init(void)
{
  const char *path = settings_opt_get("fifo_name");
  static gboolean guard_installed = FALSE;
  if (!guard_installed)
    if (!(guard_installed = settings_set_guard("fifo_name", fifo_guard)))
      scr_LogPrint(LPRINT_DEBUG, "fifo: BUG: Cannot install option guard!");
  if (path)
    return fifo_init_internal(path);
  return 1;
}
コード例 #16
0
ファイル: events.c プロジェクト: jbar/mcabber
//  evs_display_list()
// Prints list of events to mcabber log window.
void evs_display_list(void)
{
  guint count = 0;
  GSList *p;

  scr_LogPrint(LPRINT_NORMAL, "Events list:");
  for (p = evs_list; p; p = g_slist_next(p)) {
    evs_t *i = p->data;
    scr_LogPrint(LPRINT_NORMAL,
                 "Id: %-3s %s", i->id,
                 (i->description ? i->description : ""));
    count++;
  }
  scr_LogPrint(LPRINT_NORMAL, "End of events list.");
  if (count+2 > scr_getlogwinheight()) {
    scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE);
    scr_setattentionflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE,
                                   ROSTER_UI_PRIO_STATUS_WIN_MESSAGE, prio_max);
  }
}
コード例 #17
0
ファイル: xmpp_iqrequest.c プロジェクト: stef/mcabber
static LmHandlerResult cb_storage_rosternotes(LmMessageHandler *h,
                                              LmConnection *c,
                                              LmMessage *m, gpointer user_data)
{
  LmMessageNode *ansqry;

  if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
    const char *p = NULL;
    LmMessageNode *error = lm_message_node_get_child(m->node, "error");
    // No server support, or no roster notes?
    if (error && error->children)
      p = error->children->name;
    if (p && !strcmp(p, "item-not-found")) {
      // item-no-found means the server has Private Storage, but it's
      // currently empty.
      if (rosternotes)
        lm_message_node_unref(rosternotes);
      rosternotes = lm_message_node_new("storage", "storage:rosternotes");
      // We return 0 so that the IQ error message be
      // not displayed, as it isn't a real error.
    } else
      scr_LogPrint(LPRINT_LOGNORM, "Server does not support roster notes storage.");
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  ansqry = lm_message_node_get_child(m->node, "query");
  ansqry = lm_message_node_get_child(ansqry, "storage");
  if (!ansqry) {
    scr_LogPrint(LPRINT_LOG, "Invalid IQ:private result! "
                 "(storage:rosternotes)");
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }
  // Copy the rosternotes node
  if (rosternotes)
    lm_message_node_unref(rosternotes);
  lm_message_node_deep_ref(ansqry);
  rosternotes = ansqry;
  return 0;
}
コード例 #18
0
ファイル: xmpp_iq.c プロジェクト: weiss/mcabber
// This function borrows some code from the Pidgin project
LmHandlerResult handle_iq_time(LmMessageHandler *h, LmConnection *c,
                               LmMessage *m, gpointer ud)
{
  LmMessage *r;
  LmMessageNode *query;
  char *buf, *utf8_buf;
  time_t now_t;
  struct tm *now;

  time(&now_t);

  if (!settings_opt_get_int("iq_hide_requests")) {
    scr_LogPrint(LPRINT_LOGNORM, "Received an IQ time request from <%s>",
                 lm_message_get_from(m));
  }

  if (settings_opt_get_int("iq_time_hide")) {
    send_iq_error(c, m, XMPP_ERROR_SERVICE_UNAVAILABLE);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  buf = g_new0(char, 512);

  r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT);
  query = lm_message_node_add_child(r->node, "query", NULL);
  lm_message_node_set_attribute(query, "xmlns", NS_TIME);

  now = gmtime(&now_t);

  strftime(buf, 512, "%Y%m%dT%T", now);
  lm_message_node_add_child(query, "utc", buf);

  now = localtime(&now_t);

  strftime(buf, 512, "%Z", now);
  if ((utf8_buf = to_utf8(buf))) {
    lm_message_node_add_child(query, "tz", utf8_buf);
    g_free(utf8_buf);
  }

  strftime(buf, 512, "%d %b %Y %T", now);
  if ((utf8_buf = to_utf8(buf))) {
    lm_message_node_add_child(query, "display", utf8_buf);
    g_free(utf8_buf);
  }

  lm_connection_send(c, r, NULL);
  lm_message_unref(r);
  g_free(buf);
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #19
0
ファイル: filetransfer.c プロジェクト: alkino/mcabber-jingle
static void _jft_send(char **args, JingleFT *jft2)
{
  JingleFT *jft = jft2;

  if (jft == NULL && !args[1]) {
    scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: give me a name!");
    return;
  }

  scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: Trying to send %s",
               args[1]);

  if (jft == NULL && (jft = _new(args[1])) == NULL)
    return;
  
  {
    gchar *ressource, *recipientjid;
    const gchar *namespaces[] = {NS_JINGLE, NS_JINGLE_APP_FT, NULL};

    if (CURRENT_JID == NULL) { // CURRENT_JID = the jid of the user which has focus
      scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: Please, choose a valid JID in the roster");
      jft->state = JINGLE_FT_ERROR;
      return;
    }
    ressource = jingle_find_compatible_res(CURRENT_JID, namespaces);
    if (ressource == NULL) {
      scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: Cannot send file, because this buddy"
                                   " has no compatible ressource available");

      jft->state = JINGLE_FT_ERROR;
      return;
    }

    recipientjid = g_strdup_printf("%s/%s", CURRENT_JID, ressource);

    new_session_with_apps(recipientjid, (const gchar*[]){"file", NULL},
                          (gconstpointer[]){jft, NULL},
                          (const gchar*[]){NS_JINGLE_APP_FT, NULL});
コード例 #20
0
ファイル: xmpp_muc.c プロジェクト: Like-all/mcabber
// Join a MUC room
void xmpp_room_join(const char *room, const char *nickname, const char *passwd)
{
  LmMessage *x;
  LmMessageNode *y;
  gchar *roomid;
  GSList *room_elt;

  if (!xmpp_is_online() || !room)
    return;
  if (!nickname)        return;

  roomid = g_strdup_printf("%s/%s", room, nickname);
  if (check_jid_syntax(roomid)) {
    scr_LogPrint(LPRINT_NORMAL, "<%s/%s> is not a valid Jabber room", room,
                 nickname);
    g_free(roomid);
    return;
  }

  room_elt = roster_find(room, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM);
  // Add room if it doesn't already exist
  if (!room_elt) {
    room_elt = roster_add_user(room, NULL, NULL, ROSTER_TYPE_ROOM,
                               sub_none, -1);
  } else {
    // Make sure this is a room (it can be a conversion user->room)
    buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
  }
  // If insideroom is TRUE, this is a nickname change and we don't care here
  if (!buddy_getinsideroom(room_elt->data)) {
    // We're trying to enter a room
    buddy_setnickname(room_elt->data, nickname);
  }

  // Send the XML request
  x = lm_message_new_presence(mystatus, roomid, mystatusmsg);
  xmpp_insert_entity_capabilities(x->node, mystatus); // Entity Caps (XEP-0115)
  y = lm_message_node_add_child(x->node, "x", NULL);
  lm_message_node_set_attribute(y, "xmlns", NS_MUC);
  if (passwd)
    lm_message_node_add_child(y, "password", passwd);

  lm_connection_send(lconnection, x, NULL);
  lm_message_unref(x);
  g_free(roomid);
}
コード例 #21
0
ファイル: xmpp_iq.c プロジェクト: weiss/mcabber
LmHandlerResult handle_iq_version(LmMessageHandler *h, LmConnection *c,
                                  LmMessage *m, gpointer ud)
{
  LmMessage *r;
  LmMessageNode *query;

  if (!settings_opt_get_int("iq_hide_requests")) {
    scr_LogPrint(LPRINT_LOGNORM, "Received an IQ version request from <%s>",
                 lm_message_get_from(m));
  }

  if (settings_opt_get_int("iq_version_hide")) {
    send_iq_error(c, m, XMPP_ERROR_SERVICE_UNAVAILABLE);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT);

  query = lm_message_node_add_child(r->node, "query", NULL);
  lm_message_node_set_attribute(query, "xmlns", NS_VERSION);

  lm_message_node_add_child(query, "name", PACKAGE_NAME);

  // MCabber version
  if (!settings_opt_get_int("iq_version_hide_version")) {
    char *ver = mcabber_version();
    lm_message_node_add_child(query, "version", ver);
    g_free(ver);
  }

  // OS details
  if (!settings_opt_get_int("iq_version_hide_os")) {
    char *os;
    struct utsname osinfo;
    uname(&osinfo);
    os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release,
                         osinfo.machine);
    lm_message_node_add_child(query, "os", os);
    g_free(os);
  }

  lm_connection_send(c, r, NULL);
  lm_message_unref(r);
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #22
0
ファイル: xmpp_iqrequest.c プロジェクト: capterin/mcabber
// Warning!! xmlns has to be a namespace from iq_request_handlers[].xmlns
void xmpp_iq_request(const char *fulljid, const char *xmlns)
{
  LmMessage *iq;
  LmMessageNode *query;
  LmMessageHandler *handler;
  gpointer data = NULL;
  GDestroyNotify notifier = NULL;
  GError *error = NULL;
  int i;

  iq = lm_message_new_with_sub_type(fulljid, LM_MESSAGE_TYPE_IQ,
                                    LM_MESSAGE_SUB_TYPE_GET);
  for (i = 0; strcmp(iq_request_handlers[i].xmlns, xmlns) != 0 ; ++i)
       ;
  query = lm_message_node_add_child(iq->node,
                                    iq_request_handlers[i].querytag,
                                    NULL);
  lm_message_node_set_attribute(query, "xmlns", xmlns);

  if (!g_strcmp0(xmlns, NS_PING)) {     // Create handler for ping queries
    struct timeval *now = g_new(struct timeval, 1);
    gettimeofday(now, NULL);
    data = (gpointer)now;
    notifier = g_free;
  }

  handler = lm_message_handler_new(iq_request_handlers[i].handler,
                                   data, notifier);

  lm_connection_send_with_reply(lconnection, iq, handler, &error);
  lm_message_handler_unref(handler);
  lm_message_unref(iq);

  if (error) {
    scr_LogPrint(LPRINT_LOGNORM, "Error sending IQ request: %s.", error->message);
    g_error_free(error);
  }
}
コード例 #23
0
ファイル: filetransfer.c プロジェクト: alkino/mcabber-jingle
static void _jft_flush(char **args)
{
  GSList *el, *el2 = info_list;
  int count = 0;
  el = info_list;
  while (el) {
    JingleFTInfo *jftinf;
    jftinf = el->data;
    if (jftinf->jft->state == JINGLE_FT_ERROR ||
        jftinf->jft->state == JINGLE_FT_REJECT ||
        jftinf->jft->state == JINGLE_FT_ENDING) {
      count++;
      _free(jftinf->jft);
      info_list = g_slist_delete_link(info_list, el);
      if (info_list == NULL)
        break;
      el = el2;
      continue;
    }
    el2 = el;
    el = el->next;
  }
  scr_LogPrint(LPRINT_LOGNORM, "JFT: %i file%s removed", count, (count>1) ? "s" : "");
}
コード例 #24
0
ファイル: xmpp_muc.c プロジェクト: Like-all/mcabber
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();
}
コード例 #25
0
ファイル: xmpp_muc.c プロジェクト: Like-all/mcabber
// Specific MUC message handling (for example invitation processing)
void got_muc_message(const char *from, LmMessageNode *x, time_t timestamp)
{
  LmMessageNode *node;
  // invitation
  node = lm_message_node_get_child(x, "invite");
  if (node) {
    const char *invite_from;
    const char *reason = NULL;
    const char *password = NULL;

    invite_from = lm_message_node_get_attribute(node, "from");
    reason = lm_message_node_get_child_value(node, "reason");
    password = lm_message_node_get_child_value(node, "password");
    if (invite_from)
      got_invite(invite_from, from, reason, password, TRUE);
  }

  // declined invitation
  node = lm_message_node_get_child(x, "decline");
  if (node) {
    const char *decline_from = lm_message_node_get_attribute(node, "from");
    const char *reason = lm_message_node_get_child_value(node, "reason");
    if (decline_from) {
      if (reason && reason[0])
        scr_LogPrint(LPRINT_LOGNORM, "<%s> declined your invitation: %s.",
                     from, reason);
      else
        scr_LogPrint(LPRINT_LOGNORM, "<%s> declined your invitation.", from);
    }
  }

  // status codes
  for (node = x -> 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 101:
                  mesg = "Your affilation has changed while absent.";
                  break;
          case 102:
                  mesg = "The room shows unavailable members.";
                  break;
          case 103:
                  mesg = "The room does not show unavailable members.";
                  break;
          case 104:
                  mesg = "The room configuration has changed.";
                  break;
          case 170:
                  mesg = "The room is logged.";
                  break;
          case 171:
                  mesg = "The room is not logged.";
                  break;
          case 172:
                  mesg = "The room is not anonymous.";
                  break;
          case 173:
                  mesg = "The room is semi-anonymous.";
                  break;
          case 174:
                  mesg = "The room is anonymous.";
                  break;
          default:
                  scr_LogPrint(LPRINT_DEBUG,
                               "got_muc_message: Unknown MUC status code: %s.",
                               codestr);
                  break;
        }
        if (mesg) {
          scr_WriteIncomingMessage(from, mesg, timestamp,
                                   HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
        if (settings_opt_get_int("log_muc_conf"))
            hlog_write_message(from, 0, -1, mesg);
        }
      }
    }
  }
}
コード例 #26
0
ファイル: filetransfer.c プロジェクト: alkino/mcabber-jingle
static gboolean handle_data(gconstpointer jingleft, const gchar *data, guint len)
{
  JingleFT *jft = (JingleFT *) jingleft;
  GError *err = NULL;
  GIOStatus status;
  gsize bytes_written = 0;

  if (jft->dir != JINGLE_FT_INCOMING)
    return FALSE;

  if (jft->md5 == NULL) {
    jft->md5 = g_checksum_new(G_CHECKSUM_MD5);
  }
  
  g_checksum_update(jft->md5, (guchar*)data, (gsize)len);
    
  // TODO: check if the file already exist or if it was created
  // during the call to jingle_ft_check and handle_data
  if (jft->outfile == NULL) {
    jft->outfile = g_io_channel_new_file(jft->name, "w", &err);
    if (jft->outfile == NULL || err != NULL) {
      scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message,
                   jft->name);
    //TODO: propagate the GError ?
      g_error_free(err);
      return FALSE;
    }
    jft->state = JINGLE_FT_STARTING;
    status = g_io_channel_set_encoding(jft->outfile, NULL, &err);
    if (status != G_IO_STATUS_NORMAL || err != NULL) {
     scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message,
                  jft->name);
     g_error_free(err);
     return FALSE;
   }
  }
  
  jft->state = JINGLE_FT_STARTING;

  status = g_io_channel_write_chars(jft->outfile, data, (gssize) len,
                                    &bytes_written, &err);
  if (status != G_IO_STATUS_NORMAL || err != NULL) {
     scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message,
                  jft->name);
    g_error_free(err);
    return FALSE;
  }
  status = g_io_channel_flush(jft->outfile, &err);
  if (status != G_IO_STATUS_NORMAL || err != NULL) {
    scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message,
                 jft->name);
    g_error_free(err);
    return FALSE;
  }

  if (bytes_written != len) {
    // not supposed to happen if status is normal, unless outfile is non-blocking
    return FALSE;
  }
  
  jft->transmit += len;
  return TRUE;
}
コード例 #27
0
ファイル: xmpp_iq.c プロジェクト: weiss/mcabber
LmHandlerResult handle_iq_roster(LmMessageHandler *h, LmConnection *c,
                                 LmMessage *m, gpointer ud)
{
  LmMessageNode *y;
  const char *fjid, *name, *group, *sub, *ask;
  char *cleanalias;
  enum subscr esub;
  int need_refresh = FALSE;
  guint roster_type;

  y = lm_message_node_find_child(lm_message_node_find_xmlns(m->node, NS_ROSTER),
                                 "item");
  for ( ; y; y = y->next) {
    char *name_tmp = NULL;

    fjid = lm_message_node_get_attribute(y, "jid");
    name = lm_message_node_get_attribute(y, "name");
    sub = lm_message_node_get_attribute(y, "subscription");
    ask = lm_message_node_get_attribute(y, "ask");

    if (lm_message_node_find_child(y, "group"))
      group = lm_message_node_get_value(lm_message_node_find_child(y, "group"));
    else
      group = NULL;

    if (!fjid)
      continue;

    cleanalias = jidtodisp(fjid);

    esub = sub_none;
    if (sub) {
      if (!strcmp(sub, "to"))          esub = sub_to;
      else if (!strcmp(sub, "from"))   esub = sub_from;
      else if (!strcmp(sub, "both"))   esub = sub_both;
      else if (!strcmp(sub, "remove")) esub = sub_remove;
    }

    if (esub == sub_remove) {
      roster_del_user(cleanalias);
      scr_LogPrint(LPRINT_LOGNORM, "Buddy <%s> has been removed "
                   "from the roster", cleanalias);
      g_free(cleanalias);
      need_refresh = TRUE;
      continue;
    }

    if (ask && !strcmp(ask, "subscribe"))
      esub |= sub_pending;

    if (!name) {
      if (!settings_opt_get_int("roster_hide_domain")) {
        name = cleanalias;
      } else {
        char *p;
        name = name_tmp = g_strdup(cleanalias);
        p = strchr(name_tmp, JID_DOMAIN_SEPARATOR);
        if (p)  *p = '\0';
      }
    }

    // Tricky... :-\  My guess is that if there is no JID_DOMAIN_SEPARATOR,
    // this is an agent.
    if (strchr(cleanalias, JID_DOMAIN_SEPARATOR))
      roster_type = ROSTER_TYPE_USER;
    else
      roster_type = ROSTER_TYPE_AGENT;

    roster_add_user(cleanalias, name, group, roster_type, esub, 1);

    g_free(name_tmp);
    g_free(cleanalias);
  }

  // Acknowledge IQ message
  if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_SET) {
    LmMessage *result;
    result = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT);
    lm_connection_send(c, result, NULL);
    lm_message_unref(result);
  }

  buddylist_build();
  update_roster = TRUE;
  if (need_refresh)
    scr_update_buddy_window();
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #28
0
ファイル: xmpp_iqrequest.c プロジェクト: capterin/mcabber
static void storage_bookmarks_parse_conference(LmMessageNode *node)
{
  const char *fjid, *name, *autojoin;
  const char *pstatus, *awhois, *fjoins, *group;
  char *bjid;
  GSList *room_elt;

  fjid = lm_message_node_get_attribute(node, "jid");
  if (!fjid)
    return;
  name = lm_message_node_get_attribute(node, "name");
  autojoin = lm_message_node_get_attribute(node, "autojoin");
  awhois = lm_message_node_get_attribute(node, "autowhois");
  pstatus = lm_message_node_get_child_value(node, "print_status");
  fjoins = lm_message_node_get_child_value(node, "flag_joins");
  group = lm_message_node_get_child_value(node, "group");

  bjid = jidtodisp(fjid); // Bare jid

  // Make sure this is a room (it can be a conversion user->room)
  room_elt = roster_find(bjid, jidsearch, 0);
  if (!room_elt) {
    room_elt = roster_add_user(bjid, name, group, ROSTER_TYPE_ROOM,
                               sub_none, -1);
  } else {
    buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
    /*
    // If the name is available, should we use it?
    // I don't think so, it would be confusing because this item is already
    // in the roster.
    if (name)
      buddy_setname(room_elt->data, name);

    // The same question for roster group.
    if (group)
      buddy_setgroup(room_elt->data, group);
    */
  }

  // Set the print_status and auto_whois values
  if (pstatus) {
    enum room_printstatus i;
    for (i = status_none; i <= status_all; i++)
      if (!strcasecmp(pstatus, strprintstatus[i]))
        break;
    if (i <= status_all)
      buddy_setprintstatus(room_elt->data, i);
  }
  if (awhois) {
    enum room_autowhois i = autowhois_default;
    if (!g_strcmp0(awhois, "1") || !(g_strcmp0(awhois, "true")))
      i = autowhois_on;
    else if (!g_strcmp0(awhois, "0") || !(g_strcmp0(awhois, "false")))
      i = autowhois_off;
    if (i != autowhois_default)
      buddy_setautowhois(room_elt->data, i);
  }
  if (fjoins) {
    enum room_flagjoins i;
    for (i = flagjoins_none; i <= flagjoins_all; i++)
      if (!strcasecmp(fjoins, strflagjoins[i]))
        break;
    if (i <= flagjoins_all)
      buddy_setflagjoins(room_elt->data, i);
  }

  // Is autojoin set?
  // If it is, we'll look up for more information (nick? password?) and
  // try to join the room.
  if (autojoin && !g_strcmp0(autojoin, "1")) {
    const char *nick, *passwd;
    char *tmpnick = NULL;
    nick = lm_message_node_get_child_value(node, "nick");
    passwd = lm_message_node_get_child_value(node, "password");
    if (!nick || !*nick)
      nick = tmpnick = default_muc_nickname(NULL);
    // Let's join now
    scr_LogPrint(LPRINT_LOGNORM, "Auto-join bookmark <%s>", bjid);
    xmpp_room_join(bjid, nick, passwd);
    g_free(tmpnick);
  }
  g_free(bjid);

  buddylist_build();
  update_roster = TRUE;
}
コード例 #29
0
ファイル: xmpp_iqrequest.c プロジェクト: capterin/mcabber
static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c,
                               LmMessage *m, gpointer user_data)
{
  LmMessageNode *ansqry;
  const char *p, *bjid;
  char *buf, *tmp;

  // Check IQ result sender
  bjid = lm_message_get_from(m);
  if (!bjid)
    bjid = lm_connection_get_jid(lconnection); // No from means our JID...
  if (!bjid) {
    scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:last result (no sender name).");
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  // Check for error message
  if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
    scr_LogPrint(LPRINT_LOGNORM, "Received error IQ message (%s)", bjid);
    display_server_error(lm_message_node_get_child(m->node, "error"), NULL);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  // Check message contents
  ansqry = lm_message_node_get_child(m->node, "query");
  if (!ansqry) {
    scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:version result from <%s>!", bjid);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  buf = g_strdup_printf("Received IQ:last result from <%s>", bjid);
  scr_LogPrint(LPRINT_LOGNORM, "%s", buf);

  // bjid should now really be the "bare JID", let's strip the resource
  tmp = strchr(bjid, JID_RESOURCE_SEPARATOR);
  if (tmp) *tmp = '\0';

  scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
  g_free(buf);

  // Get result data...
  p = lm_message_node_get_attribute(ansqry, "seconds");
  if (p) {
    long int s;
    GString *sbuf;
    sbuf = g_string_new("Idle time: ");
    s = atol(p);
    // Days
    if (s > 86400L) {
      g_string_append_printf(sbuf, "%ldd ", s/86400L);
      s %= 86400L;
    }
    // hh:mm:ss
    g_string_append_printf(sbuf, "%02ld:", s/3600L);
    s %= 3600L;
    g_string_append_printf(sbuf, "%02ld:%02ld", s/60L, s%60L);
    scr_WriteIncomingMessage(bjid, sbuf->str,
                             0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
    g_string_free(sbuf, TRUE);
  } else {
    scr_WriteIncomingMessage(bjid, "No idle time reported.",
                             0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
  }
  p = lm_message_node_get_value(ansqry);
  if (p) {
    buf = g_strdup_printf("Status message: %s", p);
    scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
    g_free(buf);
  }
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
コード例 #30
0
ファイル: xmpp_iqrequest.c プロジェクト: capterin/mcabber
static LmHandlerResult cb_time(LmMessageHandler *h, LmConnection *c,
                               LmMessage *m, gpointer user_data)
{
  LmMessageNode *ansqry;
  const char *p, *bjid;
  char *buf, *tmp;

  // Check IQ result sender
  bjid = lm_message_get_from(m);
  if (!bjid)
    bjid = lm_connection_get_jid(lconnection); // No from means our JID...
  if (!bjid) {
    scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result (no sender name).");
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  // Check for error message
  if (lm_message_get_sub_type(m) == LM_MESSAGE_SUB_TYPE_ERROR) {
    scr_LogPrint(LPRINT_LOGNORM, "Received error IQ message (%s)", bjid);
    display_server_error(lm_message_node_get_child(m->node, "error"), NULL);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  // Check message contents
  ansqry = lm_message_node_get_child(m->node, "query");
  if (!ansqry) {
    scr_LogPrint(LPRINT_LOGNORM, "Invalid IQ:time result from <%s>!", bjid);
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }

  buf = g_strdup_printf("Received IQ:time result from <%s>", bjid);
  scr_LogPrint(LPRINT_LOGNORM, "%s", buf);

  // bjid should now really be the "bare JID", let's strip the resource
  tmp = strchr(bjid, JID_RESOURCE_SEPARATOR);
  if (tmp) *tmp = '\0';

  scr_WriteIncomingMessage(bjid, buf, 0, HBB_PREFIX_INFO, 0);
  g_free(buf);

  // Get result data...
  p = lm_message_node_get_child_value(ansqry, "utc");
  if (p && *p) {
    buf = g_strdup_printf("UTC:  %s", p);
    scr_WriteIncomingMessage(bjid, buf,
                             0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
    g_free(buf);
  }
  p = lm_message_node_get_child_value(ansqry, "tz");
  if (p && *p) {
    buf = g_strdup_printf("TZ:   %s", p);
    scr_WriteIncomingMessage(bjid, buf,
                             0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
    g_free(buf);
  }
  p = lm_message_node_get_child_value(ansqry, "display");
  if (p && *p) {
    buf = g_strdup_printf("Time: %s", p);
    scr_WriteIncomingMessage(bjid, buf,
                             0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
    g_free(buf);
  }
  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}