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.0 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_0.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 |                        **** WARNING ****                             |
16 |                                                                      |
17 | This module makes use of unRAR - free utility for RAR archives.      |
18 | Its license states that you MUST NOT use its code to develop         |
19 | a RAR (WinRAR) compatible archiver.                                  |
20 | Please, read unRAR license for full information.                     |
21 | unRAR & RAR copyrights are owned by Eugene Roshal                    |
22 +----------------------------------------------------------------------+
23 | Author: Antony Dovgal <tony@daylessday.org>                          |
24 | Author: Gustavo Lopes <cataphract@php.net>                           |
25 +----------------------------------------------------------------------+
26 */
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #include <php.h>
33 #include <zend_exceptions.h>
34 #include "php_rar.h"
35 
36 /* {{{ Globals with external linkage */
37 zend_class_entry *rarexception_ce_ptr;
38 /* }}} */
39 
40 /* Functions with external linkage {{{ */
41 /* Functions with external linkage {{{ */
_rar_handle_error(int errcode TSRMLS_DC)42 int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
43 {
44 	return _rar_handle_error_ex("", errcode TSRMLS_CC);
45 }
46 /* }}} */
47 
_rar_handle_error_ex(const char * preamble,int errcode TSRMLS_DC)48 int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
49 {
50 	const char *err = _rar_error_to_string(errcode);
51 
52 	if (err == NULL) {
53 		return SUCCESS;
54 	}
55 
56 	if (_rar_using_exceptions(TSRMLS_C)) {
57 		zend_throw_exception_ex(rarexception_ce_ptr, errcode TSRMLS_CC,
58 			"unRAR internal error: %s%s", preamble, err);
59 	}
60 	else {
61 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s", preamble, err);
62 	}
63 	return FAILURE;
64 }
65 /* }}} */
66 
67 /* Errors not related to the unRAR library */
_rar_handle_ext_error(const char * format TSRMLS_DC,...)68 void _rar_handle_ext_error(const char *format TSRMLS_DC, ...) /* {{{ */
69 {
70 	va_list arg;
71 	char *message;
72 
73 #if defined(ZTS) && PHP_MAJOR_VERSION < 7
74 	va_start(arg, TSRMLS_C);
75 #else
76 	va_start(arg, format);
77 #endif
78 	vspprintf(&message, 0, format, arg);
79 	va_end(arg);
80 
81 	if (_rar_using_exceptions(TSRMLS_C))
82 		zend_throw_exception(rarexception_ce_ptr, message, -1L TSRMLS_CC);
83 	else
84 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
85 	efree(message);
86 }
87 /* }}} */
88 
_rar_using_exceptions(TSRMLS_D)89 int _rar_using_exceptions(TSRMLS_D)
90 {
91 	zval *pval;
92 	pval = zend_read_static_property(rarexception_ce_ptr, "usingExceptions",
93 		sizeof("usingExceptions") -1, (zend_bool) 1 TSRMLS_CC);
94 #if PHP_MAJOR_VERSION < 7
95 	assert(Z_TYPE_P(pval) == IS_BOOL);
96 	return Z_BVAL_P(pval);
97 #else
98 	assert(Z_TYPE_P(pval) == IS_TRUE || Z_TYPE_P(pval) == IS_FALSE);
99 	return Z_TYPE_P(pval) == IS_TRUE;
100 #endif
101 }
102 
103 /* returns a string or NULL if not an error */
_rar_error_to_string(int errcode)104 const char * _rar_error_to_string(int errcode) /* {{{ */
105 {
106 	const char *ret;
107 	switch (errcode) {
108 		case 0:
109 			/* no error */
110 		case 1:
111 			/* no error (comment completely read) */
112 		case ERAR_END_ARCHIVE:
113 			/* no error */
114 			ret = NULL;
115 			break;
116 		case ERAR_NO_MEMORY:
117 			ret = "ERAR_NO_MEMORY (not enough memory)";
118 			break;
119 		case ERAR_BAD_DATA:
120 			ret = "ERAR_BAD_DATA";
121 			break;
122 		case ERAR_BAD_ARCHIVE:
123 			ret = "ERAR_BAD_ARCHIVE";
124 			break;
125 		case ERAR_UNKNOWN_FORMAT:
126 			ret = "ERAR_UNKNOWN_FORMAT";
127 			break;
128 		case ERAR_EOPEN:
129 			ret = "ERAR_EOPEN (file open error)";
130 			break;
131 		case ERAR_ECREATE:
132 			ret = "ERAR_ECREATE";
133 			break;
134 		case ERAR_ECLOSE:
135 			ret = "ERAR_ECLOSE (error closing file)";
136 			break;
137 		case ERAR_EREAD:
138 			ret = "ERAR_EREAD";
139 			break;
140 		case ERAR_EWRITE:
141 			ret = "ERAR_EWRITE";
142 			break;
143 		case ERAR_SMALL_BUF:
144 			ret = "ERAR_SMALL_BUF";
145 			break;
146 		case ERAR_UNKNOWN:
147 			ret = "ERAR_UNKNOWN (unknown RAR error)";
148 			break;
149 		case ERAR_MISSING_PASSWORD:
150 			ret = "ERAR_MISSING_PASSWORD (password needed but not specified)";
151 			break;
152 		default:
153 			ret = "unknown RAR error (should not happen)";
154 			break;
155 	}
156 	return ret;
157 }
158 /* }}} */
159 /* }}} */
160 
161 /* {{{ proto bool RarException::setUsingExceptions(using_exceptions)
162    Set whether exceptions are to be used */
PHP_METHOD(rarexception,setUsingExceptions)163 PHP_METHOD(rarexception, setUsingExceptions)
164 {
165 	zend_bool argval;
166 	int result;
167 
168 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &argval) == FAILURE ) {
169 		return;
170 	}
171 
172 	result = zend_update_static_property_bool(rarexception_ce_ptr,
173 		"usingExceptions", sizeof("usingExceptions") -1,
174 		(long) argval TSRMLS_CC);
175 
176 	if (result == FAILURE) {
177 		php_error_docref(NULL TSRMLS_CC, E_WARNING,
178 			"Could not set error handling mode. "
179 			"This is a bug, please report it.");
180 		return;
181 	}
182 }
183 /* }}} */
184 
185 /* {{{ proto bool RarException::isUsingExceptions()
186    Return whether exceptions are being used */
PHP_METHOD(rarexception,isUsingExceptions)187 PHP_METHOD(rarexception, isUsingExceptions)
188 {
189 #if PHP_MAJOR_VERSION < 7
190 	zval **pval;
191 #else
192 	zval *pval;
193 #endif
194 
195 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE ) {
196 		return;
197 	}
198 
199 	/* or zend_read_static_property, which calls zend_std_get... after chg scope */
200 #if PHP_VERSION_ID < 50399
201 	pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
202 		sizeof("usingExceptions") -1, (zend_bool) 0 TSRMLS_CC);
203 #elif PHP_MAJOR_VERSION < 7
204 	pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
205 		sizeof("usingExceptions") -1, (zend_bool) 0, NULL TSRMLS_CC);
206 #else
207 	zend_string *prop_name =
208 		zend_string_init("usingExceptions", sizeof("usingExceptions") - 1, 0);
209 	pval = zend_std_get_static_property(rarexception_ce_ptr, prop_name,
210 		(zend_bool) 0);
211 	zend_string_release(prop_name);
212 #endif
213 	/* property always exists */
214 	assert(pval != NULL);
215 #if PHP_MAJOR_VERSION < 7
216 	assert(Z_TYPE_PP(pval) == IS_BOOL);
217 	RETURN_ZVAL(*pval, 0, 0);
218 #else
219 	assert(Z_TYPE_P(pval) == IS_TRUE || Z_TYPE_P(pval) == IS_FALSE);
220 	RETURN_ZVAL(pval, 0, 0);
221 #endif
222 }
223 /* }}} */
224 
225 /* {{{ arginfo */
226 ZEND_BEGIN_ARG_INFO_EX(arginfo_rarexception_sue, 0, 0, 1)
227 	ZEND_ARG_INFO(0, using_exceptions)
228 ZEND_END_ARG_INFO()
229 
230 ZEND_BEGIN_ARG_INFO(arginfo_rarexception_void, 0)
231 ZEND_END_ARG_INFO()
232 /* }}} */
233 
234 static zend_function_entry php_rarexception_class_functions[] = {
235 	PHP_ME(rarexception,	setUsingExceptions,	arginfo_rarexception_sue,	ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
236 	PHP_ME(rarexception,	isUsingExceptions,	arginfo_rarexception_void,	ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
237 	{NULL, NULL, NULL}
238 };
239 
minit_rarerror(TSRMLS_D)240 void minit_rarerror(TSRMLS_D) /* {{{ */
241 {
242 	zend_class_entry ce;
243 
244 	INIT_CLASS_ENTRY(ce, "RarException", php_rarexception_class_functions);
245 #if PHP_MAJOR_VERSION < 7
246 	rarexception_ce_ptr = zend_register_internal_class_ex(&ce,
247 		zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
248 #else
249 	rarexception_ce_ptr = zend_register_internal_class_ex(&ce,
250 		zend_exception_get_default(TSRMLS_C));
251 #endif
252 	rarexception_ce_ptr->ce_flags |= ZEND_ACC_FINAL;
253 	zend_declare_property_bool(rarexception_ce_ptr, "usingExceptions",
254 		sizeof("usingExceptions") -1, 0L /* FALSE */,
255 		ZEND_ACC_STATIC TSRMLS_CC);
256 }
257 /* }}} */
258 
259 #ifdef __cplusplus
260 }
261 #endif
262