Skip to content

Instantly share code, notes, and snippets.

@y-yoshinoya
Created October 28, 2013 09:15
Show Gist options
  • Save y-yoshinoya/7193704 to your computer and use it in GitHub Desktop.
Save y-yoshinoya/7193704 to your computer and use it in GitHub Desktop.
direct_hb.js for Firefox 22+ and Vimperator 3.7+
// Vimperator plugin: 'Direct Hatena Bookmark'
// Last Change: 10-Apr-2008. Jan 2008
// License: Creative Commons
// Maintainer: Trapezoid <[email protected]> - http://unsigned.g.hatena.ne.jp/Trapezoid
// Parts:
// http://d.hatena.ne.jp/fls/20080309/p1
// Pagerization (c) id:ofk
// AutoPagerize (c) id:swdyh
//
// Hatena Bookmark direct add script for Vimperator 0.6.*
// for Migemo search: require XUL/Migemo Extension
(function(){
var isNormalize = true;
try{
var XMigemoCore = Components
.classes['@piro.sakura.ne.jp/xmigemo/factory;1']
.getService(Components.interfaces.pIXMigemoFactory)
.getService("ja");
}catch(ex){
var XMigemoCore = undefined;
}
function WSSEUtils(aUserName, aPassword){
this._init(aUserName, aPassword);
}
WSSEUtils.prototype = {
get userName() this._userName,
get noce() this._nonce,
get created() this._created,
get passwordDigest() this._passwordDigest,
getWSSEHeader: function(){
var result = [
'UsernameToken Username="' + this._userName + '", ',
'PasswordDigest="' + this._passwordDigest + '=", ',
'Nonce="' + this._nonce + '", ',
'Created="' + this._created + '"'
].join("");
return result;
},
_init: function(aUserName, aPassword){
var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
var seed = (new Date()).toUTCString() + uuidGenerator.generateUUID().toString();
this._userName = aUserName;
this._nonce = this._getSha1Digest(seed, true);
this._created = this._getISO8601String((new Date()));
this._passwordDigest = this._getSha1Digest(this._getSha1Digest(seed, false) + this._created + aPassword, true);
},
_getSha1Digest: function(aString, aBase64){
var cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
cryptoHash.init(Ci.nsICryptoHash.SHA1);
var inputStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
inputStream.setData(aString, aString.length);
cryptoHash.updateFromStream(inputStream, -1);
return cryptoHash.finish(aBase64);
},
_getISO8601String: function(aDate){
function zeropad(s, l){
while(s.length < l){
s = "0" + s;
}
return s;
}
var result = [
zeropad(aDate.getUTCFullYear(), 4), "-",
zeropad(aDate.getUTCMonth() + 1, 2), "-",
zeropad(aDate.getUTCDate(), 2), "T",
zeropad(aDate.getUTCHours(), 2), ":",
zeropad(aDate.getUTCMinutes(), 2), ":",
zeropad(aDate.getUTCSeconds(), 2), "Z"
].join("");
return result;
}
};
// copied from AutoPagerize (c) id:swdyh
function getElementsByXPath(xpath, node){
node = node || document;
var nodesSnapshot = (node.ownerDocument || node).evaluate(xpath, node, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var data = [];
for (var i = 0, l = nodesSnapshot.snapshotLength; i < l;
data.push(nodesSnapshot.snapshotItem(i++)));
return (data.length > 0) ? data : null;
}
function getFirstElementByXPath(xpath, node){
node = node || document;
var result = (node.ownerDocument || node).evaluate(xpath, node, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
return result.singleNodeValue ? result.singleNodeValue : null;
}
// copied from Pagerization (c) id:ofk
function parseHTML(str){
var createHTMLDocument = function() {
var xsl = (new DOMParser()).parseFromString(
['<?xml version="1.0"?>',
'<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">',
'<output method="html"/>',
'</stylesheet>'].join("\n"), "text/xml");
var xsltp = new XSLTProcessor();
xsltp.importStylesheet(xsl);
var doc = xsltp.transformToDocument(
document.implementation.createDocument("", "", null));
return doc;
};
var doc = createHTMLDocument();
var range = doc.createRange();
doc.appendChild(doc.createElement("html"));
range.selectNodeContents(doc.documentElement);
doc.documentElement.appendChild(
range.createContextualFragment(str));
return doc;
}
//
//
//
//
function httpGET(uri,callback){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200)
callback.call(this,xhr.responseText);
else
throw new Error(xhr.statusText)
}
};
xhr.open("GET",uri,true);
xhr.send(null);
}
function getNormalizedPermalink(url){
var canonical = plugins.libly.$U.getFirstNodeFromXPath('//link[@rel="canonical"]');
return canonical ? canonical.href : url;
}
function getTags(arg){
liberator.plugins.hatena_tags = [];
httpGET("http://b.hatena.ne.jp/my/add.confirm?url=http://example.com",
function(mypage_text){
var mypage_html = parseHTML(mypage_text);
var tags = getElementsByXPath('id("all-tags-container")//span',mypage_html);
tags.forEach(function(tag){
liberator.plugins.hatena_tags.push(tag.innerHTML);
});
liberator.echo("HatenaBookmark: Tag parsing is finished. Taglist length: " + tags.length);
});
}
getTags();
function addHatenaBookmarks(user,password,url,comment,normalize){
var target = normalize ? getNormalizedPermalink(url) : url;
var request = "<entry xmlns=\"http://purl.org/atom/ns#\"><title>dummy</title><link rel=\"related\" type=\"text/html\" href=\"" + target + "\"></link><summary type=\"text/plain\">" + comment + "</summary></entry>";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 201)
liberator.echo("HatenaBookmark: success");
else
liberator.echoerr("HatenaBookmark:" + xhr.statusText);
}
};
var wsse = new WSSEUtils(user,password);
xhr.open("POST","http://b.hatena.ne.jp/atom/post", true);
xhr.setRequestHeader("X-WSSE",wsse.getWSSEHeader());
xhr.setRequestHeader("Content-Type","application/atom+xml");
xhr.send(request);
}
commands.addUserCommand(['hbtags'],"Update HatenaBookmark Tags",
getTags,
{}
);
commands.addUserCommand(['hb'],"Post to HatenaBookmark",
function(args){
var arg = args.string;
try {
var passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
var logins = passwordManager.findLogins({}, 'https://www.hatena.ne.jp', 'https://www.hatena.ne.jp', null);
if(logins.length)
[hatenaUser, hatenaPassword] = [logins[0].username, logins[0].password];
else
liberator.echoerr("HatenaBookmark: account not found");
}
catch(ex){
}
addHatenaBookmarks(hatenaUser,hatenaPassword,modules.buffer.URL,arg,isNormalize);
},{
completer: function(context, arg){
let filter = context.filter;
//var match_result = filter.match(/(.*)\[(\w*)$/); //[all, commited, now inputting]
var match_result = filter.match(/((?:\[[^\]]*\])+)?\[?(.*)/); //[all, commited, now inputting]
//var m = new RegExp("^" + match_result[2]);
var m = new RegExp(XMigemoCore ? "^(" + XMigemoCore.getRegExp(match_result[2]) + ")" : "^" + match_result[2],'i');
var completionList = [];
liberator.plugins.hatena_tags.forEach(function(tag){
if(m.test(tag)){
completionList.push([(match_result[1] || "") + "[" + tag + "]","Tag"]);
}
});
context.title = ['Tag','Description'];
// context.advance(match_result[1].length);
context.completions = completionList;
}
}
);
})();
// vim:sw=4 ts=4 et:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment