Baidu Multiuser Unsafe

百度马甲切换不安全版(将保存用户名和密码,请慎用!)

目前为 2014-12-17 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Baidu Multiuser Unsafe
  3. // @namespace http://geraldl.ml/
  4. // @author Gerald <gera2ld@163.com>
  5. // @icon http://ww2.sinaimg.cn/small/a56031a1gw1emwlbe1c8gj2097097wfa.jpg
  6. // @version 2.0.1
  7. // @description 百度马甲切换不安全版(将保存用户名和密码,请慎用!)
  8. // @homepageURL http://geraldl.net/userjs/BaiduMultiuserUnsafe
  9. // @match *://*.baidu.com/*
  10. // @include *.baidu.com/*
  11. // @exclude http://developer.baidu.com/*
  12. // @exclude http://web.im.baidu.com/*
  13. // @run-at document-start
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @grant GM_addStyle
  17. // @grant GM_xmlhttpRequest
  18. // ==/UserScript==
  19.  
  20. var User_Agent='Most handsome in the world',
  21. url_login='http://wappass.baidu.com/passport/login';
  22. function safeText(t){
  23. return t.replace(/&/g,'&amp;').replace(/</g,'&lt;');
  24. }
  25. function getValue(key,def){
  26. var v=GM_getValue(key)||'';
  27. try{v=JSON.parse(v);}catch(e){v=def;}
  28. return v;
  29. }
  30. function setValue(key,val){
  31. GM_setValue(key,JSON.stringify(val));
  32. }
  33. function showMessage(msg){
  34. msgbox.firstChild.innerHTML=msg;
  35. msgbox.style.display='block';
  36. msgbox.style.top=(innerHeight-msgbox.offsetHeight)/2+'px';
  37. msgbox.style.left=(innerWidth-msgbox.offsetWidth)/2+'px';
  38. }
  39. function setCookie(s){
  40. var d=new Date();
  41. if(s) d.setTime(16094e8); else s='';
  42. document.cookie='BDUSS='+s+';domain=baidu.com;path=/;expires='+d.toGMTString();
  43. }
  44. function switchUser(user){
  45. function checkLogIn(callback){
  46. GM_xmlhttpRequest({
  47. method:'GET',
  48. url:'http://www.baidu.com',
  49. onload:function(o){
  50. var m=o.responseText.match(/<span class=user-name>(.*?)<\/span>/);
  51. if(m) setValue('ge_cuser',user);
  52. callback(!!m);
  53. },
  54. });
  55. }
  56. function checkLogInMobile(res){
  57. if(res.finalUrl.substr(0,url_login.length)==url_login)
  58. doLogInMobile(res.responseText);
  59. else checkLogIn(function(ok){
  60. if(ok) location.reload();
  61. else alert('出错了!我也不知道要怎么办。。');
  62. });
  63. }
  64. function doLogInMobile(src){
  65. var i=src.indexOf('<div id="error_area"'),j=src.indexOf('</div>',i),
  66. m=src.substr(i,j-i).match(/<span class="highlight">(.*?)<\/span>/),
  67. data={},rdata=[],form;
  68. if(m) {
  69. showMessage('登录失败!'+m[1]);
  70. }
  71. i=src.indexOf('<form action="/passport/login"');j=src.indexOf('</form>',i);
  72. form=src.substr(i,j-i);
  73. form.replace(/<input[^>]*? name="(.*?)"[^>]*? value="(.*?)"[^>]*?>/g,function(m,g1,g2){
  74. data[g1]=g2;
  75. });
  76. if(data['vcodestr']) {
  77. // TODO: 验证码
  78. // 'http://wappass.baidu.com/cgi-bin/genimage?'+data['vcodestr']
  79. showMessage('需要验证码,此功能以后再说。。或者休息一下重试~');
  80. return;
  81. } else {
  82. data['username']=user;
  83. data['password']=users[user];
  84. }
  85. for(i in data)
  86. rdata.push(encodeURIComponent(i)+'='+encodeURIComponent(data[i]));
  87. GM_xmlhttpRequest({
  88. method:'POST',
  89. url:'http://wappass.baidu.com/passport/login',
  90. data:rdata.join('&'),
  91. headers:{
  92. 'User-Agent':User_Agent,
  93. 'Content-Type':'application/x-www-form-urlencoded',
  94. },
  95. onload:checkLogInMobile,
  96. });
  97. }
  98. function logInMobile(planB){
  99. showMessage('正在尝试手机版登录,请等待...');
  100. GM_xmlhttpRequest({
  101. method:'GET',
  102. url:url_login+'?type=1',
  103. headers:{
  104. 'User-Agent':User_Agent,
  105. },
  106. onload:function(o){
  107. if(!o.finalUrl) {
  108. showMessage('您的运行环境不支持手机版登录(可到设置中关闭该功能),正在切换到普通登录...');
  109. setTimeout(planB,2000);
  110. return;
  111. }
  112. doLogInMobile(o.responseText);
  113. },
  114. });
  115. }
  116. function logInNormal(){
  117. setValue('ge_login',user);
  118. location.href=loginUrl+encodeURIComponent(location.href);
  119. }
  120. function logIn(){
  121. if(mobile) logInMobile(logInNormal);
  122. else logInNormal();
  123. }
  124. function logOut(){
  125. location.href='https://passport.baidu.com/?logout&u='+encodeURIComponent(location.href);
  126. }
  127. if(user) { // 切换账号
  128. if(usecookie) {
  129. var c=cookies[user];
  130. if(c) {
  131. setCookie(c);
  132. return checkLogIn(function(ok){
  133. if(ok) location.reload();
  134. else {
  135. showMessage('Cookie失效了,正在尝试重新登录...');
  136. setTimeout(logIn,1000);
  137. }
  138. });
  139. }
  140. showMessage('没有找到Cookie,正在尝试重新登录...');
  141. return setTimeout(logIn,1000);
  142. }
  143. logIn();
  144. } else { // 登出
  145. if(usecookie) {
  146. setCookie();
  147. return checkLogIn(function(ok){
  148. if(ok) logOut();
  149. else location.reload();
  150. });
  151. }
  152. logOut();
  153. }
  154. }
  155. function initLoc(){
  156. gu.right=gu._right=gu.parentNode.offsetWidth-gu.offsetWidth-gu.offsetLeft;
  157. gu.top=gu._top=gu.offsetTop;
  158. }
  159. function saveAndUpdate(){
  160. setValue('ge_users',users);initMenu();
  161. }
  162. function saveCookies(){
  163. setValue('ge_cookies',cookies);
  164. }
  165. function saveLoc(){
  166. setValue('ge_users_loc',{right:gu.right,top:gu.top});
  167. }
  168. function panelClick(e){
  169. var o=e.target,c=o.parentNode,p=c.parentNode;
  170. if(o.tagName=='A') {
  171. var d=o.getAttribute('data');
  172. if(d=='settings') { // 设置
  173. showOptions();
  174. } else if(d=='logout') { // 登出
  175. switchUser();
  176. } else if(d[0]=='u') { // 切换
  177. d=decodeURI(d.substr(1));
  178. if(d) switchUser(d);
  179. }
  180. }
  181. e.preventDefault();
  182. }
  183. function locate(l){
  184. if(l) {
  185. gu.right=l&&!isNaN(l.right)?l.right:100;
  186. gu.top=l&&!isNaN(l.top)?l.top:100;
  187. }
  188. gu.style.right=gu.right+'px';
  189. gu.style.top=gu.top+'px';
  190. }
  191. function mousemove(e){
  192. e.preventDefault();e.stopPropagation();
  193. var l={right:gu._right+gu.x-e.pageX,top:gu._top+e.pageY-gu.y};
  194. locate(l);
  195. }
  196. function pinUpdate(){
  197. if(gu.pin) {
  198. symbol.classList.add('ge_pin');
  199. symbol.setAttribute('title','固定在页面上');
  200. gu.style.position='absolute';
  201. } else {
  202. symbol.classList.remove('ge_pin');
  203. symbol.setAttribute('title','固定在屏幕上');
  204. gu.style.position='';
  205. }
  206. }
  207. function pin(){
  208. initLoc();
  209. if(gu.pin) // fixed => absolute
  210. gu.top+=window.pageYOffset;
  211. else // absolute => fixed
  212. gu.top-=window.pageYOffset;
  213. pinUpdate();
  214. locate();
  215. saveLoc();
  216. }
  217. function buildMenu(){
  218. GM_addStyle('\
  219. #ge_uu{display:block;padding:10px;text-align:left;}\
  220. #ge_uu .ge_h{display:none;}\
  221. #ge_uu{z-index:10006;font:normal normal 400 12px/18px 宋体;position:fixed;}\
  222. #ge_uu>span{background:white;color:blue;border-radius:3px;border:1px solid #c0c0c0;padding:3px;cursor:pointer;vertical-align:middle;}\
  223. #ge_uu>div{position:relative;margin-top:3px;}\
  224. #ge_uu>div>*{position:absolute;}\
  225. .ge_uu{background:white;border:1px solid silver;box-shadow:5px 5px 7px #333;}\
  226. .ge_uu{width:120px;max-height:400px;overflow-x:hidden;overflow-y:auto;}\
  227. .ge_uu>li{position:relative;display:block;padding:2px 20px 4px 6px;}\
  228. .ge_uu>li:hover,#gu_users .ge_user:hover{background:lightgray;}\
  229. .ge_uu>li:last-child:hover{background:white;}\
  230. .ge_uu span{position:absolute;top:0;right:0;color:white;background:#77f;border-radius:3px;margin:2px;cursor:pointer;padding:2px;}\
  231. .ge_uu span:hover{background:red;}\
  232. .ge_uu a,#gu_users span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;max-width:100%;}\
  233. .ge_uu>li:last-child a{display:inline;}\
  234. #gu_users{width:340px;height:100px;overflow:auto;border:1px solid;margin-bottom:.5em;}\
  235. #gu_users .ge_user{position:relative;color:dodgerblue;}\
  236. #gu_users .ge_name{display:block;margin-right:100px;padding:3px 5px;}\
  237. #gu_users .ge_control{position:absolute;top:0;right:0;text-align:right;}\
  238. .ge_sym{display:inline-block;width:7px;height:7px;border:1px solid #c0c0c0;border-radius:4px;margin-left:3px;}\
  239. .ge_sym.ge_pin{background:#c0c0c0;}\
  240. ');
  241. if(!document.querySelector('#ge_css')) GM_addStyle('\
  242. .ge_popup{display:none;z-index:10006;font:normal normal 400 12px/18px 宋体;position:fixed;background:white;border:1px solid silver;box-shadow:5px 5px 7px #333;text-align:left;}\
  243. .ge_opt{padding:20px;border-radius:5px;}\
  244. .ge_opt fieldset{border:1px solid silver;border-radius:5px;padding:5px;}\
  245. .ge_opt textarea{min-height:100px;width:100%;}\
  246. ');
  247. gu=document.createElement('div');gu.id='ge_uu';
  248. gu.innerHTML='<span>马甲<span class=ge_sym></span></span><div><ul class="ge_uu ge_h"></ul></div>';
  249. gu.style.display=getValue('float','');
  250. ul=gu.querySelector('ul');
  251. ul.addEventListener('click',panelClick,false);
  252. symbol=gu.querySelector('.ge_sym');
  253. gu.pin=!!getValue('ge_pin');pinUpdate();
  254. symbol.addEventListener('click',function(){setValue('ge_pin',gu.pin=!gu.pin);pin();},false);
  255. gu.addEventListener('mouseover',function(e){
  256. if(this.contains(e.relatedTarget)) return;
  257. ul.classList.remove('ge_h');
  258. if(gu.offsetLeft+gu.firstChild.offsetLeft+ul.offsetWidth<=document.body.offsetWidth) ul.style.pixelLeft=0;
  259. else ul.style.pixelLeft=document.body.offsetWidth-gu.offsetLeft-gu.firstChild.offsetLeft-ul.offsetWidth;
  260. },false);
  261. gu.addEventListener('mouseout',function(e){if(!this.contains(e.relatedTarget)) ul.classList.add('ge_h');},false);
  262. document.body.appendChild(gu);gu.moving=false;locate(getValue('ge_users_loc',{}));
  263. gu.firstChild.addEventListener('mousedown',function(e){
  264. e.preventDefault();e.stopPropagation();
  265. if(e.target!=gu.firstChild||gu.moving) return;gu.moving=true;
  266. initLoc();
  267. gu.x=e.pageX;
  268. gu.y=e.pageY;
  269. document.addEventListener('mousemove',mousemove,false);
  270. },false);
  271. gu.addEventListener('mouseup',function(e){
  272. if(!gu.moving) return;gu.moving=false;
  273. e.preventDefault();e.stopPropagation();
  274. document.removeEventListener('mousemove',mousemove,false);
  275. saveLoc();
  276. },false);
  277. initMenu();
  278. }
  279. function initMenu(){
  280. var d=[],i;
  281. for(i in users) d.push('<li><a href=# data="u'+encodeURI(i)+'">'+safeText(i)+'</a></li>');
  282. d.push('<li><a href=# data=settings>设置</a> | <a href=# data=logout>登出</a></li>');
  283. ul.innerHTML=d.join('');
  284. }
  285. function initManage() {
  286. function addItem(i) {
  287. var d=document.createElement('div');d.className='ge_user';
  288. d.setAttribute('data',i);
  289. d.innerHTML='<div class=ge_name>'+safeText(i)+'</div><div class=ge_control><button data=mod>修改</button><button data=del>删除</button></div>';
  290. dusers.appendChild(d);
  291. }
  292. msgbox=document.createElement('div');
  293. msgbox.className='ge_popup ge_opt';
  294. msgbox.innerHTML='<div></div><p align=right><button>关闭</button></p>';
  295. msgbox.querySelector('button').addEventListener('click',function(){
  296. msgbox.style.display='';
  297. },false);
  298. document.body.appendChild(msgbox);
  299. popup=document.createElement('div');
  300. popup.className='ge_popup ge_opt';
  301. popup.innerHTML='\
  302. <h3>百度马甲切换<font color=red>不安全版</font></h3>\
  303. <fieldset><legend>马甲管理 <button id=gu_add>添加</button></legend>\
  304. <form id=gu_modify style="display:none;"><input type=text id=gu_user placeholder="用户名"><input type=password id=gu_pwd placeholder="密码"><input type=submit value="确认"><input type=button id=gu_cancel value="取消"></form>\
  305. <div id=gu_users></div>\
  306. <label><input type=checkbox id=gu_cookie>尝试使用Cookie快速切换账号 <a title="方便快速,如Cookie失效则自动重新登录">(?)</a></label><br>\
  307. <label><input type=checkbox id=gu_mobile>尝试使用手机版登录模式 <a title="使用手机版登录后其他脚本可以获取cookie,主要缺点是使用频率较高时就会要求输入验证码">(?)</a></label><br>\
  308. </fieldset>\
  309. <fieldset><legend>马甲数据 <button id=gu_import>导入</button> <button id=gu_export>导出</button> \
  310. <a title="复制数据到以下文本框然后点击导入即可导入数据。\n点击导出后复制数据文本即可用于导入。">(?)</a></legend>\
  311. <textarea id=gu_data></textarea></fieldset>\
  312. <p align=right><button id=gu_close>关闭</button></p>\
  313. ';
  314. document.body.appendChild(popup);
  315. popup.addEventListener('click',function(e){e.stopPropagation();},false);
  316. var dmod=popup.querySelector('#gu_modify'),tdata=popup.querySelector('#gu_data'),
  317. tuser=popup.querySelector('#gu_user'),tpwd=popup.querySelector('#gu_pwd'),cur,
  318. dusers=popup.querySelector('#gu_users'),cmobi=popup.querySelector('#gu_mobile'),
  319. ccookie=popup.querySelector('#gu_cookie');
  320. ccookie.checked=usecookie;
  321. ccookie.addEventListener('change',function(e){
  322. setValue('ge_cookie',usecookie=this.checked);
  323. });
  324. cmobi.checked=mobile;
  325. cmobi.addEventListener('change',function(e){
  326. setValue('ge_mobile',mobile=this.checked);
  327. });
  328. popup.querySelector('#gu_add').addEventListener('click',function(){
  329. tuser.value=tpwd.value='';tuser.disabled=false;
  330. dmod.style.display='block';cur=null;tuser.focus();
  331. },false);
  332. dusers.addEventListener('click',function(e){
  333. var t=e.target,d,u;
  334. if(t.tagName!='BUTTON') return;
  335. d=t.getAttribute('data');cur=t.parentNode.parentNode;
  336. u=cur.getAttribute('data');
  337. if(d=='del') {
  338. delete users[u];delete cookies[u];
  339. cur.parentNode.removeChild(cur);
  340. cur=null;saveAndUpdate();saveCookies();
  341. } else if(d=='mod') {
  342. tuser.value=u;tuser.disabled=true;tpwd.value=users[u];
  343. dmod.style.display='block';tpwd.focus();tpwd.select();
  344. }
  345. },false);
  346. dmod.addEventListener('submit',function(e){
  347. e.preventDefault();
  348. var u=tuser.value,p=tpwd.value;
  349. if(!u||!p) return;
  350. if(cur) {
  351. cur.setAttribute('data',u);
  352. cur.firstChild.innerHTML=safeText(u);
  353. } else addItem(u);
  354. users[u]=p;saveAndUpdate();
  355. dmod.style.display='none';cur=null;
  356. },false);
  357. popup.querySelector('#gu_cancel').addEventListener('click',function(e){
  358. e.preventDefault();
  359. dmod.style.display='none';
  360. },false);
  361. tdata.addEventListener('click',function(){this.select();},false);
  362. popup.querySelector('#gu_import').addEventListener('click',function(o){
  363. try{
  364. o=JSON.parse(unescape(window.atob(tdata.value)));
  365. }catch(e){o=null;}
  366. if(o&&o.version=='unsafe'&&o.users) {
  367. for(var i in o.users) users[i]=o.users[i];
  368. saveAndUpdate();alert('导入成功!');showOptions();
  369. } else alert('导入失败!');
  370. },false);
  371. popup.querySelector('#gu_export').addEventListener('click',function(){
  372. var data={version:'unsafe',users:users};
  373. tdata.value=window.btoa(escape(JSON.stringify(data)));
  374. },false);
  375. popup.querySelector('#gu_close').addEventListener('click',function(){popup.style.display='';},false);
  376. showOptions=function(){
  377. popup.style.display='block';
  378. popup.style.top=(innerHeight-popup.offsetHeight)/2+'px';
  379. popup.style.left=(innerWidth-popup.offsetWidth)/2+'px';
  380. dusers.innerHTML='';
  381. for(var i in users) addItem(i);
  382. };
  383. }
  384. function init(){
  385. var user=getValue('ge_login'),pwd=null;
  386. users=getValue('ge_users',{});cookies=getValue('ge_cookies',{});
  387. mobile=getValue('ge_mobile',false);usecookie=getValue('ge_cookie',true);
  388. if(typeof users!='object') try{users=JSON.parse(users);}catch(e){users={}}
  389. if(location.href.substr(0,loginUrl.length)==loginUrl) {
  390. pwd=users[user];
  391. if(pwd) { // TODO: add mask
  392. }
  393. }
  394. if(user) setValue('ge_login','');
  395. if(pwd) window.addEventListener('load',function(){
  396. document.querySelector('#TANGRAM__PSP_3__userName').value=user;
  397. document.querySelector('#TANGRAM__PSP_3__password').value=pwd;
  398. document.querySelector('#TANGRAM__PSP_3__submit').click();
  399. },false); else window.addEventListener('DOMContentLoaded',function(){
  400. if(window.top===window&&document.head) {
  401. initManage();buildMenu();
  402. }
  403. },false);
  404. user=getValue('ge_cuser');
  405. if(user) { // update cookie
  406. m=document.cookie.match(/BDUSS=(.*?)(;|$)/);
  407. if(m) {
  408. cookies[user]=m[1];
  409. saveCookies();
  410. }
  411. setValue('ge_cuser','');
  412. }
  413. }
  414. var gu,ul,symbol,users,cookies,popup,msgbox,mobile,usecookie,showOptions,loginUrl='https://passport.baidu.com/v2/?login&u=';
  415. init();