Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 876f17c

Browse files
committed
[WIP] reuse chrome cookie for leetcode.com
* inspired by skygragon/leetcode-cli#71 Signed-off-by: Eric Wang <skygragon@gmail.com>
1 parent 07e31ff commit 876f17c

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

plugins/cookie.chrome.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
var log = require('../log');
2+
var Plugin = require('../plugin');
3+
4+
// [Usage]
5+
//
6+
// TODO: still WIP
7+
//
8+
var plugin = new Plugin(100, 'cookie.chrome', '2017.12.22',
9+
'Plugin to reuse Chrome\'s leetcode cookie.',
10+
['keytar', 'sqlite3']);
11+
12+
var Chrome = {};
13+
14+
var ChromeMAC = {
15+
db: process.env.HOME + '/Library/Application Support/Google/Chrome/Default/Cookies',
16+
iterations: 1003,
17+
getPassword: function(cb) {
18+
var keytar = require('keytar');
19+
keytar.getPassword('Chrome Safe Storage', 'Chrome').then(cb);
20+
}
21+
};
22+
23+
// TODO: test this
24+
var ChromeLinux = {
25+
db: process.env.HOME + '/.config/google-chrome/Default/Cookies',
26+
iterations: 1,
27+
getPassword: function(cb) { cb('peanuts'); }
28+
};
29+
30+
var ChromeWindows = {
31+
// TODO
32+
};
33+
34+
Object.setPrototypeOf(ChromeMAC, Chrome);
35+
Object.setPrototypeOf(ChromeLinux, Chrome);
36+
Object.setPrototypeOf(ChromeWindows, Chrome);
37+
38+
Chrome.getInstance = function() {
39+
switch (process.platform) {
40+
case 'darwin': return ChromeMAC;
41+
case 'linux': return ChromeLinux;
42+
case 'win32': return ChromeWindows;
43+
}
44+
};
45+
var my = Chrome.getInstance();
46+
47+
Chrome.decodeCookie = function(cookie, cb) {
48+
var crypto = require('crypto');
49+
crypto.pbkdf2(my.password, 'saltysalt', my.iterations, 16, 'sha1', function(e, key) {
50+
if (e) return cb(e);
51+
52+
var iv = new Buffer(' '.repeat(16));
53+
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
54+
decipher.setAutoPadding(false);
55+
56+
var buf = decipher.update(cookie.slice(3)); // remove prefix "v10" or "v11"
57+
var final = decipher.final();
58+
final.copy(buf, buf.length - 1);
59+
60+
var padding = buf[buf.length - 1];
61+
if (padding) buf = buf.slice(0, buf.length - padding);
62+
63+
return cb(null, buf.toString('utf8'));
64+
});
65+
};
66+
67+
Chrome.decodeCookies = function(keys, cb) {
68+
if (keys.length === 0) return cb(null, my.cookies);
69+
70+
var k = keys.pop();
71+
var v = my.cookies[k];
72+
if (!v) return cb('Not found cookie: ' + k);
73+
74+
my.decodeCookie(v, function(e, cookie) {
75+
my.cookies[k] = cookie;
76+
my.decodeCookies(keys, cb);
77+
});
78+
};
79+
80+
var KEYS = ['csrftoken', 'LEETCODE_SESSION'];
81+
Chrome.getCookies = function(cb) {
82+
var sqlite3 = require('sqlite3');
83+
var db = new sqlite3.Database(my.db);
84+
85+
db.serialize(function() {
86+
my.cookies = {};
87+
var sql = 'select name, encrypted_value from cookies where host_key like "%leetcode.com"';
88+
db.each(sql, function(e, x) {
89+
if (e) return cb(e);
90+
if (KEYS.indexOf(x.name) < 0) return;
91+
my.cookies[x.name] = x.encrypted_value;
92+
});
93+
94+
db.close(function() {
95+
my.getPassword(function(password) {
96+
my.password = password;
97+
my.decodeCookies(KEYS, cb);
98+
});
99+
});
100+
});
101+
};
102+
103+
plugin.signin = function(user, cb) {
104+
log.debug('try to copy leetcode cookies from chrome ...');
105+
my.getCookies(function(e, cookie) {
106+
if (e) {
107+
log.error('failed to get cookies: ' + e);
108+
return plugin.next.signin(user, cb);
109+
}
110+
111+
log.debug('Successfully copied leetcode cookies!');
112+
user.sessionId = cookie.LEETCODE_SESSION;
113+
user.sessionCSRF = cookie.csrftoken;
114+
return cb(null, user);
115+
});
116+
};
117+
118+
module.exports = plugin;

0 commit comments

Comments
 (0)