/*
Copyright 2012 Jan Ove Saltvedt
This file is part of KBot.
KBot 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.
KBot 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 KBot. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright � 2010 Jan Ove Saltvedt.
* All rights reserved.
*/
package com.kbotpro.servercom;
import com.kbotpro.Version;
import com.kbotpro.handlers.AccountsManager;
import com.kbotpro.utils.Constant;
import com.kbotpro.utils.ProgressCallback;
import com.kbotpro.utils.VirtualBrowser;
import com.kbotpro.various.StaticStorage;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import javax.swing.*;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA.
* User: Jan Ove Saltvedt
* Date: Feb 15, 2010
* Time: 6:31:49 PM
* To change this template use File | Settings | File Templates.
*/
public class HttpServerCom extends ServerCom implements Runnable{
public boolean runServerPinger = true;
private Thread serverPinger;
public HttpServerCom(){
serverPinger = new Thread(this, "ServerCom");
}
public void startServerPinger(){
runServerPinger = true;
serverPinger.start();
}
/**
* Sends login data to server for verification.
* @return returns a xml string containing response.
*/
public Object[] login(){
final UserStorage userStorage = StaticStorage.userStorage;
String xml = null;
try {
String postParams = "username="+ URLEncoder.encode(userStorage.getUsername(), "UTF-8");
postParams += "&md5="+URLEncoder.encode(MD5(userStorage.getPassword()), "UTF-8");
VirtualBrowser virtualBrowser = new VirtualBrowser();
xml = virtualBrowser.post(new URL("http://"+ Constant.SERVER_HOST+"/kbotpro/botcom/auth.php"), postParams, null);
} catch (UnsupportedEncodingException e) {
xml = "<login><succeeded>false</succeeded><message>Could not URL encode data.</message></login>";
} catch (NoSuchAlgorithmException e) {
xml = "<login><succeeded>false</succeeded><message>This computer does not support MD5 hashing.</message></login>";
} catch (MalformedURLException e) {
xml = "<login><succeeded>false</succeeded><message>An error occured! </message></login>";
}
try {
Document document = new SAXBuilder().build(new StringReader(xml));
org.jdom.Element root = document.getRootElement();
String succeded = root.getChildText("succeeded");
if(!succeded.equals("true")){
StaticStorage.userStorage = null;
return new Object[]{Boolean.FALSE, root.getChildText("message")};
}
else{
userStorage.setUserID(Integer.parseInt(root.getChildText("userID")));
userStorage.setSessionID(Integer.parseInt(root.getChildText("sessionID")));
userStorage.setSessionKey(root.getChildText("sessionKey"));
userStorage.setAccessLevel(Integer.parseInt(root.getChildText("access")));
startServerPinger();
return new Object[]{Boolean.TRUE, root.getChildText("message")};
}
} catch (JDOMException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
return new Object[]{Boolean.FALSE, "Error in server response."};
} catch (IOException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
return new Object[]{Boolean.FALSE, "Error in server response."};
}
}
private String getSettingsInternal(){
final UserStorage userStorage = StaticStorage.userStorage;
try {
String postParams = "userID="+userStorage.getUserID();
postParams += "&sessionID="+userStorage.getSessionID();
postParams += "&sessionKey="+URLEncoder.encode(userStorage.getSessionKey(), "UTF-8");
VirtualBrowser virtualBrowser = new VirtualBrowser();
return virtualBrowser.post(new URL("http://"+ Constant.SERVER_HOST+"/kbotpro/botcom/getSettings.php"), postParams, null);
} catch (UnsupportedEncodingException e) {
return "<login><succeeded>false</succeeded><message>Could not URL encode data.</message></login>";
} catch (MalformedURLException e) {
return "<login><succeeded>false</succeeded><message>An error occured! </message></login>";
}
}
public String getAccountsInternal(){
final UserStorage userStorage = StaticStorage.userStorage;
try {
String postParams = "userID="+userStorage.getUserID();
postParams += "&sessionID="+userStorage.getSessionID();
postParams += "&sessionKey="+URLEncoder.encode(userStorage.getSessionKey(), "UTF-8");
VirtualBrowser virtualBrowser = new VirtualBrowser();
return virtualBrowser.post(new URL("http://"+ Constant.SERVER_HOST+"/kbotpro/botcom/getAccounts.php"), postParams, null);
} catch (UnsupportedEncodingException e) {
return "<login><succeeded>false</succeeded><message>Could not URL encode data.</message></login>";
} catch (MalformedURLException e) {
return "<login><succeeded>false</succeeded><message>An error occured! </message></login>";
}
}
public boolean setSettingServerSide(String name, String value){
final UserStorage userStorage = StaticStorage.userStorage;
try {
String postParams = "userID="+userStorage.getUserID();
postParams += "&sessionID="+userStorage.getSessionID();
postParams += "&sessionKey="+URLEncoder.encode(userStorage.getSessionKey(), "UTF-8");
postParams += "&settingName="+URLEncoder.encode(name, "UTF-8");
postParams += "&settingValue="+URLEncoder.encode(value, "UTF-8");
VirtualBrowser virtualBrowser = new VirtualBrowser();
String xml = virtualBrowser.post(new URL("http://" + Constant.SERVER_HOST + "/kbotpro/botcom/setSetting.php"), postParams, null);
Document document = new SAXBuilder().build(new StringReader(xml));
Element root = document.getRootElement();
return root.getChildText("succeeded").equals("true");
} catch (UnsupportedEncodingException e) {
return false;
} catch (MalformedURLException e) {
return false;
} catch (JDOMException e) {
return false;
} catch (IOException e) {
return false;
}
}
public void getSettings(){
String xml = getSettingsInternal();
HashMap<String, String> settings = new HashMap<String, String>();
try {
Document document = new SAXBuilder().build(new StringReader(xml));
Element root = document.getRootElement();
if(root.getChildText("succeeded").equals("true")){
for(Element setting: (List<Element>)root.getChildren("setting")){
settings.put(setting.getChildText("name"), setting.getChildText("value"));
}
}
} catch (JDOMException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
} catch (IOException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
}
StaticStorage.userStorage.settings = settings;
}
private boolean outdatedOpen = false;
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p/>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
public void run() {
while(StaticStorage.userStorage != null && runServerPinger){
final UserStorage userStorage = StaticStorage.userStorage;
VirtualBrowser virtualBrowser = new VirtualBrowser();
try {
String postParams = "userID="+ userStorage.getUserID();
postParams += "&sessionID="+ userStorage.getSessionID();
postParams += "&sessionKey="+URLEncoder.encode(userStorage.getSessionKey(), "UTF-8");
String response = virtualBrowser.post(new URL("http://"+ Constant.SERVER_HOST+"/kbotpro/botcom/pinger.php"), postParams, null);
try {
Document document = new SAXBuilder().build(new StringReader(response));
Element root = document.getRootElement();
if(!root.getChildText("succeeded").equals("true")){
JOptionPane.showMessageDialog(null, root.getChildText("message"), "Error in server comunication.", JOptionPane.ERROR_MESSAGE);
}
Element tasks = root.getChild("tasks");
if(tasks != null){
for(Element task: (List<Element>)tasks.getChildren("task")){
String action = task.getChildText("action");
if(action.equalsIgnoreCase("killbot")){
System.exit(-10);
} else if(action.equalsIgnoreCase("checkBuild")){
int build = Integer.valueOf(task.getChildText("build"));
if(Integer.valueOf(Version.build) < build){
if(!outdatedOpen){
new Thread(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(null, "This version of KBot is considered outdated. \nPlease update your bot.", "Bot Outdated", JOptionPane.ERROR_MESSAGE);
}
}).start();
}
}
}
}
}
} catch (JDOMException e) {
if(!response.contains("<succeeded>true</succeeded>")){
Pattern pattern = Pattern.compile("<message>([\\w\\s]+)</message>");
Matcher matcher = pattern.matcher(response);
if(matcher.find()){
String message = matcher.group(1);
JOptionPane.showMessageDialog(null, message, "Error in server comunication.", JOptionPane.ERROR_MESSAGE);
return;
}
else{
JOptionPane.showMessageDialog(null, "Could not connect with master server.", "Error in server comunication.", JOptionPane.ERROR_MESSAGE);
return;
}
}
} catch (IOException e) {
if(!response.contains("<succeeded>true</succeeded>")){
Pattern pattern = Pattern.compile("<message>([\\w\\s]+)</message>");
Matcher matcher = pattern.matcher(response);
if(matcher.find()){
String message = matcher.group(1);
JOptionPane.showMessageDialog(null, message, "Error in server comunication.", JOptionPane.ERROR_MESSAGE);
return;
}
else{
JOptionPane.showMessageDialog(null, "Could not connect with master server.", "Error in server comunication.", JOptionPane.ERROR_MESSAGE);
return;
}
}
}
} catch (UnsupportedEncodingException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
} catch (MalformedURLException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
}
try {
Thread.sleep(600000);
} catch (InterruptedException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
}
}
}
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
public static String SHA1(String text)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md;
md = MessageDigest.getInstance("SHA-1");
byte[] sha1hash;
md.update(text.getBytes("iso-8859-1"), 0, text.length());
sha1hash = md.digest();
return convertToHex(sha1hash);
}
public static String MD5(String text)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md;
md = MessageDigest.getInstance("MD5");
byte[] sha1hash;
md.update(text.getBytes("iso-8859-1"), 0, text.length());
sha1hash = md.digest();
return convertToHex(sha1hash);
}
public String getScriptList() {
VirtualBrowser virtualBrowser = new VirtualBrowser();
try {
return virtualBrowser.get(new URL("http://"+ Constant.SERVER_HOST+"/kbotpro/botcom/scriptList.php"), null, null);
} catch (MalformedURLException e) {
return "<scripts></scripts>";
}
}
public byte[] downloadScript(int id, ProgressCallback progressCallback) {
final UserStorage userStorage = StaticStorage.userStorage;
try {
String postParams = "userID="+userStorage.getUserID();
postParams += "&sessionID="+userStorage.getSessionID();
postParams += "&sessionKey="+URLEncoder.encode(userStorage.getSessionKey(), "UTF-8");
postParams += "&scriptID="+id;
VirtualBrowser virtualBrowser = new VirtualBrowser();
return virtualBrowser.postRaw(new URL("http://"+ Constant.SERVER_HOST+"/kbotpro/botcom/downloadscript.php"), postParams, progressCallback);
} catch (UnsupportedEncodingException e) {
return new byte[0];
} catch (MalformedURLException e) {
return new byte[0];
}
}
public boolean addAccount(AccountsManager.Account account) {
final UserStorage userStorage = StaticStorage.userStorage;
try {
String postParams = "userID="+userStorage.getUserID();
postParams += "&sessionID="+userStorage.getSessionID();
postParams += "&sessionKey="+URLEncoder.encode(userStorage.getSessionKey(), "UTF-8");
postParams += "&enusername="+URLEncoder.encode(account.encryptedUsername, "UTF-8");
postParams += "&usernamehash="+URLEncoder.encode(account.usernameHash, "UTF-8");
postParams += "&enpasswd="+URLEncoder.encode(account.encryptedPassword, "UTF-8");
postParams += "&passwdhash="+URLEncoder.encode(account.passwordHash, "UTF-8");
VirtualBrowser virtualBrowser = new VirtualBrowser();
String xml = virtualBrowser.post(new URL("http://" + Constant.SERVER_HOST + "/kbotpro/botcom/addAccount.php"), postParams, null);
Document document = new SAXBuilder().build(new StringReader(xml));
Element root = document.getRootElement();
return root.getChildText("succeeded").equals("true");
} catch (UnsupportedEncodingException e) {
return false;
} catch (MalformedURLException e) {
return false;
} catch (JDOMException e) {
return false;
} catch (IOException e) {
return false;
}
}
public boolean deleteAccount(AccountsManager.Account account) {
final UserStorage userStorage = StaticStorage.userStorage;
try {
String postParams = "userID="+userStorage.getUserID();
postParams += "&sessionID="+userStorage.getSessionID();
postParams += "&sessionKey="+URLEncoder.encode(userStorage.getSessionKey(), "UTF-8");
postParams += "&accountID="+account.ID;
VirtualBrowser virtualBrowser = new VirtualBrowser();
String xml = virtualBrowser.post(new URL("http://" + Constant.SERVER_HOST + "/kbotpro/botcom/deleteAccount.php"), postParams, null);
Document document = new SAXBuilder().build(new StringReader(xml));
Element root = document.getRootElement();
return root.getChildText("succeeded").equals("true");
} catch (UnsupportedEncodingException e) {
return false;
} catch (MalformedURLException e) {
return false;
} catch (JDOMException e) {
return false;
} catch (IOException e) {
return false;
}
}
}