Skip to content

Update gist posting to work with the lastest changes to gist.github.com #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: experimental
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions html/lib/base64.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
*
* Base64 encode / decode
* http://www.webtoolkit.info/
*
**/

var Base64 = {

// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;

input = Base64._utf8_encode(input);

while (i < input.length) {

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 = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

}

return output;
},

// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;

input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

while (i < input.length) {

enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));

chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;

output = output + String.fromCharCode(chr1);

if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}

}

output = Base64._utf8_decode(output);

return output;

},

// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";

for (var n = 0; n < string.length; n++) {

var c = string.charCodeAt(n);

if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}

}

return utftext;
},

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;

while ( i < utftext.length ) {

c = utftext.charCodeAt(i);

if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}

}

return string;
}

}
24 changes: 24 additions & 0 deletions html/lib/cookies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}

function eraseCookie(name) {
createCookie(name,"",-1);
}
164 changes: 121 additions & 43 deletions html/views/history/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,22 @@ var Commit = function(obj) {
}
this.header = this.raw.substring(0, messageStart);

if (typeof this.header !== 'undefined') {
var match = this.header.match(/\nauthor (.*) <(.*@.*|.*)> ([0-9].*)/);
if (typeof match !== 'undefined' && typeof match[2] !== 'undefined') {
if (!(match[2].match(/@[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/)))
this.author_email = match[2];
if (typeof this.header !== 'undefined') {
var match = this.header.match(/\nauthor (.*) <(.*@.*|.*)> ([0-9].*)/);
if (typeof match !== 'undefined' && typeof match[2] !== 'undefined') {
if (!(match[2].match(/@[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/)))
this.author_email = match[2];

if (typeof match[3] !== 'undefined')
this.author_date = new Date(parseInt(match[3]) * 1000);
this.author_date = new Date(parseInt(match[3]) * 1000);

match = this.header.match(/\ncommitter (.*) <(.*@.*|.*)> ([0-9].*)/);
match = this.header.match(/\ncommitter (.*) <(.*@.*|.*)> ([0-9].*)/);
if (typeof match[2] !== 'undefined')
this.committer_email = match[2];
if (typeof match[3] !== 'undefined')
this.committer_date = new Date(parseInt(match[3]) * 1000);
}
}
}
}
}

this.reloadRefs = function() {
Expand All @@ -66,10 +66,10 @@ var confirm_gist = function(confirmation_message) {

// Set optional confirmation_message
confirmation_message = confirmation_message || "Yes. Paste this commit.";
var deleteMessage = Controller.getConfig_("github.token") ? " " : "You might not be able to delete it after posting.<br>";
var deleteMessage = Controller.getConfig_("github.token") ? " " : 'Since your <a target="_new" href="http://help.github.com/mac-set-up-git/#_set_up_your_info">github token</a> is not set, you will not be able to delete it.<br>';
var publicMessage = Controller.isFeatureEnabled_("publicGist") ? "<b>public</b>" : "private";
// Insert the verification links into div#notification_message
var notification_text = 'This will create a ' + publicMessage + ' paste of your commit to <a href="http://gist.github.com/">http://gist.github.com/</a><br>' +
var notification_text = 'This will create a ' + publicMessage + ' paste of your commit to <a target="_new" href="http://gist.github.com/">http://gist.github.com/</a><br>' +
deleteMessage +
'Are you sure you want to continue?<br/><br/>' +
'<a href="#" onClick="hideNotification();return false;" style="color: red;">No. Cancel.</a> | ' +
Expand All @@ -80,51 +80,129 @@ var confirm_gist = function(confirmation_message) {
$("spinner").style.display = "none";
}

var gistie = function() {
notify("Uploading code to Gistie..", 0);
var storage = {
setKey: function(key, value) {
return createCookie(key, value, 365 * 10);
},

parameters = {
"file_ext[gistfile1]": "patch",
"file_name[gistfile1]": commit.object.subject.replace(/[^a-zA-Z0-9]/g, "-") + ".patch",
"file_contents[gistfile1]": commit.object.patch(),
};
getKey: function(key) {
return readCookie(key);
},

deleteKey: function(key) {
return eraseCookie(key);
},
};

// See http://developer.github.com/v3/oauth/
var gistAuth = function() {
var login = Controller.getConfig_("github.user");
if (login) {
var password = prompt("Enter GitHub password for " + login + " to authroize GitX to post gists:");
if (!password || password.length == 0) {
return gistie(true);
}

notify("Authenticating...", 0);

var t = new XMLHttpRequest();
t.onload = function() {
if (t.status == 201) {
try {
var jsonResponse = JSON.parse(t.responseText);
storage.setKey('oauth2token', jsonResponse.token);
gistie();
} catch (e) {
authFailover("During parse: " + t.responseText);
}
} else {
authFailover("Wrong status code (" + t.status + "): " + t.responseText);
}
}

var jsonRequest = {
scopes: 'gist',
note: 'GitX'
};

t.open('POST', "https://api.github.com/authorizations");
t.setRequestHeader('Accept', 'application/json');
t.setRequestHeader('Authorization', makeBasicAuth(login, password));
t.send(JSON.stringify(jsonRequest));
}

function authFailover(errorMessage) {
notify("Authentication failed; creating an anonymous gist.", 0);
Controller.log_(errorMessage);
setTimeout(function() {
gistie(true);
}, 1000);
}

// TODO: Replace true with private preference
token = Controller.getConfig_("github.token");
login = Controller.getConfig_("github.user");
if (token && login) {
parameters.login = login;
parameters.token = token;
function makeBasicAuth(user, password) {
var tok = user + ':' + password;
var hash = Base64.encode(tok);
return "Basic " + hash;
}
if (!Controller.isFeatureEnabled_("publicGist"))
parameters.private = true;

var params = [];
for (var name in parameters)
params.push(encodeURIComponent(name) + "=" + encodeURIComponent(parameters[name]));
params = params.join("&");
}

var needsGithubPassword = function() {
var login = Controller.getConfig_("github.user");
var token = storage.getKey('oauth2token');

return login && !token;
}

var gistie = function(skipAuth) {
if (!skipAuth && needsGithubPassword())
return gistAuth();

notify("Creating a Gist...", 0);

// See API at http://developer.github.com/v3/gists/
var filename = commit.object.subject.replace(/[^a-zA-Z0-9]+/g, "-") + ".patch";
var files = {};
files[filename] = { content: commit.object.patch() };
var postdata = {
description: commit.object.subject + " : " + commit.object.realSha(),
public: Controller.isFeatureEnabled_("publicGist") ? 'true' : 'false',
files: files,
};

var t = new XMLHttpRequest();
t.onreadystatechange = function() {
if (t.readyState == 4 && t.status >= 200 && t.status < 300) {
if (m = t.responseText.match(/<a href="\/gists\/([a-f0-9]+)\/edit">/))
notify("Code uploaded to gistie <a target='_new' href='http://gist.github.com/" + m[1] + "'>#" + m[1] + "</a>", 1);
else {
notify("Pasting to Gistie failed :(.", -1);
t.onload = function() {
if (t.status == 201) {
var responseJson = JSON.parse(t.responseText);
var gistURL = responseJson.html_url;
try {
notify("Gist posted: <a target='_new' href='" + gistURL + "'>" + gistURL + "</a>", 1);
} catch (e) {
notify("Gist creation failed: " + e + "; \n" + t.responseText, -1);
Controller.log_(t.responseText);
}
} else if (t.status == 401) { // Authentication fail
// Clear out our saved credentials, since they're not working
storage.deleteKey('oauth2token');
gistAuth();
} else {
notify("Gist creation failed with HTTP " + t.status + ": " + t.responseText, -1);
Controller.log_(t.status);
Controller.log_(t.responseText);
}
}
};

t.open('POST', "https://gist.github.com/gists");
t.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
t.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
t.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
t.open('POST', "https://api.github.com/gists");
t.setRequestHeader('Accept', 'application/json');
var token = storage.getKey('oauth2token');
if (token) {
t.setRequestHeader('Authorization', 'token ' + token);
}

try {
t.send(params);
t.send(JSON.stringify(postdata));
} catch(e) {
notify("Pasting to Gistie failed: " + e, -1);
notify("Failed to send JSON when sending the Gist data: " + e, -1);
}
}

Expand Down
2 changes: 2 additions & 0 deletions html/views/history/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<link rel="stylesheet" href="../../css/GitX.css" type="text/css" media="screen" title="no title" charset="utf-8">
<script src="../../lib/GitX.js" type="text/javascript" charset="utf-8"></script>
<script src="../../lib/md5.js" type="text/javascript" charset="utf-8"></script>
<script src="../../lib/base64.js" type="text/javascript" charset="utf-8"></script>
<script src="../../lib/cookies.js" type="text/javascript" charset="utf-8"></script>
<script src="../../lib/diffHighlighter.js" type="text/javascript" charset="utf-8"></script>
<script src="../../lib/keyboardNavigation.js" type="text/javascript" charset="utf-8"></script>

Expand Down