示例#1
0
文件: buddy.c 项目: dylex/pidgin
void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
{
	SilcPurple sg = gc->proto_data;
	SilcClient client = sg->client;
	SilcClientConnection conn = sg->conn;
	SilcMime mime;
	char type[32];
	unsigned char *icon;
	const char *t;
	SilcAttributeObjMime obj;

	/* Remove */
	if (!img) {
		silc_client_attribute_del(client, conn,
					  SILC_ATTRIBUTE_USER_ICON, NULL);
		return;
	}

	/* Add */
	mime = silc_mime_alloc();
	if (!mime)
		return;

	t = purple_imgstore_get_extension(img);
	if (!t || purple_strequal(t, "icon")) {
		silc_mime_free(mime);
		return;
	}
	if (purple_strequal(t, "jpg"))
		t = "jpeg";
	g_snprintf(type, sizeof(type), "image/%s", t);
	silc_mime_add_field(mime, "Content-Type", type);
	silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img));

	obj.mime = icon = silc_mime_encode(mime, &obj.mime_len);
	if (obj.mime)
		silc_client_attribute_add(client, conn,
					  SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj));

	silc_free(icon);
	silc_mime_free(mime);
}
示例#2
0
文件: util.c 项目: Draghtnod/pidgin
SilcDList silcpurple_image_message(const char *msg, SilcMessageFlags *mflags)
{
	SilcMime mime = NULL, p;
	SilcDList list, parts = NULL;
	const char *start, *end, *last;
	GData *attribs;
	char *type;
	gboolean images = FALSE;

	last = msg;
	while (last && *last && purple_markup_find_tag("img", last, &start,
						     &end, &attribs)) {
		PurpleStoredImage *image = NULL;
		const char *id;

		/* Check if there is text before image */
		if (start - last) {
			char *text, *tmp;
			p = silc_mime_alloc();

			/* Add content type */
			silc_mime_add_field(p, "Content-Type",
					    "text/plain; charset=utf-8");

			tmp = g_strndup(last, start - last);
			text = purple_unescape_html(tmp);
			g_free(tmp);

			/* Add text */
			silc_mime_add_data(p, (const unsigned char *)text, strlen(text));
			g_free(text);

			if (!parts)
				parts = silc_dlist_init();
			silc_dlist_add(parts, p);
		}

		id = g_datalist_get_data(&attribs, "id");
		if (id && (image = purple_imgstore_find_by_id(atoi(id)))) {
			unsigned long imglen = purple_imgstore_get_size(image);
			gconstpointer img = purple_imgstore_get_data(image);

			p = silc_mime_alloc();

			/* Add content type */
			type = silcpurple_file2mime(purple_imgstore_get_filename(image));
			if (!type) {
				g_datalist_clear(&attribs);
				last = end + 1;
				continue;
			}
			silc_mime_add_field(p, "Content-Type", type);
			g_free(type);

			/* Add content transfer encoding */
			silc_mime_add_field(p, "Content-Transfer-Encoding", "binary");

			/* Add image data */
			silc_mime_add_data(p, img, imglen);

			if (!parts)
				parts = silc_dlist_init();
			silc_dlist_add(parts, p);
			images = TRUE;
		}

		g_datalist_clear(&attribs);

		/* Continue after tag */
		last = end + 1;
	}

	/* Check for text after the image(s) */
	if (images && last && *last) {
		char *tmp = purple_unescape_html(last);
		p = silc_mime_alloc();

		/* Add content type */
		silc_mime_add_field(p, "Content-Type",
				    "text/plain; charset=utf-8");

		/* Add text */
		silc_mime_add_data(p, (const unsigned char *)tmp, strlen(tmp));
		g_free(tmp);

		if (!parts)
			parts = silc_dlist_init();
		silc_dlist_add(parts, p);
	}

	/* If there weren't any images, don't return anything. */
	if (!images) {
		if (parts)
			silc_dlist_uninit(parts);
		return NULL;
	}

	if (silc_dlist_count(parts) > 1) {
		/* Multipart MIME message */
		char b[32];
		mime = silc_mime_alloc();
		silc_mime_add_field(mime, "MIME-Version", "1.0");
		g_snprintf(b, sizeof(b), "b%4X%4X",
			   (unsigned int)time(NULL),
			   silc_dlist_count(parts));
		silc_mime_set_multipart(mime, "mixed", b);
		silc_dlist_start(parts);
		while ((p = silc_dlist_get(parts)) != SILC_LIST_END)
			silc_mime_add_multipart(mime, p);
	} else {
		/* Simple MIME message */
		silc_dlist_start(parts);
		mime = silc_dlist_get(parts);
		silc_mime_add_field(mime, "MIME-Version", "1.0");
	}

	*mflags &= ~SILC_MESSAGE_FLAG_UTF8;
	*mflags |= SILC_MESSAGE_FLAG_DATA;

	/* Encode message. Fragment if it is too large */
	list = silc_mime_encode_partial(mime, 0xfc00);

	silc_dlist_uninit(parts);

	/* Added multiparts gets freed here */
	silc_mime_free(mime);

	return list;
}
示例#3
0
SilcDList silc_mime_encode_partial(SilcMime mime, int max_size)
{
    unsigned char *buf, *tmp;
    SilcUInt32 buf_len, len, tmp_len, off;
    SilcDList list;
    SilcBuffer buffer;
    SilcMime partial;
    char type[128], id[64];
    int num;

    SILC_LOG_DEBUG(("Fragmenting MIME message"));

    /* Encode as normal */
    buf = silc_mime_encode(mime, &buf_len);
    if (!buf)
        return NULL;

    list = silc_dlist_init();

    /* Fragment if it is too large */
    if (buf_len > max_size) {
        memset(id, 0, sizeof(id));
        memset(type, 0, sizeof(type));
        gethostname(type, sizeof(type) - 1);
        srand((time(NULL) + buf_len) ^ rand());
        silc_snprintf(id, sizeof(id) - 1, "%X%X%X%s",
                      (unsigned int)rand(), (unsigned int)time(NULL),
                      (unsigned int)buf_len, type);

        SILC_LOG_DEBUG(("Fragment ID %s", id));

        partial = silc_mime_alloc();
        if (!partial)
            return NULL;

        silc_mime_add_field(partial, "MIME-Version", "1.0");
        memset(type, 0, sizeof(type));
        silc_snprintf(type, sizeof(type) - 1,
                      "message/partial; id=\"%s\"; number=1", id);
        silc_mime_add_field(partial, "Content-Type", type);
        silc_mime_add_data(partial, buf, max_size);

        tmp = silc_mime_encode(partial, &tmp_len);
        if (!tmp)
            return NULL;
        silc_mime_free(partial);

        /* Add to list */
        buffer = silc_buffer_alloc_size(tmp_len);
        if (!buffer)
            return NULL;
        silc_buffer_put(buffer, tmp, tmp_len);
        silc_dlist_add(list, buffer);
        silc_free(tmp);

        len = buf_len - max_size;
        off = max_size;
        num = 2;
        while (len > 0) {
            partial = silc_mime_alloc();
            if (!partial)
                return NULL;

            memset(type, 0, sizeof(type));
            silc_mime_add_field(partial, "MIME-Version", "1.0");

            if (len > max_size) {
                silc_snprintf(type, sizeof(type) - 1,
                              "message/partial; id=\"%s\"; number=%d",
                              id, num++);
                silc_mime_add_data(partial, buf + off, max_size);
                off += max_size;
                len -= max_size;
            } else {
                silc_snprintf(type, sizeof(type) - 1,
                              "message/partial; id=\"%s\"; number=%d; total=%d",
                              id, num, num);
                silc_mime_add_data(partial, buf + off, len);
                len = 0;
            }

            silc_mime_add_field(partial, "Content-Type", type);

            tmp = silc_mime_encode(partial, &tmp_len);
            if (!tmp)
                return NULL;
            silc_mime_free(partial);

            /* Add to list */
            buffer = silc_buffer_alloc_size(tmp_len);
            if (!buffer)
                return NULL;
            silc_buffer_put(buffer, tmp, tmp_len);
            silc_dlist_add(list, buffer);
            silc_free(tmp);
        }
    } else {
        /* No need to fragment */
        buffer = silc_buffer_alloc_size(buf_len);
        if (!buffer)
            return NULL;
        silc_buffer_put(buffer, buf, buf_len);
        silc_dlist_add(list, buffer);
    }

    silc_free(buf);

    return list;
}
示例#4
0
SilcMime silc_mime_decode(SilcMime mime, const unsigned char *data,
                          SilcUInt32 data_len)
{
    SilcMime m = NULL;
    int i, k;
    char *tmp, *field, *value, *line;

    SILC_LOG_DEBUG(("Parsing MIME message"));

    if (!data)
        return NULL;

    if (!mime) {
        mime = silc_mime_alloc();
        if (!mime)
            return NULL;
        m = mime;
    }

    /* Parse the fields */
    line = tmp = (char *)data;
    for (i = 0; i < data_len; i++) {
        /* Get field line */
        if (data_len - i >= 2 && tmp[i] == '\r' && tmp[i + 1] == '\n') {
            /* Get field */
            field = strchr(line, ':');
            if (!field)
                goto err;
            field = silc_memdup(line, field - line);
            if (!field)
                goto err;

            /* Get value. Remove whitespaces too. */
            value = strchr(line, ':');
            if ((tmp + i) - value < 2)
                goto err;
            value++;
            for (k = 0; k < (tmp + i) - value; k++) {
                if (value[k] == '\r')
                    goto err;
                if (value[k] != ' ' && value[k] != '\t')
                    break;
            }
            value += k;
            if ((tmp + i) - value < 1)
                goto err;
            value = silc_memdup(value, (tmp + i) - value);
            if (!value)
                goto err;

            SILC_LOG_DEBUG(("Header '%s' '%s'", field, value));

            /* Add field and value */
            silc_mime_add_field(mime, field, value);
            silc_free(field);
            silc_free(value);

            /* Mark start of next line */
            line = (tmp + i) + 2;
            i += 2;

            /* Break if this is last header */
            if (data_len - i >= 2 &&
                    tmp[i] == '\r' && tmp[i + 1] == '\n') {
                i += 2;
                break;
            }
        }
    }

    /* Parse multiparts if present */
    field = (char *)silc_mime_get_field(mime, "Content-Type");
    if (field && strstr(field, "multipart")) {
        char b[1024];
        SilcMime p;
        unsigned int len;

        mime->multiparts = silc_dlist_init();
        if (!mime->multiparts)
            goto err;

        /* Get multipart type */
        value = strchr(field, '/');
        if (!value)
            goto err;
        value++;
        if (strchr(field, '"'))
            value++;
        if (!strchr(field, ';'))
            goto err;
        memset(b, 0, sizeof(b));
        len = (unsigned int)(strchr(field, ';') - value);
        if (len > sizeof(b) - 1)
            goto err;
        strncpy(b, value, len);
        if (strchr(b, '"'))
            *strchr(b, '"') = '\0';
        mime->multitype = silc_memdup(b, strlen(b));

        /* Get boundary */
        value = strrchr(field, '=');
        if (value && strlen(value) > 1) {
            value++;

            SILC_LOG_DEBUG(("Boundary '%s'", value));

            memset(b, 0, sizeof(b));
            line = strdup(value);
            if (strrchr(line, '"')) {
                *strrchr(line, '"') = '\0';
                silc_snprintf(b, sizeof(b) - 1, "--%s", line + 1);
                mime->boundary = strdup(line + 1);
            } else {
                silc_snprintf(b, sizeof(b) - 1, "--%s", line);
                mime->boundary = strdup(line);
            }
            silc_free(line);

            for (i = i; i < data_len; i++) {
                /* Get boundary data */
                if (data_len - i >= strlen(b) &&
                        tmp[i] == '-' && tmp[i + 1] == '-') {
                    if (memcmp(tmp + i, b, strlen(b)))
                        continue;

                    i += strlen(b);

                    if (data_len - i >= 4 &&
                            tmp[i    ] == '\r' && tmp[i + 1] == '\n' &&
                            tmp[i + 2] == '\r' && tmp[i + 3] == '\n')
                        i += 4;
                    else if (data_len - i >= 2 &&
                             tmp[i] == '\r' && tmp[i + 1] == '\n')
                        i += 2;
                    else if (data_len - i >= 2 &&
                             tmp[i] == '-' && tmp[i + 1] == '-')
                        break;

                    line = tmp + i;

                    /* Find end of boundary */
                    for (k = i; k < data_len; k++)
                        if (data_len - k >= strlen(b) &&
                                tmp[k] == '-' && tmp[k + 1] == '-')
                            if (!memcmp(tmp + k, b, strlen(b)))
                                break;
                    if (k >= data_len)
                        goto err;

                    /* Remove preceding CRLF */
                    k -= 2;

                    /* Parse the part */
                    p = silc_mime_decode(NULL, line, k - i);
                    if (!p)
                        goto err;

                    silc_dlist_add(mime->multiparts, p);
                    i += (k - i);
                }
            }
        }
    } else {
        /* Get data area.  If we are at the end and we have fields present
           there is no data area present, but, if fields are not present we
           only have data area. */
        if (i >= data_len && !silc_hash_table_count(mime->fields))
            i = 0;
        SILC_LOG_DEBUG(("Data len %d", data_len - i));
        if (data_len - i)
            silc_mime_add_data(mime, tmp + i, data_len - i);
    }

    return mime;

err:
    if (m)
        silc_mime_free(m);
    return NULL;
}