1<?php
2/**
3 * DokuWiki Plugin highlight2wiki (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  dodotori <dodotori@localhost>
7   CRC64 function adapted from https://gist.github.com/hightemp/4da5ac39b8d57fcd7e7988b90a48017d
8   several function adapted from stackoverflow
9
10bookmarklet:
11javascript:Q=document.selection?document.selection.createRange().text:document.getSelection(); void(window.open(%27https://yourwebsite.com/dokuwiki/doku.php?do=highlight2wiki&te=%27+encodeURIComponent(Q)+%27&ur=%27+ encodeURIComponent(location.href)+%27%27,%27dokuwikiadd%27,%27scrollbars=yes,resizable=yes,toolbars=yes,status=yes%27));
12
13
14 */
15
16class action_plugin_highlight2wiki extends \dokuwiki\Extension\ActionPlugin
17{
18    /** @inheritDoc */
19    public function register(Doku_Event_Handler $controller)
20    {
21      //  $controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'handle_toolbar_define',array());
22        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this,'_hookjs');
23        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE',  $this, 'allowMyAction');
24        $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE',  $this, 'performMyAction');
25
26    }
27
28    /**
29     * FIXME Event handler for
30     *
31     * @param Doku_Event $event  event object by reference
32     * @param mixed      $param  optional parameter passed when event was registered
33     * @return void
34     */
35    public function _hookjs(Doku_Event $event, $param) {
36        $event->data['script'][] = array(
37                            'type'    => 'text/javascript',
38                            'charset' => 'utf-8',
39                            '_data'   => '',
40							'src'     => 'https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js'); // Mark.Js library included
41                            //'src'     => DOKU_BASE.'lib/plugins/highlight2wiki/script.js');
42    }
43    public function allowMyAction(Doku_Event $event, $param) {
44        if($event->data != 'highlight2wiki') return;
45        $event->preventDefault();
46
47    }
48
49    public function performMyAction(Doku_Event $event, $param) {
50    if($event->data != 'highlight2wiki') return;
51    $event->preventDefault();
52	global $ACT, $JSINFO, $ID, $INPUT, $auth, $TPL, $INFO;
53
54 		//LOGIN NEEDED ?8 		//NOT LOGGED IN ? -> FORCE LOGIN
55 		if( $INFO['userinfo']== null ) {
56 		  header("Location: ?do=login");
57 		  die('<a href="?do=login">LOGIN</a>');
58 		}
59
60
61
62        $timestamp = date("Y:m:d:H:i:s");
63        //$title=$_GET['ti'];     // things to log : title
64        //$titlestring = preg_replace('/%u([0-9A-F]+)/', '&#x$1;', $title); // convert the unicode dont need title parameter anymore
65        //$titlestring = html_entity_decode($titlestring, ENT_COMPAT, 'UTF-8');
66        $url=$_GET['ur'];
67        //$urlkey = preg_replace( "#^[^:/.]*[:/]+#i", "",$url );
68        //$urlkey = urlencode($urlkey); //crc64($url);
69        //if (strlen($urlkey)>250){
70            $urlkey = crc64($url);
71        //}
72        $yournamespace = $this->getConf('highlight_namespace');
73        $allowed_tags = $this->getConf('allowed_tags');
74        $allow_css = $this->getConf('allow_css');
75        $allow_javascript = $this->getConf('allow_javascript');
76        $title_as_pagename = $this->getConf('title_as_pagename');
77	    $targeturl= DOKU_BASE."doku.php?id=$yournamespace:$urlkey&do=edit";
78        $highlightactionurl = DOKU_BASE."doku.php?do=highlight2wiki";
79	    $url_host = parse_url($url,PHP_URL_SCHEME)."://".parse_url($url, PHP_URL_HOST) ;
80
81
82	 if(empty($url)){
83	echo "<p>put your link here:</p>";
84        echo '<input id="linktogo">';
85         echo '<input type="button" onclick="location.href=\'?do=highlight2wiki&ur=\'+encodeURIComponent(getElementById(\'linktogo\').value);" value="Highlight2wiki" />';
86	 }
87	    echo'<input type="button" value="DarkMode"  class="unibutton" onpointerdown="HLdarkmode()">';
88        echo '<script>
89		    console.log("'.$url.'");
90			console.log("'.$urlkey.'");
91			console.log("'.$yournamespace.'");
92
93            var url = "'.$url.'"
94            var urlkey = "'.$urlkey.'";
95            var timestamp = "'.$timestamp.'";
96            var targeturl = "'.$targeturl.'";
97            var highlightactionurl ="'.$highlightactionurl.'";
98			var url_host ="'.$url_host.'";
99
100            </script>';
101
102
103
104// From URL to get webpage contents.
105
106 function parseurl($newurl="") // to convert encode url
107{
108   // $newurl = rawurlencode($newurl);
109    $a = array("%3A","%2F","%40","+");
110    $b = array(":","/","@"," ");
111    $newurl = str_replace($a,$b,$newurl);
112    return $newurl;
113}
114
115$purl = parseurl($url);
116
117
118
119 if(!empty($url)){
120if (function_exists('curl_init')) //check if curl function existed
121{
122     $ch = curl_init();
123     $agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36';
124     curl_setopt($ch, CURLOPT_USERAGENT, $agent);// Return Page contents.
125     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
126     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
127     curl_setopt($ch, CURLOPT_URL, $url);
128	 curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 1);   // cancel if below 1 byte/second
129     curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 30);   // for a period of 30 seconds
130     $result1 = curl_exec($ch);
131	 //grab URL and pass it to the variable.
132	 // Initialize a CURL session.
133	 //$result =file_get_contents($url);
134
135		$context2 = stream_context_create(
136    array(
137        "http" => array(
138            "header" => "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
139        ),
140		  "ssl"=>array(
141        "verify_peer"=>false,
142        "verify_peer_name"=>false,)
143    )
144	);
145
146	 $result2 =file_get_contents($url, false, $context2);
147	 //echo '<p>'.strlen($result1).'</p>';
148	 //echo '<p>'.strlen($result2).'</p>';
149	 if(strlen($result2)>strlen($result1)){ //check length of each result
150     $result = $result2;
151	 }else{
152	 $result = $result1;
153	 }
154}
155else
156{
157	$context = stream_context_create(
158    array(
159        "http" => array(
160            "header" => "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
161        ),
162		  "ssl"=>array(
163        "verify_peer"=>false,
164        "verify_peer_name"=>false,)
165    )
166    );
167    $result =file_get_contents($url, false, $context);
168	echo '<p>file_get_contents</p>';
169
170}
171}
172
173
174//$result2= file_get_contents($url);
175//if(strcmp($result, $result2)<"0"){
176//$result = $result2;
177//}
178
179/*  DOM parser stripper from https://stackoverflow.com/questions/8021543/extract-all-the-text-and-img-tags-from-html-in-php  */
180if($result!=""){
181//preg_match('/lang=(["\'])?((?:.(?!\1|>))*.?)/',$result,$matchlang);
182$allowed_attributes = array('charset','lang','src','href');
183
184$dom = new DOMDocument();
185
186
187//$dom->loadHTML($result);
188@$dom->loadHTML(mb_convert_encoding($result, 'HTML-ENTITIES', 'UTF-8'));
189
190
191
192//mb_convert_encoding($data, 'HTML-ENTITIES', 'UTF-8')
193foreach($dom->getElementsByTagName('*') as $node)
194{
195    foreach($node->attributes as $attribute)
196    {
197		if(is_iterable($attribute->name)){
198	    foreach($attribute->name as $AName){
199		    if(in_array($AName, $allowed_attributes)){
200			continue;
201			}else{
202			$node->removeAttributeNode($attribute);
203			}
204
205		}
206		}
207        //if (in_array($attribute->name, $allowed_attributes)) {continue;}
208        //$node->removeAttributeNode($attribute);
209		//removeAttribute('href')
210    }
211}
212
213if($allow_javascript==0){  //javascript_conf
214/*$html = preg_replace('/<\s*script.+?<\s*\/\s*script.*?>/si', ' ', $html );  */
215foreach($dom->getElementsByTagName('script') as $node){$node->nodeValue="";}
216echo'<script>console.log("no js")</script>';
217}
218
219if($allow_css==0){ //css conf
220/*$html = preg_replace('/<\s*style.+?<\s*\/\s*script.*?>/si', ' ', $html );  */
221foreach($dom->getElementsByTagName('style') as $node){$node->nodeValue="";}
222echo'<script>console.log("no css")</script>';
223}
224
225
226//echo '<meta lang="'.$matchlang[2].'"><html>';
227echo '<meta Content-Type" content="text/html; charset="UTF-8">';
228$titles = $dom->saveHTML($dom->getElementsByTagName('title')->item(0));
229$html = $dom->saveHTML($dom->getElementsByTagname('body')->item(0));
230
231if($allow_javascript==0){
232$html = preg_replace('/<\s*script.+?<\s*\/\s*script.*?>/si', ' ', $html );
233}
234$html=preg_replace("/<body[^>]+\>/ix", "", $html);
235$html = str_replace("<body>", "", $html);
236$html = str_replace("</body>", "", $html);
237
238echo'<div id="wanttext">';
239echo $titles;
240echo $html;
241}
242
243echo "</div>";
244
245// add onload function
246echo' <script>	</script>';
247
248
249
250
251
252
253/* change the target page name to title+ crc64 code    */
254if($title_as_pagename ==1){
255$titles2=RemoveSpecialChar(Strip_tags($titles));
256if (strlen(utf8_encode($titles2))>140){     //check the title length if longer than 150
257$titles2 = substr(utf8_encode($titles2),0,140);
258$titles2 = utf8_decode($titles2);
259}
260$titles2 = $titles2."-".crc64($url);
261$targeturl= DOKU_BASE."doku.php?id=$yournamespace:$titles2&do=edit";
262}
263/*  dokuwiki editor iframe  */
264echo '<iframe src="'.$targeturl.'" id="edtop" width="100%" height="800 px" onload="loadH2WFunc()"></iframe>';
265
266        echo'<div id="ednavbar">
267        <!--Button to invoke the function to get the selected text-->
268        <!--<input type="button" value="Highlight" class="unibutton"   onpointerdown ="getSelectedText()">-->
269        <!--<input type="button" value="Load" class="unibutton" onpointerdown ="loadhighlight();">-->
270	    <input type="button" value="✎Mark"  class="unibutton" onpointerdown="markjs()">
271        <input type="button" value="⌛Load"  class="unibutton" onpointerdown="loadmarkjs()" >
272		<input type = "button" value="〒Tag" class="unibutton" onpointerdown="edittag();">
273        <input type="button" value="✍Learn" class="unibutton" onpointerdown="loadmarkjsfr();">
274        <input type="button" class="unibutton" value="��Up" onpointerdown="jQuery(\'html, body\').animate({scrollTop:0}, \'300\')").scrollIntoView");">
275		<input type="button" class="unibutton" value="��Dn" onpointerdown="document.getElementById(\'edtop\').scrollIntoView();">
276        <input type="button" class="unibutton" value="☯Dark"  onpointerdown="HLdarkmode()" >
277		</div>';
278
279
280echo '
281        <!--Form to show the selected text as output-->
282        <form align="right"
283          <input type="button" value="Go to Top " onclick="document.getElementById(\'wanttext\').scrollIntoView();" >
284          <p> </p>
285
286        </form>';
287
288
289
290
291      //  <form name="testform" hidden="hidden" >
292           // <textarea name="selectedtext"
293                      //rows="3"
294                      //cols="20"
295                     // hidden="hidden"></textarea>
296       // </form>
297
298
299
300} //end of performMyAction
301
302} // end of class
303
304
305
306function crc64Table() //CRC64 hasing for encoding
307{
308    $crc64tab = [];
309
310    // ECMA polynomial
311    $poly64rev = (0xC96C5795 << 32) | 0xD7870F42;
312
313    // ISO polynomial
314    // $poly64rev = (0xD8 << 56);
315
316    for ($i = 0; $i < 256; $i++)
317    {
318        for ($part = $i, $bit = 0; $bit < 8; $bit++) {
319            if ($part & 1) {
320                $part = (($part >> 1) & ~(0x8 << 60)) ^ $poly64rev;
321            } else {
322                $part = ($part >> 1) & ~(0x8 << 60);
323            }
324        }
325
326       $crc64tab[$i] = $part;
327    }
328
329    return $crc64tab;
330}
331
332
333
334//https://www.php.net/manual/en/function.str-replace.php#100871
335
336
337
338
339
340
341/**
342* @param string $string
343* @param string $format
344* @return mixed
345*
346* Formats:
347*  crc64('php'); // afe4e823e7cef190
348*  crc64('php', '0x%x'); // 0xafe4e823e7cef190
349*  crc64('php', '0x%X'); // 0xAFE4E823E7CEF190
350*  crc64('php', '%d'); // -5772233581471534704 signed int
351*  crc64('php', '%u'); // 12674510492238016912 unsigned int
352*/
353function crc64($string, $format = '%x')
354{
355    static $crc64tab;
356
357    if ($crc64tab === null) {
358        $crc64tab = crc64Table();
359    }
360
361    $crc = 0;
362
363    for ($i = 0; $i < strlen($string); $i++) {
364        $crc = $crc64tab[($crc ^ ord($string[$i])) & 0xff] ^ (($crc >> 8) & ~(0xff << 56));
365    }
366
367    return sprintf($format, $crc);
368}
369
370
371
372
373//check itf-8 //floern.com/;
374
375function is_utf8($str) {
376    $strlen = strlen($str);
377    for ($i = 0; $i < $strlen; $i++) {
378        $ord = ord($str[$i]);
379        if ($ord < 0x80) continue; // 0bbbbbbb
380        elseif (($ord & 0xE0) === 0xC0 && $ord > 0xC1) $n = 1; // 110bbbbb (exkl C0-C1)
381        elseif (($ord & 0xF0) === 0xE0) $n = 2; // 1110bbbb
382        elseif (($ord & 0xF8) === 0xF0 && $ord < 0xF5) $n = 3; // 11110bbb (exkl F5-FF)
383        else return false; // invalid UTF-8-Zeichen
384        for ($c=0; $c<$n; $c++) // $n following bytes? // 10bbbbbb
385            if (++$i === $strlen || (ord($str[$i]) & 0xC0) !== 0x80)
386                return false; // invalid UTF-8 char
387    }
388    return true; // didn't find any invalid characters
389}
390
391
392 function RemoveSpecialChar($str) {
393// Using str_replace() function
394// to replace the word
395$res = str_replace( array( '\'', '"',
396',' , ';', '<', '>','&',':','/' ), '', $str);
397return $res;
398 }
399