PageRenderTime 103ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/php5/ext/gettext/gettext.c

http://github.com/vpj/PHP-Extension-API
C | 392 lines | 260 code | 73 blank | 59 comment | 35 complexity | d6829e7b9f7097a84ff1f107a1e7767e MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2009 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Alex Plotnick <alex@wgate.com> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id: gettext.c,v 1.46.2.2.2.4.2.10 2008/12/31 11:15:37 sebastian Exp $ */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #if HAVE_LIBINTL
  24. #include <stdio.h>
  25. #include "ext/standard/info.h"
  26. #include "php_gettext.h"
  27. /* {{{ arginfo */
  28. ZEND_BEGIN_ARG_INFO(arginfo_textdomain, 0)
  29. ZEND_ARG_INFO(0, domain)
  30. ZEND_END_ARG_INFO()
  31. ZEND_BEGIN_ARG_INFO(arginfo_gettext, 0)
  32. ZEND_ARG_INFO(0, msgid)
  33. ZEND_END_ARG_INFO()
  34. ZEND_BEGIN_ARG_INFO(arginfo_dgettext, 0)
  35. ZEND_ARG_INFO(0, domain_name)
  36. ZEND_ARG_INFO(0, msgid)
  37. ZEND_END_ARG_INFO()
  38. ZEND_BEGIN_ARG_INFO(arginfo_dcgettext, 0)
  39. ZEND_ARG_INFO(0, domain_name)
  40. ZEND_ARG_INFO(0, msgid)
  41. ZEND_ARG_INFO(0, category)
  42. ZEND_END_ARG_INFO()
  43. ZEND_BEGIN_ARG_INFO(arginfo_bindtextdomain, 0)
  44. ZEND_ARG_INFO(0, domain_name)
  45. ZEND_ARG_INFO(0, dir)
  46. ZEND_END_ARG_INFO()
  47. #if HAVE_NGETTEXT
  48. ZEND_BEGIN_ARG_INFO(arginfo_ngettext, 0)
  49. ZEND_ARG_INFO(0, msgid1)
  50. ZEND_ARG_INFO(0, msgid2)
  51. ZEND_ARG_INFO(0, count)
  52. ZEND_END_ARG_INFO()
  53. #endif
  54. #if HAVE_DNGETTEXT
  55. ZEND_BEGIN_ARG_INFO(arginfo_dngettext, 0)
  56. ZEND_ARG_INFO(0, domain)
  57. ZEND_ARG_INFO(0, msgid1)
  58. ZEND_ARG_INFO(0, msgid2)
  59. ZEND_ARG_INFO(0, count)
  60. ZEND_END_ARG_INFO()
  61. #endif
  62. #if HAVE_DCNGETTEXT
  63. ZEND_BEGIN_ARG_INFO(arginfo_dcngettext, 0)
  64. ZEND_ARG_INFO(0, domain)
  65. ZEND_ARG_INFO(0, msgid1)
  66. ZEND_ARG_INFO(0, msgid2)
  67. ZEND_ARG_INFO(0, count)
  68. ZEND_ARG_INFO(0, category)
  69. ZEND_END_ARG_INFO()
  70. #endif
  71. #if HAVE_BIND_TEXTDOMAIN_CODESET
  72. ZEND_BEGIN_ARG_INFO(arginfo_bind_textdomain_codeset, 0)
  73. ZEND_ARG_INFO(0, domain)
  74. ZEND_ARG_INFO(0, codeset)
  75. ZEND_END_ARG_INFO()
  76. #endif
  77. /* }}} */
  78. /* {{{ php_gettext_functions[]
  79. */
  80. const zend_function_entry php_gettext_functions[] = {
  81. PHP_NAMED_FE(textdomain, zif_textdomain, arginfo_textdomain)
  82. PHP_NAMED_FE(gettext, zif_gettext, arginfo_gettext)
  83. /* Alias for gettext() */
  84. PHP_NAMED_FE(_, zif_gettext, arginfo_gettext)
  85. PHP_NAMED_FE(dgettext, zif_dgettext, arginfo_dgettext)
  86. PHP_NAMED_FE(dcgettext, zif_dcgettext, arginfo_dcgettext)
  87. PHP_NAMED_FE(bindtextdomain, zif_bindtextdomain, arginfo_bindtextdomain)
  88. #if HAVE_NGETTEXT
  89. PHP_NAMED_FE(ngettext, zif_ngettext, arginfo_ngettext)
  90. #endif
  91. #if HAVE_DNGETTEXT
  92. PHP_NAMED_FE(dngettext, zif_dngettext, arginfo_dngettext)
  93. #endif
  94. #if HAVE_DCNGETTEXT
  95. PHP_NAMED_FE(dcngettext, zif_dcngettext, arginfo_dcngettext)
  96. #endif
  97. #if HAVE_BIND_TEXTDOMAIN_CODESET
  98. PHP_NAMED_FE(bind_textdomain_codeset, zif_bind_textdomain_codeset, arginfo_bind_textdomain_codeset)
  99. #endif
  100. {NULL, NULL, NULL}
  101. };
  102. /* }}} */
  103. #include <libintl.h>
  104. zend_module_entry php_gettext_module_entry = {
  105. STANDARD_MODULE_HEADER,
  106. "gettext",
  107. php_gettext_functions,
  108. NULL,
  109. NULL,
  110. NULL,
  111. NULL,
  112. PHP_MINFO(php_gettext),
  113. NO_VERSION_YET,
  114. STANDARD_MODULE_PROPERTIES
  115. };
  116. #ifdef COMPILE_DL_GETTEXT
  117. ZEND_GET_MODULE(php_gettext)
  118. #endif
  119. #define PHP_GETTEXT_MAX_DOMAIN_LENGTH 1024
  120. #define PHP_GETTEXT_MAX_MSGID_LENGTH 4096
  121. #define PHP_GETTEXT_DOMAIN_LENGTH_CHECK \
  122. if (domain_len > PHP_GETTEXT_MAX_DOMAIN_LENGTH) { \
  123. php_error_docref(NULL TSRMLS_CC, E_WARNING, "domain passed too long"); \
  124. RETURN_FALSE; \
  125. }
  126. #define PHP_GETTEXT_LENGTH_CHECK(check_name, check_len) \
  127. if (check_len > PHP_GETTEXT_MAX_MSGID_LENGTH) { \
  128. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s passed too long", check_name); \
  129. RETURN_FALSE; \
  130. }
  131. PHP_MINFO_FUNCTION(php_gettext)
  132. {
  133. php_info_print_table_start();
  134. php_info_print_table_row(2, "GetText Support", "enabled");
  135. php_info_print_table_end();
  136. }
  137. /* {{{ proto string textdomain(string domain)
  138. Set the textdomain to "domain". Returns the current domain */
  139. PHP_NAMED_FUNCTION(zif_textdomain)
  140. {
  141. char *domain, *domain_name, *retval;
  142. int domain_len;
  143. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &domain, &domain_len) == FAILURE) {
  144. return;
  145. }
  146. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  147. if (strcmp(domain, "") && strcmp(domain, "0")) {
  148. domain_name = domain;
  149. } else {
  150. domain_name = NULL;
  151. }
  152. retval = textdomain(domain_name);
  153. RETURN_STRING(retval, 1);
  154. }
  155. /* }}} */
  156. /* {{{ proto string gettext(string msgid)
  157. Return the translation of msgid for the current domain, or msgid unaltered if a translation does not exist */
  158. PHP_NAMED_FUNCTION(zif_gettext)
  159. {
  160. char *msgid, *msgstr;
  161. int msgid_len;
  162. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &msgid, &msgid_len) == FAILURE) {
  163. return;
  164. }
  165. PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
  166. msgstr = gettext(msgid);
  167. RETURN_STRING(msgstr, 1);
  168. }
  169. /* }}} */
  170. /* {{{ proto string dgettext(string domain_name, string msgid)
  171. Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist */
  172. PHP_NAMED_FUNCTION(zif_dgettext)
  173. {
  174. char *domain, *msgid, *msgstr;
  175. int domain_len, msgid_len;
  176. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &msgid, &msgid_len) == FAILURE) {
  177. return;
  178. }
  179. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  180. PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
  181. msgstr = dgettext(domain, msgid);
  182. RETURN_STRING(msgstr, 1);
  183. }
  184. /* }}} */
  185. /* {{{ proto string dcgettext(string domain_name, string msgid, long category)
  186. Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist */
  187. PHP_NAMED_FUNCTION(zif_dcgettext)
  188. {
  189. char *domain, *msgid, *msgstr;
  190. int domain_len, msgid_len;
  191. long category;
  192. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &domain, &domain_len, &msgid, &msgid_len, &category) == FAILURE) {
  193. return;
  194. }
  195. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  196. PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
  197. msgstr = dcgettext(domain, msgid, category);
  198. RETURN_STRING(msgstr, 1);
  199. }
  200. /* }}} */
  201. /* {{{ proto string bindtextdomain(string domain_name, string dir)
  202. Bind to the text domain domain_name, looking for translations in dir. Returns the current domain */
  203. PHP_NAMED_FUNCTION(zif_bindtextdomain)
  204. {
  205. char *domain, *dir;
  206. int domain_len, dir_len;
  207. char *retval, dir_name[MAXPATHLEN];
  208. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &dir, &dir_len) == FAILURE) {
  209. return;
  210. }
  211. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  212. if (domain[0] == '\0') {
  213. php_error(E_WARNING, "The first parameter of bindtextdomain must not be empty");
  214. RETURN_FALSE;
  215. }
  216. if (dir[0] != '\0' && strcmp(dir, "0")) {
  217. if (!VCWD_REALPATH(dir, dir_name)) {
  218. RETURN_FALSE;
  219. }
  220. } else if (!VCWD_GETCWD(dir_name, MAXPATHLEN)) {
  221. RETURN_FALSE;
  222. }
  223. retval = bindtextdomain(domain, dir_name);
  224. RETURN_STRING(retval, 1);
  225. }
  226. /* }}} */
  227. #if HAVE_NGETTEXT
  228. /* {{{ proto string ngettext(string MSGID1, string MSGID2, int N)
  229. Plural version of gettext() */
  230. PHP_NAMED_FUNCTION(zif_ngettext)
  231. {
  232. char *msgid1, *msgid2, *msgstr;
  233. int msgid1_len, msgid2_len;
  234. long count;
  235. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
  236. return;
  237. }
  238. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  239. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  240. msgstr = ngettext(msgid1, msgid2, count);
  241. if (msgstr) {
  242. RETVAL_STRING(msgstr, 1);
  243. }
  244. }
  245. /* }}} */
  246. #endif
  247. #if HAVE_DNGETTEXT
  248. /* {{{ proto string dngettext (string domain, string msgid1, string msgid2, int count)
  249. Plural version of dgettext() */
  250. PHP_NAMED_FUNCTION(zif_dngettext)
  251. {
  252. char *domain, *msgid1, *msgid2, *msgstr = NULL;
  253. int domain_len, msgid1_len, msgid2_len;
  254. long count;
  255. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", &domain, &domain_len,
  256. &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
  257. return;
  258. }
  259. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  260. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  261. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  262. msgstr = dngettext(domain, msgid1, msgid2, count);
  263. if (msgstr) {
  264. RETVAL_STRING(msgstr, 1);
  265. }
  266. }
  267. /* }}} */
  268. #endif
  269. #if HAVE_DCNGETTEXT
  270. /* {{{ proto string dcngettext (string domain, string msgid1, string msgid2, int n, int category)
  271. Plural version of dcgettext() */
  272. PHP_NAMED_FUNCTION(zif_dcngettext)
  273. {
  274. char *domain, *msgid1, *msgid2, *msgstr = NULL;
  275. int domain_len, msgid1_len, msgid2_len;
  276. long count, category;
  277. RETVAL_FALSE;
  278. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssll", &domain, &domain_len,
  279. &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count, &category) == FAILURE) {
  280. return;
  281. }
  282. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  283. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  284. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  285. msgstr = dcngettext(domain, msgid1, msgid2, count, category);
  286. if (msgstr) {
  287. RETVAL_STRING(msgstr, 1);
  288. }
  289. }
  290. /* }}} */
  291. #endif
  292. #if HAVE_BIND_TEXTDOMAIN_CODESET
  293. /* {{{ proto string bind_textdomain_codeset (string domain, string codeset)
  294. Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. */
  295. PHP_NAMED_FUNCTION(zif_bind_textdomain_codeset)
  296. {
  297. char *domain, *codeset, *retval = NULL;
  298. int domain_len, codeset_len;
  299. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &codeset, &codeset_len) == FAILURE) {
  300. return;
  301. }
  302. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  303. retval = bind_textdomain_codeset(domain, codeset);
  304. if (!retval) {
  305. RETURN_FALSE;
  306. }
  307. RETURN_STRING(retval, 1);
  308. }
  309. /* }}} */
  310. #endif
  311. #endif /* HAVE_LIBINTL */
  312. /*
  313. * Local variables:
  314. * tab-width: 4
  315. * c-basic-offset: 4
  316. * End:
  317. * vim600: sw=4 ts=4 fdm=marker
  318. * vim<600: sw=4 ts=4
  319. */