Пример #1
0
function macro_BBS($formatter, $value, $options = array())
{
    global $DBInfo;
    # set defaults
    $ncount = 20;
    # default
    $bname = $formatter->page->name;
    $nid = '';
    # check options
    $args = preg_split('/\\s*,\\s*/', $value);
    foreach ($args as $arg) {
        $arg = trim($arg);
        if ($arg == '') {
            continue;
        }
        if (($p = strpos($arg, '=')) !== false) {
            $k = substr($arg, 0, $p);
            $v = substr($arg, $p + 1);
            if ($k == 'no') {
                $nid = $v;
            } else {
                if ($k == 'mode') {
                    $options['mode'] = $v;
                }
            }
        } else {
            if ($arg == 'mode') {
            } else {
                if ($arg == (int) $arg . "") {
                    $ncount = $arg;
                } else {
                    $bname = $arg;
                }
            }
        }
    }
    $bpage = _rawurlencode($bname);
    $nid = $nid ? $nid : $_GET['no'];
    $nids = array();
    if ($nid) {
        $nids = preg_split('/\\s+/', $nid);
        rsort($nids);
    }
    $options['p'] = $_GET['p'] > 0 ? $_GET['p'] : 1;
    $options['c'] = $ncount != 20 ? $ncount : '';
    $options['p'] = intval($options['p']);
    # is it exists ?
    if (!$DBInfo->hasPage($bname)) {
        return _("This bbs does not exists yet. Please save this page first");
    }
    # load a config file
    $conf0 = array();
    if (file_exists('config/bbs.' . $bname . '.php')) {
        $confname = 'bbs.' . $bname . '.php';
        $conf0 = _load_php_vars('config/bbs.default.php');
    } else {
        $confname = 'bbs.default.php';
    }
    $conf = _load_php_vars('config/' . $confname);
    $conf = array_merge($conf0, $conf);
    $conf['data_dir'] = $DBInfo->data_dir;
    $conf['dba_type'] = $DBInfo->dba_type;
    if (!$DBInfo->use_bbs) {
        return '[[BBS]]';
    }
    #if ($DBInfo->use_bbs == 1);
    #if ($DBInfo->use_bbs == 2);
    $MyBBS = new BBS_text($bname, $conf);
    // XXX
    if ($options['new'] and $MyBBS) {
        return $MyBBS;
    }
    if (!$MyBBS) {
        return '[[BBS]]';
    }
    $msg = '';
    $btn = array();
    # read messages
    #
    $formatter->baserule[] = "/^((-=)+-?\$)/";
    $formatter->baserule[] = "/ comment #(\\d+)\\b/";
    $formatter->baserule[] = "/\\[reply (\\d+)\\]/";
    $formatter->baserepl[] = "<hr />\n";
    $formatter->baserepl[] = " comment [#c\\1 #\\1]";
    $formatter->baserepl[] = "<script type='text/javascript'><!--\n" . " addReplyLink(\\1); //--></script>";
    $msg = '';
    $narticle = sizeof($nids);
    $js = '';
    if ($nid and $narticle == 1 and $options['mode'] == 'simple') {
        $nid = $nids[0];
        if (!$nid or !$MyBBS->hasPage($nid)) {
            return '[[BBS(error)]]';
        }
        include_once 'lib/metadata.php';
        $body = $MyBBS->getPage($nid);
        list($metas, $body) = _get_metadata($body);
        $img = '';
        if ($MyBBS->use_attach) {
            $cache = new Cache_text('attachments');
            $attachs = $cache->fetch($MyBBS->bbsname . ':' . $nid);
            if (preg_match('/^attachment:([^\\?]+)(\\?.*)?$/', $attachs[0], $m)) {
                $img = $formatter->macro_repl('Attachment', $m[1] . '?thumbwidth=100');
            }
            $subject = $formatter->link_tag($bpage, "?no={$nid}", $metas['Subject']);
        }
        $out = "<div class='simpleView'><table>\n" . "<tr><td class='img'>" . $img . "</td><td class='subject'>" . $subject . '</td></tr>' . "<tr><td colspan='2'></td>\n</tr></table></div>";
        return $out;
    }
    foreach ($nids as $nid) {
        if (!$nid or !$MyBBS->hasPage($nid)) {
            continue;
        }
        $fields = array('Name', 'Subject', 'Date', 'Email', 'HomePage', 'IP', 'Keywords');
        include_once 'lib/metadata.php';
        #Name: wkpark
        #Subject: Oh well
        #Date: 2006-04-29 42:04:39
        #Email: wkpark@gmail.com
        #HomePage:
        #IP: 2xx.xxx.xxx.x
        $body = $MyBBS->getPage($nid);
        if ($body != null) {
            $options['nosisters'] = 1;
            $MyBBS->counter->incCounter($nid, $options);
            list($metas, $body) = _get_metadata($body);
            $boundary = strtoupper(md5("COMMENT"));
            # XXX
            $copy = $body;
            list($comment, $copy) = explode("----" . $boundary . "\n", $copy, 2);
            while (!empty($comment)) {
                list($comment, $copy) = explode("----" . $boundary . "\n", $copy, 2);
                if (preg_match('/^Comment-Id:\\s*(\\d+)/i', $comment, $m)) {
                    list($myhead, $my) = explode("\n\n", $comment, 2);
                    $hidden .= '<pre style="display:none;" id="comment_text_' . $m[1] . '">' . _html_escape($my) . '</pre>';
                }
            }
            ob_start();
            # add some basic rule/repl for bts
            $rule = "/-{4}(?:" . $boundary . ")?\nComment-Id:\\s*(\\d+)\n" . "From:\\s*([^\n]+)\nDate:\\s*([^\n]+)\n\n/im";
            $repl = "----\n'''Comment-Id:''' [#c\\1][#c\\1 #\\1] by \\2 on [[DateTime(\\3)]] [reply \\1]\n\n";
            $body = preg_replace($rule, $repl, $body);
            $formatter->quote_style = 'bbs-comment';
            $options['usemeta'] = 1;
            #
            $q_save = $formatter->self_query;
            $query = '?no=' . $nid . '&amp;p=' . $options['p'];
            $formatter->self_query = $query;
            $save = $formatter->preview;
            $formatter->preview = 1;
            $save_markup = $formatter->format;
            ob_start();
            if ($conf['default_markup']) {
                $formatter->pi['#format'] = $conf['default_markup'];
            }
            $formatter->send_page($body, $options);
            $body = ob_get_contents();
            ob_end_clean();
            $formatter->pi['#format'] = $save_markup;
            $formatter->self_query = $q_save;
            $msg .= "<div class='bbsArticle'>" . '<div class="head"><h2>' . _("No") . ' ' . $nid . ': ' . $metas['Subject'] . '</h2></div>' . '<div class="body">' . '<div class="extra"> @ ' . $metas['Date'] . ' (' . _mask_hostname($metas['IP'], 3) . ')</div>' . '<div class="user"><h3>' . $metas['Name'] . '</h3></div>' . '<div class="article">' . $body . "</div>\n</div>\n" . '<div class="foot"><div></div></div>' . "</div>\n";
            $snid = $nid;
            $btn['edit'] = $formatter->link_tag($bpage, "?action=bbs&amp;mode=edit&amp;no=" . $nid, '<span>' . _("Edit") . '</span>', 'class="button"');
            $btn['delete'] = $formatter->link_tag($bpage, "?action=bbs&amp;mode=delete&amp;no=" . $nid, '<span>' . _("Delete") . '</span>', 'class="button"');
            if ($narticle == 1 and $conf['use_comment']) {
                $opts['action'] = 'bbs';
                $opts['no'] = $nid;
                $opts['p'] = $options['p'];
                $opts['mode'] = 'comment';
                $opts['nopreview'] = 1;
                $p = new WikiPage($bname . ':' . $opts['no'], $options);
                $opts['datestamp'] = $p->mtime();
                $comment = $formatter->macro_repl('Comment', 'usemeta', $opts);
                unset($opts['no']);
                # XXX
            }
            $msg .= '<div class="bbsComment">' . $comment . '</div><div class="bbsArticleBtn">' . implode(" ", $btn) . '</div>';
            unset($btn['delete']);
            unset($btn['edit']);
            $title = str_replace('"', '\\"', $metas['Subject']);
            $js .= <<<JS
<script type="text/javascript">
/*<![CDATA[*/
document.title+=" [" + {$snid} + "] - " + "{$title}";
/*]]>*/
</script>
JS;
        }
    }
    if (!empty($msg) and !$_GET['p']) {
        return $msg;
    }
    if (1) {
        # XXX
        $nochk = _("Please check article numbers.");
        $js .= <<<JS
<script type='text/javascript'>
/*<![CDATA[*/
  function send_list(obj,mode) {
    var tmp="";
    var i, chk=false;

    form=obj.parentNode.parentNode;

    for(i=0;i< form.length;i++) {
       if(form[i].type!="checkbox") continue;
       if(form[i].checked) {
          tmp+=form[i].value+" ";
          chk=true;
       }
    }
    if(chk==true) {
       form.no.value = tmp.substr(0,tmp.length-1);
       if (mode!=undefined) {
         form.elements.action.value = 'bbs';
         form.elements.mode.value = mode;
       } else {
         form.removeChild(form.elements.mode);
         form.removeChild(form.elements.action);
       }
       form.submit();
       return false;
    }
    alert ("{$nochk}");
    return false;
  }
/*]]>*/
</script>

JS;
    }
    # get list
    $options['perpage'] = $ncount;
    $list = $MyBBS->getList($ncount, $options);
    # get total number of articles
    $tot = $MyBBS->getCount();
    $pages = intval($tot / $ncount);
    if ($tot % $ncount) {
        $pages++;
    }
    if ($options['mode'] == 'rss') {
        $rss = '<' . '?xml version="1.0" encoding="utf-8"?>' . "\n" . '<rss version="2.0">' . "\n";
        $rss .= "<channel>\n<title>" . $DBInfo->sitename . ": </title>\n";
        $rss .= "<link>" . qualifiedUrl($formatter->link_url($bpage)) . "</link>\n";
        $rss .= "<description></description>\n";
        $rss .= "<pubDate>" . gmdate('D, j M Y H:i:s', time()) . " +0000</pubDate>\n";
        foreach ($list as $l) {
            $item = "<item>\n";
            $item .= "<title><![CDATA[" . $l[7] . "]]></title>\n";
            $item .= "<link>" . qualifiedUrl($formatter->link_url($bpage, "?no={$l['0']}")) . "</link>\n";
            $item .= "<author><![CDATA[" . $l[3] . "]]></author>\n";
            $item .= "<description><![CDATA[" . $l[3] . "]]></description>\n";
            $item .= "<pubDate>" . gmdate('D, j M Y H:i:s', $l[2]) . " +0000</pubDate>\n</item>\n";
            $rss .= $item;
        }
        $rss .= "</channel>\n</rss>\n";
        return $rss;
    } else {
        if ($options['mode'] == 'simple') {
            $simple = "<div class='bbsSimple'><table class='bbsSimple'>\n";
            foreach ($list as $l) {
                $date = date("Y-m-d", $l[2]);
                $my = $l[7];
                $title = '';
                if (function_exists('mb_strimwidth') and strlen($l[7]) > 60) {
                    $title = 'title="' . $l[7] . '"';
                    $my = mb_strimwidth($l[7], 0, 40, '...', $DBInfo->charset);
                }
                $simple .= "<tr><td class='date'>[" . $date . "]</td><td>" . $formatter->link_tag($bpage, "?no={$l['0']}" . $extra, $my, $title) . '</td></tr>';
            }
            $simple .= "<tr><td colspan='2' class='more'>" . $formatter->link_tag($bpage, "", _("More") . '&#187;') . "</td>\n</tr>\n";
            $simple .= "</table>";
            return $simple;
        }
    }
    if ($pages > 1) {
        $pnut = _get_pagelist($formatter, $pages, '?' . $extra . ($extra ? '&amp;p=' : 'p='), $options['p'], $ncount);
    } else {
        $pnut = "<div class='clear'></div>";
    }
    $extra = $options['p'] ? '&amp;p=' . $options['p'] : '';
    #$head=array(_("no"),'C',_("Title"),_("Name"),_("Date"),_("Hit"));
    #$out.="<col width='3%' class='num' /><col width='1%' class='check' /><col width='63%' class='title' /><col width='14%' /><col width='13%' /><col width='7%' class='hit' />\n";
    #$out.='<thead><tr><th>'.implode("</th><th>",$head)."</th></tr><thead>\n";
    #$out.="<tbody>\n";
    $item = array();
    foreach ($list as $l) {
        $nid =& $l[0];
        $ip =& $l[1];
        $date = date("Y-m-d", $l[2]);
        $user = $l[3];
        $subject = $formatter->link_tag($bpage, "?no={$nid}" . $extra, $l[7]);
        $hit = $MyBBS->counter->pageCounter($nid);
        $chk = '<input type="checkbox" value="' . $nid . '">';
        #$item=array(in_array($nid,$nids) ? '<strong>&raquo;</strong>':$nid,$chk,$subject,$user,$date,$hit);
        $item[] = array('num' => in_array($nid, $nids) ? '<strong>&raquo;</strong>' : $nid, 'check' => $chk, 'subject' => $subject, 'name' => $user, 'date' => $date, 'hit' => $hit);
        ##$tmp='<tr><td>'.implode("</td><td>",$item)."</td></tr>\n";
        #$tmp="<tr><td class='no'>$item[0]</td><td class='check'>$item[1]</td>".
        #    "<td class='title'>$item[2]</td><td class='name'>$item[3]</td>".
        #    "<td class='date'>$item[4]</td><td class='hit'>$item[5]</td>".
        #    "</tr>\n";
        #$out.=$tmp;
    }
    $formatter->_vars['item'] =& $item;
    $out .= $formatter->include_theme('plugin/BBS/default', 'list', array());
    #$out.= $formatter->include_theme('plugin/BBS/default_tpl','list',array());
    #$out.= $formatter->processor_repl('tpl_','',array('path'=>'theme/plugin/BBS/blue_tpl/list.tpl'));
    #$out.="</tbody>\n";
    $btn['new'] = $formatter->link_tag($bpage, "?action=bbs&amp;mode=edit", '<span>' . _("New") . '</span>', 'class="button"');
    unset($btn['edit']);
    $bn['view'] = $formatter->link_tag($bpage, "", '<span>' . _("Read") . '</span>', 'onclick="return send_list(this)" onfocus="blur()" class="button"');
    $bn['delete'] = $formatter->link_tag($bpage, "", '<span>' . _("Delete") . '</span>', 'onclick="return send_list(this,\'delete\')" onfocus="blur()" class="button"');
    $del = "<div class='bbsAdminBtn'>" . implode(" ", $bn) . "</div>\n";
    $btns = "<div class='bbsBtn'>" . implode(" ", $btn) . "</div>\n";
    $lnk = $formatter->link_url($bpage, '?action=bbs');
    $form0 = "<form method='get' action='{$lnk}'>\n";
    $form1 = '<input type="hidden" name="no" />';
    if ($options['p']) {
        $form1 .= '<input type="hidden" name="p" value="' . $options['p'] . "\" />\n";
    }
    $form1 .= '<input type="hidden" name="mode" />' . '<input type="hidden" name="action" />';
    $form1 .= "</form>\n";
    $pnut = "<div class='pnut'>{$pnut}</div>";
    $info = '<div class="bbsRSS">' . sprintf(_("Total %s articles."), '<strong>' . $tot . '</strong>') . ' ' . $formatter->link_tag($bpage, '?action=bbs&amp;mode=rss', $formatter->icon['rss']) . '</div>';
    return $info . $pnut . $msg . $js . $form0 . $out . $del . $form1 . $pnut . $btns;
}
Пример #2
0
function _parse_rlog($formatter, $log, $options = array())
{
    global $DBInfo;
    $tz_offset = $formatter->tz_offset;
    if (!empty($DBInfo->wikimasters) and is_array($DBInfo->wikimasters) and in_array($options['id'], $DBInfo->wikimasters)) {
        $admin = 1;
    }
    if (!empty($options['info_actions'])) {
        $actions = $options['info_actions'];
    } else {
        if (isset($DBInfo->info_actions)) {
            $actions = $DBInfo->info_actions;
        } else {
            $actions = array('recall' => 'view', 'raw' => 'source', 'diff' => 'diff');
        }
    }
    if (!$formatter->page->exists() && !in_array('revert', $actions)) {
        $actions['revert'] = 'revert';
    }
    if (!empty($DBInfo->use_avatar)) {
        if (is_string($DBInfo->use_avatar)) {
            $type = $DBInfo->use_avatar;
        } else {
            $type = 'identicon';
        }
        $avatarlink = qualifiedUrl($formatter->link_url('', '?action=' . $type . '&amp;seed='));
    }
    $ipicon = '<img src="' . $DBInfo->imgs_dir . '/misc/ip.png" />';
    $members = $DBInfo->members;
    // do not check admin member users
    $user = $DBInfo->user;
    $ismember = $user->is_member;
    $diff_action = null;
    if (isset($actions['diff'])) {
        $diff_action = _($actions['diff']);
        unset($actions['diff']);
    }
    $state = 0;
    $flag = 0;
    $time_current = time();
    $simple = !empty($options['simple']) ? 1 : 0;
    $url = $formatter->link_url($formatter->page->urlname);
    $diff_btn = _("Compare");
    $out = "<div class='wikiInfo'>\n";
    if (!empty($options['title'])) {
        $out .= $options['title'];
    } else {
        $out .= "<h2>" . _("Revision History") . "</h2>\n";
    }
    $out .= "<form id='infoform' method='get' action='{$url}'>";
    $out .= "<div><table class='info'><thead><tr>\n";
    $out .= "<th>" . _("Ver.") . "</th><th>" . _("Date") . "</th>" . "<th>" . _("Changes") . "</th>" . "<th>" . _("Editor") . "</th>" . "<th><button type='submit'><span>{$diff_btn}</span></button></th>\n";
    if (!$simple) {
        if (!empty($actions)) {
            $out .= "<th>" . _("View") . "</th>";
        }
        if (isset($admin)) {
            $out .= "<th>" . _("admin.") . "</th>";
        }
    }
    $out .= "</tr>\n</thead>\n";
    $out .= "<tbody>\n";
    $users = array();
    $rr = 0;
    #foreach ($lines as $line) {
    $count = 0;
    $showcount = (!empty($options['count']) and $options['count'] > 5) ? $options['count'] : 10;
    $line = '';
    $ok = 0;
    $log .= "\n";
    // hack
    $ii = 0;
    for (; !empty($line) or !empty($log); list($line, $log) = explode("\n", $log, 2)) {
        if (!$state) {
            if (!preg_match("/^---/", $line)) {
                continue;
            } else {
                $state = 1;
                continue;
            }
        }
        if ($state == 1 and $ok == 1) {
            if (!empty($options['action'])) {
                $act = $options['action'];
            } else {
                $act = 'info';
            }
            $lnk = $formatter->link_to('?action=' . $act . '&amp;rev=' . $rev, _("Show next revisions"), ' class="button small"');
            $out .= '<tr><td colspan="2"></td><td colspan="' . (!empty($admin) ? 5 : 4) . '">' . $lnk . '</td></tr>';
            break;
        }
        switch ($state) {
            case 1:
                $rr++;
                preg_match("/^revision ([0-9a-f\\.]+)\\s*/", $line, $match);
                $rev = $match[1];
                if (isset($match[2]) and preg_match("/\\./", $match[2])) {
                    $state = 0;
                    break;
                }
                $state = 2;
                break;
            case 2:
                $change = '';
                $inf = preg_replace("/date:\\s([0-9\\/:\\s]+)(;\\s+author:.*;\\s+state:.*;)?/", "\\1", $line);
                if (strstr($inf, 'lines:') !== FALSE) {
                    list($inf, $change) = explode('lines:', $inf, 2);
                }
                if (!empty($options['ago'])) {
                    if (preg_match('/^[0-9]+$/', $inf)) {
                        $rrev = '#' . $rr;
                        $ed_time = $inf;
                        $inf = gmdate("Y-m-d H:i:s", $ed_time + $tz_offset);
                    } else {
                        $ed_time = strtotime($inf . ' GMT');
                    }
                    $time_diff = (int) ($time_current - $ed_time) / 60;
                    if ($time_diff > 1440 * 31) {
                        $inf = gmdate("Y-m-d H:i:s", strtotime($inf . ' GMT') + $tz_offset);
                    } else {
                        if (($time_diff = $time_diff / 60) > 24) {
                            $day = (int) ($time_diff / 24);
                            if ($day == 1) {
                                $inf = _("Yesterday");
                            } else {
                                $inf = sprintf(_("%s days ago"), (int) ($time_diff / 24));
                            }
                        } else {
                            if ($time_diff > 1) {
                                $inf = sprintf(_("%s hours ago"), (int) $time_diff);
                            } else {
                                $inf = sprintf(_("%s min ago"), $time_diff % 60);
                            }
                        }
                    }
                } else {
                    if (preg_match('/^[0-9]+$/', $inf)) {
                        $rrev = '#' . $rr;
                        $ed_time = $inf;
                        $inf = gmdate("Y-m-d H:i:s", $inf + $tz_offset);
                    } else {
                        if ($tz_offset != '') {
                            $inf = gmdate("Y-m-d H:i:s", strtotime($inf . ' GMT') + $tz_offset);
                        } else {
                            $inf = date("Y-m-d H:i:s", strtotime($inf));
                        }
                        // localtime
                    }
                }
                $inf = $formatter->link_to("?action=recall&rev={$rev}", $inf);
                $change = preg_replace("/\\+(\\d+)\\s\\-(\\d+)/", "<span class='diff-added'><span>+\\1</span></span><span class='diff-removed'><span>-\\2</span></span>", $change);
                $state = 3;
                break;
            case 3:
                $dummy = explode(';;', $line, 3);
                $ip = $dummy[0];
                $realip = $lastip = $ip;
                if (($p = strpos($ip, ',')) !== false) {
                    // IP addresses via proxies
                    $realip = substr($ip, 0, $p);
                    $tmp = explode(',', $ip);
                    $lastip = $ip = array_pop($tmp);
                }
                $user = trim($dummy[1]);
                if (($p = strpos($user, ' ')) !== false) {
                    // XXX
                    $user = substr($user, 0, $p);
                } else {
                    if (substr($user, 0, 9) == 'Anonymous') {
                        $user = '******';
                    }
                }
                if (!empty($DBInfo->use_avatar)) {
                    $crypted = crypt($ip, $ip);
                    $mylnk = preg_replace('/seed=/', 'seed=' . $crypted, $avatarlink);
                    $avatar = '<img src="' . $mylnk . '" style="width:16px;height:16px;vertical-align:middle" alt="avatar" />';
                } else {
                    $avatar = '';
                }
                if ($user and $user != 'Anonymous') {
                    if (array_key_exists($user, $users)) {
                        $ip = $users[$user];
                    } else {
                        if (!empty($DBInfo->use_nick)) {
                            $u = $DBInfo->udb->getUser($user);
                            if (!empty($u->info['nick'])) {
                                if ($DBInfo->interwiki['User']) {
                                    $ip = $formatter->link_repl('[wiki:User:'******' ' . $u->info['nick'] . ']');
                                } else {
                                    if (!empty($u->info['home'])) {
                                        $ip = $formatter->link_repl('[' . $u->info['home'] . ' ' . $u->info['nick'] . ']');
                                    } else {
                                        $ip = $formatter->link_repl('[wiki:' . $user . ' ' . $u->info['nick'] . ']');
                                    }
                                }
                            }
                            $ip = $avatar . $ip;
                            $users[$user] = $ip;
                        } else {
                            if (strpos($user, ' ') !== false) {
                                $ip = $avatar . $formatter->link_repl($user);
                                $users[$user] = $ip;
                            } else {
                                if (empty($DBInfo->no_wikihomepage)) {
                                    if (empty($DBInfo->use_hostname) or $DBInfo->hasPage($user)) {
                                        $ip = $avatar . $formatter->link_tag($user);
                                    } else {
                                        $ip = $avatar . $user;
                                    }
                                    $users[$user] = $ip;
                                }
                            }
                        }
                    }
                }
                if (empty($users[$user])) {
                    $rip = $ip;
                    $u = $user;
                    if ($u == 'Anonymous') {
                        $u = $ip;
                    }
                    if (isset($DBInfo->interwiki['Whois'])) {
                        $wip = "<a href='" . $DBInfo->interwiki['Whois'] . "{$ip}' target='_blank'>{$ipicon}</a>";
                    } else {
                        $wip = "<a href='?action=whois&amp;q=" . $ip . "' target='_blank'>{$ipicon}</a>";
                    }
                    if ($ismember) {
                        if (!empty($DBInfo->use_admin_user_url)) {
                            $u = '<a href="' . $DBInfo->use_admin_user_url . $u . '">' . $u . '</a>';
                        }
                        if (!in_array($user, $members)) {
                            $ip = $u . $wip;
                        } else {
                            $ip = $u;
                        }
                    } else {
                        if (empty($DBInfo->show_hosts)) {
                            $ip = $user;
                        } else {
                            if (!empty($DBInfo->mask_hostname)) {
                                if ($user == 'Anonymous') {
                                    $ip = _mask_hostname($ip);
                                } else {
                                    $ip = $user;
                                }
                            } else {
                                if (!empty($members) and in_array($u, $members)) {
                                    $ip = $user;
                                } else {
                                    if (!empty($avatar)) {
                                        if ($user == 'Anonymous') {
                                            $u = _($user);
                                        }
                                        $ip = $u;
                                    } else {
                                        $ip = $u . $wip;
                                    }
                                }
                            }
                        }
                    }
                    $ip = $avatar . $ip;
                    if ($user != 'Anonymous') {
                        $users[$user] = $ip;
                    } else {
                        $users[$rip] = $ip;
                    }
                }
                $comment = !empty($dummy[2]) ? _stripslashes($dummy[2]) : '';
                if ($realip != $lastip) {
                    $via = '<span class="via-proxy">' . $realip . '</span>';
                    $comment = isset($comment[0]) ? $via . ' ' . $comment : $via;
                }
                $state = 4;
                break;
            case 4:
                if (!$rev) {
                    break;
                }
                $rowspan = 1;
                if (!$simple and $comment) {
                    $rowspan = 2;
                }
                $rrev = !empty($rrev) ? $rrev : $formatter->link_to("?action=recall&rev={$rev}", $rev);
                $alt = $ii++ % 2 == 0 ? ' class="alt"' : '';
                $out .= "<tr{$alt}>\n";
                $out .= "<th class='rev' valign='top' rowspan={$rowspan}>{$rrev}</th><td nowrap='nowrap' class='date'>{$inf}</td><td class='change'>{$change}</td><td class='author'>{$ip}&nbsp;</td>";
                $rrev = '';
                $achecked = "";
                $bchecked = "";
                if ($flag == 1) {
                    $achecked = "checked ";
                } else {
                    if (!$flag) {
                        $bchecked = "checked ";
                    }
                }
                $onclick = "onclick='ToggleRev(this)'";
                $out .= "<th nowrap='nowrap' class='check'><input type='radio' name='rev' value='{$rev}' {$achecked} {$onclick} />\n";
                $out .= "<input type='radio' name='rev2' value='{$rev}' {$bchecked} {$onclick} /></th>";
                if (!$simple) {
                    $out .= "<td nowrap='nowrap' class='view'>";
                    foreach ($actions as $k => $v) {
                        $k = is_numeric($k) ? $v : $k;
                        $out .= $formatter->link_to("?action={$k}&amp;rev={$rev}", _($v), ' class="button-small"') . ' ';
                    }
                    if ($flag) {
                        if ($diff_action) {
                            $out .= " " . $formatter->link_to("?action=diff&amp;rev={$rev}", $diff_action, ' class="button-small"');
                        }
                        $out .= "</td>";
                        if (isset($admin)) {
                            $out .= "<td><input type='checkbox' name='range[{$flag}]' value='{$rev}' /></td>";
                        }
                    } else {
                        $out .= "</td>";
                        if (isset($admin)) {
                            $out .= "<td><input type='image' src='{$DBInfo->imgs_dir}/smile/checkmark.png' onClick=\"ToggleAll('infoform');return false;\"/></td>";
                        }
                    }
                }
                $out .= "</tr>\n";
                if (!$simple and $comment) {
                    $out .= "<tr class='log'><td colspan='" . (!empty($admin) ? 6 : 5) . "'><p>{$comment}&nbsp;</p></td></tr>\n";
                }
                $state = 1;
                $flag++;
                $count++;
                if ((empty($options['all']) or $options['all'] != 1) and $count >= $showcount) {
                    $ok = 1;
                }
                break;
        }
    }
    if (!$simple and !empty($admin)) {
        $out .= "<tr><td colspan='" . (!empty($admin) ? 7 : 6) . "' align='right'><input type='checkbox' name='show' checked='checked' />" . _("show only") . ' ';
        if ($DBInfo->security->is_protected("rcspurge", $options)) {
            $out .= "<input type='password' name='passwd'>";
        }
        $out .= "<input type='submit' name='rcspurge' value='" . _("purge") . "'></td></tr>";
    }
    $out .= "<input type='hidden' name='action' value='diff'/>\n</tbody></table></div></form>\n";
    $out .= "<script type='text/javascript' src='{$DBInfo->url_prefix}/local/checkbox.js'></script></div>\n";
    return $out;
}
Пример #3
0
function do_contributors($formatter, $options)
{
    global $DBInfo, $Config;
    if (!$formatter->page->exists()) {
        $formatter->send_header('', $options);
        $title = _("Page not found.");
        $formatter->send_title($title, '', $options);
        $formatter->send_footer('', $options);
        return;
    }
    // get contributors
    $params = array();
    $retval = array();
    $params['retval'] =& $retval;
    if (!empty($DBInfo->version_class)) {
        $cache = new Cache_Text('infostat');
        if (!$formatter->refresh and $cache->exists($formatter->page->name)) {
            $retval = $cache->fetch($formatter->page->name);
        }
        if (empty($retval)) {
            $version = $DBInfo->lazyLoad('version', $DBInfo);
            $out = $version->rlog($formatter->page->name, '', '', '-z');
            $retval = array();
            if (!isset($out[0])) {
                $msg = _("No older revisions available");
                $info = "<h2>{$msg}</h2>";
            } else {
                $params = array();
                $params['all'] = 1;
                $params['id'] = $options['id'];
                $params['retval'] =& $retval;
                $ret = _stat_rlog($formatter, $out, $params);
            }
            if (!empty($retval)) {
                $cache->update($formatter->page->name, $retval);
            }
        }
    }
    $formatter->send_header('', $options);
    $title = _("Contributors of this page");
    $formatter->send_title($title, '', $options);
    // do not check admin member users
    $user = $DBInfo->user;
    $ismember = $user->is_member;
    $total = count($retval['revs']);
    $total_lab = _("Total Revisions");
    $initial = $retval['rev'];
    $init_lab = _("Initial Revision");
    $contrib_lab = _("User");
    $edit_lab = _("Edit Count");
    echo <<<HEAD
<div class="wikiInfo">
<table class="wiki center">
<tr>
<th>{$total_lab}</th><th>{$total}</th>
</tr>
<tr>
<th>{$init_lab}</th><th>r{$initial}</th>
</tr>
<tr>
<th>{$contrib_lab}</th><th>{$edit_lab}</th>
</tr>
HEAD;
    $opt = intval($Config['mask_hostname']);
    // sort users
    $authors = array_keys($retval['users']);
    $edits = array();
    foreach ($authors as $n) {
        if ($retval['users'][$n]['edit'] > 0) {
            $edits[$n] = $retval['users'][$n]['edit'];
        }
    }
    // sort by edits
    arsort($edits);
    foreach ($edits as $u => $c) {
        if (!$ismember && preg_match('/^([0-9]+\\.){3}[0-9]+$/', $u)) {
            $u = _mask_hostname($u, $opt);
        } else {
            $u = $formatter->link_tag($formatter->page->urlname, '?action=userinfo&q=' . $u, $u);
        }
        echo "<tr><td>", $u, "</td><td>", $c, "</td></tr>\n";
    }
    echo "</table></div>";
    $formatter->send_footer('', $options);
    return;
}
Пример #4
0
function macro_RecentChanges($formatter, $value = '', $options = '')
{
    global $DBInfo, $Config;
    // get members to hide log
    $members = $DBInfo->members;
    $checknew = 1;
    $checkchange = 0;
    $template_bra = "";
    $template = '"$icon&nbsp;&nbsp;$title$updated $date . . . . $user $count$diff $extra<br />\\n"';
    $template_cat = "";
    $use_day = 1;
    $users = array();
    $target = '';
    if (!empty($options['target'])) {
        $target = "target='{$options['target']}'";
    }
    $bookmark_action = empty($options['bookmark_action']) ? '?action=bookmark' : '?action=' . $options['bookmark_action'];
    // $date_fmt='D d M Y';
    $date_fmt = $DBInfo->date_fmt_rc;
    $days = !empty($DBInfo->rc_days) ? $DBInfo->rc_days : RC_DEFAULT_DAYS;
    $perma_icon = $formatter->perma_icon;
    $changed_time_fmt = $DBInfo->changed_time_fmt;
    $args = explode(',', $value);
    // first arg assumed to be a date fmt arg
    if (preg_match("/^[\\s\\/\\-:aABdDFgGhHiIjmMOrSTY\\[\\]]+\$/", $args[0])) {
        $my_date_fmt = $args[0];
    }
    $strimwidth = isset($DBInfo->rc_strimwidth) ? $DBInfo->rc_strimwidth : 20;
    // use javascript
    $use_js = 0;
    // show last edit entry only
    $last_entry_only = 1;
    $last_entry_check = 60 * 60 * 24;
    // show last editor only
    $last_editor_only = 1;
    // show editrange like as MoinMoin
    $use_editrange = 0;
    // avatar
    $use_avatar = 0;
    $avatar_type = 'identicon';
    if (!empty($DBInfo->use_avatar)) {
        $use_avatar = 1;
        if (is_string($DBInfo->use_avatar)) {
            $avatar_type = $DBInfo->use_avatar;
        }
    }
    // RC cache delay
    // $rc_cache_delay <= $rc_delay
    $cache_delay = isset($DBInfo->rc_cache_delay) ? $DBInfo->rc_cache_delay : 0;
    $avatarlink = $formatter->link_url('', '?action=' . $avatar_type . '&amp;seed=');
    $ipicon = '<img src="' . $DBInfo->imgs_dir . '/misc/ip.png" />';
    $trash = 0;
    $rctype = '';
    $opts = array();
    $bra = '';
    $cat = '';
    $cat0 = '';
    $rctitle = "<h2>" . _("Recent Changes") . "</h2>";
    foreach ($args as $arg) {
        $arg = trim($arg);
        if (($p = strpos($arg, '=')) !== false) {
            $k = trim(substr($arg, 0, $p));
            $v = trim(substr($arg, $p + 1));
            if ($k == 'item' or $k == 'items') {
                $opts['items'] = min((int) $v, RC_MAX_ITEMS);
            } else {
                if ($k == 'days') {
                    $days = min(abs($v), RC_MAX_DAYS);
                } else {
                    if ($k == "datefmt") {
                        $my_date_fmt = $v;
                    } else {
                        if ($k == 'ago') {
                            if (is_numeric($v) and $v == abs($v)) {
                                $opts['ago'] = abs($v);
                            } else {
                                $opts['from'] = $v;
                            }
                        } else {
                            if ($k == "new") {
                                $checknew = $v;
                            } else {
                                if ($k == "delay") {
                                    $cache_delay = intval($v);
                                } else {
                                    if ($k == 'strimwidth' and is_numeric($v) and (abs($v) > 15 or $v == 0)) {
                                        $strimwidth = abs($v);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } else {
            if ($arg == "quick") {
                $opts['quick'] = 1;
            } else {
                if ($arg == "nonew") {
                    $checknew = 0;
                } else {
                    if ($arg == "change") {
                        $checkchange = 1;
                    } else {
                        if ($arg == "showhost") {
                            $showhost = 1;
                        } else {
                            if ($arg == "comment") {
                                $comment = 1;
                            } else {
                                if ($arg == "comments") {
                                    $comment = 1;
                                } else {
                                    if ($arg == "nobookmark") {
                                        $nobookmark = 1;
                                    } else {
                                        if ($arg == "noperma") {
                                            $perma_icon = '';
                                        } else {
                                            if ($arg == "button") {
                                                $button = 1;
                                            } else {
                                                if ($arg == "timesago") {
                                                    $timesago = 1;
                                                } else {
                                                    if ($arg == "notitle") {
                                                        $rctitle = '';
                                                    } else {
                                                        if ($arg == "hits") {
                                                            $use_hits = 1;
                                                        } else {
                                                            if ($arg == "daysago") {
                                                                $use_daysago = 1;
                                                            } else {
                                                                if ($arg == "trash") {
                                                                    $trash = 1;
                                                                } else {
                                                                    if ($arg == "editrange") {
                                                                        $use_editrange = 1;
                                                                    } else {
                                                                        if ($arg == "allauthors") {
                                                                            $last_editor_only = 0;
                                                                        } else {
                                                                            if ($arg == "allusers") {
                                                                                $last_editor_only = 0;
                                                                            } else {
                                                                                if ($arg == "allentries") {
                                                                                    $last_entry_only = 0;
                                                                                } else {
                                                                                    if ($arg == "avatar") {
                                                                                        $use_avatar = 1;
                                                                                    } else {
                                                                                        if ($arg == "noavatar") {
                                                                                            $use_avatar = 0;
                                                                                        } else {
                                                                                            if ($arg == "js") {
                                                                                                $use_js = 1;
                                                                                            } else {
                                                                                                if ($arg == "diffwidth") {
                                                                                                    $use_diffwidth = 1;
                                                                                                } else {
                                                                                                    if (in_array($arg, array('simple', 'moztab', 'board', 'table', 'list'))) {
                                                                                                        $rctype = $arg;
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    ksort($opts);
    if (!empty($nobookmark)) {
        $use_js = 0;
    }
    // set as dynamic macro or not.
    if ($formatter->_macrocache and empty($options['call']) and empty($use_js) || $rctype != 'list') {
        return $formatter->macro_cache_repl('RecentChanges', $value);
    }
    if (empty($options['call'])) {
        $formatter->_dynamic_macros['@RecentChanges'] = 1;
    }
    if (empty($DBInfo->interwiki)) {
        $formatter->macro_repl('InterWiki', '', array('init' => 1));
    }
    // reset some conflict params
    if (empty($DBInfo->use_counter)) {
        $use_hits = 0;
    }
    if (empty($DBInfo->show_hosts)) {
        $showhost = 0;
    }
    if (!empty($rctype)) {
        if ($rctype == "simple") {
            $checkchange = 0;
            $use_day = 0;
            if ($showhost) {
                $template = '"$icon&nbsp;&nbsp;$title @ $day $date by $user $count $extra<br />\\n"';
            } else {
                $template = '"$icon&nbsp;&nbsp;$title @ $day $date $count $extra<br />\\n"';
            }
        } else {
            if ($rctype == "list") {
                $rctitle = '';
                $changed_time_fmt = !empty($my_date_fmt) ? $my_date_fmt : '[H:i]';
                $checkchange = 0;
                $use_day = 0;
                $template = '"<li>$date $title</li>\\n"';
                $template_bra = "<ul>\n";
                $template_cat = "</ul>\n";
            } else {
                if ($rctype == "moztab") {
                    $use_day = 1;
                    $template = '"<li>$title $date</li>\\n"';
                } else {
                    if ($rctype == "table") {
                        $bra = "<table border='0' cellpadding='0' cellspacing='0' width='100%'>";
                        $template = '"<tr><td style=\'white-space:nowrap;width:2%\'>$icon</td><td style=\'width:40%\'>$title$updated</td><td class=\'date\' style=\'width:15%\'>$date</td><td>$user $count$diff $extra</td></tr>\\n"';
                        $cat = "</table>";
                        $cat0 = "";
                    } else {
                        if ($rctype == "board") {
                            $changed_time_fmt = !empty($my_date_fmt) ? $my_date_fmt : 'm-d [H:i]';
                            $use_day = 0;
                            $template_bra = "<table border='0' cellpadding='0' cellspacing='0' width='100%'>";
                            if (empty($nobookmark)) {
                                $cols = 3;
                            } else {
                                $cols = 2;
                            }
                            $template_bra .= "<thead><tr><th colspan='{$cols}' class='title'>" . _("Title") . "</th>";
                            if (!empty($showhost)) {
                                $template_bra .= "<th class='author'>" . _("Editor") . '</th>';
                            }
                            $template_bra .= "<th class='editinfo'>" . _("Changes") . '</th>';
                            if (!empty($use_hits)) {
                                $template_bra .= "<th class='hits'>" . _("Hits") . "</th>";
                            }
                            $template_bra .= "<th class='date'>" . _("Change Date") . '</th>';
                            $template_bra .= "</tr></thead>\n<tbody>\n";
                            $template = '"<tr$alt><td style=\'white-space:nowrap;width:2%\'>$icon</td><td class=\'title\' style=\'width:40%\'>$title$updated</td>';
                            if (empty($nobookmark)) {
                                $template .= '<td>$bmark</td>';
                            }
                            if (!empty($showhost)) {
                                $template .= '<td class=\'author\'>$user</td>';
                            }
                            $template .= '<td class=\'editinfo\'>$count';
                            if (!empty($checkchange) or !empty($checknew)) {
                                $template .= ' $diff';
                            }
                            $template .= '</td>';
                            if (!empty($use_hits)) {
                                $template .= '<td class=\'hits\'>$hits</td>';
                            }
                            $template .= '<td class=\'date\'>$date</td>';
                            $template_extra = $template . '</tr>\\n<tr class=\'log\'$style><td colspan=\'6\'><div>$extra</div></td></tr>\\n"';
                            $template .= '</tr>\\n"';
                            $template_cat = "</tbody></table>";
                            $cat0 = "";
                        }
                    }
                }
            }
        }
    }
    // override days
    $days = !empty($_GET['days']) ? min(abs($_GET['days']), RC_MAX_DAYS) : $days;
    // override ago
    empty($opts['ago']) ? $opts['ago'] = 0 : null;
    if (!empty($_GET['ago']) and is_numeric($_GET['ago'])) {
        $opts['ago'] = abs($_GET['ago']);
    } else {
        $opts['from'] = $_GET['ago'];
    }
    // override times
    // accept both 'item' or 'items'
    $tmp = isset($_GET['item']) ? $_GET['item'] : (isset($_GET['items']) ? $_GET['items'] : null);
    !empty($tmp) ? $opts['items'] = min(abs($tmp), RC_MAX_ITEMS) : null;
    unset($tmp);
    // daysago
    $daysago = '&amp;days=' . $days;
    $daysago = $opts['ago'] ? $daysago . '&amp;ago=' . $opts['ago'] : $daysago;
    $u = $DBInfo->user;
    # retrive user info
    // check member
    $ismember = $u->is_member;
    // use uniq avatar ?
    $uniq_avatar = 0;
    if (!empty($DBInfo->use_uniq_avatar)) {
        $uniq_avatar = $DBInfo->use_uniq_avatar;
    }
    if ($ismember) {
        $uniq_avatar = 'Y';
    }
    // change avatar after year :>
    if ($u->id != 'Anonymous') {
        $bookmark = !empty($u->info['bookmark']) ? $u->info['bookmark'] : '';
    } else {
        $bookmark = $u->bookmark;
    }
    $tz_offset = $formatter->tz_offset;
    if (!$bookmark or !empty($nobookmark)) {
        if (!empty($checknew) and preg_match('/^\\d+(\\s*\\*\\s*\\d+)*$/', $checknew)) {
            $checknew = eval('return ' . $checknew . ';');
        }
        if ($checknew > 1) {
            $bookmark = strtotime(date('Y-m-d', time() - $checknew) . ' 00:00:00');
        }
    }
    if (!$bookmark) {
        $bookmark = time();
    }
    // set search query
    if (isset($_GET['q'][0])) {
        $query = _preg_search_escape(trim($_GET['q']));
        if (@preg_match('/' . $query . '/', '') === false) {
            unset($query);
        }
    }
    // make rclog uniq key
    $locals = get_defined_vars();
    unset($locals['bookmark']);
    unset($locals['formatter']);
    unset($locals['options']);
    unset($locals['DBInfo']);
    unset($locals['Config']);
    unset($locals['args']);
    unset($locals['arg']);
    unset($locals['u']);
    unset($locals['k']);
    unset($locals['v']);
    unset($locals['p']);
    unset($locals['value']);
    unset($locals['tz_offset']);
    unset($locals['members']);
    $rckey = md5(serialize($locals));
    $rckey2 = $rckey;
    $rclog = '<!-- rckey = ' . $rckey . ', cache delay = ' . $cache_delay . ' -->';
    if ($use_js) {
        unset($locals['use_js']);
        $rckey2 = md5(serialize($locals));
        // rckey without js option
    }
    unset($locals);
    // check RC cache
    $lc = new Cache_text('rccache');
    $mtime = $lc->mtime($rckey);
    if (empty($formatter->refresh)) {
        if (($val = $lc->fetch($rckey)) !== false and $DBInfo->checkUpdated($mtime, $cache_delay)) {
            return $val . '<!-- cached at ' . date('Y-m-d H:i:s', $mtime) . ' -->';
        } else {
            if (!empty($options['ajax']) && $rctype == 'list' && $rckey != $rckey2) {
                // rctype == list with ajax option does not depend on "use_js" option.
                $mtime = $lc->mtime($rckey2);
                if (($val = $lc->fetch($rckey2)) !== false and $DBInfo->checkUpdated($mtime, $cache_delay)) {
                    return $val . '<!-- cached at ' . date('Y-m-d H:i:s', $mtime) . ' -->';
                }
            }
        }
        // need to update cache
        if ($val !== false and $lc->exists($rckey . '.lock')) {
            return $val . '<!-- cached at ' . date('Y-m-d H:i:s', $mtime) . ' -->';
        }
        $lc->update($rckey . '.lock', array('lock'), 5);
        // 5s lock
    } else {
        $lc->update($rckey . '.lock', array('lock'), 5);
        // 5s lock
    }
    // $uniq_avatar is numeric case: change avatar icon after 24 hours
    if (is_numeric($uniq_avatar)) {
        $uniq_avatar = $rckey . date('mdH', time());
    } else {
        if (is_string($uniq_avatar) and preg_match('/^[YmdHi]+$/', $uniq_avatar)) {
            // date format string case: change avatar icon after 'Ymd' etc period
            $uniq_avatar = $rckey . date($uniq_avatar, time());
        }
    }
    $time_current = isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : time();
    $secs_per_day = 60 * 60 * 24;
    //$time_cutoff= $time_current - ($days * $secs_per_day);
    $lines = $DBInfo->editlog_raw_lines($days, $opts);
    // make a daysago button
    $btnlist = '';
    if (!empty($use_daysago) or !empty($_GET['ago'])) {
        $msg[0] = _("Show changes for ");
        $agolist = array(-$days, $days, 2 * $days, 3 * $days);
        $btn = array();
        $arg = 'days=' . $days . '&amp;ago';
        $msg[1] = _("days ago");
        foreach ($agolist as $d) {
            $d += $opts['ago'];
            if ($d <= 0) {
                continue;
            }
            $link = $formatter->link_tag($formatter->page_urlname, "?{$arg}=" . $d, $d);
            $btn[] = $link;
        }
        #if (sizeof($lines)==0) $btn=array_slice($btn,0,1);
        $btn[] = $formatter->link_tag($formatter->page_urlname, "?{$arg}=...", '...', 'onClick="return daysago(this)"');
        $script = "<script type='text/javascript' src='{$DBInfo->url_prefix}/local/rc.js' ></script>";
        $btnlist = $msg[0] . ' <ul><li>' . implode("</li>\n<li>", $btn) . '</li></ul> ' . $msg[1];
        $btnlist = $script . "<div class='rc-button'>\n" . $btnlist . "</div>\n";
    }
    $rc = new Cache_text('rclogs');
    $ratchet_day = FALSE;
    $editors = array();
    $editcount = array();
    $rc_delay = isset($DBInfo->rc_delay) ? $DBInfo->rc_delay : $rc_cache_delay;
    $rctimestamp = 0;
    $needupdate = false;
    $use_val = false;
    while (($val = $rc->fetch($rckey)) !== false) {
        $use_val = true;
        if (!empty($formatter->refresh) or !$DBInfo->checkUpdated($rc->mtime($rckey), $rc_delay)) {
            $use_val = $rc->exists($rckey . '.lock');
        }
        if (!$use_val) {
            break;
        }
        $editors = $val['editors'];
        $editcount = $val['editcount'];
        $lastmod = $val['lastmod'];
        $rclastline = $val['lastline'];
        $rctimestamp = $val['timestamp'];
        $users = $val['users'];
        break;
    }
    // no cache available
    if (!$use_val) {
        $rc->update($rckey . '.lock', array('lock'), 5);
    }
    // 5s lock
    $lastline = $lines[0];
    $tmp = explode("\t", $lastline, 6);
    $timestamp = $tmp[2];
    unset($tmp);
    $updatemod = array();
    $needupdate = $rctimestamp < $timestamp or $lastline != $rclastline;
    if ($needupdate) {
        foreach ($lines as $line) {
            $parts = explode("\t", $line, 6);
            if ($lastline == $rclastline) {
                break;
            }
            $page_key = $parts[0];
            $ed_time = $parts[2];
            $user = $parts[4];
            $addr = $parts[1];
            if ($user == 'Anonymous') {
                $user = '******' . $addr;
            } else {
                $user = $user . "\t" . $addr;
            }
            $day = gmdate('Ymd', $ed_time + $tz_offset);
            //if ($day != $ratchet_day) {
            //  $ratchet_day = $day;
            //}
            if ($last_entry_only and !empty($last_entry_check)) {
                if (!empty($lastmod[$page_key]) and $lastmod[$page_key] < $ed_time + $last_entry_check) {
                    $edit_day = gmdate('Ymd', $lastmod[$page_key] + $tz_offset);
                    $editors[$page_key][$edit_day][] = $user;
                    $editcount[$page_key][$edit_day]++;
                    if ($needupdate and empty($updatemod[$page_key])) {
                        $updatemod[$page_key] = $ed_time;
                    }
                    continue;
                }
            } else {
                if (!empty($editcount[$page_key][$day])) {
                    $editors[$page_key][$day][] = $user;
                    $editcount[$page_key][$day]++;
                    if ($needupdate and empty($updatemod[$page_key])) {
                        $updatemod[$page_key] = $ed_time;
                    }
                    continue;
                }
            }
            if (empty($editcount[$page_key])) {
                $editcount[$page_key] = array();
                $editors[$page_key] = array();
            }
            $editcount[$page_key][$day] = 1;
            $editors[$page_key][$day] = array();
            $editors[$page_key][$day][] = $user;
            $lastmod[$page_key] = $ed_time;
            if ($needupdate) {
                $updatemod[$page_key] = $ed_time;
            }
        }
    }
    if (!empty($lastmod)) {
        $lastmod = array_merge($lastmod, $updatemod);
    }
    // search query
    if (isset($query[0])) {
        $lines = preg_grep("/{$query}/i", $lines);
    }
    // setup hidelog rule
    $hiderule = null;
    if (!$ismember && !empty($Config['ruleset']['hiderule'])) {
        $rule = implode('|', $Config['ruleset']['hiderule']);
        if (preg_match('@' . $rule . '@', null) !== false) {
            $hiderule = '@' . $rule . '@';
        }
    }
    $out = "";
    $ratchet_day = FALSE;
    $br = "";
    $ii = 0;
    $rc_list = array();
    $list = array();
    foreach ($lines as $line) {
        $parts = explode("\t", $line);
        $page_key = $parts[0];
        $ed_time = $parts[2];
        $day = gmdate('Ymd', $ed_time + $tz_offset);
        // show last edit only
        if (!empty($last_entry_only) and !empty($logs[$page_key])) {
            continue;
        } else {
            if (!empty($logs[$page_key][$day])) {
                continue;
            }
        }
        $page_name = $DBInfo->keyToPagename($parts[0]);
        if (!empty($hiderule)) {
            if (preg_match($hiderule, $page_name)) {
                continue;
            }
        }
        // show trashed pages only
        if ($trash and $DBInfo->hasPage($page_name)) {
            continue;
        }
        $addr = $parts[1];
        $user = $parts[4];
        $log = _stripslashes($parts[5]);
        $act = rtrim($parts[6]);
        $via_proxy = false;
        if (($p = strpos($addr, ',')) !== false) {
            // user via Proxy
            $via_proxy = true;
            $real_ip = substr($addr, 0, $p);
            $log_proxy = '<span class="via-proxy">' . $real_ip . '</span>';
            $log = isset($log[0]) ? $log_proxy . ' ' . $log : $log_proxy;
            $dum = explode(',', $addr);
            $addr = array_pop($dum);
        }
        //    if ($ed_time < $time_cutoff)
        //      break;
        $group = '';
        if ($formatter->group) {
            if (!preg_match("/^({$formatter->group})(.*)\$/", $page_name, $match)) {
                continue;
            }
            $title = $match[2];
        } else {
            if (!empty($formatter->use_group) and ($p = strpos($page_name, '~')) !== false) {
                $title = substr($page_name, $p + 1);
                $group = ' (' . substr($page_name, 0, $p) . ')';
            } else {
                $title = $page_name;
            }
        }
        if (!empty($changed_time_fmt)) {
            if (empty($timesago)) {
                $date = gmdate($changed_time_fmt, $ed_time + $tz_offset);
            } else {
                $date = _timesago($ed_time, 'Y-m-d', $tz_offset);
            }
        }
        $pageurl = _rawurlencode($page_name);
        // get title
        $title0 = get_title($title) . $group;
        $title0 = _html_escape($title0);
        if ($rctype == 'list') {
            $attr = '';
        } else {
            $attr = " id='title-{$ii}'";
        }
        if (!empty($strimwidth) and strlen(get_title($title)) > $strimwidth and function_exists('mb_strimwidth')) {
            $title0 = mb_strimwidth($title0, 0, $strimwidth, '...', $DBInfo->charset);
        }
        $attr .= ' title="' . $title0 . '"';
        $title = $formatter->link_tag($pageurl, "", $title0, $target . $attr);
        // simple list format
        if ($rctype == 'list') {
            if (empty($logs[$page_key])) {
                $logs[$page_key] = array();
            }
            $logs[$page_key][$day] = 1;
            if (!$DBInfo->hasPage($page_name)) {
                $act = 'DELETE';
                $title = '<strike>' . $title . '</strike>';
            }
            $list[$page_name] = array($title, $date, $ed_time, $act);
            continue;
        }
        // print $ed_time."/".$bookmark."//";
        $diff = '';
        $updated = '';
        if ($act == 'UPLOAD') {
            $icon = $formatter->link_tag($pageurl, "?action=uploadedfiles", $formatter->icon['attach']);
        } else {
            if (!$DBInfo->hasPage($page_name)) {
                $icon = $formatter->link_tag($pageurl, "?action=info", $formatter->icon['del']);
                if (!empty($use_js)) {
                    $rc_list[] = $page_name;
                }
            } else {
                $icon = $formatter->link_tag($pageurl, "?action=diff", $formatter->icon['diff'], " id='icon-{$ii}'");
                if (empty($use_js) and $ed_time > $bookmark) {
                    $icon = $formatter->link_tag($pageurl, "?action=diff&amp;date={$bookmark}", $formatter->icon['diff']);
                    $updated = ' ' . $formatter->link_tag($pageurl, "?action=diff&amp;date={$bookmark}", $formatter->icon['updated'], 'class="updated"');
                    $add = 0;
                    $del = 0;
                    if ($checknew or $checkchange) {
                        $p = new WikiPage($page_name);
                        $v = $p->get_rev($bookmark);
                        if (empty($v)) {
                            $icon = $formatter->link_tag($pageurl, "?action=info", $formatter->icon['show']);
                            $updated = ' ' . $formatter->link_tag($pageurl, "?action=info", $formatter->icon['new'], 'class="new"');
                            $add += $p->lines();
                        }
                    }
                    if ($checkchange) {
                        if (empty($v)) {
                            // new
                            $infos = array();
                        } else {
                            $infos = $p->get_info('>' . $bookmark);
                        }
                        foreach ($infos as $inf) {
                            $tmp = explode(' ', trim($inf[1]));
                            if (isset($tmp[1])) {
                                $add += $tmp[0];
                                $del += $tmp[1];
                            }
                        }
                    }
                    if (!empty($add)) {
                        $diff .= '<span class="diff-added"><span>+' . $add . '</span></span>';
                    }
                    if (!empty($del)) {
                        $diff .= '<span class="diff-removed"><span>' . $del . '</span></span>';
                    }
                } else {
                    if (!empty($use_js)) {
                        $diff = '<span id="diff-' . $ii . '"></span>';
                        $rc_list[] = $page_name;
                    }
                }
            }
        }
        if (!empty($use_hits)) {
            $hits = $DBInfo->counter->pageCounter($page_name);
        }
        if (!empty($showhost)) {
            if ($last_editor_only) {
                // show last editor only
                $editor = $editors[$page_key][$day];
                if (is_array($editor)) {
                    $editor = $editor[0];
                }
            } else {
                // all show all authors
                // count edit number
                // make range list
                if ($use_editrange) {
                    // MoinMoin like edit range
                    $editor_list = array();
                    if ($editors[$page_key][$day]) {
                        foreach ($editors[$page_key][$day] as $idx => $name) {
                            if (empty($editor_list[$name])) {
                                $editor_list[$name] = array();
                            }
                            $editor_list[$name][] = $idx + 1;
                        }
                    }
                    $editor_counts = array();
                    foreach ($editor_list as $name => $edits) {
                        $range = ',';
                        if (isset($edits[1])) {
                            $edits[] = 999999;
                            // MoinMoin method
                            for ($i = 0, $sz = count($edits) - 1; $i < $sz; $i++) {
                                if (substr($range, -1) == ',') {
                                    $range .= $edits[$i];
                                    if ($edits[$i] + 1 == $edits[$i + 1]) {
                                        $range .= '-';
                                    } else {
                                        $range .= ',';
                                    }
                                } else {
                                    if ($edits[$i] + 1 != $edits[$i + 1]) {
                                        $range .= $edits[$i] . ',';
                                    }
                                }
                            }
                            $range = trim($range, ',-');
                            $editor_counts[$name] = $range;
                        } else {
                            $editor_counts[$name] = $edits[0];
                        }
                    }
                } else {
                    $editor_counts = array_count_values($editors[$page_key][$day]);
                }
                $editor = array_keys($editor_counts);
            }
            $all_user = array();
            foreach ((array) $editor as $user) {
                if (!$last_editor_only and isset($editor[1]) and isset($editor_counts[$user])) {
                    $count = " <span class='range'>[" . $editor_counts[$user] . "]</span>";
                } else {
                    $count = '';
                }
                if (!empty($showhost) && substr($user, 0, 9) == 'Anonymous') {
                    $ouser = $user;
                    if (isset($users[$ouser])) {
                        $user = $users[$ouser];
                    } else {
                        $checkaddr = null;
                        $addr = null;
                        $tmp = $user;
                        if (strpos($user, "\t") !== false) {
                            list($tmp, $addr) = explode("\t", $user);
                        }
                        $checkaddr = substr($tmp, 10);
                        // Anonymous-127.0.0.1 or Anonymous-email@foo.bar
                        if (($p = strpos($checkaddr, ',')) !== false) {
                            $dum = explode(',', $checkaddr);
                            $checkaddr = array_pop($dum);
                            // last address is the REMOTE_ADDR
                        }
                        $user = $addr = $addr ? $addr : $checkaddr;
                        if (!is_numeric($checkaddr[0]) and preg_match('/^[a-z][a-z0-9_\\-\\.]+@[a-z][a-z0-9_\\-]+(\\.[a-z0-9_]+)+$/i', $user)) {
                            $user = $checkaddr;
                            if (!empty($DBInfo->hide_emails)) {
                                $user = substr(md5($user), 0, 8);
                            } else {
                                $user = email_guard($user);
                            }
                        } else {
                            if (isset($DBInfo->interwiki['Whois'])) {
                                $wip = "<a href='" . $DBInfo->interwiki['Whois'] . "{$addr}' target='_blank'>{$ipicon}</a>";
                            } else {
                                $wip = "<a href='?action=whois&q=" . $addr . "' target='_blank'>{$ipicon}</a>";
                            }
                            if ($ismember) {
                                if (in_array($user, $members)) {
                                    $wip = '';
                                }
                                if (!empty($DBInfo->use_admin_user_url)) {
                                    $user = '******' . $DBInfo->use_admin_user_url . $user . '">' . $user . '</a>' . $wip;
                                } else {
                                    $user = $user . $wip;
                                }
                            } else {
                                if (!empty($DBInfo->mask_hostname)) {
                                    $user = _mask_hostname($addr, intval($DBInfo->mask_hostname));
                                }
                            }
                        }
                        $avatar = '';
                        if (!empty($use_avatar)) {
                            if (!empty($uniq_avatar)) {
                                $key = $addr . $uniq_avatar;
                            } else {
                                $key = $addr . $rckey;
                            }
                            $crypted = md5($key);
                            $mylnk = preg_replace('/seed=/', 'seed=' . $crypted, $avatarlink);
                            $avatar = '<img src="' . $mylnk . '" class="avatar" alt="avatar" />';
                        }
                        $user = $avatar . $user;
                        $users[$ouser] = $user;
                    }
                } else {
                    list($user, $addr) = explode("\t", $user);
                    $ouser = $user;
                    if (!isset($users[$ouser])) {
                        if (isset($DBInfo->interwiki['Whois'])) {
                            $wip = "<a href='" . $DBInfo->interwiki['Whois'] . "{$addr}' target='_blank'>{$ipicon}</a>";
                        } else {
                            $wip = "<a href='?action=whois&q=" . $addr . "' target='_blank'>{$ipicon}</a>";
                        }
                        $avatar = '';
                        if (!empty($use_avatar)) {
                            if (!empty($uniq_avatar)) {
                                $key = $addr . $uniq_avatar;
                            } else {
                                $key = $addr . $rckey;
                            }
                            if (!$ismember) {
                                $key .= $user;
                            }
                            // not a member: show different avatar for login user
                            $crypted = md5($key);
                            $mylnk = preg_replace('/seed=/', 'seed=' . $crypted, $avatarlink);
                            if ($ouser != 'Anonymous') {
                                $mylnk .= '&amp;user='******'<img src="' . $mylnk . '" class="avatar" alt="avatar" />';
                        }
                    }
                    if (isset($users[$ouser])) {
                        $user = $users[$ouser];
                    } else {
                        if ($ismember) {
                            if (in_array($user, $members)) {
                                $wip = '';
                            }
                            if (!empty($DBInfo->use_admin_user_url)) {
                                $user = $avatar . '<a href="' . $DBInfo->use_admin_user_url . $user . '">' . $user . '</a>' . $wip;
                            } else {
                                $user = $avatar . $user . $wip;
                            }
                            $users[$ouser] = $user;
                        } else {
                            if (!empty($DBInfo->use_nick)) {
                                $uid = $user;
                                if (($p = strpos($uid, ' ')) !== false) {
                                    $uid = substr($uid, 0, $p);
                                }
                                $u = $DBInfo->udb->getUser($uid);
                                if (!empty($u->info)) {
                                    if (!empty($DBInfo->interwiki['User'])) {
                                        $user = $formatter->link_repl('[wiki:User:'******' ' . $u->info['nick'] . ']');
                                    } else {
                                        if (!empty($u->info['home'])) {
                                            $user = $formatter->link_repl('[' . $u->info['home'] . ' ' . $u->info['nick'] . ']');
                                        } else {
                                            if (!empty($u->info['nick'])) {
                                                $user = $formatter->link_repl('[wiki:' . $uid . ' ' . $u->info['nick'] . ']');
                                            }
                                        }
                                    }
                                }
                                $user = $avatar . $user;
                                $users[$ouser] = $user;
                            } else {
                                if (strpos($user, ' ') !== false) {
                                    $user = $avatar . $formatter->link_repl($user);
                                    $users[$ouser] = $user;
                                } else {
                                    if (empty($DBInfo->no_wikihomepage) and $DBInfo->hasPage($user)) {
                                        $user = $formatter->link_tag(_rawurlencode($user), "", $user);
                                        $user = $avatar . $user;
                                        $users[$ouser] = $user;
                                    } else {
                                        if (substr($user, 0, 9) == 'Anonymous') {
                                            $addr = substr($user, 10);
                                            $user = _('Anonymous');
                                        }
                                        $uid = $user;
                                        if (preg_match('/^[a-z][a-z0-9_\\-\\.]+@[a-z][a-z0-9_\\-]+(\\.[a-z0-9_]+)+$/i', $user)) {
                                            if (!empty($DBInfo->hide_emails)) {
                                                $user = substr(md5($user), 0, 8);
                                            } else {
                                                $user = email_guard($user);
                                            }
                                        }
                                        $user = $avatar . $user;
                                        $users[$ouser] = $user;
                                    }
                                }
                            }
                        }
                    }
                }
                $all_user[] = $user . $count;
            }
            if (isset($editor[1])) {
                $user = '******' . implode("</span> <span class='editor'>", $all_user) . "</span></span>\n";
            } else {
                $user = '******' . $all_user[0] . "</span>\n";
            }
        } else {
            $user = '******';
        }
        $jsattr = '';
        if (!empty($use_js)) {
            $jsattr = ' onclick="update_bookmark(' . $ed_time . ');return false;"';
        }
        $bmark = '';
        if ($day != $ratchet_day) {
            $ratchet_day = $day;
            if (!empty($use_day)) {
                $tag = str_replace('-', '', $day);
                $perma = "<a name='{$tag}'></a><a class='perma' href='#{$tag}'>{$perma_icon}</a>";
                $out .= $cat0;
                $rcdate = gmdate($date_fmt, $ed_time + $tz_offset);
                $out .= sprintf("%s<span class='rc-date' style='font-size:large'>%s ", $br, $rcdate);
                if (empty($nobookmark)) {
                    $out .= "<span class='rc-bookmark' style='font-size:small'>[" . $formatter->link_tag($formatter->page->urlname, $bookmark_action . "&amp;time={$ed_time}" . $daysago, _("set bookmark"), $jsattr) . "]</span>\n";
                }
                $br = "<br />";
                $out .= '</span>' . $perma . '<br />' . $bra;
                $cat0 = $cat;
            } else {
                $bmark = $formatter->link_to($bookmark_action . "&amp;time={$ed_time}" . $daysago, _("Bookmark"), $jsattr . ' class="button-small"');
            }
        }
        //if (empty($use_day) and empty($nobookmark)) {
        if (empty($nobookmark)) {
            $date = $formatter->link_to($bookmark_action . "&amp;time={$ed_time}" . $daysago, $date, ' id="time-' . $ii . '" ' . $jsattr);
        }
        $count = "";
        $extra = "";
        if ($editcount[$page_key][$day] > 1) {
            $count = '<span id="change-' . $ii . '">' . sprintf(_("%s changes"), " <span class='num'>" . $editcount[$page_key][$day] . "</span>") . '</span>';
        } else {
            $count = '<span id="change-' . $ii . '"></span>';
        }
        if (!empty($comment) && !empty($log)) {
            $extra = "&nbsp; &nbsp; &nbsp; <small name='word-break'>{$log}</small>";
        }
        $alt = $ii % 2 == 0 ? ' class="alt"' : '';
        if ($extra and isset($template_extra)) {
            if ($rctype == 'board' and !empty($use_js)) {
                $style = ' style="display:none"';
            } else {
                $style = '';
            }
            if (!empty($use_js)) {
                $title = '<button onclick="toggle_log(this);return false;"><span>+</span></button>' . $title;
            }
            $out .= eval('return ' . $template_extra . ';');
        } else {
            $out .= eval('return ' . $template . ';');
        }
        if (empty($logs[$page_key])) {
            $logs[$page_key] = array();
        }
        $logs[$page_key][$day] = 1;
        ++$ii;
    }
    if ($needupdate) {
        $rc->update($rckey, array('editors' => $editors, 'editcount' => $editcount, 'lastmod' => $lastmod, 'lastline' => $lastline, 'timestamp' => $timestamp, 'users' => $users));
    }
    $js = '';
    if (!empty($rc_list)) {
        require_once 'lib/JSON.php';
        $json = new Services_JSON();
        $icon_new = $formatter->icon['new'];
        $icon_updated = $formatter->icon['updated'];
        $icon_show = $formatter->icon['show'];
        $icon_diff = $formatter->icon['diff'];
        $js = "<script type='text/javascript'>\n/*<![CDATA[*/\nvar rclist =";
        $ext = array();
        if (!empty($checknew)) {
            $ext[] = 'new=1';
        }
        if (!empty($checkchange)) {
            $ext[] = 'change=1';
        }
        $arg = implode('&', $ext);
        //$url = qualifiedURL($formatter->link_url('RecentChanges')); // FIXME
        //$url = preg_replace('/^https?:/', '', $url);
        $url = $formatter->link_url('RecentChanges');
        $postdata = "action=recentchanges/ajax" . ($arg ? '&' . $arg : '');
        $js .= $json->encode($rc_list) . ";\n";
        if ($use_diffwidth) {
            $js .= "var use_diffwidth = true;\n";
        } else {
            $js .= "var use_diffwidth = false;\n";
        }
        $js .= <<<EOF
function diff_width(size) {
    if (size < 0)
        size = -size;
    if (size < 5)
      return '';
    else if (size < 10)
      return 'display:inline-block;width:25px';
    else
      return 'display:inline-block;width:' + ~~(25 + 2*Math.sqrt(size)) + 'px';
}

function update_bookmark(time) {
    var url = "{$url}";
    if (rclist.length) {
      var timetag;
      if (typeof time == 'undefined') timetag = '';
      else timetag = '&time=' + time;

      var data = "{$postdata}";
      data += timetag + '&value=' + encodeURIComponent(json_encode(rclist));
      var txt = HTTPPost(url, data);
      var ret;
      if (txt == null) return;

      var icon_new = "{$icon_new}";
      var icon_updated = "{$icon_updated}";
      var icon_show = "{$icon_show}";
      var icon_diff = "{$icon_diff}";

      ret = window["eval"]("(" + txt + ")");
      var bookmark = ret['__-_-bookmark-_-__'];
      var jj = 0;
      for (var ii = 0; ii < rclist.length; ii++) {
        // update time
        var time = document.getElementById('time-' + ii);
        var tstr = time.firstChild.innerText;
        var d0 = Date.parse(tstr); // test
        if (isNaN(d0)) {
          // recalc time string
          var timestamp = time.href.match(/time=(\\d+)/);
          tstr = timesago(timestamp[1], "{$date_fmt}", {$tz_offset});
          if (tstr != null)
            time.firstChild.innerText = tstr;
        }

        var item = document.getElementById('title-' + ii);
        var title = item.getAttribute('title');
        if (rclist[jj] != title) {
          var re = new RegExp("^.*" + url_prefix + '/');
          title = decodeURIComponent(item.href.replace(re, ''));
        }

        if (ret[title] && ret[title]['state'] == 'deleted') { jj++; continue; }

        if (rclist[jj] == title && ret[title]) {
          var icon = document.getElementById('icon-' + ii);
          var state = document.createElement('SPAN');
          if (ret[title]['state'] == 'new') {
            state.innerHTML = icon_new;
            state.setAttribute('class', 'new');
            icon.href = icon.href.replace(/action=(diff|info)((?:&|&amp;)date=\\d+)?/, 'action=info');
            icon.innerHTML = icon_show;
          } else {
            state.innerHTML = icon_updated;
            state.setAttribute('class', 'updated');
            icon.href = icon.href.replace(/action=(diff|info)((?:&|&amp;)date=\\d+)?/, 'action=diff&date=' + bookmark);
            icon.innerHTML = icon_diff;
          }

          // remove previous icon
          if (item.firstChild.nextSibling)
            item.removeChild(item.firstChild.nextSibling);
          item.appendChild(state); // add updated / new icon

          var change = document.getElementById('change-' + ii);
          if (!change) continue;
          var diff = document.getElementById('diff-' + ii);
          var nodiff = !diff;

          // remove previous diff info
          if (change.lastChild && change.lastChild.tagName == 'SPAN')
            change.removeChild(change.lastChild);
          else if (diff && diff.lastChild)
            diff.removeChild(diff.lastChild);

          // add diff info
          var diff0 = document.createElement('SPAN');
          if (ret[title]['add']) {
            var add = document.createElement('SPAN');
            var add2 = document.createElement('SPAN');
            add.setAttribute('class', 'diff-added');
            var txt = document.createTextNode('+' + ret[title]['add']);
            add2.appendChild(txt);
            add.appendChild(add2);
            diff0.appendChild(add);
            if (use_diffwidth)
            add.style.cssText = diff_width(ret[title]['add']);
          }
          if (ret[title]['del']) {
            var del = document.createElement('SPAN');
            var del2 = document.createElement('SPAN');
            del.setAttribute('class', 'diff-removed');
            var txt = document.createTextNode(ret[title]['del']);
            del2.appendChild(txt);
            del.appendChild(del2);
            diff0.appendChild(del);
            if (use_diffwidth)
            del.style.cssText = diff_width(ret[title]['del']);
          }
          if (nodiff)
            change.appendChild(diff0);
          else
            diff.appendChild(diff0);
          jj++;
        } else {
          if (item.firstChild.nextSibling)
            item.removeChild(item.firstChild.nextSibling);

          var change = document.getElementById('change-' + ii);
          if (!change) continue;
          var diff = document.getElementById('diff-' + ii);

          // remove diff info
          if (change.lastChild && change.lastChild.tagName == 'SPAN')
            change.removeChild(change.lastChild);
          else if (diff && diff.lastChild)
            diff.removeChild(diff.lastChild);

          // recover diff icon and link
          var icon = document.getElementById('icon-' + ii);
          if (icon && icon.firstChild) {
            var alt = icon.firstChild.getAttribute('alt');
            if (alt != 'D' && alt != '@') {
              icon.innerHTML = icon_diff;
            }
            // recover link
            icon.href = icon.href.replace(/action=(diff|info)(&date=\\d+)?/, 'action=diff');
          }
        }
      }
    }
}
if(window.addEventListener)window.addEventListener("load",update_bookmark,false);
else if(window.attachEvent)window.attachEvent("onload",update_bookmark);
/*]]>*/
</script>
EOF;
    } else {
        if (!empty($list)) {
            $out = '';
            foreach ($list as $k => $v) {
                $out .= '<li><span data-timestamp="' . $v[2] . '" class="date">' . $v[1] . '</span> ' . $v[0] . '</li>' . "\n";
            }
            //if (!empty($options['ajax'])) {
            //  return '<ul>'.$out.'</ul>';
            //}
        }
    }
    if (in_array($rctype, array('list', 'simple')) and $use_js) {
        static $rc_id = 1;
        $rcid = ' id="rc' . $rc_id . '"';
        $extra = '';
        if (!empty($opts['items'])) {
            $extra .= '&item=' . $opts['items'];
        }
        if (!empty($my_date_fmt)) {
            $extra .= '&datefmt=' . $my_date_fmt;
        }
        $url = $formatter->link_url('RecentChanges', "?action=recentchanges/ajax&type={$rctype}" . $extra);
        $js = <<<JS
<script type='text/javascript'>
/*<![CDATA[*/
(function() {
  var url = "{$url}";
  var txt = HTTPGet(url);
  var rc = document.getElementById("rc{$rc_id}");
  if (txt.substring(0,5) != 'false') {
    var m = null;
    if (m = txt.match(/<ul>[\\s\\S]*<\\/ul>/)) {
      rc.innerHTML = m[0];
    }
  }
})();
/*]]>*/
</script>
JS;
        $rc_id++;
    } else {
        if ($use_js and $rctype == 'board') {
            $js .= <<<JS
<script type='text/javascript'>
/*<![CDATA[*/
function toggle_log(el)
{
  var item = el.parentNode.parentNode; // container
  var log = item.nextSibling;
  if (log.tagName == undefined)
    log = log.nextSibling; // for IE6

  if (log.style.display == "none") {
    el.className = "close";
    log.style.display = "";
  } else {
    el.className = "open";
    log.style.display = "none";
  }
}
/*]]>*/
</script>
JS;
        }
    }
    $out = $btnlist . '<div class="recentChanges"' . $rcid . '>' . $rctitle . $template_bra . $out . $template_cat . $cat0 . '</div>' . $js . $rclog;
    $lc->update($rckey, $out);
    $lc->remove($rckey . '.lock');
    // unlock
    $rc->remove($rckey . '.lock');
    // unlock
    return $out;
}
Пример #5
0
function _render_stat($formatter, $retval, $params = array())
{
    global $DBInfo;
    $show_table = false;
    if (empty($DBInfo->stat_no_show_all) || in_array($params['id'], $DBInfo->members)) {
        $show_table = true;
    }
    extract($retval);
    // basic information
    $total_lines = $formatter->page->lines();
    $orig_author = $author;
    $count_revs = count($revs);
    $count_users = count($users);
    // parameters
    $first_contribution_author_ratio = 85;
    //echo '<pre>';
    //print_r($users);
    $authors = array_keys($users);
    $edits = array();
    $user_adds = array();
    $user_dels = array();
    $orig_lines = $total_lines;
    $total_adds = 0;
    $total_dels = 0;
    foreach ($authors as $n) {
        $edits[$n] = $users[$n]['edit'];
        $user_adds[$n] = $users[$n]['add'];
        $user_dels[$n] = $users[$n]['del'];
        $total_adds += $users[$n]['add'];
        $total_dels += $users[$n]['del'];
    }
    $orig_lines -= $total_adds - $total_dels;
    // fix original author info.
    if ($rev === '1.1') {
        $users[$orig_author]['add'] += $orig_lines;
        $user_adds[$orig_author] += $orig_lines;
    }
    $adds[$count_revs - 1] = $orig_lines;
    $total_adds += $orig_lines;
    //echo "<pre>";
    //print_r($adds);
    //print_r($dels);
    //print_r($edits);
    //echo '</pre>';
    // sort by edits
    arsort($edits);
    $contribs = array();
    $total_edits = $count_revs;
    $mean_edits = $count_revs / $count_users;
    $max_edits = $users[$authors[0]]['edit'];
    $mean_adds = $total_adds / $count_users;
    $mean_dels = $total_dels / $count_users;
    foreach ($edits as $u => $c) {
        $point = _calc_contrib_points($c, $total_edits, $max_edits, $mean_edits, $user_adds[$u], $user_dels[$u], $total_lines, $mean_adds, $mean_dels);
        $count = sprintf("%4.1f %%", round($point * 100, 1));
        $contribs[$u] = $count;
    }
    $authors = $others = array_keys($edits);
    array_shift($others);
    if (isset($params['retval'])) {
        $ret = array('total_revs' => $count_revs, 'initial_rev' => $rev, 'original_author' => $orig_author, 'total_editors' => $count_users, 'contributions' => $contribs);
        if ($count_users == 1) {
            $ret['first_author'] = $orig_author;
        } else {
            if ($contribs[$authors[0]] > $first_contribution_author_ratio) {
                $ret['first_author'] = $authors[0];
            }
        }
        $params['retval'] = $ret;
        return 0;
    }
    foreach ($others as $u) {
        $contribs[$u] .= ' (<span class="diff-added">' . sprintf("%4.1f", round($user_adds[$u] / $user_adds[$authors[0]] * 100, 2));
        $contribs[$u] .= '</span>/';
        $contribs[$u] .= '<span class="diff-removed">' . sprintf("%4.1f", round($user_dels[$u] / $user_dels[$authors[0]] * 100, 2));
        $contribs[$u] .= '</span>)';
    }
    $u = preg_match('/^([0-9]+\\.){3}[0-9]+$/', $orig_author) ? _mask_hostname($orig_author) : $orig_author;
    $ou = $count_users == 1 ? $orig_author : $authors[0];
    $ou = preg_match('/^([0-9]+\\.){3}[0-9]+$/', $ou) ? _mask_hostname($ou) : $ou;
    $out = "<div class='wikiInfo'><h2>" . _("Revision Statistics") . "</h2>\n";
    $out .= '<h3>' . sprintf(_("Total %d revisions"), $count_revs) . ', ';
    $out .= sprintf(_("Total %d editors"), sizeof($users)) . '</h3>' . "\n";
    $out .= '<table class="wiki center">';
    $out .= '<tr><th>' . _("Initial revision") . '</th><td>' . $rev . '</td></tr>' . "\n";
    $out .= '<tr><th>' . _("Original Author") . '</th><td>' . $u . '</td></tr>' . "\n";
    if ($count_users == 1 && $show_table) {
        $out .= '<tr><th>' . _("First Contribution Author") . '</th><td>' . $ou . '</td></tr>' . "\n";
    } else {
        if ($show_table && $contribs[$authors[0]] > $first_contribution_author_ratio) {
            $out .= '<tr><th>' . _("First Contribution Author") . '</th><td>' . $ou . '</td></tr>' . "\n";
        }
    }
    $out .= '</table> <br />' . "\n";
    if ($show_table) {
        $out .= '<table class="wiki center"><tr><th>' . _("User") . '</th><th>' . _("Add") . '</th><th>' . _("Del") . '</th><th>' . _("Edit") . '</th><th>' . _("Contributions") . '</th><th>' . _("IP") . '</th></tr>';
        foreach ($edits as $u => $c) {
            $v = $users[$u];
            $ips = array_map('_mask_hostname', array_keys($v['ip']));
            $uu = preg_match('/^([0-9]+\\.){3}[0-9]+$/', $u) ? _mask_hostname($u) : $u;
            $out .= '<tr><td>' . $uu . '</td><td><span class="diff-added">+' . $v['add'] . '</span></td><td>' . '<span class="diff-removed"> -' . $v['del'] . '</span></td><td> ' . $v['edit'] . "</td>";
            $out .= '<td>' . $contribs[$u] . '</td>';
            $out .= '<td>' . implode(', ', $ips) . "</td></tr>\n";
        }
        $out .= '</table>';
    }
    // binning
    $c = sizeof($times);
    $min = intval($times[$c - 1] / 3600) * 3600;
    $max = intval($times[0] / 3600) * 3600;
    $range = $max - $min;
    if ($c > 50) {
        $bin = $range / 20;
        $szbin = 20;
    } else {
        if ($c > 20) {
            $bin = $range / 10;
            $szbin = 10;
        } else {
            if ($c > 5) {
                $bin = $range / 5;
                $szbin = 5;
            } else {
                $bin = $range / $c;
                $szbin = $c;
            }
        }
    }
    $add_bins = array();
    $del_bins = array();
    $sum = array();
    for ($i = 0; $i <= $szbin; $i++) {
        $add_bins[$i] = 0;
        $del_bins[$i] = 0;
        $sum[$i] = 0;
    }
    for ($i = $c - 1; $i >= 0; $i--) {
        $j = intval(($times[$i] - $min) / $bin);
        $add_bins[$j] += $adds[$i];
        $del_bins[$j] -= $dels[$i];
        $sum[$j] += -$adds[$i] + $dels[$i];
    }
    $sum[$szbin] = $total_lines;
    for ($i = $szbin - 1; $i >= 0; $i--) {
        $sum[$i] += $sum[$i + 1];
    }
    $barchart = '';
    $labels = array();
    for ($j = 0; $j <= $szbin; $j++) {
        $labels[$j] = gmdate('Y-m-d', $j * $bin + $min);
    }
    $lab = '["' . implode('","', $labels) . '"]';
    $add = '[' . implode(',', $add_bins) . ']';
    $del = '[' . implode(',', $del_bins) . ']';
    $sum = '[' . implode(',', $sum) . ']';
    $barchart = <<<EOS
<script type='text/javascript'>
(function() {
var data = {
    labels : {$lab},
    datasets : [
        {
            label : "added lines",
            fillColor : "rgba(0,220,0,0.0)",
            strokeColor : "rgba(0,220,0,0.8)",
            pointColor : "rgba(0,220,0,0.6)",
            highlightFill : "rgba(0,220,0,0)",
            highlightStroke : "rgba(0,220,0,1)",
            data : {$add}
        },
        {
            label : "deleted lines",
            fillColor : "rgba(220,0,0,0.0)",
            strokeColor : "rgba(220,0,0,0.8)",
            pointColor : "rgba(220,0,0,0.6)",
            highlightFill : "rgba(220,0,0,0.75)",
            highlightStroke : "rgba(220,0,0,1)",
            data : {$del}
        },
        {
            label : "total lines",
            fillColor : "rgba(0,220,220,0.0)",
            strokeColor : "rgba(0,220,220,0.8)",
            pointColor : "rgba(0,220,220,0.7)",
            highlightFill : "rgba(0,220,220,0)",
            highlightStroke : "rgba(0,220,220,1)",
            data : {$sum}
        }
    ]
};

// onload
var oldOnload = window.onload;
window.onload = function(ev) {
    try { oldOnload(); } catch(e) {};
    var ctx = document.getElementById("info-stat").getContext("2d");
    window.myBar = new Chart(ctx).Line(data,
        { scaleBeginAtZero:false, scaleIntegersOnly:false,responsive:true });
};
})();
</script>
EOS;
    $dump = '';
    for ($j = 0; $j < $szbin; $j++) {
        $dump .= 'add= ' . $add_bins[$j] . ', del= ' . $del_bins[$j] . ', sum= ' . $sum[$j] . "\n";
    }
    return $out . "<div class='info-stat'><canvas id='info-stat'></canvas>" . $barchart;
}
Пример #6
0
function do_blame($formatter, $params)
{
    global $DBInfo;
    $rev = '';
    $option = '';
    if (!empty($params['rev'])) {
        if (preg_match('/^\\d\\.\\d+$/', $params['rev'])) {
            $rev = $params['rev'];
            $option = ' -r' . $rev;
        }
    }
    if (!$formatter->page->exists()) {
        $params['msg'] = _("Error: Page Not found !");
        do_invalid($formatter, $params);
        return;
    }
    $formatter->send_header('', $params);
    if (isset($rev[0])) {
        $params['.title'] = sprintf(_("Blame r%s"), $rev);
    } else {
        $params['.title'] = sprintf(_("Blame of %s page"), _html_escape($formatter->page->name));
    }
    $key = $DBInfo->getPageKey($formatter->page->name);
    // FIXME call blame
    $fp = popen("blame -x,v/ {$option} " . $key, 'r');
    //.' '.$formatter->NULL, 'r');
    $out = '';
    if (is_resource($fp)) {
        while (!feof($fp)) {
            $line = fgets($fp, 2048);
            $out .= $line;
        }
        pclose($fp);
    }
    $formatter->send_title($title, '', $params);
    $lines = explode("\n", $out);
    $end = array_pop($lines);
    if ($end != '') {
        array_push($lines, $end);
    }
    $u =& $DBInfo->user;
    $is_member = $u->is_member;
    // members
    $members = $DBInfo->members;
    // check modified blame or not
    if (($p = strpos($lines[0], "\t")) !== false && $p < 23) {
        $sep = "@\t@";
        $count = 5;
    } else {
        $sep = "@\\s+@";
        $count = 4;
    }
    $ipicon = '<img src="' . $DBInfo->imgs_dir . '/misc/ip.png" />';
    if (!empty($DBInfo->use_avatar)) {
        if (is_string($DBInfo->use_avatar)) {
            $type = $DBInfo->use_avatar;
        } else {
            $type = 'identicon';
        }
        $avatarlink = qualifiedUrl($formatter->link_url('', '?action=' . $type . '&amp;seed='));
    }
    echo '<div class="wikiBlame"><table>';
    $ov = '';
    $alts = array('', ' alt');
    $j = 0;
    $ii = 1;
    $blame_url = $formatter->link_url($formatter->page->urlname, '?action=blame&rev=');
    foreach ($lines as $line) {
        $tmp = preg_split($sep, $line, $count);
        $v = trim($tmp[0]);
        if ($count == 4) {
            $u = trim($tmp[1], '(');
            $t = trim($tmp[2], '):');
            $l = $tmp[3];
        } else {
            $ip = $tmp[1];
            $u = $tmp[2];
            $t = $tmp[3];
            $l = $tmp[4];
            if (!empty($DBInfo->use_avatar)) {
                $crypted = crypt($ip, $ip);
                $mylnk = preg_replace('/seed=/', 'seed=' . $crypted, $avatarlink);
                $avatar = '<img src="' . $mylnk . '" style="width:16px;height:16px;vertical-align:middle" alt="avatar" />';
            } else {
                $avatar = '';
            }
            if ($u == 'Anonymous') {
                if (!$is_member) {
                    $avatar . ($u = _mask_hostname($ip, 2));
                } else {
                    if (isset($DBInfo->interwiki['Whois'])) {
                        $wip = "<a href='" . $DBInfo->interwiki['Whois'] . "{$ip}' target='_blank'>{$ipicon}</a>";
                    } else {
                        $wip = "<a href='?action=whois&amp;q=" . $ip . "' target='_blank'>{$ipicon}</a>";
                    }
                    $u = $ip;
                    if (!empty($DBInfo->use_admin_user_url)) {
                        $u = '<a href="' . $DBInfo->use_admin_user_url . $u . '">' . $u . '</a>';
                    }
                    $u = $avatar . $u . $wip;
                }
            } else {
                if (isset($DBInfo->interwiki['Whois'])) {
                    $wip = "<a href='" . $DBInfo->interwiki['Whois'] . "{$ip}' target='_blank'>{$ipicon}</a>";
                } else {
                    $wip = "<a href='?action=whois&amp;q=" . $ip . "' target='_blank'>{$ipicon}</a>";
                }
                if ($is_member) {
                    if (!in_array($u, $members)) {
                        $u = $avatar . $u . $wip;
                    } else {
                        $u = $avatar . $u;
                    }
                } else {
                    $u = $avatar . $u;
                }
            }
            $t = date('y-m-d', $t);
        }
        if ($ov != $v) {
            $alt = $alts[++$j % 2];
        } else {
            $alt = '';
        }
        $link = '<a href="' . $blame_url . $v . '">' . $v . '</a>';
        echo '<tr><td class="version' . $alt . '">r' . $link, '</td> <td class="author' . $alt . '">', "{$u}", '</td> <td class="date' . $alt . '">', $t, '</td><td class="line">' . $ii . '</td><td class="src' . $alt . '">' . str_replace('<', '&lt', $l) . '</td></tr>';
        $ov = $v;
        $ii++;
    }
    echo '</table></div>';
    $formatter->send_footer('', $params);
    return;
}