void syslog(int priority, const char *message, ...) { va_list args; LPTSTR strs[2]; unsigned short etype; char *tmp = NULL; DWORD evid; /* default event source */ if (INVALID_HANDLE_VALUE == PW32G(log_source)) openlog("php", LOG_PID, LOG_SYSLOG); switch (priority) { /* translate UNIX type into NT type */ case LOG_ALERT: etype = EVENTLOG_ERROR_TYPE; evid = PHP_SYSLOG_ERROR_TYPE; break; case LOG_INFO: etype = EVENTLOG_INFORMATION_TYPE; evid = PHP_SYSLOG_INFO_TYPE; break; default: etype = EVENTLOG_WARNING_TYPE; evid = PHP_SYSLOG_WARNING_TYPE; } va_start(args, message); /* initialize vararg mechanism */ vspprintf(&tmp, 0, message, args); /* build message */ strs[0] = PW32G(log_header); /* write header */ strs[1] = tmp; /* then the message */ /* report the event */ ReportEvent(PW32G(log_source), etype, (unsigned short) priority, evid, NULL, 2, 0, strs, NULL); va_end(args); efree(tmp); }
void openlog(const char *ident, int logopt, int facility) { closelog(); PW32G(log_source) = RegisterEventSource(NULL, "PHP-" PHP_VERSION); spprintf(&PW32G(log_header), 0, (logopt & LOG_PID) ? "%s[%d]" : "%s", ident, getpid()); }
/* 128 is safe here, the specifier in snprintf isn't longer than that */ *error_message = ecalloc(1, HOST_NAME_LEN + 128); snprintf(*error_message, HOST_NAME_LEN + 128, "Failed to connect to mailserver at \"%s\" port %d, verify your \"SMTP\" " "and \"smtp_port\" setting in php.ini or use ini_set()", PW32G(mail_host), !INI_INT("smtp_port") ? 25 : INI_INT("smtp_port")); return FAILURE; } else { ret = SendText(RPath, Subject, mailTo, mailCc, mailBcc, data, headers ? ZSTR_VAL(headers_trim) : NULL, headers ? ZSTR_VAL(headers_lc) : NULL, error_message); TSMClose(); if (RPath) { efree(RPath); } if (headers) { zend_string_free(headers_trim); zend_string_free(headers_lc); } if (ret != SUCCESS) { *error = ret; return FAILURE; } return SUCCESS; } } //******************************************************************** // Name: TSendMail::~TSendMail // Input: // Output: // Description: DESTRUCTOR // Author/Date: jcar 20/9/96 // History: //********************************************************************/ PHPAPI void TSMClose() { Post("QUIT\r\n"); Ack(NULL); /* to guarantee that the cleanup is not made twice and compomise the rest of the application if sockets are used elesewhere */ shutdown(PW32G(mail_socket), 0); closesocket(PW32G(mail_socket)); }
/********************************************************************* // 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: //********************************************************************/ static int Ack(char **server_response) { ZEND_TLS char buf[MAIL_BUFFER_SIZE]; int rlen; int Index = 0; int Received = 0; #if SENDMAIL_DEBUG return (SUCCESS); #endif again: if ((rlen = recv(PW32G(mail_socket), buf + Index, ((MAIL_BUFFER_SIZE) - 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; /* SMPT RFC says \r\n is the only valid line ending, who are we to argue ;) * The response code must contain at least 5 characters ex. 220\r\n */ if (Received < 5 || buf[Received - 1] != '\n' || buf[Received - 2] != '\r') { goto again; } if (buf[0] > '3') { /* If we've a valid pointer, return the SMTP server response so the error message contains more information */ if (server_response) { int dec = 0; /* See if we have something like \r, \n, \r\n or \n\r at the end of the message and chop it off */ if (Received > 2) { if (buf[Received-1] == '\n' || buf[Received-1] == '\r') { dec++; if (buf[Received-2] == '\r' || buf[Received-2] == '\n') { dec++; } } } *server_response = estrndup(buf, Received - dec); } return (SMTP_SERVER_ERROR); } return (SUCCESS); }
void closelog(void) { if (INVALID_HANDLE_VALUE != PW32G(log_source)) { DeregisterEventSource(PW32G(log_source)); PW32G(log_source) = INVALID_HANDLE_VALUE; } if (PW32G(log_header)) { efree(PW32G(log_header)); PW32G(log_header) = NULL; } }
/********************************************************************* // Name: Post // Input: // Output: // Description: // Author/Date: jcar 20/9/96 // History: //********************************************************************/ static int Post(LPCSTR msg) { int len = (int)strlen(msg); int slen; int index = 0; #if SENDMAIL_DEBUG if (msg) printf("POST: '%s'\n", msg); return (SUCCESS); #endif while (len > 0) { if ((slen = send(PW32G(mail_socket), msg + index, len, 0)) < 1) return (FAILED_TO_SEND); len -= slen; index += slen; } 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: //********************************************************************/ static int MailConnect() { int res, namelen; short portnum; struct hostent *ent; IN_ADDR addr; #ifdef HAVE_IPV6 IN6_ADDR addr6; #endif SOCKADDR_IN sock_in; #if SENDMAIL_DEBUG return 0; #endif /* Create Socket */ if ((PW32G(mail_socket) = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return (FAILED_TO_OBTAIN_SOCKET_HANDLE); } /* Get our own host name */ if (gethostname(PW32G(mail_local_host), HOST_NAME_LEN)) { closesocket(PW32G(mail_socket)); return (FAILED_TO_GET_HOSTNAME); } ent = gethostbyname(PW32G(mail_local_host)); if (!ent) { closesocket(PW32G(mail_socket)); return (FAILED_TO_GET_HOSTNAME); } namelen = (int)strlen(ent->h_name); #ifdef HAVE_IPV6 if (inet_pton(AF_INET, ent->h_name, &addr) == 1 || inet_pton(AF_INET6, ent->h_name, &addr6) == 1) #else if (inet_pton(AF_INET, ent->h_name, &addr) == 1) #endif { if (namelen + 2 >= HOST_NAME_LEN) { closesocket(PW32G(mail_socket)); return (FAILED_TO_GET_HOSTNAME); } strcpy(PW32G(mail_local_host), "["); strcpy(PW32G(mail_local_host) + 1, ent->h_name); strcpy(PW32G(mail_local_host) + namelen + 1, "]"); } else { if (namelen >= HOST_NAME_LEN) { closesocket(PW32G(mail_socket)); return (FAILED_TO_GET_HOSTNAME); } strcpy(PW32G(mail_local_host), ent->h_name); } /* Resolve the servers IP */ /* if (!isdigit(PW32G(mail_host)[0])||!gethostbyname(PW32G(mail_host))) { return (FAILED_TO_RESOLVE_HOST); } */ portnum = (short) INI_INT("smtp_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(PW32G(mail_host)); if (connect(PW32G(mail_socket), (LPSOCKADDR) & sock_in, sizeof(sock_in))) { closesocket(PW32G(mail_socket)); return (FAILED_TO_CONNECT); } /* receive Server welcome message */ res = Ack(NULL); return (res); }
/********************************************************************* // Name: SendText // 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. // 5,6) headers of the message. Note that the second // parameter, headers_lc, is actually a lowercased version of // headers. The should match exactly (in terms of length), // only differ in case // Output: Error code or SUCCESS // Description: // Author/Date: jcar 20/9/96 // History: //*******************************************************************/ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char *mailBcc, char *data, char *headers, char *headers_lc, char **error_message) { int res; char *p; char *tempMailTo, *token, *pos1, *pos2; char *server_response = NULL; char *stripped_header = NULL; zend_string *data_cln; /* 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 ? */ /* mfischer, 20020514: I commented this out because it really seems bogus. Only a username for example may still be a valid address at the destination system. if (strchr(mailTo, '@') == NULL) return (BAD_MSG_DESTINATION); */ snprintf(PW32G(mail_buffer), sizeof(PW32G(mail_buffer)), "HELO %s\r\n", PW32G(mail_local_host)); /* in the beginning of the dialog */ /* attempt reconnect if the first Post fail */ if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { int err = MailConnect(); if (0 != err) { return (FAILED_TO_SEND); } if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { return (res); } } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); return (res); } SMTP_SKIP_SPACE(RPath); FormatEmailAddress(PW32G(mail_buffer), RPath, "MAIL FROM:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); return W32_SM_SENDMAIL_FROM_MALFORMED; } tempMailTo = estrdup(mailTo); /* Send mail to all rcpt's */ token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); if (mailCc && *mailCc) { tempMailTo = estrdup(mailCc); /* Send mail to all rcpt's */ token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); } /* Send mail to all Cc rcpt's */ else if (headers && (pos1 = strstr(headers_lc, "cc:")) && ((pos1 == headers_lc) || (*(pos1-1) == '\n'))) { /* Real offset is memaddress from the original headers + difference of * string found in the lowercase headrs + 3 characters to jump over * the cc: */ pos1 = headers + (pos1 - headers_lc) + 3; if (NULL == (pos2 = strstr(pos1, "\r\n"))) { tempMailTo = estrndup(pos1, strlen(pos1)); } else { tempMailTo = estrndup(pos1, pos2 - pos1); } token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); } /* Send mail to all Bcc rcpt's This is basically a rip of the Cc code above. Just don't forget to remove the Bcc: from the header afterwards. */ if (mailBcc && *mailBcc) { tempMailTo = estrdup(mailBcc); /* Send mail to all rcpt's */ token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); } else if (headers) { if ((pos1 = strstr(headers_lc, "bcc:")) && (pos1 == headers_lc || *(pos1-1) == '\n')) { /* Real offset is memaddress from the original headers + difference of * string found in the lowercase headrs + 4 characters to jump over * the bcc: */ pos1 = headers + (pos1 - headers_lc) + 4; if (NULL == (pos2 = strstr(pos1, "\r\n"))) { tempMailTo = estrndup(pos1, strlen(pos1)); /* Later, when we remove the Bcc: out of the header we know it was the last thing. */ pos2 = pos1; } else { tempMailTo = estrndup(pos1, pos2 - pos1); } token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); /* Now that we've identified that we've a Bcc list, remove it from the current header. */ stripped_header = ecalloc(1, strlen(headers)); /* headers = point to string start of header pos1 = pointer IN headers where the Bcc starts '4' = Length of the characters 'bcc:' Because we've added +4 above for parsing the Emails we've to subtract them here. */ memcpy(stripped_header, headers, pos1 - headers - 4); if (pos1 != pos2) { /* if pos1 != pos2 , pos2 points to the rest of the headers. Since pos1 != pos2 if "\r\n" was found, we know those characters are there and so we jump over them (else we would generate a new header which would look like "\r\n\r\n". */ memcpy(stripped_header + (pos1 - headers - 4), pos2 + 2, strlen(pos2) - 2); } } } /* Simplify the code that we create a copy of stripped_header no matter if we actually strip something or not. So we've a single efree() later. */ if (headers && !stripped_header) { stripped_header = estrndup(headers, strlen(headers)); } if ((res = Post("DATA\r\n")) != SUCCESS) { if (stripped_header) { efree(stripped_header); } return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); if (stripped_header) { efree(stripped_header); } return (res); } /* send message header */ if (Subject == NULL) { res = PostHeader(RPath, "No Subject", mailTo, stripped_header); } else { res = PostHeader(RPath, Subject, mailTo, stripped_header); } if (stripped_header) { efree(stripped_header); } if (res != SUCCESS) { return (res); } /* Escape \n. sequences * We use php_str_to_str() and not php_str_replace_in_subject(), since the latter * uses ZVAL as it's parameters */ data_cln = php_str_to_str(data, strlen(data), PHP_WIN32_MAIL_DOT_PATTERN, sizeof(PHP_WIN32_MAIL_DOT_PATTERN) - 1, PHP_WIN32_MAIL_DOT_REPLACE, sizeof(PHP_WIN32_MAIL_DOT_REPLACE) - 1); if (!data_cln) { data_cln = ZSTR_EMPTY_ALLOC(); } /* send message contents in 1024 chunks */ { char c, *e2, *e = ZSTR_VAL(data_cln) + ZSTR_LEN(data_cln); p = ZSTR_VAL(data_cln); while (e - p > 1024) { e2 = p + 1024; c = *e2; *e2 = '\0'; if ((res = Post(p)) != SUCCESS) { zend_string_free(data_cln); return(res); } *e2 = c; p = e2; } if ((res = Post(p)) != SUCCESS) { zend_string_free(data_cln); return(res); } } zend_string_free(data_cln); /*send termination dot */ if ((res = Post("\r\n.\r\n")) != SUCCESS) return (res); if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); return (res); } return (SUCCESS); }
/********************************************************************* // 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! //********************************************************************/ PHPAPI int TSendMail(char *host, int *error, char **error_message, char *headers, char *Subject, char *mailTo, char *data, char *mailCc, char *mailBcc, char *mailRPath) { int ret; char *RPath = NULL; zend_string *headers_lc = NULL, *headers_trim = NULL; /* headers_lc is only created if we've a header at all */ char *pos1 = NULL, *pos2 = NULL; if (host == NULL) { *error = BAD_MAIL_HOST; return FAILURE; } else if (strlen(host) >= HOST_NAME_LEN) { *error = BAD_MAIL_HOST; return FAILURE; } else { strcpy(PW32G(mail_host), host); } if (headers) { char *pos = NULL; /* Use PCRE to trim the header into the right format */ if (NULL == (headers_trim = php_win32_mail_trim_header(headers))) { *error = W32_SM_PCRE_ERROR; return FAILURE; } /* Create a lowercased header for all the searches so we're finally case * insensitive when searching for a pattern. */ headers_lc = zend_string_tolower(headers_trim); } /* Fall back to sendmail_from php.ini setting */ if (mailRPath && *mailRPath) { RPath = estrdup(mailRPath); } else if (INI_STR("sendmail_from")) { RPath = estrdup(INI_STR("sendmail_from")); } else if (headers_lc) { int found = 0; char *lookup = ZSTR_VAL(headers_lc); while (lookup) { pos1 = strstr(lookup, "from:"); if (!pos1) { break; } else if (pos1 != ZSTR_VAL(headers_lc) && *(pos1-1) != '\n') { if (strlen(pos1) >= sizeof("from:")) { lookup = pos1 + sizeof("from:"); continue; } else { break; } } found = 1; /* Real offset is memaddress from the original headers + difference of * string found in the lowercase headrs + 5 characters to jump over * the from: */ pos1 = headers + (pos1 - lookup) + 5; if (NULL == (pos2 = strstr(pos1, "\r\n"))) { RPath = estrndup(pos1, strlen(pos1)); } else { RPath = estrndup(pos1, pos2 - pos1); } break; } if (!found) { if (headers_lc) { zend_string_free(headers_lc); } *error = W32_SM_SENDMAIL_FROM_NOT_SET; return FAILURE; } } /* attempt to connect with mail host */ *error = MailConnect(); if (*error != 0) { if (RPath) { efree(RPath); } if (headers) { zend_string_free(headers_trim); zend_string_free(headers_lc); } /* 128 is safe here, the specifier in snprintf isn't longer than that */ *error_message = ecalloc(1, HOST_NAME_LEN + 128); snprintf(*error_message, HOST_NAME_LEN + 128, "Failed to connect to mailserver at \"%s\" port %d, verify your \"SMTP\" " "and \"smtp_port\" setting in php.ini or use ini_set()", PW32G(mail_host), !INI_INT("smtp_port") ? 25 : INI_INT("smtp_port")); return FAILURE; } else { ret = SendText(RPath, Subject, mailTo, mailCc, mailBcc, data, headers ? ZSTR_VAL(headers_trim) : NULL, headers ? ZSTR_VAL(headers_lc) : NULL, error_message); TSMClose(); if (RPath) { efree(RPath); } if (headers) { zend_string_free(headers_trim); zend_string_free(headers_lc); } if (ret != SUCCESS) { *error = ret; return FAILURE; } return SUCCESS; } }
PHPAPI int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) { __int64 timer; LARGE_INTEGER li; BOOL b; double dt; TSRMLS_FETCH(); /* Get the time, if they want it */ if (time_Info != NULL) { if (PW32G(starttime).tv_sec == 0) { b = QueryPerformanceFrequency(&li); if (!b) { PW32G(starttime).tv_sec = -1; } else { PW32G(freq) = li.QuadPart; b = QueryPerformanceCounter(&li); if (!b) { PW32G(starttime).tv_sec = -1; } else { getfilesystemtime(&PW32G(starttime)); timer = li.QuadPart; dt = (double)timer/PW32G(freq); PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); if (PW32G(starttime).tv_usec < 0) { PW32G(starttime).tv_usec += 1000000; --PW32G(starttime).tv_sec; } PW32G(starttime).tv_sec -= (int)dt; } } } if (PW32G(starttime).tv_sec > 0) { b = QueryPerformanceCounter(&li); if (!b) { PW32G(starttime).tv_sec = -1; } else { timer = li.QuadPart; if (timer < PW32G(lasttime)) { getfilesystemtime(time_Info); dt = (double)timer/PW32G(freq); PW32G(starttime) = *time_Info; PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); if (PW32G(starttime).tv_usec < 0) { PW32G(starttime).tv_usec += 1000000; --PW32G(starttime).tv_sec; } PW32G(starttime).tv_sec -= (int)dt; } else { PW32G(lasttime) = timer; dt = (double)timer/PW32G(freq); time_Info->tv_sec = PW32G(starttime).tv_sec + (int)dt; time_Info->tv_usec = PW32G(starttime).tv_usec + (int)((dt-(int)dt)*1000000); if (time_Info->tv_usec > 1000000) { time_Info->tv_usec -= 1000000; ++time_Info->tv_sec; } } } } if (PW32G(starttime).tv_sec < 0) { getfilesystemtime(time_Info); } } /* Get the timezone, if they want it */ if (timezone_Info != NULL) { _tzset(); timezone_Info->tz_minuteswest = _timezone; timezone_Info->tz_dsttime = _daylight; } /* And return */ return 0; }