今日は朝から php + MariaDB の環境で以下のエラーが発生して困ってしまいました。
Malformed communication packet というエラーは初めて見たかもしれません。
† MariaDB をダウングレードして暫定対処
原因としては MariaDB のバージョンアップに起因するようなので、以下のように MariaDB をダウングレードして暫定対象しました。
† 同じ話題が Stack Overflow にも
以下の Stack Overflow のエントリににもあるように、意外と同じところでハマった人は多いようです。
これを見ると PHP 7.3 では発生しないという話も出ているので PHP 7.1 と最新版の Maria DB の問題みたいですね。
Laravel の Auth を使うとパスワードは DB にハッシュ化された状態で格納されます。
これはこれでセキュリティのために必要な挙動なので、これに文句を言うつもりはありません。
しかしながら、例えば管理者用のパスワードを忘れてしまい、DBを強制的に上書きしてログインしたいような場合、このハッシュがどのように作られているのか分からないとお手上げです。今日はまさにそんな状態に陥ってしまったので、解決方法を調べてみました。結論から言うと、以下のようにインタラクティブな php (artisan の tinker)を起動して、プログラムで DB を書き換えることができます。
これだと一撃で実行できるので、楽ちんです。
[Laravel でパスワードを忘れたときの再設定方法 の続きを読む]PHP のファイルが静的解析したくなったので、ソースから AST を得る方法を調べてみました。
以前、Eclipse の ASTParser を使う話を書いたことがありましたが、それの PHP 版になります。
今回の作業にあたって、以下のスライドがとても参考になりました。
PHP は 7 になってから内部的に AST が利用されているため、以前よりも AST を得るのは簡単になっています。
既に以下のような extension が提供されているので、いずれかをインストールすれば大丈夫です。
今回はマニュアルが充実している前者のnikic/php-ast を入れてみることにしました。
以下、構築メモになります。
PHP 7.1 がリリースされました*1。
昨年 12 月の PHP 7.0 リリース以来の大型バージョンアップとなります。
詳細な変更点についてはPHP: PHP 7 ChangeLog に記載がありますが、型まわりでいろいろと改良が加わっているようです。
「PHP 7.1」リリース、型関連の機能を強化 | OSDN Magazine
PHP開発チームは12月1日、プログラミング言語の最新版「PHP 7.1.0」をリリースした。Nullable型が導入されたほか、関数の戻り値としてvoidを指定できるようになるなど、多数の新機能が加わっている。
MySQL (MariaDB)で PHP で言うところのimplode() をやりたいと思っていろいろ調べてみたら、GROUP_CONCAT()*1 を使えば一撃で実現できることが分かったのでメモ。
例えば以下のようなテーブルがあったときに GROUP_CONCAT() を使うとこんな感じになります。
GROUP_CONCAT() には DISTINCT や ORDER BY が効くところもポイントです。
† カンマ区切りのデータの検索は FIND_IN_SET() で
カンマ区切りになった1つのフィールドから、一致するデータの個数を返してくれるのがFIND_IN_SET()*2。
真っ当な正規化を行っていればこんな関数のお世話になる機会はないはずですが、テーブル設計の時に「どうせ検索条件としてこのフィールドは使わないはずだから、非正規形のままカンマ区切りでフィールドにいれちゃえ」なんていう無精をしたりするとお世話になることがあります。真っ当な解決方法としてはテーブル構造を正規化することですが、それがイヤな場合はFULLTEXT インデックスを使ったりしていましたが、一番お手軽に解決できるのが FIND_IN_SET() です。パフォーマンス的にはアレかもしれないので注意は必要ですけどね。
実際の例としては以下のような感じになります。FIND_IN_SET() の第1引数は検索する文字列、第2引数はカンマ区切りの文字列で、返り値は見つかった個数(見つからないときは 0 )になります。GROUP_CONCAT() と違ってセパレーターが指定できないので、元になる文字列の構造には注意が必要です。
Chrome の機能拡張にマルウェアが仕込まれていて騒ぎになっているようです。
その中で紹介されていたCookie の httponly という属性*1が興味深かったのでメモ。
Cookie の仕様とセキュリティ
httponly 属性をつけると、そのクッキーは Cookie ヘッダ以外から読み取ることができなくなりなり、JavaScript から参照できなくなります。 Secureの反対の意味、 http でしか送信されないCookieという意味では ない ので気をつけて下さい。
このオプションはXSS脆弱性があった場合の被害を小さくします。 XSS脆弱性によって攻撃者が任意のJavaScriptが実行できてしまうと、 document.cookie の値を読んで Session ID などのログイン情報などを盗み見れてしまう可能性がありますが、 HttpOnly属性をつけておくとクッキーが XSS 脆弱性によって読み取られることがなくなります。
アプリを書くときに Cookie のSecure 属性は意識してつけていたものの、HttpOnly は Secure の逆かと勘違いしていて、完全にスルーしていました。なかなかの大失態です。
Java の場合にはServlet 3.0 から HttpOnly を指定するためのメソッドjavax.servlet.http.Cookie#setHttpOnly()*2があります。また、PHP の場合には PHP 5.2 以降であればsetcookie()*3の第7引数を使って設定することができます。
以前にIFTTT を使って Twitter アイコンを日替わりにするというのをやりましたが、今日は日替わりかつランダムにアイコンが変わるようにしてみたいと思います。
IFTTT だけではランダムにアイコンを変えることができないので、以下のような PHP のスクリプトを用意しました。これを PHP が使えるウェブサーバの適当なディレクトリにアップロードし、同じディレクトリに画像ファイルを好きなだけを入れておきます。設定が終わったら URL をブラウザで開くと、画像がランダムに表示されるのが分かると思います。(http://example.jp/path/to/randomicon.php の部分は各自の環境に読み替えてください。)
randomicon.php
あとは画像のような感じで IFTTT の設定欄にアップロードした php へのパスを仕込めば OK。
かんこれに始まって、「○○これくしょん」というゲームがあちこちで登場していますが、「コードガールこれくしょん」というプログラミングで美少女を集めるという一風変わったゲームが登場しています。
プログラミング学習ゲーム「コードガールこれくしょん」公開! - GAME Watch
プレーヤーは、最初は簡単な問題から、徐々にレベルが上がっていくクエスト形式でストーリーを進行させていく。プログラミング言語はPHP、Rubyに対応しており、6月にはPythonへの対応も予定されている。
ソフトウェアを本職にしている身としては問題の難易度がどんな感じなのかちょっと気になりますね。。。。
PHP でログ出力を行うためには例えばlog4php などのライブラリを使うという手もありますが、mod_php を使っている場合には Apache の CustomLog を使って Apache にログ出力をしてもらうという手が使えることが分かったのでメモ。
まず、httpd.conf や <VirtualHost> 定義の中に以下のような CustomLog の定義を作成しておきます。
今回は出力にfoo という環境変数を使うので LogFormat に追加されているのは%{foo}e だけですが、これらの定義は必要に応じて追加してください。
あとは PHP 側から apache_setenv() を使って該当の環境変数をセットしてやれば OK。
上記の場合はこんな感じでログ出力がされます。
PHP から AD (Active Directory) を認証データベースとして使うスクリプトを作ってみました。
SSO 関連の実装となると、とにかく LDAP は避けて通れないですからね。
† PHP で LDAP を使えるようにする
まず基本的な事項ですが、AD の実体は LDAP なので、PHP からは LDAP を使ってアクセスすることになります。PHP の LDAP サポートはデフォルトでは有効になっていないので、CentOS や RHEL の場合には yum でモジュールを追加したり、ソースからインストールしている場合は--with-ldap[=DIR] をつけてリコンパイルしてやる必要があります。
† Base DN を調べておく
サンプルを動作させるために必要になるので、AD サーバ上で Base DN (Distinguished Name) を調べておきます。
LDAP に馴染みがないとこれが何なのか分かりづらいかもしれませんが、ツリー状のデータ構造を持つ LDAP の検索の起点になるのが BaseDN です。
例えば AD が入っている Windows Server 上でコマンドプロンプトを開いて以下のようなコマンドを打つと hoge ユーザーの DN が表示できます。
(うまく行かない場合はユーザー名の部分を * にするとユーザーの一覧が表示できるはずです。)
表示されている文字列はユーザーの DN なので Base DN としてはその末尾の部分DC=example,DC=local を使います。
これはかなりシンプルな構成の AD の例ですが、構成等によっては OU= という部分が含まれていたりするはずです。