Tagged ‘PHP’

PHPで複数のURLを404チェックする関数の速度比較

amazonのAPIなんかを利用して画像のパスを取得し保存していると稀に画像が削除されてしまってる事がある。
毎回、amazonのAPIを叩く様にしてもいいかもしれないけど頻繁にアクセスするとamazonに怒られるかもしれない。
そこで、ファイルが存在するかチェックする事にしたのだけどPHPには色々関数があるのでそれぞれチェックしてみた。
(さらに…)

マルチバイト文字のtrim

yahoo!の検索エンジンがGooleの検索エンジンになるというニュースはありましたが
とうとう切り替わったのを確認してしまいました。(徐々に切り替わっていくらしい)

Googleはページの表示スピードも見てるらしいので少しでもPHPのスピードを上げたくて最近ではベンチを使って速度を比較している。
他者の計ったベンチがGoogleで調べればすぐに出てくるのになぜ自分で調べるかというと、例えば文字の置換はstr_replaceを使い。
$str = str_replase(“AAA”, “BBB”, $str);
とするが普通で速度も早いが、検索文字(例の場合”AAA”)の出現がレアな場合
if (strpos($str,”AAA”) !== false) $str = str_replase(“AAA”, “BBB”, $str);
と置換する前に先に検索した方が早かったりするので、実際のデータが無いと分からないのでベンチを計る必要が出てきたりする。

そんな中、比較的遅いというmb_ereg_replaceを使ってるマルチバイトのtrimを調査してみることにした。
$str = mb_ereg_replace(“^[  ]+”, “”, $str);
$str = mb_ereg_replace(“[  ]+$”, “”, $str);
昔、Shift-JISで単純にtrimの第2引数に全角スペースを入れてトリムすると文字化けしたのでmb_ereg_replaceを使ってるが、安全だけど遅い。
そこで昔文字化けした理由を調べに文字コードをwikipediaで見てみた。
Shift_JIS
第1バイトが81-9FとE0-FC、
第2バイトが40-7Eと80-FC
EUC-JP
第1バイトがA1-A8とADとB0-F4とF9-FC、(亜種は8FとF5-FEも)
第2バイトがA1-FE(亜種は第3バイトにもA1-FE)
UTF-8
第1バイトがC2-FD、
第2バイト以降が80-BF
trimのデフォルトの第2引数は
” ” (0x20), 半角スペース
“\t” (0x09), タブ
“\n” (0x0A), 改行
“\r” (0x0D), 復帰
“\0” (0x00), NUL バイト
“\x0B” (0x0B), 垂直タブ
とどの文字コードにも危険なコードが含まれていないので普通に使える。
ただtrimはマルチバイトには対応していないのでシングルバイトに変換され削除されるので全角スペースを除去しようとすると下記のように問題が発生する。
Shift_JISの全角スペースは0x8140でtrimの第2引数に全角スペースを入れると81と40が削られアウト
(http://charset.7jp.net/sjis.htmlの81と40が絡む行や列が文字化けする。)
EUC-JPの全角スペースは0xA1A1でtrimの第2引数に全角スペースを入れるとA1が削られアウト
(http://charset.7jp.net/euc.htmlのA1が絡む行や列が文字化けする。)
UTF-8の全角スペースは0xE38080でtrimの第2引数に全角スペースを入れるとE3と80が削られアウト

正しく全角スペースをトリムするならmb_ereg_replaceしか無く、すべての全角スペースが半角スペースになってもよければ
$str = trim(str_replase(“ ”, ” “, $str));
と先に全角スペースを半角スペースに変換するなど、シチュエーションによって使い分けるしか無いようだ。

新楽天ブックス系API

今日も暇だったのでメールの整理をしていたら「【重要】旧楽天ブックス系APIの廃止のお知らせと移行のお願い(楽天ウェブサービス)」のメールが・・・
後で見ようとマークを付けていた様だけどすっかり忘れてしまってた。日付を見ると5月25日。一ヶ月以上前のメールだ。
新楽天ブックス系APIはISBNやJANに対応してるらしい。
旧楽天ブックス系APIを使ったコンテンツを作った事があるがamazonとかのAPIと比べ劣っていたので出来るコンテンツが限られていたけど今回のは使えそうだ。
MyReleaseに新楽天ブックス系APIを付けてみた。
提供してくれる情報も豊富で書名や著者のフリガナまで付いてる。
テストで適当なISBNコードを入れてやってみた。返ってきたXMLを見ると名前にコロンが付いてる。XML名前空間ってやつだ。(名前空間の使い道はよくわかってない)
確かsimplexmlでは対応してなかったような・・・PHP4の時使ってたDOMの方ならなんとかなった気がするが面倒いなとか思いつつググってみると
楽天 API と simplexml_load_file : やおよろグッ!に解決方法が載ってた。
先にファイルを読み込んでセミコロンの部分を取り除いてからsimplexmlって方法。
裏技的な方法だけど問題なさそうなのでやってみた。
他の箇所も調整してたので時間は掛かったけど問題なく動いてる。
めでたしめでたし。と思ってると
SimpleXMLで名前空間付きタグの一覧を取得する – 肉とご飯と甘いもの @ sotarok
simplexmlでもやりようはあるみたい。

DNRH-001にVINE モジュール

仮サーバーの環境を本サーバーに近いように弄ってるとdomxmlが無いことに気づいた、結構使ってたのでPHPに標準で付いてる関数かと思ってた、検索してみるとモジュールを追加しなくてはいけないらしい。ダウンロードしてコンパイルみたいな事書いてたので面倒だなと思ってるとMLogの記事を発見、PHPのモジュールもソフトみたいにapt-getでインストールできる様だ。

# rpm -qa|grep php

でインストールされてるアプリからPHPを含むのを見てみる、当然だがそれっぽいのは無い。

# apt-get update

念のため最新版チェック

# apt-get install php-domxml

domxmlをインストール

# service apache2 reload

サーバーの再起動

# rpm -qa|grep php

でインストールされてる事を確認して

# php -r 'var_dump(function_exists("domxml_open_file"));'

domxmlの関数が使えるかチェック

ついでにphpMyAdminがmcryptを使ってるらしく下の方にアラートが出てたので

# apt-get install php-mcrypt

ってしてインストールした。
依存性の関係でlibmcryptも自動でインストールしてくれた。

あと、PEARにMailパッケージが入ってなかったので入れる。

# pear install -a Mail

ついでにアップデートもしとく

# pear upgrade-all
# pear update-channels

いたずら防止に画像認証

入会のフォームに誰かがいたずらしてる様だ。
以前、掲示板に中国ドメインによる攻撃があったので中国ドメインと攻撃したIPを除外する様にhtaccessを書いていて
myreleaseにも同じ様にしてるので大丈夫だと思ってたんだけど、ダメみたい。
そこで画像認証を考えてみた。
結構、色んな人が作ってくれてるので簡単に設置できる。

http://uda2.com/kcaptcha/form_example.php
もう少し画像認証について調べてみたらどうも一般的なユーザーには好まれない様だ。
どうしようかと、思ってお問い合わせのあった人の情報を削除するためにDBを覗くと似たメールアドレスで使ってる人を発見。
攻撃されてるのではなく単に間違えて入力した様だ・・・。

iコンシェルはiCalendar

b19nature_animals_land068.jpg最新のdocomoの携帯にiコンシェルという機能が付いた。
「ひつじのしつじ」でおなじみのアレだ。
元々、パソコンや携帯でスケジュール管理をするのが苦手(書くほどの予定もない・・・)のなのでGoogle カレンダーとかも牛のリマインダーもスルーしてたんだけど、iコンシェルは楽しそう。
そこで、「MyRelease」のコミックの発売情報を載せてみるかな と作ろうiモードコンテンツ:スケジューラデータフォーマット | サービス・機能 | NTTドコモを調べてみたら
誤記発見、「CHARASET=SHIFT_JIS;ENCODING=QUOTED-PRINTABLE:」とか書いてる「CHARASET」でなく「CHARSET」ですよね?
ずずっと見ていくと「緯度・経度」とかもひっぱってこれるみたい。
集合場所までナビまでしてくれたりするんかな?
iコンシェルのを作る前にGoogleカレンダーの事もよく知らないので調べてみると
iCal(iCalender)とかいう書式らしい、元々はvCalenderとかいうvCard(電子名刺)の親戚みたいなものの様だ。
サイトによって書式にぶれがあるのが気になるがRSSと同じで読むソフトがなんとかしてくれるという事だろう。(サイトによってはそれぞれのカレンダー用に用意してる所もあった)
調べてる内にイベントソーシャルサイトeventcastを見つけた。Google Calendar、iCal、c2talk、カレンダぴ、auケータイとのやりとりができるらしい。
他のケータイにも対応してるみたいだけどよくわからない。
とりあえず、単品のイベントならYahooカレンダーにも登録できる事が分かった。
リマインダ ボタンの作成)
ヘッダを header(‘Content-Type: text/calendar; charset=utf-8’);
で拡張子は.icsだそうだ
ポチポチやってると日付に関する指定がやたら多く微妙な言い回しなので調べたが
iCalendarの仕様がよくわからん、調べたが結局よくわからん様だこれも受け取るソフトがなんとかしてくれると信じよう。
http://my-release.info/1/COMIC.ics
グーグルカレンダーに登録 Googleカレンダーに登録はこれでいけるみたい。
一回間違えたデータを登録すると登録し直してもすぐに反映されない。
頻繁にicsファイルを見ないようにしてるのかもしれない。
そんで本命のiコンシェルやけど Googleカレンダーよりは設定項目が少ないけど日本語はQUOTED-PRINTABLEとかいうのに変換しなきゃいけないらしく、「imap_8bit」か「quoted_printable_encode」を使うと出来るんみたいだけど。xreaではいけるけどチカッパはダメだった。
ネットで替わりの関数を探し2コ見つけたので試したけら1コはコンパクトだけど正しい答えが返って来なかったので長い方(Quoted-Printableのエンコード (ふえうさぎの記憶墓地))を拝借することにした。
ちなみにiコンシェルの場合は
ヘッダを header(‘Content-type: text/x-vcalendar; charset=Shift_JIS’);
で拡張子は.vcs
そんなこんなで丸一日かけて完成
http://my-release.info/1/COMIC.vcs
って、オレ最新のdocomo持ってないから確認できない・・・

RSS対応ってどうなの?

RSSにちょこっと対応しようかなと思ってみた。
きっかけはこの記事
ユニークなものからシンプルなものまで、RSSのアイコン集: Part 5
なんかイイ感じのアイコンが並んでるので使いたいなと思ってやってみた。
とはいえ、情報はあるので整形するだけでRSSは作れてしまうんだけど、あえてRSS 1.0とRSS 2.0とATOMに対応させようとライブラリを探した。
超簡単って事で「FeedWriter.php」ってのを使うことにした。
PHPでATOM、RSS1/2フォーマットのフィードが超簡単に吐き出せる「FeedWriter.php」
設置は1時間もかからず済んだが全然動かない。
色々、いじっててPHP5の関数(privateとか)って事に気づいた、チカッパはPHP4なので動かない。って事でPHP用4に改造、しかもソース見たら重複するノード名はitem以外使えない様になってる(XMLとしては片手落ちだけどRSSでは問題無いっぽい)それならややこしいことせずに連想配列を使ってクラスを1つに纏めて、文字コードを変更する機能とかなんやら付け加えて、完成したら丸一日かかってしまった。予定では2時間ほどで出来る予定やったのに・・・
□RSS 1.0:http://my-release.info/1/COMIC.rdf
□RSS 2.0:http://my-release.info/1/COMIC.rss
□ATOM:http://my-release.info/1/COMIC.xml
RSSの種類は拡張子を変えると切り替わる様にした。
正直そこまでして誰が喜ぶのか分からないが・・・
以前からRSS対応は視野にあったんだけどMyReleaseで扱ってる商品が「11月下旬」みたいなのがあって、どうしても月単位でないと情報が欠けてしまうので「RSSやメール配信に向いてない」と考え付けなかったんです。
そういう訳で使う人が殆どいないのでこっそり仕様で設置する予定です。

メールが迷惑メール扱いされるので対策してみた

どうも、最近hotmailもyahooメールもスパム扱いされる事が分かったので対応する事にした
調べてみると「登録」とかの文字が入ってるとダメとか送信元のドメインとメアドのドメインが一致しないとダメとかあったがとりあえずメールソフトから送れるのでドメインの問題かと思うがチカッパは設定項目が少ないので無理そうなのでソケット使って直接送るしかなにのか・・・と思ってたら
PEARだとドメインとか設定できる場所があるらしい事が判明。
久しぶりにPEARを使うことにしてみた。(一回やってみただけなので例のごとくすっかり忘れてる)
http://www.karate-style.jp/2007/06/11/pear/
でMail系のが入ってるか調べてみた。
・net_useragent_detect
・net_url
・xml_rpc
・sqlite
・archive_tar
・xml_parser
・net_socket
・db
・http_request
・net_smtp
・pear
・http
・mail
・console_getopt
入ってなさそうな感じだ・・・。
なんでもPEARを簡単にインストールできるものがあるらしい。
http://www.karate-style.jp/2007/06/13/pear-2/
を参考にhttp://go-pear.org/にアクセス。
繋がらない・・・
http://pear.php.net/go-pear
に引っ越し(?)してるらしい。
指示通りインストールしたら、赤い文字でパスワードがどうこうでセキュリティがみたいな
英文が現れたので調べるとbasic認証とかしないといけないらしいので適当に認証付けたら警告文は消えた。
あとは、htaccessでパスを指定っと、やりながらこの記事を書いて気づいたんですが「Mail」は既にインストールされてますね。
・・・意味がない。とりあえず、いつか使うかもしれないので残しておいてhtaccessのパス指定だけ戻して使わない様にしときます。
ということで試してみた所、
噂通り、PEARのMailのsmtpだと迷惑メールになりませんでした。
結果、何が原因かは分からなかったけど、普通のメールを送る様な感じの設定だと送れるみたい。
ちなみに削除方法も見つけたのでメモっときます。
http://tatsuyakun.jp/2008/07/pear.html
実行演算子 ってのでPHPでtelnetとかで使うコマンドがバッククォート (“)で括るだけで使える見たいです。

いろんな空白

偏すが空白かどうかは普段($a=="")で調べるている、ただ、$a=0の場合は問題ないが$a="0";の場合はfalseになってしまう。

空白については前に書いたが誤りがあるようなので調べ直してみた。
ついでにJavaScriptも調べたがJavaScriptは未定義の変数を見ると止まるので未定義は調べていない。

  PHP JavaScript
  ($a=="") (!$a) (empty($a)) (a=="") (!a)
未定義 true true true    
$a=0; true true true true true
$a="0"; false true true false false
$a=-1; false false false false false
$a=null; true true true false true
$a=false; true true true true true
$a=array(); false true true true false

※javascriptはa=new Array();

色々違いすぎてよく分からなくなってくるがPHPの(!$a)と(empty($a))は同じで($a=="")の様に型に縛られる事もなさそうなので(!$a)が一番思ってる動作に近い。
ただ、-1がfalseにならないのが以外だ。何かの言語でflaseを返した気がするんだけど色んな言語をかじりすぎて分からない・・・
最終的にはTPOで、厳密に知りたければ($a==="")みたいに=を3つ連ねて確認が一番なんだけどね。

ISBN変換

やらなきゃいけない事は他にもいろいろあるのにまたツールを作った。
以前からAmazonで言うところのISBN-13のハイフンの打つタイミングがよく分からないので調べてみたら桁数は違うけど規則性がある事を発見した。
例えば、978-4088745213だと正式には978-4-08-874521-3になる。
wikipedia風に言うと「接頭記号」-「グループ記号」-「出版者記号」-「書名記号」-「チェックデジット」となる。「接頭記号」と「グループ記号」と「チェックデジット」は桁数が決まってるので問題無いが「出版者記号」「書名記号」は桁数が決まっていない、そこでISBN 出版社リストを見ていると「出版者記号」の頭の2桁を見ると桁数が分かる事を発見した。
PHPで書くと下記の様な感じだ($aに「出版者記号」の頭の2桁が代入されてるとする)
if ($a < 25) $keta = 2; else if ($a < 75) $keta = 3; else if ($a < 86) $keta = 4; else if ($a < 90) $keta = 5; else if ($a < 99) $keta = 6; else $keta = 7; 更に調べてみるとISBN-10とISBN-13は現在のところ変換可能という事が分かった。 ISBN-13とISBNの大きな違いは「接頭記号」が付くかどうかで、「接頭記号」には978と979があるという事でISBN-10からISBN-13への変換は無理と思いこんでいたんだけど実際は979は使われていないみたい。そうなると978付けて「チェックデジット」を付け直すと変換が可能という事になる。 ISBN変換