package com.bao.lc.site.s3.commands; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.chain.Context; import org.apache.commons.collections.MapUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.client.methods.HttpUriRequest; import org.htmlparser.Node; import org.htmlparser.NodeFilter; import org.htmlparser.Parser; import org.htmlparser.filters.AndFilter; import org.htmlparser.filters.HasAttributeFilter; import org.htmlparser.filters.NodeClassFilter; import org.htmlparser.filters.OrFilter; import org.htmlparser.tags.FormTag; import org.htmlparser.tags.ImageTag; import org.htmlparser.tags.InputTag; import org.htmlparser.util.NodeList; import org.htmlparser.util.ParserException; import com.bao.lc.ResMgr; import com.bao.lc.bean.IDValuePair; import com.bao.lc.bean.ResultCode; import com.bao.lc.client.RequestBuilder; import com.bao.lc.httpcommand.AbstractCommand; import com.bao.lc.httpcommand.params.HttpCommandPNames; import com.bao.lc.httpcommand.params.HttpCommandParams; import com.bao.lc.site.RandCodeBuilder; import com.bao.lc.site.s3.gui.GUIUtils; import com.bao.lc.site.s3.params.TdPNames; import com.bao.lc.site.s3.params.TdParams; import com.bao.lc.util.MiscUtils; public class ParseLoginPage extends AbstractCommand { private static Log log = LogFactory.getLog(ParseLoginPage.class); private FormTag loginForm = null; private ImageTag vCodeImage = null; public ParseLoginPage() { reset(); } private void reset() { loginForm = null; vCodeImage = null; } @Override protected IDValuePair preExecute(Context context) throws Exception { return ResultCode.RC_OK; } @Override protected IDValuePair doExecute(Context context) throws Exception { return ResultCode.RC_OK; } @Override protected IDValuePair postExecute(Context context) throws Exception { String content = MapUtils.getString(context, TdPNames._LOGIN_PAGE_CONTENT); if(content == null) { log.error("content is null."); return ResultCode.RC_NULL_PARAMETER; } String encoding = MapUtils.getString(context, TdPNames._LOGIN_PAGE_ENCODING); if(encoding == null) { log.error("encoding is null."); return ResultCode.RC_NULL_PARAMETER; } // 1. parse content parseContent(context, content, encoding); // 2. Verification Code String vCode = MapUtils.getString(context, TdPNames._LOGIN_VOCDE); if(vCode == null) { vCode = getVerificationCode(context, this.vCodeImage.extractImageLocn()); if(vCode == null) { TdParams.getUI(context).info(ResMgr.getString("td.msg.vcode.input.null")); return ResultCode.RC_INPUT_NULL_VCODE; } } // 3. Get all input parameters Map<String, String> params = new HashMap<String, String>(); getInputParameters(context, vCode, this.loginForm, params); // 4. create next hop String location = this.loginForm.getFormLocation(); URI baseURI = HttpCommandParams.getTargetRequestURI(context); if(baseURI == null) { throw new ParserException("Assert failure. baseURI is null."); } // Create request of the next hop RequestBuilder rb = new RequestBuilder(); rb.method(this.loginForm.getFormMethod()).baseURI(baseURI).reference(location); rb.paramMap(params).encoding(encoding); HttpUriRequest nextRequest = rb.create(); // done context.put(HttpCommandPNames.TARGET_REQUEST, nextRequest); context.put(HttpCommandPNames.TARGET_REFERER, baseURI.toString()); return ResultCode.RC_OK; } protected void parseContent(Context context, String content, String charset) throws ParserException { // 2. Create parser to parse the content Parser parser = MiscUtils.createParser(content, charset, log); // Set filters List<NodeFilter> predicates = new ArrayList<NodeFilter>(3); NodeFilter[] a = new NodeFilter[0]; // 1. login form filters predicates.add(new HasAttributeFilter("id", "loginForm")); predicates.add(new HasAttributeFilter("name", "loginForm")); predicates.add(new NodeClassFilter(FormTag.class)); NodeFilter loginFormFilter = new AndFilter(predicates.toArray(a)); // 2. verification code source filters predicates.clear(); predicates.add(new HasAttributeFilter("id", "img_rrand_code")); predicates.add(new NodeClassFilter(ImageTag.class)); NodeFilter vCodeSrcFilter = new AndFilter(predicates.toArray(a)); predicates.clear(); NodeFilter finalFilter = new OrFilter(loginFormFilter, vCodeSrcFilter); // parse NodeList nodeList = parser.parse(finalFilter); // Validation for(int i = 0, size = nodeList.size(); i < size; i++) { Node node = nodeList.elementAt(i); if(node instanceof FormTag) { this.loginForm = (FormTag) node; } else if(node instanceof ImageTag) { this.vCodeImage = (ImageTag) node; } } if(this.loginForm == null || this.vCodeImage == null) { throw new ParserException("loginForm or(and) vCodeImage doesn't exist. loginForm=" + this.loginForm + ", vCodeImage=" + this.vCodeImage); } } private void getInputParameters(Context context, String vCode, FormTag loginForm, Map<String, String> params) { NodeList inputList = loginForm.getFormInputs(); for(int i = 0, size = inputList.size(); i < size; i++) { InputTag input = (InputTag) inputList.elementAt(i); String name = input.getAttribute("name"); String value = input.getAttribute("value"); if(name.equals("loginUser.user_name")) { value = MapUtils.getString(context, TdPNames.PARAM_USER); } else if(name.equals("user.password")) { value = MapUtils.getString(context, TdPNames.PARAM_PASSWORD); } else if(name.equals("randCode")) { value = vCode; } params.put(name, value); } } private String getVerificationCode(Context context, String vCodeLocation) throws Exception { URI baseURI = HttpCommandParams.getTargetRequestURI(context); boolean isFirstLogin = MapUtils.getBooleanValue(context, TdPNames._IS_FIRST_LOGIN, true); if(!isFirstLogin) { vCodeLocation += "&" + MiscUtils.randJS(); } // Create request of the next hop RequestBuilder rb = new RequestBuilder(); rb.baseURI(baseURI).reference(vCodeLocation); HttpUriRequest nextRequest = rb.create(); // Do execute GetVerificationCode RandCodeBuilder rcb = new RandCodeBuilder(); rcb.context(context).request(nextRequest).referer(baseURI.toString()); rcb.prompt(ResMgr.getString("td.rand.code.input")).parent(GUIUtils.getMainFrame()); String vCode = rcb.build(); context.put(TdPNames._LOGIN_VOCDE, vCode); return vCode; } }