/*
* Copyright 2010, 2011 Ali Piccioni & Francois Poizat
*
* This program is distributed under the terms of the GNU General Public License
*
* This file is part of Team Liquid Android App.
*
* Team Liquid Android App is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Team Liquid Android App is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Team Liquid Android App. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.opensourcetlapp.tl;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
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.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
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.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.SimpleXmlSerializer;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.htmlcleaner.XmlSerializer;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.text.Html;
import android.util.Log;
public class TLLib {
public static final int PROGRESS_CONNECTING = 100;
public static final int PROGRESS_DOWNLOADING = 101;
public static final int PROGRESS_PARSING = 102;
private static final String TAG = "TLLib";
private static final String TEMP_FILE_NAME = "TLLIBTEMP";
private static final String LOGIN_URL = "http://www.teamliquid.net/mytlnet/login.php";
private static final String LOGOUT_URL = "http://www.teamliquid.net/mytlnet/logout.php";
private static final String CREATE_NEW_THREAD_URL = "http://www.teamliquid.net/forum/addtopic.php";
private static final String CREATE_NEW_BLOG_POST_URL = "http://www.teamliquid.net/blogs/addblogentry.php";
private static final String POST_URL = "http://www.teamliquid.net/forum/postmessage.php";
private static final String PM_URL = "http://www.teamliquid.net/mytlnet/index.php";
private static final String SUB_URL = "http://www.teamliquid.net/mytlnet/mythreads.php";
private static final String EDIT_URL = "http://www.teamliquid.net/forum/edit.php";
private static final String SEARCH_URL = "http://www.teamliquid.net/forum/search.php";
private static final String USER_FIELD = "loginname";
private static final String PASS_FIELD = "loginpasswd";
private static final String REMEMBERME = "makeAcookie";
private static CookieStore cookieStore;
public static boolean loginStatus = false;
public static String loginName;
private static String tokenField;
private static HtmlCleaner cleaner = null;
private static XmlSerializer serializer;
public static HtmlCleaner buildDefaultHtmlCleaner(){
if (cleaner == null){
cleaner = new HtmlCleaner();
CleanerProperties props = cleaner.getProperties();
props.setAllowHtmlInsideAttributes(true);
props.setAllowMultiWordAttributes(true);
props.setRecognizeUnicodeChars(true);
props.setOmitComments(true);
}
//props.setPruneTags("script");
return cleaner;
}
public static XmlSerializer getXmlSerializer(){
if (serializer == null){
buildDefaultHtmlCleaner();
serializer = new SimpleXmlSerializer(cleaner.getProperties());
}
return serializer;
}
public static String getAbsoluteURL(String relativeURL){
if (relativeURL.charAt(0) == '/'){
return Config.DOMAIN_NAME + relativeURL;
}
else {
return Config.DOMAIN_NAME + "/" + relativeURL;
}
}
public static boolean login(String login, String pw, Handler handler, Context context) throws IOException{
handler.sendEmptyMessage(TLHandler.PROGRESS_LOGIN);
logout();
// Fetch the token
HtmlCleaner cleaner = TLLib.buildDefaultHtmlCleaner();
URL url = new URL(LOGIN_URL);
//TagNode node = TagNodeFromURLEx2(cleaner, url, handler, context, "<html>", false);
TagNode node = TLLib.TagNodeFromURLLoginToken(cleaner, url, handler, context);
String token = null;
try {
TagNode result = (TagNode) (node.evaluateXPath("//input")[0]);
token = result.getAttributeByName("value");
} catch (XPatherException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (token == null){
return false;
}
//
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(LOGIN_URL);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair(USER_FIELD, login));
nvps.add(new BasicNameValuePair(PASS_FIELD, pw));
nvps.add(new BasicNameValuePair(REMEMBERME, "1"));
nvps.add(new BasicNameValuePair("stage", "1"));
nvps.add(new BasicNameValuePair("back_url", "/"));
nvps.add(new BasicNameValuePair("token", token));
Log.d("token:", token);
tokenField = token;
if (cookieStore != null) {
httpclient.setCookieStore(cookieStore);
}
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpost);
HttpEntity entity = response.getEntity();
Header [] headers = response.getHeaders("Set-Cookie");
if ( cookieStore.getCookies().size() < 2 ){
loginName = null;
loginStatus = false;
}
else {
loginName = login;
loginStatus = true;
cookieStore = httpclient.getCookieStore();
}
if (entity != null) {
entity.consumeContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return loginStatus;
}
public static void logout() throws IOException{
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpGet httpGet = new HttpGet(LOGOUT_URL+ "?t=" +tokenField);
try {
httpclient.execute(httpGet);
} catch (ClientProtocolException e) {
e.printStackTrace();
}
loginStatus = false;
cookieStore = null;
}
public static void subscribeThread(String topicId) throws IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpPost httpost = new HttpPost(SUB_URL);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("action", "toggleSub"));
nvps.add(new BasicNameValuePair("thread_id", topicId));
nvps.add(new BasicNameValuePair("token", tokenField));
Log.d(TAG, "Subscribing Thread");
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpost);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
}
}
public static void sendPM(String to, String subject, String message) throws IOException{
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpPost httpost = new HttpPost(PM_URL);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("to", to));
nvps.add(new BasicNameValuePair("subject", subject));
nvps.add(new BasicNameValuePair("body", message));
nvps.add(new BasicNameValuePair("view", "Send"));
nvps.add(new BasicNameValuePair("token", tokenField));
Log.d(TAG, "Sending message");
Log.d(TAG, to);
Log.d(TAG, subject);
Log.d(TAG, message);
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpost);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
}
}
public static void postMessage(String message, String backurl, String topicId, Context context) throws IOException{
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpPost httpost = new HttpPost(POST_URL);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("bericht", message));
nvps.add(new BasicNameValuePair("stage", "1"));
nvps.add(new BasicNameValuePair("backurl", backurl));
nvps.add(new BasicNameValuePair("token", tokenField));
nvps.add(new BasicNameValuePair("topic_id", topicId));
nvps.add(new BasicNameValuePair("submit_button", "Post"));
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpost);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
}
}
public static void editMessage(String message, int topicId, int postId, int currentPage, String token, Context context) throws IOException{
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpPost httpost = new HttpPost(EDIT_URL);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("action", "edit"));
nvps.add(new BasicNameValuePair("token", token));
nvps.add(new BasicNameValuePair("stage", "1"));
nvps.add(new BasicNameValuePair("topic_id", Integer.toString(topicId)));
nvps.add(new BasicNameValuePair("post_id", Integer.toString(postId)));
nvps.add(new BasicNameValuePair("currentPage", Integer.toString(currentPage)));
nvps.add(new BasicNameValuePair("content", message));
nvps.add(new BasicNameValuePair("submit_button", "Update"));
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpost);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
}
}
private static void writeEntitytoFile(HttpEntity entity, Context context) throws IllegalStateException, IOException{
InputStream is = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(context.openFileOutput("TEMP.html", Context.MODE_PRIVATE)));
String line;
while ((line = br.readLine()) != null){
bw.write(line);
}
}
private static TagNode TagNodeFromURLHelper(InputStream is, String fullTag, Handler handler, Context context, HtmlCleaner cleaner) throws IOException{
SharedPreferences settings = context.getSharedPreferences(Settings.SETTINGS_FILE_NAME, 0);
boolean disableSmartParsing = settings.getBoolean(Settings.DISABLE_SMART_PARSING, false);
if (fullTag != null && !disableSmartParsing){
FileOutputStream fos = context.openFileOutput(TEMP_FILE_NAME, Context.MODE_WORLD_WRITEABLE);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
TagParser.extractTagToFile(fullTag, is, bw);
bw.flush();
bw.close();
if (handler != null)
handler.sendEmptyMessage(PROGRESS_PARSING);
return cleaner.clean(context.openFileInput(TEMP_FILE_NAME));
} else{
if (handler != null)
handler.sendEmptyMessage(PROGRESS_PARSING);
return cleaner.clean(is);
}
}
public static TagNode TagNodeFromURLEx2(HtmlCleaner cleaner, URL url,
Handler handler, Context context, String fullTag, boolean login) throws IOException {
handler.sendEmptyMessage(PROGRESS_CONNECTING);
DefaultHttpClient httpclient = new DefaultHttpClient();
if (cookieStore != null){
httpclient.setCookieStore(cookieStore);
}
HttpGet httpGet = new HttpGet(url.toExternalForm());
HttpResponse response = httpclient.execute(httpGet);
if (cookieStore == null){
cookieStore = httpclient.getCookieStore();
}
handler.sendEmptyMessage(PROGRESS_DOWNLOADING);
HttpEntity httpEntity = response.getEntity();
InputStream is = httpEntity.getContent();
return TagNodeFromURLHelper(is, fullTag, handler, context, cleaner);
}
// TODO: Get rid of all these TagNode functions. Their respective Activity classes should call TagNodeFromURLEx2 directly
public static TagNode TagNodeFromURLShowForumList(HtmlCleaner cleaner, URL url,
Handler handler, Context context) throws IOException{
return TagNodeFromURLEx2(cleaner, url, handler, context, "<TABLE cellpadding=0 cellspacing=0 width=\"764\" >", true);
}
public static TagNode TagNodeFromURLLoginToken(HtmlCleaner cleaner, URL url, Handler handler, Context context) throws IOException {
return TagNodeFromURLEx2(cleaner, url, handler, context, "<div id=\"loginbox\">", false);
}
public static TagNode TagNodeFromURLShowForum(HtmlCleaner cleaner, URL url,
Handler handler, Context context) throws IOException{
return TagNodeFromURLEx2(cleaner, url, handler, context, "<table width=\"747\" class=\"solid\" cellspacing=0>", true);
}
public static TagNode TagNodeFromURLSearch(HtmlCleaner cleaner, String search,
Handler handler, Context context) throws IOException{
return TagNodeFromURLEx2(cleaner,new URL(SEARCH_URL+"?q="+search.replaceAll("\\s", "+")), handler, context, "<table cellpadding=\"5\" cellspacing=0 width=\"100%\">", true);
}
public static TagNode TagNodeFromURLMyPosts(HtmlCleaner cleaner, URL url,
Handler handler, Context context) throws IOException{
return TagNodeFromURLEx2(cleaner, url, handler, context, "<table width='748' cellpadding='3' cellspacing='0' border='0' style='border:1px solid #00005D;'>", true);
}
public static TagNode TagNodeFromURLMySubs(HtmlCleaner cleaner, URL url,
Handler handler, Context context) throws IOException{
return TagNodeFromURLEx2(cleaner, url, handler, context, "<table width=\"100%\" class=\"solid\" cellspacing=0>", true);
}
private static final String APPLICATION_TITLE = "Team Liquid";
public static String makeActivityTitle(String subtitle){
if (subtitle == null || subtitle.length() == 0){
return APPLICATION_TITLE;
}
else {
return String.format("%s - %s", APPLICATION_TITLE, subtitle);
}
}
public static Object[] parseEditText(HtmlCleaner cleaner, URL url, TLHandler handler, Context context) throws IOException {
// Although probably not THE worst hack I've written, this function ranks near the top.
// TODO: rework this routine get rid of code duplication.
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpGet httpGet = new HttpGet(url.toExternalForm());
HttpResponse response = httpclient.execute(httpGet);
handler.sendEmptyMessage(PROGRESS_DOWNLOADING);
InputStream is = response.getEntity().getContent();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
FileOutputStream fos = context.openFileOutput(TEMP_FILE_NAME, Context.MODE_PRIVATE);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
String line;
String formStart = "<form action=\"/forum/edit.php";
while((line = br.readLine()) != null){
if (line.startsWith(formStart)){
Log.d(TAG, line);
bw.write(line);
break;
}
}
String start = "\t\t<textarea";
String end = "\t\t<p>";
StringBuffer sb = new StringBuffer();
while((line = br.readLine()) != null){
if (line.startsWith(start)){
bw.write("</form>");
int i = line.lastIndexOf('>');
sb.append(Html.fromHtml(line.substring(i+1)).toString());
sb.append("\n");
break;
}
else {
bw.write(line);
}
}
while ((line = br.readLine()) != null){
if (line.startsWith(end)){
break;
}
sb.append(Html.fromHtml(line).toString());
sb.append("\n");
}
bw.flush();
bw.close();
if (handler != null)
handler.sendEmptyMessage(PROGRESS_PARSING);
Object []ret = new Object[2];
ret[0] = sb.toString();
ret[1] = cleaner.clean(context.openFileInput(TEMP_FILE_NAME));
return ret;
}
public static String parseQuoteText(HtmlCleaner cleaner, URL url, TLHandler handler, Context context) throws IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpGet httpGet = new HttpGet(url.toExternalForm());
HttpResponse response = httpclient.execute(httpGet);
handler.sendEmptyMessage(PROGRESS_DOWNLOADING);
InputStream is = response.getEntity().getContent();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
return parseTextArea(br);
}
public static Object[] tagNodeWithEditText(HtmlCleaner cleaner, URL url,
Handler handler, Context context, String fullTag, boolean login) throws IOException {
Object [] ret = new Object[2];
handler.sendEmptyMessage(PROGRESS_CONNECTING);
DefaultHttpClient httpclient = new DefaultHttpClient();
if (login){
httpclient.setCookieStore(cookieStore);
}
HttpGet httpGet = new HttpGet(url.toExternalForm());
HttpResponse response = httpclient.execute(httpGet);
handler.sendEmptyMessage(PROGRESS_DOWNLOADING);
InputStream is = response.getEntity().getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(context.openFileInput(TEMP_FILE_NAME)));
ret[0] = TagNodeFromURLHelper(is, fullTag, handler, context, cleaner);
ret[1] = parseTextArea(br);
return ret;
}
public static String parseTextArea (BufferedReader br) throws IOException{
String start = "<textarea";
String end = "</textarea>";
String line;
StringBuffer sb = new StringBuffer();
while((line = br.readLine()) != null){
if (line.contains(start)){
int i = line.indexOf(start);
int j = line.indexOf('>', i);
int k = line.length();
try {
if (line.contains(end)){
k = line.indexOf(end); // The case where the tag is closed on the same line
Log.d(TAG, String.format("%d, %d", j+1, k));
sb.append(Html.fromHtml(line.substring(j+1, k)).toString());
return sb.toString();
}
else {
sb.append(Html.fromHtml(line.substring(j+1, k)).toString());
sb.append("\n");
}
}
catch (StringIndexOutOfBoundsException e) {
// Do nothing
}
break;
}
}
while ((line = br.readLine()) != null){
if (line.contains(end)){
int i = line.indexOf(end);
sb.append(Html.fromHtml(line.substring(0, i)).toString());
break;
}
sb.append(Html.fromHtml(line).toString());
sb.append("\n");
}
return sb.toString();
}
public static void postNewThread(int forumCode, String subject,
String message) throws IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(cookieStore);
HttpPost httpost;
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
if (forumCode == 18){
httpost = new HttpPost(CREATE_NEW_BLOG_POST_URL);
nvps.add(new BasicNameValuePair("topic_name", subject));
nvps.add(new BasicNameValuePair("bericht", message));
nvps.add(new BasicNameValuePair("stage", "1"));
nvps.add(new BasicNameValuePair("submit", "Post Message"));
nvps.add(new BasicNameValuePair("type", ""));
}else {
httpost = new HttpPost(CREATE_NEW_THREAD_URL);
nvps.add(new BasicNameValuePair("topic_name", subject));
nvps.add(new BasicNameValuePair("content", message));
nvps.add(new BasicNameValuePair("submit", "Post Message"));
nvps.add(new BasicNameValuePair("type", String.format("%d", forumCode)));
}
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpost);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
}
}
}