aboutsummaryrefslogtreecommitdiffstats
path: root/hash.js
blob: 772c3a1c5e4b52d24f2afae43d3e978f372450db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// PLUGIN_INFO//{{{
var PLUGIN_INFO =
<VimperatorPlugin>
    <name>{NAME}</name>
    <description>hash of file</description>
    <author mail="konbu.komuro@gmail.com" homepage="http://d.hatena.ne.jp/hogelog/">hogelog</author>
    <version>0.2.2</version>
    <minVersion>2.3</minVersion>
    <maxVersion>2.3</maxVersion>
    <updateURL>https://github.com/vimpr/vimperator-plugins/raw/master/hash.js</updateURL>
    <detail><![CDATA[

== COMMANDS ==
hash:
    :hash md2|md5|sha1|sha256|sha384|sha512 file-path

]]></detail>
</VimperatorPlugin>;
//}}}

(function() {
    const PR_UINT_MAX = 0xffffffff;
    let Crypt = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
    let Algos = [
        ["md2", "MD2 Algorithm"],
        ["md5", "MD5 Algorithm"],
        ["sha1", "SHA1 Algorithm"],     // SHA-1
        ["sha256", "SHA256 Algorithm"], // SHA-256
        ["sha384", "SHA384 Algorithm"], // SHA-384
        ["sha512", "SHA512 Algorithm"], // SHA-512
    ];

    function getStream(path)
    {
        let file = io.File(path);
        let stream = Cc["@mozilla.org/network/file-input-stream;1"]
            .createInstance(Ci.nsIFileInputStream);
        stream.init(file, 0x01, 0444, 0);
        return stream;
    }

    // return the two-digit hexadecimal code for a byte
    function toHexString(charCode)
    {
      return ("0" + charCode.toString(16)).slice(-2);
    }


    commands.addUserCommand(["hash"], "hash of file",
        function(args){
            if (args.length!=2) {

                liberator.echo("usage \":hash md2|md5|sha1|sha256|sha384|sha512 file-path\"");
                return false;
            }
            let [algo, path] = args;
            let stream = getStream(path);

            Crypt.initWithString(algo);

            // read the entire stream
            Crypt.updateFromStream(stream, PR_UINT_MAX);

            stream.close();

            // get base-64 string
            let hash = Crypt.finish(false);

            // convert the binary hash data to a hex string.
            let str = [toHexString(hash.charCodeAt(i)) for(i in hash)].join("");
            util.copyToClipboard(str, true);
        },
        {
            bang: true,
            completer: function (context, args){
                if (args.completeArg == 0) {
                    context.title = ["hash", "algorithm"];
                    context.completions = Algos;
                } else if (args.completeArg == 1) {
                    completion.url(context, "f");
                }
            },
            literal: 1,
        },
        true
        );

})();
// vim: fdm=marker sw=4 ts=4 et:
ss="nx">Open specified page of Hatena::Diary == Commands == == Global variables == == Options == == ToDo == ]]></detail> <detail lang="ja"><![CDATA[ == 概要 == はてなダイアリーのタイトル/カテゴリのインクリメンタル検索 == コマンド == :hatedaopen or :ho : コマンドを実行すると'Search Hatena::Diary?' というプロンプトが表示されインクリメンタル検索モードになる キーワードを入力することでダイアリーの一覧をインクリメンタルに絞り込む事ができる キーワードを空白区切りで複数入力するとAnd検索となる == グローバル変数 == g:hatedaOpner_userId: 検索対象とするはてなidとダイアリーを設定する この変数に設定されている情報を元にダイアリーのエントリ一覧を取得する ex) >|| js <<EOM liberator.globalVariables.hateDAopener_accounts = [ ['snaka72', 'd'], ['Snaka', 'd'], ['snaka72', 'vimperator.g'] ]; EOM ||< == ToDo == - APIを用意する ]]></detail> </VimperatorPlugin>; // }}} plugins.hateDAopener = (function(){ // PUBLIC ///////////////////////////////////////////////////////////////{{{ let self = { getEntryList: function(keywords) { return filteredCandidates(keywords); }, }; // }}} // COMMAND //////////////////////////////////////////////////////////////{{{ commands.addUserCommand( ["hatedaopen", "ho"], "Hatena::Diary opener", function(args) { commandline.input('Search Hatena::Diary? ', function(str) { if (!str || str == '') return; liberator.open(str, args.bang ? liberator.NEW_TAB : liberator.CURRENT_TAB); }, { default: args.string, completer: function(context) { dump("context", context); hatedaCompleter(context, context.filter.split(' ')); }, onChange: function(str) { showCompletions(); } }); if (args.string != "") showCompletions(); }, { bang: true, count: "*", }, true ); // }}} // PRIVATE //////////////////////////////////////////////////////////////{{{ /** * search diary */ function hatedaCompleter(context, args) { context.format = { anchored: false, title: ["Title and URL", "Tags"], keys: { text: "url", baseUrl:"baseUrl", path: "path", name: "name", tags: "tags" }, process: [templateTitleAndUrl, templateTags] }; context.filterFunc = null; context.regenerate = true; context.generate = function() filteredCandidates(args); context.createRow = createRow; } /** * get accounts * @return accounts info * ex. [['snaka72', 'd'], ['snaka72', 'vimperator.g'], ...] */ function accounts() liberator.globalVariables.hateDAopener_accounts || []; /** * filter candidates by words */ function filteredCandidates(words) ( generateCandidates() .filter(function(i) let (targetString = '' + i.tags + ' ' + i.name) (words || []).every(function(word) targetString.match(word, 'i')) ) ); /** * create completion row */ function createRow(item, highlightGroup) { if (typeof icon == "function") icon = icon(); if (highlightGroup) { var text = item[0] || ""; var desc = item[1] || ""; } else { var text = this.process[0].call(this, item, item.text); var desc = this.process[1].call(this, item, item.description); } // <e4x> return <div highlight={highlightGroup || "CompItem"} style="white-space: nowrap"> <!-- The non-breaking spaces prevent empty elements - from pushing the baseline down and enlarging - the row. --> <li highlight="CompResult" style="width: 75%">{text}&#160;</li> <li highlight="CompDesc" style="width: 25%">{desc}&#160;</li> </div>; // </e4x> } /** * Get candidates list * @return [{"url": "(url)", "name": "hogehoge", "tags": "[hoge]"}, ... ] */ function generateCandidates() { let allEntries = []; let notEmpty = function(i) i && i != ""; accounts().forEach(function([userId, diary]) { let entries = getDiaryEntries(userId, diary) .filter(notEmpty) .map(function([dateTime, path, titleAndTag]) let ([title, tags] = extractTitleAndTags(titleAndTag)) { "url" : hatenaDiaryUrl(diary, userId) + path, "baseUrl" : hatenaDiaryUrl(diary, userId), "path" : path, "name" : title, "tags" : tags } ); allEntries = allEntries.concat(entries); }); return allEntries; } /** * Get Diary entries * @param String UserID * @return [String dateTime, String path, String titleAndTag] */ let getDiaryEntries = (function() { let cache = {}; return function(userId, diary) { let key = userId + '/' + diary; if (cache[key]) return cache[key]; let res = util.httpGet(hatenaDiaryUrl(diary, userId) + "/archive/plaintext"); return cache[key] = res.responseText .split(/\r?\n/) .map(function(i) i.split(',')); }; })(); function hatenaDiaryUrl(diary, userId) 'http://' + diary + '.hatena.ne.jp/' + userId; /** * @param String Title and Tags ex. "[hoge, fuga]About me." * @return [String title, [String tags, ...]] */ function extractTitleAndTags(titleAndTag) let (patternTags = /\[[^\]]+\]/g) [ titleAndTag.replace(patternTags, ''), (titleAndTag.match(patternTags) || []) ]; /** * template: title & url */ function templateTitleAndUrl(item) <> <img src={getFaviconURI(item.baseUrl + '/')} /> <span class="td-strut"/>{item.name} <a href={item.text} highlight="simpleURL"> <span class="extra-info">{item.text.replace(/^https?:\/\//, '')}</span> </a> </>; /** * template: tags */ function templateTags(item) item.tags && item.tags.length > 0 ? item.tags.join("") : ""; // UTILITY // let getFaviconURI = (function() { let faviconCache = {}; return function (pageURI) { if (faviconCache[pageURI]) return faviconCache[pageURI]; let uri = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService) .newURI(pageURI, null, null); let faviconURI = Cc["@mozilla.org/browser/favicon-service;1"] .getService(Ci.nsIFaviconService) .getFaviconImageForPage(uri); return faviconCache[pageURI] = faviconURI.spec; } })(); let showCompletions = function() { if (!options.get('wildoptions').has('auto')) { evalWithContext(function() { completions.complete(true, false); completions.itemList.show(); }, commandline.input); } }; let evalWithContext = function(func, context) { let str; let fstr = func.toString(); if (fstr.indexOf('function () {') == 0) { str = fstr.replace(/.*?{([\s\S]+)}.*?/m, "$1"); } else { str = '(' + fstr + ')()'; } return liberator.eval(str, context); }; function dump(title, obj) liberator.dump(title + "\n" + util.objectToString(obj)); // }}} return self; })(); // vim:sw=4 ts=4 et si fdm=marker fenc=utf-8