PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/ext_zend_compat/gettext/gettext.cpp

https://gitlab.com/Blueprint-Marketing/hhvm
C++ | 400 lines | 264 code | 74 blank | 62 comment | 35 complexity | 0324470b83be449376293fdf76a42d07 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2013 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, 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 _(string msgid)
  171. An alias for gettext() */
  172. PHP_NAMED_FUNCTION(zif__)
  173. {
  174. zif_gettext(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  175. }
  176. /* }}} */
  177. /* {{{ proto string dgettext(string domain_name, string msgid)
  178. Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist */
  179. PHP_NAMED_FUNCTION(zif_dgettext)
  180. {
  181. char *domain, *msgid, *msgstr;
  182. int domain_len, msgid_len;
  183. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &msgid, &msgid_len) == FAILURE) {
  184. return;
  185. }
  186. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  187. PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
  188. msgstr = dgettext(domain, msgid);
  189. RETURN_STRING(msgstr, 1);
  190. }
  191. /* }}} */
  192. /* {{{ proto string dcgettext(string domain_name, string msgid, long category)
  193. Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist */
  194. PHP_NAMED_FUNCTION(zif_dcgettext)
  195. {
  196. char *domain, *msgid, *msgstr;
  197. int domain_len, msgid_len;
  198. long category;
  199. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &domain, &domain_len, &msgid, &msgid_len, &category) == FAILURE) {
  200. return;
  201. }
  202. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  203. PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
  204. msgstr = dcgettext(domain, msgid, category);
  205. RETURN_STRING(msgstr, 1);
  206. }
  207. /* }}} */
  208. /* {{{ proto string bindtextdomain(string domain_name, string dir)
  209. Bind to the text domain domain_name, looking for translations in dir. Returns the current domain */
  210. PHP_NAMED_FUNCTION(zif_bindtextdomain)
  211. {
  212. char *domain, *dir;
  213. int domain_len, dir_len;
  214. char *retval, dir_name[MAXPATHLEN];
  215. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &dir, &dir_len) == FAILURE) {
  216. return;
  217. }
  218. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  219. if (domain[0] == '\0') {
  220. php_error(E_WARNING, "The first parameter of bindtextdomain must not be empty");
  221. RETURN_FALSE;
  222. }
  223. if (dir[0] != '\0' && strcmp(dir, "0")) {
  224. if (!VCWD_REALPATH(dir, dir_name)) {
  225. RETURN_FALSE;
  226. }
  227. } else if (!VCWD_GETCWD(dir_name, MAXPATHLEN)) {
  228. RETURN_FALSE;
  229. }
  230. retval = bindtextdomain(domain, dir_name);
  231. RETURN_STRING(retval, 1);
  232. }
  233. /* }}} */
  234. #if HAVE_NGETTEXT
  235. /* {{{ proto string ngettext(string MSGID1, string MSGID2, int N)
  236. Plural version of gettext() */
  237. PHP_NAMED_FUNCTION(zif_ngettext)
  238. {
  239. char *msgid1, *msgid2, *msgstr;
  240. int msgid1_len, msgid2_len;
  241. long count;
  242. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
  243. return;
  244. }
  245. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  246. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  247. msgstr = ngettext(msgid1, msgid2, count);
  248. if (msgstr) {
  249. RETVAL_STRING(msgstr, 1);
  250. }
  251. }
  252. /* }}} */
  253. #endif
  254. #if HAVE_DNGETTEXT
  255. /* {{{ proto string dngettext (string domain, string msgid1, string msgid2, int count)
  256. Plural version of dgettext() */
  257. PHP_NAMED_FUNCTION(zif_dngettext)
  258. {
  259. char *domain, *msgid1, *msgid2, *msgstr = NULL;
  260. int domain_len, msgid1_len, msgid2_len;
  261. long count;
  262. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", &domain, &domain_len,
  263. &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
  264. return;
  265. }
  266. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  267. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  268. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  269. msgstr = dngettext(domain, msgid1, msgid2, count);
  270. if (msgstr) {
  271. RETVAL_STRING(msgstr, 1);
  272. }
  273. }
  274. /* }}} */
  275. #endif
  276. #if HAVE_DCNGETTEXT
  277. /* {{{ proto string dcngettext (string domain, string msgid1, string msgid2, int n, int category)
  278. Plural version of dcgettext() */
  279. PHP_NAMED_FUNCTION(zif_dcngettext)
  280. {
  281. char *domain, *msgid1, *msgid2, *msgstr = NULL;
  282. int domain_len, msgid1_len, msgid2_len;
  283. long count, category;
  284. RETVAL_FALSE;
  285. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssll", &domain, &domain_len,
  286. &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count, &category) == FAILURE) {
  287. return;
  288. }
  289. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  290. PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
  291. PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
  292. msgstr = dcngettext(domain, msgid1, msgid2, count, category);
  293. if (msgstr) {
  294. RETVAL_STRING(msgstr, 1);
  295. }
  296. }
  297. /* }}} */
  298. #endif
  299. #if HAVE_BIND_TEXTDOMAIN_CODESET
  300. /* {{{ proto string bind_textdomain_codeset (string domain, string codeset)
  301. Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. */
  302. PHP_NAMED_FUNCTION(zif_bind_textdomain_codeset)
  303. {
  304. char *domain, *codeset, *retval = NULL;
  305. int domain_len, codeset_len;
  306. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &codeset, &codeset_len) == FAILURE) {
  307. return;
  308. }
  309. PHP_GETTEXT_DOMAIN_LENGTH_CHECK
  310. retval = bind_textdomain_codeset(domain, codeset);
  311. if (!retval) {
  312. RETURN_FALSE;
  313. }
  314. RETURN_STRING(retval, 1);
  315. }
  316. /* }}} */
  317. #endif
  318. #endif /* HAVE_LIBINTL */
  319. /*
  320. * Local variables:
  321. * tab-width: 4
  322. * c-basic-offset: 4
  323. * End:
  324. * vim600: sw=4 ts=4 fdm=marker
  325. * vim<600: sw=4 ts=4
  326. */