예제 #1
0
function do_autosave($formatter, $options)
{
    global $DBInfo;
    if (session_id() == '') {
        // ip based
        if ($DBInfo->user->id == 'Anonymous') {
            $myid = md5($_SERVER['REMOTE_ADDR'] . '.' . 'MONIWIKI');
            // IP based for Anonymous user XXX
        } else {
            $myid = md5($DBInfo->user->id . $_SERVER['REMOTE_ADDR'] . '.' . 'MONIWIKI');
        }
    } else {
        if (0) {
            if ($_SESSION['_autosave']) {
                $myid = $_SESSION['_autosave'];
            } else {
                $myid = session_id();
                $_SESSION['_autosave'] = $myid;
            }
        } else {
            if ($DBInfo->user->id == 'Anonymous') {
                $myid = md5($_SERVER['REMOTE_ADDR'] . '.' . 'MONIWIKI');
                // IP based for Anonymous user XXX
            } else {
                $myid = md5($DBInfo->user->id . $_SERVER['REMOTE_ADDR'] . '.' . 'MONIWIKI');
            }
        }
    }
    $myid = md5($myid . $formatter->page->name);
    if (isset($options['section'])) {
        $myid .= '.' . $options['section'];
    }
    // XXX section support
    $save = new Cache_text('autosave');
    if (!empty($options['retrive'])) {
        $saved = $save->fetch($myid);
        $os = rtrim($saved);
        $stamp = $save->mtime($myid);
        echo $stamp . "\n" . $os;
        return true;
    } else {
        if (!empty($options['remove'])) {
            $save->remove($myid);
            echo 'true';
            return true;
        }
    }
    $savetext = $options['savetext'];
    $datestamp = substr($options['datestamp'], 0, 10);
    // only 10-digits used
    $savetext = preg_replace("/\r\n|\r/", "\n", $savetext);
    $savetext = _stripslashes($savetext);
    if ($save->exists($myid) and $save->mtime($myid) > $datestamp) {
        echo 'false';
        return false;
    }
    $save->update($myid, $savetext);
    echo 'true';
    return true;
}
예제 #2
0
function macro_Keywords($formatter, $value, $options = array())
{
    global $DBInfo;
    $supported_lang = array('ko');
    $limit = isset($options['limit']) ? $options['limit'] : 40;
    $opts = explode(',', $value);
    $sort = '';
    foreach ($opts as $opt) {
        $opt = trim($opt);
        if ($opt == 'delicious' or $opt == 'del.icio.us') {
            $tag_link = 'http://del.icio.us/tag/$TAG';
        } else {
            if ($opt == 'technorati') {
                $tag_link = 'http://www.technorati.com/tag/$TAG';
            } else {
                if ($opt == 'flickr') {
                    $tag_link = 'http://www.flickr.com/photos/tags/$TAG';
                } else {
                    if ($opt == 'all') {
                        $options['all'] = 1;
                        $limit = 0;
                    } else {
                        if ($opt == 'random') {
                            $options['random'] = $options['all'] = 1;
                        } else {
                            if ($opt == 'suggest') {
                                $options['suggest'] = 1;
                            } else {
                                if ($opt == 'tour') {
                                    $options['tour'] = 1;
                                } else {
                                    if ($opt == 'cloud') {
                                        $options['cloud'] = 1;
                                    } else {
                                        if ($opt == 'freq') {
                                            $sort = 'freq';
                                        } else {
                                            if (($p = strpos($opt, '=')) !== false) {
                                                $k = substr($opt, 0, $p);
                                                $v = substr($opt, $p + 1);
                                                if ($k == 'limit') {
                                                    $limit = $v;
                                                } else {
                                                    if ($k == 'random') {
                                                        $options['all'] = 1;
                                                        $v = (int) $v;
                                                        $v = $v > 0 ? $v : 1;
                                                        $options['random'] = $v;
                                                    } else {
                                                        if ($k == 'sort' and in_array($v, array('freq', 'alpha'))) {
                                                            $sort = $v;
                                                        } else {
                                                            if ($k == 'type' and in_array($v, array('full', 'title'))) {
                                                                $search = $v . 'search';
                                                            } else {
                                                                if ($k == 'url') {
                                                                    $tag_link = $v;
                                                                    if (preg_match('/\\$TAG/', $tag_link) === false) {
                                                                        $tag_link .= '$TAG';
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                                // else ignore
                                            } else {
                                                $pagename = $opt;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if (isset($options['random']) and empty($limit)) {
        $limit = 0;
    }
    if (isset($options['sort']) and $options['sort'] == 'freq') {
        $sort = 'freq';
    }
    if (empty($pagename)) {
        $pagename = $formatter->page->name;
    }
    # get cached keywords
    $cache = new Cache_text('keyword');
    $pkey = $pagename;
    $mc = new Cache_text('macro');
    $mkey = 'Keywords.' . md5($pagename . $value);
    $mykeys = array();
    # check cache mtime
    $cmt = $mc->mtime($mkey);
    $pmt = $cache->mtime($pkey);
    if ($cmt > $pmt) {
        # check update or not
        $dmt = $cache->mtime();
        if ($dmt > $cmt) {
            # XXX crude method
            $mykeys = array();
        } else {
            $mykeys = $mc->fetch($mkey);
        }
    } else {
        $mc->remove($mkey);
    }
    if (!$mykeys) {
        if (!empty($options['all'])) {
            $pages = $DBInfo->getPageLists();
        } else {
            $pages = array($pagename);
        }
        foreach ($pages as $pn) {
            if ($keys = $cache->fetch($pn)) {
                $mykeys = array_merge($mykeys, $keys);
            }
        }
        $mc->update($mkey, $mykeys);
    }
    if (!empty($options['all'])) {
        $use_sty = 1;
        $words = array_count_values($mykeys);
        unset($words['']);
        $ncount = array_sum($words);
        // total count
        arsort($words);
        $max = current($words);
        // get max hit number
        if (!empty($options['random'])) {
            $rws = array();
            $selected = array_rand($words, min($options['random'], count($words)));
            foreach ($selected as $k) {
                $rws[$k] = $words[$k];
            }
            $words =& $rws;
        }
        if ($sort != 'freq') {
            ksort($words);
        }
        #sort($words);
        #print $sort." $value";
        #print "<pre>";
        #print_r($words);
        #print "</pre>";
    } else {
        $max = 3;
        // default weight
        $words = array();
        foreach ($mykeys as $key) {
            $words[$key] = $max;
            // give weight to all selected keywords
        }
    }
    # automatically generate list of keywords
    if (empty($options['all']) and (empty($words) or isset($options['suggest']))) {
        $common = <<<EOF
am an a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9
if on in by it at up as down over into for from to of he his him she her back
is are be being been or no not nor and all through under until
these there the top
with here only has had both did faw few little most almost much off on out
also each were was too any very more within then
across before behind beneath beyond after again against around among
so such since because but yet however ever during
it its the this that what where how when who whoever which their them
you your will shall may might we us our
get got would could have
can't won't didn't don't
aiff arj arts asp au avi bin biz css cgi com doc edu exe firm gif gz gzip
htm html info jpeg jpg js jsp mp3 mpeg mpg mov
nom pdf php pl qt ra ram rec shop sit tar tgz tiff txt wav web zip
one two three four five six seven eight nine ten eleven twelve
ftp http https www web net org or kr co us de
EOF;
        $page = $DBInfo->getPage($pagename);
        if (!$page->exists()) {
            return '';
        }
        $raw = $page->get_raw_body();
        $raw = rtrim($raw);
        // strip macros, entities
        $raw = preg_replace("/&[^;\\s]+;|\\[\\[[^\\[]+\\]\\]/", ' ', $raw);
        $raw = preg_replace("/^##.*\$/m", ' ', $raw);
        $raw = preg_replace("/([;\"',`\\\\\\/\\.:@#\\!\\?\$%\\^&\\*\\(\\)\\{\\}\\[\\]\\-_\\+=\\|<>])/", ' ', strip_tags($raw . ' ' . $pagename));
        // pagename also
        $raw = preg_replace("/((?<=[a-z0-9]|[B-Z]{2})([A-Z][a-z]))/", " \\1", $raw);
        $raw = strtolower($raw);
        $raw = preg_replace("/\\b/", ' ', $raw);
        //$raw=preg_replace("/\b([0-9a-zA-Z'\"])\\1+\s*/",' ',$raw);
        $words = preg_split("/\\s+|\n/", $raw);
        // remove common words
        $common_word_page0 = LOCAL_KEYWORDS . '/CommonWords';
        $lines0 = array();
        if ($DBInfo->hasPage($common_word_page0)) {
            $p = $DBInfo->getPage($common_word_page0);
            $lines0 = explode("\n", $p->get_raw_body());
        }
        $lang = isset($formatter->pi['#language']) ? $formatter->pi['#language'] : $DBInfo->default_language;
        if ($lang and in_array($lang, $supported_lang)) {
            $common_word_page = LOCAL_KEYWORDS . '/CommonWords' . ucfirst($lang);
            if ($DBInfo->hasPage($common_word_page)) {
                $p = $DBInfo->getPage($common_word_page);
                $lines = explode("\n", $p->get_raw_body());
                $lines = array_merge($lines, $lines0);
                foreach ($lines as $line) {
                    if (isset($line[0]) and $line[0] == '#') {
                        continue;
                    }
                    $common .= "\n" . $line;
                }
                $common = rtrim($common);
            }
        }
        $words = array_diff($words, preg_split("/\\s+|\n/", $common));
        while (!empty($DBInfo->use_stemmer)) {
            include_once dirname(__FILE__) . '/../lib/stemmer.ko.php';
            include_once dirname(__FILE__) . '/../lib/stemmer.php';
            $indexer = new KoreanStemmer();
            if (!is_resource($indexer->_dict)) {
                break;
            }
            $founds = array();
            foreach ($words as $key) {
                if (preg_match('/^[a-zA-Z0-9]+$/', $key)) {
                    // ignore alphanumeric
                    $stem = PorterStemmer::Stem($key);
                    $founds[] = $stem;
                    continue;
                }
                $match = null;
                $stem = $indexer->getStem(trim($key), $match, $type);
                if (!empty($stem)) {
                    $founds[] = $stem;
                } else {
                    if (!empty($last)) {
                        //print_r($match);
                    }
                }
            }
            $words = $founds;
            $indexer->close();
            break;
        }
        $preword = '';
        $bigwords = array();
        foreach ($words as $word) {
            if (strlen($word) > 2 and strlen($preword) > 2) {
                if ($word == $preword) {
                    continue;
                }
                $key = $preword . ' ' . $word;
                $rkey = $word . ' ' . $preword;
                if (isset($bigwords[$key])) {
                    $bigwords[$key]++;
                } else {
                    if (isset($bigwords[$rkey])) {
                        $bigwords[$rkey]++;
                    } else {
                        $bigwords[$key] = 1;
                    }
                }
            }
            $preword = $word;
        }
        $words = array_count_values($words);
        unset($words['']);
        $ncount = array_sum($words);
        // total count
        /*   
            $words=array_diff(array_keys($counts),preg_split("/\s+|\n/",$common));
        
            if (function_exists('array_intersect_key')) {
                $words=array_intersect_key($counts,$words);
            } else {
                $ret = array();
                foreach($words as $key) {
                    if(array_key_exists($key, $counts))
                        $ret[$key] = $counts[$key];
                }
                $words=&$ret;
            }
        */
        if ($bigwords) {
            //
            $bigwords = array_filter($bigwords, create_function('$a', 'return ($a != 1);'));
            foreach ($bigwords as $k => $v) {
                $words["{$k}"] = $v;
            }
        }
        arsort($words);
        $max = current($words);
        // get max hit number
        $nwords = array();
        if (isset($options['merge'])) {
            foreach ($mykeys as $key) {
                $nwords[$key] = $max;
                // give weight to all selected keywords
            }
        }
        if ($nwords) {
            foreach ($nwords as $k => $v) {
                $words[$k] = $v;
            }
        }
        $use_sty = 1;
    }
    //
    if (!empty($options['call'])) {
        return $words;
    }
    if ($limit and ($sz = sizeof($words)) > $limit) {
        arsort($words);
        $mywords = array_keys($words);
        $mywords = array_slice($mywords, 0, $limit);
        $nwords = array();
        foreach ($mywords as $k) {
            $nwords[$k] = $words[$k];
        }
        $words =& $nwords;
    }
    // make criteria list
    $fz = 0;
    $min = 0;
    $sty = array();
    if (!empty($use_sty)) {
        $fact = array();
        $weight = $max;
        // $ncount
        #print 'max='.$max.' ratio='.$weight/$ncount.':';
        $test = array(0.8, 0.6, 0.4, 0.5, 0.5, 0.5);
        // six level
        for ($i = 0; $i < 6 and $weight > 0; $i++) {
            $weight = (int) ($weight * $test[$i]);
            if ($weight > 0) {
                $fact[] = $weight;
            }
            #print $weight.'--';
        }
        $max = current($fact);
        $min = $limit ? max(1, end($fact)) - 1 : 0;
        // XXX
        // make font-size style
        $fz = max(sizeof($fact), 2);
        $fsh = (MAX_FONT_SZ - MIN_FONT_SZ) / ($fz - 1);
        $fs = MAX_FONT_SZ;
        // max font-size:24px;
        for ($i = 0; $i < $fz; $i++) {
            $ifs = (int) ($fs + 0.5);
            $sty[] = " style='font-size:{$ifs}px;'";
            #print '/'.$ifs;
            $fs -= $fsh;
            $fs = max($fs, 9);
            // min font-size:9px
        }
    }
    if (empty($sort) or $sort != 'freq') {
        ksort($words);
    }
    $link = $formatter->link_url(_rawurlencode($pagename), '');
    if (!isset($tag_link)) {
        if (empty($search)) {
            $search = 'fullsearch&amp;keywords=1';
        }
        if (!empty($options['tour'])) {
            $search = 'tour&amp;arena=keylinks';
        }
        $tag_link = $formatter->link_url(_rawurlencode($pagename), '?action=' . $search . '&amp;value=$TAG');
    }
    $out = '';
    if (!empty($options['add'])) {
        $out = "<form method='post' action='{$link}'>\n";
        $out .= "<input type='hidden' name='action' value='keywords' />\n";
    }
    if (isset($options['cloud'])) {
        $out = '';
        foreach ($words as $key => $val) {
            $style = $sty[$fz - 1];
            for ($i = 0; $i < $fz; $i++) {
                if ($val > $fact[$i]) {
                    $style = $sty[$i];
                    break;
                }
            }
            if ($val > $min) {
                $out .= "<a href='" . qualifiedUrl(str_replace('$TAG', $key, $tag_link)) . "'";
                if ($use_sty) {
                    $out .= ' ' . $style;
                } else {
                    $out .= " style='12'";
                }
                $out .= ">" . $key . "</a>";
            }
        }
        $out = preg_replace('/&amp;/', urlencode('&'), $out);
        $tout = "<a href='http://www.roytanck.com/tag1' style='font-size:20px'>Tag name</a><a href='http://www.roytanck.com/tag2' style='font-size:10px'>Tag two</a>";
        $formatter->register_javascripts(array('js/swfobject.js'));
        $_swf_prefix = qualifiedUrl("{$DBInfo->url_prefix}/local/wp-cumulus");
        // FIXME
        return <<<SWF
<script type="text/javascript">
var flashvars = {
   mode : "tags",
   distr : "true",
   tcolor : "0xffffff",
   tcolor2 : "0x86B9F2",
   hicolor : "0xBAD8F8",
   tagcloud : "<tags>{$out}</tags>"
};

var params = {
   wmode: "opaque",
   bgcolor: "#333333"
};

var attrs = {
   id: "myCloudContent"
};

swfobject.embedSWF("{$_swf_prefix}/tagcloud.swf", "myCloud", "200", "200", "9.0.0","expressInstall.swf", flashvars, params, attrs);
</script>
<div id="myCloud">
</div>
SWF;
    }
    $out .= '<ul>';
    $checkbox = '';
    foreach ($words as $key => $val) {
        $style = '';
        if ($fz > 0) {
            $style = $sty[$fz - 1];
            for ($i = 0; $i < $fz; $i++) {
                if ($val > $fact[$i]) {
                    $style = $sty[$i];
                    break;
                }
            }
        }
        if ($val > $min) {
            $checked = '';
            if ($val >= $max) {
                $checked = 'checked="checked"';
                $ok = 1;
            }
            if (!empty($options['add'])) {
                $checkbox = "<input type='checkbox' {$checked} name='key[]' " . "value='{$key}' />";
            }
            $out .= " <li class=\"tag-item\"";
            if (!empty($use_sty)) {
                $out .= " {$style} title=\"{$val} " . _("hits") . '"';
            }
            $out .= ">{$checkbox}" . "<a href='" . str_replace('$TAG', $key, $tag_link) . "' rel='nofollow'>" . $key . "</a></li>\n";
        }
    }
    $inp = '';
    $form_close = '';
    if (!empty($options['add'])) {
        $msg = _("add keywords");
        $inp = "<li><input type='text' name='keywords' size='12' />: {$msg}</li>";
        if ($ok) {
            $btn = _("Update keywords");
        } else {
            $btn = _("Add keywords");
        }
        $btn1 = _("Add as common words");
        $btn2 = _("Unselect all");
        $btnc = _("Suggest new Keywords");
        $form_close = "<input type='submit' value='{$btn}'/>\n";
        $form_close .= "<input type='submit' name='suggest' value='{$btnc}' />\n";
        $form_close .= "<input type='submit' name='common' value='{$btn1}' />\n";
        $form_close .= "<input type='button' value='{$btn2}' onClick='UncheckAll(this)' />\n";
        $form_close .= "<select name='lang'><option>---</option>\n";
        foreach ($supported_lang as $l) {
            $form_close .= "<option value='{$l}'>{$l}</option>\n";
        }
        $langmsg = _("select language");
        $form_close .= "</select>: {$langmsg}\n</form>\n";
        $form_close .= <<<EOF
<script type='text/javascript' src='{$DBInfo->url_prefix}/local/checkbox.js'>
</script>
EOF;
    }
    return "<div class='cloudView'>" . $out . "{$inp}</ul></div>{$form_close}";
}
예제 #3
0
파일: rss.php 프로젝트: ahastudio/moniwiki
function macro_Rss($formatter, $value)
{
    global $DBInfo;
    $rsscache = new Cache_text('rsscache');
    $key = _rawurlencode($value);
    // rss TTL = 7200 sec (60*60*2)
    if (!$formatter->refresh && $rsscache->exists($key) && time() < $rsscache->mtime($key) + 7200) {
        return $rsscache->fetch($key);
    }
    if ($rsscache->exists($key . '.lock')) {
        return '';
    }
    $args = explode(',', $value);
    // first arg assumed to be a date fmt arg
    $date_fmt = '';
    $title_width = 0;
    if (count($args) > 1) {
        if (preg_match("/^[\\s\\/\\-:aABdDFgGhHiIjmMOrSTY\\[\\]]+\$/", $args[0])) {
            $date_fmt = array_shift($args);
        }
        if (is_numeric($args[0])) {
            $title_width = array_shift($args);
            // too small or too big
            if ($title_width < 10 || $title_width > 40) {
                $title_width = 0;
            }
        }
        $value = implode(',', $args);
    }
    $cache = new Cache_text("rssxml");
    # reflash rss each 7200 second (60*60*2)
    if (!$cache->exists($key) or time() > $cache->mtime($key) + 7200) {
        $fp = @fopen("{$value}", "r");
        if (!$fp) {
            return "[[RSS(ERR: not a valid URL! {$value})]]";
        }
        while ($data = fread($fp, 4096)) {
            $xml_data .= $data;
        }
        fclose($fp);
        $cache->update($key, $xml_data);
    } else {
        $xml_data = $cache->fetch($key);
    }
    // detect charset
    $charset = 'UTF-8';
    list($line, $dummy) = explode("\n", $xml_data, 2);
    preg_match("/\\sencoding=?(\"|')([^'\"]+)/", $line, $match);
    if ($match) {
        $charset = strtoupper($match[2]);
    }
    // override $charset for php5
    if ((int) phpversion() >= 5) {
        $charset = 'UTF-8';
    }
    $xml_parser = xml_parser_create();
    $rss_parser = new WikiRSSParser($charset);
    if (!empty($date_fmt)) {
        $rss_parser->setDateFormat($date_fmt);
    }
    if (!empty($title_width)) {
        $rss_parser->setTitleWidth($title_width);
    }
    xml_set_object($xml_parser, $rss_parser);
    xml_set_element_handler($xml_parser, "startElement", "endElement");
    xml_set_character_data_handler($xml_parser, "characterData");
    ob_start();
    $ret = xml_parse($xml_parser, $xml_data);
    if (!$ret) {
        return sprintf("[[RSS(XML error: %s at line %d)]]", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser));
    }
    $out = ob_get_contents();
    ob_end_clean();
    xml_parser_free($xml_parser);
    $out = '<ul class="rss">' . $out . '</ul>';
    #  if (strtolower(str_replace("-","",$options['oe'])) == 'euckr')
    if (function_exists('iconv') and strtoupper($DBInfo->charset) != $charset) {
        $new = iconv($charset, $DBInfo->charset, $out);
        if ($new !== false) {
            return $new;
        }
    }
    $rsscache->remove($key . '.lock');
    $rsscache->update($key, $out);
    return $out;
}
예제 #4
0
function macro_Fetch($formatter, $url = '', $params = array())
{
    global $DBInfo;
    if (empty($url)) {
        $params['retval']['error'] = _("Empty URL");
        return false;
    }
    // check valid url
    if (!preg_match('@^((ftp|https?)://[^/]+)/@', $url, $m)) {
        return false;
    }
    $siteurl = $m[1];
    require_once "lib/HTTPClient.php";
    $sz = 0;
    $allowed = 'png|jpeg|jpg|gif';
    if (!empty($DBInfo->fetch_exts)) {
        $allowed = $DBInfo->fetch_exts;
    }
    // urlencode()
    $url = _urlencode($url);
    // set default params
    $maxage = !empty($DBInfo->fetch_maxage) ? (int) $DBInfo->fetch_maxage : 60 * 60 * 24 * 7;
    $timeout = !empty($DBInfo->fetch_timeout) ? (int) $DBInfo->fetch_timeout : 15;
    $vartmp_dir = $DBInfo->vartmp_dir;
    $buffer_size = 2048 * 1024;
    // default buffer size
    if (!empty($DBInfo->fetch_buffer_size) and $DBInfo->fetch_buffer_size > 2048 * 1024) {
        $buffer_size = $DBInfo->fetch_buffer_size;
    }
    // set referrer
    $referer = '';
    if (!empty($DBInfo->fetch_referer_re)) {
        foreach ($DBInfo->fetch_referer_re as $re => $ref) {
            if (preg_match($re, $url)) {
                $referer = $ref;
                break;
            }
        }
    }
    // default referrer
    if (empty($referer) and !empty($DBInfo->fetch_referer)) {
        $referer = $DBInfo->fetch_referer;
    }
    // check site available
    $si = new Cache_text('siteinfo');
    if ($si->exists($siteurl)) {
        if (!empty($params['refresh'])) {
            $si->remove($siteurl);
        } else {
            if (empty($params['refresh']) && ($check = $si->fetch($siteurl)) !== false) {
                $params['retval']['status'] = $check['status'];
                $params['retval']['error'] = $check['error'];
                return false;
            }
        }
    }
    $sc = new Cache_text('fetchinfo');
    $error = null;
    if (empty($params['refresh']) and $sc->exists($url) and $sc->mtime($url) < time() + $maxage) {
        $info = $sc->fetch($url);
        $sz = $info['size'];
        $mimetype = $info['mimetype'];
        $error = !empty($info['error']) ? $info['error'] : null;
        // already retrived and found some error
        if (empty($params['refresh']) and !empty($error)) {
            $params['retval']['status'] = $info['status'];
            $params['retval']['error'] = $error;
            $params['retval']['mimetype'] = $mimetype;
            $params['retval']['size'] = $sz;
            return false;
        }
    } else {
        // check connection
        $http = new HTTPClient();
        // get file header
        $http->nobody = true;
        $http->referer = $referer;
        $http->sendRequest($url, array(), 'GET');
        //if ($http->status == 301 || $http->status == 302 ) {
        //
        //}
        if ($http->status != 200) {
            if ($http->status == 404) {
                $params['retval']['error'] = '404 File Not Found';
            } else {
                $params['retval']['error'] = !empty($http->error) ? $http->error : sprintf(_("Invalid Status %d"), $http->status);
            }
            $params['retval']['status'] = $http->status;
            // check alive site
            if ($http->status == -210) {
                $si->update($siteurl, array('status' => $http->status, 'error' => $params['retval']['error']), 60 * 60 * 24);
                return false;
            }
            $sc->update($url, array('size' => -1, 'mimetype' => '', 'error' => $params['retval']['error'], 'status' => $params['retval']['status']), 60 * 60 * 24 * 3);
            return false;
        }
        if (isset($http->resp_headers['content-length'])) {
            $sz = $http->resp_headers['content-length'];
        }
        if (isset($http->resp_headers['content-type'])) {
            $mimetype = $http->resp_headers['content-type'];
        } else {
            $mimetype = 'application/octet-stream';
        }
        $sc->update($url, array('size' => $sz, 'mimetype' => $mimetype));
    }
    // size info
    if (is_numeric($sz)) {
        $unit = array('Bytes', 'KB', 'MB', 'GB');
        $tmp = $sz;
        for ($i = 0; $i < 4; $i++) {
            if ($tmp <= 1024) {
                break;
            }
            $tmp = $tmp / 1024;
        }
        $hsz = round($tmp, 2) . ' ' . $unit[$i];
        if (empty($buffer_size) && !empty($DBInfo->fetch_max_size) and $sz > $DBInfo->fetch_max_size) {
            $params['retval']['error'] = sprintf(_("Too big file size (%s). Please contact WikiMasters to increase \$fetch_max_size"), $hsz);
            $params['retval']['mimetype'] = $mimetype;
            return false;
        }
    } else {
        $params['retval']['error'] = _("Can't get file size info");
        $params['retval']['mimetype'] = $mimetype;
        return false;
    }
    $is_image = false;
    if (preg_match('/^image\\/(jpe?g|gif|png)$/', $mimetype, $m)) {
        $ext = isset($m[1]) ? '.' . $m[1] : '';
        $is_image = true;
    } else {
        $ext = '.' . get_extension('data/mime.types', $mimetype);
    }
    if (!empty($DBInfo->fetch_images_only) and !$is_image) {
        // always check the content-type
        $params['retval']['error'] = sprintf(_("Invalid mime-type %s"), $mimetype);
        $params['retval']['mimetype'] = $mimetype;
        return false;
    }
    if (empty($params['call'])) {
        if ($is_image) {
            $img_url = $formatter->link_url('', '?action=fetch&amp;url=' . $url);
            return '<div class="externalImage"><div><img src="' . $img_url . '">' . '<div><a href="' . $url . '"><span>[' . strtoupper($m[1]) . ' ' . _("external image") . ' (' . $hsz . ')' . ']</span></a></div></div>';
        }
        return $formatter->link_to('?action=fetch&amp;url=' . $url, $mimetype . ' (' . $hsz . ')');
    }
    // cache dir/filename/cache url
    if (!empty($DBInfo->cache_public_dir) and !empty($DBInfo->cache_public_url)) {
        $fc = new Cache_text('fetchfile', array('dir' => $DBInfo->cache_public_dir));
        $fetchname = $fc->getKey($url);
        $fetchfile = $DBInfo->cache_public_dir . '/' . $fetchname . $ext;
        $fetch_url = $DBInfo->cache_public_url . '/' . $fetchname . $ext;
    } else {
        $fc = new Cache_text('fetchfile');
        $fetchname = $fc->getKey($url);
        $fetchfile = $fc->cache_dir . '/' . $fetchname;
        $fetch_url = null;
    }
    // real fetch job.
    if (!empty($params['refresh']) or !file_exists($fetchfile)) {
        $fp = fopen($fetchfile, 'w');
        if (!is_resource($fp)) {
            $params['retval']['error'] = sprintf(_("Fail to open %s"), $fetchfile);
            return false;
        }
        // retry to get all info
        $http = new HTTPClient();
        if (!empty($buffer_size)) {
            $http->max_buffer_size = $buffer_size;
        }
        $http->vartmp_dir = $vartmp_dir;
        $save = ini_get('max_execution_time');
        set_time_limit(0);
        $http->timeout = $timeout;
        $http->referer = $referer;
        $http->sendRequest($url, array(), 'GET');
        set_time_limit($save);
        if ($http->status != 200) {
            fclose($fp);
            unlink($fetchfile);
            // Error found! save error status to the info cache
            $params['retval']['status'] = $http->status;
            $params['retval']['error'] = $http->error;
            $params['retval']['mimetype'] = $mimetype;
            $params['retval']['size'] = $sz;
            $sc->update($url, array('size' => $sz, 'mimetype' => $mimetype, 'error' => $http->error, 'status' => $params['retval']['status']));
            return false;
        }
        if (!empty($http->resp_body)) {
            fwrite($fp, $http->resp_body);
            fclose($fp);
        } else {
            fclose($fp);
            if (!empty($http->resp_body_file) && file_exists($http->resp_body_file)) {
                copy($http->resp_body_file, $fetchfile);
                unlink($http->resp_body_file);
            }
        }
        // update error status.
        if (!empty($error)) {
            $sc->update($url, array('size' => $sz, 'mimetype' => $mimetype));
        }
    }
    if (!empty($fetch_url) and !empty($DBInfo->fetch_use_cache_url)) {
        $formatter->send_header(array('Status: 302', 'Location: ' . $fetch_url));
        return null;
    }
    if (!empty($params['thumbwidth'])) {
        // check allowed thumb widths.
        $thumb_widths = isset($DBInfo->thumb_widths) ? $DBInfo->thumb_widths : array('120', '240', '320', '480', '600', '800', '1024');
        $width = 320;
        // default
        if (!empty($DBInfo->default_thumb_width)) {
            $width = $DBInfo->default_thumb_width;
        }
        if (!empty($thumb_widths)) {
            if (in_array($params['thumbwidth'], $thumb_widths)) {
                $width = $params['thumbwidth'];
            } else {
                header("HTTP/1.1 404 Not Found");
                echo "Invalid thumbnail width", "<br />", "valid thumb widths are ", implode(', ', $thumb_widths);
                return;
            }
        } else {
            $width = $params['thumbwidth'];
        }
        $thumb_width = $width;
        $force_thumb = true;
    } else {
        // automatically generate thumb images to support low-bandwidth mobile version
        if (is_mobile()) {
            $force_thumb = (!isset($params['m']) or $params['m'] == 1);
        }
    }
    // generate thumb file to support low-bandwidth mobile version
    $thumbfile = '';
    while ((!empty($params['thumb']) or $force_thumb) and preg_match('/^image\\/(jpe?g|gif|png)$/', $mimetype)) {
        if (empty($thumb_width)) {
            $thumb_width = 320;
            // default
            if (!empty($DBInfo->fetch_thumb_width)) {
                $thumb_width = $DBInfo->fetch_thumb_width;
            }
        }
        $thumbfile = preg_replace('@' . $ext . '$@', '.w' . $thumb_width . $ext, $fetchfile);
        if (empty($params['refresh']) && file_exists($thumbfile)) {
            break;
        }
        list($w, $h) = getimagesize($fetchfile);
        if ($w <= $thumb_width) {
            $thumbfile = $fetchfile;
            break;
        }
        require_once 'lib/mediautils.php';
        // generate thumbnail using the gd func or the ImageMagick(convert)
        resize_image($ext, $fetchfile, $thumbfile, $w, $h, $thumb_width);
        break;
    }
    $down_mode = 'inline';
    if (!empty($thumbfile)) {
        $fetchfile = $thumbfile;
    }
    header("Content-Type: {$mimetype}\r\n");
    header("Content-Length: " . filesize($fetchfile));
    //header("Content-Disposition: $down_mode; ".$fname );
    header("Content-Description: MoniWiki PHP Fetch Downloader");
    $mtime = filemtime($fetchfile);
    $lastmod = gmdate("D, d M Y H:i:s", $mtime) . ' GMT';
    $etag = md5($lastmod . $url . $thumbfile);
    header("Last-Modified: " . $lastmod);
    header('ETag: "' . $etag . '"');
    header("Pragma:");
    header('Cache-Control: public, max-age=' . $maxage);
    $need = http_need_cond_request($mtime, $lastmod, $etag);
    if (!$need) {
        header('X-Cache-Debug: Cached OK');
        header('HTTP/1.0 304 Not Modified');
        @ob_end_clean();
        return null;
    }
    @ob_clean();
    $ret = readfile($fetchfile);
    return null;
}
예제 #5
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;
}
예제 #6
0
function processor_xsltproc($formatter, $value)
{
    global $DBInfo;
    $xsltproc = "xsltproc ";
    if ($value[0] == '#' and $value[1] == '!') {
        list($line, $value) = explode("\n", $value, 2);
        # get parameters
        list($tag, $args) = explode(" ", $line, 2);
    }
    $pagename = $formatter->page->name;
    $vartmp_dir =& $DBInfo->vartmp_dir;
    $cache = new Cache_text("docbook");
    if (empty($formatter->preview) and empty($formatter->refresh) and $cache->exists($pagename) and $cache->mtime($pagename) > $formatter->page->mtime()) {
        return $cache->fetch($pagename);
    }
    list($line, $body) = explode("\n", $value, 2);
    $buff = "";
    while ($line[0] == '<' and $line[1] == '?' or !$line) {
        preg_match("/^<\\?xml-stylesheet\\s+href=\"([^\"]+)\"/", $line, $match);
        if ($match) {
            if ($DBInfo->hasPage($match[1])) {
                $line = '<?xml-stylesheet href="' . getcwd() . '/' . $DBInfo->text_dir . '/' . $match[1] . '" type="text/xml"?>';
            }
            $flag = 1;
        }
        $buff .= $line . "\n";
        list($line, $body) = explode("\n", $body, 2);
        if (!empty($flag)) {
            break;
        }
    }
    $src = $buff . $line . "\n" . $body;
    $tmpf = tempnam($vartmp_dir, "XSLT");
    $fp = fopen($tmpf, "w");
    fwrite($fp, $src);
    fclose($fp);
    $cmd = "{$xsltproc} --xinclude {$tmpf}";
    $fp = popen($cmd . $formatter->NULL, "r");
    #fwrite($fp,$src);
    $html = '';
    if (is_resource($fp)) {
        while ($s = fgets($fp, 1024)) {
            $html .= $s;
        }
        pclose($fp);
    }
    unlink($tmpf);
    if (empty($html)) {
        $src = str_replace("<", "&lt;", $value);
        $cache->remove($pagename);
        return "<pre class='code'>{$src}\n</pre>\n";
    }
    if (function_exists("iconv") and strtoupper($DBInfo->charset) != 'UTF-8') {
        $new = iconv('UTF-8', $DBInfo->charset, $html);
        if ($new) {
            $html = $new;
        }
    }
    if (empty($formatter->preview)) {
        $cache->update($pagename, $html);
    }
    return $html;
}
예제 #7
0
파일: wiki.php 프로젝트: sedrion/moniwiki
 function cache_instructions($pi, $params = array())
 {
     global $Config;
     global $DBInfo;
     $pagename = $this->name;
     // update aliases
     if (!empty($Config['use_alias'])) {
         $ac = new Cache_text('alias');
         // is it removed ?
         if ($ac->exists($pagename) and empty($pi['#alias']) and empty($pi['#title'])) {
             // remove aliases
             store_aliases($pagename, array());
         } else {
             if (!$ac->exists($pagename) or $ac->mtime($pagename) < $this->mtime() or !empty($_GET['update_alias'])) {
                 $as = array();
                 // parse #alias
                 if (!empty($pi['#alias'])) {
                     $as = get_csv($pi['#alias']);
                 }
                 // add #title as a alias
                 if (!empty($pi['#title'])) {
                     $as[] = $pi['#title'];
                 }
                 // update aliases
                 store_aliases($pagename, $as);
             }
         }
     }
     // update redirects cache
     $redirect = isset($pi['#redirect'][0]) ? $pi['#redirect'] : null;
     update_redirects($pagename, $redirect, $params['refresh']);
     if (!empty($Config['use_keywords']) or !empty($Config['use_tagging']) or !empty($_GET['update_keywords'])) {
         $tcache = new Cache_text('keyword');
         $cache = new Cache_text('keywords');
         $cur = $tcache->fetch($pagename);
         if (empty($cur)) {
             $cur = array();
         }
         $keys = array();
         if (empty($pi['#keywords'])) {
             $tcache->remove($pagename);
         } else {
             $keys = explode(',', $pi['#keywords']);
             $keys = array_map('trim', $keys);
             if (!$tcache->exists($pagename) or $tcache->mtime($pagename) < $this->mtime() or !empty($_GET['update_keywords'])) {
                 $tcache->update($pagename, $keys);
             }
         }
         $adds = array_diff($keys, $cur);
         $dels = array_diff($cur, $keys);
         // merge new keywords
         foreach ($adds as $a) {
             if (!isset($a[0])) {
                 continue;
             }
             $l = $cache->fetch($a);
             if (!is_array($l)) {
                 $l = array();
             }
             $l = array_merge($l, array($pagename));
             $cache->update($a, $l);
         }
         // remove deleted keywords
         foreach ($dels as $d) {
             if (!isset($d[0])) {
                 continue;
             }
             $l = $cache->fetch($d);
             if (!is_array($l)) {
                 $l = array();
             }
             $l = array_diff($l, array($pagename));
             $cache->update($d, $l);
         }
     }
     if (!empty($pi['#title']) and !empty($Config['use_titlecache'])) {
         $tc = new Cache_text('title');
         $old = $tc->fetch($pagename);
         if (!isset($pi['#title'])) {
             $tc->remove($pagename);
         } else {
             if ($old != $pi['#title'] or !$tcache->exists($pagename) or !empty($_GET['update_title'])) {
                 $tc->update($pagename, $pi['#title']);
             }
         }
     }
     return;
 }
예제 #8
0
function macro_WordIndex($formatter, $value, $params = array())
{
    global $DBInfo;
    $pagelinks = $formatter->pagelinks;
    // save
    $save = $formatter->sister_on;
    $formatter->sister_on = 0;
    if (!empty($DBInfo->use_titlecache)) {
        $cache = new Cache_text('title');
    }
    $word_limit = 50;
    $start = 0;
    $prev = 0;
    if (!empty($params['start']) and is_numeric($params['start'])) {
        $start = $params['start'];
    }
    if (!empty($params['prev']) and is_numeric($params['prev'])) {
        $prev = $params['prev'];
    }
    $value = strval($value);
    if ($value == '' or $value == 'all') {
        $sel = '';
    } else {
        $sel = $value;
    }
    if (@preg_match('/' . $sel . '/i', '') === false) {
        $sel = '';
    }
    $keys = array();
    $dict = array();
    // cache wordindex
    $wc = new Cache_text('wordindex');
    $delay = !empty($DBInfo->default_delaytime) ? $DBInfo->default_delaytime : 0;
    $index_lock = 'wordindex.lock';
    $locked = $wc->exists($index_lock);
    if ($locked or $wc->exists('key') and $DBInfo->checkUpdated($wc->mtime('key'), $delay)) {
        if ($formatter->group) {
            $keys = $wc->fetch('key.' . $formatter->group);
            $dict = $wc->fetch('wordindex.' . $formatter->group);
        } else {
            $keys = $wc->fetch('key');
            $dict = $wc->fetch('wordindex');
        }
        if (empty($dict) and $locked) {
            // no cache found
            return _("Please wait...");
        }
    }
    if (empty($keys) or empty($dict)) {
        $wc->update($index_lock, array('dummy'), 30);
        // 30 sec
        $all_pages = array();
        if ($formatter->group) {
            $group_pages = $DBInfo->getLikePages($formatter->group);
            foreach ($group_pages as $page) {
                $all_pages[] = str_replace($formatter->group, '', $page);
            }
        } else {
            $all_pages = $DBInfo->getPageLists();
        }
        foreach ($all_pages as $page) {
            if (!empty($DBInfo->use_titlecache) and $cache->exists($page)) {
                $title = $cache->fetch($page);
            } else {
                $title = $page;
            }
            $tmp = preg_replace("/[\\?!\$%\\.\\^;&\\*()_\\+\\|\\[\\]<>\"' \\-~\\/:]/", " ", $title);
            $tmp = preg_replace("/((?<=[A-Za-z0-9])[A-Z][a-z0-9])/", " \\1", ucwords($tmp));
            $words = preg_split("/\\s+/", $tmp);
            foreach ($words as $word) {
                $word = ltrim($word);
                if (!$word) {
                    continue;
                }
                $key = get_key($word);
                $keys[$key] = $key;
                if (!empty($dict[$key][$word])) {
                    $dict[$key][$word][] = $page;
                } else {
                    if (empty($dict[$key])) {
                        $dict[$key] = array();
                    }
                    $dict[$key][$word] = array($page);
                }
            }
        }
        sort($keys);
        foreach ($keys as $k) {
            #ksort($dict[$k]);
            #ksort($dict[$k], SORT_STRING);
            #uksort($dict[$k], "strnatcasecmp");
            uksort($dict[$k], "strcasecmp");
        }
        if ($formatter->group) {
            $wc->update('key.' . $formatter->group, $keys);
            $wc->update('wordindex.' . $formatter->group, $dict);
        } else {
            $wc->update('key', $keys);
            $wc->update('wordindex', $dict);
        }
        $wc->remove($index_lock);
    }
    if (isset($sel[0]) and isset($dict[$sel])) {
        $selected = array($sel);
    } else {
        $selected =& $keys;
    }
    $out = '';
    $key = -1;
    $count = 0;
    $idx = 0;
    foreach ($selected as $k) {
        $words = array_keys($dict[$k]);
        $sz = count($words);
        for ($idx = $start; $idx < $sz; $idx++) {
            $word = $words[$idx];
            $pages =& $dict[$k][$word];
            $pkey = $k;
            if ($key != $pkey) {
                $key = $pkey;
                if (!empty($sel) and !preg_match('/^' . $sel . '/i', $pkey)) {
                    continue;
                }
                if (!empty($out)) {
                    $out .= "</ul>";
                }
                $ukey = urlencode($key);
                $out .= "<a name='{$ukey}'></a><h3><a href='#top'>{$key}</a></h3>\n";
            }
            if (!empty($sel) and !preg_match('/^' . $sel . '/i', $pkey)) {
                continue;
            }
            $out .= "<h4>{$word}</h4>\n";
            $out .= "<ul>\n";
            foreach ($pages as $page) {
                $out .= '<li>' . $formatter->word_repl('"' . $page . '"') . "</li>\n";
            }
            $out .= "</ul>\n";
            $count++;
            if ($count >= $word_limit) {
                break;
            }
        }
    }
    if (isset($sel[0])) {
        $last = count($dict[$sel]);
        $offset = $idx + 1;
        $pager = array();
        if ($start > 0) {
            // get previous start offset.
            $count = 0;
            $idx -= $word_limit - 1;
            if ($idx < 0) {
                $idx = 0;
            }
            $link = $formatter->link_url($formatter->page->name, '?action=wordindex&amp;sec=' . $sel . '&amp;start=' . $idx);
            $pager[] = "<a href='{$link}'>" . _("&#171; Prev") . '</a>';
        }
        if ($offset < $last) {
            $link = $formatter->link_url($formatter->page->name, '?action=wordindex&amp;sec=' . $sel . '&amp;start=' . $offset);
            $pager[] = "<a href='{$link}'>" . _("Next &#187;") . '</a>';
        }
        if (!empty($pager)) {
            $out .= implode(' | ', $pager) . "<br />\n";
        }
    }
    $index = array();
    $tlink = '';
    if (isset($sel[0])) {
        $tlink = $formatter->link_url($formatter->page->name, '?action=wordindex&amp;sec=');
    }
    foreach ($keys as $key) {
        $name = strval($key);
        if ($key == 'Others') {
            $name = _("Others");
        }
        $ukey = urlencode($key);
        $link = !empty($tlink) ? preg_replace('/sec=/', 'sec=' . _urlencode($key), $tlink) : '';
        $index[] = "<a href='{$link}#{$ukey}'>{$name}</a>";
    }
    $str = implode(' | ', $index);
    $formatter->pagelinks = $pagelinks;
    // restore
    $formatter->sister_on = $save;
    return "<center><a name='top'></a>{$str}</center>\n{$out}";
}
예제 #9
0
파일: pull.php 프로젝트: reviforks/moniwiki
function macro_Pull($formatter, $pagename = '', $params = array())
{
    global $DBInfo;
    if (empty($pagename)) {
        $params['retval']['error'] = _("Empty PageName");
        return false;
    }
    if (empty($DBInfo->pull_url)) {
        $params['retval']['error'] = _("Empty \$pull_url");
        return false;
    }
    if (strpos($DBInfo->pull_url, '$PAGE') === false) {
        $url = $DBInfo->pull_url . _rawurlencode($pagename);
    } else {
        $url = preg_replace('/\\$PAGE/', _rawurlencode($pagename), $DBInfo->pull_url);
    }
    $url .= '?action=raw';
    require_once "lib/HTTPClient.php";
    $sz = 0;
    // set default params
    $maxage = !empty($DBInfo->pull_maxage) ? (int) $DBInfo->pull_maxage : 60 * 60 * 24 * 7;
    $timeout = !empty($DBInfo->pull_timeout) ? (int) $DBInfo->pull_timeout : 15;
    $maxage = (int) $maxage;
    // check connection
    $http = new HTTPClient();
    $sc = new Cache_text('mirrorinfo');
    $error = null;
    $headers = array();
    while ($sc->exists($pagename) and time() < $sc->mtime($pagename) + $maxage) {
        $info = $sc->fetch($pagename);
        if ($info == false) {
            break;
        }
        $sz = $info['size'];
        $etag = $info['etag'];
        $lastmod = $info['last-modified'];
        $error = !empty($info['error']) ? $info['error'] : null;
        // already retrived and found some error
        if (empty($params['refresh']) and !empty($error)) {
            return false;
        }
        // conditional get
        $headers['Cache-Control'] = 'maxage=0';
        $headers['If-Modified-Since'] = $lastmod;
        if (empty($DBInfo->pull_no_etag)) {
            $headers['If-None-Match'] = $etag;
        }
        // do not refresh for no error cases
        if (empty($error)) {
            unset($params['refresh']);
        }
        break;
    }
    // get file header
    $http->nobody = true;
    if (!empty($headers)) {
        $http->headers = array_merge($http->headers, $headers);
    }
    $http->sendRequest($url, array(), 'GET');
    if ($http->status == 304) {
        // not modified
        $params['retval']['status'] = 304;
        return true;
    }
    if ($http->status != 200) {
        $params['retval']['error'] = sprintf(_("Invalid Status %d"), $http->status);
        $params['retval']['status'] = $http->status;
        return false;
    } else {
        if (!empty($params['check'])) {
            $params['retval']['status'] = 200;
            return true;
        }
    }
    if (isset($http->resp_headers['content-length'])) {
        $sz = $http->resp_headers['content-length'];
    }
    $etag = '';
    $lastmod = '';
    if (isset($http->resp_headers['etag'])) {
        $etag = $http->resp_headers['etag'];
    }
    if (isset($http->resp_headers['last-modified'])) {
        $lastmod = $http->resp_headers['last-modified'];
    }
    $sc->update($pagename, array('size' => $sz, 'etag' => $etag, 'last-modified' => $lastmod));
    // size info
    if (is_numeric($sz)) {
        $unit = array('Bytes', 'KB', 'MB', 'GB');
        $tmp = $sz;
        for ($i = 0; $i < 4; $i++) {
            if ($tmp <= 1024) {
                break;
            }
            $tmp = $tmp / 1024;
        }
        $hsz = round($tmp, 2) . ' ' . $unit[$i];
    } else {
        $params['retval']['error'] = _("Can't get file size info");
        $params['retval']['mimetype'] = $mimetype;
        return false;
    }
    $pagefile = $DBInfo->getPageKey($pagename);
    $mtime = @strtotime($lastmod);
    $my_mtime = $formatter->page->mtime();
    // not exactly same file.
    if ($my_mtime != $mtime or abs($mtime - $my_mtime) > 60) {
        $params['refresh'] = 1;
    }
    // force refresh
    // real fetch job.
    if (!empty($params['refresh']) or !file_exists($pagefile)) {
        @unlink($pagefile);
        $fp = fopen($pagefile, 'w');
        if (!is_resource($fp)) {
            $params['retval']['error'] = sprintf(_("Fail to open %s"), $pagefile);
            return false;
        }
        // retry to get all info
        $http = new HTTPClient();
        $save = ini_get('max_execution_time');
        set_time_limit(0);
        $http->timeout = $timeout;
        $http->sendRequest($url, array(), 'GET');
        set_time_limit($save);
        if ($http->status != 200) {
            fclose($fp);
            unlink($pagefile);
            // Error found! save error status to the info cache
            $params['retval']['error'] = !empty($http->error) ? $http->error : sprintf(_("Invalid Status %d"), $http->status);
            $params['retval']['status'] = $http->status;
            $params['retval']['etag'] = $etag;
            $params['retval']['last-modified'] = $lastmod;
            $params['retval']['size'] = $sz;
            $sc->update($pagename, array('size' => $sz, 'etag' => $mimetype, 'last-modified' => $lastmod, 'error' => $http->error, 'status' => $params['retval']['status']));
            return false;
        }
        if (!empty($http->resp_body)) {
            fwrite($fp, $http->resp_body);
        }
        fclose($fp);
        //$mtime = @strtotime($lastmod);
        //touch($pagefile, $mtime);
        // remove PI cache to update
        $pi = new Cache_text('PI');
        $pi->remove($formatter->page->name);
        // update error status.
        if (!empty($error)) {
            $sc->update($pagename, array('size' => $sz, 'etag' => $etag, 'last-modified' => $lastmod));
        }
        $loc = $formatter->link_url($pagename);
        $loc = preg_replace('/&amp;/', '&', $loc);
        $formatter->send_header(array('Status: 302', 'Location: ' . $loc), $params);
        echo 'Successfully fetched';
    } else {
        echo 'Not modified';
    }
    return null;
}
예제 #10
0
파일: wiki.php 프로젝트: reviforks/moniwiki
 function cache_instructions($pi, $params = array())
 {
     global $Config;
     global $DBInfo;
     $pagename = $this->name;
     // update aliases
     if (!empty($Config['use_alias'])) {
         $ac = new Cache_text('alias');
         // is it removed ?
         if ($ac->exists($pagename) and empty($pi['#alias']) and empty($pi['#title'])) {
             // remove aliases
             store_aliases($pagename, array());
         } else {
             if (!$ac->exists($pagename) or $ac->mtime($pagename) < $this->mtime() or !empty($_GET['update_alias'])) {
                 $as = array();
                 // parse #alias
                 if (!empty($pi['#alias'])) {
                     $as = get_csv($pi['#alias']);
                 }
                 // add #title as a alias
                 if (!empty($pi['#title'])) {
                     $as[] = $pi['#title'];
                 }
                 // update aliases
                 store_aliases($pagename, $as);
             }
         }
     }
     // update #redirect
     $rc = new Cache_Text('redirect');
     $old = $rc->fetch($pagename);
     if ($old or isset($pi['#redirect'][0])) {
         // update invert redirect index
         $rc2 = new Cache_Text('redirects');
         if (!empty($params['refresh']) or $old != $pi['#redirect']) {
             // update direct cache
             $rc->update($pagename, $pi['#redirect']);
             $nr = $pi['#redirect'];
             if (($p = strpos($nr, '#')) > 0) {
                 // get pagename only
                 //$anchor = substr($nr, $p);
                 $nr = substr($nr, 0, $p);
             }
             if (!isset($nr[0])) {
                 $rc->remove($pagename);
             } else {
                 if (!preg_match('@^https?://@', $nr)) {
                     // not a URL redirect
                     // add redirect links
                     $redirects = $rc2->fetch($nr);
                     if (empty($redirects)) {
                         $redirects = array();
                     }
                     $redirects = array_merge($redirects, array($pagename));
                     $rc2->update($nr, $redirects);
                 }
             }
             while ($old != '' and $old != false) {
                 // get pagename only
                 if (($p = strpos($old, '#')) > 0) {
                     //$anchor = substr($old, $p);
                     $old = substr($old, 0, $p);
                 }
                 if ($nr == $old) {
                     break;
                 }
                 // check A#s-1 ~ A#s-2 redirects
                 // delete redirect links
                 $l = $rc2->fetch($old);
                 if ($l !== false and is_array($l)) {
                     $redirects = array_diff($l, array($pagename));
                     if (empty($redirects)) {
                         $rc2->remove($old);
                     } else {
                         $rc2->update($old, $redirects);
                     }
                 }
                 break;
             }
         }
     }
     if (!empty($Config['use_keywords']) or !empty($Config['use_tagging']) or !empty($_GET['update_keywords'])) {
         $tcache = new Cache_text('keyword');
         $cache = new Cache_text('keywords');
         $cur = $tcache->fetch($pagename);
         if (empty($cur)) {
             $cur = array();
         }
         $keys = array();
         if (empty($pi['#keywords'])) {
             $tcache->remove($pagename);
         } else {
             $keys = explode(',', $pi['#keywords']);
             $keys = array_map('trim', $keys);
             if (!$tcache->exists($pagename) or $tcache->mtime($pagename) < $this->mtime() or !empty($_GET['update_keywords'])) {
                 $tcache->update($pagename, $keys);
             }
         }
         $adds = array_diff($keys, $cur);
         $dels = array_diff($cur, $keys);
         // merge new keywords
         foreach ($adds as $a) {
             if (!isset($a[0])) {
                 continue;
             }
             $l = $cache->fetch($a);
             if (!is_array($l)) {
                 $l = array();
             }
             $l = array_merge($l, array($pagename));
             $cache->update($a, $l);
         }
         // remove deleted keywords
         foreach ($dels as $d) {
             if (!isset($d[0])) {
                 continue;
             }
             $l = $cache->fetch($d);
             if (!is_array($l)) {
                 $l = array();
             }
             $l = array_diff($l, array($pagename));
             $cache->update($d, $l);
         }
     }
     if (!empty($pi['#title']) and !empty($Config['use_titlecache'])) {
         $tc = new Cache_text('title');
         $old = $tc->fetch($pagename);
         if (!isset($pi['#title'])) {
             $tc->remove($pagename);
         } else {
             if ($old != $pi['#title'] or !$tcache->exists($pagename) or !empty($_GET['update_title'])) {
                 $tc->update($pagename, $pi['#title']);
             }
         }
     }
     return;
 }