Jeans CMS 製作日記 / Regulations http://www.rad51.net/blog/jeans/ 自分のための次世代CMS製作メモ / 規約 ja Jeans CMS © Weblog http://backend.userland.com/rss https://www.rad51.net/jeans/skins/jeans/images/jeans2.gif Jeans CMS 製作日記 http://www.rad51.net/blog/jeans/ リクエストに関する規約 http://www.rad51.net/blog/jeans/?itemid=591
1)キー名が『binary』で終わる場合以外は、ヌルバイトは使用禁止。
2)キー名が『id』で終わる場合は、数値のみを利用。
3)キー名が『path』で終わる場合、URLもしくはファイルなどのパスを指定できる。ただし、日本語使用不可。
4)キー名が『text』で終わる場合、ヌルバイト以外なら何でも使用可。
5)上のどれにも当てはまらない場合、英数字、ピリオド、ハイフン、アンダースコア、スラッシュおよび日本語のみが使用可能。
6)URIに『#』および2つ以上の『?』を含むものを禁止。

(080208 改定)
キー名が『binary』で終わる場合に、ヌルバイトを受け付けるようにした。また、6)の条件を追加した。

coreクラスにおける、該当部分のコードは以下のとおり。
private function forSecurity(){
    // Remove unnecessary cookie settings
    foreach($_COOKIE as $key=>$value) {
        if (strpos($key,_CONF_COOKIEPREFIX)===0) continue;
        unset($_COOKIE[$key]);
        unset($_REQUEST[$key]);
    }
    // Check NULL byte in string.
    self::checkRequest($_REQUEST);
    // Remove $_COOKIE keys in $_REQUEST
    // This is for avoiding bugs due to cookie keys.
    foreach($_COOKIE as $key=>$value) unset($_REQUEST[$key]);
    // Send content-type with character set anyway, to avoid XSS by invalid character like UTF-7.
    @header('Content-Type: text/html; charset=iso-8859-1');
    // MISC
    if (!empty($_SERVER['HTTP_REFERER'])) {
        if (!preg_match('!^(http|https|ftp)://!',$_SERVER['HTTP_REFERER'])) unset($_SERVER['HTTP_REFERER']);
    }    
    if (preg_match('/(#|\?[^\?]*\?)/',$_SERVER['REQUEST_URI'])) {
        exit("<html><body>URI shouldn't contain '#' and 2x'?'. Please check the browser/robot setting.</body></html>");
    }
}
private function checkRequest(&$request,$requestkey=null){
    if (is_array($request)) {
        foreach($request as $key=>&$value) self::checkRequest($value,$requestkey===null?$key:$requestkey);
    } else {
        if (preg_match('/binary$/i',$requestkey)) return;
        elseif (strpos($request,"\0")!==false) exit('Null byte cannot be used.');
        switch(true){
        case preg_match('/text$/i',$requestkey):
            return;
        case preg_match('/id$/i',$requestkey):
            if (is_numeric($request)) return; else break;
        case preg_match('/path$/i',$requestkey):
            if (preg_match('/^([0-9a-zA-Z\x80-\xFF\-_\.:\/\\]*)$/',$request)) return; else break;
        default:
            if (preg_match('/^([0-9a-zA-Z\x80-\xFF\-_\.\/]*)$/',$request)) return; else break;
        }
        exit('Request type mismatch');
    }
}
]]>
Regulations http://www.rad51.net/blog/jeans/?itemid=591 Sun, 03 Feb 2008 16:00:24 PST ITEM591_20080203
デストラクタの利用に関する規約 http://www.rad51.net/blog/jeans/?itemid=558
1)プラグイン

 基本的に、プラグインのデストラクタは、他のプラグインのオブジェクトに依存しないこと。もし依存する場合は、個々のデストラクタ内で適切に処理すること。ただし、ライブラリの各機能は使用可能。

2)ライブラリ(sqlクラス・coreクラスを除く)

 基本的に、ライブラリオブジェクトのデストラクタは、他のライブラリオブジェクトに依存しないこと。もし依存する場合は、個々のデストラクタ内で適切に処理すること。ただし、sqlクラス・coreクラスは利用可能。

3)sqlクラス

 coreクラス以外のライブラリのオブジェクトに依存しないこと。

4)coreクラス

 いかなるオブジェクトにも依存しないこと。

 coreクラスに次のメソッドを用意した。
public function autoload($className){
    $this->loadedClasses[$className]=strtolower($className);
    …略…
}
public function __destruct(){
    self::shutdown($this);
}
static public function shutdown(&$obj){
    static $destructed;
    if (isset($destructed)) return;
    $excluded=strtolower(get_class($obj));
    // Unset objects
    $plugins=$libraries='';
    foreach(self::$obj->loadedClasses as $class=>$lcase){
        if ($lcase==$excluded) continue;
        if (substr($lcase,0,3)=='jp_') $plugins.="$class::\$obj=null;\n";
        elseif ($lcase!='sql') $libraries.="if (isset($class::\$obj)) $class::\$obj=null;\n";
    }
    eval($plugins.$libraries);
    if ($excluded!='sql') sql::$obj=null;
}
ライブラリオブジェクトのデストラクタで、『core::shutdown($this);』を実行するようにする。]]>
Regulations http://www.rad51.net/blog/jeans/?itemid=558 Thu, 10 Jan 2008 12:37:20 PST ITEM558_20080110
規約 http://www.rad51.net/blog/jeans/?itemid=541
1)グローバル変数、グローバル関数は利用しない(スーパーグローバルは除く)。

2)include, require, include_once, require_once は使用しない(index.php, config.php, core.php を除く)。

3)echo, print は使用しない(core.php を除く)。HTMLタブを出力するときは『core::echohtml()』を、タブ以外を出力するときは『echo::p()』を利用する。

4)SQLクエリーを作成するときは、『sql::fill()』もしくは、『sql::query()』の、フィリング機能を利用する。

5)『sqlite_query()』などのデータベース関連関数は直接利用せず、代わりに『sql::query()』などを利用する(sqlite.phpは除く)。

6)SQLiteでクエリー用の関数を作成する場合、原則としてMySQLやPostgreSQLなどでも利用できるものを使う。ただし、SQLiteの機能を最大限に利用するようなプラグインを作成する場合はこの限りではない。

7)プラグイン名は『jp_』から始まり、英数字のみ(アンダースコアは含まない)。『jp_プラグイン名_クラス名』という名のクラスを『jp_プラグイン名_クラス名.php』というファイル名で記述し、このphpファイルをプラグイン管理領域におけば、インクルードはコアが自動的に実行してくれる。

1-4は、セキュリティ関連。134については、この規約に従っても問題なくプログラミングできるような環境はすでにできあがっている。2についてもほぼできあがっていて、ファイルのインクルード=クラスの読み込みととらえることで、__autoload()関数により、自動的にインクルードが行われる。これらの規約に従って書くことで、セキュリティーチェックがずいぶん楽になると思う。

56は、MySQL、PostgreSQLなどの対応を睨んだもの。SQLiteそのものはクエリーの文法がベーシックなので、ほかのデーターベースエンジンへの対応は難しくなさそう。ただ、SQLiteの便利なところは、異なるファイルを用いることで、テーブルごとにデーターベースを分けて使うことが出来ること。MySQLなどでも同様のことが出来るのであるが、レンタルサーバなどで環境に制約がある場合はこういったことは出来ない。SQLiteがあればそれを使うに越したことはないという仕様になると思われる。

]]>
Regulations http://www.rad51.net/blog/jeans/?itemid=541 Wed, 26 Dec 2007 22:45:16 PST ITEM541_20071226