src/mime.c

changeset 14253
b63ebf84c42b
parent 14252
d10dda2777a9
child 14254
77edc7a6191a
--- a/src/mime.c	Sat Aug 19 00:24:14 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,562 +0,0 @@
-/*
- * Gaim
- *
- * Gaim is the legal property of its developers, whose names are too
- * numerous to list here. Please refer to the COPYRIGHT file distributed
- * with this source distribution
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <glib.h>
-#include <glib/ghash.h>
-#include <glib/glist.h>
-#include <glib/gstring.h>
-
-/* this should become "util.h" if we ever get this into gaim proper */
-#include "debug.h"
-#include "mime.h"
-#include "util.h"
-
-/**
- * @struct mime_fields
- *
- * Utility structure used in both MIME document and parts, which maps
- * field names to their values, and keeps an easily accessible list of
- * keys.
- */
-struct mime_fields {
-	GHashTable *map;
-	GList *keys;
-};
-
-struct _GaimMimeDocument {
-	struct mime_fields fields;
-	GList *parts;
-};
-
-struct _GaimMimePart {
-	struct mime_fields fields;
-	struct _GaimMimeDocument *doc;
-	GString *data;
-};
-
-static void
-fields_set(struct mime_fields *mf, const char *key, const char *val)
-{
-	char *k, *v;
-
-	g_return_if_fail(mf != NULL);
-	g_return_if_fail(mf->map != NULL);
-
-	k = g_ascii_strdown(key, -1);
-	v = g_strdup(val);
-
-	/* append to the keys list only if it's not already there */
-	if(! g_hash_table_lookup(mf->map, k)) {
-		mf->keys = g_list_append(mf->keys, k);
-	}
-
-	/* important to use insert. If the key is already in the table, then
-		 it's already in the keys list. Insert will free the new instance
-		 of the key rather than the old instance. */
-	g_hash_table_insert(mf->map, k, v);
-}
-
-
-static const char *
-fields_get(struct mime_fields *mf, const char *key)
-{
-	char *kdown;
-	const char *ret;
-
-	g_return_val_if_fail(mf != NULL, NULL);
-	g_return_val_if_fail(mf->map != NULL, NULL);
-
-	kdown = g_ascii_strdown(key, -1);
-	ret = g_hash_table_lookup(mf->map, kdown);
-	g_free(kdown);
-
-	return ret;
-}
-
-
-static void
-fields_init(struct mime_fields *mf)
-{
-	g_return_if_fail(mf != NULL);
-
-	mf->map = g_hash_table_new_full(g_str_hash, g_str_equal,
-					g_free, g_free);
-}
-
-
-static void
-fields_loadline(struct mime_fields *mf, const char *line, gsize len)
-{
-	/* split the line into key: value */
-	char *key, *val;
-	char **tokens;
-
-	/* feh, need it to be NUL terminated */
-	key = g_strndup(line, len);
-
-	/* split */
-	val = strchr(key, ':');
-	if(! val) {
-		g_free(key);
-		return;
-	}
-	*val++ = '\0';
-
-	/* normalize whitespace (sorta) and trim on key and value */
-	tokens = g_strsplit(key, "\t\r\n", 0);
-	key = g_strjoinv("", tokens);
-	key = g_strstrip(key);
-	g_strfreev(tokens);
-
-	tokens = g_strsplit(val, "\t\r\n", 0);
-	val = g_strjoinv("", tokens);
-	val = g_strstrip(val);
-	g_strfreev(tokens);
-
-	fields_set(mf, key, val);
-
-	g_free(key);
-	g_free(val);
-}
-
-
-static void
-fields_load(struct mime_fields *mf, char **buf, gsize *len)
-{
-	char *tail;
-
-	while ((tail = g_strstr_len(*buf, *len, "\r\n")))
-	{
-		char *line;
-		gsize ln;
-
-		/* determine the current line */
-		line = *buf;
-		ln = tail - line;
-
-		/* advance our search space past the CRLF */
-		*buf = tail + 2;
-		*len -= (ln + 2);
-
-		/* empty line, end of headers */
-		if(! ln) return;
-
-		/* look out for line continuations */
-		if(line[ln-1] == ';') {
-			tail = g_strstr_len(*buf, *len, "\r\n");
-			if(tail) {
-				gsize cln;
-
-				cln = tail - *buf;
-				ln = tail - line;
-
-				/* advance our search space past the CRLF (again) */
-				*buf = tail + 2;
-				*len -= (cln + 2);
-			}
-		}
-
-		/* process our super-cool line */
-		fields_loadline(mf, line, ln);
-	}
-}
-
-
-static void
-field_write(const char *key, const char *val, GString *str)
-{
-	g_string_append_printf(str, "%s: %s\r\n", key, val);
-}
-
-
-static void
-fields_write(struct mime_fields *mf, GString *str)
-{
-	g_return_if_fail(mf != NULL);
-
-	g_hash_table_foreach(mf->map, (GHFunc) field_write, str);
-	g_string_append(str, "\r\n");
-}
-
-
-static void
-fields_destroy(struct mime_fields *mf)
-{
-	g_return_if_fail(mf != NULL);
-
-	g_hash_table_destroy(mf->map);
-	g_list_free(mf->keys);
-
-	mf->map = NULL;
-	mf->keys = NULL;
-}
-
-
-static GaimMimePart *
-part_new(GaimMimeDocument *doc)
-{
-	GaimMimePart *part;
-
-	part = g_new0(GaimMimePart, 1);
-	fields_init(&part->fields);
-	part->doc = doc;
-	part->data = g_string_new(NULL);
-
-	doc->parts = g_list_prepend(doc->parts, part);
-
-	return part;
-}
-
-
-static void
-part_load(GaimMimePart *part, const char *buf, gsize len)
-{
-
-	char *b = (char *) buf;
-	gsize n = len;
-
-	fields_load(&part->fields, &b, &n);
-
-	/* the remainder will have a blank line, if there's anything at all,
-		 so check if there's anything then trim off the trailing four
-		 bytes, \r\n\r\n */
-	if(n > 4) n -= 4;
-	g_string_append_len(part->data, b, n);
-}
-
-
-static void
-part_write(GaimMimePart *part, GString *str)
-{
-	fields_write(&part->fields, str);
-	g_string_append_printf(str, "%s\r\n\r\n", part->data->str);
-}
-
-
-static void
-part_free(GaimMimePart *part)
-{
-
-	fields_destroy(&part->fields);
-
-	g_string_free(part->data, TRUE);
-	part->data = NULL;
-
-	g_free(part);
-}
-
-
-GaimMimePart *
-gaim_mime_part_new(GaimMimeDocument *doc)
-{
-	g_return_val_if_fail(doc != NULL, NULL);
-	return part_new(doc);
-}
-
-
-const GList *
-gaim_mime_part_get_fields(GaimMimePart *part)
-{
-	g_return_val_if_fail(part != NULL, NULL);
-	return part->fields.keys;
-}
-
-
-const char *
-gaim_mime_part_get_field(GaimMimePart *part, const char *field)
-{
-	g_return_val_if_fail(part != NULL, NULL);
-	return fields_get(&part->fields, field);
-}
-
-
-char *
-gaim_mime_part_get_field_decoded(GaimMimePart *part, const char *field)
-{
-	const char *f;
-
-	g_return_val_if_fail(part != NULL, NULL);
-
-	f = fields_get(&part->fields, field);
-	return gaim_mime_decode_field(f);
-}
-
-
-void
-gaim_mime_part_set_field(GaimMimePart *part, const char *field, const char *value)
-{
-	g_return_if_fail(part != NULL);
-	fields_set(&part->fields, field, value);
-}
-
-
-const char *
-gaim_mime_part_get_data(GaimMimePart *part)
-{
-	g_return_val_if_fail(part != NULL, NULL);
-	g_return_val_if_fail(part->data != NULL, NULL);
-
-	return part->data->str;
-}
-
-
-void
-gaim_mime_part_get_data_decoded(GaimMimePart *part, guchar **data, gsize *len)
-{
-	const char *enc;
-
-	g_return_if_fail(part != NULL);
-	g_return_if_fail(data != NULL);
-	g_return_if_fail(len != NULL);
-
-	g_return_if_fail(part->data != NULL);
-
-	enc = gaim_mime_part_get_field(part, "content-transfer-encoding");
-
-	if(! enc) {
-		*data = (guchar *)g_strdup(part->data->str);
-		*len = part->data->len;
-
-	} else if(! g_ascii_strcasecmp(enc, "7bit")) {
-		*data = (guchar *)g_strdup(part->data->str);
-		*len = part->data->len;
-
-	} else if(! g_ascii_strcasecmp(enc, "8bit")) {
-		*data = (guchar *)g_strdup(part->data->str);
-		*len = part->data->len;
-
-	} else if(! g_ascii_strcasecmp(enc, "base16")) {
-		*data = gaim_base16_decode(part->data->str, len);
-
-	} else if(! g_ascii_strcasecmp(enc, "base64")) {
-	*data = gaim_base64_decode(part->data->str, len);
-
-	} else if(! g_ascii_strcasecmp(enc, "quoted-printable")) {
-		*data = gaim_quotedp_decode(part->data->str, len);
-
-	} else {
-		gaim_debug_warning("mime", "gaim_mime_part_get_data_decoded:"
-					 " unknown encoding '%s'\n", enc);
-		*data = NULL;
-		*len = 0;
-	}
-}
-
-
-gsize
-gaim_mime_part_get_length(GaimMimePart *part)
-{
-	g_return_val_if_fail(part != NULL, 0);
-	g_return_val_if_fail(part->data != NULL, 0);
-
-	return part->data->len;
-}
-
-
-void
-gaim_mime_part_set_data(GaimMimePart *part, const char *data)
-{
-	g_return_if_fail(part != NULL);
-	g_string_free(part->data, TRUE);
-	part->data = g_string_new(data);
-}
-
-
-GaimMimeDocument *
-gaim_mime_document_new()
-{
-	GaimMimeDocument *doc;
-
-	doc = g_new0(GaimMimeDocument, 1);
-	fields_init(&doc->fields);
-
-	return doc;
-}
-
-
-static void
-doc_parts_load(GaimMimeDocument *doc, const char *boundary, const char *buf, gsize len)
-{
-	char *b = (char *) buf;
-	gsize n = len;
-
-	const char *bnd;
-	gsize bl;
-
-	bnd = g_strdup_printf("--%s", boundary);
-	bl = strlen(bnd);
-
-	for(b = g_strstr_len(b, n, bnd); b; ) {
-		char *tail;
-
-		/* skip the boundary */
-		b += bl;
-		n -= bl;
-
-		/* skip the trailing \r\n or -- as well */
-		if(n >= 2) {
-			b += 2;
-			n -= 2;
-		}
-
-		/* find the next boundary */
-		tail = g_strstr_len(b, n, bnd);
-
-		if(tail) {
-			gsize sl;
-
-			sl = tail - b;
-			if(sl) {
-				GaimMimePart *part = part_new(doc);
-				part_load(part, b, sl);
-			}
-		}
-
-		b = tail;
-	}
-}
-
-
-GaimMimeDocument *
-gaim_mime_document_parsen(const char *buf, gsize len)
-{
-	GaimMimeDocument *doc;
-
-	char *b = (char *) buf;
-	gsize n = len;
-
-	g_return_val_if_fail(buf != NULL, NULL);
-
-	doc = gaim_mime_document_new();
-
-	if (!len)
-		return doc;
-
-	fields_load(&doc->fields, &b, &n);
-
-	{
-		const char *ct = fields_get(&doc->fields, "content-type");
-		if(ct && gaim_str_has_prefix(ct, "multipart")) {
-			char *bd = strrchr(ct, '=');
-			if(bd++) {
-				doc_parts_load(doc, bd, b, n);
-			}
-		}
-	}
-
-	return doc;
-}
-
-
-GaimMimeDocument *
-gaim_mime_document_parse(const char *buf)
-{
-	g_return_val_if_fail(buf != NULL, NULL);
-	return gaim_mime_document_parsen(buf, strlen(buf));
-}
-
-
-void
-gaim_mime_document_write(GaimMimeDocument *doc, GString *str)
-{
-	const char *bd = NULL;
-
-	g_return_if_fail(doc != NULL);
-	g_return_if_fail(str != NULL);
-
-	{
-		const char *ct = fields_get(&doc->fields, "content-type");
-		if(ct && gaim_str_has_prefix(ct, "multipart")) {
-			char *b = strrchr(ct, '=');
-			if(b++) bd = b;
-		}
-	}
-
-	fields_write(&doc->fields, str);
-
-	if(bd) {
-		GList *l;
-
-		for(l = doc->parts; l; l = l->next) {
-			g_string_append_printf(str, "--%s\r\n", bd);
-
-			part_write(l->data, str);
-
-			if(! l->next) {
-				g_string_append_printf(str, "--%s--\r\n", bd);
-			}
-		}
-	}
-}
-
-
-const GList *
-gaim_mime_document_get_fields(GaimMimeDocument *doc)
-{
-	g_return_val_if_fail(doc != NULL, NULL);
-	return doc->fields.keys;
-}
-
-
-const char *
-gaim_mime_document_get_field(GaimMimeDocument *doc, const char *field)
-{
-	g_return_val_if_fail(doc != NULL, NULL);
-	return fields_get(&doc->fields, field);
-}
-
-
-void
-gaim_mime_document_set_field(GaimMimeDocument *doc, const char *field, const char *value)
-{
-	g_return_if_fail(doc != NULL);
-	fields_set(&doc->fields, field, value);
-}
-
-
-const GList *
-gaim_mime_document_get_parts(GaimMimeDocument *doc)
-{
-	g_return_val_if_fail(doc != NULL, NULL);
-	return doc->parts;
-}
-
-
-void
-gaim_mime_document_free(GaimMimeDocument *doc)
-{
-	if (!doc)
-		return;
-
-	fields_destroy(&doc->fields);
-
-	while(doc->parts) {
-		part_free(doc->parts->data);
-		doc->parts = g_list_delete_link(doc->parts, doc->parts);
-	}
-
-	g_free(doc);
-}

mercurial