PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/yaf_config.c

https://gitlab.com/oytunistrator/yaf
C | 405 lines | 279 code | 63 blank | 63 comment | 49 complexity | 7f45687c6a90009ec3793be9aa3331f0 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Yet Another Framework |
  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: Xinchen Hui <laruence@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "php_ini.h"
  21. #include "standard/php_filestat.h" /* for php_stat */
  22. #include "php_yaf.h"
  23. #include "yaf_namespace.h"
  24. #include "yaf_exception.h"
  25. #include "yaf_config.h"
  26. #include "configs/yaf_config_ini.h"
  27. #include "configs/yaf_config_simple.h"
  28. zend_class_entry *yaf_config_ce;
  29. static zval * yaf_config_ini_zval_persistent(zval *zvalue TSRMLS_DC);
  30. static zval * yaf_config_ini_zval_losable(zval *zvalue TSRMLS_DC);
  31. /* {{{ ARG_INFO
  32. */
  33. ZEND_BEGIN_ARG_INFO_EX(yaf_config_void_arginfo, 0, 0, 0)
  34. ZEND_END_ARG_INFO()
  35. /* }}} */
  36. /** {{{ yaf_config_ini_modified
  37. */
  38. static int yaf_config_ini_modified(zval * file, long ctime TSRMLS_DC) {
  39. zval n_ctime;
  40. php_stat(Z_STRVAL_P(file), Z_STRLEN_P(file), 7 /* FS_CTIME */ , &n_ctime TSRMLS_CC);
  41. if (Z_TYPE(n_ctime) != IS_BOOL && ctime != Z_LVAL(n_ctime)) {
  42. return Z_LVAL(n_ctime);
  43. }
  44. return 0;
  45. }
  46. /* }}} */
  47. /** {{{ static void yaf_config_cache_dtor(yaf_config_cache **cache)
  48. */
  49. static void yaf_config_cache_dtor(yaf_config_cache **cache) {
  50. if (*cache) {
  51. zend_hash_destroy((*cache)->data);
  52. pefree((*cache)->data, 1);
  53. pefree(*cache, 1);
  54. }
  55. }
  56. /* }}} */
  57. /** {{{ static void yaf_config_zval_dtor(zval **value)
  58. */
  59. static void yaf_config_zval_dtor(zval **value) {
  60. if (*value) {
  61. switch(Z_TYPE_PP(value)) {
  62. case IS_STRING:
  63. case IS_CONSTANT:
  64. CHECK_ZVAL_STRING(*value);
  65. pefree((*value)->value.str.val, 1);
  66. pefree(*value, 1);
  67. break;
  68. #ifdef IS_CONSTANT_ARRAY
  69. case IS_CONSTANT_ARRAY:
  70. #endif
  71. case IS_ARRAY: {
  72. zend_hash_destroy((*value)->value.ht);
  73. pefree((*value)->value.ht, 1);
  74. pefree(*value, 1);
  75. }
  76. break;
  77. }
  78. }
  79. }
  80. /* }}} */
  81. /** {{{ static void yaf_config_copy_persistent(HashTable *pdst, HashTable *src TSRMLS_DC)
  82. */
  83. static void yaf_config_copy_persistent(HashTable *pdst, HashTable *src TSRMLS_DC) {
  84. zval **ppzval;
  85. char *key;
  86. uint keylen;
  87. ulong idx;
  88. for(zend_hash_internal_pointer_reset(src);
  89. zend_hash_has_more_elements(src) == SUCCESS;
  90. zend_hash_move_forward(src)) {
  91. if (zend_hash_get_current_key_ex(src, &key, &keylen, &idx, 0, NULL) == HASH_KEY_IS_LONG) {
  92. zval *tmp;
  93. if (zend_hash_get_current_data(src, (void**)&ppzval) == FAILURE) {
  94. continue;
  95. }
  96. tmp = yaf_config_ini_zval_persistent(*ppzval TSRMLS_CC);
  97. if (tmp) {
  98. zend_hash_index_update(pdst, idx, (void **)&tmp, sizeof(zval *), NULL);
  99. }
  100. } else {
  101. zval *tmp;
  102. if (zend_hash_get_current_data(src, (void**)&ppzval) == FAILURE) {
  103. continue;
  104. }
  105. tmp = yaf_config_ini_zval_persistent(*ppzval TSRMLS_CC);
  106. if (tmp) {
  107. zend_hash_update(pdst, key, keylen, (void **)&tmp, sizeof(zval *), NULL);
  108. }
  109. }
  110. }
  111. }
  112. /* }}} */
  113. /** {{{ static void yaf_config_copy_losable(HashTable *ldst, HashTable *src TSRMLS_DC)
  114. */
  115. static void yaf_config_copy_losable(HashTable *ldst, HashTable *src TSRMLS_DC) {
  116. zval **ppzval, *tmp;
  117. char *key;
  118. ulong idx;
  119. uint keylen;
  120. for(zend_hash_internal_pointer_reset(src);
  121. zend_hash_has_more_elements(src) == SUCCESS;
  122. zend_hash_move_forward(src)) {
  123. if (zend_hash_get_current_key_ex(src, &key, &keylen, &idx, 0, NULL) == HASH_KEY_IS_LONG) {
  124. if (zend_hash_get_current_data(src, (void**)&ppzval) == FAILURE) {
  125. continue;
  126. }
  127. tmp = yaf_config_ini_zval_losable(*ppzval TSRMLS_CC);
  128. zend_hash_index_update(ldst, idx, (void **)&tmp, sizeof(zval *), NULL);
  129. } else {
  130. if (zend_hash_get_current_data(src, (void**)&ppzval) == FAILURE) {
  131. continue;
  132. }
  133. tmp = yaf_config_ini_zval_losable(*ppzval TSRMLS_CC);
  134. zend_hash_update(ldst, key, keylen, (void **)&tmp, sizeof(zval *), NULL);
  135. }
  136. }
  137. }
  138. /* }}} */
  139. /** {{{ static zval * yaf_config_ini_zval_persistent(zval *zvalue TSRMLS_DC)
  140. */
  141. static zval * yaf_config_ini_zval_persistent(zval *zvalue TSRMLS_DC) {
  142. zval *ret = (zval *)pemalloc(sizeof(zval), 1);
  143. INIT_PZVAL(ret);
  144. switch (zvalue->type) {
  145. case IS_RESOURCE:
  146. case IS_OBJECT:
  147. break;
  148. case IS_BOOL:
  149. case IS_LONG:
  150. case IS_NULL:
  151. break;
  152. case IS_CONSTANT:
  153. case IS_STRING:
  154. CHECK_ZVAL_STRING(zvalue);
  155. Z_TYPE_P(ret) = IS_STRING;
  156. ret->value.str.val = pestrndup(zvalue->value.str.val, zvalue->value.str.len, 1);
  157. ret->value.str.len = zvalue->value.str.len;
  158. break;
  159. #ifdef IS_CONSTANT_ARRAY
  160. case IS_CONSTANT_ARRAY:
  161. #endif
  162. case IS_ARRAY: {
  163. HashTable *tmp_ht, *original_ht = zvalue->value.ht;
  164. tmp_ht = (HashTable *)pemalloc(sizeof(HashTable), 1);
  165. if (!tmp_ht) {
  166. return NULL;
  167. }
  168. zend_hash_init(tmp_ht, zend_hash_num_elements(original_ht), NULL, (dtor_func_t)yaf_config_zval_dtor, 1);
  169. yaf_config_copy_persistent(tmp_ht, original_ht TSRMLS_CC);
  170. Z_TYPE_P(ret) = IS_ARRAY;
  171. ret->value.ht = tmp_ht;
  172. }
  173. break;
  174. }
  175. return ret;
  176. }
  177. /* }}} */
  178. /** {{{ static zval * yaf_config_ini_zval_losable(zval *zvalue TSRMLS_DC)
  179. */
  180. static zval * yaf_config_ini_zval_losable(zval *zvalue TSRMLS_DC) {
  181. zval *ret;
  182. MAKE_STD_ZVAL(ret);
  183. switch (zvalue->type) {
  184. case IS_RESOURCE:
  185. case IS_OBJECT:
  186. break;
  187. case IS_BOOL:
  188. case IS_LONG:
  189. case IS_NULL:
  190. break;
  191. case IS_CONSTANT:
  192. case IS_STRING:
  193. CHECK_ZVAL_STRING(zvalue);
  194. ZVAL_STRINGL(ret, zvalue->value.str.val, zvalue->value.str.len, 1);
  195. break;
  196. #ifdef IS_CONSTANT_ARRAY
  197. case IS_CONSTANT_ARRAY:
  198. #endif
  199. case IS_ARRAY: {
  200. HashTable *original_ht = zvalue->value.ht;
  201. array_init(ret);
  202. yaf_config_copy_losable(Z_ARRVAL_P(ret), original_ht TSRMLS_CC);
  203. }
  204. break;
  205. }
  206. return ret;
  207. }
  208. /* }}} */
  209. /** {{{ static yaf_config_t * yaf_config_ini_unserialize(yaf_config_t *this_ptr, zval *filename, zval *section TSRMLS_DC)
  210. */
  211. static yaf_config_t * yaf_config_ini_unserialize(yaf_config_t *this_ptr, zval *filename, zval *section TSRMLS_DC) {
  212. char *key;
  213. uint len;
  214. yaf_config_cache **ppval;
  215. if (!YAF_G(configs)) {
  216. return NULL;
  217. }
  218. len = spprintf(&key, 0, "%s#%s", Z_STRVAL_P(filename), Z_STRVAL_P(section));
  219. if (zend_hash_find(YAF_G(configs), key, len + 1, (void **)&ppval) == SUCCESS) {
  220. if (yaf_config_ini_modified(filename, (*ppval)->ctime TSRMLS_CC)) {
  221. efree(key);
  222. return NULL;
  223. } else {
  224. zval *props;
  225. MAKE_STD_ZVAL(props);
  226. array_init(props);
  227. yaf_config_copy_losable(Z_ARRVAL_P(props), (*ppval)->data TSRMLS_CC);
  228. efree(key);
  229. /* tricky way */
  230. Z_SET_REFCOUNT_P(props, 0);
  231. return yaf_config_ini_instance(this_ptr, props, section TSRMLS_CC);
  232. }
  233. efree(key);
  234. }
  235. return NULL;
  236. }
  237. /* }}} */
  238. /** {{{ static void yaf_config_ini_serialize(yaf_config_t *this_ptr, zval *filename, zval *section TSRMLS_DC)
  239. */
  240. static void yaf_config_ini_serialize(yaf_config_t *this_ptr, zval *filename, zval *section TSRMLS_DC) {
  241. char *key;
  242. uint len;
  243. long ctime;
  244. zval *configs;
  245. HashTable *persistent;
  246. yaf_config_cache *cache;
  247. if (!YAF_G(configs)) {
  248. YAF_G(configs) = (HashTable *)pemalloc(sizeof(HashTable), 1);
  249. if (!YAF_G(configs)) {
  250. return;
  251. }
  252. zend_hash_init(YAF_G(configs), 8, NULL, (dtor_func_t) yaf_config_cache_dtor, 1);
  253. }
  254. cache = (yaf_config_cache *)pemalloc(sizeof(yaf_config_cache), 1);
  255. if (!cache) {
  256. return;
  257. }
  258. persistent = (HashTable *)pemalloc(sizeof(HashTable), 1);
  259. if (!persistent) {
  260. return;
  261. }
  262. configs = zend_read_property(yaf_config_ini_ce, this_ptr, ZEND_STRL(YAF_CONFIG_PROPERT_NAME), 1 TSRMLS_CC);
  263. zend_hash_init(persistent, zend_hash_num_elements(Z_ARRVAL_P(configs)), NULL, (dtor_func_t) yaf_config_zval_dtor, 1);
  264. yaf_config_copy_persistent(persistent, Z_ARRVAL_P(configs) TSRMLS_CC);
  265. ctime = yaf_config_ini_modified(filename, 0 TSRMLS_CC);
  266. cache->ctime = ctime;
  267. cache->data = persistent;
  268. len = spprintf(&key, 0, "%s#%s", Z_STRVAL_P(filename), Z_STRVAL_P(section));
  269. zend_hash_update(YAF_G(configs), key, len + 1, (void **)&cache, sizeof(yaf_config_cache *), NULL);
  270. efree(key);
  271. }
  272. /* }}} */
  273. /** {{{ yaf_config_t * yaf_config_instance(yaf_config_t *this_ptr, zval *arg1, zval *arg2 TSRMLS_DC)
  274. */
  275. yaf_config_t * yaf_config_instance(yaf_config_t *this_ptr, zval *arg1, zval *arg2 TSRMLS_DC) {
  276. yaf_config_t *instance;
  277. if (!arg1) {
  278. return NULL;
  279. }
  280. if (Z_TYPE_P(arg1) == IS_STRING) {
  281. if (strncasecmp(Z_STRVAL_P(arg1) + Z_STRLEN_P(arg1) - 3, "ini", 3) == 0) {
  282. if (YAF_G(cache_config)) {
  283. if ((instance = yaf_config_ini_unserialize(this_ptr, arg1, arg2 TSRMLS_CC))) {
  284. return instance;
  285. }
  286. }
  287. instance = yaf_config_ini_instance(this_ptr, arg1, arg2 TSRMLS_CC);
  288. if (!instance) {
  289. return NULL;
  290. }
  291. if (YAF_G(cache_config)) {
  292. yaf_config_ini_serialize(instance, arg1, arg2 TSRMLS_CC);
  293. }
  294. return instance;
  295. }
  296. yaf_trigger_error(YAF_ERR_TYPE_ERROR TSRMLS_CC, "Expects a path to *.ini configuration file as parameter");
  297. return NULL;
  298. }
  299. if (Z_TYPE_P(arg1) == IS_ARRAY) {
  300. zval *readonly;
  301. MAKE_STD_ZVAL(readonly);
  302. ZVAL_BOOL(readonly, 1);
  303. instance = yaf_config_simple_instance(this_ptr, arg1, readonly TSRMLS_CC);
  304. efree(readonly);
  305. return instance;
  306. }
  307. yaf_trigger_error(YAF_ERR_TYPE_ERROR TSRMLS_CC, "Expects a string or an array as parameter");
  308. return NULL;
  309. }
  310. /* }}} */
  311. /** {{{ yaf_config_methods
  312. */
  313. zend_function_entry yaf_config_methods[] = {
  314. PHP_ABSTRACT_ME(yaf_config, get, NULL)
  315. PHP_ABSTRACT_ME(yaf_config, set, NULL)
  316. PHP_ABSTRACT_ME(yaf_config, readonly, NULL)
  317. PHP_ABSTRACT_ME(yaf_config, toArray, NULL)
  318. {NULL, NULL, NULL}
  319. };
  320. /* }}} */
  321. /** {{{ YAF_STARTUP_FUNCTION
  322. */
  323. YAF_STARTUP_FUNCTION(config) {
  324. zend_class_entry ce;
  325. YAF_INIT_CLASS_ENTRY(ce, "Yaf_Config_Abstract", "Yaf\\Config_Abstract", yaf_config_methods);
  326. yaf_config_ce = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
  327. yaf_config_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
  328. zend_declare_property_null(yaf_config_ce, ZEND_STRL(YAF_CONFIG_PROPERT_NAME), ZEND_ACC_PROTECTED TSRMLS_CC);
  329. zend_declare_property_bool(yaf_config_ce, ZEND_STRL(YAF_CONFIG_PROPERT_NAME_READONLY), 1, ZEND_ACC_PROTECTED TSRMLS_CC);
  330. YAF_STARTUP(config_ini);
  331. YAF_STARTUP(config_simple);
  332. return SUCCESS;
  333. }
  334. /* }}} */
  335. /*
  336. * Local variables:
  337. * tab-width: 4
  338. * c-basic-offset: 4
  339. * End:
  340. * vim600: noet sw=4 ts=4 fdm=marker
  341. * vim<600: noet sw=4 ts=4
  342. */