// 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); }
// 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; }
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); } }
// 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; }
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; }
// 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; }
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; }
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; }
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; }
// 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; }
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; }
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; }
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; }
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; }
// 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; }
// 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); } }
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; }
// 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; }
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});
// 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); }
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; }
// 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); } }
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" : ""); }
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(); }
// 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); } } } } }
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; }
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; }
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; }
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; }
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; }