dec64(和名:でじこん)

数字列をURLで扱える形で変換する関数群です。
base64エンコードの数字入力限定版というとわかりやすいかも。

base64というと非ASCII文字列をASCII文字に変換する用途に使われますが、
このエンコードでは数字列を短縮化するのが目的です。

使用例

<?php
$dec64=new dec64();
$src="31415926535897";
$enc=$dec64->encode($src);
print $enc;
$dec=$dec64->decode($enc);
print $dec;

本体

<?php
class dec64 {
	function __construct() {
		// digit convert(0-9 to binary)
		$this->digicon= array(
			0=>'000',
			1=>'001',
			2=>'010',
			3=>'011',
			4=>'100',
			5=>'101',
			6=>'1100',
			7=>'1101',
			8=>'1110',
			9=>'1111'
		);
		
		// replace_list(6bit safecode)
		$replace_list=array();
		// 0-9 -> 0-9
		for ($i=0;$i<=9;$i++) {
			$replace_list[$i]=0x30+$i;
		}
		// 10-35 -> A-Z
		for ($i=10;$i<=35;$i++) {
			$replace_list[$i]=0x41+$i-10;
		}
		// 36-61 -> a-z
		for ($i=36;$i<=61;$i++) {
			$replace_list[$i]=0x61+$i-36;
		}
		// 62->'-' 63->'_'
		array_push($replace_list,0x2d,0x5f);
		$this->replace_list=$replace_list;
	}

	function encode($num) {
		$ebit='';
		for ($clm=0;$clm<strlen($num);$clm++) {
			$t=substr($num,$clm,1);
			$ebit .= $this->digicon[$t];
		}
		$mod=strlen($ebit)%6;
		switch ($mod) {
			case 0:
				$suffix='';
				break;
			case 1:
				$suffix='00011';
				break;
			case 2:
				$suffix='0001';
				break;
			case 3:
				$suffix='111';
				break;
			case 4:
				$suffix='00';
				break;
			case 5:
				$suffix='0';
				break;
		}
		return $this->bin64_encode($ebit . $suffix);
	}

	function bin64_encode($bin) {
		$rz='';
		
		for($cur_s=0;$cur_s<strlen($bin);$cur_s+=6) {
			$src=substr($bin,$cur_s,6);
			$gen=bindec($src);
			$dst=chr($this->replace_list[$gen]);
			$rz .= $dst;
		}
		return $rz;
	}

	function decode($str) {
		$exted=$this->bin64_decode($str);

		$sizesrc=strlen($exted);
		$clm=0;
		$ddig='';
		while ($sizesrc > $clm) {
			$remain=$sizesrc-$clm;
			$bef=substr($exted,$clm,2);
			if ($remain < 3) {
				break;
			}
			if ($bef == '11') {
				if ($remain==3) {
					break;
				}
				$enable_digits=4;
			} else {
				if ( (($remain==4) or ($remain==5)) and (substr($exted,-1,1) == '1') ) {
					break;
				}
				$enable_digits=3;
			}
			$unit=substr($exted,$clm,$enable_digits);
			$clm+=$enable_digits;
			$ddig .= array_search($unit,$this->digicon);
		}
		return $ddig;
	}

	function bin64_decode($str) {
		$rz='';
		
		for($cur_s=0;$cur_s<strlen($str);$cur_s++) {
			$src=substr($str,$cur_s,1);
			$gen=array_search(ord($src),$this->replace_list);
			$dst=sprintf("%06s",decbin($gen));
			$rz .= $dst;
		}
		return $rz;
	}
}
?>

Sajax+PHPセッション

PHPセッション機能を利用するにはCookieかGETクエリ文字列でセッションIDを渡さないといけない。
しかしSajaxのAjax通信部分ではHTTPヘッダを追加できないのでセッションを利用できない。
仕方ないのでSajax自体を書き換えることにした。

function sajax_get_my_uri() {
	session_start();
	return $_SERVER["REQUEST_URI"] . '?PHPSESSID=' . urlencode(session_id());
}

・・・たいしたことはしてませんね。

この場合必ずGETクエリで渡さないといけないのでCookieは使わないようにする。
ということで以下の設定値を適用する

session.use_cookies = 0
session.use_only_cookies = 0
session.use_trans_sid = 0

postgresql8.3.12,phpPgAdmin5.0という環境で一般ユーザーがデータベースを作ってスキーマを見ると

ERROR: permission denied for relation pg_authid

と言われてテーブルのリストを見ることができない。
一般ユーザがpg_authidを見ることができないのは当然だけどこれじゃ使えない。

とりあえず対策考えた。
pg_rolesというテーブルがpg_authidのほぼクローン(パスワードが隠されてる)なので、差し替えれば良い。

すなわちclasses/database/Postgres.php 867行目

LEFT JOIN pg_catalog.pg_authid pu ON (pn.nspowner = pu.oid)

これを

LEFT JOIN pg_catalog.pg_roles pu ON (pn.nspowner = pu.oid)

こうするととりあえず見ることができた。

他で問題が起きそうだけどそのときはまた考えよう。

PEAR::Mailの認証方式

PEAR::Mailのオブジェクト作成時に、Mail::factory('smtp',array('auth'=>'true'));
とするとSMTP認証を行うことができるが、認証方式は自動的に決定されてしまう。

これが不都合な場合、'auth'=>'LOGIN'のように認証方式を直接記入することで明示的に選択できる。

Google 日本語入力

Google日本語入力
http://www.google.com/intl/ja/ime/

流石Google
入力途中でも予測変換してくれるしなかなか凄い。
起動後はちょっと重いかなと思うが、使っていると気にならないぐらい速くなる。
ただ予測変換が災いしてGoogleで検索するとき予測単語列が被る。

PDO+MySQLは面倒である

Apache+PHP+PDO+Postgresqlの場合DSNにユーザ名を書いておきそれが
.pgpassに一致する接続設定がある場合パスワードを読んでくれるのでDSNさえ書けば
$pgsql_connect= new PDO($dsn)
これだけですむ。

mysqlの場合DSNにユーザ名をかけないしどうやら.my.cnfは適用されない。
$mysql_connection=new PDO($dsn,$username,$password)
とパスワードまでベタ書きしなきゃいけないらしい。
pgsqlに慣れてしまった今となっては
パスワードをweb領域外とはいえコードに書くのはいやだな。