Last active
August 29, 2015 14:16
-
-
Save abdul/3152e2af038cfc391ce9 to your computer and use it in GitHub Desktop.
HTTPURLLoader - http://www.abdulqabiz.com/blog/archives/2006/03/03/http-authentication-for-httpget-requests-using-actionscript-3/
This file contains hidden or 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
/** | |
* @class Base64 | |
* @author Abdul Qabiz (http://www.abdulqabiz.com) | |
* @version 1.0 | |
* @requires ActionScript 3.0 and Flash Player 8.5 (atleast) | |
* | |
* @credits Based on Aardwulf Systems'(www.aardwulf.com) Javascript implementation. | |
* (http://www.aardwulf.com/tutor/base64/base64.html) | |
* | |
**/ | |
package com.abdulqabiz.crypto | |
{ | |
public class Base64 | |
{ | |
private static const KEY_STR:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
//Base64:encode(..) encodes a string to a base64 string | |
public static function encode(input:String):String | |
{ | |
var output:String = ""; | |
var chr1:uint, chr2:uint, chr3:uint; | |
var enc1:uint, enc2:uint, enc3:uint, enc4:uint; | |
var i:uint = 0; | |
var length:uint = input.length; | |
do{ | |
chr1 = input.charCodeAt(i++); | |
chr2 = input.charCodeAt(i++); | |
chr3 = input.charCodeAt(i++); | |
enc1 = chr1 >> 2; | |
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); | |
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); | |
enc4 = chr3 & 63; | |
if (isNaN(chr2)) | |
{ | |
enc3 = enc4 = 64; | |
} | |
else if (isNaN(chr3)) | |
{ | |
enc4 = 64; | |
} | |
output+= KEY_STR.charAt(enc1) + KEY_STR.charAt(enc2) + KEY_STR.charAt(enc3) + KEY_STR.charAt(enc4); | |
}while (i < length); | |
return output; | |
} | |
//Base64:decode(..) decodes a base64 string | |
public static function decode(input:String):String | |
{ | |
var output:String = ""; | |
var chr1:uint, chr2:uint, chr3:uint; | |
var enc1:int, enc2:int, enc3:int, enc4:int; | |
var i:uint = 0; | |
var length:uint = input.length; | |
// remove all characters that are not A-Z, a-z, 0-9, +, /, or = | |
var base64test:RegExp = /[^A-Za-z0-9\+\/\=]/g; | |
if (base64test.exec(input)) | |
{ | |
throw new Error("There were invalid base64 characters in the input text.\n" + | |
"Valid base64 characters are A-Z, a-z, 0-9, '+', '/', and '='\n" + | |
"Expect errors in decoding."); | |
} | |
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); | |
do{ | |
enc1 = input.indexOf(input.charAt(i++)); | |
enc2 = input.indexOf(input.charAt(i++)); | |
enc3 = input.indexOf(input.charAt(i++)); | |
enc4 = input.indexOf(input.charAt(i++)); | |
chr1 = (enc1 << 2) | (enc2 >> 4); | |
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); | |
chr3 = ((enc3 & 3) << 6) | enc4; | |
output+= String.fromCharCode(chr1); | |
if (enc3 != 64) | |
{ | |
output+= String.fromCharCode(chr2); | |
} | |
if (enc4 != 64) | |
{ | |
output+= String.fromCharCode(chr3); | |
} | |
}while(i < length); | |
return output; | |
} | |
} | |
} |
This file contains hidden or 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
/** | |
_________________________________________________________________________________________________________________ | |
HTTPURLLoader is small http client for GET requests and header manipulation. | |
@class HTTPURLLoader (public) | |
@author Abdul Qabiz (mail at abdulqabiz dot com) | |
@version 1.01 (3/5/2007) | |
@availability 9.0+ | |
@usage<code>new HTTPURLLoader ();</code> | |
@example | |
<code> | |
httpURLLoader = new HTTPURLLoader (); | |
</code> | |
__________________________________________________________________________________________________________________ | |
*/ | |
package com.abdulqabiz.net | |
{ | |
import flash.net.*; | |
import flash.events.*; | |
import flash.system.Security; | |
import flash.errors.EOFError; | |
import flash.utils.*; | |
import mx.utils.StringUtil; | |
dynamic public class HTTPURLLoader extends EventDispatcher | |
{ | |
//Events | |
[Event(name="close", type="flash.events.Event.CLOSE")] | |
[Event(name="complete", type="flash.events.Event.COMPLETE")] | |
[Event(name="open", type="flash.events.Event.CONNECT")] | |
[Event(name="ioError", type="flash.events.IOErrorEvent.IO_ERROR")] | |
[Event(name="securityError", type="flash.events.SecurityErrorEvent.SECURITY_ERROR")] | |
[Event(name="progress", type="flash.events.ProgressEvent.PROGRESS")] | |
[Event(name="httpStatus", type="flash.events.HTTPStatusEvent.HTTP_STATUS")] | |
//class attributes | |
private var _httpPort:uint = 80; | |
private var socket:Socket; | |
private var _request:URLRequest; | |
public var _httpRequest:String; | |
public var _httpServer:String; | |
private var headerComplete:Boolean = false; | |
private var _header:Object; | |
private var _data:String = ""; | |
private var _bytesLoaded:int = 0; | |
private var _bytesTotal:int = 0; | |
private var headerTmp:String = ""; | |
private var _httpVersion:Number; | |
private var _httpStatusCode:int; | |
private var _httpStatusText:String; | |
public function HTTPURLLoader(request:URLRequest = null) | |
{ | |
//doesn't really need it here, as load(..) requires request | |
_request = request; | |
// create http-socket | |
socket = new Socket(); | |
//subscribe to events | |
socket.addEventListener( "connect" , onConnectEvent , false , 0 ); | |
socket.addEventListener( "close" , onCloseEvent , false, 0 ); | |
socket.addEventListener( "ioError" , onIOErrorEvent , false, 0 ); | |
socket.addEventListener( "securityError" , onSecurityErrorEvent , false, 0 ); | |
socket.addEventListener( "socketData" , onSocketDataEvent , false , 0 ); | |
} | |
/*__________________________________________________________________________________________________________________ | |
Public Methods | |
__________________________________________________________________________________________________________________ | |
*/ | |
public function load(request:URLRequest):void | |
{ | |
_request = request; | |
if(parseURL()) | |
{ | |
try | |
{ | |
socket.connect(_httpServer, _httpPort); | |
} | |
catch (e:Error) | |
{ | |
} | |
} | |
else | |
{ | |
throw new Error("Invalid URL"); | |
} | |
} | |
public function close():void | |
{ | |
if(socket.connected) | |
{ | |
socket.close(); | |
dispatchEvent(new Event(Event.CLOSE)); | |
} | |
} | |
/*__________________________________________________________________________________________________________________ | |
Public Properties | |
__________________________________________________________________________________________________________________ | |
*/ | |
public function get data():String | |
{ | |
return _data; | |
} | |
public function get header():Object | |
{ | |
return _header; | |
} | |
public function get bytesLoaded():int | |
{ | |
return _bytesLoaded; | |
} | |
public function get bytesTotal ():int | |
{ | |
return _bytesTotal; | |
} | |
/*__________________________________________________________________________________________________________________ | |
Private Methods | |
__________________________________________________________________________________________________________________ | |
*/ | |
private function onConnectEvent(event:Event):void | |
{ | |
sendHeaders(); | |
dispatchEvent(new Event(Event.CONNECT)); | |
} | |
private function onCloseEvent(event:Event):void | |
{ | |
dispatchEvent(new Event(flash.events.Event.COMPLETE)); | |
} | |
private function onIOErrorEvent(event:IOErrorEvent):void | |
{ | |
dispatchEvent(event); | |
} | |
private function onSecurityErrorEvent(event:SecurityErrorEvent):void | |
{ | |
dispatchEvent(event.clone()); | |
} | |
private function onSocketDataEvent(event:ProgressEvent):void | |
{ | |
_bytesLoaded += socket.bytesAvailable; | |
dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, _bytesLoaded, _bytesTotal)) | |
var str:String = ""; | |
try | |
{ | |
str = socket.readUTFBytes(socket.bytesAvailable); | |
} | |
catch(e:Error) | |
{ | |
} | |
if(!headerComplete) | |
{ | |
var httpStatus:String; | |
var headerEndIndex:int = str.indexOf("\r\n\r\n"); | |
if(headerEndIndex != -1) | |
{ | |
headerTmp += str.substring(0, headerEndIndex); | |
headerComplete = true; | |
_data += str.substring(headerEndIndex + 4); | |
var headerArr:Array = headerTmp.split("\r\n"); | |
var headerLine:String; | |
var headerParts:Array; | |
for each(headerLine in headerArr) | |
{ | |
if(headerLine.indexOf("HTTP/1.") != -1) | |
{ | |
headerParts = headerLine.split(" "); | |
if(headerParts.length > 0) | |
{ | |
_httpVersion = parseFloat(StringUtil.trim(headerParts.shift().split("/")[1])); | |
} | |
if(headerParts.length > 0) | |
{ | |
_httpStatusCode = parseInt(StringUtil.trim(headerParts.shift())); | |
} | |
if(headerParts.length > 0) | |
{ | |
_httpStatusText = StringUtil.trim(headerParts.join(" ")); | |
} | |
dispatchEvent(new HTTPStatusEvent(HTTPStatusEvent.HTTP_STATUS, false, false, _httpStatusCode)); | |
} | |
else | |
{ | |
var colonIndex:int = headerLine.indexOf(":"); | |
if(colonIndex != -1) { | |
var key:String = StringUtil.trim(headerLine.substring(0, colonIndex)); | |
var value:String = StringUtil.trim(headerLine.substring(colonIndex + 1)); | |
if (!_header) | |
{ | |
_header = new Object (); | |
} | |
_header[key] = value; | |
} | |
} | |
} | |
if(_header["Content-Length"]) | |
{ | |
// total bytes = content-length + header size (number of characters in header) | |
// not working, need to work on right logic.. | |
_bytesTotal = int(_header["Content-Length"]) + headerTmp.length; | |
} | |
} | |
else | |
{ | |
headerTmp += str; | |
} | |
} | |
else | |
{ | |
_data += str; | |
} | |
} | |
private function sendHeaders():void | |
{ | |
var requestHeaders:Array = _request.requestHeaders; | |
var h:String = ""; | |
_header = null; | |
_bytesLoaded = 0; | |
_bytesTotal = 0; | |
_data = ""; | |
headerComplete = false; | |
headerTmp = ""; | |
//create an HTTP 1.0 Header Request | |
h+= "GET " + _httpRequest + " HTTP/1.0\r\n"; | |
h+= "Host:" + _httpServer + "\r\n"; | |
if(requestHeaders.length > 0) | |
{ | |
for each(var rh:URLRequestHeader in requestHeaders) | |
{ | |
h+= rh.name + ":" + rh.value + "\r\n"; | |
} | |
} | |
//set HTTP headers to socket buffer | |
socket.writeUTFBytes(h + "\r\n\r\n") | |
//push the data to server | |
socket.flush() | |
} | |
private function parseURL():Boolean | |
{ | |
//parse URL into sockServer and sockRequest | |
var d:Array = _request.url.split('http://')[1].split('/'); | |
if(d.length > 0) | |
{ | |
_httpServer = d.shift(); | |
//load crossdomain, if its on server. | |
Security.loadPolicyFile("http://"+_httpServer+"/crossdomain.xml"); | |
_httpRequest = '/' + d.join('/'); | |
return true; | |
} | |
return false; | |
} | |
} | |
} |
This file contains hidden or 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
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="onAppInit()"> | |
<mx:Script> | |
import flash.net.*; | |
import com.abdulqabiz.net.HTTPURLLoader; | |
import com.abdulqabiz.crypto.Base64; | |
private var loader:HTTPURLLoader; | |
private var END_POINT:String = "http://rpc.bloglines.com/"; | |
//you need to set your email/password required for Bloglines access. | |
private var email:String = "YOUR_EMAIL_FOR_BLOGLINES"; | |
private var password:String = "YOUR_BLOGLINES_PASSWORD"; | |
private function onAppInit():void | |
{ | |
loader = new HTTPURLLoader(); | |
loader.addEventListener("complete", onComplete); | |
loader.addEventListener("httpStatus", onHTTPStatus); | |
loader.addEventListener("progress", onProgress); | |
//for simplicity,not handling following three events. | |
//loader.addEventListener("close", onClose); | |
//loader.addEventListener("ioError", onIOError); | |
//loader.addEventListener("securityError",onSecurityError); | |
} | |
private function onComplete(event:Event):void | |
{ | |
//headers stroed as name-value(hash map) | |
var rh:Object = HTTPURLLoader(event.target).responseHeaders; | |
var str:String = ""; | |
for(var p:String in rh) | |
{ | |
str+= p + ":" + rh[p] + "\n"; | |
} | |
console.text+="Response Headers: \n" + str + "\n\n"; | |
//data property holds the content | |
console.text+="Body Content:\n" + HTTPURLLoader(event.target).data + "\n\n"; | |
} | |
private function onProgress(event:ProgressEvent):void | |
{ | |
//bytesTotal is not accurate, and its 0 if server doesn't send Content-Length header. | |
console.text+= "Event: progress:-\n" + "bytesLoaded: " + event.bytesLoaded + "\n\n"; | |
} | |
private function onHTTPStatus(event:HTTPStatusEvent):void | |
{ | |
//if httpStatus is 401, 403, 404, 500, 501, socket is closed. | |
console.text+= "Event: httpStatus (" + event.status + ")\n\n"; | |
} | |
private function loadURL():void | |
{ | |
var request:URLRequest = new URLRequest(); | |
//call listsubs method of Bloglines | |
request.url = END_POINT + "listsubs"; | |
var credentials:String = Base64.encode(email + ":" + password); | |
//create HTTP Auth request header | |
var authHeader:URLRequestHeader = new URLRequestHeader("Authorization","Basic " + credentials); | |
//add the header to request | |
request.requestHeaders.push(authHeader); | |
//make the request. | |
loader.load(request); | |
} | |
</mx:Script> | |
<mx:Button label="Load URL" click="loadURL()"/> | |
<mx:TextArea id="console" width="100%" height="100%"/> | |
</mx:Application> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment