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