Commit 969685a88fce6db5c92c90b6c4e85e48114dca8f

Authored by 山上
0 parents

pay

Too many changes to show.

To preserve performance only 17 of 17+ files are displayed.

  1 +php_flag register_globals On
  2 +php_flag display_errors On
  3 +php_value error_reporting 6135
  1 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2 +"http://www.w3.org/TR/html4/loose.dtd">
  3 +<html>
  4 +<head>
  5 +<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
  6 +<title>クレジット決済 中止</title>
  7 +<link href="css/style.css" rel="stylesheet" type="text/css">
  8 +<script>
  9 +{literal}
  10 +
  11 +{/literal}
  12 +</script>
  13 +</head>
  14 +<body>
  15 +<h1>クレジット決済 中止ページ</h1>
  16 +<hr><br>
  17 +
  18 +<p>クレジット決済処理を中止しました。</p><br>
  19 +
  20 +<p>この画面を閉じて、はじめからやり直してください。</p><br>
  21 +
  22 +
  23 + <input type="button" value="閉じる" onClick="window.close();">
  24 +
  25 +</body>
  26 +</html>
  1 +<?php
  2 +//*****************************************************************************
  3 +//* プログラムID:complete.php
  4 +//* 機能 :決済完了処理
  5 +//*****************************************************************************
  6 +header( "Content-type: text/html; charset=EUC-JP");
  7 +
  8 +include('./inc/smarty.conf');
  9 +
  10 +// EPSILON クレジットカード認証完了、コンビニ受付番号発行完了
  11 +// クライアント側プログラム(PHP版)
  12 +//
  13 +// このプログラムの実行には、以下のモジュールが必要です。
  14 +// ・PHP(ver5,,,,,
  15 +// ・PEAR:
  16 +// ・PEAR:HTTP_Request:
  17 +// ・PEAR:Net_URL:
  18 +// ・PEAR:Net_Socket:
  19 +// ・PEAR:XML_Parser:
  20 +// ・PEAR:XML_Serializer:
  21 +//
  22 +
  23 +//include Libraly
  24 +//PEAR拡張モジュールの読み込み。
  25 +//既に該当のモジュールをインストール済みの場合は適宜読み込み先パスを変更してください。
  26 +require_once "./lib/http/Request.php";
  27 +require_once "./lib/xml/Unserializer.php";
  28 +
  29 +//char setting
  30 +//サーバ環境に応じ適宜変更してください。
  31 +mb_language("Japanese");
  32 +mb_internal_encoding("EUC-JP");
  33 +
  34 +// 変数の設定
  35 +
  36 +// オーダー情報確認CGIのURL(試験用)
  37 +// オーダー情報確認CGIについては2種類ありますのでご注意お願いいたします。
  38 +// 詳細はCGI設定マニュアルの「オーダー情報確認CGI-1,2」をご確認願います。
  39 +// 各CGIの説明
  40 +// CGI-1:認証にパスワード要/発信元IP無制限
  41 +// CGI-2:認証にパスワード不要/発信元IPの制限有
  42 +
  43 +// 以下にはCGI-1と2で設定パラメータが相違しますので利用されるCGIによって変更してください。
  44 +
  45 +// 接続先URLの設定
  46 +
  47 +// CGI-1利用の場合 本番環境への接続の場合は契約後弊社からご連絡いたしますURLに変更してください
  48 +//$getsales_url = 'http://beta.epsilon.jp/client/getsales.cgi';
  49 +$getsales_url = 'https://secure.epsilon.jp/client/getsales.cgi';
  50 +// CGI-2利用の場合 本番環境への接続の場合は契約後弊社からご連絡いたしますURLに変更してください
  51 +//my $getsales_url = 'https://beta.epsilon.jp/cgi-bin/order/getsales2.cgi';
  52 +
  53 +// 発行されたユーザーID(契約コード)を入力してください
  54 +// CGI-1,2共通
  55 +$user_id = '33317000';
  56 +
  57 +// 発行されたパスワードを入力してください。
  58 +// CGI-1利用の場合 弊社からお知らせしたパスワードを設定してください。
  59 +// CGI-2利用の場合 当値は利用しませんので適当な値を設定してください。txZaDA9o,j6ralKCA
  60 +$passwd = '0yTJkjCd';
  61 +
  62 +// エラーが発生した場合のメッセージ
  63 +$err_msg;
  64 +
  65 +// オーダー情報取得CGIを実行した結果を格納する連想配列
  66 +$responce = array();
  67 +
  68 +// 各支払い方法
  69 +$payment_name = array(
  70 + 1 => "クレジットカード決済",
  71 + 2 => "クレジットカード決済",
  72 + 3 => "コンビニ決済",
  73 + 4 => "ネット銀行決済(ジャパンネット銀行)",
  74 + 5 => "ネット銀行決済(e-bank)",
  75 + 7 => "ペイジー",
  76 + 8 => "WebMoney",
  77 + 9 => "Do-Link決済",
  78 + 12 => "BitCash決済",
  79 + 13 => "電子マネーちょコム");
  80 +
  81 +// コンビニ・ペイジー支払の場合の支払い方法の簡単な説明
  82 +$setsumei = array(
  83 + # セブンイレブン
  84 + 11 => "以下の払込票ページをプリントアウトされるか、払込票番号をメモして<br>" .
  85 + "最寄りのセブンイレブンのレジにてお支払いください。<br>" ,
  86 + # ファミリーマート
  87 + 21 => "ファミリーマート店頭にございます Famiポート/ファミネットにて<br>" .
  88 + "以下の2つの数字をご入力頂き、発行されるFamiポート申込券をレジまで<br>" .
  89 + "お持ちになり代金をお支払いください。<br>",
  90 + # ローソン
  91 + 31 => "ローソンの店内に設置してあるLoppiのトップ画面の中から、「インターネット受付」<br>" .
  92 + "をお選びください。次画面のジャンルの中から「インターネット受付」をお選び頂き、<br>" .
  93 + "画面に従って以下の「お支払い受付番号」と、ご登録頂いた「電話番号」をご入力下さい。<br>" ,
  94 + # セイコーマート
  95 + 32 => "セイコーマートの店内に設置してあるセイコーマートクラブステーション(情報端末)の<br>" .
  96 + "トップ画面の中から、「インターネット受付」をお選び下さい。画面に従って以下の<br>" .
  97 + "「お支払い受付番号」と、ご登録頂いた「電話番号」をご入力下さい。<br>" ,
  98 + # ペイジー
  99 + 88 => "ペイジーでお支払い頂く際には銀行のATMもしくはオンラインバンキングで<br>お支払いただく方法がございます。<BR>" .
  100 + "ご利用可能な銀行につきましては以下リンクでご確認お願いいたします。<BR><BR>".
  101 + "<a href='http://www.epsilon.jp/service/payeasy_list.html' target='_blank'>ペイジーお支払可能銀行一覧</a><BR><BR>".
  102 + "お支払可能な銀行、オンラインバンキングで「収納機関番号」、「確認番号」、<br>ご登録いただいた「電話番号」を入力の上ご入金お願いします。" );
  103 +
  104 +// パラメータとして渡される(GET)トランザクションコードを取得します。
  105 +$trans_code = $_REQUEST['trans_code'];
  106 +
  107 +
  108 +// 結果問い合わせ用HTTPリクエスト送信
  109 +
  110 +// CGI-1利用の場合
  111 +// ※オーダー情報確認CGIの実行にはベーシック認証が必要です。
  112 +$request = new HTTP_Request($getsales_url);
  113 +$request->setMethod(HTTP_REQUEST_METHOD_POST);
  114 +$request->addHeader("Content-Type","application/x-www-form-urlencoded");
  115 +$request->setBody("trans_code=" . $trans_code);
  116 +
  117 +$request->setBasicAuth($user_id, $passwd);
  118 +$response = $request->sendRequest();
  119 +
  120 +// CGI-2利用の場合
  121 +//$request = new HTTP_Request($getsales_url);
  122 +//$request->setMethod(HTTP_REQUEST_METHOD_POST);
  123 +//$request->addHeader("Content-Type","application/x-www-form-urlencoded");
  124 +//$request->setBody("trans_code=" . $trans_code . "&contract_code=" . $user_id);
  125 +//$response = $request->sendRequest();
  126 +
  127 +// 以降はCGI-1,2どちらも共通です。
  128 +
  129 +if (PEAR::isError($response)) {
  130 + // インターフェイスCGIの実行に失敗した場合
  131 + $err_msg = "データの送信に失敗しました<br><br>";
  132 + $err_msg .= "<br />res_statusCd=" . $request->getResponseCode();
  133 + $err_msg .= "<br />res_status=" . $request->getResponseHeader('Status');
  134 + echo $err_msg;
  135 + exit;
  136 +}
  137 +
  138 +
  139 +// CGIの実行に成功した場合、応答内容(XML)を解析します
  140 + // 応答内容(XML)の解析
  141 +
  142 +$res_code = $request->getResponseCode();
  143 +$res_content = $request->getResponseBody();
  144 +
  145 +//xml unserializer
  146 +$temp_xml_res = str_replace("x-sjis-cp932", "EUC-JP", $res_content);
  147 +$unserializer =& new XML_Unserializer();
  148 +$unserializer->setOption('parseAttributes', TRUE);
  149 +$unseriliz_st = $unserializer->unserialize($temp_xml_res);
  150 +if ($unseriliz_st === true) {
  151 + //xmlを解析
  152 + $res_array = $unserializer->getUnserializedData();
  153 + //error check
  154 + if($res_array['result']['result'] == "0"){
  155 + echo "処理に失敗しました<br><br>";
  156 + exit(1);
  157 + }
  158 +
  159 + $res_param_array = array();
  160 + //pram setting
  161 + foreach($res_array['result'] as $uns_k => $uns_v){
  162 + list($result_atr_key, $result_atr_val) = each($uns_v);
  163 + $res_param_array[$result_atr_key] = mb_convert_encoding(urldecode($result_atr_val), "EUC-JP" ,"auto");
  164 + }
  165 + $debug_printj .= "<br />xml_memo2_msg=" . $xml_memo2_msg;
  166 +
  167 +}else{
  168 + //xml parser error
  169 + echo "xml parser error<br><br>";
  170 + exit(1);
  171 +}
  172 +$result_html;
  173 +
  174 +if ($res_param_array['payment_code'] == 3){
  175 + // コンビニ支払の場合
  176 + if ($res_param_array['conveni_code'] == 11){
  177 + // セブンイレブンの場合
  178 + $result_html = $setsumei[11] . "<br><br>\n";
  179 + $result_html .= "払込票 : <a href=\"" . $res_param_array['haraikomi_url'] . "\">ここをクリック</a> <br>\n";
  180 + $result_html .= "払込票番号 : " . $res_param_array['receipt_no'] . "<br>\n";
  181 + }
  182 + elseif ($res_param_array['conveni_code'] == 21){
  183 + // ファミリーマートの場合
  184 + $result_html = $setsumei[21] . "<br><br>\n";
  185 + $result_html .="企業コード: " . $res_param_array['kigyou_code'] . "<br>\n";
  186 + $result_html .= "注文番号 : " . $res_param_array['receipt_no'] . "<br>\n";
  187 + }
  188 + elseif (($res_param_array['conveni_code'] == 31) || ($res_param_array['conveni_code'] == 32)){
  189 + // ローソン、セイコーマートの場合
  190 + $result_html = $setsumei{$res_param_array{'conveni_code'}} . "<br><br>\n";
  191 + $result_html .= "お支払い受付番号 : " . $res_param_array['receipt_no'] . "<br>\n";
  192 + }
  193 + else { // 不明(異常)
  194 + $err_msg = "支払情報の取得に失敗しました $res_param_array{'conveni_code'}";
  195 + exit(0);
  196 + }
  197 + $conveni_limit_date = split("-",$res_param_array['conveni_limit']);
  198 + $result_html .= "<br>支払期限:" . $conveni_limit_date[0] . "年"
  199 + . $conveni_limit_date[1] . "月" . $conveni_limit_date[2] . "日<br>\n";
  200 + $payment_name = $payment_name[$res_param_array['payment_code']];
  201 + $item_name = mb_convert_encoding(urldecode($res_param_array['item_name']), "EUC-JP" ,"auto");
  202 + $item_price = $res_param_array['item_price'];
  203 +}
  204 +elseif ($res_param_array['payment_code'] == 7 ){
  205 + // ペイジーの場合
  206 + $result_html = $setsumei[88] . "<br><br>\n";
  207 + $result_html .= "収納機関番号: " . $res_param_array['kigyou_code'] . "<br>\n";
  208 + $result_html .= "確認番号 : " . $res_param_array['receipt_no'] . "<br>\n";
  209 + $payment_name = $payment_name[$res_param_array['payment_code']];
  210 + $item_name = mb_convert_encoding(urldecode($res_param_array['item_name']), "EUC-JP" ,"auto");
  211 + $item_price = $res_param_array['item_price'];
  212 +}
  213 +else {
  214 + // それ以外の決済の場合
  215 + $result_html = "ご注文ありがとうございました。";
  216 + $payment_name = $payment_name[$res_param_array['payment_code']];
  217 + $item_name = mb_convert_encoding(urldecode($res_param_array['item_name']), "EUC-JP" ,"auto");
  218 + $item_price = $res_param_array['item_price'];
  219 +
  220 +}
  221 +
  222 +//め〜るNiポン!の場合
  223 +if($res_param_array['memo1'] == "1"){
  224 +
  225 + //登録済みチェック(F5回避)
  226 + include("./inc/dbcon_PAY_ADM.inc");
  227 + $strSQL = "SELECT * FROM log_data_tbl WHERE order_number = '".$res_param_array['order_number']."'";
  228 +//echo $strSQL."<hr>";
  229 + $objRec = pg_exec($strSQL);
  230 + if($objRec==false){
  231 + echo("SQL実行に失敗しました(SELECT)");
  232 + exit;
  233 + }
  234 + $dataCnt = pg_numrows($objRec);
  235 + if($dataCnt <= 0){
  236 + //データがない場合のみ更新処理
  237 +
  238 + //ポイント確認
  239 + include("./inc/dbcon_MLP_ADM.inc");
  240 + $strSQL = "SELECT * FROM point_tbl WHERE user_id = '".$res_param_array['user_id']."'";
  241 +//echo $strSQL."<hr>";
  242 + $objRec = pg_exec($strSQL);
  243 + if($objRec==false){
  244 + echo("SQL実行に失敗しました(SELECT)");
  245 + exit;
  246 + }
  247 + if(pg_numrows($objRec) > 0){
  248 + $objF = pg_fetch_object($objRec, 0);
  249 + $pointOLD = $objF->use_point;
  250 + }else{
  251 + echo("該当データなし");
  252 + exit;
  253 + }
  254 + $strMEMO1 = "購入ポイント:".$res_param_array['memo2'];
  255 + $strMEMO2 = "更新前ポイント:".$pointOLD;
  256 + $strPointUPDATE = intval($res_param_array['memo2']) + intval($pointOLD);
  257 +
  258 + //団体名取得
  259 + $strSQL = "SELECT * FROM mst_kanri WHERE user_id = '".$res_param_array['user_id']."'";
  260 + $objRec = pg_exec($strSQL);
  261 + if($objRec==false){
  262 + echo("SQL実行に失敗しました(SELECT)");
  263 + exit;
  264 + }
  265 + if(pg_numrows($objRec) > 0){
  266 + $objF = pg_fetch_object($objRec, 0);
  267 + $pg_user_name = $objF->user_name;
  268 + }else{
  269 + echo("該当データなし");
  270 + exit;
  271 + }
  272 +
  273 + //クレジット決済ログ
  274 + include("./inc/dbcon_PAY_ADM.inc");
  275 + $strSQL = "";
  276 + $strSQL .= "INSERT INTO log_data_tbl ";
  277 + $strSQL .= " ( ";
  278 + $strSQL .= " order_number, ";
  279 + $strSQL .= " contract_code, ";
  280 + $strSQL .= " user_id, ";
  281 + $strSQL .= " user_name, ";
  282 + $strSQL .= " user_mail_add, ";
  283 + $strSQL .= " item_code, ";
  284 + $strSQL .= " item_name, ";
  285 + $strSQL .= " mission_code, ";
  286 + $strSQL .= " item_price, ";
  287 + $strSQL .= " process_code, ";
  288 + $strSQL .= " yobi1, ";
  289 + $strSQL .= " yobi2, ";
  290 + $strSQL .= " yobi3, ";
  291 + $strSQL .= " service_flg, ";
  292 + $strSQL .= " pg_group_id, ";
  293 + $strSQL .= " pg_user_id, ";
  294 + $strSQL .= " update_datetime ";
  295 + $strSQL .= " ) ";
  296 + $strSQL .= " VALUES( ";
  297 + $strSQL .= " '".$res_param_array['order_number']."', ";
  298 + $strSQL .= " '".$res_param_array['contract_code']."', ";
  299 + $strSQL .= " '".$res_param_array['user_id']."', ";
  300 + $strSQL .= " '".$res_param_array['user_name']."', ";
  301 + $strSQL .= " '".$res_param_array['user_mail_add']."', ";
  302 + $strSQL .= " '".$res_param_array['item_code']."', ";
  303 + $strSQL .= " '".mb_convert_encoding(urldecode($res_param_array['item_name']), "EUC-JP" ,"auto")."', ";
  304 + $strSQL .= " '".$res_param_array['mission_code']."', ";
  305 + $strSQL .= " '".$res_param_array['item_price']."', ";
  306 + $strSQL .= " '".$res_param_array['process_code']."', ";
  307 + $strSQL .= " '".$strMEMO1."', ";
  308 + $strSQL .= " '".$strMEMO2."', ";
  309 + $strSQL .= " '', ";
  310 + $strSQL .= " '".$res_param_array['memo1']."', ";
  311 + $strSQL .= " '".$res_param_array['user_id']."', ";
  312 + $strSQL .= " '', ";
  313 + $strSQL .= " '".date("Y/m/d H:i:s")."' ";
  314 + $strSQL .= " ) ";
  315 +//echo $strSQL."<hr>";
  316 + $objRec = pg_exec($strSQL);
  317 + if($objRec==false){
  318 + echo("SQL実行に失敗しました(INSERT)");
  319 + exit;
  320 + }
  321 +
  322 + //ポイント更新
  323 + include("./inc/dbcon_MLP_ADM.inc");
  324 + $strSQL = "";
  325 + $strSQL .= "UPDATE point_tbl ";
  326 + $strSQL .= "SET use_point = ".$strPointUPDATE." ";
  327 + $strSQL .= "WHERE user_id = '".$res_param_array['user_id']."'";
  328 +//echo $strSQL."<hr>";
  329 + $objRec = pg_exec($strSQL);
  330 + if($objRec==false){
  331 + echo("SQL実行に失敗しました(UPDATE)");
  332 + exit;
  333 + }
  334 +
  335 + //メール送信
  336 + //各種設定-----------//
  337 + include("./inc/jcode.php");
  338 + $strFrom = "From: support@media-tek.co.jp\n";
  339 + $strSubject = "【め〜るNiポン】ポイントご購入完了のお知らせ";
  340 + $strSubject = "=?iso-2022-jp?B?" . base64_encode(jcodeconvert($strSubject, 0, 3)) . "?=";
  341 + $GMT = date("Z");
  342 + $GMT_ABS = abs($GMT);
  343 + $GMT_HOUR = floor($GMT_ABS / 3600);
  344 + $GMT_MIN = floor(($GMT_ABS - $GMT_HOUR * 3600) / 60);
  345 + if ($GMT >= 0) $GMT_FLG = "+"; else $GMT_FLG = "-";
  346 + $GMT_RFC = date("D, d M Y H:i:s ").sprintf($GMT_FLG."%02d%02d", $GMT_HOUR, $GMT_MIN);
  347 + $Headers = "Date: ".$GMT_RFC."\n";
  348 + $Headers .= $strFrom;
  349 + $Headers .= "Bcc: support@media-tek.co.jp\n";
  350 + $Headers .= "Subject: $strSubject\n";
  351 + $Headers .= "MIME-Version: 1.0\n";
  352 + $Headers .= "X-Mailer: PHP/".phpversion()."\n";
  353 + $Headers .= "Content-type: text/plain; charset=ISO-2022-JP\n";
  354 + $Headers .= "Content-Transfer-Encoding: 7bit";
  355 + //本文
  356 + $strComment = "";
  357 + $strComment .= $res_param_array['user_name']." 様\n";
  358 + $strComment .= "\n";
  359 + $strComment .= "この度は【め〜るNiポン】のポイントをご購入いただき、ありがとうございます。\n";
  360 + $strComment .= "\n";
  361 + $strComment .= "ご購入内容------------------------------------------------------------------\n";
  362 + $strComment .= "■ご利用団体名 :".$pg_user_name." 様\n";
  363 + $strComment .= "■ご購入ポイント:".number_format($res_param_array['memo2'])."ポイント\n";
  364 + $strComment .= "■ご購入価格合計:".number_format($res_param_array['item_price'])."円\n";
  365 + $strComment .= "\n";
  366 + $strComment .= "■お支払い方法 :".$payment_name."\n";
  367 + $strComment .= "----------------------------------------------------------------------------\n";
  368 + $strComment .= "\n";
  369 + $strComment .= "■ご利用可能ポイント数(".date("Y年m月d日 H時i分")." 現在)\n";
  370 + $strComment .= "  ".number_format($strPointUPDATE)."ポイント\n";
  371 + $strComment .= "\n";
  372 + $strComment .= "※ご購入されたポイントは即時追加させていただいております\n";
  373 + $strComment .= " サービスの性質上、返品・返金は出来ません。\n";
  374 + $strComment .= "\n";
  375 + $strComment .= "※このメールに心当たりのない場合、<support@media-tek.co.jp>までご連絡ください。\n";
  376 + $strComment .= "\n";
  377 + $strComment .= "今後とも【め〜るNiポン】をよろしくお願いいたします。\n";
  378 + $strComment .= "----------------------------------------------------------------------------\n";
  379 + $strComment .= "め〜るNiポン:http://www.mail-ni-pon.net\n";
  380 + $strComment .= "メディアテック株式会社:http://www.media-tek.co.jp\n";
  381 + $strComment .= "----------------------------------------------------------------------------\n";
  382 + //エンコード設定
  383 + $strComment = mb_convert_encoding($strComment, "JIS", "auto");
  384 + //メール送信プログラム
  385 + $intBool = mail($res_param_array['user_mail_add'], $strSubject, $strComment, $Headers);
  386 +
  387 + }
  388 +
  389 + $result_html .= "<br>(め〜るNiポン!での画面を更新、または別ページへの移動でポイント表示が更新されます)";
  390 +}
  391 +
  392 +$o_smarty->assign('payment_name' , $payment_name);
  393 +$o_smarty->assign('item_name' , $item_name);
  394 +$o_smarty->assign('item_price' , number_format($item_price));
  395 +$o_smarty->assign('result_html' , $result_html);
  396 +$o_smarty->assign('err_msg' , $err_msg);
  397 +
  398 +$o_smarty->display('complete.tpl');
  399 +
  400 +?>
  1 +<?php
  2 +//*****************************************************************************
  3 +//* プログラムID:confirmation.php
  4 +//* 機能 :クレジット決済確認画面(イプシロン登録ページ!!)
  5 +//*****************************************************************************
  6 +header( "Content-type: text/html; charset=EUC-JP");
  7 +
  8 +include('./inc/smarty.conf');
  9 +
  10 +$SrvcCD = $_POST["SrvcCD"];
  11 +$RetPage = $_POST["RetPage"];
  12 +$hidName = $_POST["hidName"];
  13 +$hidPoint = $_POST["hidPoint"];
  14 +$hidMoney = $_POST["hidMoney"];
  15 +$selPoint = $_POST["selPoint"];
  16 +$pg_user_id = $_POST["pg_user_id"];
  17 +$pg_user_name = $_POST["pg_user_name"];
  18 +$inpMail = $_POST["inpMail"];
  19 +$inpName = $_POST["inpName"];
  20 +if($SrvcCD == "1"){
  21 +//め〜るNiポン!
  22 + $SERVICE_NAME = "め〜るNiポン!"; //サービス名
  23 + $srvcName = $hidName; //商品名
  24 + $srvcMoney = number_format($hidMoney)."円"; //金額(表示)
  25 + $srvcOrderNumber = "MLP".date("Ymd").sprintf("%05d",rand(0,99999)); //オーダー番号
  26 + $srvcMissionCode = 1; //一回のみ
  27 + $srvcProcessCode = 1; //初回課金
  28 + $srvcItemCode = "MLP-".$hidPoint; //商品コード
  29 + $srvcItemName = $SERVICE_NAME.$srvcName; //商品名
  30 + $srvcItemPrice = $hidMoney; //金額
  31 + $srvcUserID = $pg_user_id; //ユーザID
  32 + $srvcUserName = $inpName; //ユーザ名
  33 + $srvcUserMail = $inpMail; //ユーザメールアドレス
  34 + $srvcMemo1 = $SrvcCD; //サービスコード
  35 + $srvcMemo2 = $hidPoint; //購入ポイント
  36 +
  37 +}
  38 +//クレジット決済お決まりコード
  39 +// EPSILON オーダー情報送信プログラム(PHP版)
  40 +// このプログラムの実行には、以下のモジュールが必要です。
  41 +// ・PHP(ver5,,,,,
  42 +// ・PEAR:
  43 +// ・PEAR:HTTP_Request:
  44 +// ・PEAR:Net_URL:
  45 +// ・PEAR:Net_Socket:
  46 +// ・PEAR:XML_Parser:
  47 +// ・PEAR:XML_Serializer:
  48 +//include Libraly
  49 +//PEAR拡張モジュールの読み込み。
  50 +//既に該当のモジュールをインストール済みの場合は適宜読み込み先パスを変更してください。
  51 +require_once "./lib/http/Request.php";
  52 +require_once "./lib/xml/Unserializer.php";
  53 +//char setting
  54 +//サーバ環境に応じ適宜変更してください。
  55 +mb_language("Japanese");
  56 +mb_internal_encoding("EUC-JP");
  57 +// 変数の初期化
  58 +// FORMで送信した内容をこのプログラムファイルで受け取るために、プログラムファイルの名前を設定します。
  59 +$my_self = "confirmation.php";
  60 +// オーダー情報送信先URL(試験用)
  61 +// 本番環境でご利用の場合は契約時に弊社からお送りするURLに変更してください。
  62 +//$order_url = "http://beta.epsilon.jp/cgi-bin/order/receive_order3.cgi";
  63 +$order_url = "https://secure.epsilon.jp/cgi-bin/order/receive_order3.cgi";
  64 +
  65 +//// 以下の各項目についてご利用環境に沿った設定に変更してください
  66 +// 契約番号(8桁) オンライン登録時に発行された契約番号を入力してください。
  67 +$contract_code = "33317000";
  68 +// 注文番号(注文毎にユニークな番号を割り当てます。ここでは仮に乱数を使用しています。)
  69 +$order_number =$srvcOrderNumber;
  70 +// 決済区分 (使用したい決済方法を指定してください。登録時に申し込まれていない決済方法は指定できません。)
  71 +$st_code = '10000-0000-00000'; // 指定方法はCGI設定マニュアルの「決済区分について」を参照してください。
  72 +// 課金区分 (1:一回のみ 2〜10:月次課金)
  73 +// 月次課金について契約がない場合は利用できません。また、月次課金を設定した場合決済区分はクレジットカード決済のみとなります。
  74 +$mission_code = $srvcMissionCode;
  75 +// 処理区分 (1:初回課金 2:登録済み課金 3:登録のみ 4:登録変更 8:月次課金解除 9:退会)
  76 +// 月次課金をご利用にならない場合は1:初回課金をご利用ください。
  77 +// 各処理区分のご利用に関してはCGI設定マニュアルの「処理区分について」を参照してください。
  78 +$process_code = $srvcProcessCode;
  79 +// 追加情報 1,2 (入力は必須ではありません)
  80 +$memo1 = $srvcMemo1;
  81 +$memo2 = $srvcMemo2;
  82 +// 商品コード (商品毎に識別コードを指定してください。ここでは仮に固定の値を指定しています。)
  83 +$item_code = $srvcItemCode;
  84 +//// 変更設定ここまで
  85 +// エラーが発生した場合のメッセージ
  86 +$err_msg;
  87 +// オーダー情報を送信した結果を格納する連想配列
  88 +$responce = array();
  89 +// 商品名と価格
  90 +$item_name = $srvcItemName;
  91 +$item_price = $srvcItemPrice;
  92 +//echo $item_price."<hr>";
  93 +
  94 +// ユーザー固有情報
  95 +// ここでは仮にフォームに入力してもらっていますが、ユーザーID等の値はクライアント様側で
  96 +// 管理されている値を使用してください。
  97 +$user_id = $srvcUserID; // ユーザーID
  98 +$user_name = $srvcUserName; // ユーザー氏名
  99 +$user_mail_add = $srvcUserMail ;// メールアドレス
  100 +
  101 +// CGIの状態(入力画面から実行されたか、確認画面から実行されたか)を判別する値
  102 +$come_from = $_REQUEST['come_from']; // CGIの状態設定
  103 +
  104 +if ($come_from == 'kakunin'){ // 購入確認画面で[確認]ボタンを押した場合
  105 +
  106 + //EPSILONに情報を送信します。
  107 +
  108 + // httpリクエスト用のオプションを指定
  109 + $option = array(
  110 + "timeout" => "20", // タイムアウトの秒数指定
  111 + // "allowRedirects" => true, // リダイレクトの許可設定(true/false)
  112 + // "maxRedirects" => 3, // リダイレクトの最大回数
  113 + );
  114 +
  115 + // HTTP_Requestの初期化
  116 + $request = new HTTP_Request($order_url, $option);
  117 +
  118 + // HTTPのヘッダー設定
  119 + //$http->addHeader("User-Agent", "xxxxx");
  120 + //$http->addHeader("Referer", "xxxxxx");
  121 +
  122 + //set method
  123 + $request->setMethod(HTTP_REQUEST_METHOD_POST);
  124 + //set post data
  125 + $request->addPostData('contract_code', $contract_code);
  126 + $request->addPostData('user_id', $user_id);
  127 + $request->addPostData('user_name', mb_convert_encoding($user_name, "EUC-JP", "auto"));
  128 + $request->addPostData('user_mail_add', $user_mail_add);
  129 + $request->addPostData('item_code', $item_code);
  130 + $request->addPostData('item_name', mb_convert_encoding($item_name, "EUC-JP", "auto"));
  131 + $request->addPostData('order_number', $order_number);
  132 + $request->addPostData('st_code', $st_code);
  133 +
  134 + $request->addPostData('mission_code', $mission_code);
  135 + $request->addPostData('item_price', $item_price);
  136 + $request->addPostData('process_code', $process_code);
  137 + $request->addPostData('memo1', $memo1);
  138 + $request->addPostData('memo2', $memo2);
  139 + $request->addPostData('xml', '1');
  140 +
  141 + // HTTPリクエスト実行
  142 + $response = $request->sendRequest();
  143 + if (!PEAR::isError($response)) {
  144 +
  145 + // 応答内容(XML)の解析
  146 +
  147 + $res_code = $request->getResponseCode();
  148 + $res_content = $request->getResponseBody();
  149 +
  150 + //xml unserializer
  151 + $temp_xml_res = str_replace("x-sjis-cp932", "EUC-JP", $res_content);
  152 + $unserializer =& new XML_Unserializer();
  153 + $unserializer->setOption('parseAttributes', TRUE);
  154 + $unseriliz_st = $unserializer->unserialize($temp_xml_res);
  155 + if ($unseriliz_st === true) {
  156 + //xmlを解析
  157 + $res_array = $unserializer->getUnserializedData();
  158 + $is_xml_error = false;
  159 + $xml_redirect_url = "";
  160 + $xml_error_cd = "";
  161 + $xml_error_msg = "";
  162 + $xml_memo1_msg = "";
  163 + $xml_memo2_msg = "";
  164 + foreach($res_array['result'] as $uns_k => $uns_v){
  165 + //$debug_printj .= "<br />k=" . $uns_k;
  166 + list($result_atr_key, $result_atr_val) = each($uns_v);
  167 + //$debug_printj .= "<br />result_atr_key=" . $result_atr_key;
  168 + //$debug_printj .= "<br />result_atr_val=" . $result_atr_val;
  169 +
  170 + switch ($result_atr_key) {
  171 + case 'redirect':
  172 + $xml_redirect_url = rawurldecode($result_atr_val);
  173 + break;
  174 + case 'err_code':
  175 + $is_xml_error = true;
  176 + $xml_error_cd = $result_atr_val;
  177 + break;
  178 + case 'err_detail':
  179 + $xml_error_msg = mb_convert_encoding(urldecode($result_atr_val), "EUC-JP" ,"auto");
  180 + break;
  181 + case 'memo1':
  182 + $xml_memo1_msg = mb_convert_encoding(urldecode($result_atr_val), "EUC-JP" ,"auto");
  183 + break;
  184 + case 'memo2':
  185 + $xml_memo2_msg = mb_convert_encoding(urldecode($result_atr_val), "EUC-JP" ,"auto");
  186 + break;
  187 + default:
  188 + break;
  189 + }
  190 + }
  191 +
  192 + }else{
  193 + //xml parser error
  194 + $err_msg = "xml parser error<br><br>";
  195 + //exit(1);
  196 + }
  197 +
  198 +
  199 +
  200 + }else{ //http error
  201 +
  202 + //$debug_printj .= "http error";
  203 + $err_msg = "データの送信に失敗しました<br><br>";
  204 + $err_msg .= "<br />res_statusCd=" . $request->getResponseCode();
  205 + $err_msg .= "<br />res_status=" . $request->getResponseHeader('Status');
  206 +
  207 + //exit(1);
  208 +
  209 + }
  210 +
  211 + if($err_msg <> ""){
  212 + //
  213 + }elseif($is_xml_error){
  214 + // データ送信結果が失敗だった場合、オーダー入力画面に戻し、エラーメッセージを表示します。
  215 + $err_msg = "error_cd:" . $xml_error_cd . "error_msg:" . $xml_error_msg;
  216 + //exit(1);
  217 + }else{
  218 + // データ送信に成功した場合、リダイレクト先URLへリダイレクトさせてください。
  219 + header("Location: " . $xml_redirect_url);
  220 + //exit(0);
  221 + }
  222 +
  223 +}
  224 +//ここまで
  225 +
  226 +
  227 +
  228 +$o_smarty->assign('SrvcCD' , $SrvcCD);
  229 +$o_smarty->assign('SERVICE_NAME' , $SERVICE_NAME);
  230 +$o_smarty->assign('RetPage' ,$RetPage);
  231 +$o_smarty->assign('srvcName' , $srvcName);
  232 +$o_smarty->assign('srvcMoney' , $srvcMoney);
  233 +$o_smarty->assign('hidMoney' , $hidMoney);
  234 +$o_smarty->assign('hidPoint' , $hidPoint);
  235 +$o_smarty->assign('selPoint' , $selPoint);
  236 +$o_smarty->assign('inpMail' , $_POST["inpMail"]);
  237 +$o_smarty->assign('inpName' , $_POST["inpName"]);
  238 +
  239 +$o_smarty->assign('pg_user_id',$pg_user_id);
  240 +$o_smarty->assign('pg_user_name',$pg_user_name);
  241 +
  242 +$o_smarty->assign('err_msg' , $err_msg);
  243 +
  244 +//イプシロン決済用データ
  245 +$o_smarty->assign('contract_code', $contract_code);
  246 +$o_smarty->assign('user_id', $user_id);
  247 +$o_smarty->assign('user_name', $user_name);
  248 +$o_smarty->assign('user_mail_add', $user_mail_add);
  249 +$o_smarty->assign('item_code', $item_code);
  250 +$o_smarty->assign('item_name', $item_name);
  251 +$o_smarty->assign('order_number', $order_number);
  252 +$o_smarty->assign('st_code', $st_code);
  253 +$o_smarty->assign('mission_code', $mission_code);
  254 +$o_smarty->assign('item_price', $item_price);
  255 +$o_smarty->assign('process_code', $process_code);
  256 +$o_smarty->assign('memo1', $memo1);
  257 +$o_smarty->assign('memo2', $memo2);
  258 +
  259 +$o_smarty->display('confirmation.tpl');
  260 +
  261 +
  262 +?>
  1 +/* CSS Document */
  2 +
  3 +* {
  4 + margin: 0;
  5 + padding: 0;
  6 +}
  7 +
  8 +h1{
  9 + font-size: 0.9em;
  10 + padding: 7px 0 7px 7px;
  11 + width: auto;
  12 + background-color: #FF9999;
  13 +
  14 +}
  15 +
  16 +h2{
  17 + font-size: 0.9em;
  18 + padding: 7px 0 7px 7px;
  19 +}
  20 +
  21 +h3{
  22 + font-size: 0.9em;
  23 + padding: 7px 0 7px 7px;
  24 +}
  25 +
  26 +
  27 +p{
  28 + font-size: 0.85em;
  29 + line-height: 130%;
  30 + margin-top: 0;
  31 + margin-left: 10px;
  32 +}
  33 +
  34 +.page_font{
  35 + font-size: 0.85em;
  36 +}
  37 +
  38 +.page_sfont{
  39 + font-size: 0.75em;
  40 +}
  41 +
  42 +hr.line_b{
  43 + margin: 0;
  44 + padding: 0;
  45 +}
  46 +
  47 +
  48 +/* クレジット決済ページ */
  49 +
  50 +#waku{
  51 + border: 1px solid #333;
  52 + width: 257px;
  53 + padding: 7px;
  54 + /*
  55 + line-height: 120%;
  56 + */
  57 + margin-left: 7px;
  58 +}
  59 +
  60 +div.kadom {
  61 + border-radius: 10px; /* CSS3 */
  62 + -moz-border-radius: 10px; /* Firefox */
  63 + -webkit-border-radius: 10px; /* Safari,Chrome */
  64 +
  65 + border: 2px #FFB417 solid; /* 枠線の装飾 */
  66 + background-color: #FFCC66; /* 背景色 */
  67 + width: 260px;
  68 + margin-left: 7px;
  69 + padding: 5px;
  70 + line-height: 120%;
  71 +}
  72 +
  73 +/* クレジット決済 確認ページ */
  74 +
  75 +#ta_bor table{
  76 + border: 1px solid #333;
  77 + border-collapse: collapse;
  78 + margin-left: 7px;
  79 + margin-bottom: 7px;
  80 +}
  81 +
  82 +#ta_bor th{
  83 + border: 1px solid #333;
  84 + background-color: #FFE6B0;
  85 + font-size: 0.85em;
  86 + padding: 5px;
  87 +}
  88 +
  89 +#ta_bor td{
  90 + border: 1px solid #333;
  91 + background-color: #FFF;
  92 + font-size: 0.85em;
  93 + padding: 5px;
  94 +}
  95 +
  1 +<?php
  2 +//*****************************************************************************
  3 +//* プログラムID:srvc1000.php
  4 +//* 機能 :め〜るNiポン! ポイント購入画面
  5 +//*****************************************************************************
  6 +header( "Content-type: text/html; charset=EUC-JP");
  7 +
  8 +?>
  9 +エラー画面
  1 +<?php
  2 + $hostname="localhost";
  3 + $database="post_kanri";
  4 +
  5 + if( !$pg_con=pg_connect("host=$hostname dbname=$database user=pgsqladmin password=pgsqladmin") ) {
  6 + print "Error : connect to ${hostname}<br>";
  7 + exit;
  8 + }
  9 +?>
  1 +<?php
  2 + $hostname="localhost";
  3 + $database="Credit_Log_Data";
  4 + //$database="Credit_Log_Data_TEST";
  5 +
  6 + if( !$pg_con=pg_connect("host=$hostname dbname=$database user=pgsqladmin password=pgsqladmin") ) {
  7 + print "Error : connect to ${hostname}<br>";
  8 + exit;
  9 + }
  10 +?>
  1 +<?php
  2 +/*************************************************************************
  3 + ________________________________
  4 +
  5 + jcode.phps by TOMO
  6 + ________________________________
  7 +
  8 +
  9 + [Version] : 1.34 (2002/10/10)
  10 + [URL] : http://www.spencernetwork.org/
  11 + [E-MAIL] : groove@spencernetwork.org
  12 + [Changes] :
  13 + v1.30 Changed XXXtoUTF8 and UTF8toXXX with conversion tables.
  14 + v1.31 Deleted a useless and harmful line in JIStoUTF8() (^^;
  15 + v1.32 Fixed miss type of jsubstr().
  16 + Fixed HANtoZEN_EUC(), HANtoZEN_SJIS() and HANtoZEN_JIS().
  17 + v1.33 Fixed JIStoXXX(), HANtoZEN_JIS() and ZENtoHAN_JIS().
  18 + Added jstr_split() as O-MA-KE No.4.
  19 + Added jstrcut() as O-MA-KE No.5.
  20 + Changed the logic of AutoDetect()
  21 + v1.34 Fixed ZENtoHAN_SJIS()
  22 +
  23 + * jcode.phps is free but without any warranty.
  24 + * use this script at your own risk.
  25 +
  26 +***************************************************************************/
  27 +
  28 +function JcodeConvert(&$str, $from, $to)
  29 +{
  30 + //0:AUTO DETECT
  31 + //1:EUC-JP
  32 + //2:Shift_JIS
  33 + //3:ISO-2022-JP(JIS)
  34 + //4:UTF-8
  35 +
  36 + if ($from == 0) $from = AutoDetect($str);
  37 +
  38 + if ($from == 1 && $to == 2) return EUCtoSJIS($str);
  39 + if ($from == 1 && $to == 3) return EUCtoJIS($str);
  40 + if ($from == 1 && $to == 4) return EUCtoUTF8($str);
  41 + if ($from == 2 && $to == 1) return SJIStoEUC($str);
  42 + if ($from == 2 && $to == 3) return SJIStoJIS($str);
  43 + if ($from == 2 && $to == 4) return SJIStoUTF8($str);
  44 + if ($from == 3 && $to == 1) return JIStoEUC($str);
  45 + if ($from == 3 && $to == 2) return JIStoSJIS($str);
  46 + if ($from == 3 && $to == 4) return JIStoUTF8($str);
  47 + if ($from == 4 && $to == 1) return UTF8toEUC($str);
  48 + if ($from == 4 && $to == 2) return UTF8toSJIS($str);
  49 + if ($from == 4 && $to == 3) return UTF8toJIS($str);
  50 +
  51 + return $str;
  52 +}
  53 +
  54 +function AutoDetect(&$str)
  55 +{
  56 + //0:US-ASCII
  57 + //1:EUC-JP
  58 + //2:Shift_JIS
  59 + //3:ISO-2022-JP(JIS)
  60 + //4:UTF-8
  61 + //5:Unknown
  62 +
  63 + if (!ereg("[\x80-\xFF]", $str)) {
  64 + // --- Check ISO-2022-JP ---
  65 + if (ereg("\x1B", $str)) return 3; // ISO-2022-JP(JIS)
  66 + return 0; //US-ASCII
  67 + }
  68 +
  69 + $b = unpack('C*', ereg_replace("^[^\x80-\xFF]+", "", $str));
  70 + $n = count($b);
  71 +
  72 + // --- Check EUC-JP ---
  73 + $euc = TRUE;
  74 + for ($i = 1; $i <= $n; ++$i){
  75 + if ($b[$i] < 0x80) {
  76 + continue;
  77 + }
  78 + if ($b[$i] < 0x8E) {
  79 + $euc = FALSE; break;
  80 + }
  81 + if ($b[$i] == 0x8E) {
  82 + if (!isset($b[++$i])) {
  83 + $euc = FALSE; break;
  84 + }
  85 + if (($b[$i] < 0xA1) || (0xDF < $b[$i])) {
  86 + $euc = FALSE; break;
  87 + }
  88 + } elseif ((0xA1 <= $b[$i]) && ($b[$i] <= 0xFE)) {
  89 + if (!isset($b[++$i])) {
  90 + $euc = FALSE; break;
  91 + }
  92 + if (($b[$i] < 0xA1) || (0xFE < $b[$i])) {
  93 + $euc = FALSE; break;
  94 + }
  95 + } else {
  96 + $euc = FALSE; break;
  97 + }
  98 + }
  99 + if ($euc) return 1; // EUC-JP
  100 +
  101 + // --- Check UTF-8 ---
  102 + $utf8 = TRUE;
  103 + for ($i = 1; $i <= $n; ++$i) {
  104 + if (($b[$i] < 0x80)) {
  105 + continue;
  106 + }
  107 + if ((0xC0 <= $b[$i]) && ($b[$i] <=0xDF)) {
  108 + if (!isset($b[++$i])) {
  109 + $utf8 = FALSE; break;
  110 + }
  111 + if (($b[$i] < 0x80) || (0xEF < $b[$i])) {
  112 + $utf8 = FALSE; break;
  113 + }
  114 + } elseif ((0xE0 <= $b[$i]) && ($b[$i] <= 0xEF)) {
  115 + if (!isset($b[++$i])) {
  116 + $utf8 = FALSE; break;
  117 + }
  118 + if (($b[$i] < 0x80) || (0xBF < $b[$i])) {
  119 + $utf8 = FALSE; break;
  120 + }
  121 + if (!isset($b[++$i])) {
  122 + $utf8 = FALSE; break;
  123 + }
  124 + if (($b[$i] < 0x80) || (0xBF < $b[$i])) {
  125 + $utf8 = FALSE; break;
  126 + }
  127 + } else {
  128 + $utf8 = FALSE; break;
  129 + }
  130 + }
  131 + if ($utf8) return 4; // UTF-8
  132 +
  133 + // --- Check Shift_JIS ---
  134 + $sjis = TRUE;
  135 + for ($i = 1; $i <= $n; ++$i) {
  136 + if (($b[$i] <= 0x80) || (0xA1 <= $b[$i] && $b[$i] <= 0xDF)) {
  137 + continue;
  138 + }
  139 + if (($b[$i] == 0xA0) || ($b[$i] > 0xEF)) {
  140 + $sjis = FALSE; break;
  141 + }
  142 + if (!isset($b[++$i])) {
  143 + $sjis = FALSE; break;
  144 + }
  145 + if (($b[$i] < 0x40) || ($b[$i] == 0x7F) || ($b[$i] > 0xFC)){
  146 + $sjis = FALSE; break;
  147 + }
  148 + }
  149 + if ($sjis) return 2; // Shift_JIS
  150 +
  151 + return 5; // Unknown
  152 +}
  153 +
  154 +function HANtoZEN(&$str, $encode)
  155 +{
  156 + //0:PASS
  157 + //1:EUC-JP
  158 + //2:Shift_JIS
  159 + //3:ISO-2022-JP(JIS)
  160 + //4:UTF-8
  161 +
  162 + if ($encode == 0) return $str;
  163 + if ($encode == 1) return HANtoZEN_EUC($str);
  164 + if ($encode == 2) return HANtoZEN_SJIS($str);
  165 + if ($encode == 3) return HANtoZEN_JIS($str);
  166 + if ($encode == 4) return HANtoZEN_UTF8($str);
  167 +
  168 + return $str;
  169 +}
  170 +
  171 +function ZENtoHAN(&$str, $encode, $kana=1, $alph=1)
  172 +{
  173 + //0:PASS
  174 + //1:EUC-JP
  175 + //2:Shift_JIS
  176 + //3:ISO-2022-JP(JIS)
  177 +
  178 + if ($encode == 0) return $str;
  179 + if ($encode == 1) return ZENtoHAN_EUC($str, $kana, $alph, $kana);
  180 + if ($encode == 2) return ZENtoHAN_SJIS($str, $kana, $alph, $kana);
  181 + if ($encode == 3) return ZENtoHAN_JIS($str, $kana, $alph, $kana);
  182 +
  183 + return $str;
  184 +}
  185 +
  186 +function JIStoSJIS(&$str_JIS)
  187 +{
  188 + $str_SJIS = '';
  189 + $mode = 0;
  190 + $b = unpack('C*', $str_JIS);
  191 + $n = count($b);
  192 +
  193 + for ($i = 1; $i <= $n; ++$i) {
  194 +
  195 + //Check escape sequence
  196 + while ($b[$i] == 0x1B) {
  197 + if (($b[$i+1] == 0x24 && $b[$i+2] == 0x42)
  198 + || ($b[$i+1] == 0x24 && $b[$i+2] == 0x40)) {
  199 + $mode = 1;
  200 + } elseif (($b[$i+1] == 0x28 && $b[$i+2] == 0x49)) {
  201 + $mode = 2;
  202 + } else {
  203 + $mode = 0;
  204 + }
  205 + $i += 3;
  206 + if (!isset($b[$i])) break 2;
  207 + }
  208 +
  209 + //Do convert
  210 + if ($mode == 1) {
  211 + $b1 = $b[$i];
  212 + $b2 = $b[++$i];
  213 + if ($b1 & 0x01) {
  214 + $b1 >>= 1;
  215 + if ($b1 < 0x2F) $b1 += 0x71; else $b1 -= 0x4F;
  216 + if ($b2 > 0x5F) $b2 += 0x20; else $b2 += 0x1F;
  217 + } else {
  218 + $b1 >>= 1;
  219 + if ($b1 <= 0x2F) $b1 += 0x70; else $b1 -= 0x50;
  220 + $b2 += 0x7E;
  221 + }
  222 + $str_SJIS .= chr($b1).chr($b2);
  223 + } elseif ($mode == 2) {
  224 + $str_SJIS .= chr($b[$i] + 0x80);
  225 + } else {
  226 + $str_SJIS .= chr($b[$i]);
  227 + }
  228 + }
  229 +
  230 + return $str_SJIS;
  231 +}
  232 +
  233 +function JIStoEUC(&$str_JIS)
  234 +{
  235 + $str_EUC = '';
  236 + $mode = 0;
  237 + $b = unpack('C*', $str_JIS);
  238 + $n = count($b);
  239 +
  240 + for ($i = 1; $i <= $n; ++$i) {
  241 +
  242 + //Check escape sequence
  243 + while ($b[$i] == 0x1B) {
  244 + if (($b[$i+1] == 0x24 && $b[$i+2] == 0x42)
  245 + || ($b[$i+1] == 0x24 && $b[$i+2] == 0x40)) {
  246 + $mode = 1;
  247 + } elseif (($b[$i+1] == 0x28 && $b[$i+2] == 0x49)) {
  248 + $mode = 2;
  249 + } else {
  250 + $mode = 0;
  251 + }
  252 + $i += 3;
  253 + if (!isset($b[$i])) break 2;
  254 + }
  255 +
  256 + //Do convert
  257 + if ($mode == 1) {
  258 + $str_EUC .= chr($b[$i] + 0x80).chr($b[++$i] + 0x80);
  259 + } elseif ($mode == 2) {
  260 + $str_EUC .= chr(0x8E).chr($b[$i] + 0x80);
  261 + } else {
  262 + $str_EUC .= chr($b[$i]);
  263 + }
  264 + }
  265 +
  266 + return $str_EUC;
  267 +}
  268 +
  269 +function SJIStoJIS(&$str_SJIS)
  270 +{
  271 + $str_JIS = '';
  272 + $mode = 0;
  273 + $b = unpack('C*', $str_SJIS);
  274 + $n = count($b);
  275 +
  276 + //Escape sequence
  277 + $ESC = array(chr(0x1B).chr(0x28).chr(0x42),
  278 + chr(0x1B).chr(0x24).chr(0x42),
  279 + chr(0x1B).chr(0x28).chr(0x49));
  280 +
  281 + for ($i = 1; $i <= $n; ++$i) {
  282 + $b1 = $b[$i];
  283 + if (0xA1 <= $b1 && $b1 <= 0xDF) {
  284 + if ($mode != 2) {
  285 + $mode = 2;
  286 + $str_JIS .= $ESC[$mode];
  287 + }
  288 + $str_JIS .= chr($b1 - 0x80);
  289 + } elseif ($b1 >= 0x80) {
  290 + if ($mode != 1) {
  291 + $mode = 1;
  292 + $str_JIS .= $ESC[$mode];
  293 + }
  294 + $b2 = $b[++$i];
  295 + $b1 <<= 1;
  296 + if ($b2 < 0x9F) {
  297 + if ($b1 < 0x13F) $b1 -= 0xE1; else $b1 -= 0x61;
  298 + if ($b2 > 0x7E) $b2 -= 0x20; else $b2 -= 0x1F;
  299 + } else {
  300 + if ($b1 < 0x13F) $b1 -= 0xE0; else $b1 -= 0x60;
  301 + $b2 -= 0x7E;
  302 + }
  303 + $str_JIS .= chr($b1).chr($b2);
  304 + } else {
  305 + if ($mode != 0) {
  306 + $mode = 0;
  307 + $str_JIS .= $ESC[$mode];
  308 + }
  309 + $str_JIS .= chr($b1);
  310 + }
  311 + }
  312 + if ($mode != 0) $str_JIS .= $ESC[0];
  313 +
  314 + return $str_JIS;
  315 +}
  316 +
  317 +function SJIStoEUC(&$str_SJIS)
  318 +{
  319 + $b = unpack('C*', $str_SJIS);
  320 + $n = count($b);
  321 + $str_EUC = '';
  322 +
  323 + for ($i = 1; $i <= $n; ++$i) {
  324 + $b1 = $b[$i];
  325 + if (0xA1 <= $b1 && $b1 <= 0xDF) {
  326 + $str_EUC .= chr(0x8E).chr($b1);
  327 + } elseif ($b1 >= 0x81) {
  328 + $b2 = $b[++$i];
  329 + $b1 <<= 1;
  330 + if ($b2 < 0x9F) {
  331 + if ($b1 < 0x13F) $b1 -= 0x61; else $b1 -= 0xE1;
  332 + if ($b2 > 0x7E) $b2 += 0x60; else $b2 += 0x61;
  333 + } else {
  334 + if ($b1 < 0x13F) $b1 -= 0x60; else $b1 -= 0xE0;
  335 + $b2 += 0x02;
  336 + }
  337 + $str_EUC .= chr($b1).chr($b2);
  338 + } else {
  339 + $str_EUC .= chr($b1);
  340 + }
  341 + }
  342 +
  343 + return $str_EUC;
  344 +}
  345 +
  346 +function EUCtoJIS(&$str_EUC)
  347 +{
  348 + $str_JIS = '';
  349 + $mode = 0;
  350 + $b = unpack('C*', $str_EUC);
  351 + $n = count($b);
  352 +
  353 + //Escape sequence
  354 + $ESC = array(chr(0x1B).chr(0x28).chr(0x42),
  355 + chr(0x1B).chr(0x24).chr(0x42),
  356 + chr(0x1B).chr(0x28).chr(0x49));
  357 +
  358 + for ($i = 1; $i <= $n; ++$i) {
  359 + $b1 = $b[$i];
  360 + if ($b1 == 0x8E) {
  361 + if ($mode != 2) {
  362 + $mode = 2;
  363 + $str_JIS .= $ESC[$mode];
  364 + }
  365 + $str_JIS .= chr($b[++$i] - 0x80);
  366 + } elseif ($b1 > 0x8E) {
  367 + if ($mode != 1) {
  368 + $mode = 1;
  369 + $str_JIS .= $ESC[$mode];
  370 + }
  371 + $str_JIS .= chr($b1 - 0x80).chr($b[++$i] - 0x80);
  372 + } else {
  373 + if ($mode != 0) {
  374 + $mode = 0;
  375 + $str_JIS .= $ESC[$mode];
  376 + }
  377 + $str_JIS .= chr($b1);
  378 + }
  379 + }
  380 + if ($mode != 0) $str_JIS .= $ESC[0];
  381 +
  382 + return $str_JIS;
  383 +}
  384 +
  385 +function EUCtoSJIS(&$str_EUC)
  386 +{
  387 + $str_SJIS = '';
  388 + $b = unpack('C*', $str_EUC);
  389 + $n = count($b);
  390 +
  391 + for ($i = 1; $i <= $n; ++$i) {
  392 + $b1 = $b[$i];
  393 + if ($b1 > 0x8E) {
  394 + $b2 = $b[++$i];
  395 + if ($b1 & 0x01) {
  396 + $b1 >>= 1;
  397 + if ($b1 < 0x6F) $b1 += 0x31; else $b1 += 0x71;
  398 + if ($b2 > 0xDF) $b2 -= 0x60; else $b2 -= 0x61;
  399 + } else {
  400 + $b1 >>= 1;
  401 + if ($b1 <= 0x6F) $b1 += 0x30; else $b1 += 0x70;
  402 + $b2 -= 0x02;
  403 + }
  404 + $str_SJIS .= chr($b1).chr($b2);
  405 + } elseif ($b1 == 0x8E) {
  406 + $str_SJIS .= chr($b[++$i]);
  407 + } else {
  408 + $str_SJIS .= chr($b1);
  409 + }
  410 + }
  411 +
  412 + return $str_SJIS;
  413 +}
  414 +
  415 +function SJIStoUTF8(&$str_SJIS)
  416 +{
  417 + global $table_jis_utf8;
  418 +
  419 + $str_UTF8 = '';
  420 + $b = unpack('C*', $str_SJIS);
  421 + $n = count($b);
  422 +
  423 + for ($i = 1; $i <= $n; ++$i) {
  424 + if (0xA1 <= $b[$i] && $b[$i] <= 0xDF) { //Hankaku
  425 + $b2 = $b[$i] - 0x40;
  426 + $u2 = 0xBC | (($b2 >> 6) & 0x03);
  427 + $u3 = 0x80 | ($b2 & 0x3F);
  428 + $str_UTF8 .= chr(0xEF).chr($u2).chr($u3);
  429 + } elseif ($b[$i] >= 0x80) { //Zenkaku
  430 + $b1 = $b[$i] << 1;
  431 + $b2 = $b[++$i];
  432 + if ($b2 < 0x9F) {
  433 + if ($b1 < 0x13F) $b1 -= 0xE1; else $b1 -= 0x61;
  434 + if ($b2 > 0x7E) $b2 -= 0x20; else $b2 -= 0x1F;
  435 + } else {
  436 + if ($b1 < 0x13F) $b1 -= 0xE0; else $b1 -= 0x60;
  437 + $b2 -= 0x7E;
  438 + }
  439 + $b1 &= 0xFF;
  440 + $jis = ($b1 << 8) + $b2;
  441 + if (isset($table_jis_utf8[$jis])) {
  442 + $utf8 = $table_jis_utf8[$jis];
  443 + if ($utf8 < 0xFFFF) {
  444 + $str_UTF8 .= chr($utf8 >> 8).chr($utf8);
  445 + } else {
  446 + $str_UTF8 .= chr($utf8 >> 16).chr($utf8 >> 8).chr($utf8);
  447 + }
  448 + } else {
  449 + $str_UTF8 .= '?'; //Unknown
  450 + }
  451 + } else { //ASCII
  452 + $str_UTF8 .= chr($b[$i]);
  453 + }
  454 + }
  455 +
  456 + return $str_UTF8;
  457 +}
  458 +
  459 +function EUCtoUTF8(&$str_EUC)
  460 +{
  461 + global $table_jis_utf8;
  462 +
  463 + $str_UTF8 = '';
  464 + $b = unpack('C*', $str_EUC);
  465 + $n = count($b);
  466 +
  467 + for ($i = 1; $i <= $n; ++$i) {
  468 + if ($b[$i] == 0x8E) { //Hankaku
  469 + $b2 = $b[++$i] - 0x40;
  470 + $u2 = 0xBC | (($b2 >> 6) & 0x03);
  471 + $u3 = 0x80 | ($b2 & 0x3F);
  472 + $str_UTF8 .= chr(0xEF).chr($u2).chr($u3);
  473 + } elseif ($b[$i] >= 0x80) { //Zenkaku
  474 + $jis = (($b[$i] - 0x80) << 8) + ($b[++$i] - 0x80);
  475 + if (isset($table_jis_utf8[$jis])) {
  476 + $utf8 = $table_jis_utf8[$jis];
  477 + if ($utf8 < 0xFFFF) {
  478 + $str_UTF8 .= chr($utf8 >> 8).chr($utf8);
  479 + } else {
  480 + $str_UTF8 .= chr($utf8 >> 16).chr($utf8 >> 8).chr($utf8);
  481 + }
  482 + } else { //Unknown
  483 + $str_UTF8 .= '?';
  484 + }
  485 + } else { //ASCII
  486 + $str_UTF8 .= chr($b[$i]);
  487 + }
  488 + }
  489 +
  490 + return $str_UTF8;
  491 +}
  492 +
  493 +function JIStoUTF8(&$str_JIS)
  494 +{
  495 + global $table_jis_utf8;
  496 +
  497 + $str_UTF8 = '';
  498 + $mode = 0;
  499 + $b = unpack('C*', $str_JIS);
  500 + $n = count($b);
  501 +
  502 + for ($i = 1; $i <= $n; ++$i) {
  503 +
  504 + //Check escape sequence
  505 + while ($b[$i] == 0x1B) {
  506 + if (($b[$i+1] == 0x24 && $b[$i+2] == 0x42)
  507 + || ($b[$i+1] == 0x24 && $b[$i+2] == 0x40)) {
  508 + $mode = 1;
  509 + } elseif ($b[$i+1] == 0x28 && $b[$i+2] == 0x49) {
  510 + $mode = 2;
  511 + } else {
  512 + $mode = 0;
  513 + }
  514 + $i += 3;
  515 + if (!isset($b[$i])) break 2;
  516 + }
  517 +
  518 + if ($mode == 1) { //Zenkaku
  519 + $jis = ($b[$i] << 8) + $b[++$i];
  520 + if (isset($table_jis_utf8[$jis])) {
  521 + $utf8 = $table_jis_utf8[$jis];
  522 + if ($utf8 < 0xFFFF) {
  523 + $str_UTF8 .= chr($utf8 >> 8).chr($utf8);
  524 + } else {
  525 + $str_UTF8 .= chr($utf8 >> 16).chr($utf8 >> 8).chr($utf8);
  526 + }
  527 + } else { //Unknown
  528 + $str_UTF8 .= '?';
  529 + }
  530 + } elseif ($mode == 2) { //Hankaku
  531 + $b2 = $b[$i] + 0x40;
  532 + $u2 = 0xBC | (($b2 >> 6) & 0x03);
  533 + $u3 = 0x80 | ($b2 & 0x3F);
  534 + $str_UTF8 .= chr(0xEF).chr($u2).chr($u3);
  535 + } else { //ASCII
  536 + $str_UTF8 .= chr($b[$i]);
  537 + }
  538 + }
  539 +
  540 + return $str_UTF8;
  541 +}
  542 +
  543 +function UTF8toSJIS(&$str_UTF8)
  544 +{
  545 + global $table_utf8_jis;
  546 +
  547 + $str_SJIS = '';
  548 + $b = unpack('C*', $str_UTF8);
  549 + $n = count($b);
  550 +
  551 + for ($i = 1; $i <= $n; ++$i) {
  552 + if ($b[$i] >= 0x80) { //Not ASCII
  553 + if ($b[$i] <= 0xDF) { //2 Bytes
  554 + $utf8 = ($b[$i] << 8) + $b[++$i];
  555 + } else { //3 Bytes
  556 + $utf8 = ($b[$i] << 16) + ($b[++$i] << 8) + $b[++$i];
  557 + }
  558 + if (isset($table_utf8_jis[$utf8])) {
  559 + $jis = $table_utf8_jis[$utf8];
  560 + if ($jis < 0xFF) { //Hankaku
  561 + $str_SJIS .= chr($jis + 0x80);
  562 + } else { //Zenkaku
  563 + $b1 = $jis >> 8;
  564 + $b2 = $jis & 0xFF;
  565 + if ($b1 & 0x01) {
  566 + $b1 >>= 1;
  567 + if ($b1 < 0x2F) $b1 += 0x71; else $b1 -= 0x4F;
  568 + if ($b2 > 0x5F) $b2 += 0x20; else $b2 += 0x1F;
  569 + } else {
  570 + $b1 >>= 1;
  571 + if ($b1 <= 0x2F) $b1 += 0x70; else $b1 -= 0x50;
  572 + $b2 += 0x7E;
  573 + }
  574 + $str_SJIS .= chr($b1).chr($b2);
  575 + }
  576 + } else { //Unknown
  577 + $str_SJIS .= '?';
  578 + }
  579 + } else { //ASCII
  580 + $str_SJIS .= chr($b[$i]);
  581 + }
  582 + }
  583 +
  584 + return $str_SJIS;
  585 +}
  586 +
  587 +function UTF8toEUC(&$str_UTF8)
  588 +{
  589 + global $table_utf8_jis;
  590 +
  591 + $str_EUC = '';
  592 + $b = unpack('C*', $str_UTF8);
  593 + $n = count($b);
  594 +
  595 + for ($i = 1; $i <= $n; $i++) {
  596 + if ($b[$i] >= 0x80) { //Not ASCII
  597 + if ($b[$i] <= 0xDF) { //2 Bytes
  598 + $utf8 = ($b[$i++] << 8) + $b[$i];
  599 + } else { //3 Bytes
  600 + $utf8 = ($b[$i++] << 16) + ($b[$i++] << 8) + $b[$i];
  601 + }
  602 + if (isset($table_utf8_jis[$utf8])) {
  603 + $jis = $table_utf8_jis[$utf8];
  604 + if ($jis < 0xFF) { //Hankaku
  605 + $str_EUC .= chr(0x8E).chr($jis - 0x80);
  606 + } else { //Zenkaku
  607 + $str_EUC .= chr(($jis >> 8) - 0x80).chr(($jis & 0xFF) - 0x80);
  608 + }
  609 + } else { //Unknown
  610 + $str_EUC .= '?';
  611 + }
  612 + } else { //ASCII
  613 + $str_EUC .= chr($b[$i]);
  614 + }
  615 + }
  616 +
  617 + return $str_EUC;
  618 +}
  619 +
  620 +function UTF8toJIS(&$str_UTF8)
  621 +{
  622 + global $table_utf8_jis;
  623 +
  624 + $str_JIS = '';
  625 + $mode = 0;
  626 + $b = unpack('C*', $str_UTF8);
  627 + $n = count($b);
  628 +
  629 + //Escape sequence
  630 + $ESC = array(chr(0x1B).chr(0x28).chr(0x42),
  631 + chr(0x1B).chr(0x24).chr(0x42),
  632 + chr(0x1B).chr(0x28).chr(0x49));
  633 +
  634 + for ($i = 1; $i <= $n; ++$i) {
  635 + if ($b[$i] >= 0x80) { //Not ASCII
  636 + if ($b[$i] <= 0xDF) { //2 Bytes
  637 + $utf8 = ($b[$i] << 8) + $b[++$i];
  638 + } else { //3 Bytes
  639 + $utf8 = ($b[$i] << 16) + ($b[++$i] << 8) + $b[++$i];
  640 + }
  641 + if (isset($table_utf8_jis[$utf8])) {
  642 + $jis = $table_utf8_jis[$utf8];
  643 + if ($jis < 0xFF) { //Hankaku
  644 + if ($mode != 2) {
  645 + $mode = 2;
  646 + $str_JIS .= $ESC[$mode];
  647 + }
  648 + $str_JIS .= chr($jis);
  649 + } else { //Zenkaku
  650 + if ($mode != 1) {
  651 + $mode = 1;
  652 + $str_JIS .= $ESC[$mode];
  653 + }
  654 + $str_JIS .= chr($jis >> 8).chr($jis & 0xFF);
  655 + }
  656 + } else { //Unknown
  657 + if ($mode != 0) {
  658 + $mode = 0;
  659 + $str_JIS .= $ESC[$mode];
  660 + }
  661 + $str_JIS .= '?';
  662 + }
  663 + } else { //ASCII
  664 + if ($mode != 0) {
  665 + $mode = 0;
  666 + $str_JIS .= $ESC[$mode];
  667 + }
  668 + $str_JIS .= chr($b[$i]);
  669 + }
  670 + }
  671 + if ($mode != 0) $str_JIS .= $ESC[0];
  672 +
  673 + return $str_JIS;
  674 +}
  675 +
  676 +function HANtoZEN_EUC(&$str_HAN)
  677 +{
  678 + $table_han2zen_euc = array(0xA1A3,0xA1D6,0xA1D7,0xA1A2,0xA1A6,0xA5F2,
  679 + 0xA5A1,0xA5A3,0xA5A5,0xA5A7,0xA5A9,0xA5E3,0xA5E5,0xA5E7,0xA5C3,0xA1BC,
  680 + 0xA5A2,0xA5A4,0xA5A6,0xA5A8,0xA5AA,0xA5AB,0xA5AD,0xA5AF,0xA5B1,0xA5B3,
  681 + 0xA5B5,0xA5B7,0xA5B9,0xA5BB,0xA5BD,0xA5BF,0xA5C1,0xA5C4,0xA5C6,0xA5C8,
  682 + 0xA5CA,0xA5CB,0xA5CC,0xA5CD,0xA5CE,0xA5CF,0xA5D2,0xA5D5,0xA5D8,0xA5DB,
  683 + 0xA5DE,0xA5DF,0xA5E0,0xA5E1,0xA5E2,0xA5E4,0xA5E6,0xA5E8,0xA5E9,0xA5EA,
  684 + 0xA5EB,0xA5EC,0xA5ED,0xA5EF,0xA5F3,0xA1AB,0xA1AC);
  685 +
  686 + $str_ZEN = '';
  687 + $b = unpack('C*', $str_HAN);
  688 + $n = count($b);
  689 +
  690 + for ($i = 1; $i <= $n; ++$i) {
  691 + $b1 = $b[$i];
  692 + if ($b1 == 0x8E) {
  693 + $b2 = $b[++$i];
  694 + $ofs = 0;
  695 + if ((($b2 == 0xB3) || (0xB6 <= $b2 && $b2 <= 0xC4) || (0xCA <= $b2 && $b2 <= 0xCE))
  696 + && (isset($b[$i+1]) && $b[$i+1] == 0x8E)) {
  697 + // Dakuten
  698 + if ($b[$i+2] == 0xDE) {
  699 + if ($b2 == 0xB3) $ofs = 78; else $ofs = 1;
  700 + $i += 2;
  701 + // Han-Dakuten
  702 + } elseif (($b[$i+2] == 0xDF) && (0xCA <= $b2 && $b2 <= 0xCE)) {
  703 + $ofs = 2;
  704 + $i += 2;
  705 + }
  706 + }
  707 + $b2 -= 0xA1;
  708 + $c1 = (($table_han2zen_euc[$b2]) & 0xFF00) >> 8;
  709 + $c2 = (($table_han2zen_euc[$b2]) & 0x00FF) + $ofs;
  710 + $str_ZEN .= chr($c1).chr($c2);
  711 + } elseif ($b1 >= 0xA1) {
  712 + $str_ZEN .= chr($b1).chr($b[++$i]);
  713 + } else {
  714 + $str_ZEN .= chr($b1);
  715 + }
  716 + }
  717 +
  718 + return $str_ZEN;
  719 +}
  720 +
  721 +function HANtoZEN_SJIS(&$str_HAN)
  722 +{
  723 + $table_han2zen_sjis = array(0x8142,0x8175,0x8176,0x8141,0x8145,0x8392,
  724 + 0x8340,0x8342,0x8344,0x8346,0x8348,0x8383,0x8385,0x8387,0x8362,0x815B,
  725 + 0x8341,0x8343,0x8345,0x8347,0x8349,0x834A,0x834C,0x834E,0x8350,0x8352,
  726 + 0x8354,0x8356,0x8358,0x835A,0x835C,0x835E,0x8360,0x8363,0x8365,0x8367,
  727 + 0x8369,0x836A,0x836B,0x836C,0x836D,0x836E,0x8371,0x8374,0x8377,0x837A,
  728 + 0x837D,0x837E,0x8380,0x8381,0x8382,0x8384,0x8386,0x8388,0x8389,0x838A,
  729 + 0x838B,0x838C,0x838D,0x838F,0x8393,0x814A,0x814B);
  730 +
  731 + $str_ZEN = '';
  732 + $b = unpack('C*', $str_HAN);
  733 + $n = count($b);
  734 +
  735 + for ($i = 1; $i <= $n; ++$i) {
  736 + $b1 = $b[$i];
  737 + if (0xA1 <= $b1 && $b1 <= 0xDF) {
  738 + $ofs = 0;
  739 + if ((($b1 == 0xB3) || (0xB6 <= $b1 && $b1 <= 0xC4) || (0xCA <= $b1 && $b1 <= 0xCE))
  740 + && isset($b[$i+1])) {
  741 + // Dakuten
  742 + if ($b[$i+1] == 0xDE) {
  743 + if ($b1 == 0xB3) $ofs = 79; else $ofs = 1;
  744 + ++$i;
  745 + // Han-Dakuten
  746 + } elseif (($b[$i+1] == 0xDF) && (0xCA <= $b1 && $b1 <= 0xCE)) {
  747 + $ofs = 2;
  748 + ++$i;
  749 + }
  750 + }
  751 + $b1 -= 0xA1;
  752 + $c1 = (($table_han2zen_sjis[$b1]) & 0xFF00) >> 8;
  753 + $c2 = (($table_han2zen_sjis[$b1]) & 0x00FF) + $ofs;
  754 + $str_ZEN .= chr($c1).chr($c2);
  755 + } elseif ($b1 >= 0x80) {
  756 + $str_ZEN .= chr($b1).chr($b[++$i]);
  757 + } else {
  758 + $str_ZEN .= chr($b1);
  759 + }
  760 + }
  761 +
  762 + return $str_ZEN;
  763 +}
  764 +
  765 +function HANtoZEN_JIS(&$str_HAN)
  766 +{
  767 + $table_han2zen_jis = array(0x2123,0x2156,0x2157,0x2122,0x2126,0x2572,
  768 + 0x2521,0x2523,0x2525,0x2527,0x2529,0x2563,0x2565,0x2567,0x2543,0x213C,
  769 + 0x2522,0x2524,0x2526,0x2528,0x252A,0x252B,0x252D,0x252F,0x2531,0x2533,
  770 + 0x2535,0x2537,0x2539,0x253B,0x253D,0x253F,0x2541,0x2544,0x2546,0x2548,
  771 + 0x254A,0x254B,0x254C,0x254D,0x254E,0x254F,0x2552,0x2555,0x2558,0x255B,
  772 + 0x255E,0x255F,0x2560,0x2561,0x2562,0x2564,0x2566,0x2568,0x2569,0x256A,
  773 + 0x256B,0x256C,0x256D,0x256F,0x2573,0x212B,0x212C);
  774 +
  775 + $str_ZEN = '';
  776 + $b = unpack('C*', $str_HAN);
  777 + $n = count($b);
  778 + $mode = 0;
  779 + $new_mode = 0;
  780 + $esc = FALSE;
  781 + $ESC = array(chr(0x1B).chr(0x28).chr(0x42),
  782 + chr(0x1B).chr(0x24).chr(0x42),
  783 + chr(0x1B).chr(0x28).chr(0x49));
  784 +
  785 + for ($i = 1; $i <= $n; ++$i) {
  786 +
  787 + while ($b[$i] == 0x1B) {
  788 + if (($b[$i+1] == 0x24 && $b[$i+2] == 0x42)
  789 + || ($b[$i+1] == 0x24 && $b[$i+2] == 0x40)) {
  790 + $mode = 1; //Zenkaku
  791 + } elseif ($b[$i+1] == 0x28 && $b[$i+2] == 0x49) {
  792 + $mode = 2; //Hankaku
  793 + } else {
  794 + $mode = 0; //ASCII
  795 + }
  796 + $i += 3;
  797 + if (!isset($b[$i])) break 2;
  798 + }
  799 +
  800 + if ($mode == 2) {
  801 + if ($new_mode != 1) $esc = TRUE;
  802 + $new_mode = 1;
  803 + $b1 = $b[$i];
  804 + $ofs = 0;
  805 + if ((($b1 == 0x33) || (0x36 <= $b1 && $b1 <= 0x44) || (0x4A <= $b1 && $b1 <= 0x4E))
  806 + && isset($b[$i+1])) {
  807 + // Dakuten
  808 + if ($b[$i+1] == 0x5E) {
  809 + if ($b1 == 0x33) $ofs = 78; else $ofs = 1;
  810 + ++$i;
  811 + // Han-Dakuten
  812 + } elseif (($b[$i+1] == 0x5F) && (0x4A <= $b1 && $b1 <= 0x4E) ) {
  813 + $ofs = 2;
  814 + ++$i;
  815 + }
  816 + }
  817 + $b1 -= 0x21;
  818 + $c1 = ($table_han2zen_jis[$b1] & 0xFF00) >> 8;
  819 + $c2 = ($table_han2zen_jis[$b1] & 0x00FF) + $ofs;
  820 + $str = chr($c1).chr($c2);
  821 + } else {
  822 + if ($new_mode != $mode) $esc = TRUE;
  823 + $new_mode = $mode;
  824 + $str = chr($b[$i]);
  825 + }
  826 +
  827 + if ($esc) { //add escape sequence
  828 + $str_ZEN .= $ESC[$new_mode];
  829 + $esc = FALSE;
  830 + }
  831 + $str_ZEN .= $str;
  832 + }
  833 +
  834 + if ($new_mode != 0) $str_ZEN .= $ESC[0];
  835 +
  836 + return $str_ZEN;
  837 +}
  838 +
  839 +function HANtoZEN_UTF8(&$str_HAN)
  840 +{
  841 + $table_han2zen_utf8_1 = array(0xE38082,0xE3808C,0xE3808D,0xE38081,0xE383BB,
  842 + 0xE383B2,0xE382A1,0xE382A3,0xE382A5,0xE382A7,0xE382A9,0xE383A3,0xE383A5,
  843 + 0xE383A7,0xE38383,0xE383BC,0xE382A2,0xE382A4,0xE382A6,0xE382A8,0xE382AA,
  844 + 0xE382AB,0xE382AD,0xE382AF,0xE382B1,0xE382B3,0xE382B5,0xE382B7,0xE382B9,
  845 + 0xE382BB,0xE382BD);
  846 +
  847 + $table_han2zen_utf8_2 = array(0xE382BF,0xE38381,0xE38384,0xE38386,0xE38388,
  848 + 0xE3838A,0xE3838B,0xE3838C,0xE3838D,0xE3838E,0xE3838F,0xE38392,0xE38395,
  849 + 0xE38398,0xE3839B,0xE3839E,0xE3839F,0xE383A0,0xE383A1,0xE383A2,0xE383A4,
  850 + 0xE383A6,0xE383A8,0xE383A9,0xE383AA,0xE383AB,0xE383AC,0xE383AD,0xE383AF,
  851 + 0xE383B3,0xE3829B,0xE3829C);
  852 +
  853 + $str_ZEN = '';
  854 + $b = unpack('C*', $str_HAN);
  855 + $n = count($b);
  856 +
  857 + for ($i = 1; $i <= $n; ++$i) {
  858 + if ($b[$i] >= 0x80) {
  859 + if (($b[$i] & 0xE0) == 0xC0) {
  860 + $str_ZEN .= chr($b[$i]).chr($b[++$i]);
  861 + } elseif (($b[$i] & 0xF0) == 0xE0) {
  862 + if ($b[$i+1] == 0xBD && (0xA1 <= $b[$i+2] && $b[$i+2] <= 0xBF)) {
  863 + $zen = $table_han2zen_utf8_1[$b[$i+2] - 0xA1];
  864 + $b[$i] = ($zen & 0xFF0000) >> 16;
  865 + $b[$i+1] = ($zen & 0x00FF00) >> 8;
  866 + $b[$i+2] = $zen & 0x0000FF;
  867 + } elseif ($b[$i+1] == 0xBE && (0x80 <= $b[$i+2] && $b[$i+2] <= 0x9F)) {
  868 + $zen = $table_han2zen_utf8_2[$b[$i+2] - 0x80];
  869 + $b[$i] = ($zen & 0xFF0000) >> 16;
  870 + $b[$i+1] = ($zen & 0x00FF00) >> 8;
  871 + $b[$i+2] = $zen & 0x0000FF;
  872 + }
  873 + $str_ZEN .= chr($b[$i]).chr($b[++$i]).chr($b[++$i]);
  874 + }
  875 + } else {
  876 + $str_ZEN .= chr($b[$i]);
  877 + }
  878 + }
  879 +
  880 + return $str_ZEN;
  881 +}
  882 +
  883 +function ZENtoHAN_EUC(&$str_ZEN, $kana = 1, $alph = 1, $sym = 1)
  884 +{
  885 + $kana_euc = array(
  886 + 0x00A7,0x00B1,0x00A8,0x00B2,0x00A9,0x00B3,0x00AA,0x00B4,0x00AB,0x00B5,
  887 + 0x00B6,0xB6DE,0x00B7,0xB7DE,0x00B8,0xB8DE,0x00B9,0xB9DE,0x00BA,0xBADE,
  888 + 0x00BB,0xBBDE,0x00BC,0xBCDE,0x00BD,0xBDDE,0x00BE,0xBEDE,0x00BF,0xBFDE,
  889 + 0x00C0,0xC0DE,0x00C1,0xC1DE,0x00AF,0x00C2,0xC2DE,0x00C3,0xC3DE,0x00C4,
  890 + 0xC4DE,0x00C5,0x00C6,0x00C7,0x00C8,0x00C9,0x00CA,0xCADE,0xCADF,0x00CB,
  891 + 0xCBDE,0xCBDF,0x00CC,0xCCDE,0xCCDF,0x00CD,0xCDDE,0xCDDF,0x00CE,0xCEDE,
  892 + 0xCEDF,0x00CF,0x00D0,0x00D1,0x00D2,0x00D3,0x00AC,0x00D4,0x00AD,0x00D5,
  893 + 0x00AE,0x00D6,0x00D7,0x00D8,0x00D9,0x00DA,0x00DB,0x0000,0x00DC,0x0000,
  894 + 0x0000,0x00A6,0x00DD,0xB3DE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  895 + 0x0000,0x0000,0x0000,0x0000,0x0000
  896 + );
  897 +
  898 + $sym_euc = array(
  899 + 0x0020,0x8EA4,0x8EA1,0x0000,0x0000,0x8EA5,0x0000,0x0000,0x0000,0x0000,
  900 + 0x8EDE,0x8EDF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  901 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8EB0,0x0000,0x0000,
  902 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  903 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  904 + 0x0000,0x0000,0x0000,0x8EA2,0x8EA3,0x0000,0x0000,0x0000,0x0000,0x0000,
  905 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  906 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  907 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  908 + 0x0000,0x0000,0x0000,0x0000,0x0000
  909 + );
  910 +
  911 + $str_HAN = '';
  912 + $b = unpack('C*', $str_ZEN);
  913 + $n = count($b);
  914 +
  915 + for ($i = 1; $i <= $n; ++$i) {
  916 + $b1 = $b[$i];
  917 + if ($b1 >= 0x80) {
  918 + ++$i;
  919 + if ($kana == 1 && $b1 == 0xA5) { // Katakana
  920 + $c = $b[$i] - 0xA1;
  921 + $c1 = ($kana_euc[$c] & 0xFF00) >> 8;
  922 + $c2 = $kana_euc[$c] & 0x00FF;
  923 + if ($c1 == 0x00) {
  924 + if ($c2 == 0x00) {
  925 + $str_HAN .= chr($b1).chr($b[$i]);
  926 + } else {
  927 + $str_HAN .= chr(0x8E).chr($c2);
  928 + }
  929 + } else {
  930 + $str_HAN .= chr(0x8E).chr($c1).chr(0x8E).chr($c2);
  931 + }
  932 + } elseif ($sym == 1 && $b1 == 0xA1) { // Symbol
  933 + $c = $b[$i] - 0xA1;
  934 + $c1 = ($sym_euc[$c] & 0xFF00) >> 8;
  935 + $c2 = $sym_euc[$c] & 0x00FF;
  936 + if ($c1 == 0x00) {
  937 + if ($c2 == 0x00) {
  938 + $str_HAN .= chr($b1).chr($b[$i]);
  939 + } else {
  940 + $str_HAN .= chr($c2);
  941 + }
  942 + } else {
  943 + $str_HAN .= chr($c1).chr($c2);
  944 + }
  945 + } elseif ( $alph == 1 && $b1 == 0xA3 ) { // Alphabet & Number
  946 + $str_HAN .= chr($b[$i] - 0x80);
  947 + } else { // Rest of Zenkaku
  948 + $str_HAN .= chr($b1).chr($b[$i]);
  949 + }
  950 + } else { // ASCII
  951 + $str_HAN .= chr($b1);
  952 + }
  953 + }
  954 +
  955 + return $str_HAN;
  956 +}
  957 +
  958 +function ZENtoHAN_SJIS(&$str_ZEN, $kana = 1, $alph = 1, $sym = 1)
  959 +{
  960 + $kana_sjis = array(
  961 + 0x00A7,0x00B1,0x00A8,0x00B2,0x00A9,0x00B3,0x00AA,0x00B4,0x00AB,0x00B5,
  962 + 0x00B6,0xB6DE,0x00B7,0xB7DE,0x00B8,0xB8DE,0x00B9,0xB9DE,0x00BA,0xBADE,
  963 + 0x00BB,0xBBDE,0x00BC,0xBCDE,0x00BD,0xBDDE,0x00BE,0xBEDE,0x00BF,0xBFDE,
  964 + 0x00C0,0xC0DE,0x00C1,0xC1DE,0x00AF,0x00C2,0xC2DE,0x00C3,0xC3DE,0x00C4,
  965 + 0xC4DE,0x00C5,0x00C6,0x00C7,0x00C8,0x00C9,0x00CA,0xCADE,0xCADF,0x00CB,
  966 + 0xCBDE,0xCBDF,0x00CC,0xCCDE,0xCCDF,0x00CD,0xCDDE,0xCDDF,0x00CE,0xCEDE,
  967 + 0xCEDF,0x00CF,0x00D0,0x0000,0x00D1,0x00D2,0x00D3,0x00AC,0x00D4,0x00AD,
  968 + 0x00D5,0x00AE,0x00D6,0x00D7,0x00D8,0x00D9,0x00DA,0x00DB,0x0000,0x00DC,
  969 + 0x0000,0x0000,0x00A6,0x00DD,0xB3DE,0x0000,0x0000,0x0000,0x0000,0x0000,
  970 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  971 + );
  972 +
  973 + $sym_sjis = array(
  974 + 0x20,0xA4,0xA1,0x00,0x00,0xA5,0x00,0x00,0x00,0x00,0xDE,0xDF,0x00,0x00,
  975 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,
  976 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  977 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xA3,0x00,
  978 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  979 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  980 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  981 + );
  982 +
  983 + $str_HAN = '';
  984 + $b = unpack('C*', $str_ZEN);
  985 + $n = count($b);
  986 +
  987 + for ($i = 1; $i <= $n; ++$i) {
  988 + $b1 = $b[$i];
  989 + if ($b1 >= 0x80) {
  990 + $b2 = $b[++$i];
  991 + if ($kana == 1 && $b1 == 0x83 // Katakana
  992 + && (0x3F < $b2 && $b2 < 0x9F)) {
  993 + $c = $b2 - 0x40;
  994 + $c1 = ($kana_sjis[$c] & 0xFF00) >> 8;
  995 + $c2 = $kana_sjis[$c] & 0x00FF;
  996 + if ($c1 == 0x00) {
  997 + if ($c2 == 0x00) {
  998 + $str_HAN .= chr($b1).chr($b2);
  999 + } else {
  1000 + $str_HAN .= chr($c2);
  1001 + }
  1002 + } else {
  1003 + $str_HAN .= chr($c1).chr($c2);
  1004 + }
  1005 + } elseif ($sym == 1 && $b1 == 0x81 // Symbol
  1006 + && (0x3F < $b2 && $b2 < 0x9F)) {
  1007 + $c1 = $sym_sjis[ $b2 - 0x40 ];
  1008 + if ($c1 == 0x00) {
  1009 + $str_HAN .= chr($b1).chr($b2);
  1010 + } else {
  1011 + $str_HAN .= chr($c1);
  1012 + }
  1013 + } elseif ($alph == 1 && $b1 == 0x82 // Alphabet & Number
  1014 + && (0x3F < $b2 && $b2 < 0x9F)) {
  1015 + if ($b2 < 0x80) {
  1016 + $str_HAN .= chr($b2 - 0x1F);
  1017 + } else {
  1018 + $str_HAN .= chr($b2 - 0x20);
  1019 + }
  1020 + } else { // Rest of Zenkaku
  1021 + $str_HAN .= chr($b1).chr($b2);
  1022 + }
  1023 + } else { // ASCII
  1024 + $str_HAN .= chr($b1);
  1025 + }
  1026 + }
  1027 +
  1028 + return $str_HAN;
  1029 +}
  1030 +
  1031 +function ZENtoHAN_JIS(&$str_ZEN, $kana = 1, $alph = 1, $sym = 1)
  1032 +{
  1033 + $kana_jis = array(
  1034 + 0x0027,0x0031,0x0028,0x0032,0x0029,0x0033,0x002A,0x0034,0x002B,0x0035,
  1035 + 0x0036,0x365E,0x0037,0x375E,0x0038,0x385E,0x0039,0x395E,0x003A,0x3A5E,
  1036 + 0x003B,0x3B5E,0x003C,0x3C5E,0x003D,0x3D5E,0x003E,0x3E5E,0x003F,0x3F5E,
  1037 + 0x0040,0x405E,0x0041,0x415E,0x002F,0x0042,0x425E,0x0043,0x435E,0x0044,
  1038 + 0x445E,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x4A5E,0x4A5F,0x004B,
  1039 + 0x4B5E,0x4B5F,0x004C,0x4C5E,0x4C5F,0x004D,0x4D5E,0x4D5F,0x004E,0x4E5E,
  1040 + 0x4E5F,0x004F,0x0050,0x0051,0x0052,0x0053,0x002C,0x0054,0x002D,0x0055,
  1041 + 0x002E,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x0000,0x005C,0x0000,
  1042 + 0x0000,0x0026,0x005D,0x335E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  1043 + 0x0000,0x0000,0x0000,0x0000,0x0000
  1044 + );
  1045 +
  1046 + $sym_jis = array(
  1047 + 0x0020,0xFF24,0xFF21,0x0000,0x0000,0xFF25,0x0000,0x0000,0x0000,0x0000,
  1048 + 0xFF5E,0xFF5F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  1049 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFF30,0x0000,0x0000,
  1050 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  1051 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  1052 + 0x0000,0x0000,0x0000,0xFF22,0xFF23,0x0000,0x0000,0x0000,0x0000,0x0000,
  1053 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  1054 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  1055 + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  1056 + 0x0000,0x0000,0x0000,0x0000,0x0000
  1057 + );
  1058 +
  1059 + $str_HAN = '';
  1060 + $b = unpack('C*', $str_ZEN);
  1061 + $n = count($b);
  1062 + $mode = 0;
  1063 + $new_mode = 0;
  1064 + $esc = FALSE;
  1065 + $ESC = array(chr(0x1B).chr(0x28).chr(0x42),
  1066 + chr(0x1B).chr(0x24).chr(0x42),
  1067 + chr(0x1B).chr(0x28).chr(0x49));
  1068 +
  1069 + for ($i = 1; $i <= $n; ++$i) {
  1070 + while ($b[$i] == 0x1B) {
  1071 + if (($b[$i+1] == 0x24 && $b[$i+2] == 0x42)
  1072 + || ($b[$i+1] == 0x24 && $b[$i+2] == 0x40)) {
  1073 + $mode = 1;
  1074 + } elseif ($b[$i+1] == 0x28 && $b[$i+2] == 0x49) {
  1075 + $mode = 2;
  1076 + } else {
  1077 + $mode = 0;
  1078 + }
  1079 + $i += 3;
  1080 + if (!isset($b[$i])) break 2;
  1081 + }
  1082 +
  1083 + $b1 = $b[$i];
  1084 + if ($mode == 1) { //Zenkaku
  1085 + ++$i;
  1086 + if ($alph == 1 && $b1 == 0x23) { //Alphabet & Number
  1087 + if ($new_mode != 0) $esc = TRUE;
  1088 + $new_mode = 0;
  1089 + $str = chr($b[$i]);
  1090 + } elseif ($sym == 1 && $b1 == 0x21) { //Symbol
  1091 + $c = $b[$i] - 0x21;
  1092 + $c1 = ($sym_jis[$c] & 0xFF00) >> 8;
  1093 + $c2 = $sym_jis[$c] & 0x00FF;
  1094 + if ($c1 == 0x00) {
  1095 + if ($c2 == 0x00) {
  1096 + if ($new_mode != 1) $esc = TRUE;
  1097 + $new_mode = 1;
  1098 + $str = chr($b1).chr($b[$i]);
  1099 + } else {
  1100 + if ($new_mode != 0) $esc = true;
  1101 + $new_mode = 0;
  1102 + $str = chr($c2);
  1103 + }
  1104 + } else {
  1105 + if ($new_mode != 2) $esc = TRUE;
  1106 + $new_mode = 2;
  1107 + $str = chr($c2);
  1108 + }
  1109 + } elseif ($kana == 1 && $b1 == 0x25) { //Katakana
  1110 + $c = $b[$i] - 0x21;
  1111 + $c1 = ($kana_jis[$c] & 0xFF00) >> 8;
  1112 + $c2 = $kana_jis[$c] & 0x00FF;
  1113 + if ($c1 == 0x00) {
  1114 + if ($c2 == 0x00) {
  1115 + if ($new_mode != 1) $esc = TRUE;
  1116 + $new_mode = 1;
  1117 + $str = chr($b1).chr($b[$i]);
  1118 + } else {
  1119 + if ($new_mode != 2) $esc = TRUE;
  1120 + $new_mode = 2;
  1121 + $str = chr($c2);
  1122 + }
  1123 + } else {
  1124 + if ($new_mode != 2) $esc = TRUE;
  1125 + $new_mode = 2;
  1126 + $str = chr($c1).chr($c2);
  1127 + }
  1128 + } else {
  1129 + if ($new_mode != 1) $esc = TRUE;
  1130 + $new_mode = 1;
  1131 + $str = chr($b1).chr($b[$i]);
  1132 + }
  1133 + } elseif ($mode == 2) {
  1134 + if ($new_mode != 2) $esc = TRUE;
  1135 + $new_mode = 2;
  1136 + $str = chr($b1);
  1137 + } else {
  1138 + if ($new_mode != 0) $esc = TRUE;
  1139 + $new_mode = 0;
  1140 + $str = chr($b1);
  1141 + }
  1142 +
  1143 + if ($esc) { //add escape sequense
  1144 + $str_HAN .= $ESC[$new_mode];
  1145 + $esc = FALSE;
  1146 + }
  1147 + $str_HAN .= $str;
  1148 + }
  1149 +
  1150 + if ($new_mode != 0) $str_HAN .= $ESC[0];
  1151 +
  1152 + return $str_HAN;
  1153 +}
  1154 +
  1155 +
  1156 +/*
  1157 + O-MA-KE No.1
  1158 + jsubstr() - substr() function for japanese(euc-jp)
  1159 + for using shift_jis encoding, remove comment string.
  1160 +*/
  1161 +function jsubstr($str, $start = 0, $length = 0)
  1162 +{
  1163 + $b = unpack('C*', $str);
  1164 + $m = count($b);
  1165 +
  1166 + for ($i = 1; $i <= $m; ++$i) {
  1167 + if ($b[$i] >= 0x80) { //Japanese
  1168 +// if ( 0xA0 < $b[$i] && $b[$i] < 0xE0 ) { //SJIS Hankaku
  1169 +// $jstr[] = chr($b[$i]);
  1170 +// } else {
  1171 + $jstr[] = chr($b[$i]).chr($b[++$i]);
  1172 +// }
  1173 + } else { //ASCII
  1174 + $jstr[] = chr($b[$i]);
  1175 + }
  1176 + }
  1177 + if (!isset($jstr)) $jstr[] = '';
  1178 +
  1179 + $n = count($jstr);
  1180 + if ($start < 0) $start += $n;
  1181 + if ($length < 0) $end = $n + $length; else $end = $start + $length;
  1182 + if ($end > $n) $end = $n;
  1183 +
  1184 + $s = '';
  1185 + for ($j = $start; $j < $end; ++$j) $s .= $jstr[$j];
  1186 +
  1187 + return $s;
  1188 +}
  1189 +
  1190 +/*
  1191 + O-MA-KE No.2
  1192 + jstrlen() - strlen() function for japanese(euc-jp)
  1193 + for using shift_jis encoding, remove comment string.
  1194 +*/
  1195 +function jstrlen($str)
  1196 +{
  1197 + $b = unpack('C*', $str);
  1198 + $n = count($b);
  1199 + $l = 0;
  1200 +
  1201 + for ($i = 1; $i <= $n; ++$i) {
  1202 + if ($b[$i] >= 0x80
  1203 +// && ($b[$i] <= 0xA0 || $b[$i] >= 0xE0) //exclude SJIS Hankaku
  1204 + ) {
  1205 + ++$i;
  1206 + }
  1207 + ++$l;
  1208 + }
  1209 +
  1210 + return $l;
  1211 +}
  1212 +
  1213 +/*
  1214 + O-MA-KE No.3
  1215 + jstr_replace() - str_replace() function for japanese(euc-jp)
  1216 + for using shift_jis encoding, remove comment string.
  1217 +*/
  1218 +function jstr_replace($before, $after, $str)
  1219 +{
  1220 + $b = unpack('C*', $str);
  1221 + $n = strlen($str);
  1222 + $l = strlen($before);
  1223 + if ($l == 0) $l = 1;
  1224 + $s = '';
  1225 + $i = 1;
  1226 +
  1227 + while($i <= $n) {
  1228 + for ($j = 0; $j < $l; $k = $i + (++$j)) {
  1229 + if ($b[$k] >= 0x80) { //Japanese
  1230 +// if ( 0xA0 < $b[$k] && $b[$k] < 0xE0 ) { //SJIS Hankaku
  1231 +// $c[] = chr($b[$k]);
  1232 +// } else {
  1233 + $c[] = chr($b[$k]).chr($b[$k+1]);
  1234 + $k = $i + (++$j);
  1235 +// }
  1236 + } else { //ASCII
  1237 + $c[] = chr($b[$k]);
  1238 + }
  1239 + if (!isset($b[$k+1])) break;
  1240 + }
  1241 + if ($before == implode('', $c)) {
  1242 + $s .= $after; //replace
  1243 + $i += $l;
  1244 + } else {
  1245 + $s .= $c[0];
  1246 + $i += strlen($c[0]);
  1247 + }
  1248 + unset($c);
  1249 + }
  1250 +
  1251 + return $s;
  1252 +}
  1253 +
  1254 +/*
  1255 + O-MA-KE No.4
  1256 + jchunk_split() - This function is similar to chunk_split()
  1257 + and is designed for euc-jp encoding.
  1258 +*/
  1259 +function jchunk_split($str, $width = 76, $end = "\r\n")
  1260 +{
  1261 + if ($width < 1) return '';
  1262 +
  1263 + $b = unpack('C*', $str);
  1264 + $n = count($b);
  1265 + $s = '';
  1266 + $l = 0;
  1267 +
  1268 + for ($i = 1; $i <= $n; ++$i) {
  1269 +
  1270 + if ($b[$i] >= 0x80) { // 8bit (Japanese)
  1271 +// if ( 0xA0 < $b[$i] && $b[$i] < 0xE0 ) { // SJIS Hankaku
  1272 +// $c = chr($b[$i]);
  1273 +// $w = 1;
  1274 +// } else {
  1275 + if ($b[$i] == 0x8E) { // EUC-JP Hankaku
  1276 + $w = 1;
  1277 + } else { // Zenkaku
  1278 + $w = 2;
  1279 + }
  1280 + $c = chr($b[$i]).chr($b[++$i]);
  1281 +// }
  1282 + } else { // 7bit (ASCII)
  1283 + $w = 1;
  1284 + $c = chr($b[$i]);
  1285 + }
  1286 +
  1287 + if (($l += $w) > $width) {
  1288 + $l = $w;
  1289 + $s .= $end;
  1290 + }
  1291 +
  1292 + $s .= $c;
  1293 + }
  1294 +
  1295 + return $s;
  1296 +}
  1297 +
  1298 +/*
  1299 + O-MA-KE No.5
  1300 + jstrcut() - This function is similar to mb_strcut() and substr(),
  1301 + and is designed for euc-jp encoding.
  1302 +*/
  1303 +function jstrcut($str, $start, $len = 0)
  1304 +{
  1305 + $b = unpack('C*', $str);
  1306 + $n = count($b);
  1307 + $s = '';
  1308 + $c = '';
  1309 + $l = 0;
  1310 +
  1311 + if ($start < 0) $start += $n;
  1312 + if ($start < 0) $start = 0;
  1313 +
  1314 + if ($len == 0) $len = $n;
  1315 + if ($len < 0) $len += ($n - $start);
  1316 + if ($len > $n) $len = $n;
  1317 + if ($len < 1) return '';
  1318 +
  1319 + for ($i = 1; $i <= $n; ++$i) {
  1320 +
  1321 + if ($b[$i] >= 0x80) { // 8bit (Japanese)
  1322 +// if ( 0xA0 < $b[$i] && $b[$i] < 0xE0 ) { // SJIS Hankaku
  1323 +// $c = chr($b[$i]);
  1324 +// $w = 1;
  1325 +// } else {
  1326 + if ($b[$i] == 0x8E) { // EUC-JP Hankaku
  1327 + $w = 1;
  1328 + } else { // Zenkaku
  1329 + $w = 2;
  1330 + }
  1331 + $c = chr($b[$i]).chr($b[++$i]);
  1332 +// }
  1333 + } else { // 7bit (ASCII)
  1334 + $w = 1;
  1335 + $c = chr($b[$i]);
  1336 + }
  1337 +
  1338 + if ($i > $start) {
  1339 + $l += $w;
  1340 + if ($l > $len) break;
  1341 + $s .= $c;
  1342 + }
  1343 +
  1344 + }
  1345 +
  1346 + return $s;
  1347 +}
  1348 +
  1349 +?>
  1 +<?php
  2 + require_once('./lib/smarty/Smarty.class.php');
  3 + $o_smarty=new Smarty();
  4 + $o_smarty->template_dir='./templates/';
  5 + $o_smarty->compile_dir='./templates_c/';
  6 +?>
  1 +<?php
  2 +//
  3 +// +----------------------------------------------------------------------+
  4 +// | PHP Version 4 |
  5 +// +----------------------------------------------------------------------+
  6 +// | Copyright (c) 1997-2003 The PHP Group |
  7 +// +----------------------------------------------------------------------+
  8 +// | This source file is subject to version 2.0 of the PHP license, |
  9 +// | that is bundled with this package in the file LICENSE, and is |
  10 +// | available at through the world-wide-web at |
  11 +// | http://www.php.net/license/2_02.txt. |
  12 +// | If you did not receive a copy of the PHP license and are unable to |
  13 +// | obtain it through the world-wide-web, please send a note to |
  14 +// | license@php.net so we can mail you a copy immediately. |
  15 +// +----------------------------------------------------------------------+
  16 +// | Authors: Stig Bakken <ssb@php.net> |
  17 +// | Chuck Hagenbuch <chuck@horde.org> |
  18 +// +----------------------------------------------------------------------+
  19 +//
  20 +// $Id: Socket.php,v 1.38 2008/02/15 18:24:17 chagenbu Exp $
  21 +
  22 +require_once 'PEAR.php';
  23 +
  24 +define('NET_SOCKET_READ', 1);
  25 +define('NET_SOCKET_WRITE', 2);
  26 +define('NET_SOCKET_ERROR', 4);
  27 +
  28 +/**
  29 + * Generalized Socket class.
  30 + *
  31 + * @version 1.1
  32 + * @author Stig Bakken <ssb@php.net>
  33 + * @author Chuck Hagenbuch <chuck@horde.org>
  34 + */
  35 +class Net_Socket extends PEAR {
  36 +
  37 + /**
  38 + * Socket file pointer.
  39 + * @var resource $fp
  40 + */
  41 + var $fp = null;
  42 +
  43 + /**
  44 + * Whether the socket is blocking. Defaults to true.
  45 + * @var boolean $blocking
  46 + */
  47 + var $blocking = true;
  48 +
  49 + /**
  50 + * Whether the socket is persistent. Defaults to false.
  51 + * @var boolean $persistent
  52 + */
  53 + var $persistent = false;
  54 +
  55 + /**
  56 + * The IP address to connect to.
  57 + * @var string $addr
  58 + */
  59 + var $addr = '';
  60 +
  61 + /**
  62 + * The port number to connect to.
  63 + * @var integer $port
  64 + */
  65 + var $port = 0;
  66 +
  67 + /**
  68 + * Number of seconds to wait on socket connections before assuming
  69 + * there's no more data. Defaults to no timeout.
  70 + * @var integer $timeout
  71 + */
  72 + var $timeout = false;
  73 +
  74 + /**
  75 + * Number of bytes to read at a time in readLine() and
  76 + * readAll(). Defaults to 2048.
  77 + * @var integer $lineLength
  78 + */
  79 + var $lineLength = 2048;
  80 +
  81 + /**
  82 + * Connect to the specified port. If called when the socket is
  83 + * already connected, it disconnects and connects again.
  84 + *
  85 + * @param string $addr IP address or host name.
  86 + * @param integer $port TCP port number.
  87 + * @param boolean $persistent (optional) Whether the connection is
  88 + * persistent (kept open between requests
  89 + * by the web server).
  90 + * @param integer $timeout (optional) How long to wait for data.
  91 + * @param array $options See options for stream_context_create.
  92 + *
  93 + * @access public
  94 + *
  95 + * @return boolean | PEAR_Error True on success or a PEAR_Error on failure.
  96 + */
  97 + function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null)
  98 + {
  99 + if (is_resource($this->fp)) {
  100 + @fclose($this->fp);
  101 + $this->fp = null;
  102 + }
  103 +
  104 + if (!$addr) {
  105 + return $this->raiseError('$addr cannot be empty');
  106 + } elseif (strspn($addr, '.0123456789') == strlen($addr) ||
  107 + strstr($addr, '/') !== false) {
  108 + $this->addr = $addr;
  109 + } else {
  110 + $this->addr = @gethostbyname($addr);
  111 + }
  112 +
  113 + $this->port = $port % 65536;
  114 +
  115 + if ($persistent !== null) {
  116 + $this->persistent = $persistent;
  117 + }
  118 +
  119 + if ($timeout !== null) {
  120 + $this->timeout = $timeout;
  121 + }
  122 +
  123 + $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
  124 + $errno = 0;
  125 + $errstr = '';
  126 + $old_track_errors = @ini_set('track_errors', 1);
  127 + if ($options && function_exists('stream_context_create')) {
  128 + if ($this->timeout) {
  129 + $timeout = $this->timeout;
  130 + } else {
  131 + $timeout = 0;
  132 + }
  133 + $context = stream_context_create($options);
  134 +
  135 + // Since PHP 5 fsockopen doesn't allow context specification
  136 + if (function_exists('stream_socket_client')) {
  137 + $flags = $this->persistent ? STREAM_CLIENT_PERSISTENT : STREAM_CLIENT_CONNECT;
  138 + $addr = $this->addr . ':' . $this->port;
  139 + $fp = stream_socket_client($addr, $errno, $errstr, $timeout, $flags, $context);
  140 + } else {
  141 + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
  142 + }
  143 + } else {
  144 + if ($this->timeout) {
  145 + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
  146 + } else {
  147 + $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
  148 + }
  149 + }
  150 +
  151 + if (!$fp) {
  152 + if ($errno == 0 && isset($php_errormsg)) {
  153 + $errstr = $php_errormsg;
  154 + }
  155 + @ini_set('track_errors', $old_track_errors);
  156 + return $this->raiseError($errstr, $errno);
  157 + }
  158 +
  159 + @ini_set('track_errors', $old_track_errors);
  160 + $this->fp = $fp;
  161 +
  162 + return $this->setBlocking($this->blocking);
  163 + }
  164 +
  165 + /**
  166 + * Disconnects from the peer, closes the socket.
  167 + *
  168 + * @access public
  169 + * @return mixed true on success or a PEAR_Error instance otherwise
  170 + */
  171 + function disconnect()
  172 + {
  173 + if (!is_resource($this->fp)) {
  174 + return $this->raiseError('not connected');
  175 + }
  176 +
  177 + @fclose($this->fp);
  178 + $this->fp = null;
  179 + return true;
  180 + }
  181 +
  182 + /**
  183 + * Find out if the socket is in blocking mode.
  184 + *
  185 + * @access public
  186 + * @return boolean The current blocking mode.
  187 + */
  188 + function isBlocking()
  189 + {
  190 + return $this->blocking;
  191 + }
  192 +
  193 + /**
  194 + * Sets whether the socket connection should be blocking or
  195 + * not. A read call to a non-blocking socket will return immediately
  196 + * if there is no data available, whereas it will block until there
  197 + * is data for blocking sockets.
  198 + *
  199 + * @param boolean $mode True for blocking sockets, false for nonblocking.
  200 + * @access public
  201 + * @return mixed true on success or a PEAR_Error instance otherwise
  202 + */
  203 + function setBlocking($mode)
  204 + {
  205 + if (!is_resource($this->fp)) {
  206 + return $this->raiseError('not connected');
  207 + }
  208 +
  209 + $this->blocking = $mode;
  210 + socket_set_blocking($this->fp, $this->blocking);
  211 + return true;
  212 + }
  213 +
  214 + /**
  215 + * Sets the timeout value on socket descriptor,
  216 + * expressed in the sum of seconds and microseconds
  217 + *
  218 + * @param integer $seconds Seconds.
  219 + * @param integer $microseconds Microseconds.
  220 + * @access public
  221 + * @return mixed true on success or a PEAR_Error instance otherwise
  222 + */
  223 + function setTimeout($seconds, $microseconds)
  224 + {
  225 + if (!is_resource($this->fp)) {
  226 + return $this->raiseError('not connected');
  227 + }
  228 +
  229 + return socket_set_timeout($this->fp, $seconds, $microseconds);
  230 + }
  231 +
  232 + /**
  233 + * Sets the file buffering size on the stream.
  234 + * See php's stream_set_write_buffer for more information.
  235 + *
  236 + * @param integer $size Write buffer size.
  237 + * @access public
  238 + * @return mixed on success or an PEAR_Error object otherwise
  239 + */
  240 + function setWriteBuffer($size)
  241 + {
  242 + if (!is_resource($this->fp)) {
  243 + return $this->raiseError('not connected');
  244 + }
  245 +
  246 + $returned = stream_set_write_buffer($this->fp, $size);
  247 + if ($returned == 0) {
  248 + return true;
  249 + }
  250 + return $this->raiseError('Cannot set write buffer.');
  251 + }
  252 +
  253 + /**
  254 + * Returns information about an existing socket resource.
  255 + * Currently returns four entries in the result array:
  256 + *
  257 + * <p>
  258 + * timed_out (bool) - The socket timed out waiting for data<br>
  259 + * blocked (bool) - The socket was blocked<br>
  260 + * eof (bool) - Indicates EOF event<br>
  261 + * unread_bytes (int) - Number of bytes left in the socket buffer<br>
  262 + * </p>
  263 + *
  264 + * @access public
  265 + * @return mixed Array containing information about existing socket resource or a PEAR_Error instance otherwise
  266 + */
  267 + function getStatus()
  268 + {
  269 + if (!is_resource($this->fp)) {
  270 + return $this->raiseError('not connected');
  271 + }
  272 +
  273 + return socket_get_status($this->fp);
  274 + }
  275 +
  276 + /**
  277 + * Get a specified line of data
  278 + *
  279 + * @access public
  280 + * @return $size bytes of data from the socket, or a PEAR_Error if
  281 + * not connected.
  282 + */
  283 + function gets($size)
  284 + {
  285 + if (!is_resource($this->fp)) {
  286 + return $this->raiseError('not connected');
  287 + }
  288 +
  289 + return @fgets($this->fp, $size);
  290 + }
  291 +
  292 + /**
  293 + * Read a specified amount of data. This is guaranteed to return,
  294 + * and has the added benefit of getting everything in one fread()
  295 + * chunk; if you know the size of the data you're getting
  296 + * beforehand, this is definitely the way to go.
  297 + *
  298 + * @param integer $size The number of bytes to read from the socket.
  299 + * @access public
  300 + * @return $size bytes of data from the socket, or a PEAR_Error if
  301 + * not connected.
  302 + */
  303 + function read($size)
  304 + {
  305 + if (!is_resource($this->fp)) {
  306 + return $this->raiseError('not connected');
  307 + }
  308 +
  309 + return @fread($this->fp, $size);
  310 + }
  311 +
  312 + /**
  313 + * Write a specified amount of data.
  314 + *
  315 + * @param string $data Data to write.
  316 + * @param integer $blocksize Amount of data to write at once.
  317 + * NULL means all at once.
  318 + *
  319 + * @access public
  320 + * @return mixed If the socket is not connected, returns an instance of PEAR_Error
  321 + * If the write succeeds, returns the number of bytes written
  322 + * If the write fails, returns false.
  323 + */
  324 + function write($data, $blocksize = null)
  325 + {
  326 + if (!is_resource($this->fp)) {
  327 + return $this->raiseError('not connected');
  328 + }
  329 +
  330 + if (is_null($blocksize) && !OS_WINDOWS) {
  331 + return @fwrite($this->fp, $data);
  332 + } else {
  333 + if (is_null($blocksize)) {
  334 + $blocksize = 1024;
  335 + }
  336 +
  337 + $pos = 0;
  338 + $size = strlen($data);
  339 + while ($pos < $size) {
  340 + $written = @fwrite($this->fp, substr($data, $pos, $blocksize));
  341 + if ($written === false) {
  342 + return false;
  343 + }
  344 + $pos += $written;
  345 + }
  346 +
  347 + return $pos;
  348 + }
  349 + }
  350 +
  351 + /**
  352 + * Write a line of data to the socket, followed by a trailing "\r\n".
  353 + *
  354 + * @access public
  355 + * @return mixed fputs result, or an error
  356 + */
  357 + function writeLine($data)
  358 + {
  359 + if (!is_resource($this->fp)) {
  360 + return $this->raiseError('not connected');
  361 + }
  362 +
  363 + return fwrite($this->fp, $data . "\r\n");
  364 + }
  365 +
  366 + /**
  367 + * Tests for end-of-file on a socket descriptor.
  368 + *
  369 + * Also returns true if the socket is disconnected.
  370 + *
  371 + * @access public
  372 + * @return bool
  373 + */
  374 + function eof()
  375 + {
  376 + return (!is_resource($this->fp) || feof($this->fp));
  377 + }
  378 +
  379 + /**
  380 + * Reads a byte of data
  381 + *
  382 + * @access public
  383 + * @return 1 byte of data from the socket, or a PEAR_Error if
  384 + * not connected.
  385 + */
  386 + function readByte()
  387 + {
  388 + if (!is_resource($this->fp)) {
  389 + return $this->raiseError('not connected');
  390 + }
  391 +
  392 + return ord(@fread($this->fp, 1));
  393 + }
  394 +
  395 + /**
  396 + * Reads a word of data
  397 + *
  398 + * @access public
  399 + * @return 1 word of data from the socket, or a PEAR_Error if
  400 + * not connected.
  401 + */
  402 + function readWord()
  403 + {
  404 + if (!is_resource($this->fp)) {
  405 + return $this->raiseError('not connected');
  406 + }
  407 +
  408 + $buf = @fread($this->fp, 2);
  409 + return (ord($buf[0]) + (ord($buf[1]) << 8));
  410 + }
  411 +
  412 + /**
  413 + * Reads an int of data
  414 + *
  415 + * @access public
  416 + * @return integer 1 int of data from the socket, or a PEAR_Error if
  417 + * not connected.
  418 + */
  419 + function readInt()
  420 + {
  421 + if (!is_resource($this->fp)) {
  422 + return $this->raiseError('not connected');
  423 + }
  424 +
  425 + $buf = @fread($this->fp, 4);
  426 + return (ord($buf[0]) + (ord($buf[1]) << 8) +
  427 + (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
  428 + }
  429 +
  430 + /**
  431 + * Reads a zero-terminated string of data
  432 + *
  433 + * @access public
  434 + * @return string, or a PEAR_Error if
  435 + * not connected.
  436 + */
  437 + function readString()
  438 + {
  439 + if (!is_resource($this->fp)) {
  440 + return $this->raiseError('not connected');
  441 + }
  442 +
  443 + $string = '';
  444 + while (($char = @fread($this->fp, 1)) != "\x00") {
  445 + $string .= $char;
  446 + }
  447 + return $string;
  448 + }
  449 +
  450 + /**
  451 + * Reads an IP Address and returns it in a dot formatted string
  452 + *
  453 + * @access public
  454 + * @return Dot formatted string, or a PEAR_Error if
  455 + * not connected.
  456 + */
  457 + function readIPAddress()
  458 + {
  459 + if (!is_resource($this->fp)) {
  460 + return $this->raiseError('not connected');
  461 + }
  462 +
  463 + $buf = @fread($this->fp, 4);
  464 + return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]),
  465 + ord($buf[2]), ord($buf[3]));
  466 + }
  467 +
  468 + /**
  469 + * Read until either the end of the socket or a newline, whichever
  470 + * comes first. Strips the trailing newline from the returned data.
  471 + *
  472 + * @access public
  473 + * @return All available data up to a newline, without that
  474 + * newline, or until the end of the socket, or a PEAR_Error if
  475 + * not connected.
  476 + */
  477 + function readLine()
  478 + {
  479 + if (!is_resource($this->fp)) {
  480 + return $this->raiseError('not connected');
  481 + }
  482 +
  483 + $line = '';
  484 + $timeout = time() + $this->timeout;
  485 + while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
  486 + $line .= @fgets($this->fp, $this->lineLength);
  487 + if (substr($line, -1) == "\n") {
  488 + return rtrim($line, "\r\n");
  489 + }
  490 + }
  491 + return $line;
  492 + }
  493 +
  494 + /**
  495 + * Read until the socket closes, or until there is no more data in
  496 + * the inner PHP buffer. If the inner buffer is empty, in blocking
  497 + * mode we wait for at least 1 byte of data. Therefore, in
  498 + * blocking mode, if there is no data at all to be read, this
  499 + * function will never exit (unless the socket is closed on the
  500 + * remote end).
  501 + *
  502 + * @access public
  503 + *
  504 + * @return string All data until the socket closes, or a PEAR_Error if
  505 + * not connected.
  506 + */
  507 + function readAll()
  508 + {
  509 + if (!is_resource($this->fp)) {
  510 + return $this->raiseError('not connected');
  511 + }
  512 +
  513 + $data = '';
  514 + while (!feof($this->fp)) {
  515 + $data .= @fread($this->fp, $this->lineLength);
  516 + }
  517 + return $data;
  518 + }
  519 +
  520 + /**
  521 + * Runs the equivalent of the select() system call on the socket
  522 + * with a timeout specified by tv_sec and tv_usec.
  523 + *
  524 + * @param integer $state Which of read/write/error to check for.
  525 + * @param integer $tv_sec Number of seconds for timeout.
  526 + * @param integer $tv_usec Number of microseconds for timeout.
  527 + *
  528 + * @access public
  529 + * @return False if select fails, integer describing which of read/write/error
  530 + * are ready, or PEAR_Error if not connected.
  531 + */
  532 + function select($state, $tv_sec, $tv_usec = 0)
  533 + {
  534 + if (!is_resource($this->fp)) {
  535 + return $this->raiseError('not connected');
  536 + }
  537 +
  538 + $read = null;
  539 + $write = null;
  540 + $except = null;
  541 + if ($state & NET_SOCKET_READ) {
  542 + $read[] = $this->fp;
  543 + }
  544 + if ($state & NET_SOCKET_WRITE) {
  545 + $write[] = $this->fp;
  546 + }
  547 + if ($state & NET_SOCKET_ERROR) {
  548 + $except[] = $this->fp;
  549 + }
  550 + if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) {
  551 + return false;
  552 + }
  553 +
  554 + $result = 0;
  555 + if (count($read)) {
  556 + $result |= NET_SOCKET_READ;
  557 + }
  558 + if (count($write)) {
  559 + $result |= NET_SOCKET_WRITE;
  560 + }
  561 + if (count($except)) {
  562 + $result |= NET_SOCKET_ERROR;
  563 + }
  564 + return $result;
  565 + }
  566 +
  567 + /**
  568 + * Turns encryption on/off on a connected socket.
  569 + *
  570 + * @param bool $enabled Set this parameter to true to enable encryption
  571 + * and false to disable encryption.
  572 + * @param integer $type Type of encryption. See
  573 + * http://se.php.net/manual/en/function.stream-socket-enable-crypto.php for values.
  574 + *
  575 + * @access public
  576 + * @return false on error, true on success and 0 if there isn't enough data and the
  577 + * user should try again (non-blocking sockets only). A PEAR_Error object
  578 + * is returned if the socket is not connected
  579 + */
  580 + function enableCrypto($enabled, $type)
  581 + {
  582 + if (version_compare(phpversion(), "5.1.0", ">=")) {
  583 + if (!is_resource($this->fp)) {
  584 + return $this->raiseError('not connected');
  585 + }
  586 + return @stream_socket_enable_crypto($this->fp, $enabled, $type);
  587 + } else {
  588 + return $this->raiseError('Net_Socket::enableCrypto() requires php version >= 5.1.0');
  589 + }
  590 + }
  591 +
  592 +}
  1 +<?php
  2 +// +-----------------------------------------------------------------------+
  3 +// | Copyright (c) 2002-2004, Richard Heyes |
  4 +// | All rights reserved. |
  5 +// | |
  6 +// | Redistribution and use in source and binary forms, with or without |
  7 +// | modification, are permitted provided that the following conditions |
  8 +// | are met: |
  9 +// | |
  10 +// | o Redistributions of source code must retain the above copyright |
  11 +// | notice, this list of conditions and the following disclaimer. |
  12 +// | o Redistributions in binary form must reproduce the above copyright |
  13 +// | notice, this list of conditions and the following disclaimer in the |
  14 +// | documentation and/or other materials provided with the distribution.|
  15 +// | o The names of the authors may not be used to endorse or promote |
  16 +// | products derived from this software without specific prior written |
  17 +// | permission. |
  18 +// | |
  19 +// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
  20 +// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
  21 +// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  22 +// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
  23 +// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  24 +// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
  25 +// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  26 +// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  27 +// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
  28 +// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  29 +// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
  30 +// | |
  31 +// +-----------------------------------------------------------------------+
  32 +// | Author: Richard Heyes <richard at php net> |
  33 +// +-----------------------------------------------------------------------+
  34 +//
  35 +// $Id: URL.php,v 1.49 2007/06/28 14:43:07 davidc Exp $
  36 +//
  37 +// Net_URL Class
  38 +
  39 +
  40 +class Net_URL
  41 +{
  42 + var $options = array('encode_query_keys' => false);
  43 + /**
  44 + * Full url
  45 + * @var string
  46 + */
  47 + var $url;
  48 +
  49 + /**
  50 + * Protocol
  51 + * @var string
  52 + */
  53 + var $protocol;
  54 +
  55 + /**
  56 + * Username
  57 + * @var string
  58 + */
  59 + var $username;
  60 +
  61 + /**
  62 + * Password
  63 + * @var string
  64 + */
  65 + var $password;
  66 +
  67 + /**
  68 + * Host
  69 + * @var string
  70 + */
  71 + var $host;
  72 +
  73 + /**
  74 + * Port
  75 + * @var integer
  76 + */
  77 + var $port;
  78 +
  79 + /**
  80 + * Path
  81 + * @var string
  82 + */
  83 + var $path;
  84 +
  85 + /**
  86 + * Query string
  87 + * @var array
  88 + */
  89 + var $querystring;
  90 +
  91 + /**
  92 + * Anchor
  93 + * @var string
  94 + */
  95 + var $anchor;
  96 +
  97 + /**
  98 + * Whether to use []
  99 + * @var bool
  100 + */
  101 + var $useBrackets;
  102 +
  103 + /**
  104 + * PHP4 Constructor
  105 + *
  106 + * @see __construct()
  107 + */
  108 + function Net_URL($url = null, $useBrackets = true)
  109 + {
  110 + $this->__construct($url, $useBrackets);
  111 + }
  112 +
  113 + /**
  114 + * PHP5 Constructor
  115 + *
  116 + * Parses the given url and stores the various parts
  117 + * Defaults are used in certain cases
  118 + *
  119 + * @param string $url Optional URL
  120 + * @param bool $useBrackets Whether to use square brackets when
  121 + * multiple querystrings with the same name
  122 + * exist
  123 + */
  124 + function __construct($url = null, $useBrackets = true)
  125 + {
  126 + $this->url = $url;
  127 + $this->useBrackets = $useBrackets;
  128 +
  129 + $this->initialize();
  130 + }
  131 +
  132 + function initialize()
  133 + {
  134 + $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
  135 +
  136 + $this->user = '';
  137 + $this->pass = '';
  138 + $this->host = '';
  139 + $this->port = 80;
  140 + $this->path = '';
  141 + $this->querystring = array();
  142 + $this->anchor = '';
  143 +
  144 + // Only use defaults if not an absolute URL given
  145 + if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) {
  146 + $this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
  147 +
  148 + /**
  149 + * Figure out host/port
  150 + */
  151 + if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) &&
  152 + preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches))
  153 + {
  154 + $host = $matches[1];
  155 + if (!empty($matches[3])) {
  156 + $port = $matches[3];
  157 + } else {
  158 + $port = $this->getStandardPort($this->protocol);
  159 + }
  160 + }
  161 +
  162 + $this->user = '';
  163 + $this->pass = '';
  164 + $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
  165 + $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
  166 + $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
  167 + $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
  168 + $this->anchor = '';
  169 + }
  170 +
  171 + // Parse the url and store the various parts
  172 + if (!empty($this->url)) {
  173 + $urlinfo = parse_url($this->url);
  174 +
  175 + // Default querystring
  176 + $this->querystring = array();
  177 +
  178 + foreach ($urlinfo as $key => $value) {
  179 + switch ($key) {
  180 + case 'scheme':
  181 + $this->protocol = $value;
  182 + $this->port = $this->getStandardPort($value);
  183 + break;
  184 +
  185 + case 'user':
  186 + case 'pass':
  187 + case 'host':
  188 + case 'port':
  189 + $this->$key = $value;
  190 + break;
  191 +
  192 + case 'path':
  193 + if ($value{0} == '/') {
  194 + $this->path = $value;
  195 + } else {
  196 + $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
  197 + $this->path = sprintf('%s/%s', $path, $value);
  198 + }
  199 + break;
  200 +
  201 + case 'query':
  202 + $this->querystring = $this->_parseRawQueryString($value);
  203 + break;
  204 +
  205 + case 'fragment':
  206 + $this->anchor = $value;
  207 + break;
  208 + }
  209 + }
  210 + }
  211 + }
  212 + /**
  213 + * Returns full url
  214 + *
  215 + * @return string Full url
  216 + * @access public
  217 + */
  218 + function getURL()
  219 + {
  220 + $querystring = $this->getQueryString();
  221 +
  222 + $this->url = $this->protocol . '://'
  223 + . $this->user . (!empty($this->pass) ? ':' : '')
  224 + . $this->pass . (!empty($this->user) ? '@' : '')
  225 + . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
  226 + . $this->path
  227 + . (!empty($querystring) ? '?' . $querystring : '')
  228 + . (!empty($this->anchor) ? '#' . $this->anchor : '');
  229 +
  230 + return $this->url;
  231 + }
  232 +
  233 + /**
  234 + * Adds or updates a querystring item (URL parameter).
  235 + * Automatically encodes parameters with rawurlencode() if $preencoded
  236 + * is false.
  237 + * You can pass an array to $value, it gets mapped via [] in the URL if
  238 + * $this->useBrackets is activated.
  239 + *
  240 + * @param string $name Name of item
  241 + * @param string $value Value of item
  242 + * @param bool $preencoded Whether value is urlencoded or not, default = not
  243 + * @access public
  244 + */
  245 + function addQueryString($name, $value, $preencoded = false)
  246 + {
  247 + if ($this->getOption('encode_query_keys')) {
  248 + $name = rawurlencode($name);
  249 + }
  250 +
  251 + if ($preencoded) {
  252 + $this->querystring[$name] = $value;
  253 + } else {
  254 + $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
  255 + }
  256 + }
  257 +
  258 + /**
  259 + * Removes a querystring item
  260 + *
  261 + * @param string $name Name of item
  262 + * @access public
  263 + */
  264 + function removeQueryString($name)
  265 + {
  266 + if ($this->getOption('encode_query_keys')) {
  267 + $name = rawurlencode($name);
  268 + }
  269 +
  270 + if (isset($this->querystring[$name])) {
  271 + unset($this->querystring[$name]);
  272 + }
  273 + }
  274 +
  275 + /**
  276 + * Sets the querystring to literally what you supply
  277 + *
  278 + * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc
  279 + * @access public
  280 + */
  281 + function addRawQueryString($querystring)
  282 + {
  283 + $this->querystring = $this->_parseRawQueryString($querystring);
  284 + }
  285 +
  286 + /**
  287 + * Returns flat querystring
  288 + *
  289 + * @return string Querystring
  290 + * @access public
  291 + */
  292 + function getQueryString()
  293 + {
  294 + if (!empty($this->querystring)) {
  295 + foreach ($this->querystring as $name => $value) {
  296 + // Encode var name
  297 + $name = rawurlencode($name);
  298 +
  299 + if (is_array($value)) {
  300 + foreach ($value as $k => $v) {
  301 + $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
  302 + }
  303 + } elseif (!is_null($value)) {
  304 + $querystring[] = $name . '=' . $value;
  305 + } else {
  306 + $querystring[] = $name;
  307 + }
  308 + }
  309 + $querystring = implode(ini_get('arg_separator.output'), $querystring);
  310 + } else {
  311 + $querystring = '';
  312 + }
  313 +
  314 + return $querystring;
  315 + }
  316 +
  317 + /**
  318 + * Parses raw querystring and returns an array of it
  319 + *
  320 + * @param string $querystring The querystring to parse
  321 + * @return array An array of the querystring data
  322 + * @access private
  323 + */
  324 + function _parseRawQuerystring($querystring)
  325 + {
  326 + $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
  327 + $return = array();
  328 +
  329 + foreach ($parts as $part) {
  330 + if (strpos($part, '=') !== false) {
  331 + $value = substr($part, strpos($part, '=') + 1);
  332 + $key = substr($part, 0, strpos($part, '='));
  333 + } else {
  334 + $value = null;
  335 + $key = $part;
  336 + }
  337 +
  338 + if (!$this->getOption('encode_query_keys')) {
  339 + $key = rawurldecode($key);
  340 + }
  341 +
  342 + if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
  343 + $key = $matches[1];
  344 + $idx = $matches[2];
  345 +
  346 + // Ensure is an array
  347 + if (empty($return[$key]) || !is_array($return[$key])) {
  348 + $return[$key] = array();
  349 + }
  350 +
  351 + // Add data
  352 + if ($idx === '') {
  353 + $return[$key][] = $value;
  354 + } else {
  355 + $return[$key][$idx] = $value;
  356 + }
  357 + } elseif (!$this->useBrackets AND !empty($return[$key])) {
  358 + $return[$key] = (array)$return[$key];
  359 + $return[$key][] = $value;
  360 + } else {
  361 + $return[$key] = $value;
  362 + }
  363 + }
  364 +
  365 + return $return;
  366 + }
  367 +
  368 + /**
  369 + * Resolves //, ../ and ./ from a path and returns
  370 + * the result. Eg:
  371 + *
  372 + * /foo/bar/../boo.php => /foo/boo.php
  373 + * /foo/bar/../../boo.php => /boo.php
  374 + * /foo/bar/.././/boo.php => /foo/boo.php
  375 + *
  376 + * This method can also be called statically.
  377 + *
  378 + * @param string $path URL path to resolve
  379 + * @return string The result
  380 + */
  381 + function resolvePath($path)
  382 + {
  383 + $path = explode('/', str_replace('//', '/', $path));
  384 +
  385 + for ($i=0; $i<count($path); $i++) {
  386 + if ($path[$i] == '.') {
  387 + unset($path[$i]);
  388 + $path = array_values($path);
  389 + $i--;
  390 +
  391 + } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
  392 + unset($path[$i]);
  393 + unset($path[$i-1]);
  394 + $path = array_values($path);
  395 + $i -= 2;
  396 +
  397 + } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
  398 + unset($path[$i]);
  399 + $path = array_values($path);
  400 + $i--;
  401 +
  402 + } else {
  403 + continue;
  404 + }
  405 + }
  406 +
  407 + return implode('/', $path);
  408 + }
  409 +
  410 + /**
  411 + * Returns the standard port number for a protocol
  412 + *
  413 + * @param string $scheme The protocol to lookup
  414 + * @return integer Port number or NULL if no scheme matches
  415 + *
  416 + * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
  417 + */
  418 + function getStandardPort($scheme)
  419 + {
  420 + switch (strtolower($scheme)) {
  421 + case 'http': return 80;
  422 + case 'https': return 443;
  423 + case 'ftp': return 21;
  424 + case 'imap': return 143;
  425 + case 'imaps': return 993;
  426 + case 'pop3': return 110;
  427 + case 'pop3s': return 995;
  428 + default: return null;
  429 + }
  430 + }
  431 +
  432 + /**
  433 + * Forces the URL to a particular protocol
  434 + *
  435 + * @param string $protocol Protocol to force the URL to
  436 + * @param integer $port Optional port (standard port is used by default)
  437 + */
  438 + function setProtocol($protocol, $port = null)
  439 + {
  440 + $this->protocol = $protocol;
  441 + $this->port = is_null($port) ? $this->getStandardPort($protocol) : $port;
  442 + }
  443 +
  444 + /**
  445 + * Set an option
  446 + *
  447 + * This function set an option
  448 + * to be used thorough the script.
  449 + *
  450 + * @access public
  451 + * @param string $optionName The optionname to set
  452 + * @param string $value The value of this option.
  453 + */
  454 + function setOption($optionName, $value)
  455 + {
  456 + if (!array_key_exists($optionName, $this->options)) {
  457 + return false;
  458 + }
  459 +
  460 + $this->options[$optionName] = $value;
  461 + $this->initialize();
  462 + }
  463 +
  464 + /**
  465 + * Get an option
  466 + *
  467 + * This function gets an option
  468 + * from the $this->options array
  469 + * and return it's value.
  470 + *
  471 + * @access public
  472 + * @param string $opionName The name of the option to retrieve
  473 + * @see $this->options
  474 + */
  475 + function getOption($optionName)
  476 + {
  477 + if (!isset($this->options[$optionName])) {
  478 + return false;
  479 + }
  480 +
  481 + return $this->options[$optionName];
  482 + }
  483 +
  484 +}
  485 +?>
  1 +<?php
  2 +/**
  3 + * Class for performing HTTP requests
  4 + *
  5 + * PHP versions 4 and 5
  6 + *
  7 + * LICENSE:
  8 + *
  9 + * Copyright (c) 2002-2007, Richard Heyes
  10 + * All rights reserved.
  11 + *
  12 + * Redistribution and use in source and binary forms, with or without
  13 + * modification, are permitted provided that the following conditions
  14 + * are met:
  15 + *
  16 + * o Redistributions of source code must retain the above copyright
  17 + * notice, this list of conditions and the following disclaimer.
  18 + * o Redistributions in binary form must reproduce the above copyright
  19 + * notice, this list of conditions and the following disclaimer in the
  20 + * documentation and/or other materials provided with the distribution.
  21 + * o The names of the authors may not be used to endorse or promote
  22 + * products derived from this software without specific prior written
  23 + * permission.
  24 + *
  25 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  28 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  29 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  30 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  31 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  35 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36 + *
  37 + * @category HTTP
  38 + * @package HTTP_Request
  39 + * @author Richard Heyes <richard@phpguru.org>
  40 + * @author Alexey Borzov <avb@php.net>
  41 + * @copyright 2002-2007 Richard Heyes
  42 + * @license http://opensource.org/licenses/bsd-license.php New BSD License
  43 + * @version CVS: $Id: Request.php,v 1.63 2008/10/11 11:07:10 avb Exp $
  44 + * @link http://pear.php.net/package/HTTP_Request/
  45 + */
  46 +
  47 +/**
  48 + * PEAR and PEAR_Error classes (for error handling)
  49 + */
  50 +require_once 'PEAR.php';
  51 +/**
  52 + * Socket class
  53 + */
  54 +require_once 'Net/Socket.php';
  55 +/**
  56 + * URL handling class
  57 + */
  58 +require_once 'Net/URL.php';
  59 +
  60 +/**#@+
  61 + * Constants for HTTP request methods
  62 + */
  63 +define('HTTP_REQUEST_METHOD_GET', 'GET', true);
  64 +define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true);
  65 +define('HTTP_REQUEST_METHOD_POST', 'POST', true);
  66 +define('HTTP_REQUEST_METHOD_PUT', 'PUT', true);
  67 +define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true);
  68 +define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true);
  69 +define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true);
  70 +/**#@-*/
  71 +
  72 +/**#@+
  73 + * Constants for HTTP request error codes
  74 + */
  75 +define('HTTP_REQUEST_ERROR_FILE', 1);
  76 +define('HTTP_REQUEST_ERROR_URL', 2);
  77 +define('HTTP_REQUEST_ERROR_PROXY', 4);
  78 +define('HTTP_REQUEST_ERROR_REDIRECTS', 8);
  79 +define('HTTP_REQUEST_ERROR_RESPONSE', 16);
  80 +define('HTTP_REQUEST_ERROR_GZIP_METHOD', 32);
  81 +define('HTTP_REQUEST_ERROR_GZIP_READ', 64);
  82 +define('HTTP_REQUEST_ERROR_GZIP_DATA', 128);
  83 +define('HTTP_REQUEST_ERROR_GZIP_CRC', 256);
  84 +/**#@-*/
  85 +
  86 +/**#@+
  87 + * Constants for HTTP protocol versions
  88 + */
  89 +define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true);
  90 +define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true);
  91 +/**#@-*/
  92 +
  93 +if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
  94 + /**
  95 + * Whether string functions are overloaded by their mbstring equivalents
  96 + */
  97 + define('HTTP_REQUEST_MBSTRING', true);
  98 +} else {
  99 + /**
  100 + * @ignore
  101 + */
  102 + define('HTTP_REQUEST_MBSTRING', false);
  103 +}
  104 +
  105 +/**
  106 + * Class for performing HTTP requests
  107 + *
  108 + * Simple example (fetches yahoo.com and displays it):
  109 + * <code>
  110 + * $a = &new HTTP_Request('http://www.yahoo.com/');
  111 + * $a->sendRequest();
  112 + * echo $a->getResponseBody();
  113 + * </code>
  114 + *
  115 + * @category HTTP
  116 + * @package HTTP_Request
  117 + * @author Richard Heyes <richard@phpguru.org>
  118 + * @author Alexey Borzov <avb@php.net>
  119 + * @version Release: 1.4.4
  120 + */
  121 +class HTTP_Request
  122 +{
  123 + /**#@+
  124 + * @access private
  125 + */
  126 + /**
  127 + * Instance of Net_URL
  128 + * @var Net_URL
  129 + */
  130 + var $_url;
  131 +
  132 + /**
  133 + * Type of request
  134 + * @var string
  135 + */
  136 + var $_method;
  137 +
  138 + /**
  139 + * HTTP Version
  140 + * @var string
  141 + */
  142 + var $_http;
  143 +
  144 + /**
  145 + * Request headers
  146 + * @var array
  147 + */
  148 + var $_requestHeaders;
  149 +
  150 + /**
  151 + * Basic Auth Username
  152 + * @var string
  153 + */
  154 + var $_user;
  155 +
  156 + /**
  157 + * Basic Auth Password
  158 + * @var string
  159 + */
  160 + var $_pass;
  161 +
  162 + /**
  163 + * Socket object
  164 + * @var Net_Socket
  165 + */
  166 + var $_sock;
  167 +
  168 + /**
  169 + * Proxy server
  170 + * @var string
  171 + */
  172 + var $_proxy_host;
  173 +
  174 + /**
  175 + * Proxy port
  176 + * @var integer
  177 + */
  178 + var $_proxy_port;
  179 +
  180 + /**
  181 + * Proxy username
  182 + * @var string
  183 + */
  184 + var $_proxy_user;
  185 +
  186 + /**
  187 + * Proxy password
  188 + * @var string
  189 + */
  190 + var $_proxy_pass;
  191 +
  192 + /**
  193 + * Post data
  194 + * @var array
  195 + */
  196 + var $_postData;
  197 +
  198 + /**
  199 + * Request body
  200 + * @var string
  201 + */
  202 + var $_body;
  203 +
  204 + /**
  205 + * A list of methods that MUST NOT have a request body, per RFC 2616
  206 + * @var array
  207 + */
  208 + var $_bodyDisallowed = array('TRACE');
  209 +
  210 + /**
  211 + * Methods having defined semantics for request body
  212 + *
  213 + * Content-Length header (indicating that the body follows, section 4.3 of
  214 + * RFC 2616) will be sent for these methods even if no body was added
  215 + *
  216 + * @var array
  217 + */
  218 + var $_bodyRequired = array('POST', 'PUT');
  219 +
  220 + /**
  221 + * Files to post
  222 + * @var array
  223 + */
  224 + var $_postFiles = array();
  225 +
  226 + /**
  227 + * Connection timeout.
  228 + * @var float
  229 + */
  230 + var $_timeout;
  231 +
  232 + /**
  233 + * HTTP_Response object
  234 + * @var HTTP_Response
  235 + */
  236 + var $_response;
  237 +
  238 + /**
  239 + * Whether to allow redirects
  240 + * @var boolean
  241 + */
  242 + var $_allowRedirects;
  243 +
  244 + /**
  245 + * Maximum redirects allowed
  246 + * @var integer
  247 + */
  248 + var $_maxRedirects;
  249 +
  250 + /**
  251 + * Current number of redirects
  252 + * @var integer
  253 + */
  254 + var $_redirects;
  255 +
  256 + /**
  257 + * Whether to append brackets [] to array variables
  258 + * @var bool
  259 + */
  260 + var $_useBrackets = true;
  261 +
  262 + /**
  263 + * Attached listeners
  264 + * @var array
  265 + */
  266 + var $_listeners = array();
  267 +
  268 + /**
  269 + * Whether to save response body in response object property
  270 + * @var bool
  271 + */
  272 + var $_saveBody = true;
  273 +
  274 + /**
  275 + * Timeout for reading from socket (array(seconds, microseconds))
  276 + * @var array
  277 + */
  278 + var $_readTimeout = null;
  279 +
  280 + /**
  281 + * Options to pass to Net_Socket::connect. See stream_context_create
  282 + * @var array
  283 + */
  284 + var $_socketOptions = null;
  285 + /**#@-*/
  286 +
  287 + /**
  288 + * Constructor
  289 + *
  290 + * Sets up the object
  291 + * @param string The url to fetch/access
  292 + * @param array Associative array of parameters which can have the following keys:
  293 + * <ul>
  294 + * <li>method - Method to use, GET, POST etc (string)</li>
  295 + * <li>http - HTTP Version to use, 1.0 or 1.1 (string)</li>
  296 + * <li>user - Basic Auth username (string)</li>
  297 + * <li>pass - Basic Auth password (string)</li>
  298 + * <li>proxy_host - Proxy server host (string)</li>
  299 + * <li>proxy_port - Proxy server port (integer)</li>
  300 + * <li>proxy_user - Proxy auth username (string)</li>
  301 + * <li>proxy_pass - Proxy auth password (string)</li>
  302 + * <li>timeout - Connection timeout in seconds (float)</li>
  303 + * <li>allowRedirects - Whether to follow redirects or not (bool)</li>
  304 + * <li>maxRedirects - Max number of redirects to follow (integer)</li>
  305 + * <li>useBrackets - Whether to append [] to array variable names (bool)</li>
  306 + * <li>saveBody - Whether to save response body in response object property (bool)</li>
  307 + * <li>readTimeout - Timeout for reading / writing data over the socket (array (seconds, microseconds))</li>
  308 + * <li>socketOptions - Options to pass to Net_Socket object (array)</li>
  309 + * </ul>
  310 + * @access public
  311 + */
  312 + function HTTP_Request($url = '', $params = array())
  313 + {
  314 + $this->_method = HTTP_REQUEST_METHOD_GET;
  315 + $this->_http = HTTP_REQUEST_HTTP_VER_1_1;
  316 + $this->_requestHeaders = array();
  317 + $this->_postData = array();
  318 + $this->_body = null;
  319 +
  320 + $this->_user = null;
  321 + $this->_pass = null;
  322 +
  323 + $this->_proxy_host = null;
  324 + $this->_proxy_port = null;
  325 + $this->_proxy_user = null;
  326 + $this->_proxy_pass = null;
  327 +
  328 + $this->_allowRedirects = false;
  329 + $this->_maxRedirects = 3;
  330 + $this->_redirects = 0;
  331 +
  332 + $this->_timeout = null;
  333 + $this->_response = null;
  334 +
  335 + foreach ($params as $key => $value) {
  336 + $this->{'_' . $key} = $value;
  337 + }
  338 +
  339 + if (!empty($url)) {
  340 + $this->setURL($url);
  341 + }
  342 +
  343 + // Default useragent
  344 + $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )');
  345 +
  346 + // We don't do keep-alives by default
  347 + $this->addHeader('Connection', 'close');
  348 +
  349 + // Basic authentication
  350 + if (!empty($this->_user)) {
  351 + $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass));
  352 + }
  353 +
  354 + // Proxy authentication (see bug #5913)
  355 + if (!empty($this->_proxy_user)) {
  356 + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass));
  357 + }
  358 +
  359 + // Use gzip encoding if possible
  360 + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) {
  361 + $this->addHeader('Accept-Encoding', 'gzip');
  362 + }
  363 + }
  364 +
  365 + /**
  366 + * Generates a Host header for HTTP/1.1 requests
  367 + *
  368 + * @access private
  369 + * @return string
  370 + */
  371 + function _generateHostHeader()
  372 + {
  373 + if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) {
  374 + $host = $this->_url->host . ':' . $this->_url->port;
  375 +
  376 + } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) {
  377 + $host = $this->_url->host . ':' . $this->_url->port;
  378 +
  379 + } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) {
  380 + $host = $this->_url->host . ':' . $this->_url->port;
  381 +
  382 + } else {
  383 + $host = $this->_url->host;
  384 + }
  385 +
  386 + return $host;
  387 + }
  388 +
  389 + /**
  390 + * Resets the object to its initial state (DEPRECATED).
  391 + * Takes the same parameters as the constructor.
  392 + *
  393 + * @param string $url The url to be requested
  394 + * @param array $params Associative array of parameters
  395 + * (see constructor for details)
  396 + * @access public
  397 + * @deprecated deprecated since 1.2, call the constructor if this is necessary
  398 + */
  399 + function reset($url, $params = array())
  400 + {
  401 + $this->HTTP_Request($url, $params);
  402 + }
  403 +
  404 + /**
  405 + * Sets the URL to be requested
  406 + *
  407 + * @param string The url to be requested
  408 + * @access public
  409 + */
  410 + function setURL($url)
  411 + {
  412 + $this->_url = &new Net_URL($url, $this->_useBrackets);
  413 +
  414 + if (!empty($this->_url->user) || !empty($this->_url->pass)) {
  415 + $this->setBasicAuth($this->_url->user, $this->_url->pass);
  416 + }
  417 +
  418 + if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) {
  419 + $this->addHeader('Host', $this->_generateHostHeader());
  420 + }
  421 +
  422 + // set '/' instead of empty path rather than check later (see bug #8662)
  423 + if (empty($this->_url->path)) {
  424 + $this->_url->path = '/';
  425 + }
  426 + }
  427 +
  428 + /**
  429 + * Returns the current request URL
  430 + *
  431 + * @return string Current request URL
  432 + * @access public
  433 + */
  434 + function getUrl()
  435 + {
  436 + return empty($this->_url)? '': $this->_url->getUrl();
  437 + }
  438 +
  439 + /**
  440 + * Sets a proxy to be used
  441 + *
  442 + * @param string Proxy host
  443 + * @param int Proxy port
  444 + * @param string Proxy username
  445 + * @param string Proxy password
  446 + * @access public
  447 + */
  448 + function setProxy($host, $port = 8080, $user = null, $pass = null)
  449 + {
  450 + $this->_proxy_host = $host;
  451 + $this->_proxy_port = $port;
  452 + $this->_proxy_user = $user;
  453 + $this->_proxy_pass = $pass;
  454 +
  455 + if (!empty($user)) {
  456 + $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
  457 + }
  458 + }
  459 +
  460 + /**
  461 + * Sets basic authentication parameters
  462 + *
  463 + * @param string Username
  464 + * @param string Password
  465 + */
  466 + function setBasicAuth($user, $pass)
  467 + {
  468 + $this->_user = $user;
  469 + $this->_pass = $pass;
  470 +
  471 + $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
  472 + }
  473 +
  474 + /**
  475 + * Sets the method to be used, GET, POST etc.
  476 + *
  477 + * @param string Method to use. Use the defined constants for this
  478 + * @access public
  479 + */
  480 + function setMethod($method)
  481 + {
  482 + $this->_method = $method;
  483 + }
  484 +
  485 + /**
  486 + * Sets the HTTP version to use, 1.0 or 1.1
  487 + *
  488 + * @param string Version to use. Use the defined constants for this
  489 + * @access public
  490 + */
  491 + function setHttpVer($http)
  492 + {
  493 + $this->_http = $http;
  494 + }
  495 +
  496 + /**
  497 + * Adds a request header
  498 + *
  499 + * @param string Header name
  500 + * @param string Header value
  501 + * @access public
  502 + */
  503 + function addHeader($name, $value)
  504 + {
  505 + $this->_requestHeaders[strtolower($name)] = $value;
  506 + }
  507 +
  508 + /**
  509 + * Removes a request header
  510 + *
  511 + * @param string Header name to remove
  512 + * @access public
  513 + */
  514 + function removeHeader($name)
  515 + {
  516 + if (isset($this->_requestHeaders[strtolower($name)])) {
  517 + unset($this->_requestHeaders[strtolower($name)]);
  518 + }
  519 + }
  520 +
  521 + /**
  522 + * Adds a querystring parameter
  523 + *
  524 + * @param string Querystring parameter name
  525 + * @param string Querystring parameter value
  526 + * @param bool Whether the value is already urlencoded or not, default = not
  527 + * @access public
  528 + */
  529 + function addQueryString($name, $value, $preencoded = false)
  530 + {
  531 + $this->_url->addQueryString($name, $value, $preencoded);
  532 + }
  533 +
  534 + /**
  535 + * Sets the querystring to literally what you supply
  536 + *
  537 + * @param string The querystring data. Should be of the format foo=bar&x=y etc
  538 + * @param bool Whether data is already urlencoded or not, default = already encoded
  539 + * @access public
  540 + */
  541 + function addRawQueryString($querystring, $preencoded = true)
  542 + {
  543 + $this->_url->addRawQueryString($querystring, $preencoded);
  544 + }
  545 +
  546 + /**
  547 + * Adds postdata items
  548 + *
  549 + * @param string Post data name
  550 + * @param string Post data value
  551 + * @param bool Whether data is already urlencoded or not, default = not
  552 + * @access public
  553 + */
  554 + function addPostData($name, $value, $preencoded = false)
  555 + {
  556 + if ($preencoded) {
  557 + $this->_postData[$name] = $value;
  558 + } else {
  559 + $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value);
  560 + }
  561 + }
  562 +
  563 + /**
  564 + * Recursively applies the callback function to the value
  565 + *
  566 + * @param mixed Callback function
  567 + * @param mixed Value to process
  568 + * @access private
  569 + * @return mixed Processed value
  570 + */
  571 + function _arrayMapRecursive($callback, $value)
  572 + {
  573 + if (!is_array($value)) {
  574 + return call_user_func($callback, $value);
  575 + } else {
  576 + $map = array();
  577 + foreach ($value as $k => $v) {
  578 + $map[$k] = $this->_arrayMapRecursive($callback, $v);
  579 + }
  580 + return $map;
  581 + }
  582 + }
  583 +
  584 + /**
  585 + * Adds a file to form-based file upload
  586 + *
  587 + * Used to emulate file upload via a HTML form. The method also sets
  588 + * Content-Type of HTTP request to 'multipart/form-data'.
  589 + *
  590 + * If you just want to send the contents of a file as the body of HTTP
  591 + * request you should use setBody() method.
  592 + *
  593 + * @access public
  594 + * @param string name of file-upload field
  595 + * @param mixed file name(s)
  596 + * @param mixed content-type(s) of file(s) being uploaded
  597 + * @return bool true on success
  598 + * @throws PEAR_Error
  599 + */
  600 + function addFile($inputName, $fileName, $contentType = 'application/octet-stream')
  601 + {
  602 + if (!is_array($fileName) && !is_readable($fileName)) {
  603 + return PEAR::raiseError("File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE);
  604 + } elseif (is_array($fileName)) {
  605 + foreach ($fileName as $name) {
  606 + if (!is_readable($name)) {
  607 + return PEAR::raiseError("File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE);
  608 + }
  609 + }
  610 + }
  611 + $this->addHeader('Content-Type', 'multipart/form-data');
  612 + $this->_postFiles[$inputName] = array(
  613 + 'name' => $fileName,
  614 + 'type' => $contentType
  615 + );
  616 + return true;
  617 + }
  618 +
  619 + /**
  620 + * Adds raw postdata (DEPRECATED)
  621 + *
  622 + * @param string The data
  623 + * @param bool Whether data is preencoded or not, default = already encoded
  624 + * @access public
  625 + * @deprecated deprecated since 1.3.0, method setBody() should be used instead
  626 + */
  627 + function addRawPostData($postdata, $preencoded = true)
  628 + {
  629 + $this->_body = $preencoded ? $postdata : urlencode($postdata);
  630 + }
  631 +
  632 + /**
  633 + * Sets the request body (for POST, PUT and similar requests)
  634 + *
  635 + * @param string Request body
  636 + * @access public
  637 + */
  638 + function setBody($body)
  639 + {
  640 + $this->_body = $body;
  641 + }
  642 +
  643 + /**
  644 + * Clears any postdata that has been added (DEPRECATED).
  645 + *
  646 + * Useful for multiple request scenarios.
  647 + *
  648 + * @access public
  649 + * @deprecated deprecated since 1.2
  650 + */
  651 + function clearPostData()
  652 + {
  653 + $this->_postData = null;
  654 + }
  655 +
  656 + /**
  657 + * Appends a cookie to "Cookie:" header
  658 + *
  659 + * @param string $name cookie name
  660 + * @param string $value cookie value
  661 + * @access public
  662 + */
  663 + function addCookie($name, $value)
  664 + {
  665 + $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : '';
  666 + $this->addHeader('Cookie', $cookies . $name . '=' . $value);
  667 + }
  668 +
  669 + /**
  670 + * Clears any cookies that have been added (DEPRECATED).
  671 + *
  672 + * Useful for multiple request scenarios
  673 + *
  674 + * @access public
  675 + * @deprecated deprecated since 1.2
  676 + */
  677 + function clearCookies()
  678 + {
  679 + $this->removeHeader('Cookie');
  680 + }
  681 +
  682 + /**
  683 + * Sends the request
  684 + *
  685 + * @access public
  686 + * @param bool Whether to store response body in Response object property,
  687 + * set this to false if downloading a LARGE file and using a Listener
  688 + * @return mixed PEAR error on error, true otherwise
  689 + */
  690 + function sendRequest($saveBody = true)
  691 + {
  692 + if (!is_a($this->_url, 'Net_URL')) {
  693 + return PEAR::raiseError('No URL given', HTTP_REQUEST_ERROR_URL);
  694 + }
  695 +
  696 + $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host;
  697 + $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port;
  698 +
  699 + if (strcasecmp($this->_url->protocol, 'https') == 0) {
  700 + // Bug #14127, don't try connecting to HTTPS sites without OpenSSL
  701 + if (version_compare(PHP_VERSION, '4.3.0', '<') || !extension_loaded('openssl')) {
  702 + return PEAR::raiseError('Need PHP 4.3.0 or later with OpenSSL support for https:// requests',
  703 + HTTP_REQUEST_ERROR_URL);
  704 + } elseif (isset($this->_proxy_host)) {
  705 + return PEAR::raiseError('HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY);
  706 + }
  707 + $host = 'ssl://' . $host;
  708 + }
  709 +
  710 + // magic quotes may fuck up file uploads and chunked response processing
  711 + $magicQuotes = ini_get('magic_quotes_runtime');
  712 + ini_set('magic_quotes_runtime', false);
  713 +
  714 + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
  715 + // connection token to a proxy server...
  716 + if (isset($this->_proxy_host) && !empty($this->_requestHeaders['connection']) &&
  717 + 'Keep-Alive' == $this->_requestHeaders['connection'])
  718 + {
  719 + $this->removeHeader('connection');
  720 + }
  721 +
  722 + $keepAlive = (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty($this->_requestHeaders['connection'])) ||
  723 + (!empty($this->_requestHeaders['connection']) && 'Keep-Alive' == $this->_requestHeaders['connection']);
  724 + $sockets = &PEAR::getStaticProperty('HTTP_Request', 'sockets');
  725 + $sockKey = $host . ':' . $port;
  726 + unset($this->_sock);
  727 +
  728 + // There is a connected socket in the "static" property?
  729 + if ($keepAlive && !empty($sockets[$sockKey]) &&
  730 + !empty($sockets[$sockKey]->fp))
  731 + {
  732 + $this->_sock =& $sockets[$sockKey];
  733 + $err = null;
  734 + } else {
  735 + $this->_notify('connect');
  736 + $this->_sock =& new Net_Socket();
  737 + $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions);
  738 + }
  739 + PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest());
  740 +
  741 + if (!PEAR::isError($err)) {
  742 + if (!empty($this->_readTimeout)) {
  743 + $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]);
  744 + }
  745 +
  746 + $this->_notify('sentRequest');
  747 +
  748 + // Read the response
  749 + $this->_response = &new HTTP_Response($this->_sock, $this->_listeners);
  750 + $err = $this->_response->process(
  751 + $this->_saveBody && $saveBody,
  752 + HTTP_REQUEST_METHOD_HEAD != $this->_method
  753 + );
  754 +
  755 + if ($keepAlive) {
  756 + $keepAlive = (isset($this->_response->_headers['content-length'])
  757 + || (isset($this->_response->_headers['transfer-encoding'])
  758 + && strtolower($this->_response->_headers['transfer-encoding']) == 'chunked'));
  759 + if ($keepAlive) {
  760 + if (isset($this->_response->_headers['connection'])) {
  761 + $keepAlive = strtolower($this->_response->_headers['connection']) == 'keep-alive';
  762 + } else {
  763 + $keepAlive = 'HTTP/'.HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol;
  764 + }
  765 + }
  766 + }
  767 + }
  768 +
  769 + ini_set('magic_quotes_runtime', $magicQuotes);
  770 +
  771 + if (PEAR::isError($err)) {
  772 + return $err;
  773 + }
  774 +
  775 + if (!$keepAlive) {
  776 + $this->disconnect();
  777 + // Store the connected socket in "static" property
  778 + } elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) {
  779 + $sockets[$sockKey] =& $this->_sock;
  780 + }
  781 +
  782 + // Check for redirection
  783 + if ( $this->_allowRedirects
  784 + AND $this->_redirects <= $this->_maxRedirects
  785 + AND $this->getResponseCode() > 300
  786 + AND $this->getResponseCode() < 399
  787 + AND !empty($this->_response->_headers['location'])) {
  788 +
  789 +
  790 + $redirect = $this->_response->_headers['location'];
  791 +
  792 + // Absolute URL
  793 + if (preg_match('/^https?:\/\//i', $redirect)) {
  794 + $this->_url = &new Net_URL($redirect);
  795 + $this->addHeader('Host', $this->_generateHostHeader());
  796 + // Absolute path
  797 + } elseif ($redirect{0} == '/') {
  798 + $this->_url->path = $redirect;
  799 +
  800 + // Relative path
  801 + } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') {
  802 + if (substr($this->_url->path, -1) == '/') {
  803 + $redirect = $this->_url->path . $redirect;
  804 + } else {
  805 + $redirect = dirname($this->_url->path) . '/' . $redirect;
  806 + }
  807 + $redirect = Net_URL::resolvePath($redirect);
  808 + $this->_url->path = $redirect;
  809 +
  810 + // Filename, no path
  811 + } else {
  812 + if (substr($this->_url->path, -1) == '/') {
  813 + $redirect = $this->_url->path . $redirect;
  814 + } else {
  815 + $redirect = dirname($this->_url->path) . '/' . $redirect;
  816 + }
  817 + $this->_url->path = $redirect;
  818 + }
  819 +
  820 + $this->_redirects++;
  821 + return $this->sendRequest($saveBody);
  822 +
  823 + // Too many redirects
  824 + } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
  825 + return PEAR::raiseError('Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS);
  826 + }
  827 +
  828 + return true;
  829 + }
  830 +
  831 + /**
  832 + * Disconnect the socket, if connected. Only useful if using Keep-Alive.
  833 + *
  834 + * @access public
  835 + */
  836 + function disconnect()
  837 + {
  838 + if (!empty($this->_sock) && !empty($this->_sock->fp)) {
  839 + $this->_notify('disconnect');
  840 + $this->_sock->disconnect();
  841 + }
  842 + }
  843 +
  844 + /**
  845 + * Returns the response code
  846 + *
  847 + * @access public
  848 + * @return mixed Response code, false if not set
  849 + */
  850 + function getResponseCode()
  851 + {
  852 + return isset($this->_response->_code) ? $this->_response->_code : false;
  853 + }
  854 +
  855 + /**
  856 + * Returns the response reason phrase
  857 + *
  858 + * @access public
  859 + * @return mixed Response reason phrase, false if not set
  860 + */
  861 + function getResponseReason()
  862 + {
  863 + return isset($this->_response->_reason) ? $this->_response->_reason : false;
  864 + }
  865 +
  866 + /**
  867 + * Returns either the named header or all if no name given
  868 + *
  869 + * @access public
  870 + * @param string The header name to return, do not set to get all headers
  871 + * @return mixed either the value of $headername (false if header is not present)
  872 + * or an array of all headers
  873 + */
  874 + function getResponseHeader($headername = null)
  875 + {
  876 + if (!isset($headername)) {
  877 + return isset($this->_response->_headers)? $this->_response->_headers: array();
  878 + } else {
  879 + $headername = strtolower($headername);
  880 + return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false;
  881 + }
  882 + }
  883 +
  884 + /**
  885 + * Returns the body of the response
  886 + *
  887 + * @access public
  888 + * @return mixed response body, false if not set
  889 + */
  890 + function getResponseBody()
  891 + {
  892 + return isset($this->_response->_body) ? $this->_response->_body : false;
  893 + }
  894 +
  895 + /**
  896 + * Returns cookies set in response
  897 + *
  898 + * @access public
  899 + * @return mixed array of response cookies, false if none are present
  900 + */
  901 + function getResponseCookies()
  902 + {
  903 + return isset($this->_response->_cookies) ? $this->_response->_cookies : false;
  904 + }
  905 +
  906 + /**
  907 + * Builds the request string
  908 + *
  909 + * @access private
  910 + * @return string The request string
  911 + */
  912 + function _buildRequest()
  913 + {
  914 + $separator = ini_get('arg_separator.output');
  915 + ini_set('arg_separator.output', '&');
  916 + $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : '';
  917 + ini_set('arg_separator.output', $separator);
  918 +
  919 + $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : '';
  920 + $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : '';
  921 + $path = $this->_url->path . $querystring;
  922 + $url = $host . $port . $path;
  923 +
  924 + if (!strlen($url)) {
  925 + $url = '/';
  926 + }
  927 +
  928 + $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
  929 +
  930 + if (in_array($this->_method, $this->_bodyDisallowed) ||
  931 + (0 == strlen($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method ||
  932 + (empty($this->_postData) && empty($this->_postFiles)))))
  933 + {
  934 + $this->removeHeader('Content-Type');
  935 + } else {
  936 + if (empty($this->_requestHeaders['content-type'])) {
  937 + // Add default content-type
  938 + $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
  939 + } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) {
  940 + $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime());
  941 + $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
  942 + }
  943 + }
  944 +
  945 + // Request Headers
  946 + if (!empty($this->_requestHeaders)) {
  947 + foreach ($this->_requestHeaders as $name => $value) {
  948 + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
  949 + $request .= $canonicalName . ': ' . $value . "\r\n";
  950 + }
  951 + }
  952 +
  953 + // Method does not allow a body, simply add a final CRLF
  954 + if (in_array($this->_method, $this->_bodyDisallowed)) {
  955 +
  956 + $request .= "\r\n";
  957 +
  958 + // Post data if it's an array
  959 + } elseif (HTTP_REQUEST_METHOD_POST == $this->_method &&
  960 + (!empty($this->_postData) || !empty($this->_postFiles))) {
  961 +
  962 + // "normal" POST request
  963 + if (!isset($boundary)) {
  964 + $postdata = implode('&', array_map(
  965 + create_function('$a', 'return $a[0] . \'=\' . $a[1];'),
  966 + $this->_flattenArray('', $this->_postData)
  967 + ));
  968 +
  969 + // multipart request, probably with file uploads
  970 + } else {
  971 + $postdata = '';
  972 + if (!empty($this->_postData)) {
  973 + $flatData = $this->_flattenArray('', $this->_postData);
  974 + foreach ($flatData as $item) {
  975 + $postdata .= '--' . $boundary . "\r\n";
  976 + $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"';
  977 + $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n";
  978 + }
  979 + }
  980 + foreach ($this->_postFiles as $name => $value) {
  981 + if (is_array($value['name'])) {
  982 + $varname = $name . ($this->_useBrackets? '[]': '');
  983 + } else {
  984 + $varname = $name;
  985 + $value['name'] = array($value['name']);
  986 + }
  987 + foreach ($value['name'] as $key => $filename) {
  988 + $fp = fopen($filename, 'r');
  989 + $basename = basename($filename);
  990 + $type = is_array($value['type'])? @$value['type'][$key]: $value['type'];
  991 +
  992 + $postdata .= '--' . $boundary . "\r\n";
  993 + $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"';
  994 + $postdata .= "\r\nContent-Type: " . $type;
  995 + $postdata .= "\r\n\r\n" . fread($fp, filesize($filename)) . "\r\n";
  996 + fclose($fp);
  997 + }
  998 + }
  999 + $postdata .= '--' . $boundary . "--\r\n";
  1000 + }
  1001 + $request .= 'Content-Length: ' .
  1002 + (HTTP_REQUEST_MBSTRING? mb_strlen($postdata, 'iso-8859-1'): strlen($postdata)) .
  1003 + "\r\n\r\n";
  1004 + $request .= $postdata;
  1005 +
  1006 + // Explicitly set request body
  1007 + } elseif (0 < strlen($this->_body)) {
  1008 +
  1009 + $request .= 'Content-Length: ' .
  1010 + (HTTP_REQUEST_MBSTRING? mb_strlen($this->_body, 'iso-8859-1'): strlen($this->_body)) .
  1011 + "\r\n\r\n";
  1012 + $request .= $this->_body;
  1013 +
  1014 + // No body: send a Content-Length header nonetheless (request #12900),
  1015 + // but do that only for methods that require a body (bug #14740)
  1016 + } else {
  1017 +
  1018 + if (in_array($this->_method, $this->_bodyRequired)) {
  1019 + $request .= "Content-Length: 0\r\n";
  1020 + }
  1021 + $request .= "\r\n";
  1022 + }
  1023 +
  1024 + return $request;
  1025 + }
  1026 +
  1027 + /**
  1028 + * Helper function to change the (probably multidimensional) associative array
  1029 + * into the simple one.
  1030 + *
  1031 + * @param string name for item
  1032 + * @param mixed item's values
  1033 + * @return array array with the following items: array('item name', 'item value');
  1034 + * @access private
  1035 + */
  1036 + function _flattenArray($name, $values)
  1037 + {
  1038 + if (!is_array($values)) {
  1039 + return array(array($name, $values));
  1040 + } else {
  1041 + $ret = array();
  1042 + foreach ($values as $k => $v) {
  1043 + if (empty($name)) {
  1044 + $newName = $k;
  1045 + } elseif ($this->_useBrackets) {
  1046 + $newName = $name . '[' . $k . ']';
  1047 + } else {
  1048 + $newName = $name;
  1049 + }
  1050 + $ret = array_merge($ret, $this->_flattenArray($newName, $v));
  1051 + }
  1052 + return $ret;
  1053 + }
  1054 + }
  1055 +
  1056 +
  1057 + /**
  1058 + * Adds a Listener to the list of listeners that are notified of
  1059 + * the object's events
  1060 + *
  1061 + * Events sent by HTTP_Request object
  1062 + * - 'connect': on connection to server
  1063 + * - 'sentRequest': after the request was sent
  1064 + * - 'disconnect': on disconnection from server
  1065 + *
  1066 + * Events sent by HTTP_Response object
  1067 + * - 'gotHeaders': after receiving response headers (headers are passed in $data)
  1068 + * - 'tick': on receiving a part of response body (the part is passed in $data)
  1069 + * - 'gzTick': on receiving a gzip-encoded part of response body (ditto)
  1070 + * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
  1071 + *
  1072 + * @param HTTP_Request_Listener listener to attach
  1073 + * @return boolean whether the listener was successfully attached
  1074 + * @access public
  1075 + */
  1076 + function attach(&$listener)
  1077 + {
  1078 + if (!is_a($listener, 'HTTP_Request_Listener')) {
  1079 + return false;
  1080 + }
  1081 + $this->_listeners[$listener->getId()] =& $listener;
  1082 + return true;
  1083 + }
  1084 +
  1085 +
  1086 + /**
  1087 + * Removes a Listener from the list of listeners
  1088 + *
  1089 + * @param HTTP_Request_Listener listener to detach
  1090 + * @return boolean whether the listener was successfully detached
  1091 + * @access public
  1092 + */
  1093 + function detach(&$listener)
  1094 + {
  1095 + if (!is_a($listener, 'HTTP_Request_Listener') ||
  1096 + !isset($this->_listeners[$listener->getId()])) {
  1097 + return false;
  1098 + }
  1099 + unset($this->_listeners[$listener->getId()]);
  1100 + return true;
  1101 + }
  1102 +
  1103 +
  1104 + /**
  1105 + * Notifies all registered listeners of an event.
  1106 + *
  1107 + * @param string Event name
  1108 + * @param mixed Additional data
  1109 + * @access private
  1110 + * @see HTTP_Request::attach()
  1111 + */
  1112 + function _notify($event, $data = null)
  1113 + {
  1114 + foreach (array_keys($this->_listeners) as $id) {
  1115 + $this->_listeners[$id]->update($this, $event, $data);
  1116 + }
  1117 + }
  1118 +}
  1119 +
  1120 +
  1121 +/**
  1122 + * Response class to complement the Request class
  1123 + *
  1124 + * @category HTTP
  1125 + * @package HTTP_Request
  1126 + * @author Richard Heyes <richard@phpguru.org>
  1127 + * @author Alexey Borzov <avb@php.net>
  1128 + * @version Release: 1.4.4
  1129 + */
  1130 +class HTTP_Response
  1131 +{
  1132 + /**
  1133 + * Socket object
  1134 + * @var Net_Socket
  1135 + */
  1136 + var $_sock;
  1137 +
  1138 + /**
  1139 + * Protocol
  1140 + * @var string
  1141 + */
  1142 + var $_protocol;
  1143 +
  1144 + /**
  1145 + * Return code
  1146 + * @var string
  1147 + */
  1148 + var $_code;
  1149 +
  1150 + /**
  1151 + * Response reason phrase
  1152 + * @var string
  1153 + */
  1154 + var $_reason;
  1155 +
  1156 + /**
  1157 + * Response headers
  1158 + * @var array
  1159 + */
  1160 + var $_headers;
  1161 +
  1162 + /**
  1163 + * Cookies set in response
  1164 + * @var array
  1165 + */
  1166 + var $_cookies;
  1167 +
  1168 + /**
  1169 + * Response body
  1170 + * @var string
  1171 + */
  1172 + var $_body = '';
  1173 +
  1174 + /**
  1175 + * Used by _readChunked(): remaining length of the current chunk
  1176 + * @var string
  1177 + */
  1178 + var $_chunkLength = 0;
  1179 +
  1180 + /**
  1181 + * Attached listeners
  1182 + * @var array
  1183 + */
  1184 + var $_listeners = array();
  1185 +
  1186 + /**
  1187 + * Bytes left to read from message-body
  1188 + * @var null|int
  1189 + */
  1190 + var $_toRead;
  1191 +
  1192 + /**
  1193 + * Constructor
  1194 + *
  1195 + * @param Net_Socket socket to read the response from
  1196 + * @param array listeners attached to request
  1197 + */
  1198 + function HTTP_Response(&$sock, &$listeners)
  1199 + {
  1200 + $this->_sock =& $sock;
  1201 + $this->_listeners =& $listeners;
  1202 + }
  1203 +
  1204 +
  1205 + /**
  1206 + * Processes a HTTP response
  1207 + *
  1208 + * This extracts response code, headers, cookies and decodes body if it
  1209 + * was encoded in some way
  1210 + *
  1211 + * @access public
  1212 + * @param bool Whether to store response body in object property, set
  1213 + * this to false if downloading a LARGE file and using a Listener.
  1214 + * This is assumed to be true if body is gzip-encoded.
  1215 + * @param bool Whether the response can actually have a message-body.
  1216 + * Will be set to false for HEAD requests.
  1217 + * @throws PEAR_Error
  1218 + * @return mixed true on success, PEAR_Error in case of malformed response
  1219 + */
  1220 + function process($saveBody = true, $canHaveBody = true)
  1221 + {
  1222 + do {
  1223 + $line = $this->_sock->readLine();
  1224 + if (!preg_match('!^(HTTP/\d\.\d) (\d{3})(?: (.+))?!', $line, $s)) {
  1225 + return PEAR::raiseError('Malformed response', HTTP_REQUEST_ERROR_RESPONSE);
  1226 + } else {
  1227 + $this->_protocol = $s[1];
  1228 + $this->_code = intval($s[2]);
  1229 + $this->_reason = empty($s[3])? null: $s[3];
  1230 + }
  1231 + while ('' !== ($header = $this->_sock->readLine())) {
  1232 + $this->_processHeader($header);
  1233 + }
  1234 + } while (100 == $this->_code);
  1235 +
  1236 + $this->_notify('gotHeaders', $this->_headers);
  1237 +
  1238 + // RFC 2616, section 4.4:
  1239 + // 1. Any response message which "MUST NOT" include a message-body ...
  1240 + // is always terminated by the first empty line after the header fields
  1241 + // 3. ... If a message is received with both a
  1242 + // Transfer-Encoding header field and a Content-Length header field,
  1243 + // the latter MUST be ignored.
  1244 + $canHaveBody = $canHaveBody && $this->_code >= 200 &&
  1245 + $this->_code != 204 && $this->_code != 304;
  1246 +
  1247 + // If response body is present, read it and decode
  1248 + $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']);
  1249 + $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']);
  1250 + $hasBody = false;
  1251 + if ($canHaveBody && ($chunked || !isset($this->_headers['content-length']) ||
  1252 + 0 != $this->_headers['content-length']))
  1253 + {
  1254 + if ($chunked || !isset($this->_headers['content-length'])) {
  1255 + $this->_toRead = null;
  1256 + } else {
  1257 + $this->_toRead = $this->_headers['content-length'];
  1258 + }
  1259 + while (!$this->_sock->eof() && (is_null($this->_toRead) || 0 < $this->_toRead)) {
  1260 + if ($chunked) {
  1261 + $data = $this->_readChunked();
  1262 + } elseif (is_null($this->_toRead)) {
  1263 + $data = $this->_sock->read(4096);
  1264 + } else {
  1265 + $data = $this->_sock->read(min(4096, $this->_toRead));
  1266 + $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
  1267 + }
  1268 + if ('' == $data && (!$this->_chunkLength || $this->_sock->eof())) {
  1269 + break;
  1270 + } else {
  1271 + $hasBody = true;
  1272 + if ($saveBody || $gzipped) {
  1273 + $this->_body .= $data;
  1274 + }
  1275 + $this->_notify($gzipped? 'gzTick': 'tick', $data);
  1276 + }
  1277 + }
  1278 + }
  1279 +
  1280 + if ($hasBody) {
  1281 + // Uncompress the body if needed
  1282 + if ($gzipped) {
  1283 + $body = $this->_decodeGzip($this->_body);
  1284 + if (PEAR::isError($body)) {
  1285 + return $body;
  1286 + }
  1287 + $this->_body = $body;
  1288 + $this->_notify('gotBody', $this->_body);
  1289 + } else {
  1290 + $this->_notify('gotBody');
  1291 + }
  1292 + }
  1293 + return true;
  1294 + }
  1295 +
  1296 +
  1297 + /**
  1298 + * Processes the response header
  1299 + *
  1300 + * @access private
  1301 + * @param string HTTP header
  1302 + */
  1303 + function _processHeader($header)
  1304 + {
  1305 + if (false === strpos($header, ':')) {
  1306 + return;
  1307 + }
  1308 + list($headername, $headervalue) = explode(':', $header, 2);
  1309 + $headername = strtolower($headername);
  1310 + $headervalue = ltrim($headervalue);
  1311 +
  1312 + if ('set-cookie' != $headername) {
  1313 + if (isset($this->_headers[$headername])) {
  1314 + $this->_headers[$headername] .= ',' . $headervalue;
  1315 + } else {
  1316 + $this->_headers[$headername] = $headervalue;
  1317 + }
  1318 + } else {
  1319 + $this->_parseCookie($headervalue);
  1320 + }
  1321 + }
  1322 +
  1323 +
  1324 + /**
  1325 + * Parse a Set-Cookie header to fill $_cookies array
  1326 + *
  1327 + * @access private
  1328 + * @param string value of Set-Cookie header
  1329 + */
  1330 + function _parseCookie($headervalue)
  1331 + {
  1332 + $cookie = array(
  1333 + 'expires' => null,
  1334 + 'domain' => null,
  1335 + 'path' => null,
  1336 + 'secure' => false
  1337 + );
  1338 +
  1339 + // Only a name=value pair
  1340 + if (!strpos($headervalue, ';')) {
  1341 + $pos = strpos($headervalue, '=');
  1342 + $cookie['name'] = trim(substr($headervalue, 0, $pos));
  1343 + $cookie['value'] = trim(substr($headervalue, $pos + 1));
  1344 +
  1345 + // Some optional parameters are supplied
  1346 + } else {
  1347 + $elements = explode(';', $headervalue);
  1348 + $pos = strpos($elements[0], '=');
  1349 + $cookie['name'] = trim(substr($elements[0], 0, $pos));
  1350 + $cookie['value'] = trim(substr($elements[0], $pos + 1));
  1351 +
  1352 + for ($i = 1; $i < count($elements); $i++) {
  1353 + if (false === strpos($elements[$i], '=')) {
  1354 + $elName = trim($elements[$i]);
  1355 + $elValue = null;
  1356 + } else {
  1357 + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
  1358 + }
  1359 + $elName = strtolower($elName);
  1360 + if ('secure' == $elName) {
  1361 + $cookie['secure'] = true;
  1362 + } elseif ('expires' == $elName) {
  1363 + $cookie['expires'] = str_replace('"', '', $elValue);
  1364 + } elseif ('path' == $elName || 'domain' == $elName) {
  1365 + $cookie[$elName] = urldecode($elValue);
  1366 + } else {
  1367 + $cookie[$elName] = $elValue;
  1368 + }
  1369 + }
  1370 + }
  1371 + $this->_cookies[] = $cookie;
  1372 + }
  1373 +
  1374 +
  1375 + /**
  1376 + * Read a part of response body encoded with chunked Transfer-Encoding
  1377 + *
  1378 + * @access private
  1379 + * @return string
  1380 + */
  1381 + function _readChunked()
  1382 + {
  1383 + // at start of the next chunk?
  1384 + if (0 == $this->_chunkLength) {
  1385 + $line = $this->_sock->readLine();
  1386 + if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
  1387 + $this->_chunkLength = hexdec($matches[1]);
  1388 + // Chunk with zero length indicates the end
  1389 + if (0 == $this->_chunkLength) {
  1390 + $this->_sock->readLine(); // make this an eof()
  1391 + return '';
  1392 + }
  1393 + } else {
  1394 + return '';
  1395 + }
  1396 + }
  1397 + $data = $this->_sock->read($this->_chunkLength);
  1398 + $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
  1399 + if (0 == $this->_chunkLength) {
  1400 + $this->_sock->readLine(); // Trailing CRLF
  1401 + }
  1402 + return $data;
  1403 + }
  1404 +
  1405 +
  1406 + /**
  1407 + * Notifies all registered listeners of an event.
  1408 + *
  1409 + * @param string Event name
  1410 + * @param mixed Additional data
  1411 + * @access private
  1412 + * @see HTTP_Request::_notify()
  1413 + */
  1414 + function _notify($event, $data = null)
  1415 + {
  1416 + foreach (array_keys($this->_listeners) as $id) {
  1417 + $this->_listeners[$id]->update($this, $event, $data);
  1418 + }
  1419 + }
  1420 +
  1421 +
  1422 + /**
  1423 + * Decodes the message-body encoded by gzip
  1424 + *
  1425 + * The real decoding work is done by gzinflate() built-in function, this
  1426 + * method only parses the header and checks data for compliance with
  1427 + * RFC 1952
  1428 + *
  1429 + * @access private
  1430 + * @param string gzip-encoded data
  1431 + * @return string decoded data
  1432 + */
  1433 + function _decodeGzip($data)
  1434 + {
  1435 + if (HTTP_REQUEST_MBSTRING) {
  1436 + $oldEncoding = mb_internal_encoding();
  1437 + mb_internal_encoding('iso-8859-1');
  1438 + }
  1439 + $length = strlen($data);
  1440 + // If it doesn't look like gzip-encoded data, don't bother
  1441 + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
  1442 + return $data;
  1443 + }
  1444 + $method = ord(substr($data, 2, 1));
  1445 + if (8 != $method) {
  1446 + return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD);
  1447 + }
  1448 + $flags = ord(substr($data, 3, 1));
  1449 + if ($flags & 224) {
  1450 + return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA);
  1451 + }
  1452 +
  1453 + // header is 10 bytes minimum. may be longer, though.
  1454 + $headerLength = 10;
  1455 + // extra fields, need to skip 'em
  1456 + if ($flags & 4) {
  1457 + if ($length - $headerLength - 2 < 8) {
  1458 + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
  1459 + }
  1460 + $extraLength = unpack('v', substr($data, 10, 2));
  1461 + if ($length - $headerLength - 2 - $extraLength[1] < 8) {
  1462 + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
  1463 + }
  1464 + $headerLength += $extraLength[1] + 2;
  1465 + }
  1466 + // file name, need to skip that
  1467 + if ($flags & 8) {
  1468 + if ($length - $headerLength - 1 < 8) {
  1469 + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
  1470 + }
  1471 + $filenameLength = strpos(substr($data, $headerLength), chr(0));
  1472 + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {
  1473 + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
  1474 + }
  1475 + $headerLength += $filenameLength + 1;
  1476 + }
  1477 + // comment, need to skip that also
  1478 + if ($flags & 16) {
  1479 + if ($length - $headerLength - 1 < 8) {
  1480 + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
  1481 + }
  1482 + $commentLength = strpos(substr($data, $headerLength), chr(0));
  1483 + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {
  1484 + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
  1485 + }
  1486 + $headerLength += $commentLength + 1;
  1487 + }
  1488 + // have a CRC for header. let's check
  1489 + if ($flags & 1) {
  1490 + if ($length - $headerLength - 2 < 8) {
  1491 + return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
  1492 + }
  1493 + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength));
  1494 + $crcStored = unpack('v', substr($data, $headerLength, 2));
  1495 + if ($crcReal != $crcStored[1]) {
  1496 + return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
  1497 + }
  1498 + $headerLength += 2;
  1499 + }
  1500 + // unpacked data CRC and size at the end of encoded data
  1501 + $tmp = unpack('V2', substr($data, -8));
  1502 + $dataCrc = $tmp[1];
  1503 + $dataSize = $tmp[2];
  1504 +
  1505 + // finally, call the gzinflate() function
  1506 + // don't pass $dataSize to gzinflate, see bugs #13135, #14370
  1507 + $unpacked = gzinflate(substr($data, $headerLength, -8));
  1508 + if (false === $unpacked) {
  1509 + return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ);
  1510 + } elseif ($dataSize != strlen($unpacked)) {
  1511 + return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ);
  1512 + } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
  1513 + return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
  1514 + }
  1515 + if (HTTP_REQUEST_MBSTRING) {
  1516 + mb_internal_encoding($oldEncoding);
  1517 + }
  1518 + return $unpacked;
  1519 + }
  1520 +} // End class HTTP_Response
  1521 +?>
Please register or login to post a comment