1<?php 2/** 3 * @author Myron Turner <turnermm02@shaw.ca> 4 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 5*/ 6// must be run within Dokuwiki 7if(!defined('DOKU_INC')) die(); 8class action_plugin_xtern extends DokuWiki_Action_Plugin { 9 private $accumulator = null; 10 private $current; 11 function __construct() { 12 $this->accumulator = metaFN('xtern:accumulator','.ser'); 13 } 14 public function register(Doku_Event_Handler $controller) { 15 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_unknown'); 16 $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'curl_check'); 17 $controller->register_hook('IO_WIKIPAGE_READ', 'AFTER', $this, 'handle_wiki_read'); 18 $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, 'handle_wiki_content'); 19 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'handle_page_save'); 20 21 } 22 23 /** 24 * @param Doku_Event $event event object by reference 25 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 26 * handler was registered] 27 * @return void 28 */ 29 30 public function curl_check(Doku_Event $event, $param) { 31 global $USERINFO,$JSINFO,$ID; 32 $admin = false; 33 if(isset($USERINFO)) { 34 $groups = $USERINFO['grps']; 35 if(in_array('admin', $groups)) $admin = true; 36 } 37 if($admin && !function_exists("curl_init")) { 38 msg($this->getLang('nocurl'),2); 39 return; 40 } 41 $this->accumulator = metaFN('xtern:accumulator','.ser'); 42 if($this->getConf('noicons')) { 43 $JSINFO['xtern_disable'] = '1'; 44 } 45 if($this->getConf('alt_div')) { 46 $JSINFO['xtern_selector'] = "#" .$this->getConf('alt_div') . " a"; 47 } 48 else if($this->getConf('alt_class')) { 49 $JSINFO['xtern_selector'] = '.' . $this->getConf('alt_class') . " a"; 50 } 51 $skip = $this->getConf('skip_pages'); 52 if($skip) { 53 $skip = preg_replace("/\s+/","",$skip) ; 54 $skip = str_replace(',','|',$skip) ; 55 $regex = "#^($skip)$#"; 56 if(preg_match($regex,$ID)) { 57 $JSINFO['xtern_skip'] = 1; 58 } 59 } 60 } 61 62 public function handle_ajax_call_unknown(Doku_Event $event, $param) { 63 if ($event->data !== 'extern_url') { 64 return; 65 } 66 67 global $lang,$INPUT; 68 $event->stopPropagation(); 69 $event->preventDefault(); 70 $url = $INPUT->str('url'); 71 if(!function_exists("curl_init")) { 72 echo "NOCURL"; 73 return; 74 } 75 $url = urldecode($url); 76 $ch = curl_init($url); 77 if($this->getConf('ca_required')) { 78 curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/ca/cacert.pem"); 79 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); 80 } 81 curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 82 curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1); 83 curl_setopt($ch, CURLOPT_MAXREDIRS, 5); 84 curl_setopt($ch,CURLOPT_TIMEOUT,10); 85 curl_setopt($ch, CURLOPT_NOBODY, 1); //just fetch headers 86 $output = curl_exec($ch); 87 $curl_errno = curl_errno($ch); 88 if($curl_errno) { 89 if($curl_errno == "28") { 90 $status = "408"; 91 } 92 else if($curl_errno == "60") { 93 $status = "495"; 94 } 95 else $status = $curl_errno; 96 } 97 else $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); 98 curl_close($ch); 99 echo "$status"; 100 return 1; 101 } 102 103 function handle_wiki_read(Doku_Event $event, $param) { 104 global $INPUT, $ACT; 105 if($event->data[3]) { //by-pass revision 106 return; 107 } 108 $act = act_clean($ACT); 109 if($act != 'edit') return; 110 if(!file_exists($this->accumulator)) return; 111 $id = $INPUT->str('id'); 112 $id = str_replace(array('/','\\'), ':', $id); 113 $ar = unserialize(file_get_contents($this->accumulator)); 114 $srch = array('__\s*BROKEN-LINK:','LINK-BROKEN\s*__') ; 115 $event->result = preg_replace("#$srch#", "",$event->result); 116 $event->result = str_replace($srch,"",$event->result); 117 if(!empty($ar[$id])) { 118 foreach($ar[$id] as $url) { 119 $this->update_wiki_page($event->result, $url) ; 120 } 121 } 122 123 //__BROKEN-LINK: __ BROKEN-LINK:[ 124 $event->result = preg_replace('/__\s*BROKEN-LINK:__\s*BROKEN-LINK:/ms', '__ BROKEN-LINK:', $event->result); 125 $event->result = preg_replace('/\s*LINK-BROKEN\s*__\s*LINK-BROKEN\s*__/ms', 'LINK-BROKEN__', $event->result); 126 $event->result = preg_replace('/_*\s*BROKEN-LINK:_*\s*BROKEN-LINK:/ms', '__BROKEN-LINK: ', $event->result); 127 $event->result = preg_replace('/LINK-BROKEN__LINK-BROKEN__/ms', 'LINK-BROKEN__', $event->result); 128 $event->result = preg_replace('/BROKEN-LINK:\s+/ms', 'BROKEN-LINK: ', $event->result); 129 $event->result = preg_replace('/__BROKEN-LINK: \s*_*\s* BROKEN-LINK:/ms','__ BROKEN-LINK:',$event->result); 130 131 } 132 133 function update_wiki_page(&$result, $url) 134 { 135 msg(($url) , 2); 136 $this->current = $url; 137 // $result = preg_replace_callback("|(?<!LINK:)(\[\[)?(" . preg_quote($url) . "(\|)*([^\]]+)*(\]\])?)[\s]*|ms", function ($matches) 138 $result = preg_replace_callback("|(?<!__LINK:)(\[\[)?(" . preg_quote($url) . "(\|)*([^\]]+)*(\]\])?)[\s]*|ms", function ($matches) 139 { 140 $test = preg_split("/[\s]+/", $matches[2]); 141 foreach ($test as $piece) 142 { 143 if (strpos($piece, 'http') !== false) 144 { 145 if (strpos($piece, $this->current) !== false && strpos($matches[0], '-LINK:' . $piece) === false) 146 { 147 if ($matches[1] == '[[') 148 { 149 $link = preg_quote($this->current); 150 $matches[0] = preg_replace("#\[\[($link.*?)\]\]#ms", "__ BROKEN-LINK:[[$1]] LINK-BROKEN __", $matches[0]); 151 } 152 else 153 { 154 $matches[0] = str_replace($piece, "__ BROKEN-LINK:" . $piece . " LINK-BROKEN __", $matches[0]); 155 } 156 } 157 } 158 } 159 160 return $matches[0]; 161 } 162 , $result); 163 } 164 165 function handle_wiki_content(Doku_Event $event, $param) { 166 global $ACT; 167 168 if($ACT == 'preview') { 169 return; 170 } 171 else if($this->getConf('conceal')) { 172 $event->data = preg_replace('#\<em\s+class=(\"|\')u(\1)\>\s*BROKEN\-LINK\:(.*?)LINK\-BROKEN\s*</em>#',"$3",$event->data); 173 return; 174 } 175 } 176 function handle_page_save(Doku_Event $event, $param) { 177 global $INPUT; 178 $url = $INPUT->str('xtern_url'); 179 if(!isset($url) || empty($url)) return; 180 if($event->data['contentChanged']) return; 181 if(strpos($event->data['newContent'], 'BROKEN-LINK:') !== false) { 182 $event->data['contentChanged'] = true; 183 } 184 } 185 186 function write_debug($data) { 187 return; 188 $debug_handle=fopen(DOKU_INC.'xtern.txt', 'wb'); 189 if(!$debug_handle) return; 190 fwrite($debug_handle, $data); 191 fclose($debug_handle); 192 } 193 194 } 195