static int _zkmuc_source_query(xmpp_ua_t *ua, xmpp_stanza_t *stanza, void *userdata) { zkmuc_ctx_t *ctx = (zkmuc_ctx_t *)userdata; char *from = xmpp_stanza_get_attribute(stanza, "from"); char *id = xmpp_stanza_get_id(stanza); if (id == NULL) { return 0; } xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, "x"); if(x && xmpp_stanza_get_ns(x) && !strcmp(XMPP_NS_SOURCE, xmpp_stanza_get_ns(x))) { char *action = xmpp_stanza_get_attribute(x, "action"); if (!strcmp("query", action)) { xmpp_stanza_t *message = xmpp_stanza_new(_xmpp_ctx); xmpp_stanza_set_name(message, "message"); xmpp_stanza_set_attribute(message, "to", from); xmpp_stanza_set_id(message, id); xmpp_stanza_t *result_x = xmpp_stanza_new(_xmpp_ctx); xmpp_stanza_set_name(result_x, "x"); xmpp_stanza_set_ns(result_x, XMPP_NS_SOURCE); xmpp_stanza_set_attribute(result_x, "action", "result"); WaitForSingleObject(ctx->_mutex_4_source, INFINITE); zkmuc_source_t *item = ctx->head; while (item) { xmpp_stanza_t *stanza_item = xmpp_stanza_new(_xmpp_ctx); xmpp_stanza_set_name(stanza_item, "item"); char buf[32]; xmpp_stanza_set_attribute(stanza_item, "cid", itoa(item->cid, buf, 10)); xmpp_stanza_set_attribute(stanza_item, "sid", itoa(item->sid, buf, 10)); xmpp_stanza_set_attribute(stanza_item, "desc", item->description); xmpp_stanza_set_attribute(stanza_item, "mcu", item->mcu); xmpp_stanza_add_child(result_x, stanza_item); xmpp_stanza_release(stanza_item); item = item->next; } ReleaseMutex(ctx->_mutex_4_source); xmpp_stanza_add_child(message, result_x); xmpp_stanza_release(result_x); xmpp_ua_send(ctx->ua, message); xmpp_stanza_release(message); return 1; } } return 0; }
/** Get the first child of a stanza with a given namespace. * This function searches all the immediate children of a stanza for a child * stanza that matches the namespace provided. The first matching child * is returned. * * @param stanza a Strophe stanza object * @param ns a string with the namespace to match * * @return the matching child stanza object or NULL if no match was found * * @ingroup Stanza */ xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t * const stanza, const char * const ns) { xmpp_stanza_t *child; for (child = stanza->children; child; child = child->next) { if (xmpp_stanza_get_ns(child) && strcmp(ns, xmpp_stanza_get_ns(child)) == 0) break; } return child; }
static gboolean _is_valid_form_element(xmpp_stanza_t *stanza) { const char *name = xmpp_stanza_get_name(stanza); if (g_strcmp0(name, STANZA_NAME_X) != 0) { log_error("Error parsing form, root element not <x/>."); return FALSE; } const char *ns = xmpp_stanza_get_ns(stanza); if (g_strcmp0(ns, STANZA_NS_DATA) != 0) { log_error("Error parsing form, namespace not %s.", STANZA_NS_DATA); return FALSE; } const char *type = xmpp_stanza_get_type(stanza); if ((g_strcmp0(type, "form") != 0) && (g_strcmp0(type, "submit") != 0) && (g_strcmp0(type, "cancel") != 0) && (g_strcmp0(type, "result") != 0)) { log_error("Error parsing form, unknown type."); return FALSE; } return TRUE; }
int stanza_get_idle_time(xmpp_stanza_t * const stanza) { xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); if (query == NULL) { return 0; } char *ns = xmpp_stanza_get_ns(query); if (ns == NULL) { return 0; } if (strcmp(ns, STANZA_NS_LASTACTIVITY) != 0) { return 0; } char *seconds_str = xmpp_stanza_get_attribute(query, STANZA_ATTR_SECONDS); if (seconds_str == NULL) { return 0; } int result = atoi(seconds_str); if (result < 1) { return 0; } else { return result; } }
static int _handle_features(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { xmpp_stanza_t *child, *mech; char *text; /* remove the handler that detects missing stream:features */ xmpp_timed_handler_delete(conn, _handle_missing_features); /* check for TLS */ if (!conn->secured) { if (!conn->tls_disabled) { child = xmpp_stanza_get_child_by_name(stanza, "starttls"); if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_TLS) == 0)) conn->tls_support = 1; } else { conn->tls_support = 0; } } /* check for SASL */ child = xmpp_stanza_get_child_by_name(stanza, "mechanisms"); if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) { for (mech = xmpp_stanza_get_children(child); mech; mech = xmpp_stanza_get_next(mech)) { if (xmpp_stanza_get_name(mech) && strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) { text = xmpp_stanza_get_text(mech); if (strcasecmp(text, "PLAIN") == 0) conn->sasl_support |= SASL_MASK_PLAIN; else if (strcasecmp(text, "DIGEST-MD5") == 0) conn->sasl_support |= SASL_MASK_DIGESTMD5; else if (strcasecmp(text, "SCRAM-SHA-1") == 0) conn->sasl_support |= SASL_MASK_SCRAMSHA1; else if (strcasecmp(text, "ANONYMOUS") == 0) conn->sasl_support |= SASL_MASK_ANONYMOUS; xmpp_free(conn->ctx, text); } } } _auth(conn); return 0; }
static int _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { char *id = xmpp_stanza_get_id(stanza); if (id != NULL) { log_debug("IQ version result handler fired, id: %s.", id); } else { log_debug("IQ version result handler fired."); } const char *jid = xmpp_stanza_get_attribute(stanza, "from"); xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); if (query == NULL) { return 1; } char *ns = xmpp_stanza_get_ns(query); if (g_strcmp0(ns, STANZA_NS_VERSION) != 0) { return 1; } char *name_str = NULL; char *version_str = NULL; char *os_str = NULL; xmpp_stanza_t *name = xmpp_stanza_get_child_by_name(query, "name"); xmpp_stanza_t *version = xmpp_stanza_get_child_by_name(query, "version"); xmpp_stanza_t *os = xmpp_stanza_get_child_by_name(query, "os"); if (name != NULL) { name_str = xmpp_stanza_get_text(name); } if (version != NULL) { version_str = xmpp_stanza_get_text(version); } if (os != NULL) { os_str = xmpp_stanza_get_text(os); } PContact contact; Jid *jidp = jid_create(jid); if (muc_room_is_active(jidp->barejid)) { contact = muc_get_participant(jidp->barejid, jidp->resourcepart); } else { contact = roster_get_contact(jidp->barejid); } Resource *resource = p_contact_get_resource(contact, jidp->resourcepart); const char *presence = string_from_resource_presence(resource->presence); handle_software_version_result(jid, presence, name_str, version_str, os_str); jid_destroy(jidp); return 1; }
gboolean stanza_is_muc_self_presence(xmpp_stanza_t * const stanza, const char * const self_jid) { if (stanza == NULL) { return FALSE; } if (strcmp(xmpp_stanza_get_name(stanza), STANZA_NAME_PRESENCE) != 0) { return FALSE; } xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X); if (x == NULL) { return FALSE; } char *ns = xmpp_stanza_get_ns(x); if (ns == NULL) { return FALSE; } if (strcmp(ns, STANZA_NS_MUC_USER) != 0) { return FALSE; } xmpp_stanza_t *x_children = xmpp_stanza_get_children(x); if (x_children == NULL) { return FALSE; } while (x_children != NULL) { if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) { char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE); if (strcmp(code, "110") == 0) { return TRUE; } } x_children = xmpp_stanza_get_next(x_children); } // for older server that don't send status 110 x_children = xmpp_stanza_get_children(x); while (x_children != NULL) { if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_ITEM) == 0) { char *jid = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_JID); if (jid != NULL) { if (g_str_has_prefix(jid, self_jid)) { return TRUE; } } } x_children = xmpp_stanza_get_next(x_children); } return FALSE; }
static int _zkmuc_on_rcv_invite(xmpp_ua_t *ua, xmpp_stanza_t *stanza, void *userdata) { char *ns = xmpp_stanza_get_ns(stanza); if (ns != NULL && !strcmp(ns, XMPP_NS_CONFERECE)) { zkmuc_ctx_t *ctx = (zkmuc_ctx_t *)userdata; char *from = xmpp_stanza_get_attribute(stanza, "from"); xmpp_stanza_t *stanza_body = xmpp_stanza_get_child_by_name(stanza, "body"); if (stanza_body) { char *room_id = xmpp_stanza_get_text(stanza_body); ctx->invite_cb(ctx, from, room_id, ctx->invite_data); } return 1; } return 0; }
int version_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { xmpp_stanza_t *reply, *query, *name, *version, *text; const char *ns; xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata; printf("Received version request from %s\n", xmpp_stanza_get_from(stanza)); reply = xmpp_stanza_reply(stanza); xmpp_stanza_set_type(reply, "result"); query = xmpp_stanza_new(ctx); xmpp_stanza_set_name(query, "query"); ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)); if (ns) { xmpp_stanza_set_ns(query, ns); } name = xmpp_stanza_new(ctx); xmpp_stanza_set_name(name, "name"); xmpp_stanza_add_child(query, name); xmpp_stanza_release(name); text = xmpp_stanza_new(ctx); xmpp_stanza_set_text(text, "libstrophe example bot"); xmpp_stanza_add_child(name, text); xmpp_stanza_release(text); version = xmpp_stanza_new(ctx); xmpp_stanza_set_name(version, "version"); xmpp_stanza_add_child(query, version); xmpp_stanza_release(version); text = xmpp_stanza_new(ctx); xmpp_stanza_set_text(text, "1.0"); xmpp_stanza_add_child(version, text); xmpp_stanza_release(text); xmpp_stanza_add_child(reply, query); xmpp_stanza_release(query); xmpp_send(conn, reply); xmpp_stanza_release(reply); return 1; }
gboolean stanza_is_room_nick_change(xmpp_stanza_t * const stanza) { if (stanza == NULL) { return FALSE; } if (strcmp(xmpp_stanza_get_name(stanza), STANZA_NAME_PRESENCE) != 0) { return FALSE; } xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X); if (x == NULL) { return FALSE; } char *ns = xmpp_stanza_get_ns(x); if (ns == NULL) { return FALSE; } if (strcmp(ns, STANZA_NS_MUC_USER) != 0) { return FALSE; } xmpp_stanza_t *x_children = xmpp_stanza_get_children(x); if (x_children == NULL) { return FALSE; } while (x_children != NULL) { if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) { char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE); if (strcmp(code, "303") == 0) { return TRUE; } } x_children = xmpp_stanza_get_next(x_children); } return FALSE; }
/* stream:error handler */ static int _handle_error(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { xmpp_stanza_t *child; char *name; /* free old stream error if it's still there */ if (conn->stream_error) { xmpp_stanza_release(conn->stream_error->stanza); if (conn->stream_error->text) xmpp_free(conn->ctx, conn->stream_error->text); xmpp_free(conn->ctx, conn->stream_error); } /* create stream error structure */ conn->stream_error = (xmpp_stream_error_t *)xmpp_alloc(conn->ctx, sizeof(xmpp_stream_error_t)); conn->stream_error->text = NULL; conn->stream_error->type = XMPP_SE_UNDEFINED_CONDITION; if (conn->stream_error) { child = xmpp_stanza_get_children(stanza); do { char *ns = NULL; if (child) { ns = xmpp_stanza_get_ns(child); } if (ns && strcmp(ns, XMPP_NS_STREAMS_IETF) == 0) { name = xmpp_stanza_get_name(child); if (strcmp(name, "text") == 0) { if (conn->stream_error->text) xmpp_free(conn->ctx, conn->stream_error->text); conn->stream_error->text = xmpp_stanza_get_text(child); } else if (strcmp(name, "bad-format") == 0) conn->stream_error->type = XMPP_SE_BAD_FORMAT; else if (strcmp(name, "bad-namespace-prefix") == 0) conn->stream_error->type = XMPP_SE_BAD_NS_PREFIX; else if (strcmp(name, "conflict") == 0) conn->stream_error->type = XMPP_SE_CONFLICT; else if (strcmp(name, "connection-timeout") == 0) conn->stream_error->type = XMPP_SE_CONN_TIMEOUT; else if (strcmp(name, "host-gone") == 0) conn->stream_error->type = XMPP_SE_HOST_GONE; else if (strcmp(name, "host-unknown") == 0) conn->stream_error->type = XMPP_SE_HOST_UNKNOWN; else if (strcmp(name, "improper-addressing") == 0) conn->stream_error->type = XMPP_SE_IMPROPER_ADDR; else if (strcmp(name, "internal-server-error") == 0) conn->stream_error->type = XMPP_SE_INTERNAL_SERVER_ERROR; else if (strcmp(name, "invalid-from") == 0) conn->stream_error->type = XMPP_SE_INVALID_FROM; else if (strcmp(name, "invalid-id") == 0) conn->stream_error->type = XMPP_SE_INVALID_ID; else if (strcmp(name, "invalid-namespace") == 0) conn->stream_error->type = XMPP_SE_INVALID_NS; else if (strcmp(name, "invalid-xml") == 0) conn->stream_error->type = XMPP_SE_INVALID_XML; else if (strcmp(name, "not-authorized") == 0) conn->stream_error->type = XMPP_SE_NOT_AUTHORIZED; else if (strcmp(name, "policy-violation") == 0) conn->stream_error->type = XMPP_SE_POLICY_VIOLATION; else if (strcmp(name, "remote-connection-failed") == 0) conn->stream_error->type = XMPP_SE_REMOTE_CONN_FAILED; else if (strcmp(name, "resource-constraint") == 0) conn->stream_error->type = XMPP_SE_RESOURCE_CONSTRAINT; else if (strcmp(name, "restricted-xml") == 0) conn->stream_error->type = XMPP_SE_RESTRICTED_XML; else if (strcmp(name, "see-other-host") == 0) conn->stream_error->type = XMPP_SE_SEE_OTHER_HOST; else if (strcmp(name, "system-shutdown") == 0) conn->stream_error->type = XMPP_SE_SYSTEM_SHUTDOWN; else if (strcmp(name, "undefined-condition") == 0) conn->stream_error->type = XMPP_SE_UNDEFINED_CONDITION; else if (strcmp(name, "unsupported-encoding") == 0) conn->stream_error->type = XMPP_SE_UNSUPPORTED_ENCODING; else if (strcmp(name, "unsupported-stanza-type") == 0) conn->stream_error->type = XMPP_SE_UNSUPPORTED_STANZA_TYPE; else if (strcmp(name, "unsupported-version") == 0) conn->stream_error->type = XMPP_SE_UNSUPPORTED_VERSION; else if (strcmp(name, "xml-not-well-formed") == 0) conn->stream_error->type = XMPP_SE_XML_NOT_WELL_FORMED; } } while ((child = xmpp_stanza_get_next(child))); conn->stream_error->stanza = xmpp_stanza_clone(stanza); } return 1; }
char * caps_create_sha1_str(xmpp_stanza_t * const query) { char *category = NULL; char *type = NULL; char *lang = NULL; char *name = NULL; char *feature_str = NULL; GSList *identities = NULL; GSList *features = NULL; GSList *form_names = NULL; DataForm *form = NULL; FormField *field = NULL; GHashTable *forms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)form_destroy); xmpp_stanza_t *child = xmpp_stanza_get_children(query); while (child) { if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_IDENTITY) == 0) { category = xmpp_stanza_get_attribute(child, "category"); type = xmpp_stanza_get_attribute(child, "type"); lang = xmpp_stanza_get_attribute(child, "xml:lang"); name = xmpp_stanza_get_attribute(child, "name"); GString *identity_str = g_string_new(category); g_string_append(identity_str, "/"); if (type) { g_string_append(identity_str, type); } g_string_append(identity_str, "/"); if (lang) { g_string_append(identity_str, lang); } g_string_append(identity_str, "/"); if (name) { g_string_append(identity_str, name); } g_string_append(identity_str, "<"); identities = g_slist_insert_sorted(identities, g_strdup(identity_str->str), (GCompareFunc)strcmp); g_string_free(identity_str, TRUE); } else if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_FEATURE) == 0) { feature_str = xmpp_stanza_get_attribute(child, "var"); features = g_slist_insert_sorted(features, g_strdup(feature_str), (GCompareFunc)strcmp); } else if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_X) == 0) { if (g_strcmp0(xmpp_stanza_get_ns(child), STANZA_NS_DATA) == 0) { form = form_create(child); char *form_type = form_get_form_type_field(form); form_names = g_slist_insert_sorted(form_names, g_strdup(form_type), (GCompareFunc)strcmp); g_hash_table_insert(forms, g_strdup(form_type), form); } } child = xmpp_stanza_get_next(child); } GString *s = g_string_new(""); GSList *curr = identities; while (curr) { g_string_append(s, curr->data); curr = g_slist_next(curr); } curr = features; while (curr) { g_string_append(s, curr->data); g_string_append(s, "<"); curr = g_slist_next(curr); } curr = form_names; while (curr) { form = g_hash_table_lookup(forms, curr->data); char *form_type = form_get_form_type_field(form); g_string_append(s, form_type); g_string_append(s, "<"); GSList *sorted_fields = form_get_non_form_type_fields_sorted(form); GSList *curr_field = sorted_fields; while (curr_field) { field = curr_field->data; g_string_append(s, field->var); g_string_append(s, "<"); GSList *sorted_values = form_get_field_values_sorted(field); GSList *curr_value = sorted_values; while (curr_value) { g_string_append(s, curr_value->data); g_string_append(s, "<"); curr_value = g_slist_next(curr_value); } g_slist_free(sorted_values); curr_field = g_slist_next(curr_field); } g_slist_free(sorted_fields); curr = g_slist_next(curr); } char *result = p_sha1_hash(s->str); g_string_free(s, TRUE); g_slist_free_full(identities, g_free); g_slist_free_full(features, g_free); g_slist_free_full(form_names, g_free); g_hash_table_destroy(forms); return result; }
static int _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { char *id = xmpp_stanza_get_id(stanza); char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR); xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X); char *xmlns = NULL; if (x != NULL) { xmlns = xmpp_stanza_get_ns(x); } char *type = NULL; if (error_stanza != NULL) { type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE); } // handle MUC join errors if (g_strcmp0(xmlns, STANZA_NS_MUC) == 0) { Jid *fulljid = jid_create(from); char *error_cond = NULL; xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS); if (reason_st != NULL) { error_cond = xmpp_stanza_get_name(reason_st); } if (error_cond == NULL) { error_cond = "unknown"; } log_info("Error joining room: %s, reason: %s", fulljid->barejid, error_cond); handle_room_join_error(fulljid->barejid, error_cond); return 1; } // stanza_get_error never returns NULL char *err_msg = stanza_get_error_message(stanza); GString *log_msg = g_string_new("presence stanza error received"); if (id != NULL) { g_string_append(log_msg, " id="); g_string_append(log_msg, id); } if (from != NULL) { g_string_append(log_msg, " from="); g_string_append(log_msg, from); } if (type != NULL) { g_string_append(log_msg, " type="); g_string_append(log_msg, type); } g_string_append(log_msg, " error="); g_string_append(log_msg, err_msg); log_info(log_msg->str); g_string_free(log_msg, TRUE); handle_presence_error(from, type, err_msg); free(err_msg); return 1; }
static int version_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { xmpp_stanza_t *reply, *query, *name, *version, *text; conflate_handle_t *handle = (conflate_handle_t*) userdata; xmpp_ctx_t *ctx = handle->ctx; char *ns; struct utsname un = {}; printf("Received version request from %s\n", xmpp_stanza_get_attribute(stanza, "from")); reply = xmpp_stanza_new(ctx); assert(reply); xmpp_stanza_set_name(reply, "iq"); xmpp_stanza_set_type(reply, "result"); xmpp_stanza_set_id(reply, xmpp_stanza_get_id(stanza)); xmpp_stanza_set_attribute(reply, "to", xmpp_stanza_get_attribute(stanza, "from")); query = xmpp_stanza_new(ctx); assert(query); xmpp_stanza_set_name(query, "query"); ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)); if (ns) { xmpp_stanza_set_ns(query, ns); } name = xmpp_stanza_new(ctx); assert(name); xmpp_stanza_set_name(name, "name"); add_and_release(query, name); text = xmpp_stanza_new(ctx); assert(text); xmpp_stanza_set_text(text, handle->conf->software); add_and_release(name, text); version = xmpp_stanza_new(ctx); assert(version); xmpp_stanza_set_name(version, "version"); add_and_release(query, version); text = xmpp_stanza_new(ctx); assert(text); xmpp_stanza_set_text(text, handle->conf->version); add_and_release(version, text); if (uname(&un) == 0) { char os_buf[128]; snprintf(os_buf, sizeof(os_buf), "%s/%s/%s", un.machine, un.sysname, un.release); xmpp_stanza_t *os = xmpp_stanza_new(ctx); assert(os); xmpp_stanza_set_name(os, "os"); add_and_release(query, os); text = xmpp_stanza_new(ctx); assert(text); xmpp_stanza_set_text(text, os_buf); add_and_release(os, text); } add_and_release(reply, query); xmpp_send(conn, reply); xmpp_stanza_release(reply); return 1; }
char * caps_create_sha1_str(xmpp_stanza_t * const query) { char *category = NULL; char *type = NULL; char *lang = NULL; char *name = NULL; char *feature_str = NULL; GSList *identities = NULL; GSList *features = NULL; GSList *form_names = NULL; DataForm *form = NULL; FormField *field = NULL; GHashTable *forms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)stanza_destroy_form); GString *s = g_string_new(""); xmpp_stanza_t *child = xmpp_stanza_get_children(query); while (child != NULL) { if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_IDENTITY) == 0) { category = xmpp_stanza_get_attribute(child, "category"); type = xmpp_stanza_get_attribute(child, "type"); lang = xmpp_stanza_get_attribute(child, "xml:lang"); name = xmpp_stanza_get_attribute(child, "name"); GString *identity_str = g_string_new(category); g_string_append(identity_str, "/"); if (type != NULL) { g_string_append(identity_str, type); } g_string_append(identity_str, "/"); if (lang != NULL) { g_string_append(identity_str, lang); } g_string_append(identity_str, "/"); if (name != NULL) { g_string_append(identity_str, name); } g_string_append(identity_str, "<"); identities = g_slist_insert_sorted(identities, g_strdup(identity_str->str), (GCompareFunc)strcmp); g_string_free(identity_str, TRUE); } else if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_FEATURE) == 0) { feature_str = xmpp_stanza_get_attribute(child, "var"); features = g_slist_insert_sorted(features, g_strdup(feature_str), (GCompareFunc)strcmp); } else if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_X) == 0) { if (strcmp(xmpp_stanza_get_ns(child), STANZA_NS_DATA) == 0) { form = stanza_create_form(child); form_names = g_slist_insert_sorted(form_names, g_strdup(form->form_type), (GCompareFunc)strcmp); g_hash_table_insert(forms, g_strdup(form->form_type), form); } } child = xmpp_stanza_get_next(child); } GSList *curr = identities; while (curr != NULL) { g_string_append(s, curr->data); curr = g_slist_next(curr); } curr = features; while (curr != NULL) { g_string_append(s, curr->data); g_string_append(s, "<"); curr = g_slist_next(curr); } curr = form_names; while (curr != NULL) { form = g_hash_table_lookup(forms, curr->data); g_string_append(s, form->form_type); g_string_append(s, "<"); GSList *curr_field = form->fields; while (curr_field != NULL) { field = curr_field->data; g_string_append(s, field->var); g_string_append(s, "<"); GSList *curr_value = field->values; while (curr_value != NULL) { g_string_append(s, curr_value->data); g_string_append(s, "<"); curr_value = g_slist_next(curr_value); } curr_field = g_slist_next(curr_field); } curr = g_slist_next(curr); } EVP_MD_CTX mdctx; const EVP_MD *md; unsigned char md_value[EVP_MAX_MD_SIZE]; unsigned int md_len; OpenSSL_add_all_digests(); md = EVP_get_digestbyname("SHA1"); EVP_MD_CTX_init(&mdctx); EVP_DigestInit_ex(&mdctx, md, NULL); EVP_DigestUpdate(&mdctx, s->str, strlen(s->str)); EVP_DigestFinal_ex(&mdctx, md_value, &md_len); EVP_MD_CTX_cleanup(&mdctx); char *result = g_base64_encode(md_value, md_len); g_string_free(s, TRUE); g_slist_free_full(identities, g_free); g_slist_free_full(features, g_free); g_slist_free_full(form_names, g_free); g_hash_table_destroy(forms); return result; }
static int _handle_features_sasl(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { xmpp_stanza_t *bind, *session, *iq, *res, *text; char *resource; /* remove missing features handler */ xmpp_timed_handler_delete(conn, _handle_missing_features_sasl); /* we are expecting <bind/> and <session/> since this is a XMPP style connection */ bind = xmpp_stanza_get_child_by_name(stanza, "bind"); if (bind && strcmp(xmpp_stanza_get_ns(bind), XMPP_NS_BIND) == 0) { /* resource binding is required */ conn->bind_required = 1; } session = xmpp_stanza_get_child_by_name(stanza, "session"); if (session && strcmp(xmpp_stanza_get_ns(session), XMPP_NS_SESSION) == 0) { /* session establishment required */ conn->session_required = 1; } /* if bind is required, go ahead and start it */ if (conn->bind_required) { /* bind resource */ /* setup response handlers */ handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL); handler_add_timed(conn, _handle_missing_bind, BIND_TIMEOUT, NULL); /* send bind request */ iq = xmpp_stanza_new(conn->ctx); if (!iq) { disconnect_mem_error(conn); return 0; } xmpp_stanza_set_name(iq, "iq"); xmpp_stanza_set_type(iq, "set"); xmpp_stanza_set_id(iq, "_xmpp_bind1"); bind = xmpp_stanza_copy(bind); if (!bind) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return 0; } /* request a specific resource if we have one */ resource = xmpp_jid_resource(conn->ctx, conn->jid); if ((resource != NULL) && (strlen(resource) == 0)) { /* jabberd2 doesn't handle an empty resource */ xmpp_free(conn->ctx, resource); resource = NULL; } /* if we have a resource to request, do it. otherwise the server will assign us one */ if (resource) { res = xmpp_stanza_new(conn->ctx); if (!res) { xmpp_stanza_release(bind); xmpp_stanza_release(iq); disconnect_mem_error(conn); return 0; } xmpp_stanza_set_name(res, "resource"); text = xmpp_stanza_new(conn->ctx); if (!text) { xmpp_stanza_release(res); xmpp_stanza_release(bind); xmpp_stanza_release(iq); disconnect_mem_error(conn); return 0; } xmpp_stanza_set_text(text, resource); xmpp_stanza_add_child(res, text); xmpp_stanza_release(text); xmpp_stanza_add_child(bind, res); xmpp_stanza_release(res); xmpp_free(conn->ctx, resource); } xmpp_stanza_add_child(iq, bind); xmpp_stanza_release(bind); /* send bind request */ xmpp_send(conn, iq); xmpp_stanza_release(iq); } else { /* can't bind, disconnect */ xmpp_error(conn->ctx, "xmpp", "Stream features does not allow "\ "resource bind."); xmpp_disconnect(conn); } return 0; }
int handle_message(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { xmpp_stanza_t *child = NULL; xmppipe_state_t *state = userdata; char *message = NULL; const char *type = NULL; const char *from = NULL; const char *to = NULL; const char *ns; char *etype = NULL; char *efrom = NULL; char *eto = NULL; char *emessage = NULL; char *symbol = "m"; if (xmpp_stanza_get_child_by_name(stanza, "delay")) return 1; from = xmpp_stanza_get_attribute(stanza, "from"); if (from == NULL) return 1; to = xmpp_stanza_get_attribute(stanza, "to"); if (to == NULL) return 1; type = xmpp_stanza_get_type(stanza); if (type == NULL) return 1; /* Check if the message is from us */ if (XMPPIPE_STREQ(type, "groupchat") && XMPPIPE_STREQ(from, state->mucjid)) return 1; child = xmpp_stanza_get_child_by_name(stanza, "displayed"); if (child != NULL) { ns = xmpp_stanza_get_ns(child); if (XMPPIPE_STREQ(ns, "urn:xmpp:chat-markers:0")) { if (!(state->opt & XMPPIPE_OPT_CHAT_MARKER)) return 1; symbol = "M"; } } child = xmpp_stanza_get_child_by_name(stanza, "body"); if (child != NULL) { message = xmpp_stanza_get_text(child); if (message != NULL) { if (state->encode) { size_t len = strlen(message); unsigned char *buf = NULL; size_t n = 0; xmpp_base64_decode_bin(state->ctx, message, len, &buf, &n); if (buf == NULL) { /* Not a base64 message */ return 1; } emessage = xmppipe_nfmt_encode((char *)buf, n); xmpp_free(state->ctx, buf); } else { emessage = xmppipe_fmt_encode(message); } xmpp_free(state->ctx, message); } goto XMPPIPE_STDOUT; } child = xmpp_stanza_get_child_by_name(stanza, "subject"); if (child != NULL) { message = xmpp_stanza_get_text(child); if (message != NULL) emessage = xmppipe_fmt_encode(message); symbol = "S"; xmpp_free(state->ctx, message); } XMPPIPE_STDOUT: etype = xmppipe_fmt_encode(type); efrom = xmppipe_fmt_encode(from); eto = xmppipe_fmt_encode(to); (void)printf("%s:%s:%s:%s:%s\n", symbol, etype, efrom, eto, emessage == NULL ? "" : emessage); state->interval = 0; free(etype); free(efrom); free(eto); free(emessage); return 1; }
/** Fire off all stanza handlers that match. * This function is called internally by the event loop whenever stanzas * are received from the XMPP server. * * @param conn a Strophe connection object * @param stanza a Strophe stanza object */ void handler_fire_stanza(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza) { xmpp_handlist_t *item, *prev; char *id, *ns, *name, *type; /* call id handlers */ id = xmpp_stanza_get_id(stanza); if (id) { prev = NULL; item = (xmpp_handlist_t *)hash_get(conn->id_handlers, id); while (item) { xmpp_handlist_t *next = item->next; if (item->user_handler && !conn->authenticated) { item = next; continue; } if (!((xmpp_handler)(item->handler))(conn, stanza, item->userdata)) { /* handler is one-shot, so delete it */ if (prev) prev->next = next; else { hash_drop(conn->id_handlers, id); hash_add(conn->id_handlers, id, next); } xmpp_free(conn->ctx, item->id); xmpp_free(conn->ctx, item); item = NULL; } if (item) prev = item; item = next; } } /* call handlers */ ns = xmpp_stanza_get_ns(stanza); name = xmpp_stanza_get_name(stanza); type = xmpp_stanza_get_type(stanza); /* enable all added handlers */ for (item = conn->handlers; item; item = item->next) item->enabled = 1; prev = NULL; item = conn->handlers; while (item) { /* skip newly added handlers */ if (!item->enabled) { prev = item; item = item->next; continue; } /* don't call user handlers until authentication succeeds */ if (item->user_handler && !conn->authenticated) { prev = item; item = item->next; continue; } if ((!item->ns || (ns && strcmp(ns, item->ns) == 0) || xmpp_stanza_get_child_by_ns(stanza, item->ns)) && (!item->name || (name && strcmp(name, item->name) == 0)) && (!item->type || (type && strcmp(type, item->type) == 0))) if (!((xmpp_handler)(item->handler))(conn, stanza, item->userdata)) { /* handler is one-shot, so delete it */ if (prev) prev->next = item->next; else conn->handlers = item->next; if (item->ns) xmpp_free(conn->ctx, item->ns); if (item->name) xmpp_free(conn->ctx, item->name); if (item->type) xmpp_free(conn->ctx, item->type); xmpp_free(conn->ctx, item); item = NULL; } if (item) { prev = item; item = item->next; } else if (prev) item = prev->next; else item = conn->handlers; } }
static void _presence_error_handler(xmpp_stanza_t *const stanza) { const char *xmlns = NULL; xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X); if (x) { xmlns = xmpp_stanza_get_ns(x); } const char *from = xmpp_stanza_get_from(stanza); xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR); // handle MUC join errors if (g_strcmp0(xmlns, STANZA_NS_MUC) == 0) { const char *error_cond = NULL; xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS); if (reason_st) { error_cond = xmpp_stanza_get_name(reason_st); } if (error_cond == NULL) { error_cond = "unknown"; } Jid *fulljid = jid_create(from); log_info("Error joining room: %s, reason: %s", fulljid->barejid, error_cond); if (muc_active(fulljid->barejid)) { muc_leave(fulljid->barejid); } cons_show_error("Error joining room %s, reason: %s", fulljid->barejid, error_cond); jid_destroy(fulljid); return; } GString *log_msg = g_string_new("presence stanza error received"); const char *id = xmpp_stanza_get_id(stanza); if (id) { g_string_append(log_msg, " id="); g_string_append(log_msg, id); } if (from) { g_string_append(log_msg, " from="); g_string_append(log_msg, from); } const char *type = NULL; if (error_stanza) { type = xmpp_stanza_get_type(error_stanza); } if (type) { g_string_append(log_msg, " type="); g_string_append(log_msg, type); } // stanza_get_error never returns NULL char *err_msg = stanza_get_error_message(stanza); g_string_append(log_msg, " error="); g_string_append(log_msg, err_msg); log_info(log_msg->str); g_string_free(log_msg, TRUE); if (from) { ui_handle_recipient_error(from, err_msg); } else { ui_handle_error(err_msg); } free(err_msg); }