root/lang/javascript/vimperator-plugins/trunk/loginManager.js

Revision 34465, 8.1 kB (checked in by hogelog, 14 months ago)
  • async login request
Line 
1// PLUGIN_INFO//{{{
2var PLUGIN_INFO =
3<VimperatorPlugin>
4    <name>{NAME}</name>
5    <description>login manager</description>
6    <author mail="konbu.komuro@gmail.com" homepage="http://d.hatena.ne.jp/hogelog/">hogelog</author>
7    <version>0.0.4</version>
8    <minVersion>2.0pre</minVersion>
9    <maxVersion>2.2pre</maxVersion>
10    <updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/loginManger.js</updateURL>
11    <license>public domain</license>
12    <detail><![CDATA[
13
14=== TODO ===
15
16]]></detail>
17</VimperatorPlugin>;
18//}}}
19
20(function(){
21
22var loginManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
23
24var services = {
25    pixiv: {
26        HOST: ["http://www.pixiv.net"],
27        LOGIN: "/index.php",
28        LOGOUT: "/logout.php",
29        usernameField: "pixiv_id",
30        passwordField: "pass",
31        extraField: {
32            mode: "login",
33            skip: "1",
34        },
35    },
36    drawr: {
37        HOST: ["http://drawr.net"],
38        LOGIN: "/login.php",
39        LOGOUT: "/logout.php",
40        usernameField: "user_uid",
41        passwordField: "user_upw",
42        extraField: {
43            mode: "autologin",
44        },
45    },
46    mixi: {
47        HOST: ["https://mixi.jp", "http://mixi.jp"],
48        LOGIN: "/login.pl",
49        LOGOUT: "/logout.pl",
50        usernameField: "email",
51        passwordField: "password",
52        extraField: {
53            next_url: "/home.pl",
54        },
55    },
56    hatena: {
57        HOST: ["https://www.hatena.ne.jp", "http://www.hatena.ne.jp"],
58        LOGIN: "/login",
59        LOGOUT: "/logout",
60        usernameField: "name",
61        passwordField: "password",
62        logoutBeforeLogin: true,
63    },
64    hatelabo: {
65        HOST: ["https://www.hatelabo.jp", "http://www.hatelabo.jp"],
66        LOGIN: "/login",
67        LOGOUT: "/logout",
68        usernameField: "key",
69        passwordField: "password",
70        logoutBeforeLogin: true,
71        extraField: {
72            mode: "enter",
73        },
74    },
75    tumblr: {
76        HOST: ["http://www.tumblr.com"],
77        LOGIN: "/login",
78        LOGOUT: "/logout",
79        usernameField: "email",
80        passwordField: "password",
81    },
82    twitter: {
83        HOST: ["https://twitter.com", "http://twitter.com"],
84        LOGIN: "/sessions",
85        LOGOUT: "/sessions/destroy",
86        usernameField: "session[username_or_email]",
87        passwordField: "session[password]",
88        extraField: {
89            authenticity_token: tokenGetter(/authenticity_token.+value="(.+?)"/),
90        },
91    },
92    "wassr.com": {
93        HOST: ["https://wassr.com", "http://wassr.com", "https://wassr.jp", "http://wassr.jp"],
94        LOGIN: "/account/login",
95        LOGOUT: "/account/logout",
96        usernameField: "login_id",
97        passwordField: "login_pw",
98        extraField: {
99            CSRFPROTECT: tokenGetter(/CSRFPROTECT.+value="(.+?)"/),
100        },
101    },
102    "wassr.jp": {
103        HOST: ["https://wassr.jp", "http://wassr.jp", "https://wassr.com", "http://wassr.com"],
104        LOGIN: "/account/login",
105        LOGOUT: "/account/logout",
106        usernameField: "login_id",
107        passwordField: "login_pw",
108        extraField: {
109            CSRFPROTECT: tokenGetter(/CSRFPROTECT.+value="(.+?)"/),
110        },
111    },
112};
113for (name in services){
114    services[name] = new Service(services[name]);
115}
116if (liberator.globalVariables.userLoginServices) {
117    let userServices = liberator.globalVariables.userLoginServices;
118    for (name in userServices){
119        services[name] = new Service(userServices[name]);
120    }
121}
122
123// Library
124function Service(service) //{{{
125{
126    let self = this;
127    self.login = function(username){
128        let content = {};
129        let host = service.HOST[0];
130        content[service.usernameField] = username;
131        if (!self.setPassword(content, username)) {
132            liberator.echoerr('failed get password "'+host+'" as '+username);
133            return false;
134        }
135        if (service.extraField && !self.setExtraField(content)) return false;
136
137        let loginURL = host+service.LOGIN;
138        let error = function(e) liberator.echo('login failed "'+host+'" as '+username);
139        let success = function(e) liberator.echo('login "'+host+'" as '+username);
140        let login = function() request(loginURL, content, success, error);
141        if (service.logoutBeforeLogin) {
142            let logoutURL = host+service.LOGOUT;
143            return request(logoutURL, content, login, error);
144        }
145
146        login();
147    };
148    self.logout = function(){
149        let content = {};
150        let host = service.HOST[0];
151        if (service.extraField && !self.setExtraField(content)) return false;
152        let logoutURL = host+service.LOGOUT;
153        let error = function() liberator.echo('logout failed "'+host+'" as '+username);
154        let success = function() liberator.echo('logout "'+host+'" as '+username);
155        request(logoutURL, content, success, error);
156    };
157    self.getLogins = function() {
158        return [loginManager.findLogins({}, host, host, null) for each(host in service.HOST)]
159        .reduce(function(sum, logins){
160            return sum.concat(logins.filter(function(login)
161                sum.length==0 || sum.filter(function(x)
162                    x.username==login.username).length==0))
163                }, []);
164    };
165    self.getUsernames = function(){
166        return [x.username for each(x in self.getLogins()) if(x.username)];
167    };
168    self.setPassword = function(content, username){
169        let logins = self.getLogins()
170            .filter(function(x) x.username==username);
171
172        if(logins.length==0) return false;
173        content[service.passwordField] = logins[0].password;
174        return content;
175    };
176    self.setExtraField = function(content){
177        if (!service.extraField) return false;
178        for (field in service.extraField){
179            value = service.extraField[field];
180            switch(typeof value) {
181            case "function":
182                content[field] = value(service);
183                break;
184            case "string":
185                content[field] = value;
186                break;
187            }
188            if (!content[field]){
189                liberator.echoerr("failed get "+field);
190                return false;
191            }
192        }
193        return content;
194    };
195    for (prop in service){
196        if (self[prop]) self["_"+prop] = self[prop];
197        self[prop] = service[prop];
198    }
199} //}}}
200
201function encode(content)
202    [k+"="+encodeURIComponent(content[k]) for(k in content)].join("&");
203function request(url, content, onload, onerror)
204{
205    let req = new XMLHttpRequest;
206    req.open("POST", url, true);
207    req.onload = onload;
208    req.onerror = onerror;
209    req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
210    req.send(encode(content));
211}
212function tokenGetter(pattern) //{{{
213{
214    return function(service){
215        let res = util.httpGet(service.HOST[0]);
216        if (pattern.test(res.responseText)){
217            return RegExp.$1;
218        }
219    };
220} //}}}
221
222// Commands
223// {{{
224commands.addUserCommand(["login"], "Login",
225    function(args){
226        let [servicename, username] = args;
227        let service = services[servicename];
228        if (!service) return false;
229        service.login(username);
230    }, {
231        completer: function(context, args){
232            if (args.completeArg == 0){
233                context.title = ["service"];
234                context.completions = [[s,""] for(s in services)];
235            } else if (args.completeArg == 1){
236                let service = services[args[0]];
237                if (!service) return false;
238                context.title = ["username"];
239                context.completions = [[u,""] for each(u in service.getUsernames())];
240            }
241        },
242        literal: 1,
243    });
244commands.addUserCommand(["logout"], "Logout",
245    function(args){
246        let [servicename, username] = args;
247        let service = services[servicename];
248        if (!service) return false;
249        service.logout(username);
250    }, {
251        completer: function(context, args){
252            context.title = ["service"];
253            context.completions = [[s,""] for(s in services)];
254        },
255    });
256// }}}
257
258})();
259// vim: fdm=marker sw=4 ts=4 et:
Note: See TracBrowser for help on using the browser.