Example #1
0
/** Count the attributes in a stanza object.
 *
 *  @param stanza a Strophe stanza object
 *
 *  @return the number of attributes for the stanza object
 *
 *  @ingroup Stanza
 */
int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza)
{
    if (stanza->attributes == NULL) {
        return 0;
    }

    return hash_num_keys(stanza->attributes);
}
Example #2
0
/* always returns number of bytes written or that would have been
 * written if the buffer was large enough
 * return values < 0 indicate some error occured,
 * and return values > buflen indicate buffer was not large enough
 */
static int _render_stanza_recursive(xmpp_stanza_t *stanza,
			     char * const buf, size_t const buflen)
{
    char *ptr = buf;
    size_t left = buflen;
    int ret, written;
    xmpp_stanza_t *child;
    hash_iterator_t *iter;
    const char *key;

    assert(stanza);

    written = 0;

    if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP;

    if (stanza->type == XMPP_STANZA_TEXT) {
	if (!stanza->data) return XMPP_EINVOP;

        assert(stanza->data);
	ret = xmpp_snprintf(ptr, left, "%s", stanza->data);
	if (ret < 0) return XMPP_EMEM;
	_render_update(&written, buflen, ret, &left, &ptr);
    } else { /* stanza->type == XMPP_STANZA_TAG */
	if (!stanza->data) return XMPP_EINVOP;

	/* write begining of tag and attributes */
        assert(stanza->data);
	ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
	if (ret < 0) return XMPP_EMEM;
	_render_update(&written, buflen, ret, &left, &ptr);

	if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
	    iter = hash_iter_new(stanza->attributes);
	    while ((key = hash_iter_next(iter))) {
                assert(hash_get(stanza->attributes, key));
		ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key,
			       (char *)hash_get(stanza->attributes, key));
		if (ret < 0) return XMPP_EMEM;
		_render_update(&written, buflen, ret, &left, &ptr);
	    }
	    hash_iter_release(iter);
	}

	if (!stanza->children) {
	    /* write end if singleton tag */
	    ret = xmpp_snprintf(ptr, left, "/>");
	    if (ret < 0) return XMPP_EMEM;
	    _render_update(&written, buflen, ret, &left, &ptr);
	} else {
	    /* this stanza has child stanzas */

	    /* write end of start tag */
	    ret = xmpp_snprintf(ptr, left, ">");
	    if (ret < 0) return XMPP_EMEM;
	    _render_update(&written, buflen, ret, &left, &ptr);

	    /* iterate and recurse over child stanzas */
	    child = stanza->children;
	    while (child) {
		ret = _render_stanza_recursive(child, ptr, left);
		if (ret < 0) return ret;

		_render_update(&written, buflen, ret, &left, &ptr);

		child = child->next;
	    }

	    /* write end tag */
            assert(stanza->data);
	    ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
	    if (ret < 0) return XMPP_EMEM;

	    _render_update(&written, buflen, ret, &left, &ptr);
	}
    }

    return written;
}
Example #3
0
/* always returns number of bytes written or that would have been
 * written if the buffer was large enough
 * return values < 0 indicate some error occurred,
 * and return values > buflen indicate buffer was not large enough
 */
static int _render_stanza_recursive(xmpp_stanza_t *stanza,
                             char * const buf, size_t const buflen)
{
    char *ptr = buf;
    size_t left = buflen;
    int ret, written;
    xmpp_stanza_t *child;
    hash_iterator_t *iter;
    const char *key;
    char *tmp;

    written = 0;

    if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP;

    if (stanza->type == XMPP_STANZA_TEXT) {
        if (!stanza->data) return XMPP_EINVOP;

        tmp = _escape_xml(stanza->ctx, stanza->data);
        if (tmp == NULL) return XMPP_EMEM;
        ret = xmpp_snprintf(ptr, left, "%s", tmp);
        xmpp_free(stanza->ctx, tmp);
        if (ret < 0) return XMPP_EMEM;
        _render_update(&written, buflen, ret, &left, &ptr);
    } else { /* stanza->type == XMPP_STANZA_TAG */
        if (!stanza->data) return XMPP_EINVOP;

        /* write beginning of tag and attributes */
        ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
        if (ret < 0) return XMPP_EMEM;
        _render_update(&written, buflen, ret, &left, &ptr);

        if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
            iter = hash_iter_new(stanza->attributes);
            while ((key = hash_iter_next(iter))) {
                if (!strcmp(key, "xmlns")) {
                    /* don't output namespace if parent stanza is the same */
                    if (stanza->parent &&
                        stanza->parent->attributes &&
                        hash_get(stanza->parent->attributes, key) &&
                        !strcmp((char*)hash_get(stanza->attributes, key),
                            (char*)hash_get(stanza->parent->attributes, key)))
                        continue;
                    /* or if this is the stream namespace */
                    if (!stanza->parent &&
                        !strcmp((char*)hash_get(stanza->attributes, key),
                            XMPP_NS_CLIENT))
                        continue;
                }
                tmp = _escape_xml(stanza->ctx,
                    (char *)hash_get(stanza->attributes, key));
                if (tmp == NULL) return XMPP_EMEM;
                ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
                xmpp_free(stanza->ctx, tmp);
                if (ret < 0) return XMPP_EMEM;
                _render_update(&written, buflen, ret, &left, &ptr);
            }
            hash_iter_release(iter);
        }

        if (!stanza->children) {
            /* write end if singleton tag */
            ret = xmpp_snprintf(ptr, left, "/>");
            if (ret < 0) return XMPP_EMEM;
            _render_update(&written, buflen, ret, &left, &ptr);
        } else {
            /* this stanza has child stanzas */

            /* write end of start tag */
            ret = xmpp_snprintf(ptr, left, ">");
            if (ret < 0) return XMPP_EMEM;
            _render_update(&written, buflen, ret, &left, &ptr);

            /* iterate and recurse over child stanzas */
            child = stanza->children;
            while (child) {
                ret = _render_stanza_recursive(child, ptr, left);
                if (ret < 0) return ret;

                _render_update(&written, buflen, ret, &left, &ptr);

                child = child->next;
            }

            /* write end tag */
            ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
            if (ret < 0) return XMPP_EMEM;

            _render_update(&written, buflen, ret, &left, &ptr);
        }
    }

    return written;
}
Example #4
0
int main(int argc, char **argv)
{
    xmpp_ctx_t *ctx;
    hash_t *table, *clone;
    hash_iterator_t *iter;
    unsigned int seed;
    const char *key;
    char *result;
    int err = 0;
    int i;

    /* initialize random numbers */
    if (argc > 2) {
	/* use a seed from the command line */
	seed = (unsigned int)atoi(argv[1]);
    } else {
	seed = (unsigned int)clock();
    }
    /* using random seed 'seed' */
    srand(seed);

    /* allocate a default context */
    ctx = xmpp_ctx_new(NULL, NULL);
    if (ctx == NULL) {
	/* ctx allocation failed! */
	return -1;
    }

    /* allocate a hash table */
    table = hash_new(ctx, TABLESIZE, NULL);
    if (table == NULL) {
	/* table allocation failed! */
	return 1;
    }

    /* test insertion */
    for (i = 0; i < nkeys; i++) {
	err = hash_add(table, keys[i], (void*)values[i]);
	if (err) return err;
    }

    /* test key count */
    if (hash_num_keys(table) != nkeys) {
	/* wrong number of keys in table! */
	return 1;
    }

    /* test cloning */
    clone = hash_clone(table);

    /* test lookup */
    for (i = 0; i < nkeys; i++) {
	result = hash_get(clone, keys[i]);
	if (result == NULL) {
	    /* lookup failed! */
	    return 1;
	}
	if (strcmp(values[i], result)) {
	    /* lookup returned incorrect value! */
	    return 1;
	}
    }

    /* test key iterator */
    iter = hash_iter_new(clone);
    if (iter == NULL) {
	/* iterator allocation failed! */
	return 1;
    }
    for (i = 0; i < nkeys; i++) {
	key = hash_iter_next(iter);
	printf("key: '%s'\n", key);
    }
    key = hash_iter_next(iter);
    if (key != NULL) {
	/* extra keys returned! */
	return 1;
    }
    key = hash_iter_next(iter);
    if (key != NULL) {
	/* extra keys returned! */
	return 1;
    }
    hash_iter_release(iter);

    /* release the hash table */
    hash_release(table);

    /* test drops */
    hash_drop(clone, keys[2]);
    if (hash_get(clone, keys[2]) != NULL) return 1;
    hash_drop(clone, keys[1]);
    hash_drop(clone, keys[4]);
    if (hash_get(clone, keys[4]) != NULL) return 1;
    if (hash_get(clone, keys[1]) != NULL) return 1;
    /* keys 0,3 should still be available */
    if (hash_get(clone, keys[0]) == NULL) return 1;
    if (hash_get(clone, keys[3]) == NULL) return 1;

    /* release our clone */
    hash_release(clone);

    /* release our library context */
    xmpp_ctx_free(ctx);

    return err;
}