Created
April 19, 2010 01:02
-
-
Save saltybeagle/370653 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// XMLHTTP JS class is is developed by Alex Serebryakov (#0.9.1) | |
// For more information, consult www.ajaxextended.com | |
// What's new in 0.9.1: | |
// - fixed the _createQuery function (used to force multipart requests) | |
// - fixed the getResponseHeader function (incorrect search) | |
// - fixed the _parseXML function (bug in the ActiveX parsing section) | |
// - fixed the _destroyScripts function (DOM errors reported) | |
proxy_xmlhttp = function() { | |
// The following two options are configurable | |
// you don't need to change the rest. Plug & play! | |
var _maximumRequestLength = 1500; | |
var _apiURL = 'http://www.yourhost.com/xmlhttp.php'; | |
this.status = null; | |
this.statusText = null; | |
this.responseText = null; | |
this.responseXML = null; | |
this.synchronous = false; | |
this.readyState = 0; | |
this.onreadystatechange = function() { }; | |
this.onerror = function() { }; | |
this.onload = function() { }; | |
this.abort = function() { | |
_stop = true; | |
_destroyScripts(); | |
}; | |
this.getAllResponseHeaders = function() { | |
// Returns all response headers as a string | |
var result = ''; | |
for (var property in _responseHeaders) { | |
result += property + ': ' + _responseHeaders[property] + '\r\n'; | |
} | |
return result; | |
}; | |
this.getResponseHeader = function(name) { | |
// Returns a response header value | |
// Note, that the search is case-insensitive | |
for(var property in _responseHeaders) { | |
if(property.toLowerCase() == name.toLowerCase()) { | |
return _responseHeaders[property]; | |
} | |
} | |
return null; | |
}; | |
this.overrideMimeType = function(type) { | |
_overrideMime = type; | |
}; | |
this.open = function(method, url, sync, userName, password) { | |
// Setting the internal values | |
if (!_checkParameters(method, url)) { | |
return; | |
} | |
_method = (method) ? method : ''; | |
_url = (url) ? url : ''; | |
_userName = (userName) ? userName : ''; | |
_password = (password) ? password : ''; | |
_setReadyState(1); | |
}; | |
this.openRequest = function(method, url, sync, userName, password) { | |
// This method is inserted for compatibility purposes only | |
return this.open(method, url, sync, userName, password); | |
}; | |
this.send = function(data) { | |
if (_stop) { | |
return; | |
} | |
var src = _createQuery(data); | |
_createScript(src); | |
// _setReadyState(2); | |
}; | |
this.setRequestHeader = function(name, value) { | |
// Set the request header. If the defined header | |
// already exists (search is case-insensitive), rewrite it | |
if (_stop) { | |
return; | |
} | |
for(var property in _requestHeaders) { | |
if(property.toLowerCase() == name.toLowerCase()) { | |
_requestHeaders[property] = value; return; | |
} | |
} | |
_requestHeaders[name] = value; | |
}; | |
var _method = ''; | |
var _url = ''; | |
var _userName = ''; | |
var _password = ''; | |
var _requestHeaders = { | |
"HTTP-Referer": escape(document.location), | |
"Content-Type": "application/x-www-form-urlencoded" | |
}; | |
var _responseHeaders = { }; | |
var _overrideMime = ""; | |
var self = this; | |
var _id = ''; | |
var _scripts = []; | |
var _stop = false; | |
var _throwError = function(description) { | |
// Stop script execution and run | |
// the user-defined error handler | |
self.onerror(description); | |
self.abort(); | |
return false; | |
}; | |
var _createQuery = function(data) { | |
if(!data) { | |
data = ''; | |
} | |
var headers = ''; | |
for (var property in _requestHeaders) { | |
headers += property + '=' + _requestHeaders[property] + '&'; | |
} | |
var originalsrc = _method + | |
'$' + _id + | |
'$' + _userName + | |
'$' + _password + | |
'$' + headers + | |
'$' + _escape(data) + | |
'$' + _url; | |
var src = originalsrc; | |
var max = _maximumRequestLength, request = []; | |
var total = Math.floor(src.length / max), current = 0; | |
while(src.length > 0) { | |
var query = _apiURL + '?' + 'multipart' + '$' + _id + '$' + current++ + '$' + total + '$' + src.substr(0, max); | |
request.push(query); | |
src = src.substr(max); | |
} | |
if(request.length == 1) { | |
src = _apiURL + '?' + originalsrc; | |
} else { | |
src = request; | |
} | |
return src; | |
}; | |
var _checkParameters = function(method, url) { | |
// Check the method value (GET, POST, HEAD) | |
// and the prefix of the url (http://) | |
if(!method) { | |
return _throwError('Please, specify the query method (GET, POST or HEAD)'); | |
} | |
if(!url) { | |
return _throwError('Please, specify the URL'); | |
} | |
if(method.toLowerCase() != 'get' && | |
method.toLowerCase() != 'post' && | |
method.toLowerCase() != 'head') { | |
return _throwError('Please, specify either a GET, POST or a HEAD method'); | |
} | |
if(url.toLowerCase().substr(0,7) != 'http://') { | |
return _throwError('Only HTTP protocol is supported (http://)'); | |
} | |
return true; | |
}; | |
var _createScript = function(src) { | |
if ('object' == typeof src) { | |
for(var i = 0; i < src.length; i++) { | |
_createScript(src[i]); | |
} | |
return true; | |
} | |
// Create the SCRIPT tag | |
var script = document.createElement('script'); | |
script.src = src; | |
script.type = 'text/javascript'; | |
if (navigator.userAgent.indexOf('Safari')){ | |
script.charset = 'utf-8'; // Safari bug | |
} | |
script = document.getElementsByTagName('head')[0].appendChild(script); | |
_scripts.push(script); | |
return script; | |
}; | |
var _escape = function(string) { | |
// Native escape() function doesn't quote the plus sign + | |
string = escape(string); | |
string = string.replace('+', '%2B'); | |
return string; | |
}; | |
var _destroyScripts = function() { | |
// Removes the SCRIPT nodes used by the class | |
for(var i = 0; i < _scripts.length; i++) { | |
if(_scripts[i].parentNode) { | |
_scripts[i].parentNode.removeChild(_scripts[i]); | |
} | |
} | |
}; | |
var _registerCallback = function() { | |
// Register a callback variable (in global scope) | |
// that points to current instance of the class | |
_id = 'v' + Math.random().toString().substr(2); | |
window[_id] = self; | |
}; | |
var _setReadyState = function(number) { | |
// Set the ready state property of the class | |
self.readyState = number; | |
self.onreadystatechange(); | |
if(number == 4) { | |
self.onload(); | |
} | |
}; | |
var _parseXML = function() { | |
var type = self.getResponseHeader('Content-type') + _overrideMime; | |
if(!(type.indexOf('html') > -1 || type.indexOf('xml') > -1)) { | |
return; | |
} | |
var xml; | |
if(document.implementation && | |
document.implementation.createDocument && | |
navigator.userAgent.indexOf('Opera') == -1) { | |
var parser = new DOMParser(); | |
xml = parser.parseFromString(self.responseText, "text/xml"); | |
self.responseXML = xml; | |
} else if (window.ActiveXObject) { | |
xml = new ActiveXObject('MSXML2.DOMDocument.3.0'); | |
if (xml.loadXML(self.responseText)) { | |
self.responseXML = xml; | |
} | |
} else { | |
xml = document.body.appendChild(document.createElement('div')); | |
xml.style.display = 'none'; | |
xml.innerHTML = self.responseText; | |
_cleanWhitespace(xml, true); | |
self.responseXML = xml.childNodes[0]; | |
document.body.removeChild(xml); | |
} | |
}; | |
var _cleanWhitespace = function(element, deep) { | |
var i = element.childNodes.length; | |
if(i === 0) { | |
return; | |
} | |
do { | |
var node = element.childNodes[--i]; | |
if (node.nodeType == 3 && !_cleanEmptySymbols(node.nodeValue)) { | |
element.removeChild(node); | |
} | |
if (node.nodeType == 1 && deep) { | |
_cleanWhitespace(node, true); | |
} | |
} while(i > 0); | |
}; | |
var _cleanEmptySymbols = function(string) { | |
string = string.replace('\r', ''); | |
string = string.replace('\n', ''); | |
string = string.replace(' ', ''); | |
return (string.length === 0) ? false : true; | |
}; | |
this._parse = function(object) { | |
// Parse the received data and set all | |
// the appropriate properties of the class | |
if(_stop) { | |
return true; | |
} | |
if(object.multipart) { | |
return true; | |
} | |
if(!object.success) { | |
return _throwError(object.description); | |
} | |
_responseHeaders = object.responseHeaders; | |
this.status = object.status; | |
this.statusText = object.statusText; | |
this.responseText = object.responseText; | |
_parseXML(); | |
_destroyScripts(); | |
_setReadyState(4); | |
return true; | |
}; | |
_registerCallback(); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// XMLHTTP PHP class is developed by Alex Serebryakov (#0.9.1) | |
// For more information, consult www.ajaxextended.com | |
// NOTE: THE FILE SHOULD BE SAVED AS UTF-8 WITHOUT BOM | |
$AJAX = new XMLHTTP(); | |
class XMLHTTP | |
{ | |
var $env = Array(); | |
var $log = false; | |
var $abort = false; | |
function XMLHTTP() { | |
$query = $_SERVER['QUERY_STRING']; | |
$query = $this->checkMultipart($query); | |
$this->getEnvironment($query); | |
$data = $this->contactServer(); | |
$data = $this->parseData($data); | |
if($this->log) $this->logRequest('successfull'); | |
$this->respond($data); | |
} | |
function checkMultipart($query) { | |
$q = $this->splitData('$', $query, 5); | |
if($q[0] != "multipart") return $query; | |
if(strpos($q[1], ".") > -1) { | |
$this->logRequest('HACK ATTEMPT ('.$q[1].')'); | |
$this->abort = true; return; | |
} | |
$data = $this->getMultipart($q[1]); | |
$data['max'] = $q[3]; | |
$data[$q[2]] = $q[4]; | |
$alldone = true; $query = ""; | |
for($i = 0; $i <= $q[3]; $i++) { | |
if(!$data[$i]) { $alldone = false; } | |
$query .= $data[$i]; | |
} | |
if($alldone) { | |
$this->clearMultipart($q[1]); | |
return $query; | |
} | |
$this->saveMultipart($q[1], $data); | |
$this->env['callback'] = $q[1]; | |
$result = Array("success" => true, "multipart" => true); | |
$this->respond($result); $this->abort = true; | |
} | |
function getMultipart($name) { | |
if(!file_exists($name)) { return Array(); } | |
$fp = fopen($name, "r"); $data = ""; | |
while(!feof($fp)) { $data .= fgets($fp); } | |
fclose($fp); return unserialize($data); | |
} | |
function clearMultipart($name) { | |
if(file_exists($name)) { unlink($name); } | |
} | |
function saveMultipart($name, $data) { | |
$fp = fopen($name, "w"); | |
fwrite($fp, serialize($data)); fclose($fp); | |
} | |
function getEnvironment($query) { | |
if($this->abort) return; | |
$env = Array(); | |
$query = explode('$', $query); | |
$env['method'] = strtoupper($query[0]); | |
$env['url'] = $query[6]; | |
$env['callback'] = $query[1]; | |
$url = $this->splitData('/', substr($env['url'], 7), 2); | |
$env['page'] = '/'.$url[1]; | |
$env['host'] = explode(':', $url[0]); | |
$env['port'] = (isset($env['host'][1])) ? $env['host'][1] : 80; | |
$env['host'] = $env['host'][0]; | |
$env['request'] = $this->decodeQuery($query[5]); | |
$env['ip'] = $_SERVER['REMOTE_ADDR']; | |
$env['useragent'] = $_SERVER['HTTP_USER_AGENT']; | |
$env['headers'] = $query[4]; | |
$env['headers'] = str_replace("=",": ", $env['headers']); | |
$env['headers'] = str_replace("&","\r\n", $env['headers']); | |
$env['username'] =$query[2]; | |
$env['password'] = $query[3]; | |
if ($env['method'] != 'GET' && $env['method'] != 'POST' && $env['method'] != 'HEAD') | |
$this->throwError('Please, specify either a GET, a POST or a HEAD method'); | |
if (substr($env['url'], 0, 7) != 'http://') | |
$this->throwError('Only HTTP protocol is supported (http://)'); | |
if (strlen($env['callback']) < 2) | |
$this->throwError('Internal error: callback function undefined'); | |
// Make sure you restrict the host of the request | |
// Otherwise your server will act like an open proxy | |
$allowedhosts = array('www.yourhost.com', 'anotherallowedhost.com'); | |
if (!in_array($env['host'], $allowedhosts)) { | |
$this->throwError('Requested host is not allowed'); | |
} | |
$this->env = $env; | |
} | |
function decodeQuery($query) { | |
$query = preg_replace('/%(?!5B)(?!5D)([0-9a-f]{2})/si', '%u00\\1', $query); | |
$query = preg_replace_callback('/%u([0-9A-F]{4})/si', array(&$this, 'decodeChar'), $query); | |
return $query; | |
} | |
function decodeChar($char) { | |
$charCode = hexdec($char[1]); $result = ''; | |
if (is_callable('iconv')) { | |
$result = iconv('UCS-2BE', 'UTF-8', pack('n', $charCode)); | |
} else { | |
// Manual decoding table is still to come. Soon. | |
if ($charCode < 128) $result = chr($charCode); | |
} | |
return $result; | |
} | |
function contactServer() { | |
if($this->abort) return; | |
$fp = fsockopen($this->env['host'], $this->env['port'], $errno, $errstr, 10); | |
if(!$fp) $this->throwError('Unable to contact host '.$this->env['host']); | |
$out = $this->env['method']." ".$this->env['page']." HTTP/1.0\r\n"; | |
$out .= "Host: ".$this->env['host']."\r\n"; | |
$out .= "User-Agent: ".$this->env['useragent']."\r\n"; | |
$out .= "Forwarded: by ".$this->env['host']." for ".$this->env['ip']."\r\n"; | |
$out .= "Accept: text/xml,application/xml,application/xhtml+xml,"; | |
$out .= "text/html;q=0.9,text/plain;q=0.8,q=0.2,text/css\r\n"; | |
$out .= "Accept-Encoding: gzip, deflate, compress;q=0.9\r\n"; | |
$out .= str_replace('HTTP-Referer: http%3A//','Referer: http://',$this->env['headers']); | |
$out .= 'Authorization: Basic '.base64_encode($this->env['username'].':'.$this->env['password'])."\r\n"; | |
if($this->env['method'] == 'POST') | |
$out .= 'Content-Length: '.strlen($this->env['request'])."\r\n"; | |
$out .= "Connection: Close\r\n\r\n"; | |
if($this->env['method'] == 'POST') | |
$out .= $this->env['request']."\r\n"; | |
$data = ""; | |
if ($fp) { | |
fwrite($fp, $out); | |
while (!feof($fp)) { | |
$data .= fgets($fp, 128); | |
} | |
fclose($fp); | |
} | |
return $data; | |
} | |
function parseData($data) { | |
if($this->abort) return; | |
$result = Array(); | |
$result['success'] = true; | |
$result['responseHeaders'] = Array(); | |
$headers = substr($data, 0, strpos($data, "\r\n\r\n")); | |
$headers = explode("\r\n", $headers); | |
for ($i = 1; $i < count($headers); $i++) { | |
$header = $this->splitData(":", $headers[$i], 2); | |
$result['responseHeaders'][$header[0]] = trim($header[1]); | |
} | |
$status = explode(' ', $headers[0]); | |
$result['status'] = $status[1]; | |
$result['statusText'] = $status[2]; | |
$data = substr($data, strpos($data, "\r\n\r\n") + 4); | |
if(isset($result['responseHeaders']['Content-Encoding']) && $result['responseHeaders']['Content-Encoding'] == 'gzip') { | |
$data = substr($data, 10); $data = gzinflate($data); | |
} | |
$data = trim($data); | |
$charset = explode('=', $result['responseHeaders']['Content-Type']); | |
if (isset($charset[1])) { | |
$charset = strtolower($charset[1]); | |
} else { | |
$charset = ''; | |
} | |
if($charset == "windows-1251" && is_callable('iconv')) | |
$data = iconv("windows-1251", "utf-8", $data); | |
$data = str_replace("\r", '\r', $data); | |
$data = str_replace("\n", '\n', $data); | |
$data = str_replace('\'', "\'", $data); | |
$result["responseText"] = $data; | |
return $result; | |
} | |
function respond($data) { | |
if($this->abort) return; | |
$data = $this->parseResponse($data); | |
echo $this->env['callback']."._parse(".$data.")"; | |
} | |
function parseResponse($data) { | |
$output = ""; | |
foreach($data as $key=>$value) { | |
$v = (is_array($value)) ? $this->parseResponse($value) : "'".$value."'"; | |
$output .= "'$key': $v, "; | |
} | |
$output = "{ ".substr($output, 0, -2). " }"; | |
return $output; | |
} | |
function splitData($separator, $data, $length) { | |
if(!$separator) return Array(); | |
if(!$data) return Array(); | |
$data = explode($separator, $data); | |
if($length) { | |
while(count($data) > $length) { | |
$data[count($data)-2] .= $separator.$data[count($data)-1]; | |
array_pop($data); | |
} | |
} | |
return $data; | |
} | |
function throwError($description) { | |
$result = Array("success" => false, "description" => $description); | |
$this->logRequest('Error: '.$description); | |
// Since all errors of this script are fatal | |
// we should terminate it | |
$this->respond($result); $this->abort = true; | |
} | |
function logRequest($extra) { | |
if($this->abort) return; | |
if(!$this->log) return; | |
$fp = fopen("log.txt","a"); if(!$fp) return; | |
$data = $this->env['ip'].' | '.date("d.m.y H:i:s").' | '.$_SERVER["HTTP_REFERER"]." | ".$this->env['url']." | ".$extra."\r\n"; | |
fwrite($fp, $data); fclose($fp); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment