<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:admin="http://webns.net/mvcb/"
>
<channel rdf:about="http://driveool.livedoor.biz/">
<title>mylog</title>
<link>http://driveool.livedoor.biz/</link>
<description>Sabel: Open-Source PHP Framework
</description>
<dc:language>ja</dc:language>
<admin:generatorAgent rdf:resource="http://blog.livedoor.com/?v=2.0" />
<items>
 <rdf:Seq>
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51069364.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51068519.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51067810.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51067536.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51066504.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51063695.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51062975.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51059156.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51053759.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51053455.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51051031.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51050881.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51047874.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51047842.html" />
  <rdf:li rdf:resource="http://driveool.livedoor.biz/archives/51047343.html" />
 </rdf:Seq>
</items>
</channel>

<item rdf:about="http://driveool.livedoor.biz/archives/51069364.html">
<title>Sabel JS - DatePicker(Sabel.Widget.Calendar)</title>
<link>http://driveool.livedoor.biz/archives/51069364.html</link>
<description>Sabel 1.1で追加されるSabel.Widget.Calendarのサンプル。

カレンダーで日付を選択し、その選択された日付をインプットに適用するDatePicker.jsを書いてみた。


DatePicker.js

function datepicker(inputs) {
  Sabel.Array.each(inputs, function(input) {
    ...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-05T00:32:25+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[Sabel 1.1で追加されるSabel.Widget.Calendarのサンプル。<br/>
<br/>
カレンダーで日付を選択し、その選択された日付をインプットに適用するDatePicker.jsを書いてみた。

<pre class="box">
DatePicker.js

function datepicker(inputs) {
  Sabel.Array.each(inputs, function(input) {
    var div = document.createElement("div");
    div.style.position = "absolute";
    div.style.zIndex = 100;
    document.body.appendChild(div);
    
    var self = {
      element: Sabel.get(input),
      calendar: new Sabel.Widget.Calendar(div, {
        callback: function(date) {
          self.element.value = date.join("-");
        }
      }),
      render: function() {
        self.calendar.render();
      }
    };
    
    div.style.top  = Sabel.Element.getCumulativeTop(self.element)  + "px";
    div.style.left = Sabel.Element.getCumulativeLeft(self.element) + "px";
    
    self.calendar.WeekDays = ["日", "月", "火", "水", "木", "金", "土"];
    self.element.observe("mousedown", self.render);
  });
}
</pre>

インプットのidをdatepicker()関数に渡すだけで使用できる（簡単に使えるようにしているため、任意のタイミングでカレンダーを消すなどの処理はできない）。インプットをクリックすると、そのインプットの位置にカレンダーが表示され、日付をクリックするとインプットに年-月-日が入る。

<pre class="box">
&lt;script type="text/javascript" src="Sabel.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="DatePicker.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript"&gt;
  new Sabel.Event(window, "load", function() {
    datepicker(["inputid1", "inputid2", ...]);
  });
&lt;/script&gt;
</pre>

動作の様子は<a href="http://driveool.livedoor.biz/smpl/datepicker.html" target="_blank">こちら</a>。<br/>
* 実際にサンプルのように表示するにはSabelに含まれるcssや画像が必要<br/>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51068519.html">
<title>Internet Explorerではこのページは表示できません</title>
<link>http://driveool.livedoor.biz/archives/51068519.html</link>
<description>JavaScriptを使用していて「Internet Explorerではこのページは表示できません」と出ることがある。IEがDOMの構築を終える前にDOM操作などを行おうとする場合にこうなったりならなかったり。

とりあえず、window.onloadイベントのリスナーで処理すれば安全な様子。


n...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-04T00:37:43+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[JavaScriptを使用していて「Internet Explorerではこのページは表示できません」と出ることがある。IEがDOMの構築を終える前にDOM操作などを行おうとする場合にこうなったりならなかったり。<br/>
<br/>
とりあえず、window.onloadイベントのリスナーで処理すれば安全な様子。

<pre class="box">
new Sabel.Event(window, "load", function(){
  // process
});
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51067810.html">
<title>grep | sed</title>
<link>http://driveool.livedoor.biz/archives/51067810.html</link>
<description>以下のような実行ログから失敗したid(\[\d+\]の部分)を抽出する。


20080701 15:20:01 SUCCESS: username [10502]
20080701 18:14:41 FAILURE: username [3821]
20080702 08:39:22 SUCCESS: username [9134]
20080702 14:43:52 FAILURE: username [6810]
20080702 21...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-03T00:56:26+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[以下のような実行ログから失敗したid(\[\d+\]の部分)を抽出する。

<pre class="box">
20080701 15:20:01 SUCCESS: username [10502]
20080701 18:14:41 FAILURE: username [3821]
20080702 08:39:22 SUCCESS: username [9134]
20080702 14:43:52 FAILURE: username [6810]
20080702 21:11:05 SUCCESS: username [8819]
20080703 08:31:34 SUCCESS: username [13266]
...
</pre>

grepで失敗の行を取り出してsedに渡す。<br/>
結果をfailures.phpに出力。

<pre class="box">
grep FAILURE some.log | sed -e 's/^.*\[\([0-9]*\)\]/\1 => 1,/' > failures.php
</pre>

こんな感じになる。

<pre class="box">
3821 => 1,
6810 => 1,
...
</pre>

ちょっと付け足してphpの配列にする。<br/>
使用する側のプログラムではissetでチェックしたいのでこの形式に。<br/>
in_array()だと遅い。

<pre class="box">
&lt;?php

$failures = array(
3821 => 1,
6810 => 1,
...
);

...

if (!isset($failures[$targetId])) {
  // process
}
</pre>

キャプチャに使う括弧をバックスラッシュでエスケープする必要がある。<br/>
これに少しはまった。
]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51067536.html">
<title>Sabel 1.1 Release Announcement</title>
<link>http://driveool.livedoor.biz/archives/51067536.html</link>
<description>Sabel-1.1のリリースが7/7(月)に決定しました。
概要は以下の通りです。

(Core)Sabel::using()でクラスファイルを読み込めたかどうかに応じてbool値を返すように変更
(Function)get_temp_dir()関数追加
(Function)md5hash()関数追加
(Function)remove_nullbyte()関数...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-07-02T01:07:50+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[Sabel-1.1のリリースが7/7(月)に決定しました。<br/>
概要は以下の通りです。

<ul><li>(Core)Sabel::using()でクラスファイルを読み込めたかどうかに応じてbool値を返すように変更
</li><li>(Function)get_temp_dir()関数追加
</li><li>(Function)md5hash()関数追加
</li><li>(Function)remove_nullbyte()関数追加
</li><li>(DI)DIコンテナ追加
</li><li>(Aspect)Aspect追加(AOPアライアンス準準拠)
</li><li>(Mail)メール(送信/Mimeデコード)追加
</li><li>(Http)HTTPクライアント追加
</li><li>(Annotation)バックスラッシュによるクオートのエスケープに対応
</li><li>(Response)設計の改善・ステータスオブジェクト追加
</li><li>(Request-Validator)一つの入力に対し複数のバリデーションメソッドを登録できるように改善
</li><li>(Controller-Redirector)外部サイトにリダイレクトする際などに使用するurl()メソッドが正常に動作しない問題の修正
</li><li>(View-Pager)実装の改善(3割程度の高速化)
</li><li>(View-PageViewer)実装のスリム化(setPriorityPrevious(), setPriorityNext(), setIgnoreEmpty()メソッド削除)
</li><li>(Session-Memcache)createメソッドでポート番号を指定できるように改善, addServer()メソッド追加
</li><li>(Storage-Memcache)addServer()メソッド追加
</li><li>(Cache-Memcache)addServer()メソッド追加
</li><li>(Util-FileSystem)Sabel_Util_FileSystemによりディレクトリやファイルを作成する際のデフォルトのパーミッションを744から755に変更
</li><li>(DB)バイナリデータ(画像・ファイル)の保存・取得に対応
</li><li>(DB)行のバージョニング(楽観的ロック)に対応
</li><li>(DB)sabel.db.mssql(Microsoft SQL Server)パッケージの追加
</li><li>(DB)Sabel_DB_Modelの各メソッドに対するコールバックの対応が変更
</li><li>(DB)Joinオブジェクト使用時のカラムの指定を可能に改善
</li><li>(DB-Model)selectWithChildrenメソッドを削除
</li><li>(DB-Model)save()メソッドによりモデルの状態をデータベースに反映する際、プライマリキーの値が変更されている場合に例外を投げるように変更
</li><li>(Test)Sabel_Test_Fixtureクラス追加
</li><li>(Processor-Action)リクエストバリデーションがURIクエリに対応
</li><li>(Processor-Session)session.use_trans_sidがOnかつクライアントがCOOKIEを無効にしている時にセッションIDが2重に付加される問題の修正, セッションが開始されていない際にリンクやリダイレクト先URIにセッション名が付加される問題の修正
</li><li>(JS)Sabel.Environment追加
</li><li>(JS)Sabel.Class追加
</li><li>(JS)Sabel.KeyEvent追加
</li><li>(JS)Sabel.Number追加
</li><li>(JS)Ajaxアップローダ追加(apc必須)
</li><li>(JS)Dateピッカー(カレンダー)追加
</li><li>(JS)ElementにgetRegion(), replaceClass()メソッド追加
</li><li>(JS)Sabel.Util.UriをSabel.Uriに変更
</li><li>(JS)Element.getDimentionsメソッドのバグ修正
</li><li>(JS)Effectのバグ修正
</li><li>(JS)要素の絶対位置取得メソッドのバグ修正
</li><li>(JS)現在のスクロール量取得メソッド追加
</li><li>(JS)Stringクラスの大幅な改善(sprintf, htmlspecialchars, chr, repeat追加など)
</li><li>(JS)Ajaxのオプションにtimeout, scope追加
</li><li>(JS)Eventにscope追加
</li><li>(JS)widget.Overlayの改善(Widget.Overlayにリネーム)
</li><li>(Task)各種ジェネレータ追加
</li><li>(Task)バッチ実行ファイル(sabel.php)で正常なアプリケーションルートパスが定義されない問題の修正
</li><li>(Addon-Form)Formオブジェクトが保持するHTMLを書き出すオブジェクトの初期化に不具合があったのを修正, モデルにバージョンカラムがある場合にclose()メソッドで&lt;/form&gt;タグとともにバージョン値をhiddenで書き出すように対応
</li><li>(Addon-Renderer)ショートタグ形式の場合にHTMLエスケープするようにSabelレンダラを改善, SabelレンダラのHTMLタグを抜き出す正規表現を最小マッチに変更
</li><li>(Lib-Paginate)setOrderColumn()メソッドをsetOrderColumns()に変更, setDefaultOrder()メソッド追加, uriの指定を省略可能に改善
</li><li>rewriteモジュールがロードされていない場合にInternal Server Errorになる問題の修正
</li><li>Scaffold(sabelコマンド)にlangオプション(ja)追加
</li><li>$_SERVER["HTTP_HOST"]を参照している箇所を$_SERVER["SERVER_NAME"]を参照するように変更
</li></ul>

<br/>

&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.sabel.jp/"><img src="http://image.blog.livedoor.jp/driveool/imgs/3/a/3af945b1.gif" border="0" alt="Powered by Sabel" title="Powered by Sabel" class="pict" /></a>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51066504.html">
<title>Apache - Basic Authentication</title>
<link>http://driveool.livedoor.biz/archives/51066504.html</link>
<description>簡単に済ませたいとき、たまに使うBasic認証。「たまに」なのでいつも忘れる。

パスワードファイル作成。

$ htpasswd -c /usr/local/www/data/myapp/config/.htpasswd username
New password: [enter password]
Re-type new password: [enter password]
Adding pass...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-30T19:50:25+09:00</dc:date>
<dc:subject>Server</dc:subject>
<content:encoded><![CDATA[簡単に済ませたいとき、たまに使うBasic認証。「たまに」なのでいつも忘れる。<br/>
<br/>
パスワードファイル作成。
<pre class="box">
$ htpasswd -c /usr/local/www/data/myapp/config/.htpasswd username
New password: [enter password]
Re-type new password: [enter password]
Adding password for user username
</pre>

http.confに設定を追加する。

<pre class="box">
&lt;Directory "/usr/local/www/data/myapp/"&gt;
    AuthType Basic
    AuthName "Private Area"
    AuthUserFile /usr/local/www/data/myapp/config/.htpasswd
    Require valid-user
&lt;/Directory&gt;
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51063695.html">
<title>Quoted-Printable Encode/Decode</title>
<link>http://driveool.livedoor.biz/archives/51063695.html</link>
<description>phpにquoted_printable_decode()関数はあるけど、quoted_printable_encode()関数はないので、エンコードは次のように行う(mb拡張があればmb_encode_mimeheader()でQエンコーディング使えば良い)。


$fp = fopen(&quot;php://temp&quot;, &quot;r+&quot;);

stream_filter_appand($fp, &quot;conv...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-26T23:21:08+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[phpにquoted_printable_decode()関数はあるけど、quoted_printable_encode()関数はないので、エンコードは次のように行う(mb拡張があればmb_encode_mimeheader()でQエンコーディング使えば良い)。<br/>

<pre class="box">
$fp = fopen("php://temp", "r+");

stream_filter_appand($fp, "convert.quoted-printable-encode",
                     STREAM_FILTER_READ,
                     array("line-length" => 74,
                           "line-break-chars" => "\r\n")
                    );

fputs($fp, $str);
rewind($fp);
$encoded = stream_get_contents($fp);
fclose($fp);
</pre>

多くのMUAがヘッダに含まれるアンダースコアをスペースに変換する(ボディのアンダースコアはそのまま)。変換するMUAは、確認したところで、Outlook Express6, Thunderbird, Mail, Becky, Sylpheed, Eudora, Entourage。変換しないMUAはShuriken。<br/>
<br/>
変換したりしなかったりなので、ヘッダでもボディでも、とにかくアンダースコアは=5Fに変換しておけば良い。

<pre class="box">
$encoded = str_replace("_", "=5F", $encoded);
</pre>

デコード時は、先程挙げた多くのMUAと同様、ヘッダの場合にのみアンダースコアをスペースに変換する。=5Fはquoted_printable_decode()関数がアンダースコアに変換するので、気にしなくて良い。

<pre class="box">
if ($isHeader) {
  $str = str_replace("_", " ", $str);
}

$decoded = quoted_printable_decode($str);
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51062975.html">
<title>response headers in the download script</title>
<link>http://driveool.livedoor.biz/archives/51062975.html</link>
<description>日本語ファイル名のファイルをダウンロードさせる場合、少しブラウザ(ユーザエージェント)を気にする必要がある。

Safariはサーバ側でどうにもできないため、ダウンロードリンクの最後(ファイル名として扱われる)をファイル名をURLデコードしたものにする。


&amp;lt;a hr...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-25T23:33:25+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[日本語ファイル名のファイルをダウンロードさせる場合、少しブラウザ(ユーザエージェント)を気にする必要がある。<br/>
<br/>
Safariはサーバ側でどうにもできないため、ダウンロードリンクの最後(ファイル名として扱われる)をファイル名をURLデコードしたものにする。

<pre class="box">
&lt;a href="/dlscript/&lt;?php echo urlencode($filename) ?&gt;"&gt;
  &lt;?php echo htmlentities($filename, ENT_QUOTES) ?&gt;
&lt;/a&gt;
</pre>

サーバ側では、IEの場合にヘッダに付加するファイル名をShift-JISに変換する。Safariの場合はヘッダにファイル名を付加しない(付加すると文字化けする)。

<pre class="box">
$filename = urldecode($filename);
$path = "/path/to/" . $filename;

header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($path));

$ua = (isset($_SERVER["HTTP_USER_AGENT"])) ? $_SERVER["HTTP_USER_AGENT"] : "unknown";
if (strpos($ua, "MSIE") !== false) {
  $filename = mb_convert_encoding($filename, "SJIS", "UTF-8");
}
      
if (strpos($ua, "Safari") === false) {
  header("Content-Disposition: attachment; filename="' . $filename . '"');
} else {
  header("Content-Disposition: attachment");
}
      
echo file_get_contents($path);
</pre>

以下のブラウザで文字化けすることなくダウンロードできることを確認。

<ul>
  <li>Windows: IE6, IE7, Firefox2, Opera9.?, Safari3</li>
  <li>Linux: Firefox2, Opera9.?</li>
  <li>Mac: Firefox3, Opera9.?, Safari3</li>
</ul>
]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51059156.html">
<title>mailtoを使用する際のスパム対策</title>
<link>http://driveool.livedoor.biz/archives/51059156.html</link>
<description>HTMLでメールアドレスを素で書くとスパムロボットに拾われるため、JavaScriptを使ったスパム対策をする。

今回利用したスクリプトがこちらで、ほんの少し改造して使いやすくした。

使い方はCryptMailto.jsを読み込み、idを振った空のタグを用意し、popup_mailer()関数...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-20T23:49:17+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[HTMLでメールアドレスを素で書くとスパムロボットに拾われるため、JavaScriptを使ったスパム対策をする。<br/>
<br/>
今回利用したスクリプトが<a href="http://www.csg.is.titech.ac.jp/~yanagisawa/Sites/javascript/caesarAddress2.html" target="_blank">こちら</a>で、ほんの少し改造して使いやすくした。<br/>
<br/>
使い方はCryptMailto.jsを読み込み、idを振った空のタグを用意し、popup_mailer()関数にアカウント名・ドメイン名・idを渡す。<br/>
<br/>

例えばHTMLは次のようになる(ソース上にメールアドレスが現れない)。

<pre class="box">
&lt;p&gt;
  お問い合わせ先: &lt;span id="info"&gt&lt;/span&gt;
&lt;/p&gt;

&lt;script type="text/javascript" src="/js/CryptMailto.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
  popup_mailer("info", "example.com", "info");
&lt;/script&gt;
</pre>

サンプルは<a href="/smpl/crypt_mailto.html" target="_blank">こちら</a>で。

]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51053759.html">
<title>Javascript - mouseover, mouseout</title>
<link>http://driveool.livedoor.biz/archives/51053759.html</link>
<description>Javascriptでdivなどのmouseoverやmouseoutイベントを扱う際、そのdivが他の要素を内包していると厄介な挙動をする。







&amp;lt;div id=&quot;a&quot; onmouseover=&quot;alert('over');&quot; onmouseout=&quot;alert('out');&quot;&amp;gt;
  &amp;lt;div id=&quot;b&quot;&amp;gt;
    &amp;lt;div id=&quot;c&quot;&amp;gt;&amp;lt;/div&amp;g...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-15T14:14:31+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[Javascriptでdivなどのmouseoverやmouseoutイベントを扱う際、そのdivが他の要素を内包していると厄介な挙動をする。<br/>
<br/>

<div>
<img src="http://image.blog.livedoor.jp/driveool/imgs/8/a/8a8efd86.gif" width="167" height="141" border="0" alt="div3" hspace="5" class="pict" />
</div>

<pre class="box">
&lt;div id="a" onmouseover="alert('over');" onmouseout="alert('out');"&gt;
  &lt;div id="b"&gt;
    &lt;div id="c"&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</pre>

例えば上記のように、a内にbがあり、b内にcがある状態で、aのmouseover, mouseoutイベントでアラートを表示すると、マウスがb上に移動すると一度outし直後に再びoverする。c上に移動した時も同様。<br/>
<br/>
IEでは以前からonmouseenterやonmouseleaveがあるようで、これを使うとbやcは関係なく、aに入った時と出た時だけイベントが発生してくれる。<br/>
他のブラウザでも同様の振る舞いを実現するにはそれ用の実装をする必要があるが、Sabel JS(Sabel 1.1以降)だと以下のようにできる。

<pre class="box">
&lt;div id="a"&gt;
  &lt;div id="b"&gt;
    &lt;div id="c"&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;script type="text/javascript"&gt;
  var a = Sabel.get("a");
  a.observe("mouseenter", function(){ alert('over'); });
  a.observe("mouseleave", function(){ alert('out');  });
&lt;/script&gt;
</pre>

動作の様子は<a href="http://driveool.livedoor.biz/smpl/smpl1.html">こちら</a>で。]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51053455.html">
<title>mysql - skip-show-database</title>
<link>http://driveool.livedoor.biz/archives/51053455.html</link>
<description>MySQLでのSHOW DATABASESコマンド権限の管理。

バージョンの表示と、テスト用データベース'sample'の作成。

$ mysql -u root

mysql&amp;gt; SELECT VERSION();
+------------+
| VERSION()  |
+------------+
| 5.0.51-log | 
+------------+
1 row in set (0.00 ...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-13T18:47:52+09:00</dc:date>
<dc:subject>Database</dc:subject>
<content:encoded><![CDATA[MySQLでのSHOW DATABASESコマンド権限の管理。<br/>
<br/>
バージョンの表示と、テスト用データベース'sample'の作成。
<pre class="box">
$ mysql -u root

mysql&gt; SELECT VERSION();
+------------+
| VERSION()  |
+------------+
| 5.0.51-log | 
+------------+
1 row in set (0.00 sec)

mysql> CREATE DATABASE sample;
Query OK, 1 row affected (0.00 sec)
</pre>

fooユーザを作成し、SELECTのみ許可する。

<pre class="box">
$ mysql -u root

mysql&gt; GRANT Select ON *.* TO foo@localhost;
Query OK, 0 rows affected (0.00 sec)

mysql&gt; SELECT * FROM mysql.user WHERE `User` = 'foo'\G
*************************** 1. row ***************************
                 Host: localhost
                 User: foo
             Password: 
          Select_priv: Y
          Insert_priv: N
          Update_priv: N

          ...

         Show_db_priv: N
           Super_priv: N

          ...

1 row in set (0.00 sec)
</pre>

fooユーザにShow_dbの権限は無いはずなのに、SHOW DATABASESコマンドが実行でき、全てのデータベースが見れてしまう。

<pre class="box">
$ mysql -u foo

mysql&gt; SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mysql              | 
| sample             | 
| test               | 
+--------------------+
4 rows in set (0.00 sec)
</pre>

fooユーザを再作成し、'sample'データベースでのSELECTのみ許可する。

<pre class="box">
$ mysql -u root

mysql&gt; DELETE FROM mysql.user WHERE `User` = 'foo';
Query OK, 1 row affected (0.00 sec)

mysql&gt; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

mysql&gt; GRANT Select ON sample.* TO foo@localhost;
Query OK, 0 rows affected (0.00 sec)
</pre>

先程と同様fooユーザにShow_dbの権限は無く、SHOW DATABASESコマンドも実行できる。しかし、権限の無い'mysql'データベースは見えなくなる。('information_schema'や'test'が見えるのはよくわからない。)

<pre class="box">
$ mysql -u foo

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| sample             | 
| test               | 
+--------------------+
3 rows in set (0.00 sec)
</pre>

次に、my.cnfに'skip-show-database'を追加し、mysqlを再起動する。

<pre class="box">
$ vi /path/to/my.cnf

[mysqld]

...

skip-show-database

...
</pre>

fooユーザでSHOW DATABASESコマンドを実行すると、拒否するようになったことが分かる。'skip-show-database'がONで、Show_db権限がない場合に、SHOW DATABASESコマンドは拒否される模様。

<pre class="box">
$ mysql -u foo

mysql&gt; SHOW DATABASES;
ERROR 1227 (42000): Access denied; you need the SHOW DATABASES privilege for this operation
</pre>

確認のために、Show_db権限をfooユーザに与える。

<pre class="box">
$ mysql -u root

mysql&gt; UPDATE mysql.user SET Show_db_priv = 'Y' WHERE `User` = 'foo';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
</pre>

SHOW DATABASESコマンドを実行すると、全データベースが表示される。

<pre class="box">
$ mysql -u foo

mysql&gt; SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mysql              | 
| sample             | 
| test               | 
+--------------------+
4 rows in set (0.00 sec)
</pre>

一般ユーザはSHOW DATABASESコマンドは必要ない(自分が使用するデータベースだけ知っていればいい)ので、'skip-show-database'は常にONにしておいたほうが良さそう。で、Show_db権限は与えないこと。<br/>
<br/>
SHOW PROCESSLISTやSHOW VARIABLESとかも禁止にするにはどうするんだろう。小一時間情報を探してみたけれど、わからなかった。できないのかもしれない。]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51051031.html">
<title>Thunderbird - Sorting messages by Thread</title>
<link>http://driveool.livedoor.biz/archives/51051031.html</link>
<description>Thunderbirdでスレッド表示すると、同じ件名だと全く関係ないメールでもスレッド化してしまうので、それの対処。

以下の作業をする前に、Thunderbirdを閉じておく。

ホームディレクトリ以下のどこかにある、prefs.jsを変更する。
Windowsだと次のようなパスにある。
...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-11T03:43:37+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[Thunderbirdでスレッド表示すると、同じ件名だと全く関係ないメールでもスレッド化してしまうので、それの対処。<br/>
<br/>
以下の作業をする前に、Thunderbirdを閉じておく。<br/>
<br/>
ホームディレクトリ以下のどこかにある、prefs.jsを変更する。<br/>
Windowsだと次のようなパスにある。<br/>

<pre class="box">
C:\Documents and Settings\user\Application Data\Thunderbird\Profiles\xxxxx.default\prefs.js
</pre>

Linuxだと次のようなパスにある。<br/>

<pre class="box">
/home/user/.thunderbird/xxxxx.default/prefs.js
</pre>

prefs.jsに以下の一行を追加。<br/>

<pre class="box">
user_pref("mail.thread_without_re", false);
</pre>

この&quot;xxxxx.default&quot;ディレクトリの下の、MailやImapMailディレクトリ内の*.msfファイル(インデックスファイル)を削除する。<br/>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51050881.html">
<title>Postfix - pass a mail to the php script</title>
<link>http://driveool.livedoor.biz/archives/51050881.html</link>
<description>ある特定のユーザ、もしくはドメイン宛のメールをPHPに渡す場合のPostfixの設定。

まず、transportの設定をする。全ユーザの場合はドメイン名だけで良い。

$ vi /etc/postfix/transport

user@example.com phpscript:
# example.com phpscript:


main.cfでこの...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-10T11:33:10+09:00</dc:date>
<dc:subject>Server</dc:subject>
<content:encoded><![CDATA[ある特定のユーザ、もしくはドメイン宛のメールをPHPに渡す場合のPostfixの設定。<br/>
<br/>
まず、transportの設定をする。全ユーザの場合はドメイン名だけで良い。
<pre class="box">
$ vi /etc/postfix/transport

user@example.com phpscript:
# example.com phpscript:
</pre>

main.cfでこのファイルを指定する。

<pre class="box">
$ vi /etc/postfix/transport

transport_maps = hash:/etc/postfix/transport
</pre>

postmapコマンドでtransport.dbを更新する。

<pre class="box">
$ /usr/sbin/postmap /etc/postfix/transport
</pre>

master.cfで&quot;phpscript&quot;サービスの設定をする。

<pre class="box">
$ vi /etc/postfix/master.cf

phpscript unix  -      n      n      -      -      pipe
  flags= user=nobody argv=/path/to/php /path/to/script.php
</pre>

postfixを再起動する。

<pre class="box">
$ /etc/init.d/postfix restart
</pre>

phpではstdinからメールのソースを取得できる。

<pre class="box">
$ vi /path/to/script.php

&lt;?php

$mail = file_get_contents(&quot;php://stdin&quot;);
</pre>
]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51047874.html">
<title>Use sequence in each database</title>
<link>http://driveool.livedoor.biz/archives/51047874.html</link>
<description>MySQLはカラムをAUTO_INCREMENTで定義すれば、新規連番を振ってくれる。振られた連番はLAST_INSERT_ID()関数で取得できる。


CREATE TABLE foo
(
  id INTEGER PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(24) NOT NULL
)

-------------------------------------...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-09T02:26:36+09:00</dc:date>
<dc:subject>Database</dc:subject>
<content:encoded><![CDATA[MySQLはカラムをAUTO_INCREMENTで定義すれば、新規連番を振ってくれる。振られた連番はLAST_INSERT_ID()関数で取得できる。

<pre class="box">
CREATE TABLE foo
(
  id INTEGER PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(24) NOT NULL
)

-------------------------------------------

mysql_query("INSERT INTO foo(name) VALUES('test')", $conn);
$res = mysql_query("SELECT LAST_INSERT_ID() AS id", $conn);
$row = mysql_fetch_assoc($res);
var_dump($row["id"]);
</pre>

PostgreSQLはカラムをSERIAL、またはBIGSERIALで定義すれば、新規連番を振ってくれる。振られた連番はLASTVAL()関数で取得できる。

<pre class="box">
CREATE TABLE foo
(
  id SERIAL NOT NULL,
  name VARCHAR(24) NOT NULL
)

-------------------------------------------

pg_query($conn, "INSERT INTO foo(name) VALUES('test')");
$res = pg_query($conn, "SELECT LASTVAL() AS id");
$row = pg_fetch_assoc($res);
var_dump($row["id"]);
</pre>

SQLiteはカラムを&quot;INTEGER PRIMARY KEY&quot;または&quot;INTEGER NOT NULL PRIMARY KEY&quot;で定義すれば、新規連番を振ってくれる。振られた連番はPDOのlastInsertId()メソッドで取得できる。

<pre class="box">
CREATE TABLE foo
(
  id INTEGER PRIMARY KEY,
  name VARCHAR(24) NOT NULL
)

-------------------------------------------

$stmt = $pdo->prepare("INSERT INTO foo(name) VALUES('test')");
$stmt->execute();
var_dump($pdo->lastInsertId());
</pre>

Firebirdではシーケンス(旧ジェネレータ)を作成し、GEN_ID()関数にそのシーケンス名を渡し新規連番を取得する。その値でINSERTする。

<pre class="box">
CREATE TABLE FOO
(
  ID INTEGER NOT NULL PRIMARY KEY,
  NAME VARCHAR(24) NOT NULL
)

CREATE SEQUENCE FOO_ID_SEQ;

-------------------------------------------

$res = ibase_query($conn, 'SELECT GEN_ID(FOO_ID_SEQ, 1) AS ID FROM RDB$DATABASE');
$row = ibase_fetch_assoc($res);
$lastId = $row["ID"];
ibase_query($conn, "INSERT INTO FOO(ID, NAME) VALUES({$lastId}, 'test')");
var_dump($lastId);
</pre>

Oracleではシーケンスオブジェクトを作成し、NEXTVALにより新規連番を取得する。その値でINSERTする。

<pre class="box">
CREATE TABLE FOO
(
  ID INTEGER NOT NULL PRIMARY KEY,
  NAME VARCHAR(24) NOT NULL
)

CREATE SEQUENCE FOO_ID_SEQ;

-------------------------------------------

$stmt = oci_parse($conn, "SELECT FOO_ID_SEQ.NEXTVAL AS ID FROM DUAL");
oci_execute($stmt, OCI_COMMIT_ON_SUCCESS);
$row = oci_fetch_assoc($stmt);
$lastId = $row["ID"];
$stmt = oci_parse($conn, "INSERT INTO FOO(ID, NAME) VALUES({$lastId}, 'test')");
oci_execute($stmt, OCI_COMMIT_ON_SUCCESS);
var_dump($lastId);
</pre>

SQL ServerはカラムをIDENTIFYで定義すれば、新規連番を振ってくれる。振られた連番はSCOPE_IDENTITY()関数で取得できる。

<pre class="box">
CREATE TABLE foo
(
  id INTEGER IDENTITY(1, 1) NOT NULL,
  name VARCHAR(24) NOT NULL
)

-------------------------------------------

mssql_query("INSERT INTO foo(name) VALUES('test')", $conn);
$res = mssql_query("SELECT SCOPE_IDENTITY() AS id", $conn);
$row = mssql_fetch_assoc($res);
var_dump($row["id"]);
</pre>]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51047842.html">
<title>php - cloning an object</title>
<link>http://driveool.livedoor.biz/archives/51047842.html</link>
<description>あるクラスの多くのインスタンスを必要とする時、newでそれぞれのインスタンスを生成するよりも、一つのインスタンスを複製(クローン)した方がパフォーマンスが良い。


class Foo
{
  public $obj = null;
  public $var = &quot;foo&quot;;
  
  public function __construct...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-08T00:36:20+09:00</dc:date>
<dc:subject>PHP</dc:subject>
<content:encoded><![CDATA[あるクラスの多くのインスタンスを必要とする時、newでそれぞれのインスタンスを生成するよりも、一つのインスタンスを複製(クローン)した方がパフォーマンスが良い。<br/>

<pre class="box">
class Foo
{
  public $obj = null;
  public $var = "foo";
  
  public function __construct()
  {
    $obj = new stdClass();
    $obj-&gt;a = 10;
    $obj-&gt;b = 20;
    
    $this-&gt;obj = $obj;
  }
}
</pre>

まずは一つ一つ、それぞれnewでインスタンスを生成する。

<pre class="box">
$objs = array();
$start = microtime();
for ($i = 0; $i &lt; 10000; $i++) {
  $objs[] = new Foo();
}

var_dump(microtime() - $start);
var_dump(memory_get_peak_usage(true));
</pre>

上記コードの所要時間と使用メモリ量。

<pre class="box">
float(0.0505634)  // 50.6 msec
int(6553600)  // 6554 KB
</pre>

次は最初にインスタンスを生成し、それを複製する。

<pre class="box">
$objs = array();
$start = microtime();
$foo = new Foo();
for ($i = 0; $i &lt; 10000; $i++) {
  $objs[] = clone $foo;
}

var_dump(microtime() - $start);
var_dump(memory_get_peak_usage(true));
</pre>

結果、所要時間は先程の半分以下、メモリ使用量は約半分になる。

<pre class="box">
float(0.019881)   // 19.9 msec
int(3407872)  // 3408 KB
</pre>

メモリ使用量が減るのは、それぞれのインスタンスが保持する$objが同じオブジェクトを参照しているため。以下のコードを実行することでそれを確認できる。

<pre class="box">
$foo  = new Foo();
$foo2 = clone $foo;

$foo2->var = "bar";
$foo2->obj->a = 100;
$foo2->obj->b = 200;

var_dump($foo-&gt;var);   // "foo"
var_dump($foo2-&gt;var);  // "bar"

var_dump($foo->obj-&gt;a);   // 100
var_dump($foo2->obj-&gt;a);  // 100

var_dump($foo->obj-&gt;b);   // 200
var_dump($foo2->obj-&gt;b);  // 200
</pre>

この挙動だと困る場合は__clone()メソッド(クローンの時にコールされるマジックメソッド)を実装し、内部のオブジェクトも複製する。

<pre class="box">
class Foo
{
  ...
  
  public function __clone()
  {
    $this->obj = clone $this->obj;
  }
}
</pre>

<pre class="box">
$foo  = new Foo();
$foo2 = clone $foo;

$foo2->var = "bar";
$foo2->obj->a = 100;
$foo2->obj->b = 200;

var_dump($foo-&gt;var);   // "foo"
var_dump($foo2-&gt;var);  // "bar"

var_dump($foo->obj-&gt;a);   // 10
var_dump($foo2->obj-&gt;a);  // 100

var_dump($foo->obj-&gt;b);   // 20
var_dump($foo2->obj-&gt;b);  // 200
</pre>

ただ、これだと一つ一つインスタンスを生成するのとそう変わらない。

<pre class="box">
float(0.0442957)  // 44.3 msec
int(6029312)  // 6030 KB
</pre>

使えるところでは使ったほうが吉。<br/>
ただ、「使えるところ」はあまりないかも。]]>
</content:encoded>
</item>
<item rdf:about="http://driveool.livedoor.biz/archives/51047343.html">
<title>Install Java on Linux</title>
<link>http://driveool.livedoor.biz/archives/51047343.html</link>
<description>Linux(CentOS, Fedora)にSunのJavaをインストールする。

インストールする前はこんな感じ。

$ java -version
java version &quot;1.7.0&quot;
IcedTea Runtime Environment (build 1.7.0-b21)
IcedTea Server VM (build 1.7.0-b21, mixed mode)




JDKをhttp://java.sun...</description>
<dc:creator>driveool</dc:creator>
<dc:date>2008-06-06T14:40:12+09:00</dc:date>
<dc:subject>Others</dc:subject>
<content:encoded><![CDATA[Linux(CentOS, Fedora)にSunのJavaをインストールする。<br/>
<br/>
インストールする前はこんな感じ。<br/>
<pre class="box">
$ java -version
java version "1.7.0"
IcedTea Runtime Environment (build 1.7.0-b21)
IcedTea Server VM (build 1.7.0-b21, mixed mode)
</pre>

<br/>

JDKを<a href="http://java.sun.com/javase/ja/6/download.html" target="_blank">http://java.sun.com/javase/ja/6/download.html</a>の辺りからダウンロードしてくる。<br/>
<br/>

・インストールする
<pre class="box">
$ chmod +x jdk-6u6-linux-i586-rpm.bin
$ sudo ./jdk-6u6-linux-i586-rpm.bin
</pre>

・環境変数の設定
<pre class="box">
$ vi /etc/profile.d/java.sh

#!/bin/sh

export JAVA_HOME="/usr/java/jdk1.6.0_06"
export JAVA_PATH="$JAVA_HOME"
export PATH="$JAVA_HOME/bin:$PATH"
</pre>

・設定を有効にする
<pre class="box">
$ source /etc/profile.d/java.sh
</pre>

<br/>

インストール後はこんな感じ。
<pre class="box">
$ java -version
java version "1.6.0_06"
java(TM) SE Runtime Environment (build 1.6.0_06-b02)
java HotSpot(TM) Server VM (build 1.6.0_06-b22, mixed mode)
</pre>]]>
</content:encoded>
</item>

</rdf:RDF>