vc.fq.FanfouExporter.ExportTread.java Source code

Java tutorial

Introduction

Here is the source code for vc.fq.FanfouExporter.ExportTread.java

Source

/*
 * Copyright 2012, Unicorn-Feng
 * All rights reserved.
 * 
 * This file is part of FanfouExporter.
 * FanfouExporter 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
 * any later version.
 * 
 * FanfouExporter 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 FanfouExporter.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 *?? FanfouExporter
 *Export Tool for Fanfou
 *Author:  Unicorn-Feng
 *Website: http://fq.vc 
 */

package vc.fq.FanfouExporter;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JOptionPane;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * ??
 * @author  Unicorn-Feng
 * @link http://fq.vc
 */
public class ExportTread extends Thread {
    public static final String consumer_key = "5ee8c6fae7022acc00e5f59cbeb80372";
    public static final String consumer_secret = "3385a4a2951d47b5f66dc6b039539c00";
    public static final String HMAC_SHA1 = "HmacSHA1";
    public String oauth_token;
    public String oauth_token_secret;
    private PrintWriter outstream;
    private int picnum = 0;
    private int errtime = 0;
    private int num = 0;
    private int format;
    private int content;
    private boolean exportPic;
    private String picpath;
    private String filepath;
    private String filename;
    private String extention;

    /**
      * ???
      */
    public void exitTread() {
        if (format == 1) {
            outstream.println();
            outstream.close();
        } else if (format == 2) {
            outstream.println("</statuses>");
            outstream.close();
        }
        Main.isStart = false;
        Main.btnStart.setText("");
    }

    /**
    * 
    */
    public void run() {
        String username = Main.txtUsr.getText();
        String password = Main.txtPwd.getText();
        String userID = Main.txtFriID.getText();
        filepath = Main.txtFilePath.getText();
        exportPic = Main.chkbxPic.isSelected();

        if (filepath.charAt(filepath.length() - 1) == '/' || filepath.charAt(filepath.length() - 1) == '\\') {
            filepath = filepath.substring(0, filepath.length() - 1);
        }

        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        if (Main.rdbtnUsrTL.isSelected()) {
            content = 1;
            filename = df.format(new Date()) + "_" + username + "_tl";
        } else if (Main.rdbtnMention.isSelected()) {
            content = 2;
            filename = df.format(new Date()) + "_" + username + "_mention";
        } else if (Main.rdbtnDM.isSelected()) {
            content = 3;
            filename = df.format(new Date()) + "_" + username + "_dm";
        } else if (Main.rdbtnFriTL.isSelected()) {
            content = 4;
            filename = df.format(new Date()) + "_" + userID + "_tl";
        } else //?
        {
            content = 5;
            filename = df.format(new Date()) + "_" + username + "_fav";
        }

        if (Main.rdbtnCSV.isSelected()) {
            format = 1;
            extention = ".csv";
        } else if (Main.rdbtnXML.isSelected()) {
            format = 2;
            extention = ".xml";
        } else if (Main.rdbtnHTML.isSelected()) {
            format = 3;
            extention = ".html";
        } else {
            format = 4;
            extention = ".txt";
        }

        setLog("\r\n?" + filepath + "\\" + filename + extention);
        if (exportPic) {
            setLog("" + filepath + "\\" + filename + "_pic ");
        }

        setLog("\r\n??...");

        /* XAuth?,?Access_Token?Access_Token_Secret */
        String strxauth = XAuth(username, password);
        if (strxauth == null) {
            Main.isStart = false;
            Main.btnStart.setText("");
            return;
        }
        try {
            String[] tokenarr = strxauth.split("&");
            String[] tokenarr2 = tokenarr[0].split("=");
            oauth_token = tokenarr2[1];
            tokenarr2 = tokenarr[1].split("=");
            oauth_token_secret = tokenarr2[1];
            setLog("??\r\n");
        } catch (ArrayIndexOutOfBoundsException e) {
            setLog("?Access_Token\r\n?");
            Main.isStart = false;
            Main.btnStart.setText("");
            return;
        }

        filepath = filepath.replace("\\", "/");

        File dirFile = new File(filepath);
        boolean mkdir;
        if (!dirFile.exists() && !dirFile.isDirectory()) {
            int option = JOptionPane.showConfirmDialog(null, "?,??", "?",
                    JOptionPane.YES_NO_OPTION);
            if (option == JOptionPane.YES_OPTION) {
                mkdir = dirFile.mkdirs();
                if (mkdir == false) {
                    setLog("");
                    Main.isStart = false;
                    Main.btnStart.setText("");
                    return;
                }
                setLog("?");
            } else {
                setLog("?");
                Main.isStart = false;
                Main.btnStart.setText("");
                return;
            }
        }

        /*  */
        if (exportPic) {
            picpath = filepath + "/" + filename + "_pic";
            dirFile = new File(picpath);
            if (!dirFile.exists() && !dirFile.isDirectory()) {
                mkdir = dirFile.mkdirs();
                if (mkdir == false) {
                    setLog("");
                    Main.isStart = false;
                    Main.btnStart.setText("");
                    return;
                }
                setLog("?");
            }
        }

        /*  */
        if (format != 3) //?html?
        {
            try {
                if (format == 1) //.csv
                    outstream = new PrintWriter(new OutputStreamWriter(
                            new FileOutputStream(filepath + "/" + filename + extention), "gb2312"));
                else
                    outstream = new PrintWriter(new OutputStreamWriter(
                            new FileOutputStream(filepath + "/" + filename + extention), "UTF-8"));
            } catch (FileNotFoundException e) {
                setLog(e.getMessage());
                Main.isStart = false;
                Main.btnStart.setText("");
                return;
            } catch (UnsupportedEncodingException e) {
                setLog(e.getMessage());
                Main.isStart = false;
                Main.btnStart.setText("");
                return;
            }
        }

        if (format == 1) {
            outstream.println(
                    ",?,?id,??,?,id,,,??,?");
        } else if (format == 2) {
            outstream.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            outstream.println("<statuses>");
        }

        HttpURLConnection connection;

        int page = 1;

        while (true) {
            try {
                setLog("5s," + String.valueOf(num + 1) + "??");
                Thread.sleep(5000); //?5s
            } catch (InterruptedException e) {
                setLog("?\r\n" + String.valueOf(num) + "??");
                exitTread();
                return;
            }

            if (content == 1) //??
            {
                connection = timeline(page);
            } else if (content == 2) //??
            {
                connection = mention(page);
            } else if (content == 3) //?
            {
                connection = timeline(page);
            } else if (content == 4) //???
            {
                connection = timeline(page, userID);
            } else //?
            {
                connection = favorites(page);
            }

            if (errtime >= 5) {
                setLog("\r\n" + String.valueOf(num) + "??");
                exitTread();
                return;
            }
            String line;
            try {
                if (connection.getResponseCode() == 200) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                    line = reader.readLine();
                } else if (connection.getResponseCode() == 403) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                    String log = "";
                    line = reader.readLine();
                    while (line != null) {
                        log = log + "\r\n" + line;
                        line = reader.readLine();
                    }
                    setLog(log);
                    setLog("??TA?");
                    exitTread();
                    return;
                } else if (connection.getResponseCode() == 404) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                    String log = "";
                    line = reader.readLine();
                    while (line != null) {
                        log = log + "\r\n" + line;
                        line = reader.readLine();
                    }
                    setLog(log);
                    setLog("");
                    exitTread();
                    return;
                } else {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                    String log = "";
                    line = reader.readLine();
                    while (line != null) {
                        log = log + "\r\n" + line;
                        line = reader.readLine();
                    }
                    errtime++;
                    setLog(":\r\n" + log + "\r\n" + errtime + "?");
                    continue;
                }
            } catch (SocketTimeoutException e) {
                errtime++;
                setLog(":\r\n" + e.getMessage() + "\r\n" + errtime + "?");
                continue;
            } catch (IOException e) {
                errtime++;
                setLog(":\r\n" + e.getMessage() + "\r\n" + errtime + "?");
                continue;
            }
            writeFile(line, format, page);
            page++;
        } //while(true)
    }

    /**
     * GET?API
     * @param strURL
     * @param page
     * @return
     */
    public HttpURLConnection connectAPI(String strURL, int page) {
        long timestamp = System.currentTimeMillis() / 1000;
        long nonce = System.nanoTime();
        String pageID = String.valueOf(page);

        StringBuffer strBuf = new StringBuffer(210);
        strBuf.append("count=60");
        strBuf.append("&oauth_consumer_key=").append(consumer_key);
        strBuf.append("&oauth_nonce=").append(nonce);
        strBuf.append("&oauth_signature_method=HMAC-SHA1");
        strBuf.append("&oauth_timestamp=").append(timestamp);
        strBuf.append("&oauth_token=").append(oauth_token);
        String params = strBuf.toString();
        System.out.println(params.length());

        params = params + "&page=" + pageID;

        try {
            params = "GET&" + URLEncoder.encode(strURL, "UTF-8") + "&" + URLEncoder.encode(params, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            setLog("?");
        }
        String sig = generateSignature(params, oauth_token_secret);

        strBuf = new StringBuffer(280);
        strBuf.append("OAuth realm=\"Fantalker\",oauth_consumer_key=\"");
        strBuf.append(consumer_key);
        strBuf.append("\",oauth_signature_method=\"HMAC-SHA1\"");
        strBuf.append(",oauth_timestamp=\"").append(timestamp).append("\"");
        strBuf.append(",oauth_nonce=\"").append(nonce).append("\"");
        strBuf.append(",oauth_signature=\"").append(sig).append("\"");
        strBuf.append(",oauth_token=\"").append(oauth_token).append("\"");
        String authorization = strBuf.toString();

        strURL = strURL + "?count=60&page=" + pageID;
        try {
            URL url = new URL(strURL);
            HttpURLConnection connection;
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.addRequestProperty("Authorization", authorization);
            connection.connect();
            return connection;
        } catch (SocketTimeoutException e) {
            setLog(" " + e.getMessage());
        } catch (IOException e) {
            setLog(e.getMessage());
        }
        return null;
    }

    /**
     * GET /favorites ???
     * @param pageID ?
     * @return
     * @see https://github.com/FanfouAPI/FanFouAPIDoc/wiki/favorites
     */
    public HttpURLConnection favorites(int page) {
        String strURL = "http://api.fanfou.com/favorites/id.json";
        return connectAPI(strURL, page);
    }

    /**
     * ?
     * @param month
     * @return 
     */
    public static int getMonth(String month) {
        if (month.equals("Jan"))
            return 1;
        else if (month.equals("Feb"))
            return 2;
        else if (month.equals("Mar"))
            return 3;
        else if (month.equals("Apr"))
            return 4;
        else if (month.equals("May"))
            return 5;
        else if (month.equals("Jun"))
            return 6;
        else if (month.equals("Jul"))
            return 7;
        else if (month.equals("Aug"))
            return 8;
        else if (month.equals("Sep"))
            return 9;
        else if (month.equals("Oct"))
            return 10;
        else if (month.equals("Nov"))
            return 11;
        else if (month.equals("Dec"))
            return 12;
        else
            return -1;
    }

    /**
     * ?
     * @param strdate UTC "Mon Mar 26 09:28:48 +0000 2012"
     * @return  "2012-03-26 17:28:48"
     */
    public static String getStrDate(String strdate) {
        String strTmp;
        int year, month, day, hour, minute, second;

        strTmp = strdate.substring(26, 30);
        year = Integer.parseInt(strTmp);
        strTmp = strdate.substring(4, 7);
        month = getMonth(strTmp);
        strTmp = strdate.substring(8, 10);
        day = Integer.parseInt(strTmp);
        strTmp = strdate.substring(11, 13);
        hour = Integer.parseInt(strTmp);
        strTmp = strdate.substring(14, 16);
        minute = Integer.parseInt(strTmp);
        strTmp = strdate.substring(17, 19);
        second = Integer.parseInt(strTmp);

        Calendar calendar = new GregorianCalendar(year, month - 1, day, hour, minute, second);
        calendar.add(Calendar.HOUR_OF_DAY, 8);
        SimpleDateFormat format = new java.text.SimpleDateFormat("yyyy-MM-dd kk:mm:ss");
        return format.format(calendar.getTime());
    }

    /**
     *  GET /statuses/mentions ?/???60??
     * @param pageID ?
     * @return
     * @see https://github.com/FanfouAPI/FanFouAPIDoc/wiki/statuses.mentions
     */
    public HttpURLConnection mention(int page) {
        String strURL = "http://api.fanfou.com/statuses/mentions.json";
        return connectAPI(strURL, page);
    }

    /**
     * photourl???outpath
     * @param photourl URL?
     * @param outpath ??
     * @return ??
     */
    public String savePhoto(String photourl, String outpath) {
        URL url;
        String photo;
        BufferedInputStream bfis;
        try {
            url = new URL(photourl);

            int index = photourl.lastIndexOf("/");
            photo = photourl.substring(index + 1, photourl.length());

            bfis = new BufferedInputStream(url.openStream());
        } catch (IOException e) {
            setLog(e.getMessage());
            return "";
        }

        File file = new File(outpath + "\\" + photo);
        byte[] bytes = new byte[100];
        OutputStream outstream;

        try {
            outstream = new FileOutputStream(file);
            int len;
            len = bfis.read(bytes);
            while (len > 0) {
                outstream.write(bytes, 0, len);
                len = bfis.read(bytes);
            }
            bfis.close();
            outstream.flush();
            outstream.close();
            picnum++;
            setLog("??" + String.valueOf(picnum) + "");
            return photo;
        } catch (FileNotFoundException e) {
            setLog(e.getMessage());
            return "";
        } catch (IOException e) {
            setLog(e.getMessage());
            return "";
        }
    }

    /**
      * txtLog
      * @param str
      */
    public static void setLog(String str) {
        String log = Main.txtLog.getText();
        log = log + "\r\n" + str;
        Main.txtLog.setText(log);
        int length = Main.txtLog.getText().length();
        Main.txtLog.select(length, length);
    }

    /**
     *  GET /statuses/user_timeline ????
     * @param pageID ?
     * @param userID ID
     * @return
     * @see https://github.com/FanfouAPI/FanFouAPIDoc/wiki/statuses.user-timeline
     */
    public HttpURLConnection timeline(int page, String userID) {
        long timestamp = System.currentTimeMillis() / 1000;
        long nonce = System.nanoTime();
        String strURL = "http://api.fanfou.com/statuses/user_timeline.json";
        String pageID = String.valueOf(page);

        StringBuffer strBuf = new StringBuffer(200);
        strBuf.append("count=60");
        if (userID != null) {
            strBuf.append("&id=").append(userID);
        }
        strBuf.append("&oauth_consumer_key=").append(consumer_key);
        strBuf.append("&oauth_nonce=").append(nonce);
        strBuf.append("&oauth_signature_method=HMAC-SHA1");
        strBuf.append("&oauth_timestamp=").append(timestamp);
        strBuf.append("&oauth_token=").append(oauth_token);
        String params = strBuf.toString();

        params = params + "&page=" + pageID;

        try {
            params = "GET&" + URLEncoder.encode(strURL, "UTF-8") + "&" + URLEncoder.encode(params, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            setLog("?");
        }
        String sig = generateSignature(params, oauth_token_secret);

        strBuf = new StringBuffer(280);
        strBuf.append("OAuth realm=\"Fantalker\",oauth_consumer_key=\"");
        strBuf.append(consumer_key);
        strBuf.append("\",oauth_signature_method=\"HMAC-SHA1\"");
        strBuf.append(",oauth_timestamp=\"").append(timestamp).append("\"");
        strBuf.append(",oauth_nonce=\"").append(nonce).append("\"");
        strBuf.append(",oauth_signature=\"").append(sig).append("\"");
        strBuf.append(",oauth_token=\"").append(oauth_token).append("\"");
        String authorization = strBuf.toString();

        strURL = strURL + "?count=60&page=" + pageID;
        if (userID != null) {
            strURL = strURL + "&id=" + userID;
        }
        try {
            URL url = new URL(strURL);
            HttpURLConnection connection;
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.addRequestProperty("Authorization", authorization);
            connection.connect();
            return connection;
        } catch (SocketTimeoutException e) {
            setLog(" " + e.getMessage());
        } catch (IOException e) {
            setLog(e.getMessage());
        }
        return null;
    }

    /**
     *  GET /statuses/user_timeline ????
     * @param pageID ?
     * @return
     * @see https://github.com/FanfouAPI/FanFouAPIDoc/wiki/statuses.user-timeline
     */
    public HttpURLConnection timeline(int page) {
        return timeline(page, null);
    }

    /**
     * ?XAuth
     * @param username
     * @param password
     * @return oauth_token=Access_Token&oauth_token_secret=Access_Token_Secret
     */
    public String XAuth(String username, String password) {
        URL url;
        try {
            url = new URL("http://fanfou.com/oauth/access_token");
        } catch (MalformedURLException e) {
            setLog(e.getMessage());
            return null;
        }
        long timestamp = System.currentTimeMillis() / 1000;
        long nonce = System.nanoTime();
        String params;
        String authorization;
        params = "oauth_consumer_key=" + consumer_key + "&oauth_nonce=" + String.valueOf(nonce)
                + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=" + String.valueOf(timestamp)
                + "&x_auth_username=" + username + "&x_auth_password=" + password + "&x_auth_mode=client_auth";

        try {
            params = "GET&" + URLEncoder.encode(url.toString(), "UTF-8") + "&" + URLEncoder.encode(params, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            setLog("?");
        }

        String sig = generateSignature(params);

        authorization = "OAuth realm=\"Fantalker\",oauth_consumer_key=\"" + consumer_key
                + "\",oauth_signature_method=\"HMAC-SHA1\"" + ",oauth_timestamp=\"" + String.valueOf(timestamp)
                + "\"" + ",oauth_nonce=\"" + String.valueOf(nonce) + "\"" + ",oauth_signature=\"" + sig + "\""
                + ",x_auth_username=\"" + username + "\"" + ",x_auth_password=\"" + password + "\""
                + ",x_auth_mode=\"client_auth\"";

        try {
            HttpURLConnection connection;
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.addRequestProperty("Authorization", authorization);
            connection.connect();

            String line;
            if (connection.getResponseCode() == 200) {

            } else if (connection.getResponseCode() == 401) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                String log = Main.txtLog.getText();
                line = reader.readLine();
                while (line != null) {
                    log = log + "\r\n" + line;
                    line = reader.readLine();
                }
                Main.txtLog.setText(log);
                JOptionPane.showMessageDialog(null, "id?", "", JOptionPane.ERROR_MESSAGE);
                return null;
            } else {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                String log = Main.txtLog.getText();
                line = reader.readLine();
                while (line != null) {
                    log = log + "\r\n" + line;
                    line = reader.readLine();
                }
                setLog(log);
                JOptionPane.showMessageDialog(null, "?", "",
                        JOptionPane.ERROR_MESSAGE);
                return null;
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            line = reader.readLine();
            return line;
        } catch (SocketTimeoutException e) {
            setLog("?:" + e.getMessage());
            return null;
        } catch (IOException e) {
            setLog("?? I/O:" + e.getMessage());
            return null;
        }
    }

    /**
     * 
     * @param line ?JSON
     * @param format ? 1csv 2xml 3html 4txt
     * @param page ?
     */
    public void writeFile(String line, int format, int page) {
        String created_at;
        String id;
        String text;
        String source;
        JSONObject userjson;
        String userid;
        String screen_name;
        String description;
        String profile_image_url;
        String location;
        JSONObject photojson;
        String photourl = "";
        String picname = "";
        /* JSON? */
        try {
            JSONArray jsonarr = new JSONArray(line);
            int arrlen = jsonarr.length();
            if (arrlen == 0) {
                setLog("\r\n?\r\n" + String.valueOf(num) + "??");
                exitTread();
                Main.export.interrupt();
                return;
            }

            if (format == 3) {
                try {
                    outstream = new PrintWriter(new OutputStreamWriter(
                            new FileOutputStream(filepath + "/" + filename + "_" + String.valueOf(page) + ".html"),
                            "UTF-8"));
                    outstream.println("<html>");
                    outstream.println("<head>");
                    outstream.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
                    outstream.println("<title>" + filename + "</title>");
                    outstream.println("</head>");
                    outstream.println("<body>");
                    outstream.print("<a href=\"" + filepath + "/" + filename + "_" + String.valueOf(page - 1)
                            + ".html\"></a>  ");
                    outstream.println("<a href=\"" + filepath + "/" + filename + "_" + String.valueOf(page + 1)
                            + ".html\"></a><br /><hr><br />");
                } catch (FileNotFoundException e) {
                    setLog(e.getMessage());
                    Main.isStart = false;
                    Main.btnStart.setText("");
                    Main.export.interrupt();
                    return;
                } catch (UnsupportedEncodingException e) {
                    setLog(e.getMessage());
                    Main.isStart = false;
                    Main.btnStart.setText("");
                    Main.export.interrupt();
                    return;
                }
            }

            JSONObject[] json = new JSONObject[61];
            for (int j = 0; j < arrlen; j++) {
                json[j] = jsonarr.getJSONObject(j);
                created_at = json[j].getString("created_at");
                created_at = getStrDate(created_at);
                id = json[j].getString("id");
                text = json[j].getString("text");
                source = json[j].getString("source");
                userjson = json[j].getJSONObject("user");

                userid = userjson.getString("id");
                screen_name = userjson.getString("screen_name");
                description = userjson.getString("description");
                profile_image_url = userjson.getString("profile_image_url");
                location = userjson.getString("location");

                photourl = "";
                picname = "";
                try {
                    photojson = json[j].getJSONObject("photo");
                    photourl = photojson.getString("largeurl");
                    if (exportPic) {
                        picname = savePhoto(photourl, picpath);
                    }
                } catch (JSONException e) {

                }

                if (format == 1) //csv
                {
                    StringBuffer sb = new StringBuffer(500);
                    sb.append(created_at).append(",\"").append(text).append("\",");
                    sb.append(id).append(",").append(source).append(",");
                    sb.append(photourl).append(",");
                    sb.append(userid).append(",").append(screen_name).append(",\"");
                    sb.append(description).append("\",").append(profile_image_url).append(",");
                    sb.append(location);
                    outstream.println(sb.toString());
                } else if (format == 2) //xml
                {
                    outstream.println("  <status>");
                    outstream.println("    <created_at>" + created_at + "</created_at>");
                    outstream.println("    <text>");
                    outstream.println("      " + text);
                    outstream.println("    </text>");
                    outstream.println("    <id>" + id + "</id>");
                    outstream.println("    <source>");
                    outstream.println("      " + source);
                    outstream.println("    </source>");
                    if (photourl != "") {
                        outstream.println("    <photo>" + photourl + "</photo>");
                    }
                    outstream.println("    <user>");
                    outstream.println("      <user_id>" + userid + "</user_id>");
                    outstream.println("      <screen_name>" + screen_name + "</screen_name>");
                    outstream.println("      <description>" + description + "</description>");
                    outstream.println("      <profile_image_url>" + profile_image_url + "</profile_image_url>");
                    outstream.println("      <location>" + location + "</location>");
                    outstream.println("    </user>");
                    outstream.println("  </status>");
                } else if (format == 3) //html
                {
                    outstream.println("<b>" + screen_name + "</b> " + userid);
                    outstream.println("<br />");
                    outstream.println("<small>" + description + "</small>");
                    outstream.println("<br />");
                    outstream.println("<small><i>" + location + "</i></small>");
                    outstream.println("<br /><br />");
                    outstream.println(text);
                    outstream.println("<br /><br />");
                    if (picname != "") {
                        outstream.println("<img src=\"" + filename + "_pic\\" + picname + "\" /><br />");
                    }
                    outstream.println("<small>" + created_at + "</small>");
                    outstream.println("<br /><small>" + " " + source + "</small>");
                    outstream.println("<br />");
                    outstream.println("<small>id: " + id + "</small>");
                    outstream.println("<br /><br />");
                    outstream.println("<hr><br />");
                } else //txt
                {
                    outstream.println("@" + screen_name + " (" + userid + ")");
                    outstream.println();
                    outstream.println(text);
                    outstream.println();
                    outstream.println(created_at);
                    outstream.println(" " + source);
                    outstream.println("id: " + id);
                    outstream.println();
                    outstream.println("========================================");
                    outstream.println();
                }

            } //for

            num = num + arrlen;
            setLog("?" + String.valueOf(num) + "??");
            errtime = 0;

        } catch (JSONException e) {
            errtime++;
            setLog(":\r\n" + e.getMessage() + "\r\n" + errtime + "?");
        }
        if (format == 3) {
            outstream.print("<a href=\"" + filepath + "/" + filename + "_" + String.valueOf(page - 1)
                    + ".html\"></a>  ");
            outstream.println("<a href=\"" + filepath + "/" + filename + "_" + String.valueOf(page + 1)
                    + ".html\"></a><br /><hr><br />");
            outstream.println("</body>");
            outstream.println("</html>");
            outstream.close();
        }
    }

    /**
      * Computes RFC 2104-compliant HMAC signature.
     * @author Yusuke Yamamoto - yusuke at mac.com
     * @edit Unicorn-Feng
     * @see <a href="http://oauth.net/core/1.0/">OAuth Core 1.0</a>
      * @param data the data to be signed
      * @param access token secret
      * @return signature
      * @see <a href="http://oauth.net/core/1.0/#rfc.section.9.2.1">OAuth Core - 9.2.1.  Generating Signature</a>
      */
    public static String generateSignature(String data, String token) {
        byte[] byteHMAC = null;
        try {
            Mac mac = Mac.getInstance(HMAC_SHA1);
            SecretKeySpec spec;
            if (token == null) {
                String oauthSignature = encode(consumer_secret) + "&";
                spec = new SecretKeySpec(oauthSignature.getBytes(), HMAC_SHA1);
            } else {
                String oauthSignature = encode(consumer_secret) + "&" + encode(token);
                spec = new SecretKeySpec(oauthSignature.getBytes(), HMAC_SHA1);
            }
            mac.init(spec);
            byteHMAC = mac.doFinal(data.getBytes());
        } catch (InvalidKeyException e) {
            setLog(e.getMessage());
        } catch (NoSuchAlgorithmException ignore) {
            // should never happen
        }
        try {
            return URLEncoder.encode(BASE64Encoder.encode(byteHMAC), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            setLog("?");
        }
        return null;
    }

    public static String generateSignature(String data) {
        return generateSignature(data, null);
    }

    /**
     * @author Yusuke Yamamoto - yusuke at mac.com
     * @see <a href="http://oauth.net/core/1.0/">OAuth Core 1.0</a>
     * @param value string to be encoded
     * @return encoded string
     * @see <a href="http://wiki.oauth.net/TestCases">OAuth / TestCases</a>
     * @see <a href="http://groups.google.com/group/oauth/browse_thread/thread/a8398d0521f4ae3d/9d79b698ab217df2?hl=en&lnk=gst&q=space+encoding#9d79b698ab217df2">Space encoding - OAuth | Google Groups</a>
     * @see <a href="http://tools.ietf.org/html/rfc3986#section-2.1">RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax - 2.1. Percent-Encoding</a>
     */
    public static String encode(String value) {
        String encoded = null;
        try {
            encoded = URLEncoder.encode(value, "UTF-8");
        } catch (UnsupportedEncodingException ignore) {
        }
        StringBuffer buf = new StringBuffer(encoded.length());
        char focus;
        for (int i = 0; i < encoded.length(); i++) {
            focus = encoded.charAt(i);
            if (focus == '*') {
                buf.append("%2A");
            } else if (focus == '+') {
                buf.append("%20");
            } else if (focus == '%' && (i + 1) < encoded.length() && encoded.charAt(i + 1) == '7'
                    && encoded.charAt(i + 2) == 'E') {
                buf.append('~');
                i += 2;
            } else {
                buf.append(focus);
            }
        }
        return buf.toString();
    }

}