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 :
19 : /* $Id: gettext.c 272370 2008-12-31 11:15:49Z sebastian $ */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "php.h"
26 :
27 : #if HAVE_LIBINTL
28 :
29 : #include <stdio.h>
30 : #include "ext/standard/info.h"
31 : #include "php_gettext.h"
32 :
33 : /* {{{ arginfo */
34 : ZEND_BEGIN_ARG_INFO(arginfo_textdomain, 0)
35 : ZEND_ARG_INFO(0, domain)
36 : ZEND_END_ARG_INFO()
37 :
38 : ZEND_BEGIN_ARG_INFO(arginfo_gettext, 0)
39 : ZEND_ARG_INFO(0, msgid)
40 : ZEND_END_ARG_INFO()
41 :
42 : ZEND_BEGIN_ARG_INFO(arginfo_dgettext, 0)
43 : ZEND_ARG_INFO(0, domain_name)
44 : ZEND_ARG_INFO(0, msgid)
45 : ZEND_END_ARG_INFO()
46 :
47 : ZEND_BEGIN_ARG_INFO(arginfo_dcgettext, 0)
48 : ZEND_ARG_INFO(0, domain_name)
49 : ZEND_ARG_INFO(0, msgid)
50 : ZEND_ARG_INFO(0, category)
51 : ZEND_END_ARG_INFO()
52 :
53 : ZEND_BEGIN_ARG_INFO(arginfo_bindtextdomain, 0)
54 : ZEND_ARG_INFO(0, domain_name)
55 : ZEND_ARG_INFO(0, dir)
56 : ZEND_END_ARG_INFO()
57 :
58 : #if HAVE_NGETTEXT
59 : ZEND_BEGIN_ARG_INFO(arginfo_ngettext, 0)
60 : ZEND_ARG_INFO(0, msgid1)
61 : ZEND_ARG_INFO(0, msgid2)
62 : ZEND_ARG_INFO(0, count)
63 : ZEND_END_ARG_INFO()
64 : #endif
65 :
66 : #if HAVE_DNGETTEXT
67 : ZEND_BEGIN_ARG_INFO(arginfo_dngettext, 0)
68 : ZEND_ARG_INFO(0, domain)
69 : ZEND_ARG_INFO(0, msgid1)
70 : ZEND_ARG_INFO(0, msgid2)
71 : ZEND_ARG_INFO(0, count)
72 : ZEND_END_ARG_INFO()
73 : #endif
74 :
75 : #if HAVE_DCNGETTEXT
76 : ZEND_BEGIN_ARG_INFO(arginfo_dcngettext, 0)
77 : ZEND_ARG_INFO(0, domain)
78 : ZEND_ARG_INFO(0, msgid1)
79 : ZEND_ARG_INFO(0, msgid2)
80 : ZEND_ARG_INFO(0, count)
81 : ZEND_ARG_INFO(0, category)
82 : ZEND_END_ARG_INFO()
83 : #endif
84 :
85 : #if HAVE_BIND_TEXTDOMAIN_CODESET
86 : ZEND_BEGIN_ARG_INFO(arginfo_bind_textdomain_codeset, 0)
87 : ZEND_ARG_INFO(0, domain)
88 : ZEND_ARG_INFO(0, codeset)
89 : ZEND_END_ARG_INFO()
90 : #endif
91 : /* }}} */
92 :
93 : /* {{{ php_gettext_functions[]
94 : */
95 : const zend_function_entry php_gettext_functions[] = {
96 : PHP_NAMED_FE(textdomain, zif_textdomain, arginfo_textdomain)
97 : PHP_NAMED_FE(gettext, zif_gettext, arginfo_gettext)
98 : /* Alias for gettext() */
99 : PHP_NAMED_FE(_, zif_gettext, arginfo_gettext)
100 : PHP_NAMED_FE(dgettext, zif_dgettext, arginfo_dgettext)
101 : PHP_NAMED_FE(dcgettext, zif_dcgettext, arginfo_dcgettext)
102 : PHP_NAMED_FE(bindtextdomain, zif_bindtextdomain, arginfo_bindtextdomain)
103 : #if HAVE_NGETTEXT
104 : PHP_NAMED_FE(ngettext, zif_ngettext, arginfo_ngettext)
105 : #endif
106 : #if HAVE_DNGETTEXT
107 : PHP_NAMED_FE(dngettext, zif_dngettext, arginfo_dngettext)
108 : #endif
109 : #if HAVE_DCNGETTEXT
110 : PHP_NAMED_FE(dcngettext, zif_dcngettext, arginfo_dcngettext)
111 : #endif
112 : #if HAVE_BIND_TEXTDOMAIN_CODESET
113 : PHP_NAMED_FE(bind_textdomain_codeset, zif_bind_textdomain_codeset, arginfo_bind_textdomain_codeset)
114 : #endif
115 : {NULL, NULL, NULL}
116 : };
117 : /* }}} */
118 :
119 : #include <libintl.h>
120 :
121 : zend_module_entry php_gettext_module_entry = {
122 : STANDARD_MODULE_HEADER,
123 : "gettext",
124 : php_gettext_functions,
125 : NULL,
126 : NULL,
127 : NULL,
128 : NULL,
129 : PHP_MINFO(php_gettext),
130 : NO_VERSION_YET,
131 : STANDARD_MODULE_PROPERTIES
132 : };
133 :
134 : #ifdef COMPILE_DL_GETTEXT
135 : ZEND_GET_MODULE(php_gettext)
136 : #endif
137 :
138 : #define PHP_GETTEXT_MAX_DOMAIN_LENGTH 1024
139 : #define PHP_GETTEXT_MAX_MSGID_LENGTH 4096
140 :
141 : #define PHP_GETTEXT_DOMAIN_LENGTH_CHECK \
142 : if (domain_len > PHP_GETTEXT_MAX_DOMAIN_LENGTH) { \
143 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "domain passed too long"); \
144 : RETURN_FALSE; \
145 : }
146 :
147 : #define PHP_GETTEXT_LENGTH_CHECK(check_name, check_len) \
148 : if (check_len > PHP_GETTEXT_MAX_MSGID_LENGTH) { \
149 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s passed too long", check_name); \
150 : RETURN_FALSE; \
151 : }
152 :
153 : PHP_MINFO_FUNCTION(php_gettext)
154 42 : {
155 42 : php_info_print_table_start();
156 42 : php_info_print_table_row(2, "GetText Support", "enabled");
157 42 : php_info_print_table_end();
158 42 : }
159 :
160 : /* {{{ proto string textdomain(string domain)
161 : Set the textdomain to "domain". Returns the current domain */
162 : PHP_NAMED_FUNCTION(zif_textdomain)
163 9 : {
164 : char *domain, *domain_name, *retval;
165 : int domain_len;
166 :
167 9 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &domain, &domain_len) == FAILURE) {
168 1 : return;
169 : }
170 :
171 8 : PHP_GETTEXT_DOMAIN_LENGTH_CHECK
172 :
173 13 : if (strcmp(domain, "") && strcmp(domain, "0")) {
174 6 : domain_name = domain;
175 : } else {
176 1 : domain_name = NULL;
177 : }
178 :
179 7 : retval = textdomain(domain_name);
180 :
181 7 : RETURN_STRING(retval, 1);
182 : }
183 : /* }}} */
184 :
185 : /* {{{ proto string gettext(string msgid)
186 : Return the translation of msgid for the current domain, or msgid unaltered if a translation does not exist */
187 : PHP_NAMED_FUNCTION(zif_gettext)
188 10 : {
189 : char *msgid, *msgstr;
190 : int msgid_len;
191 :
192 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &msgid, &msgid_len) == FAILURE) {
193 1 : return;
194 : }
195 :
196 9 : PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
197 8 : msgstr = gettext(msgid);
198 :
199 8 : RETURN_STRING(msgstr, 1);
200 : }
201 : /* }}} */
202 :
203 : /* {{{ proto string dgettext(string domain_name, string msgid)
204 : Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist */
205 : PHP_NAMED_FUNCTION(zif_dgettext)
206 7 : {
207 : char *domain, *msgid, *msgstr;
208 : int domain_len, msgid_len;
209 :
210 7 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &msgid, &msgid_len) == FAILURE) {
211 4 : return;
212 : }
213 :
214 3 : PHP_GETTEXT_DOMAIN_LENGTH_CHECK
215 2 : PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
216 :
217 1 : msgstr = dgettext(domain, msgid);
218 :
219 1 : RETURN_STRING(msgstr, 1);
220 : }
221 : /* }}} */
222 :
223 : /* {{{ proto string dcgettext(string domain_name, string msgid, long category)
224 : Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist */
225 : PHP_NAMED_FUNCTION(zif_dcgettext)
226 5 : {
227 : char *domain, *msgid, *msgstr;
228 : int domain_len, msgid_len;
229 : long category;
230 :
231 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &domain, &domain_len, &msgid, &msgid_len, &category) == FAILURE) {
232 1 : return;
233 : }
234 :
235 4 : PHP_GETTEXT_DOMAIN_LENGTH_CHECK
236 3 : PHP_GETTEXT_LENGTH_CHECK("msgid", msgid_len)
237 :
238 2 : msgstr = dcgettext(domain, msgid, category);
239 :
240 2 : RETURN_STRING(msgstr, 1);
241 : }
242 : /* }}} */
243 :
244 : /* {{{ proto string bindtextdomain(string domain_name, string dir)
245 : Bind to the text domain domain_name, looking for translations in dir. Returns the current domain */
246 : PHP_NAMED_FUNCTION(zif_bindtextdomain)
247 17 : {
248 : char *domain, *dir;
249 : int domain_len, dir_len;
250 : char *retval, dir_name[MAXPATHLEN];
251 :
252 17 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &dir, &dir_len) == FAILURE) {
253 2 : return;
254 : }
255 :
256 15 : PHP_GETTEXT_DOMAIN_LENGTH_CHECK
257 :
258 14 : if (domain[0] == '\0') {
259 1 : php_error(E_WARNING, "The first parameter of bindtextdomain must not be empty");
260 1 : RETURN_FALSE;
261 : }
262 :
263 24 : if (dir[0] != '\0' && strcmp(dir, "0")) {
264 12 : if (!VCWD_REALPATH(dir, dir_name)) {
265 1 : RETURN_FALSE;
266 : }
267 1 : } else if (!VCWD_GETCWD(dir_name, MAXPATHLEN)) {
268 0 : RETURN_FALSE;
269 : }
270 :
271 12 : retval = bindtextdomain(domain, dir_name);
272 :
273 12 : RETURN_STRING(retval, 1);
274 : }
275 : /* }}} */
276 :
277 : #if HAVE_NGETTEXT
278 : /* {{{ proto string ngettext(string MSGID1, string MSGID2, int N)
279 : Plural version of gettext() */
280 : PHP_NAMED_FUNCTION(zif_ngettext)
281 10 : {
282 : char *msgid1, *msgid2, *msgstr;
283 : int msgid1_len, msgid2_len;
284 : long count;
285 :
286 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
287 6 : return;
288 : }
289 :
290 4 : PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
291 3 : PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
292 :
293 2 : msgstr = ngettext(msgid1, msgid2, count);
294 2 : if (msgstr) {
295 2 : RETVAL_STRING(msgstr, 1);
296 : }
297 : }
298 : /* }}} */
299 : #endif
300 :
301 : #if HAVE_DNGETTEXT
302 : /* {{{ proto string dngettext (string domain, string msgid1, string msgid2, int count)
303 : Plural version of dgettext() */
304 : PHP_NAMED_FUNCTION(zif_dngettext)
305 6 : {
306 6 : char *domain, *msgid1, *msgid2, *msgstr = NULL;
307 : int domain_len, msgid1_len, msgid2_len;
308 : long count;
309 :
310 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", &domain, &domain_len,
311 : &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) {
312 1 : return;
313 : }
314 :
315 5 : PHP_GETTEXT_DOMAIN_LENGTH_CHECK
316 4 : PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
317 3 : PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
318 :
319 2 : msgstr = dngettext(domain, msgid1, msgid2, count);
320 2 : if (msgstr) {
321 2 : RETVAL_STRING(msgstr, 1);
322 : }
323 : }
324 : /* }}} */
325 : #endif
326 :
327 : #if HAVE_DCNGETTEXT
328 : /* {{{ proto string dcngettext (string domain, string msgid1, string msgid2, int n, int category)
329 : Plural version of dcgettext() */
330 : PHP_NAMED_FUNCTION(zif_dcngettext)
331 10 : {
332 10 : char *domain, *msgid1, *msgid2, *msgstr = NULL;
333 : int domain_len, msgid1_len, msgid2_len;
334 : long count, category;
335 :
336 10 : RETVAL_FALSE;
337 :
338 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssll", &domain, &domain_len,
339 : &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count, &category) == FAILURE) {
340 1 : return;
341 : }
342 :
343 9 : PHP_GETTEXT_DOMAIN_LENGTH_CHECK
344 8 : PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
345 7 : PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
346 :
347 6 : msgstr = dcngettext(domain, msgid1, msgid2, count, category);
348 :
349 6 : if (msgstr) {
350 6 : RETVAL_STRING(msgstr, 1);
351 : }
352 : }
353 : /* }}} */
354 : #endif
355 :
356 : #if HAVE_BIND_TEXTDOMAIN_CODESET
357 :
358 : /* {{{ proto string bind_textdomain_codeset (string domain, string codeset)
359 : Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. */
360 : PHP_NAMED_FUNCTION(zif_bind_textdomain_codeset)
361 4 : {
362 4 : char *domain, *codeset, *retval = NULL;
363 : int domain_len, codeset_len;
364 :
365 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &domain, &domain_len, &codeset, &codeset_len) == FAILURE) {
366 2 : return;
367 : }
368 :
369 2 : PHP_GETTEXT_DOMAIN_LENGTH_CHECK
370 :
371 2 : retval = bind_textdomain_codeset(domain, codeset);
372 :
373 2 : if (!retval) {
374 1 : RETURN_FALSE;
375 : }
376 1 : RETURN_STRING(retval, 1);
377 : }
378 : /* }}} */
379 : #endif
380 :
381 :
382 : #endif /* HAVE_LIBINTL */
383 :
384 : /*
385 : * Local variables:
386 : * tab-width: 4
387 : * c-basic-offset: 4
388 : * End:
389 : * vim600: sw=4 ts=4 fdm=marker
390 : * vim<600: sw=4 ts=4
391 : */
392 :
|