--- /dev/null
+<?php
+// vim: tabstop=2:shiftwidth=2
+
+/**
+ * AsyncHTTP.php ($Revision$)
+ *
+ * by hsur ( http://blog.cles.jp/np_cles )
+ * $Id$
+ */
+
+/*
+ * Copyright (C) 2007 CLES. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, cles( http://blog.cles.jp/np_cles ) gives
+ * permission to link the code of this program with those files in the PEAR
+ * library that are licensed under the PHP License (or with modified versions
+ * of those files that use the same license as those files), and distribute
+ * linked combinations including the two. You must obey the GNU General Public
+ * License in all respects for all of the code used other than those files in
+ * the PEAR library that are licensed under the PHP License. If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so. If you do not wish to do so, delete
+ * this exception statement from your version.
+ */
+
+/* Examples
+ *
+ * $ahttp = new cles_AsyncHTTP();
+ *
+ * $reqestId[] = $http->setRequest('http://example.com/url1','GET');
+ * $reqestId[] = $http->setRequest('http://example.com/url2','GET');
+ *
+ * $response = $http->getResponses();
+ */
+
+define('CLES_ASYNCHTTP_GETBYTES', 8192);
+define('CLES_ASYNCHTTP_INPROGRESS', 115);
+define('CLES_ASYNCHTTP_TIMEOUT', 110);
+
+class cles_AsyncHTTP {
+ var $asyncMode;
+ var $timeout = 120;
+ var $userAgent = 'CLES AsyncHTTP Lib';
+
+ var $_requests;
+ var $_sockets;
+ var $_responses;
+ var $_errornos;
+ var $_errorstrs;
+
+ var $_debug = false;
+ var $_debugMsg = '';
+
+ function _getTimeStamp(){
+ list($usec, $sec) = explode(" ", microtime());
+ return $timestamp = date('Y/m/d H:i:s').substr($usec,1);
+ }
+
+ function _log($msg){
+ $m = $this->_getTimeStamp().':'.$msg."\n";
+ $this->_debugMsg .= $m;
+// echo $msg;
+ }
+
+ function cles_AsyncHTTP(){
+ $this->init();
+ }
+
+ function init() {
+ $this->_requests = array();
+ $this->_sockets = array();
+ $this->_responses = array();
+ $this->_errornos = array();
+ $this->_errorstrs = array();
+
+ $this->asyncMode = function_exists('socket_create') ? true : false;
+ }
+
+ function setRequest($url, $method = "", $headers = "", $post = array ("")){
+ $this->_requests[] = func_get_args();
+ return count($this->_requests) - 1;
+ }
+
+ function getResponses(){
+ $this->_startedTimestamp = $this->_getTimeStamp();
+
+ if( $this->asyncMode )
+ $this->_sendAsync();
+ else
+ $this->_sendSync();
+
+ foreach( $this->_responses as $id => $response){
+ if( $this->_errornos[$id] !== 0 ){
+ unset($this->_responses[$id]);
+ continue;
+ }
+
+ list($header, $body) = split("\r\n\r\n", $response, 2);
+ preg_match("/HTTP\/1\.[0-1] ([0-9]+) ([^\r\n]*)\r?\n/", $header, $httpresp);
+ $respCd = $httpresp[1];
+ $respMsg = $httpresp[2];
+
+ if( $respCd != '200' ){
+ $this->_errornos[$id] = -1;
+ $this->_errorstrs[$id] = 'HTTP Error: '."[$respCd] (".$this->_requests[$id][0].") $respMsg";
+ unset($this->_responses[$id]);
+ } else {
+ $this->_responses[$id] = $body;
+ }
+ }
+
+ $this->_finishedTimestamp = $this->_getTimeStamp();
+ return $this->_responses;
+ }
+
+ function isError($id){
+ if( $this->_errornos[$id] === 0 )
+ return false;
+ else
+ return true;
+ }
+
+ function getErrorNo($id){
+ return $this->_errornos[$id];
+ }
+
+ function getError($id){
+ return $this->_errorstrs[$id];
+ }
+
+ function _sendAsync(){
+ $this->_debug && $this->_log('Using async mode.');
+ $expired = time() + $this->timeout;
+
+ // connect
+ foreach ($this->_requests as $id => $request) {
+ $url = parse_url($request[0]);
+ $port = ($url['port'] ? $url['port'] : 80);
+
+ $this->_debug && $this->_log('Open async connection (id:'.$id.')');
+ if (phpversion() >= '5.0.0') {
+ $s = stream_socket_client($url['host'].":".$port, $this->_errornos[$id], $this->_errorstrs[$id], $this->timeout, STREAM_CLIENT_ASYNC_CONNECT);
+ } else {
+ $s = $this->_async_connect($url['host'], $port, $this->_errornos[$id], $this->_errorstrs[$id], $this->timeout);
+ }
+ if ($s) {
+ $this->_sockets[$id] = $s;
+ $this->_responses[$id] = '';
+ } else {
+ $this->_errornos[$id] = -1;
+ $this->_errorstrs[$id] = 'Connection Failed '.__LINE__;
+ }
+ }
+
+ // send and recieve
+ while (count($this->_sockets)) {
+ $read = $write = $this->_sockets;
+ $e = null;
+
+ $timeout = $expired - time();
+ $timeout = ($timeout < 0 ) ? 0 : $timeout;
+
+ $this->_debug && $this->_log('socket_select (timeout:'.$timeout.')');
+ if (phpversion() >= '5.0.0') {
+ $n = stream_select($read, $write, $e, $timeout );
+ } else {
+ $n = socket_select($read, $write, $e, $timeout );
+ }
+
+ if( $n ){
+ foreach ($write as $w) {
+ $id = array_search($w, $this->_sockets);
+ $this->_debug && $this->_log('Request send (id:'.$id.')');
+ if (phpversion() >= '5.0.0') {
+ fwrite($w, $this->_makePayload($id));
+// stream_socket_shutdown($w, 1);
+ } else {
+ socket_write($w, $this->_makePayload($id));
+ socket_shutdown($w, 1);
+ }
+ }
+ foreach ($read as $r) {
+ $id = array_search($r, $this->_sockets);
+ if (phpversion() >= '5.0.0') {
+ $data = fread($r, CLES_ASYNCHTTP_GETBYTES);
+ } else {
+ $data = socket_read($r, CLES_ASYNCHTTP_GETBYTES);
+ }
+ $this->_debug && $this->_log('Response recieved (id:'.$id.', length:'.strlen($data).')');
+ if (strlen($data) == 0) {
+ if ($this->_errornos[$id] == CLES_ASYNCHTTP_INPROGRESS) {
+ $this->_errornos[$id] = -1;
+ $this->_errorstrs[$id] = 'Connection Failed'.__LINE__;
+ }
+ if (phpversion() >= '5.0.0') {
+ fclose($r);
+ } else {
+ socket_close($r);
+ }
+ unset($this->_sockets[$id]);
+ $this->_debug && $this->_log('Connection closed (id:'.$id.')');
+ } else {
+ $this->_errornos[$id] = 0;
+ $this->_errorstrs[$id] = '';
+ $this->_responses[$id] .= $data;
+ }
+ }
+ } else {
+ foreach ($this->_sockets as $id => $s) {
+ $this->_debug && $this->_log('Timeout (id:'.$id.')');
+ $this->_errornos[$id] = CLES_ASYNCHTTP_TIMEOUT;
+ $this->_errorstrs[$id] = socket_strerror(CLES_ASYNCHTTP_TIMEOUT);
+ if (phpversion() >= '5.0.0') {
+ fclose($s);
+ } else {
+ socket_close($s);
+ }
+ unset($this->_sockets[$id]);
+ }
+ break;
+ }
+ }
+ }
+
+ function _sendSync(){
+ $this->_debug && $this->_log('Using sync mode.');
+ $expired = time() + $this->timeout;
+
+ foreach ($this->_requests as $id => $request) {
+ $url = parse_url($request[0]);
+ $port = ($url['port'] ? $url['port'] : 80);
+
+ $timeout = $expired - time();
+ $timeout = ($timeout < 1 ) ? 1 : $timeout;
+ $s = fsockopen($url['host'], $port, $this->_errornos[$id], $this->_errorstrs[$id], $timeout);
+ stream_set_timeout($s, $timeout);
+ if ($s) {
+ $this->_responses[$id] = '';
+ $this->_debug && $this->_log('Request send (id:'.$id.')');
+ fputs($s, $this->_makePayload($id));
+ while (!feof($s)) {
+ $data = fgets($s, CLES_ASYNCHTTP_GETBYTES);
+ $this->_debug && $this->_log('Response recieved (id:'.$id.', length:'.strlen($data).')');
+ $this->_responses[$id] .= $data;
+ }
+ $this->_debug && $this->_log('Connection closed (id:'.$id.')');
+ fclose($s);
+ } else {
+ $this->_errornos[$id] = -1;
+ $this->_errorstrs[$id] = 'Connection Failed '.__LINE__;
+ }
+ }
+ }
+
+ function _makePayload($id){
+ $params = $this->_requests[$id];
+ $url = $params[0];
+ $method = (strtoupper($params[1]) == 'POST') ? 'POST' : 'GET';
+ $headers = $params[2];
+ $post = $params[3];
+
+ $url = parse_url($url);
+ if (isset ($url['query'])) {
+ $url['query'] = "?".$url['query'];
+ } else {
+ $url['query'] = "";
+ }
+
+ if (!isset ($url['port']))
+ $url['port'] = 80;
+
+ $request = $method.' '.$url['path'].$url['query']." HTTP/1.0\r\n";
+ $request .= ( $url['port'] == 80 )?
+ "Host: " . $url['host'] . "\r\n" :
+ "Host: " . $url['host'] . ':' . $url['port'] . "\r\n";
+ $request .= 'User-Agent: '.$this->userAgent."\r\n";
+ if (isset ($url['user']) && isset ($url['pass'])) {
+ $request .= "Authorization: Basic ".base64_encode($url['user'].":".$url['pass'])."\r\n";
+ }
+ $request .= $headers;
+
+ if( $method == "POST" ){
+ $postdata = array();
+ while (list ($name, $value) = each($post)) {
+ $postdata[] = $name."=".urlencode($value);
+ }
+ $postdata = implode("&", $postdata);
+ $request .= "Connection: Close\r\n";
+ $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
+ $request .= "Content-Length: ".strlen($postdata)."\r\n";
+ $request .= "\r\n";
+ $request .= $postdata;
+ } else {
+ $request .= "\r\n";
+ }
+
+ return $request;
+ }
+
+ function _async_connect($host, $port, &$errno, &$errstr, $timeout) {
+ $ip = gethostbyname($host);
+ $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+ if (socket_set_nonblock($socket)) {
+ $r = @socket_connect($socket, $ip, $port);
+ if ($r || socket_last_error() == CLES_ASYNCHTTP_INPROGRESS) {
+ return $socket;
+ }
+ }
+
+ $errno = socket_last_error($socket);
+ $errstr = socket_strerror($errno);
+ socket_close($socket);
+ return false;
+ }
+}
--- /dev/null
+<?php
+// vim: tabstop=2:shiftwidth=2
+
+/**
+ * AsyncHTTP.php ($Revision$)
+ *
+ * by hsur ( http://blog.cles.jp/np_cles )
+ * $Id$
+ */
+
+/*
+ * Copyright (C) 2007 CLES. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, cles( http://blog.cles.jp/np_cles ) gives
+ * permission to link the code of this program with those files in the PEAR
+ * library that are licensed under the PHP License (or with modified versions
+ * of those files that use the same license as those files), and distribute
+ * linked combinations including the two. You must obey the GNU General Public
+ * License in all respects for all of the code used other than those files in
+ * the PEAR library that are licensed under the PHP License. If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so. If you do not wish to do so, delete
+ * this exception statement from your version.
+ */
+
+require_once 'cles/AsyncHTTP.php';
+
+class cles_AsyncHTTP_RawPost extends cles_AsyncHTTP {
+ var $userAgent = 'CLES AsyncHTTP(RawPost) Lib';
+
+ function cles_AsyncHTTP_RawPost(){
+ $this->init();
+ }
+
+ function _makePayload($id){
+ $params = $this->_requests[$id];
+ $url = $params[0];
+ $method = 'POST';
+ $headers = $params[2];
+ $rawpost = $params[3];
+
+ $url = parse_url($url);
+ if (isset ($url['query'])) {
+ $url['query'] = "?".$url['query'];
+ } else {
+ $url['query'] = "";
+ }
+
+ if (!isset ($url['port']))
+ $url['port'] = 80;
+
+ $request = $method.' '.$url['path'].$url['query']." HTTP/1.1\r\n";
+ $request .= ( $url['port'] == 80 )?
+ "Host: " . $url['host'] . "\r\n" :
+ "Host: " . $url['host'] . ':' . $url['port'] . "\r\n";
+ $request .= "Connection: Close\r\n";
+ $request .= 'User-Agent: '.$this->userAgent."\r\n";
+ if (isset ($url['user']) && isset ($url['pass'])) {
+ $request .= "Authorization: Basic ".base64_encode($url['user'].":".$url['pass'])."\r\n";
+ }
+ $request .= $headers;
+
+ $request .= "Content-Length: ".strlen($rawpost)."\r\n";
+ $request .= "\r\n";
+ $request .= $rawpost;
+
+ return $request;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+// vim: tabstop=2:shiftwidth=2
+
+/**
+ * sharedlibs.php ($Revision$)
+ *
+ * by hsur ( http://blog.cles.jp/np_cles )
+ * $Id$
+*/
+
+/*
+ * Copyright (C) 2006 CLES. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, cles( http://blog.cles.jp/np_cles ) gives
+ * permission to link the code of this program with those files in the PEAR
+ * library that are licensed under the PHP License (or with modified versions
+ * of those files that use the same license as those files), and distribute
+ * linked combinations including the two. You must obey the GNU General Public
+ * License in all respects for all of the code used other than those files in
+ * the PEAR library that are licensed under the PHP License. If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so. If you do not wish to do so, delete
+ * this exception statement from your version.
+*/
+
+if (!defined('NP_SHAREDLIBS_LOADED')) {
+ if (!defined('PATH_SEPARATOR')) {
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ define('PATH_SEPARATOR', ';');
+ } else {
+ define('PATH_SEPARATOR', ':');
+ }
+ }
+ ini_set('include_path', dirname(__FILE__).PATH_SEPARATOR.ini_get('include_path'));
+
+ define('NP_SHAREDLIBS_LOADED', true);
+}