org.opensourcetlapp.tl.TLLib.java Source code

Java tutorial

Introduction

Here is the source code for org.opensourcetlapp.tl.TLLib.java

Source

/*
 * 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();
        }
    }

}