diff options
author | Jeffrey Stedfast <fejj@ximian.com> | 2003-08-12 01:57:45 +0800 |
---|---|---|
committer | Jeffrey Stedfast <fejj@src.gnome.org> | 2003-08-12 01:57:45 +0800 |
commit | b328a21e7c026aaa9cdd5e332ed7e39e0003d8eb (patch) | |
tree | 2c0f3caac1a793197a951958fa7f07cdbf61ac07 /camel/camel-mime-part.c | |
parent | 7b1013be730b11384d0e0af340758bdef3f00330 (diff) | |
download | gsoc2013-evolution-b328a21e7c026aaa9cdd5e332ed7e39e0003d8eb.tar.gz gsoc2013-evolution-b328a21e7c026aaa9cdd5e332ed7e39e0003d8eb.tar.zst gsoc2013-evolution-b328a21e7c026aaa9cdd5e332ed7e39e0003d8eb.zip |
New test suite for the mime parser (which is where the below 2 fixes were
* tests/message/test4.c: New test suite for the mime parser (which
is where the below 2 fixes were noticed).
* camel-mime-parser.c (folder_boundary_check): Calculate 'len' by
subtracting the boundary start from inend rather than 'atleast'.
(folder_scan_content): Calculate 'inend' differently depending on
the EOF state.
2003-08-08 Jeffrey Stedfast <fejj@ximian.com>
* camel-mime-filter-tohtml.c (html_convert): Rather than checking
*inptr == '\n', check inptr >= inend - this gets rid of an Invalid
Read report from valgrind.
* camel-mime-part.c (write_to_stream): Don't necessarily re-encode
just because the encodings differ. Need to look into making it so
that message/rfc822 and multipart parts ignore the
Content-Transfer-Encoding header and just keep their 'encoding'
bits set to DEFAULT.
2003-08-05 Jeffrey Stedfast <fejj@ximian.com>
* providers/imap/camel-imap-folder.c (get_content): Updated.
* camel-mime-message.c (camel_mime_message_init): Don't override
the mime_type here.
(process_header): Updated to use CamelDataWrapper's mime_type
field.
(find_best_encoding): Same.
(best_encoding): Here too.
* camel-digest-folder.c (camel_digest_folder_new): Updated for
CamelMimePart::content_type change.
* camel-mime-part.c (camel_mime_part_init): Override our parent
class's default mime_type.
(camel_mime_part_finalize): Don't need to unref the content_type
anymore.
(process_header): Updated to use CamelDataWrapper's mime_type
field.
(camel_mime_part_set_filename): Same.
(camel_mime_part_get_filename): Same.
(camel_mime_part_get_content_type): Same.
(set_content_object): Here too.
(write_to_stream): Updated.
(construct_from_parser): Updated.
* camel-mime-part.h: Remove the content_type field.
2003-07-31 Jeffrey Stedfast <fejj@ximian.com>
* tests/lib/messages.c (test_message_compare_content): If the
chunks differ, perform a hexdump on the data being compared so
that we may analyse it easier.
* camel-multipart-signed.c (write_to_stream): Return ssize_t.
* camel-mime-utils.h: Added the CamelMimePartEncodingType enum
here.
* camel-mime-part.h: Removed the CamelMimePartEncodingType enum
from here.
* camel-mime-part.c (write_to_stream): Updated to return
ssize_t. Also minor changes to only re-encode the content stream
if the charset or encoding changed (this way we write it out in
the original raw form if nothing changed).
* camel-mime-part-utils.c
(simple_data_wrapper_construct_from_parser): Drastically
simplify. We no longer scan html content to try and find the
charset, nor do we care about converting the content to UTF-8 and
handling broken windows charsets.
* camel-mime-message.c (find_best_encoding): Use
decode_to_stream() here. Also updated to not assume the content
charset is UTF-8 since it is very likely not the case anymore
since data-wrappers no longer are converted to UTF-8 at parse
time.
* camel-folder-summary.c (summary_build_content_info_message): Use
decode_to_stream instead here too.
* camel-folder-search.c (match_words_1message): Use
decode_to_stream instead of write_to_stream so we can search the
contents.
* camel-data-wrapper.c (camel_data_wrapper_init): Set the default
encoding to DEFAULT.
(write_to_stream): Updated to return ssize_t
(camel_data_wrapper_decode_to_stream): New virtual function to
decode a data wrapper to a stream (results in nearly identical
behaviour to the old write_to_stream method).
(decode_to_stream): Default implementation of above virtual
method. Decodes base64/qp/etc streams.
* camel-data-wrapper.h: Removed the rawtext bit and added an
encoding member.
svn path=/trunk/; revision=22171
Diffstat (limited to 'camel/camel-mime-part.c')
-rw-r--r-- | camel/camel-mime-part.c | 244 |
1 files changed, 128 insertions, 116 deletions
diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c index 1c85efb3e4..a31c179d99 100644 --- a/camel/camel-mime-part.c +++ b/camel/camel-mime-part.c @@ -72,10 +72,10 @@ static CamelMediumClass *parent_class=NULL; #define CMD_CLASS(so) CAMEL_MEDIUM_CLASS (CAMEL_OBJECT_GET_CLASS(so)) /* from CamelDataWrapper */ -static ssize_t write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); -static int construct_from_stream (CamelDataWrapper *dw, CamelStream *s); +static ssize_t write_to_stream (CamelDataWrapper *dw, CamelStream *stream); +static int construct_from_stream (CamelDataWrapper *dw, CamelStream *stream); -/* from CamelMedia */ +/* from CamelMedium */ static void add_header (CamelMedium *medium, const char *header_name, const void *header_value); static void set_header (CamelMedium *medium, const char *header_name, const void *header_value); static void remove_header (CamelMedium *medium, const char *header_name); @@ -86,10 +86,10 @@ static void free_headers (CamelMedium *medium, GAr static void set_content_object (CamelMedium *medium, CamelDataWrapper *content); /* from camel mime parser */ -static int construct_from_parser (CamelMimePart *, CamelMimeParser *); +static int construct_from_parser (CamelMimePart *mime_part, CamelMimeParser *mp); /* forward references */ -static void set_disposition (CamelMimePart *mime_part, const gchar *disposition); +static void set_disposition (CamelMimePart *mime_part, const char *disposition); /* format output of headers */ static int write_references(CamelStream *stream, struct _header_raw *h); @@ -144,24 +144,27 @@ camel_mime_part_class_init (CamelMimePartClass *camel_mime_part_class) camel_medium_class->get_headers = get_headers; camel_medium_class->free_headers = free_headers; camel_medium_class->set_content_object = set_content_object; - + camel_data_wrapper_class->write_to_stream = write_to_stream; camel_data_wrapper_class->construct_from_stream= construct_from_stream; } static void -camel_mime_part_init (gpointer object, gpointer klass) +camel_mime_part_init (gpointer object, gpointer klass) { - CamelMimePart *camel_mime_part = CAMEL_MIME_PART (object); + CamelMimePart *mime_part = CAMEL_MIME_PART (object); - camel_mime_part->content_type = header_content_type_new ("text", "plain"); - camel_mime_part->description = NULL; - camel_mime_part->disposition = NULL; - camel_mime_part->content_id = NULL; - camel_mime_part->content_MD5 = NULL; - camel_mime_part->content_location = NULL; - camel_mime_part->content_languages = NULL; - camel_mime_part->encoding = CAMEL_MIME_PART_ENCODING_DEFAULT; + if (((CamelDataWrapper *) mime_part)->mime_type) + header_content_type_unref (((CamelDataWrapper *) mime_part)->mime_type); + ((CamelDataWrapper *) mime_part)->mime_type = header_content_type_new ("text", "plain"); + + mime_part->description = NULL; + mime_part->disposition = NULL; + mime_part->content_id = NULL; + mime_part->content_MD5 = NULL; + mime_part->content_location = NULL; + mime_part->content_languages = NULL; + mime_part->encoding = CAMEL_MIME_PART_ENCODING_DEFAULT; } @@ -177,9 +180,6 @@ camel_mime_part_finalize (CamelObject *object) camel_string_list_free (mime_part->content_languages); header_disposition_unref(mime_part->disposition); - if (mime_part->content_type) - header_content_type_unref (mime_part->content_type); - header_raw_clear(&mime_part->headers); } @@ -188,19 +188,20 @@ camel_mime_part_finalize (CamelObject *object) CamelType camel_mime_part_get_type (void) { - static CamelType camel_mime_part_type = CAMEL_INVALID_TYPE; + static CamelType type = CAMEL_INVALID_TYPE; - if (camel_mime_part_type == CAMEL_INVALID_TYPE) { - camel_mime_part_type = camel_type_register (CAMEL_MEDIUM_TYPE, "CamelMimePart", - sizeof (CamelMimePart), - sizeof (CamelMimePartClass), - (CamelObjectClassInitFunc) camel_mime_part_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_part_init, - (CamelObjectFinalizeFunc) camel_mime_part_finalize); + if (type == CAMEL_INVALID_TYPE) { + type = camel_type_register (CAMEL_MEDIUM_TYPE, + "CamelMimePart", + sizeof (CamelMimePart), + sizeof (CamelMimePartClass), + (CamelObjectClassInitFunc) camel_mime_part_class_init, + NULL, + (CamelObjectInitFunc) camel_mime_part_init, + (CamelObjectFinalizeFunc) camel_mime_part_finalize); } - return camel_mime_part_type; + return type; } @@ -222,8 +223,8 @@ process_header(CamelMedium *medium, const char *header_name, const char *header_ switch (header_type) { case HEADER_DESCRIPTION: /* raw header->utf8 conversion */ g_free (mime_part->description); - if (mime_part->content_type) { - charset = header_content_type_param (mime_part->content_type, "charset"); + if (((CamelDataWrapper *) mime_part)->mime_type) { + charset = header_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "charset"); charset = e_iconv_charset_name (charset); } else charset = NULL; @@ -237,6 +238,7 @@ process_header(CamelMedium *medium, const char *header_name, const char *header_ mime_part->content_id = header_contentid_decode (header_value); break; case HEADER_ENCODING: + /* FIXME: ignore this if we are a multipart or a message/rfc822 part */ text = header_token_decode (header_value); mime_part->encoding = camel_mime_part_encoding_from_string (text); g_free (text); @@ -250,9 +252,9 @@ process_header(CamelMedium *medium, const char *header_name, const char *header_ mime_part->content_location = header_location_decode (header_value); break; case HEADER_CONTENT_TYPE: - if (mime_part->content_type) - header_content_type_unref (mime_part->content_type); - mime_part->content_type = header_content_type_decode (header_value); + if (((CamelDataWrapper *) mime_part)->mime_type) + header_content_type_unref (((CamelDataWrapper *) mime_part)->mime_type); + ((CamelDataWrapper *) mime_part)->mime_type = header_content_type_decode (header_value); break; default: return FALSE; @@ -328,7 +330,7 @@ free_headers (CamelMedium *medium, GArray *gheaders) /* **** Content-Description */ void -camel_mime_part_set_description (CamelMimePart *mime_part, const gchar *description) +camel_mime_part_set_description (CamelMimePart *mime_part, const char *description) { char *text = header_encode_string (description); @@ -337,7 +339,7 @@ camel_mime_part_set_description (CamelMimePart *mime_part, const gchar *descript g_free (text); } -const gchar * +const char * camel_mime_part_get_description (CamelMimePart *mime_part) { return mime_part->description; @@ -346,7 +348,7 @@ camel_mime_part_get_description (CamelMimePart *mime_part) /* **** Content-Disposition */ static void -set_disposition (CamelMimePart *mime_part, const gchar *disposition) +set_disposition (CamelMimePart *mime_part, const char *disposition) { header_disposition_unref(mime_part->disposition); if (disposition) @@ -357,7 +359,7 @@ set_disposition (CamelMimePart *mime_part, const gchar *disposition) void -camel_mime_part_set_disposition (CamelMimePart *mime_part, const gchar *disposition) +camel_mime_part_set_disposition (CamelMimePart *mime_part, const char *disposition) { char *text; @@ -377,7 +379,7 @@ camel_mime_part_set_disposition (CamelMimePart *mime_part, const gchar *disposit g_free(text); } -const gchar * +const char * camel_mime_part_get_disposition (CamelMimePart *mime_part) { if (mime_part->disposition) @@ -390,7 +392,7 @@ camel_mime_part_get_disposition (CamelMimePart *mime_part) /* **** Content-Disposition: filename="xxx" */ void -camel_mime_part_set_filename (CamelMimePart *mime_part, const gchar *filename) +camel_mime_part_set_filename (CamelMimePart *mime_part, const char *filename) { char *str; @@ -404,22 +406,22 @@ camel_mime_part_set_filename (CamelMimePart *mime_part, const gchar *filename) "Content-Disposition", str); g_free(str); - header_content_type_set_param (mime_part->content_type, "name", filename); - str = header_content_type_format (mime_part->content_type); + header_content_type_set_param (((CamelDataWrapper *) mime_part)->mime_type, "name", filename); + str = header_content_type_format (((CamelDataWrapper *) mime_part)->mime_type); camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", str); g_free (str); } -const gchar * +const char * camel_mime_part_get_filename (CamelMimePart *mime_part) { if (mime_part->disposition) { - const gchar *name = header_param (mime_part->disposition->params, "filename"); + const char *name = header_param (mime_part->disposition->params, "filename"); if (name) return name; } - - return header_content_type_param (mime_part->content_type, "name"); + + return header_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "name"); } @@ -441,7 +443,7 @@ camel_mime_part_set_content_id (CamelMimePart *mime_part, const char *contentid) g_free (cid); } -const gchar * +const char * camel_mime_part_get_content_id (CamelMimePart *mime_part) { return mime_part->content_id; @@ -455,7 +457,7 @@ camel_mime_part_set_content_MD5 (CamelMimePart *mime_part, const char *md5) camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-MD5", md5); } -const gchar * +const char * camel_mime_part_get_content_MD5 (CamelMimePart *mime_part) { return mime_part->content_MD5; @@ -469,7 +471,7 @@ camel_mime_part_set_content_location (CamelMimePart *mime_part, const char *loca camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Location", location); } -const gchar * +const char * camel_mime_part_get_content_location (CamelMimePart *mime_part) { return mime_part->content_location; @@ -519,7 +521,7 @@ camel_mime_part_get_content_languages (CamelMimePart *mime_part) /* **** Content-Type: */ void -camel_mime_part_set_content_type (CamelMimePart *mime_part, const gchar *content_type) +camel_mime_part_set_content_type (CamelMimePart *mime_part, const char *content_type) { camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", content_type); @@ -528,39 +530,36 @@ camel_mime_part_set_content_type (CamelMimePart *mime_part, const gchar *content CamelContentType * camel_mime_part_get_content_type (CamelMimePart *mime_part) { - return mime_part->content_type; + return ((CamelDataWrapper *) mime_part)->mime_type; } -/*********/ - - static void set_content_object (CamelMedium *medium, CamelDataWrapper *content) { - CamelMimePart *mime_part = CAMEL_MIME_PART (medium); - CamelContentType *object_content_type; - + CamelDataWrapper *mime_part = CAMEL_DATA_WRAPPER (medium); + CamelContentType *content_type; + parent_class->set_content_object (medium, content); - - object_content_type = camel_data_wrapper_get_mime_type_field (content); - if (mime_part->content_type != object_content_type) { + + content_type = camel_data_wrapper_get_mime_type_field (content); + if (mime_part->mime_type != content_type) { char *txt; - - txt = header_content_type_format (object_content_type); + + txt = header_content_type_format (content_type); camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", txt); - g_free(txt); + g_free (txt); } } /**********************************************************************/ -static int +static ssize_t write_references(CamelStream *stream, struct _header_raw *h) { - int len, out, total; + ssize_t len, out, total; char *v, *ids, *ide; - + /* this is only approximate, based on the next >, this way it retains any content from the original which may not be properly formatted, etc. It also doesn't handle the case where an individual messageid is too long, however thats a bad mail to @@ -599,7 +598,7 @@ write_references(CamelStream *stream, struct _header_raw *h) #if 0 /* not needed - yet - handled by default case */ -static int +static ssize_t write_fold(CamelStream *stream, struct _header_raw *h) { char *val; @@ -613,7 +612,7 @@ write_fold(CamelStream *stream, struct _header_raw *h) } #endif -static int +static ssize_t write_raw(CamelStream *stream, struct _header_raw *h) { char *val = h->value; @@ -622,10 +621,10 @@ write_raw(CamelStream *stream, struct _header_raw *h) } static ssize_t -write_to_stream(CamelDataWrapper *data_wrapper, CamelStream *stream) +write_to_stream (CamelDataWrapper *dw, CamelStream *stream) { - CamelMimePart *mp = CAMEL_MIME_PART(data_wrapper); - CamelMedium *medium = CAMEL_MEDIUM(data_wrapper); + CamelMimePart *mp = CAMEL_MIME_PART (dw); + CamelMedium *medium = CAMEL_MEDIUM (dw); CamelStream *ostream = stream; CamelDataWrapper *content; ssize_t total = 0; @@ -639,7 +638,7 @@ write_to_stream(CamelDataWrapper *data_wrapper, CamelStream *stream) if (mp->headers) { struct _header_raw *h = mp->headers; char *val; - int (*writefn)(CamelStream *stream, struct _header_raw *); + ssize_t (*writefn)(CamelStream *stream, struct _header_raw *); /* fold/write the headers. But dont fold headers that are already formatted (e.g. ones with parameter-lists, that we know about, and have created) */ @@ -669,80 +668,92 @@ write_to_stream(CamelDataWrapper *data_wrapper, CamelStream *stream) content = camel_medium_get_content_object(medium); if (content) { - /* I dont really like this here, but i dont know where else it might go ... */ -#define CAN_THIS_GO_ELSEWHERE -#ifdef CAN_THIS_GO_ELSEWHERE CamelMimeFilter *filter = NULL; CamelStreamFilter *filter_stream = NULL; CamelMimeFilter *charenc = NULL; + const char *content_charset = NULL; + const char *part_charset = NULL; + gboolean reencode = FALSE; const char *filename; - const char *charset; - switch (mp->encoding) { - case CAMEL_MIME_PART_ENCODING_BASE64: - filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_ENC); - break; - case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE: - filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_ENC); - break; - case CAMEL_MIME_PART_ENCODING_UUENCODE: - filename = camel_mime_part_get_filename (mp); - count = camel_stream_printf (ostream, "begin 644 %s\n", filename ? filename : "untitled"); - if (count == -1) - return -1; - total += count; - filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_UU_ENC); - break; - default: - break; + if (header_content_type_is (dw->mime_type, "text", "*")) { + content_charset = header_content_type_param (content->mime_type, "charset"); + part_charset = header_content_type_param (dw->mime_type, "charset"); + + if (content_charset && part_charset) { + content_charset = e_iconv_charset_name (content_charset); + part_charset = e_iconv_charset_name (part_charset); + } } - if (!content->rawtext && header_content_type_is(mp->content_type, "text", "*")) { - charset = header_content_type_param(mp->content_type, "charset"); - if (charset && !(!strcasecmp(charset, "us-ascii") || !strcasecmp(charset, "utf-8"))) { - charenc = (CamelMimeFilter *)camel_mime_filter_charset_new_convert("UTF-8", charset); - } + if (mp->encoding != content->encoding) { + switch (mp->encoding) { + case CAMEL_MIME_PART_ENCODING_BASE64: + filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_BASE64_ENC); + break; + case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE: + filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_QP_ENC); + break; + case CAMEL_MIME_PART_ENCODING_UUENCODE: + filename = camel_mime_part_get_filename (mp); + count = camel_stream_printf (ostream, "begin 644 %s\n", filename ? filename : "untitled"); + if (count == -1) + return -1; + total += count; + filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_UU_ENC); + break; + default: + break; + } } + if (content_charset && part_charset && part_charset != content_charset) + charenc = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (content_charset, part_charset); + if (filter || charenc) { filter_stream = camel_stream_filter_new_with_stream(stream); /* if we have a character encoder, add that always */ if (charenc) { camel_stream_filter_add(filter_stream, charenc); - camel_object_unref((CamelObject *)charenc); + camel_object_unref (charenc); } /* we only re-do crlf on encoded blocks */ - if (filter && header_content_type_is(mp->content_type, "text", "*")) { + if (filter && header_content_type_is (dw->mime_type, "text", "*")) { CamelMimeFilter *crlf = camel_mime_filter_crlf_new(CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); camel_stream_filter_add(filter_stream, crlf); - camel_object_unref((CamelObject *)crlf); + camel_object_unref (crlf); } if (filter) { camel_stream_filter_add(filter_stream, filter); - camel_object_unref((CamelObject *)filter); + camel_object_unref (filter); } stream = (CamelStream *)filter_stream; + + reencode = TRUE; } - -#endif - count = camel_data_wrapper_write_to_stream(content, stream); + if (reencode) + count = camel_data_wrapper_decode_to_stream (content, stream); + else + count = camel_data_wrapper_write_to_stream (content, stream); if (filter_stream) { - camel_stream_flush((CamelStream *)filter_stream); - camel_object_unref((CamelObject *)filter_stream); + camel_stream_flush (stream); + camel_object_unref (filter_stream); } + if (count == -1) return -1; + total += count; - if (mp->encoding == CAMEL_MIME_PART_ENCODING_UUENCODE) { + if (reencode && mp->encoding == CAMEL_MIME_PART_ENCODING_UUENCODE) { count = camel_stream_write (ostream, "end\n", 4); if (count == -1) return -1; @@ -757,22 +768,23 @@ write_to_stream(CamelDataWrapper *data_wrapper, CamelStream *stream) /* mime_part */ static int -construct_from_parser(CamelMimePart *dw, CamelMimeParser *mp) +construct_from_parser (CamelMimePart *mime_part, CamelMimeParser *mp) { + CamelDataWrapper *dw = (CamelDataWrapper *) mime_part; struct _header_raw *headers; const char *content; char *buf; size_t len; int err; - + d(printf("mime_part::construct_from_parser()\n")); - + switch (camel_mime_parser_step(mp, &buf, &len)) { case HSCAN_MESSAGE: /* set the default type of a message always */ - if (dw->content_type) - header_content_type_unref (dw->content_type); - dw->content_type = header_content_type_decode ("message/rfc822"); + if (dw->mime_type) + header_content_type_unref (dw->mime_type); + dw->mime_type = header_content_type_decode ("message/rfc822"); case HSCAN_HEADER: case HSCAN_MULTIPART: /* we have the headers, build them into 'us' */ @@ -792,7 +804,7 @@ construct_from_parser(CamelMimePart *dw, CamelMimeParser *mp) headers = headers->next; } - camel_mime_part_construct_content_from_parser(dw, mp); + camel_mime_part_construct_content_from_parser (mime_part, mp); break; default: g_warning("Invalid state encountered???: %d", camel_mime_parser_state(mp)); @@ -864,7 +876,7 @@ camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding) /* FIXME I am not sure this is the correct way to do this. */ CamelMimePartEncodingType -camel_mime_part_encoding_from_string (const gchar *string) +camel_mime_part_encoding_from_string (const char *string) { int i; |