PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/hidefl.c

https://bitbucket.org/lingfeng_xiang/php-ext-hidefl
C | 386 lines | 320 code | 63 blank | 3 comment | 54 complexity | e514d05ba9b4e864e268b8895bafb790 MD5 | raw file
  1. #ifdef HAVE_CONFIG_H
  2. #include "config.h"
  3. #endif
  4. #include "php.h"
  5. #include "php_ini.h"
  6. #include "php_scandir.h"
  7. #include "ext/standard/info.h"
  8. #include "ext/standard/php_string.h"
  9. #include "ext/standard/php_var.h"
  10. #include "ext/standard/php_smart_str.h"
  11. #include "php_hidefl.h"
  12. #define HIDEFL_DEFAULT_EXTENSION ".data"
  13. static int le_hidefl;
  14. ZEND_DECLARE_MODULE_GLOBALS(hidefl)
  15. ZEND_FUNCTION(hidefl_fetch);
  16. ZEND_FUNCTION(hidefl_wrap);
  17. ZEND_FUNCTION(hidefl_save);
  18. ZEND_BEGIN_ARG_INFO_EX(arginfo_hidefl_fetch, 0, 0, 1)
  19. ZEND_ARG_INFO(0, key)
  20. ZEND_ARG_INFO(0, thaw)
  21. ZEND_END_ARG_INFO()
  22. ZEND_BEGIN_ARG_INFO_EX(arginfo_hidefl_wrap, 0, 0, 1)
  23. ZEND_ARG_INFO(0, value)
  24. ZEND_END_ARG_INFO()
  25. ZEND_BEGIN_ARG_INFO_EX(arginfo_hidefl_save, 0, 0, 2)
  26. ZEND_ARG_INFO(0, key)
  27. ZEND_ARG_INFO(0, value)
  28. ZEND_END_ARG_INFO()
  29. PHP_INI_BEGIN()
  30. STD_PHP_INI_ENTRY("hidefl.data_path", (char*)NULL, PHP_INI_SYSTEM,
  31. OnUpdateString, data_path, zend_hidefl_globals,
  32. hidefl_globals)
  33. STD_PHP_INI_ENTRY("hidefl.data_extension", (char*)NULL, PHP_INI_SYSTEM,
  34. OnUpdateString, data_extension, zend_hidefl_globals,
  35. hidefl_globals)
  36. STD_PHP_INI_BOOLEAN("hidefl.load_unserialize", "1", PHP_INI_SYSTEM,
  37. OnUpdateBool, load_unserialize, zend_hidefl_globals,
  38. hidefl_globals)
  39. PHP_INI_END()
  40. static const zend_function_entry hidefl_functions[] = {
  41. ZEND_FE(hidefl_fetch, arginfo_hidefl_fetch)
  42. ZEND_FE(hidefl_wrap, arginfo_hidefl_wrap)
  43. ZEND_FE(hidefl_save, arginfo_hidefl_save)
  44. ZEND_FE_END
  45. };
  46. static inline void
  47. hidefl_init_globals(zend_hidefl_globals *hidefl_globals)
  48. {
  49. hidefl_globals->data_path = NULL;
  50. hidefl_globals->data_extension = NULL;
  51. hidefl_globals->load_unserialize = 1;
  52. }
  53. static inline int
  54. hidefl_serialize(smart_str *retval, zval **struc TSRMLS_DC)
  55. {
  56. php_serialize_data_t var_hash;
  57. PHP_VAR_SERIALIZE_INIT(var_hash);
  58. php_var_serialize(retval, struc, &var_hash TSRMLS_CC);
  59. PHP_VAR_SERIALIZE_DESTROY(var_hash);
  60. return SUCCESS;
  61. }
  62. static inline int
  63. hidefl_unserialize(zval *retval, const char *payload,
  64. size_t payload_len TSRMLS_DC)
  65. {
  66. php_unserialize_data_t var_hash;
  67. PHP_VAR_UNSERIALIZE_INIT(var_hash);
  68. if (!php_var_unserialize(&retval, (const unsigned char **)&payload,
  69. (const unsigned char *)payload + payload_len,
  70. &var_hash TSRMLS_CC)) {
  71. PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
  72. zval_ptr_dtor(&retval);
  73. return FAILURE;
  74. }
  75. PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
  76. return SUCCESS;
  77. }
  78. static inline int
  79. hidefl_plist_key(char **key, char *id)
  80. {
  81. int key_len = 0;
  82. key_len = spprintf(key, 0, "hidefl:id=%s", id);
  83. key_len += 1;
  84. return key_len;
  85. }
  86. static inline int
  87. hidefl_load_data(const char *data_file TSRMLS_DC)
  88. {
  89. char *p;
  90. char key[MAXPATHLEN] = {0,};
  91. unsigned int key_len;
  92. if (access(data_file, R_OK) != 0) {
  93. zend_error(E_WARNING, "hidefl cannot read %s", data_file);
  94. return FAILURE;
  95. }
  96. p = strrchr(data_file, DEFAULT_SLASH);
  97. if (p && p[1]) {
  98. strlcpy(key, p+1, sizeof(key));
  99. p = strrchr(key, '.');
  100. if (p) {
  101. p[0] = '\0';
  102. key_len = strlen(key);
  103. zval *data = NULL;
  104. struct stat sb;
  105. FILE *fp;
  106. char *contents;
  107. long contents_len = 0;
  108. if (VCWD_STAT(data_file, &sb) == -1) {
  109. return FAILURE;
  110. }
  111. fp = fopen(data_file, "rb");
  112. if (!fp || sb.st_size == 0) {
  113. return FAILURE;
  114. }
  115. contents_len = sizeof(char) * sb.st_size;
  116. contents = emalloc(contents_len);
  117. contents_len = fread(contents, 1, contents_len, fp);
  118. if (HIDEFL_G(load_unserialize)) {
  119. /* unserialize */
  120. data = (zval *)pemalloc(sizeof(zval), 1);
  121. INIT_PZVAL(data);
  122. if (hidefl_unserialize(data, contents,
  123. contents_len TSRMLS_CC) != SUCCESS) {
  124. if (data) {
  125. pefree(data, 1);
  126. }
  127. efree(contents);
  128. fclose(fp);
  129. return FAILURE;
  130. }
  131. } else {
  132. /* string */
  133. data = (zval *)pemalloc(sizeof(zval), 1);
  134. INIT_PZVAL(data);
  135. Z_TYPE_P(data) = IS_STRING;
  136. data->value.str.val = pestrndup(contents, contents_len, 1);
  137. data->value.str.len = contents_len;
  138. }
  139. efree(contents);
  140. fclose(fp);
  141. zend_rsrc_list_entry le;
  142. le.type = le_hidefl;
  143. le.ptr = data;
  144. char *plist_key = NULL;
  145. int plist_key_len = 0;
  146. plist_key_len = hidefl_plist_key(&plist_key, key);
  147. if (data == NULL ||
  148. zend_hash_update(&EG(persistent_list), plist_key,
  149. plist_key_len, (void *)&le,
  150. sizeof(zend_rsrc_list_entry),
  151. NULL) == FAILURE) {
  152. if (plist_key) {
  153. efree(plist_key);
  154. }
  155. if (data) {
  156. pefree(data, 1);
  157. }
  158. zend_error(E_ERROR, "Unable to add %s to the hidefl data",
  159. data_file);
  160. return FAILURE;
  161. }
  162. if (plist_key) {
  163. efree(plist_key);
  164. }
  165. return SUCCESS;
  166. }
  167. }
  168. return FAILURE;
  169. }
  170. ZEND_RSRC_DTOR_FUNC(hidefl_list_dtor)
  171. {
  172. if (rsrc->ptr) {
  173. zval *data = (zval *)rsrc->ptr;
  174. if (data) {
  175. pefree(data, 1);
  176. }
  177. rsrc->ptr = NULL;
  178. }
  179. }
  180. ZEND_MINIT_FUNCTION(hidefl)
  181. {
  182. ZEND_INIT_MODULE_GLOBALS(hidefl, hidefl_init_globals, NULL);
  183. le_hidefl = zend_register_list_destructors_ex(
  184. NULL, hidefl_list_dtor, "Hidefl persistent context", module_number);
  185. REGISTER_INI_ENTRIES();
  186. if (HIDEFL_G(data_path)) {
  187. char *p = NULL;
  188. char file[MAXPATHLEN] = {0,};
  189. int i, ndir;
  190. struct dirent **nlist = NULL;
  191. if ((ndir = php_scandir(HIDEFL_G(data_path), &nlist,
  192. 0, php_alphasort)) > 0) {
  193. for (i = 0; i < ndir; i++) {
  194. if (!(p = strrchr(nlist[i]->d_name, '.')) ||
  195. (p && HIDEFL_G(data_extension)
  196. && strcmp(p, HIDEFL_G(data_extension)) != 0) ||
  197. (p && strcmp(p, HIDEFL_DEFAULT_EXTENSION) != 0)) {
  198. free(nlist[i]);
  199. continue;
  200. }
  201. snprintf(file, MAXPATHLEN, "%s%c%s",
  202. HIDEFL_G(data_path), DEFAULT_SLASH, nlist[i]->d_name);
  203. hidefl_load_data(file TSRMLS_CC);
  204. free(nlist[i]);
  205. }
  206. free(nlist);
  207. }
  208. }
  209. return SUCCESS;
  210. }
  211. ZEND_MSHUTDOWN_FUNCTION(hidefl)
  212. {
  213. UNREGISTER_INI_ENTRIES();
  214. return SUCCESS;
  215. }
  216. ZEND_MINFO_FUNCTION(hidefl)
  217. {
  218. php_info_print_table_start();
  219. php_info_print_table_row(2, "Hidefl support", "enabled");
  220. php_info_print_table_row(2, "Extension Version", HIDEFL_EXT_VERSION);
  221. php_info_print_table_end();
  222. }
  223. zend_module_entry hidefl_module_entry = {
  224. #if ZEND_MODULE_API_NO >= 20010901
  225. STANDARD_MODULE_HEADER,
  226. #endif
  227. "hidefl",
  228. hidefl_functions,
  229. ZEND_MINIT(hidefl),
  230. ZEND_MSHUTDOWN(hidefl),
  231. NULL,
  232. NULL,
  233. ZEND_MINFO(hidefl),
  234. #if ZEND_MODULE_API_NO >= 20010901
  235. HIDEFL_EXT_VERSION,
  236. #endif
  237. STANDARD_MODULE_PROPERTIES
  238. };
  239. #ifdef COMPILE_DL_HIDEFL
  240. ZEND_GET_MODULE(hidefl)
  241. #endif
  242. ZEND_FUNCTION(hidefl_fetch)
  243. {
  244. char *key = NULL;
  245. long key_len = 0;
  246. zend_bool thaw = 0;
  247. zval *data = NULL;
  248. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
  249. "s|b", &key, &key_len, &thaw) == FAILURE) {
  250. RETURN_FALSE;
  251. }
  252. char *plist_key = NULL;
  253. int plist_key_len = 0;
  254. plist_key_len = hidefl_plist_key(&plist_key, key);
  255. zend_rsrc_list_entry *le = NULL;
  256. if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len,
  257. (void *)&le) == SUCCESS) {
  258. if (le->type == le_hidefl) {
  259. data = le->ptr;
  260. }
  261. }
  262. if (plist_key) {
  263. efree(plist_key);
  264. }
  265. if (!data) {
  266. RETURN_FALSE;
  267. }
  268. if (HIDEFL_G(load_unserialize)) {
  269. *return_value = *data;
  270. zval_copy_ctor(return_value);
  271. } else {
  272. /* unserialize */
  273. if (hidefl_unserialize(return_value, Z_STRVAL_P(data),
  274. Z_STRLEN_P(data) TSRMLS_CC) != SUCCESS) {
  275. zval_dtor(return_value);
  276. RETVAL_FALSE;
  277. }
  278. }
  279. }
  280. ZEND_FUNCTION(hidefl_wrap)
  281. {
  282. RETURN_FALSE;
  283. }
  284. ZEND_FUNCTION(hidefl_save)
  285. {
  286. char *key;
  287. long key_len;
  288. zval **struc;
  289. smart_str buf = {0};
  290. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
  291. "sZ", &key, &key_len, &struc) == FAILURE) {
  292. return;
  293. }
  294. hidefl_serialize(&buf, struc TSRMLS_CC);
  295. if (!buf.c) {
  296. RETURN_FALSE;
  297. }
  298. if (HIDEFL_G(data_path) && buf.c) {
  299. FILE *fp;
  300. char file[MAXPATHLEN] = {0,};
  301. if (HIDEFL_G(data_extension)) {
  302. snprintf(file, MAXPATHLEN, "%s%c%s%s",
  303. HIDEFL_G(data_path), DEFAULT_SLASH,
  304. key, HIDEFL_G(data_extension));
  305. } else {
  306. snprintf(file, MAXPATHLEN, "%s%c%s%s",
  307. HIDEFL_G(data_path), DEFAULT_SLASH,
  308. key, HIDEFL_DEFAULT_EXTENSION);
  309. }
  310. fp = fopen(file, "wb");
  311. if (!fp) {
  312. smart_str_free(&buf);
  313. RETVAL_FALSE;
  314. }
  315. fwrite(buf.c, 1, buf.len, fp);
  316. fclose(fp);
  317. } else {
  318. smart_str_free(&buf);
  319. RETVAL_FALSE;
  320. }
  321. smart_str_free(&buf);
  322. RETVAL_TRUE;
  323. }