aboutsummaryrefslogtreecommitdiffstats
path: root/account_switcher.js
blob: 1cb1ba628c3ae434b6463a0b7cfbe7223446d2ae (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Vimperator plugin: "Update mixi echo"
// Last Change: 21-Oct-2008. Jan 2008
// License: Creative Commons
// Maintainer: mattn <mattn.jp@gmail.com> - http://mattn.kaoriya.net/

(function(){
	var ucnv = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
		.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
	ucnv.charset = "EUC-JP";
	function sprintf(format){
		var i = 1, re = /%s/, result = "" + format;
		while (re.test(result) && i < arguments.length) result = result.replace(re, arguments[i++]);
		return result;
	}
	function parseHTML(str, ignoreTags) {
		var exp = "^[\\s\\S]*?<html(?:\\s[^>]*)?>|</html\\s*>[\\S\\s]*$";
		if (ignoreTags) {
			if (typeof ignoreTags == "string") ignoreTags = [ignoreTags];
			var stripTags = [];
			ignoreTags = ignoreTags.filter(function(tag) tag[tag.length - 1] == "/" || !stripTags.push(tag))
			                       .map(function(tag) tag.replace(/\/$/, ""));
			if (stripTags.length > 0) {
				stripTags = stripT
var PLUGIN_INFO =
<VimperatorPlugin>
<name>{NAME}</name>
<description>Switch account easily.</description>
<description lang="ja">複数のアカウントを切り替えることができます</description>
<minVersion>2.1a1pre</minVersion>
<maxVersion>2.1a1pre</maxVersion>
<updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/account_switcher.js</updateURL>
<author mail="masa138@gmail.com" homepage="http://www.hatena.ne.jp/masa138/">Masayuki KIMURA</author>
<version>0.08</version>
<detail><![CDATA[

== Commands ==
:account {username}@{servicename}
    {servicename}  {username} でログインします
    このときログインマネージャーの値を使用するので
    ログインマネージャーにパスワードを保存しておく必要があります

:loginmultiaccounts
    .vimperatorrc であらかじめ設定しておいたアカウントすべてにログインします
    日常的に使うサーヴィスのメインアカウントを登録しておくことでコマンド一つで
    すべてにログインできます


== Global variables ==
accountSwitcherServices
    Google, Hatena, Hatelabo 以外のアカウントにも対応することが出来ます

accountSwitcherLoginServices
    :loginmultiaccounts でログインするアカウントの配列

== .vimperatorrc ==
以下の様に記述しておけば:loginmultiaccounts を実行したときに
すべてのアカウントにログインできます
>||
js <<EOM
liberator.globalVariables.accountSwitcherLoginServices = [
    'bar@hatena',
    'buz@hatelabo',
    'foo@google',
];
||<

accountSwitcherOpenNewTab
    ログイン後に jump 先を新しいタブで開くかどうか指定することが出来ます
>||
js <<EOM
// タブで開く
liberator.accountSwitcherOpenNewTab = 1;
||<

]]></detail>
</VimperatorPlugin>;
(function(){
    var services = [];
    var accounts = [];
    var nowLogin = [];
    var isFirst  = true;

    var manager = Components.classes["@mozilla.org/login-manager;1"].getService(Components.interfaces.nsILoginManager);

    var ns         = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
    var statusBar  = document.getElementById('status-bar');
    var targetElem = document.getElementById('page-report-button');
    var afterSLine = targetElem.nextSibling;
    var sbPannel   = document.createElementNS(ns, 'statusbarpannel');
    var img        = sbPannel.appendChild(document.createElementNS(ns, 'image'));
    sbPannel.id    = 'account-switcher-pannel';

    var loginServices;

    var _services = {
        google: {
            host   : 'https://www.google.com',
            login  : '/accounts/LoginAuth',
            id     : 'Email',
            pw     : 'Passwd',
            ex     : ['GALX'],
            logout : 'http://mail.google.com/mail/?logout',
        },
        hatena: {
            host   : 'https://www.hatena.ne.jp',
            login  : '/login',
            id     : 'name',
            pw     : 'password',
            logout : '/logout',
        },
        hatelabo: {
            host   : 'https://www.hatelabo.jp',
            login  : '/login',
            id     : 'key',
            pw     : 'password',
            ex     : ['mode=enter'],
            logout : '/logout',
        },
        twitter: {
            host   : 'https://twitter.com',
            login  : '/sessions',
            id     : 'session[username_or_email]',
            pw     : 'session[password]',
            ex     : ['authenticity_token'],
            exhost : 'https://twitter.com',
            logout : '/sessions/destroy',
            jump   : '/',
        },
        tumblr : {
            host   : 'http://www.tumblr.com',
            login  : '/login',
            id     : 'email',
            pw     : 'password',
            logout : '/logout',
            jump   : '/dashboard',
        },
    };

    function init() {
        var rcServices = liberator.globalVariables.accountSwitcherServices;
        rcServices = !rcServices ? [] : rcServices;

        // loginmultiaccounts でログインするアカウントの読み込み
        loginServices = liberator.globalVariables.accountSwitcherLoginServices;
        loginServices = !loginServices ? [] : loginServices;

        for (var key in _services)  if (_services.hasOwnProperty(key)) services[key] = _services[key];
        for (var key in rcServices) if (rcServices.hasOwnProperty(key)) {
            var s = rcServices[key];
            if (services[key] == null) services[key] = s;
            else {
                for (var k in s) if (s.hasOwnProperty(k)) {
                    services[key][k] = s[k];
                }
            }
        }

        var hosts = [key for (key in services)];
        for (var i in hosts) {
            var host = hosts[i];
            if (isFirst) nowLogin[host] = '';
            var logins = manager.findLogins({}, services[host].host, "", null);
            var ignoreAccounts = liberator.globalVariables.accountSwitcherIngnoreAccounts;
            for (var i = 0; i < logins.length; i++) {
                var login = logins[i];
                var usernameAndService = [login.username, host].join('@');
                if (!!ignoreAccounts && ignoreAccounts.indexOf(usernameAndService) != -1) continue;
                accounts[usernameAndService] = {};
                var a = accounts[usernameAndService];
                a.username = login.username;
                a.password = login.password;
                a.host     = host;
            }
        }

        isFirst = false;
    }

    function changeAccount(user) {
        var username = accounts[user].username;
        var password = accounts[user].password;
        var params   = [];

        var service = services[accounts[user].host];
        if (service.host == null || service.logout == null) return;
        if (!!service.params) params = service.params;

        var req = new XMLHttpRequest();
        var url = (service.logout.indexOf('http') != 0) ? service.host + service.logout : service.logout;
        req.open("POST", url, true);
        req.onload = function(e) {
            var url = (service.login.indexOf('http') != 0) ? service.host + service.login : service.login;
            var ex  = service.ex;
            if (!!ex) {
                var res;
                if (!!service.exhost) {
                    res = util.httpGet(service.exhost);
                } else {
                    res = util.httpGet(url);
                }
                for (var i = 0, length = ex.length; i < length; i++) {
                    var value = ex[i];
                    if (value.indexOf('=') > 0) {
                        params.push(value);
                    } else {
                        res.responseText.match(new RegExp('<([^<>]*?name=\"' + value + '\"[^<>]*?)>'));
                        RegExp.$1.match(/value=\"([\w-]+)\"/);
                        params.push(value + '=' + encodeURIComponent(RegExp.$1));
                    }
                }
            }
            if (service.login == null || service.id == null || service.pw == null) return;
            var req = new XMLHttpRequest();
            req.open("POST", url, true);
            req.onload = function(e) {
                if (service.jump != null) {
                    var url = (service.jump.indexOf('http') == -1) ? service.host + service.jump : service.jump;
                    if (!!liberator.globalVariables.accountSwitcherOpenNewTab && window.content.location.href != 'about:blank') {
                        liberator.open(url, liberator.NEW_BACKGROUND_TAB);
                    } else {
                        window.content.location.href = url;
                    }
                } else if(content.location.href != 'about:blank') {
                    window.content.location.reload();
                }
                var needle = '.hatena.ne.jp';
                if (service.host.toLowerCase().lastIndexOf(needle) == service.host.length - needle.length) {
                    img.setAttribute('src', 'http://www.hatena.ne.jp/users/' + username.substr(0, 2) + '/' + username + '/profile_s.gif');
                    img.setAttribute('tooltiptext', 'id:' + username);
                    if (!document.getElementById('account_switcher_pannel')) {
                        if (afterSLine != null) {
                            statusBar.insertBefore(sbPannel, afterSLine);
                        } else {
                            statusBar.appendChild(sbPannel);
                        }
                    }
                }
            };
            req.onerror = function(e) { liberator.echoerr('Login error in account_switcher.js'); };
            req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            params.push(service.id + '=' + encodeURIComponent(username));
            params.push(service.pw + '=' + encodeURIComponent(password));
            req.send(params.join('&'));
            nowLogin[user.substr(user.lastIndexOf('@') + 1)] = user;
        };
        req.onerror = function(e) { liberator.echoerr('Logout error in account_switcher.js'); };
        req.send(null);
    }

    function loginMultiAccounts() {
        for (var i = 0, length = loginServices.length; i < length; i++) {
            for (var key in accounts) if (accounts.hasOwnProperty(key)) {
                if (key == loginServices[i]) {
                    changeAccount(key);
                    continue;
                }
            }
        }
    }

    commands.addUserCommand(["loginmultiaccounts"], "Login multi accounts",
        function() {
            init();
            loginMultiAccounts();
        }
    );

    commands.addUserCommand(["account"], "Change Account",
        function(args) {
            if (!args) {
                liberator.echo("Usage: account {username}@{servicename}");
            } else {
                var user = args[args.length - 1];
                if (!user) return;
                changeAccount(user);
            }
        }, {
            completer: function(context, args) {
                init();
                context.title = ["Account", "Service"];
                for (var service in nowLogin) if (nowLogin.hasOwnProperty(service)) {
                    var username = nowLogin[service];
                    if (username != '') delete(accounts[username]);
                }
                var compls = [[key, accounts[key].host] for (key in accounts) if (accounts.hasOwnProperty(key))];
                if (args.length > 0) {
                    for (var i = 0; i < args.length; i++) {
                        var user = args[i];
                        if (user != '') {
                            compls = compls.filter(function(c) c[0].indexOf(user) != -1);
                        }
                    }
                }
                return [0, compls];
            }
        }
    );
})();
// vim:sw=4 ts=4 et: