Created
September 13, 2012 08:02
-
-
Save gitbuh/3712767 to your computer and use it in GitHub Desktop.
qpdiff
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
all : dist/x86/qpdiff dist/arm/qpdiff | |
dist/x86/qpdiff : | |
g++ -Wall -Wextra -pedantic src/qpdiff.cpp -o dist/x86/qpdiff | |
dist/arm/qpdiff : | |
arm-linux-gnueabi-g++ -Wall -Wextra -pedantic src/qpdiff.cpp -o dist/arm/qpdiff | |
clean : | |
rm dist/x86/qpdiff dist/arm/qpdiff |
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
#include <iomanip> | |
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <sstream> | |
#include <cstdlib> | |
using namespace std; | |
string env(string var, string defaultval) { | |
const char* value = getenv(var.c_str()); | |
return value == NULL ? defaultval : value; | |
} | |
string env(string var) { | |
return env(var, ""); | |
} | |
int main( int argc, char** argv ) { | |
if (argc < 4) { | |
cout << "Title, old file and new file are required." << endl; | |
return 1; | |
} | |
const char* title = argv[1]; | |
ifstream oldfile (argv[2], ios::in|ios::binary); | |
ifstream newfile (argv[3], ios::in|ios::binary); | |
char oldchar; | |
char newchar; | |
if (!(oldfile.is_open() && newfile.is_open())) { | |
cout << "Unable to open files." << endl; | |
return 2; | |
} | |
// find changed bytes | |
ostringstream oldbytes; | |
ostringstream newbytes; | |
int pos = 0; | |
int lastpos = -2; | |
while (!oldfile.eof()) { | |
if (newfile.eof()) { | |
cout << "File sizes don't match." << endl; | |
return 3; | |
} | |
oldfile.get(oldchar); | |
newfile.get(newchar); | |
if (oldchar != newchar) { | |
if (pos == lastpos + 1) { | |
oldbytes << ", \"" << hex << (int)oldchar << "\""; | |
newbytes << ", \"" << hex << (int)newchar << "\""; | |
} else { | |
if (lastpos != -2) { | |
oldbytes << "]," << endl; | |
newbytes << "]," << endl; | |
} | |
oldbytes << setw(8) << setfill(' ') << "\"" << pos << "\": [\"" << hex << (int)oldchar << "\""; | |
newbytes << setw(8) << setfill(' ') << "\"" << pos << "\": [\"" << hex << (int)newchar << "\""; | |
} | |
lastpos = pos; | |
} | |
++pos; | |
} | |
if (lastpos != -2) { | |
oldbytes << "]" << endl; | |
newbytes << "]" << endl; | |
} | |
oldfile.close(); | |
newfile.close(); | |
// write patch | |
cout << "{" << endl << | |
"\"title\": \"" << title << "\"," << endl << | |
"\"author\": \"" << env("PATCH_AUTHOR", "Anonymous") << "\"," << endl << | |
"\"target\": \"" << env("PATCH_TARGET") << "\"," << endl << | |
"\"version\": \"" << env("PATCH_VERSION", "1.0") << "\"," << endl << | |
"\"initial\": { " << endl << oldbytes.str() << endl << " } " << endl << | |
"\"options\": { \"" << env("PATCH_OPTION_NAME", "Patched") << "\" { " << endl << | |
newbytes.str() << " } } " << endl << "}" << endl; | |
return 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
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi"> | |
<style> | |
label { display: block; font-weight: bold; color: #999; line-height: 200%; } | |
label input, textarea { width:100%; border:1px solid silver; border-radius: 3px; line-height: 150%; color: #666; } | |
input[type="submit"], input[type="button"] { border:1px solid #ccc; border-radius: 3px; padding: 1em; color:white; font-weight: bold; } | |
input[type="submit"] { float: right; background: #393 } | |
input[type="button"] { background: #933 } | |
form, fieldset, textarea { border:none; margin: none; padding: none; } | |
</style> | |
</head> | |
<body> | |
<h1>qpdiff</h1> | |
<textarea id="response" style="display:none"></textarea> | |
<form method="GET" action="."><fieldset> | |
<label>Patch title: <input name="title" type="text" value=""></label> | |
<label>Original file: <input name="oldfile" type="text" value=""></label> | |
<label>Modified file: <input name="newfile" type="text" value=""></label> | |
<label>Patch target: <input name="PATCH_TARGET" type="text" value=""></label> | |
<label>Patch version: <input name="PATCH_VERSION" type="text" value=""></label> | |
<label>Patch author: <input name="PATCH_AUTHOR" type="text" value=""></label> | |
<label>Patch option name: <input name="PATCH_OPTION_NAME" type="text" value=""></label> | |
<br> | |
<div><input type="button" name="quit" value="Quit"><input type="submit" value="Create patch"></div> | |
</fieldset></form> | |
<script> | |
var form = document.forms[0], | |
responseArea = document.getElementById('response'); | |
function requestURL(string) { | |
return "http://localhost:8987/" + encodeURIComponent(string) + "/"; | |
} | |
function makeRequest(data, onComplete) { | |
var xhr = new XMLHttpRequest(); | |
if (onComplete) | |
xhr.onreadystatechange = onComplete; | |
xhr.open("GET", requestURL(data), true); | |
xhr.send(); | |
} | |
// load saved form data | |
makeRequest('load', function() { | |
var data; | |
if (this.readyState == 4) { | |
data = JSON.parse(this.responseText); | |
for (key in form) { | |
if (form[key] && form[key].type == "text" && form[key].name) { | |
form[key].value = data[form[key].name]; | |
} | |
} | |
} | |
}); | |
// quit button | |
form.quit.onclick = function() { | |
makeRequest('exit'); | |
} | |
// submit button | |
form.onsubmit = function() { | |
var data = {}, key; | |
for (key in form) { | |
if (form[key] && form[key].type == "text" && form[key].name) { | |
data[form[key].name] = form[key].value; | |
} | |
} | |
makeRequest(JSON.stringify(data), function() { | |
if (this.readyState == 4) { | |
responseArea.style.display = 'block'; | |
responseArea.style.height = this.responseText.split('\n').length + 'em'; | |
responseArea.textContent = this.responseText; | |
} | |
}); | |
return false; | |
} | |
</script> | |
</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
// https://developer.mozilla.org/en-US/docs/Rhino/Shell | |
// http://jebbeich.blogspot.com/2011/10/simple-webserver-for-rhino-in.html | |
importPackage(java.io); | |
importPackage(java.net); | |
function saveUrl(url, file) { | |
var uc = new URL(url).openConnection(); | |
uc.connect(); | |
var input = uc.getInputStream(); | |
var output = new FileOutputStream(file); | |
var buffer = new java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 1 << 8); | |
var bytes = -1; | |
while ((bytes = input.read(buffer)) > -1) { | |
output.write(buffer, 0, bytes); | |
} | |
input.close(); | |
output.close(); | |
} | |
function startServer(html) { | |
var s = new ServerSocket(8987); | |
var remote, is, out, request, str, writer; | |
function respond(text) { | |
out.println(text); | |
out.flush(); | |
remote.close(); | |
} | |
print('Waiting for connection'); | |
while (1) { | |
try { | |
remote = s.accept(); | |
is = new BufferedReader(new InputStreamReader(remote.getInputStream())); | |
out = new PrintWriter(remote.getOutputStream()); | |
request = ''; | |
do { | |
str = is.readLine(); | |
request += str; | |
// stop reading once a blank line is hit. | |
} while (!str.equals('')); | |
// Send the headers | |
out.println('HTTP/1.0 200 OK'); | |
out.println('Content-Type: text/html'); | |
out.println('Server: qpdiff'); | |
// this blank line signals the end of the headers | |
out.println(''); | |
// strip request to first path segment, must have terminating slash | |
request = decodeURIComponent(request.replace(/.*?\//, '').replace(/\/.*/, '')); | |
print('Got request: ' + request); | |
// exit | |
if (request == 'exit') { | |
print('Stopping server.'); | |
return; | |
} | |
// load | |
if (request == 'load') { | |
print('Loading settings.'); | |
respond(readFile('/mnt/sdcard/qpdiff.json')); | |
continue; | |
} | |
// form post, convert request to an object | |
request = JSON.parse(request); | |
// store request | |
writer = new FileWriter('/mnt/sdcard/qpdiff.json'); | |
writer.write(JSON.stringify(request)); | |
writer.close(); | |
var commandOpts = { output: "", err: "", env: request }; | |
runCommand('/bin/qpdiff', | |
request.title, request.oldfile, request.newfile, commandOpts); | |
print('Command output: ' + commandOpts.output); | |
if (commandOpts.err) | |
print('Command errors: ' + commandOpts.err); | |
respond(commandOpts.output); | |
} catch (e) { | |
print('Error: ' + e); | |
} | |
} | |
} | |
function main() { | |
try { | |
print("Updating files."); | |
// update html file | |
var html = readUrl('https://raw.github.com/gist/3712767/server/qpdiff.html'); | |
var writer = new FileWriter('/mnt/sdcard/qpdiff.html'); | |
writer.write(html); | |
writer.close(); | |
// update qpdiff binary | |
saveUrl('https://raw.github.com/gist/3712767/dist/arm/qpdiff', '/mnt/sdcard/qpdiff.bin') | |
runCommand('su', '-c', | |
'cp /mnt/sdcard/qpdiff.bin /bin/qpdiff; rm /mnt/sdcard/qpdiff.bin'); | |
// load the droid stuff and show a webview | |
print("Loading web view."); | |
load('/sdcard/com.googlecode.rhinoforandroid/extras/rhino/android.js'); | |
var droid = new Android(); | |
droid.webViewShow("file:///mnt/sdcard/qpdiff.html"); | |
// main loop | |
print("Starting server."); | |
startServer(html); | |
// exiting | |
} catch (e) { | |
print('Error: ' + e); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment