Typechoソース分析(2)
目次前情提要 インストールプロセス に進む.インストール第1ステップ は構成 に入る.来`start` 結語 前情提要
前回は
インストールプロセスに入る
次に
まず
異常処理部は、
前回は
install.php
ファイルのset_include_path
を分析した.今日は続けます.インストールプロセスに入る
Typecho/Common.php
の導入に来たので、不思議かもしれませんが、このディレクトリが見つからないのではないでしょうか.いくつかの導入経路が設定されていることを忘れないでください.だから、一つ一つ探して、最後にvar
ディレクトリの下で、Typecho/Common.php
を見つけます.この方法で導入するのを見てください.書類を探しても扱いにくいです.そのため、ネーミングスペースなどがますます重要になり、set_include_path
という導入案も徐々に減少していきます.次に
Typecho_Common::init();
という行のコードを実行する方法は、さっき導入したファイルで、この方法に入ります./**
*
*
* @param $className
*/
public static function __autoLoad($className)
{
@include_once str_replace(array('\\', '_'), '/', $className) . '.php';
}
/**
*
*
* @access public
* @return void
*/
public static function init()
{
/** */
spl_autoload_register(array('Typecho_Common', '__autoLoad'));
/** php6 */
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
$_GET = self::stripslashesDeep($_GET);
$_POST = self::stripslashesDeep($_POST);
$_COOKIE = self::stripslashesDeep($_COOKIE);
reset($_GET);
reset($_POST);
reset($_COOKIE);
}
/** */
set_exception_handler(array('Typecho_Common', 'exceptionHandle'));
}
まず
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
の部分を見て、これはphp 5.4以降永遠にfalseに戻ったので、5.4以降は実行されません.古いバージョンであれば、この処理はいくつかのエスケープに反斜線のある文字を復元し、元の内容にすることです.そして残りの部分は自動ロードと異常処理関数を登録することです.自動ロードは私の前の文章を見て、自分で理解することができます.異常処理部は、
debug
であるか否かに応じた2種類の出力モードである./**
*
*
* @access public
* @param $exception
* @return void
*/
public static function exceptionHandle($exception)
{
if (defined('__TYPECHO_DEBUG__')) {
echo ''
;
echo '' . htmlspecialchars($exception->getMessage()) . '';
echo htmlspecialchars($exception->__toString());
echo '';
} else {
@ob_end_clean();
if (404 == $exception->getCode() && !empty(self::
$exceptionHandle)) {
$handleClass = self::$exceptionHandle;
new $handleClass($exception);
} else {
self::error($exception);
}
}
exit;
}self::$exceptionHandle
これは の にまた します.EXceptionHandleがない はerror
メソッドが び され、エラー が われ、error_log
が される/**
*
*
* @access public
* @param mixed $exception
* @return void
*/
public static function error($exception)
{
$isException = is_object($exception);
$message = '';
if ($isException) {
$code = $exception->getCode();
$message = $exception->getMessage();
} else {
$code = $exception;
}
$charset = self::$charset;
if ($isException && $exception instanceof Typecho_Db_Exception) {
$code = 500;
@error_log($message);
//
$message = 'Database Server Error';
if ($exception instanceof Typecho_Db_Adapter_Exception) {
$code = 503;
$message = 'Error establishing a database connection';
} else if ($exception instanceof Typecho_Db_Query_Exception) {
$message = 'Database Query Error';
}
} else {
switch ($code) {
case 500:
$message = 'Server Error';
break;
case 404:
$message = 'Page Not Found';
break;
default:
$code = 'Error';
break;
}
}
/** http code */
if (is_numeric($code) && $code > 200) {
Typecho_Response::setStatus($code);
}
$message = nl2br($message);
if (defined('__TYPECHO_EXCEPTION_FILE__')) {
require_once __TYPECHO_EXCEPTION_FILE__;
} else {
echo
<<<EOF
{$charset}">
<span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$code</span><span class="token punctuation">}</span></span>
{$message}
EOF;
}
exit;
}
ここまでinit
メソッドは みで、install.php
ファイルに って を けます.//
if (!empty($_GET) || !empty($_POST)) {
if (empty($_SERVER['HTTP_REFERER'])) {
exit;
}
$parts = parse_url($_SERVER['HTTP_REFERER']);
if (!empty($parts['port'])) {
$parts['host'] = "{$parts['host']}:{$parts['port']}";
}
if (empty($parts['host']) || $_SERVER['HTTP_HOST'] != $parts['host']) {
exit;
}
}
これはドメイン をブロックします. えばiframeのネストされたページです. のために、referer
が されたhost
と しなければブロックしないと します.$options = new stdClass();
$options->generator = 'Typecho ' . Typecho_Common::VERSION;
list($soft, $currentVersion) = explode(' ', $options->generator);
$options->software = $soft;
$options->version = $currentVersion;
list($prefixVersion, $suffixVersion) = explode('/', $currentVersion);
/** */
$lang = _r('lang', Typecho_Cookie::get('__typecho_lang'));
$langs = Widget_Options_General::getLangs();
if (empty($lang) || (!empty($langs) && !isset($langs[$lang]))) {
$lang = 'zh_CN';
}
if ('zh_CN' != $lang) {
$dir = defined('__TYPECHO_LANG_DIR__') ? __TYPECHO_LANG_DIR__ : __TYPECHO_ROOT_DIR__ . '/usr/langs';
Typecho_I18n::setLang($dir . '/' . $lang . '.mo');
}
Typecho_Cookie::set('__typecho_lang', $lang);
セットアップバージョン、セットアップ 、ついでにcookie
に を き みます.
りの はインストールプロセスなので、ゆっくり してみましょう.まずインストールファイルの の についてお しします
include 'admin/copyright.php';
include 'admin/footer.php';
?>
この2つのファイルはすべて のためです if(!defined('__TYPECHO_ADMIN__')) exit; ?>
その を せずに したので、この2つの は たちが っている に します.<li if (!isset($_GET['finish']) && !isset($_GET['config'])) : ?> class="current" endif; ?>><span>1</span> _e(' '); ?></li>
<li if (isset($_GET['config'])) : ?> class="current" endif; ?>><span>2</span> _e(' '); ?></li>
<li if (isset($_GET['start'])) : ?> class="current" endif; ?>><span>3</span> _e(' '); ?></li>
<li if (isset($_GET['finish'])) : ?> class="current" endif; ?>><span>4</span> _e(' '); ?></li>
これがurl
のパラメータ に づいて される _e
と_t
はいずれも であり、echo
は であり、もう1つは である. ですよ、start
という は、 な では えませんよ. してこそ えます.
インストールの のステップ
いくつかの ファイルが されます. が ある は、 リストボックスが されますが、デフォルトでは は1つしかありません. に、 のステップをクリックすると、 のurl
にジャンプし、config
パラメータを します.
へのアクセス
のステップをクリックすると、 のステップに ります. するデータパラメータを し、 を した 、 のステップをクリックすると、post
メソッドが のconfig
URLにジャンプします.ここで な は、データベースのアダプタを すると、 するデータベースアダプタの ページを り えることです.また、ページロード にどのデータがサポートされているかを します.この2つのセグメントは のコードにあります.
$adapters = array('Mysql', 'Mysqli', 'Pdo_Mysql', 'SQLite', 'Pdo_SQLite', 'Pgsql', 'Pdo_Pgsql');
foreach ($adapters as $firstAdapter) {
if (_p($firstAdapter)) {
break;
}
}
$adapter = _r('dbAdapter', $firstAdapter);
$parts = explode('_', $adapter);
$type = $adapter == 'Mysqli' ? 'Mysql' : array_pop($parts);
?>
require_once './install/' . $type . '.php'; ?>
<script>
var _select = document.config.dbAdapter;
_select.onchange = function() {
setTimeout("window.location.href = 'install.php?config&dbAdapter=" + this.value + "'; ",0);
}
</script>
アダプタによって なるデータベース ページがロードされます.こちらではmysql
を しています.install/mysql.php
ページに ります.sae、gae、baeなどの がたくさんあります.これらはすべてスキップして、 を ます. else: ?>
<li>
<label class="typecho-label" for="dbHost"> _e(' '); ?></label>
<input type="text" class="text" name="dbHost" id="dbHost" value=""/>
<p class="description"> _e(' "%s"', 'localhost'); ?></p>
</li>
<li>
<label class="typecho-label" for="dbPort"> _e(' '); ?></label>
<input type="text" class="text" name="dbPort" id="dbPort" value=""/>
<p class="description"> _e(' , '); ?></p>
</li>
<li>
<label class="typecho-label" for="dbUser"> _e(' '); ?></label>
<input type="text" class="text" name="dbUser" id="dbUser" value="" />
<p class="description"> _e(' "%s"', 'root'); ?></p>
</li>
<li>
<label class="typecho-label" for="dbPassword"> _e(' '); ?></label>
<input type="password" class="text" name="dbPassword" id="dbPassword" value="" />
</li>
<li>
<label class="typecho-label" for="dbDatabase"> _e(' '); ?></label>
<input type="text" class="text" name="dbDatabase" id="dbDatabase" value="" />
<p class="description"> _e(' '); ?></p>
</li>
endif; ?>
<input type="hidden" name="dbCharset" value="" />
<li>
<label class="typecho-label" for="dbCharset"> _e(' '); ?></label>
<select name="dbCharset" id="dbCharset">
<option value="utf8" if (_r('dbCharset') == 'utf8'): ?> selected endif; ?>>utf8</option>
<option value="utf8mb4" if (_r('dbCharset') == 'utf8mb4'): ?> selected endif; ?>>utf8mb4</option>
</select>
<p class="description"> _e(' utf8mb4 MySQL 5.5.3 '); ?></p>
</li>
<li>
<label class="typecho-label" for="dbEngine"> _e(' '); ?></label>
<select name="dbEngine" id="dbEngine">
<option value="MyISAM" if (_r('dbEngine') == 'MyISAM'): ?> selected endif; ?>>MyISAM</option>
<option value="InnoDB" if (_r('dbEngine') == 'InnoDB'): ?> selected endif; ?>>InnoDB</option>
</select>
</li>
これが たちが を す ですよ. を した 、post
に のページを し、 の に ります.if (_r('created') && !file_exists('./config.inc.php')) {
echo ' . _t(' , ') . '';
$success = false;
} else {
if (NULL == _r('userUrl')) {
$success = false;
echo ' . _t(' ') . '';
} else if (NULL == _r('userName')) {
$success = false;
echo ' . _t(' ') . '';
} else if (NULL == _r('userMail')) {
$success = false;
echo ' . _t(' ') . '';
} else if (32 < strlen(_r('userName'))) {
$success = false;
echo ' . _t(' , 32 ') . '';
} else if (200 < strlen(_r('userMail'))) {
$success = false;
echo ' . _t(' , 200 ') . '';
}
}
この はいくつかの に するものがあります. に わない はif (_r('created') && !file_exists('./config.inc.php')) {
を えて します. してください. で しましょう.$_dbConfig = _rFrom('dbHost', 'dbUser', 'dbPassword', 'dbCharset', 'dbPort', 'dbDatabase', 'dbFile', 'dbDsn', 'dbEngine');
$_dbConfig = array_filter($_dbConfig);
$dbConfig = array();
foreach ($_dbConfig as $key => $val) {
$dbConfig[strtolower(substr($key, 2))] = $val;
}
//
if (_r('config')) {
$replace = array_keys($dbConfig);
foreach ($replace as &$key) {
$key = '{' . $key . '}';
}
if (!empty($_dbConfig['dbDsn'])) {
$dbConfig['dsn'] = str_replace($replace, array_values($dbConfig), $dbConfig['dsn']);
}
$config = str_replace($replace, array_values($dbConfig), _r('config'));
}
if (!isset($config) && $success && !_r('created')) {
$installDb = new Typecho_Db($adapter, _r('dbPrefix'));
$installDb->addServer($dbConfig, Typecho_Db::READ | Typecho_Db::WRITE);
/** */
try {
$installDb->query('SELECT 1=1');
} catch (Typecho_Db_Adapter_Exception $e) {
$success = false;
echo '
. _t(' , , ') . '';
} catch (Typecho_Db_Exception $e) {
$success = false;
echo '
. _t(' : " %s ". , .',$e->getMessage()) . '';
}
}
これはデータベース の を して、それからデータベースに して、データベース のコードはtypecho
のパッケージで、みんなは で ることができて、すごいです. に すると、エラーが します. したら、データベース をリセットします.これは インストールに するはずです.その 、cookie
がデータベース を き む//
if (isset($installDb)) {
try {
$installDb->query($installDb->update('table.options')
->rows(array('value' => 0))->where('name = ?', 'installed'));
} catch (Exception $e) {
// do nothing
}
}
Typecho_Cookie::set('__typecho_config', base64_encode(serialize(array_merge(array(
'prefix' => _r('dbPrefix'),
'userName' => _r('userName'),
'userPassword' => _r('userPassword'),
'userMail' => _r('userMail'),
'adapter' => $adapter,
'siteUrl' => _r('userUrl')
), $dbConfig))));
の に してください.if (_r('created')) {
header('Location: ./install.php?start');
exit;
}
これはどういう ですか. で そう/** */
$lines = array_slice(file(__FILE__), 1, 31);
$lines[] = "
/** */
\$db = new Typecho_Db('{$adapter}', '" . _r('dbPrefix') . "');
\$db->addServer(" . (empty($config) ? var_export($dbConfig, true) : $config) . ", Typecho_Db::READ | Typecho_Db::WRITE);
Typecho_Db::set(\$db);
";
$contents = implode('', $lines);
if (!Typecho_Common::isAppEngine()) {
@file_put_contents('./config.inc.php', $contents);
}
このセクションはプロファイルに き まれます.if (!file_exists('./config.inc.php')) {
?>
<div class="message notice"><p> _e(' config.inc.php '); ?><br />
_e(' config.inc.php , '); ?></p>
<p><textarea rows="5" onmouseover="this.select();" class="w-100 mono" readonly> echo htmlspecialchars($contents); ?></textarea></p>
<p><button name="created" value="1" type="submit" class="btn primary"> , »</button></p></div>
} else {
header('Location: ./install.php?start');
exit;
}
ファイルの き みに すると、 のページにジャンプしてcreated
パラメータを し、 のステップの に します. き みに すると、start
にジャンプします.//
if(!$success && file_exists(__TYPECHO_ROOT_DIR__ . '/config.inc.php')) {
@unlink(__TYPECHO_ROOT_DIR__ . '/config.inc.php');
}
インストールに したら、ファイルを します.start
へ
この は な に した.require_once dirname(__FILE__) . '/config.inc.php';
//
$db = Typecho_Db::get();
try {
$installed = $db->fetchRow($db->select()->from('table.options')->where('name = ?', 'installed'));
if (empty($installed) || $installed['value'] == 1) {
Typecho_Response::setStatus(404);
exit;
}
} catch (Exception $e) {
// do nothing
}
これは の り、プロファイルが まれている はデータベースにリンクし、インストールされているかどうかを し、インストールされている は404
とエラーを します. if (!isset($db)) : ?>
<h1 class="typecho-install-title"> _e(' !'); ?></h1>
<div class="typecho-install-body">
<form method="post" action="?config" name="config">
<p class="message error"> _e(' config.inc.php , !'); ?> <button class="btn primary" type="submit"> _e(' »'); ?></button></p>
</form>
</div>
else : ?>
db
が されていなければ、エラーが されます.すべてがうまくいけば、データベースの を し、プロファイルを します. した はインストール を し、 した はジャンプし、インストールに します.インストールプロセスのページが えないというのは、 すぎるので してしまいますが、 の がはっきりしていませんので、ここで します. if(('Mysql' == $type && (1050 == $code || '42S01' == $code)) ||
('SQLite' == $type && ('HY000' == $code || 1 == $code)) ||
('Pgsql' == $type && '42P07' == $code)) {
if(_r('delete')) {
//
$dbPrefix = $config['prefix'];
$tableArray = array($dbPrefix . 'comments', $dbPrefix . 'contents', $dbPrefix . 'fields', $dbPrefix . 'metas', $dbPrefix . 'options', $dbPrefix . 'relationships', $dbPrefix . 'users',);
foreach($tableArray as $table) {
if($type == 'Mysql') {
$installDb->query("DROP TABLE IF EXISTS `{$table}`");
} elseif($type == 'Pgsql') {
$installDb->query("DROP TABLE {$table}");
} elseif($type == 'SQLite') {
$installDb->query("DROP TABLE {$table}");
}
}
echo ' . _t(' ') . '
. _t(' »') . '';
} elseif (_r('goahead')) {
//
//
$installDb->query($installDb->update('table.options')->rows(array('value' => $config['siteUrl']))->where('name = ?', 'siteUrl'));
unset($_SESSION['typecho']);
header('Location: ./install.php?finish&use_old');
exit;
} else {
echo ' . _t(' .')
. '
' . ' . _t(' ') . ' '
. _t(' ') . ' . _t(' ') . '';
}
これが にデータベースが する の である.ライブラリを したり、 のデータベースを したりして、 、インストールプロセスを します.
めくくり
これで、インストールはすべて しました. たちはインストールモジュールを しました. に を いますか.フロント、 、 に していないdb
、 にバックグラウンドを します.また ね