/* {{{ PHPAPI char *php_std_date(time_t t TSRMLS_DC) Return date string in standard format for http headers */ PHPAPI char *php_std_date(time_t t TSRMLS_DC) { struct tm *tm1, tmbuf; char *str; tm1 = php_gmtime_r(&t, &tmbuf); str = emalloc(81); str[0] = '\0'; if (!tm1) { return str; } if (PG(y2k_compliance)) { snprintf(str, 80, "%s, %02d %s %04d %02d:%02d:%02d GMT", day_short_names[tm1->tm_wday], tm1->tm_mday, mon_short_names[tm1->tm_mon], tm1->tm_year + 1900, tm1->tm_hour, tm1->tm_min, tm1->tm_sec); } else { snprintf(str, 80, "%s, %02d-%s-%02d %02d:%02d:%02d GMT", day_full_names[tm1->tm_wday], tm1->tm_mday, mon_short_names[tm1->tm_mon], ((tm1->tm_year) % 100), tm1->tm_hour, tm1->tm_min, tm1->tm_sec); } str[79] = 0; return (str); }
/* {{{ char *http_date(time_t) */ PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC) { char *date = NULL; struct tm *gmtime, tmbuf; if ((gmtime = php_gmtime_r(&t, &tmbuf))) { spprintf(&date, 0, "%s, %02d %s %04d %02d:%02d:%02d GMT", days[gmtime->tm_wday], gmtime->tm_mday, months[gmtime->tm_mon], gmtime->tm_year + 1900, gmtime->tm_hour, gmtime->tm_min, gmtime->tm_sec ); } return date; }
/* {{{ ftp_mdtm */ time_t ftp_mdtm(ftpbuf_t *ftp, const char *path) { time_t stamp; struct tm *gmt, tmbuf; struct tm tm; char *ptr; int n; if (ftp == NULL) { return -1; } if (!ftp_putcmd(ftp, "MDTM", path)) { return -1; } if (!ftp_getresp(ftp) || ftp->resp != 213) { return -1; } /* parse out the timestamp */ for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++); n = sscanf(ptr, "%4u%2u%2u%2u%2u%2u", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); if (n != 6) { return -1; } tm.tm_year -= 1900; tm.tm_mon--; tm.tm_isdst = -1; /* figure out the GMT offset */ stamp = time(NULL); gmt = php_gmtime_r(&stamp, &tmbuf); if (!gmt) { return -1; } gmt->tm_isdst = -1; /* apply the GMT offset */ tm.tm_sec += stamp - mktime(gmt); tm.tm_isdst = gmt->tm_isdst; stamp = mktime(&tm); return stamp; }
/* {{{ PHPAPI char *php_std_date(time_t t) Return date string in standard format for http headers */ PHPAPI char *php_std_date(time_t t) { struct tm *tm1, tmbuf; char *str; tm1 = php_gmtime_r(&t, &tmbuf); str = emalloc(81); str[0] = '\0'; if (!tm1) { return str; } snprintf(str, 80, "%s, %02d %s %04d %02d:%02d:%02d GMT", day_short_names[tm1->tm_wday], tm1->tm_mday, mon_short_names[tm1->tm_mon], tm1->tm_year + 1900, tm1->tm_hour, tm1->tm_min, tm1->tm_sec); str[79] = 0; return (str); }
/* time_t parse_date(char *) Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <*****@*****.**>, et al. */ static inline time_t parse_date(const char *date) { time_t t = 0; int tz_offset = -1, year = -1, month = -1, monthday = -1, weekday = -1, hours = -1, minutes = -1, seconds = -1; struct tm tm; enum assume_next dignext = DATE_MDAY; const char *indate = date; int part = 0; /* max 6 parts */ while (*date && (part < 6)) { int found = 0; while (*date && !HTTP_IS_CTYPE(alnum, *date)) { date++; } if (HTTP_IS_CTYPE(alpha, *date)) { /* a name coming up */ char buf[32] = ""; size_t len; sscanf(date, "%31[A-Za-z]", buf); len = strlen(buf); if (weekday == -1) { weekday = check_day(buf, len); if (weekday != -1) { found = 1; } } if (!found && (month == -1)) { month = check_month(buf); if (month != -1) { found = 1; } } if (!found && (tz_offset == -1)) { /* this just must be a time zone string */ tz_offset = check_tzone(buf); if (tz_offset != -1) { found = 1; } } if (!found) { return -1; /* bad string */ } date += len; } else if (HTTP_IS_CTYPE(digit, *date)) { /* a digit */ int val; char *end; if ((seconds == -1) && (3 == sscanf(date, "%02d:%02d:%02d", &hours, &minutes, &seconds))) { /* time stamp! */ date += 8; found = 1; } else { val = (int) strtol(date, &end, 10); if ((tz_offset == -1) && ((end - date) == 4) && (val < 1300) && (indate < date) && ((date[-1] == '+' || date[-1] == '-'))) { /* four digits and a value less than 1300 and it is preceeded with a plus or minus. This is a time zone indication. */ found = 1; tz_offset = (val / 100 * 60 + val % 100) * 60; /* the + and - prefix indicates the local time compared to GMT, this we need ther reversed math to get what we want */ tz_offset = date[-1] == '+' ? -tz_offset : tz_offset; } if (((end - date) == 8) && (year == -1) && (month == -1) && (monthday == -1)) { /* 8 digits, no year, month or day yet. This is YYYYMMDD */ found = 1; year = val / 10000; month = (val % 10000) / 100 - 1; /* month is 0 - 11 */ monthday = val % 100; } if (!found && (dignext == DATE_MDAY) && (monthday == -1)) { if ((val > 0) && (val < 32)) { monthday = val; found = 1; } dignext = DATE_YEAR; } if (!found && (dignext == DATE_YEAR) && (year == -1)) { year = val; found = 1; if (year < 1900) { year += year > 70 ? 1900 : 2000; } if(monthday == -1) { dignext = DATE_MDAY; } } if (!found) { return -1; } date = end; } } part++; } if (-1 == seconds) { seconds = minutes = hours = 0; /* no time, make it zero */ } if ((-1 == monthday) || (-1 == month) || (-1 == year)) { /* lacks vital info, fail */ return -1; } if (sizeof(time_t) < 5) { /* 32 bit time_t can only hold dates to the beginning of 2038 */ if (year > 2037) { return 0x7fffffff; } } tm.tm_sec = seconds; tm.tm_min = minutes; tm.tm_hour = hours; tm.tm_mday = monthday; tm.tm_mon = month; tm.tm_year = year - 1900; tm.tm_wday = 0; tm.tm_yday = 0; tm.tm_isdst = 0; t = mktime(&tm); /* time zone adjust */ if (t != -1) { struct tm *gmt, keeptime2; long delta; time_t t2; if((gmt = php_gmtime_r(&t, &keeptime2))) { tm = *gmt; /* MSVC quirks */ } else { return -1; /* illegal date/time */ } t2 = mktime(&tm); /* Add the time zone diff (between the given timezone and GMT) and the diff between the local time zone and GMT. */ delta = (tz_offset != -1 ? tz_offset : 0) + (t - t2); if((delta > 0) && (t + delta < t)) { return -1; /* time_t overflow */ } t += delta; } return t; }
PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...) { int s, r, i=0, fd; long written, towrite; int getcaller=0; char *wbuf; struct timeval tv; time_t now; struct tm tm; #if defined(AF_UNIX) struct sockaddr_un saun; #endif #ifdef PHP_WIN32 LPTSTR strs[2]; unsigned short etype; DWORD evid; #endif char buf[5000]; char error[5000]; char *ip_address; char *fname; char *alertstring; int lineno; va_list ap; TSRMLS_FETCH(); #if PHP_VERSION_ID >= 50500 getcaller = (loglevel & S_GETCALLER) == S_GETCALLER; #endif /* remove the S_GETCALLER flag */ loglevel = loglevel & ~S_GETCALLER; SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script)); /* dump core if wanted */ if (SUHOSIN_G(coredump) && loglevel == S_MEMORY) { volatile unsigned int *x = 0; volatile int y = *x; } if (SUHOSIN_G(log_use_x_forwarded_for)) { ip_address = suhosin_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC); if (ip_address == NULL) { ip_address = "X-FORWARDED-FOR not set"; } } else { ip_address = suhosin_getenv("REMOTE_ADDR", 11 TSRMLS_CC); if (ip_address == NULL) { ip_address = "REMOTE_ADDR not set"; } } va_start(ap, fmt); ap_php_vsnprintf(error, sizeof(error), fmt, ap); va_end(ap); while (error[i]) { if (error[i] < 32) error[i] = '.'; i++; } if (SUHOSIN_G(simulation)) { alertstring = "ALERT-SIMULATION"; } else { alertstring = "ALERT"; } if (zend_is_executing(TSRMLS_C)) { zend_execute_data *exdata = EG(current_execute_data); if (exdata) { if (getcaller && exdata->prev_execute_data) { lineno = exdata->prev_execute_data->opline->lineno; fname = (char *)exdata->prev_execute_data->op_array->filename; } else { lineno = exdata->opline->lineno; fname = (char *)exdata->op_array->filename; } } else { lineno = zend_get_executed_lineno(TSRMLS_C); fname = (char *)zend_get_executed_filename(TSRMLS_C); } ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno); } else { fname = suhosin_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC); if (fname==NULL) { fname = "unknown"; } ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname); } /* Syslog-Logging disabled? */ if (((SUHOSIN_G(log_syslog)|S_INTERNAL) & loglevel)==0) { goto log_file; } #if defined(AF_UNIX) ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SUHOSIN_G(log_syslog_facility)|SUHOSIN_G(log_syslog_priority)),getpid(),buf); s = socket(AF_UNIX, SOCK_DGRAM, 0); if (s == -1) { goto log_file; } memset(&saun, 0, sizeof(saun)); saun.sun_family = AF_UNIX; strcpy(saun.sun_path, SYSLOG_PATH); /*saun.sun_len = sizeof(saun);*/ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); if (r) { close(s); s = socket(AF_UNIX, SOCK_STREAM, 0); if (s == -1) { goto log_file; } memset(&saun, 0, sizeof(saun)); saun.sun_family = AF_UNIX; strcpy(saun.sun_path, SYSLOG_PATH); /*saun.sun_len = sizeof(saun);*/ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); if (r) { close(s); goto log_file; } } send(s, error, strlen(error), 0); close(s); #endif #ifdef PHP_WIN32 ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf); switch (SUHOSIN_G(log_syslog_priority)) { /* translate UNIX type into NT type */ case 1: /*LOG_ALERT:*/ etype = EVENTLOG_ERROR_TYPE; break; case 6: /*LOG_INFO:*/ etype = EVENTLOG_INFORMATION_TYPE; break; default: etype = EVENTLOG_WARNING_TYPE; } evid = loglevel; strs[0] = error; /* report the event */ if (log_source == NULL) { log_source = RegisterEventSource(NULL, "Suhosin-" SUHOSIN_EXT_VERSION); } ReportEvent(log_source, etype, (unsigned short) SUHOSIN_G(log_syslog_priority), evid, NULL, 1, 0, strs, NULL); #endif log_file: /* File-Logging disabled? */ if ((SUHOSIN_G(log_file) & loglevel)==0) { goto log_sapi; } if (!SUHOSIN_G(log_filename) || !SUHOSIN_G(log_filename)[0]) { goto log_sapi; } fd = open(SUHOSIN_G(log_filename), O_CREAT|O_APPEND|O_WRONLY, 0640); if (fd == -1) { suhosin_log(S_INTERNAL, "Unable to open logfile: %s", SUHOSIN_G(log_filename)); return; } gettimeofday(&tv, NULL); now = tv.tv_sec; php_gmtime_r(&now, &tm); ap_php_snprintf(error, sizeof(error), "%s %2d %02d:%02d:%02d [%u] %s\n", month_names[tm.tm_mon], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, getpid(),buf); towrite = strlen(error); wbuf = error; php_flock(fd, LOCK_EX); while (towrite > 0) { written = write(fd, wbuf, towrite); if (written < 0) { break; } towrite -= written; wbuf += written; } php_flock(fd, LOCK_UN); close(fd); log_sapi: /* SAPI Logging activated? */ SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script), SUHOSIN_G(log_phpscript)); if (((SUHOSIN_G(log_sapi)|S_INTERNAL) & loglevel)!=0) { #if PHP_VERSION_ID < 50400 sapi_module.log_message(buf); #else sapi_module.log_message(buf TSRMLS_CC); #endif } if ((SUHOSIN_G(log_stdout) & loglevel)!=0) { printf("%s\n", buf); } /*log_script:*/ /* script logging activaed? */ if (((SUHOSIN_G(log_script) & loglevel)!=0) && SUHOSIN_G(log_scriptname)!=NULL) { char cmd[8192], *cmdpos, *bufpos; FILE *in; int space; struct stat st; char *sname = SUHOSIN_G(log_scriptname); while (isspace(*sname)) ++sname; if (*sname == 0) goto log_phpscript; if (VCWD_STAT(sname, &st) < 0) { suhosin_log(S_INTERNAL, "unable to find logging shell script %s - file dropped", sname); goto log_phpscript; } if (access(sname, X_OK|R_OK) < 0) { suhosin_log(S_INTERNAL, "logging shell script %s is not executable - file dropped", sname); goto log_phpscript; } /* TODO: clean up this code to calculate size of output dynamically */ ap_php_snprintf(cmd, sizeof(cmd) - 20, "%s %s \'", sname, loglevel2string(loglevel)); space = sizeof(cmd) - strlen(cmd) - 20; cmdpos = cmd + strlen(cmd); bufpos = buf; if (space <= 1) return; while (space > 2 && *bufpos) { if (*bufpos == '\'') { if (space<=5) break; *cmdpos++ = '\''; *cmdpos++ = '\\'; *cmdpos++ = '\''; *cmdpos++ = '\''; bufpos++; space-=4; } else { *cmdpos++ = *bufpos++; space--; } } *cmdpos++ = '\''; *cmdpos++ = ' '; *cmdpos++ = '2'; *cmdpos++ = '>'; *cmdpos++ = '&'; *cmdpos++ = '1'; *cmdpos = 0; if ((in=VCWD_POPEN(cmd, "r"))==NULL) { suhosin_log(S_INTERNAL, "Unable to execute logging shell script: %s", sname); goto log_phpscript; } /* read and forget the result */ while (1) { int readbytes = fread(cmd, 1, sizeof(cmd), in); if (readbytes<=0) { break; } if (strncmp(cmd, "sh: ", 4) == 0) { /* assume this is an error */ suhosin_log(S_INTERNAL, "Error while executing logging shell script: %s", sname); pclose(in); goto log_phpscript; } } pclose(in); } log_phpscript: if ((SUHOSIN_G(log_phpscript) & loglevel)!=0 && EG(in_execution) && SUHOSIN_G(log_phpscriptname) && SUHOSIN_G(log_phpscriptname)[0]) { zend_file_handle file_handle; zend_op_array *new_op_array; zval *result = NULL; long orig_execution_depth = SUHOSIN_G(execution_depth); #if PHP_VERSION_ID < 50400 zend_bool orig_safe_mode = PG(safe_mode); #endif char *orig_basedir = PG(open_basedir); char *phpscript = SUHOSIN_G(log_phpscriptname); SDEBUG("scriptname %s", SUHOSIN_G(log_phpscriptname)); #ifdef ZEND_ENGINE_2 if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) { #else if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { file_handle.filename = phpscript; file_handle.free_filename = 0; #endif if (!file_handle.opened_path) { file_handle.opened_path = estrndup(phpscript, strlen(phpscript)); } new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); zend_destroy_file_handle(&file_handle TSRMLS_CC); if (new_op_array) { HashTable *active_symbol_table = EG(active_symbol_table); zval *zerror, *zerror_class; if (active_symbol_table == NULL) { active_symbol_table = &EG(symbol_table); } EG(return_value_ptr_ptr) = &result; EG(active_op_array) = new_op_array; MAKE_STD_ZVAL(zerror); MAKE_STD_ZVAL(zerror_class); ZVAL_STRING(zerror, buf, 1); ZVAL_LONG(zerror_class, loglevel); zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL); zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL); SUHOSIN_G(execution_depth) = 0; if (SUHOSIN_G(log_phpscript_is_safe)) { #if PHP_VERSION_ID < 50400 PG(safe_mode) = 0; #endif PG(open_basedir) = NULL; } zend_execute(new_op_array TSRMLS_CC); SUHOSIN_G(execution_depth) = orig_execution_depth; #if PHP_VERSION_ID < 50400 PG(safe_mode) = orig_safe_mode; #endif PG(open_basedir) = orig_basedir; #ifdef ZEND_ENGINE_2 destroy_op_array(new_op_array TSRMLS_CC); #else destroy_op_array(new_op_array); #endif efree(new_op_array); #ifdef ZEND_ENGINE_2 if (!EG(exception)) #endif { if (EG(return_value_ptr_ptr)) { zval_ptr_dtor(EG(return_value_ptr_ptr)); EG(return_value_ptr_ptr) = NULL; } } } else { suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname)); return; } } else { suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname)); return; } } }
/* {{{ php_date */ static void php_date(INTERNAL_FUNCTION_PARAMETERS, int gm) { pval **format, **timestamp; time_t the_time; struct tm *ta, tmbuf; int i, size = 0, length, h, beat, fd, wd, yd, wk; char tmp_buff[32]; #if !HAVE_TM_GMTOFF long tzone; char *tname[2]= {"GMT Standard Time", "BST"}; #endif switch(ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &format) == FAILURE) { WRONG_PARAM_COUNT; } the_time = time(NULL); break; case 2: if (zend_get_parameters_ex(2, &format, ×tamp) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(timestamp); the_time = Z_LVAL_PP(timestamp); #ifdef PHP_WIN32 if (the_time < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Windows does not support dates prior to midnight (00:00:00), January 1, 1970"); RETURN_FALSE; } #endif break; default: WRONG_PARAM_COUNT; } convert_to_string_ex(format); if (gm) { ta = php_gmtime_r(&the_time, &tmbuf); #if !HAVE_TM_GMTOFF tzone = 0; #endif } else { ta = php_localtime_r(&the_time, &tmbuf); #if !HAVE_TM_GMTOFF #ifdef __CYGWIN__ tzone = _timezone; #else tzone = timezone; #endif if (tzname[0] != NULL) { tname[0] = tzname[0]; } else { tname[0] = "???"; } if (tzname[1] != NULL) { tname[1] = tzname[1]; } #endif } if (!ta) { /* that really shouldn't happen... */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected error"); RETURN_FALSE; } for (i = 0; i < Z_STRLEN_PP(format); i++) { switch (Z_STRVAL_PP(format)[i]) { case 'r': /* rfc822 format */ size += 31; break; case 'U': /* seconds since the epoch */ size += 10; break; case 'F': /* month, textual, full */ case 'l': /* day (of the week), textual */ size += 28; break; case 'T': /* timezone name */ #if HAVE_TM_ZONE size += strlen(ta->tm_zone); #elif HAVE_TZNAME if (ta->tm_isdst > 0 ) { size += strlen(tname[1]); } else { size += strlen(tname[0]); } #endif break; case 'Z': /* timezone offset in seconds */ size += 6; break; case 'O': /* GMT offset in [+-]HHMM format */ size += 5; break; case 'Y': /* year, numeric, 4 digits */ size += 4; break; case 'M': /* month, textual, 3 letters */ case 'D': /* day, textual, 3 letters */ case 'z': /* day of the year, 1 to 366 */ case 'B': /* Swatch Beat, 3 digits */ size += 3; break; case 'y': /* year, numeric, 2 digits */ case 'm': /* month, numeric */ case 'n': /* month, numeric, no leading zeroes */ case 'd': /* day of the month, numeric */ case 'j': /* day of the month, numeric, no leading zeros */ case 'H': /* hour, numeric, 24 hour format */ case 'h': /* hour, numeric, 12 hour format */ case 'G': /* hour, numeric, 24 hour format, no leading zeroes */ case 'g': /* hour, numeric, 12 hour format, no leading zeroes */ case 'i': /* minutes, numeric */ case 's': /* seconds, numeric */ case 'A': /* AM/PM */ case 'a': /* am/pm */ case 'S': /* standard english suffix for the day of the month (e.g. 3rd, 2nd, etc) */ case 't': /* days in current month */ case 'W': /* ISO-8601 week number of year, weeks starting on Monday */ size += 2; break; case '\\': if (i < Z_STRLEN_PP(format) - 1) { i++; } size ++; break; case 'L': /* boolean for leap year */ case 'w': /* day of the week, numeric */ case 'I': /* DST? */ default: size++; break; } } Z_STRVAL_P(return_value) = (char *) emalloc(size + 1); Z_STRVAL_P(return_value)[0] = '\0'; for (i = 0; i < Z_STRLEN_PP(format); i++) { switch (Z_STRVAL_PP(format)[i]) { case '\\': if (i < Z_STRLEN_PP(format) - 1) { char ch[2]; ch[0]=Z_STRVAL_PP(format)[i + 1]; ch[1]='\0'; strcat(Z_STRVAL_P(return_value), ch); i++; } break; case 'U': /* seconds since the epoch */ sprintf(tmp_buff, "%ld", (long)the_time); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'F': /* month, textual, full */ strcat(Z_STRVAL_P(return_value), mon_full_names[ta->tm_mon]); break; case 'l': /* day (of the week), textual, full */ strcat(Z_STRVAL_P(return_value), day_full_names[ta->tm_wday]); break; case 'Y': /* year, numeric, 4 digits */ sprintf(tmp_buff, "%d", ta->tm_year + YEAR_BASE); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'M': /* month, textual, 3 letters */ strcat(Z_STRVAL_P(return_value), mon_short_names[ta->tm_mon]); break; case 'D': /* day (of the week), textual, 3 letters */ strcat(Z_STRVAL_P(return_value), day_short_names[ta->tm_wday]); break; case 'z': /* day (of the year) */ sprintf(tmp_buff, "%d", ta->tm_yday); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'y': /* year, numeric, 2 digits */ sprintf(tmp_buff, "%02d", ((ta->tm_year)%100)); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'm': /* month, numeric */ sprintf(tmp_buff, "%02d", ta->tm_mon + 1); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'n': /* month, numeric, no leading zeros */ sprintf(tmp_buff, "%d", ta->tm_mon + 1); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'd': /* day of the month, numeric */ sprintf(tmp_buff, "%02d", ta->tm_mday); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'j': sprintf(tmp_buff, "%d", ta->tm_mday); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'H': /* hour, numeric, 24 hour format */ sprintf(tmp_buff, "%02d", ta->tm_hour); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'h': /* hour, numeric, 12 hour format */ h = ta->tm_hour % 12; if (h==0) h = 12; sprintf(tmp_buff, "%02d", h); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'G': /* hour, numeric, 24 hour format, no leading zeros */ sprintf(tmp_buff, "%d", ta->tm_hour); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'g': /* hour, numeric, 12 hour format, no leading zeros */ h = ta->tm_hour % 12; if (h==0) h = 12; sprintf(tmp_buff, "%d", h); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'i': /* minutes, numeric */ sprintf(tmp_buff, "%02d", ta->tm_min); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 's': /* seconds, numeric */ sprintf(tmp_buff, "%02d", ta->tm_sec); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'A': /* AM/PM */ strcat(Z_STRVAL_P(return_value), (ta->tm_hour >= 12 ? "PM" : "AM")); break; case 'a': /* am/pm */ strcat(Z_STRVAL_P(return_value), (ta->tm_hour >= 12 ? "pm" : "am")); break; case 'S': /* standard english suffix, e.g. 2nd/3rd for the day of the month */ if (ta->tm_mday >= 10 && ta->tm_mday <= 19) { strcat(Z_STRVAL_P(return_value), "th"); } else { switch (ta->tm_mday % 10) { case 1: strcat(Z_STRVAL_P(return_value), "st"); break; case 2: strcat(Z_STRVAL_P(return_value), "nd"); break; case 3: strcat(Z_STRVAL_P(return_value), "rd"); break; default: strcat(Z_STRVAL_P(return_value), "th"); break; } } break; case 't': /* days in current month */ sprintf(tmp_buff, "%2d", phpday_tab[isleap((ta->tm_year+YEAR_BASE))][ta->tm_mon] ); strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'w': /* day of the week, numeric EXTENSION */ sprintf(tmp_buff, "%01d", ta->tm_wday); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'O': /* GMT offset in [+-]HHMM format */ #if HAVE_TM_GMTOFF sprintf(tmp_buff, "%c%02d%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 )); #else sprintf(tmp_buff, "%c%02d%02d", ((ta->tm_isdst ? tzone - 3600:tzone)>0)?'-':'+', abs((ta->tm_isdst ? tzone - 3600 : tzone) / 3600), abs(((ta->tm_isdst ? tzone - 3600 : tzone) % 3600) / 60)); #endif strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'Z': /* timezone offset in seconds */ #if HAVE_TM_GMTOFF sprintf(tmp_buff, "%ld", ta->tm_gmtoff); #else sprintf(tmp_buff, "%ld", ta->tm_isdst ? -(tzone- 3600) : -tzone); #endif strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'L': /* boolean for leapyear */ sprintf(tmp_buff, "%d", (isleap((ta->tm_year+YEAR_BASE)) ? 1 : 0 ) ); strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'T': /* timezone name */ #if HAVE_TM_ZONE strcat(Z_STRVAL_P(return_value), ta->tm_zone); #elif HAVE_TZNAME strcat(Z_STRVAL_P(return_value), ta->tm_isdst ? tname[1] : tname[0]); #endif break; case 'B': /* Swatch Beat a.k.a. Internet Time */ beat = (((((long)the_time)-(((long)the_time) - ((((long)the_time) % 86400) + 3600))) * 10) / 864); while (beat < 0) { beat += 1000; } beat = beat % 1000; sprintf(tmp_buff, "%03d", beat); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'I': sprintf(tmp_buff, "%d", ta->tm_isdst); strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'r': #if HAVE_TM_GMTOFF sprintf(tmp_buff, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d", day_short_names[ta->tm_wday], ta->tm_mday, mon_short_names[ta->tm_mon], ta->tm_year + YEAR_BASE, ta->tm_hour, ta->tm_min, ta->tm_sec, (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ) ); #else sprintf(tmp_buff, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d", day_short_names[ta->tm_wday], ta->tm_mday, mon_short_names[ta->tm_mon], ta->tm_year + YEAR_BASE, ta->tm_hour, ta->tm_min, ta->tm_sec, ((ta->tm_isdst ? tzone - 3600 : tzone) > 0) ? '-' : '+', abs((ta->tm_isdst ? tzone - 3600 : tzone) / 3600), abs( ((ta->tm_isdst ? tzone - 3600 : tzone) % 3600) / 60 ) ); #endif strcat(Z_STRVAL_P(return_value), tmp_buff); break; case 'W': /* ISO-8601 week number of year, weeks starting on Monday */ wd = ta->tm_wday == 0 ? 6 : ta->tm_wday - 1; /* weekday */ yd = ta->tm_yday + 1; /* days since January 1st */ fd = (7 + wd - yd % 7+ 1) % 7; /* weekday (1st January) */ /* week is a last year week (52 or 53) */ if ((yd <= 7 - fd) && fd > 3){ wk = (fd == 4 || (fd == 5 && isleap((ta->tm_year + YEAR_BASE - 1)))) ? 53 : 52; } /* week is a next year week (1) */ else if (isleap((ta->tm_year+YEAR_BASE)) + 365 - yd < 3 - wd){ wk = 1; } /* normal week */ else { wk = (yd + 6 - wd + fd) / 7 - (fd > 3); } sprintf(tmp_buff, "%02d", wk); /* SAFE */ strcat(Z_STRVAL_P(return_value), tmp_buff); break; default: length = strlen(Z_STRVAL_P(return_value)); Z_STRVAL_P(return_value)[length] = Z_STRVAL_PP(format)[i]; Z_STRVAL_P(return_value)[length + 1] = '\0'; break; } } Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value)); Z_TYPE_P(return_value) = IS_STRING; }