Package net.traviangui.hostInterface

Source Code of net.traviangui.hostInterface.HttpServer$Pair

package net.traviangui.hostInterface;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.MissingResourceException;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.traviangui.hostInterface.HttpServer.Pair.IntPair;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.cookie.CookieSpec;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.params.HttpMethodParams;


/**
* In VilloNanny, there is one instance of Util per Server.
*
*/
public class HttpServer
{
    private static final Logger log = Logger.getLogger( HttpServer.class.toString());
    public static final String USERAGENT_DEFAULT = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
    private static final String PATTERN_UTIL_SRC = "src=\"([^\"\\\\?]*)[^\"]*\"";
    private static final String PATTERN_IS_LOGIN_PAGE = "<input\\\\s*type\\\\s*=\\\\s*\"image\"\\\\s*value\\\\s*=\\\\s*\"login\"";

    private static final String SERVER_URL      = "http://s3.travian.net";
    private static final String SERVER_LOGIN    = "magius";
    private static final String SERVER_PASSWORD = "3antonio";
   
    private HttpClient client;
   
    public String httpGetPage(String urlString) throws Exception
    {
        int remaningTries = 3;
       
        String page = "";
        while( remaningTries > 0) {
            remaningTries--;
            try {
                page = httpGetPage( urlString, false);
            } catch ( Exception e) {
                log.warning( "Error getting html page...");
            }
        }
        return page;
    }
   
    public String httpGetPage( String urlString, boolean quick) throws Exception
    {
        log.finest( "Getting " + urlString + " (with login check) ...");
        if (urlString==null) {
            log.warning( "Nothing to get");
            return "";
        }
        String page = httpGetPageNoLogin( urlString, quick);
        // Check if login page returned, and perform login
        if( isLoginPage( page)) {
            String s = "Login page returned; performing login for " + urlString;
//          log.debug(s);
            //EventLog.log(s);
            page = loginWithPage( page, urlString, quick);
            if (isLoginPage(page)) {
                throw new ConversationException("Can't login");
            }
            // Now fetch original page again because we might get the wrong village otherwise
            page = httpGetPageNoLogin( urlString, quick);
        }      
        log.finest( "Got (with login check) " + urlString);
        return page;
    }
   
    public String httpGetPageNoLogin(String urlString, boolean quick) throws ConversationException, InterruptedException
    {
//        console.checkFlags();
        // GAC modify to run from local files for decoupled debug
        testMode = 0; //configManager.getInt("testMode/@httpGet", 0);   

          if    ((testMode & 1) == 1) {
                // log.debug("GAC Getting " + urlString + " from DiskFile " + fname);
                String page = null;
                try {
                    page = readFromFile(urlString);
                    // return the page
                    return page;
                } catch (IOException e) {
                    // GAC - check if in read/write mode, in which case ignore the error and carry on to access page
                    if  ((testMode & 2) == 2) {
                        // Warn what we are doing
//                        EventLog.log("Cannot Find Page on Disk " + urlString + " ***** Getting from Server");
                        log.info( "Cannot Find Page on Disk " + urlString + " ***** Getting from Server");
                    } else {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        // GAC just exit for now - create missing file manually and restart!
                        System.exit(-1);
                    }
                }
          }     // else {       // GAC added for test mode, returns above so just continue rather than make second change
       
        GetMethod get = new GetMethod(urlString);
        addHeaders(get);
        try {
            log.finest("Getting " + urlString + " ...");
            client.executeMethod(get);
           
            // Save the url for reference header
            lastVisitPage = urlString;
           
            String page = get.getResponseBodyAsString();
           
            // Find src fields and load them to simulate real browser
            // Pattern p = Pattern.compile(" src=\"([^\"\\?]*)[^\"]*\"");
            Pattern p = getPattern( PATTERN_UTIL_SRC);
            Matcher m = p.matcher(page);
            try {
                while (m.find()) {
                    String src = m.group(1);
                    getIfNotCachedAndDrop(urlString, src);
                }
            } catch (IndexOutOfBoundsException e) {
                saveTestPattern("util.src", p, page);
                throw new ConversationException(e);
            }
            // GAC add mode to write file to disk
            if  ((testMode & 2) == 2) {
                writeToFile(urlString, page);
            }

            return page;
        } catch (java.net.ConnectException e) {
            throw new ConversationException("Connection to \"" + urlString + "\" failed (check network/proxy setup).", e);
        } catch (IOException e) {
            throw new ConversationException("Can't read page " + urlString, e);
        } finally {
            get.releaseConnection();
            Thread.sleep( 2*1000);
            log.finest("Got " + urlString);
        }      
    }

    /**
     * Force login
     * @throws Exception
     */
    public void login(boolean sharp) throws Exception {
        int counter = 2; // retries
        while (true) {
            try {
                String loginUrlString = SERVER_URL;
                // Get login form. The method will detect the login page and perform login for us
                httpGetPage(loginUrlString);
                break;
            } catch (ConversationException e) {
                log.finest("Login failed: " + e.getMessage());
                log.severe( e.toString());
                if (counter-- > 0) {
                    log.finest("Retrying...");
                    Thread.sleep( 2*1000);
                } else {
                    log.severe("Login error ");
                    throw e;
                }
            }
        }
    }
   
    /**
     *
     * @throws Exception
     * @loginForm the html page containing the login form
     * @urlString the url that returned the login form
     */
    private String loginWithPage(String loginForm, String urlString, boolean quick) throws Exception {
        Pattern p;
        Matcher m;
        fillLoginParameters( loginForm, urlString);
        String loginPostString = baseUrl + "dorf1.php";
        Calendar localTime = new GregorianCalendar();
        localTime.set(Calendar.YEAR, 1970);
        localTime.set(Calendar.MONTH, Calendar.JANUARY);
        localTime.set(Calendar.DAY_OF_MONTH, 1);
        String pageAfterLogin = httpPostPage(loginPostString, loginPostNames, loginPostValues, quick);
        // See if we got any cookies
        CookieSpec cookiespec = CookiePolicy.getDefaultSpec();
        Cookie[] logoncookies = cookiespec.match(serverHost, serverPort, "/", false, client.getState().getCookies());
        if (logoncookies.length==0) {
            this.loginPassword=null;
            throw new ConversationException("Authentication failed");
        }
        log.info("Authentication ok");
        // Find server time
         p = Pattern.compile("(?s)id=\"tp1\"[^>]*>(.*?)</span>");
//        p = getPattern("util.serverTime");
        m = p.matcher(pageAfterLogin);
        if (m.find()) {
            String serverTimeString = m.group(1);
            Date serverDate;
            try {
                serverDate = timeFormat.parse(serverTimeString); // TODO timezone del server
            } catch (ParseException e) {
                throw new ConversationException("Can't parse server time: " + serverTimeString);
            }
            this.serverTimeMillisDelta = localTime.getTimeInMillis() - serverDate.getTime();
        } else {
            if (isSurveyPage(pageAfterLogin)) {
                log.finest("Survey page or broadcast msg detected, see logs for more details!");
                log.fine(pageAfterLogin);
                // survey or broadcast message is present
                httpGetPage(HttpServer.getFullUrl(urlString, "dorf1.php?ok=1"));
            }
            throw new ConversationException("Can't find server time");
        }
        return pageAfterLogin;
    }

   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
  private static final String ERROR_MESSAGE_BUNDLE_NAME = "Messages";
  private static boolean utf8;
  public static final long MILLI_SECOND = 1000;
  public static final long MILLI_MINUTE = 60 * MILLI_SECOND;
  public static final long MILLI_HOUR = 60 * MILLI_MINUTE;
  private String serverHost;
  private int serverPort;
  private List<String> loginPostNames;
  private List<String> loginPostValues;
  private String loginPassword = null; // Remember password when typed by user
  private long serverTimeMillisDelta=0; // Difference between PC time and server time in milliseconds (>0 if server lower)
  private String baseUrl; // http://s1.travian3.it/
  private SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");;
//  private SimpleDateFormat completionTimeFormat = new SimpleDateFormat("HH:mm");
//  private int redirectCounter = 0;
  private String lastVisitPage = "";
  public static final String P_FLAGS = "(?s)(?i)(?u)"; // dotall, case insensitive, unicode case match
  private static int screenx = 1280;
  private static int screeny = 1024;
  private static int uidCounter = 0;

  private static int testMode = 0;    // GAC add mode to run from saved pages on disk
  private static String  TEST_DIR = "logs" + File.separator + "TestPages-";    // and the root of a location for them
    private static HttpServer instance;
  /*
   *  GAC added for test mode 
   *   Fetch entire contents of a text file and return as a string, use to load pages from disk if doing repeated testing
   *     controlled by global config variable  <testMode  httpGet="1" />
   *  the files are stored in a sub directory specified by TEST_DIR with the language appended to seperate them
   *
   *  Based on PatternDebugger routine but without header so can save source pages as files from browser using view source
   *    mode 1 - read from disk, currently does a hard exit if cannot find a page to support simple debug strategy 
   *    mode 2 - write all pages to disk, coverts . and ? characters to _ and appends .txt for easy access from text editors
   *  TODO mode 3, read from disk until cannot find a page then fetch it and write it
   *      - does not always work because of cookies error
   */
  private String readFromFile(String urlString) throws IOException {
    // build directory from base + language specific so store identical named pages in different location
    String inputDir = TEST_DIR + "es";
      String filePath = null;
    // extend to include server as a sub directory - control via config variable?
      filePath = urlString.substring(urlString.indexOf('/', 1)+2, urlString.indexOf('.', 1) );
      inputDir = inputDir + File.separator + filePath;
      // EventLog.log("Getting URL from Disk " + urlString + " Translator " + getTranslator().getLanguage() );
      // log.debug("GAC Getting URL from Disk " + urlString);
      if ( urlString.indexOf('/', 8) > 0) {
        filePath = inputDir + File.separator + urlString.substring(1+urlString.indexOf('/', 8));    // GAC get name at end of string after first http://
      } else {
        // no substring
        filePath = inputDir + File.separator + "dorf1.php";
      }
    // store base Url as not calling login
    baseUrl = urlString.substring(0, urlString.indexOf("/", "http://".length()) + 1);
      // check for characters that are not valid in filenames and then add .txt to make into safe windows file
    filePath = filePath.replace('?', '_');
    filePath = filePath.replace('.', '_');
    filePath = filePath.concat(".txt");
      // default the map look ups so dont have to do all of them
      if (filePath.indexOf("&c=") !=-1) {
        // check if have this one
        File f = new File(filePath);
        if (f.exists()) {
          // all ok use it
        } else {
          // default to an unoccupied valley - needs to be saved manually
          filePath = TEST_DIR + "es" + File.separator + "karte_php_unoccupied.txt";     
       
      }
      log.finest("Getting " + urlString + " from DiskFile \"" + filePath + "\"");
    BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
    /*
    String line = in.readLine(); // date
    if (line==null) {
      throw new IOException("Empty file");
    }
    this.desc = in.readLine();
    if (this.desc == null) {
      throw new IOException("File too short: missing description on second line");
    }
    log.info("Description: " + desc);
    String patternString = in.readLine();
    if (patternString==null) {
      throw new IOException("File too short: missing pattern on third line");
    }
    log.info("patternString: " + patternString);
    this.pattern = Pattern.compile(patternString);
    */
    StringBuffer pageBuffer = new StringBuffer();
    String line = in.readLine();
    while (line!=null) {
      pageBuffer.append(line + "\n");
      line = in.readLine();
    }
    in.close();
    return pageBuffer.toString();
  }
 
  public void writeToFile(String urlString, String page) {
    String outputDir = TEST_DIR + "es";
    String outputFilename = null;
    // GAC add server as subdirectory
    outputFilename = urlString.substring(urlString.indexOf('/', 1)+2, urlString.indexOf('.', 1) );
      outputDir = outputDir + File.separator + outputFilename;
      // EventLog.log("Getting URL from Disk " + urlString);
      log.fine( "Write URL to Disk " + urlString);
      if ( urlString.indexOf('/', 8) > 0) {
        outputFilename = urlString.substring(urlString.indexOf('/', 8) + 1);    // GAC get name at end of string after first http://
      } else {
        // no substring
        outputFilename = "dorf1.php";
      }
    // store base Url as not calling login
    baseUrl = urlString.substring(0, urlString.indexOf("/", "http://".length()) + 1);
      // check for characters that are not valid in filenames and then add .txt to make into safe windows file
    outputFilename = outputFilename.replace('?', '_');
    outputFilename = outputFilename.replace('.', '_');
    outputFilename = outputFilename.concat(".txt");
      // GAC dont default the map look ups so one day may have all of them
   
    // String outputFilename = "match" +  pattern.toString().hashCode() + ".txt";
    // Globally synchronized to avoid file corruption when writing concurrently from different "servers"
    // GAC Performance may be an issue if used a lot
    // TODO - add server name into directory structure
    synchronized (HttpServer.class) {
      try {
        File outDirFile = new File(outputDir);
        if (!outDirFile.exists()) {
          log.fine("Creating directory " + outDirFile.getAbsolutePath());
          outDirFile.mkdirs();
        }
        String fullPath = outputDir + File.separator + outputFilename;
        PrintWriter out = new PrintWriter(new File(fullPath), "utf8");
        // out.println(new Date());
        // out.println(desc);
        // out.println(pattern.toString());
        out.println(page);
        out.close();
        log.fine("Page saved to file " + fullPath);
      } catch (IOException e) {
        log.severe("Cannot output page to file" + e.toString());
      }
    }
  }
 

  // Used by AutoConfigurator only to create a minimal Util
  public HttpServer() {
    this.client = getHttpClient();
  }
 
 
  /**
   * Return a unique identifier
   * @param prefix
   * @return
   */
  public static synchronized String getNewUid(String prefix) {
    uidCounter++;
    // This is reasonably unique and short
    return prefix + String.valueOf(System.currentTimeMillis()/1000 % 10000000) + uidCounter;
  }

  public static void log(String message, Exception e) {
    log.severe( message + ": " + e.toString());
  }
 
 
  private boolean isSurveyPage(String page) {
      // Pattern p = Pattern.compile("dorf1.php\\?ok=1");
    Pattern p = getPattern("util.isSurveyPage");
      Matcher m = p.matcher(page);
      return m.find();
  }
 
  private void fillLoginParameters(String loginForm, String urlString) throws Exception
  {
    URL loginUrl;
    if (!urlString.endsWith("/")) {
      urlString += "/";
    }
    try {
      loginUrl = new URL(urlString);
    } catch (MalformedURLException e) {
      throw new Exception( "loginUrl for server is invalid. " + e.toString());
    }
    baseUrl = urlString.substring(0, urlString.indexOf("/", "http://".length()) + 1);
    serverHost = loginUrl.getHost();
    serverPort = loginUrl.getPort();
    if (serverPort==-1) {
      serverPort = loginUrl.getDefaultPort();
      if (serverPort==-1) {
        serverPort = 80;
      }
    }
    loginPostNames = new ArrayList<String>();
    loginPostValues = new ArrayList<String>();
    // Find username field
    String userNameField;
    // Pattern p = Pattern.compile("<input .* type=\"text\".*name=\"(.*?)\"");
    Pattern p = getPattern("<input .* type=\"text\" name=\"(.*?)\"");
    Matcher m = p.matcher(loginForm);
    if (m.find()) {
      userNameField = m.group(1);
    } else {
      saveTestPattern("util.userNameField", p, loginForm);
      throw new ConversationException("Can't find username input field");
    }
    if (m.find()) {
      log.warning( "Too many username input fields; ignoring...");
    }
    loginPostNames.add(userNameField);
    String user = SERVER_LOGIN;
    loginPostValues.add(user);
    // Find password field
    String pwdField;
     p = Pattern.compile("<input .*type=\"password\".*name=\"(.*?)\"");
//    p = getPattern("util.pwdField");
    m = p.matcher(loginForm);
    if (m.find()) {
      pwdField = m.group(1);
    } else {
      saveTestPattern("util.pwdField", p, loginForm);
      throw new ConversationException("Can't find password input field");
    }
    if (m.find()) {
      log.warning("Too many password input fields; ignoring...");
    }
    loginPostNames.add(pwdField);
    String pwd = SERVER_PASSWORD;
    if (pwd==null) {
      pwd = this.loginPassword;
      if (pwd==null) {
          log.finest("Waiting for password input");
        pwd = inputLine("Type the password for " + user + " on " + ": ");
        this.loginPassword = pwd;
      }
    }
    loginPostValues.add(pwd);
    // Find all hidden fields
     addHiddenPostFields(loginForm, "<form method=\"post\" name=\"snd\" action=\"dorf1.php\">", loginPostNames, loginPostValues);
//    addHiddenPostFields(loginForm, "util.hiddenPostFields", loginPostNames, loginPostValues);
    // Add button params
    addButtonCoordinates("s1", "login", 80, 20, loginPostNames, loginPostValues);
    try {
      int pos = loginPostNames.indexOf("w");
      loginPostValues.set(pos, screenx + ":" + screeny); // %3A = ":"
    } catch (Exception e) {
      log.warning("Can't find login parameter 'w' (ignoring)");
    }
    // Other params
//    loginPostNames.add("autologin");
//    loginPostValues.add("ja");
  }
 
  public static void addButtonCoordinates(String prefix, String value, int x, int y, List<String> names, List<String> values)
  {
        names.add( prefix);
        values.add( value);

        int vx = (int) (Math.random() * x);
    int vy = (int) (Math.random() * y);
    names.add(prefix + ".x");
    values.add(Integer.toString(vx));
    names.add(prefix + ".y");
    values.add(Integer.toString(vy));
  }

  /**
   * @return the start position of the form
   */
  public int addHiddenPostFields(String page, String patternKey, List<String> names, List<String> values) throws ConversationException {
    Pattern p;
    Matcher m;
    // Find start of form
    // p = Pattern.compile(startFromPattern);
    p = getPattern(patternKey);
    m = p.matcher(page);
    if (!m.find()) {
      saveTestPattern(patternKey, p, page);
      throw new ConversationException("Can't find start of form with pattern \"" + p.pattern() + "\"");
    }
    int startPos = m.start();
    // Find end of form
     p = Pattern.compile("</form>");
//    p = getPattern("util.formEnd");
    m = p.matcher(page);
    m.region(startPos, page.length());
    // Confirm send resource does not have "</form>"
    int endPos = page.length();
    if (m.find()) {   
      endPos = m.end();
    }
   
    // Test for JamVM problem
    if (endPos < startPos ) {
      log.fine(String.format("endPos=%s is before startPos=%s. Setting endPos to end of file", endPos, startPos));
      endPos = page.length();
      // log.debug("endPos pattern = " + getPattern("util.formEnd"));
      // log.debug("Page dump\n"+page);
    }
   
    // Find hidden fields
     p = Pattern.compile("<input +type=\"hidden\" +name=\"(.*?)\" +value=\"(.*?)\"");
//    p = getPattern("util.hiddenField");
    m = p.matcher(page);
    m.region(startPos, endPos);
    while (m.find()) {
      String name = m.group(1);
      String value = m.group(2);
      names.add(name);
      values.add(value);
   
    return startPos;
  }

  public boolean isLoginPage(String page) {
    Pattern p;
    Matcher m;
     p = Pattern.compile("(?s)(?i)<input type=\"image\" value=\"login\"");
//    p = getPattern( PATTERN_IS_LOGIN_PAGE);
    m = p.matcher(page);
    return m.find();
  }

  private void addHeaders( HttpMethod m) {
      m.setRequestHeader(
                  "Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
    m.addRequestHeader("Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
    m.addRequestHeader("Accept-Language", "en,it;q=0.5");
    m.addRequestHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");


    // Use the lastVisitPage
    if (!lastVisitPage.equals("")) {
      m.addRequestHeader("Referer", lastVisitPage);
    }
  }

  public String httpPostPage(String url, List<String> postNames, List<String> postValues, boolean quick) throws ConversationException, Exception {
    log.fine("Posting " + url + " ...");
   
      // GAC modify to run from local files for decoupled debug
      if   ((testMode & 1) == 1) {
          String page = null;
        try {
          page = readFromFile(url+postNames);
          return page;
        } catch (IOException e) {
          // GAC - check if in read/write mode, in which case ignore the error and carry on to access page
          if   ((testMode & 2) == 2) {
            // Warn what we are doing
              log.finest("Cannot Find Page on Disk " + url + " ***** Getting from Server");
          } else {
            // TODO Auto-generated catch block
            e.printStackTrace();
            // GAC just exit for now - create missing file manually and restart!
            System.exit(-1);
          }
        }
      } // else {    // GAC added for test mode
      // continue with original code
   
    PostMethod httpPost = new PostMethod(url);
    addHeaders(httpPost);
    NameValuePair[] postData = new NameValuePair[postNames.size()];
    for (int i = 0; i < postData.length; i++) {
      postData[i] = new NameValuePair(postNames.get(i), postValues.get(i));
    }
    httpPost.setRequestBody(postData);
    String page;
    try {
      client.executeMethod(httpPost);

      // Save the url for reference header
      lastVisitPage = url;

      page = httpPost.getResponseBodyAsString();
    } catch (IOException e) {
      throw new ConversationException("Can't read page " + url, e);
    } finally {
      httpPost.releaseConnection();
    }
     
    // Follow any redirects
        int statuscode = httpPost.getStatusCode();
        if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) ||
            (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) ||
            (statuscode == HttpStatus.SC_SEE_OTHER) ||
            (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
            Header header = httpPost.getResponseHeader("location");
            if (header != null) {
                String newuri = header.getValue();
                if ((newuri == null) || (newuri.equals(""))) {
                    newuri = "/";
                }
                log.fine("Redirect target: " + newuri);
                page = httpGetPageNoLogin(newuri, quick);
            } else {
              throw new ConversationException("Invalid redirect (location=null)");
            }
        }
    log.fine("Posted " + url);
   
    // GAC add mode to write file to disk
    if   ((testMode & 2) == 2) {
      writeToFile(url+postNames, page);
   
    return page;
  }
 
  private void getIfNotCachedAndDrop(String pageUrl, String src) {
   
      // GAC modify to run from local files for decoupled debug
      if (testMode == 1) {
          // GAC TODO - consider how handle in mode 3, at the moment only ignoring for mode 1
          // hoping it was cached previously!
          log.finest("Ignoring Cache Request: " + pageUrl);
          return ;
      } // else {    // GAC added for test mode


    try {
      // src can be relative or absolute
      // - when relative, ok
      // - when absolute, remove start
      String relative = src;
      if (src.startsWith("http://")) { // Not relative
        int pos = relative.indexOf("/", "http://".length());
        relative = relative.substring(pos);
      } else {
        // Make full url
        int pos = pageUrl.indexOf("/", "http://".length());
        if (pos==-1) {
          src = pageUrl + "/" + src;
        } else {
          src = pageUrl.substring(0, pos + 1) + src;
        }
      }
      String cachePath = "imageCache";
      File file = new File(cachePath, relative);
      if (!file.canRead()) {
        log.fine("Caching resource : " + src);
        GetMethod getObj = new GetMethod(src);
        try {
          addHeaders(getObj);
          client.executeMethod(getObj);
          // Non need to save it, just create a placeholder
          file.getParentFile().mkdirs();
          file.createNewFile();
          // Save in cache
//        FileOutputStream output = new FileOutputStream(file);
//        InputStream input = getObj.getResponseBodyAsStream();
//        int data;
//        while ((data=input.read()) > -1) {
//          output.write(data);
//        }
//        output.close();
        } catch (Exception e) {
          log.severe("Error while caching resource " + src + " (ignored)" + e.toString());
          // ignored
        } finally {
          getObj.releaseConnection();
        }
      }
//    else {
//      log.debug("Skipping cached resource: " + src);
//    }
    } catch (Exception e) {
      log.warning("Error while checking cache for resource " + src + " (ignored):" + e.getMessage());
      // ignored
    }
  }
 
//  public static void sleep(long milli) {
//    if (milli<0) {
//      log.fine("Not sleeping: negative value " + milli);
//      return;
//    }
//    Date awake = new Date(System.currentTimeMillis() + milli);
//    String s = String.format("Sleeping %s minutes until %s ...", milli / MILLI_MINUTE, format(awake));
////    log.info(s);
//    log.finest(s);
//    try {
//      Thread.sleep(milli);
//    } catch (InterruptedException e) {
//      log.fine("Sleep interrputed");
//      // Nothing
//    }
////    log.debug("Resuming after pause");
//  }
 
 
 
    public static String getFullUrl(String currentPageUrlString, String newUrlEnd) {
        return currentPageUrlString.substring(0, currentPageUrlString.lastIndexOf("/") + 1) + newUrlEnd;
    }
   
    public static String getFullUrl( String newUrlEnd) {
        return SERVER_URL + "/" + newUrlEnd;
    }
   
  /**
   * Convert "HH:mm:ss" into seconds
   * @param timeString
   * @return
   */
  public static int timeToSeconds(String timeString) {
    int value = 0;
    String[] parts = timeString.trim().split(":");
    for (int i = 0; i < parts.length; i++) {
      String elem = parts[i];
      int elemVal = Integer.parseInt(elem);
      value = value*60 + elemVal;
    }
    return value;
  }
 
  /**
   * Transforms "HH:mm:ss" into date
   * @param timeNeeded
   * @return
   */
//  public Date getCompletionTime(String timeNeeded) {
//    int seconds = timeToSeconds(timeNeeded);
//    Calendar time = new GregorianCalendar();
//    time.add(Calendar.SECOND, seconds);
//    return time.getTime();
//  }

//  public Date calcWhenAvailable(ResourceTypeMap production, ResourceTypeMap availableResources, ResourceTypeMap neededResources) {
//    float hoursNeeded = 0;
//    for (ResourceType res : ResourceType.values()) {
//      if (res==ResourceType.FOOD) {
//        continue;
//      }
//      int missing = neededResources.get(res) - availableResources.get(res);
//      float time = missing / (float)production.get(res);
//      if (time>hoursNeeded) {
//        hoursNeeded = time;
//      }
//    }
//    int seconds = (int) (hoursNeeded * 3600);
//    Calendar cal = new GregorianCalendar();
//    cal.add(Calendar.SECOND, seconds);
//    return cal.getTime();
//  }
 

 
  /**
   * Convert milliseconds into "HH:mm:ss"
   * @param milliPause
   * @return
   */
  public String milliToTimeString(long milliPause) {
    long hours = milliPause / 3600000;
    long min = (milliPause - hours*3600000) / 60000;
    long sec = (milliPause % 60000) / 1000;
    return hours + ":" + min + ":" + sec; // TODO aggiungere lo zero iniziale se una cifra
  }

  public static String inputLine(String prompt) throws Exception {
    return inputLine(prompt, null);
  }
 
  public static String inputLine(String prompt, String defaultValue) throws Exception {
    // TODO hide typing or at least clear password at the end
    System.out.println(prompt);
    BufferedReader readIn = new BufferedReader(new InputStreamReader(System.in));
    try {
      String result = readIn.readLine();
      // Failed attempt to clear password (doesn't work): System.out.println((char)27 + "A                                                                            ");
      if (defaultValue!=null && (result==null || result.trim().length()==0)) {
        System.out.println(defaultValue);
        return defaultValue;
      }
      return result;
    } catch (IOException e) {
      throw new Exception("Can't read user input", e);
    }
  }

  public Date serverTimeToLocalTime(Date serverTime) {
    return new Date(serverTime.getTime() + serverTimeMillisDelta);
  }


 

  /**
   * Returns a localised message, loaded from a message bundle.
   * @param key the key to the message
   * @param caller the class of the caller, needed to retrieve the bundle file from the same package of the caller
   * @return
   */
//  public static String getLocalMessage(String key, Class caller) {
//    try {
//      ResourceBundle bundle = getResourceBundle(ERROR_MESSAGE_BUNDLE_NAME, caller);
//      return bundle.getString(key);
//    } catch (MissingResourceException e) {
//      return key;
//    }
//  }

  /**
   * Ottiene un bundle caricando il file che si trova nello stesso package della classe indicata
   * @param bundleName nomeBundle
   * @param callerClass chiamante
   * @return ResourceBundle
   * @throws MissingResourceException bundle non esiste
   */
//  public static ResourceBundle getResourceBundle(String bundleName, Class caller) throws MissingResourceException {
//    StringBuffer fullBundleName = new StringBuffer(caller.getPackage().getName()).append(".").append(bundleName);
//    return ResourceBundle.getBundle(fullBundleName.toString());
//  }
 
  private HttpClient getHttpClient() {
    HttpClient client = new HttpClient();
    // Timeout
    client.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, (int) (MILLI_SECOND * 30)); // milliseconds
    client.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, (int) (MILLI_SECOND * 30));
    client.getParams().setParameter(HttpConnectionParams.STALE_CONNECTION_CHECK, true);
    // User agent
    String userAgent = USERAGENT_DEFAULT;
    client.getParams().setParameter(HttpMethodParams.USER_AGENT, userAgent);
    // Proxy
//    if (configManager.getBoolean("proxy/@enabled", false)) {
//      String host = configManager.getString("proxy/hostName", null);
//      int port = configManager.getInt("proxy/hostPort", 0);
//      client.getHostConfiguration().setProxy(host, port);
//      String user = configManager.getString("proxy/proxyUser", null);
//      String pwd = configManager.getString("proxy/proxyPassword", null);
//      if (user != null) {
//        Credentials credentials = null;
//        String ntHost = configManager.getString("proxy/NTHost", null);
//        String ntDomain = configManager.getString("proxy/NTDomain", null);
//        if ((ntHost != null) && (ntDomain != null)) {
//          credentials = new NTCredentials(user, pwd, ntHost, ntDomain);
//        } else {
//          credentials = new UsernamePasswordCredentials(user, pwd);
//        }
//        AuthScope authScope = new AuthScope(host, port);
//        client.getState().setProxyCredentials(authScope, credentials);
//      }
//    }
    return client;
  }


    public Pattern getPattern(String patternString, Object ... params)
    {
        patternString = String.format( patternString, params);
        return Pattern.compile(P_FLAGS + patternString);
    }

    public void saveTestPattern(String desc, Pattern pattern, String page) {
        String outputDir = "logs/patterns";
        PatternDebugger patternDebugger = new PatternDebugger(desc, pattern, page);
        patternDebugger.toFile(outputDir);
    }
 
 
//  /**
//   * Convert map id to a coordinate
//   * @param id the map id
//   * @return coorinate
//   */
//  public static IntPair id2coord(int id) {
//        int x = id % 801;
//        x -= 401;
//        int y = id / 801;
//        y = 400 - y;
//      return new IntPair(x, y);
//  }
//  /**
//   * Convert a coordinate into map id
//   * @param coord the coordinate
//   * @return the map id.
//   */
//    public static int coord2id(IntPair coord) {
//        int id = (400 - coord.second) * 801 + coord.first + 401;
//        return id;
//    }
  /**
   *
   * @author biminus
   * A class for holding 2 elements.
   * @param <T1> first
   * @param <T2> second
   */
    // TODO I would put this in the misc package [xtian]
  public static class Pair<T1, T2> {
      public T1 first;
      public T2 second;

      public Pair(T1 t1, T2 t2) {
          first = t1;
          second = t2;
      }

      public String toString() {
          return "(" + first + "," + second + ")";
      }
     
      /**
       * Pair<Integer, Integer> class for convenience.
       * @author biminus
       *
       */
      public static class IntPair extends Pair<Integer, Integer> {
          public IntPair(Integer first, Integer second) {
              super(first, second);
          }
      }
  }
    public static HttpServer getHttpServer( )
    {
        if( instance == null ) {
            instance = new HttpServer( );
        }
        return instance;
    }

    public String getMapPage( int coordX, int coordY) throws ConversationException, Exception
    {
        String page =  HttpServer.getHttpServer().httpGetPage( SERVER_URL + "/karte.php");
        Thread.sleep( (long) (2000 + 1000*Math.random()));

        // now need to call Post to move to Specified Coordinates
        List<String> postNames = new ArrayList<String>();
        List<String> postValues = new ArrayList<String>();
       
        // Util.addHiddenPostFields(page, "<form method=\"POST\" name=\"snd\" action=\"build.php\">", postNames, postValues);
        // Util.addButtonCoordinates("s1", 80, 20, postNames, postValues);
       
        // Map Form does not appear to have hidden fields
        // post it and get the page back
        postNames.add( "xp");
        postValues.add( Integer.toString( coordX));
        postNames.add( "yp");
        postValues.add( Integer.toString( coordY));
       
        addButtonCoordinates("s1", "ok", 0, 0, postNames, postValues);
        page = httpPostPage( SERVER_URL + "/karte.php", postNames, postValues, false);
       
        return page;
    }
 
 

 
}
TOP

Related Classes of net.traviangui.hostInterface.HttpServer$Pair

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.