package com.shuzijun.leetcode.plugin.window; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.codebrig.journey.JourneyBrowserView; import com.codebrig.journey.JourneyLoader; import com.codebrig.journey.proxy.CefBrowserProxy; import com.codebrig.journey.proxy.browser.CefFrameProxy; import com.codebrig.journey.proxy.callback.CefCookieVisitorProxy; import com.codebrig.journey.proxy.handler.CefLoadHandlerProxy; import com.codebrig.journey.proxy.misc.BoolRefProxy; import com.codebrig.journey.proxy.network.CefCookieManagerProxy; import com.codebrig.journey.proxy.network.CefCookieProxy; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.FrameWrapper; import com.intellij.ui.components.JBPanel; import com.shuzijun.leetcode.plugin.manager.ViewManager; import com.shuzijun.leetcode.plugin.model.Config; import com.shuzijun.leetcode.plugin.setting.PersistentConfig; import com.shuzijun.leetcode.plugin.utils.*; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.jetbrains.annotations.NotNull; import org.joor.Reflect; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.lang.reflect.Proxy; import java.net.HttpCookie; import java.util.ArrayList; import java.util.List; /** * @author shuzijun */ public class LoginFrame extends FrameWrapper { private JTree tree; private Project project; private boolean isComponent = false; public LoginFrame(Project project, JTree tree) { super(project); this.tree = tree; this.project = project; } public void loadComponent() { isComponent = true; if (classLoader()) { loadJCEFComponent(); setTitle("login"); } else { loadCookieComponent(); setSize(new Dimension(400, 200)); setTitle("login cookie"); } } private void loadJCEFComponent() { JourneyBrowserView browser = new JourneyBrowserView(URLUtils.getLeetcodeLogin()); this.getFrame().addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { browser.getCefClient().dispose(); } }); browser.getCefClient().addLoadHandler(CefLoadHandlerProxy.createHandler(new CefLoadHandlerProxy() { @Override public void onLoadingStateChange(CefBrowserProxy cefBrowserProxy, boolean b, boolean b1, boolean b2) { LogUtils.LOG.debug("onLoadEnd:" + cefBrowserProxy.getURL()); if (CefCookieManagerProxy.getGlobalManager() != null) { final List<HttpCookie> cookieList = new ArrayList<>(); final Boolean[] isSession = {Boolean.FALSE}; boolean v = CefCookieManagerProxy.getGlobalManager().visitAllCookies(CefCookieVisitorProxy.createVisitor(new CefCookieVisitorProxy() { @Override public boolean visit(CefCookieProxy cefCookieProxy, int count, int total, BoolRefProxy boolRefProxy) { Object cefCookie = ((Reflect.ProxyInvocationHandler) Proxy.getInvocationHandler(cefCookieProxy)).getUnderlyingObject(); if (Reflect.on(cefCookie).field("domain").toString().contains("leetcode")) { HttpCookie cookie = new HttpCookie(Reflect.on(cefCookie).field("name").toString(), Reflect.on(cefCookie).field("value").toString()); cookie.setDomain(Reflect.on(cefCookie).field("domain").toString()); cookie.setPath(Reflect.on(cefCookie).field("path").toString()); cookieList.add(cookie); if ("LEETCODE_SESSION".equals(Reflect.on(cefCookie).field("name").toString())) { isSession[0] = Boolean.TRUE; } } if (count == total - 1 && isSession[0]) { HttpRequestUtils.setCookie(cookieList); if (HttpRequestUtils.isLogin()) { Config config = PersistentConfig.getInstance().getInitConfig(); config.addCookie(config.getUrl() + config.getLoginName(), CookieUtils.httpCookieToJSONString(cookieList)); PersistentConfig.getInstance().setInitConfig(config); ViewManager.loadServiceData(tree, project); httpLogin.examineEmail(project); cefBrowserProxy.executeJavaScript("alert('Login is successful. Please close the window')", "leetcode-editor", 0); } else { LogUtils.LOG.info("login failure"); } } return true; } })); } } @Override public void onLoadEnd(CefBrowserProxy cefBrowserProxy, CefFrameProxy cefFrameProxy, int i) { } @Override public void onLoadError(CefBrowserProxy cefBrowserProxy, CefFrameProxy cefFrameProxy, CefLoadHandlerProxy.ErrorCode errorCode, String s, String s1) { cefFrameProxy.executeJavaScript("alert('The page failed to load, please check the network and open it again')", "leetcode-editor", 0); } })); this.setComponent(browser); } private void loadCookieComponent() { JBPanel panel = new JBPanel(); panel.setLayout(new BorderLayout()); JTextArea cookieText = new JTextArea(); cookieText.setLineWrap(true); cookieText.setMinimumSize(new Dimension(400, 200)); cookieText.setPreferredSize(new Dimension(400, 200)); panel.add(cookieText, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); JButton cookieHelp = new JButton("help"); cookieHelp.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { BrowserUtil.browse("https://github.com/shuzijun/leetcode-editor/blob/master/doc/LoginHelp.md"); } }); JButton loginButton = new JButton("login"); loginButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String cookiesString = cookieText.getText(); if (StringUtils.isBlank(cookiesString)) { JOptionPane.showMessageDialog(null, "cookie is null"); return; } final List<HttpCookie> cookieList = new ArrayList<>(); String[] cookies = cookiesString.split(";"); for (String cookieString : cookies) { String[] cookie = cookieString.trim().split("="); if (cookie.length >= 2) { HttpCookie basicClientCookie = new HttpCookie(cookie[0], cookie[1]); basicClientCookie.setDomain("." + URLUtils.getLeetcodeHost()); basicClientCookie.setPath("/"); cookieList.add(basicClientCookie); } } HttpRequestUtils.setCookie(cookieList); ProgressManager.getInstance().run(new Task.Backgroundable(project, "leetcode.editor.login", false) { @Override public void run(@NotNull ProgressIndicator progressIndicator) { if (HttpRequestUtils.isLogin()) { Config config = PersistentConfig.getInstance().getInitConfig(); config.addCookie(config.getUrl() + config.getLoginName(), CookieUtils.httpCookieToJSONString(cookieList)); PersistentConfig.getInstance().setInitConfig(config); MessageUtils.getInstance(project).showInfoMsg("info", PropertiesUtils.getInfo("login.success")); ViewManager.loadServiceData(tree, project); httpLogin.examineEmail(project); return; } else { JOptionPane.showMessageDialog(null, PropertiesUtils.getInfo("login.failed")); return; } } }); close(); } }); JButton closeButton = new JButton("close"); closeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { close(); } }); buttonPanel.add(loginButton); buttonPanel.add(cookieHelp); buttonPanel.add(closeButton); panel.add(buttonPanel, BorderLayout.SOUTH); this.setComponent(panel); } private boolean classLoader() { synchronized (this) { String path = PathManager.getPluginsPath() + File.separator + "leetcode-editor" + File.separator + "natives" + File.separator; if (!new File(path, "icudtl.dat").exists() && !new File(path, "jcef_app.app").exists()) { return Boolean.FALSE; } else { JourneyLoader.getJourneyClassLoader(path); return Boolean.TRUE; } } } public static class httpLogin { public static boolean ajaxLogin(Config config, JTree tree, Project project) { if (StringUtils.isBlank(PersistentConfig.getInstance().getPassword())) { return Boolean.FALSE; } try { HttpEntity ent = MultipartEntityBuilder.create() .addTextBody("csrfmiddlewaretoken", HttpRequestUtils.getToken()) .addTextBody("login", config.getLoginName()) .addTextBody("password", PersistentConfig.getInstance().getPassword()) .addTextBody("next", "/problems") .build(); HttpRequest httpRequest = HttpRequest.post(URLUtils.getLeetcodeLogin(),ent.getContentType().getValue()); httpRequest.setBody(IOUtils.toString(ent.getContent(),"UTF-8")); httpRequest.addHeader("x-requested-with", "XMLHttpRequest"); httpRequest.addHeader("accept", "*/*"); HttpResponse response = HttpRequestUtils.executePost(httpRequest); if (response == null) { MessageUtils.getInstance(project).showWarnMsg("warning", PropertiesUtils.getInfo("request.failed")); return Boolean.FALSE; } String body = response.getBody(); if ((response.getStatusCode() == 200 || response.getStatusCode() == 302)) { if (StringUtils.isNotBlank(body) && body.startsWith("{")) { JSONObject jsonObject = JSONObject.parseObject(body); JSONArray jsonArray = jsonObject.getJSONObject("form").getJSONArray("errors"); if (jsonArray.isEmpty()) { MessageUtils.getInstance(project).showInfoMsg("info", PropertiesUtils.getInfo("login.success")); examineEmail(project); ViewManager.loadServiceData(tree, project); return Boolean.TRUE; } else { MessageUtils.getInstance(project).showInfoMsg("info", StringUtils.join(jsonArray, ",")); return Boolean.FALSE; } } else if (StringUtils.isBlank(body)) { MessageUtils.getInstance(project).showInfoMsg("info", PropertiesUtils.getInfo("login.success")); examineEmail(project); ViewManager.loadServiceData(tree, project); return Boolean.TRUE; } else { HttpRequestUtils.resetHttpclient(); MessageUtils.getInstance(project).showInfoMsg("info", PropertiesUtils.getInfo("login.unknown")); SentryUtils.submitErrorReport(null, String.format("login.unknown:\nStatusCode:%s\nbody:%s", response.getStatusCode(), body)); return Boolean.FALSE; } } else if (response.getStatusCode() == 400) { JSONObject jsonObject = JSONObject.parseObject(body); MessageUtils.getInstance(project).showInfoMsg("info", StringUtils.join(jsonObject.getJSONObject("form").getJSONArray("errors"), ",")); return Boolean.FALSE; } else { HttpRequestUtils.resetHttpclient(); MessageUtils.getInstance(project).showInfoMsg("info", PropertiesUtils.getInfo("login.unknown")); SentryUtils.submitErrorReport(null, String.format("login.unknown:\nStatusCode:%s\nbody:%s", response.getStatusCode(), body)); return Boolean.FALSE; } } catch (Exception e) { LogUtils.LOG.error("登陆错误", e); MessageUtils.getInstance(project).showInfoMsg("info", PropertiesUtils.getInfo("login.failed")); return Boolean.FALSE; } } public static void examineEmail(Project project) { ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { @Override public void run() { HttpRequest httpRequest = HttpRequest.post(URLUtils.getLeetcodeGraphql(),"application/json"); try { httpRequest.setBody("{\"operationName\":\"user\",\"variables\":{},\"query\":\"query user {\\n user {\\n socialAccounts\\n username\\n emails {\\n email\\n primary\\n verified\\n __typename\\n }\\n phone\\n profile {\\n rewardStats\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}"); httpRequest.addHeader("Accept", "application/json"); HttpResponse response = HttpRequestUtils.executePost(httpRequest); if (response != null && response.getStatusCode() == 200) { String body = response.getBody(); JSONArray jsonArray = JSONObject.parseObject(body).getJSONObject("data").getJSONObject("user").getJSONArray("emails"); if (jsonArray != null && jsonArray.size() > 0) { for (int i = 0; i < jsonArray.size(); i++) { JSONObject object = jsonArray.getJSONObject(i); if (object.getBoolean("verified")) { return; } } } MessageUtils.getInstance(project).showWarnMsg("info", PropertiesUtils.getInfo("user.email")); } } catch (Exception i) { LogUtils.LOG.error("验证邮箱错误"); } } }); } } }