示例#1
0
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;
}
示例#2
0
文件: stanza.c 项目: alk/libstrophe
/** 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;
}
示例#3
0
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;
}
示例#4
0
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;
    }
}
示例#5
0
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;
}
示例#6
0
文件: iq.c 项目: dotoole/profanity
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;
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
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;
}
示例#10
0
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;

}
示例#11
0
/* 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;
}
示例#12
0
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;
}
示例#13
0
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;
}
示例#14
0
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;
}
示例#15
0
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;
}
示例#16
0
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;
}
示例#17
0
文件: message.c 项目: msantos/xmppipe
    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;
}
示例#18
0
/** 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;
    }
}
示例#19
0
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);
}