Source for file PhpSecInfo.php

Documentation is available at PhpSecInfo.php

  1. <?php
  2. /**
  3. * Main class file
  4. *
  5. * @package PhpSecInfo
  6. * @author Ed Finkler <coj@funkatron.com>
  7. */
  8.  
  9.  
  10. /**
  11. * The default language setting if none is set/retrievable
  12. *
  13. */
  14. define ('PHPSECINFO_LANG_DEFAULT', 'en');
  15.  
  16. /**
  17. * a general version string to differentiate releases
  18. *
  19. */
  20. define ('PHPSECINFO_VERSION', '0.1.1');
  21.  
  22. /**
  23. * a YYYYMMDD date string to indicate "build" date
  24. *
  25. */
  26. define ('PHPSECINFO_BUILD', '20061023');
  27.  
  28. /**
  29. * This is the main class for the phpsecinfo system. It's responsible for
  30. * dynamically loading tests, running those tests, and generating the results
  31. * output
  32. *
  33. * Example:
  34. * <code>
  35. * <?php require_once('PhpSecInfo/PhpSecInfo.php'); ?>
  36. * <?php phpsecinfo(); ?>
  37. * </code>
  38. *
  39. * If you want to capture the output, or just grab the test results and display them
  40. * in your own way, you'll need to do slightly more work.
  41. *
  42. * Example:
  43. * <code>
  44. * require_once('PhpSecInfo/PhpSecInfo.php');
  45. * // instantiate the class
  46. * $psi = new PhpSecInfo();
  47. *
  48. * // load and run all tests
  49. * $psi->loadAndRun();
  50. *
  51. * // grab the results as a multidimensional array
  52. * $results = $psi->getResultsAsArray();
  53. * echo "<pre>"; echo print_r($results, true); echo "</pre>";
  54. *
  55. * // grab the standard results output as a string
  56. * $html = $psi->getOutput();
  57. *
  58. * // send it to the browser
  59. * echo $html;
  60. * </code>
  61. *
  62. *
  63. * The procedural function "phpsecinfo" is defined below this class.
  64. * @see phpsecinfo()
  65. *
  66. * @author Ed Finkler <coj@funkatron.com>
  67. *
  68. * v0.1.1
  69. * - Added PhpSecInfo::getOutput(), PhpSecInfo::loadAndRun() and PhpSecInfo::getResultsAsArray() methods
  70. * - Modified PhpSecInfo::runTests() to fix undefined offsent notices
  71. * - Modified PhpSecInfo_Test::setMessageForResult() to fix undefined offset notices
  72. *
  73. * v0.1
  74. * - Initial public release
  75. *
  76. */
  77. class PhpSecInfo
  78. {
  79.  
  80. /**
  81. * An array of tests to run
  82. *
  83. * @var array PhpSecInfo_Test
  84. */
  85. var $tests_to_run = array();
  86.  
  87. /**
  88. * An array of results. Each result is an associative array:
  89. * <code>
  90. * $result['result'] = PHPSECINFO_TEST_RESULT_NOTICE;
  91. * $result['message'] = "a string describing the test results and what they mean";
  92. * </code>
  93. *
  94. * @var array
  95. */
  96. var $test_results = array();
  97.  
  98.  
  99. /**
  100. * An array of tests that were not run
  101. *
  102. * <code>
  103. * $result['result'] = PHPSECINFO_TEST_RESULT_NOTRUN;
  104. * $result['message'] = "a string explaining why the test was not run";
  105. * </code>
  106. *
  107. * @var array
  108. */
  109. var $tests_not_run = array();
  110.  
  111.  
  112. /**
  113. * The language code used. Defaults to PHPSECINFO_LANG_DEFAULT, which
  114. * is 'en'
  115. *
  116. * @var string
  117. * @see PHPSECINFO_LANG_DEFAULT
  118. */
  119. var $language = PHPSECINFO_LANG_DEFAULT;
  120.  
  121.  
  122. /**
  123. * An array of integers recording the number of test results in each category. Categories can include
  124. * some or all of the PHPSECINFO_TEST_* constants. Constants are the keys, # of results are the values.
  125. *
  126. * @var array
  127. */
  128. var $result_counts = array();
  129.  
  130.  
  131. /**
  132. * The number of tests that have been run
  133. *
  134. * @var integer
  135. */
  136. var $num_tests_run = 0;
  137.  
  138.  
  139. /**
  140. * Constructor
  141. *
  142. * @return PhpSecInfo
  143. */
  144. function PhpSecInfo() {
  145.  
  146. }
  147.  
  148.  
  149. /**
  150. * recurses through the Test subdir and includes classes in each test group subdir,
  151. * then builds an array of classnames for the tests that will be run
  152. *
  153. */
  154. function loadTests() {
  155.  
  156. $test_root = dir(dirname(__FILE__).DIRECTORY_SEPARATOR.'Test');
  157.  
  158. //echo "<pre>"; echo print_r($test_root, true); echo "</pre>";
  159.  
  160. while (false !== ($entry = $test_root->read())) {
  161. if ( is_dir($test_root->path.DIRECTORY_SEPARATOR.$entry) && !preg_match('|^\.(.*)$|', $entry) ) {
  162. $test_dirs[] = $entry;
  163. }
  164. }
  165. //echo "<pre>"; echo print_r($test_dirs, true); echo "</pre>";
  166.  
  167. // include_once all files in each test dir
  168. foreach ($test_dirs as $test_dir) {
  169. $this_dir = dir($test_root->path.DIRECTORY_SEPARATOR.$test_dir);
  170.  
  171. while (false !== ($entry = $this_dir->read())) {
  172. if (!is_dir($this_dir->path.DIRECTORY_SEPARATOR.$entry)) {
  173. include_once $this_dir->path.DIRECTORY_SEPARATOR.$entry;
  174. $classNames[] = "PhpSecInfo_Test_".$test_dir."_".basename($entry, '.php');
  175. }
  176. }
  177.  
  178. }
  179.  
  180. $this->tests_to_run =& $classNames;
  181. }
  182.  
  183.  
  184. /**
  185. * This runs the tests in the tests_to_run array
  186. *
  187. */
  188. function runTests() {
  189. // initialize a bunch of arrays
  190. $this->test_results = array();
  191. $this->result_counts = array();
  192. $this->result_counts[PHPSECINFO_TEST_RESULT_NOTRUN] = 0;
  193. $this->num_tests_run = 0;
  194.  
  195. /**
  196. * @var PhpSecInfo_Test
  197. */
  198. foreach ($this->tests_to_run as $testClass) {
  199. $test = new $testClass();
  200.  
  201. if ($test->isTestable()) {
  202. $test->test();
  203. $rs = array('result' => $test->getResult(), 'message' => $test->getMessage());
  204. $this->test_results[$test->getTestGroup()][$test->getTestName()] = $rs;
  205.  
  206. // initialize if not yet set
  207. if (!isset ($this->result_counts[$rs['result']]) ) {
  208. $this->result_counts[$rs['result']] = 0;
  209. }
  210.  
  211. $this->result_counts[$rs['result']]++;
  212. $this->num_tests_run++;
  213. } else {
  214. $rs = array('result' => $test->getResult(), 'message' => $test->getMessage());
  215. $this->result_counts[PHPSECINFO_TEST_RESULT_NOTRUN]++;
  216. $this->tests_not_run[$test->getTestGroup()."::".$test->getTestName()] = $rs;
  217. }
  218. }
  219. }
  220.  
  221.  
  222. /**
  223. * This is the main output method. The look and feel mimics phpinfo()
  224. *
  225. */
  226. function renderOutput() {
  227.  
  228. /**
  229. * We need to use PhpSecInfo_Test::getBooleanIniValue() below
  230. * @see PhpSecInfo_Test::getBooleanIniValue()
  231. */
  232. require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'Test'.DIRECTORY_SEPARATOR.'Test.php');
  233.  
  234.  
  235. ?>
  236. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
  237. <html><head>
  238. <style type="text/css">
  239. body {background-color: #ffffff; color: #000000;}
  240. body, td, th, h1, h2 {font-family: sans-serif;}
  241. pre {margin: 0px; font-family: monospace;}
  242. a:link {color: #000099; text-decoration: none; background-color: #ffffff;}
  243. a:hover {text-decoration: underline;}
  244. table {border-collapse: collapse;}
  245. .center {text-align: center;}
  246. .center table { margin-left: auto; margin-right: auto; text-align: left;}
  247. .center th { text-align: center !important; }
  248. td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;}
  249. h1 {font-size: 150%;}
  250. h2 {font-size: 125%;}
  251. .p {text-align: left;}
  252. .e {background-color: #ccccff; font-weight: bold; color: #000000;}
  253. .h {background-color: #9999cc; font-weight: bold; color: #000000;}
  254. .v {background-color: #cccccc; color: #000000;}
  255. .vr {background-color: #cccccc; text-align: right; color: #000000;}
  256. img {float: right; border: 0px;}
  257. hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;}
  258.  
  259. .v-ok {background-color:#009900;color:#ffffff;}
  260. .v-notice {background-color:orange;color:#000000;}
  261. .v-warn {background-color:#990000;color:#ffffff;}
  262. .v-notrun {background-color:#cccccc;color:#000000;}
  263. .v-error {background-color:#F6AE15;color:#000000;font-weight:bold;}
  264.  
  265. }
  266. </style>
  267. <title>phpsecinfo()</title></head>
  268. <body><div class="center">
  269. <table border="0" cellpadding="3" width="600">
  270. <tr class="h"><td>
  271. <h1 class="p">
  272. <?php if ( PhpSecInfo_Test::getBooleanIniValue('expose_php') ) : ?>
  273. <a href="http://www.php.net/"><img border="0" src="<?php echo '?=' . php_logo_guid() ?>" alt="PHP Logo" /></a>
  274. <?php endif; ?>
  275. PHP Environment Security Info
  276. </h1>
  277. <h2 class="p">Version <?php echo PHPSECINFO_VERSION ?>; build <?php echo PHPSECINFO_BUILD ?></h2>
  278. </td></tr>
  279. </table>
  280. <br />
  281. <?php
  282. foreach ($this->test_results as $group_name=>$group_results) {
  283. $this->_outputRenderTable($group_name, $group_results);
  284. }
  285.  
  286. $this->_outputRenderNotRunTable();
  287.  
  288. $this->_outputRenderStatsTable();
  289.  
  290. ?>
  291.  
  292. </div></body></html>
  293. <?php
  294. }
  295.  
  296.  
  297. /**
  298. * This is a helper method that makes it easy to output tables of test results
  299. * for a given test group
  300. *
  301. * @param string $group_name
  302. * @param array $group_results
  303. */
  304. function _outputRenderTable($group_name, $group_results) {
  305.  
  306. // exit out if $group_results was empty or not an array. This sorta seems a little hacky...
  307. if (!is_array($group_results) || sizeof($group_results) < 1) {
  308. return false;
  309. }
  310.  
  311. ksort($group_results);
  312.  
  313. ?>
  314. <h2><?php echo htmlspecialchars($group_name, ENT_QUOTES) ?></h2>
  315.  
  316. <table border="0" cellpadding="3" width="600">
  317. <tr class='h'>
  318. <th>Test</th>
  319. <th>Result</th>
  320. </tr>
  321. <?php foreach ($group_results as $test_name=>$test_results): ?>
  322.  
  323. <tr>
  324. <td class="e"><?php echo htmlspecialchars($test_name, ENT_QUOTES) ?></td>
  325. <td class="<?php echo $this->_outputGetCssClassFromResult($test_results['result']) ?>">
  326. <?php echo $test_results['message'] ?>
  327. </td>
  328. </tr>
  329.  
  330. <?php endforeach; ?>
  331. </table><br />
  332.  
  333. <?php
  334. return true;
  335. }
  336.  
  337.  
  338.  
  339. /**
  340. * This outputs a table containing a summary of the test results (counts and % in each result type)
  341. *
  342. * @see PHPSecInfo::_outputRenderTable()
  343. * @see PHPSecInfo::_outputGetResultTypeFromCode()
  344. */
  345. function _outputRenderStatsTable() {
  346.  
  347. foreach($this->result_counts as $code=>$val) {
  348. if ($code != PHPSECINFO_TEST_RESULT_NOTRUN) {
  349. $percentage = round($val/$this->num_tests_run * 100,2);
  350.  
  351. $stats[$this->_outputGetResultTypeFromCode($code)] = array( 'count' => $val,
  352. 'result' => $code,
  353. 'message' => "$val out of {$this->num_tests_run} ($percentage%)");
  354. }
  355. }
  356.  
  357. $this->_outputRenderTable('Test Results Summary', $stats);
  358.  
  359. }
  360.  
  361.  
  362.  
  363. /**
  364. * This outputs a table containing a summary or test that were not executed, and the reasons why they were skipped
  365. *
  366. * @see PHPSecInfo::_outputRenderTable()
  367. */
  368. function _outputRenderNotRunTable() {
  369.  
  370. $this->_outputRenderTable('Tests Not Run', $this->tests_not_run);
  371.  
  372. }
  373.  
  374.  
  375.  
  376.  
  377. /**
  378. * This is a helper function that returns a CSS class corresponding to
  379. * the result code the test returned. This allows us to color-code
  380. * results
  381. *
  382. * @param integer $code
  383. * @return string
  384. */
  385. function _outputGetCssClassFromResult($code) {
  386.  
  387. switch ($code) {
  388. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_OK">PHPSECINFO_TEST_RESULT_OK</a>:
  389. return 'v-ok';
  390. break;
  391.  
  392. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_NOTICE">PHPSECINFO_TEST_RESULT_NOTICE</a>:
  393. return 'v-notice';
  394. break;
  395.  
  396. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_WARN">PHPSECINFO_TEST_RESULT_WARN</a>:
  397. return 'v-warn';
  398. break;
  399.  
  400. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_NOTRUN">PHPSECINFO_TEST_RESULT_NOTRUN</a>:
  401. return 'v-notrun';
  402. break;
  403.  
  404. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_ERROR">PHPSECINFO_TEST_RESULT_ERROR</a>:
  405. return 'v-error';
  406. break;
  407.  
  408. default:
  409. return 'v-notrun';
  410. break;
  411. }
  412.  
  413. }
  414.  
  415.  
  416.  
  417. /**
  418. * This is a helper function that returns a label string corresponding to
  419. * the result code the test returned. This is mainly used for the Test
  420. * Results Summary table.
  421. *
  422. * @see PHPSecInfo::_outputRenderStatsTable()
  423. * @param integer $code
  424. * @return string
  425. */
  426. function _outputGetResultTypeFromCode($code) {
  427.  
  428. switch ($code) {
  429. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_OK">PHPSECINFO_TEST_RESULT_OK</a>:
  430. return 'Passed';
  431. break;
  432.  
  433. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_NOTICE">PHPSECINFO_TEST_RESULT_NOTICE</a>:
  434. return 'Notices';
  435. break;
  436.  
  437. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_WARN">PHPSECINFO_TEST_RESULT_WARN</a>:
  438. return 'Warnings';
  439. break;
  440.  
  441. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_NOTRUN">PHPSECINFO_TEST_RESULT_NOTRUN</a>:
  442. return 'Not Run';
  443. break;
  444.  
  445. case <a href="../PhpSecInfo/_PhpSecInfo_Test_Test_php.html#definePHPSECINFO_TEST_RESULT_ERROR">PHPSECINFO_TEST_RESULT_ERROR</a>:
  446. return 'Errors';
  447. break;
  448.  
  449. default:
  450. return 'Invalid Result Code';
  451. break;
  452. }
  453.  
  454. }
  455.  
  456.  
  457. /**
  458. * Loads and runs all the tests
  459. *
  460. * As loading, then running, is a pretty common process, this saves a extra method call
  461. *
  462. * @since 0.1.1
  463. *
  464. */
  465. function loadAndRun() {
  466. $this->loadTests();
  467. $this->runTests();
  468. }
  469.  
  470.  
  471. /**
  472. * returns an associative array of test data. Four keys are set:
  473. * - test_results (array)
  474. * - tests_not_run (array)
  475. * - result_counts (array)
  476. * - num_tests_run (integer)
  477. *
  478. * note that this must be called after tests are loaded and run
  479. *
  480. * @since 0.1.1
  481. * @return array
  482. */
  483. function getResultsAsArray() {
  484. $results = array();
  485.  
  486. $results['test_results'] = $this->test_results;
  487. $results['tests_not_run'] = $this->tests_not_run;
  488. $results['result_counts'] = $this->result_counts;
  489. $results['num_tests_run'] = $this->num_tests_run;
  490.  
  491. return $results;
  492. }
  493.  
  494.  
  495.  
  496. /**
  497. * returns the standard output as a string instead of echoing it to the browser
  498. *
  499. * note that this must be called after tests are loaded and run
  500. *
  501. * @since 0.1.1
  502. *
  503. * @return string
  504. */
  505. function getOutput() {
  506. ob_start();
  507. $this->renderOutput();
  508. $output = ob_get_clean();
  509. return $output;
  510. }
  511.  
  512.  
  513.  
  514.  
  515. }
  516.  
  517.  
  518.  
  519.  
  520. /**
  521. * A globally-available function that runs the tests and creates the result page
  522. *
  523. */
  524. function phpsecinfo() {
  525. ini_set('display_errors', 'On');
  526. error_reporting(E_ALL);
  527.  
  528. $psi =& new PhpSecInfo();
  529. $psi->loadAndRun();
  530. $psi->renderOutput();

Documentation generated on Tue, 24 Oct 2006 10:53:38 -0400 by phpDocumentor 1.3.0RC3