function do_qr($formatter, $params = array()) { global $Config; if (isset($params['value']) && isset($params['value'][0])) { $value = $params['value']; } else { $encoded = _urlencode(strtr($formatter->page->name, ' ', '_')); $value = qualifiedUrl($formatter->link_url($encoded)); } if (!empty($Config['cache_public_dir']) and !empty($Config['cache_public_url'])) { $fc = new Cache_text('qr', array('ext' => 'png', 'dir' => $Config['cache_public_dir'])); $pngname = $fc->getKey($value); $pngfile = $Config['cache_public_dir'] . '/' . $pngname; $png_url = !empty($Config['cache_public_url']) ? $Config['cache_public_url'] . '/' . $pngname : $Config['url_prefix'] . '/' . $pngfile; } else { $uniq = md5($value); $pngfile = $cache_dir . '/' . $uniq . '.png'; $png_url = $cache_url . '/' . $uniq . '.png'; } $img_exists = file_exists($pngfile); if (!$img_exists || $formatter->refresh) { require_once dirname(__FILE__) . '/../lib/phpqrcode.php'; QRcode::png($value, $pngfile, 'l', 3, 1); } if (!empty($Config['use_cache_url'])) { header("Pragma: no-cache"); header('Cache-Control: public, max-age=0, s-maxage=0'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Cache-Control: no-store, no-cache, must-revalidate', false); $formatter->send_header(array('Status: 302', 'Location: ' . $png_url)); return null; } $down_mode = 'inline'; header("Content-Type: image/png\r\n"); $mtime = filemtime($pngfile); $lastmod = gmdate('D, d M Y H:i:s', $mtime) . ' GMT'; $etag = md5($lastmod . $key); header('Last-Modified: ' . $lastmod); header('ETag: "' . $etag . '"'); $maxage = 60 * 60 * 24 * 30; header('Cache-Control: public, max-age=' . $maxage); $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { header('HTTP/1.0 304 Not Modified'); @ob_end_clean(); return null; } @ob_clean(); $ret = readfile($pngfile); return null; }
function do_latex2png($formatter, $options) { $retval = false; $opts = array(); $opts['retval'] =& $retval; if (isset($options['dpi']) and $options['dpi'] > 120 and $options['dpi'] < 600) { $opts['dpi'] = $options['dpi']; } $my = $formatter->processor_repl('latex', $options['value'], $opts); if (!empty($opts['retval'])) { $png = $opts['retval']; } else { $png = $my; } $mtime = filemtime($png); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $etag = md5($mtime); $headers = array(); $headers[] = 'Pragma: cache'; $maxage = 60 * 60 * 24 * 7; $headers[] = 'Cache-Control: private, 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; } if (file_exists($png)) { Header("Content-type: image/png"); readfile($png); } else { // 43byte 1x1 transparent gif // http://stackoverflow.com/questions/2933251/code-golf-1x1-black-pixel // http://www.perlmonks.org/?node_id=7974 $gif = base64_decode('R0lGODlhAQABAJAAAAAAAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw'); Header("Content-type: image/gif"); Header("Content-length: " . strlen($gif)); header('Connection: Close'); echo $gif; flush(); } }
function do_titleindex($formatter, $options) { global $DBInfo, $Config; if (isset($options['q'])) { if (!$options['q']) { print ''; return; } #if (!$options['q']) { print "<ul></ul>"; return; } $limit = isset($options['limit']) ? intval($options['limit']) : 100; $limit = min(100, $limit); $val = ''; $rule = ''; while ($DBInfo->use_hangul_search) { include_once "lib/unicode.php"; $val = $options['q']; if (strtoupper($DBInfo->charset) != 'UTF-8' and function_exists('iconv')) { $val = iconv($DBInfo->charset, 'UTF-8', $options['q']); } if (!$val) { break; } $rule = utf8_hangul_getSearchRule($val); $test = @preg_match("/^{$rule}/", ''); if ($test === false) { $rule = $options['q']; } break; } if (!$rule) { $rule = trim($options['q']); } $test = validate_needle('^' . $rule); if (!$test) { $rule = preg_quote($rule); } $indexer = $DBInfo->lazyLoad('titleindexer'); $pages = $indexer->getLikePages($rule, $limit); sort($pages); //array_unshift($pages, $options['q']); $ct = "Content-Type: text/plain"; $ct .= '; charset=' . $DBInfo->charset; header($ct); $maxage = 60 * 10; header('Cache-Control: public, max-age=' . $maxage . ',s-maxage=' . $maxage . ', post-check=0, pre-check=0'); if ($pages) { $ret = implode("\n", $pages); #$ret= "<ul>\n<li>".implode("</li>\n<li>",$pages)."</li>\n</ul>\n"; } else { #$ret= "<ul>\n<li>".$options['q']."</li></ul>"; $ret = ''; #$ret= "<ul>\n</ul>"; } if (strtoupper($DBInfo->charset) != 'UTF-8' and function_exists('iconv')) { $val = iconv('UTF-8', $DBInfo->charset, $ret); if ($val) { print $val; return; } } #print 'x'.$rule; print $ret; return; } else { if ($options['sec'] == '') { if (!empty($DBInfo->no_all_titleindex)) { return; } $tc = new Cache_text('persist', array('depth' => 0)); // all pages $mtime = $DBInfo->mtime(); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $etag = md5($mtime . $DBInfo->etag_seed); $options['etag'] = $etag; $options['mtime'] = $mtime; // set the s-maxage for proxy $date = gmdate('Y-m-d-H-i-s', $mtime); $proxy_maxage = !empty($Config['proxy_maxage']) ? ', s-maxage=' . $Config['proxy_maxage'] : ''; $header[] = 'Content-Type: text/plain'; $header[] = 'Cache-Control: public' . $proxy_maxage . ', max-age=0, must-revalidate'; $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { $header[] = 'HTTP/1.0 304 Not Modified'; } else { $header[] = 'Content-Disposition: attachment; filename="titleindex-' . $date . '.txt"'; } $formatter->send_header($header, $options); if (!$need) { @ob_end_clean(); return; } if (($out = $tc->fetch('titleindex', 0, array('print' => 1))) === false) { $args = array('all' => 1); $pages = $DBInfo->getPageLists($args); sort($pages); $out = join("\n", $pages); $ttl = !empty($DBInfo->titleindex_ttl) ? $DBInfo->titleindex_ttl : 60 * 60 * 24; $tc->update('titleindex', $out, $ttl); echo $out; } return; } } $formatter->send_header("", $options); $formatter->send_title("", "", $options); print macro_TitleIndex($formatter, $options['sec'], $options); $formatter->send_footer($args, $options); }
function dl_file_resume($ctype, $file, $fname, $mode = 'inline', $header = '') { # from http://kr2.php.net/manual/en/function.fread.php#63893 # ans some modification //Gather relevent info about file $size = filesize($file); if ($size == 0) { return; } //Begin writing headers //header("Cache-Control:"); header("Cache-Control: public"); if (is_array($header)) { foreach ($header as $h) { header($h); } } //Use the switch-generated Content-Type header("Content-Type: {$ctype}"); if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { # workaround for IE filename bug with multiple periods / multiple dots # in filename that adds square brackets to filename # - eg. setup.abc.exe becomes setup[1].abc.exe $fname = preg_replace('/\\./', '%2e', $fname, substr_count($fname, '.') - 1); } header("Accept-Ranges: bytes"); //check if http_range is sent by browser (or download manager) $range = 0; if (isset($_SERVER['HTTP_RANGE'])) { list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']); //if yes, download missing part str_replace($range, "-", $range); $size2 = $size - 1; $new_length = $size2 - $range; header("HTTP/1.1 206 Partial Content"); header("Content-Range: bytes {$range}{$size2}/{$size}"); header("Content-Length: {$new_length}"); header("Content-Disposition: {$mode}; {$fname}"); } else { $size2 = $size - 1; header("Pragma:"); $maxage = 60 * 60 * 24 * 7; header('Cache-Control: public, max-age=' . $maxage); header("Content-Range: bytes 0-{$size2}/{$size}"); header("Content-Length: " . $size); header("Content-Disposition: {$mode}; {$fname}"); $mtime = filemtime($file); $lastmod = gmdate("D, d M Y H:i:s", $mtime) . " GMT"; $etag = md5($lastmod); header("Last-Modified: " . $lastmod); header('ETag: "' . $etag . '"'); $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { header('X-Cache-Debug: Cached OK'); header('HTTP/1.0 304 Not Modified'); @ob_end_clean(); return; } } //open the file $fp = fopen("{$file}", "rb"); if (!is_resource($fp)) { return; } //seek to start of missing part fseek($fp, $range); //start buffered download //reset time limit for big files set_time_limit(0); $chunksize = 1 * (1024 * 1024); // 1MB chunks $left = $size; // start output buffering //ob_start(); while (!feof($fp) and $left > 0) { $sz = $chunksize < $left ? $chunksize : $left; echo fread($fp, $sz); flush(); @ob_flush(); $left -= $sz; } fclose($fp); //ob_end_flush(); return; }
function do_rss_rc($formatter, $options) { global $DBInfo, $Config; // get members to hide log $members = $DBInfo->members; $days = !empty($DBInfo->rc_days) ? $DBInfo->rc_days : RSS_DEFAULT_DAYS; $options['quick'] = 1; if (!empty($options['c'])) { $options['items'] = $options['c']; } $lines = $DBInfo->editlog_raw_lines($days, $options); if (!empty($DBInfo->rss_rc_options)) { $opts = $DBInfo->rss_rc_options; $opts = explode(',', $opts); foreach ($opts as $opt) { $options[$opt] = 1; // FIXME } } // HTTP conditional get $mtime = $DBInfo->mtime(); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $cache_ttl = !empty($DBInfo->rss_rc_ttl) ? $DBInfo->rss_rc_ttl : 60; /* 60 seconds */ // make etag based on some options and mtime. $check_opts = array('quick', 'items', 'oe', 'diffs', 'raw', 'nomsg', 'summary'); $check = array(); foreach ($check_opts as $c) { if (isset($options[$c])) { $check[$c] = $options[$c]; } } $etag = md5($mtime . $DBInfo->logo_img . serialize($check) . $cache_ttl . $options['id']); $headers = array(); $headers[] = 'Pragma: cache'; $maxage = $cache_ttl; $public = 'public'; if ($options['id'] != 'Anonymous') { $public = 'private'; } $headers[] = 'Cache-Control: ' . $public . ', max-age=' . $maxage; $headers[] = 'Last-Modified: ' . $lastmod; $headers[] = 'ETag: "' . $etag . '"'; $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { $headers[] = 'HTTP/1.0 304 Not Modified'; } foreach ($headers as $h) { header($h); } if (!$need) { @ob_end_clean(); return; } $cache = new Cache_Text('rss_rc'); $cache_delay = min($cache_ttl, 30); $mtime = $cache->mtime($etag); $val = false; if (empty($formatter->refresh)) { if (($val = $cache->fetch($etag)) !== false and $DBInfo->checkUpdated($mtime, $cache_delay)) { header("Content-Type: text/xml"); echo $val; return; } } // need to update cache if ($val !== false and $cache->exists($etag . '.lock')) { header("Content-Type: text/xml"); echo $val . '<!-- cached at ' . date('Y-m-d H:i:s', $mtime) . ' -->'; return; } if ($cache->exists($etag . '.lock')) { header("Content-Type: text/xml"); echo ''; return; } $cache->update($etag . '.lock', array('lock'), 5); // 5s lock $time_current = time(); # $secs_per_day= 60*60*24; # $days_to_show= 30; # $time_cutoff= $time_current - ($days_to_show * $secs_per_day); $URL = qualifiedURL($formatter->prefix); $img_url = qualifiedURL($DBInfo->logo_img); $url = qualifiedUrl($formatter->link_url("RecentChanges")); $channel = <<<CHANNEL <channel rdf:about="{$URL}"> <title>{$DBInfo->sitename}</title> <link>{$url}</link> <description>RecentChanges at {$DBInfo->sitename}</description> <image rdf:resource="{$img_url}"></image> <items> <rdf:Seq> CHANNEL; $items = ""; $ratchet_day = FALSE; if (!$lines) { $lines = array(); } foreach ($lines as $line) { $parts = explode("\t", $line); $page_name = $DBInfo->keyToPagename($parts[0]); // hide log if (!empty($members) && !in_array($options['id'], $members) && !empty($Config['ruleset']['hidelog'])) { if (in_array($page_name, $Config['ruleset']['hidelog'])) { continue; } } $addr = $parts[1]; $ed_time = $parts[2]; $user = $parts[4]; $log = _stripslashes($parts[5]); $act = rtrim($parts[6]); # if ($ed_time < $time_cutoff) # break; $url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name))); $diff_url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name), '?action=diff')); $extra = "<br /><a href='{$diff_url}'>" . _("show changes") . "</a>\n"; if (!$DBInfo->hasPage($page_name)) { $status = 'deleted'; $html = '<![CDATA[' . "<a href='{$url}'>" . $page_name . "</a> is deleted" . ']]>' . "\n"; } else { $status = 'updated'; if (!empty($options['diffs'])) { $p = new WikiPage($page_name); $f = new Formatter($p); $options['raw'] = 1; $options['nomsg'] = 1; $html = $f->macro_repl('Diff', '', $options); if (!$html) { ob_start(); $f->send_page('', array('fixpath' => 1)); #$f->send_page(''); $html = ob_get_contents(); ob_end_clean(); $extra = ''; } $html = str_replace(']', ']', $html); $html = "<![CDATA[" . $html . $extra . "]]>"; #$html=strtr($html.$extra,array('&'=>'&','<'=>'<')); } else { if (!empty($options['summary'])) { $p = new WikiPage($page_name); $f = new Formatter($p); $f->section_edit = 0; $f->sister_on = 0; $f->perma_icon = ''; $options['nomsg'] = 1; $b = $p->_get_raw_body(); $chunks = preg_split('/\\n#{4,}/', $b); # summary breaker is #### ob_start(); if ($chunks) { $f->send_page($chunks[0], array('fixpath' => 1)); } else { $f->send_page('', array('fixpath' => 1)); } #$f->send_page(''); $html = ob_get_contents(); ob_end_clean(); $chunks = preg_split('/<!-- break -->/', $html); # <!-- break --> if ($chunks[0]) { $html = $chunks[0]; } $html = str_replace(']', ']', $html); $html = "<![CDATA[" . $html . "]]>"; } else { $html = str_replace('&', '&', $log); } } } $zone = "+00:00"; $date = gmdate("Y-m-d\\TH:i:s", $ed_time) . $zone; #$datetag = gmdate("YmdHis",$ed_time); $channel .= "<rdf:li rdf:resource=\"{$url}\"></rdf:li>\n"; $valid_page_name = preg_replace('/&(?!#?\\w+;)/', '&', _html_escape($page_name)); $items .= "<item rdf:about=\"{$url}\">\n"; $items .= " <title>{$valid_page_name}</title>\n"; $items .= " <link>{$url}</link>\n"; $items .= " <description>{$html}</description>\n"; $items .= " <dc:date>{$date}</dc:date>\n"; $items .= "<dc:creator>{$user}</dc:creator>\n"; $items .= "<dc:contributor>{$user}</dc:contributor>\n"; # $items.=" <dc:contributor>\n <rdf:Description>\n" # ." <rdf:value>$user</rdf:value>\n" # ." </rdf:Description>\n </dc:contributor>\n"; $items .= " <wiki:status>{$status}</wiki:status>\n"; $items .= " <wiki:diff>{$diff_url}</wiki:diff>\n"; $items .= "</item>\n"; } $url = qualifiedUrl($formatter->link_url($DBInfo->frontpage)); $channel .= <<<FOOT </rdf:Seq> </items> </channel> <image rdf:about="{$img_url}"> <title>{$DBInfo->sitename}</title> <link>{$url}</link> <url>{$img_url}</url> </image> FOOT; $url = qualifiedUrl($formatter->link_url("FindPage")); $form = <<<FORM <textinput> <title>Search</title> <link>{$url}</link> <name>goto</name> </textinput> FORM; $new = ""; if (!empty($options['oe']) and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; if (function_exists('iconv')) { $out = $head . $channel . $items . $form; $new = iconv($DBInfo->charset, $charset, $out); if (!$new) { $charset = $DBInfo->charset; } } } else { $charset = $DBInfo->charset; } $head = <<<HEAD <?xml version="1.0" encoding="{$charset}"?> <?xml-stylesheet href="{$DBInfo->url_prefix}/css/_feed.css" type="text/css"?> <rdf:RDF xmlns="http://purl.org/rss/1.0/" \txmlns:wiki="http://purl.org/rss/1.0/modules/wiki/" \txmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" \txmlns:xlink="http://www.w3.org/1999/xlink" \txmlns:dc="http://purl.org/dc/elements/1.1/"> <!-- Add "diffs=1" to add change diffs to the description of each items. Add "summary=1" to add summary to the description of each items. Add "oe=utf-8" to convert the charset of this rss to UTF-8. --> HEAD; header("Content-Type: text/xml"); if ($new) { $out = $head . $new; } else { $out = $head . $channel . $items . $form; } $out .= "</rdf:RDF>\n"; echo $out; $cache->update($etag, $out); $cache->remove($etag . '.lock'); }
function macro_Fetch($formatter, $url = '', $params = array()) { global $DBInfo; if (empty($url)) { $params['retval']['error'] = _("Empty URL"); return false; } // check valid url if (!preg_match('@^((ftp|https?)://[^/]+)/@', $url, $m)) { return false; } $siteurl = $m[1]; require_once "lib/HTTPClient.php"; $sz = 0; $allowed = 'png|jpeg|jpg|gif'; if (!empty($DBInfo->fetch_exts)) { $allowed = $DBInfo->fetch_exts; } // urlencode() $url = _urlencode($url); // set default params $maxage = !empty($DBInfo->fetch_maxage) ? (int) $DBInfo->fetch_maxage : 60 * 60 * 24 * 7; $timeout = !empty($DBInfo->fetch_timeout) ? (int) $DBInfo->fetch_timeout : 15; $vartmp_dir = $DBInfo->vartmp_dir; $buffer_size = 2048 * 1024; // default buffer size if (!empty($DBInfo->fetch_buffer_size) and $DBInfo->fetch_buffer_size > 2048 * 1024) { $buffer_size = $DBInfo->fetch_buffer_size; } // set referrer $referer = ''; if (!empty($DBInfo->fetch_referer_re)) { foreach ($DBInfo->fetch_referer_re as $re => $ref) { if (preg_match($re, $url)) { $referer = $ref; break; } } } // default referrer if (empty($referer) and !empty($DBInfo->fetch_referer)) { $referer = $DBInfo->fetch_referer; } // check site available $si = new Cache_text('siteinfo'); if ($si->exists($siteurl)) { if (!empty($params['refresh'])) { $si->remove($siteurl); } else { if (empty($params['refresh']) && ($check = $si->fetch($siteurl)) !== false) { $params['retval']['status'] = $check['status']; $params['retval']['error'] = $check['error']; return false; } } } $sc = new Cache_text('fetchinfo'); $error = null; if (empty($params['refresh']) and $sc->exists($url) and $sc->mtime($url) < time() + $maxage) { $info = $sc->fetch($url); $sz = $info['size']; $mimetype = $info['mimetype']; $error = !empty($info['error']) ? $info['error'] : null; // already retrived and found some error if (empty($params['refresh']) and !empty($error)) { $params['retval']['status'] = $info['status']; $params['retval']['error'] = $error; $params['retval']['mimetype'] = $mimetype; $params['retval']['size'] = $sz; return false; } } else { // check connection $http = new HTTPClient(); // get file header $http->nobody = true; $http->referer = $referer; $http->sendRequest($url, array(), 'GET'); //if ($http->status == 301 || $http->status == 302 ) { // //} if ($http->status != 200) { if ($http->status == 404) { $params['retval']['error'] = '404 File Not Found'; } else { $params['retval']['error'] = !empty($http->error) ? $http->error : sprintf(_("Invalid Status %d"), $http->status); } $params['retval']['status'] = $http->status; // check alive site if ($http->status == -210) { $si->update($siteurl, array('status' => $http->status, 'error' => $params['retval']['error']), 60 * 60 * 24); return false; } $sc->update($url, array('size' => -1, 'mimetype' => '', 'error' => $params['retval']['error'], 'status' => $params['retval']['status']), 60 * 60 * 24 * 3); return false; } if (isset($http->resp_headers['content-length'])) { $sz = $http->resp_headers['content-length']; } if (isset($http->resp_headers['content-type'])) { $mimetype = $http->resp_headers['content-type']; } else { $mimetype = 'application/octet-stream'; } $sc->update($url, array('size' => $sz, 'mimetype' => $mimetype)); } // size info if (is_numeric($sz)) { $unit = array('Bytes', 'KB', 'MB', 'GB'); $tmp = $sz; for ($i = 0; $i < 4; $i++) { if ($tmp <= 1024) { break; } $tmp = $tmp / 1024; } $hsz = round($tmp, 2) . ' ' . $unit[$i]; if (empty($buffer_size) && !empty($DBInfo->fetch_max_size) and $sz > $DBInfo->fetch_max_size) { $params['retval']['error'] = sprintf(_("Too big file size (%s). Please contact WikiMasters to increase \$fetch_max_size"), $hsz); $params['retval']['mimetype'] = $mimetype; return false; } } else { $params['retval']['error'] = _("Can't get file size info"); $params['retval']['mimetype'] = $mimetype; return false; } $is_image = false; if (preg_match('/^image\\/(jpe?g|gif|png)$/', $mimetype, $m)) { $ext = isset($m[1]) ? '.' . $m[1] : ''; $is_image = true; } else { $ext = '.' . get_extension('data/mime.types', $mimetype); } if (!empty($DBInfo->fetch_images_only) and !$is_image) { // always check the content-type $params['retval']['error'] = sprintf(_("Invalid mime-type %s"), $mimetype); $params['retval']['mimetype'] = $mimetype; return false; } if (empty($params['call'])) { if ($is_image) { $img_url = $formatter->link_url('', '?action=fetch&url=' . $url); return '<div class="externalImage"><div><img src="' . $img_url . '">' . '<div><a href="' . $url . '"><span>[' . strtoupper($m[1]) . ' ' . _("external image") . ' (' . $hsz . ')' . ']</span></a></div></div>'; } return $formatter->link_to('?action=fetch&url=' . $url, $mimetype . ' (' . $hsz . ')'); } // cache dir/filename/cache url if (!empty($DBInfo->cache_public_dir) and !empty($DBInfo->cache_public_url)) { $fc = new Cache_text('fetchfile', array('dir' => $DBInfo->cache_public_dir)); $fetchname = $fc->getKey($url); $fetchfile = $DBInfo->cache_public_dir . '/' . $fetchname . $ext; $fetch_url = $DBInfo->cache_public_url . '/' . $fetchname . $ext; } else { $fc = new Cache_text('fetchfile'); $fetchname = $fc->getKey($url); $fetchfile = $fc->cache_dir . '/' . $fetchname; $fetch_url = null; } // real fetch job. if (!empty($params['refresh']) or !file_exists($fetchfile)) { $fp = fopen($fetchfile, 'w'); if (!is_resource($fp)) { $params['retval']['error'] = sprintf(_("Fail to open %s"), $fetchfile); return false; } // retry to get all info $http = new HTTPClient(); if (!empty($buffer_size)) { $http->max_buffer_size = $buffer_size; } $http->vartmp_dir = $vartmp_dir; $save = ini_get('max_execution_time'); set_time_limit(0); $http->timeout = $timeout; $http->referer = $referer; $http->sendRequest($url, array(), 'GET'); set_time_limit($save); if ($http->status != 200) { fclose($fp); unlink($fetchfile); // Error found! save error status to the info cache $params['retval']['status'] = $http->status; $params['retval']['error'] = $http->error; $params['retval']['mimetype'] = $mimetype; $params['retval']['size'] = $sz; $sc->update($url, array('size' => $sz, 'mimetype' => $mimetype, 'error' => $http->error, 'status' => $params['retval']['status'])); return false; } if (!empty($http->resp_body)) { fwrite($fp, $http->resp_body); fclose($fp); } else { fclose($fp); if (!empty($http->resp_body_file) && file_exists($http->resp_body_file)) { copy($http->resp_body_file, $fetchfile); unlink($http->resp_body_file); } } // update error status. if (!empty($error)) { $sc->update($url, array('size' => $sz, 'mimetype' => $mimetype)); } } if (!empty($fetch_url) and !empty($DBInfo->fetch_use_cache_url)) { $formatter->send_header(array('Status: 302', 'Location: ' . $fetch_url)); return null; } if (!empty($params['thumbwidth'])) { // check allowed thumb widths. $thumb_widths = isset($DBInfo->thumb_widths) ? $DBInfo->thumb_widths : array('120', '240', '320', '480', '600', '800', '1024'); $width = 320; // default if (!empty($DBInfo->default_thumb_width)) { $width = $DBInfo->default_thumb_width; } if (!empty($thumb_widths)) { if (in_array($params['thumbwidth'], $thumb_widths)) { $width = $params['thumbwidth']; } else { header("HTTP/1.1 404 Not Found"); echo "Invalid thumbnail width", "<br />", "valid thumb widths are ", implode(', ', $thumb_widths); return; } } else { $width = $params['thumbwidth']; } $thumb_width = $width; $force_thumb = true; } else { // automatically generate thumb images to support low-bandwidth mobile version if (is_mobile()) { $force_thumb = (!isset($params['m']) or $params['m'] == 1); } } // generate thumb file to support low-bandwidth mobile version $thumbfile = ''; while ((!empty($params['thumb']) or $force_thumb) and preg_match('/^image\\/(jpe?g|gif|png)$/', $mimetype)) { if (empty($thumb_width)) { $thumb_width = 320; // default if (!empty($DBInfo->fetch_thumb_width)) { $thumb_width = $DBInfo->fetch_thumb_width; } } $thumbfile = preg_replace('@' . $ext . '$@', '.w' . $thumb_width . $ext, $fetchfile); if (empty($params['refresh']) && file_exists($thumbfile)) { break; } list($w, $h) = getimagesize($fetchfile); if ($w <= $thumb_width) { $thumbfile = $fetchfile; break; } require_once 'lib/mediautils.php'; // generate thumbnail using the gd func or the ImageMagick(convert) resize_image($ext, $fetchfile, $thumbfile, $w, $h, $thumb_width); break; } $down_mode = 'inline'; if (!empty($thumbfile)) { $fetchfile = $thumbfile; } header("Content-Type: {$mimetype}\r\n"); header("Content-Length: " . filesize($fetchfile)); //header("Content-Disposition: $down_mode; ".$fname ); header("Content-Description: MoniWiki PHP Fetch Downloader"); $mtime = filemtime($fetchfile); $lastmod = gmdate("D, d M Y H:i:s", $mtime) . ' GMT'; $etag = md5($lastmod . $url . $thumbfile); header("Last-Modified: " . $lastmod); header('ETag: "' . $etag . '"'); header("Pragma:"); header('Cache-Control: public, max-age=' . $maxage); $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { header('X-Cache-Debug: Cached OK'); header('HTTP/1.0 304 Not Modified'); @ob_end_clean(); return null; } @ob_clean(); $ret = readfile($fetchfile); return null; }
function identicon_build($seed = '', $img = true, $outsize = '', $random = true, $displaysize = '') { //make an identicon and return the filepath or if write=false return picture directly if (function_exists("gd_info")) { // init random seed if ($random) { $id = substr(sha1($seed), 0, 10); mt_srand(hexdec($id)); } else { $id = $seed; } if ($outsize == '') { $outsize = $this->identicon_options['size']; } if ($displaysize == '') { $displaysize = $outsize; } // HTTP Conditional get. $mtime = filemtime(__FILE__); $lastmod = substr(gmdate('r', $mtime), 0, -5) . 'GMT'; $etag = $mtime . $displaysize . $outsize . $id; $etag = md5($etag); $need = http_need_cond_request($mtime, $lastmod, $etag); $maxage = 60 * 60 * 24 * 7; header('Last-Modified: ' . $lastmod); header('ETag: "' . $etag . '"'); header('Cache-Control: public, max-age=' . $maxage); header('Pragma: cache'); if (!$need) { header('HTTP/1.0 304 Not Modified'); @ob_end_clean(); return true; } // $this->im = imagecreatetruecolor($this->size, $this->size); $this->colors = array(imagecolorallocate($this->im, 255, 255, 255)); if ($random) { $this->identicon_set_randomness($id); } else { $this->colors = array(imagecolorallocate($this->im, 255, 255, 255), imagecolorallocate($this->im, 0, 0, 0)); $this->transparent = false; } imagefill($this->im, 0, 0, $this->colors[0]); for ($i = 0; $i < $this->blocks; $i++) { for ($j = 0; $j < $this->blocks; $j++) { $this->identicon_draw_shape($i, $j); } } $out = @imagecreatetruecolor($outsize, $outsize); imagesavealpha($out, true); imagealphablending($out, false); imagecopyresampled($out, $this->im, 0, 0, 0, 0, $outsize, $outsize, $this->size, $this->size); imagedestroy($this->im); header("Content-type: image/png"); imagepng($out); imagedestroy($out); return true; } else { //php GD image manipulation is required return false; //php GD image isn't installed but don't want to mess up blog layout } }
function do_editstat($formatter, $params = array()) { global $Config; $opts = array(); $opts['.oldest'] = !empty($Config['editstat_datetime_oldest']) ? $Config['editstat_datetime_oldest'] : '-1 year'; if (!empty($params['days'])) { $days = intval($params['days']); } else { $days = 50; } // default 50 days if ($days > 200) { $days = 200; } $opts['.max_range'] = $days . ' day'; // image height if (!empty($params['h'])) { $height = intval($params['h']); } else { $height = 30; } // default image height if ($height > 200) { $height = 200; } // check request paramters if (isset($params['type']) && $params['type'] == 'user') { $type = 'user_count'; } else { $type = 'data'; } // round timestamp $tmp = time(); $tmp = date('Y-m-d 00:00:00', $tmp); $time = strtotime($tmp); // setup headers $lastmod = substr(gmdate('r', $time), 0, -5) . 'GMT'; $tag = $type . ',' . $time . ',' . $days . ',' . $height; $etag = md5($tag); $need = http_need_cond_request($time, $lastmod, $etag); if (!$need) { header('HTTP/1.0 304 Not Modified'); @ob_end_clean(); return; } // get editlogbin $data = cached_editlogbin($formatter, $opts); // check max $j = 0; $max = 0; foreach ($data[$type] as $idx => $c) { if ($c > $max) { $max = $c; } if (++$j > 30) { break; } } // graph parameters $wpen = 3; // pen width $gap = 1; // margin // $days + today $width = ($days + 1) * ($wpen + $gap) + $gap; $nolab = false; // make transparent image $canvas = imagecreatetruecolor($width, $height + ($nolab ? 0 : 8) + $gap * 2); imagealphablending($canvas, false); $bg = imagecolorallocatealpha($canvas, 255, 255, 255, 127); imagefill($canvas, 0, 0, $bg); imagesavealpha($canvas, true); $pens = array(); $r = 128; $g = 128; $b = 128; $pens[0] = imagecolorallocate($canvas, $r, $g, $b); $r = 185; $g = 180; $b = 184; $pens[1] = imagecolorallocate($canvas, $r, $g, $b); if (!$nolab) { $lab = $type[0] == 'u' ? 'Edit users' : 'Editstat'; imagestring($canvas, 1, 2, $height + 1, $lab . ' ' . date('Y-m-d H:i'), $pens[0]); } $x = $gap; $tmp = strtotime('-' . $days . ' days'); // week $time = strtotime(date('Y-m-d 00:00:00', $tmp)); $n = date('w', $time) - 1; $pen = 0; foreach ($data[$type] as $idx => $c) { $h = (int) ($c / $max * $height + 0.5); if ($n >= 7) { // change pen color for each weeks $pen++; $pen = $pen % 2; $n = 0; } imagefilledrectangle($canvas, $x, $height, $x + $wpen - 1, $height - $h, $pens[$pen]); $x += $wpen + $gap; $n++; } // setup expires $time = strtotime('+1 day'); $tmp = strtotime(date('Y-m-d 00:00:00', $time)); $expires = gmdate("D, d M Y H:i:s", $tmp) . ' GMT'; header('Content-Type: image/png'); $maxage = 60 * 60 * 24; header('Cache-Control: public, s-maxage=' . $maxage . ', max-age=' . $maxage); header('Last-Modified: ' . $lastmod); header('Expires: ' . $expires); header('ETag:"' . $etag . '"'); imagepng($canvas); imagedestroy($canvas); }
function do_retroidenticon($formatter, $params = array()) { $pixeldim = 5; $pixelsize = 80; $outsize = $pixelsize * $pixeldim; // Please see http://writings.orangegnome.com/writes/creating-identicons/ // Get seed if (!empty($params['seed'])) { $seed = $params['seed']; } else { $seed = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']); } if (!empty($params['pixelsize']) and $params['pixelsize'] > 1 and $params['pixelsize'] < 80) { $pixelsize = $params['pixelsize']; $outsize = $pixelsize * $pixeldim; } // HTTP Conditional get. $mtime = filemtime(__FILE__); $lastmod = substr(gmdate('r', $mtime), 0, -5) . 'GMT'; $etag = $mtime . $outsize . $seed; $etag = md5($etag); $need = http_need_cond_request($mtime, $lastmod, $etag); $maxage = 60 * 60 * 24 * 7; header('Last-Modified: ' . $lastmod); header('ETag: "' . $etag . '"'); header('Cache-Control: public, max-age=' . $maxage); header('Pragma: cache'); if (!$need) { header('HTTP/1.0 304 Not Modified'); @ob_end_clean(); return true; } // Convert seed to MD5 $hash = md5($seed); // Get color from first 6 characters $color = substr($hash, 0, 6); $pixels = array(); // make a multidimension array $half = round(($pixeldim - 1) / 2); for ($j = 0; $j < $pixeldim; $j++) { for ($i = 0; $i <= $half; $i++) { $k = 6 + $i * $pixeldim + $j; $pixels[$i][$j] = hexdec(substr($hash, $k, 1)) % 2 === 1; $pixels[$pixeldim - $i - 1][$j] = $pixels[$i][$j]; } } // set image size $image = imagecreatetruecolor($outsize, $outsize); // forground color. The hex code we assigned earlier needs to be decoded to RGB $color = imagecolorallocate($image, hexdec(substr($color, 0, 2)) & 255, hexdec(substr($color, 2, 2)) & 255, hexdec(substr($color, 4, 2)) & 255); // FIXME background color $bg = imagecolorallocate($image, 238, 238, 238); // Color the pixels for ($k = 0; $k < count($pixels); $k++) { for ($l = 0; $l < count($pixels[$k]); $l++) { // default pixel color is the background color $pixel = $bg; // If the value in the $pixels array is true, make the pixel color the primary color if ($pixels[$k][$l]) { $pixel = $color; } // Color the pixel. In a 400x400 image with a 5x5 grid of "pixels", each "pixel" is 80x80 imagefilledrectangle($image, $k * $pixelsize, $l * $pixelsize, ($k + 1) * $pixelsize, ($l + 1) * $pixelsize, $pixel); } } // Output the image header('Content-type: image/png'); imagepng($image); imagedestroy($image); return; }
function do_atom($formatter, $options) { global $DBInfo, $Config; global $_release; define('ATOM_DEFAULT_DAYS', 7); // get members to hide log $members = $DBInfo->members; $days = $DBInfo->rc_days ? $DBInfo->rc_days : ATOM_DEFAULT_DAYS; $options['quick'] = 1; if ($options['c']) { $options['items'] = $options['c']; } $lines = $DBInfo->editlog_raw_lines($days, $options); // HTTP conditional get $mtime = $DBInfo->mtime(); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $cache_ttl = !empty($DBInfo->atom_ttl) ? $DBInfo->atom_ttl : 60 * 30; /* 30 minutes */ // make etag based on some options and mtime. $check_opts = array('quick', 'items', 'c'); $check = array(); foreach ($check_opts as $c) { if (isset($options[$c])) { $check[$c] = $options[$c]; } } $etag = md5($mtime . $DBInfo->logo_img . serialize($check) . $cache_ttl . $options['id']); $headers = array(); $headers[] = 'Pragma: cache'; $maxage = $cache_ttl; $public = 'public'; if ($options['id'] != 'Anonymous') { $public = 'private'; } $headers[] = 'Cache-Control: ' . $public . ', max-age=' . $maxage; $headers[] = 'Last-Modified: ' . $lastmod; $headers[] = 'ETag: "' . $etag . '"'; $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { $headers[] = 'HTTP/1.0 304 Not Modified'; } foreach ($headers as $h) { header($h); } if (!$need) { @ob_end_clean(); return; } $cache = new Cache_Text('atom'); $cache_delay = min($cache_ttl, 30); $mtime = $cache->mtime($etag); $time_current = time(); $val = false; if (empty($formatter->refresh)) { if (($val = $cache->fetch($etag)) !== false and $DBInfo->checkUpdated($mtime, $cache_delay)) { header("Content-Type: application/xml"); echo $val; return; } } // need to update cache if ($val !== false and $cache->exists($etag . '.lock')) { header("Content-Type: application/xml"); echo $val . '<!-- cached at ' . date('Y-m-d H:i:s', $mtime) . ' -->'; return; } if ($cache->exists($etag . '.lock')) { header("Content-Type: application/xml"); echo ''; return; } $cache->update($etag . '.lock', array('lock'), 30); // 30s lock $URL = qualifiedURL($formatter->prefix); $img_url = qualifiedURL($DBInfo->logo_img); $url = qualifiedUrl($formatter->link_url($DBInfo->frontpage)); $surl = qualifiedUrl($formatter->link_url($options['page'] . '?action=atom')); $channel = <<<CHANNEL <title>{$DBInfo->sitename}</title> <link href="{$url}"></link> <link rel="self" type="application/atom+xml" href="{$surl}" /> <subtitle>RecentChanges at {$DBInfo->sitename}</subtitle> <generator version="{$_release}">MoniWiki Atom feeder</generator> CHANNEL; $items = ""; $ratchet_day = FALSE; if (!$lines) { $lines = array(); } foreach ($lines as $line) { $parts = explode("\t", $line); $page_name = $DBInfo->keyToPagename($parts[0]); // hide log if (!empty($members) && !in_array($options['id'], $members) && !empty($Config['ruleset']['hidelog'])) { if (in_array($page_name, $Config['ruleset']['hidelog'])) { continue; } } $addr = $parts[1]; $ed_time = $parts[2]; $user = $parts[4]; $user_uri = ''; if ($user != 'Anonymous' && $DBInfo->hasPage($user)) { $user_uri = $formatter->link_url(_rawurlencode($user), "", $user); $user_uri = '<uri>' . $user_uri . '</uri>'; } $log = _stripslashes($parts[5]); $act = rtrim($parts[6]); $url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name))); $diff_url = qualifiedUrl($formatter->link_url(_rawurlencode($page_name), '?action=diff')); $extra = "<br /><a href='{$diff_url}'>" . _("show changes") . "</a>\n"; $content = ''; if (!$DBInfo->hasPage($page_name)) { $status = 'deleted'; $content = "<content type='html'><a href='{$url}'>{$page_name}</a> is deleted</content>\n"; } else { $status = 'updated'; if ($options['diffs']) { $p = new WikiPage($page_name); $f = new Formatter($p); $options['raw'] = 1; $options['nomsg'] = 1; $html = $f->macro_repl('Diff', '', $options); if (!$html) { ob_start(); $f->send_page('', array('fixpath' => 1)); #$f->send_page(''); $html = ob_get_contents(); ob_end_clean(); $extra = ''; } $content = " <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>{$html}</content>\n"; } else { if ($log) { $html = str_replace('&', '&', $log); $content = "<content type='text'>" . $html . "</content>\n"; } else { $content = "<content type='text'>updated</content>\n"; } } } $zone = '+00:00'; $date = gmdate("Y-m-d\\TH:i:s", $ed_time) . $zone; if (!isset($updated)) { $updated = $date; } #$datetag = gmdate("YmdHis",$ed_time); $valid_page_name = str_replace('&', '&', $page_name); $items .= "<entry>\n"; $items .= " <title>{$valid_page_name}</title>\n"; $items .= " <link href='{$url}'></link>\n"; $items .= ' ' . $content; $items .= " <author><name>{$user}</name>{$user_uri}</author>\n"; $items .= " <updated>{$date}</updated>\n"; $items .= " <contributor><name>{$user}</name>{$user_uri}</contributor>\n"; $items .= "</entry>\n"; } $updated = " <updated>{$updated}</updated>\n"; $new = ""; if ($options['oe'] and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; if (function_exists('iconv')) { $out = $head . $channel . $items . $form; $new = iconv($DBInfo->charset, $charset, $out); if (!$new) { $charset = $DBInfo->charset; } } } else { $charset = $DBInfo->charset; } $head = <<<HEAD <?xml version="1.0" encoding="{$charset}"?> <!--<?xml-stylesheet href="{$DBInfo->url_prefix}/css/_feed.css" type="text/css"?>--> <feed xmlns="http://www.w3.org/2005/Atom"> <!-- Add "diffs=1" to add change diffs to the description of each items. Add "oe=utf-8" to convert the charset of this rss to UTF-8. --> HEAD; header("Content-Type: application/xml"); $out = ''; if ($new) { $out = $head . $new; } else { $out = $head . $channel . $updated . $items . $form; } $out .= "</feed>\n"; echo $out; $cache->update($etag, $out); $cache->remove($etag . '.lock'); }
function wiki_main($options) { global $DBInfo, $Config; $pagename = isset($options['pagename'][0]) ? $options['pagename'] : $DBInfo->frontpage; # get primary variables if (isset($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] == 'POST') { // reset some reserved variables if (isset($_POST['retstr'])) { unset($_POST['retstr']); } if (isset($_POST['header'])) { unset($_POST['header']); } # hack for TWiki plugin $action = ''; if (!empty($_FILES['filepath']['name'])) { $action = 'draw'; } if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) { # hack for Oekaki: PageName----action----filename list($pagename, $action, $value) = explode('----', $pagename, 3); $options['value'] = $value; } else { $value = !empty($_POST['value']) ? $_POST['value'] : ''; $action = !empty($_POST['action']) ? $_POST['action'] : $action; if (empty($action)) { $dum = explode('----', $pagename, 3); if (isset($dum[0][0]) && isset($dum[1][0])) { $pagename = trim($dum[0]); $action = trim($dum[1]); $value = isset($dum[2][0]) ? $dum[2] : ''; } } } $goto = !empty($_POST['goto']) ? $_POST['goto'] : ''; $popup = !empty($_POST['popup']) ? 1 : 0; // ignore invalid POST actions if (empty($goto) and empty($action)) { header('Status: 405 Not allowed'); return; } } else { // reset some reserved variables if (isset($_GET['retstr'])) { unset($_GET['retstr']); } if (isset($_GET['header'])) { unset($_GET['header']); } $action = !empty($_GET['action']) ? $_GET['action'] : ''; $value = isset($_GET['value'][0]) ? $_GET['value'] : ''; $goto = isset($_GET['goto'][0]) ? $_GET['goto'] : ''; $rev = !empty($_GET['rev']) ? $_GET['rev'] : ''; if ($options['id'] == 'Anonymous') { $refresh = 0; } else { $refresh = !empty($_GET['refresh']) ? $_GET['refresh'] : ''; } $popup = !empty($_GET['popup']) ? 1 : 0; } // parse action // action=foobar, action=foobar/macro, action=foobar/json etc. $full_action = $action; $action_mode = ''; if (($p = strpos($action, '/')) !== false) { $full_action = strtr($action, '/', '-'); $action_mode = substr($action, $p + 1); $action = substr($action, 0, $p); } $options['page'] = $pagename; $options['action'] =& $action; $reserved = array('call', 'prefix'); foreach ($reserved as $k) { unset($options[$k]); } // unset all reserved // check pagename length $key = $DBInfo->pageToKeyname($pagename); if (!empty($options['action']) && strlen($key) > 255) { $i = 252; // 252 + reserved 3 (.??) = 255 $newname = $DBInfo->keyToPagename(substr($key, 0, 252)); $j = mb_strlen($newname, $Config['charset']); $j--; do { $newname = mb_substr($pagename, 0, $j, $Config['charset']); $key = $DBInfo->pageToKeyname($newname); } while (strlen($key) > 248 && --$j > 0); $options['page'] = $newname; $options['orig_pagename'] = $pagename; // original page name $pagename = $newname; } else { $options['orig_pagename'] = ''; } if (function_exists('local_pre_check')) { local_pre_check($action, $options); } // load ruleset if (!empty($Config['config_ruleset'])) { $ruleset_file = 'config/ruleset.' . $Config['config_ruleset'] . '.php'; if (file_exists($ruleset_file)) { $ruleset = load_ruleset($ruleset_file); $Config['ruleset'] = $ruleset; } // is it robot ? if (!empty($ruleset['allowedrobot'])) { if (empty($_SERVER['HTTP_USER_AGENT'])) { $options['is_robot'] = 1; } else { $options['is_robot'] = is_allowed_robot($ruleset['allowedrobot'], $_SERVER['HTTP_USER_AGENT']); } } // setup staff members if (!empty($ruleset['staff'])) { $DBInfo->members = array_merge($DBInfo->members, $ruleset['staff']); } } $page = $DBInfo->getPage($pagename); $page->is_static = false; // FIXME $pis = array(); // get PI cache if ($page->exists()) { $page->pi = $pis = $page->get_instructions('', array('refresh' => $refresh)); // set some PIs for robot if (!empty($options['is_robot'])) { $DBInfo->use_sectionedit = 0; # disable section edit $page->is_static = true; } else { if ($_SERVER['REQUEST_METHOD'] == 'GET' or $_SERVER['REQUEST_METHOD'] == 'HEAD') { if (empty($action) and empty($refresh)) { $page->is_static = empty($pis['#nocache']) && empty($pis['#dynamic']); } } } } // HEAD support for robots if (empty($action) and !empty($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] == 'HEAD') { if (!$page->exists()) { header("HTTP/1.1 404 Not found"); header("Status: 404 Not found"); } else { if ($page->is_static or is_static_action($options)) { $mtime = $page->mtime(); $etag = $page->etag($options); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); header('Last-Modified: ' . $lastmod); if (!empty($action)) { $etag = '"' . $etag . '"'; header('ETag: ' . $etag); } // checksum request if (isset($_SERVER['HTTP_X_GET_CHECKSUM'])) { header('X-Checksum: md5-' . md5($page->get_raw_body())); } } } return; } if (is_static_action($options) or !empty($DBInfo->use_conditional_get) and $page->is_static) { $mtime = $page->mtime(); $etag = $page->etag($options); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { @ob_end_clean(); $headers = array(); $headers[] = 'HTTP/1.0 304 Not Modified'; $headers[] = 'Last-Modified: ' . $lastmod; foreach ($headers as $header) { header($header); } return; } } $formatter = new Formatter($page, $options); $formatter->refresh = !empty($refresh) ? $refresh : ''; $formatter->popup = !empty($popup) ? $popup : ''; $formatter->tz_offset = $options['tz_offset']; // check blocklist/whitelist for block_actions $act = strtolower($action); while (!empty($DBInfo->block_actions) && !empty($ruleset) && in_array($act, $DBInfo->block_actions)) { require_once 'lib/checkip.php'; // check whitelist if (isset($ruleset['whitelist']) && check_ip($ruleset['whitelist'], $_SERVER['REMOTE_ADDR'])) { break; } $res = null; // check blacklist if (isset($ruleset['blacklist']) && check_ip($ruleset['blacklist'], $_SERVER['REMOTE_ADDR']) || isset($ruleset['blacklist.ranges']) && search_network($ruleset['blacklist.ranges'], $_SERVER['REMOTE_ADDR'])) { $res = true; } else { if (!empty($DBInfo->use_dynamic_blacklist)) { require_once 'plugin/ipinfo.php'; $blacklist = get_cached_temporary_blacklist(); $retval = array(); $ret = array('retval' => &$retval); $res = search_network($blacklist, $_SERVER['REMOTE_ADDR'], $ret); if ($res !== false) { // retrieve found $ac = new Cache_Text('ipblock'); $info = $ac->fetch($retval, 0, $ret); if ($info !== false) { if (!$info['suspended']) { // whitelist IP break; } $res = true; } else { $ac->remove($retval); // expired IP entry. $res = false; } } } } // show warning message if ($res) { $options['notice'] = _("Your IP is in the blacklist"); $options['msg'] = _("Please contact WikiMasters"); $options['msgtype'] = 'warn'; if (!empty($DBInfo->edit_actions) and in_array($act, $DBInfo->edit_actions)) { $options['action'] = $action = 'edit'; } else { if ($act != 'edit') { $options['action'] = $action = 'show'; } } break; } // check kiwirian if (isset($ruleset['kiwirian']) && in_array($options['id'], $ruleset['kiwirian'])) { $options['title'] = _("You are blocked in this wiki"); $options['msg'] = _("Please contact WikiMasters"); do_invalid($formatter, $options); return false; } break; } // set robot class if (!empty($options['is_robot'])) { if (!empty($DBInfo->security_class_robot)) { $class = 'Security_' . $DBInfo->security_class_robot; include_once 'plugin/security/' . $DBInfo->security_class_robot . '.php'; } else { $class = 'Security_robot'; include_once 'plugin/security/robot.php'; } $DBInfo->security = new $class($DBInfo); // is it allowed to robot ? if (!$DBInfo->security->is_allowed($action, $options)) { $action = 'show'; if (!empty($action_mode)) { return '[]'; } } $DBInfo->extra_macros = ''; } while (empty($action) or $action == 'show') { if (isset($value[0])) { # ?value=Hello $options['value'] = $value; do_goto($formatter, $options); return true; } else { if (isset($goto[0])) { # ?goto=Hello $options['value'] = $goto; do_goto($formatter, $options); return true; } } if (!$page->exists()) { if (isset($options['retstr'])) { return false; } if (!empty($DBInfo->auto_search) && $action != 'show' && ($p = getPlugin($DBInfo->auto_search))) { $action = $DBInfo->auto_search; break; } // call notfound action $action = 'notfound'; break; } # render this page if (isset($_GET['redirect']) and !empty($DBInfo->use_redirect_msg) and $action == 'show') { $redirect = $_GET['redirect']; $options['msg'] = '<h3>' . sprintf(_("Redirected from page \"%s\""), $formatter->link_tag(_rawurlencode($redirect), '?action=show', $redirect)) . "</h3>"; } if (empty($action)) { $options['pi'] = 1; } # protect a recursivly called #redirect if (!empty($DBInfo->control_read) and !$DBInfo->security->is_allowed('read', $options)) { $options['action'] = 'read'; do_invalid($formatter, $options); return; } $formatter->pi = $formatter->page->get_instructions(); if (!empty($DBInfo->body_attr)) { $options['attr'] = $DBInfo->body_attr; } $ret = $formatter->send_header('', $options); if (empty($options['is_robot'])) { if ($DBInfo->use_counter) { $DBInfo->counter->incCounter($pagename, $options); } if (!empty($DBInfo->use_referer) and isset($_SERVER['HTTP_REFERER'])) { log_referer($_SERVER['HTTP_REFERER'], $pagename); } } $formatter->send_title("", "", $options); $formatter->write("<div id='wikiContent'>\n"); if (isset($options['timer']) and is_object($options['timer'])) { $options['timer']->Check("init"); } // force #nocache for #redirect pages if (isset($formatter->pi['#redirect'][0])) { $formatter->pi['#nocache'] = 1; } $extra_out = ''; $options['pagelinks'] = 1; if (!empty($Config['cachetime']) and $Config['cachetime'] > 0 and empty($formatter->pi['#nocache'])) { $cache = new Cache_text('pages', array('ext' => 'html')); $mcache = new Cache_text('dynamic_macros'); $mtime = $cache->mtime($pagename); $now = time(); $check = $now - $mtime; $_macros = null; if ($cache->mtime($pagename) < $formatter->page->mtime()) { $formatter->refresh = 1; } // force update $valid = false; $delay = !empty($DBInfo->default_delaytime) ? $DBInfo->default_delaytime : 0; if (empty($formatter->refresh) and $DBInfo->checkUpdated($mtime, $delay) and $check < $Config['cachetime']) { if ($mcache->exists($pagename)) { $_macros = $mcache->fetch($pagename); } // FIXME TODO: check postfilters if (0 && empty($_macros)) { #$out = $cache->fetch($pagename); $valid = $cache->fetch($pagename, '', array('print' => 1)); } else { $out = $cache->fetch($pagename); $valid = $out !== false; } $mytime = gmdate("Y-m-d H:i:s", $mtime + $options['tz_offset']); $extra_out = "<!-- Cached at {$mytime} -->"; } if (!$valid) { $formatter->_macrocache = 1; ob_start(); $formatter->send_page('', $options); flush(); $out = ob_get_contents(); ob_end_clean(); $formatter->_macrocache = 0; $_macros = $formatter->_dynamic_macros; if (!empty($_macros)) { $mcache->update($pagename, $_macros); } if (isset($out[0])) { $cache->update($pagename, $out); } } if (!empty($_macros)) { $mrule = array(); $mrepl = array(); foreach ($_macros as $m => $v) { if (!is_array($v)) { continue; } $mrule[] = '@@' . $v[0] . '@@'; $options['mid'] = $v[1]; $mrepl[] = $formatter->macro_repl($m, '', $options); // XXX } echo $formatter->get_javascripts(); $out = str_replace($mrule, $mrepl, $out); // no more dynamic macros found if (empty($formatter->_dynamic_macros)) { // update contents $cache->update($pagename, $out); // remove dynamic macros cache $mcache->remove($pagename); } } if ($options['id'] != 'Anonymous') { $args['refresh'] = 1; } // add refresh menu } else { ob_start(); $formatter->send_page('', $options); flush(); $out = ob_get_contents(); ob_end_clean(); } // fixup to use site specific thumbwidth if (!empty($Config['site_thumb_width']) and $Config['site_thumb_width'] != $DBInfo->thumb_width) { $opts = array('thumb_width' => $Config['site_thumb_width']); $out = $formatter->postfilter_repl('imgs_for_mobile', $out, $opts); } echo $out, $extra_out; // automatically set #dynamic PI if (empty($formatter->pi['#dynamic']) and !empty($formatter->_dynamic_macros)) { $pis = $formatter->pi; if (empty($pis['raw'])) { // empty PIs $pis = array(); } else { if (isset($pis['#format']) and !preg_match('/#format\\s/', $pis['raw'])) { // #format not found in PIs unset($pis['#format']); } } $pis['#dynamic'] = 1; // internal instruction $pi_cache = new Cache_text('PI'); $pi_cache->update($formatter->page->name, $pis); } else { if (empty($formatter->_dynamic_macros) and !empty($formatter->pi['#dynamic'])) { $pi_cache = new Cache_text('PI'); $pi_cache->remove($formatter->page->name); // reset PI $mcache->remove($pagename); // remove macro cache if (isset($out[0])) { $cache->update($pagename, $out); } // update cache content } } if (isset($options['timer']) and is_object($options['timer'])) { $options['timer']->Check("send_page"); } $formatter->write("<!-- wikiContent --></div>\n"); if (!empty($DBInfo->extra_macros) and $formatter->pi['#format'] == $DBInfo->default_markup) { if (!empty($formatter->pi['#nocomment'])) { $options['nocomment'] = 1; $options['notoolbar'] = 1; } $options['mid'] = 'dummy'; echo '<div id="wikiExtra">' . "\n"; $mout = ''; $extra = array(); if (is_array($DBInfo->extra_macros)) { $extra = $DBInfo->extra_macros; } else { $extra[] = $DBInfo->extra_macros; } // XXX if (!empty($formatter->pi['#comment'])) { array_unshift($extra, 'Comment'); } foreach ($extra as $macro) { $mout .= $formatter->macro_repl($macro, '', $options); } echo $formatter->get_javascripts(); echo $mout; echo '</div>' . "\n"; } $args['editable'] = 1; $formatter->send_footer($args, $options); return; } $act = $action; if (!empty($DBInfo->myplugins) and array_key_exists($action, $DBInfo->myplugins)) { $act = $DBInfo->myplugins[$action]; } if ($act) { $options['noindex'] = true; $options['custom'] = ''; $options['help'] = ''; $options['value'] = $value; $a_allow = $DBInfo->security->is_allowed($act, $options); if (!empty($action_mode)) { $myopt = $options; $myopt['explicit'] = 1; $f_allow = $DBInfo->security->is_allowed($full_action, $myopt); # check if hello/ajax is defined or not if ($f_allow === false && $a_allow) { $f_allow = $a_allow; } # follow action permission if it is not defined explicitly. if (!$f_allow) { $args = array('action' => $action); $args['allowed'] = $options['allowed'] = $f_allow; if ($f_allow === false) { $title = sprintf(_("%s action is not found."), $action); } else { $title = sprintf(_("Invalid %s action."), $action_mode); } if ($action_mode == 'ajax') { $args['title'] = $title; return ajax_invalid($formatter, $args); } $options['title'] = $title; return do_invalid($formatter, $options); } } else { if (!$a_allow) { $options['allowed'] = $a_allow; if ($options['custom'] != '' and method_exists($DBInfo->security, $options['custom'])) { $options['action'] = $action; if ($action) { call_user_func(array(&$DBInfo->security, $options['custom']), $formatter, $options); } return; } return do_invalid($formatter, $options); } else { if ($_SERVER['REQUEST_METHOD'] == "POST" and $DBInfo->security->is_protected($act, $options) and !$DBInfo->security->is_valid_password($_POST['passwd'], $options)) { # protect some POST actions and check a password $title = sprintf(_("Fail to \"%s\" !"), $action); $formatter->send_header("", $options); $formatter->send_title($title, "", $options); $formatter->send_page("== " . _("Please enter the valid password") . " =="); $formatter->send_footer("", $options); return; } } } $options['action_mode'] = ''; if (!empty($action_mode) and in_array($action_mode, array('ajax', 'macro'))) { if ($_SERVER['REQUEST_METHOD'] == "POST") { $options = array_merge($_POST, $options); } else { $options = array_merge($_GET, $options); } $options['action_mode'] = $action_mode; if ($action_mode == 'ajax') { $formatter->ajax_repl($action, $options); } else { if (!empty($DBInfo->use_macro_as_action)) { # XXX echo $formatter->macro_repl($action, $options['value'], $options); } else { do_invalid($formatter, $options); } } return; } // is it valid action ? $plugin = $pn = getPlugin($action); if ($plugin === '') { // action not found $plugin = $action; } if (!function_exists("do_post_" . $plugin) and !function_exists("do_" . $plugin) and $pn) { include_once "plugin/{$pn}.php"; } if (function_exists("do_" . $plugin)) { if ($_SERVER['REQUEST_METHOD'] == "POST") { $options = array_merge($_POST, $options); } else { $options = array_merge($_GET, $options); } call_user_func("do_{$plugin}", $formatter, $options); return; } else { if (function_exists("do_post_" . $plugin)) { if ($_SERVER['REQUEST_METHOD'] == "POST") { $options = array_merge($_POST, $options); } else { # do_post_* set some primary variables as $options $options['value'] = isset($_GET['value'][0]) ? $_GET['value'] : ''; } call_user_func("do_post_{$plugin}", $formatter, $options); return; } } do_invalid($formatter, $options); return; } }
function do_sitemap($formatter, $options) { global $DBInfo, $Config; $tc = new Cache_text('persist', array('depth' => 0)); $extra = ''; if (!empty($formater->group)) { $extra = '.' . $formatter->group; } if (!empty($formatter->prefix)) { $extra .= qualifiedUrl($formatter->prefix); } // all pages $mtime = $DBInfo->mtime(); $lastmod = gmdate('D, d M Y H:i:s \\G\\M\\T', $mtime); $etag = md5($mtime . $DBInfo->etag_seed . $extra); $options['etag'] = $etag; $options['mtime'] = $mtime; // set the s-maxage for proxy $date = gmdate('Y-m-d-H-i-s', $mtime); $proxy_maxage = !empty($Config['proxy_maxage']) ? ', s-maxage=' . $Config['proxy_maxage'] : ''; // only xml format supported $format = 'text/xml'; if (isset($options['format']) and in_array($options['format'], array('text/xml'))) { $format = $options['format']; } $header[] = 'Content-Type: ' . $format; $header[] = 'Cache-Control: public' . $proxy_maxage . ', max-age=0, must-revalidate'; $need = http_need_cond_request($mtime, $lastmod, $etag); if (!$need) { $header[] = 'HTTP/1.0 304 Not Modified'; } else { $header[] = 'Content-Disposition: attachment; filename="sitemap-' . $date . '.xml"'; } $formatter->send_header($header, $options); if (!$need) { @ob_end_clean(); return; } if (!$formatter->refresh && ($ret = $tc->fetch('sitemap' . $extra . '.mtime')) !== false) { if (($ret = $tc->fetch('sitemap' . $extra, 0, array('print' => 1))) !== false) { return; } } // set sitemap public cache $ext = $format == 'text/xml' ? 'xml' : 'txt'; $sc = new Cache_text('sitemap', array('dir' => $DBInfo->cache_public_dir, 'ext' => $ext, 'depth' => 0)); # get page list set_time_limit(0); if ($formater->group) { $group_pages = $DBInfo->getLikePages($formater->group); foreach ($group_pages as $page) { $all_pages[] = str_replace($formatter->group, '', $page); } usort($all_pages, 'strcasecmp'); } else { if (!empty($Config['sitemap_sortby'])) { // call PageSort macro. $opts = array(); $opts['sortby'] = $Config['sitemap_sortby']; // date or size $opts['.call'] = 1; $ret = $formatter->macro_repl('PageSort', '', $opts); $all_pages = array(); if (!empty($ret['count'])) { $tc->fetch('pagedate.raw'); $rawfile = $tc->cache_path . '/' . $tc->getKey('pagedate.raw'); $fp = fopen($rawfile, 'r'); if (is_resource($fp)) { while (($line = fgets($fp, 1024)) != false) { $tmp = explode("\t", $line); $all_pages[] = $tmp[0]; } fclose($fp); } } } else { $args = array('all' => 1); $all_pages = $DBInfo->getPageLists($args); usort($all_pages, 'strcasecmp'); } } $count = sizeof($all_pages); $map = ''; $zone = '+00:00'; $ttl = !empty($DBInfo->sitemap_ttl) ? $DBInfo->sitemap_ttl : 60 * 60 * 24 * 7; if ($count > 50000) { $map = <<<HEAD <?xml version="1.0" encoding="UTF-8"?> <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> HEAD; $date = gmdate("Y-m-d\\TH:i:s", time()) . $zone; // W3C datetime format $total = intval($count / 50000) + ($count % 50000 > 0 ? 1 : 0); for ($i = 0; $i < $total; $i++) { $mapname = $sc->getKey(sprintf('sitemap' . $extra . '%03d', $i)); $map .= "<sitemap>\n<loc>\n" . qualifiedUrl($DBInfo->cache_public_url . '/' . $mapname) . '</loc>' . "\n"; $map .= '<lastmod>' . $date . "</lastmod>\n</sitemap>\n"; } $map .= "</sitemapindex>\n"; $tc->update('sitemap' . $extra, $map); $tc->update('sitemap' . $extra . '.mtime', array('dummy' => 1), $ttl); } # charset if ($options['oe'] and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; } else { $charset = $DBInfo->charset; } $head = <<<HEAD <?xml version="1.0" encoding="{$charset}"?> <urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9" url="http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> HEAD; $foot = <<<FOOT </urlset> FOOT; # process page list $i = 0; $ii = 0; $items = array(); foreach ($all_pages as $page) { $ii++; $url = qualifiedUrl($formatter->link_url(_rawurlencode($page))); $p = new WikiPage($page); $t = $p->mtime(); $date = gmdate("Y-m-d\\TH:i:s", $t) . $zone; // W3C datetime format $item = "<url>\n"; $item .= " <loc>" . $url . "</loc>\n"; $item .= " <lastmod>" . $date . "</lastmod>\n"; $item .= "</url>"; $items[] = $item; if ($ii >= 50000) { $ii = 0; // process output $out = implode("\n", $items); if ($options['oe'] and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; if (function_exists('iconv')) { $new = iconv($DBInfo->charset, $charset, $items); if (!$new) { $charset = $DBInfo->charset; } if ($new) { $out = $new; } } } $sc->update(sprintf('sitemap' . $extra . '%03d', $i), $head . $out . $foot); $i++; $items = array(); } } $sc->update('sitemap' . $extra . '.mtime', array('dummy' => 1), $ttl); // process output if ($count > 50000) { if (count($items)) { $out = implode("\n", $items); if ($options['oe'] and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; if (function_exists('iconv')) { $new = iconv($DBInfo->charset, $charset, $items); if (!$new) { $charset = $DBInfo->charset; } if ($new) { $out = $new; } } } $sc->update(sprintf('sitemap' . $extra . '%03d', $i), $head . $out . $foot); } } else { $out = implode("\n", $items); if ($options['oe'] and strtolower($options['oe']) != $DBInfo->charset) { $charset = $options['oe']; if (function_exists('iconv')) { $new = iconv($DBInfo->charset, $charset, $items); if (!$new) { $charset = $DBInfo->charset; } if ($new) { $out = $new; } } } $map = $head . $out . $foot; $tc->update('sitemap' . $extra, $map); $tc->update('sitemap' . $extra, array('dummy' => 1), $ttl); } echo $map; }