PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - standard - mail.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 115
Code covered: 71.3 % Executed lines: 82
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Author: Rasmus Lerdorf <rasmus@php.net>                              |
      16                 :    +----------------------------------------------------------------------+
      17                 :  */
      18                 : 
      19                 : /* $Id: mail.c 282504 2009-06-21 15:29:16Z iliaa $ */
      20                 : 
      21                 : #include <stdlib.h>
      22                 : #include <ctype.h>
      23                 : #include <stdio.h>
      24                 : #include "php.h"
      25                 : #include "ext/standard/info.h"
      26                 : #include "ext/standard/php_string.h"
      27                 : #include "ext/standard/basic_functions.h"
      28                 : 
      29                 : #if HAVE_SYSEXITS_H
      30                 : #include <sysexits.h>
      31                 : #endif
      32                 : #if HAVE_SYS_SYSEXITS_H
      33                 : #include <sys/sysexits.h>
      34                 : #endif
      35                 : 
      36                 : #if PHP_SIGCHILD
      37                 : #if HAVE_SIGNAL_H
      38                 : #include <signal.h>
      39                 : #endif
      40                 : #endif
      41                 : 
      42                 : #include "php_mail.h"
      43                 : #include "php_ini.h"
      44                 : #include "safe_mode.h"
      45                 : #include "exec.h"
      46                 : 
      47                 : #ifdef PHP_WIN32
      48                 : #include "win32/sendmail.h"
      49                 : #endif
      50                 : 
      51                 : #ifdef NETWARE
      52                 : #define EX_OK           0       /* successful termination */
      53                 : #define EX_TEMPFAIL     75      /* temp failure; user is invited to retry */
      54                 : #endif
      55                 : 
      56                 : #define SKIP_LONG_HEADER_SEP(str, pos)                                                                                                                                  \
      57                 :         if (str[pos] == '\r' && str[pos + 1] == '\n' && (str[pos + 2] == ' ' || str[pos + 2] == '\t')) {        \
      58                 :                 pos += 2;                                                                                                                                                                               \
      59                 :                 while (str[pos + 1] == ' ' || str[pos + 1] == '\t') {                                                                                   \
      60                 :                         pos++;                                                                                                                                                                          \
      61                 :                 }                                                                                                                                                                                               \
      62                 :                 continue;                                                                                                                                                                               \
      63                 :         }                                                                                                                                                                                                       \
      64                 : 
      65                 : #define MAIL_ASCIIZ_CHECK(str, len)                             \
      66                 :         p = str;                                                                        \
      67                 :         e = p + len;                                                            \
      68                 :         while ((p = memchr(p, '\0', (e - p)))) {        \
      69                 :                 *p = ' ';                                                               \
      70                 :         }                                                                                       \
      71                 : 
      72                 : extern long php_getuid(void);
      73                 : 
      74                 : /* {{{ proto int ezmlm_hash(string addr)
      75                 :    Calculate EZMLM list hash value. */
      76                 : PHP_FUNCTION(ezmlm_hash)
      77               7 : {
      78               7 :         char *str = NULL;
      79               7 :         unsigned int h = 5381;
      80                 :         int j, str_len;
      81                 : 
      82               7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
      83               5 :                 return;
      84                 :         }
      85                 : 
      86              42 :         for (j = 0; j < str_len; j++) {
      87              40 :                 h = (h + (h << 5)) ^ (unsigned long) (unsigned char) tolower(str[j]);
      88                 :         }
      89                 : 
      90               2 :         h = (h % 53);
      91                 : 
      92               2 :         RETURN_LONG((int) h);
      93                 : }
      94                 : /* }}} */
      95                 : 
      96                 : /* {{{ proto int mail(string to, string subject, string message [, string additional_headers [, string additional_parameters]])
      97                 :    Send an email message */
      98                 : PHP_FUNCTION(mail)
      99              10 : {
     100              10 :         char *to=NULL, *message=NULL, *headers=NULL;
     101              10 :         char *subject=NULL, *extra_cmd=NULL;
     102              10 :         int to_len, message_len, headers_len = 0;
     103              10 :         int subject_len, extra_cmd_len = 0, i;
     104              10 :         char *force_extra_parameters = INI_STR("mail.force_extra_parameters");
     105                 :         char *to_r, *subject_r;
     106                 :         char *p, *e;
     107                 : 
     108              10 :         if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
     109               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect.  The fifth parameter is disabled in SAFE MODE");
     110               0 :                 RETURN_FALSE;
     111                 :         }
     112                 : 
     113              10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss",        &to, &to_len, &subject, &subject_len, &message, &message_len,
     114                 :                                                                                                                                         &headers, &headers_len, &extra_cmd, &extra_cmd_len) == FAILURE
     115                 :         ) {
     116               2 :                 return;
     117                 :         }
     118                 : 
     119                 :         /* ASCIIZ check */
     120               8 :         MAIL_ASCIIZ_CHECK(to, to_len);
     121               8 :         MAIL_ASCIIZ_CHECK(subject, subject_len);
     122               8 :         MAIL_ASCIIZ_CHECK(message, message_len);
     123               8 :         if (headers) {
     124               2 :                 MAIL_ASCIIZ_CHECK(headers, headers_len);
     125                 :         }
     126               8 :         if (extra_cmd) {
     127               1 :                 MAIL_ASCIIZ_CHECK(extra_cmd, extra_cmd_len);
     128                 :         }
     129                 : 
     130               8 :         if (to_len > 0) {
     131               8 :                 to_r = estrndup(to, to_len);
     132               8 :                 for (; to_len; to_len--) {
     133               8 :                         if (!isspace((unsigned char) to_r[to_len - 1])) {
     134               8 :                                 break;
     135                 :                         }
     136               0 :                         to_r[to_len - 1] = '\0';
     137                 :                 }
     138             136 :                 for (i = 0; to_r[i]; i++) {
     139             128 :                         if (iscntrl((unsigned char) to_r[i])) {
     140                 :                                 /* According to RFC 822, section 3.1.1 long headers may be separated into
     141                 :                                  * parts using CRLF followed at least one linear-white-space character ('\t' or ' ').
     142                 :                                  * To prevent these separators from being replaced with a space, we use the
     143                 :                                  * SKIP_LONG_HEADER_SEP to skip over them. */
     144               0 :                                 SKIP_LONG_HEADER_SEP(to_r, i);
     145               0 :                                 to_r[i] = ' ';
     146                 :                         }
     147                 :                 }
     148                 :         } else {
     149               0 :                 to_r = to;
     150                 :         }
     151                 : 
     152               8 :         if (subject_len > 0) {
     153               8 :                 subject_r = estrndup(subject, subject_len);
     154               8 :                 for (; subject_len; subject_len--) {
     155               8 :                         if (!isspace((unsigned char) subject_r[subject_len - 1])) {
     156               8 :                                 break;
     157                 :                         }
     158               0 :                         subject_r[subject_len - 1] = '\0';
     159                 :                 }
     160             104 :                 for (i = 0; subject_r[i]; i++) {
     161              96 :                         if (iscntrl((unsigned char) subject_r[i])) {
     162               0 :                                 SKIP_LONG_HEADER_SEP(subject_r, i);
     163               0 :                                 subject_r[i] = ' ';
     164                 :                         }
     165                 :                 }
     166                 :         } else {
     167               0 :                 subject_r = subject;
     168                 :         }
     169                 : 
     170               8 :         if (force_extra_parameters) {
     171               1 :                 extra_cmd = php_escape_shell_cmd(force_extra_parameters);
     172               7 :         } else if (extra_cmd) {
     173               1 :                 extra_cmd = php_escape_shell_cmd(extra_cmd);
     174                 :         }
     175                 : 
     176               8 :         if (php_mail(to_r, subject_r, message, headers, extra_cmd TSRMLS_CC)) {
     177               4 :                 RETVAL_TRUE;
     178                 :         } else {
     179               4 :                 RETVAL_FALSE;
     180                 :         }
     181                 : 
     182               8 :         if (extra_cmd) {
     183               2 :                 efree (extra_cmd);
     184                 :         }
     185               8 :         if (to_r != to) {
     186               8 :                 efree(to_r);
     187                 :         }
     188               8 :         if (subject_r != subject) {
     189               8 :                 efree(subject_r);
     190                 :         }
     191                 : }
     192                 : /* }}} */
     193                 : 
     194                 : /* {{{ php_mail
     195                 :  */
     196                 : PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd TSRMLS_DC)
     197              22 : {
     198                 : #if (defined PHP_WIN32 || defined NETWARE)
     199                 :         int tsm_err;
     200                 :         char *tsm_errmsg = NULL;
     201                 : #endif
     202                 :         FILE *sendmail;
     203                 :         int ret;
     204              22 :         char *sendmail_path = INI_STR("sendmail_path");
     205              22 :         char *sendmail_cmd = NULL;
     206              22 :         char *mail_log = INI_STR("mail.log");
     207              22 :         char *hdr = headers;
     208                 : #if PHP_SIGCHILD
     209                 :         void (*sig_handler)() = NULL;
     210                 : #endif
     211                 : 
     212                 : #define MAIL_RET(val) \
     213                 :         if (hdr != headers) {   \
     214                 :                 efree(hdr);     \
     215                 :         }       \
     216                 :         return val;     \
     217                 : 
     218              22 :         if (mail_log) {
     219                 :                 char *tmp;
     220               0 :                 int l = spprintf(&tmp, 0, "mail() on [%s:%d]: To: %s -- Headers: %s\n", zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C), to, hdr ? hdr : "");
     221               0 :                 php_stream *stream = php_stream_open_wrapper(mail_log, "a", IGNORE_URL_WIN | REPORT_ERRORS | STREAM_DISABLE_OPEN_BASEDIR, NULL);
     222                 : 
     223               0 :                 if (hdr) { /* find all \r\n instances and replace them with spaces, so a log line is always one line long */ 
     224               0 :                         char *p = tmp;
     225               0 :                         while ((p = strpbrk(p, "\r\n"))) {
     226               0 :                                 *p = ' ';
     227                 :                         }
     228               0 :                         tmp[l - 1] = '\n';
     229                 :                 }
     230               0 :                 if (stream) {
     231               0 :                         php_stream_write(stream, tmp, l);
     232               0 :                         php_stream_close(stream);
     233                 :                 }
     234               0 :                 efree(tmp);
     235                 :         }
     236              22 :         if (PG(mail_x_header)) {
     237               0 :                 char *tmp = zend_get_executed_filename(TSRMLS_C);
     238                 :                 char *f;
     239                 :                 size_t f_len;
     240                 : 
     241               0 :                 php_basename(tmp, strlen(tmp), NULL, 0,&f, &f_len TSRMLS_CC);
     242                 : 
     243               0 :                 if (headers != NULL) {
     244               0 :                         spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\r\n%s", php_getuid(), f, headers);
     245                 :                 } else {
     246               0 :                         spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\n", php_getuid(), f);
     247                 :                 }
     248               0 :                 efree(f);
     249                 :         }
     250                 : 
     251              22 :         if (!sendmail_path) {
     252                 : #if (defined PHP_WIN32 || defined NETWARE)
     253                 :                 /* handle old style win smtp sending */
     254                 :                 if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, message, NULL, NULL, NULL TSRMLS_CC) == FAILURE) {
     255                 :                         if (tsm_errmsg) {
     256                 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tsm_errmsg);
     257                 :                                 efree(tsm_errmsg);
     258                 :                         } else {
     259                 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", GetSMErrorText(tsm_err));
     260                 :                         }
     261                 :                         MAIL_RET(0);
     262                 :                 }
     263                 :                 MAIL_RET(1);
     264                 : #else
     265               0 :                 MAIL_RET(0);
     266                 : #endif
     267                 :         }
     268              22 :         if (extra_cmd != NULL) {
     269               2 :                 spprintf(&sendmail_cmd, 0, "%s %s", sendmail_path, extra_cmd);
     270                 :         } else {
     271              20 :                 sendmail_cmd = sendmail_path;
     272                 :         }
     273                 : 
     274                 : #if PHP_SIGCHILD
     275                 :         /* Set signal handler of SIGCHLD to default to prevent other signal handlers
     276                 :          * from being called and reaping the return code when our child exits.
     277                 :          * The original handler needs to be restored after pclose() */
     278                 :         sig_handler = (void *)signal(SIGCHLD, SIG_DFL);
     279                 :         if (sig_handler == SIG_ERR) {
     280                 :                 sig_handler = NULL;
     281                 :         }
     282                 : #endif
     283                 : 
     284                 : #ifdef PHP_WIN32
     285                 :         sendmail = popen(sendmail_cmd, "wb");
     286                 : #else
     287                 :         /* Since popen() doesn't indicate if the internal fork() doesn't work
     288                 :          * (e.g. the shell can't be executed) we explicitely set it to 0 to be
     289                 :          * sure we don't catch any older errno value. */
     290              22 :         errno = 0;
     291              22 :         sendmail = popen(sendmail_cmd, "w");
     292                 : #endif
     293              22 :         if (extra_cmd != NULL) {
     294               2 :                 efree (sendmail_cmd);
     295                 :         }
     296                 : 
     297              22 :         if (sendmail) {
     298                 : #ifndef PHP_WIN32
     299              22 :                 if (EACCES == errno) {
     300               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Permission denied: unable to execute shell to run mail delivery binary '%s'", sendmail_path);
     301               0 :                         pclose(sendmail);
     302                 : #if PHP_SIGCHILD
     303                 :                         /* Restore handler in case of error on Windows
     304                 :                            Not sure if this applicable on Win but just in case. */
     305                 :                         if (sig_handler) {
     306                 :                                 signal(SIGCHLD, sig_handler);
     307                 :                         }
     308                 : #endif
     309               0 :                         MAIL_RET(0);
     310                 :                 }
     311                 : #endif
     312              22 :                 fprintf(sendmail, "To: %s\n", to);
     313              22 :                 fprintf(sendmail, "Subject: %s\n", subject);
     314              22 :                 if (hdr != NULL) {
     315              16 :                         fprintf(sendmail, "%s\n", hdr);
     316                 :                 }
     317              22 :                 fprintf(sendmail, "\n%s\n", message);
     318              22 :                 ret = pclose(sendmail);
     319                 : 
     320                 : #if PHP_SIGCHILD
     321                 :                 if (sig_handler) {
     322                 :                         signal(SIGCHLD, sig_handler);
     323                 :                 }
     324                 : #endif
     325                 : 
     326                 : #ifdef PHP_WIN32
     327                 :                 if (ret == -1)
     328                 : #else
     329                 : #if defined(EX_TEMPFAIL)
     330              22 :                 if ((ret != EX_OK)&&(ret != EX_TEMPFAIL))
     331                 : #elif defined(EX_OK)
     332                 :                 if (ret != EX_OK)
     333                 : #else
     334                 :                 if (ret != 0)
     335                 : #endif
     336                 : #endif
     337                 :                 {
     338               4 :                         MAIL_RET(0);
     339                 :                 } else {
     340              18 :                         MAIL_RET(1);
     341                 :                 }
     342                 :         } else {
     343               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute mail delivery program '%s'", sendmail_path);
     344                 : #if PHP_SIGCHILD
     345                 :                 if (sig_handler) {
     346                 :                         signal(SIGCHLD, sig_handler);                                           
     347                 :                 }
     348                 : #endif
     349               0 :                 MAIL_RET(0);
     350                 :         }
     351                 : 
     352                 :         MAIL_RET(1); /* never reached */
     353                 : }
     354                 : /* }}} */
     355                 : 
     356                 : /* {{{ PHP_MINFO_FUNCTION
     357                 :  */
     358                 : PHP_MINFO_FUNCTION(mail)
     359              43 : {
     360              43 :         char *sendmail_path = INI_STR("sendmail_path");
     361                 : 
     362                 : #ifdef PHP_WIN32
     363                 :         if (!sendmail_path) {
     364                 :                 php_info_print_table_row(2, "Internal Sendmail Support for Windows", "enabled");
     365                 :         } else {
     366                 :                 php_info_print_table_row(2, "Path to sendmail", sendmail_path);
     367                 :         }
     368                 : #else
     369              43 :         php_info_print_table_row(2, "Path to sendmail", sendmail_path);
     370                 : #endif
     371              43 : }
     372                 : /* }}} */
     373                 : 
     374                 : /*
     375                 :  * Local variables:
     376                 :  * tab-width: 4
     377                 :  * c-basic-offset: 4
     378                 :  * End:
     379                 :  * vim600: sw=4 ts=4 fdm=marker
     380                 :  * vim<600: sw=4 ts=4
     381                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:10 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.