PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/main/php_ini.c

http://github.com/infusion/PHP
C | 953 lines | 690 code | 117 blank | 146 comment | 193 complexity | 332ea383f967a7d2db9bf5b134094916 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2011 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: Zeev Suraski <zeev@zend.com> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id: php_ini.c 307587 2011-01-19 14:21:46Z pajoye $ */
  19. #include "php.h"
  20. #include "ext/standard/info.h"
  21. #include "zend_ini.h"
  22. #include "zend_ini_scanner.h"
  23. #include "php_ini.h"
  24. #include "ext/standard/dl.h"
  25. #include "zend_extensions.h"
  26. #include "zend_highlight.h"
  27. #include "SAPI.h"
  28. #include "php_main.h"
  29. #include "php_scandir.h"
  30. #ifdef PHP_WIN32
  31. #include "win32/php_registry.h"
  32. #endif
  33. #if HAVE_SCANDIR && HAVE_ALPHASORT && HAVE_DIRENT_H
  34. #include <dirent.h>
  35. #endif
  36. #ifndef S_ISREG
  37. #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
  38. #endif
  39. #ifdef PHP_WIN32
  40. #define TRANSLATE_SLASHES_LOWER(path) \
  41. { \
  42. char *tmp = path; \
  43. while (*tmp) { \
  44. if (*tmp == '\\') *tmp = '/'; \
  45. else *tmp = tolower(*tmp); \
  46. tmp++; \
  47. } \
  48. }
  49. #else
  50. #define TRANSLATE_SLASHES_LOWER(path)
  51. #endif
  52. typedef struct _php_extension_lists {
  53. zend_llist engine;
  54. zend_llist functions;
  55. } php_extension_lists;
  56. /* True globals */
  57. static int is_special_section = 0;
  58. static HashTable *active_ini_hash;
  59. static HashTable configuration_hash;
  60. static int has_per_dir_config = 0;
  61. static int has_per_host_config = 0;
  62. PHPAPI char *php_ini_opened_path=NULL;
  63. static php_extension_lists extension_lists;
  64. PHPAPI char *php_ini_scanned_path=NULL;
  65. PHPAPI char *php_ini_scanned_files=NULL;
  66. /* {{{ php_ini_displayer_cb
  67. */
  68. static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type TSRMLS_DC)
  69. {
  70. if (ini_entry->displayer) {
  71. ini_entry->displayer(ini_entry, type);
  72. } else {
  73. char *display_string;
  74. uint display_string_length, esc_html=0;
  75. if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
  76. if (ini_entry->orig_value && ini_entry->orig_value[0]) {
  77. display_string = ini_entry->orig_value;
  78. display_string_length = ini_entry->orig_value_length;
  79. esc_html = !sapi_module.phpinfo_as_text;
  80. } else {
  81. if (!sapi_module.phpinfo_as_text) {
  82. display_string = "<i>no value</i>";
  83. display_string_length = sizeof("<i>no value</i>") - 1;
  84. } else {
  85. display_string = "no value";
  86. display_string_length = sizeof("no value") - 1;
  87. }
  88. }
  89. } else if (ini_entry->value && ini_entry->value[0]) {
  90. display_string = ini_entry->value;
  91. display_string_length = ini_entry->value_length;
  92. esc_html = !sapi_module.phpinfo_as_text;
  93. } else {
  94. if (!sapi_module.phpinfo_as_text) {
  95. display_string = "<i>no value</i>";
  96. display_string_length = sizeof("<i>no value</i>") - 1;
  97. } else {
  98. display_string = "no value";
  99. display_string_length = sizeof("no value") - 1;
  100. }
  101. }
  102. if (esc_html) {
  103. php_html_puts(display_string, display_string_length TSRMLS_CC);
  104. } else {
  105. PHPWRITE(display_string, display_string_length);
  106. }
  107. }
  108. }
  109. /* }}} */
  110. /* {{{ php_ini_displayer
  111. */
  112. static int php_ini_displayer(zend_ini_entry *ini_entry, int module_number TSRMLS_DC)
  113. {
  114. if (ini_entry->module_number != module_number) {
  115. return 0;
  116. }
  117. if (!sapi_module.phpinfo_as_text) {
  118. PUTS("<tr>");
  119. PUTS("<td class=\"e\">");
  120. PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
  121. PUTS("</td><td class=\"v\">");
  122. php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
  123. PUTS("</td><td class=\"v\">");
  124. php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
  125. PUTS("</td></tr>\n");
  126. } else {
  127. PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
  128. PUTS(" => ");
  129. php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
  130. PUTS(" => ");
  131. php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
  132. PUTS("\n");
  133. }
  134. return 0;
  135. }
  136. /* }}} */
  137. /* {{{ php_ini_available
  138. */
  139. static int php_ini_available(zend_ini_entry *ini_entry, int *module_number_available TSRMLS_DC)
  140. {
  141. if (ini_entry->module_number == *module_number_available) {
  142. *module_number_available = -1;
  143. return ZEND_HASH_APPLY_STOP;
  144. } else {
  145. return ZEND_HASH_APPLY_KEEP;
  146. }
  147. }
  148. /* }}} */
  149. /* {{{ display_ini_entries
  150. */
  151. PHPAPI void display_ini_entries(zend_module_entry *module)
  152. {
  153. int module_number, module_number_available;
  154. TSRMLS_FETCH();
  155. if (module) {
  156. module_number = module->module_number;
  157. } else {
  158. module_number = 0;
  159. }
  160. module_number_available = module_number;
  161. zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) php_ini_available, &module_number_available TSRMLS_CC);
  162. if (module_number_available == -1) {
  163. php_info_print_table_start();
  164. php_info_print_table_header(3, "Directive", "Local Value", "Master Value");
  165. zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) php_ini_displayer, (void *) (zend_intptr_t) module_number TSRMLS_CC);
  166. php_info_print_table_end();
  167. }
  168. }
  169. /* }}} */
  170. /* php.ini support */
  171. #define PHP_EXTENSION_TOKEN "extension"
  172. #define ZEND_EXTENSION_TOKEN "zend_extension"
  173. /* {{{ config_zval_dtor
  174. */
  175. PHPAPI void config_zval_dtor(zval *zvalue)
  176. {
  177. if (Z_TYPE_P(zvalue) == IS_ARRAY) {
  178. zend_hash_destroy(Z_ARRVAL_P(zvalue));
  179. free(Z_ARRVAL_P(zvalue));
  180. } else if (Z_TYPE_P(zvalue) == IS_STRING) {
  181. free(Z_STRVAL_P(zvalue));
  182. }
  183. }
  184. /* Reset / free active_ini_sectin global */
  185. #define RESET_ACTIVE_INI_HASH() do { \
  186. active_ini_hash = NULL; \
  187. is_special_section = 0; \
  188. } while (0)
  189. /* }}} */
  190. /* {{{ php_ini_parser_cb
  191. */
  192. static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, HashTable *target_hash)
  193. {
  194. zval *entry;
  195. HashTable *active_hash;
  196. char *extension_name;
  197. if (active_ini_hash) {
  198. active_hash = active_ini_hash;
  199. } else {
  200. active_hash = target_hash;
  201. }
  202. switch (callback_type) {
  203. case ZEND_INI_PARSER_ENTRY: {
  204. if (!arg2) {
  205. /* bare string - nothing to do */
  206. break;
  207. }
  208. /* PHP and Zend extensions are not added into configuration hash! */
  209. if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), PHP_EXTENSION_TOKEN)) { /* load PHP extension */
  210. extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
  211. zend_llist_add_element(&extension_lists.functions, &extension_name);
  212. } else if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), ZEND_EXTENSION_TOKEN)) { /* load Zend extension */
  213. extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
  214. zend_llist_add_element(&extension_lists.engine, &extension_name);
  215. /* All other entries are added into either configuration_hash or active ini section array */
  216. } else {
  217. /* Store in active hash */
  218. zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, arg2, sizeof(zval), (void **) &entry);
  219. Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
  220. }
  221. }
  222. break;
  223. case ZEND_INI_PARSER_POP_ENTRY: {
  224. zval *option_arr;
  225. zval *find_arr;
  226. if (!arg2) {
  227. /* bare string - nothing to do */
  228. break;
  229. }
  230. /* fprintf(stdout, "ZEND_INI_PARSER_POP_ENTRY: %s[%s] = %s\n",Z_STRVAL_P(arg1), Z_STRVAL_P(arg3), Z_STRVAL_P(arg2)); */
  231. /* If option not found in hash or is not an array -> create array, otherwise add to existing array */
  232. if (zend_hash_find(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, (void **) &find_arr) == FAILURE || Z_TYPE_P(find_arr) != IS_ARRAY) {
  233. option_arr = (zval *) pemalloc(sizeof(zval), 1);
  234. INIT_PZVAL(option_arr);
  235. Z_TYPE_P(option_arr) = IS_ARRAY;
  236. Z_ARRVAL_P(option_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
  237. zend_hash_init(Z_ARRVAL_P(option_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
  238. zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, option_arr, sizeof(zval), (void **) &find_arr);
  239. free(option_arr);
  240. }
  241. /* arg3 is possible option offset name */
  242. if (arg3 && Z_STRLEN_P(arg3) > 0) {
  243. zend_symtable_update(Z_ARRVAL_P(find_arr), Z_STRVAL_P(arg3), Z_STRLEN_P(arg3) + 1, arg2, sizeof(zval), (void **) &entry);
  244. } else {
  245. zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2, sizeof(zval), (void **) &entry);
  246. }
  247. Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
  248. }
  249. break;
  250. case ZEND_INI_PARSER_SECTION: { /* Create an array of entries of each section */
  251. /* fprintf(stdout, "ZEND_INI_PARSER_SECTION: %s\n",Z_STRVAL_P(arg1)); */
  252. char *key = NULL;
  253. uint key_len;
  254. /* PATH sections */
  255. if (!strncasecmp(Z_STRVAL_P(arg1), "PATH", sizeof("PATH") - 1)) {
  256. key = Z_STRVAL_P(arg1);
  257. key = key + sizeof("PATH") - 1;
  258. key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1;
  259. is_special_section = 1;
  260. has_per_dir_config = 1;
  261. /* make the path lowercase on Windows, for case insensitivty. Does nothign for other platforms */
  262. TRANSLATE_SLASHES_LOWER(key);
  263. /* HOST sections */
  264. } else if (!strncasecmp(Z_STRVAL_P(arg1), "HOST", sizeof("HOST") - 1)) {
  265. key = Z_STRVAL_P(arg1);
  266. key = key + sizeof("HOST") - 1;
  267. key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1;
  268. is_special_section = 1;
  269. has_per_host_config = 1;
  270. zend_str_tolower(key, key_len); /* host names are case-insensitive. */
  271. } else {
  272. is_special_section = 0;
  273. }
  274. if (key && key_len > 0) {
  275. /* Strip any trailing slashes */
  276. while (key_len > 0 && (key[key_len - 1] == '/' || key[key_len - 1] == '\\')) {
  277. key_len--;
  278. key[key_len] = 0;
  279. }
  280. /* Strip any leading whitespace and '=' */
  281. while (*key && (
  282. *key == '=' ||
  283. *key == ' ' ||
  284. *key == '\t'
  285. )) {
  286. key++;
  287. key_len--;
  288. }
  289. /* Search for existing entry and if it does not exist create one */
  290. if (zend_hash_find(target_hash, key, key_len + 1, (void **) &entry) == FAILURE) {
  291. zval *section_arr;
  292. section_arr = (zval *) pemalloc(sizeof(zval), 1);
  293. INIT_PZVAL(section_arr);
  294. Z_TYPE_P(section_arr) = IS_ARRAY;
  295. Z_ARRVAL_P(section_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
  296. zend_hash_init(Z_ARRVAL_P(section_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
  297. zend_hash_update(target_hash, key, key_len + 1, section_arr, sizeof(zval), (void **) &entry);
  298. free(section_arr);
  299. }
  300. active_ini_hash = Z_ARRVAL_P(entry);
  301. }
  302. }
  303. break;
  304. }
  305. }
  306. /* }}} */
  307. /* {{{ php_load_php_extension_cb
  308. */
  309. static void php_load_php_extension_cb(void *arg TSRMLS_DC)
  310. {
  311. #ifdef HAVE_LIBDL
  312. php_load_extension(*((char **) arg), MODULE_PERSISTENT, 0 TSRMLS_CC);
  313. #endif
  314. }
  315. /* }}} */
  316. /* {{{ php_load_zend_extension_cb
  317. */
  318. static void php_load_zend_extension_cb(void *arg TSRMLS_DC)
  319. {
  320. zend_load_extension(*((char **) arg));
  321. }
  322. /* }}} */
  323. /* {{{ php_init_config
  324. */
  325. int php_init_config(TSRMLS_D)
  326. {
  327. char *php_ini_file_name = NULL;
  328. char *php_ini_search_path = NULL;
  329. int php_ini_scanned_path_len;
  330. char *open_basedir;
  331. int free_ini_search_path = 0;
  332. zend_file_handle fh;
  333. if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) config_zval_dtor, 1) == FAILURE) {
  334. return FAILURE;
  335. }
  336. if (sapi_module.ini_defaults) {
  337. sapi_module.ini_defaults(&configuration_hash);
  338. }
  339. zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
  340. zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
  341. open_basedir = PG(open_basedir);
  342. if (sapi_module.php_ini_path_override) {
  343. php_ini_file_name = sapi_module.php_ini_path_override;
  344. php_ini_search_path = sapi_module.php_ini_path_override;
  345. free_ini_search_path = 0;
  346. } else if (!sapi_module.php_ini_ignore) {
  347. int search_path_size;
  348. char *default_location;
  349. char *env_location;
  350. char *binary_location;
  351. static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 };
  352. #ifdef PHP_WIN32
  353. char *reg_location;
  354. char phprc_path[MAXPATHLEN];
  355. #endif
  356. env_location = getenv("PHPRC");
  357. #ifdef PHP_WIN32
  358. if (!env_location) {
  359. char dummybuf;
  360. int size;
  361. SetLastError(0);
  362. /*If the given bugger is not large enough to hold the data, the return value is
  363. the buffer size, in characters, required to hold the string and its terminating
  364. null character. We use this return value to alloc the final buffer. */
  365. size = GetEnvironmentVariableA("PHPRC", &dummybuf, 0);
  366. if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
  367. /* The environment variable doesn't exist. */
  368. env_location = "";
  369. } else {
  370. if (size == 0) {
  371. env_location = "";
  372. } else {
  373. size = GetEnvironmentVariableA("PHPRC", phprc_path, size);
  374. env_location = phprc_path;
  375. }
  376. }
  377. }
  378. #else
  379. if (!env_location) {
  380. env_location = "";
  381. }
  382. #endif
  383. /*
  384. * Prepare search path
  385. */
  386. search_path_size = MAXPATHLEN * 4 + strlen(env_location) + 3 + 1;
  387. php_ini_search_path = (char *) emalloc(search_path_size);
  388. free_ini_search_path = 1;
  389. php_ini_search_path[0] = 0;
  390. /* Add environment location */
  391. if (env_location[0]) {
  392. if (*php_ini_search_path) {
  393. strlcat(php_ini_search_path, paths_separator, search_path_size);
  394. }
  395. strlcat(php_ini_search_path, env_location, search_path_size);
  396. php_ini_file_name = env_location;
  397. }
  398. #ifdef PHP_WIN32
  399. /* Add registry location */
  400. reg_location = GetIniPathFromRegistry();
  401. if (reg_location != NULL) {
  402. if (*php_ini_search_path) {
  403. strlcat(php_ini_search_path, paths_separator, search_path_size);
  404. }
  405. strlcat(php_ini_search_path, reg_location, search_path_size);
  406. efree(reg_location);
  407. }
  408. #endif
  409. /* Add cwd (not with CLI) */
  410. if (strcmp(sapi_module.name, "cli") != 0) {
  411. if (*php_ini_search_path) {
  412. strlcat(php_ini_search_path, paths_separator, search_path_size);
  413. }
  414. strlcat(php_ini_search_path, ".", search_path_size);
  415. }
  416. /* Add binary directory */
  417. #ifdef PHP_WIN32
  418. binary_location = (char *) emalloc(MAXPATHLEN);
  419. if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
  420. efree(binary_location);
  421. binary_location = NULL;
  422. }
  423. #else
  424. if (sapi_module.executable_location) {
  425. binary_location = (char *)emalloc(MAXPATHLEN);
  426. if (!strchr(sapi_module.executable_location, '/')) {
  427. char *envpath, *path;
  428. int found = 0;
  429. if ((envpath = getenv("PATH")) != NULL) {
  430. char *search_dir, search_path[MAXPATHLEN];
  431. char *last;
  432. path = estrdup(envpath);
  433. search_dir = php_strtok_r(path, ":", &last);
  434. while (search_dir) {
  435. snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location);
  436. if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK)) {
  437. found = 1;
  438. break;
  439. }
  440. search_dir = php_strtok_r(NULL, ":", &last);
  441. }
  442. efree(path);
  443. }
  444. if (!found) {
  445. efree(binary_location);
  446. binary_location = NULL;
  447. }
  448. } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
  449. efree(binary_location);
  450. binary_location = NULL;
  451. }
  452. } else {
  453. binary_location = NULL;
  454. }
  455. #endif
  456. if (binary_location) {
  457. char *separator_location = strrchr(binary_location, DEFAULT_SLASH);
  458. if (separator_location && separator_location != binary_location) {
  459. *(separator_location) = 0;
  460. }
  461. if (*php_ini_search_path) {
  462. strlcat(php_ini_search_path, paths_separator, search_path_size);
  463. }
  464. strlcat(php_ini_search_path, binary_location, search_path_size);
  465. efree(binary_location);
  466. }
  467. /* Add default location */
  468. #ifdef PHP_WIN32
  469. default_location = (char *) emalloc(MAXPATHLEN + 1);
  470. if (0 < GetWindowsDirectory(default_location, MAXPATHLEN)) {
  471. if (*php_ini_search_path) {
  472. strlcat(php_ini_search_path, paths_separator, search_path_size);
  473. }
  474. strlcat(php_ini_search_path, default_location, search_path_size);
  475. }
  476. /* For people running under terminal services, GetWindowsDirectory will
  477. * return their personal Windows directory, so lets add the system
  478. * windows directory too */
  479. if (0 < GetSystemWindowsDirectory(default_location, MAXPATHLEN)) {
  480. if (*php_ini_search_path) {
  481. strlcat(php_ini_search_path, paths_separator, search_path_size);
  482. }
  483. strlcat(php_ini_search_path, default_location, search_path_size);
  484. }
  485. efree(default_location);
  486. #else
  487. default_location = PHP_CONFIG_FILE_PATH;
  488. if (*php_ini_search_path) {
  489. strlcat(php_ini_search_path, paths_separator, search_path_size);
  490. }
  491. strlcat(php_ini_search_path, default_location, search_path_size);
  492. #endif
  493. }
  494. PG(open_basedir) = NULL;
  495. /*
  496. * Find and open actual ini file
  497. */
  498. memset(&fh, 0, sizeof(fh));
  499. /* If SAPI does not want to ignore all ini files OR an overriding file/path is given.
  500. * This allows disabling scanning for ini files in the PHP_CONFIG_FILE_SCAN_DIR but still
  501. * load an optional ini file. */
  502. if (!sapi_module.php_ini_ignore || sapi_module.php_ini_path_override) {
  503. /* Check if php_ini_file_name is a file and can be opened */
  504. if (php_ini_file_name && php_ini_file_name[0]) {
  505. struct stat statbuf;
  506. if (!VCWD_STAT(php_ini_file_name, &statbuf)) {
  507. if (!((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
  508. fh.handle.fp = VCWD_FOPEN(php_ini_file_name, "r");
  509. if (fh.handle.fp) {
  510. fh.filename = php_ini_opened_path = expand_filepath(php_ini_file_name, NULL TSRMLS_CC);
  511. }
  512. }
  513. }
  514. }
  515. /* Otherwise search for php-%sapi-module-name%.ini file in search path */
  516. if (!fh.handle.fp) {
  517. const char *fmt = "php-%s.ini";
  518. char *ini_fname;
  519. spprintf(&ini_fname, 0, fmt, sapi_module.name);
  520. fh.handle.fp = php_fopen_with_path(ini_fname, "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
  521. efree(ini_fname);
  522. if (fh.handle.fp) {
  523. fh.filename = php_ini_opened_path;
  524. }
  525. }
  526. /* If still no ini file found, search for php.ini file in search path */
  527. if (!fh.handle.fp) {
  528. fh.handle.fp = php_fopen_with_path("php.ini", "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
  529. if (fh.handle.fp) {
  530. fh.filename = php_ini_opened_path;
  531. }
  532. }
  533. }
  534. if (free_ini_search_path) {
  535. efree(php_ini_search_path);
  536. }
  537. PG(open_basedir) = open_basedir;
  538. if (fh.handle.fp) {
  539. fh.type = ZEND_HANDLE_FP;
  540. RESET_ACTIVE_INI_HASH();
  541. zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
  542. {
  543. zval tmp;
  544. Z_STRLEN(tmp) = strlen(fh.filename);
  545. Z_STRVAL(tmp) = zend_strndup(fh.filename, Z_STRLEN(tmp));
  546. Z_TYPE(tmp) = IS_STRING;
  547. Z_SET_REFCOUNT(tmp, 0);
  548. zend_hash_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path"), (void *) &tmp, sizeof(zval), NULL);
  549. if (php_ini_opened_path) {
  550. efree(php_ini_opened_path);
  551. }
  552. php_ini_opened_path = zend_strndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
  553. }
  554. }
  555. /* Check for PHP_INI_SCAN_DIR environment variable to override/set config file scan directory */
  556. php_ini_scanned_path = getenv("PHP_INI_SCAN_DIR");
  557. if (!php_ini_scanned_path) {
  558. /* Or fall back using possible --with-config-file-scan-dir setting (defaults to empty string!) */
  559. php_ini_scanned_path = PHP_CONFIG_FILE_SCAN_DIR;
  560. }
  561. php_ini_scanned_path_len = strlen(php_ini_scanned_path);
  562. /* Scan and parse any .ini files found in scan path if path not empty. */
  563. if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) {
  564. struct dirent **namelist;
  565. int ndir, i;
  566. struct stat sb;
  567. char ini_file[MAXPATHLEN];
  568. char *p;
  569. zend_file_handle fh2;
  570. zend_llist scanned_ini_list;
  571. zend_llist_element *element;
  572. int l, total_l = 0;
  573. if ((ndir = php_scandir(php_ini_scanned_path, &namelist, 0, php_alphasort)) > 0) {
  574. zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
  575. memset(&fh2, 0, sizeof(fh2));
  576. for (i = 0; i < ndir; i++) {
  577. /* check for any file with .ini extension */
  578. if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) {
  579. free(namelist[i]);
  580. continue;
  581. }
  582. /* Reset active ini section */
  583. RESET_ACTIVE_INI_HASH();
  584. if (IS_SLASH(php_ini_scanned_path[php_ini_scanned_path_len - 1])) {
  585. snprintf(ini_file, MAXPATHLEN, "%s%s", php_ini_scanned_path, namelist[i]->d_name);
  586. } else {
  587. snprintf(ini_file, MAXPATHLEN, "%s%c%s", php_ini_scanned_path, DEFAULT_SLASH, namelist[i]->d_name);
  588. }
  589. if (VCWD_STAT(ini_file, &sb) == 0) {
  590. if (S_ISREG(sb.st_mode)) {
  591. if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
  592. fh2.filename = ini_file;
  593. fh2.type = ZEND_HANDLE_FP;
  594. if (zend_parse_ini_file(&fh2, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) {
  595. /* Here, add it to the list of ini files read */
  596. l = strlen(ini_file);
  597. total_l += l + 2;
  598. p = estrndup(ini_file, l);
  599. zend_llist_add_element(&scanned_ini_list, &p);
  600. }
  601. }
  602. }
  603. }
  604. free(namelist[i]);
  605. }
  606. free(namelist);
  607. if (total_l) {
  608. int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0;
  609. php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
  610. if (!php_ini_scanned_files_len) {
  611. *php_ini_scanned_files = '\0';
  612. }
  613. total_l += php_ini_scanned_files_len;
  614. for (element = scanned_ini_list.head; element; element = element->next) {
  615. if (php_ini_scanned_files_len) {
  616. strlcat(php_ini_scanned_files, ",\n", total_l);
  617. }
  618. strlcat(php_ini_scanned_files, *(char **)element->data, total_l);
  619. strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l);
  620. }
  621. }
  622. zend_llist_destroy(&scanned_ini_list);
  623. }
  624. } else {
  625. /* Make sure an empty php_ini_scanned_path ends up as NULL */
  626. php_ini_scanned_path = NULL;
  627. }
  628. if (sapi_module.ini_entries) {
  629. /* Reset active ini section */
  630. RESET_ACTIVE_INI_HASH();
  631. zend_parse_ini_string(sapi_module.ini_entries, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
  632. }
  633. return SUCCESS;
  634. }
  635. /* }}} */
  636. /* {{{ php_shutdown_config
  637. */
  638. int php_shutdown_config(void)
  639. {
  640. zend_hash_destroy(&configuration_hash);
  641. if (php_ini_opened_path) {
  642. free(php_ini_opened_path);
  643. php_ini_opened_path = NULL;
  644. }
  645. if (php_ini_scanned_files) {
  646. free(php_ini_scanned_files);
  647. php_ini_scanned_files = NULL;
  648. }
  649. return SUCCESS;
  650. }
  651. /* }}} */
  652. /* {{{ php_ini_register_extensions
  653. */
  654. void php_ini_register_extensions(TSRMLS_D)
  655. {
  656. zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC);
  657. zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC);
  658. zend_llist_destroy(&extension_lists.engine);
  659. zend_llist_destroy(&extension_lists.functions);
  660. }
  661. /* }}} */
  662. /* {{{ php_parse_user_ini_file
  663. */
  664. PHPAPI int php_parse_user_ini_file(const char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC)
  665. {
  666. struct stat sb;
  667. char ini_file[MAXPATHLEN];
  668. zend_file_handle fh;
  669. snprintf(ini_file, MAXPATHLEN, "%s%c%s", dirname, DEFAULT_SLASH, ini_filename);
  670. if (VCWD_STAT(ini_file, &sb) == 0) {
  671. if (S_ISREG(sb.st_mode)) {
  672. memset(&fh, 0, sizeof(fh));
  673. if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
  674. fh.filename = ini_file;
  675. fh.type = ZEND_HANDLE_FP;
  676. /* Reset active ini section */
  677. RESET_ACTIVE_INI_HASH();
  678. if (zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, target_hash TSRMLS_CC) == SUCCESS) {
  679. /* FIXME: Add parsed file to the list of user files read? */
  680. return SUCCESS;
  681. }
  682. return FAILURE;
  683. }
  684. }
  685. }
  686. return FAILURE;
  687. }
  688. /* }}} */
  689. /* {{{ php_ini_activate_config
  690. */
  691. PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC)
  692. {
  693. char *str;
  694. zval *data;
  695. uint str_len;
  696. ulong num_index;
  697. /* Walk through config hash and alter matching ini entries using the values found in the hash */
  698. for (zend_hash_internal_pointer_reset(source_hash);
  699. zend_hash_get_current_key_ex(source_hash, &str, &str_len, &num_index, 0, NULL) == HASH_KEY_IS_STRING;
  700. zend_hash_move_forward(source_hash)
  701. ) {
  702. zend_hash_get_current_data(source_hash, (void **) &data);
  703. zend_alter_ini_entry_ex(str, str_len, Z_STRVAL_P(data), Z_STRLEN_P(data), modify_type, stage, 0 TSRMLS_CC);
  704. }
  705. }
  706. /* }}} */
  707. /* {{{ php_ini_has_per_dir_config
  708. */
  709. PHPAPI int php_ini_has_per_dir_config(void)
  710. {
  711. return has_per_dir_config;
  712. }
  713. /* }}} */
  714. /* {{{ php_ini_activate_per_dir_config
  715. */
  716. PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC)
  717. {
  718. zval *tmp2;
  719. char *ptr;
  720. #if PHP_WIN32
  721. char path_bak[MAXPATHLEN];
  722. #endif
  723. if (path_len > MAXPATHLEN) {
  724. return;
  725. }
  726. #if PHP_WIN32
  727. memcpy(path_bak, path, path_len);
  728. path_bak[path_len - 1] = 0;
  729. TRANSLATE_SLASHES_LOWER(path_bak);
  730. path = path_bak;
  731. #endif
  732. /* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
  733. if (has_per_dir_config && path && path_len) {
  734. ptr = path + 1;
  735. while ((ptr = strchr(ptr, '/')) != NULL) {
  736. *ptr = 0;
  737. /* Search for source array matching the path from configuration_hash */
  738. if (zend_hash_find(&configuration_hash, path, strlen(path) + 1, (void **) &tmp2) == SUCCESS) {
  739. php_ini_activate_config(Z_ARRVAL_P(tmp2), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
  740. }
  741. *ptr = '/';
  742. ptr++;
  743. }
  744. }
  745. }
  746. /* }}} */
  747. /* {{{ php_ini_has_per_host_config
  748. */
  749. PHPAPI int php_ini_has_per_host_config(void)
  750. {
  751. return has_per_host_config;
  752. }
  753. /* }}} */
  754. /* {{{ php_ini_activate_per_host_config
  755. */
  756. PHPAPI void php_ini_activate_per_host_config(const char *host, uint host_len TSRMLS_DC)
  757. {
  758. zval *tmp;
  759. if (has_per_host_config && host && host_len) {
  760. /* Search for source array matching the host from configuration_hash */
  761. if (zend_hash_find(&configuration_hash, host, host_len, (void **) &tmp) == SUCCESS) {
  762. php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
  763. }
  764. }
  765. }
  766. /* }}} */
  767. /* {{{ cfg_get_entry
  768. */
  769. PHPAPI zval *cfg_get_entry(const char *name, uint name_length)
  770. {
  771. zval *tmp;
  772. if (zend_hash_find(&configuration_hash, name, name_length, (void **) &tmp) == SUCCESS) {
  773. return tmp;
  774. } else {
  775. return NULL;
  776. }
  777. }
  778. /* }}} */
  779. /* {{{ cfg_get_long
  780. */
  781. PHPAPI int cfg_get_long(const char *varname, long *result)
  782. {
  783. zval *tmp, var;
  784. if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
  785. *result = 0;
  786. return FAILURE;
  787. }
  788. var = *tmp;
  789. zval_copy_ctor(&var);
  790. convert_to_long(&var);
  791. *result = Z_LVAL(var);
  792. return SUCCESS;
  793. }
  794. /* }}} */
  795. /* {{{ cfg_get_double
  796. */
  797. PHPAPI int cfg_get_double(const char *varname, double *result)
  798. {
  799. zval *tmp, var;
  800. if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
  801. *result = (double) 0;
  802. return FAILURE;
  803. }
  804. var = *tmp;
  805. zval_copy_ctor(&var);
  806. convert_to_double(&var);
  807. *result = Z_DVAL(var);
  808. return SUCCESS;
  809. }
  810. /* }}} */
  811. /* {{{ cfg_get_string
  812. */
  813. PHPAPI int cfg_get_string(const char *varname, char **result)
  814. {
  815. zval *tmp;
  816. if (zend_hash_find(&configuration_hash, varname, strlen(varname)+1, (void **) &tmp) == FAILURE) {
  817. *result = NULL;
  818. return FAILURE;
  819. }
  820. *result = Z_STRVAL_P(tmp);
  821. return SUCCESS;
  822. }
  823. /* }}} */
  824. PHPAPI HashTable* php_ini_get_configuration_hash(void) /* {{{ */
  825. {
  826. return &configuration_hash;
  827. } /* }}} */
  828. /*
  829. * Local variables:
  830. * tab-width: 4
  831. * c-basic-offset: 4
  832. * indent-tabs-mode: t
  833. * End:
  834. * vim600: sw=4 ts=4 fdm=marker
  835. * vim<600: sw=4 ts=4
  836. */