1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | http://www.php.net/license/3_01.txt                                  |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Kirti Velankar <kirtig@yahoo-inc.com>                       |
14    +----------------------------------------------------------------------+
15 */
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19 
20 #include "../php_intl.h"
21 #include "dateformat_class.h"
22 #include "../intl_convert.h"
23 #include "dateformat_class.h"
24 #include "dateformat_attr.h"
25 
26 #include <unicode/ustring.h>
27 #include <unicode/udat.h>
28 #include <unicode/ucal.h>
29 
internal_set_calendar(IntlDateFormatter_object * dfo,char * timezone_id,int timezone_id_len,int calendar,zval * return_value TSRMLS_DC)30 static void internal_set_calendar(IntlDateFormatter_object *dfo, char* timezone_id, int timezone_id_len, int calendar, zval* return_value TSRMLS_DC){
31 	int         timezone_utf16_len = 0;
32 	UChar*      timezone_utf16  = NULL; /* timezone_id in UTF-16 */
33 	char*       locale = NULL;
34 
35 	UCalendar*   ucal_obj = NULL;
36 
37 	/* check for the validity  of value of calendar passed */
38 	intl_error_reset( NULL TSRMLS_CC );
39 	if( calendar > 1){
40 		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
41 			"datefmt_set_calendar: calendar value specified is out of valid range", 0 TSRMLS_CC);
42 		RETURN_FALSE;
43 	}
44 
45 	/* Convert timezone to UTF-16. */
46 	intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len, timezone_id, timezone_id_len, &INTL_DATA_ERROR_CODE(dfo));
47 	INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" );
48 
49 	/* Get the locale for the dateformatter */
50 	locale = (char *)udat_getLocaleByType(DATE_FORMAT_OBJECT(dfo), ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(dfo));
51 
52 	/* Set the calendar if passed */
53 	ucal_obj = ucal_open(timezone_utf16, timezone_utf16_len, locale, calendar, &INTL_DATA_ERROR_CODE(dfo) );
54 	udat_setCalendar( DATE_FORMAT_OBJECT(dfo), ucal_obj );
55 	INTL_METHOD_CHECK_STATUS(dfo, "Error setting the calendar.");
56 
57 	if( timezone_utf16){
58 		efree(timezone_utf16);
59 	}
60 }
61 
62 /* {{{ proto unicode IntlDateFormatter::getDateType( )
63  * Get formatter datetype. }}} */
64 /* {{{ proto string datefmt_get_datetype( IntlDateFormatter $mf )
65  * Get formatter datetype.
66  */
PHP_FUNCTION(datefmt_get_datetype)67 PHP_FUNCTION( datefmt_get_datetype )
68 {
69 	DATE_FORMAT_METHOD_INIT_VARS;
70 
71 	/* Parse parameters. */
72 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE )
73 	{
74 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
75 			"datefmt_get_datetype: unable to parse input params", 0 TSRMLS_CC );
76 		RETURN_FALSE;
77 	}
78 
79 	/* Fetch the object. */
80 	DATE_FORMAT_METHOD_FETCH_OBJECT;
81 
82 	INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter datetype." );
83 
84 	RETURN_LONG(dfo->date_type );
85 }
86 /* }}} */
87 
88 /* {{{ proto unicode IntlDateFormatter::getTimeType( )
89  * Get formatter timetype. }}} */
90 /* {{{ proto string datefmt_get_timetype( IntlDateFormatter $mf )
91  * Get formatter timetype.
92  */
PHP_FUNCTION(datefmt_get_timetype)93 PHP_FUNCTION( datefmt_get_timetype )
94 {
95 	DATE_FORMAT_METHOD_INIT_VARS;
96 
97 	/* Parse parameters. */
98 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE )
99 	{
100 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
101 			"datefmt_get_timetype: unable to parse input params", 0 TSRMLS_CC );
102 		RETURN_FALSE;
103 	}
104 
105 	/* Fetch the object. */
106 	DATE_FORMAT_METHOD_FETCH_OBJECT;
107 
108 	INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter timetype." );
109 
110 	RETURN_LONG(dfo->time_type );
111 }
112 /* }}} */
113 
114 
115 /* {{{ proto unicode IntlDateFormatter::getCalendar( )
116  * Get formatter calendar. }}} */
117 /* {{{ proto string datefmt_get_calendar( IntlDateFormatter $mf )
118  * Get formatter calendar.
119  */
PHP_FUNCTION(datefmt_get_calendar)120 PHP_FUNCTION( datefmt_get_calendar )
121 {
122 	DATE_FORMAT_METHOD_INIT_VARS;
123 
124 	/* Parse parameters. */
125 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE )
126 	{
127 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
128 			"datefmt_get_calendar: unable to parse input params", 0 TSRMLS_CC );
129 		RETURN_FALSE;
130 	}
131 
132 	/* Fetch the object. */
133 	DATE_FORMAT_METHOD_FETCH_OBJECT;
134 
135 	INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter calendar." );
136 
137 	RETURN_LONG(dfo->calendar);
138 }
139 /* }}} */
140 
141 /* {{{ proto unicode IntlDateFormatter::getTimeZoneId( )
142  * Get formatter timezone_id. }}} */
143 /* {{{ proto string datefmt_get_timezone_id( IntlDateFormatter $mf )
144  * Get formatter timezone_id.
145  */
PHP_FUNCTION(datefmt_get_timezone_id)146 PHP_FUNCTION( datefmt_get_timezone_id )
147 {
148 	DATE_FORMAT_METHOD_INIT_VARS;
149 
150 	/* Parse parameters. */
151 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE )
152 	{
153 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
154 			"datefmt_get_timezone_id: unable to parse input params", 0 TSRMLS_CC );
155 		RETURN_FALSE;
156 	}
157 
158 	/* Fetch the object. */
159 	DATE_FORMAT_METHOD_FETCH_OBJECT;
160 
161 	INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter timezone_id." );
162 
163 	if( dfo->timezone_id ){
164 		RETURN_STRING((char*)dfo->timezone_id, TRUE );
165 	}else{
166 		RETURN_NULL();
167 	}
168 }
169 
170 /* {{{ proto boolean IntlDateFormatter::setTimeZoneId( $timezone_id)
171  * Set formatter timezone_id. }}} */
172 /* {{{ proto boolean datefmt_set_timezone_id( IntlDateFormatter $mf,$timezone_id)
173  * Set formatter timezone_id.
174  */
PHP_FUNCTION(datefmt_set_timezone_id)175 PHP_FUNCTION( datefmt_set_timezone_id )
176 {
177 	char* 		timezone_id 		= NULL;
178 	int 		timezone_id_len 	= 0;
179 
180 	DATE_FORMAT_METHOD_INIT_VARS;
181 
182 	/* Parse parameters. */
183 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, IntlDateFormatter_ce_ptr,&timezone_id, &timezone_id_len) == FAILURE )
184 	{
185 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
186 			"datefmt_set_timezone_id: unable to parse input params", 0 TSRMLS_CC );
187 		RETURN_FALSE;
188 	}
189 
190 	/* Fetch the object. */
191 	DATE_FORMAT_METHOD_FETCH_OBJECT;
192 
193 	/* set the timezone for the calendar */
194 	internal_set_calendar( dfo, timezone_id, timezone_id_len, dfo->calendar, return_value TSRMLS_CC );
195 
196 	/* Set the IntlDateFormatter variable */
197         if( dfo->timezone_id ){
198 		efree(dfo->timezone_id);
199 	}
200 	dfo->timezone_id = estrndup(timezone_id, timezone_id_len);
201 
202 	RETURN_TRUE;
203 }
204 
205 /* {{{ proto string IntlDateFormatter::getPattern( )
206  * Get formatter pattern. }}} */
207 /* {{{ proto string datefmt_get_pattern( IntlDateFormatter $mf )
208  * Get formatter pattern.
209  */
PHP_FUNCTION(datefmt_get_pattern)210 PHP_FUNCTION( datefmt_get_pattern )
211 {
212 	UChar  value_buf[64];
213 	int    length = USIZE( value_buf );
214 	UChar* value  = value_buf;
215 	zend_bool   is_pattern_localized =FALSE;
216 
217 	DATE_FORMAT_METHOD_INIT_VARS;
218 
219 	/* Parse parameters. */
220 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, IntlDateFormatter_ce_ptr ) == FAILURE )
221 	{
222 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
223 			"datefmt_get_pattern: unable to parse input params", 0 TSRMLS_CC );
224 		RETURN_FALSE;
225 	}
226 
227 	/* Fetch the object. */
228 	DATE_FORMAT_METHOD_FETCH_OBJECT;
229 
230 	length = udat_toPattern(DATE_FORMAT_OBJECT(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo));
231 	if(INTL_DATA_ERROR_CODE(dfo) == U_BUFFER_OVERFLOW_ERROR && length >= USIZE( value_buf )) {
232 		++length; /* to avoid U_STRING_NOT_TERMINATED_WARNING */
233 		INTL_DATA_ERROR_CODE(dfo) = U_ZERO_ERROR;
234 		value = eumalloc(length);
235 		length = udat_toPattern(DATE_FORMAT_OBJECT(dfo), is_pattern_localized, value, length, &INTL_DATA_ERROR_CODE(dfo) );
236 		if(U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
237 			efree(value);
238 			value = value_buf;
239 		}
240 	}
241 	INTL_METHOD_CHECK_STATUS(dfo, "Error getting formatter pattern" );
242 
243 	INTL_METHOD_RETVAL_UTF8( dfo, value, length, ( value != value_buf ) );
244 }
245 /* }}} */
246 
247 /* {{{ proto bool IntlDateFormatter::setPattern( string $pattern )
248  * Set formatter pattern. }}} */
249 /* {{{ proto bool datefmt_set_pattern( IntlDateFormatter $mf, string $pattern )
250  * Set formatter pattern.
251  */
PHP_FUNCTION(datefmt_set_pattern)252 PHP_FUNCTION( datefmt_set_pattern )
253 {
254 	char*       value = NULL;
255 	int         value_len = 0;
256 	int         slength = 0;
257 	UChar*	    svalue  = NULL;
258 	zend_bool   is_pattern_localized =FALSE;
259 
260 
261 	DATE_FORMAT_METHOD_INIT_VARS;
262 
263 	/* Parse parameters. */
264 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
265 		&object, IntlDateFormatter_ce_ptr,  &value, &value_len ) == FAILURE )
266 	{
267 		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
268 			"datefmt_set_pattern: unable to parse input params", 0 TSRMLS_CC);
269 		RETURN_FALSE;
270 	}
271 
272 	DATE_FORMAT_METHOD_FETCH_OBJECT;
273 
274 	/* Convert given pattern to UTF-16. */
275 	intl_convert_utf8_to_utf16(&svalue, &slength, value, value_len, &INTL_DATA_ERROR_CODE(dfo));
276 	INTL_METHOD_CHECK_STATUS(dfo, "Error converting pattern to UTF-16" );
277 
278 	udat_applyPattern(DATE_FORMAT_OBJECT(dfo), (UBool)is_pattern_localized, svalue, slength);
279 
280 	if (svalue) {
281 		efree(svalue);
282 	}
283 	INTL_METHOD_CHECK_STATUS(dfo, "Error setting symbol value");
284 
285 	RETURN_TRUE;
286 }
287 /* }}} */
288 
289 /* {{{ proto string IntlDateFormatter::getLocale()
290  * Get formatter locale. }}} */
291 /* {{{ proto string datefmt_get_locale(IntlDateFormatter $mf)
292  * Get formatter locale.
293  */
PHP_FUNCTION(datefmt_get_locale)294 PHP_FUNCTION( datefmt_get_locale )
295 {
296 	char *loc;
297 	long  loc_type =ULOC_ACTUAL_LOCALE;
298 
299 	DATE_FORMAT_METHOD_INIT_VARS;
300 
301 	/* Parse parameters. */
302 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l",
303 		&object, IntlDateFormatter_ce_ptr,&loc_type) == FAILURE )
304 	{
305 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
306 			"datefmt_get_locale: unable to parse input params", 0 TSRMLS_CC );
307 
308 		RETURN_FALSE;
309 	}
310 
311 	/* Fetch the object. */
312 	DATE_FORMAT_METHOD_FETCH_OBJECT;
313 
314 	loc = (char *)udat_getLocaleByType(DATE_FORMAT_OBJECT(dfo), loc_type,&INTL_DATA_ERROR_CODE(dfo));
315 	INTL_METHOD_CHECK_STATUS(dfo, "Error getting locale");
316 	RETURN_STRING(loc, 1);
317 }
318 /* }}} */
319 
320 /* {{{ proto string IntlDateFormatter::isLenient()
321  * Get formatter isLenient. }}} */
322 /* {{{ proto string datefmt_isLenient(IntlDateFormatter $mf)
323  * Get formatter locale.
324  */
PHP_FUNCTION(datefmt_is_lenient)325 PHP_FUNCTION( datefmt_is_lenient )
326 {
327 
328 	DATE_FORMAT_METHOD_INIT_VARS;
329 
330 	/* Parse parameters. */
331 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
332 		&object, IntlDateFormatter_ce_ptr ) == FAILURE )
333 	{
334 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
335 			"datefmt_is_lenient: unable to parse input params", 0 TSRMLS_CC );
336 
337 		RETURN_FALSE;
338 	}
339 
340 	/* Fetch the object. */
341 	DATE_FORMAT_METHOD_FETCH_OBJECT;
342 
343 	RETVAL_BOOL(udat_isLenient(DATE_FORMAT_OBJECT(dfo)));
344 }
345 /* }}} */
346 
347 /* {{{ proto string IntlDateFormatter::setLenient()
348  * Set formatter lenient. }}} */
349 /* {{{ proto string datefmt_setLenient(IntlDateFormatter $mf)
350  * Set formatter lenient.
351  */
PHP_FUNCTION(datefmt_set_lenient)352 PHP_FUNCTION( datefmt_set_lenient )
353 {
354 	zend_bool isLenient  = FALSE;
355 
356 	DATE_FORMAT_METHOD_INIT_VARS;
357 
358 	/* Parse parameters. */
359 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob",
360 	&object, IntlDateFormatter_ce_ptr,&isLenient ) == FAILURE )
361 	{
362 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
363 			"datefmt_set_lenient: unable to parse input params", 0 TSRMLS_CC );
364 		RETURN_FALSE;
365 	}
366 
367 	/* Fetch the object. */
368 	DATE_FORMAT_METHOD_FETCH_OBJECT;
369 
370 	udat_setLenient(DATE_FORMAT_OBJECT(dfo), (UBool)isLenient );
371 }
372 /* }}} */
373 
374 /* {{{ proto bool IntlDateFormatter::setPattern( int $calendar )
375  * Set formatter calendar. }}} */
376 /* {{{ proto bool datefmt_set_calendar( IntlDateFormatter $mf, int $calendar )
377  * Set formatter calendar.
378  */
PHP_FUNCTION(datefmt_set_calendar)379 PHP_FUNCTION( datefmt_set_calendar )
380 {
381 	long	calendar = 0;
382 
383 	DATE_FORMAT_METHOD_INIT_VARS;
384 
385 	/* Parse parameters. */
386 	if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
387 		&object, IntlDateFormatter_ce_ptr, &calendar ) == FAILURE ) {
388 		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
389 			"datefmt_set_calendar: unable to parse input params", 0 TSRMLS_CC);
390 		RETURN_FALSE;
391 	}
392 
393 	/* check for the validity  of value of calendar passed */
394 	intl_error_reset( NULL TSRMLS_CC );
395 	if (calendar > 1) {
396 		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
397 			"datefmt_set_calendar: calendar value specified is out of valid range", 0 TSRMLS_CC);
398 		RETURN_FALSE;
399 	}
400 
401 	DATE_FORMAT_METHOD_FETCH_OBJECT;
402 
403 	internal_set_calendar( dfo, dfo->timezone_id, strlen(dfo->timezone_id), calendar, return_value TSRMLS_CC );
404 
405 	/* Set the calendar  value in the IntlDateFormatter object */
406 	dfo->calendar = calendar;
407 
408 	RETURN_TRUE;
409 }
410 /* }}} */
411 
412 
413