diff options
Diffstat (limited to 'ext/date/php_date.c')
-rw-r--r-- | ext/date/php_date.c | 186 |
1 files changed, 83 insertions, 103 deletions
diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 2e616b1704..fd6453f5d8 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -495,9 +495,11 @@ int php_date_global_timezone_db_enabled; /* on 90'35; common sunrise declaration (sun body disappeared) */ #define DATE_SUNRISE_ZENITH "90.583333" +static PHP_INI_MH(OnUpdate_date_timezone); + /* {{{ INI Settings */ PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("date.timezone", "", PHP_INI_ALL, OnUpdateString, default_timezone, zend_date_globals, date_globals) + STD_PHP_INI_ENTRY("date.timezone", "", PHP_INI_ALL, OnUpdate_date_timezone, default_timezone, zend_date_globals, date_globals) PHP_INI_ENTRY("date.default_latitude", DATE_DEFAULT_LATITUDE, PHP_INI_ALL, NULL) PHP_INI_ENTRY("date.default_longitude", DATE_DEFAULT_LONGITUDE, PHP_INI_ALL, NULL) PHP_INI_ENTRY("date.sunset_zenith", DATE_SUNSET_ZENITH, PHP_INI_ALL, NULL) @@ -563,11 +565,13 @@ static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC); static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC); static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC); +static HashTable *date_object_get_gc(zval *object, zval ***table, int *n TSRMLS_DC); static HashTable *date_object_get_properties(zval *object TSRMLS_DC); +static HashTable *date_object_get_gc_interval(zval *object, zval ***table, int *n TSRMLS_DC); static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC); -zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC); -void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC); +zval *date_interval_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC); +void date_interval_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC); /* {{{ Module struct */ zend_module_entry date_module_entry = { @@ -597,6 +601,7 @@ static PHP_GINIT_FUNCTION(date) date_globals->default_timezone = NULL; date_globals->timezone = NULL; date_globals->tzcache = NULL; + date_globals->timezone_valid = 0; } /* }}} */ @@ -842,101 +847,58 @@ timelib_tzinfo *php_date_parse_tzfile_wrapper(char *formal_tzname, const timelib } /* }}} */ +/* Callback to check the date.timezone only when changed increases performance */ +/* {{{ static PHP_INI_MH(OnUpdate_date_timezone) */ +static PHP_INI_MH(OnUpdate_date_timezone) +{ + if (OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC) == FAILURE) { + return FAILURE; + } + + DATEG(timezone_valid) = 0; + if (stage == PHP_INI_STAGE_RUNTIME) { + if (!timelib_timezone_id_is_valid(DATEG(default_timezone), DATE_TIMEZONEDB)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG); + } else { + DATEG(timezone_valid) = 1; + } + } + + return SUCCESS; +} +/* }}} */ + /* {{{ Helper functions */ static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC) { - char *env; - /* Checking configure timezone */ - if (DATEG(timezone) && (strlen(DATEG(timezone)) > 0)) { + if (DATEG(timezone) && (strlen(DATEG(timezone))) > 0) { return DATEG(timezone); } - /* Check environment variable */ - env = getenv("TZ"); - if (env && *env && timelib_timezone_id_is_valid(env, tzdb)) { - return env; - } /* Check config setting for default timezone */ if (!DATEG(default_timezone)) { /* Special case: ext/date wasn't initialized yet */ zval ztz; - - if (SUCCESS == zend_get_configuration_directive("date.timezone", sizeof("date.timezone"), &ztz) && - Z_TYPE(ztz) == IS_STRING && - Z_STRLEN(ztz) > 0 && - timelib_timezone_id_is_valid(Z_STRVAL(ztz), tzdb)) { + + if (SUCCESS == zend_get_configuration_directive("date.timezone", sizeof("date.timezone"), &ztz) + && Z_TYPE(ztz) == IS_STRING && Z_STRLEN(ztz) > 0 && timelib_timezone_id_is_valid(Z_STRVAL(ztz), tzdb)) { return Z_STRVAL(ztz); } - } else if (*DATEG(default_timezone) && timelib_timezone_id_is_valid(DATEG(default_timezone), tzdb)) { - return DATEG(default_timezone); - } -#if HAVE_TM_ZONE - /* Try to guess timezone from system information */ - { - struct tm *ta, tmbuf; - time_t the_time; - char *tzid = NULL; - - the_time = time(NULL); - ta = php_localtime_r(&the_time, &tmbuf); - if (ta) { - tzid = timelib_timezone_id_from_abbr(ta->tm_zone, ta->tm_gmtoff, ta->tm_isdst); - } - if (! tzid) { - tzid = "UTC"; + } else if (*DATEG(default_timezone)) { + if (DATEG(timezone_valid) == 1) { + return DATEG(default_timezone); } - - php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%s/%.1f/%s' instead", tzid, ta ? ta->tm_zone : "Unknown", ta ? (float) (ta->tm_gmtoff / 3600) : 0, ta ? (ta->tm_isdst ? "DST" : "no DST") : "Unknown"); - return tzid; - } -#endif -#ifdef PHP_WIN32 - { - char *tzid; - TIME_ZONE_INFORMATION tzi; - - switch (GetTimeZoneInformation(&tzi)) - { - /* DST in effect */ - case TIME_ZONE_ID_DAYLIGHT: - /* If user has disabled DST in the control panel, Windows returns 0 here */ - if (tzi.DaylightBias == 0) { - goto php_win_std_time; - } - - tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.DaylightBias) * -60, 1); - if (! tzid) { - tzid = "UTC"; - } - php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%.1f/DST' instead", tzid, ((tzi.Bias + tzi.DaylightBias) / -60.0)); - break; - /* no DST or not in effect */ - case TIME_ZONE_ID_UNKNOWN: - case TIME_ZONE_ID_STANDARD: - default: -php_win_std_time: - tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.StandardBias) * -60, 0); - if (! tzid) { - tzid = "UTC"; - } - php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%.1f/no DST' instead", tzid, ((tzi.Bias + tzi.StandardBias) / -60.0)); - break; - - } - return tzid; - } -#elif defined(NETWARE) - /* Try to guess timezone from system information */ - { - char *tzid = timelib_timezone_id_from_abbr("", ((_timezone * -1) + (daylightOffset * daylightOnOff)), daylightOnOff); - if (tzid) { - return tzid; + if (!timelib_timezone_id_is_valid(DATEG(default_timezone), tzdb)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid date.timezone value '%s', we selected the timezone 'UTC' for now.", DATEG(default_timezone)); + return "UTC"; } + + DATEG(timezone_valid) = 1; + return DATEG(default_timezone); } -#endif /* Fallback to UTC */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We had to select 'UTC' because your platform doesn't provide functionality for the guessing algorithm"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone."); return "UTC"; } @@ -1020,6 +982,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca timelib_time_offset *offset = NULL; timelib_sll isoweek, isoyear; int rfc_colon; + int weekYearSet = 0; if (!format_len) { return estrdup(""); @@ -1046,7 +1009,6 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca offset = timelib_get_time_zone_info(t->sse, t->tz_info); } } - timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); for (i = 0; i < format_len; i++) { rfc_colon = 0; @@ -1062,8 +1024,12 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca case 'z': length = slprintf(buffer, 32, "%d", (int) timelib_day_of_year(t->y, t->m, t->d)); break; /* week */ - case 'W': length = slprintf(buffer, 32, "%02d", (int) isoweek); break; /* iso weeknr */ - case 'o': length = slprintf(buffer, 32, "%d", (int) isoyear); break; /* iso year */ + case 'W': + if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; } + length = slprintf(buffer, 32, "%02d", (int) isoweek); break; /* iso weeknr */ + case 'o': + if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; } + length = slprintf(buffer, 32, "%d", (int) isoyear); break; /* iso year */ /* month */ case 'F': length = slprintf(buffer, 32, "%s", mon_full_names[t->m - 1]); break; @@ -1213,14 +1179,13 @@ PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localt /* {{{ php_idate */ -PHPAPI int php_idate(char format, time_t ts, int localtime) +PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC) { timelib_time *t; timelib_tzinfo *tzi; int retval = -1; timelib_time_offset *offset = NULL; timelib_sll isoweek, isoyear; - TSRMLS_FETCH(); t = timelib_time_ctor(); @@ -1346,7 +1311,7 @@ PHP_FUNCTION(idate) ts = time(NULL); } - ret = php_idate(format[0], ts, 0); + ret = php_idate(format[0], ts, 0 TSRMLS_CC); if (ret == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized date format token."); RETURN_FALSE; @@ -1956,6 +1921,7 @@ static void date_register_classes(TSRMLS_D) date_object_handlers_date.clone_obj = date_object_clone_date; date_object_handlers_date.compare_objects = date_object_compare_date; date_object_handlers_date.get_properties = date_object_get_properties; + date_object_handlers_date.get_gc = date_object_get_gc; #define REGISTER_DATE_CLASS_CONST_STRING(const_name, value) \ zend_declare_class_constant_stringl(date_ce_date, const_name, sizeof(const_name)-1, value, sizeof(value)-1 TSRMLS_CC); @@ -2006,6 +1972,7 @@ static void date_register_classes(TSRMLS_D) date_object_handlers_interval.write_property = date_interval_write_property; date_object_handlers_interval.get_properties = date_object_get_properties_interval; date_object_handlers_interval.get_property_ptr_ptr = NULL; + date_object_handlers_interval.get_gc = date_object_get_gc_interval; INIT_CLASS_ENTRY(ce_period, "DatePeriod", date_funcs_period); ce_period.create_object = date_object_new_period; @@ -2026,7 +1993,6 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_ { php_date_obj *intern; zend_object_value retval; - zval *tmp; intern = emalloc(sizeof(php_date_obj)); memset(intern, 0, sizeof(php_date_obj)); @@ -2035,7 +2001,7 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_ } zend_object_std_init(&intern->std, class_type TSRMLS_CC); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *)); + object_properties_init(&intern->std, class_type); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_date; @@ -2097,6 +2063,13 @@ static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC) return 1; } +static HashTable *date_object_get_gc(zval *object, zval ***table, int *n TSRMLS_DC) +{ + *table = NULL; + *n = 0; + return zend_std_get_properties(object TSRMLS_CC); +} + static HashTable *date_object_get_properties(zval *object TSRMLS_DC) { HashTable *props; @@ -2108,7 +2081,7 @@ static HashTable *date_object_get_properties(zval *object TSRMLS_DC) props = zend_std_get_properties(object TSRMLS_CC); - if (!dateobj->time || GC_G(gc_active)) { + if (!dateobj->time) { return props; } @@ -2154,7 +2127,6 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl { php_timezone_obj *intern; zend_object_value retval; - zval *tmp; intern = emalloc(sizeof(php_timezone_obj)); memset(intern, 0, sizeof(php_timezone_obj)); @@ -2163,7 +2135,7 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl } zend_object_std_init(&intern->std, class_type TSRMLS_CC); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *)); + object_properties_init(&intern->std, class_type); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_timezone; @@ -2210,7 +2182,6 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl { php_interval_obj *intern; zend_object_value retval; - zval *tmp; intern = emalloc(sizeof(php_interval_obj)); memset(intern, 0, sizeof(php_interval_obj)); @@ -2219,7 +2190,7 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl } zend_object_std_init(&intern->std, class_type TSRMLS_CC); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *)); + object_properties_init(&intern->std, class_type); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_interval; @@ -2244,6 +2215,14 @@ static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC) return new_ov; } +static HashTable *date_object_get_gc_interval(zval *object, zval ***table, int *n TSRMLS_DC) +{ + + *table = NULL; + *n = 0; + return zend_std_get_properties(object TSRMLS_CC); +} + static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) { HashTable *props; @@ -2255,7 +2234,7 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) props = zend_std_get_properties(object TSRMLS_CC); - if (!intervalobj->initialized || GC_G(gc_active)) { + if (!intervalobj->initialized) { return props; } @@ -2286,7 +2265,6 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas { php_period_obj *intern; zend_object_value retval; - zval *tmp; intern = emalloc(sizeof(php_period_obj)); memset(intern, 0, sizeof(php_period_obj)); @@ -2295,7 +2273,7 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas } zend_object_std_init(&intern->std, class_type TSRMLS_CC); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *)); + object_properties_init(&intern->std, class_type); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_period; @@ -3499,7 +3477,7 @@ static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *forma } /* {{{ date_interval_read_property */ -zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC) +zval *date_interval_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) { php_interval_obj *obj; zval *retval; @@ -3511,12 +3489,13 @@ zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); member = &tmp_member; + key = NULL; } obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC); if (!obj->initialized) { - retval = (zend_get_std_object_handlers())->read_property(object, member, type TSRMLS_CC); + retval = (zend_get_std_object_handlers())->read_property(object, member, type, key TSRMLS_CC); if (member == &tmp_member) { zval_dtor(member); } @@ -3538,7 +3517,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC GET_VALUE_FROM_STRUCT(invert, "invert"); GET_VALUE_FROM_STRUCT(days, "days"); /* didn't find any */ - retval = (zend_get_std_object_handlers())->read_property(object, member, type TSRMLS_CC); + retval = (zend_get_std_object_handlers())->read_property(object, member, type, key TSRMLS_CC); if (member == &tmp_member) { zval_dtor(member); @@ -3561,7 +3540,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC /* }}} */ /* {{{ date_interval_write_property */ -void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +void date_interval_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) { php_interval_obj *obj; zval tmp_member, tmp_value; @@ -3571,12 +3550,13 @@ void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); member = &tmp_member; + key = NULL; } obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC); if (!obj->initialized) { - (zend_get_std_object_handlers())->write_property(object, member, value TSRMLS_CC); + (zend_get_std_object_handlers())->write_property(object, member, value, key TSRMLS_CC); if (member == &tmp_member) { zval_dtor(member); } @@ -3607,7 +3587,7 @@ void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS SET_VALUE_FROM_STRUCT(s, "s"); SET_VALUE_FROM_STRUCT(invert, "invert"); /* didn't find any */ - (zend_get_std_object_handlers())->write_property(object, member, value TSRMLS_CC); + (zend_get_std_object_handlers())->write_property(object, member, value, key TSRMLS_CC); } while(0); if (member == &tmp_member) { |