function macro_Category($formatter, $value = '', $params = array()) { if (!isset($formatter->categories)) { $formatter->categories = array(); } if (isset($value[0])) { // add a backlink $tmp = $formatter->word_repl('[[' . $value . ']]'); // is it a category link if (preg_match('@' . $formatter->category_regex . '@', $value)) { $formatter->categories[] = $value; return '<span></span>'; } // not a category link return $tmp; } $cc = new Cache_Text('categories'); if (count($formatter->categories) > 0) { if (!$formatter->preview) { $cc->update($formatter->page->name, $formatter->categories); } $categories = $formatter->categories; } else { if ($formatter->page->exists()) { $categories = $cc->fetch($formatter->page->name); } else { $cc->remove($formatter->page->name); $categories = array(); } } if (!empty($params['call']) || !empty($params['.call'])) { return $categories; } if (empty($categories)) { return ''; } $out = '<div class="wikiCategory">'; $out .= '<h2>' . _("Category") . '</h2>'; $out .= '<ul>'; foreach ($categories as $cat) { if (preg_match('@' . $formatter->category_regex . '@', $cat, $m)) { // strip category prefix if (isset($m[1])) { $text = $m[1]; } else { $text = substr($cat, strlen($m[0])); } $tmp = $formatter->word_repl('[[' . $cat . ']]', $text); $out .= '<li>' . $tmp . '</li>' . "\n"; } } $out .= '</ul></div>'; return $out; }
/** * Store pagelinks * * @author Won-Kyu Park <*****@*****.**> */ function store_pagelinks($pagename, $pagelinks) { global $DBInfo; $bcache = new Cache_Text('backlinks'); $cache = new Cache_Text('pagelinks'); unset($pagelinks['TwinPages']); $cur = $cache->fetch($pagename); if (!is_array($cur)) { $cur = array(); } $add = array_diff($pagelinks, $cur); $del = array_diff($cur, $pagelinks); // merge new backlinks foreach ($add as $a) { if (!isset($a[0])) { continue; } $bl = $bcache->fetch($a); if (!is_array($bl)) { $bl = array(); } $bl = array_merge($bl, array($pagename)); $bl = array_unique($bl); sort($bl); $bcache->update($a, $bl); } // remove deleted backlinks foreach ($del as $d) { if (!isset($d[0])) { continue; } $bl = $bcache->fetch($d); if (!is_array($bl)) { $bl = array(); } $bl = array_diff($bl, array($pagename)); sort($bl); $bcache->update($d, $bl); } if (!empty($pagelinks)) { $cache->update($pagename, $pagelinks); } else { $cache->remove($pagename); } }
function do_ipinfo($formatter, $params = array()) { global $DBInfo, $Config; $u = $DBInfo->user; $list = ''; $myip = ''; $mask = 24; $masks = array(24, 25, 16, 18, 8); $ttls = array(1800 => '30 minutes', 3600 => '1 hour', 7200 => '2 hours', 10800 => '3 hours', 21600 => '6 hours', 43200 => '12 hours', 1 => '1 day', 2 => '2 days', 7 => '7 days', 30 => '1 month', 60 => '2 month', 182 => '6 month', 365 => '1 year'); $reasons = array(100 => _("Vandalism"), 150 => _("Abusing"), 200 => _("Incompatible License"), 210 => _("CCL BY"), 220 => _("CCL NC"), 300 => _("Discussion needed"), 400 => _("Robot"), 500 => _("Testing")); if (!empty($params['q'])) { $tmp = normalize_network($params['q']); $myip = $params['q']; if ($tmp === false) { $params['msg'] = sprintf(_("Invalid IP Address %s"), $ip); $params['q'] = ''; } else { $myip = $params['q'] = $ip = $tmp[0]; if ($tmp[1] != 32) { $netmask = $tmp[1]; } } } $control_action = false; if (!empty($params['q']) && isset($_POST) && !empty($params['button_block'])) { $control_action = 'block'; } else { if (!empty($params['q']) && !empty($params['toggle'])) { $control_action = 'toggle'; $params['ttl'] = -1; // HACK to toggle block staus } else { if (!empty($params['q']) && !empty($params['remove'])) { if (in_array($u->id, $DBInfo->owners)) { $control_action = 'remove'; } else { $control_action = 'reset'; } $params['ttl'] = -1; // HACK } } } while ($u->is_member && $control_action !== false) { // check parameters // TTL check if (!empty($params['reason']) and array_key_exists($params['reason'], $reasons)) { $reason = $params['reason']; } if (!empty($params['comment'])) { $comment = $params['comment']; } $ttl = !empty($params['ttl']) ? (int) $params['ttl'] : 1800; // default 30 minutes if (in_array($u->id, $DBInfo->owners)) { $ttl = !empty($params['ttl']) ? $params['ttl'] : 0; // default for owners } else { if ($ttl >= 60) { $ttl = 1800; } } if ($ttl < 0) { $ttl = 1; } else { if ($ttl <= 365) { // days to seconds $ttl = $ttl * 60 * 60 * 24; } } if ($ttl >= 0 && !in_array($u->id, $DBInfo->owners)) { if (empty($comment) && empty($reason)) { $params['msg'] = _("Please select block reason"); break; } } $netmask = !empty($params['netmask']) ? (int) $params['netmask'] : $netmask; if ($netmask >= 32) { $netmask = ''; } $try = $ip; if (!empty($netmask)) { $try .= '/' . $netmask; } $tmp = normalize_network($try); if ($tmp === false) { if (empty($netmask)) { $params['msg'] = sprintf(_("Not a valid IP address: %s"), $try); } else { $params['msg'] = sprintf(_("Not a valid IP range: %s"), $try); } } else { // prepare to return $ret = array(); $retval = array(); $ret['retval'] =& $retval; if ($tmp[1] == 32) { // normalized IP $ip = $tmp[0]; // abusefilter cache $arena = 'abusefilter'; $ac = new Cache_Text('abusefilter'); // fetch monitor information $info = $ac->fetch($ip, 0, $ret); if ($info === false) { $new_info = array('create' => 0, 'delete' => 0, 'revert' => 0, 'save' => 0, 'edit' => 0, 'add_lines' => 0, 'del_lines' => 0, 'add_chars' => 0, 'del_chars' => 0); $new_info['id'] = $ip; $new_info['suspended'] = true; } else { $new_info = $info; $new_info['id'] = $ip; } } else { // normalized IP $ip = $tmp[0] . '/' . $tmp[1]; // ipblock cache $arena = 'ipblock'; $ac = new Cache_Text('ipblock'); // fetch monitor information $info = $ac->fetch($ip, 0, $ret); if ($info === false) { $new_info['id'] = $ip; $new_info['suspended'] = true; } else { $new_info = $info; $new_info['id'] = $ip; } } if (!empty($reason)) { $new_info['reason'] = $reason; } if (!empty($comment)) { // upate comments $comments = array(); if (!empty($info['comment'])) { $comments = explode("\n", $new_info['comment']); } $comments[] = date('Y-m-d H:i', time()) . "\t" . $u->id . "\t" . $comment; if (sizeof($comments) > 100) { array_shift($comments); } $new_info['comment'] = implode("\n", $comments); } if ($ttl == 1) { if ($control_action == 'reset') { $new_info['suspended'] = false; } else { if ($control_action == 'toggle') { $new_info['suspended'] = !$new_info['suspended']; } } $newttl = $retval['ttl'] - (time() - $retval['mtime']); if ($newttl < 0) { $newttl = 0; } if ($control_action == 'remove') { $ac->remove($ip); } else { $ac->update($ip, $new_info, $newttl); } } else { $new_info['suspended'] = true; $ac->update($ip, $new_info, $ttl); } if ($control_action == 'toggle') { $params['msg'] = sprintf(_("Successfully Toggle Block status: %s"), $try); } else { if ($control_action == 'reset') { $params['msg'] = sprintf(_("Successfully Enable IP (range) status: %s"), $try); } else { if ($control_action == 'remove') { $params['msg'] = sprintf(_("Successfully Removed IP range: %s"), $try); } else { if (!empty($netmask)) { $params['msg'] = sprintf(_("Successfully Blocked IP range: %s"), $try); } else { $params['msg'] = sprintf(_("Successfully Blocked IP address: %s"), $try); } } } } } break; } if (!empty($params['q']) && empty($params['button_block'])) { // search $retval = array(); $ret = array('retval' => &$retval); $try = $params['q']; $cache = 'abusefilter'; if (!empty($netmask)) { $try .= '/' . $netmask; $cache = 'ipblock'; } // try to find blocked IP or IP range $ac = new Cache_Text($cache); $info = $ac->fetch($try, 0, $ret); if ($info === false) { // get temporary blocked IP ranges $blocked = get_cached_temporary_blacklist(); $res = search_network($blocked, $params['q'], $ret); $permenant = false; if ($res === false) { // search blacklist ranges $res = search_network($Config['ruleset']['blacklist.ranges'], $params['q'], $ret); $permenant = true; } if ($res) { list($network, $netmask) = explode('/', $retval); if ($netmask == 32) { $title = _("Temporary blocked IP (range) found") . ' : ' . $network; } else { $found = $retval; if ($permenant) { $title = _("Permenantly blocked IP range found") . ' : ' . $found; // show all temporary blocked list $list = macro_IpInfo($formatter); } else { $title = _("Temporary blocked IP range found") . ' : ' . $found; // retrieve found $ac = new Cache_Text('ipblock'); $info = $ac->fetch($found, 0, $ret); if ($info !== false) { $info['ttl'] = $retval['ttl']; $info['mtime'] = $retval['mtime']; $list = macro_IpInfo($formatter, '', array('info' => $info)); } } } } else { $title = _("IP (range) is not found"); // show all temporary blocked list $list = macro_IpInfo($formatter); } } else { $info['ttl'] = $retval['ttl']; $info['mtime'] = $retval['mtime']; $list = macro_IpInfo($formatter, '', array('info' => $info)); $title = _("Temporary blocked IP found") . ' : ' . $params['q']; } } else { if ($u->is_member) { $opt = 'range'; if (!empty($params['static'])) { $opt = 'static'; } if (!empty($params['all'])) { $opt = ''; } $list = macro_IpInfo($formatter, $opt); } else { if (!$u->is_member) { $myip = $params['q'] = $_SERVER['REMOTE_ADDR']; } } } $params['.title'] = _("IP Information"); if (!empty($title)) { $params['title'] = $title; } else { if (!empty($params['q'])) { $params['title'] = sprintf(_("%s: IP Information"), $params['q']); } } $formatter->send_header('', $params); $formatter->send_title($title, '', $params); $searchform = <<<FORM <form method='post' action=''> <label>Search</label>: <input type='text' name='q' value='{$myip}' placeholder='IP or IP range' /> <input type='submit' name='button_search' value='search' /><br /> <input type='hidden' name='action' value='ipinfo' /> </form> FORM; echo '<h2>' . _("Temporary blocked IPs") . '</h2>', "\n"; echo $searchform; echo $list; echo $searchform; echo '<h2>' . _("Input IP or IP range") . '</h2>', "\n"; $mask_select = '<select name="netmask"><option value="">-- ' . _("Netmask") . ' --</option>' . "\n"; foreach ($masks as $m) { $selected = ''; if ($m == $netmask) { $selected = ' selected="selected"'; } $mask_select .= '<option value="' . $m . '"' . $selected . '>' . "\n"; $mask_select .= $m . ' : '; $c = 1 << 32 - $m; if ($c > 1) { $c -= 2; } $mask_select .= number_format($c) . ' IPs'; $mask_select .= '</option>' . "\n"; } $mask_select .= '</select>' . "\n"; $ttl_select = '<select name="ttl"><option value="0">-- ' . _("Expire") . ' --</option>' . "\n"; foreach ($ttls as $time => $str) { $ttl_select .= '<option value="' . $time . '">' . $str . '</option>' . "\n"; } $ttl_select .= '</select>' . "\n"; $reason_select = '<select name="reason"><option value="">-- ' . _("Block reason") . ' --</option>' . "\n"; foreach ($reasons as $code => $str) { $reason_select .= '<option value="' . $code . '">' . $str . '</option>' . "\n"; } $reason_select .= '</select>' . "\n"; $ip_lab = _("IP Address"); $net_lab = _("Netmask (i.e. 24)"); $ttl_lab = _("Expire"); $block_btn = _("Block IP"); echo <<<FORM <form method='post' action=''> <table class='wiki'><tr><th>{$ip_lab}</th> <th>{$net_lab}</th> <th>{$ttl_lab}</th> </tr> <tr> <td><input type='text' name='q' value='{$myip}' /></td> <td> {$mask_select} </td> <td> {$ttl_select} </td> </tr> <tr><td>{$reason_select}</td><td colspan='2'><input type='text' name='comment' size='50' /></td></tr> </table> FORM; echo <<<FORM <input type='hidden' name='action' value='ipinfo' /> <input type='submit' name='button_block' value='{$block_btn}' /> </form> FORM; $formatter->send_footer('', $params); }
function do_rss_rc($formatter, $options) { global $DBInfo, $Config; // get members to hide log $members = $DBInfo->members; $days = !empty($DBInfo->rc_days) ? $DBInfo->rc_days : RSS_DEFAULT_DAYS; $options['quick'] = 1; if (!empty($options['c'])) { $options['items'] = $options['c']; } $lines = $DBInfo->editlog_raw_lines($days, $options); if (!empty($DBInfo->rss_rc_options)) { $opts = $DBInfo->rss_rc_options; $opts = explode(',', $opts); foreach ($opts as $opt) { $options[$opt] = 1; // FIXME } } // HTTP conditional get $mtime = $DBInfo->mtime(); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $cache_ttl = !empty($DBInfo->rss_rc_ttl) ? $DBInfo->rss_rc_ttl : 60; /* 60 seconds */ // make etag based on some options and mtime. $check_opts = array('quick', 'items', 'oe', 'diffs', 'raw', 'nomsg', 'summary'); $check = array(); foreach ($check_opts as $c) { if (isset($options[$c])) { $check[$c] = $options[$c]; } } $etag = md5($mtime . $DBInfo->logo_img . serialize($check) . $cache_ttl . $options['id']); $headers = array(); $headers[] = 'Pragma: cache'; $maxage = $cache_ttl; $public = 'public'; if ($options['id'] != 'Anonymous') { $public = 'private'; } $headers[] = 'Cache-Control: ' . $public . ', max-age=' . $maxage; $headers[] = 'Last-Modified: ' . $lastmod; $headers[] = 'ETag: "' . $etag . '"'; $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { $headers[] = 'HTTP/1.0 304 Not Modified'; } foreach ($headers as $h) { header($h); } if (!$need) { @ob_end_clean(); return; } $cache = new Cache_Text('rss_rc'); $cache_delay = min($cache_ttl, 30); $mtime = $cache->mtime($etag); $val = false; if (empty($formatter->refresh)) { if (($val = $cache->fetch($etag)) !== false and $DBInfo->checkUpdated($mtime, $cache_delay)) { header("Content-Type: text/xml"); echo $val; return; } } // need to update cache if ($val !== false and $cache->exists($etag . '.lock')) { header("Content-Type: text/xml"); echo $val . '<!-- cached at ' . date('Y-m-d H:i:s', $mtime) . ' -->'; return; } if ($cache->exists($etag . '.lock')) { header("Content-Type: text/xml"); echo ''; return; } $cache->update($etag . '.lock', array('lock'), 5); // 5s lock $time_current = time(); # $secs_per_day= 60*60*24; # $days_to_show= 30; # $time_cutoff= $time_current - ($days_to_show * $secs_per_day); $URL = qualifiedURL($formatter->prefix); $img_url = qualifiedURL($DBInfo->logo_img); $url = qualifiedUrl($formatter->link_url("RecentChanges")); $channel = <<<CHANNEL <channel rdf:about="{$URL}"> <title>{$DBInfo->sitename}</title> <link>{$url}</link> <description>RecentChanges at {$DBInfo->sitename}</description> <image rdf:resource="{$img_url}"></image> <items> <rdf:Seq> CHANNEL; $items = ""; $ratchet_day = FALSE; if (!$lines) { $lines = array(); } foreach ($lines as $line) { $parts = explode("\t", $line); $page_name = $DBInfo->keyToPagename($parts[0]); // hide log if (!empty($members) && !in_array($options['id'], $members) && !empty($Config['ruleset']['hidelog'])) { if (in_array($page_name, $Config['ruleset']['hidelog'])) { continue; } } $addr = $parts[1]; $ed_time = $parts[2]; $user = $parts[4]; $log = _stripslashes($parts[5]); $act = rtrim($parts[6]); # if ($ed_time < $time_cutoff) # break; $url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name))); $diff_url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name), '?action=diff')); $extra = "<br /><a href='{$diff_url}'>" . _("show changes") . "</a>\n"; if (!$DBInfo->hasPage($page_name)) { $status = 'deleted'; $html = '<![CDATA[' . "<a href='{$url}'>" . $page_name . "</a> is deleted" . ']]>' . "\n"; } else { $status = 'updated'; if (!empty($options['diffs'])) { $p = new WikiPage($page_name); $f = new Formatter($p); $options['raw'] = 1; $options['nomsg'] = 1; $html = $f->macro_repl('Diff', '', $options); if (!$html) { ob_start(); $f->send_page('', array('fixpath' => 1)); #$f->send_page(''); $html = ob_get_contents(); ob_end_clean(); $extra = ''; } $html = str_replace(']', ']', $html); $html = "<![CDATA[" . $html . $extra . "]]>"; #$html=strtr($html.$extra,array('&'=>'&','<'=>'<')); } else { if (!empty($options['summary'])) { $p = new WikiPage($page_name); $f = new Formatter($p); $f->section_edit = 0; $f->sister_on = 0; $f->perma_icon = ''; $options['nomsg'] = 1; $b = $p->_get_raw_body(); $chunks = preg_split('/\\n#{4,}/', $b); # summary breaker is #### ob_start(); if ($chunks) { $f->send_page($chunks[0], array('fixpath' => 1)); } else { $f->send_page('', array('fixpath' => 1)); } #$f->send_page(''); $html = ob_get_contents(); ob_end_clean(); $chunks = preg_split('/<!-- break -->/', $html); # <!-- break --> if ($chunks[0]) { $html = $chunks[0]; } $html = str_replace(']', ']', $html); $html = "<![CDATA[" . $html . "]]>"; } else { $html = str_replace('&', '&', $log); } } } $zone = "+00:00"; $date = gmdate("Y-m-d\\TH:i:s", $ed_time) . $zone; #$datetag = gmdate("YmdHis",$ed_time); $channel .= "<rdf:li rdf:resource=\"{$url}\"></rdf:li>\n"; $valid_page_name = preg_replace('/&(?!#?\\w+;)/', '&', _html_escape($page_name)); $items .= "<item rdf:about=\"{$url}\">\n"; $items .= " <title>{$valid_page_name}</title>\n"; $items .= " <link>{$url}</link>\n"; $items .= " <description>{$html}</description>\n"; $items .= " <dc:date>{$date}</dc:date>\n"; $items .= "<dc:creator>{$user}</dc:creator>\n"; $items .= "<dc:contributor>{$user}</dc:contributor>\n"; # $items.=" <dc:contributor>\n <rdf:Description>\n" # ." <rdf:value>$user</rdf:value>\n" # ." </rdf:Description>\n </dc:contributor>\n"; $items .= " <wiki:status>{$status}</wiki:status>\n"; $items .= " <wiki:diff>{$diff_url}</wiki:diff>\n"; $items .= "</item>\n"; } $url = qualifiedUrl($formatter->link_url($DBInfo->frontpage)); $channel .= <<<FOOT </rdf:Seq> </items> </channel> <image rdf:about="{$img_url}"> <title>{$DBInfo->sitename}</title> <link>{$url}</link> <url>{$img_url}</url> </image> FOOT; $url = qualifiedUrl($formatter->link_url("FindPage")); $form = <<<FORM <textinput> <title>Search</title> <link>{$url}</link> <name>goto</name> </textinput> FORM; $new = ""; if (!empty($options['oe']) and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; if (function_exists('iconv')) { $out = $head . $channel . $items . $form; $new = iconv($DBInfo->charset, $charset, $out); if (!$new) { $charset = $DBInfo->charset; } } } else { $charset = $DBInfo->charset; } $head = <<<HEAD <?xml version="1.0" encoding="{$charset}"?> <?xml-stylesheet href="{$DBInfo->url_prefix}/css/_feed.css" type="text/css"?> <rdf:RDF xmlns="http://purl.org/rss/1.0/" \txmlns:wiki="http://purl.org/rss/1.0/modules/wiki/" \txmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" \txmlns:xlink="http://www.w3.org/1999/xlink" \txmlns:dc="http://purl.org/dc/elements/1.1/"> <!-- Add "diffs=1" to add change diffs to the description of each items. Add "summary=1" to add summary to the description of each items. Add "oe=utf-8" to convert the charset of this rss to UTF-8. --> HEAD; header("Content-Type: text/xml"); if ($new) { $out = $head . $new; } else { $out = $head . $channel . $items . $form; } $out .= "</rdf:RDF>\n"; echo $out; $cache->update($etag, $out); $cache->remove($etag . '.lock'); }
function do_atom($formatter, $options) { global $DBInfo, $Config; global $_release; define('ATOM_DEFAULT_DAYS', 7); // get members to hide log $members = $DBInfo->members; $days = $DBInfo->rc_days ? $DBInfo->rc_days : ATOM_DEFAULT_DAYS; $options['quick'] = 1; if ($options['c']) { $options['items'] = $options['c']; } $lines = $DBInfo->editlog_raw_lines($days, $options); // HTTP conditional get $mtime = $DBInfo->mtime(); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $cache_ttl = !empty($DBInfo->atom_ttl) ? $DBInfo->atom_ttl : 60 * 30; /* 30 minutes */ // make etag based on some options and mtime. $check_opts = array('quick', 'items', 'c'); $check = array(); foreach ($check_opts as $c) { if (isset($options[$c])) { $check[$c] = $options[$c]; } } $etag = md5($mtime . $DBInfo->logo_img . serialize($check) . $cache_ttl . $options['id']); $headers = array(); $headers[] = 'Pragma: cache'; $maxage = $cache_ttl; $public = 'public'; if ($options['id'] != 'Anonymous') { $public = 'private'; } $headers[] = 'Cache-Control: ' . $public . ', max-age=' . $maxage; $headers[] = 'Last-Modified: ' . $lastmod; $headers[] = 'ETag: "' . $etag . '"'; $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { $headers[] = 'HTTP/1.0 304 Not Modified'; } foreach ($headers as $h) { header($h); } if (!$need) { @ob_end_clean(); return; } $cache = new Cache_Text('atom'); $cache_delay = min($cache_ttl, 30); $mtime = $cache->mtime($etag); $time_current = time(); $val = false; if (empty($formatter->refresh)) { if (($val = $cache->fetch($etag)) !== false and $DBInfo->checkUpdated($mtime, $cache_delay)) { header("Content-Type: application/xml"); echo $val; return; } } // need to update cache if ($val !== false and $cache->exists($etag . '.lock')) { header("Content-Type: application/xml"); echo $val . '<!-- cached at ' . date('Y-m-d H:i:s', $mtime) . ' -->'; return; } if ($cache->exists($etag . '.lock')) { header("Content-Type: application/xml"); echo ''; return; } $cache->update($etag . '.lock', array('lock'), 30); // 30s lock $URL = qualifiedURL($formatter->prefix); $img_url = qualifiedURL($DBInfo->logo_img); $url = qualifiedUrl($formatter->link_url($DBInfo->frontpage)); $surl = qualifiedUrl($formatter->link_url($options['page'] . '?action=atom')); $channel = <<<CHANNEL <title>{$DBInfo->sitename}</title> <link href="{$url}"></link> <link rel="self" type="application/atom+xml" href="{$surl}" /> <subtitle>RecentChanges at {$DBInfo->sitename}</subtitle> <generator version="{$_release}">MoniWiki Atom feeder</generator> CHANNEL; $items = ""; $ratchet_day = FALSE; if (!$lines) { $lines = array(); } foreach ($lines as $line) { $parts = explode("\t", $line); $page_name = $DBInfo->keyToPagename($parts[0]); // hide log if (!empty($members) && !in_array($options['id'], $members) && !empty($Config['ruleset']['hidelog'])) { if (in_array($page_name, $Config['ruleset']['hidelog'])) { continue; } } $addr = $parts[1]; $ed_time = $parts[2]; $user = $parts[4]; $user_uri = ''; if ($user != 'Anonymous' && $DBInfo->hasPage($user)) { $user_uri = $formatter->link_url(_rawurlencode($user), "", $user); $user_uri = '<uri>' . $user_uri . '</uri>'; } $log = _stripslashes($parts[5]); $act = rtrim($parts[6]); $url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name))); $diff_url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name), '?action=diff')); $extra = "<br /><a href='{$diff_url}'>" . _("show changes") . "</a>\n"; $content = ''; if (!$DBInfo->hasPage($page_name)) { $status = 'deleted'; $content = "<content type='html'><a href='{$url}'>{$page_name}</a> is deleted</content>\n"; } else { $status = 'updated'; if ($options['diffs']) { $p = new WikiPage($page_name); $f = new Formatter($p); $options['raw'] = 1; $options['nomsg'] = 1; $html = $f->macro_repl('Diff', '', $options); if (!$html) { ob_start(); $f->send_page('', array('fixpath' => 1)); #$f->send_page(''); $html = ob_get_contents(); ob_end_clean(); $extra = ''; } $content = " <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>{$html}</content>\n"; } else { if ($log) { $html = str_replace('&', '&', $log); $content = "<content type='text'>" . $html . "</content>\n"; } else { $content = "<content type='text'>updated</content>\n"; } } } $zone = '+00:00'; $date = gmdate("Y-m-d\\TH:i:s", $ed_time) . $zone; if (!isset($updated)) { $updated = $date; } #$datetag = gmdate("YmdHis",$ed_time); $valid_page_name = str_replace('&', '&', $page_name); $items .= "<entry>\n"; $items .= " <title>{$valid_page_name}</title>\n"; $items .= " <link href='{$url}'></link>\n"; $items .= ' ' . $content; $items .= " <author><name>{$user}</name>{$user_uri}</author>\n"; $items .= " <updated>{$date}</updated>\n"; $items .= " <contributor><name>{$user}</name>{$user_uri}</contributor>\n"; $items .= "</entry>\n"; } $updated = " <updated>{$updated}</updated>\n"; $new = ""; if ($options['oe'] and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; if (function_exists('iconv')) { $out = $head . $channel . $items . $form; $new = iconv($DBInfo->charset, $charset, $out); if (!$new) { $charset = $DBInfo->charset; } } } else { $charset = $DBInfo->charset; } $head = <<<HEAD <?xml version="1.0" encoding="{$charset}"?> <!--<?xml-stylesheet href="{$DBInfo->url_prefix}/css/_feed.css" type="text/css"?>--> <feed xmlns="http://www.w3.org/2005/Atom"> <!-- Add "diffs=1" to add change diffs to the description of each items. Add "oe=utf-8" to convert the charset of this rss to UTF-8. --> HEAD; header("Content-Type: application/xml"); $out = ''; if ($new) { $out = $head . $new; } else { $out = $head . $channel . $updated . $items . $form; } $out .= "</feed>\n"; echo $out; $cache->update($etag, $out); $cache->remove($etag . '.lock'); }
function wiki_main($options) { global $DBInfo, $Config; $pagename = isset($options['pagename'][0]) ? $options['pagename'] : $DBInfo->frontpage; # get primary variables if (isset($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] == 'POST') { // reset some reserved variables if (isset($_POST['retstr'])) { unset($_POST['retstr']); } if (isset($_POST['header'])) { unset($_POST['header']); } # hack for TWiki plugin $action = ''; if (!empty($_FILES['filepath']['name'])) { $action = 'draw'; } if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) { # hack for Oekaki: PageName----action----filename list($pagename, $action, $value) = explode('----', $pagename, 3); $options['value'] = $value; } else { $value = !empty($_POST['value']) ? $_POST['value'] : ''; $action = !empty($_POST['action']) ? $_POST['action'] : $action; if (empty($action)) { $dum = explode('----', $pagename, 3); if (isset($dum[0][0]) && isset($dum[1][0])) { $pagename = trim($dum[0]); $action = trim($dum[1]); $value = isset($dum[2][0]) ? $dum[2] : ''; } } } $goto = !empty($_POST['goto']) ? $_POST['goto'] : ''; $popup = !empty($_POST['popup']) ? 1 : 0; // ignore invalid POST actions if (empty($goto) and empty($action)) { header('Status: 405 Not allowed'); return; } } else { // reset some reserved variables if (isset($_GET['retstr'])) { unset($_GET['retstr']); } if (isset($_GET['header'])) { unset($_GET['header']); } $action = !empty($_GET['action']) ? $_GET['action'] : ''; $value = isset($_GET['value'][0]) ? $_GET['value'] : ''; $goto = isset($_GET['goto'][0]) ? $_GET['goto'] : ''; $rev = !empty($_GET['rev']) ? $_GET['rev'] : ''; if ($options['id'] == 'Anonymous') { $refresh = 0; } else { $refresh = !empty($_GET['refresh']) ? $_GET['refresh'] : ''; } $popup = !empty($_GET['popup']) ? 1 : 0; } // parse action // action=foobar, action=foobar/macro, action=foobar/json etc. $full_action = $action; $action_mode = ''; if (($p = strpos($action, '/')) !== false) { $full_action = strtr($action, '/', '-'); $action_mode = substr($action, $p + 1); $action = substr($action, 0, $p); } $options['page'] = $pagename; $options['action'] =& $action; $reserved = array('call', 'prefix'); foreach ($reserved as $k) { unset($options[$k]); } // unset all reserved // check pagename length $key = $DBInfo->pageToKeyname($pagename); if (!empty($options['action']) && strlen($key) > 255) { $i = 252; // 252 + reserved 3 (.??) = 255 $newname = $DBInfo->keyToPagename(substr($key, 0, 252)); $j = mb_strlen($newname, $Config['charset']); $j--; do { $newname = mb_substr($pagename, 0, $j, $Config['charset']); $key = $DBInfo->pageToKeyname($newname); } while (strlen($key) > 248 && --$j > 0); $options['page'] = $newname; $options['orig_pagename'] = $pagename; // original page name $pagename = $newname; } else { $options['orig_pagename'] = ''; } if (function_exists('local_pre_check')) { local_pre_check($action, $options); } // load ruleset if (!empty($Config['config_ruleset'])) { $ruleset_file = 'config/ruleset.' . $Config['config_ruleset'] . '.php'; if (file_exists($ruleset_file)) { $ruleset = load_ruleset($ruleset_file); $Config['ruleset'] = $ruleset; } // is it robot ? if (!empty($ruleset['allowedrobot'])) { if (empty($_SERVER['HTTP_USER_AGENT'])) { $options['is_robot'] = 1; } else { $options['is_robot'] = is_allowed_robot($ruleset['allowedrobot'], $_SERVER['HTTP_USER_AGENT']); } } // setup staff members if (!empty($ruleset['staff'])) { $DBInfo->members = array_merge($DBInfo->members, $ruleset['staff']); } } $page = $DBInfo->getPage($pagename); $page->is_static = false; // FIXME $pis = array(); // get PI cache if ($page->exists()) { $page->pi = $pis = $page->get_instructions('', array('refresh' => $refresh)); // set some PIs for robot if (!empty($options['is_robot'])) { $DBInfo->use_sectionedit = 0; # disable section edit $page->is_static = true; } else { if ($_SERVER['REQUEST_METHOD'] == 'GET' or $_SERVER['REQUEST_METHOD'] == 'HEAD') { if (empty($action) and empty($refresh)) { $page->is_static = empty($pis['#nocache']) && empty($pis['#dynamic']); } } } } // HEAD support for robots if (empty($action) and !empty($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] == 'HEAD') { if (!$page->exists()) { header("HTTP/1.1 404 Not found"); header("Status: 404 Not found"); } else { if ($page->is_static or is_static_action($options)) { $mtime = $page->mtime(); $etag = $page->etag($options); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); header('Last-Modified: ' . $lastmod); if (!empty($action)) { $etag = '"' . $etag . '"'; header('ETag: ' . $etag); } // checksum request if (isset($_SERVER['HTTP_X_GET_CHECKSUM'])) { header('X-Checksum: md5-' . md5($page->get_raw_body())); } } } return; } if (is_static_action($options) or !empty($DBInfo->use_conditional_get) and $page->is_static) { $mtime = $page->mtime(); $etag = $page->etag($options); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { @ob_end_clean(); $headers = array(); $headers[] = 'HTTP/1.0 304 Not Modified'; $headers[] = 'Last-Modified: ' . $lastmod; foreach ($headers as $header) { header($header); } return; } } $formatter = new Formatter($page, $options); $formatter->refresh = !empty($refresh) ? $refresh : ''; $formatter->popup = !empty($popup) ? $popup : ''; $formatter->tz_offset = $options['tz_offset']; // check blocklist/whitelist for block_actions $act = strtolower($action); while (!empty($DBInfo->block_actions) && !empty($ruleset) && in_array($act, $DBInfo->block_actions)) { require_once 'lib/checkip.php'; // check whitelist if (isset($ruleset['whitelist']) && check_ip($ruleset['whitelist'], $_SERVER['REMOTE_ADDR'])) { break; } $res = null; // check blacklist if (isset($ruleset['blacklist']) && check_ip($ruleset['blacklist'], $_SERVER['REMOTE_ADDR']) || isset($ruleset['blacklist.ranges']) && search_network($ruleset['blacklist.ranges'], $_SERVER['REMOTE_ADDR'])) { $res = true; } else { if (!empty($DBInfo->use_dynamic_blacklist)) { require_once 'plugin/ipinfo.php'; $blacklist = get_cached_temporary_blacklist(); $retval = array(); $ret = array('retval' => &$retval); $res = search_network($blacklist, $_SERVER['REMOTE_ADDR'], $ret); if ($res !== false) { // retrieve found $ac = new Cache_Text('ipblock'); $info = $ac->fetch($retval, 0, $ret); if ($info !== false) { if (!$info['suspended']) { // whitelist IP break; } $res = true; } else { $ac->remove($retval); // expired IP entry. $res = false; } } } } // show warning message if ($res) { $options['notice'] = _("Your IP is in the blacklist"); $options['msg'] = _("Please contact WikiMasters"); $options['msgtype'] = 'warn'; if (!empty($DBInfo->edit_actions) and in_array($act, $DBInfo->edit_actions)) { $options['action'] = $action = 'edit'; } else { if ($act != 'edit') { $options['action'] = $action = 'show'; } } break; } // check kiwirian if (isset($ruleset['kiwirian']) && in_array($options['id'], $ruleset['kiwirian'])) { $options['title'] = _("You are blocked in this wiki"); $options['msg'] = _("Please contact WikiMasters"); do_invalid($formatter, $options); return false; } break; } // set robot class if (!empty($options['is_robot'])) { if (!empty($DBInfo->security_class_robot)) { $class = 'Security_' . $DBInfo->security_class_robot; include_once 'plugin/security/' . $DBInfo->security_class_robot . '.php'; } else { $class = 'Security_robot'; include_once 'plugin/security/robot.php'; } $DBInfo->security = new $class($DBInfo); // is it allowed to robot ? if (!$DBInfo->security->is_allowed($action, $options)) { $action = 'show'; if (!empty($action_mode)) { return '[]'; } } $DBInfo->extra_macros = ''; } while (empty($action) or $action == 'show') { if (isset($value[0])) { # ?value=Hello $options['value'] = $value; do_goto($formatter, $options); return true; } else { if (isset($goto[0])) { # ?goto=Hello $options['value'] = $goto; do_goto($formatter, $options); return true; } } if (!$page->exists()) { if (isset($options['retstr'])) { return false; } if (!empty($DBInfo->auto_search) && $action != 'show' && ($p = getPlugin($DBInfo->auto_search))) { $action = $DBInfo->auto_search; break; } // call notfound action $action = 'notfound'; break; } # render this page if (isset($_GET['redirect']) and !empty($DBInfo->use_redirect_msg) and $action == 'show') { $redirect = $_GET['redirect']; $options['msg'] = '<h3>' . sprintf(_("Redirected from page \"%s\""), $formatter->link_tag(_rawurlencode($redirect), '?action=show', $redirect)) . "</h3>"; } if (empty($action)) { $options['pi'] = 1; } # protect a recursivly called #redirect if (!empty($DBInfo->control_read) and !$DBInfo->security->is_allowed('read', $options)) { $options['action'] = 'read'; do_invalid($formatter, $options); return; } $formatter->pi = $formatter->page->get_instructions(); if (!empty($DBInfo->body_attr)) { $options['attr'] = $DBInfo->body_attr; } $ret = $formatter->send_header('', $options); if (empty($options['is_robot'])) { if ($DBInfo->use_counter) { $DBInfo->counter->incCounter($pagename, $options); } if (!empty($DBInfo->use_referer) and isset($_SERVER['HTTP_REFERER'])) { log_referer($_SERVER['HTTP_REFERER'], $pagename); } } $formatter->send_title("", "", $options); $formatter->write("<div id='wikiContent'>\n"); if (isset($options['timer']) and is_object($options['timer'])) { $options['timer']->Check("init"); } // force #nocache for #redirect pages if (isset($formatter->pi['#redirect'][0])) { $formatter->pi['#nocache'] = 1; } $extra_out = ''; $options['pagelinks'] = 1; if (!empty($Config['cachetime']) and $Config['cachetime'] > 0 and empty($formatter->pi['#nocache'])) { $cache = new Cache_text('pages', array('ext' => 'html')); $mcache = new Cache_text('dynamic_macros'); $mtime = $cache->mtime($pagename); $now = time(); $check = $now - $mtime; $_macros = null; if ($cache->mtime($pagename) < $formatter->page->mtime()) { $formatter->refresh = 1; } // force update $valid = false; $delay = !empty($DBInfo->default_delaytime) ? $DBInfo->default_delaytime : 0; if (empty($formatter->refresh) and $DBInfo->checkUpdated($mtime, $delay) and $check < $Config['cachetime']) { if ($mcache->exists($pagename)) { $_macros = $mcache->fetch($pagename); } // FIXME TODO: check postfilters if (0 && empty($_macros)) { #$out = $cache->fetch($pagename); $valid = $cache->fetch($pagename, '', array('print' => 1)); } else { $out = $cache->fetch($pagename); $valid = $out !== false; } $mytime = gmdate("Y-m-d H:i:s", $mtime + $options['tz_offset']); $extra_out = "<!-- Cached at {$mytime} -->"; } if (!$valid) { $formatter->_macrocache = 1; ob_start(); $formatter->send_page('', $options); flush(); $out = ob_get_contents(); ob_end_clean(); $formatter->_macrocache = 0; $_macros = $formatter->_dynamic_macros; if (!empty($_macros)) { $mcache->update($pagename, $_macros); } if (isset($out[0])) { $cache->update($pagename, $out); } } if (!empty($_macros)) { $mrule = array(); $mrepl = array(); foreach ($_macros as $m => $v) { if (!is_array($v)) { continue; } $mrule[] = '@@' . $v[0] . '@@'; $options['mid'] = $v[1]; $mrepl[] = $formatter->macro_repl($m, '', $options); // XXX } echo $formatter->get_javascripts(); $out = str_replace($mrule, $mrepl, $out); // no more dynamic macros found if (empty($formatter->_dynamic_macros)) { // update contents $cache->update($pagename, $out); // remove dynamic macros cache $mcache->remove($pagename); } } if ($options['id'] != 'Anonymous') { $args['refresh'] = 1; } // add refresh menu } else { ob_start(); $formatter->send_page('', $options); flush(); $out = ob_get_contents(); ob_end_clean(); } // fixup to use site specific thumbwidth if (!empty($Config['site_thumb_width']) and $Config['site_thumb_width'] != $DBInfo->thumb_width) { $opts = array('thumb_width' => $Config['site_thumb_width']); $out = $formatter->postfilter_repl('imgs_for_mobile', $out, $opts); } echo $out, $extra_out; // automatically set #dynamic PI if (empty($formatter->pi['#dynamic']) and !empty($formatter->_dynamic_macros)) { $pis = $formatter->pi; if (empty($pis['raw'])) { // empty PIs $pis = array(); } else { if (isset($pis['#format']) and !preg_match('/#format\\s/', $pis['raw'])) { // #format not found in PIs unset($pis['#format']); } } $pis['#dynamic'] = 1; // internal instruction $pi_cache = new Cache_text('PI'); $pi_cache->update($formatter->page->name, $pis); } else { if (empty($formatter->_dynamic_macros) and !empty($formatter->pi['#dynamic'])) { $pi_cache = new Cache_text('PI'); $pi_cache->remove($formatter->page->name); // reset PI $mcache->remove($pagename); // remove macro cache if (isset($out[0])) { $cache->update($pagename, $out); } // update cache content } } if (isset($options['timer']) and is_object($options['timer'])) { $options['timer']->Check("send_page"); } $formatter->write("<!-- wikiContent --></div>\n"); if (!empty($DBInfo->extra_macros) and $formatter->pi['#format'] == $DBInfo->default_markup) { if (!empty($formatter->pi['#nocomment'])) { $options['nocomment'] = 1; $options['notoolbar'] = 1; } $options['mid'] = 'dummy'; echo '<div id="wikiExtra">' . "\n"; $mout = ''; $extra = array(); if (is_array($DBInfo->extra_macros)) { $extra = $DBInfo->extra_macros; } else { $extra[] = $DBInfo->extra_macros; } // XXX if (!empty($formatter->pi['#comment'])) { array_unshift($extra, 'Comment'); } foreach ($extra as $macro) { $mout .= $formatter->macro_repl($macro, '', $options); } echo $formatter->get_javascripts(); echo $mout; echo '</div>' . "\n"; } $args['editable'] = 1; $formatter->send_footer($args, $options); return; } $act = $action; if (!empty($DBInfo->myplugins) and array_key_exists($action, $DBInfo->myplugins)) { $act = $DBInfo->myplugins[$action]; } if ($act) { $options['noindex'] = true; $options['custom'] = ''; $options['help'] = ''; $options['value'] = $value; $a_allow = $DBInfo->security->is_allowed($act, $options); if (!empty($action_mode)) { $myopt = $options; $myopt['explicit'] = 1; $f_allow = $DBInfo->security->is_allowed($full_action, $myopt); # check if hello/ajax is defined or not if ($f_allow === false && $a_allow) { $f_allow = $a_allow; } # follow action permission if it is not defined explicitly. if (!$f_allow) { $args = array('action' => $action); $args['allowed'] = $options['allowed'] = $f_allow; if ($f_allow === false) { $title = sprintf(_("%s action is not found."), $action); } else { $title = sprintf(_("Invalid %s action."), $action_mode); } if ($action_mode == 'ajax') { $args['title'] = $title; return ajax_invalid($formatter, $args); } $options['title'] = $title; return do_invalid($formatter, $options); } } else { if (!$a_allow) { $options['allowed'] = $a_allow; if ($options['custom'] != '' and method_exists($DBInfo->security, $options['custom'])) { $options['action'] = $action; if ($action) { call_user_func(array(&$DBInfo->security, $options['custom']), $formatter, $options); } return; } return do_invalid($formatter, $options); } else { if ($_SERVER['REQUEST_METHOD'] == "POST" and $DBInfo->security->is_protected($act, $options) and !$DBInfo->security->is_valid_password($_POST['passwd'], $options)) { # protect some POST actions and check a password $title = sprintf(_("Fail to \"%s\" !"), $action); $formatter->send_header("", $options); $formatter->send_title($title, "", $options); $formatter->send_page("== " . _("Please enter the valid password") . " =="); $formatter->send_footer("", $options); return; } } } $options['action_mode'] = ''; if (!empty($action_mode) and in_array($action_mode, array('ajax', 'macro'))) { if ($_SERVER['REQUEST_METHOD'] == "POST") { $options = array_merge($_POST, $options); } else { $options = array_merge($_GET, $options); } $options['action_mode'] = $action_mode; if ($action_mode == 'ajax') { $formatter->ajax_repl($action, $options); } else { if (!empty($DBInfo->use_macro_as_action)) { # XXX echo $formatter->macro_repl($action, $options['value'], $options); } else { do_invalid($formatter, $options); } } return; } // is it valid action ? $plugin = $pn = getPlugin($action); if ($plugin === '') { // action not found $plugin = $action; } if (!function_exists("do_post_" . $plugin) and !function_exists("do_" . $plugin) and $pn) { include_once "plugin/{$pn}.php"; } if (function_exists("do_" . $plugin)) { if ($_SERVER['REQUEST_METHOD'] == "POST") { $options = array_merge($_POST, $options); } else { $options = array_merge($_GET, $options); } call_user_func("do_{$plugin}", $formatter, $options); return; } else { if (function_exists("do_post_" . $plugin)) { if ($_SERVER['REQUEST_METHOD'] == "POST") { $options = array_merge($_POST, $options); } else { # do_post_* set some primary variables as $options $options['value'] = isset($_GET['value'][0]) ? $_GET['value'] : ''; } call_user_func("do_post_{$plugin}", $formatter, $options); return; } } do_invalid($formatter, $options); return; } }
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; }