ID: 14983
Comment by: [EMAIL PROTECTED]
Reported By: [EMAIL PROTECTED]
Status: Feedback
Bug Type: Reproducible crash
Operating System: Windows 2000
PHP Version: 4.1.1
New Comment:

Here is the diff.

-Enrico

--- sendmail-old.c      Mon Sep  4 18:26:16 2000
+++ sendmail.c  Thu Jan 10 20:20:56 2002
@@ -16,6 +16,8 @@
  *  The complete wSendmail package with source code can be located
  *  from http://www.jgaa.com
  *
+
+ modified by Enrico Demarin Jan 2001
  */
 
 #include "php.h"                               /*php specific */
@@ -217,7 +219,7 @@
        if (strchr(mailTo, '@') == NULL)
                return (BAD_MSG_DESTINATION);
 
-       sprintf(Buffer, "HELO %s\r\n", LocalHost);
+       snprintf(Buffer, MAIL_BUFFER_SIZE, "HELO %s\r\n", LocalHost);
 
        /* in the beggining of the dialog */
        /* attempt reconnect if the first Post fail */
@@ -229,7 +231,7 @@
        if ((res = Ack()) != SUCCESS)
                return (res);
 
-       sprintf(Buffer, "MAIL FROM:<%s>\r\n", RPath);
+       snprintf(Buffer, MAIL_BUFFER_SIZE,"MAIL FROM:<%s>\r\n", RPath);
        if ((res = Post(Buffer)) != SUCCESS)
                return (res);
        if ((res = Ack()) != SUCCESS)
@@ -242,7 +244,7 @@
        token = strtok(tempMailTo, ",");
        while(token != NULL)
        {
-               sprintf(Buffer, "RCPT TO:<%s>\r\n", token);
+               snprintf(Buffer, MAIL_BUFFER_SIZE, "RCPT TO:<%s>\r\n", token);
                if ((res = Post(Buffer)) != SUCCESS)
                        return (res);
                if ((res = Ack()) != SUCCESS)
@@ -259,7 +261,7 @@
                token = strtok(tempMailTo, ",");
                while(token != NULL)
                {
-                       sprintf(Buffer, "RCPT TO:<%s>\r\n", token);
+                       snprintf(Buffer, MAIL_BUFFER_SIZE, "RCPT TO:<%s>\r\n", token);
                        if ((res = Post(Buffer)) != SUCCESS)
                                return (res);
                        if ((res = Ack()) != SUCCESS)
@@ -341,14 +343,15 @@
        struct tm *tm = localtime(&tNow);
        int zoneh = abs(_timezone);
        int zonem, res;
+       int i;
+
        char *p;
 
-       p = Buffer;
        zoneh /= (60 * 60);
        zonem = (abs(_timezone) / 60) - (zoneh * 60);
 
        if(!xheaders || !strstr(xheaders, "Date:")){
-               p += sprintf(p, "Date: %s, %02d %s %04d %02d:%02d:%02d
%s%02d%02d\r\n",
+               snprintf(Buffer, MAIL_BUFFER_SIZE, "Date: %s, %02d %s %04d
%02d:%02d:%02d %s%02d%02d\r\n",
                                         days[tm->tm_wday],
                                         tm->tm_mday,
                                         months[tm->tm_mon],
@@ -359,21 +362,56 @@
                                         (_timezone > 0) ? "+" : (_timezone < 0) ? "-" 
: "",
                                         zoneh,
                                         zonem);
+
+                                       if ((res = Post(Buffer)) != SUCCESS)
+                                       return (res);
        }
 
        if(!xheaders || !strstr(xheaders, "From:")){
-               p += sprintf(p, "From: %s\r\n", RPath);
+               snprintf(Buffer, MAIL_BUFFER_SIZE, "From: %s\r\n", RPath);
+               if ((res = Post(Buffer)) != SUCCESS)
+               return (res);
        }
-       p += sprintf(p, "Subject: %s\r\n", Subject);
+
+       snprintf(Buffer, MAIL_BUFFER_SIZE, "Subject: %s\r\n", Subject);
+       if ((res = Post(Buffer)) != SUCCESS)
+       return (res);
+
        if(!xheaders || !strstr(xheaders, "To:")){
-               p += sprintf(p, "To: %s\r\n", mailTo);
+               snprintf(Buffer, MAIL_BUFFER_SIZE, "To: %s\r\n", mailTo);
+               if ((res = Post(Buffer)) != SUCCESS)
+               return (res);
        }
+
        if(xheaders){
-               p += sprintf(p, "%s\r\n", xheaders);
-       }
 
-       if ((res = Post(Buffer)) != SUCCESS)
-               return (res);
+                               /* send extre headers in 1024 chunks */
+                               if (strlen(xheaders) <= 1024) {
+                                               if ((res = Post(xheaders)) != SUCCESS)
+                                               return (res);
+                               } else {
+                                               p = xheaders;
+               
+                                               while (1) {
+                                               if (*p == '\0')
+                                                       break;
+                                               if (strlen(p) >= 1024)
+                                               i = 1024;
+                                                       else
+                                               i = strlen(p);
+
+                                               /* put next chunk in buffer */
+                                               strncpy(Buffer, p, i);
+                                               Buffer[i] = '\0';
+                                               p += i;
+
+                                               /* send chunk */
+                                               if ((res = Post(Buffer)) != SUCCESS)
+                                               return (res);
+                                               }
+                               }
+                               }
+
 
        if ((res = Post("\r\n")) != SUCCESS)
                return (res);


Previous Comments:
------------------------------------------------------------------------

[2002-01-11 11:00:08] [EMAIL PROTECTED]

It would be nice if you post a diff instead of the whole file...

------------------------------------------------------------------------

[2002-01-10 21:07:29] [EMAIL PROTECTED]


this is what i came up with to fix the behaviour. It's a quick fix cause
i needed PHP working for a demo tomorrow, but it appears to fix the
problem.

- Enrico

/* 
 *    PHP Sendmail for Windows.
 *
 *  This file is rewriten specificly for PHPFI.  Some functionality
 *  has been removed (MIME and file attachments).  This code was 
 *  modified from code based on code writen by Jarle Aase.
 *
 *  This class is based on the original code by Jarle Aase, see
bellow:
 *  wSendmail.cpp  It has been striped of some functionality to match
 *  the requirements of phpfi.
 *
 *  Very simple SMTP Send-mail program for sending command-line level
 *  emails and CGI-BIN form response for the Windows platform.
 *
 *  The complete wSendmail package with source code can be located
 *  from http://www.jgaa.com
 *

 modified by Enrico Demarin Jan 2001
 */

#include "php.h"                                /*php specific */
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include "time.h"
#include <string.h>
#include <malloc.h>
#include <memory.h>
#include <winbase.h>
#include "sendmail.h"
#include "php_ini.h"

/*
   extern int _daylight;
   extern long _timezone;
 */
/*enum
   {
   DO_CONNECT = WM_USER +1
   };
 */

static char *days[] =
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static char *months[] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec"};

#ifndef THREAD_SAFE
char Buffer[MAIL_BUFFER_SIZE];

/* socket related data */
SOCKET sc;
WSADATA Data;
struct hostent *adr;
SOCKADDR_IN sock_in;
int WinsockStarted;
/* values set by the constructor */
char *AppName;
char MailHost[HOST_NAME_LEN];
char LocalHost[HOST_NAME_LEN];
#endif
char seps[] = " ,\t\n";
char *php_mailer = "PHP 4.0 WIN32";

char *get_header(char *h, char *headers);

/* Error messages */
static char *ErrorMessages[] =
{
        {"Success"},
        {"Bad arguments from form"},
        {"Unable to open temporary mailfile for read"},
        {"Failed to Start Sockets"},
        {"Failed to Resolve Host"},
        {"Failed to obtain socket handle"},
        {"Failed to Connect"},
        {"Failed to Send"},
        {"Failed to Receive"},
        {"Server Error"},
        {"Failed to resolve the host IP name"},
        {"Out of memory"},
        {"Unknown error"},
        {"Bad Message Contents"},
        {"Bad Message Subject"},
        {"Bad Message destination"},
        {"Bad Message Return Path"},
        {"Bad Mail Host"},
        {"Bad Message File"},
        {"PHP Internal error: php.ini sendmail from variable not set!"}
};



/*********************************************************************
// Name:  TSendMail
// Input:   1) host:    Name of the mail host where the SMTP server
resides
//                      max accepted length of name = 256
//          2) appname: Name of the application to use in the X-mailer
//                      field of the message. if NULL is given the
application
//                      name is used as given by the GetCommandLine()
function
//                      max accespted length of name = 100
// Output:  1) error:   Returns the error code if something went wrong
or
//                      SUCCESS otherwise.
//
//  See SendText() for additional args!
//********************************************************************/
int TSendMail(char *host, int *error,
                          char *headers, char *Subject, char *mailTo, char *data)
{
        int ret;
        char *RPath = NULL;

        WinsockStarted = FALSE;

        if (host == NULL) {
                *error = BAD_MAIL_HOST;
                return BAD_MAIL_HOST;
        } else if (strlen(host) >= HOST_NAME_LEN) {
                *error = BAD_MAIL_HOST;
                return BAD_MAIL_HOST;
        } else {
                strcpy(MailHost, host);
        }

        if (INI_STR("sendmail_from")){
                RPath = estrdup(INI_STR("sendmail_from"));
                } else {
                        return 19;
        }

        /* attempt to connect with mail host */
        *error = MailConnect();
        if (*error != 0) {
                if(RPath)efree(RPath);
                return *error;
        } else {
                ret = SendText(RPath, Subject, mailTo, data, headers);
                TSMClose();
                if (ret != SUCCESS) {
                        *error = ret;
                }
                if(RPath)efree(RPath);
                return ret;
        }
}

//********************************************************************
// Name:  TSendMail::~TSendMail
// Input:
// Output:
// Description: DESTRUCTOR
// Author/Date:  jcar 20/9/96
// History:
//********************************************************************/
void TSMClose()
{
        Post("QUIT\r\n");
        Ack();
        /* to guarantee that the cleanup is not made twice and 
           compomise the rest of the application if sockets are used
           elesewhere 
        */

        shutdown(sc, 0); 
        closesocket(sc);
}


/*********************************************************************
// Name:  char *GetSMErrorText
// Input:   Error index returned by the menber functions
// Output:  pointer to a string containing the error description
// Description:
// Author/Date:  jcar 20/9/96
// History:
//*******************************************************************/
char *GetSMErrorText(int index)
{

        if ((index > MAX_ERROR_INDEX) || (index < MIN_ERROR_INDEX))
                return (ErrorMessages[UNKNOWN_ERROR]);
        else
                return (ErrorMessages[index]);
}


/*********************************************************************
// Name:  TSendText
// Input:       1) RPath:   return path of the message
//                                  Is used to fill the "Return-Path"
and the
//                                  "X-Sender" fields of the message.
//                  2) Subject: Subject field of the message. If NULL is
given
//                                  the subject is set to "No Subject"
//                  3) mailTo:  Destination address
//                  4) data:        Null terminated string containing
the data to be send.
// Output:      Error code or SUCCESS
// Description:
// Author/Date:  jcar 20/9/96
// History:
//*******************************************************************/
int SendText(char *RPath, char *Subject, char *mailTo, char *data, char
*headers)
{
        int res, i;
        char *p;
        char *tempMailTo, *token, *pos1, *pos2;

        /* check for NULL parameters */
        if (data == NULL)
                return (BAD_MSG_CONTENTS);
        if (mailTo == NULL)
                return (BAD_MSG_DESTINATION);
        if (RPath == NULL)
                return (BAD_MSG_RPATH);

        /* simple checks for the mailto address */
        /* have ampersand ? */
        if (strchr(mailTo, '@') == NULL)
                return (BAD_MSG_DESTINATION);

        snprintf(Buffer, MAIL_BUFFER_SIZE, "HELO %s\r\n", LocalHost);

        /* in the beggining of the dialog */
        /* attempt reconnect if the first Post fail */
        if ((res = Post(Buffer)) != SUCCESS) {
                MailConnect();
                if ((res = Post(Buffer)) != SUCCESS)
                        return (res);
        }
        if ((res = Ack()) != SUCCESS)
                return (res);

        snprintf(Buffer, MAIL_BUFFER_SIZE,"MAIL FROM:<%s>\r\n", RPath);
        if ((res = Post(Buffer)) != SUCCESS)
                return (res);
        if ((res = Ack()) != SUCCESS)
                return (res);


        tempMailTo = estrdup(mailTo);
        
        /* Send mail to all rcpt's */
        token = strtok(tempMailTo, ",");
        while(token != NULL)
        {
                snprintf(Buffer, MAIL_BUFFER_SIZE, "RCPT TO:<%s>\r\n", token);
                if ((res = Post(Buffer)) != SUCCESS)
                        return (res);
                if ((res = Ack()) != SUCCESS)
                        return (res);
                token = strtok(NULL, ",");
        }

        /* Send mail to all Cc rcpt's */
        efree(tempMailTo);
        if (headers && (pos1 = strstr(headers, "Cc:"))) {
                pos2 = strstr(pos1, "\r\n");
                tempMailTo = estrndup(pos1, pos2-pos1);

                token = strtok(tempMailTo, ",");
                while(token != NULL)
                {
                        snprintf(Buffer, MAIL_BUFFER_SIZE, "RCPT TO:<%s>\r\n", token);
                        if ((res = Post(Buffer)) != SUCCESS)
                                return (res);
                        if ((res = Ack()) != SUCCESS)
                                return (res);
                        token = strtok(NULL, ",");
                }
                efree(tempMailTo);
        }

        if ((res = Post("DATA\r\n")) != SUCCESS)
                return (res);
        if ((res = Ack()) != SUCCESS)
                return (res);


        /* send message header */
        if (Subject == NULL)
                res = PostHeader(RPath, "No Subject", mailTo, headers);
        else
                res = PostHeader(RPath, Subject, mailTo, headers);
        if (res != SUCCESS)
                return (res);


        /* send message contents in 1024 chunks */
        if (strlen(data) <= 1024) {
                if ((res = Post(data)) != SUCCESS)
                        return (res);
        } else {
                p = data;
                while (1) {
                        if (*p == '\0')
                                break;
                        if (strlen(p) >= 1024)
                                i = 1024;
                        else
                                i = strlen(p);

                        /* put next chunk in buffer */
                        strncpy(Buffer, p, i);
                        Buffer[i] = '\0';
                        p += i;

                        /* send chunk */
                        if ((res = Post(Buffer)) != SUCCESS)
                                return (res);
                }
        }

        /*send termination dot */
        if ((res = Post("\r\n.\r\n")) != SUCCESS)
                return (res);
        if ((res = Ack()) != SUCCESS)
                return (res);

        return (SUCCESS);
}



/*********************************************************************
// Name:  PostHeader
// Input:       1) return path
//                  2) Subject
//                  3) destination address
//                  4) DoMime flag
// Output:      Error code or Success
// Description:
// Author/Date:  jcar 20/9/96
// History:
//********************************************************************/
int PostHeader(char *RPath, char *Subject, char *mailTo, char
*xheaders)
{

        /* Print message header according to RFC 822 */
        /* Return-path, Received, Date, From, Subject, Sender, To, cc */

        time_t tNow = time(NULL);
        struct tm *tm = localtime(&tNow);
        int zoneh = abs(_timezone);
        int zonem, res;
        int i;

        char *p;

        zoneh /= (60 * 60);
        zonem = (abs(_timezone) / 60) - (zoneh * 60);

        if(!xheaders || !strstr(xheaders, "Date:")){
                snprintf(Buffer, MAIL_BUFFER_SIZE, "Date: %s, %02d %s %04d
%02d:%02d:%02d %s%02d%02d\r\n",
                                         days[tm->tm_wday],
                                         tm->tm_mday,
                                         months[tm->tm_mon],
                                         tm->tm_year + 1900,
                                         tm->tm_hour,
                                         tm->tm_min,
                                         tm->tm_sec,
                                         (_timezone > 0) ? "+" : (_timezone < 0) ? "-" 
: "",
                                         zoneh,
                                         zonem);

                                        if ((res = Post(Buffer)) != SUCCESS)
                                        return (res);
        }

        if(!xheaders || !strstr(xheaders, "From:")){
                snprintf(Buffer, MAIL_BUFFER_SIZE, "From: %s\r\n", RPath);
                if ((res = Post(Buffer)) != SUCCESS)
                return (res);
        }

        snprintf(Buffer, MAIL_BUFFER_SIZE, "Subject: %s\r\n", Subject);
        if ((res = Post(Buffer)) != SUCCESS)
        return (res);

        if(!xheaders || !strstr(xheaders, "To:")){
                snprintf(Buffer, MAIL_BUFFER_SIZE, "To: %s\r\n", mailTo);
                if ((res = Post(Buffer)) != SUCCESS)
                return (res);
        }

        if(xheaders){

                                /* send extre headers in 1024 chunks */
                                if (strlen(xheaders) <= 1024) {
                                                if ((res = Post(xheaders)) != SUCCESS)
                                                return (res);
                                } else {
                                                p = xheaders;
                
                                                while (1) {
                                                if (*p == '\0')
                                                        break;
                                                if (strlen(p) >= 1024)
                                                i = 1024;
                                                        else
                                                i = strlen(p);

                                                /* put next chunk in buffer */
                                                strncpy(Buffer, p, i);
                                                Buffer[i] = '\0';
                                                p += i;

                                                /* send chunk */
                                                if ((res = Post(Buffer)) != SUCCESS)
                                                return (res);
                                                }
                                }
                                }


        if ((res = Post("\r\n")) != SUCCESS)
                return (res);

        return (SUCCESS);
}



/*********************************************************************
// Name:  MailConnect
// Input:   None
// Output:  None
// Description: Connect to the mail host and receive the welcome
message.
// Author/Date:  jcar 20/9/96
// History:
//********************************************************************/
int MailConnect()
{

        int res;
        short portnum;

        /* Create Socket */
        if ((sc = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
                return (FAILED_TO_OBTAIN_SOCKET_HANDLE);

        /* Get our own host name */
        if (gethostname(LocalHost, HOST_NAME_LEN))
                return (FAILED_TO_GET_HOSTNAME);

        /* Resolve the servers IP */
        /*
        if (!isdigit(MailHost[0])||!gethostbyname(MailHost))
        {
                return (FAILED_TO_RESOLVE_HOST);
        }
        */

        portnum = (short) INI_INT("sendmail_port");
        if (!portnum) {
                portnum = 25;
        }

        /* Connect to server */
        sock_in.sin_family = AF_INET;
        sock_in.sin_port = htons(portnum);
        sock_in.sin_addr.S_un.S_addr = GetAddr(MailHost);

        if (connect(sc, (LPSOCKADDR) & sock_in, sizeof(sock_in)))
                return (FAILED_TO_CONNECT);

        /* receive Server welcome message */
        res = Ack();
        return (res);
}






/*********************************************************************
// Name:  Post
// Input:
// Output:
// Description:
// Author/Date:  jcar 20/9/96
// History:
//********************************************************************/
int Post(LPCSTR msg)
{
        int len = strlen(msg);
        int slen;
        int index = 0;

        while (len > 0) {
                if ((slen = send(sc, msg + index, len, 0)) < 1)
                        return (FAILED_TO_SEND);
                len -= slen;
                index += slen;
        }
        return (SUCCESS);
}



/*********************************************************************
// Name:  Ack
// Input:
// Output:
// Description:
// Get the response from the server. We only want to know if the
// last command was successful.
// Author/Date:  jcar 20/9/96
// History:
//********************************************************************/
int Ack()
{
        static char *buf;
        int rlen;
        int Index = 0;
        int Received = 0;

        if (!buf)
                if ((buf = (char *) malloc(1024 * 4)) == NULL)
                        return (OUT_OF_MEMORY);

  again:

        if ((rlen = recv(sc, buf + Index, ((1024 * 4) - 1) - Received, 0)) <
1)
                return (FAILED_TO_RECEIVE);

        Received += rlen;
        buf[Received] = 0;
        /*err_msg   fprintf(stderr,"Received: (%d bytes) %s", rlen, buf +
Index); */

        /* Check for newline */
        Index += rlen;
        
        if ((buf[Received - 4] == ' ' && buf[Received - 3] == '-') ||
            (buf[Received - 2] != '\r') || (buf[Received - 1] != '\n'))
                /* err_msg          fprintf(stderr,"Incomplete server message.
Awaiting CRLF\n"); */
                goto again;                             /* Incomplete data. Line must 
be terminated by CRLF
                                           And not contain a space followed by a '-'
*/

        if (buf[0] > '3')
                return (SMTP_SERVER_ERROR);

        return (SUCCESS);
}


/*********************************************************************
// Name:  unsigned long GetAddr (LPSTR szHost)
// Input:
// Output:
// Description: Given a string, it will return an IP address.
//   - first it tries to convert the string directly
//   - if that fails, it tries o resolve it as a hostname
//
// WARNING: gethostbyname() is a blocking function
// Author/Date:  jcar 20/9/96
// History:
//********************************************************************/
unsigned long GetAddr(LPSTR szHost)
{
        LPHOSTENT lpstHost;
        u_long lAddr = INADDR_ANY;

        /* check that we have a string */
        if (*szHost) {

                /* check for a dotted-IP address string */
                lAddr = inet_addr(szHost);

                /* If not an address, then try to resolve it as a hostname */
                if ((lAddr == INADDR_NONE) && (strcmp(szHost, "255.255.255.255"))) {

                        lpstHost = gethostbyname(szHost);
                        if (lpstHost) {         /* success */
                                lAddr = *((u_long FAR *) (lpstHost->h_addr));
                        } else {
                                lAddr = INADDR_ANY;             /* failure */
                        }
                }
        }
        return (lAddr);
}                                                               /* end GetAddr() */


------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/?id=14983


Edit this bug report at http://bugs.php.net/?id=14983&edit=1


-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to