0

Spring Security

asked 2008-10-28 19:33:40 +0800

ganjaryn gravatar image ganjaryn
18 1

Hi

I'm trying to configure ZK (3.5.1) with Spring Security (2.0.4) on Tomcat 6 following steps described in SmallTalk. I get following exceptions after succesfull login.

SEVERE: Servlet.service() for servlet zkLoader threw exception
java.lang.IllegalStateException: Recover an invalidated session, org.zkoss.zk.ui.http.SimpleSession@de26e52
at org.zkoss.zk.ui.http.SimpleSession.recover(SimpleSession.java:354)
at org.zkoss.zk.ui.sys.SessionsCtrl.getSession(SessionsCtrl.java:92)
at org.zkoss.zk.ui.http.WebManager.getSession(WebManager.java:287)
at org.zkoss.zk.ui.http.WebManager.getSession(WebManager.java:269)
at org.zkoss.zk.ui.http.DHtmlLayoutServlet.doGet(DHtmlLayoutServlet.java:157)
at javax.servlet.http.HttpServlet.service(Unknown Source)
at javax.servlet.http.HttpServlet.service(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(Unknown Source)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.providers.anonymous.AnonymousProcessingFilter.doFilterHttp(AnonymousProcessingFilter.java:105)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.rememberme.RememberMeProcessingFilter.doFilterHttp(RememberMeProcessingFilter.java:116)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.basicauth.BasicProcessingFilter.doFilterHttp(BasicProcessingFilter.java:174)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:277)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(Unknown Source)
at org.apache.catalina.core.StandardWrapperValve.invoke(Unknown Source)
at org.apache.catalina.core.StandardContextValve.invoke(Unknown Source)
at org.apache.catalina.core.StandardHostValve.invoke(Unknown Source)
at org.apache.catalina.valves.ErrorReportValve.invoke(Unknown Source)
at org.apache.catalina.core.StandardEngineValve.invoke(Unknown Source)
at org.apache.catalina.connector.CoyoteAdapter.service(Unknown Source)
at org.apache.coyote.http11.Http11AprProcessor.process(Unknown Source)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Unknown Source)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(Unknown Source)
at java.lang.Thread.run(Thread.java:619)
2008-10-28 20:14:56 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet auEngine threw exception
java.lang.IllegalStateException: Recover an invalidated session, org.zkoss.zk.ui.http.SimpleSession@de26e52
at org.zkoss.zk.ui.http.SimpleSession.recover(SimpleSession.java:354)
at org.zkoss.zk.ui.sys.SessionsCtrl.getSession(SessionsCtrl.java:92)
at org.zkoss.zk.ui.http.WebManager.getSession(WebManager.java:287)
at org.zkoss.zk.ui.http.WebManager.getSession(WebManager.java:282)
at org.zkoss.zk.au.http.DHtmlUpdateServlet.doGet(DHtmlUpdateServlet.java:319)
at org.zkoss.zk.au.http.DHtmlUpdateServlet.doPost(DHtmlUpdateServlet.java:379)
at javax.servlet.http.HttpServlet.service(Unknown Source)
at javax.servlet.http.HttpServlet.service(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(Unknown Source)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.providers.anonymous.AnonymousProcessingFilter.doFilterHttp(AnonymousProcessingFilter.java:105)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.rememberme.RememberMeProcessingFilter.doFilterHttp(RememberMeProcessingFilter.java:116)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.basicauth.BasicProcessingFilter.doFilterHttp(BasicProcessingFilter.java:174)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:277)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(Unknown Source)
at org.apache.catalina.core.StandardWrapperValve.invoke(Unknown Source)
at org.apache.catalina.core.StandardContextValve.invoke(Unknown Source)
at org.apache.catalina.core.StandardHostValve.invoke(Unknown Source)
at org.apache.catalina.valves.ErrorReportValve.invoke(Unknown Source)
at org.apache.catalina.core.StandardEngineValve.invoke(Unknown Source)
at org.apache.catalina.connector.CoyoteAdapter.service(Unknown Source)
at org.apache.coyote.http11.Http11AprProcessor.process(Unknown Source)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Unknown Source)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(Unknown Source)
at java.lang.Thread.run(Thread.java:619)

Regards
Daniel

delete flag offensive retag edit

4 Replies

Sort by ยป oldest newest

answered 2008-10-30 20:32:41 +0800

petr5250 gravatar image petr5250
15

updated 2008-11-01 09:28:33 +0800

Hi,
I have exactly same problem.

First page (login page) is loaded normally. If the login is unsuccessful login page is reloaded normally, but after successful login I can't load any other page (not even login page).

Can anyone help?


Regards
Petr

link publish delete flag offensive edit

answered 2008-11-01 06:23:56 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

Would you provide sample codes and the procedures to replicate this issue? Thanks.

link publish delete flag offensive edit

answered 2008-11-01 10:01:39 +0800

petr5250 gravatar image petr5250
15

Hi,
here is my code:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/applicationContext-security.xml
		</param-value>
	</context-param>

	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


	<listener>
		<description>
			Used to cleanup when a session is destroyed
		</description>
		<display-name>ZK Session Cleaner</display-name>
		<listener-class>
			org.zkoss.zk.ui.http.HttpSessionListener
		</listener-class>
	</listener>

	<listener>
		<listener-class>
			org.springframework.web.util.Log4jConfigListener
		</listener-class>
	</listener>

	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

	<listener>
		<listener-class>
			org.springframework.security.ui.session.HttpSessionEventPublisher
		</listener-class>
	</listener>

	<listener>
		<listener-class>
			org.springframework.web.context.request.RequestContextListener
		</listener-class>
	</listener>

	<servlet>
		<description>ZK loader for ZUML pages</description>
		<servlet-name>zkLoader</servlet-name>
		<servlet-class>
			org.zkoss.zk.ui.http.DHtmlLayoutServlet
		</servlet-class>
		<!-- Must. Specifies URI of the update engine (DHtmlUpdateServlet).
			It must be the same as <url-pattern> for the update engine.
		-->
		<init-param>
			<param-name>update-uri</param-name>
			<param-value>/zkau</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet>
		<description>The asynchronous update engine for ZK</description>
		<servlet-name>auEngine</servlet-name>
		<servlet-class>
			org.zkoss.zk.au.http.DHtmlUpdateServlet
		</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>zkLoader</servlet-name>
		<url-pattern>*.zul</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>zkLoader</servlet-name>
		<url-pattern>*.zhtml</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>auEngine</servlet-name>
		<url-pattern>/zkau/*</url-pattern>
	</servlet-mapping>

	<!-- //// -->
	<!-- MIME mapping -->
	<mime-mapping>
		<extension>gif</extension>
		<mime-type>image/gif</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>html</extension>
		<mime-type>text/html</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>htm</extension>
		<mime-type>text/html</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>jpeg</extension>
		<mime-type>image/jpeg</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>jpg</extension>
		<mime-type>image/jpeg</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>js</extension>
		<mime-type>application/x-javascript</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>png</extension>
		<mime-type>image/png</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>txt</extension>
		<mime-type>text/plain</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>xml</extension>
		<mime-type>text/xml</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>zhtml</extension>
		<mime-type>text/html</mime-type>
	</mime-mapping>

	<mime-mapping>
		<extension>zul</extension>
		<mime-type>text/html</mime-type>
	</mime-mapping>

	<welcome-file-list>
		<welcome-file>index.zul</welcome-file>
		<welcome-file>index.zhtml</welcome-file>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
	</welcome-file-list>
</web-app>

zk.xml:

<?xml version="1.0" encoding="UTF-8"?>
<zk>
	<listener>
		<description>ThreadLocal Synchronization Listener</description>
		<listener-class>
			org.zkoss.zkplus.util.ThreadLocalListener
		</listener-class>
	</listener>

	<preference>
		<name>ThreadLocal</name>
		<value>
			org.springframework.security.context.ThreadLocalSecurityContextHolderStrategy=contextHolder
		</value>
	</preference>

	<log>
		<log-base>org.zkoss</log-base>
	</log>

	<client-config>
		<error-reload>
			<error-code>301</error-code>
			<reload-uri>/login.zul</reload-uri>
		</error-reload>
		<error-reload>
			<error-code>403</error-code>
			<reload-uri>/login.zul</reload-uri>
		</error-reload>
		<error-reload>
			<error-code>404</error-code>
			<reload-uri>/login.zul</reload-uri>
		</error-reload>
	</client-config>

	<session-config>
		<session-timeout>3600</session-timeout>
		<timer-as-inactive>true</timer-as-inactive>
	</session-config>
	
	<device-config>
		<device-type>ajax</device-type>
		<timeout-uri>/login.zul</timeout-uri>
	</device-config>
</zk>

applicationContext-security.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">

	<global-method-security secured-annotations="enabled">
	</global-method-security>
	
    <http auto-config="true">
        <intercept-url pattern="/login.zul*" access="ROLE_ANONYMOUS" requires-channel="https"/>
        <intercept-url pattern="/*.zul" access="ROLE_USER" requires-channel="https"/>
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>

		<form-login authentication-failure-url="/login.zul?error=1" login-page="/login.zul" default-target-url="/" always-use-default-target="true" />
		<anonymous granted-authority="ROLE_ANONYMOUS" key="anonymous" username="anonymousUser"/>
		<logout invalidate-session="false" logout-success-url="/login.zul" logout-url="/logout.zul"/>
		<remember-me key="superSecretKey" />
    </http>
    
    <!--
    Usernames/Passwords are
        rod/koala
        dianne/emu
        scott/wombat
        peter/opal
    -->
    <authentication-provider>
        <password-encoder hash="md5"/>
        <user-service>
            <user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
	        <user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" />
            <user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a" authorities="ROLE_USER" />
            <user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_USER" />
	    </user-service>
	</authentication-provider>
</beans:beans>

login.zul:

<?xml version="1.0" encoding="utf-8"?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>

<zk xmlns="http://www.zkoss.org/2005/zul"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
	http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd"
	xmlns:h="http://www.w3.org/1999/xhtml">

	<window id="loginWindow" border="normal"
		title="Login Window" width="350px"
		use="LoginWindow">
		<h:form id="loginForm" action="j_spring_security_check" style="margin: 0px;">
			<grid>
				<columns height="0px" style="height: 0px;">
					<column width="40%" />
					<column width="60%" />
				</columns>
				<rows>
					<row>
						<label value="Username:" />
						<textbox id="uiTextboxUsername"
							name="j_username" value="${sessionScope.username}"
							constraint="no empty" width="95%" />
					</row>
					<row>
						<label value="Password:" />
						<textbox id="uiTextboxPassword"
							name="j_password" type="password" constraint="no empty"
							width="95%" />
					</row>
					<row>
						<button label="Login" forward="onOK" />
					</row>
				</rows>
			</grid>
		</h:form>
	</window>
</zk>

LoginWindow.java:

import org.zkoss.zhtml.Form;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.ext.AfterCompose;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

public class LoginWindow extends Window implements AfterCompose {

	static final long serialVersionUID = 0x1;

	private Textbox uiTextboxUsername;

	private Textbox uiTextboxPassword;

	private Form loginForm;
	
	public void afterCompose() {
        //wire variables
        Components.wireVariables(this, this);
        
        //auto forward
        Components.addForwards(this, this);
    }

	public Textbox getUiTextboxUsername() {
		return uiTextboxUsername;
	}

	public Textbox getUiTextboxPassword() {
		return uiTextboxPassword;
	}

	public Form getLoginForm() {
		return loginForm;
	}
	
	public void onOK(Event evt) {
        doLogin();        
    }

	public void doLogin() {
		// submit the form
		Clients.submitForm(getLoginForm());
		
		Sessions.getCurrent().setAttribute("username",
				uiTextboxUsername.getValue());
	}
}

index.zul:

<?xml version="1.0" encoding="utf-8" ?>

<zk xmlns="http://www.zkoss.org/2005/zul"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
	http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd">
	
	<label value="You are in."/>
</zk>

Thrown exception is same as in the first post.

I'm using ZK 3.5.1 and Spring Security 2.0.4.

Regards
Petr

link publish delete flag offensive edit

answered 2008-11-04 01:40:36 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

ZK think you are login with an "already invalidated session" and complains. We have lift the bug to be only a warning. You might have to wait for ZK 3.5.2 or use Freshly version.

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2008-10-28 19:33:40 +0800

Seen: 784 times

Last updated: Nov 04 '08

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More