You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

392 lines
10 KiB

13 years ago
27 years ago
27 years ago
25 years ago
25 years ago
25 years ago
25 years ago
27 years ago
25 years ago
25 years ago
18 years ago
18 years ago
18 years ago
26 years ago
12 years ago
26 years ago
18 years ago
12 years ago
18 years ago
12 years ago
18 years ago
12 years ago
18 years ago
12 years ago
25 years ago
25 years ago
18 years ago
18 years ago
12 years ago
25 years ago
25 years ago
25 years ago
25 years ago
18 years ago
18 years ago
12 years ago
25 years ago
25 years ago
25 years ago
18 years ago
18 years ago
12 years ago
25 years ago
12 years ago
25 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2014 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$ */
  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. PHP_FE_END
  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);
  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);
  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);
  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);
  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);
  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);
  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);
  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);
  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);
  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. */