General
Jeans & Development | 電子ブロック工房 | 三日坊主 | フロントページ |
ver 0.2.0 公開 [General]
2008年3月13日
コアがほぼ完成したので、バックアップを取る意味もかねて、公開。現在、ver 0.2.0。αのさらにαのような物だけれど、とりあえずRSSフィードを出力することを確認。
今後の開発ロードマップは次のとおり。
1)デフォルトスキンを問題なく表示できるように、スキン変数・テンプレート変数まわりのコードをチェック。
2)コメント周りのコードの実装。
3)プラグインインターフェースを整備。プラグインオプションとか、イベントとか。
4)管理画面用スキンの製作。および、管理アクション用のコードの実装。
うーん、長い道のりだ。
<%media(20080314-jeans 0.2.0.1.6.zip|ver 0.2.0はここからダウンロードできます。)%>
・αバージョンで、実用性はゼロです。
・セキュリティーチェックを行っていないので、ローカルの環境にのみインストールしてください。インストールは、ZIPファイルを解凍するだけです。
・登録してあるユーザのユーザ名は『admin』パスワードは『admin』です。logintest.php経由でアクセスすると、自動的にログインされます。
・RSSフィードは、xml-rss2.phpにアクセスすると表示できます。
・スキンは/skins/フォルダに、テンプレートはスキンフォルダ内のtemplate_xxx.incに保存されています。
・ここはこんな風にしたら良いとか、ご意見ありましたら、よろしくお願いします。
今後の開発ロードマップは次のとおり。
1)デフォルトスキンを問題なく表示できるように、スキン変数・テンプレート変数まわりのコードをチェック。
2)コメント周りのコードの実装。
3)プラグインインターフェースを整備。プラグインオプションとか、イベントとか。
4)管理画面用スキンの製作。および、管理アクション用のコードの実装。
うーん、長い道のりだ。
<%media(20080314-jeans 0.2.0.1.6.zip|ver 0.2.0はここからダウンロードできます。)%>
・αバージョンで、実用性はゼロです。
・セキュリティーチェックを行っていないので、ローカルの環境にのみインストールしてください。インストールは、ZIPファイルを解凍するだけです。
・登録してあるユーザのユーザ名は『admin』パスワードは『admin』です。logintest.php経由でアクセスすると、自動的にログインされます。
・RSSフィードは、xml-rss2.phpにアクセスすると表示できます。
・スキンは/skins/フォルダに、テンプレートはスキンフォルダ内のtemplate_xxx.incに保存されています。
・ここはこんな風にしたら良いとか、ご意見ありましたら、よろしくお願いします。
テンプレートをファイルとして保存 [General]
2008年3月11日
現在のところ、スキンデータはすべてskins/ディレクトリにファイルとして保存され、テンプレートデータはすべてjeans_templateテーブルとしてデータベースに保存されている。少し分かりにくい。
スキンとテンプレートをフルコンパイルした場合には、どちらもグローバル関数としてPHPファイルに記述する予定である。従って、コンパイルする前のスキンやテンプレートはどこに記述されていても良いし、それらを呼び出す際の速度の問題などもそれほど考える必要も無い。ならば、これらを記述する方法としては、分かりやすさと編集の容易さがポイントとなる。
スキンとテンプレートをフルコンパイルした場合には、どちらもグローバル関数としてPHPファイルに記述する予定である。従って、コンパイルする前のスキンやテンプレートはどこに記述されていても良いし、それらを呼び出す際の速度の問題などもそれほど考える必要も無い。ならば、これらを記述する方法としては、分かりやすさと編集の容易さがポイントとなる。
コードのクラスへの振り分けを少し整理 [General]
2008年3月5日
現在のJeansのアーキテクチャは次のとおり。

見てのとおり、少し複雑である。制御があちらこちらに飛んでしまっているように感じる。もう少し分かりやすくしたい。
まず、index.phpからの制御がcoreとskinに向いているが、これらはそれぞれ、Nucleusのglobalfunctions.phpのインクルードとselector()の実行に相当する。Jeansでは管理画面もスキンを通じてアクセスする予定なので、skinは実際にはほとんどの場合に使われることになる(例外は、アクションの呼び出し)。次にsqlクラスだが、これはcoreクラスの初期化の際に必ず呼び出される。
そこで、skinクラスとsqlクラスの機能をcoreに統合することにする。skinクラスのメソッドはcoreクラスにそのまま取り込み、sqlクラスはそのままの形でcore.phpファイル内に記述する。skinクラス相当分のコードのパースはアクションの呼び出し(actionクラスを利用)の際に少々無駄になるが、50行ほどの簡単なコードだから、パフォーマンスへの影響は少ない。
この変更を施すと、アーキテクチャは次のようになる。

これなら、分かりやすい。すべての制御がcoreから始まり、それをjitとactionの二つのクラスがサポートすることが一目瞭然。

見てのとおり、少し複雑である。制御があちらこちらに飛んでしまっているように感じる。もう少し分かりやすくしたい。
まず、index.phpからの制御がcoreとskinに向いているが、これらはそれぞれ、Nucleusのglobalfunctions.phpのインクルードとselector()の実行に相当する。Jeansでは管理画面もスキンを通じてアクセスする予定なので、skinは実際にはほとんどの場合に使われることになる(例外は、アクションの呼び出し)。次にsqlクラスだが、これはcoreクラスの初期化の際に必ず呼び出される。
そこで、skinクラスとsqlクラスの機能をcoreに統合することにする。skinクラスのメソッドはcoreクラスにそのまま取り込み、sqlクラスはそのままの形でcore.phpファイル内に記述する。skinクラス相当分のコードのパースはアクションの呼び出し(actionクラスを利用)の際に少々無駄になるが、50行ほどの簡単なコードだから、パフォーマンスへの影響は少ない。
この変更を施すと、アーキテクチャは次のようになる。

これなら、分かりやすい。すべての制御がcoreから始まり、それをjitとactionの二つのクラスがサポートすることが一目瞭然。
PDOへの移行はほぼ終了 [General]
2008年3月1日
アンケートの結果に従ってPDOを利用することにし、sqlクラスを全面的に書き換えた。次の例のように使うことになる。
これで、規約に沿ってコアやプラグインを書いている限り、SQLインジェクションはほぼ100%起こらない。
$res=sql::query('SELECT * FROM jeans_item WHERE icat=<%catid%>',array('catid'=>$catid)); while ($row=$res->fetch()) core::p($row['ititle']);もしくは
$res=sql::prepare('SELECT * FROM jeans_item WHERE icat= :catid'); $res->bindParam(':catid',$catid); $res->execute(); while ($row=$res->fetch()) core::p($row['ititle']);もしくは
$res=sql::prepare('SELECT * FROM jeans_item WHERE icat= :catid'); $res->execute(array(':catid'=>$catid)); while ($row=$res->fetch()) core::p($row['ititle']);
これで、規約に沿ってコアやプラグインを書いている限り、SQLインジェクションはほぼ100%起こらない。
アンケートにご協力お願いします [General]
2008年2月18日
RSSフィードで購読なさっている方へ:アンケートにご協力お願いできますでしょうか。
Jeans CMSにおいては、いくらか規約を設けることでセキュリティーを確保する予定です。ただ、規約があまりにも複雑で敷居が高すぎる場合、その規約が守られないことになってしまいます。過ぎたるは及ばざるが如しにならないように、うまく規約を設定する必要があります。
SQLインジェクションを防ぐため、SQLクエリー実行部分のスクリプトの記述に関して規約を作る必要があるのですが、ここでプリペアードステートメントを使用することを規約とするかどうか、悩んでいます。
例えば、次のスクリプトは、現在のNucleusで使われている様式です。
コード0:現在のNucleus様式
Jeans CMSにおいては、いくらか規約を設けることでセキュリティーを確保する予定です。ただ、規約があまりにも複雑で敷居が高すぎる場合、その規約が守られないことになってしまいます。過ぎたるは及ばざるが如しにならないように、うまく規約を設定する必要があります。
SQLインジェクションを防ぐため、SQLクエリー実行部分のスクリプトの記述に関して規約を作る必要があるのですが、ここでプリペアードステートメントを使用することを規約とするかどうか、悩んでいます。
例えば、次のスクリプトは、現在のNucleusで使われている様式です。
コード0:現在のNucleus様式
$res=mysql_query( 'SELECT i.itime as itime, c.cblog as blogid, substr(i.itime,0,4) as year, substr(i.itime,5,2) as month, substr(i.itime,8,2) as day, '. 'FROM jeans_item as i, jeans_category as c '. 'WHERE i.icat=c.catid AND c.cblog='.intval($blogid).' '. ' AND c.catid='.intval($catid).' '. 'ORDER BY i.itime DESC LIMIT '.intval($limit));
coreを基底クラスに? [General]
2008年2月17日
coreクラスは、config.phpをインクルードしたときに一番初めに定義されるクラスだ。今、このcoreクラスをすべてのクラスの基底クラスにするかどうかで悩んでいる。
例えば、プラグインで文字出力を行う場合、現在の仕様では
のように記述するが、coreクラスを基底クラスとしてプラグインクラスを作成すると、
のように記述してもよいし、
のように記述することもできる。PHP5ではメソッドのオーバーライドができないように設定できるから、プラグインでpメソッドやechohtmlメソッドを書き換えて変なことをするのも禁止できる。
例えば、プラグインで文字出力を行う場合、現在の仕様では
core::p($text); core:echohtml('<p>id: <%1%></p>',$id);
のように記述するが、coreクラスを基底クラスとしてプラグインクラスを作成すると、
$this->p($text); $this->echohtml('<p>id: <%1%></p>',$id);
のように記述してもよいし、
self::p($text);
のように記述することもできる。PHP5ではメソッドのオーバーライドができないように設定できるから、プラグインでpメソッドやechohtmlメソッドを書き換えて変なことをするのも禁止できる。
pluginoptionクラス [General]
2008年2月9日
プラグインオプションの値は、plugionoptionクラスのオブジェクトに保持させることにした。
pluginクラス内にて、
もしくは、
のように使う。
pluginクラス内にて、
$this->option=new pluginoption($this->id);
もしくは、
public function blogoption($bid){ $obj=new pluginoption($this->id,'blog',$bid); return $obj; }
のように使う。
プラグイン周りの仕様 [General]
2008年2月9日
現在のところ、コアではほとんどのコードでクラスのスタティックメソッドを利用するため、あまりオブジェクト指向とはいえないコードになっている。
一方で、プラグインの部分は、オブジェクト経由でアクセスする予定。理由は、次のとおり。
Nucleusと同じく、プラグインはすべてpluginクラスを継承したクラスとして記述することになる。プラグインのクラスをスタティックなメソッドの集合体として扱った場合、複数のプラグインのクラスが単一のpluginクラスを継承しているため、親クラスであるpluginクラスのそれぞれのメソッドで、各プラグインに固有の値(プラグインオプションなど)を処理できないのである。
一方で、Nucleusがやっているようにすべてオブジェクト経由で扱った場合、pluginクラスのメソッドでは$thisオブジェクトを経由することでこれを行うことができる(他方、コアの各クラスは、複数のインスタンスを持たせる必要が無いため、スタティックなメソッドやプロパティを扱うやり方で、今のところコードに混乱は無い)。
プラグインの仕様については、Nucleusのプラグインとほぼ同一のものを提供する予定である。が、もともとこのプロジェクトをはじめた動機のひとつとして、プラグインを書くときに楽をしたいというのもあるので、そうなるような仕様の変更を考えている。
現在のところ、どんなことで楽ができるかというと、
1)sql_table() 関数を使う必要が無い。
2)global $manager, $CONF, $DIR_LIBS; といった記述が不要。
3)echo htmlspecialchars($text,ENT_QUOTE,_CHARSET); の代わりに core::p($text); で良い。
4)3と同様だが、クエリーでaddslashes()やmysql_escape_string()なども使う必要が無い。
など。
一方で、プラグインの部分は、オブジェクト経由でアクセスする予定。理由は、次のとおり。
Nucleusと同じく、プラグインはすべてpluginクラスを継承したクラスとして記述することになる。プラグインのクラスをスタティックなメソッドの集合体として扱った場合、複数のプラグインのクラスが単一のpluginクラスを継承しているため、親クラスであるpluginクラスのそれぞれのメソッドで、各プラグインに固有の値(プラグインオプションなど)を処理できないのである。
一方で、Nucleusがやっているようにすべてオブジェクト経由で扱った場合、pluginクラスのメソッドでは$thisオブジェクトを経由することでこれを行うことができる(他方、コアの各クラスは、複数のインスタンスを持たせる必要が無いため、スタティックなメソッドやプロパティを扱うやり方で、今のところコードに混乱は無い)。
プラグインの仕様については、Nucleusのプラグインとほぼ同一のものを提供する予定である。が、もともとこのプロジェクトをはじめた動機のひとつとして、プラグインを書くときに楽をしたいというのもあるので、そうなるような仕様の変更を考えている。
現在のところ、どんなことで楽ができるかというと、
1)sql_table() 関数を使う必要が無い。
2)global $manager, $CONF, $DIR_LIBS; といった記述が不要。
3)echo htmlspecialchars($text,ENT_QUOTE,_CHARSET); の代わりに core::p($text); で良い。
4)3と同様だが、クエリーでaddslashes()やmysql_escape_string()なども使う必要が無い。
など。
sqlite_popen(`:memory:`) [General]
2008年1月28日
『sqlite_popen(':memory:')』を使うと、メモリ上にテーブルを構築できるらしい。
ひょっとしたら、何かのキャッシュに使えるかも?忘れないように、ここにメモ。
ただし、レンタルサーバなどでのセキュリティー上の問題が発生する可能性あり。要チェック。
<html><body><?php $db=sqlite_popen(':memory:'); @sqlite_query($db,'CREATE TABLE test(id INTEGER NOT NULL PRIMARY KEY, test TEXT)'); for($i=0;$i<3;$i++) sqlite_query($db,"INSERT INTO test(test) VALUES('".md5(rand())."')"); echo count(sqlite_array_query($db,'SELECT * FROM test')); //sqlite_close($db); ?></body></html>
ひょっとしたら、何かのキャッシュに使えるかも?忘れないように、ここにメモ。
ただし、レンタルサーバなどでのセキュリティー上の問題が発生する可能性あり。要チェック。
権限管理 [General]
2008年1月25日
スキン変数を実装していく段階で、ブログチームの管理部分に行き着いたのであるが、一からCMSを書くのであれば、さまざまな権限を別個に設定できるようにしたい。
今のところ、jeans_loginテーブルにstatusとフィールドを設けていて、ここで各メンバーのステータスを決定することにしている。どんなステータスがあるかは、
で取得できるはず。現在のところは『admin』ステータスだけであるが、『blogadmin』『poweruser』など、さまざまなステータスをここに設定できる。いろいろ考えた結果、権限管理にはもう一つテーブルを作るだけでよさそう。
今のところ、jeans_loginテーブルにstatusとフィールドを設けていて、ここで各メンバーのステータスを決定することにしている。どんなステータスがあるかは、
SELECT status FROM jeans_login GROUP BY status
で取得できるはず。現在のところは『admin』ステータスだけであるが、『blogadmin』『poweruser』など、さまざまなステータスをここに設定できる。いろいろ考えた結果、権限管理にはもう一つテーブルを作るだけでよさそう。