信長の野望・天道 開始

信長の野望・天道をやっとこさ開始した。
野戦とか攻城戦がざっくりしてるのが残念だが、今のところ楽しんでる。
KOEIのユーザー掲示板を見に行くと、たぶんいつも通り文句ばっかりだと思うので、見に行かない。
二回くらいクリアしてから様子見に行ってみよう。
とりあえず姉小路がなくて残念だ。代わりに三木なのかな?

以上

カテゴリー: コンシューマーゲーム | コメントする

[php] オートログイン機能を作る

まあ、クッキーにログイン名とパスワードを覚えさせちゃえば終わりだが、「パスワードまでクッキーに保存するのはセキュリティ的に良くない!」っていう感じらしいので、ちょっと工夫してみる。

○前提
A-1. ユーザはIDを持っており、IDからユーザ情報を取得できる。
A-2. セッションを使える。
A-3. クッキーを使える。
A-4. ユーザ情報はデータベースにある。
A-5. PDOを使える。

○方針
B-1. データベースにオートログイン用のテーブルを作成する。
B-2. 通常のログインが成功したとき、ランダムな文字列を生成してクッキーとオートログイン用テーブルに保存する。
B-3. セッションにユーザIDがあるときはログイン中と見なす。ない時はクッキーに保存されたランダムな文字列からオートログイン用テーブルに保存されたユーザIDを取得する。オートログイン用テーブルからユーザIDを取得できた場合は、セッションにユーザIDを残す。
B-4. ユーザIDを取得できればログインできたことにしてユーザ情報をIDから取得する。

○実装
B-1. データベースにオートログイン用のテーブルを作成する。
※SQLiteの例


CREATE TABLE autokeys (
   id INTEGER PRIMARY KEY,
   cookiekey CHAR(255),
   user_id INTEGER,
   created DEFAULT NULL,
   modified DEFAULT NULL
);

B-2. 通常のログインが成功したとき、ランダムな文字列を生成してクッキーとオートログイン用テーブルに保存する。


define("SHASALT", "marukatuhayatuharisekaiitidatutanodayo");    // eigenvalue for crypt
define("COOKIE_AUTOKEY", "autologinkey");    // cookie name
define("AUTOKEY_TABLE", "autokeys");      // table name of db for autologin
define("USER_KEY", "user_id");            // field name of db to access user's info
define("COOKIE_EXPIRE_AUTOKEY", 60*60*24*10);      // time, in which cookie will be deleted.

/**
 * オートログイン用にランダムな文字列を発行し、クッキーとオートログイン用テーブルに保存する。
 * @param $dbh データベースにアクセスするためのPDOインスタンス
 * @param $user_id オートログイン用テーブルに保存する、ユーザID。
 * @param $autokeyId nullなら新しくユーザIDとクッキーのセットをデータベースに作成する。nullでないなら更新する。
 * @return bool
 */
function set_new_cookiekey(PDO $dbh, $user_id, $autokeyId = null) {
   $newkey = sha1((string)$user_id . SHASALT . mt_rand());
   $time = time();
   if (null === $autokeyId) {
      $sql = "INSERT INTO " . AUTOKEY_TABLE . " (cookiekey, " . USER_KEY . ", created, modified) VALUES(?,?,?,?)";
      $data = array($newkey, $user_id, $time, $time);
   } else {
      $sql = "UPDATE " . AUTOKEY_TABLE . " SET cookiekey=?, modified=? WHERE id=?";
      $data = array($newkey, $time, $autokeyId);
   }
   $retval = false;
   try {
      $stmt = $dbh->prepare($sql);
      $retval = $stmt->execute($data);
   } catch (PDOException $e) {
      // error
   }
   setcookie(COOKIE_AUTOKEY, $newkey, $time + COOKIE_EXPIRE_AUTOKEY);
   return $retval;
}

B-3. セッションにユーザIDがあるときはログイン中と見なす。ない時はクッキーに保存されたランダムな文字列からオートログイン用テーブルに保存されたユーザIDを取得する。オートログイン用テーブルからユーザIDを取得できた場合は、セッションにユーザIDを残す。


define("SESSION_LOGGEDIN", "userid");      // session name
/**
 * セッションまたはオートログイン用データベースからユーザIDを取得する。
 * 
 * @param $dbh データベースにアクセスするためのPDOインスタンス
 * @return mix ユーザIDまたはfalse
 */
function auto_get_user_id(PDO $dbh) {
   session_start();
   // If the session info hasn't been set...
   if (empty($_SESSION[SESSION_LOGGEDIN])) {
      if (!empty($_COOKIE[COOKIE_AUTOKEY])) {
         $cookieLogin = false;
         $sql = "SELECT * FROM " . AUTOKEY_TABLE . " WHERE cookiekey=?";
         try {
            $stmt = $dbh->prepare($sql);
            if ($stmt->execute(array($_COOKIE[COOKIE_AUTOKEY]))) {
               $autokey = $stmt->fetch(PDO::FETCH_ASSOC);
               // got entry
               if ($autokey && count($autokey) > 0) {
                  $_SESSION[SESSION_LOGGEDIN] = $autokey[USER_KEY];
                  // update cookie db
                  set_new_cookiekey($dbh, $autokey[USER_KEY], $autokey['id']);
                  $cookieLogin = true;
               }
            }
         } catch (PDOException $e) {
            // error
         }
         

         if ($cookieLogin) {
            // logged in...
            return $autokey[USER_KEY];
         } else {
            // cannot login...
            // delete cookie
            setcookie(COOKIE_AUTOKEY, "", $time - COOKIE_EXPIRE_AUTOKEY);
            return false;
         }
      } else {
         return false;
      }
   } else {
      return $_SESSION[SESSION_LOGGEDIN];
   }
}

B-4. ユーザIDを取得できればログインできたことにしてユーザ情報をIDから取得する。


function login($name, $pass) {
   $dsn = "sqlite:default.db";
   $pdo = new PDO($dsn);
   
   // auto login check
   $userid = auto_get_user_id($pdo);
   
   if ($userid) {
      // セッションまたはクッキーからログイン
      $user= get_user_by_id($userid);    // ユーザ情報取得関数
   } else {
      // フォームからログイン
      $user= get_user_by_name_and_pass($name, $pass);    // ユーザ情報取得関数
   }
   
   return $user;
}

ここまで書いてなんだけど、これはひどい。後から見て全然分からん。

以上

カテゴリー: PHP | 3件のコメント

最近の出来事 2009/09/11

・一昨日、なぜかブログにつながらなかった。(ずっと待ってたら500エラーが返ってくる)
 Wordpressの再アップロードとかやってみたけど変わらず、あきらめて寝た。ところが起きたら直ってた。
 hetemlがなんかやらかしたとしか思えないが、何か他に原因があるのだろうか。

・finetuneが復活しつぁ!慌ててミスタイプした。ちょっと前までなに再生しようとしても再生されなかったのに、今なにげにアクセスしてみたら普通に再生された。喜ばしすぎる。

・古いゲームをリメイクしている。いつ完成するか分からない。新しい機能を付けないと今更CGIゲームをリメイクする意義がない。なんとかしたい。

・ロストオデッセイをあんまりやれてない。というわけで当分クリアできそうにない。

以上

カテゴリー: 聞いて欲しい独り言 | コメントする

20世紀少年読んだ

24巻もあってめんどくさいので映画で済まそうと思ってた。
でも「原作とは違う結末」ってCMで言ってたので絶望していたところ、全巻を借りることができたので取り急ぎ読んだ。
子供の頃をちょっと懐かしんだが、意外と子供の頃のこと覚えてなくて再び絶望した。
ところで映画でカンナ役誰がやってるんだろうと思って検索したら、三たび絶望した。

以上

カテゴリー: 聞いて欲しい独り言 | コメントする

今日のPythonメモ

1.多次元配列の初期化


hoge = [[0 for j in range(10)] for i in range(5)]

hoge[4][9] = 1

2.intersect


a = [1, 2, 3, 4, 5]
b = [2, 6, 4, 8]

c = list(set(a) & set(b))

以上

カテゴリー: python | コメントする

staticからprivate

これ、なんとなく気持ち悪いからやったこと無かったけど、できるんだなあ。


class PrivateTest {
   private $a = 1;
   
   public static function access($ptest) {
      return $ptest->a;
   }
}
$p = new PrivateTest();
echo PrivateTest::access($p);

1

上記はPHPだがC++でもいける。

追記:
やったこと無いって言うのはうそ。普通にやってた(演算子のオーバーロードとかで)。
PHPで上記のようなことをやろうとしてちょっと不思議に思ってしまった。
同じものを見ていても、見る側の目的意識が変わると違うように感じるものなんだなあ。

以上

カテゴリー: PHP | 4件のコメント

ロストオデッセイ開始

性懲りもなく新しいRPGを始めました。新しいといってもちょっと古いゲームです。
Amazonのレビューがあまりにも賛辞の嵐だったので買うしかなかった。

ちょっとやった感想では、まあ古きよきRPGの雰囲気が。途中で短編小説みたいなのがはさまれて変な雰囲気もありますが。
移動時のダッシュが結構早くて小気味いい。
戦闘はマグナカルタ2で戦闘そのものを楽しんでた後ではちょっと物足りないというか、ちょっとめんどくさいですが慣れればいわゆる昔ながらのRPGスタイルなので問題なくなってくるはず。
でもDVD4枚組みで、正直ちょっとひるんだ。

以上

カテゴリー: コンシューマーゲーム | コメントする

マグナカルタ2 クリア

マグナカルタ2をクリアした。
買い渋ってたけど、やってみたら良作だった。
いつもの通り、簡単に評価したい。

グラフィックはまあ、こんなもん。
ストーリーはまあ、いいと思う。
戦闘システムは結構いい。オリジナリティもあるし、やってて楽しい。インフィニット・アンディスカバリーとちょっと近い感じ。戦闘と移動の切れ目がなくていい。終盤は戦闘パターンが決まってくるけど、それは仕方ないかな。もうちょっと工夫できる余地もありそうではある。
全体的なゲームシステムも悪くないと思う。
キャラクターはちょうどいい感じ。数とかも。あんまり多いと発散しちゃって一人一人が希薄になっちゃうけど、ちょうどいいくらい。
声優は全体的にいい。ヒロインだけがちょっと下手って言うか、正直いまいち。でも平野閣下だから許す。というか許容範囲ではあり、某デストラクションとは比ぶべくもない。
ボリューム感もそこそこ。

というわけでランク付けするとしたらA–。
続編が出たら脊髄反射で購入するレベル。

追記 2009-08-17:
ランクをB++からA–に変えた。なんとなく。

以上

カテゴリー: コンシューマーゲーム | コメントする

マグナカルタ2開始

XBOX360の期待のRPG、マグナカルタ2を開始しました。
1はやったことないけど、まあ大丈夫そう。
戦闘システムはオリジナリティがあるし、戦闘がシームレスなのもいい。
ストーリーも良作っぽい雰囲気はある。
ただ、バンダイナムコのアンケートには失望した。
アクセスキーまで必要なこのアンケートに答えても、壁紙がダウンロードできるだけだった。
25ページもあるアンケート(1ページに複数の設問がある)にがんばって答えたのに。
メールアドレスを入力するところはあったが、メルマガ登録のやつだけだったし。
時間を返せ。

以上

カテゴリー: コンシューマーゲーム | コメントする

ttbaseのtaskext更新

taskextを更新して、メニューに出す項目をiniファイルで設定できるようにした。
自分でもちょっと危険だと思ってたから・・・。

以上

カテゴリー: プログラム | コメントする