1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
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: Andrei Zmievski <andrei@php.net> |
14 : | Wez Furlong <wez@php.net> |
15 : +----------------------------------------------------------------------+
16 : */
17 :
18 : /* $Id: unicode.c 284419 2009-07-20 09:42:52Z pajoye $ */
19 :
20 : #include "php_unicode.h"
21 : #include "zend_unicode.h"
22 : #include "php_property.h"
23 : #include "php_transform.h"
24 :
25 : void php_register_unicode_iterators(TSRMLS_D);
26 :
27 : /* {{{ proto unicode unicode_decode(binary input, string encoding [, int flags]) U
28 : Takes a binary string converts it to a Unicode string using the specifed encoding */
29 : static PHP_FUNCTION(unicode_decode)
30 1391 : {
31 : char *str, *enc;
32 : int str_len, enc_len;
33 : long flags;
34 : UChar *dest;
35 : int dest_len;
36 : UErrorCode status;
37 1391 : UConverter *conv = NULL;
38 : int num_conv;
39 :
40 1391 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ss|l", &str, &str_len, &enc, &enc_len, &flags)) {
41 0 : return;
42 : }
43 :
44 1391 : if (ZEND_NUM_ARGS() > 2) {
45 1 : if ((flags & 0xff) > ZEND_CONV_ERROR_LAST_ENUM) {
46 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal value for conversion error mode");
47 0 : RETURN_FALSE;
48 : }
49 : } else {
50 1390 : flags = UG(to_error_mode);
51 : }
52 :
53 1391 : status = U_ZERO_ERROR;
54 1391 : conv = ucnv_open(enc, &status);
55 1391 : if (U_FAILURE(status)) {
56 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not create converter for '%s' encoding", enc);
57 0 : RETURN_FALSE;
58 : }
59 :
60 1391 : zend_set_converter_error_mode(conv, ZEND_TO_UNICODE, (uint16_t) flags);
61 :
62 1391 : status = U_ZERO_ERROR;
63 1391 : num_conv = zend_string_to_unicode_ex(conv, &dest, &dest_len, str, str_len, &status);
64 1391 : if (U_FAILURE(status)) {
65 0 : zend_raise_conversion_error_ex("could not decode binary string", conv, ZEND_TO_UNICODE, num_conv TSRMLS_CC);
66 0 : efree(dest);
67 0 : ucnv_close(conv);
68 0 : RETURN_FALSE;
69 : }
70 1391 : ucnv_close(conv);
71 :
72 1391 : RETVAL_UNICODEL(dest, dest_len, 0);
73 : }
74 : /* }}} */
75 :
76 : /* {{{ proto binary unicode_encode(unicode input, string encoding [, int flags]) U
77 : Takes a Unicode string and converts it to a binary string using the specified encoding */
78 : static PHP_FUNCTION(unicode_encode)
79 0 : {
80 : UChar *uni;
81 : char *enc;
82 : int uni_len, enc_len;
83 : long flags;
84 : char *dest;
85 : int dest_len;
86 : UErrorCode status;
87 0 : UConverter *conv = NULL;
88 : int num_conv;
89 :
90 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Us|l", &uni, &uni_len, &enc, &enc_len, &flags) == FAILURE) {
91 0 : return;
92 : }
93 :
94 0 : if (ZEND_NUM_ARGS() > 2) {
95 0 : if ((flags & 0xff) > ZEND_CONV_ERROR_LAST_ENUM) {
96 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal value for conversion error mode");
97 0 : RETURN_FALSE;
98 : }
99 : } else {
100 0 : flags = UG(from_error_mode);
101 : }
102 :
103 0 : status = U_ZERO_ERROR;
104 0 : conv = ucnv_open(enc, &status);
105 0 : if (U_FAILURE(status)) {
106 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not create converter for '%s' encoding", enc);
107 0 : RETURN_FALSE;
108 : }
109 :
110 0 : zend_set_converter_error_mode(conv, ZEND_FROM_UNICODE, (uint16_t) flags);
111 0 : zend_set_converter_subst_char(conv, UG(from_subst_char));
112 :
113 0 : status = U_ZERO_ERROR;
114 0 : num_conv = zend_unicode_to_string_ex(conv, &dest, &dest_len, uni, uni_len, &status);
115 0 : if (U_FAILURE(status)) {
116 0 : int32_t offset = u_countChar32(uni, num_conv);
117 0 : zend_raise_conversion_error_ex("could not encode Unicode string", conv, ZEND_FROM_UNICODE, offset TSRMLS_CC);
118 0 : efree(dest);
119 0 : ucnv_close(conv);
120 0 : RETURN_FALSE;
121 : }
122 0 : ucnv_close(conv);
123 :
124 0 : RETVAL_STRINGL(dest, dest_len, 0);
125 : }
126 : /* }}} */
127 :
128 : /* {{{ proto bool unicode_set_error_mode(int direction, int mode) U
129 : Sets global conversion error mode for the specified conversion direction */
130 : PHP_FUNCTION(unicode_set_error_mode)
131 3 : {
132 : zend_conv_direction direction;
133 : long tmp, mode;
134 :
135 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &tmp, &mode) == FAILURE) {
136 0 : return;
137 : }
138 3 : direction = (zend_conv_direction) tmp;
139 :
140 3 : if (direction != ZEND_FROM_UNICODE && direction != ZEND_TO_UNICODE) {
141 0 : php_error(E_WARNING, "Invalid conversion direction value");
142 0 : RETURN_FALSE;
143 : }
144 :
145 3 : if ((mode & 0xff) > ZEND_CONV_ERROR_LAST_ENUM) {
146 0 : php_error(E_WARNING, "Illegal value for conversion error mode");
147 0 : RETURN_FALSE;
148 : }
149 :
150 3 : if (direction == ZEND_FROM_UNICODE) {
151 0 : UG(from_error_mode) = (uint16_t) mode;
152 : } else {
153 3 : UG(to_error_mode) = (uint16_t) mode;
154 : }
155 :
156 3 : zend_update_converters_error_behavior(TSRMLS_C);
157 3 : RETURN_TRUE;
158 : }
159 : /* }}} */
160 :
161 : /* {{{ proto bool unicode_set_subst_char(string character) U
162 : Sets global substitution character for conversion from Unicode to codepage */
163 : PHP_FUNCTION(unicode_set_subst_char)
164 0 : {
165 : UChar *subst_char;
166 : UChar32 cp;
167 : int subst_char_len, len;
168 :
169 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "u", &subst_char, &subst_char_len) == FAILURE) {
170 0 : return;
171 : }
172 :
173 0 : if (subst_char_len < 1 ) {
174 0 : php_error(E_WARNING, "Empty substitution character");
175 0 : RETURN_FALSE;
176 : }
177 :
178 0 : cp = zend_get_codepoint_at(subst_char, subst_char_len, 0);
179 :
180 0 : if (cp < 0 || cp >= UCHAR_MAX_VALUE) {
181 0 : zend_error(E_WARNING, "Substitution character value U+%06x is out of range (0 - 0x10FFFF)", cp);
182 0 : RETURN_FALSE;
183 : }
184 :
185 0 : len = zend_codepoint_to_uchar(cp, UG(from_subst_char));
186 0 : UG(from_subst_char)[len] = 0;
187 0 : zend_update_converters_error_behavior(TSRMLS_C);
188 0 : RETURN_TRUE;
189 : }
190 : /* }}} */
191 :
192 : /* {{{ proto int unicode_get_error_mode(int direction) U
193 : Returns global conversion error mode for the specified conversion direction */
194 : PHP_FUNCTION(unicode_get_error_mode)
195 0 : {
196 : zend_conv_direction direction;
197 : long tmp;
198 :
199 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &tmp) == FAILURE) {
200 0 : return;
201 : }
202 0 : direction = (zend_conv_direction) tmp;
203 :
204 0 : if (direction == ZEND_FROM_UNICODE) {
205 0 : RETURN_LONG(UG(from_error_mode));
206 0 : } else if (direction == ZEND_TO_UNICODE) {
207 0 : RETURN_LONG(UG(to_error_mode));
208 : } else {
209 0 : php_error(E_WARNING, "Invalid conversion direction value");
210 0 : RETURN_FALSE;
211 : }
212 : }
213 : /* }}} */
214 :
215 : /* {{{ proto string unicode_get_subst_char() U
216 : Returns global substitution character for conversion from Unicode to codepage */
217 : PHP_FUNCTION(unicode_get_subst_char)
218 0 : {
219 0 : if (zend_parse_parameters_none() == FAILURE) {
220 0 : return;
221 : }
222 :
223 0 : RETURN_UNICODE(UG(from_subst_char), 1);
224 : }
225 : /* }}} */
226 :
227 : /* {{{ proto callback unicode_set_error_handler(callback new_callback) U
228 : Set (or clear) the custom Unicode conversion error handler */
229 : PHP_FUNCTION(unicode_set_error_handler)
230 0 : {
231 : zval *error_handler;
232 0 : zend_bool had_orig_error_handler=0;
233 : zval error_handler_name;
234 :
235 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &error_handler) == FAILURE) {
236 0 : return;
237 : }
238 :
239 0 : if (Z_TYPE_P(error_handler) != IS_NULL) { /* NULL == unset */
240 0 : if (!zend_is_callable(error_handler, 0, &error_handler_name TSRMLS_CC)) {
241 0 : zend_error(E_WARNING, "%v() expects the argument (%R) to be a valid callback",
242 : get_active_function_name(TSRMLS_C), Z_TYPE(error_handler_name), Z_UNIVAL(error_handler_name));
243 0 : zval_dtor(&error_handler_name);
244 0 : return;
245 : }
246 0 : zval_dtor(&error_handler_name);
247 : }
248 :
249 0 : if (UG(conv_error_handler)) {
250 0 : had_orig_error_handler = 1;
251 0 : *return_value = *UG(conv_error_handler);
252 0 : zval_copy_ctor(return_value);
253 0 : zend_ptr_stack_push(&UG(conv_error_handlers), UG(conv_error_handler));
254 : }
255 0 : ALLOC_ZVAL(UG(conv_error_handler));
256 :
257 0 : if (Z_TYPE_P(error_handler) == IS_NULL) { /* unset user-defined handler */
258 0 : FREE_ZVAL(UG(conv_error_handler));
259 0 : UG(conv_error_handler) = NULL;
260 0 : zval_dtor(return_value);
261 0 : RETURN_TRUE;
262 : }
263 :
264 0 : *UG(conv_error_handler) = *error_handler;
265 0 : zval_copy_ctor(UG(conv_error_handler));
266 :
267 0 : if (!had_orig_error_handler) {
268 0 : RETURN_NULL();
269 : }
270 : }
271 : /* }}} */
272 :
273 : /* {{{ proto bool unicode_restore_error_handler(void) U
274 : Restores the active error handler to the one which was previously active (before the last unicode_set_error_handler() call) */
275 : PHP_FUNCTION(unicode_restore_error_handler)
276 0 : {
277 0 : if (UG(conv_error_handler)) {
278 0 : zval *ceh = UG(conv_error_handler);
279 :
280 0 : UG(conv_error_handler) = NULL;
281 0 : zval_ptr_dtor(&ceh);
282 : }
283 :
284 0 : if (zend_ptr_stack_num_elements(&UG(conv_error_handlers))==0) {
285 0 : UG(conv_error_handler) = NULL;
286 : } else {
287 0 : UG(conv_error_handler) = zend_ptr_stack_pop(&UG(conv_error_handlers));
288 : }
289 0 : RETURN_TRUE;
290 : }
291 : /* }}} */
292 :
293 : /* {{{ unicode_functions[] */
294 : const zend_function_entry unicode_functions[] = {
295 : PHP_FE(locale_get_default, NULL)
296 : PHP_FE(locale_set_default, NULL)
297 : PHP_FE(unicode_decode, NULL)
298 : PHP_FE(unicode_encode, NULL)
299 : PHP_FE(unicode_set_error_handler, NULL)
300 : PHP_FE(unicode_restore_error_handler, NULL)
301 : PHP_FE(unicode_set_error_mode, NULL)
302 : PHP_FE(unicode_set_subst_char, NULL)
303 : PHP_FE(unicode_get_error_mode, NULL)
304 : PHP_FE(unicode_get_subst_char, NULL)
305 : PHP_FE(collator_create, NULL)
306 : PHP_FE(collator_compare, NULL)
307 : PHP_FE(collator_get_default, NULL)
308 : PHP_FE(collator_set_default, NULL)
309 :
310 : /* character property functions */
311 : PHP_FE(char_is_lower, NULL)
312 : PHP_FE(char_is_upper, NULL)
313 : PHP_FE(char_is_digit, NULL)
314 : PHP_FE(char_is_alpha, NULL)
315 : PHP_FE(char_is_alnum, NULL)
316 : PHP_FE(char_is_xdigit, NULL)
317 : PHP_FE(char_is_punct, NULL)
318 : PHP_FE(char_is_graph, NULL)
319 : PHP_FE(char_is_blank, NULL)
320 : PHP_FE(char_is_space, NULL)
321 : PHP_FE(char_is_cntrl, NULL)
322 : PHP_FE(char_is_print, NULL)
323 :
324 : PHP_FE(char_is_defined, NULL)
325 : PHP_FE(char_is_id_start, NULL)
326 : PHP_FE(char_is_id_part, NULL)
327 : PHP_FE(char_is_id_ignorable, NULL)
328 : PHP_FE(char_is_iso_control, NULL)
329 : PHP_FE(char_is_mirrored, NULL)
330 : PHP_FE(char_is_base, NULL)
331 : PHP_FE(char_is_whitespace, NULL)
332 : PHP_FE(char_is_alphabetic, NULL)
333 : PHP_FE(char_is_uppercase, NULL)
334 : PHP_FE(char_is_lowercase, NULL)
335 : PHP_FE(char_is_titlecase, NULL)
336 :
337 : PHP_FE(char_get_numeric_value, NULL)
338 : PHP_FE(char_get_digit_value, NULL)
339 : PHP_FE(char_get_combining_class, NULL)
340 : PHP_FE(char_get_mirrored, NULL)
341 : PHP_FE(char_get_direction, NULL)
342 : PHP_FE(char_get_age, NULL)
343 : PHP_FE(char_get_type, NULL)
344 : PHP_FE(char_is_valid, NULL)
345 :
346 : PHP_FE(char_from_digit, NULL)
347 : PHP_FE(char_from_name, NULL)
348 : PHP_FE(char_get_name, NULL)
349 : PHP_FE(char_has_binary_property, NULL)
350 : PHP_FE(char_get_property_value, NULL)
351 : PHP_FE(char_get_property_min_value, NULL)
352 : PHP_FE(char_get_property_max_value, NULL)
353 : PHP_FE(char_get_property_name, NULL)
354 : PHP_FE(char_get_property_from_name, NULL)
355 : PHP_FE(char_get_property_value_name, NULL)
356 : PHP_FE(char_get_property_value_from_name, NULL)
357 :
358 : PHP_FE(char_enum_names, NULL)
359 : PHP_FE(char_enum_types, NULL)
360 :
361 : /* text transformation functions */
362 : PHP_FE(str_transliterate, NULL)
363 :
364 : { NULL, NULL, NULL }
365 : };
366 : /* }}} */
367 :
368 : /* {{{ unicode_module_entry
369 : */
370 : zend_module_entry unicode_module_entry = {
371 : STANDARD_MODULE_HEADER,
372 : "unicode",
373 : unicode_functions,
374 : PHP_MINIT(unicode), /* Replace with NULL if there is nothing to do at php startup */
375 : PHP_MSHUTDOWN(unicode), /* Replace with NULL if there is nothing to do at php shutdown */
376 : PHP_RINIT(unicode), /* Replace with NULL if there is nothing to do at request start */
377 : PHP_RSHUTDOWN(unicode), /* Replace with NULL if there is nothing to do at request end */
378 : PHP_MINFO(unicode),
379 : "1.0",
380 : STANDARD_MODULE_PROPERTIES
381 : };
382 : /* }}} */
383 :
384 : #ifdef COMPILE_DL_UNICODE
385 : ZEND_GET_MODULE(unicode)
386 : #endif
387 :
388 : /* {{{ PHP_MINIT_FUNCTION */
389 : PHP_MINIT_FUNCTION(unicode)
390 17007 : {
391 17007 : php_register_unicode_iterators(TSRMLS_C);
392 17007 : php_init_collation(TSRMLS_C);
393 17007 : php_register_unicode_constants(TSRMLS_C);
394 :
395 17007 : return SUCCESS;
396 : }
397 : /* }}} */
398 :
399 : /* {{{ PHP_MSHUTDOWN_FUNCTION */
400 : PHP_MSHUTDOWN_FUNCTION(unicode)
401 17039 : {
402 : /* add your stuff here */
403 :
404 :
405 17039 : return SUCCESS;
406 : }
407 : /* }}} */
408 :
409 : /* {{{ PHP_RINIT_FUNCTION */
410 : PHP_RINIT_FUNCTION(unicode)
411 16993 : {
412 16993 : return SUCCESS;
413 : }
414 : /* }}} */
415 :
416 : /* {{{ PHP_RSHUTDOWN_FUNCTION */
417 : PHP_RSHUTDOWN_FUNCTION(unicode)
418 17025 : {
419 17025 : return SUCCESS;
420 : }
421 : /* }}} */
422 :
423 : /* {{{ PHP_MINFO_FUNCTION */
424 : PHP_MINFO_FUNCTION(unicode)
425 43 : {
426 43 : php_info_print_box_start(0);
427 43 : php_info_print_table_row(2, "ICU API extension", "enabled");
428 43 : php_info_print_table_row(2, "Based on ICU library", U_COPYRIGHT_STRING);
429 43 : php_info_print_table_row(2, "ICU Version", U_ICU_VERSION);
430 43 : php_info_print_box_end();
431 43 : }
432 : /* }}} */
433 :
434 :
435 :
436 : /*
437 : * Local variables:
438 : * tab-width: 4
439 : * c-basic-offset: 4
440 : * End:
441 : * vim600: noet sw=4 ts=4 fdm=marker
442 : * vim<600: noet sw=4 ts=4
443 : */
|