PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/phpmyadmin/libraries/error_report.lib.php

https://gitlab.com/luyxtran264/myproject
PHP | 364 lines | 236 code | 29 blank | 99 comment | 38 complexity | 818699fc09d8644468e2ef113d35ad7b MD5 | raw file
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Error reporting functions used to generate and submit error reports
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. * The generated file that contains the line numbers for the js files
  13. * If you change any of the js files you can run the scripts/line-counts.sh
  14. */
  15. if (is_readable('js/line_counts.php')) {
  16. include_once 'js/line_counts.php';
  17. }
  18. /**
  19. * the url where to submit reports to
  20. */
  21. define('SUBMISSION_URL', "https://reports.phpmyadmin.net/incidents/create");
  22. /**
  23. * returns the pretty printed error report data collected from the
  24. * current configuration or from the request parameters sent by the
  25. * error reporting js code.
  26. *
  27. * @return String the report
  28. */
  29. function PMA_getPrettyReportData()
  30. {
  31. $report = PMA_getReportData();
  32. return json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
  33. }
  34. /**
  35. * returns the error report data collected from the current configuration or
  36. * from the request parameters sent by the error reporting js code.
  37. *
  38. * @param string $exception_type whether exception is 'js' or 'php'
  39. *
  40. * @return array error report if success, Empty Array otherwise
  41. */
  42. function PMA_getReportData($exception_type = 'js')
  43. {
  44. $relParams = PMA_getRelationsParam();
  45. // common params for both, php & js exceptions
  46. $report = array(
  47. "pma_version" => PMA_VERSION,
  48. "browser_name" => PMA_USR_BROWSER_AGENT,
  49. "browser_version" => PMA_USR_BROWSER_VER,
  50. "user_os" => PMA_USR_OS,
  51. "server_software" => $_SERVER['SERVER_SOFTWARE'],
  52. "user_agent_string" => $_SERVER['HTTP_USER_AGENT'],
  53. "locale" => $_COOKIE['pma_lang'],
  54. "configuration_storage" =>
  55. is_null($relParams['db']) ? "disabled" :
  56. "enabled",
  57. "php_version" => phpversion()
  58. );
  59. if ($exception_type == 'js') {
  60. if (empty($_REQUEST['exception'])) {
  61. return array();
  62. }
  63. $exception = $_REQUEST['exception'];
  64. $exception["stack"] = PMA_translateStacktrace($exception["stack"]);
  65. List($uri, $script_name) = PMA_sanitizeUrl($exception["url"]);
  66. $exception["uri"] = $uri;
  67. unset($exception["url"]);
  68. $report ["exception_type"] = 'js';
  69. $report ["exception"] = $exception;
  70. $report ["script_name"] = $script_name;
  71. $report ["microhistory"] = $_REQUEST['microhistory'];
  72. if (! empty($_REQUEST['description'])) {
  73. $report['steps'] = $_REQUEST['description'];
  74. }
  75. } elseif ($exception_type == 'php') {
  76. $errors = array();
  77. // create php error report
  78. $i = 0;
  79. if (!isset($_SESSION['prev_errors'])
  80. || $_SESSION['prev_errors'] == ''
  81. ) {
  82. return array();
  83. }
  84. foreach ($_SESSION['prev_errors'] as $errorObj) {
  85. /* @var $errorObj PMA\libraries\Error */
  86. if ($errorObj->getLine()
  87. && $errorObj->getType()
  88. && $errorObj->getNumber() != E_USER_WARNING
  89. ) {
  90. $errors[$i++] = array(
  91. "lineNum" => $errorObj->getLine(),
  92. "file" => $errorObj->getFile(),
  93. "type" => $errorObj->getType(),
  94. "msg" => $errorObj->getOnlyMessage(),
  95. "stackTrace" => $errorObj->getBacktrace(5),
  96. "stackhash" => $errorObj->getHash()
  97. );
  98. }
  99. }
  100. // if there were no 'actual' errors to be submitted.
  101. if ($i==0) {
  102. return array(); // then return empty array
  103. }
  104. $report ["exception_type"] = 'php';
  105. $report["errors"] = $errors;
  106. } else {
  107. return array();
  108. }
  109. return $report;
  110. }
  111. /**
  112. * Sanitize a url to remove the identifiable host name and extract the
  113. * current script name from the url fragment
  114. *
  115. * It returns two things in an array. The first is the uri without the
  116. * hostname and identifying query params. The second is the name of the
  117. * php script in the url
  118. *
  119. * @param String $url the url to sanitize
  120. *
  121. * @return array the uri and script name
  122. */
  123. function PMA_sanitizeUrl($url)
  124. {
  125. $components = parse_url($url);
  126. if (isset($components["fragment"])
  127. && preg_match("<PMAURL-\d+:>", $components["fragment"], $matches)
  128. ) {
  129. $uri = str_replace($matches[0], "", $components["fragment"]);
  130. $url = "http://dummy_host/" . $uri;
  131. $components = parse_url($url);
  132. }
  133. // get script name
  134. preg_match("<([a-zA-Z\-_\d]*\.php)$>", $components["path"], $matches);
  135. if (count($matches) < 2) {
  136. $script_name = 'index.php';
  137. } else {
  138. $script_name = $matches[1];
  139. }
  140. // remove deployment specific details to make uri more generic
  141. if (isset($components["query"])) {
  142. parse_str($components["query"], $query_array);
  143. unset($query_array["db"]);
  144. unset($query_array["table"]);
  145. unset($query_array["token"]);
  146. unset($query_array["server"]);
  147. $query = http_build_query($query_array);
  148. } else {
  149. $query = '';
  150. }
  151. $uri = $script_name . "?" . $query;
  152. return array($uri, $script_name);
  153. }
  154. /**
  155. * Sends report data to the error reporting server
  156. *
  157. * @param array $report the report info to be sent
  158. *
  159. * @return String the reply of the server
  160. */
  161. function PMA_sendErrorReport($report)
  162. {
  163. $data_string = json_encode($report);
  164. if (ini_get('allow_url_fopen')) {
  165. $context = array("http" =>
  166. array(
  167. 'method' => 'POST',
  168. 'content' => $data_string,
  169. 'header' => "Content-Type: application/json\r\n",
  170. )
  171. );
  172. $context = PMA\libraries\Util::handleContext($context);
  173. $response = @file_get_contents(
  174. SUBMISSION_URL,
  175. false,
  176. stream_context_create($context)
  177. );
  178. return $response;
  179. }
  180. if (!function_exists('curl_init')) {
  181. return null;
  182. }
  183. $curl_handle = curl_init(SUBMISSION_URL);
  184. if ($curl_handle === false) {
  185. return null;
  186. }
  187. $curl_handle = PMA\libraries\Util::configureCurl($curl_handle);
  188. curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, "POST");
  189. curl_setopt(
  190. $curl_handle, CURLOPT_HTTPHEADER,
  191. array('Expect:', 'Content-Type: application/json')
  192. );
  193. curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data_string);
  194. curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
  195. $response = curl_exec($curl_handle);
  196. curl_close($curl_handle);
  197. return $response;
  198. }
  199. /**
  200. * Returns number of lines in given javascript file.
  201. *
  202. * @param string $filename javascript filename
  203. *
  204. * @return Number of lines
  205. *
  206. * @todo Should gracefully handle non existing files
  207. */
  208. function PMA_countLines($filename)
  209. {
  210. global $LINE_COUNT;
  211. if (defined('LINE_COUNTS')) {
  212. return $LINE_COUNT[$filename];
  213. }
  214. // ensure that the file is inside the phpMyAdmin folder
  215. $depath = 1;
  216. foreach (explode('/', $filename) as $part) {
  217. if ($part == '..') {
  218. $depath--;
  219. } elseif ($part != '.') {
  220. $depath++;
  221. }
  222. if ($depath < 0) {
  223. return 0;
  224. }
  225. }
  226. $linecount = 0;
  227. $handle = fopen('./js/' . $filename, 'r');
  228. while (!feof($handle)) {
  229. $line = fgets($handle);
  230. if ($line === false) {
  231. break;
  232. }
  233. $linecount++;
  234. }
  235. fclose($handle);
  236. return $linecount;
  237. }
  238. /**
  239. * returns the translated line number and the file name from the cumulative line
  240. * number and an array of files
  241. *
  242. * uses the $LINE_COUNT global array of file names and line numbers
  243. *
  244. * @param array $filenames list of files in order of concatenation
  245. * @param Integer $cumulative_number the cumulative line number in the
  246. * concatenated files
  247. *
  248. * @return array the filename and line number
  249. * Returns two variables in an array:
  250. * - A String $filename the filename where the requested cumulative number
  251. * exists
  252. * - Integer $linenumber the translated line number in the returned file
  253. */
  254. function PMA_getLineNumber($filenames, $cumulative_number)
  255. {
  256. $cumulative_sum = 0;
  257. foreach ($filenames as $filename) {
  258. $filecount = PMA_countLines($filename);
  259. if ($cumulative_number <= $cumulative_sum + $filecount + 2) {
  260. $linenumber = $cumulative_number - $cumulative_sum;
  261. break;
  262. }
  263. $cumulative_sum += $filecount + 2;
  264. }
  265. if (! isset($filename)) {
  266. $filename = '';
  267. }
  268. return array($filename, $linenumber);
  269. }
  270. /**
  271. * translates the cumulative line numbers in the stack trace as well as sanitize
  272. * urls and trim long lines in the context
  273. *
  274. * @param array $stack the stack trace
  275. *
  276. * @return array $stack the modified stack trace
  277. */
  278. function PMA_translateStacktrace($stack)
  279. {
  280. foreach ($stack as &$level) {
  281. foreach ($level["context"] as &$line) {
  282. if (mb_strlen($line) > 80) {
  283. $line = mb_substr($line, 0, 75) . "//...";
  284. }
  285. }
  286. if (preg_match("<js/get_scripts.js.php\?(.*)>", $level["url"], $matches)) {
  287. parse_str($matches[1], $vars);
  288. List($file_name, $line_number) = PMA_getLineNumber(
  289. $vars["scripts"], $level["line"]
  290. );
  291. $level["filename"] = $file_name;
  292. $level["line"] = $line_number;
  293. } else {
  294. unset($level["context"]);
  295. List($uri, $script_name) = PMA_sanitizeUrl($level["url"]);
  296. $level["uri"] = $uri;
  297. $level["scriptname"] = $script_name;
  298. }
  299. unset($level["url"]);
  300. }
  301. unset($level);
  302. return $stack;
  303. }
  304. /**
  305. * generates the error report form to collect user description and preview the
  306. * report before being sent
  307. *
  308. * @return String the form
  309. */
  310. function PMA_getErrorReportForm()
  311. {
  312. $datas = array(
  313. 'report_data' => PMA_getPrettyReportData(),
  314. 'hidden_inputs' => PMA_URL_getHiddenInputs(),
  315. 'hidden_fields' => null,
  316. );
  317. $reportData = PMA_getReportData();
  318. if (!empty($reportData)) {
  319. $datas['hidden_fields'] = PMA_getHiddenFields($reportData);
  320. }
  321. return PMA\libraries\Template::get('error/report_form')
  322. ->render($datas);
  323. }
  324. /**
  325. * generates the error report form to collect user description and preview the
  326. * report before being sent
  327. *
  328. * @return String the form
  329. */
  330. function PMA_hasLatestLineCounts()
  331. {
  332. $line_counts_time = filemtime("js/line_counts.php");
  333. $js_time = filemtime("js");
  334. return $line_counts_time >= $js_time;
  335. }