php_ini.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 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$ */
  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 insensitivity. Does nothing 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. char *filename = *((char **) arg);
  321. int length = strlen(filename);
  322. if (IS_ABSOLUTE_PATH(filename, length)) {
  323. zend_load_extension(filename);
  324. } else {
  325. char *libpath;
  326. char *extension_dir = INI_STR("extension_dir");
  327. int extension_dir_len = strlen(extension_dir);
  328. if (IS_SLASH(extension_dir[extension_dir_len-1])) {
  329. spprintf(&libpath, 0, "%s%s", extension_dir, filename);
  330. } else {
  331. spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename);
  332. }
  333. zend_load_extension(libpath);
  334. efree(libpath);
  335. }
  336. }
  337. /* }}} */
  338. /* {{{ php_init_config
  339. */
  340. int php_init_config(TSRMLS_D)
  341. {
  342. char *php_ini_file_name = NULL;
  343. char *php_ini_search_path = NULL;
  344. int php_ini_scanned_path_len;
  345. char *open_basedir;
  346. int free_ini_search_path = 0;
  347. zend_file_handle fh;
  348. if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) config_zval_dtor, 1) == FAILURE) {
  349. return FAILURE;
  350. }
  351. if (sapi_module.ini_defaults) {
  352. sapi_module.ini_defaults(&configuration_hash);
  353. }
  354. zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
  355. zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
  356. open_basedir = PG(open_basedir);
  357. if (sapi_module.php_ini_path_override) {
  358. php_ini_file_name = sapi_module.php_ini_path_override;
  359. php_ini_search_path = sapi_module.php_ini_path_override;
  360. free_ini_search_path = 0;
  361. } else if (!sapi_module.php_ini_ignore) {
  362. int search_path_size;
  363. char *default_location;
  364. char *env_location;
  365. static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 };
  366. #ifdef PHP_WIN32
  367. char *reg_location;
  368. char phprc_path[MAXPATHLEN];
  369. #endif
  370. env_location = getenv("PHPRC");
  371. #ifdef PHP_WIN32
  372. if (!env_location) {
  373. char dummybuf;
  374. int size;
  375. SetLastError(0);
  376. /*If the given bugger is not large enough to hold the data, the return value is
  377. the buffer size, in characters, required to hold the string and its terminating
  378. null character. We use this return value to alloc the final buffer. */
  379. size = GetEnvironmentVariableA("PHPRC", &dummybuf, 0);
  380. if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
  381. /* The environment variable doesn't exist. */
  382. env_location = "";
  383. } else {
  384. if (size == 0) {
  385. env_location = "";
  386. } else {
  387. size = GetEnvironmentVariableA("PHPRC", phprc_path, size);
  388. if (size == 0) {
  389. env_location = "";
  390. } else {
  391. env_location = phprc_path;
  392. }
  393. }
  394. }
  395. }
  396. #else
  397. if (!env_location) {
  398. env_location = "";
  399. }
  400. #endif
  401. /*
  402. * Prepare search path
  403. */
  404. search_path_size = MAXPATHLEN * 4 + strlen(env_location) + 3 + 1;
  405. php_ini_search_path = (char *) emalloc(search_path_size);
  406. free_ini_search_path = 1;
  407. php_ini_search_path[0] = 0;
  408. /* Add environment location */
  409. if (env_location[0]) {
  410. if (*php_ini_search_path) {
  411. strlcat(php_ini_search_path, paths_separator, search_path_size);
  412. }
  413. strlcat(php_ini_search_path, env_location, search_path_size);
  414. php_ini_file_name = env_location;
  415. }
  416. #ifdef PHP_WIN32
  417. /* Add registry location */
  418. reg_location = GetIniPathFromRegistry();
  419. if (reg_location != NULL) {
  420. if (*php_ini_search_path) {
  421. strlcat(php_ini_search_path, paths_separator, search_path_size);
  422. }
  423. strlcat(php_ini_search_path, reg_location, search_path_size);
  424. efree(reg_location);
  425. }
  426. #endif
  427. /* Add cwd (not with CLI) */
  428. if (!sapi_module.php_ini_ignore_cwd) {
  429. if (*php_ini_search_path) {
  430. strlcat(php_ini_search_path, paths_separator, search_path_size);
  431. }
  432. strlcat(php_ini_search_path, ".", search_path_size);
  433. }
  434. if (PG(php_binary)) {
  435. char *separator_location, *binary_location;
  436. binary_location = estrdup(PG(php_binary));
  437. separator_location = strrchr(binary_location, DEFAULT_SLASH);
  438. if (separator_location && separator_location != binary_location) {
  439. *(separator_location) = 0;
  440. }
  441. if (*php_ini_search_path) {
  442. strlcat(php_ini_search_path, paths_separator, search_path_size);
  443. }
  444. strlcat(php_ini_search_path, binary_location, search_path_size);
  445. efree(binary_location);
  446. }
  447. /* Add default location */
  448. #ifdef PHP_WIN32
  449. default_location = (char *) emalloc(MAXPATHLEN + 1);
  450. if (0 < GetWindowsDirectory(default_location, MAXPATHLEN)) {
  451. if (*php_ini_search_path) {
  452. strlcat(php_ini_search_path, paths_separator, search_path_size);
  453. }
  454. strlcat(php_ini_search_path, default_location, search_path_size);
  455. }
  456. /* For people running under terminal services, GetWindowsDirectory will
  457. * return their personal Windows directory, so lets add the system
  458. * windows directory too */
  459. if (0 < GetSystemWindowsDirectory(default_location, MAXPATHLEN)) {
  460. if (*php_ini_search_path) {
  461. strlcat(php_ini_search_path, paths_separator, search_path_size);
  462. }
  463. strlcat(php_ini_search_path, default_location, search_path_size);
  464. }
  465. efree(default_location);
  466. #else
  467. default_location = PHP_CONFIG_FILE_PATH;
  468. if (*php_ini_search_path) {
  469. strlcat(php_ini_search_path, paths_separator, search_path_size);
  470. }
  471. strlcat(php_ini_search_path, default_location, search_path_size);
  472. #endif
  473. }
  474. PG(open_basedir) = NULL;
  475. /*
  476. * Find and open actual ini file
  477. */
  478. memset(&fh, 0, sizeof(fh));
  479. /* If SAPI does not want to ignore all ini files OR an overriding file/path is given.
  480. * This allows disabling scanning for ini files in the PHP_CONFIG_FILE_SCAN_DIR but still
  481. * load an optional ini file. */
  482. if (!sapi_module.php_ini_ignore || sapi_module.php_ini_path_override) {
  483. /* Check if php_ini_file_name is a file and can be opened */
  484. if (php_ini_file_name && php_ini_file_name[0]) {
  485. struct stat statbuf;
  486. if (!VCWD_STAT(php_ini_file_name, &statbuf)) {
  487. if (!((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
  488. fh.handle.fp = VCWD_FOPEN(php_ini_file_name, "r");
  489. if (fh.handle.fp) {
  490. fh.filename = php_ini_opened_path = expand_filepath(php_ini_file_name, NULL TSRMLS_CC);
  491. }
  492. }
  493. }
  494. }
  495. /* Otherwise search for php-%sapi-module-name%.ini file in search path */
  496. if (!fh.handle.fp) {
  497. const char *fmt = "php-%s.ini";
  498. char *ini_fname;
  499. spprintf(&ini_fname, 0, fmt, sapi_module.name);
  500. fh.handle.fp = php_fopen_with_path(ini_fname, "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
  501. efree(ini_fname);
  502. if (fh.handle.fp) {
  503. fh.filename = php_ini_opened_path;
  504. }
  505. }
  506. /* If still no ini file found, search for php.ini file in search path */
  507. if (!fh.handle.fp) {
  508. fh.handle.fp = php_fopen_with_path("php.ini", "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
  509. if (fh.handle.fp) {
  510. fh.filename = php_ini_opened_path;
  511. }
  512. }
  513. }
  514. if (free_ini_search_path) {
  515. efree(php_ini_search_path);
  516. }
  517. PG(open_basedir) = open_basedir;
  518. if (fh.handle.fp) {
  519. fh.type = ZEND_HANDLE_FP;
  520. RESET_ACTIVE_INI_HASH();
  521. zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
  522. {
  523. zval tmp;
  524. Z_STRLEN(tmp) = strlen(fh.filename);
  525. Z_STRVAL(tmp) = zend_strndup(fh.filename, Z_STRLEN(tmp));
  526. Z_TYPE(tmp) = IS_STRING;
  527. Z_SET_REFCOUNT(tmp, 0);
  528. zend_hash_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path"), (void *) &tmp, sizeof(zval), NULL);
  529. if (php_ini_opened_path) {
  530. efree(php_ini_opened_path);
  531. }
  532. php_ini_opened_path = zend_strndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
  533. }
  534. }
  535. /* Check for PHP_INI_SCAN_DIR environment variable to override/set config file scan directory */
  536. php_ini_scanned_path = getenv("PHP_INI_SCAN_DIR");
  537. if (!php_ini_scanned_path) {
  538. /* Or fall back using possible --with-config-file-scan-dir setting (defaults to empty string!) */
  539. php_ini_scanned_path = PHP_CONFIG_FILE_SCAN_DIR;
  540. }
  541. php_ini_scanned_path_len = strlen(php_ini_scanned_path);
  542. /* Scan and parse any .ini files found in scan path if path not empty. */
  543. if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) {
  544. struct dirent **namelist;
  545. int ndir, i;
  546. struct stat sb;
  547. char ini_file[MAXPATHLEN];
  548. char *p;
  549. zend_file_handle fh2;
  550. zend_llist scanned_ini_list;
  551. zend_llist_element *element;
  552. int l, total_l = 0;
  553. char *bufpath, *debpath, *endpath;
  554. int lenpath;
  555. zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
  556. memset(&fh2, 0, sizeof(fh2));
  557. bufpath = estrdup(php_ini_scanned_path);
  558. for (debpath = bufpath ; debpath ; debpath=endpath) {
  559. endpath = strchr(debpath, DEFAULT_DIR_SEPARATOR);
  560. if (endpath) {
  561. *(endpath++) = 0;
  562. }
  563. if (!debpath[0]) {
  564. /* empty string means default builtin value
  565. to allow "/foo/phd.d:" or ":/foo/php.d" */
  566. debpath = PHP_CONFIG_FILE_SCAN_DIR;
  567. }
  568. lenpath = strlen(debpath);
  569. if (lenpath > 0 && (ndir = php_scandir(debpath, &namelist, 0, php_alphasort)) > 0) {
  570. for (i = 0; i < ndir; i++) {
  571. /* check for any file with .ini extension */
  572. if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) {
  573. free(namelist[i]);
  574. continue;
  575. }
  576. /* Reset active ini section */
  577. RESET_ACTIVE_INI_HASH();
  578. if (IS_SLASH(debpath[lenpath - 1])) {
  579. snprintf(ini_file, MAXPATHLEN, "%s%s", debpath, namelist[i]->d_name);
  580. } else {
  581. snprintf(ini_file, MAXPATHLEN, "%s%c%s", debpath, DEFAULT_SLASH, namelist[i]->d_name);
  582. }
  583. if (VCWD_STAT(ini_file, &sb) == 0) {
  584. if (S_ISREG(sb.st_mode)) {
  585. if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
  586. fh2.filename = ini_file;
  587. fh2.type = ZEND_HANDLE_FP;
  588. 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) {
  589. /* Here, add it to the list of ini files read */
  590. l = strlen(ini_file);
  591. total_l += l + 2;
  592. p = estrndup(ini_file, l);
  593. zend_llist_add_element(&scanned_ini_list, &p);
  594. }
  595. }
  596. }
  597. }
  598. free(namelist[i]);
  599. }
  600. free(namelist);
  601. }
  602. }
  603. efree(bufpath);
  604. if (total_l) {
  605. int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0;
  606. php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
  607. if (!php_ini_scanned_files_len) {
  608. *php_ini_scanned_files = '\0';
  609. }
  610. total_l += php_ini_scanned_files_len;
  611. for (element = scanned_ini_list.head; element; element = element->next) {
  612. if (php_ini_scanned_files_len) {
  613. strlcat(php_ini_scanned_files, ",\n", total_l);
  614. }
  615. strlcat(php_ini_scanned_files, *(char **)element->data, total_l);
  616. strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l);
  617. }
  618. }
  619. zend_llist_destroy(&scanned_ini_list);
  620. } else {
  621. /* Make sure an empty php_ini_scanned_path ends up as NULL */
  622. php_ini_scanned_path = NULL;
  623. }
  624. if (sapi_module.ini_entries) {
  625. /* Reset active ini section */
  626. RESET_ACTIVE_INI_HASH();
  627. 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);
  628. }
  629. return SUCCESS;
  630. }
  631. /* }}} */
  632. /* {{{ php_shutdown_config
  633. */
  634. int php_shutdown_config(void)
  635. {
  636. zend_hash_destroy(&configuration_hash);
  637. if (php_ini_opened_path) {
  638. free(php_ini_opened_path);
  639. php_ini_opened_path = NULL;
  640. }
  641. if (php_ini_scanned_files) {
  642. free(php_ini_scanned_files);
  643. php_ini_scanned_files = NULL;
  644. }
  645. return SUCCESS;
  646. }
  647. /* }}} */
  648. /* {{{ php_ini_register_extensions
  649. */
  650. void php_ini_register_extensions(TSRMLS_D)
  651. {
  652. zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC);
  653. zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC);
  654. zend_llist_destroy(&extension_lists.engine);
  655. zend_llist_destroy(&extension_lists.functions);
  656. }
  657. /* }}} */
  658. /* {{{ php_parse_user_ini_file
  659. */
  660. PHPAPI int php_parse_user_ini_file(const char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC)
  661. {
  662. struct stat sb;
  663. char ini_file[MAXPATHLEN];
  664. zend_file_handle fh;
  665. snprintf(ini_file, MAXPATHLEN, "%s%c%s", dirname, DEFAULT_SLASH, ini_filename);
  666. if (VCWD_STAT(ini_file, &sb) == 0) {
  667. if (S_ISREG(sb.st_mode)) {
  668. memset(&fh, 0, sizeof(fh));
  669. if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
  670. fh.filename = ini_file;
  671. fh.type = ZEND_HANDLE_FP;
  672. /* Reset active ini section */
  673. RESET_ACTIVE_INI_HASH();
  674. 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) {
  675. /* FIXME: Add parsed file to the list of user files read? */
  676. return SUCCESS;
  677. }
  678. return FAILURE;
  679. }
  680. }
  681. }
  682. return FAILURE;
  683. }
  684. /* }}} */
  685. /* {{{ php_ini_activate_config
  686. */
  687. PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC)
  688. {
  689. char *str;
  690. zval *data;
  691. uint str_len;
  692. ulong num_index;
  693. /* Walk through config hash and alter matching ini entries using the values found in the hash */
  694. for (zend_hash_internal_pointer_reset(source_hash);
  695. zend_hash_get_current_key_ex(source_hash, &str, &str_len, &num_index, 0, NULL) == HASH_KEY_IS_STRING;
  696. zend_hash_move_forward(source_hash)
  697. ) {
  698. zend_hash_get_current_data(source_hash, (void **) &data);
  699. zend_alter_ini_entry_ex(str, str_len, Z_STRVAL_P(data), Z_STRLEN_P(data), modify_type, stage, 0 TSRMLS_CC);
  700. }
  701. }
  702. /* }}} */
  703. /* {{{ php_ini_has_per_dir_config
  704. */
  705. PHPAPI int php_ini_has_per_dir_config(void)
  706. {
  707. return has_per_dir_config;
  708. }
  709. /* }}} */
  710. /* {{{ php_ini_activate_per_dir_config
  711. */
  712. PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC)
  713. {
  714. zval *tmp2;
  715. char *ptr;
  716. #if PHP_WIN32
  717. char path_bak[MAXPATHLEN];
  718. #endif
  719. #if PHP_WIN32
  720. /* MAX_PATH is \0-terminated, path_len == MAXPATHLEN would overrun path_bak */
  721. if (path_len >= MAXPATHLEN) {
  722. #else
  723. if (path_len > MAXPATHLEN) {
  724. #endif
  725. return;
  726. }
  727. #if PHP_WIN32
  728. memcpy(path_bak, path, path_len);
  729. path_bak[path_len] = 0;
  730. TRANSLATE_SLASHES_LOWER(path_bak);
  731. path = path_bak;
  732. #endif
  733. /* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
  734. if (has_per_dir_config && path && path_len) {
  735. ptr = path + 1;
  736. while ((ptr = strchr(ptr, '/')) != NULL) {
  737. *ptr = 0;
  738. /* Search for source array matching the path from configuration_hash */
  739. if (zend_hash_find(&configuration_hash, path, strlen(path) + 1, (void **) &tmp2) == SUCCESS) {
  740. php_ini_activate_config(Z_ARRVAL_P(tmp2), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
  741. }
  742. *ptr = '/';
  743. ptr++;
  744. }
  745. }
  746. }
  747. /* }}} */
  748. /* {{{ php_ini_has_per_host_config
  749. */
  750. PHPAPI int php_ini_has_per_host_config(void)
  751. {
  752. return has_per_host_config;
  753. }
  754. /* }}} */
  755. /* {{{ php_ini_activate_per_host_config
  756. */
  757. PHPAPI void php_ini_activate_per_host_config(const char *host, uint host_len TSRMLS_DC)
  758. {
  759. zval *tmp;
  760. if (has_per_host_config && host && host_len) {
  761. /* Search for source array matching the host from configuration_hash */
  762. if (zend_hash_find(&configuration_hash, host, host_len, (void **) &tmp) == SUCCESS) {
  763. php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
  764. }
  765. }
  766. }
  767. /* }}} */
  768. /* {{{ cfg_get_entry
  769. */
  770. PHPAPI zval *cfg_get_entry(const char *name, uint name_length)
  771. {
  772. zval *tmp;
  773. if (zend_hash_find(&configuration_hash, name, name_length, (void **) &tmp) == SUCCESS) {
  774. return tmp;
  775. } else {
  776. return NULL;
  777. }
  778. }
  779. /* }}} */
  780. /* {{{ cfg_get_long
  781. */
  782. PHPAPI int cfg_get_long(const char *varname, long *result)
  783. {
  784. zval *tmp, var;
  785. if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
  786. *result = 0;
  787. return FAILURE;
  788. }
  789. var = *tmp;
  790. zval_copy_ctor(&var);
  791. convert_to_long(&var);
  792. *result = Z_LVAL(var);
  793. return SUCCESS;
  794. }
  795. /* }}} */
  796. /* {{{ cfg_get_double
  797. */
  798. PHPAPI int cfg_get_double(const char *varname, double *result)
  799. {
  800. zval *tmp, var;
  801. if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
  802. *result = (double) 0;
  803. return FAILURE;
  804. }
  805. var = *tmp;
  806. zval_copy_ctor(&var);
  807. convert_to_double(&var);
  808. *result = Z_DVAL(var);
  809. return SUCCESS;
  810. }
  811. /* }}} */
  812. /* {{{ cfg_get_string
  813. */
  814. PHPAPI int cfg_get_string(const char *varname, char **result)
  815. {
  816. zval *tmp;
  817. if (zend_hash_find(&configuration_hash, varname, strlen(varname)+1, (void **) &tmp) == FAILURE) {
  818. *result = NULL;
  819. return FAILURE;
  820. }
  821. *result = Z_STRVAL_P(tmp);
  822. return SUCCESS;
  823. }
  824. /* }}} */
  825. PHPAPI HashTable* php_ini_get_configuration_hash(void) /* {{{ */
  826. {
  827. return &configuration_hash;
  828. } /* }}} */
  829. /*
  830. * Local variables:
  831. * tab-width: 4
  832. * c-basic-offset: 4
  833. * indent-tabs-mode: t
  834. * End:
  835. * vim600: sw=4 ts=4 fdm=marker
  836. * vim<600: sw=4 ts=4
  837. */