- implement remember me.
- will use either html5 storage, google gear or cookie ( in the order listed ).
This commit is contained in:
Heng Sin Low 2009-11-06 09:46:37 +00:00
parent 748e6ead78
commit 93b430033e
9 changed files with 465 additions and 29 deletions

View File

@ -25,4 +25,6 @@ Copyright (C) 2007 Ashley G Ramdass (ADempiere WebUI).
<javascript src="/js/calc.js" charset="UTF-8"/> <javascript src="/js/calc.js" charset="UTF-8"/>
<javascript src="/js/layout.js" charset="UTF-8"/> <javascript src="/js/layout.js" charset="UTF-8"/>
<javascript src="/js/report.js" charset="UTF-8"/> <javascript src="/js/report.js" charset="UTF-8"/>
<javascript src="/js/persist-min.js" charset="UTF-8"/>
<javascript src="/js/token.js" charset="UTF-8"/>
</language> </language>

View File

@ -25,15 +25,19 @@ import javax.servlet.http.HttpSession;
import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.component.DrillCommand; import org.adempiere.webui.component.DrillCommand;
import org.adempiere.webui.component.TokenCommand;
import org.adempiere.webui.component.ZoomCommand; import org.adempiere.webui.component.ZoomCommand;
import org.adempiere.webui.desktop.DefaultDesktop; import org.adempiere.webui.desktop.DefaultDesktop;
import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.event.TokenEvent;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.BrowserToken;
import org.adempiere.webui.util.UserPreference; import org.adempiere.webui.util.UserPreference;
import org.compiere.model.MRole; import org.compiere.model.MRole;
import org.compiere.model.MSession; import org.compiere.model.MSession;
import org.compiere.model.MSysConfig; import org.compiere.model.MSysConfig;
import org.compiere.model.MUser;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Language; import org.compiere.util.Language;
@ -160,7 +164,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient
Session currSess = Executions.getCurrent().getDesktop().getSession(); Session currSess = Executions.getCurrent().getDesktop().getSession();
HttpSession httpSess = (HttpSession) currSess.getNativeSession(); HttpSession httpSess = (HttpSession) currSess.getNativeSession();
MSession.get (ctx, currSess.getRemoteAddr(), MSession mSession = MSession.get (ctx, currSess.getRemoteAddr(),
currSess.getRemoteHost(), httpSess.getId() ); currSess.getRemoteHost(), httpSess.getId() );
//enable full interface, relook into this when doing preference //enable full interface, relook into this when doing preference
@ -239,6 +243,16 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient
ExecutionCarryOver eco = new ExecutionCarryOver(this.getPage().getDesktop()); ExecutionCarryOver eco = new ExecutionCarryOver(this.getPage().getDesktop());
currSess.setAttribute("execution.carryover", eco); currSess.setAttribute("execution.carryover", eco);
} }
if ("Y".equalsIgnoreCase(Env.getContext(ctx, BrowserToken.REMEMBER_ME)))
{
MUser user = MUser.get(ctx);
BrowserToken.save(mSession, user);
}
else
{
BrowserToken.remove();
}
} }
private void createDesktop() private void createDesktop()
@ -326,5 +340,6 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient
new ZoomCommand("onZoom", Command.IGNORE_OLD_EQUIV); new ZoomCommand("onZoom", Command.IGNORE_OLD_EQUIV);
new DrillCommand("onDrillAcross", Command.IGNORE_OLD_EQUIV); new DrillCommand("onDrillAcross", Command.IGNORE_OLD_EQUIV);
new DrillCommand("onDrillDown", Command.IGNORE_OLD_EQUIV); new DrillCommand("onDrillDown", Command.IGNORE_OLD_EQUIV);
new TokenCommand(TokenEvent.ON_USER_TOKEN, Command.IGNORE_OLD_EQUIV);
} }
} }

View File

@ -0,0 +1,50 @@
/******************************************************************************
* Copyright (C) 2009 Low Heng Sin *
* Copyright (C) 2009 Idalica Corporation *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.component;
import org.adempiere.webui.event.TokenEvent;
import org.zkoss.lang.Objects;
import org.zkoss.zk.au.AuRequest;
import org.zkoss.zk.au.Command;
import org.zkoss.zk.mesg.MZk;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.event.Events;
/**
* Command class to handle user authentication token event
* @author hengsin
*
*/
public class TokenCommand extends Command {
public TokenCommand(String id, int flags) {
super(id, flags);
}
@Override
protected void process(AuRequest request) {
final String[] data = request.getData();
final Component comp = request.getComponent();
if (comp == null)
throw new UiException(MZk.ILLEGAL_REQUEST_COMPONENT_REQUIRED, this);
if (data == null || data.length < 2)
throw new UiException(MZk.ILLEGAL_REQUEST_WRONG_DATA, new Object[] {
Objects.toString(data), this });
Events.postEvent(new TokenEvent(getId(), comp, data));
}
}

View File

@ -0,0 +1,38 @@
/******************************************************************************
* Copyright (C) 2009 Low Heng Sin *
* Copyright (C) 2009 Idalica Corporation *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.event;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
/**
* Event for user authentication token
* @author hengsin
*
*/
public class TokenEvent extends Event {
/** on loading of user token **/
public final static String ON_USER_TOKEN = "onUserToken";
/**
* @param name
* @param target
* @param data
*/
public TokenEvent(String name, Component target, Object data) {
super(name, target, data);
}
}

View File

@ -1347,8 +1347,7 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
String msg = CLogger.retrieveErrorString(null); String msg = CLogger.retrieveErrorString(null);
if (msg != null) if (msg != null)
{ {
FDialog.error(curWindowNo, parent, null, msg); statusBar.setStatusLine(Msg.getMsg(Env.getCtx(), msg), true, true);
statusBar.setStatusLine(Msg.getMsg(Env.getCtx(), "SaveIgnored"), true, false);
} }
//other error will be catch in the dataStatusChanged event //other error will be catch in the dataStatusChanged event
} }

View File

@ -34,13 +34,17 @@ import org.adempiere.webui.component.ConfirmPanel;
import org.adempiere.webui.component.Label; import org.adempiere.webui.component.Label;
import org.adempiere.webui.component.Textbox; import org.adempiere.webui.component.Textbox;
import org.adempiere.webui.component.Window; import org.adempiere.webui.component.Window;
import org.adempiere.webui.event.TokenEvent;
import org.adempiere.webui.exception.ApplicationException; import org.adempiere.webui.exception.ApplicationException;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ITheme; import org.adempiere.webui.theme.ITheme;
import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.BrowserToken;
import org.adempiere.webui.util.UserPreference; import org.adempiere.webui.util.UserPreference;
import org.adempiere.webui.window.LoginWindow; import org.adempiere.webui.window.LoginWindow;
import org.compiere.Adempiere; import org.compiere.Adempiere;
import org.compiere.model.MSession;
import org.compiere.model.MUser;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.KeyNamePair; import org.compiere.util.KeyNamePair;
@ -63,6 +67,7 @@ import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.Clients; import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Comboitem; import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Image; import org.zkoss.zul.Image;
@ -79,7 +84,7 @@ public class LoginPanel extends Window implements EventListener
/** /**
* *
*/ */
private static final long serialVersionUID = -2243984359460922023L; private static final long serialVersionUID = 3992171368813030624L;
private static final String RESOURCE = "org.compiere.apps.ALoginRes"; private static final String RESOURCE = "org.compiere.apps.ALoginRes";
private ResourceBundle res = ResourceBundle.getBundle(RESOURCE); private ResourceBundle res = ResourceBundle.getBundle(RESOURCE);
@ -91,6 +96,7 @@ public class LoginPanel extends Window implements EventListener
private Textbox txtPassword; private Textbox txtPassword;
private Combobox lstLanguage; private Combobox lstLanguage;
private LoginWindow wndLogin; private LoginWindow wndLogin;
private Checkbox chkRememberMe;
public LoginPanel(Properties ctx, LoginWindow loginWindow) public LoginPanel(Properties ctx, LoginWindow loginWindow)
{ {
@ -102,6 +108,8 @@ public class LoginPanel extends Window implements EventListener
AuFocus auf = new AuFocus(txtUserId); AuFocus auf = new AuFocus(txtUserId);
Clients.response(auf); Clients.response(auf);
BrowserToken.load(this.getUuid());
} }
private void init() private void init()
@ -167,6 +175,18 @@ public class LoginPanel extends Window implements EventListener
tr.appendChild(td); tr.appendChild(td);
td.appendChild(lstLanguage); td.appendChild(lstLanguage);
tr = new Tr();
tr.setId("rowRememberMe");
table.appendChild(tr);
td = new Td();
tr.appendChild(td);
td.setSclass(ITheme.LOGIN_LABEL_CLASS);
td.appendChild(new Label(""));
td = new Td();
td.setSclass(ITheme.LOGIN_FIELD_CLASS);
tr.appendChild(td);
td.appendChild(chkRememberMe);
div = new Div(); div = new Div();
div.setSclass(ITheme.LOGIN_BOX_FOOTER_CLASS); div.setSclass(ITheme.LOGIN_BOX_FOOTER_CLASS);
ConfirmPanel pnlButtons = new ConfirmPanel(false); ConfirmPanel pnlButtons = new ConfirmPanel(false);
@ -176,6 +196,34 @@ public class LoginPanel extends Window implements EventListener
pnlButtons.getButton(ConfirmPanel.A_OK).setSclass(ITheme.LOGIN_BUTTON_CLASS); pnlButtons.getButton(ConfirmPanel.A_OK).setSclass(ITheme.LOGIN_BUTTON_CLASS);
div.appendChild(pnlButtons); div.appendChild(pnlButtons);
this.appendChild(div); this.appendChild(div);
this.addEventListener(TokenEvent.ON_USER_TOKEN, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
String[] data = (String[]) event.getData();
int AD_Session_ID = Integer.parseInt(data[0]);
MSession session = new MSession(Env.getCtx(), AD_Session_ID, null);
if (session.get_ID() == AD_Session_ID)
{
int AD_User_ID = session.getCreatedBy();
MUser user = MUser.get(Env.getCtx(), AD_User_ID);
if (user != null && user.get_ID() == AD_User_ID)
{
String token = data[1];
if (BrowserToken.validateToken(session, user, token))
{
txtUserId.setValue(user.getName());
onUserIdChange();
txtPassword.setValue(token);
txtPassword.setAttribute("user.token.hash", token);
txtPassword.setAttribute("user.token.sid", AD_Session_ID);
chkRememberMe.setChecked(true);
}
}
}
}
});
} }
private void initComponents() private void initComponents()
@ -203,7 +251,7 @@ public class LoginPanel extends Window implements EventListener
txtPassword.setId("txtPassword"); txtPassword.setId("txtPassword");
txtPassword.setType("password"); txtPassword.setType("password");
txtPassword.setCols(25); txtPassword.setCols(25);
txtPassword.setMaxlength(40); // txtPassword.setMaxlength(40);
txtPassword.setWidth("220px"); txtPassword.setWidth("220px");
lstLanguage = new Combobox(); lstLanguage = new Combobox();
@ -233,6 +281,9 @@ public class LoginPanel extends Window implements EventListener
break; break;
} }
} }
//TODO: localization
chkRememberMe = new Checkbox("Remember Me");
} }
public void onEvent(Event event) public void onEvent(Event event)
@ -255,32 +306,36 @@ public class LoginPanel extends Window implements EventListener
{ {
if(eventComp.getId().equals(txtUserId.getId())) if(eventComp.getId().equals(txtUserId.getId()))
{ {
String userId = txtUserId.getValue(); onUserIdChange();
if(userId != null && userId.length() > 0)
{
int AD_User_ID = DB.getSQLValue(null, "SELECT AD_User_ID FROM AD_User WHERE Name = ?", userId);
if(AD_User_ID > 0)
{
// Elaine 2009/02/06 Load preference from AD_Preference
UserPreference userPreference = SessionManager.getSessionApplication().loadUserPreference(AD_User_ID);
String initDefault = userPreference.getProperty(UserPreference.P_LANGUAGE);
for(int i = 0; i < lstLanguage.getItemCount(); i++)
{
Comboitem li = lstLanguage.getItemAtIndex(i);
if(li.getLabel().equals(initDefault))
{
lstLanguage.setSelectedIndex(i);
languageChanged(li.getLabel()); // Elaine 2009/04/17 language changed
break;
}
}
}
}
} }
} }
// //
} }
private void onUserIdChange() {
String userId = txtUserId.getValue();
if(userId != null && userId.length() > 0)
{
int AD_User_ID = DB.getSQLValue(null, "SELECT AD_User_ID FROM AD_User WHERE Name = ?", userId);
if(AD_User_ID > 0)
{
// Elaine 2009/02/06 Load preference from AD_Preference
UserPreference userPreference = SessionManager.getSessionApplication().loadUserPreference(AD_User_ID);
String initDefault = userPreference.getProperty(UserPreference.P_LANGUAGE);
for(int i = 0; i < lstLanguage.getItemCount(); i++)
{
Comboitem li = lstLanguage.getItemAtIndex(i);
if(li.getLabel().equals(initDefault))
{
lstLanguage.setSelectedIndex(i);
languageChanged(li.getLabel()); // Elaine 2009/04/17 language changed
break;
}
}
}
}
}
private void languageChanged(String langName) private void languageChanged(String langName)
{ {
Language language = findLanguage(langName); Language language = findLanguage(langName);
@ -309,6 +364,24 @@ public class LoginPanel extends Window implements EventListener
Login login = new Login(ctx); Login login = new Login(ctx);
String userId = txtUserId.getValue(); String userId = txtUserId.getValue();
String userPassword = txtPassword.getValue(); String userPassword = txtPassword.getValue();
//check is token
String token = (String) txtPassword.getAttribute("user.token.hash");
if (token != null && token.equals(userPassword))
{
userPassword = "";
int AD_Session_ID = (Integer)txtPassword.getAttribute("user.token.sid");
MSession session = new MSession(Env.getCtx(), AD_Session_ID, null);
if (session.get_ID() == AD_Session_ID)
{
MUser user = MUser.get(Env.getCtx(), session.getCreatedBy());
if (BrowserToken.validateToken(session, user, token))
{
userPassword = user.getPassword();
}
}
}
KeyNamePair rolesKNPairs[] = login.getRoles(userId, userPassword); KeyNamePair rolesKNPairs[] = login.getRoles(userId, userPassword);
if(rolesKNPairs == null || rolesKNPairs.length == 0) if(rolesKNPairs == null || rolesKNPairs.length == 0)
throw new WrongValueException("User Id or Password invalid!!!"); throw new WrongValueException("User Id or Password invalid!!!");
@ -348,6 +421,8 @@ public class LoginPanel extends Window implements EventListener
Session currSess = Executions.getCurrent().getDesktop().getSession(); Session currSess = Executions.getCurrent().getDesktop().getSession();
currSess.setAttribute("Check_AD_User_ID", Env.getAD_User_ID(ctx)); currSess.setAttribute("Check_AD_User_ID", Env.getAD_User_ID(ctx));
// End of temporary code for [ adempiere-ZK Web Client-2832968 ] User context lost? // End of temporary code for [ adempiere-ZK Web Client-2832968 ] User context lost?
Env.setContext(ctx, BrowserToken.REMEMBER_ME, chkRememberMe.isChecked());
} }
} }

View File

@ -0,0 +1,136 @@
/******************************************************************************
* Copyright (C) 2009 Low Heng Sin *
* Copyright (C) 2009 Idalica Corporation *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import org.compiere.Adempiere;
import org.compiere.model.MSession;
import org.compiere.model.MUser;
import org.compiere.util.CLogger;
import org.zkoss.zk.au.out.AuScript;
import org.zkoss.zk.ui.util.Clients;
import sun.misc.BASE64Encoder;
/**
* class to manage browser token for auto authentication
* @author hengsin
*
*/
public final class BrowserToken {
private final static CLogger log = CLogger.getCLogger(BrowserToken.class);
private BrowserToken() {}
public final static String REMEMBER_ME = "Login.RememberMe";
/**
* save session and user as client side token for future auto login
* @param session
* @param user
*/
public static void save(MSession session, MUser user) {
try
{
String home = getHomeToken();
String hash = getPasswordHash(session, user);
String script = "adempiere.saveUserToken('" + home + "', '" + hash + "', '" + session.getAD_Session_ID() + "');";
AuScript aus = new AuScript(null, script);
Clients.response("saveUserToken", aus);
}
catch (Exception e)
{
log.log(Level.WARNING, e.getLocalizedMessage(), e);
}
}
/**
* remove client side token for auto login
*/
public static void remove() {
try {
String home = getHomeToken();
String script = "adempiere.removeUserToken('" + home + "');";
AuScript aus = new AuScript(null, script);
Clients.response("removeUserToken", aus);
} catch (Exception e) {
log.log(Level.WARNING, e.getLocalizedMessage(), e);
}
}
/**
* load stored client side token for auto login
* @param cmpid
*/
public static void load(String cmpid) {
//remember me
try
{
String home = getHomeToken();
String script = "adempiere.findUserToken('" + cmpid + "', '" + home + "');";
AuScript aus = new AuScript(null, script);
Clients.response("findUserToken", aus);
}
catch (Exception e)
{
log.log(Level.WARNING, e.getLocalizedMessage(), e);
}
}
/**
* validate a stored client side token is valid
* @param session
* @param user
* @param token
* @return true if token is valid
*/
public static boolean validateToken(MSession session, MUser user, String token) {
try
{
String hash = getPasswordHash(session, user);
return hash.equals(token);
}
catch (Exception e)
{
log.log(Level.WARNING, e.getLocalizedMessage(), e);
}
return false;
}
private static String getHomeToken() throws UnsupportedEncodingException {
String home = Adempiere.getAdempiereHome();
BASE64Encoder encoder = new BASE64Encoder();
home = encoder.encode(home.getBytes("UTF-8"));
home = URLEncoder.encode(home, "UTF-8");
return home;
}
private static String getPasswordHash(MSession session, MUser user) throws UnsupportedEncodingException, NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
BASE64Encoder encoder = new BASE64Encoder();
digest.reset();
digest.update(session.getWebSession().getBytes("UTF-8"));
String password = user.getPassword();
byte[] input = digest.digest(password.getBytes("UTF-8"));
String hash = encoder.encode(input);
hash = URLEncoder.encode(hash, "UTF-8");
return hash;
}
}

68
zkwebui/js/persist-min.js vendored Normal file
View File

@ -0,0 +1,68 @@
(function(){if(window.google&&google.gears)
return;var F=null;if(typeof GearsFactory!='undefined'){F=new GearsFactory();}else{try{F=new ActiveXObject('Gears.Factory');if(F.getBuildInfo().indexOf('ie_mobile')!=-1)
F.privateSetGlobalObject(this);}catch(e){if((typeof navigator.mimeTypes!='undefined')&&navigator.mimeTypes["application/x-googlegears"]){F=document.createElement("object");F.style.display="none";F.width=0;F.height=0;F.type="application/x-googlegears";document.documentElement.appendChild(F);}}}
if(!F)
return;if(!window.google)
google={};if(!google.gears)
google.gears={factory:F};})();Persist=(function(){var VERSION='0.2.0',P,B,esc,init,empty,ec;ec=(function(){var EPOCH='Thu, 01-Jan-1970 00:00:01 GMT',RATIO=1000*60*60*24,KEYS=['expires','path','domain'],esc=escape,un=unescape,doc=document,me;var get_now=function(){var r=new Date();r.setTime(r.getTime());return r;}
var cookify=function(c_key,c_val){var i,key,val,r=[],opt=(arguments.length>2)?arguments[2]:{};r.push(esc(c_key)+'='+esc(c_val));for(i=0;i<KEYS.length;i++){key=KEYS[i];if(val=opt[key])
r.push(key+'='+val);}
if(opt.secure)
r.push('secure');return r.join('; ');}
var alive=function(){var k='__EC_TEST__',v=new Date();v=v.toGMTString();this.set(k,v);this.enabled=(this.remove(k)==v);return this.enabled;}
me={set:function(key,val){var opt=(arguments.length>2)?arguments[2]:{},now=get_now(),expire_at,cfg={};if(opt.expires){opt.expires*=RATIO;cfg.expires=new Date(now.getTime()+opt.expires);cfg.expires=cfg.expires.toGMTString();}
var keys=['path','domain','secure'];for(i=0;i<keys.length;i++)
if(opt[keys[i]])
cfg[keys[i]]=opt[keys[i]];var r=cookify(key,val,cfg);doc.cookie=r;return val;},has:function(key){key=esc(key);var c=doc.cookie,ofs=c.indexOf(key+'='),len=ofs+key.length+1,sub=c.substring(0,key.length);return((!ofs&&key!=sub)||ofs<0)?false:true;},get:function(key){key=esc(key);var c=doc.cookie,ofs=c.indexOf(key+'='),len=ofs+key.length+1,sub=c.substring(0,key.length),end;if((!ofs&&key!=sub)||ofs<0)
return null;end=c.indexOf(';',len);if(end<0)
end=c.length;return un(c.substring(len,end));},remove:function(k){var r=me.get(k),opt={expires:EPOCH};doc.cookie=cookify(k,'',opt);return r;},keys:function(){var c=doc.cookie,ps=c.split('; '),i,p,r=[];for(i=0;i<ps.length;i++){p=ps[i].split('=');r.push(un(p[0]));}
return r;},all:function(){var c=doc.cookie,ps=c.split('; '),i,p,r=[];for(i=0;i<ps.length;i++){p=ps[i].split('=');r.push([un(p[0]),un(p[1])]);}
return r;},version:'0.2.1',enabled:false};me.enabled=alive.call(me);return me;}());var index_of=(function(){if(Array.prototype.indexOf)
return function(ary,val){return Array.prototype.indexOf.call(ary,val);};else
return function(ary,val){var i,l;for(i=0,l=ary.length;i<l;i++)
if(ary[i]==val)
return i;return-1;};})();empty=function(){};esc=function(str){return'PS'+str.replace(/_/g,'__').replace(/ /g,'_s');};C={search_order:['localstorage','whatwg_db','globalstorage','gears','ie','flash','cookie'],name_re:/^[a-z][a-z0-9_ -]+$/i,methods:['init','get','set','remove','load','save'],sql:{version:'1',create:"CREATE TABLE IF NOT EXISTS persist_data (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)",get:"SELECT v FROM persist_data WHERE k = ?",set:"INSERT INTO persist_data(k, v) VALUES (?, ?)",remove:"DELETE FROM persist_data WHERE k = ?"},flash:{div_id:'_persist_flash_wrap',id:'_persist_flash',path:'persist.swf',size:{w:1,h:1},args:{autostart:true}}};B={gears:{size:-1,test:function(){return(window.google&&window.google.gears)?true:false;},methods:{transaction:function(fn){var db=this.db;db.execute('BEGIN').close();fn.call(this,db);db.execute('COMMIT').close();},init:function(){var db;db=this.db=google.gears.factory.create('beta.database');db.open(esc(this.name));db.execute(C.sql.create).close();},get:function(key,fn,scope){var r,sql=C.sql.get;if(!fn)
return;this.transaction(function(t){var is_valid,val;r=t.execute(sql,[key]);is_valid=r.isValidRow();val=is_valid?r.field(0):null;r.close();fn.call(scope||this,is_valid,val);});},set:function(key,val,fn,scope){var rm_sql=C.sql.remove,sql=C.sql.set,r;this.transaction(function(t){t.execute(rm_sql,[key]).close();t.execute(sql,[key,val]).close();if(fn)
fn.call(scope||this,true,val);});},remove:function(key,fn,scope){var get_sql=C.sql.get;sql=C.sql.remove,r,val=null,is_valid=false;this.transaction(function(t){if(fn){r=t.execute(get_sql,[key]);is_valid=r.isValidRow();val=is_valid?r.field(0):null;r.close();}
if(!fn||is_valid){t.execute(sql,[key]).close();}
if(fn)
fn.call(scope||this,is_valid,val);});}}},whatwg_db:{size:200*1024,test:function(){var name='PersistJS Test',desc='Persistent database test.';if(!window.openDatabase)
return false;if(!window.openDatabase(name,C.sql.version,desc,B.whatwg_db.size))
return false;return true;},methods:{transaction:function(fn){if(!this.db_created){this.db.transaction(function(t){t.executeSql(C.sql.create,[],function(){this.db_created=true;});},empty);}
this.db.transaction(fn);},init:function(){this.db=openDatabase(this.name,C.sql.version,this.o.about||("Persistent storage for "+this.name),this.o.size||B.whatwg_db.size);},get:function(key,fn,scope){var sql=C.sql.get;if(!fn)
return;scope=scope||this;this.transaction(function(t){t.executeSql(sql,[key],function(t,r){if(r.rows.length>0)
fn.call(scope,true,r.rows.item(0)['v']);else
fn.call(scope,false,null);});});},set:function(key,val,fn,scope){var rm_sql=C.sql.remove,sql=C.sql.set;this.transaction(function(t){t.executeSql(rm_sql,[key],function(){t.executeSql(sql,[key,val],function(t,r){if(fn)
fn.call(scope||this,true,val);});});});return val;},remove:function(key,fn,scope){var get_sql=C.sql.get;sql=C.sql.remove;this.transaction(function(t){if(fn){t.executeSql(get_sql,[key],function(t,r){if(r.rows.length>0){var val=r.rows.item(0)['v'];t.executeSql(sql,[key],function(t,r){fn.call(scope||this,true,val);});}else{fn.call(scope||this,false,null);}});}else{t.executeSql(sql,[key]);}});}}},globalstorage:{size:5*1024*1024,test:function(){return window.globalStorage?true:false;},methods:{key:function(key){return esc(this.name)+esc(key);},init:function(){alert('domain = '+this.o.domain);this.store=globalStorage[this.o.domain];},get:function(key,fn,scope){key=this.key(key);if(fn)
fn.call(scope||this,true,this.store.getItem(key));},set:function(key,val,fn,scope){key=this.key(key);this.store.setItem(key,val);if(fn)
fn.call(scope||this,true,val);},remove:function(key,fn,scope){var val;key=this.key(key);val=this.store[key];this.store.removeItem(key);if(fn)
fn.call(scope||this,(val!==null),val);}}},localstorage:{size:-1,test:function(){return window.localStorage?true:false;},methods:{key:function(key){return esc(this.name)+esc(key);},init:function(){this.store=localStorage;},get:function(key,fn,scope){key=this.key(key);if(fn)
fn.call(scope||this,true,this.store.getItem(key));},set:function(key,val,fn,scope){key=this.key(key);this.store.setItem(key,val);if(fn)
fn.call(scope||this,true,val);},remove:function(key,fn,scope){var val;key=this.key(key);val=this.getItem(key);this.store.removeItem(key);if(fn)
fn.call(scope||this,(val!==null),val);}}},ie:{prefix:'_persist_data-',size:64*1024,test:function(){return window.ActiveXObject?true:false;},make_userdata:function(id){var el=document.createElement('div');el.id=id;el.style.display='none';el.addBehavior('#default#userdata');document.body.appendChild(el);return el;},methods:{init:function(){var id=B.ie.prefix+esc(this.name);this.el=B.ie.make_userdata(id);if(this.o.defer)
this.load();},get:function(key,fn,scope){var val;key=esc(key);if(!this.o.defer)
this.load();val=this.el.getAttribute(key);if(fn)
fn.call(scope||this,val?true:false,val);},set:function(key,val,fn,scope){key=esc(key);this.el.setAttribute(key,val);if(!this.o.defer)
this.save();if(fn)
fn.call(scope||this,true,val);},remove:function(key,fn,scope){var val;key=esc(key);if(!this.o.defer)
this.load();val=this.el.getAttribute(key);this.el.removeAttribute(key);if(!this.o.defer)
this.save();if(fn)
fn.call(scope||this,val?true:false,val);},load:function(){this.el.load(esc(this.name));},save:function(){this.el.save(esc(this.name));}}},cookie:{delim:':',size:4000,test:function(){return P.Cookie.enabled?true:false;},methods:{key:function(key){return this.name+B.cookie.delim+key;},get:function(key,fn,scope){var val;key=this.key(key);val=ec.get(key);if(fn)
fn.call(scope||this,val!=null,val);},set:function(key,val,fn,scope){key=this.key(key);ec.set(key,val,this.o);if(fn)
fn.call(scope||this,true,val);},remove:function(key,fn,scope){var val;key=this.key(key);val=ec.remove(key)
if(fn)
fn.call(scope||this,val!=null,val);}}},flash:{test:function(){if(typeof deconcept=="undefined"||!deconcept||!deconcept.SWFObjectUtil)
return false;var major=deconcept.SWFObjectUtil.getPlayerVersion().major;return(major>=8)?true:false;},methods:{init:function(){if(!B.flash.el){var o,key,el,cfg=C.flash;el=document.createElement('div');el.id=cfg.div_id;document.body.appendChild(el);o=new deconcept.SWFObject(this.o.swf_path||cfg.path,cfg.id,cfg.size.w,cfg.size.h,'8');for(key in cfg.args)
o.addVariable(key,cfg.args[key]);o.write(el);B.flash.el=document.getElementById(cfg.id);}
this.el=B.flash.el;},get:function(key,fn,scope){var val;key=esc(key);val=this.el.get(this.name,key);if(fn)
fn.call(scope||this,val!==null,val);},set:function(key,val,fn,scope){var old_val;key=esc(key);old_val=this.el.set(this.name,key,val);if(fn)
fn.call(scope||this,true,val);},remove:function(key,fn,scope){var val;key=esc(key);val=this.el.remove(this.name,key);if(fn)
fn.call(scope||this,true,val);}}}};var init=function(){var i,l,b,key,fns=C.methods,keys=C.search_order;for(i=0,l=fns.length;i<l;i++)
P.Store.prototype[fns[i]]=empty;P.type=null;P.size=-1;for(i=0,l=keys.length;!P.type&&i<l;i++){b=B[keys[i]];if(b.test()){P.type=keys[i];P.size=b.size;for(key in b.methods)
P.Store.prototype[key]=b.methods[key];}}
P._init=true;};P={VERSION:VERSION,type:null,size:0,add:function(o){B[o.id]=o;C.search_order=[o.id].concat(C.search_order);init();},remove:function(id){var ofs=index_of(C.search_order,id);if(ofs<0)
return;C.search_order.splice(ofs,1);delete B[id];init();},Cookie:ec,Store:function(name,o){if(!C.name_re.exec(name))
throw new Error("Invalid name");if(!P.type)
throw new Error("No suitable storage found");o=o||{};this.name=name;o.domain=o.domain||location.host||'localhost';o.domain=o.domain.replace(/:\d+$/,'')
this.o=o;o.expires=o.expires||365*2;o.path=o.path||'/';this.init();}};init();return P;})();

53
zkwebui/js/token.js Normal file
View File

@ -0,0 +1,53 @@
/******************************************************************************
* Copyright (C) 2009 Low Heng Sin *
* Copyright (C) 2009 Idalica Corporation *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
var adempiere = {};
adempiere.store = new Persist.Store('UserToken');
adempiere.saveUserToken = function (key, hash, sessionId)
{
adempiere.store.o.expires = 365;
adempiere.store.set(key+".sid", sessionId);
adempiere.store.o.expires = 365;
adempiere.store.set(key+".hash", hash);
}
adempiere.findUserToken = function (cmpid, key)
{
var sid;
var fsid = function(ok, val) {
if (ok && !!val && !!sid)
{
var hash = val;
zkau.send({uuid: cmpid, cmd: 'onUserToken', data: [sid, hash], ctl: true});
}
};
var fhash = function(ok, val) {
if (ok && !!val)
{
sid = val;
adempiere.store.get(key+".hash", fsid);
}
};
adempiere.store.get(key+".sid", fhash);
}
adempiere.removeUserToken = function (key)
{
adempiere.store.o.expires = -365;
adempiere.store.set(key+".sid", "");
adempiere.store.o.expires = -365;
adempiere.store.set(key+".hash", "");
}