--- embedaddon/php/ext/intl/dateformat/dateformat.c 2012/02/21 23:47:56 1.1.1.1 +++ embedaddon/php/ext/intl/dateformat/dateformat.c 2013/07/22 01:31:52 1.1.1.2 @@ -99,17 +99,46 @@ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) } INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value); - DATE_FORMAT_METHOD_FETCH_OBJECT; + + if (calendar != UCAL_TRADITIONAL && calendar != UCAL_GREGORIAN) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: " + "invalid value for calendar type; it must be one of " + "IntlDateFormatter::TRADITIONAL (locale's default calendar) " + "or IntlDateFormatter::GREGORIAN", 0 TSRMLS_CC); + goto error; + } + + DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; + + if (DATE_FORMAT_OBJECT(dfo) != NULL) { + intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, + "datefmt_create: cannot call constructor twice", 0 TSRMLS_CC); + return; + } + /* Convert pattern (if specified) to UTF-16. */ if( pattern_str && pattern_str_len>0 ){ - intl_convert_utf8_to_utf16(&svalue, &slength, pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(dfo)); - INTL_CTOR_CHECK_STATUS(dfo, "datefmt_create: error converting pattern to UTF-16"); + intl_convert_utf8_to_utf16(&svalue, &slength, + pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(dfo)); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + /* object construction -> only set global error */ + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: " + "error converting pattern to UTF-16", 0 TSRMLS_CC); + goto error; + } } + + /* resources allocated from now on */ /* Convert pattern (if specified) to UTF-16. */ if( timezone_str && timezone_str_len >0 ){ - intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len, timezone_str, timezone_str_len, &INTL_DATA_ERROR_CODE(dfo)); - INTL_CTOR_CHECK_STATUS(dfo, "datefmt_create: error converting timezone_str to UTF-16" ); + intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len, + timezone_str, timezone_str_len, &INTL_DATA_ERROR_CODE(dfo)); + if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: " + "error converting timezone_str to UTF-16", 0 TSRMLS_CC); + goto error; + } } if(locale_len == 0) { @@ -122,25 +151,25 @@ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) DATE_FORMAT_OBJECT(dfo) = udat_open(time_type, date_type, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo)); } - /* Set the calendar if passed */ - if(!U_FAILURE(INTL_DATA_ERROR_CODE(dfo)) && calendar) { - ucal_obj = ucal_open( timezone_utf16, timezone_utf16_len, locale, calendar, &INTL_DATA_ERROR_CODE(dfo) ); - if(!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { - udat_setCalendar( DATE_FORMAT_OBJECT(dfo), ucal_obj ); + if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + if (calendar != UCAL_TRADITIONAL) { + ucal_obj = ucal_open(timezone_utf16, timezone_utf16_len, locale, + calendar, &INTL_DATA_ERROR_CODE(dfo)); + if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { + udat_setCalendar(DATE_FORMAT_OBJECT(dfo), ucal_obj); + ucal_close(ucal_obj); + } else { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create" + ": error opening calendar", 0 TSRMLS_CC); + goto error; + } } - } - - if(svalue) - { - efree(svalue); + } else { + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: date " + "formatter creation failed", 0 TSRMLS_CC); + goto error; } - if(timezone_utf16) - { - efree(timezone_utf16); - } - INTL_CTOR_CHECK_STATUS(dfo, "datefmt_create: date formatter creation failed"); - /* Set the class variables */ dfo->date_type = date_type; dfo->time_type = time_type; @@ -148,6 +177,19 @@ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) if( timezone_str && timezone_str_len > 0){ dfo->timezone_id = estrndup( timezone_str, timezone_str_len); } + +error: + if (svalue) { + efree(svalue); + } + if (timezone_utf16) { + efree(timezone_utf16); + } + if (U_FAILURE(intl_error_get_code(NULL TSRMLS_CC))) { + /* free_object handles partially constructed instances fine */ + zval_dtor(return_value); + RETVAL_NULL(); + } } /* }}} */ @@ -169,6 +211,8 @@ PHP_FUNCTION( datefmt_create ) */ PHP_METHOD( IntlDateFormatter, __construct ) { + /* return_value param is being changed, therefore we will always return + * NULL here */ return_value = getThis(); datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU); }