Example #1
0
 function get_all_blogs()
 {
     global $DBInfo;
     $blogs = array();
     $cache = new Cache_Text('blog', array('hash' => ''));
     $cache->_caches($blogs);
     return $blogs;
 }
Example #2
0
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;
}
Example #3
0
function updateBlogList($formatter)
{
    global $DBInfo;
    $cache = new Cache_Text('blog', array('hash' => ''));
    $changecache = new Cache_Text('blogchanges', array('hash' => ''));
    $rule = "@/(\\d*)" . $DBInfo->pageToKeyname('.' . $formatter->page->name) . '$@';
    $files = array();
    $changecache->_caches($files);
    foreach ($files as $file) {
        if (preg_match($rule, $file, $match)) {
            print $fname;
            #unlink($fname);
        }
    }
    $body = $formatter->page->get_raw_body();
    $lines = explode("\n", $body);
    $date = 0;
    $entries = array();
    $log = '';
    $logs = '';
    $key = $DBInfo->pageToKeyname('.' . $formatter->page->name);
    foreach ($lines as $line) {
        if (preg_match("/^##norss/i", $line)) {
            #XXX $changecache->_del($key);
            return;
        }
        if (preg_match("/^(?:{{{)?#!blog\\s+(.*)\\s+(\\d{4}-\\d{2}-\\d{2}T[^ ]+)\\s*(.*)?\$/", $line, $match)) {
            list($author, $datestamp, $title) = array($match[1], $match[2], $match[3]);
            $datestamp[10] = ' ';
            $time = strtotime($datestamp . ' GMT');
            $stamp = date('Ymd', $time);
            if (empty($date)) {
                $date = $stamp;
            }
            if ($stamp != $date) {
                $log = join("\n", $entries) . "\n";
                $logs .= $log;
                $changecache->update($date . $key, $log);
                $entries = array();
                $date = $stamp;
            }
            $entries[] = $date . "\t" . $time . "\t" . $author . "\t" . $datestamp . "\t" . $title;
        }
    }
    $log = join("\n", $entries) . "\n";
    if ($stamp) {
        $changecache->update($stamp . $key, $log);
    }
    $logs .= $log;
    $cache->update($DBInfo->pageToKeyname($formatter->page->name), $logs);
    return;
}
Example #4
0
function macro_BlogArchives($formatter, $value, $options = array())
{
    global $DBInfo;
    $cache = new Cache_Text('blogchanges', array('hash' => ''));
    preg_match("/^(?(?=')'([^']+)'|\"([^\"]+)\")?(\\s*,?.*)\$/", $value, $match);
    if ($match[1] or $match[2]) {
        $date_fmt = $match[1] ? $match[1] : $match[2];
    } else {
        $date_fmt = 'Y-m';
    }
    $opts = explode(',', $match[3]);
    $opts = array_map('trim', $opts);
    if (in_array('list', $opts)) {
        $bra = '<li>';
        $ket = '</li>';
    } else {
        $bra = '';
        $ket = "<br/>\n";
    }
    $year = date('Y');
    // show only recent two years
    $rule = "/^(({$year}|" . ($year - 1) . ")\\d{2})\\d{2}/";
    $archives = array();
    $files = array();
    $cache->_caches($files);
    foreach ($files as $file) {
        if (preg_match($rule, $file, $match)) {
            $archives[] = $match[1];
        }
    }
    $archives = array_unique($archives);
    rsort($archives);
    $out = '';
    foreach ($archives as $archive) {
        $year = substr($archive, 0, 4);
        $month = substr($archive, 4);
        $datetext = date($date_fmt, mktime(0, 0, 0, $month, 1, $year));
        $out .= $bra . $formatter->link_to('?action=blogchanges&amp;date=' . $archive, $datetext) . $ket;
    }
    if ($bra) {
        return '<ul>' . $out . '</ul>';
    }
    return $out;
}
Example #5
0
function calendar_get_dates($formatter, $date = '', $page = '')
{
    global $DBInfo;
    $cache = new Cache_Text('blogchanges', array('hash' => ''));
    if (!$page) {
        $page = '.*';
    } else {
        $page = $DBInfo->pageToKeyname('.' . $page);
    }
    if (!$date) {
        $date = date('Ym');
    }
    $rule = "/^{$date}(\\d{2})" . $page . "\$/";
    $archives = array();
    $files = array();
    $cache->_caches($files);
    foreach ($files as $file) {
        if (preg_match($rule, $file, $match)) {
            $archives[intval($match[1])] = 1;
        }
    }
    #  return array_unique($archives);
    return $archives;
}
Example #6
0
function do_contributors($formatter, $options)
{
    global $DBInfo, $Config;
    if (!$formatter->page->exists()) {
        $formatter->send_header('', $options);
        $title = _("Page not found.");
        $formatter->send_title($title, '', $options);
        $formatter->send_footer('', $options);
        return;
    }
    // get contributors
    $params = array();
    $retval = array();
    $params['retval'] =& $retval;
    if (!empty($DBInfo->version_class)) {
        $cache = new Cache_Text('infostat');
        if (!$formatter->refresh and $cache->exists($formatter->page->name)) {
            $retval = $cache->fetch($formatter->page->name);
        }
        if (empty($retval)) {
            $version = $DBInfo->lazyLoad('version', $DBInfo);
            $out = $version->rlog($formatter->page->name, '', '', '-z');
            $retval = array();
            if (!isset($out[0])) {
                $msg = _("No older revisions available");
                $info = "<h2>{$msg}</h2>";
            } else {
                $params = array();
                $params['all'] = 1;
                $params['id'] = $options['id'];
                $params['retval'] =& $retval;
                $ret = _stat_rlog($formatter, $out, $params);
            }
            if (!empty($retval)) {
                $cache->update($formatter->page->name, $retval);
            }
        }
    }
    $formatter->send_header('', $options);
    $title = _("Contributors of this page");
    $formatter->send_title($title, '', $options);
    // do not check admin member users
    $user = $DBInfo->user;
    $ismember = $user->is_member;
    $total = count($retval['revs']);
    $total_lab = _("Total Revisions");
    $initial = $retval['rev'];
    $init_lab = _("Initial Revision");
    $contrib_lab = _("User");
    $edit_lab = _("Edit Count");
    echo <<<HEAD
<div class="wikiInfo">
<table class="wiki center">
<tr>
<th>{$total_lab}</th><th>{$total}</th>
</tr>
<tr>
<th>{$init_lab}</th><th>r{$initial}</th>
</tr>
<tr>
<th>{$contrib_lab}</th><th>{$edit_lab}</th>
</tr>
HEAD;
    $opt = intval($Config['mask_hostname']);
    // sort users
    $authors = array_keys($retval['users']);
    $edits = array();
    foreach ($authors as $n) {
        if ($retval['users'][$n]['edit'] > 0) {
            $edits[$n] = $retval['users'][$n]['edit'];
        }
    }
    // sort by edits
    arsort($edits);
    foreach ($edits as $u => $c) {
        if (!$ismember && preg_match('/^([0-9]+\\.){3}[0-9]+$/', $u)) {
            $u = _mask_hostname($u, $opt);
        } else {
            $u = $formatter->link_tag($formatter->page->urlname, '?action=userinfo&q=' . $u, $u);
        }
        echo "<tr><td>", $u, "</td><td>", $c, "</td></tr>\n";
    }
    echo "</table></div>";
    $formatter->send_footer('', $options);
    return;
}
Example #7
0
 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;
 }
Example #8
0
function do_userinfo($formatter, $options)
{
    global $DBInfo;
    $user =& $DBInfo->user;
    $min_ttl = !empty($DBInfo->user_suspend_time_default) ? intval($DBInfo->user_suspend_time_default) : 60 * 30;
    $formatter->send_header('', $options);
    $allowed = $DBInfo->security_class == 'acl' && $DBInfo->security->is_allowed($options['action'], $options);
    $ismember = $user->is_member;
    $suspend = !empty($options['suspend']) ? true : false;
    $pause = !empty($options['pause']) ? true : false;
    $comment_btn = !empty($options['comment_btn']) ? true : false;
    $comment = !empty($options['comment']) ? trim($options['comment']) : '';
    $uids = (array) $options['uid'];
    if ($user->id == 'Anonymous') {
        $myid = $_SERVER['REMOTE_ADDR'];
    } else {
        $myid = $user->id;
    }
    if (!$ismember && $allowed) {
        // not a member users
        $suspend = false;
        if (empty($comment)) {
            $comment_btn = false;
        } else {
            $comment_btn = true;
        }
        // a normal user can pause himself
        if (sizeof($uids) > 1 || $uids[0] != $myid) {
            $pause = false;
        }
        // reset type
        $options['type'] = '';
    }
    // cleanup comment
    $comment = strtr($comment, array("\n" => ' ', "\t" => ' '));
    $comment = _html_escape($comment);
    // FIXME only owners can delete/suspend users
    $can_delete_user = in_array($user->id, $DBInfo->owners);
    if ($allowed || $ismember) {
        if (isset($_POST) and empty($options['act']) and isset($options['uid'])) {
            $udb =& $DBInfo->udb;
            $type = !empty($options['type']) ? $options['type'] : '';
            if (!in_array($type, array('wait', 'del'))) {
                $type = '';
            }
            // normal user not allowed to suspend, delete user
            if (!$can_delete_user) {
                $suspend = false;
                $type = '';
            }
            $change = array();
            if ($can_delete_user and !$pause and !$comment_btn) {
                foreach ($uids as $uid) {
                    $uid = _stripslashes($uid);
                    if ($type == 'del' || $type == 'wait' || $suspend) {
                        $ret = $udb->activateUser($uid, $suspend);
                    } else {
                        $ret = $udb->delUser($uid);
                    }
                    if ($ret) {
                        $change[] = $uid;
                    }
                }
            } else {
                if ($comment_btn and !empty($comment)) {
                    $mb = new Cache_Text('msgboard');
                    foreach ($uids as $uid) {
                        $info = $mb->fetch($uid, 0);
                        $ttl = 0;
                        if ($info === false) {
                            $info = array();
                            $info['comment'] = '';
                        }
                        // add comment
                        if (!empty($comment)) {
                            // upate comments
                            $comments = array();
                            if (!empty($info['comment'])) {
                                $comments = explode("\n", $info['comment']);
                            }
                            $comments[] = date('Y-m-d H:i', time()) . "\t" . $myid . "\t" . $comment;
                            if ($uid == '127.0.0.1' and sizeof($comments) > 500) {
                                array_shift($comments);
                            } else {
                                if (sizeof($comments) > 1000) {
                                    array_shift($comments);
                                }
                            }
                            $info['comment'] = implode("\n", $comments);
                        }
                        $mb->update($uid, $info);
                        $change[] = $uid;
                    }
                } else {
                    if (!empty($uids) && $pause) {
                        // user can suspend temporary himself
                        if ($ismember || sizeof($uids) == 1 && $uid == $user->id) {
                            $change = $uids;
                        }
                    }
                }
            }
            if (!empty($change)) {
                $changed = implode(',', $change);
                if ($suspend) {
                    $options['msg'] = sprintf(_("User \"%s\" are suspended !"), _html_escape($changed));
                } else {
                    if ($pause) {
                        $options['msg'] = sprintf(_("User \"%s\" are temporary suspended !"), _html_escape($changed));
                    } else {
                        if ($type == 'del' || $type == 'wait') {
                            $options['msg'] = sprintf(_("User \"%s\" are activated !"), _html_escape($changed));
                        } else {
                            if ($comment_btn) {
                                $options['msg'] = sprintf(_("Message added to \"%s\"."), _html_escape($changed));
                            } else {
                                $options['msg'] = sprintf(_("User \"%s\" are deleted !"), _html_escape($changed));
                            }
                        }
                    }
                }
            }
            if ((!$suspend and $type == 'del' || $type == 'wait' or $pause) and !empty($change)) {
                // make users temporary suspdended 5-minutes
                // or temporary suspdended 30 minutes for newly suspended user
                // abusefilter cache
                $ac = new Cache_Text('abusefilter');
                // prepare to return
                $ret = array();
                $retval = array();
                $ret['retval'] =& $retval;
                foreach ($change as $q) {
                    // fetch monitor information
                    $info = $ac->fetch($q, 0, $ret);
                    $ttl = 0;
                    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'] = $q;
                        if ($pause) {
                            $ttl = $min_ttl;
                        } else {
                            $ttl = 60 * 5;
                        }
                    } else {
                        $new_info = $info;
                        $ttl = $retval['ttl'] - (time() - $retval['mtime']);
                        $new_info['id'] = $q;
                        if ($pause) {
                            $addttl = $min_ttl;
                        } else {
                            $addttl = 60 * 5;
                        }
                        if ($ttl < $addttl) {
                            $ttl = $addttl;
                        }
                    }
                    $new_info['suspended'] = true;
                    // add comment
                    if (!empty($comment)) {
                        // add comment
                        $comments = array();
                        if (!empty($new_info['comment'])) {
                            $comments = explode("\n", $new_info['comment']);
                        }
                        $comments[] = date('Y-m-d H:i', time()) . "\t" . $user->id . "\t" . $comment;
                        if ($q == '127.0.0.1' and sizeof($comments) > 10) {
                            array_shift($comments);
                        } else {
                            if (sizeof($comments) > 5) {
                                array_shift($comments);
                            }
                        }
                        $new_info['comment'] = implode("\n", $comments);
                    }
                    $ac->update($q, $new_info, $ttl);
                }
            }
        }
        $list = macro_UserInfo($formatter, '', $options);
    } else {
        $options['msg'] = sprintf(_("You are not allowed to \"%s\" !"), "userinfo");
        $list = '';
    }
    $options['.title'] = _("User Information");
    $formatter->send_title('', '', $options);
    print $list;
    $formatter->send_footer('', $options);
    return;
}
Example #9
0
        if (!$found_old) {
            $redirect = $retval['id'];
            $dest = $info[0];
            if (!isset($redirects[$dest])) {
                $redirects[$dest] = array();
            }
            $redirects[$dest][] = $redirect;
        }
    }
}
if ($debug) {
    var_dump($redirects);
}
// check redirect invert indices
echo "\r", 'Check invert redirect indices', "\n";
$rds = new Cache_Text('redirects');
$files = array();
$rds->_caches($files, array('prefix' => 1));
echo "\r", ' * invert redirect indices = ', count($files), "\n";
$update_redirects = true;
$j = 0;
foreach ($files as $f) {
    echo "\r" . $progress[$j % 4];
    $j++;
    // low level _fetch(), _remove()
    $info = $rds->_fetch($f, 0, $ret);
    $id = $retval['id'];
    if (!$found_old && !isset($redirects[$id])) {
        // already removed
        $rds->_remove($f);
        $update_redirects = false;
Example #10
0
function ajax_pagecount($formater, $params)
{
    global $DBInfo, $Config;
    $rc = new Cache_Text('redirect');
    $redirects = 0;
    $sc = new Cache_Text('settings');
    if (($redirects = $sc->fetch('redirect')) === false) {
        $rc = new Cache_Text('redirect');
        $redirects = 0;
        if (method_exists($rc, 'count')) {
            $redirects = $rc->count();
        }
        $sc->update('redirect', $redirects, 60 * 60 * 24);
    }
    $maxage = !empty($Config['proxy_maxage']) ? ', s-maxage=' . $Config['proxy_maxage'] : '';
    header('Content-Type: text/plain');
    header('Cache-Control: public' . $maxage . ',must-revalidate,post-check=0, pre-check=0');
    $count = $DBInfo->getCounter();
    echo '{pagecount:' . $count . ',redirect:' . $redirects . '}';
}
Example #11
0
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(']', '&#93;', $html);
                $html = "<![CDATA[" . $html . $extra . "]]>";
                #$html=strtr($html.$extra,array('&'=>'&amp;','<'=>'&lt;'));
            } 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(']', '&#93;', $html);
                    $html = "<![CDATA[" . $html . "]]>";
                } else {
                    $html = str_replace('&', '&amp;', $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+;)/', '&amp;', _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');
}
Example #12
0
function macro_FullSearch($formatter, $value = "", &$opts)
{
    global $DBInfo;
    $needle = $value;
    if ($value === true) {
        $needle = $value = $formatter->page->name;
        $options['noexpr'] = 1;
    } else {
        # for MoinMoin compatibility with [[FullSearch("blah blah")]]
        #$needle = preg_replace("/^('|\")([^\\1]*)\\1/","\\2",$value);
        $needle = $value;
    }
    // for pagination
    $offset = '';
    if (!empty($opts['offset']) and is_numeric($opts['offset'])) {
        if ($opts['offset'] > 0) {
            $offset = $opts['offset'];
        }
    }
    $url = $formatter->link_url($formatter->page->urlname);
    $fneedle = _html_escape($needle);
    $tooshort = !empty($DBInfo->fullsearch_tooshort) ? $DBInfo->fullsearch_tooshort : 2;
    $m1 = _("Display context of search results");
    $m2 = _("Search BackLinks only");
    $m3 = _("Case-sensitive searching");
    $msg = _("Go");
    $bchecked = !empty($DBInfo->use_backlinks) ? 'checked="checked"' : '';
    $form = <<<EOF
<form method='get' action='{$url}'>
   <input type='hidden' name='action' value='fullsearch' />
   <input name='value' size='30' value="{$fneedle}" />
   <span class='button'><input type='submit' class='button' value='{$msg}' /></span><br />
   <input type='checkbox' name='backlinks' value='1' {$bchecked} />{$m2}<br />
   <input type='checkbox' name='context' value='20' />{$m1}<br />
   <input type='checkbox' name='case' value='1' />{$m3}<br />
   </form>
EOF;
    if (!isset($needle[0]) or !empty($opts['form'])) {
        # or blah blah
        $opts['msg'] = _("No search text");
        return $form;
    }
    $opts['form'] = $form;
    # XXX
    $excl = array();
    $incl = array();
    if (!empty($opts['noexpr'])) {
        $tmp = preg_split("/\\s+/", $needle);
        $needle = $value = join('|', $tmp);
        $raw_needle = implode(' ', $tmp);
        $needle = preg_quote($needle);
    } else {
        if (empty($opts['backlinks'])) {
            $terms = preg_split('/((?<!\\S)[-+]?"[^"]+?"(?!\\S)|\\S+)/s', $needle, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
            $common_words = array('the', 'that', 'where', 'what', 'who', 'how', 'too', 'are');
            $common = array();
            foreach ($terms as $term) {
                if (trim($term) == '') {
                    continue;
                }
                if (preg_match('/^([-+]?)("?)([^\\2]+?)\\2$/', $term, $match)) {
                    $word = str_replace(array('\\', '.', '*'), '', $match[3]);
                    $len = strlen($word);
                    if (!$match[1] and $match[2] != '"') {
                        if ($len < $tooshort or in_array($word, $common_words)) {
                            $common[] = $word;
                            continue;
                        }
                    }
                    if ($match[1] == '-') {
                        $excl[] = $word;
                    } else {
                        $incl[] = $word;
                    }
                }
            }
            $needle = implode('|', $incl);
            $needle = _preg_search_escape($needle);
            $raw_needle = implode(' ', $incl);
            $test = validate_needle($needle);
            if ($test === false) {
                // invalid regex
                $tmp = array_map('preg_quote', $incl);
                $needle = implode('|', $tmp);
            }
            $excl_needle = implode('|', $excl);
            $test = validate_needle($excl_needle);
            if ($test2 === false) {
                // invalid regex
                $tmp = array_map('preg_quote', $excl);
                $excl_needle = implode('|', $tmp);
            }
        } else {
            $cneedle = _preg_search_escape($needle);
            $test = validate_needle($cneedle);
            if ($test === false) {
                $needle = preg_quote($needle);
            } else {
                $needle = $cneedle;
            }
        }
    }
    $test3 = trim($needle);
    if (!isset($test3[0])) {
        $opts['msg'] = _("Empty expression");
        return $form;
    }
    # set arena and sid
    if (!empty($opts['backlinks'])) {
        $arena = 'backlinks';
    } else {
        if (!empty($opts['keywords'])) {
            $arena = 'keywords';
        } else {
            $arena = 'fullsearch';
        }
    }
    if ($arena == 'fullsearch') {
        $sid = md5($value . 'v' . $offset);
    } else {
        $sid = $value;
    }
    $delay = !empty($DBInfo->default_delaytime) ? $DBInfo->default_delaytime : 0;
    # retrieve cache
    $fc = new Cache_text($arena);
    if (!$formatter->refresh and $fc->exists($sid)) {
        $data = $fc->fetch($sid);
        if (!empty($opts['backlinks'])) {
            // backlinks are not needed to check it.
            $hits = $data;
            // also fetch redirects
            $r = new Cache_Text('redirects');
            $redirects = $r->fetch($sid);
        } else {
            if (is_array($data)) {
                # check cache mtime
                $cmt = $fc->mtime($sid);
                # check update or not
                $dmt = $DBInfo->mtime();
                if ($dmt > $cmt + $delay) {
                    # XXX crude method
                    $data = array();
                } else {
                    # XXX smart but incomplete method
                    if (isset($data['hits'])) {
                        $hits =& $data['hits'];
                    } else {
                        $hits =& $data;
                    }
                    foreach ($hits as $p => $c) {
                        $mp = $DBInfo->getPage($p);
                        $mt = $mp->mtime();
                        if ($mt > $cmt + $delay) {
                            $data = array();
                            break;
                        }
                    }
                }
                if (isset($data['searched'])) {
                    extract($data);
                } else {
                    if (!empty($data)) {
                        $hits = $data;
                    }
                }
            }
        }
    }
    $pattern = '/' . $needle . '/';
    if (!empty($excl_needle)) {
        $excl_pattern = '/' . $excl_needle . '/';
    }
    if (!empty($opts['case'])) {
        $pattern .= "i";
        $excl_pattern .= "i";
    }
    if (isset($hits)) {
        if (in_array($arena, array('backlinks', 'keywords'))) {
            $test = key($hits);
            if (is_int($test) and $hits[$test] != -1) {
                // fix compatible issue for keywords, backlinks
                $hits = array_flip($hits);
                foreach ($hits as $k => $v) {
                    $hits[$k] = -1;
                }
                reset($hits);
            }
            // check invert redirect index
            if (!empty($redirects)) {
                $redirects = array_flip($redirects);
                ksort($redirects);
                foreach ($redirects as $k => $v) {
                    $hits[$k] = -2;
                }
                reset($hits);
            }
        }
        //continue;
    } else {
        $hits = array();
        set_time_limit(0);
        if (!empty($opts['backlinks']) and empty($DBInfo->use_backlink_search)) {
            $hits = array();
        } else {
            if (!empty($opts['keywords']) and empty($DBInfo->use_keyword_search)) {
                $hits = array();
            } else {
                if (!empty($opts['backlinks'])) {
                    $pages = $DBInfo->getPageLists();
                    #$opts['context']=-1; # turn off context-matching
                    $cache = new Cache_text("pagelinks");
                    foreach ($pages as $page_name) {
                        $links = $cache->fetch($page_name);
                        if (is_array($links)) {
                            if (in_array($value, $links)) {
                                $hits[$page_name] = -1;
                            }
                            // ignore count if < 0
                        }
                    }
                } else {
                    if (!empty($opts['keywords'])) {
                        $pages = $DBInfo->getPageLists();
                        $opts['context'] = -1;
                        # turn off context-matching
                        $cache = new Cache_text("keyword");
                        foreach ($pages as $page_name) {
                            $links = $cache->fetch($page_name);
                            // XXX
                            if (is_array($links)) {
                                if (stristr(implode(' ', $links), $needle)) {
                                    $hits[$page_name] = -1;
                                }
                                // ignore count if < 0
                            }
                        }
                    } else {
                        $params = array();
                        $ret = array();
                        $params['ret'] =& $ret;
                        $params['offset'] = $offset;
                        $params['search'] = 1;
                        $params['incl'] = $incl;
                        $params['excl'] = $excl;
                        $pages = $DBInfo->getPageLists($params);
                        // set time_limit
                        $mt = explode(' ', microtime());
                        $timestamp = $mt[0] + $mt[1];
                        $j = 0;
                        $time_limit = isset($DBInfo->process_time_limit) ? $DBInfo->process_time_limit : 3;
                        // default 3-seconds
                        $j = 0;
                        while (list($_, $page_name) = each($pages)) {
                            // check time_limit
                            if ($time_limit and $j % 30 == 0) {
                                $mt = explode(' ', microtime());
                                $now = $mt[0] + $mt[1];
                                if ($now - $timestamp > $time_limit) {
                                    break;
                                }
                            }
                            $j++;
                            $p = new WikiPage($page_name);
                            if (!$p->exists()) {
                                continue;
                            }
                            $body = $p->_get_raw_body();
                            #$count = count(preg_split($pattern, $body))-1;
                            $count = preg_match_all($pattern, $body, $matches);
                            if ($count) {
                                foreach ($excl as $ex) {
                                    if (stristr($body, $ex)) {
                                        continue;
                                    }
                                }
                                foreach ($incl as $in) {
                                    if (!stristr($body, $in)) {
                                        continue;
                                    }
                                }
                                $hits[$page_name] = $count;
                            }
                        }
                        $searched = $j > 0 ? $j : 0;
                        $offset = !empty($offset) ? $offset + $j : $j;
                    }
                }
            }
        }
        #krsort($hits);
        #ksort($hits);
        $name = array_keys($hits);
        array_multisort($hits, SORT_DESC, $name, SORT_ASC);
        if (in_array($arena, array('backlinks', 'keywords'))) {
            $fc->update($sid, $name);
        } else {
            $fc->update($sid, array('hits' => $hits, 'offset' => $offset, 'searched' => $searched));
        }
    }
    $opts['hits'] = $hits;
    $opts['hit'] = count($hits);
    $opts['all'] = $DBInfo->getCounter();
    if ($opts['all'] > $searched) {
        $opts['next'] = $offset;
        $opts['searched'] = $searched;
    }
    if (!empty($opts['call'])) {
        return $hits;
    }
    $out = "<!-- RESULT LIST START -->";
    // for search plugin
    $out .= "<ul class='fullsearchResult'>";
    $idx = 1;
    $checkbox = '';
    while (list($page_name, $count) = each($hits)) {
        $pgname = _html_escape($page_name);
        if (!empty($opts['checkbox'])) {
            $checkbox = "<input type='checkbox' name='pagenames[]' value=\"{$pgname}\" />";
        }
        $out .= '<!-- RESULT ITEM START -->';
        // for search plugin
        $out .= '<li>' . $checkbox . $formatter->link_tag(_rawurlencode($page_name), '?action=highlight&amp;value=' . _urlencode($value), $pgname, 'tabindex="' . $idx . '"');
        if ($count > 0) {
            $out .= ' . . . . ' . sprintf($count == 1 ? _("%d match") : _("%d matches"), $count);
        } else {
            if ($count == -2) {
                $out .= " <span class='redirectIcon'><span>" . _("Redirect page") . "</span></span>\n";
            }
        }
        if (!empty($opts['context']) and $opts['context'] > 0) {
            # search matching contexts
            $p = new WikiPage($page_name);
            if ($p->exists()) {
                $body = $p->_get_raw_body();
                $out .= find_needle($body, $needle, $excl_needle, $opts['context']);
            }
        }
        $out .= "</li>\n";
        $out .= '<!-- RESULT ITEM END -->';
        // for search plugin
        $idx++;
        #if ($idx > 50) break;
    }
    $out .= "</ul>\n";
    $out .= "<!-- RESULT LIST END -->";
    // for search plugin
    return $out;
}
Example #13
0
function macro_Stat($formatter, $value, $options = array())
{
    global $DBInfo;
    if (!empty($DBInfo->version_class)) {
        $cache = new Cache_Text('infostat');
        $retval = array();
        if (!$formatter->refresh and $cache->exists($formatter->page->name)) {
            $retval = $cache->fetch($formatter->page->name);
        }
        if (empty($retval)) {
            $version = $DBInfo->lazyLoad('version', $DBInfo);
            $out = $version->rlog($formatter->page->name, '', '', '-z');
            $retval = array();
            if (!isset($out[0])) {
                $msg = _("No older revisions available");
                $info = "<h2>{$msg}</h2>";
            } else {
                $params = array();
                $params['all'] = 1;
                $params['id'] = $options['id'];
                $params['retval'] =& $retval;
                $ret = _stat_rlog($formatter, $out, $params);
            }
            if (!empty($retval)) {
                $cache->update($formatter->page->name, $retval);
            }
        }
        $merge_ip = true;
        if (!empty($DBInfo->stat_no_merge_ip_users) && empty($options['merge_ip_users'])) {
            $merge_ip = false;
        }
        if ($merge_ip) {
            $users =& $retval['users'];
            foreach ($users as $k => $v) {
                foreach ($v['ip'] as $ip => $dummy) {
                    $users[$k]['add'] += $users[$ip]['add'];
                    $users[$k]['del'] += $users[$ip]['del'];
                    $users[$k]['edit'] += $users[$ip]['edit'];
                    $users[$k]['rev'] = array_merge($users[$k]['rev'], $users[$ip]['rev']);
                    unset($users[$ip]);
                }
            }
        }
        if (!empty($retval)) {
            if (isset($options['retval'])) {
                $info = _render_stat($formatter, $retval, $options);
                return $info;
            } else {
                $info = _render_stat($formatter, $retval, $options);
            }
            $formatter->register_javascripts('js/chart/Chart.min.js');
        }
        if (isset($options['retval'])) {
            return -1;
        }
    } else {
        $msg = _("Version info is not available in this wiki");
        $info = "<h2>{$msg}</h2>";
    }
    if (isset($options['retval'])) {
        return -1;
    }
    return $info;
}
Example #14
0
    $formatter->set_wordrule();
}
$options = array();
if (class_exists('Timer')) {
    $timing = new Timer();
    $options['timer'] =& $timing;
    $options['timer']->Check("load");
}
$handle = opendir($DBInfo->text_dir);
if (!is_resource($handle)) {
    echo "Can't open {$DBInfo->text_dir}\n";
    exit;
}
set_time_limit(0);
$cache = new Cache_Text('pagelinks');
$bc = new Cache_Text('backlinks');
$ii = 1;
while (($file = readdir($handle)) !== false) {
    if (is_dir($DBInfo->text_dir . "/" . $file)) {
        continue;
    }
    $pagename = $DBInfo->keyToPagename($file);
    print "* [{$ii}] {$pagename} ";
    $ii++;
    $p = $DBInfo->getPage($pagename);
    $formatter->page = $p;
    $raw = $p->_get_raw_body();
    $pagelinks = get_pagelinks($formatter, $raw);
    $cache->update($pagename, $pagelinks);
    foreach ($pagelinks as $a) {
        if (!isset($a[0])) {
Example #15
0
function do_editlogbin($formatter, $params = array())
{
    global $Config, $DBInfo;
    $cache = new Cache_Text('editlogbin');
    if (!empty($params['title'])) {
        if (!$DBInfo->hasPage($params['title'])) {
            unset($params['title']);
        }
    }
    $args = array();
    $user = !empty($params['q']) ? $params['q'] : '';
    $start = !empty($params['start']) ? $params['start'] : '';
    $domain = !empty($params['domain']) ? $params['domain'] : '';
    $title = !empty($params['title']) ? $params['title'] : '';
    // get timestamp
    $oldest_stamp = !empty($Config['editlogbin_datetime_oldest']) ? strtotime($Config['editlogbin_datetime_oldest']) : strtotime('-1 year');
    if ($oldest_stamp < strtotime('-10 years')) {
        // too old
        $oldest_stamp = strtotime('-1 year');
    }
    if (!empty($start)) {
        if (is_numeric($start)) {
            // timestamp
            $from = $start;
        } else {
            $from = strtotime($start);
        }
        // convert to timestamp
    } else {
        $from = $oldest_stamp;
    }
    // restrict range
    $params['until'] = null;
    // reset
    if ($from < $oldest_stamp) {
        $max_range = !empty($Config['editlogbin_datetime_max_range']) ? strtotime($Config['editlogbin_datetime_max_range'], $from) : strtotime('1 year', $from);
        $params['until'] = $max_range;
    }
    //echo date('Y.m.d H.i.s', $params['until']);
    $mtime = $DBInfo->mtime();
    $key = $user . '.' . $from . '.' . $domain . '.' . $title . $mtime;
    if (empty($formatter->refresh) && ($val = $cache->fetch($key)) !== false) {
        header('Content-Type: text/plain');
        echo json_encode($val['data']);
        return;
    }
    $fp = fopen($Config['editlog_name'], 'r');
    $seek = _editlog_seek($fp, $from);
    $data = _editlog_binning($fp, $seek, $from, 60 * 60 * 24, $params);
    fclose($fp);
    header('Content-Type: text/plain');
    $cache->update($key, $data, 60 * 60 * 24);
    // TTL to 24 hour
    echo json_encode($data['data']);
}
Example #16
0
function macro_WikimediaCommons($formatter, $value, $params = array())
{
    global $DBInfo, $Config;
    // FIXME urldecode for some cases
    $value = urldecode($value);
    if (($p = strpos($value, ',')) !== false) {
        $arg = substr($value, $p + 1);
        $value = substr($value, 0, $p);
        $arg = preg_replace('@\\s*,\\s*@', ',', $arg);
        $arg = preg_replace('@\\s*=\\s*@', '=', $arg);
        $args = explode(',', $arg);
    }
    // check full url
    if (preg_match('@^https?://upload\\.wikimedia\\.org/wikipedia/commons/(thumb/)?./../([^/]+\\.(?:gif|jpe?g|png|svg))(?(1)/(\\d+px)-\\2)@', $value, $m)) {
        $remain = substr($value, strlen($m[0]));
        $value = $m[2];
        if (!empty($m[3])) {
            $width = intval($m[3]);
        }
    }
    $styles = array();
    foreach ($args as $arg) {
        $k = $v = '';
        if (($p = strpos($arg, '=')) !== false) {
            $k = substr($arg, 0, $p);
            $v = substr($arg, $p + 1);
        } else {
            continue;
        }
        $k = strtolower($k);
        switch ($k) {
            case 'width':
            case 'height':
                if (preg_match('@^(\\d+)(px|%)?$@', $v, $m)) {
                    if (isset($m[2]) && $m[2] == '%') {
                        $styles[$k] = $v;
                    } else {
                        $styles[$k] = $v;
                        ${$k} = intval($m[1]);
                    }
                }
                break;
            case 'align':
                $v = strtolower($v);
                if (in_array($v, array('left', 'right', 'center'))) {
                    $addClass = ' img' . ucfirst($v);
                }
                break;
        }
    }
    $common = new Cache_Text('wikicommons');
    $key = $value;
    if (isset($width)) {
        $key .= $width;
    }
    if (isset($height)) {
        $key .= '.h' . $height;
    }
    if (!empty($formatter->refresh) || ($images = $common->fetch($key)) === false) {
        $api_url = 'https://commons.wikimedia.org/w/api.php';
        $data = array('action' => 'query', 'titles' => 'Image:' . $value, 'prop' => 'imageinfo', 'iiprop' => 'extmetadata|url', 'format' => 'json', 'rawcontinue' => '1');
        if (!empty($width)) {
            $data['iiurlwidth'] = min(1280, $width);
        } else {
            if (!empty($height)) {
                $data['iiurlheight'] = min(1280, $height);
            } else {
                // default image width
                $data['iiurlwidth'] = 640;
            }
        }
        require_once dirname(__FILE__) . '/../lib/HTTPClient.php';
        $http = new HTTPClient();
        $save = ini_get('max_execution_time');
        set_time_limit(0);
        $http->sendRequest($api_url, $data, 'POST');
        set_time_limit($save);
        // FIXME
        if ($http->status != 200) {
            return '';
        }
        $res = json_decode($http->resp_body);
        $images = $res->query->pages;
        $common->update($key, $images);
    }
    $image = current($images);
    $image_url = $image->imageinfo[0]->thumburl;
    $desc_url = $image->imageinfo[0]->descriptionurl;
    if (empty($styles['width'])) {
        $styles['width'] = $image->imageinfo[0]->thumbwidth . 'px';
    }
    $style = '';
    foreach ($styles as $k => $v) {
        $style .= $k . ':' . $v . ';';
    }
    if (!empty($style)) {
        $style = ' style="' . $style . '"';
    }
    $copyright = $image->imageinfo[0]->extmetadata->Copyrighted->value;
    $description = $image->imageinfo[0]->extmetadata->ImageDescription->value;
    $author = $image->imageinfo[0]->extmetadata->Artist->value;
    $license = $image->imageinfo[0]->extmetadata->License->value;
    if (!empty($formatter->fetch_images) && !empty($image_url)) {
        $image_url = $formatter->fetch_action . str_replace(array('&', '?'), array('%26', '%3f'), $image_url);
        // use thumbnails ?
        if (!empty($formatter->use_thumb_by_default)) {
            $image_url .= '&amp;thumbwidth=' . $formatter->thumb_width;
        }
    }
    $copyrighted = $copyright == 'True';
    $info = ($copyrighted ? '&copy;' : '(&#596;) ') . $author;
    if ($copyrighted) {
        $info .= " ({$license})";
    }
    $out = '<div class="externalImage">';
    if (empty($addClass)) {
        $cls = ' class="' . $addClass . '"';
    }
    $out .= "<div" . $cls . "><img src='{$image_url}'{$style}>";
    $out .= "<div class='info'>" . $info . ' from ' . "<a href='{$desc_url}' target='_blank'>WikiMedia Commons</a></div>";
    $out .= "</div>";
    if (!empty($DBInfo->wikimediacommons_use_description) && !empty($description)) {
        $out .= '<div class="desc">' . $description . '</div>';
    }
    $out .= "</div>\n";
    return $out;
}
Example #17
0
function _index($formatter, $pages, $params = array())
{
    global $Config;
    if (isset($GLOBALS['.index_id'])) {
        $GLOBALS['.index_id']++;
        $index_id = $GLOBALS['.index_id'];
    } else {
        $index_id = $GLOBALS['.index_id'] = 0;
    }
    $anchor = 'index-anchor' . $index_id;
    $count = !empty($params['.count']) ? true : false;
    if ($count) {
        $cc = new Cache_Text('category');
        $bc = new Cache_Text('backlinks');
    }
    $keys = array();
    $key = '';
    $out = '';
    $redirect = '';
    $n = 0;
    foreach ($pages as $page => $info) {
        // redirect case
        if ($info == -2) {
            $urlname = _urlencode($page);
            $redirect .= '<li>' . $formatter->link_tag($urlname, '', _html_escape($page));
            $redirect .= " <span class='redirectIcon'><span>" . _("Redirect page") . "</span></span>\n";
            $redirect .= "</li>\n";
            $n++;
            continue;
        } else {
            if (is_int($info)) {
                $title = $page;
            } else {
                $title = $info;
            }
        }
        $pkey = get_key("{$title}");
        if ($key != $pkey) {
            if (isset($pkey[0])) {
                $keys[] = $pkey;
            }
            $key = $pkey;
            if (isset($out[0])) {
                $out .= "</ul></div>";
            }
            $out .= "<div><a name='{$key}'></a><h2><a href='#{$anchor}'>{$key}</a></h2>\n";
            $out .= "<ul>";
        }
        $urlname = _urlencode($page);
        $extra = '';
        // count subpages
        if ($count) {
            // get backlinks mtime
            $mtime = $bc->mtime($page);
            // get category counter info
            $cci = $cc->fetch($page, $mtime);
            if ($formatter->refresh || $cci === false) {
                // count backlinks
                $links = $bc->fetch($page);
                $c = 0;
                $p = 0;
                foreach ($links as $link) {
                    if (preg_match('@' . $Config['category_regex'] . '@', $link)) {
                        $c++;
                    } else {
                        $p++;
                    }
                }
                // update cotegory counter info
                $cci = array('C' => $c, 'P' => $p);
                $cc->update($page, $cci);
            }
            // mediawiki like category status: Category (XX C, YY P)
            $tmp = array();
            if (!empty($cci['C'])) {
                $tmp[] = $cci['C'] . ' C';
            }
            if (!empty($cci['P'])) {
                $tmp[] = $cci['P'] . ' P';
            }
            if (isset($tmp[0])) {
                $extra = ' (' . implode(', ', $tmp) . ')';
            }
        }
        $out .= '<li>' . $formatter->link_tag($urlname, '', _html_escape($title));
        $out .= $extra;
        if ($info == -2) {
            $out .= " <span class='redirectIcon'><span>" . _("Redirect page") . "</span></span>\n";
        }
        $out .= "</li>\n";
        $n++;
    }
    $out .= "</ul></div>\n";
    $keys = array_unique($keys);
    $index = array();
    foreach ($keys as $key) {
        $name = strval($key);
        $tag = '#' . $key;
        if ($name == 'Others') {
            $name = _("Others");
        }
        $index[] = "<a href='{$tag}'>{$name}</a>";
    }
    $str = implode(' | ', $index);
    if (isset($redirect[0])) {
        $redirect = '<div><h2>' . _("Redirects") . '</h2><ul>' . $redirect . '</ul></div>';
    }
    if ($n > 10) {
        $attr = " class='index-group'";
    } else {
        $attr = '';
    }
    if ($n > 0) {
        return "<div style='text-align:center'><a name='{$anchor}'></a>{$str}</div>\n<div{$attr}>{$redirect}{$out}</div>";
    } else {
        return false;
    }
}
Example #18
0
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);
}
Example #19
0
    function send_header($header = "", $options = array())
    {
        global $DBInfo;
        $plain = 0;
        $media = 'media="screen"';
        if (isset($options['action'][0]) and $options['action'] == 'print') {
            $media = '';
        }
        if (empty($options['is_robot']) && isset($this->pi['#redirect'][0]) && !empty($options['pi'])) {
            $options['value'] = $this->pi['#redirect'];
            $options['redirect'] = 1;
            $this->pi['#redirect'] = '';
            do_goto($this, $options);
            return true;
        }
        $header = !empty($header) ? $header : (!empty($options['header']) ? $options['header'] : null);
        if (!empty($header)) {
            foreach ((array) $header as $head) {
                $this->header($head);
                if (preg_match("/^content\\-type: text\\//i", $head)) {
                    $plain = 1;
                }
            }
        }
        $mtime = isset($options['mtime']) ? $options['mtime'] : $this->page->mtime();
        if ($mtime > 0) {
            $modified = $mtime > 0 ? gmdate('Y-m-d\\TH:i:s', $mtime) . '+00:00' : null;
            $lastmod = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
            $meta_lastmod = '<meta http-equiv="last-modified" content="' . $lastmod . '" />' . "\n";
        }
        if (is_static_action($options) or !empty($DBInfo->use_conditional_get) and !empty($mtime) and empty($options['nolastmod']) and $this->page->is_static) {
            $this->header('Last-Modified: ' . $lastmod);
            $etag = $this->page->etag($options);
            if (!empty($options['etag'])) {
                $this->header('ETag: "' . $options['etag'] . '"');
            } else {
                $this->header('ETag: "' . $etag . '"');
            }
        }
        // custom headers
        if (!empty($DBInfo->site_headers)) {
            foreach ((array) $DBInfo->site_headers as $head) {
                $this->header($head);
            }
        }
        $content_type = isset($DBInfo->content_type[0]) ? $DBInfo->content_type : 'text/html';
        $force_charset = '';
        if (!empty($DBInfo->force_charset)) {
            $force_charset = '; charset=' . $DBInfo->charset;
        }
        if (!$plain) {
            $this->header('Content-type: ' . $content_type . $force_charset);
        }
        if (!empty($options['action_mode']) and $options['action_mode'] == 'ajax') {
            return true;
        }
        # disabled
        #$this->header("Vary: Accept-Encoding, Cookie");
        #if (strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') and function_exists('ob_gzhandler')) {
        #  ob_start('ob_gzhandler');
        #  $etag.= '.gzip';
        #}
        if (!empty($options['metatags'])) {
            $metatags = $options['metatags'];
        } else {
            $metatags = $DBInfo->metatags;
        }
        if (!empty($options['noindex']) || !empty($this->pi['#noindex']) || (!empty($mtime) and !empty($DBInfo->delayindex) and time() - $mtime < $DBInfo->delayindex)) {
            // delay indexing like as dokuwiki
            if (preg_match("/<meta\\s+name=('|\")?robots\\1[^>]+>/i", $metatags)) {
                $metatags = preg_replace("/<meta\\s+name=('|\")?robots\\1[^>]+>/i", '<meta name="robots" content="noindex,nofollow" />', $metatags);
            } else {
                $metatags .= '<meta name="robots" content="noindex,nofollow" />' . "\n";
            }
        }
        if (isset($DBInfo->metatags_extra)) {
            $metatags .= $DBInfo->metatags_extra;
        }
        $js = !empty($DBInfo->js) ? $DBInfo->js : '';
        if (!$plain) {
            if (isset($options['trail'])) {
                $this->set_trailer($options['trail'], $this->page->name);
            } else {
                if ($DBInfo->origin) {
                    $this->set_origin($this->page->name);
                }
            }
            # find upper page
            $up_separator = '/';
            if (!empty($this->use_namespace)) {
                $up_separator .= '|\\:';
            }
            $pos = 0;
            preg_match('@(' . $up_separator . ')@', $this->page->name, $sep);
            # NameSpace/SubPage or NameSpace:SubNameSpacePage
            if (isset($sep[1])) {
                $pos = strrpos($this->page->name, $sep[1]);
            }
            if ($pos > 0) {
                $upper = substr($this->page->urlname, 0, $pos);
            } else {
                if ($this->group) {
                    $upper = _urlencode(substr($this->page->name, strlen($this->group)));
                }
            }
            // setup keywords
            $keywords = '';
            if (!empty($this->pi['#keywords'])) {
                $keywords = _html_escape($this->pi['#keywords']);
            } else {
                $keys = array();
                $dummy = strip_tags($this->page->title);
                $keys = explode(' ', $dummy);
                $keys[] = $dummy;
                $keys = array_unique($keys);
                $keywords = implode(', ', $keys);
            }
            // add redirects as keywords
            if (!empty($DBInfo->use_redirects_as_keywords)) {
                $r = new Cache_Text('redirects');
                $redirects = $r->fetch($this->page->name);
                if ($redirects !== false) {
                    sort($redirects);
                    $keywords .= ', ' . _html_escape(implode(', ', $redirects));
                }
            }
            // add site specific keywords
            if (!empty($DBInfo->site_keywords)) {
                $keywords .= ', ' . $DBInfo->site_keywords;
            }
            $keywords = "<meta name=\"keywords\" content=\"{$keywords}\" />\n";
            # find sub pages
            if (empty($options['action']) and !empty($DBInfo->use_subindex)) {
                $scache = new Cache_text('subpages');
                if (!($subs = $scache->exists($this->page->name))) {
                    if (($p = strrpos($this->page->name, '/')) !== false) {
                        $rule = _preg_search_escape(substr($this->page->name, 0, $p));
                    } else {
                        $rule = _preg_search_escape($this->page->name);
                    }
                    $subs = $DBInfo->getLikePages('^' . $rule . '\\/', 1);
                    if ($subs) {
                        $scache->update($this->page->name, 1);
                    }
                }
                if (!empty($subs)) {
                    $subindices = '';
                    if (empty($DBInfo->use_ajax)) {
                        $subindices = '<div>' . $this->macro_repl('PageList', '', array('subdir' => 1)) . '</div>';
                        $btncls = 'class="close"';
                    } else {
                        $btncls = '';
                    }
                    $this->subindex = "<fieldset id='wikiSubIndex'>" . "<legend title='[+]' {$btncls} onclick='javascript:toggleSubIndex(\"wikiSubIndex\")'></legend>" . $subindices . "</fieldset>\n";
                }
            }
            if (!empty($options['.title'])) {
                $options['title'] = $options['.title'];
            } else {
                if (empty($options['title'])) {
                    $options['title'] = !empty($this->pi['#title']) ? $this->pi['#title'] : $this->page->title;
                    $options['title'] = _html_escape($options['title']);
                } else {
                    $options['title'] = strip_tags($options['title']);
                }
            }
            $theme_type = !empty($this->_newtheme) ? $this->_newtheme : '';
            if (empty($options['css_url'])) {
                $options['css_url'] = $DBInfo->css_url;
            }
            if (empty($this->pi['#nodtd']) and !isset($options['retstr']) and $theme_type != 2) {
                if (!empty($this->html5)) {
                    if (is_string($this->html5)) {
                        echo $this->html5;
                    } else {
                        echo '<!DOCTYPE html>', "\n", '<html xmlns="http://www.w3.org/1999/xhtml">', "\n";
                    }
                } else {
                    echo $DBInfo->doctype;
                }
            }
            if ($theme_type == 2 or isset($options['retstr'])) {
                ob_start();
            } else {
                echo "<head>\n";
            }
            echo '<meta http-equiv="Content-Type" content="' . $content_type . ';charset=' . $DBInfo->charset . "\" />\n";
            echo <<<JSHEAD
<script type="text/javascript">
/*<![CDATA[*/
_url_prefix="{$DBInfo->url_prefix}";
/*]]>*/
</script>
JSHEAD;
            echo $metatags, $js, "\n";
            echo $this->get_javascripts();
            echo $keywords;
            if (!empty($meta_lastmod)) {
                echo $meta_lastmod;
            }
            $sitename = !empty($DBInfo->title_sitename) ? $DBInfo->title_sitename : $DBInfo->sitename;
            if (!empty($DBInfo->title_msgstr)) {
                $site_title = sprintf($DBInfo->title_msgstr, $sitename, $options['title']);
            } else {
                $site_title = $options['title'] . ' - ' . $sitename;
            }
            // set OpenGraph information
            $act = !empty($options['action']) ? strtolower($options['action']) : 'show';
            $is_show = $act == 'show';
            $is_frontpage = $this->page->name == get_frontpage($DBInfo->lang);
            if (!$is_frontpage && !empty($DBInfo->frontpages) && in_array($this->page->name, $DBInfo->frontpages)) {
                $is_frontpage = true;
            }
            if (!empty($DBInfo->canonical_url)) {
                if (($p = strpos($DBInfo->canonical_url, '%s')) !== false) {
                    $page_url = sprintf($DBInfo->canonical_url, $this->page->urlname);
                } else {
                    $page_url = $DBInfo->canonical_url . $this->page->urlname;
                }
            } else {
                $page_url = qualifiedUrl($this->link_url($this->page->urlname));
            }
            if ($is_show && $this->page->exists()) {
                $oc = new Cache_text('opengraph');
                if ($this->refresh || ($val = $oc->fetch($this->page->name, $this->page->mtime())) === false) {
                    $val = array('description' => '', 'image' => '');
                    if (!empty($this->pi['#redirect'])) {
                        $desc = '#redirect ' . $this->pi['#redirect'];
                    } else {
                        $raw = $this->page->_get_raw_body();
                        if (!empty($this->pi['#description'])) {
                            $desc = $this->pi['#description'];
                        } else {
                            $cut_size = 2000;
                            if (!empty($DBInfo->get_description_cut_size)) {
                                $cut_size = $DBInfo->get_description_cut_size;
                            }
                            $cut = mb_strcut($raw, 0, $cut_size, $DBInfo->charset);
                            $desc = get_description($cut);
                            if ($desc !== false) {
                                $desc = mb_strcut($desc, 0, 200, $DBInfo->charset) . '...';
                            } else {
                                $desc = $this->page->name;
                            }
                        }
                    }
                    $val['description'] = _html_escape($desc);
                    if (!empty($this->pi['#image'])) {
                        if (preg_match('@^(ftp|https?)://@', $this->pi['#image'])) {
                            $page_image = $this->pi['#image'];
                        } else {
                            if (preg_match('@^attachment:("[^"]+"|[^\\s]+)@/', $this->pi['#image'], $m)) {
                                $image = $this->macro_repl('attachment', $m[1], array('link_url' => 1));
                                if ($image[0] != 'a') {
                                    $page_image = $image;
                                }
                            }
                        }
                    }
                    if (empty($page_image)) {
                        // extract the first image
                        $punct = '<>"\'}\\]\\|\\!';
                        if (preg_match_all('@(?<=\\b)((?:attachment:(?:"[^' . $punct . ']+"|[^\\s' . $punct . '?]+)|' . '(?:https?|ftp)://(?:[^\\s' . $punct . ']+)\\.(?:png|jpe?g|gif)))@', $raw, $m)) {
                            foreach ($m[1] as $img) {
                                if ($img[0] == 'a') {
                                    $img = substr($img, 11);
                                    // strip attachment:
                                    $image = $this->macro_repl('attachment', $img, array('link_url' => 1));
                                    if ($image[0] != 'a' && preg_match('@\\.(png|jpe?g|gif)$@i', $image)) {
                                        $page_image = $image;
                                        break;
                                    }
                                } else {
                                    $page_image = $img;
                                    break;
                                }
                            }
                        }
                    }
                    if (empty($page_image) && $is_frontpage) {
                        $val['image'] = qualifiedUrl($DBInfo->logo_img);
                    } else {
                        if (!empty($page_image)) {
                            $val['image'] = $page_image;
                        }
                    }
                    $oc->update($this->page->name, $val, time());
                }
                if (empty($this->no_ogp)) {
                    // for OpenGraph
                    echo '<meta property="og:url" content="' . $page_url . '" />', "\n";
                    echo '<meta property="og:site_name" content="' . $sitename . '" />', "\n";
                    echo '<meta property="og:title" content="' . $options['title'] . '" />', "\n";
                    if ($is_frontpage) {
                        echo '<meta property="og:type" content="website" />', "\n";
                    } else {
                        echo '<meta property="og:type" content="article" />', "\n";
                    }
                    if (!empty($val['image'])) {
                        echo '<meta property="og:image" content="', $val['image'], '" />', "\n";
                    }
                    if (!empty($val['description'])) {
                        echo '<meta property="og:description" content="' . $val['description'] . '" />', "\n";
                    }
                }
                // twitter card
                echo '<meta name="twitter:card" content="summary" />', "\n";
                if (!empty($DBInfo->twitter_id)) {
                    echo '<meta name="twitter:site" content="', $DBInfo->twitter_id, '">', "\n";
                }
                echo '<meta name="twitter:domain" content="', $sitename, '" />', "\n";
                echo '<meta name="twitter:title" content="', $options['title'], '">', "\n";
                echo '<meta name="twitter:url" content="', $page_url, '">', "\n";
                if (!empty($val['description'])) {
                    echo '<meta name="twitter:description" content="' . $val['description'] . '" />', "\n";
                }
                if (!empty($val['image'])) {
                    echo '<meta name="twitter:image:src" content="', $val['image'], '" />', "\n";
                }
                // support google sitelinks serachbox
                if (!empty($DBInfo->use_google_sitelinks)) {
                    if ($is_frontpage) {
                        if (!empty($DBInfo->canonical_url)) {
                            $site_url = $DBInfo->canonical_url;
                        } else {
                            $site_url = qualifiedUrl($this->link_url(''));
                        }
                        echo <<<SITELINK
<script type='application/ld+json'>
{"@context":"http://schema.org",
 "@type":"WebSite",
 "url":"{$site_url}",
 "name":"{$sitename}",
 "potentialAction":{
  "@type":"SearchAction",
  "target":"{$site_url}?goto={search_term}",
  "query-input":"required name=search_term"
 }
}
</script>

SITELINK;
                    }
                }
                echo <<<SCHEMA
<script type='application/ld+json'>
{"@context":"http://schema.org",
 "@type":"WebPage",
 "url":"{$page_url}",
 "dateModified":"{$modified}",
 "name":"{$options['title']}"
}
</script>

SCHEMA;
                if (!empty($val['description'])) {
                    echo '<meta name="description" content="' . $val['description'] . '" />', "\n";
                }
            }
            echo '  <title>', $site_title, "</title>\n";
            echo '  <link rel="canonical" href="', $page_url, '" />', "\n";
            # echo '<meta property="og:title" content="'.$options['title'].'" />',"\n";
            if (!empty($upper)) {
                echo '  <link rel="Up" href="', $this->link_url($upper), "\" />\n";
            }
            $raw_url = $this->link_url($this->page->urlname, "?action=raw");
            $print_url = $this->link_url($this->page->urlname, "?action=print");
            echo '  <link rel="Alternate" title="Wiki Markup" href="', $raw_url, "\" />\n";
            echo '  <link rel="Alternate" media="print" title="Print View" href="', $print_url, "\" />\n";
            $css_html = '';
            if ($options['css_url']) {
                $stamp = '?' . filemtime(__FILE__);
                $css_url = _html_escape($options['css_url']);
                $css_html = '  <link rel="stylesheet" type="text/css" ' . $media . ' href="' . $css_url . "\" />\n";
                if (!empty($DBInfo->custom_css) && file_exists($DBInfo->custom_css)) {
                    $css_html .= '  <link rel="stylesheet" media="screen" type="text/css" href="' . $DBInfo->url_prefix . '/' . $DBInfo->custom_css . "{$stamp}\" />\n";
                } else {
                    if (file_exists('./css/_user.css')) {
                        $css_html .= '  <link rel="stylesheet" media="screen" type="text/css" href="' . $DBInfo->url_prefix . "/css/_user.css{$stamp}\" />\n";
                    }
                }
            }
            echo kbd_handler(!empty($options['prefix']) ? $options['prefix'] : '');
            if (isset($this->_newtheme) and $this->_newtheme == 2 or isset($options['retstr'])) {
                $ret = ob_get_contents();
                ob_end_clean();
                if (isset($options['retstr'])) {
                    $options['retstr'] = $ret;
                }
                $this->header_html = $ret;
                $this->css_html = $css_html;
            } else {
                echo $css_html;
                echo "</head>\n";
            }
        }
        return true;
    }
Example #20
0
function macro_WikimediaCommons($formatter, $value, $params = array())
{
    global $DBInfo, $Config;
    $args = array();
    if (($p = strpos($value, ',')) !== false) {
        $arg = substr($value, $p + 1);
        $value = substr($value, 0, $p);
        $arg = preg_replace('@\\s*,\\s*@', ',', $arg);
        $arg = preg_replace('@\\s*=\\s*@', '=', $arg);
        $args = explode(',', $arg);
    }
    if (!empty($params['attr'])) {
        $args = array_merge($args, (array) $params['attr']);
    }
    $data = array('action' => 'query', 'prop' => 'imageinfo', 'iiprop' => 'extmetadata|url', 'format' => 'json', 'rawcontinue' => '1');
    // default API url
    $api_url = 'https://commons.wikimedia.org/w/api.php';
    // check full url
    if (preg_match('@^https?://upload\\.wikimedia\\.org/wikipedia/(?:(en|commons)/)?(thumb/)?./../([^/]+\\.(?:gif|jpe?g|png|svg))(?(2)/(\\d+px)-\\3)@', $value, $m)) {
        // WikiMedia
        $remain = substr($value, strlen($m[0]));
        if (!empty($m[1]) && in_array($m[1], array('en'))) {
            $api_url = 'https://' . $m[1] . '.wikipedia.org/w/api.php';
        }
        $value = urldecode($m[3]);
        if (!empty($m[4])) {
            $width = intval($m[4]);
        }
        $data['titles'] = 'Image:' . $value;
        $data['iiprop'] = 'extmetadata|url';
    } else {
        if (preg_match('@^https?://((?:[^.]+)\\.(?:wikimedia|wikipedia)\\.org)/wiki/(?:Image|File):([^/]+\\.(?:gif|jpe?g|png|svg))$@', $value, $m)) {
            // WikiMedia or WikiPedia
            $api_url = 'https://' . $m[1] . '/w/api.php';
            $value = urldecode($m[2]);
            $data['titles'] = 'Image:' . $value;
            $data['iiprop'] = 'extmetadata|url';
            $source = _("WikiMedia Commons");
        } else {
            if (preg_match('@^https?://([^.]+)\\.wikia\\.com/wiki/(?:Image|File):(.*\\.(?:gif|jpe?g|png|svg))@', $value, $m)) {
                $src = 'wikia.';
                // Wikia
                $api_url = 'https://' . $m[1] . '.wikia.com/api.php';
                $value = urldecode($m[2]);
                $data['titles'] = 'Image:' . $value;
                $data['iiprop'] = 'url|user|size|comment';
                $source = _("Wikia");
            } else {
                if (preg_match('@^https?://.*\\.wikia\\..*/([^/]+)/images/./../([^/]+\\.(?:gif|jpe?g|png|svg))@', $value, $m)) {
                    $src = 'wikia.';
                    // Wikia
                    $api_url = 'https://' . $m[1] . '.wikia.com/api.php';
                    $value = urldecode($m[2]);
                    $data['titles'] = 'Image:' . $value;
                    $data['iiprop'] = 'url|user|size|comment';
                    $source = _("Wikia");
                } else {
                    $value = urldecode($value);
                    $data['titles'] = 'Image:' . $value;
                    $data['iiprop'] = 'extmetadata|url';
                    $source = _("WikiMedia Commons");
                }
            }
        }
    }
    $styles = array();
    foreach ($args as $arg) {
        $k = $v = '';
        if (($p = strpos($arg, '=')) !== false) {
            $k = substr($arg, 0, $p);
            $k = trim($k);
            $v = substr($arg, $p + 1);
            $v = trim($v, '"\'');
        } else {
            continue;
        }
        $k = strtolower($k);
        switch ($k) {
            case 'width':
            case 'height':
                if (preg_match('@^(\\d+)(px|%)?$@', $v, $m)) {
                    if (isset($m[2]) && $m[2] == '%') {
                        $styles[$k] = $v;
                    } else {
                        $styles[$k] = $v;
                        ${$k} = intval($m[1]);
                    }
                }
                break;
            case 'align':
                $v = strtolower($v);
                if (in_array($v, array('left', 'right', 'center'))) {
                    $addClass = ' img' . ucfirst($v);
                }
                break;
        }
    }
    $common = new Cache_Text('wikicommons');
    $key = $value . $src;
    if (isset($width)) {
        $key .= $width;
    }
    if (isset($height)) {
        $key .= '.h' . $height;
    }
    if (!empty($formatter->refresh) || ($images = $common->fetch($key)) === false) {
        if (!empty($width)) {
            $data['iiurlwidth'] = min(1280, $width);
        } else {
            if (!empty($height)) {
                $data['iiurlheight'] = min(1280, $height);
            } else {
                // default image width
                $data['iiurlwidth'] = 640;
            }
        }
        require_once dirname(__FILE__) . '/../lib/HTTPClient.php';
        $http = new HTTPClient();
        $save = ini_get('max_execution_time');
        set_time_limit(0);
        // support proxy
        if (!empty($DBInfo->proxy_host)) {
            $http->proxy_host = $DBInfo->proxy_host;
            if (!empty($DBInfo->proxy_port)) {
                $http->proxy_port = $DBInfo->proxy_port;
            }
        }
        $http->sendRequest($api_url, $data, 'POST');
        set_time_limit($save);
        // FIXME
        if ($http->status != 200) {
            return '';
        }
        $res = json_decode($http->resp_body);
        $images = $res->query->pages;
        $common->update($key, $images);
    }
    $image = current($images);
    $image_url = $image->imageinfo[0]->thumburl;
    $desc_url = $image->imageinfo[0]->descriptionurl;
    if (empty($styles['width']) && !empty($image->imageinfo[0]->thumbwidth)) {
        $styles['width'] = $image->imageinfo[0]->thumbwidth . 'px';
    }
    $attrs = array();
    $keys = array('width', 'height');
    foreach ($keys as $key) {
        if (isset($styles[$key])) {
            $attrs[] = $key . '="' . $styles[$key] . '"';
            unset($styles[$key]);
        }
    }
    $attr = '';
    if (count($attrs)) {
        $attr = ' ' . implode(' ', $attrs);
    }
    $style = '';
    foreach ($styles as $k => $v) {
        $style .= $k . ':' . $v . ';';
    }
    if (!empty($style)) {
        $style = ' style="' . $style . '"';
    }
    if (!empty($image->imageinfo[0]->extmetadata)) {
        $copyright = $image->imageinfo[0]->extmetadata->Copyrighted->value;
        $description = $image->imageinfo[0]->extmetadata->ImageDescription->value;
        $author = $image->imageinfo[0]->extmetadata->Artist->value;
        $license = $image->imageinfo[0]->extmetadata->License->value;
        $comment = '';
    } else {
        if (!empty($image->imageinfo[0]->user)) {
            // Wikia case
            $copyright = 'True';
            $author = sprintf(_("Uploaded by %s"), $image->imageinfo[0]->user);
            $license = '';
            $description = $image->imageinfo[0]->comment;
        } else {
            // not found
            return false;
        }
    }
    if (!empty($formatter->fetch_images) && !empty($image_url)) {
        $image_url = $formatter->fetch_action . str_replace(array('&', '?'), array('%26', '%3f'), $image_url);
        // use thumbnails ?
        if (!empty($formatter->use_thumb_by_default)) {
            $image_url .= '&amp;thumbwidth=' . $formatter->thumb_width;
        }
    }
    $copyrighted = $copyright == 'True';
    $info = ($copyrighted ? '&copy; ' : '(&#596;) ') . $author;
    if ($copyrighted && isset($license[0])) {
        $info .= " ({$license})";
    }
    $out = '<div class="externalImage">';
    if (empty($addClass)) {
        $cls = ' class="' . $addClass . '"';
    }
    $out .= "<div" . $cls . "><img src='{$image_url}'{$style}{$attr}>";
    $out .= "<div class='info'>" . $info . $comment . ' from ' . "<a href='{$desc_url}' target='_blank'>{$source}</a></div>";
    $out .= "</div>";
    if (!empty($DBInfo->wikimediacommons_use_description) && !empty($description)) {
        $out .= '<div class="desc">' . $description . '</div>';
    }
    $out .= "</div>\n";
    return $out;
}
Example #21
0
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('&', '&amp;', $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('&', '&amp;', $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');
}
Example #22
0
    function savePage($data, $options = array())
    {
        global $DBInfo;
        $time = time();
        $date = gmdate('Y-m-d H:i:s', $time);
        $ip = $_SERVER['REMOTE_ADDR'];
        $info = "{$ip},{$time},{$data['name']},{$data['pass']},{$data['email']},{$data['home']},{$data['subject']},";
        $info .= "\"{$data['categories']}\",\"{$data['files']}\",\"{$data['summary']}\"";
        if ($data['no']) {
            # check password
            $id =& $data['no'];
            $body = $this->getPage($id);
            $comments = '';
            if ($body != null) {
                include_once 'lib/metadata.php';
                #list($meta,$body)=explode("\n\n",$body,2);
                #$metas=getMetadata($meta,1);
                list($metas, $nbody) = _get_metadata($body);
                if ($nbody) {
                    $body = $nbody;
                }
                $data['name'] = $metas['Name'];
                $updated = "\nUpdated: " . gmdate('Y-m-d H:i:s', time());
                $boundary = strtoupper(md5("COMMENT"));
                # XXX
                list($body, $comments) = explode('----' . $boundary . "\n", $body, 2);
                # XXX
            } else {
                return false;
            }
        } else {
            $id = $this->incCurrent();
            $this->incCount();
            $this->counter->incCounter($id, $options);
            $this->updateIndex($id, $info);
        }
        $message = <<<EOF
Name: {$data['name']}
Subject: {$data['subject']}
Date: {$date}{$updated}
Email: {$data['email']}
HomePage: {$data['home']}
IP: {$ip}

{$data['text']}
EOF;
        if ($comments) {
            $message .= '----' . $boundary . "\n" . $comments;
        }
        $log = $_SERVER['REMOTE_ADDR'] . ';;' . $data['name'] . ';;' . $comment;
        $options['log'] = $log;
        $options['pagename'] = $this->bbsname . ':' . $data['no'];
        $ret = $DBInfo->_savePage($this->getPageKey($id), $message, $options);
        if (!empty($data['attach'])) {
            $cache = new Cache_Text('attachments');
            $cache->update($options['pagename'], $data['attach']);
        }
        return true;
    }
Example #23
0
function cached_editlogbin($formatter, $params = array())
{
    global $Config, $DBInfo;
    $cache = new Cache_Text('editlogbin');
    if (!empty($params['title'])) {
        if (!$DBInfo->hasPage($params['title'])) {
            unset($params['title']);
        }
    }
    $args = array();
    $user = !empty($params['q']) ? $params['q'] : '';
    $start = !empty($params['start']) ? $params['start'] : '';
    $domain = !empty($params['domain']) ? $params['domain'] : '';
    $title = !empty($params['title']) ? $params['title'] : '';
    // get timestamp
    $oldest_stamp = !empty($params['.oldest']) ? strtotime($params['.oldest']) : strtotime('-1 year');
    // round timestamp
    $tmp = date('Y-m-d 00:00:00', $oldest_stamp);
    $oldest_stamp = strtotime($tmp);
    if (!empty($start)) {
        if (is_numeric($start)) {
            // timestamp
            $from = $start;
        } else {
            $from = strtotime($start);
        }
        // convert to timestamp
    } else {
        $from = !empty($params['.max_range']) ? strtotime('-' . $params['.max_range']) : strtotime('-1 year');
        // restrict range
        $params['until'] = null;
        // reset
    }
    // round timestamp
    $tmp = date('Y-m-d 23:59:59', $from);
    $from = strtotime($tmp);
    $max_range = !empty($params['.max_range']) ? strtotime($params['.max_range'], $from) : strtotime('1 year', $from);
    $params['until'] = $max_range;
    if ($params['until'] > time()) {
        $params['until'] = null;
    }
    //echo date('Y.m.d H.i.s', $params['until']);
    $mtime = $DBInfo->mtime();
    $key = $user . '.' . $from . '.' . $domain . '.' . $title . $mtime;
    if (empty($formatter->refresh) && ($data = $cache->fetch($key)) !== false) {
        return $data;
    }
    $fp = fopen($Config['editlog_name'], 'r');
    $seek = _editlog_seek($fp, $from);
    $data = _editlog_binning($fp, $seek, $from, 60 * 60 * 24, $params);
    fclose($fp);
    $cache->update($key, $data, 60 * 60 * 24);
    // TTL to 24 hour
    return $data;
}
Example #24
0
function macro_PageSort($formatter, $value = '', $params = array())
{
    global $DBInfo;
    $cache = new Cache_Text('persist', array('depth' => 0));
    $ismember = $DBInfo->user->is_member;
    $refresh = $formatter->refresh && $ismember;
    if (!empty($params['sortby']) && in_array($params['sortby'], array('date', 'hits'))) {
        if ($params['sortby'] == 'date') {
            $sortby = PAGESIZE_SORTBY_DATE;
            $cachekey = 'pagedate';
        } else {
            $sortby = PAGESIZE_SORTBY_HITS;
            $cachekey = 'pagehits';
        }
    } else {
        $sortby = PAGESIZE_SORTBY_SIZE;
        $cachekey = 'pagesize';
    }
    if ($refresh || ($info = $cache->fetch($cachekey)) === false) {
        set_time_limit(0);
        if ($sortby == PAGESIZE_SORTBY_HITS) {
            $cutoff = !empty($DBInfo->counter_cutoff) ? $DBInfo->counter_cutoff : 50;
            $hits = $DBInfo->counter->getPageHits(-1, 0, $cutoff);
            $pages = array();
            foreach ($hits as $k => $v) {
                $pages[$k . "\t" . $v] = $v;
            }
        } else {
            $handle = opendir($DBInfo->text_dir);
            if (!is_resource($handle)) {
                return sprintf(_("Can't open %s\n"), $DBInfo->text_dir);
            }
            $j = 0;
            $cnt = 0;
            $pages = array();
            while (($file = readdir($handle)) !== false) {
                $j++;
                if ($file[0] == '.' || in_array($file, array('RCS', 'CVS'))) {
                    continue;
                }
                $pagefile = $DBInfo->text_dir . '/' . $file;
                if (is_dir($pagefile)) {
                    continue;
                }
                $pagename = $DBInfo->keyToPagename($file);
                $sz = $val = filesize($pagefile);
                if ($sortby == PAGESIZE_SORTBY_DATE) {
                    $val = filemtime($pagefile);
                }
                $key = $pagename . "\t" . $val;
                if ($sz > 11 && $sz < 4096) {
                    // check redirects
                    $fp = fopen($pagefile, 'r');
                    if (!is_resource($fp)) {
                        continue;
                    }
                    $pi = fgets($fp, 11);
                    if (isset($pi[0]) && $pi[0] == '#' && preg_match('@^#redirect\\s@i', $pi)) {
                        fclose($fp);
                        continue;
                    }
                    fclose($fp);
                }
                $pages[$key] = $val;
                $cnt++;
            }
            closedir($handle);
        }
        // sort
        if ($sortby != PAGESIZE_SORTBY_SIZE) {
            arsort($pages);
        } else {
            asort($pages);
        }
        $keys = array_keys($pages);
        $raw = implode("\n", $keys);
        // save sorted page list
        $cache->update($cachekey . '.raw', $raw);
        // write index file
        $idxfile = $cache->cache_path . '/' . $cache->getKey($cachekey . '.idx');
        $fp = fopen($idxfile, 'a+b');
        ftruncate($fp, 0);
        $idx = '';
        $i = 0;
        $idx = pack('N', 0);
        $len = 0;
        for ($i = 1; $i < sizeof($keys); $i++) {
            $pos = strlen($keys[$i - 1]) + 1;
            // strlen($name) + strlen("\n");
            $len += $pos;
            $idx .= pack('N', $len);
            if ($i % 500 == 0) {
                fwrite($fp, $idx);
                $idx = '';
            }
        }
        if (isset($idx[0])) {
            fwrite($fp, $idx);
        }
        fclose($fp);
        $info = array('count' => $cnt);
        // save some info.
        $cache->update($cachekey, $info, 60 * 60 * 12);
        // set TTL
    }
    if (!empty($params['.call'])) {
        return $info;
    }
    $offset = 0;
    $limit = 200;
    if (!empty($params['offset'])) {
        $offset = intval($params['offset']);
    }
    $off = $offset;
    if (!empty($params['reverse'])) {
        $off = $info['count'] - $offset;
        $off -= $limit;
    }
    $seek = 0;
    $rawfile = $cache->cache_path . '/' . $cache->getKey($cachekey . '.raw');
    $fp = fopen($rawfile, 'r');
    while ($off > 0) {
        $idxfile = $cache->cache_path . '/' . $cache->getKey($cachekey . '.idx');
        $ip = fopen($idxfile, 'rb');
        if (!is_resource($ip)) {
            break;
        }
        // ignore
        fseek($ip, $off * 4);
        $dum = unpack('N', fread($ip, 4));
        $seek = $dum[1];
        fclose($ip);
        fseek($fp, $seek);
        break;
    }
    $lst = array();
    for ($j = 0; $j < $limit; $j++) {
        $raw = fgets($fp, 2048);
        if ($raw === false) {
            break;
        }
        list($page, $val) = explode("\t", $raw, 2);
        $item = '<li>' . $formatter->link_tag($page);
        if ($sortby == PAGESIZE_SORTBY_DATE) {
            $item .= ' (' . date('Y-m-d H:i', $val) . ')</li>' . "\n";
        } else {
            if ($sortby == PAGESIZE_SORTBY_SIZE) {
                $item .= ' (' . $val . ' Bytes)</li>' . "\n";
            } else {
                $item .= ' (' . $val . ' Hits)</li>' . "\n";
            }
        }
        $lst[] = $item;
    }
    fclose($fp);
    // next query string
    $q = '&amp;offset=' . ($offset + $limit);
    if (!empty($params['reverse'])) {
        $lst = array_reverse($lst);
        $q .= '&amp;reverse=1';
    }
    if ($sortby == PAGESIZE_SORTBY_DATE) {
        $q .= '&amp;sortby=date';
    } else {
        if ($sortby == PAGESIZE_SORTBY_HITS) {
            $q .= '&amp;sortby=hits';
        }
    }
    $out = '<ul>';
    $out .= implode($lst);
    $out .= '</ul>';
    $out .= $formatter->link_to("?action=pagesort{$q}", _("Show next page"));
    return $out;
}
Example #25
0
function do_aclinfo($formatter, $options)
{
    global $DBInfo;
    if ($DBInfo->security_class == 'acl') {
        $ret = $DBInfo->security->get_acl('aclinfo', $options);
        if (is_array($ret)) {
            list($allowed, $denied, $protected) = $ret;
        }
    } else {
        $options['msg'] = _("ACL is not enabled on this Wiki");
        do_invalid($formatter, $options);
        return;
    }
    $u = $DBInfo->user;
    if (isset($options['get']) && $options['get'] > 0) {
        if (!in_array($u->id, $DBInfo->owners)) {
            $options['get'] = 1;
        }
        header('Content-Type: text/plain');
        if ($options['get'] == 1) {
            $ac = new Cache_Text('aux_acl');
        } else {
            $ac = new Cache_Text('acl');
        }
        $files = array();
        $ac->_caches($files, array('prefix' => 1));
        // prepare to return
        $ret = array();
        $retval = array();
        $ret['retval'] =& $retval;
        $acls = array();
        $cur = time();
        foreach ($files as $f) {
            // low level _fetch(), _remove()
            $info = $ac->_fetch($f, 0, $ret);
            if ($info === false) {
                $ac->_remove($f);
                continue;
            }
            $ttl = '';
            if (!empty($retval['ttl'])) {
                $ttl = $retval['ttl'] - ($cur - $retval['mtime']);
                $ttl = "\t" . $ttl;
            }
            foreach ($info as $g => $types) {
                foreach ($types as $type => $v) {
                    if (!is_array($v)) {
                        continue;
                    }
                    if (!isset($acls[$g])) {
                        $acls[$g] = array();
                    }
                    $acls[$g][$retval['id']] = $g . "\t" . $type . "\t" . implode(',', $v) . $ttl;
                }
            }
        }
        foreach ($acls as $g => $acl) {
            ksort($acl);
            foreach ($acl as $id => $entry) {
                echo $id, "\t", $entry, "\n";
            }
        }
        return;
    }
    $formatter->send_header('', $options);
    $options['.title'] = sprintf(_("ACL Information of '%s'."), _html_escape($options['page']));
    if ($u->is_member) {
        if (method_exists($DBInfo->security, 'get_page_acl')) {
            $groups = array('@ALL', '@User');
            // FIXME
            foreach ($DBInfo->security->group as $group) {
                preg_match('/^(@[^\\s]+)\\s/', $group, $m);
                if (isset($m[1])) {
                    $groups[] = $m[1];
                }
            }
            if (!empty($u->groups)) {
                $groups = array_merge($groups, $u->groups);
                $groups = array_unique($groups);
            }
            // editable actions
            $actions = array('savepage', 'deletepage', 'info', 'diff', 'recall', 'revert');
            if (!empty($DBInfo->aclinfo_actions)) {
                $actions = $DBInfo->aclinfo_actions;
            }
            if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST) && !empty($options['remove'])) {
                // remove ACL entry
                $msgs = array();
                $page = $options['value'];
                if (!empty($page)) {
                    $tmp = array_keys($options['remove']);
                    $group = $tmp[0];
                    if (in_array($group, $groups)) {
                        $acl = array($group => null);
                        $DBInfo->security->add_page_acl($page, $acl);
                    }
                }
            } else {
                if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST)) {
                    $msgs = array();
                    $page = !empty($options['value']) ? $options['value'] : $formatter->page->name;
                    $group = $options['group'];
                    $type = $options['type'];
                    $acts = (array) $options['act'];
                    $ttl = (int) $options['ttl'];
                    // Simple ACL mode.
                    if (isset($options['control'])) {
                        if (empty($group)) {
                            $group = array();
                        }
                        $options['.call'] = 1;
                        $cur = macro_AclInfo($formatter, '', $options);
                        $changed_groups = array_flip($group);
                        // only owners can change member's permissions
                        if (!in_array($u->id, $DBInfo->owners)) {
                            unset($cur['@Member']);
                            unset($changed_groups['@Member']);
                        }
                        foreach ($cur as $g => $v) {
                            if (isset($changed_groups[$g])) {
                                if ($v) {
                                    // already enabled. no need to allow again
                                    unset($changed_groups[$g]);
                                } else {
                                    $changed_groups[$g] = 'allow';
                                }
                            } else {
                                // denied
                                if ($v) {
                                    $changed_groups[$g] = 'deny';
                                }
                            }
                        }
                    }
                    if (!empty($changed_groups)) {
                        $selected_groups = array();
                        foreach ($changed_groups as $g => $v) {
                            if ($g == '@Member') {
                                if (!empty($DBInfo->aclinfo_member_group)) {
                                    $g = $DBInfo->aclinfo_member_group;
                                } else {
                                    continue;
                                }
                                // only owners can change permissions
                                if (in_array($u->id, $DBInfo->owners)) {
                                    $selected_groups[$g] = $v;
                                }
                            } else {
                                if ($g == 'Anonymous') {
                                    $selected_groups['@Guest'] = $v;
                                } else {
                                    if ($g == '@ALL') {
                                        $selected_groups[$g] = $v;
                                    } else {
                                        if (in_array($g, $groups)) {
                                            if (in_array($g, $u->groups)) {
                                                $selected_groups[$g] = $v;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        $post_data = array();
                        foreach ($selected_groups as $g => $v) {
                            $d = array();
                            $d['group'] = $g;
                            $d['type'] = $v;
                            $d['act'] = $actions;
                            // default actions
                            $d['ttl'] = in_array($u->id, $DBInfo->owners) ? 0 : 3600;
                            // default TTL
                            $post_data[] = $d;
                        }
                    } else {
                        $post_data = array();
                        $d = array();
                        $d['group'] = $group;
                        $d['type'] = $type;
                        $d['act'] = $acts;
                        $d['ttl'] = $ttl;
                        $post_data[] = $d;
                    }
                    foreach ($post_data as $d) {
                        $group = $d['group'];
                        $type = $d['type'];
                        $acts = $d['act'];
                        $ttl = $d['ttl'];
                        // check
                        if (!in_array($group, $groups)) {
                            $msgs[] = _("Invalid ACL group name");
                        }
                        if (empty($type)) {
                            $type = 'deny';
                        }
                        if (!in_array($u->id, $DBInfo->owners)) {
                            if (!in_array($type, array('deny', 'allow'))) {
                                $type = 'deny';
                            }
                            if (!in_array($group, array('@ALL', '@Guest', '@User'))) {
                                $group = null;
                            }
                        }
                        if (!in_array($type, array('deny', 'allow'))) {
                            $msgs[] = _("Invalid ACL type");
                        }
                        if (empty($group)) {
                            $msgs[] = _("Empty ACL group");
                        }
                        $acts = array_map('strtolower', $acts);
                        $acl_actions = array_map('strtolower', $actions);
                        // check actions
                        $tmp = array();
                        foreach ($acts as $act) {
                            if (in_array($act, $acl_actions)) {
                                $tmp[] = $act;
                            }
                        }
                        $acts = $tmp;
                        if (!empty($msgs)) {
                            break;
                        } else {
                            if (!empty($page) && !empty($group) && !empty($type) && !empty($acts)) {
                                if ($ttl <= 365) {
                                    $ttl = $ttl * 60 * 60 * 24;
                                }
                                $param = array('ttl' => $ttl);
                                $acl = array($group => array($type => $acts, 'ttl' => $ttl, 'mtime' => time(), '.editor' => $u->id));
                                $DBInfo->security->add_page_acl($page, $acl, $param);
                            } else {
                                $options['title'] = _("Fail to add ACL");
                            }
                        }
                    }
                    if (!empty($msgs)) {
                        $all_msg = implode(', ', $msgs);
                        if ($options['title']) {
                            $options['title'] .= ': ' . $all_msg;
                        } else {
                            $options['title'] = $all_msg;
                        }
                    } else {
                        $options['title'] = _("ACL entries added!");
                    }
                }
            }
            $formatter->send_title('', '', $options);
            $retval = array();
            $opts = array('retval' => &$retval);
            $acl = $DBInfo->security->get_page_acl($options['page'], $opts);
            if ($acl !== false) {
                $form_header = $form_footer = '';
                $form_th = '';
                if (isset($retval['ttl'])) {
                    $form_header = '<form method="POST"><input type="hidden" name="action" value="aclinfo" />';
                    $form_header .= '<input type="hidden" name="value" value="' . _html_escape($options['page']) . '">';
                    $form_footer = '</form>';
                    $form_th = '<th>' . _("Control") . '</th><th>' . _("Last-modified By") . '</th>';
                }
                echo $form_header;
                echo '<table class="wiki"><tr><th style="white-space:nowrap">', _("ACL Group"), "</th><th>", _("Type"), "</th><th>", _("Actions"), "</th>", $form_th, "</tr>\n";
                foreach ($acl as $group => $entry) {
                    $editor = $entry['.editor'];
                    $ttl_time = '';
                    if (!empty($entry['ttl'])) {
                        $ttl = $entry['ttl'];
                        $mtime = $entry['mtime'];
                        $ttl = $ttl - (time() - $mtime);
                        $tmp = $ttl;
                        $d = intval($tmp / 60 / 60 / 24);
                        $tmp -= $d * 60 * 60 * 24;
                        $h = intval($tmp / 60 / 60);
                        $tmp -= $h * 60 * 60;
                        $m = intval($tmp / 60);
                        $tmp -= $m * 60;
                        $s = $tmp % 60;
                        $ttl_time = '';
                        if (!empty($d)) {
                            $ttl_time = $d . ' ' . _("days") . ' ';
                        } else {
                            $ttl_time = sprintf("%02d:%02d:%02d", $h, $m, $s);
                        }
                    } else {
                        if (isset($entry['ttl'])) {
                            $ttl_time = '<span></span>';
                        }
                    }
                    foreach ($entry as $type => $v) {
                        if (!is_array($v)) {
                            continue;
                        }
                        echo "<tr><th>", $group, "</th>";
                        echo '<th>', $type, '</th><td>', implode(', ', $v), '</td>';
                        if (!empty($form_th)) {
                            if (!empty($ttl_time)) {
                                echo '<td>', $ttl_time, ' <input type="submit" name="remove[' . $group . ']" value="Delete" /></td>';
                            } else {
                                echo '<td></td>';
                            }
                            echo '<td>' . sprintf(_("%s"), $editor) . '</td>';
                        }
                        echo "</tr>\n";
                    }
                }
                echo '</table>', "\n";
                echo $form_footer;
            }
            $group_select = '<select name="group"><option>-- ' . _("Group") . ' --</option>';
            foreach ($groups as $g) {
                $selected = $g == '@ALL' ? ' selected="selected"' : '';
                $group_select .= '<option value="' . $g . '"' . $selected . '>' . $g . '</option>';
            }
            $group_select .= '</select>' . "\n";
            $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', 365 => '1 year');
            $ttl_select = '<select name="ttl"><option>-- ' . _("TTL") . ' --</option>';
            foreach ($ttls as $time => $str) {
                $ttl_select .= '<option value="' . $time . '">' . $str . '</option>';
            }
            $ttl_select .= '</select>' . "\n";
            $type_select = '<select name="type"><option>-- ' . _("Type") . ' --</option>';
            $type_select .= '<option value="allow">allow</option>';
            $type_select .= '<option value="deny" selected="selected">deny</option>';
            $type_select .= '</select>';
            // $type_select = '<input type="hidden" name="type" value="deny" />deny';
            $action_list = '';
            foreach ($actions as $act) {
                $action_list .= '<input type="checkbox" name="act[]" value="' . $act . '" checked="checked" />' . $act . ' ';
            }
            $form = '<form method="POST">';
            $form .= '<input type="hidden" name="action" value="aclinfo" />';
            $form .= '<input type="hidden" name="value" value="' . _html_escape($options['page']) . '" />';
            $form .= $group_select;
            $form .= $type_select;
            $form .= $action_list;
            $form .= $ttl_select;
            $form .= '<input type="submit" value="Add ACL" />';
            $form .= '</form>';
            echo $form;
        }
    } else {
        $formatter->send_title('', '', $options);
    }
    $test = false;
    if ($test && $u->is_member) {
        $params = array('page' => $options['page'], 'id' => 'Anonymous');
        $ret = $DBInfo->security->get_acl('aclinfo', $params);
        if (is_array($ret)) {
            list($allowed, $denied, $protected) = $ret;
            $title = '<h2>' . _("ACL Information of an Anonymous user.") . '</h2>';
            show_acl_table($title, $allowed, $denied, $protected);
        }
    } else {
        $title = '<h2>' . _("ACL Information.") . '</h2>';
        show_acl_table($title, $allowed, $denied, $protected);
    }
    $formatter->send_footer('', $options);
    return;
}