package com.elminster.retrieve.psn.runnable; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.elminster.common.constants.Constants.StringConstants; import com.elminster.common.constants.FileExtensionConstants; import com.elminster.common.retrieve.RetrieveException; import com.elminster.common.util.DateUtil; import com.elminster.common.util.FileUtil; import com.elminster.retrieve.psn.constants.PropertyKey; import com.elminster.retrieve.psn.exception.LoginFailedException; import com.elminster.retrieve.psn.util.Configuration; import com.elminster.retrieve.psn.util.SystemSetting; import com.elminster.retrieve.web.CookieInjectRetriever; import com.elminster.retrieve.web.cookie.PermitAllCookiesSpec; import com.elminster.retrieve.web.data.Method; /** * The base retriever. * * @author jgu * @version 1.0 */ public class BaseRetriever extends CookieInjectRetriever { /** the logger. */ private static final Log logger = LogFactory.getLog(BaseRetriever.class); /** the configuration. */ private static final Configuration configuration = Configuration.INSTANCE; /** the system setting. */ private static final SystemSetting systemSetting = SystemSetting.INSTANCE; /** the cookie file. */ public static final String COOKIE_FILE = "cookie/" + systemSetting.getPSNUsername() + FileExtensionConstants.TEXT_EXTENSION; private static final String LANG = "ja"; /** * Constructor. * * @param url * the url * @param parser * the parser */ public BaseRetriever(String url) { super(url, Method.GET_METHOD); } /** * Check the cookie valid or not. * * @return check wether the cookie is valid or not. */ private boolean checkCookieValid() { File cookieFile = new File(COOKIE_FILE); if (cookieFile.exists()) { // TODO need to be checked long lastApiCalledTime = systemSetting.getLastApiCalledTime(); if (System.currentTimeMillis() - lastApiCalledTime > DateUtil.DAY) { // expired return false; } return true; } return false; } /** * Login into the PSN. * * @throws IOException * on error * @throws URISyntaxException * on error * @throws LoginFailedException * when login failed */ private void loginIntoPSN() throws IOException, URISyntaxException, LoginFailedException { HttpClient client = new HttpClient(); CookiePolicy.registerCookieSpec("PermitAllCookiesSpec", PermitAllCookiesSpec.class); client.getParams().setCookiePolicy("PermitAllCookiesSpec"); // get base info from public profile String loginUrl = configuration.getStringProperty(PropertyKey.PSN_LOGIN_URL); String oathUrl = configuration.getStringProperty(PropertyKey.PSN_OATH_URL); String magicNumber = configuration.getStringProperty(PropertyKey.PSN_LOGIN_MAGIC_NUMBER); String username = systemSetting.getPSNUsername(); String userpassword = systemSetting.getPSNPassword(); // login PostMethod loginMethod = new PostMethod(); loginMethod.setURI(new URI(loginUrl, false)); loginMethod.setRequestHeader("Host", "auth.api.sonyentertainmentnetwork.com"); loginMethod.setRequestHeader("Connection", "keep-alive"); loginMethod.setRequestHeader("Cache-Control", "max-age=0"); loginMethod .setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); loginMethod.setRequestHeader("Origin", "https://auth.api.sonyentertainmentnetwork.com"); loginMethod.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"); loginMethod.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); loginMethod.setRequestHeader("Accept-Encoding", "gzip, deflate"); loginMethod.setRequestHeader("Accept-Language", LANG); loginMethod.setRequestHeader("AlexaToolbar-ALX_NS_PH", "AlexaToolbar/alxg-3.3"); // j_username // j_password loginMethod.addParameter(new NameValuePair("j_username", username)); loginMethod.addParameter(new NameValuePair("j_password", userpassword)); // the magic number loginMethod.addParameter(new NameValuePair("params", magicNumber)); int status = client.executeMethod(loginMethod); // the login will returns 302 sometimes. if (200 != status && 302 != status) { throw new LoginFailedException("login returns " + status); } if (logger.isDebugEnabled()) { logger.debug("response from login: " + loginMethod.getResponseBodyAsString()); } // // get next url // // if (null != responseHeaders) { // for (Header h : responseHeaders) { // System.out.println(h); // // if ("Location".equals(h.getName())) { // // nextUrl = h.getValue(); // // } // } // } logger.info("login with OATH."); StringBuilder cookie = new StringBuilder(); Cookie[] cookies = client.getState().getCookies(); for (Cookie c : cookies) { cookie.append(c.toString()).append(StringConstants.SEMICOLON); } if (logger.isDebugEnabled()) { logger.debug("cookies to set: " + cookie.toString()); } GetMethod oathMethod = new GetMethod(); oathMethod.setURI(new URI(oathUrl, false)); oathMethod.setRequestHeader("Host", "secure.us.playstation.com"); oathMethod.setRequestHeader("Connection", "keep-alive"); oathMethod.setRequestHeader("Cache-Control", "max-age=0"); oathMethod.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); oathMethod.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"); oathMethod.setRequestHeader("Referer", "https://auth.api.sonyentertainmentnetwork.com/login.jsp?service_entity=psn&request_theme=liquid"); oathMethod.setRequestHeader("Accept-Encoding", "gzip, deflate, sdch"); oathMethod.setRequestHeader("Accept-Language", LANG); oathMethod.setRequestHeader("AlexaToolbar-ALX_NS_PH", "AlexaToolbar/alxg-3.3"); oathMethod.setRequestHeader("Cookie", cookie.toString()); status = client.executeMethod(oathMethod); if (200 != status) { throw new LoginFailedException("oath returns " + status); } // FIXME check login success String oathResponse = oathMethod.getResponseBodyAsString(); if (logger.isDebugEnabled()) { logger.debug("response from OATH: " + oathResponse); } if (oathResponse.contains("signInPage")) { throw new LoginFailedException("login denied. please check username and password again."); } writeCookies(client); // release the client client = null; } /** * Write the cookies into a cache file. * * @param client * the http client * @throws IOException * on error */ private void writeCookies(HttpClient client) throws IOException { StringBuilder cookie = new StringBuilder(); Cookie[] cookies = client.getState().getCookies(); boolean first = true; for (Cookie c : cookies) { if (first) { first = false; } else { cookie.append(StringConstants.AND); } cookie.append(c.getName()); cookie.append(StringConstants.EQUAL); cookie.append(c.getValue()); } FileUtil.writeLine2file(cookie.toString(), COOKIE_FILE, false); } /** * Read the cookies from saved cookie file. * * @return the cookies * @throws IOException * on error */ protected Cookie[] readCookies() throws Exception { if (!checkCookieValid()) { try { loginIntoPSN(); } catch (URISyntaxException | LoginFailedException e) { throw e; } } systemSetting.updateLastApiCalledTime(); Cookie[] co = null; File cookieFile = new File(COOKIE_FILE); if (cookieFile.exists()) { String cookieInfo = FileUtil.readFile2String(cookieFile.getAbsolutePath()); if (null != cookieInfo) { String[] cookies = cookieInfo.split(StringConstants.AND); co = new Cookie[cookies.length]; int i = 0; for (String cookie : cookies) { String[] split = cookie.split(StringConstants.EQUAL); String cookieKey = split[0]; String cookieValue = split[1]; if (logger.isDebugEnabled()) { logger.debug("cookie: " + cookieKey + "=" + cookieValue); } // update the expiration to 1 day. co[i++] = createCookie("playstation", cookieKey, cookieValue, "/", DateUtil.DAY); } } } else { throw new IllegalStateException("Cookie file doesn't exist"); } return co; } @Override protected void configHttpMethod(HttpClient client, HttpMethod httpMethod) throws RetrieveException { httpMethod.setRequestHeader("Host", "io.playstation.com"); httpMethod.setRequestHeader("Connection", "keep-alive"); httpMethod.setRequestHeader("Accept", "application/json, text/javascript, */*; q=0.01"); httpMethod.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"); httpMethod.setRequestHeader("Referer", "https://www.playstation.com/en-us/my/compare-game-trophies/"); httpMethod.setRequestHeader("Accept-Encoding", "gzip, deflate, sdch"); httpMethod.setRequestHeader("Origin", "https://www.playstation.com"); httpMethod.setRequestHeader("Accept-Language", LANG); httpMethod.setRequestHeader("AlexaToolbar-ALX_NS_PH", "AlexaToolbar/alxg-3.3"); } }