[PHP-DEV] imap_mail_compose(): suggested bugfixes and improvements. Patch included From: Johan Ekenberg (johan <email protected>)
Date: 04/29/01

Hi!

I've been working a lot with the imap_*() functions in PHP lately, and have
discovered a few shortcomings in the imap_mail_compose() function. Attached
is a suggested patch against current CVS (2001-04-29), ext/imap/php_imap.c.
Feel free to comment on this. I'm hoping that, after you've reviewed the
changes, someone can commit it to CVS.

Here is a brief description of the suggested changes:
-----------------------------------------------------

  1) The documentation mentions $part["description"] as a valid body-part
property, but it was not included in the code and was therefore silently
ignored by PHP. It's added in the patch.

  2) Added body-part property: $part["disposition.type"]. I guess the most
obvious use is:

        $part["disposition.type"] = "attachment";

  3) Added body-part property $part["disposition"] which takes an
associative array of attributes and values:

        $part["disposition"]["filename"] = "php.ini";
        $part["disposition"]["foobar"] = "any value";

     renders this header:

        Content-Disposition: filename="php.ini"; foobar="any value"

  4) Added envelope property $envelope["custom_headers"] which takes an
array of additional headers to be added to the envelope header:

        $envelope["custom_headers"][] = "Errors-To: foo <email protected>";
        $envelope["custom_headers"][] = "Importance: Normal";
        $envelope["custom_headers"][] = "X-Mailer: Foobar Mime-Mailer 1.0";

     adds these three custom header lines to the other mail envelope
headers, after the standard rfc822 header lines. The custom headers end up
in reverse order, ie. the "X-Mailer" line above would be added first and
"Errors-To" last. I don't know if this ever matters (?), but if so it
shouldn't be that difficult to fix.

  5) There were a few formatting issues. Missing CRLF (\015\012) in some
cases screwed up placement of MIME-Boundaries and such. The patch attempts
to fix this.

  6) A few "off-by-one" errors were fixed. These did not always cause
errors, but on some occasions they produced segfaults.

Best regards,
/Johan Ekenberg

The patch: (also attached as a separate file)
-----------------------------------------------------

--- php_imap.c.orig Sun Apr 29 23:53:43 2001
+++ php_imap.c Mon Apr 30 00:23:29 2001
@@ -52,7 +52,7 @@
 MAILSTREAM DEFAULTPROTO;
 #endif

-
+#define CRLF "\015\012"
 #define PHP_EXPUNGE 32768

 static void _php_make_header_object(zval *myzvalue, ENVELOPE *en);
@@ -3154,14 +3154,14 @@
 {
         zval **envelope, **body;
         char *key;
- zval **data, **pvalue;
+ zval **data, **pvalue, **disp_data, **env_data;
         ulong ind;
         char *cookie = NIL;
         ENVELOPE *env;
         BODY *bod=NULL, *topbod=NULL;
         PART *mypart=NULL, *toppart=NULL, *part;
- PARAMETER *param;
- char tmp[8*MAILTMPLEN], *mystring=NULL, *t, *tempstring;
+ PARAMETER *param, *disp_param = NULL, *custom_headers_param = NULL,
*tmp_param = NULL;
+ char tmp[8 * MAILTMPLEN], *mystring=NULL, *t=NULL, *tempstring=NULL,
*tempstring_2=NULL;
         int myargc = ZEND_NUM_ARGS();

         if (myargc != 2 || zend_get_parameters_ex(myargc, &envelope, &body) ==
FAILURE) {
@@ -3220,6 +3220,21 @@
                 env->message_id=cpystr(Z_STRVAL_PP(pvalue));
         }

+ if (zend_hash_find(Z_ARRVAL_PP(envelope), "custom_headers",
sizeof("custom_headers"), (void **) &pvalue)== SUCCESS) {
+ if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
+ custom_headers_param = tmp_param = NULL;
+ while(zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **)
&env_data) == SUCCESS) {
+ custom_headers_param = mail_newbody_parameter();
+ convert_to_string_ex(env_data);
+ custom_headers_param->value = (char *) fs_get(Z_STRLEN_PP(env_data) +
1);
+ memcpy(custom_headers_param->value, Z_STRVAL_PP(env_data),
Z_STRLEN_PP(env_data)+1);
+ zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
+ custom_headers_param->next = tmp_param;
+ tmp_param = custom_headers_param;
+ }
+ }
+ }
+
         zend_hash_internal_pointer_reset(Z_ARRVAL_PP(body));
         zend_hash_get_current_data(Z_ARRVAL_PP(body), (void **) &data);
         zend_hash_get_current_key(Z_ARRVAL_PP(body), &key, &ind, 0); /* FIXME: is
this necessary? we're not using key/ind */
@@ -3244,9 +3259,35 @@
                         convert_to_string_ex(pvalue);
                         bod->id = cpystr(Z_STRVAL_PP(pvalue));
                 }
+ if (zend_hash_find(Z_ARRVAL_PP(data), "description",
sizeof("description"), (void **) &pvalue)== SUCCESS) {
+ convert_to_string_ex(pvalue);
+ bod->description = cpystr(Z_STRVAL_PP(pvalue));
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type",
sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) {
+ convert_to_string_ex(pvalue);
+ bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
+ memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue),
Z_STRLEN_PP(pvalue)+1);
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(data), "disposition",
sizeof("disposition"), (void **) &pvalue)== SUCCESS) {
+ if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ while(zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **)
&disp_data) == SUCCESS) {
+ disp_param = mail_newbody_parameter();
+ zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
+ disp_param->attribute = key;
+ convert_to_string_ex(disp_data);
+ disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_PP(disp_data),
Z_STRLEN_PP(disp_data)+1);
+ zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
+ disp_param->next = tmp_param;
+ tmp_param = disp_param;
+ }
+ bod->disposition.parameter = disp_param;
+ }
+ }
                 if (zend_hash_find(Z_ARRVAL_PP(data), "contents.data",
sizeof("contents.data"), (void **) &pvalue)== SUCCESS) {
                         convert_to_string_ex(pvalue);
- bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue));
+ bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
                         memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue),
Z_STRLEN_PP(pvalue)+1);
                         bod->contents.text.size = Z_STRLEN_PP(pvalue);
                 }
@@ -3296,9 +3337,35 @@
                                 convert_to_string_ex(pvalue);
                                 bod->id = cpystr(Z_STRVAL_PP(pvalue));
                         }
+ if (zend_hash_find(Z_ARRVAL_PP(data), "description",
sizeof("description"), (void **) &pvalue)== SUCCESS) {
+ convert_to_string_ex(pvalue);
+ bod->description = cpystr(Z_STRVAL_PP(pvalue));
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type",
sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) {
+ convert_to_string_ex(pvalue);
+ bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
+ memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue),
Z_STRLEN_PP(pvalue)+1);
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(data), "disposition",
sizeof("disposition"), (void **) &pvalue)== SUCCESS) {
+ if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ while(zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **)
&disp_data) == SUCCESS) {
+ disp_param = mail_newbody_parameter();
+ zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
+ disp_param->attribute = key;
+ convert_to_string_ex(disp_data);
+ disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_PP(disp_data),
Z_STRLEN_PP(disp_data)+1);
+ zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
+ disp_param->next = tmp_param;
+ tmp_param = disp_param;
+ }
+ bod->disposition.parameter = disp_param;
+ }
+ }
                         if (zend_hash_find(Z_ARRVAL_PP(data), "contents.data",
sizeof("contents.data"), (void **) &pvalue)== SUCCESS) {
                                 convert_to_string_ex(pvalue);
- bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue));
+ bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
                                 memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue),
Z_STRLEN_PP(pvalue)+1);
                                 bod->contents.text.size = Z_STRLEN_PP(pvalue);
                         }
@@ -3320,9 +3387,32 @@
         }

         rfc822_encode_body_7bit(env, topbod);
- rfc822_header (tmp, env, topbod);
- mystring=emalloc(strlen(tmp)+1);
- strcpy(mystring, tmp);
+ rfc822_header (tmp, env, topbod);
+
+ /* add custom envelope headers */
+ if (custom_headers_param) {
+ /* remove last CRLF from tmp */
+ tmp[strlen(tmp) - 2] = '\0';
+ tempstring = emalloc(strlen(tmp) + 1);
+ strcpy(tempstring, tmp);
+ do {
+ tempstring_2 = emalloc(strlen(tempstring) +
strlen(custom_headers_param->value) + strlen(CRLF) + 1);
+ sprintf(tempstring_2, "%s%s%s", tempstring, custom_headers_param->value,
CRLF);
+ efree(tempstring);
+ tempstring = emalloc(strlen(tempstring_2) + 1);
+ strcpy(tempstring, tempstring_2);
+ efree(tempstring_2);
+ } while ((custom_headers_param = custom_headers_param->next));
+
+ mystring = emalloc(strlen(tempstring) + strlen(CRLF) + 1);
+ strcpy(mystring, tempstring);
+ strcat(mystring, CRLF);
+ efree(tempstring);
+ }
+ else {
+ mystring = emalloc(strlen(tmp) + 1);
+ strcpy(mystring, tmp);
+ }

         bod=topbod;

@@ -3346,13 +3436,13 @@
                 /* for each part */
                         do {
                         /* build cookie */
- sprintf (t=tmp, "--%s\015\012", cookie);
+ sprintf (t=tmp, "--%s%s", cookie, CRLF);

                         /* append mini-header */
                                 rfc822_write_body_header(&t, &part->body);

                         /* write terminating blank line */
- strcat (t, "\015\012");
+ strcat (t, CRLF);

                         /* output cookie, mini-header, and contents */
                                 tempstring=emalloc(strlen(mystring)+strlen(tmp)+1);
@@ -3363,29 +3453,29 @@

                                 bod=&part->body;

- tempstring=emalloc(strlen(bod->contents.text.data)+strlen(mystring)+1);
+
tempstring=emalloc(strlen(bod->contents.text.data)+strlen(CRLF)+strlen(mystr
ing)+1);
                                 strcpy(tempstring,mystring);
                                 efree(mystring);
                                 mystring=tempstring;
- strcat(mystring, bod->contents.text.data);
+ sprintf(mystring, "%s%s%s", mystring, bod->contents.text.data, CRLF);

                         } while ((part = part->next));/* until done */
             /* output trailing cookie */

                         sprintf(tmp, "--%s--", cookie);
- tempstring=emalloc(strlen(tmp)+strlen(mystring)+1);
+ tempstring=emalloc(strlen(tmp)+strlen(CRLF)+strlen(mystring)+1);
                         strcpy(tempstring,mystring);
                         efree(mystring);
                         mystring=tempstring;
- strcat(mystring,tmp);
+ sprintf(mystring, "%s%s%s", mystring, tmp, CRLF);

         } else if(bod) {

- tempstring=emalloc(strlen(bod->contents.text.data)+strlen(mystring)+1);
+
tempstring=emalloc(strlen(bod->contents.text.data)+strlen(CRLF)+strlen(mystr
ing)+1);
                         strcpy(tempstring,mystring);
                         efree(mystring);
                         mystring=tempstring;
- strcat(mystring, bod->contents.text.data);
+ sprintf(mystring, "%s%s%s", mystring, bod->contents.text.data, CRLF);

         } else {
                 efree(mystring);

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: php-dev-unsubscribe <email protected>
For additional commands, e-mail: php-dev-help <email protected>
To contact the list administrators, e-mail: php-list-admin <email protected>