1<?php 2 3/** 4 * DokuWiki Plugin sentry (Action Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr <dokuwiki@cosmocode.de> 8 */ 9class action_plugin_sentry_ajax extends DokuWiki_Action_Plugin 10{ 11 12 /** 13 * Registers a callback function for a given event 14 * 15 * @param Doku_Event_Handler $controller DokuWiki's event controller object 16 * 17 * @return void 18 */ 19 public function register(Doku_Event_Handler $controller) 20 { 21 if (!$this->getConf('dsn')) { 22 return; 23 } 24 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax'); 25 } 26 27 /** 28 * 29 * This uses event AJAX_CALL_UNKNOWN 30 * 31 * @param Doku_Event $event 32 * @param $param 33 */ 34 public function handleAjax(Doku_Event $event, $param) 35 { 36 if ($event->data !== 'plugin_sentry') { 37 return; 38 } 39 $event->preventDefault(); 40 $event->stopPropagation(); 41 42 global $INPUT; 43 44 $sentryData = [ 45 'logger' => 'javascript', 46 'exception' => [ 47 'values' => [ 48 [ 49 'type' => $INPUT->str('name'), 50 'value' => $INPUT->str('message'), 51 'stacktrace' => [ 52 'frames' => $this->parseJavaScriptStacktrace($INPUT->str('stack')) 53 ], 54 ], 55 ], 56 ], 57 ]; 58 $sentryData = array_merge($sentryData, $INPUT->arr('additionalData')); 59 $sentryData['extra']['original_stack'] = $INPUT->str('stack'); 60 61 $sentryEvent = new \dokuwiki\plugin\sentry\Event($sentryData); 62 63 /** @var helper_plugin_sentry $sentryHelper */ 64 $sentryHelper = plugin_load('helper', 'sentry'); 65 $sentryHelper->logEvent($sentryEvent); 66 } 67 68 /** 69 * Tries to parse a JavaScript stack trace into sentry frames 70 * 71 * @see https://github.com/errwischt/stacktrace-parser/blob/master/lib/stacktrace-parser.js 72 * @param string $trace 73 * @return array 74 */ 75 protected function parseJavaScriptStacktrace($trace) 76 { 77 $chrome = '/^\s*at (?:(?:(?:Anonymous function)?|((?:\[object object\])?(?:new )?\S+'. 78 '(?: \[as \S+\])?)) )?\(?((?:[-\w]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i'; 79 80 $gecko = '/^(?:\s*([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i'; 81 82 $frames = []; 83 $lines = explode("\n", $trace); 84 foreach ($lines as $line) { 85 if (preg_match($gecko, $line, $parts)) { 86 $frames[] = [ 87 'filename' => $parts[3] ? $parts[3] : '<unknown file>', 88 'function' => $parts[1] ? $parts[1] : '<unknown function>', 89 'lineno' => (int)$parts[4], 90 'colno' => (int)$parts[5] 91 ]; 92 } elseif (preg_match($chrome, $line, $parts)) { 93 $frames[] = [ 94 'filename' => $parts[2] ? $parts[2] : '<unknown file>', 95 'function' => $parts[1] ? $parts[1] : '<unknown function>', 96 'lineno' => (int)$parts[3], 97 'colno' => (int)$parts[4] 98 ]; 99 } 100 } 101 return array_reverse($frames); 102 } 103} 104