Composer – PHP 依存関係管理

Composerは、PHPの依存性管理のためのツールです。プロジェクトが依存するライブラリを管理することができます。ライブラリの管理をプロジェクトごと行うことができるので、システム全体に影響することなく利用できます。

Composer のシステム要件は PHP 5.3.2以上ですが、PHP 5.3.4 以上を推奨しています。古いバージョンではエッジケースがあるかもしれないと注意事項があります。

1. インストール

Composer の公式ページのダウンロードのやり方を紹介します。

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === 'e115a8dc7871f15d853148a7fbac7da27d6c0030b848d9b3dc09e2a0388afed865e6a3d6b3c0fad45c48e2b5fc1196ae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"

インストールを確認してみます。

# which composer
/usr/local/bin/composer

これで composer がコマンドラインから使えるようになりました。

2. パッケージリスト

composer で利用できるパッケージは何があるのしょうか?
https://packagist.org/explore/ で確認できます。

私は ocr 関連のライブラリが必要なので “ocr” で検索しみるとたくさんできてきました。
今回は、”thiagoalessio/tesseract_ocr” を利用してみます。

3. パッケージのインストール

パッケージのインストールには、”composer.json” というファイルに依存関係を記述してインストールフォルダに配置する必要があります。(https://packagist.org/ 参照)

今回利用する “thiagoalessio/tesseract_ocr” に composer.json の依存関係の記述があります。バージョンを “1.0.0-RC” から “0.2.1” に変更して使用します。
(追記:実は後でわかったことですが、1.0.0-RC のtesseract_ocr をインストールすると PHP 5.3.3 では文法エラーになる構文が使われています。)

# vi /project/lib/composer.json
--- 以下の内容を記述して保存 ---
{
    "require": {
        "thiagoalessio/tesseract_ocr": "0.2.1"
    }
}

そして、次に以下のコマンドを実行します。

# composer install
Your version of PHP, 5.3.3, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing thiagoalessio/tesseract_ocr (0.2.1)
    Downloading: 100%         

Writing lock file
Generating autoload files

「使用しているPHPのバージョンが 5.3.3 なのでCVE-2013-6420の影響があるので安全に証明書の確認ができないためアップグレードすることを強くお勧めします。」と注意されました。さっそくエッジケースに出くわしましたね。
取り急ぎ、影響ないので無視します。
(追記:xdebug を有効にして composer を実行しています。。。という注意は /etc/php.d/xdebug.ini の zend_extension=/usr/lib64/php/modules/xdebug.so の行頭に ; セミコロンを付けてコメントアウトすると xdebug が無効になります。)

インストールフォルダをみると以下のファイルとフォルダが出来ています。

composer.json
composer.lock
vendor
 - autoload.php

これがあればインストールは成功です。

5. PHPからパッケージの利用

インストールした “tesseract_ocr” は TesseractOCR のラッパーライブラリなので TesseractOCR をインストールします。

# yum install tesseract

https://packagist.org/packages/thiagoalessio/tesseract_ocr を参考にして画像をOCRしてみます。
画像はこちらを使用させていただきます。

# vi test.php
--- 以下の内容を記述して保存 ---
<?php
include "lib/vendor/autoload.php";

$tocr = new TesseractOCR("./text.jpeg");
$tocr-<setLanguage("eng");
$text = $tocr->recognize();

cho "Output ==>".PHP_EOL;
echo $text;
?>

さっそく実行してみます。

# php test.php
Tesseract Open Source OCR Engine v3.04.00 with Leptonica
Output ==>
The quick brown fox
jumps over the lazy
dog,

しっかり認識できています!

以上です。

CentOS FTP ログインでユーザーをルートフォルダに限定

エンドユーザーからファイルをFTPで受け取ってシステムに取り込む際、エンドユーザーには指定のフォルダ以外を見られたくないときの vsftp の設定。

1. vsftpd ユーザーのホームディレクトリの設定

まずは、ログインユーザーがログインした際のホームディレクトリを指定します。
ユーザー別の config ファイルを作成します。

ここでは、ユーザーを foo 、ユーザーのルートフォルダを /var/ftp_upload とします。フォルダの権限設定などはしてあるものとします。

# mkdir /etc/vsftpd/user_conf
# vi /etc/vsftpd/user_conf/foo
--- 以下の内容を入力します ---
local_root=/var/ftp_upload

以下のように user_config_dir の設定を変えて保存します。

# vi /etc/vsftpd/vsftpd.conf
--- 以下の内容を入力します ---
# User config dir
user_config_dir=/etc/vsftpd/user_conf

2. フォルダの移動させない (chrootさせない)

chroot_local_user が YES の場合、chroot_list は chroot させないユーザーのリストになります。ユーザーがフォルダを移動できないように、chroot_list を有効にして、ユーザーをリストに追加して、chroot_local_user を YES にします。

# vi /etc/vsftpd/vsftpd.conf
--- 以下の内容を入力します ---
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list

ユーザー ‘foo’ を /etc/vsftpd/chroot_list に追加します。

# vi /etc/vsftpd/chroot_list
--- 以下の内容を入力します ---
foo

3. vsftpd 再起動

# service vsftpd restart

以上です。

Asterisk キューのログを MySql へ格納

Asterisk 呼情報をODBCでMySqlへ格納する方法を以前やりました。

Asterisk CDR(呼情報)をODBCでMySqlへ格納
Asterisk CDR(呼情報)をODBCでMySqlへ格納(後記)

今回はAsterisk のキュー(待ち呼)のログをODBCでMySqlへ格納する方法を紹介します。

1. キューログ用のテーブルを作成

まずは、キューログ用に queue_log テーブルを作成します。

CREATE TABLE `queue_log` (
    `id`              bigint(255) unsigned NOT NULL AUTO_INCREMENT,
    `time`            varchar(26) NOT NULL DEFAULT '',
    `callid`          varchar(40) NOT NULL DEFAULT '',
    `queuename`       varchar(20) NOT NULL DEFAULT '',
    `agent`           varchar(20) NOT NULL DEFAULT '',
    `event`           varchar(20) NOT NULL DEFAULT '',
    `data`            varchar(100) NOT NULL DEFAULT '',
    `data1`           varchar(40) NOT NULL DEFAULT '',
    `data2`           varchar(40) NOT NULL DEFAULT '',
    `data3`           varchar(40) NOT NULL DEFAULT '',
    `data4`           varchar(40) NOT NULL DEFAULT '',
    `data5`           varchar(40) NOT NULL DEFAULT '',
    `created`         timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `queue` (`queuename`),
    KEY `event` (`event`)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

2. extconfig.conf

/etc/asterisk/extconfig.conf にキューのログを格納する情報を記述します。

queue_log => odbc,asterisk,queue_log

第1パラメータ: ドライバ
第2パラメータ: res_odbc.conf のデータベースの設定情報 (DSN)
第3パラメータ: テーブル名

3. AsteriskとODBC接続の構成

AsteriskとODBC接続の構成は /etc/asterisk/res_odbc.conf で行います。

[asterisk]
enabled => yes
dsn => asterisk-connector
username => asterisk
password => asterpass
pre-connect => yes

4. ODBC設定の追加

Asteriskデータベースへの接続情報を /etc/odbc.ini へ追加します。

[asterisk-connector]
Description           = MySQL connection to 'asterisk' database
Driver                = MySQL
Database              = asterisk
Server                = localhost
UserName              = asterisk
Password              = asterpass
Port                  = 3306
Socket                = /var/lib/mysql/mysql.sock

5. 動作確認

Asterisk 再起動して動作確認します。

# service asterisk restart

キュー情報がMySqlへ格納されるか動作確認してみます。
ここでは、SIP #2501 がキューに入って #2502 が受けた結果を表示しています。

# mysql -u asterisk -p
Enter password: 

mysql> use asterisk;
mysql> select * from queue_log;

+----+----------------------------+--------------+------------+----------+----------------+------+-------+--------------+-------+-------+-------+---------------------+
| id | time                       | callid       | queuename  | agent    | event          | data | data1 | data2        | data3 | data4 | data5 | created             |
+----+----------------------------+--------------+------------+----------+----------------+------+-------+--------------+-------+-------+-------+---------------------+
| 18 | 2016-09-19 12:33:53.249160 | 1474256033.2 | queue_test | NONE     | ENTERQUEUE     |      |       | 2501         | 1     |       |       | 2016-09-19 12:33:53 |
| 19 | 2016-09-19 12:33:56.479286 | 1474256033.2 | queue_test | SIP/2502 | CONNECT        |      | 3     | 1474256033.3 | 3     |       |       | 2016-09-19 12:33:56 |
| 20 | 2016-09-19 12:34:06.721414 | 1474256033.2 | queue_test | SIP/2502 | COMPLETECALLER |      | 3     | 10           | 1     |       |       | 2016-09-19 12:34:06 |
+----+----------------------------+--------------+------------+----------+----------------+------+-------+--------------+-------+-------+-------+---------------------+
3 rows in set (0.01 sec)

参考:
http://stackoverflow.com/questions/30161384/asterisk-11-queue-log-to-mysql
http://work.mikeboylan.com/posts/2012/03/asterisk-queuelog-to-mysql.html
http://lists.digium.com/pipermail/asterisk-users/2009-September/237448.html

以上です。

PHPテキストファイルの改行コード検出

テキストファイルの改行コードの検出方法を考えてみました。
単純にファイルの先頭を数MB 読んで改行コードを判定する方法です。
改行コードが混在してたり、バイナリファイルだと正しく検出できません。

echo detectEOL("/tmp/test.txt");

function detectEOL($file) {
    if (!file_exists($file)) {
        return null;
    }

    $fpsrc = fopen($file, "r");
    if (!$fpsrc) {
        return null;
    }

    $chunk = fread($fpsrc, 10*1024);
    fclose($fpsrc);

    if (empty($chunk)) {
        return null;
    }

    if (substr_count($chunk, "\r\n")) {
        return '\r\n';
    }

    if (substr_count($chunk, "\r")) {
        return '\r';
    }

    return '\n';
}

PHPファイルエンコード変換

ファイルのエンコードを UTF-8 > Shift-JIS へ変換して、別ファイルへ出力するサンプルです。

ファイルの内容をすべて読み込んでエンコード変換する方法:

$srcfile = "/tmp/test.csv";
// 一時ファイルディレクトリにファイルを作成します
$dstfile = tempnam(sys_get_temp_dir(), 'prefix');

$contents = file_get_contents($srcfile);
$contents = mb_convert_encoding($contents, "Shift-JIS", "UTF-8");

$fp = fopen($dstfile , "w");

if ($fp) {
    fwrite($fp, $contents);
    fclose($fp);
}

上記方法だとファイルの内容が多いとメモリの使用上限に達することがあったので
少し改良した版:

$srcfile = "/tmp/test.csv";
// 一時ファイルディレクトリにファイルを作成します
$dstfile = tempnam(sys_get_temp_dir(), 'prefix');

$fpsrc = fopen($srcfile , "r");
$fpdst = fopen($dstfile , "w");

if ($fpsrc && $fpdst) {
    while(($chunk = fgets($fpsrc)) !== false) {
        $chunk = mb_convert_encoding($chunk, "Shift-JIS", "UTF-8");
        fwrite($fpdst, $chunk);
    }
}
if ($fpsrc) {
    fclose($fpsrc);
}
if ($fpdst) {
    fclose($fpdst);
}