package fr.xtof54.jsgo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.json.JSONObject;
import android.net.NetworkInfo;
import android.net.http.AndroidHttpClient;
import fr.xtof54.jsgo.EventManager.eventType;
/**
* This class is the "new" version of the ServerConnection, but specific to Android.
* It shall ultimately completely replace ServerConnection.
*
*
* @author xtof
*
*/
public class AndroidServerConnection {
private String u,p,server;
private AndroidHttpClient httpclientdirect=null;
private HttpContext httpctxt=null;
/**
* We define this interface so that all logging info can be simply displayed on the console,
* or shown as Android Toasts !
* Note that this interface really aims at showing routine messages to the user, and is thus quite different
* from the traditional logging facilities that rather aims at errors, warnings...
* @author xtof
*
*/
public interface DetLogger {
public void showMsg(String s);
}
private DetLogger logger = new DetLogger() {
@Override
public void showMsg(String s) {
System.out.println(s);
}
};
public void setLogger(DetLogger l) {logger=l;}
final String[] serverNames = {
"http://www.dragongoserver.net/",
"http://dragongoserver.sourceforge.net/"
};
void initHttp() {
if (httpclientdirect==null) {
httpclientdirect = AndroidHttpClient.newInstance(null);
httpctxt = new BasicHttpContext();
httpctxt.setAttribute(ClientContext.COOKIE_STORE, new BasicCookieStore());
// login
try {
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("userid", u));
formparams.add(new BasicNameValuePair("passwd", p));
formparams.add(new BasicNameValuePair("login", "Log+In"));
UrlEncodedFormEntity entity;
entity = new UrlEncodedFormEntity(formparams, "UTF-8");
HttpPost httppost = new HttpPost(getUrl()+"login.php");
httppost.setEntity(entity);
directConnectExecute(httppost,null);
GoJsActivity.main.updateTraffic();
} catch (Exception e) {
e.printStackTrace();
GoJsActivity.main.updateTraffic();
}
}
}
public void closeConnection() {
if (httpclientdirect!=null)
httpclientdirect.getConnectionManager().shutdown();
httpclientdirect=null;
}
/**
* creates a connection to a specific server;
* determines the correct credentials
* @param num
*/
public AndroidServerConnection(int num, String userlogin, String userpwd) {
server=serverNames[num];
// TODO: this must be handled outside of this class
// String tu = PrefUtils.getFromPrefs(GoJsActivity.main, PrefUtils.PREFS_LOGIN_USERNAME_KEY,null);
// String tp = PrefUtils.getFromPrefs(GoJsActivity.main, PrefUtils.PREFS_LOGIN_PASSWORD_KEY,null);
// if (tu==null||tp==null) {
// logger.showMsg("Please enter your credentials first via menu Settings");
// return;
// }
// if (GoJsActivity.main.debugdevel==0) {
// GoJsActivity.main.debugdevel=1;
// } else if (GoJsActivity.main.debugdevel==1) {
// tu = PrefUtils.getFromPrefs(GoJsActivity.main, PrefUtils.PREFS_LOGIN_USERNAME2_KEY,null);
// tp = PrefUtils.getFromPrefs(GoJsActivity.main, PrefUtils.PREFS_LOGIN_PASSWORD2_KEY,null);
// GoJsActivity.main.debugdevel=0;
// }
u=userlogin; p=userpwd;
}
static String[] loadCredsFromFile(String file) {
String u=null, p=null;
try {
BufferedReader f=new BufferedReader(new FileReader(file));
u=f.readLine();
p=f.readLine();
f.close();
} catch (IOException e) {
e.printStackTrace();
}
String[] res = {u,p};
return res;
}
public String getUrl() {
return server;
}
public String getLogin() {
return u;
}
public String getPwd() {
return p;
}
// ====================================================================
/*
* you'll find below direct connection to the DGS server, without using the quicksuite !
*/
Ladder ladd = null;
String res;
/**
* In the case of long strings, StringBuilder can crash because of OutOfMemory.
* So the caller must saveInFile, and then get the string back from this file.
*
* @param req
* @param saveInFile
* @return
*/
public String directConnectExecute(HttpUriRequest req, final String saveInFile) {
res=null;
try {
// is it synchronous or not ?? Yes, it seems that it is synchronous
httpclientdirect.execute(req,new ResponseHandler<String>() {
@Override
public String handleResponse(HttpResponse response0) throws ClientProtocolException, IOException {
Header[] httpHeader = response0.getHeaders("Location");
while (httpHeader.length > 0) {
httpclientdirect.close();
httpclientdirect = AndroidHttpClient.newInstance(null);
String url = httpHeader[0].getValue();
System.out.println("redirect "+url);
HttpGet httpGet = new HttpGet(url);
response0 = httpclientdirect.execute(httpGet);
httpHeader = response0.getHeaders("Location");
}
final HttpResponse response = response0;
StatusLine status = response.getStatusLine();
System.out.println("httpclient execute status "+status.toString());
HttpEntity entity = response.getEntity();
// no because I got a status>=300 but login succeeds...
// if (status.getStatusCode() >= 300) {
// throw new HttpResponseException(status.getStatusCode(),status.getReasonPhrase());
// }
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
InputStream instream = entity.getContent();
BufferedReader fin = new BufferedReader(new InputStreamReader(instream, Charset.forName("ISO-8859-1")));
if (saveInFile==null) {
System.out.println("building String with answer to request");
StringBuilder sb = new StringBuilder();
for (;;) {
String s = fin.readLine();
if (s==null) break;
System.out.println("request answer "+s);
sb.append(s);
}
res = sb.toString();
} else {
System.out.println("saving res in file "+saveInFile);
PrintWriter fout = new PrintWriter(new FileWriter(saveInFile));
for (;;) {
String s = fin.readLine();
if (s==null) break;
fout.print(s);
}
fout.close();
res=null;
}
fin.close();
GoJsActivity.main.updateTraffic();
return res;
}
},httpctxt);
System.out.println("just after execute...");
} catch (Exception e) {
e.printStackTrace();
GoJsActivity.main.updateTraffic();
}
return res;
}
public void ladderChallenge(final String rid, final int pos) {
EventManager.getEventManager().sendEvent(eventType.ladderChallengeStart);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
initHttp();
System.out.println("challengeladder - getlogin passed");
HttpGet get = new HttpGet(getUrl()+"tournaments/ladder/challenge.php?tid="+ladd.ladnum+"&rid="+rid);
String res = directConnectExecute(get,null);
System.out.println("challengeladder - got server answer");
// check if challenge possible
int i=res.indexOf("Defender is not");
if (i>=0) {
EventManager.getEventManager().sendEvent(eventType.ladderChallengeEnd);
EventManager.getEventManager().sendEvent(eventType.showMessage,"Defender is not any more challengeable");
GoJsActivity.main.updateTraffic();
return;
}
i=res.indexOf("Please confirm if you want to challenge this user");
if (i<0) {
EventManager.getEventManager().sendEvent(eventType.ladderChallengeEnd);
EventManager.getEventManager().sendEvent(eventType.showMessage,"Error when trying to challenge user");
GoJsActivity.main.updateTraffic();
return;
}
// challenge is possible.
{
HttpGet cget = new HttpGet(getUrl()+"tournaments/ladder/challenge.php?tl_challenge=Confirm+Challenge&tid="+ladd.ladnum+"&rid="+rid+"&confirm=1");
String cres = directConnectExecute(cget,null);
System.out.println("challengeladder - got server answer to challenge confirm");
System.out.println(cres);
EventManager.getEventManager().sendEvent(eventType.showMessage,"Challenge "+ladd.userList[pos]+" ok");
}
// warning: displaying this String may not be done completely, why ?
// System.out.println(res);
EventManager.getEventManager().sendEvent(eventType.ladderChallengeEnd);
GoJsActivity.main.updateTraffic();
}
});
t.start();
}
/**
* @return the players that you can challenge in the ladder, and only them !
*/
public void startLadderView(final File dir) {
EventManager.getEventManager().sendEvent(eventType.ladderStart);
if (ladd.isLadderCached()) {
EventManager.getEventManager().sendEvent(eventType.ladderEnd);
GoJsActivity.main.updateTraffic();
return;
}
Thread t = new Thread(new Runnable() {
@Override
public void run() {
initHttp();
System.out.println("getladder - getlogin passed");
HttpGet get = new HttpGet(getUrl()+"tournaments/ladder/view.php?tid="+ladd.ladnum);
// this file is erased next time we load one of the ladder - it's useless to keep both ladders in such files: it could even be removed afterwards...
final String cacheFile = "ladderHtmlString";
directConnectExecute(get, dir.getAbsolutePath()+"/"+cacheFile);
ladd.loadHTML(dir.getAbsolutePath()+"/"+cacheFile);
System.out.println("getladder - got server answer");
GoJsActivity.main.updateTraffic();
EventManager.getEventManager().sendEvent(eventType.ladderEnd);
}
});
t.start();
}
}