added japanese language
[openemr.git] / phpmyadmin / libraries / error_report.lib.php
blob80a216eff8bca06798f73a3533bdbf10a7d97846
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Error reporting functions used to generate and submit error reports
6 * @package PhpMyAdmin
7 */
9 /*
10 * Include for handleContext() and configureCurl in PMA_sendErrorReport()
12 require_once 'libraries/Util.class.php';
15 if (! defined('PHPMYADMIN')) {
16 exit;
19 /**
20 * The generated file that contains the linenumbers for the js files
21 * If you change any of the js files you can run the scripts/line-counts.sh
23 if (is_readable('js/line_counts.php')) {
24 include_once 'js/line_counts.php';
27 /**
28 * the url where to submit reports to
30 define('SUBMISSION_URL', "http://reports.phpmyadmin.net/incidents/create");
32 /**
33 * returns the error report data collected from the current configuration or
34 * from the request parameters sent by the error reporting js code.
36 * @param boolean $pretty_print whether to prettify the report
38 * @return Array/String the report
40 function PMA_getReportData($pretty_print = true)
42 if (empty($_REQUEST['exception'])) {
43 return '';
45 $exception = $_REQUEST['exception'];
46 $exception['stack'] = PMA_translateStacktrace($exception['stack']);
47 list($uri, $script_name) = PMA_sanitizeUrl($exception['url']);
48 $exception['uri'] = $uri;
49 unset($exception['url']);
50 $report = array(
51 'exception' => $exception,
52 'script_name' => $script_name,
53 'pma_version' => PMA_VERSION,
54 'browser_name' => PMA_USR_BROWSER_AGENT,
55 'browser_version' => PMA_USR_BROWSER_VER,
56 'user_os' => PMA_USR_OS,
57 'server_software' => $_SERVER['SERVER_SOFTWARE'],
58 'user_agent_string' => $_SERVER['HTTP_USER_AGENT'],
59 'locale' => $_COOKIE['pma_lang'],
60 'configuration_storage' =>
61 empty($GLOBALS['cfg']['Servers'][1]['pmadb'])
62 ? 'disabled'
63 : 'enabled',
64 'php_version' => phpversion(),
65 'microhistory' => $_REQUEST['microhistory'],
68 if (! empty($_REQUEST['description'])) {
69 $report['steps'] = $_REQUEST['description'];
72 if (!$pretty_print) {
73 return $report;
76 /* JSON_PRETTY_PRINT available since PHP 5.4 */
77 if (defined('JSON_PRETTY_PRINT')) {
78 return json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
81 return PMA_prettyPrint($report);
84 /**
85 * Sanitize a url to remove the identifiable host name and extract the
86 * current scriptname from the url fragment
88 * It returns two things in an array. The first is the uri without the
89 * hostname and identifying query params. The second is the name of the
90 * php script in the url
92 * @param String $url the url to sanitize
94 * @return Array the uri and script name
96 function PMA_sanitizeUrl($url)
98 $components = parse_url($url);
99 if (isset($components['fragment'])
100 && preg_match('<PMAURL-\d+:>', $components['fragment'], $matches)
102 $uri = str_replace($matches[0], '', $components['fragment']);
103 $url = 'http://dummy_host/' . $uri;
104 $components = parse_url($url);
107 // get script name
108 preg_match('<([a-zA-Z\-_\d]*\.php)$>', $components['path'], $matches);
109 $script_name = $matches[1];
111 // remove deployment specific details to make uri more generic
112 parse_str($components['query'], $query_array);
113 unset($query_array['db']);
114 unset($query_array['table']);
115 unset($query_array['token']);
116 unset($query_array['server']);
117 $query = http_build_query($query_array);
119 $uri = $script_name . '?' . $query;
120 return array($uri, $script_name);
124 * Sends report data to the error reporting server
126 * @param Array $report the report info to be sent
128 * @return String the reply of the server
130 function PMA_sendErrorReport($report)
132 $data_string = json_encode($report);
133 if (ini_get('allow_url_fopen')) {
134 $context = array(
135 'http' => array(
136 'method' => 'POST',
137 'content' => $data_string,
138 'header' => "Content-Type: multipart/form-data\r\n",
141 $context = PMA_Util::handleContext($context);
142 $response = file_get_contents(
143 SUBMISSION_URL,
144 false,
145 stream_context_create($context)
147 return $response;
150 if (!function_exists('curl_init')) {
151 return null;
154 $curl_handle = curl_init(SUBMISSION_URL);
155 $curl_handle = PMA_Util::configureCurl($curl_handle);
156 curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'POST');
157 curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array('Expect:'));
158 curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data_string);
159 curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
160 $response = curl_exec($curl_handle);
161 curl_close($curl_handle);
163 return $response;
167 * Returns number of lines in given javascript file.
169 * @param string $filename javascript filename
171 * @return Number of lines
173 function PMA_countLines($filename)
175 global $LINE_COUNT;
176 if (defined('LINE_COUNTS')) {
177 return $LINE_COUNT[$filename];
180 $linecount = 0;
181 $handle = fopen('./js/' . $filename, 'r');
182 while (!feof($handle)) {
183 $line = fgets($handle);
184 if ($line === false) {
185 break;
187 $linecount++;
189 fclose($handle);
190 return $linecount;
194 * returns the translated linenumber and the file name from the cumulative line
195 * number and an array of files
197 * uses the $LINE_COUNT global array of file names and line numbers
199 * @param Array $filenames list of files in order of concatenation
200 * @param Integer $cumulative_number the cumulative line number in the
201 * concatenated files
203 * @return Array the filename and linenumber
204 * Returns two variables in an array:
205 * - A String $filename the filename where the requested cumulative number
206 * exists
207 * - Integer $linenumber the translated line number in the returned file
209 function PMA_getLineNumber($filenames, $cumulative_number)
211 $cumulative_sum = 0;
212 foreach ($filenames as $filename) {
213 $filecount = PMA_countLines($filename);
214 if ($cumulative_number <= $cumulative_sum + $filecount + 2) {
215 $linenumber = $cumulative_number - $cumulative_sum;
216 break;
218 $cumulative_sum += $filecount + 2;
220 return array($filename, $linenumber);
224 * translates the cumulative line numbers in the stactrace as well as sanitize
225 * urls and trim long lines in the context
227 * @param Array $stack the stacktrace
229 * @return Array $stack the modified stacktrace
231 function PMA_translateStacktrace($stack)
233 foreach ($stack as &$level) {
234 foreach ($level["context"] as &$line) {
235 if (strlen($line) > 80) {
236 $line = substr($line, 0, 75) . "//...";
239 if (preg_match("<js/get_scripts.js.php\?(.*)>", $level["url"], $matches)) {
240 parse_str($matches[1], $vars);
241 List($file_name, $line_number) = PMA_getLineNumber(
242 $vars["scripts"], $level["line"]
244 $level["filename"] = $file_name;
245 $level["line"] = $line_number;
246 } else {
247 unset($level["context"]);
248 List($uri, $script_name) = PMA_sanitizeUrl($level["url"]);
249 $level["uri"] = $uri;
250 $level["scriptname"] = $script_name;
252 unset($level["url"]);
254 unset($level);
255 return $stack;
259 * generates the error report form to collect user description and preview the
260 * report before being sent
262 * @return String the form
264 function PMA_getErrorReportForm()
266 $html = "";
267 $html .= '<form action="error_report.php" method="post" name="report_frm"'
268 . ' id="report_frm" class="ajax">'
269 . '<fieldset style="padding-top:0px">';
271 $html .= '<p>' . __(
272 'phpMyAdmin has encountered an error. We have collected data about'
273 . ' this error as well as information about relevant configuration'
274 . ' settings to send to the phpMyAdmin team to help us in'
275 . ' debugging the problem.'
276 ) . '</p>';
278 $html .= '<div class="label"><label><p>'
279 . __('You may examine the data in the error report:')
280 . '</p></label></div>'
281 . '<pre class="report-data">'
282 . PMA_getReportData()
283 . '</pre>';
285 $html .= '<div class="label"><label><p>'
286 . __('Please explain the steps that lead to the error:')
287 . '</p></label></div>'
288 . '<textarea class="report-description" name="description"'
289 . 'id="report_description"></textarea>';
291 $html .= '<input type="checkbox" name="always_send"'
292 . ' id="always_send_checkbox"/>'
293 . '<label for="always_send_checkbox">'
294 . __('Automatically send report next time')
295 . '</label>';
297 $html .= '</fieldset>';
299 $html .= PMA_URL_getHiddenInputs();
301 $reportData = PMA_getReportData(false);
302 if (! empty($reportData)) {
303 $html .= PMA_getHiddenFields($reportData);
306 $html .= '</form>';
308 return $html;
312 * generates the error report form to collect user description and preview the
313 * report before being sent
315 * @return String the form
317 function PMA_hasLatestLineCounts()
319 $line_counts_time = filemtime("js/line_counts.php");
320 $js_time = filemtime("js");
321 return $line_counts_time >= $js_time;
325 * pretty print a variable for the user
327 * @param mixed $object the variable to pretty print
328 * @param String $namespace the namespace to use for printing values
330 * @return String the human readable form of the variable
332 function PMA_prettyPrint($object, $namespace="")
334 if (! is_array($object)) {
335 if (empty($namespace)) {
336 return "$object\n";
337 } else {
338 return "$namespace: \"$object\"\n";
341 $output = "";
342 foreach ($object as $key => $value) {
343 if ($namespace == "") {
344 $new_namespace = "$key";
345 } else {
346 $new_namespace = $namespace . "[$key]";
348 $output .= PMA_prettyPrint($value, $new_namespace);
350 return $output;