PageRenderTime 25ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/gettext/gettext.c

http://github.com/php/php-src
C | 304 lines | 200 code | 62 blank | 42 comment | 41 complexity | 798fec5f558cd50fe98d9d289b6ab8c9 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  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. | Author: Alex Plotnick <alex@wgate.com> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "php.h"
  20. #if HAVE_LIBINTL
  21. #include <stdio.h>
  22. #include "ext/standard/info.h"
  23. #include "php_gettext.h"
  24. #include "gettext_arginfo.h"
  25. #include <libintl.h>
  26. zend_module_entry php_gettext_module_entry = {
  27. STANDARD_MODULE_HEADER,
  28. "gettext",
  29. ext_functions,
  30. NULL,
  31. NULL,
  32. NULL,
  33. NULL,
  34. PHP_MINFO(php_gettext),
  35. PHP_GETTEXT_VERSION,
  36. STANDARD_MODULE_PROPERTIES
  37. };
  38. #ifdef COMPILE_DL_GETTEXT
  39. ZEND_GET_MODULE(php_gettext)
  40. #endif
  41. #define PHP_GETTEXT_MAX_DOMAIN_LENGTH 1024
  42. #define PHP_GETTEXT_MAX_MSGID_LENGTH 4096
  43. #define PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len) \
  44. if (UNEXPECTED(domain_len > PHP_GETTEXT_MAX_DOMAIN_LENGTH)) { \
  45. php_error_docref(NULL, E_WARNING, "Domain passed too long"); \
  46. RETURN_FALSE; \
  47. }
  48. #define PHP_GETTEXT_LENGTH_CHECK(check_name, check_len) \
  49. if (UNEXPECTED(check_len > PHP_GETTEXT_MAX_MSGID_LENGTH)) { \
  50. php_error_docref(NULL, E_WARNING, "%s passed too long", check_name); \
  51. RETURN_FALSE; \
  52. }
  53. PHP_MINFO_FUNCTION(php_gettext)
  54. {
  55. php_info_print_table_start();
  56. php_info_print_table_row(2, "GetText Support", "enabled");
  57. php_info_print_table_end();
  58. }
  59. /* {{{ proto string textdomain(string domain)
  60. Set the textdomain to "domain". Returns the current domain */
  61. PHP_FUNCTION(textdomain)
  62. {
  63. char *domain = NULL, *domain_name, *retval;
  64. size_t domain_len = 0;
  65. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!", &domain, &domain_len) == FAILURE) {
  66. RETURN_THROWS();
  67. }
  68. PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
  69. if (domain != NULL && strcmp(domain, "") && strcmp(domain, "0")) {
  70. domain_name = domain;
  71. } else {
  72. domain_name = NULL;
  73. }
  74. retval = textdomain(domain_name);
  75. RETURN_STRING(retval);
  76. }
  77. /* }}} */
  78. /* {{{ proto string gettext(string msgid)
  79. Return the translation of msgid for the current domain, or msgid unaltered if a translation does not exist */
  80. PHP_FUNCTION(gettext)
  81. {
  82. char *msgstr;
  83. zend_string *msgid;
  84. ZEND_PARSE_PARAMETERS_START(1, 1)
  85. Z_PARAM_STR(msgid)
  86. ZEND_PARSE_PARAMETERS_END();
  87. PHP_GETTEXT_LENGTH_CHECK("msgid", ZSTR_LEN(msgid))
  88. msgstr = gettext(ZSTR_VAL(msgid));
  89. if (msgstr != ZSTR_VAL(msgid)) {
  90. RETURN_STRING(msgstr);
  91. } else {
  92. RETURN_STR_COPY(msgid);
  93. }
  94. }
  95. /* }}} */
  96. /* {{{ proto string dgettext(string domain_name, string msgid)
  97. Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist */
  98. PHP_FUNCTION(dgettext)
  99. {
  100. char *msgstr;
  101. zend_string *domain, *msgid;
  102. if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &domain, &msgid) == FAILURE) {
  103. RETURN_THROWS();
  104. }
  105. PHP_GETTEXT_DOMAIN_LENGTH_CHECK(ZSTR_LEN(domain))
  106. PHP_GETTEXT_LENGTH_CHECK("msgid", ZSTR_LEN(msgid))
  107. msgstr = dgettext(ZSTR_VAL(domain), ZSTR_VAL(msgid));
  108. if (msgstr != ZSTR_VAL(msgid)) {
  109. RETURN_STRING(msgstr);
  110. } else {
  111. RETURN_STR_COPY(msgid);
  112. }
  113. }
  114. /* }}} */
  115. /* {{{ proto string dcgettext(string domain_name, string msgid, int category)
  116. Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist */
  117. PHP_FUNCTION(dcgettext)
  118. {
  119. char *msgstr;
  120. zend_string *domain, *msgid;
  121. zend_long category;
  122. if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl", &domain, &msgid, &category) == FAILURE) {
  123. RETURN_THROWS();
  124. }
  125. PHP_GETTEXT_DOMAIN_LENGTH_CHECK(ZSTR_LEN(domain))
  126. PHP_GETTEXT_LENGTH_CHECK("msgid", ZSTR_LEN(msgid))
  127. msgstr = dcgettext(ZSTR_VAL(domain), ZSTR_VAL(msgid), category);
  128. if (msgstr != ZSTR_VAL(msgid)) {
  129. RETURN_STRING(msgstr);
  130. } else {
  131. RETURN_STR_COPY(msgid);
  132. }
  133. }
  134. /* }}} */
  135. /* {{{ proto string bindtextdomain(string domain_name, string dir)
  136. Bind to the text domain domain_name, looking for translations in dir. Returns the current domain */
  137. PHP_FUNCTION(bindtextdomain)
  138. {
  139. char *domain, *dir;
  140. size_t domain_len, dir_len;
  141. char *retval, dir_name[MAXPATHLEN];
  142. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &domain, &domain_len, &dir, &dir_len) == FAILURE) {
  143. RETURN_THROWS();
  144. }
  145. PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
  146. if (domain[0] == '\0') {
  147. php_error(E_WARNING, "The first parameter of bindtextdomain must not be empty");
  148. RETURN_FALSE;
  149. }
  150. if (dir[0] != '\0' && strcmp(dir, "0")) {
  151. if (!VCWD_REALPATH(dir, dir_name)) {
  152. RETURN_FALSE;
  153. }
  154. } else if (!VCWD_GETCWD(dir_name, MAXPATHLEN)) {
  155. RETURN_FALSE;
  156. }
  157. retval = bindtextdomain(domain, dir_name);
  158. RETURN_STRING(retval);
  159. }
  160. /* }}} */
  161. #if HAVE_NGETTEXT
  162. /* {{{ proto string ngettext(string MSGID1, string MSGID2, int N)
  163. Plural version of gettext() */
  164. PHP_FUNCTION(ngettext)
  165. {
  166. char *msgid1, *msgid2, *msgstr;
  167. size_t msgid1_len, msgid2_len;
  168. zend_long count;
  169. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl", &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
  170. RETURN_THROWS();
  171. }
  172. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  173. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  174. msgstr = ngettext(msgid1, msgid2, count);
  175. ZEND_ASSERT(msgstr);
  176. RETURN_STRING(msgstr);
  177. }
  178. /* }}} */
  179. #endif
  180. #if HAVE_DNGETTEXT
  181. /* {{{ proto string dngettext(string domain, string msgid1, string msgid2, int count)
  182. Plural version of dgettext() */
  183. PHP_FUNCTION(dngettext)
  184. {
  185. char *domain, *msgid1, *msgid2, *msgstr = NULL;
  186. size_t domain_len, msgid1_len, msgid2_len;
  187. zend_long count;
  188. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssl", &domain, &domain_len,
  189. &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
  190. RETURN_THROWS();
  191. }
  192. PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
  193. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  194. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  195. msgstr = dngettext(domain, msgid1, msgid2, count);
  196. ZEND_ASSERT(msgstr);
  197. RETURN_STRING(msgstr);
  198. }
  199. /* }}} */
  200. #endif
  201. #if HAVE_DCNGETTEXT
  202. /* {{{ proto string dcngettext(string domain, string msgid1, string msgid2, int n, int category)
  203. Plural version of dcgettext() */
  204. PHP_FUNCTION(dcngettext)
  205. {
  206. char *domain, *msgid1, *msgid2, *msgstr = NULL;
  207. size_t domain_len, msgid1_len, msgid2_len;
  208. zend_long count, category;
  209. RETVAL_FALSE;
  210. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssll", &domain, &domain_len,
  211. &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count, &category) == FAILURE) {
  212. RETURN_THROWS();
  213. }
  214. PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
  215. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  216. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  217. msgstr = dcngettext(domain, msgid1, msgid2, count, category);
  218. ZEND_ASSERT(msgstr);
  219. RETURN_STRING(msgstr);
  220. }
  221. /* }}} */
  222. #endif
  223. #if HAVE_BIND_TEXTDOMAIN_CODESET
  224. /* {{{ proto string bind_textdomain_codeset(string domain, string codeset)
  225. Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. */
  226. PHP_FUNCTION(bind_textdomain_codeset)
  227. {
  228. char *domain, *codeset, *retval = NULL;
  229. size_t domain_len, codeset_len;
  230. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &domain, &domain_len, &codeset, &codeset_len) == FAILURE) {
  231. RETURN_THROWS();
  232. }
  233. PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
  234. retval = bind_textdomain_codeset(domain, codeset);
  235. if (!retval) {
  236. RETURN_FALSE;
  237. }
  238. RETURN_STRING(retval);
  239. }
  240. /* }}} */
  241. #endif
  242. #endif /* HAVE_LIBINTL */