2. Make mysqli be the selected default when installing (PHP at some point will deprected mysql, so better start now to advertise mysqli) 3. Prepare SQLite3 DB Layer
1256 lines
44 KiB
PHP
1256 lines
44 KiB
PHP
<?php # $Id$
|
|
# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
|
|
# All rights reserved. See LICENSE file for licensing details
|
|
|
|
if (IN_serendipity !== true) {
|
|
die ("Don't hack!");
|
|
}
|
|
|
|
/**
|
|
* Convert a PHP Ini setting to a boolean flag
|
|
*
|
|
* @access public
|
|
* @param mixed input variable
|
|
* @return boolean output variable
|
|
*/
|
|
function serendipity_ini_bool($var) {
|
|
return ($var === 'on' || $var == '1');
|
|
}
|
|
|
|
/**
|
|
* convert a size value from a PHP.ini to a bytesize
|
|
*
|
|
* @access public
|
|
* @param string size value from PHP.ini
|
|
* @return string bytesize
|
|
*/
|
|
function serendipity_ini_bytesize($val) {
|
|
if ( $val == '' )
|
|
return 0;
|
|
|
|
switch(substr($val, -1)) {
|
|
case 'k':
|
|
case 'K':
|
|
return (int) $val * 1024;
|
|
break;
|
|
case 'm':
|
|
case 'M':
|
|
return (int) $val * 1048576;
|
|
break;
|
|
default:
|
|
return $val;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the serendipity_config_local.inc.php file with core information
|
|
*
|
|
* @access public
|
|
* @param string Database name
|
|
* @param string Database prefix
|
|
* @param string Database host
|
|
* @param string Database user
|
|
* @param string Datapase Passwort
|
|
* @param string Database type
|
|
* @param string Use persistent connections?
|
|
* @param array An array of additional variables to be put into the config file
|
|
* @return true
|
|
*/
|
|
function serendipity_updateLocalConfig($dbName, $dbPrefix, $dbHost, $dbUser, $dbPass, $dbType, $dbPersistent, $privateVariables = null) {
|
|
global $serendipity;
|
|
umask(0000);
|
|
|
|
$file = 'serendipity_config_local.inc.php';
|
|
$path = $serendipity['serendipityPath'];
|
|
|
|
$oldconfig = @file_get_contents($path . $file);
|
|
$configfp = fopen($path . $file, 'w');
|
|
|
|
if (!is_resource($configfp)) {
|
|
$errs[] = sprintf(FILE_WRITE_ERROR, $file);
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD, 'chown -R www:www', $path) . ' (' . WWW_USER . ')';
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD, 'chmod 770' , $path);
|
|
$errs[] = BROWSER_RELOAD;
|
|
|
|
return $errs;
|
|
}
|
|
|
|
if (isset($_POST['sqlitedbName']) && !empty($_POST['sqlitedbName'])) {
|
|
$dbName = $_POST['sqlitedbName'];
|
|
}
|
|
|
|
$file_start = "<?php\n"
|
|
. "\t/*\n"
|
|
. "\t Serendipity configuration file\n";
|
|
$file_mark = "\n\t// End of Serendipity configuration file"
|
|
. "\n\t// You can place your own special variables after here:\n";
|
|
$file_end = "\n?>\n";
|
|
$file_personal = '';
|
|
|
|
preg_match('@' . preg_quote($file_start) . '.*' . preg_quote($file_mark) . '(.+)' . preg_quote($file_end) . '@imsU', $oldconfig, $match);
|
|
if (!empty($match[1])) {
|
|
$file_personal = $match[1];
|
|
}
|
|
|
|
fwrite($configfp, $file_start);
|
|
|
|
fwrite($configfp, "\t Written on ". date('r') ."\n");
|
|
fwrite($configfp, "\t*/\n\n");
|
|
|
|
fwrite($configfp, "\t\$serendipity['versionInstalled'] = '{$serendipity['version']}';\n");
|
|
fwrite($configfp, "\t\$serendipity['dbName'] = '" . addslashes($dbName) . "';\n");
|
|
fwrite($configfp, "\t\$serendipity['dbPrefix'] = '" . addslashes($dbPrefix) . "';\n");
|
|
fwrite($configfp, "\t\$serendipity['dbHost'] = '" . addslashes($dbHost) . "';\n");
|
|
fwrite($configfp, "\t\$serendipity['dbUser'] = '" . addslashes($dbUser) . "';\n");
|
|
fwrite($configfp, "\t\$serendipity['dbPass'] = '" . addslashes($dbPass) . "';\n");
|
|
fwrite($configfp, "\t\$serendipity['dbType'] = '" . addslashes($dbType) . "';\n");
|
|
fwrite($configfp, "\t\$serendipity['dbPersistent'] = ". (serendipity_db_bool($dbPersistent) ? 'true' : 'false') .";\n");
|
|
if ($serendipity['dbNames']) {
|
|
fwrite($configfp, "\t\$serendipity['dbCharset'] = '" . addslashes(SQL_CHARSET) . "';\n");
|
|
}
|
|
|
|
if (is_array($privateVariables) && count($privateVariables) > 0) {
|
|
foreach($privateVariables AS $p_idx => $p_val) {
|
|
fwrite($configfp, "\t\$serendipity['{$p_idx}'] = '" . addslashes($p_val) . "';\n");
|
|
}
|
|
}
|
|
|
|
fwrite($configfp, $file_mark . $file_personal . $file_end);
|
|
|
|
fclose($configfp);
|
|
|
|
@chmod($path . $file, 0700);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Setup the core database tables
|
|
*
|
|
* Creates the needed tables - beware, they will be empty and need to be stuffed with
|
|
* default templates and such...
|
|
*
|
|
* @access public
|
|
* @return null
|
|
*/
|
|
function serendipity_installDatabase() {
|
|
global $serendipity;
|
|
|
|
$queries = serendipity_parse_sql_tables(S9Y_INCLUDE_PATH . 'sql/db.sql');
|
|
$queries = str_replace('{PREFIX}', $serendipity['dbPrefix'], $queries);
|
|
|
|
foreach ($queries as $query) {
|
|
serendipity_db_schema_import($query);
|
|
}
|
|
|
|
if (file_exists(S9Y_INCLUDE_PATH . 'sql/preload.sql')) {
|
|
$queries = serendipity_parse_sql_inserts(S9Y_INCLUDE_PATH . 'sql/preload.sql');
|
|
$queries = str_replace('{PREFIX}', $serendipity['dbPrefix'], $queries);
|
|
foreach ($queries as $query) {
|
|
serendipity_db_schema_import($query);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check a default value of a config item from the configuration template files
|
|
*
|
|
* @access public
|
|
* @param string Name of the config item to check
|
|
* @param string The default value, if none is found
|
|
* @param boolean If true, it's the personal config template, if false its the global config template
|
|
* @param string Protected fields will not be echo'd in the HTML form
|
|
* @return string The default value
|
|
*/
|
|
function serendipity_query_default($optname, $default, $usertemplate = false, $type = 'string') {
|
|
global $serendipity;
|
|
|
|
/* I won't tell you the password, it's MD5 anyway, you can't do anything with it */
|
|
if ($type == 'protected' && IS_installed === true) {
|
|
return '';
|
|
}
|
|
|
|
switch ($optname) {
|
|
case 'permalinkStructure':
|
|
return $default;
|
|
|
|
case 'dbType' :
|
|
if (extension_loaded('PDO') &&
|
|
in_array('pgsql', PDO::getAvailableDrivers())) {
|
|
$type = 'pdo-postgres';
|
|
}
|
|
if (extension_loaded('pgsql')) {
|
|
$type = 'postgres';
|
|
}
|
|
if (extension_loaded('mysql')) {
|
|
$type = 'mysql';
|
|
}
|
|
if (extension_loaded('mysqli')) {
|
|
$type = 'mysqli';
|
|
}
|
|
return $type;
|
|
|
|
case 'serendipityPath':
|
|
if (empty($_SERVER['PHP_SELF'])) {
|
|
$test_path1 = $_SERVER['DOCUMENT_ROOT'] . rtrim(dirname($_SERVER['SCRIPT_FILENAME']), '/') . '/';
|
|
} else {
|
|
$test_path1 = $_SERVER['DOCUMENT_ROOT'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/';
|
|
}
|
|
$test_path2 = serendipity_getRealDir(__FILE__);
|
|
|
|
if (!empty($_SERVER['ORIG_PATH_TRANSLATED']) && file_exists(dirname($_SERVER['ORIG_PATH_TRANSLATED']) . '/serendipity_admin.php')) {
|
|
return realpath(rtrim(dirname($_SERVER['ORIG_PATH_TRANSLATED']), '/')) . '/';
|
|
}
|
|
|
|
if (file_exists($test_path1 . 'serendipity_admin.php')) {
|
|
return $test_path1;
|
|
} elseif (defined('S9Y_DATA_PATH')) {
|
|
// Shared installation!
|
|
return S9Y_DATA_PATH;
|
|
} else {
|
|
return $test_path2;
|
|
}
|
|
|
|
case 'serendipityHTTPPath':
|
|
return rtrim(dirname($_SERVER['PHP_SELF']), '/') .'/';
|
|
|
|
case 'defaultBaseURL':
|
|
case 'baseURL':
|
|
$ssl = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
|
|
$port = $_SERVER['SERVER_PORT'];
|
|
|
|
return sprintf('http%s://%s%s%s',
|
|
|
|
$ssl ? 's' : '',
|
|
preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']),
|
|
(($ssl && $port != 443) || (!$ssl && $port != 80)) ? (':' . $port) : '',
|
|
rtrim(dirname($_SERVER['PHP_SELF']), '/') .'/'
|
|
);
|
|
|
|
case 'convert':
|
|
$path = array();
|
|
|
|
$path[] = ini_get('safe_mode_exec_dir');
|
|
|
|
if (isset($_SERVER['PATH'])) {
|
|
$path = array_merge($path, explode(PATH_SEPARATOR, $_SERVER['PATH']));
|
|
}
|
|
|
|
/* add some other possible locations to the path while we are at it,
|
|
* as these are not always included in the apache path */
|
|
$path[] = '/usr/X11R6/bin';
|
|
$path[] = '/usr/bin';
|
|
$path[] = '/usr/local/bin';
|
|
|
|
foreach ($path as $dir) {
|
|
if (!empty($dir) && (function_exists('is_executable') && @is_readable($dir) && @is_executable($dir . '/convert')) || @is_file($dir . '/convert')) {
|
|
return $dir . '/convert';
|
|
}
|
|
|
|
if (!empty($dir) && (function_exists('is_executable') && @is_readable($dir . '/convert') && @is_executable($dir . '/convert.exe')) || @is_file($dir . '/convert.exe')) {
|
|
if (!preg_match('@(/|\\\|^)system32(/|\\\|$)@imsu', $dir)) {
|
|
return $dir . '/convert.exe';
|
|
}
|
|
}
|
|
}
|
|
return $default;
|
|
|
|
case 'rewrite':
|
|
return serendipity_check_rewrite($default);
|
|
|
|
default:
|
|
if ($usertemplate) {
|
|
return serendipity_get_user_var($optname, $serendipity['authorid'], $default);
|
|
}
|
|
|
|
return $default;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse a configuration template file
|
|
*
|
|
* @access public
|
|
* @param string Path to the s9y configuration template file
|
|
* @param array An array of config areas/sections that shall be returned from the template
|
|
* @param array Restrict the return of template variables to items containing a specific flag
|
|
* @return array An array with configuration items, keys and values
|
|
*/
|
|
function serendipity_parseTemplate($filename, $areas = null, $onlyFlags=null) {
|
|
global $serendipity;
|
|
|
|
$userlevel = $serendipity['serendipityUserlevel'];
|
|
|
|
if ( !IS_installed ) {
|
|
$userlevel = USERLEVEL_ADMIN;
|
|
}
|
|
|
|
$config = @include($filename);
|
|
if (! is_array($config)) {
|
|
printf(INCLUDE_ERROR,$filename);
|
|
}
|
|
|
|
foreach ( $config as $n => $category ) {
|
|
/* If $areas is an array, we filter out those categories, not within the array */
|
|
if ( is_array($areas) && !in_array($n, $areas) ) {
|
|
unset($config[$n]);
|
|
continue;
|
|
}
|
|
|
|
foreach ( $category['items'] as $i => $item ) {
|
|
$items = &$config[$n]['items'][$i];
|
|
|
|
if (!isset($items['userlevel']) || !is_numeric($items['userlevel'])) {
|
|
$items['userlevel'] = USERLEVEL_ADMIN;
|
|
}
|
|
|
|
if (!isset($items['permission']) && $userlevel < $items['userlevel']) {
|
|
unset($config[$n]['items'][$i]);
|
|
continue;
|
|
} elseif (!is_array($items['permission']) && !serendipity_checkPermission($items['permission'])) {
|
|
unset($config[$n]['items'][$i]);
|
|
continue;
|
|
} elseif (is_array($items['permission'])) {
|
|
$one_found = false;
|
|
$all_found = true;
|
|
foreach($items['permission'] AS $check_permission) {
|
|
if (serendipity_checkPermission($check_permission)) {
|
|
$one_found = true;
|
|
} else {
|
|
$all_found = false;
|
|
}
|
|
}
|
|
|
|
if (!isset($items['perm_mode'])) {
|
|
$items['perm_mode'] = 'or';
|
|
}
|
|
|
|
if ($items['perm_mode'] == 'or' && !$one_found) {
|
|
unset($config[$n]['items'][$i]);
|
|
continue;
|
|
} elseif ($items['perm_mode'] == 'and' && !$one_found && !$all_found) {
|
|
unset($config[$n]['items'][$i]);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!isset($items['flags']) || !is_array($items['flags'])) {
|
|
$items['flags'] = array();
|
|
}
|
|
|
|
if ( is_array($onlyFlags) ) {
|
|
foreach ( $onlyFlags as $onlyFlag ) {
|
|
if ( !in_array($onlyFlag, $items['flags']) ) {
|
|
unset($config[$n]['items'][$i]);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sizeof($config[$n]['items']) < 1) {
|
|
unset($config[$n]);
|
|
}
|
|
}
|
|
|
|
return $config;
|
|
}
|
|
|
|
/**
|
|
* Replace some variables within config item values with the right values
|
|
*
|
|
* @access public
|
|
* @param string Input string
|
|
* @return string Output string
|
|
*/
|
|
function serendipity_replaceEmbeddedConfigVars ($s) {
|
|
return str_replace(
|
|
array(
|
|
'%clock%'
|
|
),
|
|
|
|
array(
|
|
date('H:i')
|
|
),
|
|
|
|
$s);
|
|
}
|
|
|
|
/**
|
|
* Preprocess the configuration value and put it into a HTML output field (radio, password, text, select, ...)
|
|
*
|
|
* @access public
|
|
* @param string The type of the configuration item
|
|
* @param string The name of the configuration item
|
|
* @param string The current value of the configuration item
|
|
* @param string The default value of the configuration item
|
|
* @return null
|
|
*/
|
|
|
|
function serendipity_guessInput($type, $name, $value='', $default='') {
|
|
$data = array();
|
|
$curOptions = array();
|
|
|
|
switch ($type) {
|
|
case 'bool':
|
|
$value = serendipity_get_bool($value);
|
|
if ($value === null) {
|
|
$value = $default;
|
|
}
|
|
break;
|
|
|
|
case 'multilist':
|
|
$default = (array)$default;
|
|
$value = (array)$value;
|
|
foreach ($default as $k => $v) {
|
|
$selected = false;
|
|
foreach($value AS $vk => $vv) {
|
|
if ($vv['confkey'] == $v['confkey']) {
|
|
$selected = true;
|
|
}
|
|
}
|
|
$curOptions[$name][$k]['selected'] = $selected;
|
|
}
|
|
break;
|
|
|
|
case 'list':
|
|
$cval = (string)$value;
|
|
$default = (array)$default;
|
|
foreach ($default as $k => $v) {
|
|
$selected = ((string)$k == (string)$value);
|
|
if (empty($cval) && ((string)$k === 'false' || (string)$k === null)) {
|
|
$selected = true;
|
|
}
|
|
$curOptions[$name][$k]['selected'] = $selected;
|
|
}
|
|
break;
|
|
}
|
|
|
|
$data['type'] = $type;
|
|
$data['name'] = $name;
|
|
$data['value'] = $value;
|
|
$data['default'] = $default;
|
|
$data['selected'] = $curOptions;
|
|
|
|
return serendipity_smarty_show('admin/guess_input.tpl', $data);
|
|
}
|
|
|
|
/**
|
|
* Parses the configuration array and displays the configuration screen
|
|
*
|
|
* @access public
|
|
* @param array Configuration superarray
|
|
* @param array The previous values submitted by the user
|
|
* @param boolean If true, no HTML FORM container will be emitted
|
|
* @param boolean If true, the configuration sections will all be folded
|
|
* @param boolean If true, the user can turn config sections on and off
|
|
* @param boolean If true, the user can NOT display possibly dangerous options
|
|
* @return null
|
|
*/
|
|
function serendipity_printConfigTemplate($config, $from = false, $noForm = false, $folded = true, $allowToggle = true, $showDangerous = false) {
|
|
global $serendipity;
|
|
$data = array();
|
|
$data['noForm'] = $noForm;
|
|
$data['formToken'] = serendipity_setFormToken();
|
|
|
|
$data['allowToggle'] = $allowToggle;
|
|
|
|
foreach ($config as &$category) {
|
|
foreach ($category['items'] as &$item) {
|
|
|
|
$value = $from[$item['var']];
|
|
|
|
/* Calculate value if we are not installed, how clever :) */
|
|
if ($from == false) {
|
|
$value = serendipity_query_default($item['var'], $item['default']);
|
|
}
|
|
|
|
/* Check for installOnly flag */
|
|
if (in_array('installOnly', $item['flags']) && IS_installed === true) {
|
|
continue;
|
|
}
|
|
|
|
if (in_array('hideValue', $item['flags'])) {
|
|
$value = '';
|
|
}
|
|
|
|
if (!$showDangerous && $item['view'] == 'dangerous') {
|
|
continue;
|
|
}
|
|
|
|
if (in_array('config', $item['flags']) && isset($from['authorid'])) {
|
|
$value = serendipity_get_user_config_var($item['var'], $from['authorid'], $item['default']);
|
|
}
|
|
|
|
if (in_array('parseDescription', $item['flags'])) {
|
|
$item['description'] = serendipity_replaceEmbeddedConfigVars($item['description']);
|
|
}
|
|
|
|
if (in_array('probeDefault', $item['flags'])) {
|
|
$item['default'] = serendipity_probeInstallation($item['var']);
|
|
}
|
|
|
|
if (in_array('ifEmpty', $item['flags']) && empty($value)) {
|
|
$value = serendipity_query_default($item['var'], $item['default']);
|
|
}
|
|
$item['guessedInput'] = serendipity_guessInput($item['type'], $item['var'], $value, $item['default']);
|
|
}
|
|
}
|
|
$data['config'] = $config;
|
|
return serendipity_smarty_show('admin/config_template.tpl', $data);
|
|
}
|
|
|
|
/**
|
|
* Parse .sql files for use within Serendipity, query by query,
|
|
* accepting only CREATE commands.
|
|
*
|
|
* @access public
|
|
* @param string The filename of the SQL file
|
|
* @return array An array of queries to execute
|
|
*/
|
|
function serendipity_parse_sql_tables($filename) {
|
|
$in_table = 0;
|
|
$queries = array();
|
|
|
|
$fp = fopen($filename, 'r', 1);
|
|
if ($fp) {
|
|
while (!@feof($fp)) {
|
|
$line = trim(fgets($fp, 4096));
|
|
if ($in_table) {
|
|
$def .= $line;
|
|
if (preg_match('/^\)\s*(type\=\S+|\{UTF_8\})?\s*\;$/i', $line)) {
|
|
$in_table = 0;
|
|
array_push($queries, $def);
|
|
}
|
|
} else {
|
|
if (preg_match('#^create table \{PREFIX\}\S+\s*\(#i', $line)) {
|
|
$in_table = 1;
|
|
$def = $line;
|
|
}
|
|
|
|
if (preg_match('#^create\s*(\{fulltext\}|unique|\{fulltext_mysql\})?\s*index#i', $line)) {
|
|
array_push($queries, $line);
|
|
}
|
|
}
|
|
}
|
|
fclose($fp);
|
|
}
|
|
|
|
return $queries;
|
|
}
|
|
|
|
/**
|
|
* Parse .sql files for use within Serendipity, query by query,
|
|
* accepting only INSERT commands.
|
|
*
|
|
* @access public
|
|
* @param string The filename of the SQL file
|
|
* @return array An array of queries to execute
|
|
*/
|
|
function serendipity_parse_sql_inserts($filename) {
|
|
$queries = array();
|
|
|
|
$fp = fopen($filename, 'r', 1);
|
|
if ($fp) {
|
|
while (!@feof($fp)) {
|
|
$line = trim(fgets($fp, 65536));
|
|
if (preg_match('#^insert\s*into.*;$#i', $line)) {
|
|
array_push($queries, $line);
|
|
}
|
|
}
|
|
}
|
|
fclose($fp);
|
|
|
|
return $queries;
|
|
}
|
|
|
|
/**
|
|
* Check the serendipity Installation for problems, during installation
|
|
*
|
|
* @access public
|
|
* @return boolean Errors encountered?
|
|
*/
|
|
function serendipity_checkInstallation() {
|
|
global $serendipity, $umask;
|
|
|
|
$errs = array();
|
|
|
|
serendipity_initPermalinks();
|
|
|
|
// Check dirs
|
|
if (!is_dir($_POST['serendipityPath'])) {
|
|
$errs[] = sprintf(DIRECTORY_NON_EXISTANT, serendipity_specialchars($_POST['serendipityPath']));
|
|
}
|
|
elseif (!is_writable($_POST['serendipityPath']) ) {
|
|
$errs[] = sprintf(DIRECTORY_WRITE_ERROR, serendipity_specialchars($_POST['serendipityPath']));
|
|
}
|
|
elseif (!is_dir($_POST['serendipityPath'] . $_POST['uploadPath'] ) && @mkdir($_POST['serendipityPath'] . $_POST['uploadPath'], $umask) !== true) {
|
|
$errs[] = sprintf(DIRECTORY_CREATE_ERROR, serendipity_specialchars($_POST['serendipityPath']) . serendipity_specialchars($_POST['uploadPath']));
|
|
}
|
|
elseif (!is_writable($_POST['serendipityPath'] . $_POST['uploadPath'])) {
|
|
$errs[] = sprintf(DIRECTORY_WRITE_ERROR, serendipity_specialchars($_POST['serendipityPath']) . serendipity_specialchars($_POST['uploadPath']));
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD , 'chmod go+rws', serendipity_specialchars($_POST['serendipityPath']) . serendipity_specialchars($_POST['uploadPath']));
|
|
}
|
|
|
|
// Attempt to create the template compile directory, it might already be there, but we just want to be sure
|
|
if (!is_dir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && @mkdir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE, $umask) !== true) {
|
|
$errs[] = sprintf(DIRECTORY_CREATE_ERROR, serendipity_specialchars($_POST['serendipityPath']) . PATH_SMARTY_COMPILE);
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD , 'mkdir' , serendipity_specialchars($_POST['serendipityPath']) . PATH_SMARTY_COMPILE);
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD , 'chmod go+rwx', serendipity_specialchars($_POST['serendipityPath']) . PATH_SMARTY_COMPILE);
|
|
} elseif (is_dir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && !is_writeable($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && @chmod($_POST['serendipityPath'] . PATH_SMARTY_COMPILE, $umask) !== true) {
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD , 'chmod go+rwx', serendipity_specialchars($_POST['serendipityPath']) . PATH_SMARTY_COMPILE);
|
|
}
|
|
|
|
// Attempt to create the archives directory
|
|
if (!is_dir($_POST['serendipityPath'] . PATH_ARCHIVES) && @mkdir($_POST['serendipityPath'] . PATH_ARCHIVES, $umask) !== true) {
|
|
$errs[] = sprintf(DIRECTORY_CREATE_ERROR, serendipity_specialchars($_POST['serendipityPath']) . PATH_ARCHIVES);
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD , 'mkdir' , serendipity_specialchars($_POST['serendipityPath']) . PATH_ARCHIVES);
|
|
$errs[] = sprintf(DIRECTORY_RUN_CMD , 'chmod go+rwx', serendipity_specialchars($_POST['serendipityPath']) . PATH_ARCHIVES);
|
|
}
|
|
|
|
// Check imagick
|
|
if ($_POST['magick'] == 'true' && function_exists('is_executable') && !@is_executable($_POST['convert'])) {
|
|
$errs[] = sprintf(CANT_EXECUTE_BINARY, 'convert imagemagick');
|
|
}
|
|
|
|
if ($_POST['dbType'] == 'sqlite' || $_POST['dbType'] == 'sqlite3' || $_POST['dbType'] == 'pdo-sqlite' || $_POST['dbType'] == 'sqlite3oo') {
|
|
// We don't want that our SQLite db file can be guessed from other applications on a server
|
|
// and have access to our's. So we randomize the SQLite dbname.
|
|
$_POST['sqlitedbName'] = $_POST['dbName'] . '_' . md5(time());
|
|
}
|
|
|
|
if (empty($_POST['dbPrefix']) && empty($serendipity['dbPrefix'])) {
|
|
$errs[] = sprintf(EMPTY_SETTING, INSTALL_DBPREFIX);
|
|
} elseif (!preg_match('@^[a-z0-9_]+$@i', $_POST['dbPrefix'])) {
|
|
$errs[] = INSTALL_DBPREFIX_INVALID;
|
|
}
|
|
|
|
$serendipity['dbType'] = $_POST['dbType'];
|
|
// Probe database
|
|
// (do it after the dir stuff, as we need to be able to create the sqlite database)
|
|
include_once(S9Y_INCLUDE_PATH . "include/db/{$serendipity['dbType']}.inc.php");
|
|
// For shared installations, probe the file on include path
|
|
//include_once(S9Y_INCLUDE_PATH . 'include/db/db.inc.php');
|
|
|
|
if (S9Y_DB_INCLUDED) {
|
|
serendipity_db_probe($_POST, $errs);
|
|
}
|
|
|
|
return (count($errs) > 0 ? $errs : '');
|
|
}
|
|
|
|
/**
|
|
* Create the files needed by Serendipity [htaccess/serendipity_config_local.inc.php]
|
|
*
|
|
* @access public
|
|
* @param string Path to the serendipity directory
|
|
* @return true
|
|
*/
|
|
function serendipity_installFiles($serendipity_core = '') {
|
|
global $serendipity;
|
|
|
|
// This variable is transmitted from serendipity_admin_installer. If an empty variable is used,
|
|
// this means that serendipity_installFiles() was called from the auto-updater facility.
|
|
if (empty($serendipity_core)) {
|
|
$serendipity_core = $serendipity['serendipityPath'];
|
|
}
|
|
|
|
$htaccess = @file_get_contents($serendipity_core . '.htaccess');
|
|
|
|
// Let this function be callable outside installation and let it use existing settings.
|
|
$import = array('rewrite', 'serendipityHTTPPath', 'indexFile');
|
|
foreach($import AS $key) {
|
|
if (empty($_POST[$key]) && isset($serendipity[$key])) {
|
|
$$key = $serendipity[$key];
|
|
} else {
|
|
$$key = $_POST[$key];
|
|
}
|
|
}
|
|
|
|
if (php_sapi_name() == 'cgi' || php_sapi_name() == 'cgi-fcgi') {
|
|
$htaccess_cgi = '_cgi';
|
|
} else {
|
|
$htaccess_cgi = '';
|
|
}
|
|
|
|
/* If this file exists, a previous install failed painfully. We must consider the safer alternative now */
|
|
if (file_exists($serendipity_core . '.installer_detection_failsafe')) {
|
|
$htaccess_cgi = '_cgi';
|
|
@unlink($serendipity_core . '.htaccess');
|
|
}
|
|
|
|
/* Detect comptability with php_value directives */
|
|
if ($htaccess_cgi == '') {
|
|
$response = '';
|
|
$serendipity_root = dirname($_SERVER['PHP_SELF']) . '/';
|
|
$serendipity_host = preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']);
|
|
|
|
$old_htaccess = @file_get_contents($serendipity_core . '.htaccess');
|
|
$fp = @fopen($serendipity_core . '.htaccess', 'w');
|
|
if ($fp) {
|
|
fwrite($fp, 'php_value register_globals off'. "\n" .'php_value session.use_trans_sid 0');
|
|
fclose($fp);
|
|
|
|
$safeFP = @fopen($serendipity_core . '.installer_detection_failsafe', 'w');
|
|
fclose($safeFP);
|
|
$sock = fsockopen($serendipity_host, $_SERVER['SERVER_PORT'], $errorno, $errorstring, 10);
|
|
if ($sock) {
|
|
fputs($sock, "GET {$serendipityHTTPPath} HTTP/1.0\r\n");
|
|
fputs($sock, "Host: $serendipity_host\r\n");
|
|
fputs($sock, "User-Agent: Serendipity/{$serendipity['version']}\r\n");
|
|
fputs($sock, "Connection: close\r\n\r\n");
|
|
|
|
while (!feof($sock) && strlen($response) < 4096) {
|
|
$response .= fgets($sock, 400);
|
|
}
|
|
fclose($sock);
|
|
}
|
|
|
|
# If we get HTTP 500 Internal Server Error, we have to use the .cgi template
|
|
if (preg_match('@^HTTP/\d\.\d 500@', $response)) {
|
|
$htaccess_cgi = '_cgi';
|
|
}
|
|
|
|
if (!empty($old_htaccess)) {
|
|
$fp = @fopen($serendipity_core . '.htaccess', 'w');
|
|
fwrite($fp, $old_htaccess);
|
|
fclose($fp);
|
|
} else {
|
|
@unlink($serendipity_core . '.htaccess');
|
|
}
|
|
|
|
@unlink($serendipity_core . '.installer_detection_failsafe');
|
|
}
|
|
}
|
|
|
|
|
|
if ($rewrite == 'rewrite2') {
|
|
$template = 'htaccess' . $htaccess_cgi . '_rewrite2.tpl';
|
|
} elseif ($rewrite == 'rewrite') {
|
|
$template = 'htaccess' . $htaccess_cgi . '_rewrite.tpl';
|
|
} elseif ($rewrite == 'errordocs') {
|
|
$template = 'htaccess' . $htaccess_cgi . '_errordocs.tpl';
|
|
} else {
|
|
$template = 'htaccess' . $htaccess_cgi . '_normal.tpl';
|
|
}
|
|
|
|
if (!($a = file(S9Y_INCLUDE_PATH . 'include/tpl/' . $template, 1))) {
|
|
$errs[] = ERROR_TEMPLATE_FILE;
|
|
}
|
|
|
|
// When we write this file we cannot rely on the constants defined
|
|
// earlier, as they do not yet contain the updated contents from the
|
|
// new config. Thus we re-define those. We do still use constants
|
|
// for backwards/code compatibility.
|
|
|
|
$PAT = serendipity_permalinkPatterns(true);
|
|
|
|
$content = str_replace(
|
|
array(
|
|
'{PREFIX}',
|
|
'{indexFile}',
|
|
'{PAT_UNSUBSCRIBE}', '{PATH_UNSUBSCRIBE}',
|
|
'{PAT_ARCHIVES}', '{PATH_ARCHIVES}',
|
|
'{PAT_FEEDS}', '{PATH_FEEDS}',
|
|
'{PAT_FEED}',
|
|
'{PAT_ADMIN}', '{PATH_ADMIN}',
|
|
'{PAT_ARCHIVE}', '{PATH_ARCHIVE}',
|
|
'{PAT_PLUGIN}', '{PATH_PLUGIN}',
|
|
'{PAT_DELETE}', '{PATH_DELETE}',
|
|
'{PAT_APPROVE}', '{PATH_APPROVE}',
|
|
'{PAT_SEARCH}', '{PATH_SEARCH}',
|
|
'{PAT_COMMENTS}', '{PATH_COMMENTS}',
|
|
'{PAT_CSS}',
|
|
'{PAT_JS}',
|
|
'{PAT_PERMALINK}',
|
|
'{PAT_PERMALINK_AUTHORS}',
|
|
'{PAT_PERMALINK_FEEDCATEGORIES}',
|
|
'{PAT_PERMALINK_CATEGORIES}',
|
|
'{PAT_PERMALINK_FEEDAUTHORS}'
|
|
),
|
|
|
|
array(
|
|
$serendipityHTTPPath,
|
|
$indexFile,
|
|
trim($PAT['UNSUBSCRIBE'], '@/i'), $serendipity['permalinkUnsubscribePath'],
|
|
trim($PAT['ARCHIVES'], '@/i'), $serendipity['permalinkArchivesPath'],
|
|
trim($PAT['FEEDS'], '@/i'), $serendipity['permalinkFeedsPath'],
|
|
trim(PAT_FEED, '@/i'),
|
|
trim($PAT['ADMIN'], '@/i'), $serendipity['permalinkAdminPath'],
|
|
trim($PAT['ARCHIVE'], '@/i'), $serendipity['permalinkArchivePath'],
|
|
trim($PAT['PLUGIN'], '@/i'), $serendipity['permalinkPluginPath'],
|
|
trim($PAT['DELETE'], '@/i'), $serendipity['permalinkDeletePath'],
|
|
trim($PAT['APPROVE'], '@/i'), $serendipity['permalinkApprovePath'],
|
|
trim($PAT['SEARCH'], '@/i'), $serendipity['permalinkSearchPath'],
|
|
trim($PAT['COMMENTS'], '@/i'), $serendipity['permalinkCommentsPath'],
|
|
trim(PAT_CSS, '@/i'),
|
|
trim(PAT_JS, '@/i'),
|
|
trim($PAT['PERMALINK'], '@/i'),
|
|
trim($PAT['PERMALINK_AUTHORS'], '@/i'),
|
|
trim($PAT['PERMALINK_FEEDCATEGORIES'], '@/i'),
|
|
trim($PAT['PERMALINK_CATEGORIES'], '@/i'),
|
|
trim($PAT['PERMALINK_FEEDAUTHORS'], '@/i')
|
|
),
|
|
|
|
implode('', $a)
|
|
);
|
|
|
|
$fp = @fopen($serendipity_core . '.htaccess', 'w');
|
|
if (!$fp) {
|
|
$errs[] = sprintf(FILE_WRITE_ERROR, $serendipity_core . '.htaccess') . ' ' . FILE_CREATE_YOURSELF;
|
|
$errs[] = sprintf(COPY_CODE_BELOW , $serendipity_core . '.htaccess', 'serendipity', serendipity_specialchars($content));
|
|
return $errs;
|
|
} else {
|
|
// Check if an old htaccess file existed and try to preserve its contents. Otherwise completely wipe the file.
|
|
if ($htaccess != '' && preg_match('@^(.*)#\s+BEGIN\s+s9y.*#\s+END\s+s9y(.*)$@isU', $htaccess, $match)) {
|
|
// Code outside from s9y-code was found.
|
|
fwrite($fp, $match[1] . $content . $match[2]);
|
|
} else {
|
|
fwrite($fp, $content);
|
|
}
|
|
fclose($fp);
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Check the flags of a configuration item for their belonging into a template
|
|
*
|
|
* @access public
|
|
* @param array An item to check
|
|
* @param array The area (configuration|local) where the config item might be displayed
|
|
* @return boolean
|
|
*/
|
|
function serendipity_checkConfigItemFlags(&$item, $area) {
|
|
|
|
if ( in_array('nosave', $item['flags']) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( in_array('local', $item['flags']) && $area == 'configuration' ) {
|
|
return false;
|
|
}
|
|
|
|
if ( in_array('config', $item['flags']) && $area == 'local' ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* When paths or other options are changed in the s9y configuration, update the core files
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
function serendipity_updateConfiguration() {
|
|
global $serendipity, $umask;
|
|
|
|
// Save all basic config variables to the database
|
|
$config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
|
|
|
|
if (isset($_POST['sqlitedbName']) && !empty($_POST['sqlitedbName'])) {
|
|
$_POST['dbName'] = $_POST['sqlitedbName'];
|
|
}
|
|
|
|
// Password can be hidden in re-configuring, but we need to store old password
|
|
if (empty($_POST['dbPass']) && !empty($serendipity['dbPass'])) {
|
|
$_POST['dbPass'] = $serendipity['dbPass'];
|
|
}
|
|
|
|
foreach($config as $category) {
|
|
foreach ( $category['items'] as $item ) {
|
|
|
|
/* Don't save trash */
|
|
if ( !serendipity_checkConfigItemFlags($item, 'configuration') ) {
|
|
continue;
|
|
}
|
|
|
|
if (!isset($item['userlevel'])) {
|
|
$item['userlevel'] = USERLEVEL_ADMIN;
|
|
}
|
|
|
|
// Check permission set. Changes to blogConfiguration or siteConfiguration items
|
|
// always required authorid = 0, so that it be not specific to a userlogin
|
|
if ( $serendipity['serendipityUserlevel'] >= $item['userlevel'] || IS_installed === false ) {
|
|
$authorid = 0;
|
|
} elseif ($item['permission'] == 'blogConfiguration' && serendipity_checkPermission('blogConfiguration')) {
|
|
$authorid = 0;
|
|
} elseif ($item['permission'] == 'siteConfiguration' && serendipity_checkPermission('siteConfiguration')) {
|
|
$authorid = 0;
|
|
} else {
|
|
$authorid = $serendipity['authorid'];
|
|
}
|
|
|
|
if (is_array($_POST[$item['var']])) {
|
|
// Arrays not allowed. Use first index value.
|
|
list($a_key, $a_val) = each($_POST[$item['var']]);
|
|
$_POST[$item['var']] = $a_key;
|
|
|
|
// If it still is an array, munge it all together.
|
|
if (is_array($_POST[$item['var']])) {
|
|
$_POST[$item['var']] = @implode(',', $_POST[$item['var']]);
|
|
}
|
|
}
|
|
|
|
serendipity_set_config_var($item['var'], $_POST[$item['var']], $authorid);
|
|
}
|
|
}
|
|
|
|
if (IS_installed === false || serendipity_checkPermission('siteConfiguration')) {
|
|
return serendipity_updateLocalConfig($_POST['dbName'],
|
|
$_POST['dbPrefix'],
|
|
$_POST['dbHost'],
|
|
$_POST['dbUser'],
|
|
$_POST['dbPass'],
|
|
$_POST['dbType'],
|
|
$_POST['dbPersistent']);
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the root directory of Serendipity
|
|
*
|
|
* @access public
|
|
* @return string The root directory of Serendipity
|
|
*/
|
|
function serendipity_httpCoreDir() {
|
|
if (!empty($_SERVER['SCRIPT_FILENAME']) && substr(php_sapi_name(), 0, 3) != 'cgi') {
|
|
return dirname($_SERVER['SCRIPT_FILENAME']) . '/';
|
|
}
|
|
|
|
if (!empty($_SERVER['ORIG_PATH_TRANSLATED'])) {
|
|
return dirname(realpath($_SERVER['ORIG_PATH_TRANSLATED'])) . '/';
|
|
}
|
|
|
|
return $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']) . '/';
|
|
}
|
|
|
|
/**
|
|
* Delete obsolete files from Serendipity
|
|
*
|
|
* @access public
|
|
* @param array List of files to remove (backup is tried)
|
|
* @return boolean
|
|
*/
|
|
function serendipity_removeFiles($files = null) {
|
|
global $serendipity, $errors;
|
|
|
|
if (!is_array($files)) {
|
|
return;
|
|
}
|
|
|
|
$backupdir = S9Y_INCLUDE_PATH . 'backup';
|
|
if (!is_dir($backupdir)) {
|
|
@mkdir($backupdir, 0777);
|
|
if (!is_dir($backupdir)) {
|
|
$errors[] = sprintf(DIRECTORY_CREATE_ERROR, $backupdir);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!is_writable($backupdir)) {
|
|
$errors[] = sprintf(DIRECTORY_WRITE_ERROR, $backupdir);
|
|
return false;
|
|
}
|
|
|
|
foreach($files AS $file) {
|
|
$source = S9Y_INCLUDE_PATH . $file;
|
|
$sanefile = str_replace('/', '_', $file);
|
|
$target = $backupdir . '/' . $sanefile;
|
|
|
|
if (!file_exists($source)) {
|
|
continue;
|
|
}
|
|
|
|
if (file_exists($target)) {
|
|
$target = $backupdir . '/' . time() . '.' . $sanefile; // Backupped file already exists. Append with timestamp as name.
|
|
}
|
|
|
|
if (!is_writable($source)) {
|
|
$errors[] = sprintf(FILE_WRITE_ERROR, $source) . '<br />';
|
|
} else {
|
|
rename($source, $target);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the real directory of this function file
|
|
*
|
|
* @access public
|
|
* @param string A filename to strip extra paths from
|
|
* @return string The real directory name
|
|
*/
|
|
function serendipity_getRealDir($file) {
|
|
$dir = str_replace( "\\", "/", dirname($file));
|
|
$base = preg_replace('@/include$@', '', $dir) . '/';
|
|
return $base;
|
|
}
|
|
|
|
/**
|
|
* Try to detect if apache URL rewriting is available
|
|
*
|
|
* This function makes a dummy HTTP request and sees if it works
|
|
*
|
|
* @access public
|
|
* @param string The default option when rewrite fails
|
|
* @return string The best preference option for URL rewriting
|
|
*/
|
|
function serendipity_check_rewrite($default) {
|
|
global $serendipity;
|
|
|
|
if (IS_installed == true) {
|
|
return $default;
|
|
}
|
|
|
|
$serendipity_root = dirname($_SERVER['PHP_SELF']) . '/';
|
|
$serendipity_core = serendipity_httpCoreDir();
|
|
$old_htaccess = @file_get_contents($serendipity_core . '.htaccess');
|
|
$fp = @fopen($serendipity_core . '.htaccess', 'w');
|
|
$serendipity_host = preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']);
|
|
|
|
if (!$fp) {
|
|
printf(HTACCESS_ERROR,
|
|
'<b>chmod go+rwx ' . getcwd() . '/</b>'
|
|
);
|
|
return $default;
|
|
} else {
|
|
fwrite($fp, 'ErrorDocument 404 ' . addslashes($serendipity_root) . 'index.php');
|
|
fclose($fp);
|
|
|
|
// Do a request on a nonexistant file to see, if our htaccess allows ErrorDocument
|
|
$sock = @fsockopen($serendipity_host, $_SERVER['SERVER_PORT'], $errorno, $errorstring, 10);
|
|
$response = '';
|
|
|
|
if ($sock) {
|
|
fputs($sock, "GET {$_SERVER['PHP_SELF']}nonexistant HTTP/1.0\r\n");
|
|
fputs($sock, "Host: $serendipity_host\r\n");
|
|
fputs($sock, "User-Agent: Serendipity/{$serendipity['version']}\r\n");
|
|
fputs($sock, "Connection: close\r\n\r\n");
|
|
|
|
while (!feof($sock) && strlen($response) < 4096) {
|
|
$response .= fgets($sock, 400);
|
|
}
|
|
fclose($sock);
|
|
}
|
|
|
|
if (preg_match('@^HTTP/\d\.\d 200@', $response) && preg_match('@X\-Blog: Serendipity@', $response)) {
|
|
$default = 'errordocs';
|
|
} else {
|
|
$default = 'none';
|
|
}
|
|
|
|
if (!empty($old_htaccess)) {
|
|
$fp = @fopen($serendipity_core . '.htaccess', 'w');
|
|
fwrite($fp, $old_htaccess);
|
|
fclose($fp);
|
|
} else {
|
|
@unlink($serendipity_core . '.htaccess');
|
|
}
|
|
|
|
return $default;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove old configuration values that are no longer used by Serendipity
|
|
*
|
|
* @access public
|
|
* @return null
|
|
*/
|
|
function serendipity_removeObsoleteVars() {
|
|
global $serendipity;
|
|
|
|
$config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
|
|
foreach($config as $category) {
|
|
foreach($category['items'] as $item) {
|
|
/* Remove trash */
|
|
if (!serendipity_checkConfigItemFlags($item, 'remove')) {
|
|
serendipity_remove_config_var($item['var'], 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve an FTP-compatible checksum for a file.
|
|
*
|
|
* @access public
|
|
* @param string filename is the path to the file to checksum
|
|
* @param string type forces a particular interpretation of newlines. Mime
|
|
* types and strings starting with 'text' will cause newlines to be stripped
|
|
* before the checksum is calculated (default: null, determine from finfo
|
|
* and extension)
|
|
* @return string An MD5 checksum of the file, with newlines removed if it's
|
|
* an ASCII type; or false if the file cannot be read
|
|
*/
|
|
function serendipity_FTPChecksum($filename, $type = null) {
|
|
/** Only read the finfo database once */
|
|
static $debug_exts = array();
|
|
|
|
// Must be able to read the file
|
|
if (!is_readable($filename)) {
|
|
return false;
|
|
}
|
|
|
|
// Figure out whether it's binary or text by extension
|
|
if ($type == null) {
|
|
$parts = pathinfo($filename);
|
|
$ext = '';
|
|
// Some PHP versions throw a warning if the index doesn't exist
|
|
if (isset($parts['extension'])) {
|
|
$ext = $parts['extension'];
|
|
}
|
|
// If they're case-insensitive equal, strcasecmp() returns 0, or
|
|
// 'false'. So I use && to find if any of them are 0, in the
|
|
// most likely fail-fast order.
|
|
if (strcasecmp($ext, 'php') &&
|
|
strcasecmp($ext, 'tpl') &&
|
|
strcasecmp($ext, 'sql') &&
|
|
strcasecmp($ext, 'js') &&
|
|
strcasecmp($ext, 'txt') &&
|
|
strcasecmp($ext, 'htc') &&
|
|
strcasecmp($ext, 'css') &&
|
|
strcasecmp($ext, 'dist') &&
|
|
strcasecmp($ext, 'lib') &&
|
|
strcasecmp($ext, 'sh') &&
|
|
strcasecmp($ext, 'html') &&
|
|
strcasecmp($ext, 'htm') &&
|
|
!empty($ext)) {
|
|
if (!in_array($ext, array_keys($debug_exts))) {
|
|
$debug_exts[$ext] = $filename;
|
|
}
|
|
$type = 'bin';
|
|
} else {
|
|
$type = 'text';
|
|
}
|
|
}
|
|
|
|
// Calculate the checksum
|
|
$md5 = false;
|
|
if (stristr($type, 'text')) {
|
|
// This is a text-type file. We need to remove linefeeds before
|
|
// calculating a checksum, to account for possible FTP conversions
|
|
// that are inconvenient, but still valid. But we don't want to
|
|
// allow newlines anywhere; just different *kinds* of newlines.
|
|
$newlines = array("#\r\n#", "#\r#", "#\n#");
|
|
$file = file_get_contents($filename);
|
|
$file = preg_replace($newlines, ' ', $file);
|
|
$md5 = md5($file);
|
|
} else {
|
|
// Just get its md5sum
|
|
$md5 = md5_file($filename);
|
|
}
|
|
|
|
return $md5;
|
|
}
|
|
|
|
/**
|
|
* Validate checksums for all required files.
|
|
*
|
|
* @return A list of all files that failed checksum, where keys are the
|
|
* relative path of the file, and values are the bad checksum
|
|
*/
|
|
function serendipity_verifyFTPChecksums() {
|
|
global $serendipity;
|
|
|
|
$badsums = array();
|
|
|
|
// Load the checksums
|
|
$f = S9Y_INCLUDE_PATH . 'checksums.inc.php';
|
|
|
|
if (!file_exists($f) || filesize($f) < 1) {
|
|
return $badsums;
|
|
}
|
|
|
|
require_once $f;
|
|
// Verify that every file in the checksum list was uploaded correctly
|
|
$basedir = realpath(dirname(__FILE__) . '/../');
|
|
|
|
if (!is_array($serendipity['checksums_' . $serendipity['version']])) {
|
|
return $badsums;
|
|
}
|
|
|
|
foreach ($serendipity['checksums_' . $serendipity['version']] as $prel => $sum) {
|
|
$path = $basedir . '/' . $prel;
|
|
// Don't take checksums of directories
|
|
if (is_dir($path)) {
|
|
// Weird that it's even here.
|
|
continue;
|
|
}
|
|
|
|
// Can't checksum unreadable or nonexistent files
|
|
if (!is_readable($path)) {
|
|
$badsums[$prel] = 'missing';
|
|
continue;
|
|
}
|
|
|
|
// Validate checksum
|
|
$calcsum = serendipity_FTPChecksum($path);
|
|
if ($sum != $calcsum) {
|
|
$badsums[$prel] = $calcsum;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return $badsums;
|
|
}
|
|
|
|
|
|
/**
|
|
* Check https://raw.github.com/s9y/Serendipity/master/docs/RELEASE for the newest available version
|
|
*
|
|
* If the file is not fetch- or parseable (behind a proxy, malformed by Garvin), this will return -1
|
|
* */
|
|
function serendipity_getCurrentVersion() {
|
|
global $serendipity;
|
|
|
|
if ($serendipity['updateCheck'] != "stable" && $serendipity['updateCheck'] != "beta") {
|
|
return -1;
|
|
}
|
|
|
|
// Perform update check once a day. We use a suffix of the configured channel, so when
|
|
// the user switches channels, it has its own timer.
|
|
if ($serendipity['last_update_check_' . $serendipity['updateCheck']] >= (time()-86400)) {
|
|
// Last update was performed less than a day ago. Return last result.
|
|
return $serendipity['last_update_version_' . $serendipity['updateCheck']];
|
|
}
|
|
|
|
serendipity_set_config_var('last_update_check_' . $serendipity['updateCheck'], time());
|
|
$updateURL = 'https://raw.github.com/s9y/Serendipity/master/docs/RELEASE';
|
|
$context = stream_context_create(array('http' => array('timeout' => 5.0)));
|
|
$file = @file_get_contents($updateURL, false, $context);
|
|
|
|
if (!$file) {
|
|
if (function_exists('curl_init')) {
|
|
$ch = curl_init($updateURL);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, "5");
|
|
$file = curl_exec($ch);
|
|
curl_close($ch);
|
|
}
|
|
}
|
|
|
|
if ($file) {
|
|
if ($serendipity['updateCheck'] == "stable") {
|
|
if (preg_match('/^stable:(.+)\b/', $file, $match)) {
|
|
serendipity_set_config_var('last_update_version_' . $serendipity['updateCheck'], $match[1]);
|
|
return $match[1];
|
|
}
|
|
} else {
|
|
if (preg_match('/^beta:(.+)\b/', $file, $match)) {
|
|
serendipity_set_config_var('last_update_version_' . $serendipity['updateCheck'], $match[1]);
|
|
return $match[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* vim: set sts=4 ts=4 sw=4 expandtab : */
|