Created
March 9, 2013 09:58
-
-
Save physacco/5123696 to your computer and use it in GitHub Desktop.
Send, receive and process binary data in web browser. Using XMLHTTPRequest, ArrayBuffer and ArrayBufferViews. Tested on Firefox 20.0.
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
# encoding: utf-8 | |
# Tested on ruby 1.9.2 | |
class HTTPNotFound < Exception | |
end | |
class MimeTypes | |
HTML = "text/html; charset=utf-8" | |
JAVASCRIPT = "application/javascript: charset=utf-8" | |
BINARY = "application/octet-stream; charset=binary" | |
def self.guess(ext) | |
case ext | |
when ".htm", ".html" | |
HTML | |
when ".js" | |
JAVASCRIPT | |
else | |
BINARY | |
end | |
end | |
end | |
class Server | |
def call(env) | |
@env = env | |
@path = env["PATH_INFO"] | |
begin | |
static_dispatch | |
rescue HTTPNotFound | |
dynamic_dispatch | |
end | |
end | |
def static_dispatch | |
path = (@path == "/") ? "/index.html" : @path | |
fullpath = File.join Dir.pwd, "public", path | |
raise HTTPNotFound.new(@path) unless File.exists? fullpath | |
headers = { | |
"Content-Type" => MimeTypes::guess(File.extname(path)), | |
"Content-Length" => File.size(fullpath).to_s | |
} | |
[200, headers, File.new(fullpath)] | |
end | |
def dynamic_dispatch | |
case @path | |
when "/transform" | |
serve_transform | |
else | |
error404 | |
end | |
end | |
def error404 | |
body = "404 not found" | |
headers = { | |
"Content-Type" => MimeTypes::HTML, | |
"Content-Length" => body.size.to_s | |
} | |
[404, headers, [body]] | |
end | |
def serve_transform | |
if @env["REQUEST_METHOD"] == "POST" | |
encrypted_data = @env["rack.input"].read | |
else | |
encrypted_data = "" | |
end | |
# decrypt | |
data = encrypted_data.each_byte.map{|b| b ^ 37}.pack("C*") | |
data.force_encoding "UTF-16BE" | |
# transform | |
data1 = data.upcase | |
# encrypt | |
body = data1.each_byte.map{|b| b ^ 37}.pack("C*") | |
headers = { | |
"Content-Type" => MimeTypes::BINARY, | |
"Content-Length" => body.size.to_s | |
} | |
[200, headers, [body]] | |
end | |
end | |
run Server.new |
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
. | |
|-- config.ru | |
`-- public | |
|-- index.html | |
`-- js | |
`-- test.js |
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
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Send, Receive and Process Binary Data</title> | |
<script type="text/javascript" src="/js/transform.js"></script> | |
</head> | |
<body> | |
<h1>Convert a string to upper case</h1> | |
<input id="input" type="text" placeholder="input some words..." /> | |
<input id="transform" type="button" value="->" /> | |
<input id="output" type="text" /> | |
</body> | |
</html> |
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
(function (window, document) { | |
var ajaxload = function (config) { | |
var i, xhr, type, url, headers, data, callback, errback; | |
type = config.type || "GET"; | |
url = config.url; | |
headers = config.headers || {}; | |
data = config.data; | |
xhr = new XMLHttpRequest(); | |
xhr.open(type, url, true); | |
if (config.responseType) { | |
xhr.responseType = config.responseType; | |
} | |
for (i in headers) { | |
if (config.hasOwnProperty(i)) { | |
xhr.setRequestHeader(i, headers[i]); | |
} | |
} | |
callback = function (e) { | |
if (config.success) { | |
config.success(xhr.response, xhr.statusText, xhr); | |
} | |
}; | |
errback = function (e) { | |
if (config.error) { | |
config.error(e, xhr); | |
} | |
} | |
xhr.onload = callback; | |
xhr.onabort = errback; | |
xhr.onerror = errback; | |
xhr.ontimeout = errback; | |
xhr.send(data); | |
}; | |
var binajax = function (config) { | |
ajaxload({ | |
type: config.type, | |
url: config.url, | |
headers: { | |
"Content-Type": "application/octet-stream; charset=binary" | |
}, | |
data: config.data, | |
responseType: "arraybuffer", | |
error: config.errback, | |
success: function (buffer, statusText, xhr) { | |
if (config.callback) { | |
config.callback(buffer); | |
} | |
} | |
}); | |
}; | |
// UTF16-BE encoded ArrayBuffer -> String | |
ab2str = function (buffer) { | |
var i, bytelen, buffer1, uint8array, uint16array; | |
bytelen = buffer.byteLength; | |
buffer1 = new ArrayBuffer(bytelen); | |
uint8array = new Uint8Array(buffer); | |
uint16array = new Uint16Array(buffer1); | |
for (i = 0; i < bytelen; i += 2) { | |
uint16array[i / 2] = (uint8array[i] << 8) + uint8array[i + 1]; | |
} | |
return String.fromCharCode.apply(null, uint16array); | |
}; | |
// String -> UTF16-BE encoded ArrayBuffer | |
str2ab = function (str) { | |
var i, bytelen, buffer, uint8array, code; | |
bytelen = str.length * 2; // 2 bytes for each char | |
buffer = new ArrayBuffer(bytelen); | |
uint8array = new Uint8Array(buffer); | |
for (i = 0; i < bytelen; i += 2) { | |
code = str.charCodeAt(i / 2); | |
uint8array[i] = code >> 8; | |
uint8array[i + 1] = code % 256; | |
} | |
return buffer; | |
}; | |
xorcrypt = function (buffer, key) { | |
var i, bytelen, buffer1, uint8array, uint8array1; | |
bytelen = buffer.byteLength; | |
buffer1 = new ArrayBuffer(bytelen); | |
uint8array = new Uint8Array(buffer); | |
uint8array1 = new Uint8Array(buffer1); | |
for (i = 0; i < bytelen; i += 1) { | |
uint8array1[i] = uint8array[i] ^ key; | |
} | |
return buffer1; | |
}; | |
var transform = function (e) { | |
var input, output, text, key, ibuffer; | |
input = document.getElementById("input"); | |
output = document.getElementById("output"); | |
text = input.value.replace(/^\s+/, '').replace(/\s+$/, ''); | |
if (text === "") { | |
output.value = ""; | |
return false; | |
} | |
key = 37; | |
ibuffer = xorcrypt(str2ab(text), key); | |
binajax({ | |
type: "POST", | |
url: "/transform", | |
data: ibuffer, | |
callback: function (obuffer) { | |
output.value = ab2str(xorcrypt(obuffer, key)); | |
} | |
}); | |
}; | |
window.onload = function (e) { | |
var button = document.getElementById("transform"); | |
button.onclick = transform; | |
}; | |
}(window, document)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment