INT CONSTANT DESCRIPTION
---- ----------- ----------------------------------
0 LOG_EMERG system is unusable
1 LOG_ALERT action must be taken immediately
2 LOG_CRIT critical conditions
3 LOG_ERR error conditions
4 LOG_WARNING warning conditions
5 LOG_NOTICE normal, but significant, condition
6 LOG_INFO informational message
7 LOG_DEBUG debug-level message
static public log ( ) |
function authenticate($users = null) { if (!isset($_SERVER['PHP_AUTH_DIGEST']) || empty($_SERVER['PHP_AUTH_DIGEST'])) { return false; } # users if ($users === null) { $users = $this->users ? $this->users : array(); } # analyze if (!($data = self::parse($_SERVER['PHP_AUTH_DIGEST']))) { gb::log('GBHTTPDigestAuth: failed to parse ' . var_export($_SERVER['PHP_AUTH_DIGEST'], 1)); return false; } elseif (!isset($users[$data['username']])) { gb::log('GBHTTPDigestAuth: unknown username ' . var_export($data['username'], 1)); return false; } # check input if ($this->ttl > 0 && $data['nonce'] !== $this->nonce()) { return false; } # generate the valid response $A1 = $users[$data['username']]; # MD5(username:realm:password) $A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $data['uri']); # MD5(method:digestURI) $valid_response = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' . $A2); if ($data['response'] != $valid_response) { gb::log('GBHTTPDigestAuth: unexpected response ' . var_export($data['response'], 1)); return false; } return $data['username']; }
static function init($context) { self::$conf = gb::data('plugins/' . gb_filenoext(basename(__FILE__)), array('url' => '')); if (!self::$conf['url']) { gb::log(LOG_WARNING, 'missing "url" in configuration'); return false; } gb::observe('will-handle-request', array(__CLASS__, 'will_handle_req')); return true; }
static function init($context) { self::$conf = gb::data('plugins/google-analytics', array('property_id' => '')); if (!self::$conf['property_id']) { gb::log(LOG_WARNING, 'missing property_id in google-analytics configuration'); } else { gb::observe('on-html-footer', array(__CLASS__, 'echo_tracking_code')); return true; } return false; }
/** * Rebuild caches, indexes, etc. */ static function rebuild($forceFullRebuild = false) { gb::log(LOG_NOTICE, 'rebuilding cache' . ($forceFullRebuild ? ' (forcing full rebuild)' : '')); $time_started = microtime(1); $failures = array(); # Load rebuild plugins gb::load_plugins('rebuild'); # Load rebuilders if needed if (empty(self::$rebuilders)) { self::loadRebuilders(); } # Create rebuilder instances $rebuilders = array(); foreach (self::$rebuilders as $cls) { $rebuilders[] = new $cls($forceFullRebuild); } # Load rebuild plugins (2nd offer) gb::load_plugins('rebuild'); # Query ls-tree $ls = rtrim(git::exec('ls-files --stage')); if ($ls) { # Iterate objects $ls = explode("\n", $ls); foreach ($ls as $line) { try { # <mode> SP <object> SP <stage no> TAB <name> if (!$line) { continue; } $line = explode(' ', $line, 3); $id = $line[1]; $name = gb_normalize_git_name(substr($line[2], strpos($line[2], "\t") + 1)); foreach ($rebuilders as $rebuilder) { $rebuilder->onObject($name, $id); } } catch (RuntimeException $e) { gb::log(LOG_ERR, 'failed to rebuild object %s %s: %s', var_export($name, 1), $e->getMessage(), $e->getTraceAsString()); $failures[] = array($rebuilder, $name); } } } # Let rebuilders finalize foreach ($rebuilders as $rebuilder) { try { $rebuilder->finalize(); } catch (RuntimeException $e) { gb::log(LOG_ERR, 'rebuilder %s (0x%x) failed to finalize: %s', get_class($rebuilder), spl_object_hash($rebuilder), GBException::format($e, true, false, null, 0)); $failures[] = array($rebuilder, null); } } gb::log(LOG_NOTICE, 'cache updated -- time spent: %s', gb_format_duration(microtime(1) - $time_started)); return $failures; }
} header('HTTP/1.1 303 See Other'); header('Location: ' . $referrer); exit(0); } else { exit2("new comment: {$comment->id}\n", '200 OK'); } } catch (Exception $e) { if ($e instanceof GitError && strpos($e->getMessage(), 'nothing to commit') !== false) { gb::log('skipped duplicate comment from ' . var_export($comment->email, 1) . ' (nothing to commit)'); gb::event('was-duplicate-comment', $comment); header('HTTP/1.1 304 Not Modified'); header('Location: ' . $input['gb-referrer'] . '#skipped-duplicate-reply'); exit(0); } gb::log(LOG_ERR, 'failed to add comment ' . var_export($comment->body, 1) . ' from ' . var_export($comment->name, 1) . ' <' . var_export($comment->email, 1) . '>' . ' to ' . $post->cachename()); header('HTTP/1.1 500 Internal Server Error'); echo '$input => '; var_export($input); echo "\n"; gb_flush(); throw $e; } } else { # rejected by filter(s) if ($referrer) { $referrer->fragment = 'comments'; $referrer['comment-status'] = 'rejected'; header('HTTP/1.1 303 See Other'); header('Location: ' . $referrer); } else {
static function did_add_comment($comment) { if ($comment->spam) { return; } # really do this? if ($comment->approved && !self::$data['notify_new_comment']) { return; } elseif (!$comment->approved && !self::$data['notify_pending_comment']) { return; } $subject = '[' . gb::$site_title . '] ' . ($comment->approved ? 'New' : 'Pending') . ' comment on "' . $comment->post->title . '"'; $body = self::comment_mkbody($comment); $to = self::recipient($comment); if (!$to[0]) { gb::log(LOG_WARNING, 'failed to deduce recipient -- ' . 'please add your address to "admin" in data/email.json'); } else { GBMail::compose($subject, $body, $to)->send(true); } }
function deduceChannelTimezoneOffset($channel) { # find timezone $diffs = array(); foreach ($channel->getElementsByTagName('item') as $item) { if ($item->nodeType !== XML_ELEMENT_NODE) { continue; } $localdate = ''; $utcdate = ''; foreach ($item->childNodes as $n) { if ($n->nodeType !== XML_ELEMENT_NODE) { continue; } $nname = '' . $n->nodeName; if ($nname === 'wp:post_date') { $localdate = $n->nodeValue; } elseif ($nname === 'wp:post_date_gmt') { $utcdate = $n->nodeValue; } } if ($utcdate !== '0000-00-00 00:00:00') { # lets guess the timezone. yay $diff = strtotime($localdate) - strtotime($utcdate); if (isset($diffs[$diff])) { $diffs[$diff]++; } else { $diffs[$diff] = 1; } } } #var_export($diffs); if (count($diffs) === 1) { return key($diffs); } $k = array_keys($diffs); $mindiff = min($k[0], $k[1]); $difference = max($k[0], $k[1]) - $mindiff; if (count($diffs) === 2) { #$v = array_values($diffs); #echo "distribution ";var_dump(max($v[0],$v[1]) - min($v[0],$v[1])); #echo "difference ";var_dump($difference); #echo "variation ";var_dump(count($diffs));#floatval(max($k[0],$k[1])) / floatval($mindiff)); #echo "occurance min/max ", min($v[0],$v[1]), '/', max($v[0],$v[1]), PHP_EOL; #echo "offsets min/max ", $mindiff, '/', max($k[0],$k[1]), PHP_EOL; if ($difference === $mindiff) { return $mindiff; } # most likely DST causing the variation, so } gb::log(LOG_WARNING, 'unable to exactly deduce timezone -- guessing %s%d', $mindiff < 0 ? '-' : '+', $mindiff); return $mindiff; }
function sync($force = false) { if ($this->index === null) { return false; } $data = $this->serialize(); if ($this->checksum !== null && $this->checksum === sha1($data) && $force === false) { return false; } # no changes $bw = file_put_contents($this->path(), $data, LOCK_EX); chmod($this->path(), 0664); gb::log(LOG_NOTICE, 'wrote %s', $this->cachename()); return $bw; }
<?php require '../_base.php'; gb::verify(); $authed = gb::authenticate(false); if ($authed) { gb::log('client authorized: ' . $authed); gb_author_cookie::set($authed->email, $authed->name, gb::$site_url); gb::event('client-authorized', $authed); $url = isset($_REQUEST['referrer']) && $_REQUEST['referrer'] ? $_REQUEST['referrer'] : gb_admin::$url; header('HTTP/1.1 303 See Other'); header('Location: ' . $url); exit('<html><body>See Other <a href="' . $url . '"></a></body></html>'); } if (isset($_POST['chap-username'])) { if ($authed === CHAP::BAD_USER) { gb::$errors[] = 'No such user'; } elseif ($authed === CHAP::BAD_RESPONSE) { gb::$errors[] = 'Bad password'; } else { gb::$errors[] = 'Unknown error'; } } $auth = gb::authenticator(); include '../_header.php'; ?> <script type="text/javascript" src="<?php echo gb_admin::$url; ?> res/sha1-min.js"></script> <script type="text/javascript">
foreach ($state_fields as $k => $discard) { if ($k === 'body') { $modified_state[$k] = $post->rawBody(); } else { $v = $post->{$k}; if ($v instanceof GBDateTime) { $v = strval($v); } $modified_state[$k] = $v; } } } # commit? if ($input['commit']) { git::add($post->name); git::commit(($created ? 'Created' : 'Updated') . ' post ' . r($post->title), gb::$authorized, $post->name); } # build response entity $rsp = array('name' => $post->name, 'version' => $post->id, 'exists' => $post->exists(), 'isTracked' => $post->isTracked(), 'isDirty' => $post->isDirty(), 'state' => $modified_state); # status $status = '200 OK'; if ($created) { $status = '201 Created'; } # send JSON response gb_admin::json_rsp($rsp, $status); gb::log('saved post %s', $post->name); } catch (Exception $e) { gb::log('failed to save post: %s', GBException::format($e, true, false, null, 0)); gb_admin::json_rsp($e->getMessage(), '400 Bad Request'); }
function commit() { if ($this->txFp === false) { throw new LogicException('transaction is not active'); } $ex = null; try { $did_write = $this->txWriteData(); } catch (Exception $e) { $ex = $e; } $this->txEnd($ex); if ($ex) { throw $ex; } # commit to repo if ($did_write && $this->autocommitToRepo) { gb::log('committing changes to ' . $this->file); if (!($author = $this->autocommitToRepoAuthor)) { $author = GBUser::findAdmin()->gitAuthor(); } $m = $this->autocommitToRepoMessage ? $this->autocommitToRepoMessage : 'autocommit:' . $this->file; git::add($this->file); git::commit($m, $author); # rollback() will handle gb::reset if needed } return $did_write; }
static function perform($from, $to) { $from = gb::version_parse($from); $to = gb::version_parse($to); $froms = gb::version_format($from); $tos = gb::version_format($to); if ($from === $to) { return null; } $is_upgrade = $from < $to; $stages = self::build_stages($from, $to); gb::log('%s gitblog %s -> %s in %d stages', $is_upgrade ? 'upgrading' : 'downgrading', $froms, $tos, count($stages)); # don't break on client abort ignore_user_abort(true); foreach ($stages as $v => $stagefunc) { $prevvs = gb::version_format($v > 0 ? $v - 1 : $v); gb::log('%s -> %s (%s)', $prevvs, gb::version_format($v), $stagefunc[1], $v); # write prev version to site.json so next run will take off where we crashed, if we crash. $orig_v = gb::$version; gb::$version = $prevvs; gb_maint::sync_site_state(); gb::$version = $orig_v; $stages[$v] = call_user_func($stagefunc, $from, $to); } gb_maint::sync_site_state(); return $stages; }
static function mkmailer() { # setup conf $siteurl = new GBURL(gb::$site_url); $admin = GBUser::findAdmin(); $default_name = $admin ? $admin->name : $siteurl->host; $default_address = $admin ? $admin->email : 'root@' . $siteurl->host; self::$conf = gb::data('email', array('admin' => array($default_name, $default_address), 'from' => array(gb::$site_title, 'noreply@' . $siteurl->host), 'smtp.example-gmail' => array('secure' => 'ssl', 'host' => 'smtp.gmail.com:465', 'username' => $default_address, 'password' => 'secret'))); # since PHPMailer is one ugly piece of software $orig_error_reporting = error_reporting(E_ALL ^ E_NOTICE); # setup phpmailer $e = new PHPMailer(); $e->From = ''; $e->FromName = ''; $e->PluginDir = gb::$dir . '/lib/PHPMailer/'; # SMTP if (($c = self::$conf['smtp']) !== null) { $e->IsSMTP(); # enable SMTP # authenitcation? $e->SMTPAuth = isset($c['password']) || isset($c['username']); # secure? if (isset($c['secure']) && $c['secure']) { static $allowed = array('ssl' => 1, 'tls' => 1, '' => 1); $c['secure'] = is_string($c['secure']) ? strtolower($c['secure']) : ($c['secure'] ? 'ssl' : ''); if (!isset($allowed[$c['secure']])) { gb::log(LOG_WARNING, 'malformed configuration: bad value for "secure": %s -- only "ssl" or "tls" is allowed', $c['secure']); } else { $e->SMTPSecure = $c['secure']; } } # support for multiple hosts if (isset($c['host'])) { $e->Host = $c['host']; } elseif (isset($c['hosts'])) { $e->Host = $c['hosts']; } if (is_array($e->Host)) { $hosts = $e->Host; $e->Host = array(); foreach ($hosts as $host) { if (is_array($host)) { if (!isset($host['name'])) { gb::log(LOG_WARNING, 'malformed configuration: missing "name" for host %s', var_export($host, 1)); } else { $v[] = $host['name'] . (isset($host['port']) ? ':' . $host['port'] : ''); } } else { $v[] = $host; } } $e->Host = implode(';', $e->Host); } # default port if (isset($c['port']) && ($port = intval($c['port'])) > 0) { $e->Port = $port; } # username if (isset($c['username'])) { $e->Username = $c['username']; } # password if (isset($c['password'])) { $e->Password = $c['password']; } # connection timeout if (isset($c['timeout']) && ($i = intval($c['timeout'])) > 0) { $e->Timeout = $i; } } # gitblog <heart> UTF-8 $e->CharSet = 'utf-8'; # Default from if ($from = self::$conf['from']) { list($e->From, $e->FromName) = self::normalizeRecipient($from); } # Default sender if (($sender = self::$conf['sender']) || ($sender = self::$conf['admin'])) { list($e->Sender, $discard) = self::normalizeRecipient($sender); } # default priority if ($priority = self::$conf['priority']) { $e->Priority = intval($priority); } # reset error reporting error_reporting($orig_error_reporting); return $e; }
static function commit($message, $author = null, $pathspec = null, $deferred = false) { # clear status cache self::$status_cache = null; if ($deferred && gb::defer(array('gb', 'commit'), $message, $author, $pathspec, false)) { $pathspec = $pathspec ? r($pathspec) : ''; gb::log('deferred commit -m %s --author %s %s', escapeshellarg($message), escapeshellarg($author), $pathspec); if (!$pathspec) { gb::log(LOG_WARNING, 'deferred commits without pathspec might cause unexpected changesets'); } return true; } if ($pathspec) { $pathspec = ' ' . self::escargs($pathspec); } else { $pathspec = ''; } $author = $author ? '--author=' . escapeshellarg($author) : ''; git::exec('commit -m ' . escapeshellarg($message) . ' --quiet ' . $author . ' -- ' . $pathspec); @chmod(gb::$site_dir . '/.git/COMMIT_EDITMSG', 0664); return true; }
function parseHeaderFields() { gb::event('will-parse-object-meta', $this); # lift lists static $special_lists = array('tag' => 'tags', 'category' => 'categories'); foreach ($special_lists as $singular => $plural) { $s = false; if (isset($this->meta[$plural])) { $s = $this->meta[$plural]; unset($this->meta[$plural]); } elseif (isset($this->meta[$singular])) { $s = $this->meta[$singular]; unset($this->meta[$singular]); } if ($s) { $this->{$plural} = gb_cfilter::apply('parse-tags', $s); } } # lift specials, like title, from meta to this static $special_singles = array('title'); foreach ($special_singles as $singular) { if (isset($this->meta['title'])) { $this->title = $this->meta['title']; unset($this->meta[$singular]); } } # lift content type $charset = 'utf-8'; if (isset($this->meta['content-type'])) { $this->mimeType = $this->meta['content-type']; if (preg_match('/^([^ ;\\s\\t]+)(?:[ \\s\\t]*;[ \\s\\t]*charset=([a-zA-Z0-9_-]+)|).*$/', $this->mimeType, $m)) { if (isset($m[2]) && $m[2]) { $charset = strtolower($m[2]); } $this->mimeType = $m[1]; } unset($this->meta['content-type']); } # lift charset or encoding if (isset($this->meta['charset'])) { $charset = strtolower(trim($this->meta['charset'])); # we do not unset this, because it need to propagate to buildHeaderFields } elseif (isset($this->meta['encoding'])) { $charset = strtolower(trim($this->meta['encoding'])); # we do not unset this, because it need to propagate to buildHeaderFields } # convert body text encoding? if ($charset && $charset !== 'utf-8' && $charset !== 'utf8' && $charset !== 'ascii') { if (function_exists('mb_convert_encoding')) { $this->title = mb_convert_encoding($this->title, 'utf-8', $charset); $this->body = mb_convert_encoding($this->body, 'utf-8', $charset); } elseif (function_exists('iconv')) { $this->title = iconv($charset, 'utf-8', $this->title); $this->body = iconv($charset, 'utf-8', $this->body); } else { gb::log(LOG_ERR, 'failed to convert text encoding of %s -- neither mbstring nor iconv extension is available.', $this->name); } } # transfer author meta tag if (isset($this->meta['author'])) { $this->author = GBAuthor::parse($this->meta['author']); unset($this->meta['author']); } # specific publish (date and) time? $mp = false; if (isset($this->meta['publish'])) { $mp = $this->meta['publish']; unset($this->meta['publish']); } elseif (isset($this->meta['published'])) { $mp = $this->meta['published']; unset($this->meta['published']); } if ($mp) { $mp = strtoupper($mp); if ($mp === 'FALSE' || $mp === 'NO' || $mp === '0') { $this->draft = true; } elseif ($mp && $mp !== false && $mp !== 'TRUE' && $mp !== 'YES' && $mp !== '1') { $this->published = $this->published->mergeString($mp); } } # handle booleans static $bools = array('draft' => 'draft', 'comments' => 'commentsOpen', 'pingback' => 'pingbackOpen'); foreach ($bools as $mk => $ok) { if (isset($this->meta[$mk])) { $s = trim($this->meta[$mk]); unset($this->meta[$mk]); $this->{$ok} = $s === '' || gb_strbool($s); } } gb::event('did-parse-object-meta', $this); }
$referrer = gb::referrer_url(); # comment not found if (!$removed_comment) { if ($referrer) { $referrer['gb-error'] = 'Comment ' . $input['comment'] . ' not found'; header('HTTP/1.1 303 See Other'); header('Location: ' . $referrer); } else { header('HTTP/1.1 404 Not Found'); } exit('no such comment ' . $input['comment']); } gb::log(LOG_NOTICE, 'removed comment %s by %s from post %s', $input['comment'], $removed_comment->name, $post->cachename()); gb::event('did-remove-comment', $removed_comment); # done OK if ($referrer) { $referrer->fragment = 'comments'; header('HTTP/1.1 303 See Other'); header('Location: ' . $referrer); } else { exit2("removed comment: {$removed_comment->id}\n", '200 OK'); } } catch (Exception $e) { gb::log(LOG_ERR, 'failed to remove comment %s from %s', $input['comment'], $post->cachename()); header('HTTP/1.1 500 Internal Server Error'); echo '$input => '; var_export($input); echo "\n"; gb_flush(); throw $e; }
static function filter($text = '') { $text = preg_replace_callback('/<codeblock([^>]*)>(.*)<\\/codeblock>/Usm', array(__CLASS__, '_escapeBlockContentCB'), $text); $tokens = gb_tokenize_html($text); $out = ''; $depth = 0; $block = ''; $tag = ''; foreach ($tokens as $token) { if (substr($token, 0, 10) === '<codeblock') { $depth++; if ($depth === 1) { # code block just started $tag = $token; continue; } } elseif (substr($token, 0, 12) === '</codeblock>') { $depth--; if ($depth < 0) { gb::log(LOG_WARNING, 'stray </codeblock> messing up a code block'); $depth = 0; } if ($depth === 0) { # code block ended if ($block) { $block = base64_decode($block); $lang = ''; # find lang, if any if (preg_match('/[\\s\\t ]+lang=("[^"]*"|\'[^\']*\')[\\s\\t ]*/', $tag, $m, PREG_OFFSET_CAPTURE)) { $lang = trim($m[1][0], '"\''); $end = substr($tag, $m[0][1] + strlen($m[0][0])); $tag = substr($tag, 0, $m[0][1]) . ($end === '>' ? '>' : ' ' . $end); } # add CSS class name $extra_cssclass = ''; if (preg_match('/class="([^"]+)"/', $tag, $m)) { $extra_cssclass = $m[1]; } # remove first and last line break if present if ($block[0] === "\n") { $block = substr($block, 1); } if ($block[strlen($block) - 1] === "\n") { $block = substr($block, 0, -1); } # expand tabs if (self::$conf['tabsize']) { $block = strtr($block, array("\t" => str_repeat(' ', self::$conf['tabsize']))); } # append block to output $out .= self::highlight($block, $lang, $extra_cssclass); # clear block $block = ''; } continue; } } # in codeblock or not? if ($depth) { $block .= $token; } else { $out .= $token; } } return $out; }
static function upgrade($fromVersion) { self::sync_site_state(); # this can potentially take a very long time set_time_limit(120); $stages = gb_upgrade::perform($fromVersion, gb::$version); gb::log('triggering rebuild as an effect of the upgrade to %s', gb::$version); $failures = GBRebuilder::rebuild($stages ? true : false); gb::log('gitblog is now version %s', gb::$version); if ($failures) { gb::log(LOG_WARNING, 'rebuilding failed with %d failures', count($failures)); return false; } return true; }
static function check_comment($comment) { # null? if (!$comment) { return $comment; } # already approved? if ($comment->approved) { gb::log(LOG_INFO, 'skipping check since comment is already approved'); return $comment; } $params = array('blog' => gb::$site_url, 'user_ip' => $comment->ipAddress, 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'referrer' => $_SERVER['HTTP_REFERER'], 'blog_charset' => 'utf-8', 'comment_type' => $comment->type === GBComment::TYPE_COMMENT ? 'comment' : 'pingback', 'comment_author' => $comment->name, 'comment_author_email' => $comment->email, 'comment_content' => $comment->body()); if ($comment->uri) { $params['comment_author_url'] = $comment->uri; } # add HTTP_* server vars (request headers) static $ignore = array('HTTP_COOKIE'); foreach ($_SERVER as $key => $value) { if (strpos($key, 'HTTP_') === 0 && !in_array($key, $ignore) && is_string($value)) { $params[$key] = $value; } } # POST gb::log('checking comment'); $reqbody = http_build_query($params); $response = self::http_post($reqbody, '/1.1/comment-check', self::$key . '.' . self::$host); # parse response if ($response[1] === 'true') { gb::log('comment classed as spam'); self::$conf['spam_count'] = intval(self::$conf['spam_count']) + 1; $comment->spam = true; gb::event('did-spam-comment', $comment); if (self::$conf['delete_spam']) { $comment = null; } } elseif ($response[1] === 'false') { gb::log('comment classed as ham'); $comment->spam = false; gb::event('did-ham-comment', $comment); } else { gb::log(LOG_WARNING, 'unexpected response from /1.1/comment-check: ' . $response[1]); } # forward return $comment; }