MW211 EXIT

devlog
PHP/ファイルコピー
2014年05月02日
以下の方法がある。
┌──────────────────────────────────────┐
│$contents = file_get_contents($入力元);                                     │
│file_put_contents($出力先, $contents);                                      │
├──────────────────────────────────────┤
│if ($handle = fopen($入力元, 'rb')) {                                       │
│    $contents = stream_get_contents($handle);                               │
│    fclose($handle);                                                        │
│    file_put_contents($出力先, $contents);                                  │
│}                                                                           │
└──────────────────────────────────────┘
「file_get_contents()」は一発で簡単にできるのに対して
「stream_get_contents()」は以下のように分割して処理することができる。
┌──────────────────────────────────────┐
│$contents = stream_get_contents($handle, $サイズ, $開始位置);               │
└──────────────────────────────────────┘
分類:PHP
PHP/file_get_contents()とセキュリティ
2014年04月28日
「file_get_contents()」を使って、別サーバの情報を入手するには、
「php.ini」の設定で「allow_url_fopen=on」としなければならない。

これはファイルマニピュレーション機能を可能にするということで、
システム上のファイルの更新を許すということになる。

つまり、セキュリティ的によろしくない。

よって、「allow_url_fopen=off」設定とすることが望まれる。

そうなると別サーバのURLを指定して「file_get_contents()」で
そこの内容を取得するってことができなくなる。

でも、結構これは便利で使いたい。
ということで、代案。
curlってのを使って、以下のような感じにすればよい。
┌──────────────────────────────────────┐
│function fileGetContents代替($url) {                                        │
│    $session = curl_init($url);                                             │
│    curl_setopt($session, CURLOPT_HEADER        , FALSE);  // ヘッダ不要    │
│    curl_setopt($session, CURLOPT_RETURNTRANSFER, TRUE );  // 文字列で返却  │
│    $return = curl_exec($session);                                          │
│    curl_close($session);                                                   │
│    return $return;                                                         │
│}                                                                           │
└──────────────────────────────────────┘

「file_get_contents()」で「allow_url_fopen」の設定の影響を受けるのは
あくまで別サーバをリモートで参照する場合のみ。
自サーバ(のファイル)を参照する分には影響を受けないので
「allow_url_fopen=off」設定で上記代案を併用している場合でも
自サーバに対しては「file_get_contents()」が使用できる。
分類:PHP
PHP/マルチバイト文字数
2014年04月09日
マルチバイト文字の文字数等を取得する関数は以下の通り。

【UTF-8】マルチバイト文字はだいたい1文字あたり3バイト分を使用
┌────────────┬────────────┬────────────┐
│         文字数         │         文字幅         │        バイト数        │
├────────────┼────────────┼────────────┤
│mb_strlen('a')       →1│mb_strwidth('a')     →1│strlen('a')          →1│
├────────────┼────────────┼────────────┤
│mb_strlen('あ')      →1│mb_strwidth('あ')    →2│strlen('あ')         →3│
├────────────┼────────────┼────────────┤
│mb_strlen('aあ')     →2│mb_strwidth('aあ')   →3│strlen('aあ')        →4│
├────────────┼────────────┼────────────┤
│mb_strlen('①')      →1│mb_strwidth('①')  →1★│strlen('①')         →3│
└────────────┴────────────┴────────────┘

【SJIS-win(シフトJIS(CP932))】マルチバイト文字は1文字あたり2バイト分を使用
┌────────────┬────────────┬────────────┐
│         文字数         │         文字幅         │        バイト数        │
├────────────┼────────────┼────────────┤
│mb_strlen('a')       →1│mb_strwidth('a')     →1│strlen('a')          →1│
├────────────┼────────────┼────────────┤
│mb_strlen('あ')      →1│mb_strwidth('あ')    →2│strlen('あ')         →2│
├────────────┼────────────┼────────────┤
│mb_strlen('aあ')     →2│mb_strwidth('aあ')   →3│strlen('aあ')        →3│
├────────────┼────────────┼────────────┤
│mb_strlen('①')      →1│mb_strwidth('①')  →1★│strlen('①')         →2│
└────────────┴────────────┴────────────┘

問題は「mb_strwidth()」における記号(「①」など)の扱い(★)。
半角(1バイト幅)扱いで算出されてしまうのだ。

これは仕様で文字コードの帯域によって、以下のように定義されているからだ。
┌───────┬─────┐
│U+0000~U+0019│ 0バイト幅│
├───────┼─────┤
│U+0020~U+1FFF│ 1バイト幅│
├───────┼─────┤
│U+2000~U+FF60│ 2バイト幅│
├───────┼─────┤
│U+FF61~U+FF9F│ 1バイト幅│
├───────┼─────┤
│U+FFA0~      │ 2バイト幅│
└───────┴─────┘

ということで、全角文字なのに、半角扱いされてしまう文字を当てはめてみると…。
┌───────┬─────┐
│U+0000~U+0019│ 0バイト幅│
├───────┼─────┤
│U+0020~U+1FFF│ 1バイト幅│ω(U+03C9)
├───────┼─────┤
│U+2000~U+FF60│ 2バイト幅│※(U+203B)、①(U+2460)、★(U+2605)、℃(U+2103)
├───────┼─────┤
│U+FF61~U+FF9F│ 1バイト幅│
├───────┼─────┤
│U+FFA0~      │ 2バイト幅│
└───────┴─────┘
ん?辻褄が合わない?

さて、こんな挙動が不審な「mb_strwidth()」対策は?
思い切って使うのを止めてしまう(安定するまで)。

シフトJISならバイト数=文字幅なので、これを利用して、
シフトJISに変換してバイト数を求めるのが無難なやり方みたい。
で、変換できない(「?」になる)UTF-8特有文字とかの対策は?ってことになるが
ま、そいつらは黙殺するしかないか。
分類:PHP
PHP/セッションファイルの生成場所
2014年02月11日
「php.ini」の中身に「session.save_path」で定義されている。
┌──────────────────────────────────────┐
│session.save_path="C:\Windows\Temp"                                         │
└──────────────────────────────────────┘
分類:PHP
PHP/isset()の位置
2014年01月25日
isset()との複合条件の場合、ないかもしれないものを条件にしてしまっていいのか?
ふと不安に思ってしまうことがある。

一旦、isset()で存在を確認してから、改めてそれを判定した方が安全なのではないか?
という疑問だ。

┌──────────────────────────────────────┐
│if ((isset($a)) && ($a == 1)) {                                             │
└──────────────────────────────────────┘
「$a」が未定義の場合、上記は問題ないけど、下記はエラーとなってしまう。
┌──────────────────────────────────────┐
│if (($a == 1) && (isset($a))) {                                              │
└──────────────────────────────────────┘

一般的にAND条件は、左から判定していき、
偽がみつかった時点で判定を打ち切る。

つまり前者は、下記のイメージと同じになる。
┌──────────────────────────────────────┐
│if (isset($a)) {                                                            │
│    if ($a == 1) {                                                          │
└──────────────────────────────────────┘

ということで、順番さえ間違えなければ大丈夫。
分類:PHP
PHP/ファイルが存在したら削除
2014年01月11日
こんな感じ。
┌──────────────────────────────────────┐
│if (file_exists($ファイル)) {                                               │
│    unlink($ファイル);                                                      │
│}                                                                           │
└──────────────────────────────────────┘
分類:PHP
PHP/現在ディレクトリを確認する
2014年01月10日
Linuxの「pwd」コマンド(+ファイル名)のように、そのファイルがどの場所にあるか
調べる方法。
┌──────────────────────────────────────┐
│<?php                                                                       │
│echo __FILE__;                                                              │
└──────────────────────────────────────┘
レンタルサーバなどで場所が今いちわからない場合に使える。
分類:PHP
PHP/ダウンロード画面の雛型
2013年11月27日
PHPにてダウンロード画面を実装する場合のシンプルな雛型。
┌──────────────────────────────────────┐
<?php
if (@$_POST['command'] == 'ダウンロード実行') {
    header('Content-Disposition: attachment; filename="download.txt"');
    header('Content-Type: application/octet-stream');
    echo 'ダウンロードファイルの中身です';
} else {
    echo <<<___HTML___
<html>
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>
<title>ダウンロード画面</title>
</head>
<body>
<form method="post" action="">
<input type="submit" name="command" value="ダウンロード実行"/><br/>
</form>
</body>
</html>

___HTML___;
}
└──────────────────────────────────────┘

実はPOSTを使わなくても実現できたりする。
┌──────────────────────────────────────┐
<?php
if (isset($_GET['dl'])) {
    header('Content-Disposition: attachment; filename="download.txt"');
    header('Content-Type: application/octet-stream');
    echo 'ダウンロードファイルの中身です';
} else {
    echo <<<___HTML___
<html>
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>
<title>ダウンロード画面</title>
</head>
<body>
<a href="?dl">ダウンロード実行</a><br/>
</body>
</html>

___HTML___;
}
└──────────────────────────────────────┘
分類:PHP
PHP/(追記)formの飛び先パスについての注意
2013年11月17日
formタグのactionパラメータに、飛び先のURLを指定する場合、
それがファイルではなく、ディレクトリであった場合には
しっかり末尾に「/」をつけてあげなければならない。
┌─┬────────────────────────────────────┐
│×│<form method="post" action="/abc">                                      │
├─┼────────────────────────────────────┤
│○│<form method="post" action="/abc/">                                     │
└─┴────────────────────────────────────┘

さもないと、「301転送」が発生してしまう。
┌─┬────────────────┬───────────────────┐
│×│… "POST /abc HTTP/1.1" 301 …  │301 Moved Permanently(転送)           │
├─┼────────────────┼───────────────────┤
│○│… "POST /abc/ HTTP/1.1" 200 … │200 OK(正常)                          │
└─┴────────────────┴───────────────────┘
「301転送」が起きるとどうなるのか?POSTの中身が消えてしまう(引き継がれない)

(といっても、そうならないパスがあったりするから厄介だ)


つまり、formタグの「/」がないだけで、いくらsubmitしても
受信側で$_POSTでデータを拾えないという怪奇現象が発生してしまうのだ。
(といっても、そうならないパスがあったりするから、ますます怪奇現象だ)

【追記】
実はmod_rewriteを使っている場合の話だった。
abcを画面コントローラ名として扱っている場合、
htdocs配下に「abc」というフォルダがあると、
一旦「abc/」に「301転送」がされてしまう。

例えば「manual」というフォルダ配下にマニュアルのpdfか何かを格納しつつ
「Manual」というマニュアル画面の画面コントローラ名を使用すると
「/Manual」は、mod_rewriteが動作する前に、「manual」というフォルダに反応して
「/manual/」に「301転送」され、POSTが空っぽになってしまうわけだ。

教訓
・画面コントローラ名とフォルダ名は同じにしてはいけない
・フォルダ名を末尾の「/」なしで指定すると「301転送」される
分類:PHP
PHP/浮動小数点数を経由しないで
2013年11月05日
浮動小数点数を経由しないで整数を1/100する関数。
┌──────────────────────────────────────┐
│private function waru($in) {                                                │
│    $in = preg_replace('/\..*$/', '', $in);                                 │
│    if (preg_match('/^\-/', $in)) {                                         │
│        $in = substr($in, 1);                                               │
│        $in = '0000' . $in;                                                 │
│        return sprintf('-%d.%02d', substr($in, 0, -2),                      │
│                                   substr($in, -2));                        │
│    } else {                                                                │
│        $in = '0000' . $in;                                                 │
│        return sprintf('%d.%02d', substr($in, 0, -2),                       │
│                                  substr($in, -2));                         │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘

浮動小数点数を経由しないで小数を100倍する関数。
┌──────────────────────────────────────┐
│private function kakeru($in) {                                              │
│    return intval(str_replace('.',                                          │
│                              '',                                           │
│                              preg_replace('/(?<=\..{2}).*$/',              │
│                                           '',                              │
│                                           $in)));                          │
│}                                                                           │
└──────────────────────────────────────┘

いずれも文字列で処理している。
分類:PHP
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 … 18 次へ