Narusaseの日記 -ハニポってどうよ?(仮)- このページをアンテナに追加 RSSフィード

2016-09-24

[] PHP7.0世代ハッシュ暗号化暗号論的乱数生成およびCSRF対策周りのメモ  PHP7.0世代のハッシュ、暗号化、暗号論的乱数生成およびCSRF対策周りのメモを含むブックマーク  PHP7.0世代のハッシュ、暗号化、暗号論的乱数生成およびCSRF対策周りのメモのブックマークコメント

独自フレームワークのPHP7対応に絡んで、認証 および CSRF対策周りを再設計したいので予備調査の結果を軽くまとめる


ハッシュ関係


暗号関係


暗号論的乱数生成関係


CSRF対策

header( 'Expires: Thu, 01 Jan 1970 00:00:00 GMT' );

header( 'Last-Modified: '.gmdate( 'D, d M Y H:i:s' ).' GMT' );

// HTTP/1.1の場合

header( 'Cache-Control: no-store, no-cache, must-revalidate' );

header( 'Cache-Control: post-check=0, pre-check=0', FALSE );

// HTTP/1.0の場合

header( 'Pragma: no-cache' );

トラックバック - http://d.hatena.ne.jp/narusase/20160924

2016-02-25

[] phpDocumentor version 2.8.5 の PHP7対応  phpDocumentor version 2.8.5 の PHP7対応を含むブックマーク  phpDocumentor version 2.8.5 の PHP7対応のブックマークコメント

phpDocumentor version 2.8.5 の PHP7対応時に嵌った&修正した項目を荒くメモしておく

とりあえず、動くようにしただけなので、全ての環境で動くわけではない

インストールは下記で実施

pear channel-discover pear.phpdoc.org
pear install phpdoc/phpDocumentor

実行時に結果を置くディレクトリを空にしておかないと Segmentation fault が発生する

rm -rf /home/hoge/phpdoc/htdocs/*



PHP7では opcache.load_comments の設定が無効なので、下記のエラーが起こる

ini_get('opcache.load_comments') の結果が 0 なのか NULL なのか厳密に判別してないため、エラーになる模様

[root@dev htdocs]# phpdoc -d /home/hoge/libphp/API/ -t /home/hoge/phpdoc/htdocs/
PHP Fatal error:  Uncaught Doctrine\Common\Annotations\AnnotationException: You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1. in /usr/local/lib64/php/phpDocumentor/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php:193
Stack trace:
#0 /usr/local/lib64/php/phpDocumentor/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php(171): Doctrine\Common\Annotations\AnnotationException::optimizerPlusLoadComments()
#1 /usr/local/lib64/php/phpDocumentor/vendor/jms/serializer/src/JMS/Serializer/SerializerBuilder.php(338): Doctrine\Common\Annotations\AnnotationReader->__construct()
#2 /usr/local/lib64/php/phpDocumentor/src/Cilex/Provider/JmsSerializerServiceProvider.php(73): JMS\Serializer\SerializerBuilder->build()
#3 /usr/local/lib64/php/phpDocumentor/vendor/pimple/pimple/lib/Pimple.php(126): Cilex\Provider\JmsSerializerServiceProvider->Cilex\Provider\{closure}(Object(phpDocumentor\Application))
#4 /usr/local/lib64/php/phpDocumentor/vendor/pimple/pi in /usr/local/lib64/php/phpDocumentor/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php on line 193

Fatal error: Uncaught Doctrine\Common\Annotations\AnnotationException: You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1. in /usr/local/lib64/php/phpDocumentor/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php on line 193

Doctrine\Common\Annotations\AnnotationException: You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1. in /usr/local/lib64/php/phpDocumentor/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php on line 193

Call Stack:
    0.0002     355064   1. {main}() /usr/local/bin/phpdoc:0
    0.0004     371048   2. phpDocumentor\Bootstrap->initialize() /usr/local/bin/phpdoc:23
    0.0060    1642536   3. phpDocumentor\Application->__construct() /usr/local/lib64/php/phpDocumentor/src/phpDocumentor/Bootstrap.php:62
    0.0067    1682552   4. phpDocumentor\Application->addLogging() /usr/local/lib64/php/phpDocumentor/src/phpDocumentor/Application.php:67
    0.0073    1759328   5. Pimple->offsetGet() /usr/local/lib64/php/phpDocumentor/src/phpDocumentor/Application.php:254
    0.0073    1759328   6. Pimple::{closure:/usr/local/lib64/php/phpDocumentor/vendor/pimple/pimple/lib/Pimple.php:122-130}() /usr/local/lib64/php/phpDocumentor/vendor/pimple/pimple/lib/Pimple.php:83
    0.0073    1759352   7. phpDocumentor\Configuration\ServiceProvider->phpDocumentor\Configuration\{closure}() /usr/local/lib64/php/phpDocumentor/vendor/pimple/pimple/lib/Pimple.php:126
    0.0074    1772520   8. Pimple->offsetGet() /usr/local/lib64/php/phpDocumentor/src/phpDocumentor/Configuration/ServiceProvider.php:80
    0.0074    1772520   9. Pimple::{closure:/usr/local/lib64/php/phpDocumentor/vendor/pimple/pimple/lib/Pimple.php:122-130}() /usr/local/lib64/php/phpDocumentor/vendor/pimple/pimple/lib/Pimple.php:83
    0.0074    1772544  10. Cilex\Provider\JmsSerializerServiceProvider->Cilex\Provider\{closure}() /usr/local/lib64/php/phpDocumentor/vendor/pimple/pimple/lib/Pimple.php:126
    0.0090    2000296  11. JMS\Serializer\SerializerBuilder->build() /usr/local/lib64/php/phpDocumentor/src/Cilex/Provider/JmsSerializerServiceProvider.php:73
    0.0093    2060856  12. Doctrine\Common\Annotations\AnnotationReader->__construct() /usr/local/lib64/php/phpDocumentor/vendor/jms/serializer/src/JMS/Serializer/SerializerBuilder.php:338


vi /usr/local/lib64/php/phpDocumentor/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php

L193 近辺

if (extension_loaded('Zend OPcache') && ini_get('opcache.load_comments') == 0) {
    throw AnnotationException::optimizerPlusLoadComments();
}

↓↓↓↓↓↓

if (extension_loaded('Zend OPcache') && ini_get('opcache.load_comments') === 0) {
    throw AnnotationException::optimizerPlusLoadComments();
}




タイプヒンティング時の厳密な型判定により引っ掛かった?

vi /usr/local/lib64/php/phpDocumentor/vendor/monolog/monolog/src/Monolog/ErrorHandler.php

public function handleException(\Exception $e)

↓↓↓↓↓↓

public function handleException(Exception $e)





http://php.net/manual/ja/migration70.incompatible.php

↑の変数の取り扱いの変更の影響(Changes to the handling of indirect variables, properties, and methods)で、扱いが変わった


下記のようなNoticeが発生し、ドキュメント上に出力される

Notice: Array to string conversion in /usr/local/lib64/php/phpDocumentor/vendor/erusev/parsedown/Parsedown.php on line 1404
... 略 ...
Notice: Undefined property: Parsedown::$Array in /usr/local/lib64/php/phpDocumentor/vendor/erusev/parsedown/Parsedown.php on line 1404
... 略 ...

vi /usr/local/lib64/php/phpDocumentor/vendor/erusev/parsedown/Parsedown.php

if (isset($Element['handler']))
{
    $markup .= $this->$Element['handler']($Element['text']);
}

↓↓↓↓↓↓

if (isset($Element['handler']))
{
    $handler = $Element['handler'];
    $markup .= $this->$handler($Element['text']);
}

トラックバック - http://d.hatena.ne.jp/narusase/20160225

2015-09-11

[] PHP 5.3.10 における参照時の謎挙動  PHP 5.3.10 における参照時の謎挙動を含むブックマーク  PHP 5.3.10 における参照時の謎挙動のブックマークコメント

久々におかし仕様バグ?にであったのでメモしておく。

問1: 下記のコードについて実行結果を予測し解答せよ

?php
function drct($input) {}
$hoge = array();
drct($hoge['aaa']);
echo var_export($hoge, true)."\n";

問2: 下記のコードについて実行結果を予測し解答せよ

<?php
function ref(&$input) {}
$hoge = array();
ref($hoge['aaa']);
echo var_export($hoge, true)."\n";

手元のPHP 5.3.10にて確認したところ下記のような結果が得られた

答1:

[hoge@localhost ~]$ php ./test.php
PHP Notice:  Undefined index: aaa in /home/hoge/test.php on line 4
PHP Stack trace:
PHP   1. {main}() /home/hoge/test.php:0

Notice: Undefined index: aaa in /home/hoge/test.php on line 4

Call Stack:
    0.0005     632544   1. {main}() /home/hoge/test.php:0

array (
)

答2:

array (
  'aaa' => NULL,
)

答1 の結果は想定どおりの動きだが、答2の動きは予期しない動きではないだろうか?

おそらく、参照された瞬間に空の変数が生成されているっぽい

参照で渡した場合にNoticeがおきないことを利用してコードを書いている場合、気をつけないとこの副作用バグを生む可能性があるので要注意


一応下記のように回避することも出来るが、これも$hoge['aaa'] がすでにセットされている場合副作用があるので注意

<?php
function ref(&$input) { }
$hoge = array();
ref($hoge['aaa']);
unset($hoge['aaa']); 
echo var_export($hoge, true)."\n";
トラックバック - http://d.hatena.ne.jp/narusase/20150911

2015-07-16

[] 「通信最適化問題論点まとめ  「通信の最適化」問題の論点まとめを含むブックマーク  「通信の最適化」問題の論点まとめのブックマークコメント

注意:

途中で力尽きました、ぜんぜんまとめきれてません・・・orz



通信最適化とは

いわゆる3大キャリアを中心に、MVNOなども含む非wifi通信時(いわゆるLTEなど)におこなわれる、画像動画等に対する非可逆圧縮のこと


問題点

問題点としては複数あり、主に下記のように類型化できると思われる

1. 品質劣化問題

サービス提供者もしくはユーザー意図に反する形で(あるいは基づかない形で)、画像等に対する非可逆圧縮をおこない品質劣化をおこしている点

2. サービスへの干渉問題

一部のアプリにおいて「通信最適化」によりアプリを起動できないなどの問題が発生し、各サービス提供者およびユーザー不利益を与えている点

3. 通信の秘密への侵害問題

ユーザによる「明確な同意」に基づかずにおこなっており、いいわゆる電気通信事業法 および 日本国憲法 における「通信の秘密」を侵しており、盗聴や検閲に相当する点

4. ネットワーク中立性に反する問題

インターネットユーザー自分が見るコンテンツや使用するアプリケーション自分で選択できるべきだとするネットワーク中立性の考え方に反する点

5. 著作権侵害問題

画像等の非可逆圧縮をおこなうことから著作権における同一性保持権侵害している点

6. その他



通信最適化はどのように実現されるか

ドコモauSoftbank、その他MVNOなどで差異はあるが主として下記のようにな構造想像される


+-------------------------+
| クライアント            | ... ユーザーからみるとブラウザやアプリ相当
+-------------------------+
   ↓              ↑
  ( LTEなどのキャリア網 )
   ↓              ↑
+-------------------------+
| 透過的Proxy              | ... ここで一部のレスポンスに対して非可逆圧縮を実施
+-------------------------+
   ↓              ↑
  ( インターネット網 )
   ↓              ↑
+-------------------------+
| サービス提供者のサーバー |
+-------------------------+

凡例
↓ --- リクエスト
↑ --- レスポンス

キャリアとも「通信最適化」の詳細な仕組みや非可逆圧縮対象の選定方法などは公開されていないため想像になるが

いわゆるキャリア網とインターネット網の境界付近に透過的Proxyを配置しそこで通信パケットを一次復元画像動画、音声などに対して非可逆圧縮をかけていると想定される。


○同一レイヤー同一ペイロード原則(造語)について

話をわかりやすくするため先に、余計な話をしておこう


いわゆる、「インターネット」はサーバークライアントがありその間にネットワークがあるという形が基本となっているかと思う。

クライアントネットワークを介してサーバーに対しリクエストを行い、サーバはレスポンスとして結果を返すというのが基本的フローである。

ネットワーク内ではリクエストやレスポンスは、いわゆるプロトコルスタックにしたがって分割、パケットか、信号化され最終的には電気信号や光として伝達される。

一般的教科書的に想定されるウェブブラウズにおけるプロトコルスタックとしては、低レイヤーから順に 100BASE-TX - 802.3(ethernet) - IP - TCP - HTTP - アプリ(プログラムブラウザ) といったものあたりが想定されると思われる。


ここで、とあるクライアントと、とあるサーバー通信する場合単純化してかんがえると、クライアントは高いレイヤーから順にプロトコルスタックをたどって100BASE-TX信号としてリクエストネットワークに送出する

これに対してサーバー信号として100BASE-TX信号としてリクエストを受け取り低いレイヤーから順にプロトコルスタックをさかのぼって解釈リクエストを受け取り、プログラムで処理し、それに対して今度は逆順にレスポンスを返し、最終的にブラウザに表示されるといった流れとなる


ここで、このリクエスト or レスポンスのクライアント側とサーバー側で同一のレイヤー(同一のプロトコル)のいわゆるペイロード部分だけを注目した場合、どちらのプロトコルスタック上でも同じレイヤーにおけるペイロード部分の総体(あくま総体であって個別パケットは分割されていたり順番が相違することなどはありうる)はどちらも同一であることが原則として保障される。

このペイロード総体が同一であることが保障されていることでインターネット網での正常な通信が可能になる。

たとえば、レスポンスを対象として、サーバ側でHTTPの層でペイロードgzip圧縮(可逆圧縮)(HTTPのContent-Encodingの機能)したとしても、クライアントgzipされたペイロードHTTPの層で受け取り、それを解凍して上位の層に渡すので、双方のアプリの層では同じペイロードが得られる

従来のレスポンス
 サーバー                                                    クライアント
+--------------------------------+ (1)                   (1)+--------------------------------+
| アプリ(サーバ側プログラム)     | ↓<-                ->→ | アプリ(クライアント側ブラウザ) |
+--------------------------------+ ↓                    ↑ +--------------------------------+
| HTTP                           | ↓<- 各層で見ると   ->↑ | HTTP                           |
+--------------------------------+ ↓                    ↑ +--------------------------------+
| TCP                            | ↓<- 総体として同一 ->↑ | TCP                            |
+--------------------------------+ ↓                    ↑ +--------------------------------+
| IP                             | ↓<-                ->↑ | IP                             |
+--------------------------------+ ↓                    ↑ +--------------------------------+
| 802.3(ethernet)                | ↓<-                ->↑ | 802.3(ethernet)                |
+--------------------------------+ ↓                    ↑ +--------------------------------+
| 100BASE-TX                     | →→→→(中略)→→→→↑ | 100BASE-TX                     |
+--------------------------------+                          +--------------------------------+
従来のレスポンスは(1)のペイロードの総体はサーバー、クライアント間で維持される
また、中略の部分に無線LANや光ファイバー、ハブやL2スイッチ、ルータなどなどが存在している想定だが
その場合であっても、総体としてのペイロードは維持される


今回の「通信最適化」ではこの総体としてペイロードが同一であることが、通信経路におかれた透過的Proxyによる非可逆圧縮の影響で最上位のアプリの層で崩れてしまうことで、アプリに悪影響を与えてしまっている。


「通信の最適化」のレスポンス
 サーバー                                                    透過的Proxy(ここで改変)                                 クライアント
+--------------------------------+ (2)                   (2)+--------------------------------+(2')                  (2')+--------------------------------+
| アプリ(サーバ側プログラム)     | ↓<-                ->→ | 画像、動画などの圧縮プログラム | ↓<-                ->→ | アプリ(クライアント側ブラウザ) |
+--------------------------------+ ↓                    ↑ +--------------------------------+ ↓                    ↑ +--------------------------------+
| HTTP                           | ↓<- 各層で見ると   ->↑ | HTTP                           | ↓<- 各層で見ると   ->↑ | HTTP                           |
+--------------------------------+ ↓                    ↑ +--------------------------------+ ↓                    ↑ +--------------------------------+
| TCP                            | ↓<- 総体として同一 ->↑ | TCP                            | ↓<- 総体として同一 ->↑ | TCP                            |
+--------------------------------+ ↓                    ↑ +--------------------------------+ ↓                    ↑ +--------------------------------+
| IP                             | ↓<-                ->↑ | IP                             | ↓<-                ->↑ | IP                             |
+--------------------------------+ ↓                    ↑ +--------------------------------+ ↓                    ↑ +--------------------------------+
| 802.3(ethernet)                | ↓<-                ->↑ | 802.3(ethernet)                | ↓<-                ->↑ | 802.3(ethernet)                |
+--------------------------------+ ↓                    ↑ +--------------------------------+ ↓                    ↑ +--------------------------------+
| 100BASE-TX                     | →→→→(中略)→→→→↑ | 100BASE-TX                     | →→→→(中略)→→→→↑ | 100BASE-TX                     |
+--------------------------------+                          +--------------------------------+                          +--------------------------------+
「通信の最適化」のレスポンス(2)のペイロードの総体はサーバー、クライアント間で維持されず、Proxyで改変された(2')を受け取ってしまう



また、中略の部分に無線LAN光ファイバーハブやL2スイッチルータなどなどが存在している想定だが

その場合であっても、 サーバー - Proxy間、Proxy - クライアント間の総体としてのペイロードはそれぞれ維持される



○「通信最適化」の対象になっているか調べる方法


対象かどうか

まずは第一に3大キャリアの設定ページにて、自分対象になっているのか確認する方法は、下記を参照にすると良いだろう


通信最適化」を設定・解除する方法ドコモauソフトバンク】 ? WEBサイトでチェックもできるぞ ≫ 使い方・方法まとめサイト - usedoor

http://usedoor.jp/howto/digital/smartphone/tsuushinnosaitekika-docomo-au-softbank/


・今現在通信最適化」されているかどうか

いくつかのサイトで今現在通信最適化」がされているか確認することが出来る

有名どころを二つほど上げておくので参照してみると良いと思う


通信最適化テストページ

http://seaki.sastudio.jp/nise/photos/SANY9274i.html


通信の最低^H^H最適化確認

http://horobi.com/Saiteika/



過去に「通信最適化」されていた可能性があるかどうか

これまでの報告によると、ドコモauSoftbankBIGLOBEb-mobileU-mobileぷららモバイルLTEDTIなどで「通信最適化」が報告されています


通信最適化」、3キャリアと11社のMVNO適用実態を調べてみた | 格安スマホ回線研究所

http://yesmvno.com/optimization/


なお、IIJmio については下記のTweetによれば、現時点では行っておらず、導入の予定も(いまのところ)ない とのこと

https://twitter.com/iijmio/status/615456060028006400


加えて、下記にて紹介されているが Google Chromeの「データセーバー」や、Operaの「Turboモード」など意図して「通信最適化」をする機能意図して利用している場合、今回のキャリアによる「通信最適化」とは別に適用されている場合があるので注意が必要です。


MVNO格安SIM)であえて「通信最適化」をする方法 | エンジニア休日

http://xins.club/lab/mvno-optimization-apk/



○これまでの流れ

おおよそ下記のまとめを追うと大まかな流れは確認できると思われる


ハッハッ、見ろ!第1種電気通信事業ゴミのようだ!! #通信最適化() - Togetterまとめ

http://togetter.com/li/839917


高木浩光先生通信最適化についてau電凸(前編)「元に戻せない圧縮であるが、改ざんではない」 - Togetterまとめ

http://togetter.com/li/846035


高木浩光先生通信最適化についてau電凸(後編)「そんな適当なこと言って大丈夫か?」「大丈夫だ、問題ない」 - Togetterまとめ

http://togetter.com/li/846061


kadongo38氏「日本通信事業者よりAppleFacebook, Google の方が問題」 - Togetterまとめ

http://togetter.com/li/847364


通信最適化に対するshi3zさんのネットワーク構成認識 - Togetterまとめ

http://togetter.com/li/847799


shi3zさんの通信上の圧縮アルゴリズム利用の認識と、big_brosさんによる指摘及び圧縮アルゴリズム解説 - Togetterまとめ

http://togetter.com/li/847777


ソフトバンクの「通信速度1位」のカラクリが明らかに、ヒントは「通信最適化」 | BUZZAP!(バザップ!)

http://buzzap.jp/news/20140604-sbm-speed-network-optimize/


通信最適化に関する回答(KDDI

https://www.evernote.com/shard/s12/sh/43e35fea-d581-45df-8025-87506ab27e83/6fb4e1214127812e


個人的意見

個人的には重要論点は3つ


1. 中間圧縮することは有っても良いけど、方法がマズイ

HTTPgzip圧縮とか標準仕様にしたがってやる分には、アプリレイヤーに対して悪影響もないし問題ないけど、非可逆圧縮っていうのは無理筋

どうしてもやるなら、標準のパケット交換サービスに組み込むのではなく、オプションなり、安い別サービスなりにするべき。

サービス土管やるなら良いけど、土管勝手に余計なサービスするのは・・・・


2. 「通信最適化」をやるなら、不動産などの契約における重要事項説明と同等のレベルで「明確な個別同意」をとるべき

これがきちんとしているならそもそも通信の秘密を犯すことにはならないはず。


3. 不可逆圧縮はどのレイヤーであっても勝手にやってはならない

サービス提供者の意図、あるいはユーザー意図によってやる分にはレイヤーという意味ではアプリの層で圧縮することは正しい

・・・が、通信経路中のサービス提供者も、ユーザーも感知しないところで勝手にやるのはいけない

通信当事者では無いキャリア勝手にやることは通信の秘密を侵すいわゆる検閲でしかなく、正当業務行為としての違法性阻却事由にも合致しない


■各問題点についての整理


1. 品質劣化問題


重要論点はあまり無く、あまりに自明問題なので詳細は省略


2. サービスへの干渉問題


下記の案件で実際にサービスに悪影響発生しており、単なる懸念ではなく現実問題となっている


スマホゲーム不具合、原因はソフトバンク画像圧縮 ? すまほん!!

http://smhn.info/201506-softbank-assyuku?utm_source=dlvr.it&utm_medium=twitter


たとえば、アプリで利用するデータについてダウンロード後にCRCなどのハッシュによる破損、改変のチェックを行うようなアプリ場合、「通信最適化」で非可逆圧縮された場合当然ハッシュも変わってしまうためエラーが発生する

上記のアプリ場合、まさにこのパターン問題が起こっている


また、技術的な詳細が不明適用条件が不明な点についても問題である


3. 通信の秘密への侵害問題


まずはこちらを見てもらう


ソフトバンク、「通信最適化」は『正当業務行為』。解除不可 - Engadget Japanese

http://japanese.engadget.com/2015/07/15/softbank/


ソフトバンクによると「通信最適化」は「正当業務行為」とのことだが、この「正当業務行為」とはどういうことだろうか?

刑法では定められたいくつかの「違法性阻却事由」が定められている。

これは、たとえ違法行為であっても、当該の違法性否定する事由に合致する場合例外的違法行為であっても、違法性否定するという「違法性阻却事由」に合致するため違法ではないというロジックである

これは「通信の秘密」に対しては「正当業務行為」「正当防衛」「緊急避難」の三つが適用できると想定されている。


しかし、なにが「正当業務行為」に該当するかについては 帯域制御の運用基準に関するガイドライン などで3つの要件が示されている


帯域制御の運用基準に関するガイドライン

http://www.jaipa.or.jp/other/bandwidth/


(1). 目的正当性(帯域制御実施する目的ISP 等の業務内容に照らして正当なものであること)

(2). 行為必要性(当該目的のために帯域制御を行う必要性があること)

(3). 手段の相当性(帯域制御方法等が相当なものであること)


この全てに合致するかどうかは議論があり下記サイトなどが詳しい


ソフトバンクの「通信最適化」の適法性ロジックを突き崩す方法。 ? すまほん!!

http://smhn.info/201507-softbank-tuusin-no-saitekika-ihou?utm_source=dlvr.it&utm_medium=twitter


なお、本来ルータなど機械的な処理により、人の手による監視がない場合であっても通信の秘密侵害したことには変わりはないとされている。

そのため、ISPの業務の多くは通信の秘密侵害しているとされている。

ただし、「当事者同意」がある場合、「正当業務行為」として「違法性阻却事由」に合致する場合のいずれかを満たすため業務を行うことが出来ている。


また、通信の秘密への侵害回避する方法としてはもう一つユーザによる「当事者同意」というものもある

こちらは、たとえばSPAMメール隔離サービスなど、明らかに「通信の秘密」を犯す場合であっても、当事者の一方が「明確な同意」をしている場合には、同意に沿ってメールの中身を見ることができたりする。

ドコモauロジックとしてはこちらを採用しており、ユーザによる「個別かつ明確な同意」をとってあると強弁している。


しかし、「個別かつ明確な同意」というのはいわば重要事項説明のようなものであり、単に規約に書いてあるからOKといったものではないとされている。

いわば、「オプトイン」相当の意思の表示が必要とも・・・


4. ネットワーク中立性に反する問題


まとめ切れなかったので省略


5. 著作権侵害問題


同一性保持権著とは著作権における作者人格権の一種であり、著作物に対して著作者の意に反して変更、切除その他の改変を禁止することができる権利のことで、今回の「通信最適化」においては、画像ファイルに対し非可逆圧縮を行いしかも品質劣化が起こっているという時点で権利を侵していることはほぼ自明であるといって問題ないと思われる。

ただ、親告罪なので権利の主張をしなければ無視することも出来るし、仮に権利の主張をしたとしても裁判を経て権利を認めてもらう必要がありハードルが高い



6. その他


まとめ切れなかったので省略

KoichiYasuokaKoichiYasuoka 2015/07/16 23:07 私が http://srad.jp/~yasuoka/journal/594142 で提示した法律的論点は、問題点の議論の中には入れてもらえなかったのですね。ちょっと残念です。

narusasenarusase 2015/07/22 02:05 なるほど、そのような問題もあるのですね・・・ いかんせん、アンテナが低いもので突っ込んだ法律談義までは受信できませんでした(笑

2013-07-05

[] HTTP 1.1 で 404応答などをした際、PHP の file_get_contents() の返りが遅い問題  HTTP 1.1 で 404応答などをした際、PHP の file_get_contents() の返りが遅い問題を含むブックマーク  HTTP 1.1 で 404応答などをした際、PHP の file_get_contents() の返りが遅い問題のブックマークコメント

詳しい調査はしていないが、HTTP 1.1 でサーバ側から自前でレスポンスを返した場合(200応答以外の404などのレスポンスのときに起きた)に、クライアント側の file_get_contents() の返りが遅いという問題が起こるようだ。

原因は HTTP 1.1 では KeepAliveがデフォルト有効になるが、file_get_contents の側ではTCPコネクションのクローズまで待ってしまうことにあるようだ。

これは本来、リクエストしている file_get_contents の側で何とかするのが正しい対応かと思うが、どうも方法がよくわからない・・・

というわけでとりあえず、サーバー側で header('Connection: close'); として明示的にセッションクローズを宣言することで回避できた。


後で調べたところ、サーバ側からレスポンスする HTTPバージョンを 0.9 or 1.0 に下げることでも対応ができるらしい。

まあ、バージョンが下がればKeepAliveがデフォルト無効になるということですね。


・・・ってことは、file_get_contents で使う HTTP コンテキストオプション の protocol_version を 1.1 にして投げればクライアント側で回避できるのかな?

そのうち気が向いたらテストしてみるか・・・


なお、PHPバージョンは 5.3.10 とちと古いのでより新しいバージョンでは解消されてる可能性も・・・

トラックバック - http://d.hatena.ne.jp/narusase/20130705

2013-01-11

[] MySQL 5.5.19 にて ON DUPLICATE KEY UPDATE 使用時に LAST_INSERT_ID を呼ぶとプライマリキーの値によって不可思議な現象が起こる話  MySQL 5.5.19 にて ON DUPLICATE KEY UPDATE 使用時に LAST_INSERT_ID を呼ぶとプライマリキーの値によって不可思議な現象が起こる話を含むブックマーク  MySQL 5.5.19 にて ON DUPLICATE KEY UPDATE 使用時に LAST_INSERT_ID を呼ぶとプライマリキーの値によって不可思議な現象が起こる話のブックマークコメント

例によって同僚に、ON DUPLICATEを使ってる時の、LAST_INSERT_IDの挙動がなんかおかしいという話を受け調査を開始した。

複数の同僚に手伝ってもらいながら検証した結果次のような現象が起こることが分かったため、メモしておく。


ON DUPLICATE でプライマリキーに「文字」を利用する場合、LAST_INSERT_IDの値が 0 に変化し予期せぬ更新がかかったり、更新が失敗する問題がある。

これは、LAST_INSERT_ID が数値 しか扱えないことが原因と思われる。


次に検証手順を記す。

とりあえず、MySQLバージョンは 5.5.19

■一つ目のパターン「数値」の場合

このパターンは想定通りに動くので、特に問題は起こらない

1.まずは簡単なテーブルを作成する

mysql> CREATE TABLE IF NOT EXISTS fff (
    ->     id          VARCHAR(64),
    ->     last_update DATETIME,
    ->     PRIMARY KEY (id)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.03 sec)

2.プライマリキーに 「数値」をいれて、普通にINSERTする ・・・まあ普通に通る

mysql> INSERT INTO fff (id, last_update) VALUES ('9', NOW());
Query OK, 1 row affected (0.04 sec)

mysql> SELECT * FROM fff\G
*************************** 1. row ***************************
         id: 9
last_update: 2013-01-11 22:11:45
1 row in set (0.00 sec)

3. プライマリキーに 「数値」をいれて、普通にON DUPLICATEする ・・・これも問題なく通る

正しくインサーとされ、LAST_INSERT_IDも正しい値が取れる。

mysql> INSERT INTO fff (id, last_update) VALUES ('9', NOW()) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id), last_update = NOW();
Query OK, 2 rows affected (0.02 sec)

mysql> SELECT * FROM fff\G
*************************** 1. row ***************************
         id: 9
last_update: 2013-01-11 22:11:51
1 row in set (0.00 sec)

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                9 |
+------------------+
1 row in set (0.00 sec)


4. 最後にお掃除する

mysql> DROP TABLES fff;
Query OK, 0 rows affected (0.01 sec)


二つ目パターン「文字」の場合

このパターンは想定通りに動かないので、特に注意を要する

1.まずは簡単なテーブルを作成する

mysql> CREATE TABLE IF NOT EXISTS fff (
    ->     id          VARCHAR(64),
    ->     last_update DATETIME,
    ->     PRIMARY KEY (id)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.03 sec)

2.プライマリキーに 「文字」をいれて、普通にINSERTする ・・・まあ普通に通る

mysql> INSERT INTO fff (id, last_update) VALUES ('X', NOW());
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM fff\G
*************************** 1. row ***************************
         id: X
last_update: 2013-01-11 22:12:29
1 row in set (0.00 sec)


3. プライマリキーに 「文字」をいれて、普通にON DUPLICATEする ・・・これはWARNINGSは出るものの問題なく通るように見える

・・・が、SELECTの結果をみるとid が X から 0 になぜか変換されている。

LAST_INSERT_IDもX ではなく 0 が取れる。


この時点ですでにおかしいが、さらに続ける。


mysql> INSERT INTO fff (id, last_update) VALUES ('X', NOW()) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id), last_update = NOW();
Query OK, 2 rows affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: 'X' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM fff\G
*************************** 1. row ***************************
         id: 0
last_update: 2013-01-11 22:12:38
1 row in set (0.02 sec)

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                0 |
+------------------+
1 row in set (0.00 sec)

4. 再度プライマリキーに 「文字」をいれて、普通にON DUPLICATEする ・・・今度はWARNINGSも出ず問題なく通る

SELECT結果も正しく、Xの行が追加されている

LAST_INSERT_IDはやはり X ではなく 0 が取れる。


mysql> INSERT INTO fff (id, last_update) VALUES ('X', NOW()) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id), last_update = NOW();
Query OK, 1 row affected (0.02 sec)

mysql> SELECT * FROM fff\G
*************************** 1. row ***************************
         id: 0
last_update: 2013-01-11 22:38:33
*************************** 2. row ***************************
         id: X
last_update: 2013-01-11 22:39:18
2 rows in set (0.00 sec)

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                0 |
+------------------+
1 row in set (0.00 sec)

5. さらに再度プライマリキーに 「文字」をいれて、普通にON DUPLICATEする ・・・今度はERRORになてインサートできない

わかる人にはもうわかると思うが、これは id = 'X' ではなく、既に存在する別の id = 0 の行とおなじプライマリキーid = 'X' の行をUPDATE 仕様とした結果、プライマリキーの競合が起こり更新できい状態が発生している。

mysql> INSERT INTO fff (id, last_update) VALUES ('X', NOW()) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id), last_update = NOW();
ERROR 1062 (23000): Duplicate entry '0' for key 'PRIMARY'

6. 最後にお掃除する

mysql> DROP TABLES fff;
Query OK, 0 rows affected (0.01 sec)

■まとめ

このように、LAST_INSERT_ID が数値 しか扱えないず、LAST_INSERT_ID('文字') とした場合には 0 が返る仕様?によりON DUPLICATEとLAST_INSERT_IDを併用する際にプライマリキーに 「文字」をいれた場合不可思議な現象が発生することが有るようです。

トラックバック - http://d.hatena.ne.jp/narusase/20130111

2012-11-05

[] PHPAPCapc.include_once_override 設定時にいくつかの条件を満たした場合に include_once 等が失敗する現象  PHPのAPCの apc.include_once_override 設定時にいくつかの条件を満たした場合に include_once 等が失敗する現象を含むブックマーク  PHPのAPCの apc.include_once_override 設定時にいくつかの条件を満たした場合に include_once 等が失敗する現象のブックマークコメント

↓の続き

誤報 APCapc.include_once_override で動的な include_once 等が失敗する問題

http://d.hatena.ne.jp/narusase/20121030


どうも同僚の調査によると、動的なinclude_onceが原因ではないようだ

・・・というわけで、極限まで単純化したサンプルコードを書いてテストしてみた。


ファイルその1. /home/htdocs/test.php

<?php
function include_test($x = array()) {
    include_once('hogehoge.php');
}
echo '1'."\n";
include_test();
echo '2'."\n";
include_test();
echo 'end-'."\n";

ファイルその2. /home/lib/hogehoge.php

<?php
class hogehoge {

}

or

<?php
const hogehoge = 0;

ざっくりとわかっている条件を列挙する

つまり、5. の条件は不明だがそもそも関数内でinclude_onceされており、さらにパスがini_setなどによるパスの変化によって別ファイルが指定される可能性がある場合に起こっているようだ。



結論としては、発生条件は良く分からないが、下記の条件のいずれかを守れば「回避できそう」ということが分かりました。

1.関数内でinclude_once or require_once を呼ばない。

2.カレントディレクトリ以外のファイルの include_once or require_once はフルパスで指定する

3.どうしても関数内でinclude_once or require_once を呼ぶ場合引数初期化を行わないか、必ずarray()以外(NULL推奨)で初期化する

トラックバック - http://d.hatena.ne.jp/narusase/20121105

2012-10-30

[] 誤報APCapc.include_once_override で動的な include_once 等が失敗する問題  誤報APC の apc.include_once_override で動的な include_once 等が失敗する問題を含むブックマーク  誤報APC の apc.include_once_override で動的な include_once 等が失敗する問題のブックマークコメント

とあるよくわからないエラーを調査したときPEARのMail.php の@ 指定を解除したところ下記のようなエラーが発生したのでちょいと調べて見た。

結果としては先に設定したAPCapc.include_once_override = 1 の設定が悪さをしていた事が分かったので一応メモっておく

PHP Fatal error:  include() [<a href='function.include'>function.include</a>]: 
Cannot redeclare class mail_smtp in /省略/Mail.php on line 52

ネット上をいろいろ探してみるといくつかのサイトで引っかかる既知の問題のようだが、PEARのMail.phpの下記のようなコードが駄目らしい。


static function &factory($driver, $params = array())
{
    $driver = strtolower($driver);
    @include_once 'Mail/' . $driver . '.php';
    ...省略...
}

具体的にはこのfactory関数は include_once で関数引数として渡される文字列からinclude対象のファイル名を作っているのだが、include_once_override はこのような include_once の書き方に対応できないらしい。

まだきちんと原因を追ったのではないがおそらく、APCのinclude_once_overrideの利用時はinclude_onceはincludeと同じような動きをするようになってしまっており二重定義をして起こられている物と思われる。

また、これは動的なinclude_onceだけで起こっているようなので、静的にinclude_onceに続く文字列キーにしてincludeするかしないかを決定していると考えると現象に説明がつく。(ほんと推測ではなくはソースを当たるべき)

とりあえずは、include_once_overrideを無効化して対処したが、上記のコードはおそらく、下記のようにすることで回避できると思われる。

static function &factory($driver, $params = array())
{
    $driver = strtolower($driver);

    switch ($driver) {
    case 'mail':
        include_once 'Mail/mail.php';
        break;
    case 'sendmail':
        include_once 'Mail/sendmail.php';
        break;
    case 'smtp':
        include_once 'Mail/smtp.php';
        break;
    default:
        include_once 'Mail/' . $driver . '.php'; // include_once_override 非利用時用の保険
        break;
    }
    ...省略...
}


追記:

いろいろ調べたてサンプルコードを書いたところこちらの原因は誤報でした

動的に変数を使わずinclude_onceしてもこのエラーは起こるようです

もう少し調べたのち、改めてメモ書きます

2012-10-19

[] PHPAPCの利用によるメモリ使用量の削減について  PHPのAPCの利用によるメモリ使用量の削減についてを含むブックマーク  PHPのAPCの利用によるメモリ使用量の削減についてのブックマークコメント


きたーーーメモリ使用量減った!!


以前から悩んでいたPHPメモリ使用量が高い問題だがようやく対処方法が分かった


php.iniに下記の設定を追加することで、とあるプログラムでは14MB食ってたのが4MBまで減少した(1プロセス当り)

apc.include_once_override = 1

apc.lazy_classes = 1

apc.lazy_functions = 1


この設定は関数クラスの遅延読み込み的なことをする設定のようなので、実際には走らないコードを多く含むものについてはそこそこ効くと思われます。


なお、include_once_override の設定はコードの書き方によってはトラブルになることが多いとのことなので、使うならしばらくテスト環境などで寝かせておいてテストした方が良いかもしれません。

また、lazy_classes、lazy_functions は遅延読み込みだとすると性質上、ほんの少しだろうがパフォーマンスの劣化の副作用が伴う可能性があります。

トラックバック - http://d.hatena.ne.jp/narusase/20121019

2012-08-16

[] PHPの /** から始まるコメントが、require_once実行時に無駄メモリを食う問題  PHPの /** から始まるコメントが、require_once実行時に無駄にメモリを食う問題を含むブックマーク  PHPの /** から始まるコメントが、require_once実行時に無駄にメモリを食う問題のブックマークコメント

知り合いから教えてもらったのだが、PHPでは /** から始まるコメントが、require_once実行時に無駄メモリを食う問題があるらしい・・・ということで調査してみた


まずは、確認用のコードとして test.php を書く

<?php
echo '         peek     usage'."\n";
echo 'pre    = '.memory_get_peak_usage().' / '.memory_get_usage()."\n";
$x  = '0123456789';
for ($i = 0; $i != 12; $i++) {
    $x = $x . $x; // 適当にメモリを使ってrequire_once 時に新たにメモリを確保する必要があるようにしておく
}
$before = memory_get_peak_usage();
echo 'before = '.$before.' / '.memory_get_usage()."\n";
require_once('hoge.php');
$after = memory_get_peak_usage();
echo 'after  = '.$after.' / '.memory_get_usage()."\n";
echo 'after - before = '.($after - $before)."\n\n";

echo 'strlen = '.strlen($x)."\n";


次に、require_onceするhoge.phpを書く

<?php
class hoge {
    /**
     * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
     * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
     * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
     * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
     * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
     */
    public function hogehoge0() {
        return '01234567890123456789012345678901234567890123456789';
    }
    public function hogehoge1() {
        return '01234567890123456789012345678901234567890123456789';
    }
    public function hogehoge2() {
        return '01234567890123456789012345678901234567890123456789';
    }
}

・・・で、test.phpを実行

[user@host ~]$ php  -v
PHP 5.3.10 (cli) (built: Mar 13 2012 10:54:48)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.1.4, Copyright (c) 2002-2012, by Derick Rethans

[user@host ~]$ php test.php
         peek     usage
pre    = 670656 / 639032
before = 703808 / 680448
after  = 706328 / 685792
after - before = 2520

strlen = 40960
strlen = 40960

require_once の前後で2520バイトピークのメモリ量が増えている


次に、コメントを /** から /* に変更して再度実行してみる

[user@host ~]$ php test.php
         peek     usage
pre    = 670656 / 639032
before = 703808 / 680448
after  = 705832 / 685296
after - before = 2024

strlen = 40960

require_once の前後で2024バイトピークのメモリ量が増えている

次は、 // コメントに変えてみる

[user@host ~]$ php test.php
         peek     usage
pre    = 670656 / 639032
before = 703808 / 680448
after  = 705832 / 685296
after - before = 2024

strlen = 40960

こちらも、require_once の前後で2024バイトピークのメモリ量が増えている


結果として /** 形式の場合、 /* や // の形式に比べて 496バイトほど無駄メモリを使っている様子が見て取れ、たしかに/** から始まるコメントが、require_once実行時に無駄メモリを食う問題が存在するようである。

ちなみに、/** の場合に、コメント自体の長さを増やすとどうなるのかさらに追試してみたところ、一文字増やすごとに増えるわけではないが、文字数が多ければ多いほど無駄メモリを食っている様が見て取れた


・・・以上検証終わり


たぶん、require_once するときにプリプロセッサで // と /* のコメント無視しているのに、なぜか /** は無視されないようになっている気がする

なお、requireや、include_once、includeでも起こるかどうかは未検証

・・・PHPソースを負ったわけではないのであくまで「気がする」

・・・だれかバグ仕様かだけでも調査してくれる人いないかなー


追記(2012-08-16 22:25):

ブックマークid:iakio さんよりコメントが有りました

下記の通り、PHPのリフレクションでドキュメントコメントを取得するものがあるそうで、 /** のコメントはその戻り値として用いられるため、この現象は仕様ということで良いようです。

http://jp.php.net/manual/ja/reflectionclass.getdoccomment.php

仕様ということですので、一応 タイトルの「問題」には取り消し線を入れておきます。