* Fallback charset, if none is defined in the language files */ @define('LANG_CHARSET', 'ISO-8859-1'); /* * Create array of permission levels, with descriptions */ $serendipity['permissionLevels'] = array(USERLEVEL_EDITOR => USERLEVEL_EDITOR_DESC, USERLEVEL_CHIEF => USERLEVEL_CHIEF_DESC, USERLEVEL_ADMIN => USERLEVEL_ADMIN_DESC); /* * Check if the installed version is higher than the version of the config */ if (IS_up2date === false && !defined('IN_upgrader')) { if (preg_match(PAT_CSS, $_SERVER['REQUEST_URI'], $matches)) { $css_mode = 'serendipity_admin.css'; return 1; } serendipity_die(sprintf(SERENDIPITY_NEEDS_UPGRADE, $serendipity['versionInstalled'], $serendipity['version'], $serendipity['serendipityHTTPPath'] . 'serendipity_admin.php')); } // We don't care who tells us what to do if (!isset($serendipity['GET']['action'])) { $serendipity['GET']['action'] = isset($serendipity['POST']['action']) ? $serendipity['POST']['action'] : ''; } if (!isset($serendipity['GET']['adminAction'])) { $serendipity['GET']['adminAction'] = isset($serendipity['POST']['adminAction']) ? $serendipity['POST']['adminAction'] : ''; } // Some stuff... if (!isset($_SESSION['serendipityAuthedUser'])) { $_SESSION['serendipityAuthedUser'] = false; } if (isset($_SESSION['serendipityUser'])) { $serendipity['user'] = $_SESSION['serendipityUser']; }
function errorToExceptionHandler($errNo, $errStr, $errFile = '', $errLine = NULL, $errContext = array()) { global $serendipity; // By default, we will continue our process flow, unless: $exit = false; switch ($errNo) { case E_ERROR: case E_USER_ERROR: $type = 'Fatal Error'; $exit = true; break; case E_USER_WARNING: case E_WARNING: $type = 'Warning'; break; case E_USER_NOTICE: case E_NOTICE: case @E_STRICT: case @E_DEPRECATED: case @E_USER_DEPRECATED: $type = 'Notice'; break; case @E_RECOVERABLE_ERROR: $type = 'Catchable'; break; default: $type = 'Unknown Error'; $exit = true; break; } // NOTE: We do NOT use ini_get('error_reporting'), because that would return the global error reporting, // and not the one in our current content. @-silenced errors would otherwise never be caught on. $rep = error_reporting(); // Bypass error processing because it's @-silenced. if ($rep == 0) { return false; } // if not using Serendipity testing and user or ISP has set PHPs display_errors to show no errors at all, respect this: if ($serendipity['production'] === true && ini_get('display_errors') == 0) { return false; } // Several plugins might not adapt to proper style. This should not completely kill our execution. if ($serendipity['production'] !== 'debug' && preg_match('@Declaration.*should be compatible with@i', $args[1])) { #if (!headers_sent()) echo "<strong>Compatibility warning:</strong> Please upgrade file old '{$args[2]}', it contains incompatible signatures.<br/>Details: {$args[1]}<br/>"; return false; } $args = func_get_args(); /* * $serendipity['production'] can be: * * (bool) TRUE: Live-blog, conceal error messages * (bool) FALSE Beta/alpha builds * (string) 'debug' Developer build, specifically enabled. */ $debug_note = '<br />For more details set $serendipity[\'production\'] = \'debug\' in serendipity_config_local.inc.php to receive a stack-trace.'; // Debug environments shall be verbose... if ($serendipity['production'] === 'debug') { echo " == ERROR-REPORT (DEBUGGING ENABLED) == <br />\n"; echo " == (When you copy this debug output to a forum or other places, make sure to remove your username/passwords, as they may be contained within function calls) == \n"; echo '<pre>'; debug_print_backtrace(); // Unlimited output, debugging shall show us everything. echo "</pre>"; $debug_note = ''; } elseif ($serendipity['production'] === false) { echo " == ERROR-REPORT (BETA/ALPHA-BUILDS) == \n"; } if ($serendipity['production'] !== true) { // Display error (production: FALSE and production: 'debug') echo '<p><b>' . $type . ':</b> ' . $errStr . ' in ' . $errFile . ' on line ' . $errLine . '.' . $debug_note . '</p>'; echo '<pre style="white-space: pre-line;">'; throw new \ErrorException($type . ': ' . $errStr, 0, $errNo, $errFile, $errLine); // tracepath = all, if not ini_set('display_errors', 0); if (!$serendipity['dbConn'] || $exit) { exit; // make sure to exit in case of database connection errors or fatal errors. } } else { // Only display error (production blog) if an admin is logged in, else we discard the error. if ($serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN) { $str = " == SERENDIPITY ERROR == "; $str .= '<p><b>' . $type . ':</b> ' . $errStr . ' in ' . $errFile . ' on line ' . $errLine . '.' . $debug_note . '</p>'; if (headers_sent()) { serendipity_die($str); // case HTTP headers: needs to halt with die() here, else it will path through and gets written underneath blog content, or into streamed js files, which hardly isn't seen by many users } else { // see global include of function in plugin_api.inc.php // this also reacts on non eye-displayed errors with following small javascript, // while being in tags like <select> to push on top of page, else return non javascript use $str just there // sadly we can not use HEREDOC notation here, since this does not execute the javascript after finished writing echo "\n" . '<script> if (typeof errorHandlerCreateDOM == "function") { var fragment = window.top.errorHandlerCreateDOM("Error redirect: ' . addslashes($str) . '"); document.body.insertBefore(fragment, document.body.childNodes[0]); }' . "\n</script>\n<noscript>" . $str . "</noscript>\n"; } } } }
function errorToExceptionHandler($errNo, $errStr, $errFile = '', $errLine = NULL, $errContext = array()) { global $serendipity; $rep = ini_get('error_reporting'); // respect user has set php error_reporting to not display any errors at all if (!($rep & $errStr)) { return false; } // user used @ to specify ignoring all errors or $php_errormsg messages returned with error_reporting = 0 if ($rep == 0) { return false; } // if not using Serendipity testing and user or ISP has set PHPs display_errors to show no errors at all, respect if ($serendipity['production'] === true && ini_get('display_errors') == 0) { return false; } // any other errors go here - throw errors as exception if ($serendipity['production'] === 'debug') { echo '<p> == FULL DEBUG ERROR MODE == </p>'; echo '<pre>'; // trying to be as detailled as possible if (function_exists('debug_backtrace')) { print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); // whether or not to populate the "object" index >= PHP 5.3.6 } throw new ErrorException($errStr); // tracepath = all, if not ini_set('display_errors', 0); echo '</pre>'; // if throw new ... endtag is not set, it still looks better and browsers don't care } if ($serendipity['production'] !== true) { $e = new Exception(); echo '<p> == TESTING ERROR MODE == </p>'; echo '<pre>'; throw new ErrorException("Serendipity error: " . $errStr); // tracepath = all; echo '</pre>'; // if throw new ... endtag is not set, it still looks better and browsers don't care } else { // ToDo: enhance for more special serendipity error needs $str = '<p> == SERENDIPITY ERROR == </p>'; $str .= '<p>Please correct:</p>'; $str .= '<p>' . $errStr . ' in ' . $errFile . ' on line ' . $errLine . '</p>'; serendipity_die($str); // needs to halt with die() here, else it will path through and gets written underneath blog content. } }
function errorToExceptionHandler($errNo, $errStr, $errFile = '', $errLine = NULL, $errContext = array()) { global $serendipity; $exit = false; switch ($errNo) { case E_ERROR: case E_USER_ERROR: $type = 'Fatal Error'; $exit = true; break; case E_USER_WARNING: case E_WARNING: $type = 'Warning'; break; case E_USER_NOTICE: case E_NOTICE: case @E_STRICT: case @E_DEPRECATED: case @E_USER_DEPRECATED: $type = 'Notice'; break; case @E_RECOVERABLE_ERROR: $type = 'Catchable'; break; default: $type = 'Unknown Error'; $exit = true; break; } $rep = ini_get('error_reporting'); $args = func_get_args(); // respect user has set php error_reporting to not display any errors at all if (!($rep & $errStr)) { return false; } // user used @ to specify ignoring all errors or $php_errormsg messages returned with error_reporting = 0 if ($rep == 0) { return false; } // if not using Serendipity testing and user or ISP has set PHPs display_errors to show no errors at all, respect if ($serendipity['production'] === true && ini_get('display_errors') == 0) { return false; } // Several plugins might not adapt to proper style. This should not completely kill our execution. if ($serendipity['production'] !== 'debug' && preg_match('@Declaration.*should be compatible with@i', $args[1])) { #if (!headers_sent()) echo "<strong>Compatibility warning:</strong> Please upgrade file old '{$args[2]}', it contains incompatible signatures.<br/>Details: {$args[1]}<br/>"; return false; } // any other errors go here - throw errors as exception if ($serendipity['production'] === 'debug') { // We don't want the notices - but everything else ! echo " == FULL DEBUG ERROR MODE == \n"; echo '<pre>'; // trying to be as detailled as possible - but avoid using args containing sensibel data like passwords if (function_exists('debug_backtrace') && version_compare(PHP_VERSION, '5.3.6') >= 0) { if (version_compare(PHP_VERSION, '5.4') >= 0) { $debugbacktrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 8); } else { $debugbacktrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); } print_r($debugbacktrace); } //print_r($args); // debugging [Use with care! Not to public, since holding password and credentials!!!] // debugbacktrace is nice, but additional it is good to have the verbosity of SPL EXCEPTIONS, except for db connect errors } if ($serendipity['production'] === false) { echo " == TESTING ERROR MODE == \n"; } if ($serendipity['production'] !== true) { if (!$serendipity['dbConn'] || $exit) { echo '<p><b>' . $type . ':</b> ' . $errStr . ' in ' . $errFile . ' on line ' . $errLine . '</p>'; } else { echo '<pre style="white-space: pre-line;">'; throw new \ErrorException($type . ': ' . $errStr, 0, $errNo, $errFile, $errLine); // tracepath = all, if not ini_set('display_errors', 0); echo '</pre>'; // if using throw new ... this ending tag will not be send and displayed, but it still looks better and browsers don't really care } if (!$serendipity['dbConn'] || $exit) { exit; } // make sure to exit in case of database connection errors. } else { if ($serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN) { // ToDo: enhance for more special serendipity error needs $str = " == SERENDIPITY ERROR == "; $str .= '<p>' . $errStr . ' in ' . $errFile . ' on line ' . $errLine . '</p>'; #var_dump(headers_list()); if (headers_sent()) { serendipity_die($str); // case HTTP headers: needs to halt with die() here, else it will path through and gets written underneath blog content, or into streamed js files, which hardly isn't seen by many users } else { // see global include of function in plugin_api.inc.php // this also reacts on non eye-displayed errors with following small javascript, // while being in tags like <select> to push on top of page, else return non javascript use $str just there // sadly we can not use HEREDOC notation here, since this does not execute the javascript after finished writing echo "\n" . '<script> if (typeof errorHandlerCreateDOM == "function") { var fragment = window.top.errorHandlerCreateDOM("Error redirect: ' . addslashes($str) . '"); document.body.insertBefore(fragment, document.body.childNodes[0]); }' . "\n</script>\n<noscript>" . $str . "</noscript>\n"; } } } }
function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; static $cache = null; static $method = null; $hooks =& $bag->get('event_hooks'); if (isset($hooks[$event])) { switch ($event) { case 'css': if (strpos($eventData, '#twitter_update_list')) { // class exists in CSS, so a user has customized it and we don't need default return true; } $this->addToCSS($eventData); return true; break; case 'backend_header': $this->add_backend_header_parts(); return true; case 'backend_publish': // If signaled, we don't want to announce, don't do it! if (isset($serendipity['POST']['properties']['microblogging_dontannounce'])) { return true; } // eventData is the entry here return $this->twitter_published_entry($eventData); break; case 'backend_delete_entry': $this->entry_deleted((int) $eventData); return true; break; case 'external_plugin': $parts = explode('_', $eventData); $command = $parts[0]; if ($command == 'cacheplugintwitter') { $next_check = (int) $this->updateTwitterTimelineCache($parts); $this->show_img(dirname(__FILE__) . '/img/pixel.png', (int) $next_check); return true; } $parts = explode('=', $eventData); $command = $parts[0]; $fparts = explode('&', $parts[1]); if ($command == "tweetback") { if (!$_SESSION['serendipityAuthedUser']) { echo "DON'T HACK!<br>"; return true; } $article_url = preg_replace('@^tweetback=@', '', $eventData); $article_url = $this->urldecode($article_url); if (empty($article_url)) { echo "Dont hack!"; } $shorturls = $this->create_short_urls($article_url); $entries = $entries = $this->search($article_url, null); if (is_array($entries)) { $this->debug_entries($entries, $article_url, $shorturls); } else { echo "<p><b>ERROR</b> while fetching search results for URL {$article_url}<br/>Might be a Twitter Overload.<br/>Try again later</p>"; } return true; } else { if ($command == "gtweetback.png") { $nextcheck = $this->check_tweetbacks_global(); if (empty($nextcheck)) { $nextcheck = time() + 30 * 60; } // Default for hackers $this->show_img(dirname(__FILE__) . '/img/pixel.png', $nextcheck, 'image/png'); return true; } else { if ($command == "twitteroa-del") { $this->twitteroalog($command); // Remove current twitter OAuth key and token to allow to re-connect if (!serendipity_userLoggedIn()) { die("Don't hack!"); } $idx = $fparts[0]; // Remove access tokens $u = $this->get_config('twittername' . $idx); $kd = $this->set_config('twitteroa_key_' . $idx . $u, ''); $td = $this->set_config('twitteroa_token_' . $idx . $u, ''); // Remove old application, so it will change to the s9y app next time: $csecret = $this->set_config('twitteroa_consumer_secret' . $idx, ''); $ckey = $this->set_config('twitteroa_consumer_key' . $idx, ''); serendipity_die('<div align="center"> <h1>' . PLUGIN_EVENT_TWITTER_VERBINDUNG_DEL_OK . '</h1> <a href="javascript:window.close()">' . PLUGIN_EVENT_TWITTER_CLOSEWINDOW . '</a> </div>'); return true; } else { if ($command == "twitteroa-redirect") { $this->twitteroalog($command); if (!serendipity_userLoggedIn()) { die("Don't hack!"); } $idx = $fparts[0]; $u = $this->get_config('twittername' . $idx); $kd = $this->get_config('twitteroa_key_' . $idx . $u); $td = $this->get_config('twitteroa_token_' . $idx . $u); $ckey = $this->get_config('twitteroa_consumer_key' . $idx); $csecret = $this->get_config('twitteroa_consumer_secret' . $idx); require_once dirname(__FILE__) . '/twitteroauth/twitteroauth.php'; $twittername = $u; $callbackurl = $serendipity['baseURL'] . $serendipity['indexFile'] . '?/' . TwitterPluginFileAccess::get_permaplugin_path() . '/twitteroa-callback=' . $idx . "&twittername=" . $twittername; define('CONSUMER_KEY', $ckey); define('CONSUMER_SECRET', $csecret); define('OAUTH_CALLBACK', $callbackurl); /* Build TwitterOAuth object with client credentials. */ $connection = new TwitterOAuth($ckey, $csecret); /* Get temporary credentials. */ $request_token = $connection->getRequestToken(OAUTH_CALLBACK); /* Save temporary credentials to session. */ $_SESSION['oauth_token'] = $token = $request_token['oauth_token']; $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret']; /* If last connection failed don't display authorization link. */ switch ($connection->http_code) { case 200: /* Build authorize URL and redirect user to Twitter. */ $url = $connection->getAuthorizeURL($token); header('Location: ' . $url); exit; break; default: serendipity_die('<div align="center"> <h1>' . PLUGIN_EVENT_TWITTER_VERBINDUNG_ERROR . '</h1> <div align="left"><pre>' . print_r($connection, true) . '</pre> <pre>' . print_r($request_token, true) . '</pre> <pre>' . print_r($_SESSION, true) . '</pre> <pre>' . print_r($_REQUEST, true) . '</pre></div> <a href="javascript:window.close()">' . PLUGIN_EVENT_TWITTER_CLOSEWINDOW . '</a> </div>'); } return true; } else { if ($command == "twitteroa-callback") { $this->twitteroalog($command); if (!serendipity_userLoggedIn()) { die("Don't hack!"); } $idx = $fparts[0]; $u = $this->get_config('twittername' . $idx); $kd = $this->get_config('twitteroa_key_' . $idx . $u); $td = $this->get_config('twitteroa_token_' . $idx . $u); $ckey = $this->get_config('twitteroa_consumer_key' . $idx); $csecret = $this->get_config('twitteroa_consumer_secret' . $idx); require_once dirname(__FILE__) . '/twitteroauth/twitteroauth.php'; define('CONSUMER_KEY', $ckey); define('CONSUMER_SECRET', $csecret); /* If the oauth_token is old redirect to the connect page. */ if (isset($_REQUEST['oauth_token']) && $_SESSION['oauth_token'] !== $_REQUEST['oauth_token']) { $_SESSION['oauth_status'] = 'oldtoken'; $url = $serendipity['baseURL'] . $serendipity['indexFile'] . '?/' . TwitterPluginFileAccess::get_permaplugin_path() . '/twitteroa-redirect=' . $idx; header('Location: ' . $url); exit; } /* Create TwitteroAuth object with app key/secret and token key/secret from default phase */ $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); /* Request access tokens from twitter */ $access_token = $connection->getAccessToken($_REQUEST['oauth_verifier']); $this->set_config('twitteroa_key_' . $idx . $u, $access_token['oauth_token']); $this->set_config('twitteroa_token_' . $idx . $u, $access_token['oauth_token_secret']); /* Remove no longer needed request tokens */ unset($_SESSION['oauth_token']); unset($_SESSION['oauth_token_secret']); /* If HTTP response is 200 continue otherwise send to connect page to retry */ if (200 == $connection->http_code) { serendipity_die('<div align="center"> <h1>' . PLUGIN_EVENT_TWITTER_VERBINDUNG_OK . '</h1> <a href="javascript:window.close()">' . PLUGIN_EVENT_TWITTER_CLOSEWINDOW . '</a> </div>'); } else { serendipity_die('<div align="center"> <h1>' . PLUGIN_EVENT_TWITTER_VERBINDUNG_ERROR . '</h1> <pre>' . print_r($connection, true) . '</pre> <pre>' . print_r($access_token, true) . '</pre> <pre>' . print_r($_SESSION, true) . '</pre> <pre>' . print_r($_REQUEST, true) . '</pre> <a href="javascript:window.close()">' . PLUGIN_EVENT_TWITTER_CLOSEWINDOW . '</a> </div>'); } return true; } } } } } return false; break; case 'entry_display': $this->display_entry($eventData, $addData); return true; case 'backend_frontpage_display': if ($this->get_config('tweeter_show', 'disable') == 'frontpage') { $this->display_twitter_client(false); } return true; case 'backend_sidebar_entries': if ($serendipity['version'][0] == '1') { if ($this->get_config('tweeter_show', 'disable') == 'sidebar') { ?> <li class="serendipitySideBarMenuLink serendipitySideBarMenuEntryLinks"><a href="?serendipity[adminModule]=event_display&serendipity[adminAction]=tweeter"><?php echo PLUGIN_EVENT_TWITTER_TWEETER_SIDEBARTITLE; ?> </a></li> <?php } else { } } return true; case 'backend_sidebar_admin_appearance': if ($serendipity['version'][0] == '1') { } else { if ($this->get_config('tweeter_show', 'disable') == 'sidebar') { ?> <li><a href="?serendipity[adminModule]=event_display&serendipity[adminAction]=tweeter"><?php echo PLUGIN_EVENT_TWITTER_TWEETER_SIDEBARTITLE; ?> </a></li> <?php } } return true; case 'backend_sidebar_entries_event_display_tweeter': echo '<h2>' . PLUGIN_EVENT_TWITTER_TWEETER_SIDEBARTITLE . '</h2>'; $this->display_twitter_client(true); return true; case 'frontend_footer': $this->display_frontend_footer(); return true; case 'frontend_saveComment': $this->hook_saveComment($eventData, $addData); return true; case 'backend_display': if (!serendipity_db_bool($this->get_config('announce_articles'))) { return true; } if (isset($serendipity['POST']['properties']['microblogging_tagList'])) { $tagList = $serendipity['POST']['properties']['microblogging_tagList']; } else { $tagList = ''; } if (isset($serendipity['POST']['properties']['microblogging_dontannounce'])) { $checked_dontannounce = "checked='checked'"; } else { $checked_dontannounce = ''; } if (serendipity_db_bool($this->get_config('announce_articles_default_no'))) { $checked_dontannounce = "checked='checked'"; } if ($serendipity['version'][0] == '1') { ?> <fieldset style="margin: 5px"> <a name="microbloggingAnchor"></a> <legend><?php echo PLUGIN_EVENT_TWITTER_NAME; ?> </legend> <div class="entryproperties_microblogging_dontannounce"> <input id="properties_microblogging_dontannounce" class="input_checkbox" type="checkbox" name="serendipity[properties][microblogging_dontannounce]" <?php echo $checked_dontannounce; ?> /> <label for="properties_microblogging_dontannounce" title="<?php echo PLUGIN_EVENT_TWITTER_BACKEND_DONTANNOUNCE; ?> "> <?php echo PLUGIN_EVENT_TWITTER_BACKEND_DONTANNOUNCE; ?> </label> </div> <label for="serendipity[properties][microblogging_tagList]" title="<?php echo PLUGIN_EVENT_TWITTER_NAME; ?> "> <?php echo PLUGIN_EVENT_TWITTER_BACKEND_ENTERDESC; ?> </label><br/> <input type="text" name="serendipity[properties][microblogging_tagList]" id="properties_microblogging_tagList" class="wickEnabled input_textbox" value="<?php echo function_exists('serendipity_specialchars') ? serendipity_specialchars($tagList) : htmlspecialchars($tagList, ENT_COMPAT, LANG_CHARSET); ?> " style="width: 100%" /> </fieldset> <?php } else { ?> <fieldset class="entryproperties"> <a name="microbloggingAnchor"></a> <span class="wrap_legend"><legend><?php echo PLUGIN_EVENT_TWITTER_NAME; ?> </legend></span> <div class="entryproperties_microblogging_dontannounce form_check"> <input id="properties_microblogging_dontannounce" name="serendipity[properties][microblogging_dontannounce]" type="checkbox" <?php echo $checked_dontannounce; ?> > <label for="properties_microblogging_dontannounce"><?php echo PLUGIN_EVENT_TWITTER_BACKEND_DONTANNOUNCE; ?> </label> </div> <div class="form_field"> <label for="serendipity[properties][microblogging_tagList]" class="block_level"><?php echo PLUGIN_EVENT_TWITTER_BACKEND_ENTERDESC; ?> </label> <input id="properties_microblogging_tagList" class="wickEnabled" name="serendipity[properties][microblogging_tagList]" type="text" value="<?php echo function_exists('serendipity_specialchars') ? serendipity_specialchars($tagList) : htmlspecialchars($tagList, ENT_COMPAT, LANG_CHARSET); ?> "> </div> </fieldset> <?php } return true; } } }