1<?php 2/** 3 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4 * @author Esther Brunner <wikidesign@gmail.com> 5 */ 6 7// must be run within Dokuwiki 8if (!defined('DOKU_INC')) die(); 9 10if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 11require_once(DOKU_PLUGIN.'action.php'); 12 13if (!defined('NL')) define('NL',"\n"); 14 15class action_plugin_discussion extends DokuWiki_Action_Plugin{ 16 17 /** 18 * Return some info 19 */ 20 function getInfo(){ 21 return array( 22 'author' => 'Esther Brunner', 23 'email' => 'wikidesign@gmail.com', 24 'date' => '2006-11-24', 25 'name' => 'Discussion Plugin', 26 'desc' => 'Enables discussion features', 27 'url' => 'http://www.wikidesign.ch/en/plugin/discussion/start', 28 ); 29 } 30 31 /** 32 * Register the eventhandlers 33 */ 34 function register(&$contr){ 35 $contr->register_hook( 36 'ACTION_ACT_PREPROCESS', 37 'BEFORE', 38 $this, 39 'handle_act_preprocess', 40 array() 41 ); 42 $contr->register_hook( 43 'TPL_ACT_RENDER', 44 'AFTER', 45 $this, 46 'comments', 47 array() 48 ); 49 } 50 51 /** 52 * Main function; dispatches the comment actions 53 */ 54 function comments(&$event, $param){ 55 if ($event->data != 'show') return; // nothing to do for us 56 57 $cid = $_REQUEST['cid']; 58 59 switch ($_REQUEST['comment']){ 60 61 case 'add': 62 $comment = array( 63 'user' => $_REQUEST['user'], 64 'name' => $_REQUEST['name'], 65 'mail' => $_REQUEST['mail'], 66 'url' => $_REQUEST['url'], 67 'address' => $_REQUEST['address'], 68 'date' => $_REQUEST['date'], 69 'raw' => cleanText($_REQUEST['text']) 70 ); 71 $repl = $_REQUEST['reply']; 72 $this->_add($comment, $repl); 73 break; 74 75 case 'edit': 76 $this->_show(NULL, $cid); 77 break; 78 79 case 'save': 80 $raw = cleanText($_REQUEST['text']); 81 $this->_save($cid, $raw); 82 break; 83 84 case 'delete': 85 $this->_save($cid, ''); 86 87 case 'toogle': 88 $this->_save($cid, '', true); 89 break; 90 91 default: // 'show' => $this->_show(), 'reply' => $this->_show($cid) 92 $this->_show($cid); 93 } 94 } 95 96 /** 97 * Shows all comments of the current page 98 */ 99 function _show($reply = NULL, $edit = NULL){ 100 global $ID; 101 102 // get discussion meta file name 103 $file = metaFN($ID, '.comments'); 104 105 if (!file_exists($file)) return true; // no comments at all 106 107 $data = unserialize(io_readFile($file, false)); 108 109 if ($data['status'] == 0) return true; // comments are off 110 111 // section title 112 $title = $this->getLang('discussion'); 113 $secid = cleanID($title); 114 echo '<div class="comment_wrapper">'; 115 echo '<h2><a name="'.$secid.'" id="'.$secid.'">'.$title.'</a></h2>'; 116 echo '<div class="level2">'; 117 118 // now display the comments 119 if (isset($data['comments'])){ 120 foreach ($data['comments'] as $key => $value){ 121 if ($key == $edit) $this->_form($value['raw'], 'save', $edit); // edit form 122 else $this->_print($key, $data, '', $reply); 123 } 124 } 125 126 // comment form 127 if (($data['status'] == 1) && !$reply && !$edit) $this->_form(''); 128 129 echo '</div>'; // level2 130 echo '</div>'; // comment_wrapper 131 132 return true; 133 } 134 135 /** 136 * Adds a new comment and then displays all comments 137 */ 138 function _add($comment, $parent){ 139 global $ID; 140 global $TEXT; 141 142 $otxt = $TEXT; // set $TEXT to comment text for wordblock check 143 $TEXT = $comment['raw']; 144 145 // spamcheck against the DokuWiki blacklist 146 if (checkwordblock()){ 147 msg($this->getLang('wordblock'), -1); 148 $this->_show(); 149 return false; 150 } 151 152 $TEXT = $otxt; // restore global $TEXT 153 154 // get discussion meta file name 155 $file = metaFN($ID, '.comments'); 156 157 $data = array(); 158 $data = unserialize(io_readFile($file, false)); 159 160 if ($data['status'] != 1) return false; // comments off or closed 161 if ((!$this->getConf('allowguests')) 162 && ($comment['user'] != $_SERVER['REMOTE_USER'])) 163 return false; // guest comments not allowed 164 165 if ($comment['date']) $date = strtotime($comment['date']); 166 else $date = time(); 167 if ($date == -1) $date = time(); 168 $cid = md5($comment['user'].$date); // create a unique id 169 170 if (!is_array($data['comments'][$parent])) $parent = NULL; // invalid parent comment 171 172 // render the comment 173 $xhtml = $this->_render($comment['raw']); 174 175 // fill in the new comment 176 $data['comments'][$cid] = array( 177 'user' => htmlspecialchars($comment['user']), 178 'name' => htmlspecialchars($comment['name']), 179 'mail' => htmlspecialchars($comment['mail']), 180 'date' => $date, 181 'show' => true, 182 'raw' => trim($comment['raw']), 183 'xhtml' => $xhtml, 184 'parent' => $parent, 185 'replies' => array() 186 ); 187 if ($comment['url']) 188 $data['comments'][$cid]['url'] = htmlspecialchars($comment['url']); 189 if ($comment['address']) 190 $data['comments'][$cid]['address'] = htmlspecialchars($comment['address']); 191 192 // update parent comment 193 if ($parent) $data['comments'][$parent]['replies'][] = $cid; 194 195 // update the number of comments 196 $data['number']++; 197 198 // save the comment metadata file 199 io_saveFile($file, serialize($data)); 200 $this->_addLogEntry($date, $ID, 'cc', '', $cid); 201 202 // notify subscribers of the page 203 $this->_notify($data['comments'][$cid]); 204 205 $this->_show(); 206 return true; 207 } 208 209 /** 210 * Saves the comment with the given ID and then displays all comments 211 */ 212 function _save($cid, $raw, $toogle = false){ 213 global $ID; 214 global $TEXT; 215 global $INFO; 216 217 $otxt = $TEXT; // set $TEXT to comment text for wordblock check 218 $TEXT = $raw; 219 220 // spamcheck against the DokuWiki blacklist 221 if (checkwordblock()){ 222 msg($this->getLang('wordblock'), -1); 223 $this->_show(); 224 return false; 225 } 226 227 $TEXT = $otxt; // restore global $TEXT 228 229 // get discussion meta file name 230 $file = metaFN($ID, '.comments'); 231 232 $data = array(); 233 $data = unserialize(io_readFile($file, false)); 234 235 // someone else was trying to edit our comment -> abort 236 if (($data['comments'][$cid]['user'] != $_SERVER['REMOTE_USER']) 237 && ($INFO['perm'] != AUTH_ADMIN)) return false; 238 239 $date = time(); 240 241 if ($toogle){ // toogle visibility 242 $now = $data['comments'][$cid]['show']; 243 $data['comments'][$cid]['show'] = !$now; 244 $data['number'] = $this->_count($data); 245 246 $type = ($data['comments'][$cid]['show'] ? 'sc' : 'hc'); 247 248 } elseif (!$raw){ // remove the comment 249 unset($data['comments'][$cid]); 250 $data['number'] = $this->_count($data); 251 252 $type = 'dc'; 253 254 } else { // save changed comment 255 $xhtml = $this->_render($raw); 256 257 // now change the comment's content 258 $data['comments'][$cid]['edited'] = $date; 259 $data['comments'][$cid]['raw'] = trim($raw); 260 $data['comments'][$cid]['xhtml'] = $xhtml; 261 262 $type = 'ec'; 263 } 264 265 // save the comment metadata file 266 io_saveFile($file, serialize($data)); 267 $this->_addLogEntry($date, $ID, $type, '', $cid); 268 269 $this->_show(); 270 return true; 271 } 272 273 /** 274 * Prints an individual comment 275 */ 276 function _print($cid, &$data, $parent = '', $reply = '', $visible = true){ 277 global $conf; 278 global $lang; 279 global $ID; 280 global $INFO; 281 282 $comment = $data['comments'][$cid]; 283 284 if (!is_array($comment)) return false; // corrupt datatype 285 286 if ($comment['parent'] != $parent) return true; // reply to an other comment 287 288 if (!$comment['show']){ // comment hidden 289 if ($INFO['perm'] == AUTH_ADMIN) echo '<div class="comment_hidden">'.NL; 290 else return true; 291 } 292 293 // comment head with date and user data 294 echo '<div class="comment_head">'.NL; 295 echo '<a name="comment__'.$cid.'" id="comment__'.$cid.'">'.NL; 296 297 // show gravatar image 298 if ($this->getConf('usegravatar')){ 299 $default = DOKU_URL.'lib/plugins/discussion/images/default.gif'; 300 $size = $this->getConf('gravatar_size'); 301 if ($comment['mail']) $src = ml('http://www.gravatar.com/avatar.php?'. 302 'gravatar_id='.md5($comment['mail']). 303 '&default='.urlencode($default). 304 '&size='.$size. 305 '&rating='.$this->getConf('gravatar_rating')); 306 else $src = $default; 307 $title = ($comment['name'] ? $comment['name'] : obfuscate($comment['mail'])); 308 echo '<img src="'.$src.'" class="medialeft" title="'.$title.'"'. 309 ' alt="'.$title.'" width="'.$size.'" height="'.$size.'" />'.NL; 310 $style = ' style="margin-left: '.($size + 14).'px;"'; 311 } else { 312 $style = ' style="margin-left: 20px;"'; 313 } 314 315 echo '</a>'.NL; 316 if ($this->getConf('linkemail') && $comment['mail']){ 317 echo $this->email($comment['email'], $comment['name']); 318 } elseif ($comment['url']){ 319 echo $this->external_link($comment['url'], $comment['name'], 'urlextern'); 320 } else { 321 echo $comment['name']; 322 } 323 if ($comment['address']) echo ', '.htmlentities($comment['address']); 324 echo ', '.date($conf['dformat'], $comment['date']); 325 if ($comment['edited']) echo ' ('.date($conf['dformat'], $comment['edited']).')'; 326 echo ':'.NL; 327 echo '</div>'.NL; // class="comment_head" 328 329 // main comment content 330 echo '<div class="comment_body"'.($this->getConf('usegravatar') ? $style : '').'>'.NL; 331 echo $comment['xhtml'].NL; 332 echo '</div>'.NL; // class="comment_body" 333 334 335 if ($visible){ 336 // show hide/show toogle button? 337 echo '<div class="comment_buttons">'.NL; 338 if ($INFO['perm'] == AUTH_ADMIN){ 339 if (!$comment['show']) $label = $this->getLang('btn_show'); 340 else $label = $this->getLang('btn_hide'); 341 342 $this->_button($cid, $label, 'toogle'); 343 } 344 345 // show reply button? 346 if (($data['status'] == 1) && !$reply && $comment['show'] 347 && ($this->getConf('allowguests') || $_SERVER['REMOTE_USER'])) 348 $this->_button($cid, $this->getLang('btn_reply'), 'reply', true); 349 350 // show edit and delete button? 351 if ((($comment['user'] == $_SERVER['REMOTE_USER']) && ($comment['user'] != '')) 352 || ($INFO['perm'] == AUTH_ADMIN)) 353 $this->_button($cid, $lang['btn_secedit'], 'edit', true); 354 if ($INFO['perm'] == AUTH_ADMIN) 355 $this->_button($cid, $lang['btn_delete'], 'delete'); 356 echo '</div>'.NL; // class="comment_buttons" 357 echo '<div class="comment_line" '.($this->getConf('usegravatar') ? $style : '').'> </div>'.NL; 358 } 359 360 // replies to this comment entry? 361 if (count($comment['replies'])){ 362 echo '<div class="comment_replies"'.$style.'>'.NL; 363 $visible = ($comment['show'] && $visible); 364 foreach ($comment['replies'] as $rid){ 365 $this->_print($rid, $data, $cid, $reply, $visible); 366 } 367 echo '</div>'.NL; // class="comment_replies" 368 } 369 370 if (!$comment['show']) echo '</div>'.NL; // class="comment_hidden" 371 372 // reply form 373 if ($reply == $cid){ 374 echo '<div class="comment_replies">'.NL; 375 $this->_form('', 'add', $cid); 376 echo '</div>'.NL; // class="comment_replies" 377 } 378 } 379 380 /** 381 * Outputs the comment form 382 */ 383 function _form($raw = '', $act = 'add', $cid = NULL){ 384 global $lang; 385 global $conf; 386 global $ID; 387 global $INFO; 388 389 // not for unregistered users when guest comments aren't allowed 390 if (!$_SERVER['REMOTE_USER'] && !$this->getConf('allowguests')) return false; 391 392 // fill $raw with $_REQUEST['text'] if it's empty 393 if (!$raw) $raw = hsc($_REQUEST['text']); 394 395 ?> 396 <div class="comment_form"> 397 <form id="discussion__comment_form" method="post" action="<?php echo script() ?>" accept-charset="<?php echo $lang['encoding'] ?>" onsubmit="return validate(this);"> 398 <div class="no"> 399 <input type="hidden" name="id" value="<?php echo $ID ?>" /> 400 <input type="hidden" name="do" value="show" /> 401 <input type="hidden" name="comment" value="<?php echo $act ?>" /> 402 <?php 403 404 // for adding a comment 405 if ($act == 'add'){ 406 ?> 407 <input type="hidden" name="reply" value="<?php echo $cid ?>" /> 408 <?php 409 // for registered user 410 if ($conf['useacl'] && $_SERVER['REMOTE_USER']){ 411 ?> 412 <input type="hidden" name="user" value="<?php echo $_SERVER['REMOTE_USER'] ?>" /> 413 <input type="hidden" name="name" value="<?php echo $INFO['userinfo']['name'] ?>" /> 414 <input type="hidden" name="mail" value="<?php echo $INFO['userinfo']['mail'] ?>" /> 415 <?php 416 // for guest: show name and e-mail entry fields 417 } else { 418 ?> 419 <input type="hidden" name="user" value="<?php echo clientIP() ?>" /> 420 <div class="comment_name"> 421 <label class="block" for="discussion__comment_name"> 422 <span><?php echo $lang['fullname'] ?>:</span> 423 <input type="text" class="edit" name="name" id="discussion__comment_name" size="50" tabindex="1" value="<?php echo hsc($_REQUEST['name'])?>" /> 424 </label> 425 </div> 426 <div class="comment_mail"> 427 <label class="block" for="discussion__comment_mail"> 428 <span><?php echo $lang['email'] ?>:</span> 429 <input type="text" class="edit" name="mail" id="discussion__comment_mail" size="50" tabindex="2" value="<?php echo hsc($_REQUEST['email'])?>" /> 430 </label> 431 </div> 432 <?php 433 } 434 435 // allow entering an URL 436 if ($this->getConf('urlfield')){ 437 ?> 438 <div class="comment_url"> 439 <label class="block" for="discussion__comment_url"> 440 <span><?php echo $this->getLang('url') ?>:</span> 441 <input type="text" class="edit" name="url" id="discussion__comment_url" size="50" tabindex="3" value="<?php echo hsc($_REQUEST['url'])?>" /> 442 </label> 443 </div> 444 <?php 445 } 446 447 // allow entering an address 448 if ($this->getConf('addressfield')){ 449 ?> 450 <div class="comment_address"> 451 <label class="block" for="discussion__comment_address"> 452 <span><?php echo $this->getLang('address') ?>:</span> 453 <input type="text" class="edit" name="address" id="discussion__comment_address" size="50" tabindex="4" value="<?php echo hsc($_REQUEST['address'])?>" /> 454 </label> 455 </div> 456 <?php 457 } 458 459 // allow setting the comment date 460 if ($this->getConf('datefield') && ($INFO['perm'] == AUTH_ADMIN)){ 461 ?> 462 <div class="comment_date"> 463 <label class="block" for="discussion__comment_date"> 464 <span><?php echo $this->getLang('date') ?>:</span> 465 <input type="text" class="edit" name="date" id="discussion__comment_date" size="50" /> 466 </label> 467 </div> 468 <?php 469 } 470 471 // for saving a comment 472 } else { 473 ?> 474 <input type="hidden" name="cid" value="<?php echo $cid ?>" /> 475 <?php 476 } 477 ?> 478 <div class="comment_text"> 479 <textarea class="edit" name="text" cols="80" rows="10" id="discussion__comment_text" tabindex="5"><?php echo $raw ?></textarea> 480 </div> 481 <?php //bad and dirty event insert hook 482 $evdata = array('writable' => true); 483 trigger_event('HTML_EDITFORM_INJECTION', $evdata); 484 ?> 485 <input class="button" type="submit" name="submit" value="<?php echo $lang['btn_save'] ?>" tabindex="6" /> 486 </div> 487 </form> 488 </div> 489 <?php 490 if ($this->getConf('usecocomment')) echo $this->_coComment(); 491 } 492 493 /** 494 * Adds a javascript to interact with coComments 495 */ 496 function _coComment(){ 497 global $ID; 498 global $conf; 499 global $INFO; 500 501 $user = $_SERVER['REMOTE_USER']; 502 503 ?> 504 <script type="text/javascript"><!--//--><![CDATA[//><!-- 505 var blogTool = "DokuWiki"; 506 var blogURL = "<?php echo DOKU_URL ?>"; 507 var blogTitle = "<?php echo $conf['title'] ?>"; 508 var postURL = "<?php echo wl($ID, '', true) ?>"; 509 var postTitle = "<?php echo tpl_pagetitle($ID, true) ?>"; 510 <?php 511 if ($user){ 512 ?> 513 var commentAuthor = "<?php echo $INFO['userinfo']['name'] ?>"; 514 <?php 515 } else { 516 ?> 517 var commentAuthorFieldName = "name"; 518 <?php 519 } 520 ?> 521 var commentAuthorLoggedIn = <?php echo ($user ? 'true' : 'false') ?>; 522 var commentFormID = "discussion__comment_form"; 523 var commentTextFieldName = "text"; 524 var commentButtonName = "submit"; 525 var cocomment_force = false; 526 //--><!]]></script> 527 <script type="text/javascript" src="http://www.cocomment.com/js/cocomment.js"> 528 </script> 529 <?php 530 } 531 532 /** 533 * General button function 534 */ 535 function _button($cid, $label, $act, $jump = false){ 536 global $ID; 537 $anchor = ($jump ? '#discussion__comment_form' : '' ); 538 539 ?> 540 <form class="button" method="post" action="<?php echo script().$anchor ?>"> 541 <div class="no"> 542 <input type="hidden" name="id" value="<?php echo $ID ?>" /> 543 <input type="hidden" name="do" value="show" /> 544 <input type="hidden" name="comment" value="<?php echo $act ?>" /> 545 <input type="hidden" name="cid" value="<?php echo $cid ?>" /> 546 <input type="submit" value="<?php echo $label ?>" class="button" title="<?php echo $label ?>" /> 547 </div> 548 </form> 549 <?php 550 return true; 551 } 552 553 /** 554 * Adds an entry to the comments changelog 555 * 556 * @author Esther Brunner <wikidesign@gmail.com> 557 * @author Ben Coburn <btcoburn@silicodon.net> 558 */ 559 function _addLogEntry($date, $id, $type = 'cc', $summary = '', $extra = ''){ 560 global $conf; 561 562 $changelog = $conf['metadir'].'/_comments.changes'; 563 564 if(!$date) $date = time(); //use current time if none supplied 565 $remote = $_SERVER['REMOTE_ADDR']; 566 $user = $_SERVER['REMOTE_USER']; 567 568 $strip = array("\t", "\n"); 569 $logline = array( 570 'date' => $date, 571 'ip' => $remote, 572 'type' => str_replace($strip, '', $type), 573 'id' => $id, 574 'user' => $user, 575 'sum' => str_replace($strip, '', $summary), 576 'extra' => str_replace($strip, '', $extra) 577 ); 578 579 // add changelog line 580 $logline = implode("\t", $logline)."\n"; 581 io_saveFile($changelog, $logline, true); //global changelog cache 582 $this->_trimRecentCommentsLog($changelog); 583 } 584 585 /** 586 * Trims the recent comments cache to the last $conf['changes_days'] recent 587 * changes or $conf['recent'] items, which ever is larger. 588 * The trimming is only done once a day. 589 * 590 * @author Ben Coburn <btcoburn@silicodon.net> 591 */ 592 function _trimRecentCommentsLog($changelog){ 593 global $conf; 594 595 if (@file_exists($changelog) && 596 (filectime($changelog) + 86400) < time() && 597 !@file_exists($changelog.'_tmp')){ 598 599 io_lock($changelog); 600 $lines = file($changelog); 601 if (count($lines)<$conf['recent']) { 602 // nothing to trim 603 io_unlock($changelog); 604 return true; 605 } 606 607 io_saveFile($changelog.'_tmp', ''); // presave tmp as 2nd lock 608 $trim_time = time() - $conf['recent_days']*86400; 609 $out_lines = array(); 610 611 for ($i=0; $i<count($lines); $i++) { 612 $log = parseChangelogLine($lines[$i]); 613 if ($log === false) continue; // discard junk 614 if ($log['date'] < $trim_time) { 615 $old_lines[$log['date'].".$i"] = $lines[$i]; // keep old lines for now (append .$i to prevent key collisions) 616 } else { 617 $out_lines[$log['date'].".$i"] = $lines[$i]; // definitely keep these lines 618 } 619 } 620 621 // sort the final result, it shouldn't be necessary, 622 // however the extra robustness in making the changelog cache self-correcting is worth it 623 ksort($out_lines); 624 $extra = $conf['recent'] - count($out_lines); // do we need extra lines do bring us up to minimum 625 if ($extra > 0) { 626 ksort($old_lines); 627 $out_lines = array_merge(array_slice($old_lines,-$extra),$out_lines); 628 } 629 630 // save trimmed changelog 631 io_saveFile($changelog.'_tmp', implode('', $out_lines)); 632 @unlink($changelog); 633 if (!rename($changelog.'_tmp', $changelog)) { 634 // rename failed so try another way... 635 io_unlock($changelog); 636 io_saveFile($changelog, implode('', $out_lines)); 637 @unlink($changelog.'_tmp'); 638 } else { 639 io_unlock($changelog); 640 } 641 return true; 642 } 643 } 644 645 /** 646 * Sends a notify mail on new comment 647 * 648 * @param array $comment data array of the new comment 649 * 650 * @author Andreas Gohr <andi@splitbrain.org> 651 * @author Esther Brunner <wikidesign@gmail.com> 652 */ 653 function _notify($comment){ 654 global $conf; 655 global $ID; 656 657 if (!$conf['subscribers']) return; //subscribers enabled? 658 $bcc = subscriber_addresslist($ID); 659 if (empty($bcc)) return; 660 $to = ''; 661 $text = io_readFile($this->localFN('subscribermail')); 662 663 $text = str_replace('@PAGE@', $ID, $text); 664 $text = str_replace('@TITLE@', $conf['title'], $text); 665 $text = str_replace('@DATE@', date($conf['dformat'], $comment['date']), $text); 666 $text = str_replace('@NAME@', $comment['name'], $text); 667 $text = str_replace('@TEXT@', $comment['raw'], $text); 668 $text = str_replace('@UNSUBSCRIBE@', wl($ID, 'do=unsubscribe', true, '&'), $text); 669 $text = str_replace('@DOKUWIKIURL@', DOKU_URL, $text); 670 671 $subject = '['.$conf['title'].'] '.$this->getLang('mail_newcomment'); 672 673 mail_send($to, $subject, $text, $conf['mailfrom'], '', $bcc); 674 } 675 676 /** 677 * Counts the number of visible comments 678 */ 679 function _count($data){ 680 $number = 0; 681 foreach ($data['comments'] as $cid => $comment){ 682 if ($comment['parent']) continue; 683 if (!$comment['show']) continue; 684 $number++; 685 $rids = $comment['replies']; 686 if (count($rids)) $number = $number + $this->_countReplies($data, $rids); 687 } 688 return $number; 689 } 690 691 function _countReplies(&$data, $rids){ 692 $number = 0; 693 foreach ($rids as $rid){ 694 if (!$data['comments'][$rid]['show']) continue; 695 $number++; 696 $rids = $data['comments'][$rid]['replies']; 697 if (count($rids)) $number = $number + $this->_countReplies($data, $rids); 698 } 699 return $number; 700 } 701 702 /** 703 * Renders the comment text 704 */ 705 function _render($raw){ 706 if ($this->getConf('wikisyntaxok')){ 707 $xhtml = $this->render($raw); 708 } else { // wiki syntax not allowed -> just encode special chars 709 $xhtml = htmlspecialchars(trim($raw)); 710 } 711 return $xhtml; 712 } 713 714 /** 715 * Checks if 'newthread' was given as action or the comment form was submitted 716 */ 717 function handle_act_preprocess(&$event, $param){ 718 if ($event->data == 'newthread'){ 719 $this->_handle_newThread($event); 720 } 721 if ((in_array($_REQUEST['comment'], array('add', 'save'))) 722 && (@file_exists(DOKU_PLUGIN.'captcha/action.php'))){ 723 $this->_handle_captchaCheck(); 724 } 725 } 726 727 /** 728 * Creates a new thread page 729 */ 730 function _handle_newThread(&$event){ 731 global $ACT; 732 global $ID; 733 734 // we can handle it -> prevent others 735 $event->stopPropagation(); 736 $event->preventDefault(); 737 738 $ns = $_REQUEST['ns']; 739 $title = str_replace(':', '', $_REQUEST['title']); 740 $id = ($ns ? $ns.':' : '').cleanID($title); 741 742 // check if we are allowed to create this file 743 if (auth_quickaclcheck($id) >= AUTH_CREATE){ 744 $back = $ID; 745 $ID = $id; 746 $file = wikiFN($ID); 747 748 //check if locked by anyone - if not lock for my self 749 if (checklock($ID)){ 750 $ACT = 'locked'; 751 } else { 752 lock($ID); 753 } 754 755 // prepare the new thread file with default stuff 756 if (!@file_exists($file)){ 757 global $TEXT; 758 global $INFO; 759 global $conf; 760 761 $TEXT = pageTemplate(array($ns.':'.$title)); 762 if (!$TEXT) $TEXT = "<- [[:$back]]\n\n====== $title ======\n\n". 763 "{{gravatar>".$INFO['userinfo']['mail']." }} ". 764 "//".$INFO['userinfo']['name'].", ". 765 date($conf['dformat']).": //\n\n\n\n". 766 "~~DISCUSSION~~\n"; 767 $ACT = 'preview'; 768 } else { 769 $ACT = 'edit'; 770 } 771 } else { 772 $ACT = 'show'; 773 } 774 } 775 776 /** 777 * Checks if the CAPTCHA string submitted is valid 778 * 779 * @author Andreas Gohr <gohr@cosmocode.de> 780 * @adaption Esther Brunner <wikidesign@gmail.com> 781 */ 782 function _handle_captchaCheck(){ 783 if (@file_exists(DOKU_PLUGIN.'captcha/disabled')) return; // CAPTCHA is disabled 784 785 require_once(DOKU_PLUGIN.'captcha/action.php'); 786 $captcha = new action_plugin_captcha; 787 788 // compare provided string with decrypted captcha 789 $rand = PMA_blowfish_decrypt($_REQUEST['plugin__captcha_secret'], auth_cookiesalt()); 790 $code = $captcha->_generateCAPTCHA($captcha->_fixedIdent(), $rand); 791 792 if (!$_REQUEST['plugin__captcha_secret'] || 793 !$_REQUEST['plugin__captcha'] || 794 strtoupper($_REQUEST['plugin__captcha']) != $code){ 795 796 // CAPTCHA test failed! Continue to edit instead of saving 797 msg($captcha->getLang('testfailed'),-1); 798 if ($_REQUEST['comment'] == 'save') $_REQUEST['comment'] = 'edit'; 799 elseif ($_REQUEST['comment'] == 'add') $_REQUEST['comment'] = 'show'; 800 } 801 // if we arrive here it was a valid save 802 } 803 804} 805 806//Setup VIM: ex: et ts=4 enc=utf-8 : 807