Baidu Multiuser Unsafe

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

As of 05.03.2015. See ბოლო ვერსია.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name	Baidu Multiuser Unsafe
// @namespace	http://geraldl.ml/
// @author	Gerald <[email protected]>
// @icon	http://cn.gravatar.com/avatar/a0ad718d86d21262ccd6ff271ece08a3?s=80
// @version	2.0.3.2
// @description	百度马甲切换不安全版(将保存用户名和密码,请慎用!)
// @homepageURL	http://geraldl.net/userjs/BaiduMultiuserUnsafe
// @match	*://*.baidu.com/*
// @include	*.baidu.com/*
// @exclude	http://developer.baidu.com/*
// @exclude	http://web.im.baidu.com/*
// @run-at	document-start
// @grant	GM_getValue
// @grant	GM_setValue
// @grant	GM_addStyle
// @grant	GM_xmlhttpRequest
// ==/UserScript==

'use strict';
function safeText(t){
	return t.replace(/&/g,'&amp;').replace(/</g,'&lt;');
}
function getValue(key,def){
	var v=GM_getValue(key)||'';
	try{v=JSON.parse(v);}catch(e){v=def;}
	return v;
}
function setValue(key,val){
	GM_setValue(key,JSON.stringify(val));
}
function showMessage(msg){
	msgbox.firstChild.innerHTML=msg;
	msgbox.style.display='block';
	msgbox.style.top=(innerHeight-msgbox.offsetHeight)/2+'px';
	msgbox.style.left=(innerWidth-msgbox.offsetWidth)/2+'px';
}
function doSetCookie(s){
	var d=new Date();
	if(s) d.setTime(16094e8); else s='';
	document.cookie='BDUSS='+s+';domain=baidu.com;path=/;expires='+d.toGMTString();
}
function setCookie(s){
	var re=/\bBDUSS=/;
	if(re.test(document.cookie)) {
		doSetCookie(s);
		return true;
	}
	doSetCookie(s?s:'logout');
	if(re.test(document.cookie)) {
		if(!s) doSetCookie(s);
		return true;
	}
}
function switchUser(user){
	function checkLogIn(callback){
		GM_xmlhttpRequest({
			method:'GET',
			url:'http://www.baidu.com',
			onload:function(o){
				var m=o.responseText.match(/<span class=user-name>(.*?)<\/span>/);
				if(m) setValue('ge_cuser',user);
				callback(!!m);
			},
		});
	}
	function checkLogInMobile(res){
		if(res.finalUrl.substr(0,url_waplogin.length)==url_waplogin)
			extractData(res.responseText);
		else checkLogIn(function(ok){
			if(ok) location.reload();
			else alert('出错了!我也不知道要怎么办。。');
		});
	}
	function doLogInMobile(data){
		showMessage('正在使用手机版登录,请等待...');
		var rdata=[],i;
		data['username']=user;
		data['password']=users[user];
		for(i in data)
			rdata.push(encodeURIComponent(i)+'='+encodeURIComponent(data[i]));
		GM_xmlhttpRequest({
			method:'POST',
			url:url_waplogin,
			data:rdata.join('&'),
			headers:{
				'User-Agent':User_Agent,
				'Content-Type':'application/x-www-form-urlencoded',
			},
			onload:checkLogInMobile,
		});
	}
	function extractData(src){
		var i=src.indexOf('<div id="error_area"'),j=src.indexOf('</div>',i),
				m=src.substr(i,j-i).match(/<span class="highlight">(.*?)<\/span>/),
				data={},form;
		if(m&&m[1]!='请您输入验证码') return showMessage('登录失败:'+m[1]);
		i=src.indexOf('<form action="/passport/login"');j=src.indexOf('</form>',i);
		form=src.substr(i,j-i);
		form.replace(/<input [^>]*>/g,function(m){
			var o={};
			m.replace(/(\w+)="(.*?)"/g,function(m,g1,g2){
				o[g1]=g2;
			});
			if(o.type!='submit') data[o.name]=o.value;
		});
		data.submit='登录';
		if(data['vcodestr']) {
			form=document.createElement('form');
			form.innerHTML='\
<h3>马甲切换</h3>\
请输入验证码:<input type=text class=vcode><br>\
<img src=http://wappass.baidu.com/cgi-bin/genimage?'+data['vcodestr']+' style="cursor:pointer" title="看不清,换一张">\
<input type=submit>';
			form.onsubmit=function(e){
				e.preventDefault();
				data['verifycode']=form.querySelector('.vcode').value;
				doLogInMobile(data);
			};
			form.querySelector('img').onclick=function(){
				setTimeout(logInMobile,0);
			};
			msgbox.firstChild.innerHTML='';
			msgbox.firstChild.appendChild(form);
		} else doLogInMobile(data);
	}
	function logInMobile(planB){
		if(planB) showMessage('正在尝试手机版登录,请等待...');
		GM_xmlhttpRequest({
			method:'GET',
			url:url_waplogin+'?type=1',
			headers:{
				'User-Agent':User_Agent,
			},
			onload:function(o){
				if(!o.finalUrl) {
					setValue('ge_mobile',mobile=false);
					showMessage('您的运行环境不支持手机版登录,已自动关闭此功能,正在切换到普通登录...');
					if(planB) setTimeout(planB,2000);
					return;
				}
				extractData(o.responseText);
			},
		});
	}
	function logInNormal(){
		setValue('ge_login',user);
		location.href=url_login+encodeURIComponent(location.href);
	}
	function logIn(){
		if(mobile) logInMobile(logInNormal);
		else logInNormal();
	}
	function logOut(){
		location.href=(mobile?url_waplogout:url_logout)+encodeURIComponent(location.href);
	}
	if(user) {	// 切换账号
		if(mobile) {
			var c=cookies[user];
			if(c) {
				if(setCookie(c)) return checkLogIn(function(ok){
					if(ok) location.reload();
					else {
						showMessage('Cookie失效了,正在尝试重新登录...');
						setTimeout(logIn,1000);
					}
				}); else
					showMessage('设置Cookie失败,正在尝试重新登录...<br>这可能是因为您使用了普通登录。');
			} else
				showMessage('没有找到Cookie,正在尝试重新登录...');
			return setTimeout(logIn,1000);
		}
		logIn();
	} else {	// 登出
		if(mobile) {
			if(setCookie()) return checkLogIn(function(ok){
				if(ok) logOut();
				else location.reload();
			}); else
				showMessage('设置Cookie失败,正在尝试登出...<br>这可能是因为您使用了普通登录。');
		}
		logOut();
	}
}
function initLoc(){
	gu.right=gu._right=gu.parentNode.offsetWidth-gu.offsetWidth-gu.offsetLeft;
	gu.top=gu._top=gu.offsetTop;
}
function saveAndUpdate(){
	setValue('ge_users',users);initMenu();
}
function saveCookies(){
	setValue('ge_cookies',cookies);
}
function saveLoc(){
	setValue('ge_users_loc',{right:gu.right,top:gu.top});
}
function panelClick(e){
	var o=e.target,c=o.parentNode,p=c.parentNode;
	if(o.tagName=='A') {
		var d=o.getAttribute('data');
		if(d=='settings') {	// 设置
			showOptions();
		} else if(d=='logout') {	// 登出
			switchUser();
		} else if(d[0]=='u') {	// 切换
			d=decodeURI(d.substr(1));
			if(d) switchUser(d);
		}
	}
	e.preventDefault();
}
function locate(l){
	if(l) {
		gu.right=l&&!isNaN(l.right)?l.right:100;
		gu.top=l&&!isNaN(l.top)?l.top:100;
	}
	gu.style.right=gu.right+'px';
	gu.style.top=gu.top+'px';
}
function mousemove(e){
	e.preventDefault();e.stopPropagation();
	var l={right:gu._right+gu.x-e.pageX,top:gu._top+e.pageY-gu.y};
	locate(l);
}
function pinUpdate(){
	if(gu.pin) {
		symbol.classList.add('ge_pin');
		symbol.setAttribute('title','固定在页面上');
		gu.style.position='absolute';
	} else {
		symbol.classList.remove('ge_pin');
		symbol.setAttribute('title','固定在屏幕上');
		gu.style.position='';
	}
}
function pin(){
	initLoc();
	if(gu.pin)	// fixed => absolute
		gu.top+=window.pageYOffset;
	else	// absolute => fixed
		gu.top-=window.pageYOffset;
	pinUpdate();
	locate();
	saveLoc();
}
function buildMenu(){
	GM_addStyle('\
#ge_uu{display:block;padding:10px;text-align:left;}\
#ge_uu .ge_h{display:none;}\
#ge_uu{z-index:10006;font:normal normal 400 12px/18px 宋体;position:fixed;}\
#ge_uu>span{background:white;color:blue;border-radius:3px;border:1px solid #c0c0c0;padding:3px;cursor:pointer;vertical-align:middle;}\
#ge_uu>div{position:relative;margin-top:3px;}\
#ge_uu>div>*{position:absolute;margin:0;padding:0;}\
.ge_uu{background:white;border:1px solid silver;box-shadow:5px 5px 7px #333;}\
.ge_uu{width:120px;max-height:400px;overflow-x:hidden;overflow-y:auto;}\
.ge_uu>li{position:relative;display:block;padding:2px 20px 4px 6px;}\
.ge_uu>li:hover,#gu_users .ge_user:hover{background:lightgray;}\
.ge_uu>li:last-child:hover{background:white;}\
.ge_uu span{position:absolute;top:0;right:0;color:white;background:#77f;border-radius:3px;margin:2px;cursor:pointer;padding:2px;}\
.ge_uu span:hover{background:red;}\
.ge_uu a,#gu_users span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;max-width:100%;}\
.ge_uu>li:last-child a{display:inline;}\
#gu_users{width:340px;height:100px;overflow:auto;border:1px solid;margin-bottom:.5em;}\
#gu_users .ge_user{position:relative;color:dodgerblue;}\
#gu_users .ge_name{display:block;margin-right:100px;padding:3px 5px;}\
#gu_users .ge_control{position:absolute;top:0;right:0;text-align:right;}\
.ge_sym{display:inline-block;width:7px;height:7px;border:1px solid #c0c0c0;border-radius:4px;margin-left:3px;}\
.ge_sym.ge_pin{background:#c0c0c0;}\
');
	if(!document.querySelector('#ge_css')) GM_addStyle('\
.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;}\
.ge_opt{padding:20px;border-radius:5px;}\
.ge_opt fieldset{border:1px solid silver;border-radius:5px;padding:5px;}\
.ge_opt textarea{min-height:100px;width:100%;}\
');
	gu=document.createElement('div');gu.id='ge_uu';
	gu.innerHTML='<span>马甲<span class=ge_sym></span></span><div><ul class="ge_uu ge_h"></ul></div>';
	gu.style.display=getValue('float','');
	ul=gu.querySelector('ul');
	ul.addEventListener('click',panelClick,false);
	symbol=gu.querySelector('.ge_sym');
	gu.pin=!!getValue('ge_pin');pinUpdate();
	symbol.addEventListener('click',function(){setValue('ge_pin',gu.pin=!gu.pin);pin();},false);
	gu.addEventListener('mouseover',function(e){
		if(this.contains(e.relatedTarget)) return;
		ul.classList.remove('ge_h');
		if(gu.offsetLeft+gu.firstChild.offsetLeft+ul.offsetWidth<=document.body.offsetWidth) ul.style.pixelLeft=0;
		else ul.style.pixelLeft=document.body.offsetWidth-gu.offsetLeft-gu.firstChild.offsetLeft-ul.offsetWidth;
	},false);
	gu.addEventListener('mouseout',function(e){if(!this.contains(e.relatedTarget)) ul.classList.add('ge_h');},false);
	document.body.appendChild(gu);gu.moving=false;locate(getValue('ge_users_loc',{}));
	gu.firstChild.addEventListener('mousedown',function(e){
		e.preventDefault();e.stopPropagation();
		if(e.target!=gu.firstChild||gu.moving) return;gu.moving=true;
		initLoc();
		gu.x=e.pageX;
		gu.y=e.pageY;
		document.addEventListener('mousemove',mousemove,false);
	},false);
	gu.addEventListener('mouseup',function(e){
		if(!gu.moving) return;gu.moving=false;
		e.preventDefault();e.stopPropagation();
		document.removeEventListener('mousemove',mousemove,false);
		saveLoc();
	},false);
	initMenu();
}
function initMenu(){
	var d=[],i;
	for(i in users) d.push('<li><a href=# data="u'+encodeURI(i)+'">'+safeText(i)+'</a></li>');
	d.push('<li><a href=# data=settings>设置</a> | <a href=# data=logout>登出</a></li>');
	ul.innerHTML=d.join('');
}
function initManage() {
	function addItem(i) {
		var d=document.createElement('div');d.className='ge_user';
		d.setAttribute('data',i);
		d.innerHTML='<div class=ge_name>'+safeText(i)+'</div><div class=ge_control><button data=mod>修改</button><button data=del>删除</button></div>';
		dusers.appendChild(d);
	}
	msgbox=document.createElement('div');
	msgbox.className='ge_popup ge_opt';
	msgbox.innerHTML='<div></div><p align=right><button>关闭</button></p>';
	msgbox.querySelector('button').addEventListener('click',function(){
		msgbox.style.display='';
	},false);
	document.body.appendChild(msgbox);
	popup=document.createElement('div');
	popup.className='ge_popup ge_opt';
	popup.innerHTML='\
<h3>百度马甲切换<font color=red>不安全版</font></h3>\
<fieldset><legend>马甲管理 <button id=gu_add>添加</button></legend>\
<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><div id=gu_users></div>\
<label><input type=checkbox id=gu_mobile>尝试使用<b>手机版</b>登录模式和<b>Cookie快速切换</b>功能 \
<a title="使用手机版登录后其他脚本也可以获取cookie,主要缺点是使用频率较高时就会要求输入验证码">(?)</a></label><br>\
</fieldset>\
<fieldset><legend>马甲数据 <button id=gu_import>导入</button> <button id=gu_export>导出</button> \
<a title="复制数据到以下文本框然后点击导入即可导入数据。\n点击导出后复制数据文本即可用于导入。">(?)</a></legend>\
<textarea id=gu_data></textarea></fieldset>\
<p align=right><button id=gu_close>关闭</button></p>\
';
	document.body.appendChild(popup);
	popup.addEventListener('click',function(e){e.stopPropagation();},false);
	var dmod=popup.querySelector('#gu_modify'),tdata=popup.querySelector('#gu_data'),
			tuser=popup.querySelector('#gu_user'),tpwd=popup.querySelector('#gu_pwd'),cur,
			dusers=popup.querySelector('#gu_users'),cmobi=popup.querySelector('#gu_mobile');
	cmobi.checked=mobile;
	cmobi.addEventListener('change',function(e){
		setValue('ge_mobile',mobile=this.checked);
	});
	popup.querySelector('#gu_add').addEventListener('click',function(){
		tuser.value=tpwd.value='';tuser.disabled=false;
		dmod.style.display='block';cur=null;tuser.focus();
	},false);
	dusers.addEventListener('click',function(e){
		var t=e.target,d,u;
		if(t.tagName!='BUTTON') return;
		d=t.getAttribute('data');cur=t.parentNode.parentNode;
		u=cur.getAttribute('data');
		if(d=='del') {
			delete users[u];delete cookies[u];
			cur.parentNode.removeChild(cur);
			cur=null;saveAndUpdate();saveCookies();
		} else if(d=='mod') {
			tuser.value=u;tuser.disabled=true;tpwd.value=users[u];
			dmod.style.display='block';tpwd.focus();tpwd.select();
		}
	},false);
	dmod.addEventListener('submit',function(e){
		e.preventDefault();
		var u=tuser.value,p=tpwd.value;
		if(!u||!p) return;
		if(cur) {
			cur.setAttribute('data',u);
			cur.firstChild.innerHTML=safeText(u);
		} else addItem(u);
		users[u]=p;saveAndUpdate();
		dmod.style.display='none';cur=null;
	},false);
	popup.querySelector('#gu_cancel').addEventListener('click',function(e){
		e.preventDefault();
		dmod.style.display='none';
	},false);
	tdata.addEventListener('click',function(){this.select();},false);
	popup.querySelector('#gu_import').addEventListener('click',function(o){
		try{
			o=JSON.parse(unescape(window.atob(tdata.value)));
		}catch(e){o=null;}
		if(o&&o.version=='unsafe'&&o.users) {
			for(var i in o.users) users[i]=o.users[i];
			saveAndUpdate();alert('导入成功!');showOptions();
		} else alert('导入失败!');
	},false);
	popup.querySelector('#gu_export').addEventListener('click',function(){
		var data={version:'unsafe',users:users};
		tdata.value=window.btoa(escape(JSON.stringify(data)));
	},false);
	popup.querySelector('#gu_close').addEventListener('click',function(){popup.style.display='';},false);
	showOptions=function(){
		popup.style.display='block';
		popup.style.top=(innerHeight-popup.offsetHeight)/2+'px';
		popup.style.left=(innerWidth-popup.offsetWidth)/2+'px';
		dusers.innerHTML='';
		for(var i in users) addItem(i);
	};
}
function init(){
	var user=getValue('ge_login'),pwd=null,cuser,m;
	users=getValue('ge_users',{});cookies=getValue('ge_cookies',{});
	mobile=getValue('ge_mobile',true);
	if(typeof users!='object') try{users=JSON.parse(users);}catch(e){users={}}
	if(location.href.substr(0,url_login.length)==url_login) {
		pwd=users[user];
		if(pwd) {	// TODO: add mask
		}
	}
	if(user) setValue('ge_login','');
	if(pwd) window.addEventListener('load',function(){
		document.querySelector('#TANGRAM__PSP_3__userName').value=user;
		document.querySelector('#TANGRAM__PSP_3__password').value=pwd;
		document.querySelector('#TANGRAM__PSP_3__submit').click();
	},false); else window.addEventListener('DOMContentLoaded',function(){
		if(window.top===window&&document.head) {
			initManage();buildMenu();
		}
	},false);
	cuser=getValue('ge_cuser');
	if(cuser) {	// update cookie
		m=document.cookie.match(/\bBDUSS=(.*?)(;|$)/);
		if(m) {
			cookies[cuser]=m[1];
			saveCookies();
		}
		setValue('ge_cuser','');
	}
}
var User_Agent='Most handsome in the world',
		url_waplogin='http://wappass.baidu.com/passport/login',
		url_waplogout='http://wappass.baidu.com/passport/?logout&u=',
		url_login='https://passport.baidu.com/v2/?login&u=',
		url_logout='https://passport.baidu.com/?logout&u=',
		gu,ul,symbol,users,cookies,popup,msgbox,mobile,showOptions;
init();