[gmime] Updated code to use the new GMimeParamList instead of a linked-list
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime] Updated code to use the new GMimeParamList instead of a linked-list
- Date: Wed, 15 Mar 2017 21:33:39 +0000 (UTC)
commit 71c5b5f37989426f667fc1e37a0468f637c4334b
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date: Wed Mar 15 17:32:25 2017 -0400
Updated code to use the new GMimeParamList instead of a linked-list
examples/imap-example.c | 118 +++--
gmime/gmime-content-type.c | 76 +--
gmime/gmime-content-type.h | 7 +-
gmime/gmime-disposition.c | 82 +--
gmime/gmime-disposition.h | 6 +-
gmime/gmime-object.c | 17 +-
gmime/gmime-param.c | 1394 ++++++++++++++++++++++----------------------
gmime/gmime-param.h | 71 ++-
tests/test-headers.c | 15 +-
tests/test-mime.c | 43 +-
10 files changed, 913 insertions(+), 916 deletions(-)
---
diff --git a/examples/imap-example.c b/examples/imap-example.c
index 4859c39..ee867cf 100644
--- a/examples/imap-example.c
+++ b/examples/imap-example.c
@@ -77,23 +77,35 @@ escape_string (const char *string)
static void
write_part_bodystructure (GMimeObject *part, FILE *fp)
{
+ GMimeContentType *content_type;
+ GMimeParamList *params;
+ const char *subtype;
GMimeParam *param;
+ int i, n;
fputc ('(', fp);
- fprintf (fp, "\"%s\" ", part->content_type->type);
- if (part->content_type->subtype)
- fprintf (fp, "\"%s\" ", part->content_type->subtype);
+ content_type = g_mime_object_get_content_type (part);
+
+ fprintf (fp, "\"%s\" ", g_mime_content_type_get_media_type (content_type));
+
+ if ((subtype = g_mime_content_type_get_media_subtype (content_type)))
+ fprintf (fp, "\"%s\" ", subtype);
else
fputs ("\"\"", fp);
/* Content-Type params */
- if ((param = part->content_type->params)) {
+ params = g_mime_content_type_get_params (content_type);
+ if ((n = g_mime_param_list_length (params)) > 0) {
fputc ('(', fp);
- while (param) {
- fprintf (fp, "\"%s\" \"%s\"", param->name, param->value);
- if ((param = param->next))
+ for (i = 0; i < n; i++) {
+ if (i > 0)
fputc (' ', fp);
+
+ param = g_mime_param_list_get_parameter_at (params, i);
+ fprintf (fp, "\"%s\" \"%s\"", g_mime_param_get_name (param),
+ g_mime_param_get_value (param));
+
}
fputs (") ", fp);
} else {
@@ -103,7 +115,6 @@ write_part_bodystructure (GMimeObject *part, FILE *fp)
if (GMIME_IS_MULTIPART (part)) {
GMimeMultipart *multipart = (GMimeMultipart *) part;
GMimeObject *subpart;
- int i, n;
n = g_mime_multipart_get_count (multipart);
for (i = 0; i < n; i++) {
@@ -192,14 +203,23 @@ write_part_bodystructure (GMimeObject *part, FILE *fp)
/* print body */
write_part_bodystructure ((GMimeObject *) message->mime_part, fp);
} else if (GMIME_IS_PART (part)) {
- if (GMIME_OBJECT (part)->disposition) {
- fprintf (fp, "\"%s\" ", GMIME_OBJECT (part)->disposition->disposition);
- if ((param = GMIME_OBJECT (part)->disposition->params)) {
+ GMimeContentDisposition *disposition;
+
+ disposition = g_mime_object_get_content_disposition (part);
+
+ if (disposition) {
+ fprintf (fp, "\"%s\" ", g_mime_content_disposition_get_disposition (disposition));
+
+ params = g_mime_content_disposition_get_params (disposition);
+ if ((n = g_mime_param_list_length (params)) > 0) {
fputc ('(', fp);
- while (param) {
- fprintf (fp, "\"%s\" \"%s\"", param->name, param->value);
- if ((param = param->next))
+ for (i = 0; i < n; i++) {
+ if (i > 0)
fputc (' ', fp);
+
+ param = g_mime_param_list_get_parameter_at (params, i);
+ fprintf (fp, "\"%s\" \"%s\"", g_mime_param_get_name (param),
+ g_mime_param_get_value (param));
}
fputs (") ", fp);
} else {
@@ -209,7 +229,7 @@ write_part_bodystructure (GMimeObject *part, FILE *fp)
fputs ("NIL NIL ", fp);
}
- switch (GMIME_PART (part)->encoding) {
+ switch (g_mime_part_get_content_encoding ((GMimePart *) part)) {
case GMIME_CONTENT_ENCODING_7BIT:
fputs ("\"7bit\"", fp);
break;
@@ -351,11 +371,11 @@ struct _bodystruct {
struct {
char *type;
char *subtype;
- GMimeParam *params;
+ GMimeParamList *params;
} content;
struct {
char *type;
- GMimeParam *params;
+ GMimeParamList *params;
} disposition;
char *encoding;
struct _envelope *envelope;
@@ -415,49 +435,53 @@ decode_qstring (unsigned char **in, unsigned char *inend)
return qstring;
}
-static GMimeParam *
-decode_param (unsigned char **in, unsigned char *inend)
+static gboolean
+decode_param (unsigned char **in, unsigned char *inend, char **name, char **value)
{
GMimeParam *param;
- char *name, *val;
+ char *n, *v;
- if (!(name = decode_qstring (in, inend)))
- return NULL;
+ if (!(n = decode_qstring (in, inend)))
+ return FALSE;
- g_assert ((val = decode_qstring (in, inend)));
+ if (!(v = decode_qstring (in, inend))) {
+ g_free (n);
+ return FALSE;
+ }
- param = g_mime_param_new (name, val);
- g_free (name);
- g_free (val);
+ *name = n;
+ *value = v;
- return param;
+ return TRUE;
}
-static GMimeParam *
+static GMimeParamList *
decode_params (unsigned char **in, unsigned char *inend)
{
- GMimeParam *params, *tail, *n;
+ GMimeParamList *params;
unsigned char *inptr;
+ char *name, *value;
inptr = *in;
- params = NULL;
- tail = (GMimeParam *) ¶ms;
+
+ params = g_mime_param_list_new ();
while (inptr < inend && *inptr == ' ')
inptr++;
if (inptr == inend) {
g_assert_not_reached ();
- return NULL;
+ return params;
}
if (strncmp ((const char *) inptr, "NIL", 3) != 0) {
g_assert (*inptr == '(');
inptr++;
- while ((n = decode_param (&inptr, inend)) != NULL) {
- tail->next = n;
- tail = n;
+ while (decode_param (&inptr, inend, &name, &value)) {
+ g_mime_param_list_set_parameter (params, name, value);
+ g_free (value);
+ g_free (name);
while (inptr < inend && *inptr == ' ')
inptr++;
@@ -597,7 +621,7 @@ static void
bodystruct_dump (struct _bodystruct *part, int depth)
{
GMimeParam *param;
- int i;
+ int i, n;
for (i = 0; i < depth; i++)
fputs (" ", stderr);
@@ -606,10 +630,11 @@ bodystruct_dump (struct _bodystruct *part, int depth)
part->content.subtype);
if (part->content.params) {
- param = part->content.params;
- while (param) {
- fprintf (stderr, "; %s=%s", param->name, param->value);
- param = param->next;
+ n = g_mime_param_list_length (part->content.params);
+ for (int i = 0; i < n; i++) {
+ param = g_mime_param_list_get_parameter_at (part->content.params, i);
+ fprintf (stderr, "; %s=%s", g_mime_param_get_name (param),
+ g_mime_param_get_value (param));
}
}
@@ -662,10 +687,11 @@ bodystruct_dump (struct _bodystruct *part, int depth)
fputs (" ", stderr);
fprintf (stderr, "Content-Disposition: %s", part->disposition.type);
if (part->disposition.params) {
- param = part->disposition.params;
- while (param) {
- fprintf (stderr, "; %s=%s", param->name, param->value);
- param = param->next;
+ n = g_mime_param_list_length (part->disposition.params);
+ for (i = 0; i < n; i++) {
+ param = g_mime_param_list_get_parameter_at (part->disposition.params,
i);
+ fprintf (stderr, "; %s=%s", g_mime_param_get_name (param),
+ g_mime_param_get_value (param));
}
}
@@ -691,11 +717,11 @@ bodystruct_free (struct _bodystruct *node)
g_free (node->content.type);
g_free (node->content.subtype);
if (node->content.params)
- g_mime_param_free (node->content.params);
+ g_mime_param_list_free (node->content.params);
g_free (node->disposition.type);
if (node->disposition.params)
- g_mime_param_free (node->disposition.params);
+ g_mime_param_list_free (node->disposition.params);
g_free (node->encoding);
diff --git a/gmime/gmime-content-type.c b/gmime/gmime-content-type.c
index b1cfb4f..09ea132 100644
--- a/gmime/gmime-content-type.c
+++ b/gmime/gmime-content-type.c
@@ -57,6 +57,8 @@ static void g_mime_content_type_class_init (GMimeContentTypeClass *klass);
static void g_mime_content_type_init (GMimeContentType *content_type, GMimeContentTypeClass *klass);
static void g_mime_content_type_finalize (GObject *object);
+static void param_list_changed (GMimeParamList *list, gpointer args, GMimeContentType *content_type);
+
static GObjectClass *parent_class = NULL;
@@ -99,11 +101,12 @@ g_mime_content_type_class_init (GMimeContentTypeClass *klass)
static void
g_mime_content_type_init (GMimeContentType *content_type, GMimeContentTypeClass *klass)
{
- content_type->param_hash = g_hash_table_new (g_mime_strcase_hash, g_mime_strcase_equal);
content_type->changed = g_mime_event_new ((GObject *) content_type);
- content_type->params = NULL;
+ content_type->params = g_mime_param_list_new ();
content_type->subtype = NULL;
content_type->type = NULL;
+
+ g_mime_event_add (content_type->params->changed, (GMimeEventCallback) param_list_changed,
content_type);
}
static void
@@ -111,8 +114,7 @@ g_mime_content_type_finalize (GObject *object)
{
GMimeContentType *content_type = (GMimeContentType *) object;
- g_hash_table_destroy (content_type->param_hash);
- g_mime_param_free (content_type->params);
+ g_mime_param_list_free (content_type->params);
g_mime_event_free (content_type->changed);
g_free (content_type->subtype);
g_free (content_type->type);
@@ -121,6 +123,13 @@ g_mime_content_type_finalize (GObject *object)
}
+static void
+param_list_changed (GMimeParamList *list, gpointer args, GMimeContentType *content_type)
+{
+ g_mime_event_emit (content_type->changed, NULL);
+}
+
+
/**
* g_mime_content_type_new:
* @type: the MIME type or %NULL for the default value
@@ -180,6 +189,7 @@ g_mime_content_type_parse (GMimeParserOptions *options, const char *str)
{
GMimeContentType *mime_type;
const char *inptr = str;
+ GMimeParamList *params;
char *type, *subtype;
g_return_val_if_fail (str != NULL, NULL);
@@ -196,14 +206,10 @@ g_mime_content_type_parse (GMimeParserOptions *options, const char *str)
while (*inptr && *inptr != ';')
inptr++;
- if (*inptr++ == ';' && *inptr) {
- GMimeParam *param;
-
- param = mime_type->params = g_mime_param_parse (options, inptr);
- while (param != NULL) {
- g_hash_table_insert (mime_type->param_hash, param->name, param);
- param = param->next;
- }
+ if (*inptr++ == ';' && *inptr && (params = g_mime_param_list_parse (options, inptr))) {
+ g_mime_event_add (params->changed, (GMimeEventCallback) param_list_changed, mime_type);
+ g_mime_param_list_free (mime_type->params);
+ mime_type->params = params;
}
return mime_type;
@@ -351,32 +357,6 @@ g_mime_content_type_get_media_subtype (GMimeContentType *mime_type)
/**
- * g_mime_content_type_set_params:
- * @mime_type: a #GMimeContentType object
- * @params: a list of #GMimeParam objects
- *
- * Sets the Content-Type's parameter list.
- **/
-void
-g_mime_content_type_set_params (GMimeContentType *mime_type, GMimeParam *params)
-{
- g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
-
- /* clear the current list/hash */
- g_hash_table_remove_all (mime_type->param_hash);
- g_mime_param_free (mime_type->params);
- mime_type->params = params;
-
- while (params != NULL) {
- g_hash_table_insert (mime_type->param_hash, params->name, params);
- params = params->next;
- }
-
- g_mime_event_emit (mime_type->changed, NULL);
-}
-
-
-/**
* g_mime_content_type_get_params:
* @mime_type: a #GMimeContentType object
*
@@ -384,7 +364,7 @@ g_mime_content_type_set_params (GMimeContentType *mime_type, GMimeParam *params)
*
* Returns: the Content-Type's parameter list.
**/
-const GMimeParam *
+GMimeParamList *
g_mime_content_type_get_params (GMimeContentType *mime_type)
{
g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
@@ -407,22 +387,9 @@ g_mime_content_type_get_params (GMimeContentType *mime_type)
void
g_mime_content_type_set_parameter (GMimeContentType *mime_type, const char *name, const char *value)
{
- GMimeParam *param = NULL;
-
g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
- g_return_if_fail (name != NULL);
- g_return_if_fail (value != NULL);
- if ((param = g_hash_table_lookup (mime_type->param_hash, name))) {
- g_free (param->value);
- param->value = g_strdup (value);
- } else {
- param = g_mime_param_new (name, value);
- mime_type->params = g_mime_param_append_param (mime_type->params, param);
- g_hash_table_insert (mime_type->param_hash, param->name, param);
- }
-
- g_mime_event_emit (mime_type->changed, NULL);
+ g_mime_param_list_set_parameter (mime_type->params, name, value);
}
@@ -443,9 +410,8 @@ g_mime_content_type_get_parameter (GMimeContentType *mime_type, const char *name
GMimeParam *param;
g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
- g_return_val_if_fail (name != NULL, NULL);
- if (!(param = g_hash_table_lookup (mime_type->param_hash, name)))
+ if (!(param = g_mime_param_list_get_parameter (mime_type->params, name)))
return NULL;
return param->value;
diff --git a/gmime/gmime-content-type.h b/gmime/gmime-content-type.h
index 077dee4..eb6cb4c 100644
--- a/gmime/gmime-content-type.h
+++ b/gmime/gmime-content-type.h
@@ -52,10 +52,9 @@ struct _GMimeContentType {
GObject parent_object;
char *type, *subtype;
- GMimeParam *params;
+ GMimeParamList *params;
/* < private > */
- GHashTable *param_hash;
gpointer changed;
};
@@ -66,7 +65,6 @@ struct _GMimeContentTypeClass {
GType g_mime_content_type_get_type (void);
-
GMimeContentType *g_mime_content_type_new (const char *type, const char *subtype);
GMimeContentType *g_mime_content_type_parse (GMimeParserOptions *options, const char *str);
@@ -80,8 +78,7 @@ const char *g_mime_content_type_get_media_type (GMimeContentType *mime_type);
void g_mime_content_type_set_media_subtype (GMimeContentType *mime_type, const char *subtype);
const char *g_mime_content_type_get_media_subtype (GMimeContentType *mime_type);
-void g_mime_content_type_set_params (GMimeContentType *mime_type, GMimeParam *params);
-const GMimeParam *g_mime_content_type_get_params (GMimeContentType *mime_type);
+GMimeParamList *g_mime_content_type_get_params (GMimeContentType *mime_type);
void g_mime_content_type_set_parameter (GMimeContentType *mime_type, const char *name, const char *value);
const char *g_mime_content_type_get_parameter (GMimeContentType *mime_type, const char *name);
diff --git a/gmime/gmime-disposition.c b/gmime/gmime-disposition.c
index af388e0..db03d57 100644
--- a/gmime/gmime-disposition.c
+++ b/gmime/gmime-disposition.c
@@ -46,6 +46,8 @@ static void g_mime_content_disposition_class_init (GMimeContentDispositionClass
static void g_mime_content_disposition_init (GMimeContentDisposition *disposition,
GMimeContentDispositionClass *klass);
static void g_mime_content_disposition_finalize (GObject *object);
+static void param_list_changed (GMimeParamList *list, gpointer args, GMimeContentDisposition *disposition);
+
static GObjectClass *parent_class = NULL;
@@ -88,10 +90,11 @@ g_mime_content_disposition_class_init (GMimeContentDispositionClass *klass)
static void
g_mime_content_disposition_init (GMimeContentDisposition *disposition, GMimeContentDispositionClass *klass)
{
- disposition->param_hash = g_hash_table_new (g_mime_strcase_hash, g_mime_strcase_equal);
disposition->changed = g_mime_event_new ((GObject *) disposition);
+ disposition->params = g_mime_param_list_new ();
disposition->disposition = NULL;
- disposition->params = NULL;
+
+ g_mime_event_add (disposition->params->changed, (GMimeEventCallback) param_list_changed, disposition);
}
static void
@@ -99,8 +102,7 @@ g_mime_content_disposition_finalize (GObject *object)
{
GMimeContentDisposition *disposition = (GMimeContentDisposition *) object;
- g_hash_table_destroy (disposition->param_hash);
- g_mime_param_free (disposition->params);
+ g_mime_param_list_free (disposition->params);
g_mime_event_free (disposition->changed);
g_free (disposition->disposition);
@@ -108,6 +110,13 @@ g_mime_content_disposition_finalize (GObject *object)
}
+static void
+param_list_changed (GMimeParamList *list, gpointer args, GMimeContentDisposition *disposition)
+{
+ g_mime_event_emit (disposition->changed, NULL);
+}
+
+
/**
* g_mime_content_disposition_new:
*
@@ -141,7 +150,7 @@ g_mime_content_disposition_parse (GMimeParserOptions *options, const char *str)
{
GMimeContentDisposition *disposition;
const char *inptr = str;
- GMimeParam *param;
+ GMimeParamList *params;
char *value;
if (str == NULL)
@@ -159,13 +168,10 @@ g_mime_content_disposition_parse (GMimeParserOptions *options, const char *str)
disposition->disposition = g_strstrip (value);
/* parse the parameters, if any */
- if (*inptr++ == ';' && *inptr) {
- param = disposition->params = g_mime_param_parse (options, inptr);
-
- while (param) {
- g_hash_table_insert (disposition->param_hash, param->name, param);
- param = param->next;
- }
+ if (*inptr++ == ';' && *inptr && (params = g_mime_param_list_parse (options, inptr))) {
+ g_mime_event_add (params->changed, (GMimeEventCallback) param_list_changed, disposition);
+ g_mime_param_list_free (disposition->params);
+ disposition->params = params;
}
return disposition;
@@ -217,40 +223,14 @@ g_mime_content_disposition_get_disposition (GMimeContentDisposition *disposition
/**
- * g_mime_content_disposition_set_params:
- * @disposition: a #GMimeContentDisposition object
- * @params: a list of #GMimeParam objects
- *
- * Sets the Content-Disposition's parameter list.
- **/
-void
-g_mime_content_disposition_set_params (GMimeContentDisposition *disposition, GMimeParam *params)
-{
- g_return_if_fail (GMIME_IS_CONTENT_DISPOSITION (disposition));
-
- /* destroy the current list/hash */
- g_hash_table_remove_all (disposition->param_hash);
- g_mime_param_free (disposition->params);
- disposition->params = params;
-
- while (params != NULL) {
- g_hash_table_insert (disposition->param_hash, params->name, params);
- params = params->next;
- }
-
- g_mime_event_emit (disposition->changed, NULL);
-}
-
-
-/**
* g_mime_content_disposition_get_params:
* @disposition: a #GMimeContentDisposition object
*
* Gets the Content-Disposition parameter list.
*
- * Returns: the list of #GMimeParam's set on @disposition.
+ * Returns: the Content-Disposition's parameter list.
**/
-const GMimeParam *
+GMimeParamList *
g_mime_content_disposition_get_params (GMimeContentDisposition *disposition)
{
g_return_val_if_fail (GMIME_IS_CONTENT_DISPOSITION (disposition), NULL);
@@ -273,22 +253,9 @@ g_mime_content_disposition_get_params (GMimeContentDisposition *disposition)
void
g_mime_content_disposition_set_parameter (GMimeContentDisposition *disposition, const char *name, const char
*value)
{
- GMimeParam *param = NULL;
-
g_return_if_fail (GMIME_IS_CONTENT_DISPOSITION (disposition));
- g_return_if_fail (name != NULL);
- g_return_if_fail (value != NULL);
-
- if ((param = g_hash_table_lookup (disposition->param_hash, name))) {
- g_free (param->value);
- param->value = g_strdup (value);
- } else {
- param = g_mime_param_new (name, value);
- disposition->params = g_mime_param_append_param (disposition->params, param);
- g_hash_table_insert (disposition->param_hash, param->name, param);
- }
- g_mime_event_emit (disposition->changed, NULL);
+ g_mime_param_list_set_parameter (disposition->params, name, value);
}
@@ -309,9 +276,8 @@ g_mime_content_disposition_get_parameter (GMimeContentDisposition *disposition,
GMimeParam *param;
g_return_val_if_fail (GMIME_IS_CONTENT_DISPOSITION (disposition), NULL);
- g_return_val_if_fail (name != NULL, NULL);
- if (!(param = g_hash_table_lookup (disposition->param_hash, name)))
+ if (!(param = g_mime_param_list_get_parameter (disposition->params, name)))
return NULL;
return param->value;
@@ -350,8 +316,8 @@ g_mime_content_disposition_is_attachment (GMimeContentDisposition *disposition)
char *
g_mime_content_disposition_to_string (GMimeContentDisposition *disposition, gboolean fold)
{
- GString *string;
char *header, *buf;
+ GString *string;
g_return_val_if_fail (GMIME_IS_CONTENT_DISPOSITION (disposition), NULL);
@@ -359,7 +325,7 @@ g_mime_content_disposition_to_string (GMimeContentDisposition *disposition, gboo
string = g_string_new ("Content-Disposition: ");
g_string_append (string, disposition->disposition);
- g_mime_param_write_to_string (disposition->params, fold, string);
+ g_mime_param_list_encode (disposition->params, fold, string);
header = string->str;
g_string_free (string, FALSE);
diff --git a/gmime/gmime-disposition.h b/gmime/gmime-disposition.h
index 9446c43..e5586b2 100644
--- a/gmime/gmime-disposition.h
+++ b/gmime/gmime-disposition.h
@@ -67,10 +67,9 @@ struct _GMimeContentDisposition {
GObject parent_object;
char *disposition;
- GMimeParam *params;
+ GMimeParamList *params;
/* < private > */
- GHashTable *param_hash;
gpointer changed;
};
@@ -88,8 +87,7 @@ GMimeContentDisposition *g_mime_content_disposition_parse (GMimeParserOptions *o
void g_mime_content_disposition_set_disposition (GMimeContentDisposition *disposition, const char *value);
const char *g_mime_content_disposition_get_disposition (GMimeContentDisposition *disposition);
-void g_mime_content_disposition_set_params (GMimeContentDisposition *disposition, GMimeParam *params);
-const GMimeParam *g_mime_content_disposition_get_params (GMimeContentDisposition *disposition);
+GMimeParamList *g_mime_content_disposition_get_params (GMimeContentDisposition *disposition);
void g_mime_content_disposition_set_parameter (GMimeContentDisposition *disposition,
const char *name, const char *value);
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index caa1268..57e579c 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -322,7 +322,7 @@ write_content_type (GMimeParserOptions *options, GMimeStream *stream, const char
g_string_append (out, val);
g_free (val);
- g_mime_param_write_to_string (content_type->params, TRUE, out);
+ g_mime_param_list_encode (content_type->params, TRUE, out);
g_object_unref (content_type);
nwritten = g_mime_stream_write (stream, out->str, out->len);
@@ -352,9 +352,8 @@ _g_mime_object_unblock_header_list_changed (GMimeObject *object)
static void
content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object)
{
- GMimeParam *params;
GString *string;
- char *type, *p;
+ char *type, *str;
string = g_string_new ("Content-Type: ");
@@ -362,17 +361,15 @@ content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject
g_string_append (string, type);
g_free (type);
- if ((params = content_type->params))
- g_mime_param_write_to_string (params, FALSE, string);
+ g_mime_param_list_encode (content_type->params, FALSE, string);
- p = string->str;
- g_string_free (string, FALSE);
+ str = g_string_free (string, FALSE);
- type = p + strlen ("Content-Type: ");
+ type = str + strlen ("Content-Type: ");
_g_mime_object_block_header_list_changed (object);
g_mime_header_list_set (object->headers, "Content-Type", type);
_g_mime_object_unblock_header_list_changed (object);
- g_free (p);
+ g_free (str);
}
static ssize_t
@@ -388,7 +385,7 @@ write_disposition (GMimeParserOptions *options, GMimeStream *stream, const char
disposition = g_mime_content_disposition_parse (options, value);
g_string_append (out, disposition->disposition);
- g_mime_param_write_to_string (disposition->params, TRUE, out);
+ g_mime_param_list_encode (disposition->params, TRUE, out);
g_object_unref (disposition);
nwritten = g_mime_stream_write (stream, out->str, out->len);
diff --git a/gmime/gmime-param.c b/gmime/gmime-param.c
index c678eec..c0beaa4 100644
--- a/gmime/gmime-param.c
+++ b/gmime/gmime-param.c
@@ -31,6 +31,7 @@
#include "gmime-param.h"
#include "gmime-common.h"
#include "gmime-events.h"
+#include "gmime-internal.h"
#include "gmime-table-private.h"
#include "gmime-parse-utils.h"
#include "gmime-iconv-utils.h"
@@ -64,6 +65,24 @@ static unsigned char tohex[16] = {
};
+static GMimeParam *
+g_mime_param_new_internal (void)
+{
+ GMimeParam *param;
+
+ param = g_slice_new (GMimeParam);
+
+ param->changed = g_mime_event_new (param);
+ param->method = GMIME_PARAM_ENCODING_METHOD_DEFAULT;
+ param->charset = NULL;
+ param->value = NULL;
+ param->name = NULL;
+ param->lang = NULL;
+
+ return param;
+}
+
+
/**
* g_mime_param_new:
* @name: parameter name
@@ -73,20 +92,671 @@ static unsigned char tohex[16] = {
*
* Returns: a new paramter structure.
**/
-GMimeParam *
+static GMimeParam *
g_mime_param_new (const char *name, const char *value)
{
GMimeParam *param;
- param = g_new (GMimeParam, 1);
-
- param->next = NULL;
- param->name = g_strdup (name);
+ param = g_mime_param_new_internal ();
param->value = g_strdup (value);
+ param->name = g_strdup (name);
return param;
}
+
+/**
+ * g_mime_param_free:
+ * @param: a #GMimeParam
+ *
+ * Releases all memory used by this mime param back to the Operating
+ * System.
+ **/
+static void
+g_mime_param_free (GMimeParam *param)
+{
+ g_return_if_fail (param != NULL);
+
+ g_mime_event_free (param->changed);
+ g_free (param->charset);
+ g_free (param->value);
+ g_free (param->name);
+ g_free (param->lang);
+
+ g_slice_free (GMimeParam, param);
+}
+
+
+/**
+ * g_mime_param_get_name:
+ * @param: a #GMimeParam
+ *
+ * Gets the name of the parameter.
+ *
+ * Returns: the name of the parameter.
+ **/
+const char *
+g_mime_param_get_name (GMimeParam *param)
+{
+ g_return_val_if_fail (param != NULL, NULL);
+
+ return param->name;
+}
+
+
+/**
+ * g_mime_param_get_value:
+ * @param: a #GMimeParam
+ *
+ * Gets the value of the parameter.
+ *
+ * Returns: the value of the parameter.
+ **/
+const char *
+g_mime_param_get_value (GMimeParam *param)
+{
+ g_return_val_if_fail (param != NULL, NULL);
+
+ return param->value;
+}
+
+
+/**
+ * g_mime_param_set_value:
+ * @param: a #GMimeParam
+ * @value: the new parameter value
+ *
+ * Sets the parameter value to @value.
+ **/
+void
+g_mime_param_set_value (GMimeParam *param, const char *value)
+{
+ g_return_if_fail (param != NULL);
+ g_return_if_fail (value != NULL);
+
+ g_free (param->value);
+ param->value = g_strdup (value);
+
+ g_mime_event_emit (param->changed, NULL);
+}
+
+
+/**
+ * g_mime_param_get_charset:
+ * @param: a #GMimeParam
+ *
+ * Gets the charset used for encoding the parameter.
+ *
+ * Returns: the charset used for encoding the parameter.
+ **/
+const char *
+g_mime_param_get_charset (GMimeParam *param)
+{
+ g_return_val_if_fail (param != NULL, NULL);
+
+ return param->charset;
+}
+
+
+/**
+ * g_mime_param_set_charset:
+ * @param: a #GMimeParam
+ * @charset: the charset or %NULL to use the default
+ *
+ * Sets the parameter charset used for encoding the value.
+ **/
+void
+g_mime_param_set_charset (GMimeParam *param, const char *charset)
+{
+ g_return_if_fail (param != NULL);
+
+ g_free (param->charset);
+ param->charset = charset ? g_strdup (charset) : NULL;
+
+ g_mime_event_emit (param->changed, NULL);
+}
+
+
+/**
+ * g_mime_param_get_lang:
+ * @param: a #GMimeParam
+ *
+ * Gets the language specifier used for encoding the parameter.
+ *
+ * Returns: the language specifier used for encoding the parameter.
+ **/
+const char *
+g_mime_param_get_lang (GMimeParam *param)
+{
+ g_return_val_if_fail (param != NULL, NULL);
+
+ return param->lang;
+}
+
+
+/**
+ * g_mime_param_set_lang:
+ * @param: a #GMimeParam
+ * @lang: the language specifier
+ *
+ * Sets the parameter language specifier used for encoding the value.
+ **/
+void
+g_mime_param_set_lang (GMimeParam *param, const char *lang)
+{
+ g_return_if_fail (param != NULL);
+
+ g_free (param->lang);
+ param->lang = lang ? g_strdup (lang) : NULL;
+
+ g_mime_event_emit (param->changed, NULL);
+}
+
+
+/**
+ * g_mime_param_get_encoding_method:
+ * @param: a #GMimeParam
+ *
+ * Gets the encoding method used for encoding the parameter.
+ *
+ * Returns: the encoding method used for encoding the parameter.
+ **/
+GMimeParamEncodingMethod
+g_mime_param_get_encoding_method (GMimeParam *param)
+{
+ g_return_val_if_fail (param != NULL, GMIME_PARAM_ENCODING_METHOD_DEFAULT);
+
+ return param->method;
+}
+
+
+/**
+ * g_mime_param_set_encoding_method:
+ * @param: a #GMimeParam
+ * @method: a #GMimeParamEncodingMethod
+ *
+ * Sets the encoding method used for encoding the value.
+ **/
+void
+g_mime_param_set_encoding_method (GMimeParam *param, GMimeParamEncodingMethod method)
+{
+ g_return_if_fail (param != NULL);
+
+ param->method = method;
+
+ g_mime_event_emit (param->changed, NULL);
+}
+
+
+static void
+param_changed (GMimeParam *param, gpointer args, GMimeParamList *list)
+{
+ g_mime_event_emit (list->changed, NULL);
+}
+
+
+/**
+ * g_mime_param_list_new:
+ *
+ * Creates a new Content-Type or Content-Disposition parameter list.
+ *
+ * Returns: a new #GMimeParamList.
+ **/
+GMimeParamList *
+g_mime_param_list_new (void)
+{
+ GMimeParamList *list;
+
+ list = g_slice_new (GMimeParamList);
+ list->changed = g_mime_event_new (list);
+ list->params = g_ptr_array_new ();
+
+ return list;
+}
+
+
+/**
+ * g_mime_param_list_free:
+ * @list: a #GMimeParamList
+ *
+ * Frees the #GMimeParamList.
+ **/
+void
+g_mime_param_list_free (GMimeParamList *list)
+{
+ guint i;
+
+ g_return_if_fail (list != NULL);
+
+ for (i = 0; i < list->params->len; i++)
+ g_mime_param_free (list->params->pdata[i]);
+
+ g_ptr_array_free (list->params, TRUE);
+ g_mime_event_free (list->changed);
+
+ g_slice_free (GMimeParamList, list);
+}
+
+
+/**
+ * g_mime_param_list_length:
+ * @list: a #GMimeParamList
+ *
+ * Gets the length of the list.
+ *
+ * Returns: the number of #GMimeParam items in the list.
+ **/
+int
+g_mime_param_list_length (GMimeParamList *list)
+{
+ g_return_val_if_fail (list != NULL, -1);
+
+ return list->params->len;
+}
+
+
+/**
+ * g_mime_param_list_clear:
+ * @list: a #GMimeParamList
+ *
+ * Clears the list of parameters.
+ **/
+void
+g_mime_param_list_clear (GMimeParamList *list)
+{
+ guint i;
+
+ g_return_if_fail (list != NULL);
+
+ for (i = 0; i < list->params->len; i++)
+ g_mime_param_free (list->params->pdata[i]);
+
+ g_ptr_array_set_size (list->params, 0);
+
+ g_mime_event_emit (list->changed, NULL);
+}
+
+
+/**
+ * g_mime_param_list_add:
+ * @list: a #GMimeParamList
+ * @param: a #GMimeParam
+ *
+ * Adds a #GMimeParam to the #GMimeParamList.
+ *
+ * Returns: the index of the added #GMimeParam.
+ **/
+static void
+g_mime_param_list_add (GMimeParamList *list, GMimeParam *param)
+{
+ g_mime_event_add (param->changed, (GMimeEventCallback) param_changed, list);
+ g_ptr_array_add (list->params, param);
+}
+
+
+/**
+ * g_mime_param_list_set_parameter:
+ * @list: a #GMimeParamList
+ * @name: The name of the parameter
+ * @value: The parameter value
+ *
+ * Sets the specified parameter to @value.
+ **/
+void
+g_mime_param_list_set_parameter (GMimeParamList *list, const char *name, const char *value)
+{
+ GMimeParam *param;
+ guint i;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (value != NULL);
+
+ for (i = 0; i < list->params->len; i++) {
+ param = list->params->pdata[i];
+
+ if (!g_ascii_strcasecmp (param->name, name)) {
+ g_mime_param_set_value (param, value);
+ return;
+ }
+ }
+
+ param = g_mime_param_new (name, value);
+ g_mime_param_list_add (list, param);
+
+ g_mime_event_emit (list->changed, NULL);
+}
+
+
+/**
+ * g_mime_param_list_get_parameter:
+ * @list: list: a #GMimeParamList
+ * @name: the name of the parameter
+ *
+ * Gets the #GMimeParam with the given @name.
+ *
+ * Returns: the requested #GMimeParam.
+ **/
+GMimeParam *
+g_mime_param_list_get_parameter (GMimeParamList *list, const char *name)
+{
+ GMimeParam *param;
+ guint i;
+
+ g_return_val_if_fail (list != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ for (i = 0; i < list->params->len; i++) {
+ param = list->params->pdata[i];
+
+ if (!g_ascii_strcasecmp (param->name, name))
+ return param;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * g_mime_param_list_get_parameter_at:
+ * @list: a #GMimeParamList
+ * @index: the index of the requested parameter
+ *
+ * Gets the #GMimeParam at the specified @index.
+ *
+ * Returns: the #GMimeParam at the specified index.
+ **/
+GMimeParam *
+g_mime_param_list_get_parameter_at (GMimeParamList *list, int index)
+{
+ g_return_val_if_fail (list != NULL, NULL);
+ g_return_val_if_fail (index >= 0, NULL);
+
+ if ((guint) index >= list->params->len)
+ return NULL;
+
+ return list->params->pdata[index];
+}
+
+
+/**
+ * g_mime_param_list_remove:
+ * @list: a #GMimeParamList
+ * @name: the name of the parameter
+ *
+ * Removes a parameter from the #GMimeParamList.
+ *
+ * Returns: %TRUE if the specified parameter was removed or %FALSE otherwise.
+ **/
+gboolean
+g_mime_param_list_remove (GMimeParamList *list, const char *name)
+{
+ GMimeParam *param;
+ guint i;
+
+ g_return_val_if_fail (list != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ for (i = 0; i < list->params->len; i++) {
+ param = list->params->pdata[i];
+
+ if (!g_ascii_strcasecmp (param->name, name)) {
+ g_ptr_array_remove_index (list->params, i);
+ g_mime_param_free (param);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * g_mime_param_list_remove_at:
+ * @list: a #GMimeParamList
+ * @index: index of the param to remove
+ *
+ * Removes a #GMimeParam from the #GMimeParamList at the specified index.
+ *
+ * Returns: %TRUE if a #GMimeParam was removed or %FALSE otherwise.
+ **/
+gboolean
+g_mime_param_list_remove_at (GMimeParamList *list, int index)
+{
+ GMimeParam *param;
+
+ g_return_val_if_fail (list != NULL, FALSE);
+ g_return_val_if_fail (index >= 0, FALSE);
+
+ if ((guint) index >= list->params->len)
+ return FALSE;
+
+ param = list->params->pdata[index];
+ g_ptr_array_remove_index (list->params, index);
+ g_mime_param_free (param);
+
+ return TRUE;
+}
+
+
+/* FIXME: I wrote this in a quick & dirty fasion - it may not be 100% correct */
+static char *
+encode_param (GMimeParam *param, gboolean *encoded)
+{
+ register const unsigned char *inptr = (const unsigned char *) param->value;
+ const unsigned char *start = inptr;
+ const char *charset = NULL;
+ iconv_t cd = (iconv_t) -1;
+ char *outbuf = NULL;
+ unsigned char c;
+ char *outstr;
+ GString *str;
+
+ *encoded = FALSE;
+
+ while (*inptr && ((inptr - start) < GMIME_FOLD_LEN)) {
+ if (*inptr > 127)
+ break;
+ inptr++;
+ }
+
+ if (*inptr == '\0')
+ return g_strdup (param->value);
+
+ if (!param->charset) {
+ if (*inptr > 127)
+ charset = g_mime_charset_best (param->value, strlen (param->value));
+
+ if (!charset)
+ charset = "iso-8859-1";
+ } else {
+ charset = param->charset;
+ }
+
+ if (g_ascii_strcasecmp (charset, "UTF-8") != 0)
+ cd = g_mime_iconv_open (charset, "UTF-8");
+
+ if (cd != (iconv_t) -1) {
+ outbuf = g_mime_iconv_strdup (cd, param->value);
+ g_mime_iconv_close (cd);
+ if (outbuf == NULL) {
+ charset = "UTF-8";
+ inptr = start;
+ } else {
+ inptr = (const unsigned char *) outbuf;
+ }
+ } else {
+ charset = "UTF-8";
+ inptr = start;
+ }
+
+ /* FIXME: use rfc2047 encoding if requested... */
+ str = g_string_new (charset);
+ g_string_append_c (str, '\'');
+ if (param->lang)
+ g_string_append (str, param->lang);
+ g_string_append_c (str, '\'');
+
+ while ((c = *inptr++)) {
+ if (!is_attrchar (c))
+ g_string_append_printf (str, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]);
+ else
+ g_string_append_c (str, c);
+ }
+
+ g_free (outbuf);
+
+ outstr = g_string_free (str, FALSE);
+ *encoded = TRUE;
+
+ return outstr;
+}
+
+static void
+g_string_append_len_quoted (GString *str, const char *text, size_t len)
+{
+ register const char *inptr = text;
+ const char *inend = text + len;
+
+ g_string_append_c (str, '"');
+
+ while (inptr < inend) {
+ if ((*inptr == '"') || *inptr == '\\')
+ g_string_append_c (str, '\\');
+
+ g_string_append_c (str, *inptr);
+
+ inptr++;
+ }
+
+ g_string_append_c (str, '"');
+}
+
+
+/**
+ * g_mime_param_list_encode:
+ * @list: a #GMimeParamList
+ * @fold: %TRUE if the parameter list should be folded; otherwise, %FALSE
+ * @str: the output string buffer
+ *
+ * Encodes the parameter list into @str, folding lines if required.
+ **/
+void
+g_mime_param_list_encode (GMimeParamList *list, gboolean fold, GString *str)
+{
+ guint count, i;
+ int used;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (str != NULL);
+
+ count = list->params->len;
+ used = str->len;
+
+ for (i = 0; i < count; i++) {
+ gboolean encoded = FALSE;
+ int here = str->len;
+ size_t nlen, vlen;
+ GMimeParam *param;
+ int quote = 0;
+ char *value;
+
+ param = (GMimeParam *) list->params->pdata[i];
+
+ if (!param->value)
+ continue;
+
+ if (!(value = encode_param (param, &encoded))) {
+ w(g_warning ("appending parameter %s=%s violates rfc2184",
+ param->name, param->value));
+ value = g_strdup (param->value);
+ }
+
+ if (!encoded) {
+ char *ch;
+
+ for (ch = value; *ch; ch++) {
+ if (!is_attrchar (*ch) || is_lwsp (*ch))
+ quote++;
+ }
+ }
+
+ nlen = strlen (param->name);
+ vlen = strlen (value);
+
+ if (fold && (used + nlen + vlen + quote > GMIME_FOLD_LEN - 2)) {
+ g_string_append (str, ";\n\t");
+ here = str->len;
+ used = 1;
+ } else {
+ g_string_append (str, "; ");
+ here = str->len;
+ used += 2;
+ }
+
+ if (nlen + vlen + quote > GMIME_FOLD_LEN - 2) {
+ /* we need to do special rfc2184 parameter wrapping */
+ size_t maxlen = GMIME_FOLD_LEN - (nlen + 6);
+ char *inptr, *inend;
+ int i = 0;
+
+ inptr = value;
+ inend = value + vlen;
+
+ while (inptr < inend) {
+ char *ptr = inptr + MIN ((size_t) (inend - inptr), maxlen);
+
+ if (encoded && ptr < inend) {
+ /* be careful not to break an encoded char (ie %20) */
+ char *q = ptr;
+ int j = 2;
+
+ for ( ; j > 0 && q > inptr && *q != '%'; j--, q--);
+ if (*q == '%')
+ ptr = q;
+ }
+
+ if (i != 0) {
+ if (fold)
+ g_string_append (str, ";\n\t");
+ else
+ g_string_append (str, "; ");
+
+ here = str->len;
+ used = 1;
+ }
+
+ g_string_append_printf (str, "%s*%d%s=", param->name,
+ i++, encoded ? "*" : "");
+
+ if (encoded || !quote)
+ g_string_append_len (str, inptr, (size_t) (ptr - inptr));
+ else
+ g_string_append_len_quoted (str, inptr, (size_t) (ptr - inptr));
+
+ used += (str->len - here);
+
+ inptr = ptr;
+ }
+ } else {
+ g_string_append_printf (str, "%s%s=", param->name, encoded ? "*" : "");
+
+ if (encoded || !quote)
+ g_string_append_len (str, value, vlen);
+ else
+ g_string_append_len_quoted (str, value, vlen);
+
+ used += (str->len - here);
+ }
+
+ g_free (value);
+ }
+
+ if (fold)
+ g_string_append_c (str, '\n');
+}
+
+
#define INT_OVERFLOW(x,d) (((x) > (INT_MAX / 10)) || ((x) == (INT_MAX / 10) && (d) > (INT_MAX % 10)))
static int
@@ -239,16 +909,16 @@ decode_param_token (const char **in)
}
static gboolean
-decode_rfc2184_param (const char **in, char **paramp, int *part, gboolean *encoded)
+decode_rfc2184_param (const char **in, char **namep, int *part, gboolean *encoded)
{
gboolean is_rfc2184 = FALSE;
const char *inptr = *in;
- char *param;
+ char *name;
*encoded = FALSE;
*part = -1;
- param = decode_param_token (&inptr);
+ name = decode_param_token (&inptr);
skip_cfws (&inptr);
@@ -274,24 +944,23 @@ decode_rfc2184_param (const char **in, char **paramp, int *part, gboolean *encod
}
}
- if (paramp)
- *paramp = param;
+ *namep = name;
- if (param)
+ if (name)
*in = inptr;
return is_rfc2184;
}
static gboolean
-decode_param (GMimeParserOptions *options, const char **in, char **paramp, char **valuep, int *id, gboolean
*encoded)
+decode_param (GMimeParserOptions *options, const char **in, char **namep, char **valuep, int *id, gboolean
*encoded)
{
gboolean is_rfc2184 = FALSE;
const char *inptr = *in;
- char *param, *value = NULL;
+ char *name, *value = NULL;
char *val;
- is_rfc2184 = decode_rfc2184_param (&inptr, ¶m, id, encoded);
+ is_rfc2184 = decode_rfc2184_param (&inptr, &name, id, encoded);
if (*inptr == '=') {
inptr++;
@@ -320,20 +989,20 @@ decode_param (GMimeParserOptions *options, const char **in, char **paramp, char
value = val;
} else {
d(g_warning ("Failed to convert %s param value (\"%s\") to UTF-8: %s",
- param, value, g_strerror (errno)));
+ name, value, g_strerror (errno)));
}
}
}
}
- if (param && value) {
- *paramp = param;
+ if (name && value) {
*valuep = value;
+ *namep = name;
*in = inptr;
return TRUE;
} else {
- g_free (param);
g_free (value);
+ g_free (name);
return FALSE;
}
}
@@ -520,30 +1189,28 @@ rfc2184_param_new (char *name, char *value, int id, gboolean encoded)
g_free (value);
}
- rfc2184->param = g_new (GMimeParam, 1);
- rfc2184->param->next = NULL;
+ rfc2184->param = g_mime_param_new_internal ();
rfc2184->param->name = name;
- rfc2184->param->value = NULL;
return rfc2184;
}
-static GMimeParam *
+static GMimeParamList *
decode_param_list (GMimeParserOptions *options, const char *in)
{
struct _rfc2184_param *rfc2184, *list, *t;
- GMimeParam *param, *params, *tail;
+ char *name, *value, *charset;
struct _rfc2184_part *part;
GHashTable *rfc2184_hash;
const char *inptr = in;
- char *name, *value;
+ GMimeParamList *params;
+ GMimeParam *param;
gboolean encoded;
GString *gvalue;
guint i;
int id;
- params = NULL;
- tail = (GMimeParam *) ¶ms;
+ params = g_mime_param_list_new ();
list = NULL;
t = (struct _rfc2184_param *) &list;
@@ -571,16 +1238,13 @@ decode_param_list (GMimeParserOptions *options, const char *in)
t = rfc2184;
g_hash_table_insert (rfc2184_hash, param->name, rfc2184);
-
- tail->next = param;
- tail = param;
+ g_mime_param_list_add (params, param);
} else {
rfc2184_param_add_part (rfc2184, value, id, encoded);
g_free (name);
}
} else {
- param = g_new (GMimeParam, 1);
- param->next = NULL;
+ param = g_mime_param_new_internal ();
param->name = name;
if (encoded) {
@@ -592,8 +1256,7 @@ decode_param_list (GMimeParserOptions *options, const char *in)
param->value = value;
}
- tail->next = param;
- tail = param;
+ g_mime_param_list_add (params, param);
}
skip_cfws (&inptr);
@@ -619,9 +1282,10 @@ decode_param_list (GMimeParserOptions *options, const char *in)
g_ptr_array_free (rfc2184->parts, TRUE);
param->value = charset_convert (rfc2184->charset, gvalue->str, gvalue->len);
- g_string_free (gvalue, FALSE);
+ param->charset = rfc2184->charset ? g_strdup (rfc2184->charset) : NULL;
+ param->lang = rfc2184->lang;
- g_free (rfc2184->lang);
+ g_string_free (gvalue, FALSE);
g_free (rfc2184);
rfc2184 = t;
}
@@ -631,666 +1295,18 @@ decode_param_list (GMimeParserOptions *options, const char *in)
/**
- * g_mime_param_parse:
+ * g_mime_param_list_parse:
* @options: a #GMimeParserOptions
- * @str: input string
+ * @str: a string to parse
*
- * Parses the input stringinto a parameter list.
+ * Parses the input string into a parameter list.
*
- * Returns: a #GMimeParam linked list based on @text.
+ * Returns: a #GMimeParamList.
**/
-GMimeParam *
-g_mime_param_parse (GMimeParserOptions *options, const char *str)
+GMimeParamList *
+g_mime_param_list_parse (GMimeParserOptions *options, const char *str)
{
g_return_val_if_fail (str != NULL, NULL);
return decode_param_list (options, str);
}
-
-
-/**
- * g_mime_param_free:
- * @param: a #GMimeParam
- *
- * Releases all memory used by this mime param back to the Operating
- * System.
- **/
-void
-g_mime_param_free (GMimeParam *param)
-{
- GMimeParam *next;
-
- while (param) {
- next = param->next;
- g_free (param->name);
- g_free (param->value);
- g_free (param);
- param = next;
- }
-}
-
-
-/**
- * g_mime_param_next:
- * @param: a #GMimeParam node
- *
- * Gets the next #GMimeParam node in the list.
- *
- * Returns: the next #GMimeParam node in the list.
- **/
-const GMimeParam *
-g_mime_param_next (const GMimeParam *param)
-{
- g_return_val_if_fail (param != NULL, NULL);
-
- return param->next;
-}
-
-
-/**
- * g_mime_param_get_name:
- * @param: a #GMimeParam
- *
- * Gets the name of the parameter.
- *
- * Returns: the name of the parameter.
- **/
-const char *
-g_mime_param_get_name (const GMimeParam *param)
-{
- g_return_val_if_fail (param != NULL, NULL);
-
- return param->name;
-}
-
-
-/**
- * g_mime_param_get_value:
- * @param: a #GMimeParam
- *
- * Gets the value of the parameter.
- *
- * Returns: the value of the parameter.
- **/
-const char *
-g_mime_param_get_value (const GMimeParam *param)
-{
- g_return_val_if_fail (param != NULL, NULL);
-
- return param->value;
-}
-
-
-/**
- * g_mime_param_append:
- * @params: param list
- * @name: new param name
- * @value: new param value
- *
- * Appends a new parameter with name @name and value @value to the
- * parameter list @params.
- *
- * Returns: a param list with the new param of name @name and value
- * @value appended to the list of params @params.
- **/
-GMimeParam *
-g_mime_param_append (GMimeParam *params, const char *name, const char *value)
-{
- GMimeParam *param, *p;
-
- g_return_val_if_fail (name != NULL, params);
- g_return_val_if_fail (value != NULL, params);
-
- param = g_mime_param_new (name, value);
- if (params) {
- p = params;
- while (p->next)
- p = p->next;
- p->next = param;
- } else
- params = param;
-
- return params;
-}
-
-
-/**
- * g_mime_param_append_param:
- * @params: param list
- * @param: param to append
- *
- * Appends @param to the param list @params.
- *
- * Returns: a param list with the new param @param appended to the list
- * of params @params.
- **/
-GMimeParam *
-g_mime_param_append_param (GMimeParam *params, GMimeParam *param)
-{
- GMimeParam *p;
-
- g_return_val_if_fail (param != NULL, params);
-
- if (params) {
- p = params;
- while (p->next)
- p = p->next;
- p->next = param;
- } else
- params = param;
-
- return params;
-}
-
-/* FIXME: I wrote this in a quick & dirty fasion - it may not be 100% correct */
-static char *
-encode_param (const char *in, gboolean *encoded)
-{
- register const unsigned char *inptr = (const unsigned char *) in;
- const unsigned char *instart = inptr;
- iconv_t cd = (iconv_t) -1;
- const char *charset = NULL;
- char *outbuf = NULL;
- unsigned char c;
- char *outstr;
- GString *out;
-
- *encoded = FALSE;
-
- while (*inptr && ((inptr - instart) < GMIME_FOLD_LEN)) {
- if (*inptr > 127)
- break;
- inptr++;
- }
-
- if (*inptr == '\0')
- return g_strdup (in);
-
- if (*inptr > 127)
- charset = g_mime_charset_best (in, strlen (in));
-
- if (!charset)
- charset = "iso-8859-1";
-
- if (g_ascii_strcasecmp (charset, "UTF-8") != 0)
- cd = g_mime_iconv_open (charset, "UTF-8");
-
- if (cd != (iconv_t) -1) {
- outbuf = g_mime_iconv_strdup (cd, in);
- g_mime_iconv_close (cd);
- if (outbuf == NULL) {
- charset = "UTF-8";
- inptr = instart;
- } else {
- inptr = (const unsigned char *) outbuf;
- }
- } else {
- charset = "UTF-8";
- inptr = instart;
- }
-
- /* FIXME: set the 'language' as well, assuming we can get that info...? */
- out = g_string_new ("");
- g_string_append_printf (out, "%s''", charset);
-
- while ((c = *inptr++)) {
- if (!is_attrchar (c))
- g_string_append_printf (out, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]);
- else
- g_string_append_c (out, c);
- }
-
- g_free (outbuf);
-
- outstr = out->str;
- g_string_free (out, FALSE);
- *encoded = TRUE;
-
- return outstr;
-}
-
-static void
-g_string_append_len_quoted (GString *out, const char *in, size_t len)
-{
- register const char *inptr;
- const char *inend;
-
- g_string_append_c (out, '"');
-
- inptr = in;
- inend = in + len;
-
- while (inptr < inend) {
- if ((*inptr == '"') || *inptr == '\\')
- g_string_append_c (out, '\\');
-
- g_string_append_c (out, *inptr);
-
- inptr++;
- }
-
- g_string_append_c (out, '"');
-}
-
-static void
-param_list_format (GString *out, const GMimeParam *param, gboolean fold)
-{
- int used = out->len;
-
- while (param) {
- gboolean encoded = FALSE;
- int here = out->len;
- size_t nlen, vlen;
- int quote = 0;
- char *value;
-
- if (!param->value) {
- param = param->next;
- continue;
- }
-
- if (!(value = encode_param (param->value, &encoded))) {
- w(g_warning ("appending parameter %s=%s violates rfc2184",
- param->name, param->value));
- value = g_strdup (param->value);
- }
-
- if (!encoded) {
- char *ch;
-
- for (ch = value; *ch; ch++) {
- if (!is_attrchar (*ch) || is_lwsp (*ch))
- quote++;
- }
- }
-
- nlen = strlen (param->name);
- vlen = strlen (value);
-
- if (fold && (used + nlen + vlen + quote > GMIME_FOLD_LEN - 2)) {
- g_string_append (out, ";\n\t");
- here = out->len;
- used = 1;
- } else {
- g_string_append (out, "; ");
- here = out->len;
- used += 2;
- }
-
- if (nlen + vlen + quote > GMIME_FOLD_LEN - 2) {
- /* we need to do special rfc2184 parameter wrapping */
- size_t maxlen = GMIME_FOLD_LEN - (nlen + 6);
- char *inptr, *inend;
- int i = 0;
-
- inptr = value;
- inend = value + vlen;
-
- while (inptr < inend) {
- char *ptr = inptr + MIN ((size_t) (inend - inptr), maxlen);
-
- if (encoded && ptr < inend) {
- /* be careful not to break an encoded char (ie %20) */
- char *q = ptr;
- int j = 2;
-
- for ( ; j > 0 && q > inptr && *q != '%'; j--, q--);
- if (*q == '%')
- ptr = q;
- }
-
- if (i != 0) {
- if (fold)
- g_string_append (out, ";\n\t");
- else
- g_string_append (out, "; ");
-
- here = out->len;
- used = 1;
- }
-
- g_string_append_printf (out, "%s*%d%s=", param->name,
- i++, encoded ? "*" : "");
-
- if (encoded || !quote)
- g_string_append_len (out, inptr, (size_t) (ptr - inptr));
- else
- g_string_append_len_quoted (out, inptr, (size_t) (ptr - inptr));
-
- used += (out->len - here);
-
- inptr = ptr;
- }
- } else {
- g_string_append_printf (out, "%s%s=", param->name, encoded ? "*" : "");
-
- if (encoded || !quote)
- g_string_append_len (out, value, vlen);
- else
- g_string_append_len_quoted (out, value, vlen);
-
- used += (out->len - here);
- }
-
- g_free (value);
-
- param = param->next;
- }
-
- if (fold)
- g_string_append_c (out, '\n');
-}
-
-
-/**
- * g_mime_param_write_to_string:
- * @param: MIME Param list
- * @fold: specifies whether or not to fold headers
- * @str: output string
- *
- * Assumes the output string contains only the Content-* header and
- * it's immediate value.
- *
- * Writes the params out to the string @string.
- **/
-void
-g_mime_param_write_to_string (const GMimeParam *param, gboolean fold, GString *str)
-{
- g_return_if_fail (str != NULL);
-
- param_list_format (str, param, fold);
-}
-
-
-/**
- * g_mime_param_list_new:
- *
- * Creates a new Content-Type or Content-Disposition parameter list.
- *
- * Returns: a new #GMimeParamList.
- **/
-GMimeParamList *
-g_mime_param_list_new (void)
-{
- GMimeParamList *list;
-
- list = g_slice_new (GMimeParamList);
- list->hash = g_hash_table_new_full (g_mime_strcase_hash, g_mime_strcase_equal, NULL, NULL);
- list->changed = g_mime_event_new (list);
- list->params = g_ptr_array_new ();
-
- return list;
-}
-
-
-/**
- * g_mime_param_list_free:
- * @list: a #GMimeParamList
- *
- * Frees the #GMimeParamList.
- **/
-void
-g_mime_param_list_free (GMimeParamList *list)
-{
- guint i;
-
- g_return_if_fail (list != NULL);
-
- for (i = 0; i < list->params->len; i++)
- g_mime_param_free (list->params->pdata[i]);
-
- g_ptr_array_free (list->params, TRUE);
- g_hash_table_destroy (list->hash);
- g_mime_event_free (list->changed);
-
- g_slice_free (GMimeParamList, list);
-}
-
-
-/**
- * g_mime_param_list_length:
- * @list: a #GMimeParamList
- *
- * Gets the length of the list.
- *
- * Returns: the number of #GMimeParam items in the list.
- **/
-int
-g_mime_param_list_length (GMimeParamList *list)
-{
- g_return_val_if_fail (list != NULL, -1);
-
- return list->params->len;
-}
-
-
-/**
- * g_mime_param_list_clear:
- * @list: a #GMimeParamList
- *
- * Clears the list of parameters.
- **/
-void
-g_mime_param_list_clear (GMimeParamList *list)
-{
- guint i;
-
- g_return_if_fail (list != NULL);
-
- for (i = 0; i < list->params->len; i++)
- g_mime_param_free (list->params->pdata[i]);
-
- g_ptr_array_set_size (list->params, 0);
-}
-
-
-/**
- * g_mime_param_list_add:
- * @list: a #GMimeParamList
- * @param: a #GMimeParam
- *
- * Adds a #GMimeParam to the #GMimeParamList.
- *
- * Returns: the index of the added #GMimeParam.
- **/
-int
-g_mime_param_list_add (GMimeParamList *list, GMimeParam *param)
-{
- int index;
-
- g_return_val_if_fail (param != NULL, -1);
- g_return_val_if_fail (list != NULL, -1);
-
- index = list->params->len;
- g_ptr_array_add (list->params, param);
-
- return index;
-}
-
-
-/**
- * g_mime_param_list_insert:
- * @list: a #GMimeParamList
- * @index: index to insert at
- * @param: a #GMimeParam
- *
- * Inserts a #GMimeParam into the #GMimeParamList at the specified index.
- **/
-void
-g_mime_param_list_insert (GMimeParamList *list, int index, GMimeParam *param)
-{
- char *dest, *src;
- size_t n;
-
- g_return_if_fail (param != NULL);
- g_return_if_fail (list != NULL);
- g_return_if_fail (index >= 0);
-
- if ((guint) index < list->params->len) {
- g_ptr_array_set_size (list->params, list->params->len + 1);
-
- dest = ((char *) list->params->pdata) + (sizeof (void *) * (index + 1));
- src = ((char *) list->params->pdata) + (sizeof (void *) * index);
- n = list->params->len - index - 1;
-
- g_memmove (dest, src, (sizeof (void *) * n));
- list->params->pdata[index] = param;
- } else {
- /* the easy case */
- g_ptr_array_add (list->params, param);
- }
-}
-
-
-/**
- * g_mime_param_list_remove:
- * @list: a #GMimeParamList
- * @param: a #GMimeParam
- *
- * Removes a #GMimeParam from the #GMimeParamList.
- *
- * Returns: %TRUE if the specified #GMimeParam was removed or %FALSE otherwise.
- **/
-gboolean
-g_mime_param_list_remove (GMimeParamList *list, GMimeParam *param)
-{
- int index;
-
- g_return_val_if_fail (param != NULL, FALSE);
- g_return_val_if_fail (list != NULL, FALSE);
-
- if ((index = g_mime_param_list_index_of (list, param)) == -1)
- return FALSE;
-
- return g_mime_param_list_remove_at (list, index);
-}
-
-
-/**
- * g_mime_param_list_remove_at:
- * @list: a #GMimeParamList
- * @index: index of the param to remove
- *
- * Removes a #GMimeParam from the #GMimeParamList at the specified index.
- *
- * Returns: %TRUE if a #GMimeParam was removed or %FALSE otherwise.
- **/
-gboolean
-g_mime_param_list_remove_at (GMimeParamList *list, int index)
-{
- GMimeParam *param;
-
- g_return_val_if_fail (list != NULL, FALSE);
- g_return_val_if_fail (index >= 0, FALSE);
-
- if ((guint) index >= list->params->len)
- return FALSE;
-
- param = list->params->pdata[index];
- g_ptr_array_remove_index (list->params, index);
- g_mime_param_free (param);
-
- return TRUE;
-}
-
-
-/**
- * g_mime_param_list_contains:
- * @list: a #GMimeParamList
- * @param: a #GMimeParam
- *
- * Checks whether or not the specified #GMimeParam is contained within
- * the #GMimeParamList.
- *
- * Returns: %TRUE if the specified #GMimeParam is contained within the
- * specified #GMimeParamList or %FALSE otherwise.
- **/
-gboolean
-g_mime_param_list_contains (GMimeParamList *list, GMimeParam *param)
-{
- return g_mime_param_list_index_of (list, param) != -1;
-}
-
-
-/**
- * g_mime_param_list_index_of:
- * @list: a #GMimeParamList
- * @param: a #GMimeParam
- *
- * Gets the index of the specified #GMimeParam inside the
- * #GMimeParamList.
- *
- * Returns: the index of the requested #GMimeParam within the
- * #GMimeParamList or %-1 if it is not contained within the
- * #GMimeParamList.
- **/
-int
-g_mime_param_list_index_of (GMimeParamList *list, GMimeParam *param)
-{
- guint i;
-
- g_return_val_if_fail (param != NULL, -1);
- g_return_val_if_fail (list != NULL, -1);
-
- for (i = 0; i < list->params->len; i++) {
- if (list->params->pdata[i] == param)
- return i;
- }
-
- return -1;
-}
-
-
-/**
- * g_mime_param_list_get_param:
- * @list: a #GMimeParamList
- * @index: index of #GMimeParam to get
- *
- * Gets the #GMimeParam at the specified index.
- *
- * Returns: the #GMimeParam at the specified index or %NULL if the index is out of range.
- **/
-GMimeParam *
-g_mime_param_list_get_param (GMimeParamList *list, int index)
-{
- g_return_val_if_fail (list != NULL, NULL);
- g_return_val_if_fail (index >= 0, NULL);
-
- if ((guint) index >= list->params->len)
- return NULL;
-
- return list->params->pdata[index];
-}
-
-
-/**
- * g_mime_param_list_set_param:
- * @list: a #GMimeParamList
- * @index: index of #GMimeParam to set
- * @param: a #GMimeParam
- *
- * Sets the #GMimeParam at the specified index to @param.
- **/
-void
-g_mime_param_list_set_param (GMimeParamList *list, int index, GMimeParam *param)
-{
- GMimeParam *old;
-
- g_return_if_fail (param != NULL);
- g_return_if_fail (list != NULL);
- g_return_if_fail (index >= 0);
-
- if ((guint) index > list->params->len)
- return;
-
- if ((guint) index == list->params->len) {
- g_mime_param_list_add (list, param);
- return;
- }
-
- if ((old = list->params->pdata[index]) == param)
- return;
-
- list->params->pdata[index] = param;
- g_mime_param_free (old);
-}
diff --git a/gmime/gmime-param.h b/gmime/gmime-param.h
index cb6f6ce..9e47f09 100644
--- a/gmime/gmime-param.h
+++ b/gmime/gmime-param.h
@@ -32,32 +32,56 @@ typedef struct _GMimeParamList GMimeParamList;
/**
+ * GMimeParamEncodingMethod:
+ * @GMIME_PARAM_ENCODING_METHOD_DEFAULT: Use the default encoding method set on the #GMimeFormatOptions.
+ * @GMIME_PARAM_ENCODING_METHOD_RFC2231: Use the encoding method described in rfc2231.
+ * @GMIME_PARAM_ENCODING_METHOD_RFC2047: Use the encoding method described in rfc2047.
+ *
+ * The MIME specifications specify that the proper method for encoding Content-Type and
+ * Content-Disposition parameter values is the method described in
+ * <a href="https://tools.ietf.org/html/rfc2231">rfc2231</a>. However, it is common for
+ * some older email clients to improperly encode using the method described in
+ * <a href="https://tools.ietf.org/html/rfc2047">rfc2047</a> instead.
+ **/
+typedef enum {
+ GMIME_PARAM_ENCODING_METHOD_DEFAULT = 0,
+ GMIME_PARAM_ENCODING_METHOD_RFC2231 = 1,
+ GMIME_PARAM_ENCODING_METHOD_RFC2047 = 2
+} GMimeParamEncodingMethod;
+
+
+/**
* GMimeParam:
- * @next: Pointer to the next param.
- * @name: Parameter name.
- * @value: Parameter value.
+ * @method: The encoding method used for the parameter value.
+ * @charset: The charset to use when encoding the parameter value.
+ * @lang: the language specifier to use when encoding the value.
+ * @name: The parameter name.
+ * @value: The parameter value.
*
- * A parameter name/value pair as used for some Content header fields.
+ * A parameter name/value pair as used in the Content-Type and Content-Disposition headers.
**/
struct _GMimeParam {
- GMimeParam *next;
- char *name;
- char *value;
+ GMimeParamEncodingMethod method;
+ char *charset, *lang;
+ char *name, *value;
+
+ /* < private > */
+ gpointer changed;
};
-GMimeParam *g_mime_param_new (const char *name, const char *value);
-GMimeParam *g_mime_param_parse (GMimeParserOptions *options, const char *str);
-void g_mime_param_free (GMimeParam *param);
+const char *g_mime_param_get_name (GMimeParam *param);
-const GMimeParam *g_mime_param_next (const GMimeParam *param);
+const char *g_mime_param_get_value (GMimeParam *param);
+void g_mime_param_set_value (GMimeParam *param, const char *value);
-GMimeParam *g_mime_param_append (GMimeParam *params, const char *name, const char *value);
-GMimeParam *g_mime_param_append_param (GMimeParam *params, GMimeParam *param);
+const char *g_mime_param_get_charset (GMimeParam *param);
+void g_mime_param_set_charset (GMimeParam *param, const char *charset);
-const char *g_mime_param_get_name (const GMimeParam *param);
-const char *g_mime_param_get_value (const GMimeParam *param);
+const char *g_mime_param_get_lang (GMimeParam *param);
+void g_mime_param_set_lang (GMimeParam *param, const char *lang);
-void g_mime_param_write_to_string (const GMimeParam *param, gboolean fold, GString *str);
+GMimeParamEncodingMethod g_mime_param_get_encoding_method (GMimeParam *param);
+void g_mime_param_set_encoding_method (GMimeParam *param, GMimeParamEncodingMethod method);
/**
@@ -73,22 +97,21 @@ struct _GMimeParamList {
};
GMimeParamList *g_mime_param_list_new (void);
+GMimeParamList *g_mime_param_list_parse (GMimeParserOptions *options, const char *str);
void g_mime_param_list_free (GMimeParamList *list);
int g_mime_param_list_length (GMimeParamList *list);
void g_mime_param_list_clear (GMimeParamList *list);
-int g_mime_param_list_add (GMimeParamList *list, GMimeParam *param);
-void g_mime_param_list_insert (GMimeParamList *list, int index, GMimeParam *param);
-gboolean g_mime_param_list_remove (GMimeParamList *list, GMimeParam *param);
-gboolean g_mime_param_list_remove_at (GMimeParamList *list, int index);
+void g_mime_param_list_set_parameter (GMimeParamList *list, const char *name, const char *value);
+GMimeParam *g_mime_param_list_get_parameter (GMimeParamList *list, const char *name);
+GMimeParam *g_mime_param_list_get_parameter_at (GMimeParamList *list, int index);
-gboolean g_mime_param_list_contains (GMimeParamList *list, GMimeParam *param);
-int g_mime_param_list_index_of (GMimeParamList *list, GMimeParam *param);
+gboolean g_mime_param_list_remove (GMimeParamList *list, const char *name);
+gboolean g_mime_param_list_remove_at (GMimeParamList *list, int index);
-GMimeParam *g_mime_param_list_get_param (GMimeParamList *list, int index);
-void g_mime_param_list_set_param (GMimeParamList *list, int index, GMimeParam *param);
+void g_mime_param_list_encode (GMimeParamList *list, gboolean fold, GString *str);
G_END_DECLS
diff --git a/tests/test-headers.c b/tests/test-headers.c
index 9ae9f63..7dbb9fb 100644
--- a/tests/test-headers.c
+++ b/tests/test-headers.c
@@ -224,6 +224,7 @@ test_header_sync (void)
InternetAddress *addr, *ia;
GMimeHeaderList *headers;
GMimeContentType *type;
+ GMimeParamList *params;
GMimeMessage *message;
GMimeObject *object;
GMimeHeader *header;
@@ -232,7 +233,7 @@ test_header_sync (void)
part = g_mime_part_new_with_type ("application", "octet-stream");
object = (GMimeObject *) part;
-
+
headers = g_mime_object_get_header_list (object);
testsuite_check ("content-type synchronization");
@@ -267,10 +268,11 @@ test_header_sync (void)
if (strcmp ("text/plain; format=flowed", value) != 0)
throw (exception_new ("content-type header had unexpected value after setting a
param"));
- /* now change the content-type's parameters by setting a param list */
- g_mime_content_type_set_params (type, NULL);
+ /* now change the content-type's parameters by clearing the params */
+ params = g_mime_content_type_get_params (type);
+ g_mime_param_list_clear (params);
if (!(value = g_mime_object_get_header (object, "Content-Type")))
- throw (exception_new ("content-type header was unexpectedly null after setting
params"));
+ throw (exception_new ("content-type header was unexpectedly null after clearing
params"));
if (strcmp ("text/plain", value) != 0)
throw (exception_new ("content-type header had unexpected value after setting
params"));
@@ -313,8 +315,9 @@ test_header_sync (void)
if (strcmp ("inline; filename=hello.txt", value) != 0)
throw (exception_new ("content-disposition header had unexpected value after setting
a param"));
- /* now change the content-disposition's parameters by setting a param list */
- g_mime_content_disposition_set_params (disposition, NULL);
+ /* now change the content-disposition's parameters by clearing the params */
+ params = g_mime_content_disposition_get_params (disposition);
+ g_mime_param_list_clear (params);
if (!(value = g_mime_object_get_header (object, "Content-Disposition")))
throw (exception_new ("content-disposition header was unexpectedly null after setting
params"));
if (strcmp ("inline", value) != 0)
diff --git a/tests/test-mime.c b/tests/test-mime.c
index 4ddbac2..089fe25 100644
--- a/tests/test-mime.c
+++ b/tests/test-mime.c
@@ -526,9 +526,11 @@ test_header_folding (GMimeParserOptions *options)
static struct {
const char *input;
+ const char *charset;
const char *encoded;
} rfc2184[] = {
{ "this is a really really long filename that should force gmime to rfc2184 encode it - yay!.html",
+ "iso-8859-1",
"Content-Disposition: attachment;\n\t"
"filename*0*=iso-8859-1''this%20is%20a%20really%20really%20long%20filename%20;\n\t"
"filename*1*=that%20should%20force%20gmime%20to%20rfc2184%20encode%20it%20-;\n\t"
@@ -538,51 +540,54 @@ static struct {
static void
test_rfc2184 (GMimeParserOptions *options)
{
- GMimeParam param, *params;
+ GMimeParamList *params;
+ GMimeParam *param;
const char *value;
GString *str;
+ int count;
size_t n;
guint i;
- param.next = NULL;
- param.name = "filename";
-
- str = g_string_new ("Content-Disposition: attachment");
- n = str->len;
-
for (i = 0; i < G_N_ELEMENTS (rfc2184); i++) {
- params = NULL;
+ params = g_mime_param_list_new ();
+ g_mime_param_list_set_parameter (params, "filename", rfc2184[i].input);
- param.value = (char *) rfc2184[i].input;
+ str = g_string_new ("Content-Disposition: attachment");
+ n = str->len;
testsuite_check ("rfc2184[%u]", i);
try {
- g_mime_param_write_to_string (¶m, TRUE, str);
+ g_mime_param_list_encode (params, TRUE, str);
if (strcmp (rfc2184[i].encoded, str->str) != 0)
throw (exception_new ("encoded param does not match: %s", str->str));
- if (!(params = g_mime_param_parse (options, str->str + n + 2)))
+ g_mime_param_list_free (params);
+
+ if (!(params = g_mime_param_list_parse (options, str->str + n + 2)))
throw (exception_new ("could not parse encoded param list"));
- if (params->next != NULL)
- throw (exception_new ("parsed more than a single param?"));
+ if ((count = g_mime_param_list_length (params)) != 1)
+ throw (exception_new ("expected only 1 param, but parsed %d", count));
- value = g_mime_param_get_value (params);
- if (strcmp (rfc2184[i].input, value) != 0)
+ if (!(param = g_mime_param_list_get_parameter (params, "filename")))
+ throw (exception_new ("failed to get filename param"));
+
+ if (strcmp (rfc2184[i].input, param->value) != 0)
throw (exception_new ("parsed param value does not match"));
+ if (strcmp (rfc2184[i].charset, param->charset) != 0)
+ throw (exception_new ("parsed charset does not match"));
+
testsuite_check_passed ();
} catch (ex) {
testsuite_check_failed ("rfc2184[%u]: %s", i, ex->message);
} finally;
if (params != NULL)
- g_mime_param_free (params);
+ g_mime_param_list_free (params);
- g_string_truncate (str, n);
+ g_string_free (str, TRUE);
}
-
- g_string_free (str, TRUE);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]