/**
 * $Author: tanmf $
 * $Rev: 50965 $
 * $Date:: 2015-07-30 09:49:55 +#$:
 *
 * Copyright (C) 2012 Seeyon, Inc. All rights reserved.
 *
 * This software is the proprietary information of Seeyon, Inc.
 * Use is subject to license terms.
 */
package com.seeyon.ctp.portal.sso.thirdpartyintegration.controller;

import com.seeyon.apps.addressbook.manager.AddressBookCustomerFieldInfoManager;
import com.seeyon.apps.addressbook.po.AddressBook;
import com.seeyon.ctp.common.file.model.CtpLocalFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.seeyon.apps.cip.portal.dynamic.CipAppLinkDynamicAction;
import com.seeyon.ctp.link.biz.ShortChainInterface;
import com.seeyon.ctp.login.online.LoginOpt;
import com.seeyon.ctp.util.annotation.Inject;
import com.seeyon.infra.spring_sdk_core.DynamicContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import com.seeyon.apps.cip.api.portal.ThirdpartySpaceManagerApi;
import com.seeyon.apps.cip.custom.manager.CipCustomTaskManager;
import com.seeyon.apps.cip.util.CIPUtil;
import com.seeyon.apps.ldap.config.LDAPConfig;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.GlobalNames;
import com.seeyon.ctp.common.ServerState;
import com.seeyon.ctp.common.SystemEnvironment;
import com.seeyon.ctp.common.authenticate.LockLoginInfoFactory;
import com.seeyon.ctp.common.authenticate.domain.User;
import com.seeyon.ctp.common.authenticate.domain.UserHelper;
import com.seeyon.ctp.common.authenticate.sso.SSOTicketManager;
import com.seeyon.ctp.common.authenticate.sso.SSOTicketManager.TicketInfo;
import com.seeyon.ctp.common.config.IConfigPublicKey;
import com.seeyon.ctp.common.config.SystemConfig;
import com.seeyon.ctp.common.config.manager.ConfigManager;
import com.seeyon.ctp.common.constants.Constants;
import com.seeyon.ctp.common.constants.Constants.login_useragent_from;
import com.seeyon.ctp.common.constants.LoginConstants;
import com.seeyon.ctp.common.constants.LoginResult;
import com.seeyon.ctp.common.constants.ProductEditionEnum;
import com.seeyon.ctp.common.constants.SystemProperties;
import com.seeyon.ctp.common.controller.BaseController;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.exceptions.InfrastructureException;
import com.seeyon.ctp.common.flag.BrowserEnum;
import com.seeyon.ctp.common.flag.SysFlag;
import com.seeyon.ctp.common.i18n.LocaleContext;
import com.seeyon.ctp.common.i18n.ResourceUtil;
import com.seeyon.ctp.common.init.MclclzUtil;
import com.seeyon.ctp.common.po.config.ConfigItem;
import com.seeyon.ctp.common.po.usermessage.UserHistoryMessage;
import com.seeyon.ctp.common.security.SecurityHelper;
import com.seeyon.ctp.common.taglibs.functions.Functions;
import com.seeyon.ctp.common.thirdparty.ThirdpartyTicketManager;
import com.seeyon.ctp.common.usermessage.UserMessageManager;
import com.seeyon.ctp.common.usermessage.UserMessageUtil;
import com.seeyon.ctp.common.web.filter.CTPCsrfGuard;
import com.seeyon.ctp.login.LoginActiveX;
import com.seeyon.ctp.login.LoginControl;
import com.seeyon.ctp.login.UserUtil;
import com.seeyon.ctp.login.online.OnlineManager;
import com.seeyon.ctp.login.online.OnlineRecorder;
import com.seeyon.ctp.login.online.OnlineUser;
import com.seeyon.ctp.organization.OrgConstants;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.ctp.organization.manager.OrgManagerDirect;
import com.seeyon.ctp.portal.api.PortalApi;
import com.seeyon.ctp.portal.po.PortalHotspot;
import com.seeyon.ctp.portal.po.PortalLoginTemplate;
import com.seeyon.ctp.portal.po.PortalTemplateSetting;
import com.seeyon.ctp.portal.sso.SSOTicketBean;
import com.seeyon.ctp.portal.sso.thirdpartyintegration.ThirdpartySpace;
import com.seeyon.ctp.privilege.manager.PrivilegeMenuManager;
import com.seeyon.ctp.services.security.ServiceManager;
import com.seeyon.ctp.util.BeanUtils;
import com.seeyon.ctp.util.Cookies;
import com.seeyon.ctp.util.DateUtil;
import com.seeyon.ctp.util.LightWeightEncoder;
import com.seeyon.ctp.util.Strings;
import com.seeyon.ctp.util.UUIDLong;
import com.seeyon.ctp.util.annotation.NeedlessCheckLogin;
import com.seeyon.ctp.util.annotation.SetContentType;
import com.seeyon.ctp.util.json.JSONUtil;
import com.seeyon.v3x.mail.manager.MessageMailManager;

/**
 * <p>Title: A8单点登录第三方系统控制器</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2012</p>
 * <p>Company: seeyon.com</p>
 * @since CTP2.0
 */
public class ThirdpartyController extends BaseController {

	private static final Log log = LogFactory.getLog(ThirdpartyController.class);

	private OrgManager orgManager;

	private OrgManagerDirect orgManagerDirect;
	@Inject
	private AddressBookCustomerFieldInfoManager addressBookCustomerFieldInfoManager;

	private MessageMailManager messageMailManager;

	private PrivilegeMenuManager privilegeMenuManager;
	
	private OnlineManager onlineManager;
	
	private UserMessageManager userMessageManager;
	private CipCustomTaskManager cipCustomTaskManager;


	private static Object isExceedMaxLoginNumberLock = new Object();
	
	private PortalApi portalApi;
	
	private LoginControl  loginControl;

    private SystemConfig systemConfig;
    
    private ConfigManager configManager;
    
    private static final int expiry = 60 * 60 * 24 * 1;
	
	//不需要做集群
	private static Map<String, Integer> VlinkeParamMap ;
	private ThirdpartySpaceManagerApi thirdpartySpaceManagerApi;
	@Inject
	private DynamicContext dynamicContext;
	private CipAppLinkDynamicAction cipAppLinkDynamicAction = null;
	public void setOrgManager(OrgManager orgManager) {
		this.orgManager = orgManager;
	}

	public void setOrgManagerDirect(OrgManagerDirect orgManagerDirect) {
		this.orgManagerDirect = orgManagerDirect;
	}

	public void setMessageMailManager(MessageMailManager messageMailManager) {
		this.messageMailManager = messageMailManager;
	}

	public void setOnlineManager(OnlineManager onlineManager) {
        this.onlineManager = onlineManager;
    }

    public void setUserMessageManager(UserMessageManager userMessageManager) {
        this.userMessageManager = userMessageManager;
    }
    
    public void setPortalApi(PortalApi portalApi) {
		this.portalApi = portalApi;
	}

	public void setLoginControl(LoginControl loginControl) {
		this.loginControl = loginControl;
	}

	public void setSystemConfig(SystemConfig systemConfig) {
		this.systemConfig = systemConfig;
	}

	public void setConfigManager(ConfigManager configManager) {
		this.configManager = configManager;
	}
	private ShortChainInterface shortChainInterface;
	public void setShortChainInterface(ShortChainInterface shortChainInterface) {
		this.shortChainInterface = shortChainInterface;
	}
	/**
	 * 注入扩展接口实现
	 */
	@PostConstruct
	public void initialize() {
		cipAppLinkDynamicAction = dynamicContext.getBean(CipAppLinkDynamicAction.class);
	}
	
    static {
	    //V参数安全校验
	    VlinkeParamMap = new HashMap<String, Integer>();
	    VlinkeParamMap.put("message.link.office.assetN.audit", 0);
	    VlinkeParamMap.put("message.link.office.assetN.view", 0);
	    VlinkeParamMap.put("message.link.office.autoN.audit", 0);
	    VlinkeParamMap.put("message.link.office.autoN.view", 0);
	    VlinkeParamMap.put("message.link.office.bookN.audit", 0);
	    VlinkeParamMap.put("message.link.office.bookN.lended", 0);
	    VlinkeParamMap.put("message.link.office.stockN.audit", 0);
	    VlinkeParamMap.put("message.link.office.stockN.view", 0);
	}

	/**
	 * 打开第三方系统页面。如果没有进行单点登录，则单点登录以后再打开。
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
    @NeedlessCheckLogin
    public ModelAndView show(HttpServletRequest request, HttpServletResponse response) throws Exception {
        User user = AppContext.getCurrentUser();
        String token = null;
        if (user == null) {
             token = request.getHeader("token");
            if (Strings.isEmpty(token)) {
                token = request.getParameter("token");
            }
            if (Strings.isEmpty(token)) {
                token = Cookies.get(request, "token");
            }
            ServiceManager.getInstance().initCurrentUser(request, token);
            user = AppContext.getCurrentUser();
        }
        if (user == null) {
            OutputStream stream = response.getOutputStream();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html; charset=UTF-8");
            stream.write(ResourceUtil.getString("cip.user.loginagain").getBytes("UTF-8"));
            stream.flush();
            stream.close();
            return null;
        }
		String loginName = user.getLoginName();
		String id = request.getParameter("id");
		String pageURL = request.getParameter("pageUrl");
		String extendParam = request.getParameter("extendParam");
		String width = request.getParameter("width");
		String height = request.getParameter("height");
		String fromClient = request.getParameter("fromClient");
		ThirdpartySpace tpSpace = thirdpartySpaceManagerApi.get(id);
		String summaryId = request.getParameter("summaryId");
		String formRecordId = request.getParameter("formRecordId");
		String taskId = request.getParameter("taskId");
		Map<String,Object> map = new HashMap<String,Object>();

		if(tpSpace != null){
			//没有登录地址，说明不需要sso，直接打开页面
			if(Strings.isBlank(tpSpace.getLoginURL(user.getId(), user.getLoginAccount()))){
				if(Strings.isBlank(taskId)) {//为空则为应用接入默认处理
					pageURL = tpSpace.getPageURL(user.getId(), user.getLoginAccount());
				}else {
					map.put("taskId", taskId);
					map.put("summaryId", summaryId);
					map.put("spaceId", tpSpace);
					map.put("formRecordId", formRecordId);
					pageURL = cipCustomTaskManager.getFormCustomPageURL(map);
				}
				if(Strings.isNotBlank(pageURL)){//不为空，调用接口进行处理
				
					
					if(Strings.isNotBlank(width)){
						pageURL +="&width="+width+"&height="+height;
					}
					if(Strings.isNotBlank(extendParam)){
						pageURL+= "&extendParam="+ URLEncoder.encode(extendParam,"UTF-8");
					}
					if (Strings.isNotBlank(fromClient)) {
						
						if ("weixin".equalsIgnoreCase(fromClient)) {
							if (pageURL.contains("/mobile_portal/seeyon")) {
								pageURL = StringUtils.substringAfter(pageURL, "mobile_portal");
							}
							pageURL = CIPUtil.getUrlSuffixParam(pageURL, "cipWeinxinToken=" + token);
						} else if ("m3".equalsIgnoreCase(fromClient)) {
							if (pageURL.startsWith("/seeyon")) {
								pageURL = "/mobile_portal"+pageURL;
							}
						}
					}
					response.sendRedirect(pageURL);
					return null;
				}
			}
			else{
				String ticket = thirdpartySpaceManagerApi.ssoLogin(id, loginName, user.getId(), user.getLoginAccount());

				if(Strings.isNotBlank(ticket)){
					
					
					if(Strings.isBlank(taskId)) {//为空则为应用接入默认处理
						pageURL = tpSpace.getPageURL(user.getId(), user.getLoginAccount());
					}else {
						map.put("taskId", taskId);
						map.put("summaryId", summaryId);
						map.put("spaceId", tpSpace);
						map.put("formRecordId", formRecordId);
						pageURL = cipCustomTaskManager.getFormCustomPageURL(map);
					}

					if(Strings.isNotBlank(pageURL)){
						response.sendRedirect(doURL(pageURL, tpSpace.getTicketName(), ticket));

						return null;
					}
				}
			}
		}
		String errorTip = ResourceUtil.getString("cip.thirdspace.tip");
		PrintWriter out = response.getWriter();
		out.println("<script>");
		out.println("alert('" +  StringEscapeUtils.escapeJavaScript(errorTip) + "');");
		out.println("window.close();");
		out.println("</script>");

		return null;
	}

	/**
	 * 根据A8生成的ticket取得当前登录者的登录名<br>
	 *
	 * URL：http://a8:80/seeyon/thirdparty.do?ticket=**
	 *
	 */
	@Override
	@SetContentType
	@NeedlessCheckLogin
	public ModelAndView index(HttpServletRequest request,HttpServletResponse response) throws Exception {
		String ticket = null;
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/plain; charset=UTF-8");
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");


		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			ticket = request.getParameter(String.valueOf(params.nextElement()));

			if (ticket != null) {
				if(log.isDebugEnabled()){
					log.debug("ticket is :"+ticket);
				}
				String username = null;
				ThirdpartyTicketManager.TicketInfo ticketInfo = ThirdpartyTicketManager.getInstance().getTicketInfo(ticket);

				if (ticketInfo == null) {
					if(log.isDebugEnabled()){
						log.debug("ticket is not from thirdpartticket:"+ticket);
					}
					TicketInfo ssoTicketInf = SSOTicketManager.getInstance().getTicketInfo(ticket);
					if (ssoTicketInf != null) {
						username = ssoTicketInf.getUsername();
						if(log.isDebugEnabled()){
							log.debug("ticket is from ssoTicket,userName:"+username);
						}
					}
				}
				ThirdpartySpace tpSpace = null;
				PrintWriter out = response.getWriter();
				if (ticketInfo != null) {
					username = ticketInfo.getLoginName();
					if(log.isDebugEnabled()){
						log.debug("ticket is from thirdpartticket:"+ticket);
					}
					if(cipAppLinkDynamicAction!=null && !cipAppLinkDynamicAction.checkSSOAuth(ticketInfo.getSpaceId(),username)){
						out.println(URLEncoder.encode("无权限登录","UTF-8"));
						return null;
					}
					tpSpace = thirdpartySpaceManagerApi.get(ticketInfo.getSpaceId());

					if (tpSpace != null) {
						username = ticketInfo.getLoginName();
						if(log.isDebugEnabled()){
							log.debug("ticket is from thirdpartticket,userName:"+username);
						}
					}
				}
				if (username != null) {
					V3xOrgMember member = orgManager.getMemberByLoginName(username);

					// 做用户映射或做处理后才能返回第三方登录账号，否则返回OA登录账号
					String thirdUsername = username;
					if (null != tpSpace) {
						thirdUsername = tpSpace.getThirdpartyLoginName(username);
					}
					// 客开：默认返回人员编码
					thirdUsername = member.getCode();
					response.addHeader("LoginName", URLEncoder.encode(thirdUsername, "UTF-8"));
					AddressBook addressBook = addressBookCustomerFieldInfoManager.getByMemberId(member.getId());
					if(null != addressBook) {
						String code = addressBook.getExtAttr2();
						if(Strings.isNotBlank(code)) {
							response.addHeader("ThirdPartyLoginName", code);
						}
					}
					if (null != member) {
						response.addHeader("MemberId", String.valueOf(member.getId()));
						response.addHeader("MemberName", URLEncoder.encode(member.getName(), "UTF-8"));

					} else {
						log.warn("OA集成第三方系统通过登录名称找人失败：" + username + " " + thirdUsername);
						//CIPActionLogFactory.createLog(LogApplicationEnum.APPINTEGRATION, "单点登录","OA集成第三方系统通过登录名称找人失败：" + username + " " + thirdUsername, null, null, null);
					}
					if (AppContext.hasPlugin("m3")) {
						response.addHeader("M3URL", URLEncoder.encode(PNSPropertyUtils.getInstance().getM3URL(), "UTF-8"));
					}
					out.println(URLEncoder.encode(thirdUsername, "UTF-8"));
				}

				break;

			}
		}
//		认证完成后销毁ticket
		if (ticket != null) {
			SSOTicketManager.getInstance().ticketExpired(ticket);
		}
		return null;
	}

	/**
	 * 第三方系统退出时，通知A8一下<br>
	 *
	 * URL：http://a8:80/seeyon/thirdparty.do?method=logoutNotify&ticket=**
	 *
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@SetContentType
	@NeedlessCheckLogin
	public ModelAndView logoutNotify(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		request.setCharacterEncoding("UTF-8");

		response.setContentType("text/plain; charset=UTF-8");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");

        Enumeration params = request.getParameterNames();

        while(params.hasMoreElements()){
			String ticket = request.getParameter(String.valueOf(params.nextElement()));

			if(ticket != null){
				ThirdpartyTicketManager.TicketInfo ticketInfo = ThirdpartyTicketManager.getInstance().getTicketInfo(ticket);

				if(ticketInfo != null){
					ThirdpartyTicketManager.getInstance().removeTicketInfo(ticket);
					break;
				}
			}
        }

		return null;
	}

	private static String doURL(String loginURL, String ticketName, String ticket) {
		try {
			String[] us = loginURL.split("[?]");
			String redirectURL = loginURL;
			if(us.length < 2){
				return redirectURL + "?" + ticketName + "=" + ticket;
			}
			else{
				StringBuilder sb = new StringBuilder(redirectURL + "&from=A8&" + ticketName + "=" + ticket);
	            String internetURL=SystemEnvironment.getInternetSiteURL();
				
				if(StringUtils.isNotBlank(internetURL)){
					sb.append("&interneturl="+internetURL);
				}
				return sb.toString();
			}

		}
		catch (Exception e) {
			log.error(e.getMessage(), e);
		}

		return null;
	}

	/**
	 *
	 * 外部系统直接打开A8的主题，并能够处理<br/>
	 *
	 * SSO方式：http://***:80/seeyon/thirdparty.do?method=access&enc=Encoder{C=ticket&P=/*.do?...} <br/>
	 * 消息方式：http://***:80/seeyon/thirdparty.do?method=access&enc=Encoder{MID=历史消息ID&L=message.link.***&T=timestamp}&P=**&P=** <br/>
	 *
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@NeedlessCheckLogin
	public ModelAndView access(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String param = request.getQueryString();
		String replace = param.replace("method=access&", "");
		String enc = getEnc(request);
		if(enc == null) {
			ModelAndView mv = new ModelAndView("thirdparty/thirdpartyAccess");
			mv.addObject("ExceptionKey", "mail.read.alert.wuxiao");
			return mv;
		}
		//第三方访问判断，如果是则直接返回不需要登录
		Map<String, String> encMap = parseEnc(enc);
		if (Strings.isNotBlank(encMap.get("P"))) {
			return getMailInfo(request, response);
		}
		
		String loginFrom= request.getParameter("loginFrom");
        if (AppContext.getRawSession() == null){
            AppContext.initSystemEnvironmentContext(request, response, true);;
        }
        User currentUser= AppContext.getCurrentUser();
        //判断是否已验证登录
        V3xOrgMember user = getUserInfo(request);
        if(currentUser != null && user != null) {
        	if(currentUser.isDefaultGuest()) {
        		HttpSession session = request.getSession();
				session.removeAttribute("com.seeyon.current_user");//session.setAttribute("com.seeyon.current_user", user)
        	}else if (user.getId().equals(currentUser.getId())){
        		return getMailInfo(request, response);
        	}
        }else{
			boolean hasAccess = false;
        	ConfigItem sysMailLinkLoginSwitch = configManager.getConfigItem("sysMailLinkLoginSwitch", "sysMailLinkLoginSwitch");
			if(sysMailLinkLoginSwitch != null){
				hasAccess = "false".equals(sysMailLinkLoginSwitch.getConfigValue());
			}
			if(hasAccess){
				return getMailInfo(request, response);
			}
		}
        
        Map<String, Object> festivalLoginPageFileIdsMap = portalApi.getFestivalLoginPageFileIds();//特殊日期登录页设置
        boolean toLoginPage=false;
        List<String> festivalLoginPageFileIds=null;
        if(MapUtils.isNotEmpty(festivalLoginPageFileIdsMap)){
            toLoginPage = MapUtils.getBoolean(festivalLoginPageFileIdsMap, "festivalLoginPageFlag", false);
            Object festivalLoginPageFileIdsObj=festivalLoginPageFileIdsMap.get("fileIdList");
            if(festivalLoginPageFileIdsObj!=null && festivalLoginPageFileIdsObj instanceof List){
                festivalLoginPageFileIds=(List<String>)festivalLoginPageFileIdsObj;
            }
        }
        
        PortalTemplateSetting setting = (PortalTemplateSetting) request.getAttribute("PortalLoginTemplateSetting");
        Long loginAccountId = (Long) request.getAttribute("loginAccountId");
        List<PortalHotspot> hotSpots = null;
        if(setting == null){
        	setting= portalApi.getLoginSettingBy(OrgConstants.GROUPID.longValue(), OrgConstants.GROUPID.longValue());
        	hotSpots = portalApi.getHotSpotsBy(setting.getTemplateId(), null, OrgConstants.GROUPID.longValue(), OrgConstants.GROUPID.longValue());
        } else {
        	hotSpots = portalApi.getHotSpotsBy(setting.getTemplateId(), null, loginAccountId, loginAccountId);
        }
        if(CollectionUtils.isNotEmpty(festivalLoginPageFileIds) && CollectionUtils.isNotEmpty(hotSpots)){
            //用户设置了有效的特殊日期登录页，需要修改热点值
            List<PortalHotspot> festivalHotSpotList=new ArrayList<>(hotSpots.size());
            for (PortalHotspot hotSpot : hotSpots) {
                String hotspotkey = hotSpot.getHotspotkey();
                if("changebgi".equals(hotspotkey)){
                    //需要把这个给替换成特殊节日的
                    PortalHotspot festivalHostSpot=BeanUtils.clone(hotSpot);
                    StringBuffer hotValuebuffer=new StringBuffer();
                    StringBuffer ext3Buffer=new StringBuffer();
                    for (String fileId : festivalLoginPageFileIds) {
                        hotValuebuffer.append("fileId=").append(fileId).append(",");
                        ext3Buffer.append("1,");
                    }
                    String hotValue=new String(hotValuebuffer);
                    String ext3=new String(ext3Buffer);
                    if(hotValue.length()>1){
                        hotValue=hotValue.substring(0,hotValue.length()-1);
                        ext3=ext3.substring(0,ext3.length()-1);
                    }
                    festivalHostSpot.setHotspotvalue(hotValue);
                    festivalHostSpot.setExt3(ext3);
                    festivalHotSpotList.add(festivalHostSpot);
                }else if("changebgtype".equals(hotspotkey)){
                    PortalHotspot festivalHostSpot=BeanUtils.clone(hotSpot);
                    String hotspotvalue = festivalHostSpot.getHotspotvalue();
                    if("video".equals(hotspotvalue)){
                        festivalHostSpot.setHotspotvalue("image");
                    }
                    festivalHotSpotList.add(festivalHostSpot);
                }else {
                    festivalHotSpotList.add(hotSpot);
                }
            }
            hotSpots=festivalHotSpotList;

        }

        PortalLoginTemplate plt = portalApi.getLoginTemplate(setting.getTemplateId());
        ModelAndView modelAndView = new ModelAndView("thirdparty/login");
        Locale currentLocale = LocaleContext.make4Frontpage(request);
        List localeCode = new ArrayList();
        Map localeCodeCfg = new HashMap();
        localeCode.add(localeCodeCfg);
        localeCodeCfg.put("eleid", LoginConstants.LOCALE);
        localeCodeCfg.put("defaultValue", currentLocale.toString());
        localeCodeCfg.put("options", getLocaleInfo());

        String loginTitleName = Functions.getPageTitle();
        modelAndView.addObject("templatesJsonStr", JSONUtil.toJSONString(plt));
        modelAndView.addObject("hotSpotsJsonStr", JSONUtil.toJSONString(hotSpots));
        String layout = "all";
        if (CollectionUtils.isNotEmpty(hotSpots) && plt.getPreset() == 1) {
            //预置的
            for (PortalHotspot hotspot : hotSpots) {
                if ("note".equals(hotspot.getHotspotkey())) {
                    String noteName = hotspot.getHotspotvalue();
                    if (noteName == null || noteName.trim().length() == 0 || "null".equals(noteName)) {
                        loginTitleName = Functions.getVersion();
                    } else {
                        String suffix = SystemProperties.getInstance().getProperty("portal.loginTitle");
                        if((Boolean)(SysFlag.sys_isGovVer.getFlag())){
                            //G6的版本国际化比较特殊需要特殊处理一下看看是否是个性化过
                            if(noteName!=null&&(noteName.equals(ResourceUtil.getString(noteName)))){
                                loginTitleName = ResourceUtil.getString(noteName) + " " + Functions.getVersion();
                            }else {
                                loginTitleName = ResourceUtil.getString(noteName + suffix) + " " + Functions.getVersion();
                            }
                        }
                        else{
                        	loginTitleName = ResourceUtil.getString(noteName + suffix) + " " + Functions.getVersion();
                        }
                    }
                }
                if ("layout".equals(hotspot.getHotspotkey())) {
                    layout = hotspot.getHotspotvalue();
                }
                if("showQr".equals(hotspot.getHotspotkey())){
                    String item="qrInfoUpdate";
                    String cacheDirect = portalApi.getPortalGlobalConfigFromCacheDirect(item, -1L, -1L);
                    boolean isupdate=false;
                    if(cacheDirect==null){
                        //没有升级过，升级处理一下
                        if(!"1".equals(hotspot.getHotspotvalue())){
                            portalApi.updateQrInfo(item);
                            isupdate=true;
                        }
                    }
                    if(isupdate){
                        modelAndView.addObject("showQr", "1".equals(hotspot.getHotspotvalue()));
                    }else {
                        modelAndView.addObject("showQr",true);
                    }
                }
                if("QrInfo".equals(hotspot.getHotspotkey())){
                    modelAndView.addObject("QrInfo", hotspot.getHotspotvalue());
                }
                if("shownumber".equals(hotspot.getHotspotkey())) {
                	modelAndView.addObject("shownumber", !"hide".equals(hotspot.getHotspotvalue()));
                }
            }
        }
        Map<String,String> bgImgSize=portalApi.getCurrentLoginImgSize(hotSpots);
        modelAndView.addObject("bgImgSize", JSONUtil.toJSONString(bgImgSize));
        modelAndView.addObject("layout", layout);
        
        Map<String, LoginActiveX> activeXMap = loginControl.getLoginActiveXes();
        StringBuilder activeXLoader = new StringBuilder();
        if (activeXMap != null) {
            Iterator<String> ite = activeXMap.keySet().iterator();
            String key;
            while (ite.hasNext()) {
                key = ite.next();
                LoginActiveX loginActiveX = activeXMap.get(key);
                String activeX = loginActiveX.getActiveX(request, response);
                activeXLoader.append(activeX);
            }
        }

        modelAndView.addObject("currentLocale", currentLocale);
        modelAndView.addObject("locales", JSONUtil.toJSONString(localeCode));
        modelAndView.addObject("loginTitleName", loginTitleName);
        modelAndView.addObject("productCategory", ProductEditionEnum.getCurrentProductEditionEnum().getName());
        //并发数
        modelAndView.addObject("ServerState", ServerState.getInstance().isShutdown());
        modelAndView.addObject("ServerStateComment", Strings.toHTML(ServerState.getInstance().getComment()));
        if (onlineManager == null) {
            modelAndView.addObject("OnlineNumber", "...");
        } else {
            modelAndView.addObject("OnlineNumber", this.onlineManager.getOnlineNumber());
        }
//        if(systemConfig == null)
//        	systemConfig = (SystemConfig)AppContext.getBean("systemConfig");
        boolean verrifyCodeEnabled = "enable".equals(this.systemConfig.get("verify_code"));
		modelAndView.addObject("verifyCode", verrifyCodeEnabled);
        modelAndView.addObject("activeXLoader", activeXLoader.toString());
        if (LDAPConfig.getInstance().getIsEnableLdap()
                && request.getServerName().equalsIgnoreCase(LDAPConfig.getInstance().getA8ServerDomainName())) {
            String adssoToken = request.getHeader("authorization");
            if (adssoToken == null) {
                modelAndView.addObject("adSSOEnable", true);
            } else {
                //             modelAndView.addObject("adLoginName",ADSSOEvent.getInstance().getADLoginName(adssoToken));
                modelAndView.addObject("authorization", adssoToken);
            }
        }
        loadCAPlugIn(request, modelAndView);
        //modelAndView.addObject("hasPluginCA", true);
        String exceptPlugin = "";
        String ucServerIpOrPort = "NULL/NULL/5222";
        if (!AppContext.hasPlugin("videoconference")) {
            exceptPlugin += "@videoconf";
        }
        if (!AppContext.hasPlugin("https")) {
            exceptPlugin += "@seeyonRootCA";
        }
        if (!AppContext.hasPlugin("identification")) {
            exceptPlugin += "@identificationDog";
        }
        if (!AppContext.hasPlugin("officeOcx")) {
            exceptPlugin += "@officeOcx";
        }
        if (!AppContext.hasPlugin("barCode")) {
            exceptPlugin += "@erweima";
        }
		if (!AppContext.hasPlugin("u8")) {
			exceptPlugin += "@U8Reg";
		}
		exceptPlugin += "@wizard";
		
		//有zx插件才显示
		if (!AppContext.hasPlugin("zx")) { 
            exceptPlugin += "@zhixin";
        }

        modelAndView.addObject("ucServerIpOrPort", ucServerIpOrPort);
        modelAndView.addObject("exceptPlugin", exceptPlugin);
        // 判断是否能发送手机短信
        boolean isCanUseSMS = false;
        modelAndView.addObject("isCanUseSMS", isCanUseSMS);
        
        //判断系统配置是否启用口令加密传输，启用则生成加密种子传到页面
        if (SecurityHelper.isCryptPassword()){
            modelAndView.addObject("_SecuritySeed", SecurityHelper.getSessionContextSeed());
            HttpSession currentSession = request.getSession(false);
            if(currentSession!=null){
                int sessionTimeOutInSecond = currentSession.getMaxInactiveInterval();//获取Session的失效时间
                modelAndView.addObject("_SecuritySeedTimeOut",sessionTimeOutInSecond);
            }
        }
        //产品服务到期,产品授权到期
        ConfigItem dueRemind=configManager.getConfigItem("login_page", "dueRemind");
        modelAndView.addObject("dueRemindV",dueRemind==null?"1":dueRemind.getConfigValue());
        if(dueRemind==null||"1".equals(dueRemind.getConfigValue())){
        	modelAndView.addObject("dueRemind",portalApi.getDueRemind());
        }
		
    	String loginPageURL = (String) request.getAttribute("loginPageURL");
    	Cookie cookie = null;
    	if(loginPageURL == null){
    		loginPageURL="";
    	}
	    cookie = new Cookie("loginPageURL", loginPageURL);
        cookie.setMaxAge(expiry);
        cookie.setPath("/");
        response.addCookie(cookie);
        modelAndView.addObject("loginFrom", loginFrom);
        String rowList = request.getParameter("rowList");//显示字段
      	String btnbgc = request.getParameter("btnbgc");//登录框按钮颜色
      	String btombgc = request.getParameter("btombgc");//登录框底部色
      	String bgc = request.getParameter("bgc");//背景颜色
      	if(Strings.isBlank(rowList)){
      		rowList= "";
      	}
      	if(Strings.isBlank(btnbgc)){
      		btnbgc= "";
      	}
      	if(Strings.isBlank(btombgc)){
      		btombgc= "";
      	}
      	if(Strings.isBlank(bgc)){
      		bgc= "";
      	}
      	modelAndView.addObject("rowList", rowList);
      	modelAndView.addObject("btnbgc", btnbgc);
      	modelAndView.addObject("btombgc", btombgc);
      	modelAndView.addObject("bgc", bgc);
      	String canLocation = onlineManager.getCanLocation();
        String locationUrl = SystemProperties.getInstance().getProperty("portal.weather.locationUrl");
        modelAndView.addObject("canLocation",canLocation);
        modelAndView.addObject("locationUrl",locationUrl);
 
        modelAndView.addObject("isShowVerifyCode",LockLoginInfoFactory.getInstance().getShowVerifyCode(Strings.getRemoteAddr(request)));
        modelAndView.addObject("mailParam",replace);
        //回填用户名
        V3xOrgMember userInfo = getUserInfo(request);
        if(userInfo != null) {
			modelAndView.addObject("loginName",userInfo.getLoginName());
		} else {
        	 ModelAndView mv = new ModelAndView("thirdparty/thirdpartyAccess");
        	 mv.addObject("ExceptionKey", "mail.read.alert.guoqi");
        	 return mv;
        	 
        }
        return modelAndView;
	}

	private static Object o = null;
	private static int serverType;
    private static int m1Type;

    private static void init(){
        if(o != null){
            return;
        }

        o = MclclzUtil.invoke(c1, "getInstance", new Class[] { String.class }, null, new Object[] { "" });

        serverType = (Integer) MclclzUtil.invoke(c1, "getserverType", null, o, null);
        m1Type = (Integer) MclclzUtil.invoke(c1, "getm1Type", null, o, null);
    }

    private static final Class<?> c1 = MclclzUtil.ioiekc("com.seeyon.ctp.permission.bo.LicensePerInfo");

	public void setPrivilegeMenuManager(PrivilegeMenuManager privilegeMenuManager) {
		this.privilegeMenuManager = privilegeMenuManager;
	}
	public static class PNSPropertyUtils {

		private static final Log logger = LogFactory.getLog(PNSPropertyUtils.class);

		private static String FILE_PATH;
		private static PNSPropertyUtils property;

		private static Properties properties;

		private PNSPropertyUtils() {
			StringBuilder sb = new StringBuilder(SystemEnvironment.getApplicationFolder())
					.append(File.separator).append("WEB-INF")
					.append(File.separator).append("cfgHome")
					.append(File.separator).append("plugin")
					.append(File.separator).append("m3")
					.append(File.separator).append("pns.properties");
			FILE_PATH = sb.toString();
		}

		public static final PNSPropertyUtils getInstance() {
			if (property == null) {
				synchronized (PNSPropertyUtils.class) {
					if (property == null) {
						property = new PNSPropertyUtils();
						init();
					}
				}
			}
			return property;
		}

		private static void init() {
			CtpLocalFile file = new CtpLocalFile(FILE_PATH);

			if (file.exists()) {
				properties = new Properties();
				InputStream in = null;
				try {
					in = new FileInputStream(file);
					properties.load(in);
				} catch (FileNotFoundException e) {
					logger.error(e);
				} catch (IOException e) {
					logger.error(e);
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException e) {
							logger.error(e);
						}
					}
				}

			}

		}

		public final String getProperty(String key) {
			if (properties != null) {
				return properties.getProperty(key);
			}
			return null;
		}

		public void setProperty(String key, String value) {

			CtpLocalFile file = new CtpLocalFile(FILE_PATH);
			if (file.exists()) {
				OutputStream out = null;
				try {
					out = new FileOutputStream(file);
					properties.setProperty(key, value);
					properties.store(out, "Update PNS Property : [key=" + key
							+ "; value=" + value + "].");
				} catch (FileNotFoundException e) {
					logger.error(e);
				} catch (IOException e) {
					logger.error(e);
				} finally {
					if (out != null) {
						try {
							out.flush();
							out.close();
						} catch (IOException e) {
							logger.error(e);
						}
					}
				}

			}
		}
		
		public String getM3URL() {
			String serverType = property.getProperty("pns.server.type");
			String serverIp = property.getProperty("pns.server.ip");
			String serverPort = property.getProperty("pns.server.port");
			String serverNamespase = property.getProperty("pns.server.namespase");

			return new StringBuilder(serverType).append("://").append(serverIp).append(":").append(serverPort)
					.append(serverNamespase).toString();
		}
	}
    private  String getM3ServerAccessURL() {
        String defaultURL = "";
        HttpServletRequest request = (HttpServletRequest) AppContext.getThreadContext(GlobalNames.THREAD_CONTEXT_REQUEST_KEY);
        HttpSession session = request.getSession();
        if(session == null) {
        	return defaultURL;
        }
        String result =  (String) session.getAttribute("ClientRequestPath");
        if (result == null) {
            result = defaultURL;
        }
        return result;
    }

	public void setThirdpartySpaceManagerApi(ThirdpartySpaceManagerApi thirdpartySpaceManagerApi) {
		this.thirdpartySpaceManagerApi = thirdpartySpaceManagerApi;
	}

	

	public void setCipCustomTaskManager(CipCustomTaskManager cipCustomTaskManager) {
		this.cipCustomTaskManager = cipCustomTaskManager;
	}
	
	@NeedlessCheckLogin
	public ModelAndView mailAuth(HttpServletRequest request, HttpServletResponse response) throws Exception {		
		String loginFrom= request.getParameter("loginFrom");
        HttpSession session = request.getSession(false);
        
        try {
        //校验码转移
        String verifyCode = null;
        //iTrusCA校验码转移
        String oriToSign = null;
        //登陆口令加密种子
        String seed = null;
      //判断失败次数达到演示验证码，切换用户登录，也需要进行验证码验证
        Object isShowVerifyCode = null;
        if (session != null) {
            verifyCode = (String) session.getAttribute(LoginConstants.VerifyCode);
            oriToSign = (String) session.getAttribute("ToSign");
            seed = (String)session.getAttribute(GlobalNames.SESSION_CONTEXT_SECURITY_SEED_KEY);
            isShowVerifyCode  = session.getAttribute("userShowVerifyCode");
            try {
                session.invalidate();
            } catch (Throwable t) {
            	log.error(t.getMessage(),t);
            }
        }

        session = request.getSession(true);
        session.setAttribute("userShowVerifyCode", isShowVerifyCode);
        AppContext.putThreadContext(GlobalNames.THREAD_CONTEXT_SESSION_KEY, session);
        if (Strings.isNotBlank(verifyCode)) {
            AppContext.putSessionContext(LoginConstants.VerifyCode, verifyCode);
            log.info("verifyCode="+verifyCode);
        }
        if (Strings.isNotBlank(oriToSign)) {
            AppContext.putSessionContext("ToSign", oriToSign);
        }
        if (Strings.isNotBlank(seed)) {
            AppContext.putSessionContext(GlobalNames.SESSION_CONTEXT_SECURITY_SEED_KEY, seed);
        }
        //Session线程变量更新
        AppContext.putThreadContext(GlobalNames.THREAD_CONTEXT_SESSION_KEY, session);

        //OA-180658，对于审计管理员的特殊处理，如果没有开启审计管理员，那么不应该走密码校验
        String login_username = request.getParameter("login_username");
        if("audit-admin".equals(login_username)){
            String isAuditAdminSwitch = systemConfig.get(IConfigPublicKey.AUDIT_ENABLE);
            if(!("enable".equals(isAuditAdminSwitch))){
               //审计管理员未开启直接提示用户不存在
                LocaleContext.make4Frontpage(request);
                throw new BusinessException(ResourceUtil.getString("login.label.ErrorCode.1"));
            }
        }
        if(loginControl == null) {
        	loginControl =(LoginControl) AppContext.getBean("loginControl");
        } 
        LoginResult transDoLogin = loginControl.transDoLogin(request, session, response);
       
        if(transDoLogin.isOK()){
    	    return getMailInfo(request, response);
        }
    	} catch (Throwable e) {
            BusinessException be = getBusinessException(e);
            if(!(e instanceof InfrastructureException)){
            	log.error(e.getLocalizedMessage(),e);
            }else{
//            	session.setAttribute("login.result", e.getCause().getLocalizedMessage());
            	// 用户名密码错误不输出堆栈信息
            	log.debug(e.getCause().getLocalizedMessage(),e);
            }
            if(Strings.isNotBlank(loginFrom) && "loginPortal".equals(loginFrom)){
            	response.addHeader("LoginOk", "fail");
        		response.setContentType("text/html; charset=UTF-8");
                PrintWriter out = response.getWriter();
                String message= "";
                if(null!=be){
                	message= be.getMessage();
                }
                if(Strings.isNotBlank(message)){
                	message= message.replaceAll("<br/>", "\n\r").replaceAll("<strong>", "").replaceAll("</strong>", "");
                }
                if(Strings.isBlank(message)){
                	message= ResourceUtil.getString("login.label.ErrorCode.1");
                }
                out.println(message);
                out.close();
            }else{
            	goout(request, session, response, be, true);
            }
        }
        return null;
		
	}
	
	/**
	 * 获取链接的内容
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	private ModelAndView  getMailInfo(HttpServletRequest request, HttpServletResponse response)throws Exception{
		long time1 = System.currentTimeMillis();
	    
		ModelAndView mv = new ModelAndView("thirdparty/thirdpartyAccess");
	      
        if(Strings.isBlank(SystemEnvironment.getInternetSiteURL())){
            mv.addObject("ExceptionKey", "mail.read.alert.wuxiao");
            return mv;
        }
        
		Locale locale = LocaleContext.make4Frontpage(request);
		HttpSession session = request.getSession();
		String openFrom = request.getParameter("from");
		Long loginTime = System.currentTimeMillis();
		String enc = getEnc(request);
		if (enc == null) {
			mv.addObject("ExceptionKey", "mail.read.alert.wuxiao");
			return mv;
		}

		Map<String, String> encMap =parseEnc(enc);

		String link = null;
		long memberId = -1;
		login_useragent_from userAgentFrom = login_useragent_from.pc;
		
		String linkType = encMap.get("L");
		String path = encMap.get("P");
		if (Strings.isNotBlank(linkType)) {
			String startTimeStr= "0";
			if(encMap.containsKey("T")){
				startTimeStr= encMap.get("T");
				startTimeStr= startTimeStr.trim();
			}
			Long timeStamp = 0L;
			if(NumberUtils.isNumber(startTimeStr)){
				timeStamp= Long.parseLong(startTimeStr);
			}else{
				timeStamp= DateUtil.parse(startTimeStr,DateUtil.YEAR_MONTH_DAY_HOUR_MINUTE_SECOND_PATTERN).getTime();
			}
			int contentLinkValidity = 24;
			if (messageMailManager != null) {
				contentLinkValidity = messageMailManager.getContentLinkValidity();
			}
			if ((System.currentTimeMillis() - timeStamp) / 1000 > contentLinkValidity * 60 * 60) {
				mv.addObject("ExceptionKey", "mail.read.alert.guoqi");
				return mv;
			}
			String _messageId = encMap.get("MID");
			if (_messageId == null) {
				mv.addObject("ExceptionKey", "mail.read.alert.wuxiao");
				return mv;
			}
			Long messageId = Long.parseLong(_messageId);
			UserHistoryMessage msg = this.userMessageManager.getUserHistoryMsgById(messageId);
			if(msg == null) {
				mv.addObject("ExceptionKey", "mail.read.alert.wuxiao");
				return mv;
			}

			memberId = msg.getReceiverId();

			link = UserMessageUtil.getMessageLinkType().get(linkType);

			if (link == null) {
				mv.addObject("ExceptionKey", "mail.read.alert.wuxiao");
				return mv;
			}
			String[] linkParams = request.getParameterValues("P");
			java.text.MessageFormat formatter = new java.text.MessageFormat(link);
			int formatsCount=formatter.getFormats().length;
			if (linkParams != null) {
				if(formatsCount>linkParams.length){
					String [] params=new String[formatsCount];
					for(int i=0;i<params.length;i++){
						if(i<linkParams.length){
							params[i]=linkParams[i];
						}else{
							params[i]="";
						}
					}
					link = formatter.format(params);
				}else{
					link = formatter.format(linkParams);
				}
			}else{
				linkParams=new String[formatsCount];
				for(int i=0;i<linkParams.length;i++){
					linkParams[i]="";
				}
				link=formatter.format(linkParams);
			}
		} else if (Strings.isNotBlank(path)) {
			link = URLDecoder.decode(path);
			String ticket = encMap.get("C");

			TicketInfo ticketInfo = null;
			ticketInfo=SSOTicketBean.getTicketInfoByticketOrname(ticket);
			//因为微信汉字名ticket可能存在+号被屏蔽为空格，这里增加转换
			if(ticketInfo==null){
				ticket = ticket.replaceAll(" ", "+");
				ticketInfo=SSOTicketBean.getTicketInfoByticketOrname(ticket);
			}
			loginTime = ticketInfo.getCreateDate().getTime();
			if("weixin".equals(ticketInfo.getFrom())) {
				userAgentFrom = login_useragent_from.wechat;
			}
			if (ticketInfo != null) {
				memberId = ticketInfo.getMemberId();
			}
		} else {
			mv.addObject("ExceptionKey", "mail.read.alert.wuxiao");
			return mv;
		}

		if (memberId == -1) {
			mv.addObject("ExceptionKey", "mail.read.alert.noUser");
			return mv;
		}

		boolean isNeedLogout = false;
		
		long time2 = System.currentTimeMillis();
		log.info("Param耗时" + (time2 - time1) + "MS");

		User currentUser = (User) session.getAttribute(Constants.SESSION_CURRENT_USER);
		// 当前已经登录，但登录者不是本人
		if (currentUser != null && !currentUser.isDefaultGuest()) {
			if (currentUser.getId() != memberId) {
				mv.addObject("ExceptionKey", "mail.read.alert.exists");
				return mv;
			}
		} else {
			V3xOrgMember member = orgManager.getMemberById(memberId);
			if (member == null || member.getIsAdmin()) {
				mv.addObject("ExceptionKey", "mail.read.alert.noUser");
				return mv;
			}

			LocaleContext.setLocale(session, orgManagerDirect.getMemberLocaleById(member.getId()));

			currentUser = UserUtil.build(memberId, userAgentFrom.name(), request);
			currentUser.setLoginTimestamp(loginTime);
			currentUser.setLocale(locale);
			session.setAttribute(Constants.SESSION_CURRENT_USER, currentUser);
//			AppContext.putThreadContext(GlobalNames.SESSION_CONTEXT_USERINFO_KEY, currentUser);
			UserUtil.setCurrentUser(currentUser);
			AppContext.initSystemEnvironmentContext(request, response, true);

			currentUser.setSecurityKey(UUIDLong.longUUID());

//			currentUser.setId(memberId);
//			currentUser.setName(member.getName());
//			currentUser.setLoginName(member.getLoginName());
//			currentUser.setAccountId(member.getOrgAccountId());
//			currentUser.setLoginAccount(member.getOrgAccountId());
//			currentUser.setDepartmentId(member.getOrgDepartmentId());
//			currentUser.setLevelId(member.getOrgLevelId());
//			currentUser.setPostId(member.getOrgPostId());
//			currentUser.setInternal(member.getIsInternal());

//			currentUser.setUserAgentFrom(userAgentFrom.name());
//			currentUser.setSessionId(session.getId());
//			currentUser.setRemoteAddr(Strings.getRemoteAddr(request));
		
			// 判断客户端浏览器
			BrowserEnum browser = BrowserEnum.valueOf(request);
			if (browser == null) {
				browser = BrowserEnum.IE;
			}
			currentUser.setBrowser(browser);
		    //添加用户拥有角色
		    UserHelper.setRolesSet(orgManager.getMemberRolesForSet(currentUser.getId(), currentUser.getLoginAccount()));
		/*	Map<Long, PrivMenuBO> resources = privilegeMenuManager.getByMember(currentUser.getId(), currentUser.getLoginAccount());
			
			List<String> resList = new ArrayList<String>();
			for (PrivMenuBO res : resources.values()) {
				String code = res.getResourceCode();
				if(code == null){
					continue;
				}
				resList.add(code);
			}*/
			UserHelper.setResourceJsonStr(JSONUtil.toJSONString(privilegeMenuManager.getResourceCode(currentUser.getId(), currentUser.getLoginAccount())));

//			CurrentUser.set(currentUser);

			isNeedLogout = true;
		}
		
		long time3 = System.currentTimeMillis();
        log.info("User耗时" + (time3 - time2) + "MS");
        
		//加V参数
		if (Strings.isNotBlank(linkType)) {
		    //获取V参数位置
		    Integer paramIndex = ThirdpartyController.VlinkeParamMap.get(linkType);
		    //获取所有参数
		    String[] linkParams = request.getParameterValues("P");
		    if (paramIndex != null) {
		        if (linkParams.length > paramIndex) {
		            String paramValue = linkParams[paramIndex];
	                if (Strings.isNotBlank(paramValue)) {
	                    String vlink = SecurityHelper.func_digest(paramValue);
	                    int _index = link.indexOf("&v=");
	                    if (Strings.isNotBlank(link) && _index > -1) {
	                      //能找到V参数
	                      //取V前边的
	                      String beforeLink = link.substring(0,_index);
	                      //获取V后边的
	                      String afterLink = link.substring(_index + 1, link.length());
	                      //判断V后边是否还有&符号
	                      int _indexAfter = afterLink.indexOf("&");
	                      if (_indexAfter > -1) {
	                          //获取最后的字符串
	                         afterLink = afterLink.substring(_indexAfter, afterLink.length());
	                         link = beforeLink +  "&v=" + vlink  + afterLink;
	                      } else {
	                          link = beforeLink + "&v=" + vlink;
	                      }
	                    } else {
	                      //找不到V参数
	                        vlink = "&v=" + vlink;
	                        link = link + vlink;
	                    }
	                }
		        }
		    }
		}
		
		long time4 = System.currentTimeMillis();
        log.info("Link耗时" + (time4 - time3) + "MS");

		init();

        OnlineUser onlineUser = OnlineRecorder.getOnlineUser(currentUser);
        //并发数控制
        if (serverType == 2) {//server并发控制
            synchronized (isExceedMaxLoginNumberLock) {
                if(onlineUser == null){
                    boolean isExceedMaxLoginNumber = OnlineRecorder.isExceedMaxLoginNumberServer();

                    if(isExceedMaxLoginNumber){
						boolean isOnline = isOnline(currentUser);
						if(!isOnline) {
	                        mv.addObject("ExceptionKey", "mail.read.alert.ExceedMaxLoginNumber");
	                        return mv;
						}
                    }
					String serverPermissionType  = (String) MclclzUtil.invoke(c1, "getServerPermissionType", null, o, null);
					// 分单位并发控制
					if ("2".equals(serverPermissionType)) {
						if (OnlineRecorder.isExceedMaxLoginNumberServerInAccount(currentUser.getLoginAccount())) {
							boolean isOnline = isOnline(currentUser);
							if(!isOnline) {
		                        mv.addObject("ExceptionKey", "login.label.ErrorCode.30");
		                        return mv;
							}
						}
					}
                }
//                onlineManager.updateOnlineState(currentUser);
				LoginOpt.loginCore(currentUser);
            }
        }

        link = link + (link.contains("?") ? "&" : "?") + "_isModalDialog=true";
        if (link.indexOf("&openFrom") > -1) {
            link = link + "&extFrom="+ Strings.escapeNULL(openFrom, "");
        } else {
            link = link + "&openFrom="+ Strings.escapeNULL(openFrom, "");
        }
        if ("ucpc".equals(openFrom)) {
        	link = link + "&from=a8genius";
        }
        CTPCsrfGuard csrfGuard = CTPCsrfGuard.getInstance();
        if(csrfGuard.isEnabled()){
        	csrfGuard.updateToken(session);
        	link += Functions.csrfSuffix();
        }
		mv.addObject("link", link);
		mv.addObject("isNeedLogout", isNeedLogout);
		
		long time5 = System.currentTimeMillis();
        log.info("Online耗时" + (time5 - time4) + "MS");
        log.info("All耗时" + (time5 - time1) + "MS");

		return mv;
	}
	private boolean isOnline(User user) {
		OnlineUser onlineUser = OnlineRecorder.getOnlineUser(user);
		return onlineUser != null && onlineUser.getLoginInfoByLoginSign(user.getLoginSign()) != null;
	}
	private Map localeInfo = null;
	private Map getLocaleInfo() {
		if(null !=localeInfo && localeInfo.size()<LocaleContext.getAllLocales().size()){
			putLocaleInfo();
		}else {
			putLocaleInfo();		
		}
		return localeInfo;
	}

	private void putLocaleInfo() {
		localeInfo = new LinkedHashMap();
		List<Locale> locales = LocaleContext.getAllLocales();
		String locStr;
		for (Locale loc : locales) {
		    locStr = loc.toString();
		    localeInfo.put(locStr, ResourceUtil.getString("localeselector.locale." + locStr));
		}
	}
	
	private void loadCAPlugIn(HttpServletRequest request, ModelAndView modelAndView)
            throws UnsupportedEncodingException {
        String caFactory = SystemProperties.getInstance().getProperty("ca.factory");
        String factoryJsp = "/WEB-INF/jsp/ca/ca4" + caFactory + ".jsp";
        String sslVerifyCertValue = "no";
        String keyNum = "noKey";
        boolean hasPluginCA = AppContext.hasPlugin("ca");
        //如果是格尔CA厂商,从cookie中获取
        if ("koal".equals(caFactory)) {
            Cookie[] cookies = request.getCookies();
            if (cookies == null) {
                cookies = new Cookie[0];
            }
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //是否通过CA校验
                if ("SSL_VERIFY_CERT".equals(cookie.getName())) {
                    sslVerifyCertValue = new String(URLDecoder.decode(cookie.getValue())
                            .getBytes("ISO-8859-1"), "utf-8");
                }
                if ("KOAL_CERT_CN".equals(cookie.getName())) {
                    keyNum = new String(URLDecoder.decode(cookie.getValue()).getBytes("ISO-8859-1"), "utf-8");
                }
            }
        }
        if("Jit".equals(caFactory)){
        	this.loadJitCAPlugin(request, modelAndView);
        }
        modelAndView.addObject("caFactory", caFactory);
        modelAndView.addObject("sslVerifyCertValue", sslVerifyCertValue);
        modelAndView.addObject("keyNum", keyNum);
        modelAndView.addObject("hasPluginCA", hasPluginCA);
        modelAndView.addObject("pageUrl", factoryJsp);
        CtpLocalFile jspFile = new CtpLocalFile(SystemEnvironment.getApplicationFolder() + factoryJsp);
        if (hasPluginCA && !"koal".equals(caFactory) && jspFile.exists()) {
            modelAndView.addObject("includeJsp", true);
        } else {
            modelAndView.addObject("includeJsp", false);
        }
    }
	
	private void loadJitCAPlugin(HttpServletRequest request,ModelAndView modelAndView){
    	HttpSession session = request.getSession();
    	String randNum = generateRandomNum();
		/**************************
		 * 第三步 服务端返回认证原文   *
		 **************************/
		// 设置认证原文到session，用于程序向后传递，通讯报文中使用
    	AppContext.putSessionContext("ToSign", randNum);

		// 设置认证原文到页面，给页面程序提供参数，用于产生认证请求数据包
    	modelAndView.addObject("original", randNum);
    }
	
	/**
	 * 产生认证原文
	 */
	private String generateRandomNum() {
		/**************************
		 * 第二步 服务端产生认证原文   *
		 **************************/
		String num = "1234567890abcdefghijklmnopqrstopqrstuvwxyz";
		int size = 6;
		char[] charArray = num.toCharArray();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < size; i++) {
			sb
					.append(charArray[((int) (Math.random() * 10000) % charArray.length)]);
		}
		return sb.toString();
	}
	
	
	 private BusinessException getBusinessException(Throwable e) {
        if (e == null) {
			return null;
		}
        if (e instanceof BusinessException) {
			return (BusinessException) e;
		} else {
            return getBusinessException(e.getCause());
        }
    }
	
	 
	private void goout(HttpServletRequest request, HttpSession session, HttpServletResponse response,
            BusinessException be, boolean jumpDestination) {
        //登录失败目标页面
		String param = request.getQueryString();
		if(param != null) {
			param = param.replace("method=mailAuth&", "");
		}
        String error_destination ="thirdpartyController.do?method=access&"+param; //getErrorDestination(request, session);
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for(Cookie cookie : cookies){
                if("loginPageURL".equals(cookie.getName()) && cookie.getValue().length() > 0){
                    error_destination = request.getContextPath() + cookie.getValue();
                    cookie.setMaxAge(0);
                    cookie.setValue(null);
                    response.addCookie(cookie);
                }
            }
        }
        if (be != null && session != null) {
            //清除已有session信息
            Enumeration<String> attsEnu = session.getAttributeNames();
            List<String> attrs = new ArrayList<String>();
            while (attsEnu.hasMoreElements()) {
            	attrs.add(attsEnu.nextElement());
            }
            for (String name : attrs) {
				//为了保证用户失败验证达到一定次数弹出验证码，需要保证一个有判断的session值
            	if("userShowVerifyCode".equals(name)) {
            		continue;
            	}
            	session.removeAttribute(name);
			}
            AppContext.putSessionContext(LoginConstants.Result, be.getMessage());
            response.addHeader("LoginError", be.getCode());
        }
        try {
            if (jumpDestination) {
                response.sendRedirect(response.encodeURL(error_destination));
            }
        } catch (Exception e) {
			log.error(e.getMessage(),e);
        }
    } 
	/**
	 * 获取链接的用户信息
	 * @param request
	 * @return
	 * @throws Exception
	 */
	private V3xOrgMember getUserInfo(HttpServletRequest request) throws Exception {
		String enc = getEnc(request);
		if (enc == null) {
			return null;
		}

		Map<String, String> encMap = new HashMap<String, String>();
		String[] enc0 = enc.split("[&]");
		for (String enc1 : enc0) {
			String[] enc2 = enc1.split("[=]");

			if (enc2 != null) { 
				String key = enc2[0];
				String value = enc2.length == 2 ? enc2[1] : null;
				if(null!=value){
					value= URLEncoder.encode(value);
					value= value.replaceAll("%3F", ""); 
					value= URLDecoder.decode(value); 
					
				}
				encMap.put(key, value);
				if("MID".equals(key)) {
					break;
				}
			}
		}
		long memberId = -1;		
		String _messageId = encMap.get("MID");
		if (_messageId == null) {
			return null;
		}
		Long messageId = Long.parseLong(_messageId);
		UserHistoryMessage msg = this.userMessageManager.getUserHistoryMsgById(messageId);
		if(msg == null) {
            return null;
		}
		memberId = msg.getReceiverId();
		V3xOrgMember member= orgManager.getMemberById(memberId);
		
		return member;
	} 
	
	private Map<String,String> parseEnc(String enc){
		Map<String, String> encMap = new HashMap<String, String>();
		String[] enc0 = enc.split("[&]");
		for (String enc1 : enc0) {
			String[] enc2 = enc1.split("[=]");

			if (enc2 != null) { 
				String key = enc2[0];
				String value = enc2.length == 2 ? enc2[1] : null;
				if(null!=value){
					value= URLEncoder.encode(value);
					value= value.replaceAll("%3F", ""); 
					value= URLDecoder.decode(value); 
				}
				encMap.put(key, value);
			}
		}
		return encMap;
	}
	
	private String getEnc(HttpServletRequest request) {
		String chainId = request.getParameter("chainId");
		String enc = null;
		if(request.getParameter("enc")!=null){
			enc = LightWeightEncoder.decodeString(request.getParameter("enc").replaceAll(" ", "+"));
		}else if(Strings.isNotBlank(chainId)){
			String chain = shortChainInterface.updateChainCountAndQuery(chainId);
			if(Strings.isNotBlank(chain)) {
				enc = LightWeightEncoder.decodeString(chain.replaceAll(" ", "+"));
			}
		}else{
			String transcode= URLDecoder.decode(request.getQueryString().split("enc=")[1]);
			enc= request.getQueryString().indexOf("enc=")>0?LightWeightEncoder.decodeString(transcode):null;
		}
		return enc;
	}

}
