intl_error.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. +----------------------------------------------------------------------+
  3. | This source file is subject to version 3.01 of the PHP license, |
  4. | that is bundled with this package in the file LICENSE, and is |
  5. | available through the world-wide-web at the following url: |
  6. | https://www.php.net/license/3_01.txt |
  7. | If you did not receive a copy of the PHP license and are unable to |
  8. | obtain it through the world-wide-web, please send a note to |
  9. | license@php.net so we can mail you a copy immediately. |
  10. +----------------------------------------------------------------------+
  11. | Authors: Vadim Savchuk <vsavchuk@productengine.com> |
  12. | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
  13. | Stanislav Malyshev <stas@zend.com> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include <php.h>
  20. #include <zend_exceptions.h>
  21. #include "php_intl.h"
  22. #include "intl_error.h"
  23. #include "intl_convert.h"
  24. ZEND_EXTERN_MODULE_GLOBALS( intl )
  25. zend_class_entry *IntlException_ce_ptr;
  26. /* {{{ Return global error structure. */
  27. static intl_error* intl_g_error_get( void )
  28. {
  29. return &INTL_G( g_error );
  30. }
  31. /* }}} */
  32. /* {{{ Free mem. */
  33. static void intl_free_custom_error_msg( intl_error* err )
  34. {
  35. if( !err && !( err = intl_g_error_get( ) ) )
  36. return;
  37. if(err->free_custom_error_message ) {
  38. efree( err->custom_error_message );
  39. }
  40. err->custom_error_message = NULL;
  41. err->free_custom_error_message = 0;
  42. }
  43. /* }}} */
  44. /* {{{ Create and initialize internals of 'intl_error'. */
  45. intl_error* intl_error_create( void )
  46. {
  47. intl_error* err = ecalloc( 1, sizeof( intl_error ) );
  48. intl_error_init( err );
  49. return err;
  50. }
  51. /* }}} */
  52. /* {{{ Initialize internals of 'intl_error'. */
  53. void intl_error_init( intl_error* err )
  54. {
  55. if( !err && !( err = intl_g_error_get( ) ) )
  56. return;
  57. err->code = U_ZERO_ERROR;
  58. err->custom_error_message = NULL;
  59. err->free_custom_error_message = 0;
  60. }
  61. /* }}} */
  62. /* {{{ Set last error code to 0 and unset last error message */
  63. void intl_error_reset( intl_error* err )
  64. {
  65. if( !err && !( err = intl_g_error_get( ) ) )
  66. return;
  67. err->code = U_ZERO_ERROR;
  68. intl_free_custom_error_msg( err );
  69. }
  70. /* }}} */
  71. /* {{{ Set last error message to msg copying it if needed. */
  72. void intl_error_set_custom_msg( intl_error* err, const char* msg, int copyMsg )
  73. {
  74. if( !msg )
  75. return;
  76. if( !err ) {
  77. if( INTL_G( error_level ) )
  78. php_error_docref( NULL, INTL_G( error_level ), "%s", msg );
  79. if( INTL_G( use_exceptions ) )
  80. zend_throw_exception_ex( IntlException_ce_ptr, 0, "%s", msg );
  81. }
  82. if( !err && !( err = intl_g_error_get( ) ) )
  83. return;
  84. /* Free previous message if any */
  85. intl_free_custom_error_msg( err );
  86. /* Mark message copied if any */
  87. err->free_custom_error_message = copyMsg;
  88. /* Set user's error text message */
  89. err->custom_error_message = copyMsg ? estrdup( msg ) : (char *) msg;
  90. }
  91. /* }}} */
  92. /* {{{ Create output message in format "<intl_error_text>: <extra_user_error_text>". */
  93. zend_string * intl_error_get_message( intl_error* err )
  94. {
  95. const char *uErrorName = NULL;
  96. zend_string *errMessage = 0;
  97. if( !err && !( err = intl_g_error_get( ) ) )
  98. return ZSTR_EMPTY_ALLOC();
  99. uErrorName = u_errorName( err->code );
  100. /* Format output string */
  101. if( err->custom_error_message )
  102. {
  103. errMessage = strpprintf(0, "%s: %s", err->custom_error_message, uErrorName );
  104. }
  105. else
  106. {
  107. errMessage = strpprintf(0, "%s", uErrorName );
  108. }
  109. return errMessage;
  110. }
  111. /* }}} */
  112. /* {{{ Set last error code. */
  113. void intl_error_set_code( intl_error* err, UErrorCode err_code )
  114. {
  115. if( !err && !( err = intl_g_error_get( ) ) )
  116. return;
  117. err->code = err_code;
  118. }
  119. /* }}} */
  120. /* {{{ Return last error code. */
  121. UErrorCode intl_error_get_code( intl_error* err )
  122. {
  123. if( !err && !( err = intl_g_error_get( ) ) )
  124. return U_ZERO_ERROR;
  125. return err->code;
  126. }
  127. /* }}} */
  128. /* {{{ Set error code and message. */
  129. void intl_error_set( intl_error* err, UErrorCode code, const char* msg, int copyMsg )
  130. {
  131. intl_error_set_code( err, code );
  132. intl_error_set_custom_msg( err, msg, copyMsg );
  133. }
  134. /* }}} */
  135. /* {{{ Set error code and message. */
  136. void intl_errors_set( intl_error* err, UErrorCode code, const char* msg, int copyMsg )
  137. {
  138. intl_errors_set_code( err, code );
  139. intl_errors_set_custom_msg( err, msg, copyMsg );
  140. }
  141. /* }}} */
  142. /* {{{ */
  143. void intl_errors_reset( intl_error* err )
  144. {
  145. if(err) {
  146. intl_error_reset( err );
  147. }
  148. intl_error_reset( NULL );
  149. }
  150. /* }}} */
  151. /* {{{ */
  152. void intl_errors_set_custom_msg( intl_error* err, const char* msg, int copyMsg )
  153. {
  154. if(err) {
  155. intl_error_set_custom_msg( err, msg, copyMsg );
  156. }
  157. intl_error_set_custom_msg( NULL, msg, copyMsg );
  158. }
  159. /* }}} */
  160. /* {{{ */
  161. void intl_errors_set_code( intl_error* err, UErrorCode err_code )
  162. {
  163. if(err) {
  164. intl_error_set_code( err, err_code );
  165. }
  166. intl_error_set_code( NULL, err_code );
  167. }
  168. /* }}} */
  169. smart_str intl_parse_error_to_string( UParseError* pe )
  170. {
  171. smart_str ret = {0};
  172. zend_string *u8str;
  173. UErrorCode status;
  174. int any = 0;
  175. assert( pe != NULL );
  176. smart_str_appends( &ret, "parse error " );
  177. if( pe->line > 0 )
  178. {
  179. smart_str_appends( &ret, "on line " );
  180. smart_str_append_long( &ret, (zend_long ) pe->line );
  181. any = 1;
  182. }
  183. if( pe->offset >= 0 ) {
  184. if( any )
  185. smart_str_appends( &ret, ", " );
  186. else
  187. smart_str_appends( &ret, "at " );
  188. smart_str_appends( &ret, "offset " );
  189. smart_str_append_long( &ret, (zend_long ) pe->offset );
  190. any = 1;
  191. }
  192. if (pe->preContext[0] != 0 ) {
  193. if( any )
  194. smart_str_appends( &ret, ", " );
  195. smart_str_appends( &ret, "after \"" );
  196. u8str = intl_convert_utf16_to_utf8(pe->preContext, -1, &status );
  197. if( !u8str )
  198. {
  199. smart_str_appends( &ret, "(could not convert parser error pre-context to UTF-8)" );
  200. }
  201. else {
  202. smart_str_append( &ret, u8str );
  203. zend_string_release_ex( u8str, 0 );
  204. }
  205. smart_str_appends( &ret, "\"" );
  206. any = 1;
  207. }
  208. if( pe->postContext[0] != 0 )
  209. {
  210. if( any )
  211. smart_str_appends( &ret, ", " );
  212. smart_str_appends( &ret, "before or at \"" );
  213. u8str = intl_convert_utf16_to_utf8(pe->postContext, -1, &status );
  214. if( !u8str )
  215. {
  216. smart_str_appends( &ret, "(could not convert parser error post-context to UTF-8)" );
  217. }
  218. else
  219. {
  220. smart_str_append( &ret, u8str );
  221. zend_string_release_ex( u8str, 0 );
  222. }
  223. smart_str_appends( &ret, "\"" );
  224. any = 1;
  225. }
  226. if( !any )
  227. {
  228. smart_str_free( &ret );
  229. smart_str_appends( &ret, "no parse error" );
  230. }
  231. smart_str_0( &ret );
  232. return ret;
  233. }