Skip to content

Instantly share code, notes, and snippets.

@sente
Last active April 28, 2016 15:01
Show Gist options
  • Save sente/4536952 to your computer and use it in GitHub Desktop.
Save sente/4536952 to your computer and use it in GitHub Desktop.
On Monday afternoon, a group of online archivists released the "Aaron Swartz Memorial JSTOR Liberator." The initiative is a JavaScript-based bookmarklet that lets Internet users "liberate" an article, already in the public domain, from the online academic archive JSTOR. By running the script—which is limited to once per browser—a public domain a…
/**
*
* Base64 encode / decode
* http://www.webtoolkit.info/
*
**/
var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (byteArray) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
// input = Base64._utf8_encode(input);
// var byteArray = new Uint8Array(input);
while (i < byteArray.byteLength) {
chr1 = byteArray[i++];
chr2 = byteArray[i++];
chr3 = byteArray[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;
}
}
// www.quirksmode.org
function sendRequest(url,callback,postData,progressCallback) {
var req = createXMLHTTPObject();
if (!req) return;
var method = (postData) ? "POST" : "GET";
req.open(method,url,true);
req.responseType = 'arraybuffer';
if (progressCallback)
req.addEventListener('progress', progressCallback);
if (postData)
req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
req.onreadystatechange = function () {
if (req.readyState != 4) return;
if (req.status != 200 && req.status != 304) {
// alert('HTTP error ' + req.status);
return;
}
callback(req);
}
if (req.readyState == 4) return;
req.send(postData);
return req;
}
var XMLHttpFactories = [
function () {return new XMLHttpRequest()},
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
function createXMLHTTPObject() {
var xmlhttp = false;
for (var i=0;i<XMLHttpFactories.length;i++) {
try {
xmlhttp = XMLHttpFactories[i]();
}
catch (e) {
continue;
}
break;
}
return xmlhttp;
}
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);
}
var jstorLib_progress = (function() {
var p = {
init: function() {
var div = window.frames.jstorLib_bottom.document.createElement('div');
div.id = 'jstorLib_progress';
window.frames.jstorLib_bottom.document.body.appendChild(div);
var cssLink = window.frames.jstorLib_bottom.document.createElement('link');
cssLink.setAttribute('rel', 'stylesheet');
cssLink.setAttribute('type', 'text/css');
cssLink.setAttribute('href', 'http://aaronsw.archiveteam.org/jstor_style.css');
window.frames.jstorLib_bottom.document.getElementsByTagName('head')[0].appendChild(cssLink);
},
reset: function() {
var div = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress');
if (div) {
$(div).empty();
div.className = '';
}
},
show: function() {
var div = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress');
if (div && div.className != 'visible') {
div.className = 'visible';
}
},
hide: function() {
var div = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress');
if (div && div.className == 'visible') {
div.className = '';
}
},
updateProgress: function(itemId, complete, message) {
jstorLib_progress.show();
var statusSpan = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress_status_' + itemId);
var msgSpan = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress_msg_' + itemId);
if (!msgSpan) {
var div = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress');
if (!div) return;
var ul = div.lastChild;
if (ul && ul.nodeName!='UL')
ul = null;
if (!ul) {
ul = window.frames.jstorLib_bottom.document.createElement('ul');
div.appendChild(ul);
}
var li = window.frames.jstorLib_bottom.document.createElement('li');
statusSpan = window.frames.jstorLib_bottom.document.createElement('span');
statusSpan.id = 'jstorLib_progress_status_' + itemId;
statusSpan.className = 'status';
li.appendChild(statusSpan);
msgSpan = window.frames.jstorLib_bottom.document.createElement('span');
msgSpan.id = 'jstorLib_progress_msg_' + itemId;
li.appendChild(msgSpan);
ul.appendChild(li);
}
statusSpan.className = complete ? 'status status-complete' : 'status';
statusSpan.innerHTML = complete ? '&#x2713;' : '';
msgSpan.innerHTML = message;
},
addUploadForm: function(onsubmit_handler) {
var doc = window.frames.jstorLib_bottom.document;
var div = doc.getElementById('jstorLib_progress');
if (div) {
var form = doc.createElement('form');
form.method = 'post';
form.action = '#';
var p = doc.createElement('p');
form.appendChild(p);
p.appendChild(doc.createTextNode('Add this document to the Aaron Swartz memorial:'));
p.appendChild(doc.createElement('br'));
var textarea = doc.createElement('textarea');
textarea.name = 'your_message';
textarea.rows = 5;
textarea.cols = 30;
textarea.id = 'f-memorial-message';
// textarea.placeholder = 'Your memorial message';
textarea.value = ' ';
p.appendChild(textarea);
var input = doc.createElement('input');
input.type = 'text';
input.name = 'your_name';
input.id = 'f-memorial-name';
input.placeholder = 'Your name or nickname';
input.value = 'Anonymous';
p.appendChild(input);
p.appendChild(doc.createElement('br'));
var submit = doc.createElement('input');
submit.type = 'submit';
submit.value = 'Upload to the memorial';
p.appendChild(submit);
form.id = 'memorial-upload-form';
form.onsubmit = onsubmit_handler;
div.appendChild(form);
}
},
removeUploadForm: function() {
var doc = window.frames.jstorLib_bottom.document;
var form = doc.getElementById('memorial-upload-form');
if (form) {
form.parentNode.removeChild(form);
}
},
addParagraph: function(id, text) {
var div = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress');
if (div) {
var p = window.frames.jstorLib_bottom.document.createElement('p');
p.id = 'jstorLib_progress_para_' + id;
p.innerHTML = text;
div.appendChild(p);
}
},
removeParagraph: function(id) {
var p = window.frames.jstorLib_bottom.document.getElementById('jstorLib_progress_para_' + id);
if (p) {
p.parentNode.removeChild(p);
}
}
};
return p;
})();
var jstorLib = (function() {
var o = {
incrementUploadCounter: function() {
var newCount = jstorLib.getUploadCounter() + 1;
createCookie('jstorLib_count', newCount, 10);
return newCount;
},
getUploadCounter: function() {
var c = readCookie('jstorLib_count');
if (c) {
return c * 1;
} else {
return 0;
}
},
buildForm: function() {
var form = document.createElement('form');
form.method = 'POST';
form.action = 'http://aaronsw.archiveteam.org/data';
form.target = 'jstorLib_upload';
var input;
var fields = [ 'title', 'item', 'url', 'data', 'meta', 'bibtex',
'memorial_message', 'memorial_name' ];
for (var i=0; i<fields.length; i++) {
input = document.createElement('input');
input.name = fields[i];
input.type = 'hidden';
form.appendChild(input);
}
document.body.appendChild(form);
return form;
},
form: function() {
if (!jstorLib._form) {
jstorLib._form = jstorLib.buildForm();
}
return jstorLib._form;
},
receiveMessage: function(evt) {
// the upload frame sends us a message
var count = jstorLib.incrementUploadCounter();
count = (count==1) ? 'one document' : (count+' documents');
jstorLib_progress.updateProgress('upload', true, 'Upload complete');
jstorLib_progress.addParagraph('thanks', 'Thanks!'); // You\'ve liberated <strong>'+count+'</strong> so far.');
// var form = jstorLib.form();
// jstorLib_progress.addParagraph('message',"Message: "+form.memorial_message.value);
// jstorLib_progress.addParagraph('message',"Name: "+form.memorial_name.value);
},
submitData: function() {
jstorLib_progress.updateProgress('upload', false, 'Uploading...');
var form = jstorLib.form();
form.submit();
},
reallyOpenPDF: function(view, href) {
view.location.href = href;
// if Firefox does not show the PDF inline, it will not
// close the popup window
view.setTimeout(function() {
view.close();
}, 1000);
},
askForMessage: function() {
jstorLib_progress.addUploadForm(function(evt) {
var doc = window.frames.jstorLib_bottom.document;
var memorialMessage = doc.getElementById('f-memorial-message').value;
var memorialName = doc.getElementById('f-memorial-name').value;
var form = jstorLib.form();
form.memorial_message.value = memorialMessage;
form.memorial_name.value = memorialName;
jstorLib_progress.removeUploadForm();
jstorLib.submitData();
return false;
});
},
processResponse: function(req) {
var byteArray = new Uint8Array(req.response);
var kilobytes = Math.round(byteArray.byteLength / 1024);
jstorLib_progress.updateProgress('download', true, 'Download complete ('+kilobytes+' kB)');
if (req.view && req.view.location) {
jstorLib.reallyOpenPDF(req.view, req.href);
}
var form = jstorLib.form();
form.url.value = req.hrefDoc;
form.data.value = Base64.encode(byteArray);
var viewCitation = window.frames.jstorLib_bottom.document.getElementById('viewCitation');
if (viewCitation && viewCitation.href) {
var m = viewCitation.href.match(/doi=(.+)/);
if (m) {
jstorLib.loadBibtex(m[1]);
return;
}
}
// if not bibtex...
jstorLib.askForMessage();
},
downloadProgress: function(evt) {
var kilobytes = Math.round(evt.loaded / 1024);
jstorLib_progress.updateProgress('download', false, 'Downloading PDF ('+kilobytes+' kB)...');
},
openPDF: function(href, liberateOnly) {
var hrefDoc = href.replace(/\?acceptTC=true/, '');
jstorLib.showStatus('');
jstorLib_progress.reset();
jstorLib_progress.updateProgress('download', false, 'Requesting PDF...');
var xhr = sendRequest(href, jstorLib.processResponse, null, jstorLib.downloadProgress);
xhr.href = href;
xhr.hrefDoc = hrefDoc;
if (!liberateOnly) {
xhr.view = window.open('','_blank','width=750,height=550,top=100,left=100,resizable=1,toolbar=1,location=1,menubar=1,scrollbars=1');
var tmp = xhr.view.document
tmp.write('<html><head><title>Loading PDF...</title><style type="text/css">body{background:#000;color:#fff;font-family:Arial,Helvetica,sans-serif;font-size:18px}</style></head><body><p>Loading PDF...</p></body></html>');
tmp.close();
} else {
xhr.view = null;
}
return false;
},
askForNextItem: function() {
var targetWindow = top;
if (window.frames.jstorLib_bottom) {
targetWindow = window.frames.jstorLib_bottom;
}
var targetDoc = targetWindow.document;
var s = targetDoc.createElement('script');
s.src = 'http://aaronsw.archiveteam.org/next-item?r='+Math.random();
s.type = 'application/javascript';
targetDoc.body.appendChild(s);
targetWindow.jstorLib = jstorLib;
jstorLib.showStatus('Looking for another unliberated item...');
jstorLib_progress.updateProgress('ask-for-next-item', false, 'Asking for next item...');
},
nextItem: function(itemId, title) {
jstorLib_progress.updateProgress('ask-for-next-item', true, 'Asking for next item...');
jstorLib_progress.addParagraph('loading-title', 'Loading "'+title+'"...');
window.frames.jstorLib_bottom.location.href = 'http://www.jstor.org/stable/info/' + itemId;
jstorLib.showStatus('Loading "'+title+'"...');
},
processBibtex: function(data) {
jstorLib.form().bibtex.value = data;
jstorLib_progress.updateProgress('download-meta', true, 'Metadata complete');
jstorLib.askForMessage();
},
loadBibtex: function(encodedDoi) {
$.ajax({
url: 'http://www.jstor.org/action/downloadSingleCitation?userAction=export&include=abs&singleCitation=true&redirectURI=%2Faction%2FexportSingleCitation%3FsingleCitation%3Dtrue%26doi%3D'+encodedDoi+'&format=bibtex&noDoi=yesDoi&doi='+encodedDoi,
success: jstorLib.processBibtex,
xhrFields: { withCredentials: true }
});
jstorLib_progress.updateProgress('download-meta', false, 'Grabbing metadata...');
},
showStatus: function(msg) {
var s = window.frames.jstorLib_top.document.getElementById('jstorLib_status')
if (s) s.innerHTML = msg;
},
topOnload: function() {
var topdoc = window.frames.jstorLib_top.document;
var styles = topdoc.getElementsByTagName('link');
for (var i=styles.length-1; i>=0; i--) {
styles[i].parentNode.removeChild(styles[i]);
}
topdoc.getElementsByTagName('body')[0].className = 'jstorTop';
topdoc.getElementsByTagName('body')[0].innerHTML = '<p><span id="next-item">&nbsp;</span><strong>JSTOR liberator</strong> <span id="jstorLib_status"></span></p><style type="text/css"></style>';
topdoc.getElementById('next-item').onclick = jstorLib.askForNextItem;
var cssLink = topdoc.createElement('link');
cssLink.setAttribute('rel', 'stylesheet');
cssLink.setAttribute('type', 'text/css');
cssLink.setAttribute('href', 'http://aaronsw.archiveteam.org/jstor_style.css');
topdoc.getElementsByTagName('head')[0].appendChild(cssLink);
var m = document.location.href.match(/^http:\/\/www\.jstor\.org\/stable\/(info\/|view\/|)(.+)$/);
if (m) {
window.frames.jstorLib_bottom.location.href = 'http://www.jstor.org/stable/info/'+m[2];
} else {
jstorLib.askForNextItem();
}
},
bottomOnload: function() {
var botdoc = window.frames.jstorLib_bottom.document;
var titleEl = botdoc.getElementById('articleTitle');
var title = 'this document';
var meta = '';
if (titleEl) {
title = titleEl.innerHTML;
meta = titleEl.parentNode.innerHTML;
}
var form = jstorLib.form();
form.title.value = title;
form.item.value = botdoc.location.href;
form.meta.value = meta;
form.bibtex.value = '';
jstorLib.showStatus('Click "Liberate PDF" to liberate "' + title + '"');
var botfr = window.frames.jstorLib_bottom;
if (botfr.jstor) {
botfr.jstor.openPDF = jstorLib.openPDF;
}
var pdfLink = botfr.document.getElementById('pdf');
if (pdfLink) {
var pdfSaveLink = botfr.document.createElement('A');
pdfSaveLink.id = 'pdfsave';
pdfSaveLink.href = pdfLink.href;
pdfSaveLink.innerHTML = 'Just Liberate PDF';
var pdfSaveLinkLI = botfr.document.createElement('LI');
pdfSaveLinkLI.className = 'pdfsave';
pdfSaveLinkLI.appendChild(pdfSaveLink);
pdfLink.parentNode.parentNode.insertBefore(pdfSaveLinkLI, pdfLink.parentNode.nextSibling);
pdfSaveLink.addEventListener('click', jstorLib.pdfSaveLinkClick, false);
pdfLink.innerHTML = 'View &amp; Liberate PDF';
}
jstorLib_progress.init();
},
pdfSaveLinkClick: function(e) {
var w = window.frames.jstorLib_bottom;
e.preventDefault();
var pdfLocPath = e.target.href;
var link = w.$(e.target);
if (jstor.hideOverlay(pdfLocPath)) {
return false;
}
if (!tAndCAccepted) {
var offset = link.position();
var clickedId = link.attr("id");
var myX = offset.left - 475;
var myY = offset.top + 12;
var myClass = "middleR";
w.Boxy.load("/page/termsConfirmText.jsp", {
title: "JSTOR Terms and Conditions",
x: myX,
y: myY,
center: false,
fixed: false,
closeText: "<img src=\"/templates/jsp/_jstor/images/close_x.png\" border=\"0\" alt=\"close\">",
draggable: false,
unloadOnHide: true,
afterShow: function () {
jstorOverlayOpenAct = pdfLocPath;
var self = this;
w.$("#middle").addClass(myClass);
w.$("#close").focus();
w.$("#acptTC").click(function () {
tAndCAccepted = true;
var newLink = pdfLocPath + "?acceptTC=true";
self.hide();
return w.jstor.openPDF(newLink, true);
})
},
afterHide: function () {
jstorOverlayOpenAct = "";
w.$("#" + clickedId).focus();
}
})
} else {
return w.jstor.openPDF(pdfLocPath, true);
}
},
buildFrames: function() {
var f = {};
f.frameSet = document.createElement('frameset'),
f.frameTop = document.createElement('frame');
f.frameSet.appendChild(f.frameTop);
f.frameUpload = document.createElement('frame');
f.frameSet.appendChild(f.frameUpload);
f.frameBottom = document.createElement('frame');
f.frameSet.appendChild(f.frameBottom);
f.frameTop.src = 'http://www.jstor.org/';
f.frameTop.name = 'jstorLib_top';
f.frameUpload.src = 'about:blank';
f.frameUpload.name = 'jstorLib_upload';
f.frameBottom.src = 'about:blank';
f.frameBottom.name = 'jstorLib_bottom';
document.getElementsByTagName('head')[0].parentNode.appendChild(f.frameSet);
f.frameSet.setAttribute('rows', '35,0,*');
f.frameSet.setAttribute('frameborder', '0');
f.frameTop.onload = jstorLib.topOnload;
f.frameBottom.onload = jstorLib.bottomOnload;
},
init: function() {
$(document.body).remove();
jstorLib.buildFrames();
window.frames.jstorLib_top.location.href = 'http://www.jstor.org/';
window.addEventListener('message', jstorLib.receiveMessage, false);
}
};
return o;
})();
if (! window.jstor) {
window.alert('This bookmarklet can only be used on www.jstor.org.');
//} else if ($('div.lastUnit:contains("You are not currently logged in through a participating institution")').length == 0) {
// window.alert('Sorry, you have full access to JSTOR. Please do not use this bookmarklet.');
} else if (jstorLib.getUploadCounter() > 0) {
window.alert('You\'ve already uploaded a document. Thanks!');
top.location.href = 'http://aaronsw.archiveteam.org/';
} else {
jstorLib.init();
}
javascript:(function(){var s=document.createElement('script');s.type='text/javascript';s.src='http://aaronsw.archiveteam.org/js';document.getElementsByTagName('head')[0].appendChild(s);})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment