package org.oobd.ui.android.application; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.prefs.Preferences; import java.io.*; import java.lang.reflect.Method; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.Proxy; import java.net.SocketException; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import org.oobd.base.Core; import org.oobd.base.OOBDConstants; import org.oobd.base.IFsystem; import org.oobd.base.IFui; import org.oobd.base.archive.*; import org.oobd.base.port.ComPort_Kadaver; import org.oobd.base.port.ComPort_Telnet; import org.oobd.base.port.OOBDPort; import org.oobd.base.support.Onion; import org.oobd.base.scriptengine.OobdScriptengine; import org.oobd.crypt.AES.EncodeDecodeAES; import org.oobd.crypt.AES.PassPhraseProvider; import org.oobd.ui.android.Diagnose; import org.oobd.ui.android.MainActivity; import org.oobd.ui.android.bus.ComPort; import android.app.Activity; import android.app.AlertDialog; import android.app.Application; import android.net.DhcpInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.Uri; import android.os.Environment; import android.os.IBinder; import android.util.Log; import android.widget.Toast; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; /** * @author Andreas Budde, Peter Mayer Base class to maintain global application * state. This activity is Initialised before all others. Store here * e.g. list of bluetooth devices,... */ public class OOBDApp extends Application implements IFsystem, OOBDConstants { // Constants that are global for the Android App public static final String VISUALIZER_UPDATE = "OOBD Broadcast_UI_Update"; public static final String UPDATE_LEVEL = "OOBD Update Level"; public static final int REQUEST_ENABLE_BT = 10; public Core core; // make it singleton private static OOBDApp mInstance; private Toast mToast; private OOBDPort myComPort; private String userPassPhrase = ""; String webRootDir = ""; String webLibraryDir = ""; Preferences appProbs; String oobdMacAddress = "-"; InetAddress oobdIPAddress = null; public static OOBDApp getInstance() { return mInstance; } @Override public String getOobdURL() { InetAddress ip; String hostname; ip = getSystemIP(); // even when using the external address, ip.getHostName() returns just "localhost", which //makes the server unreachable; so on android we use the ip address as host. Not so nice, but it works. hostname = ip.getHostAddress(); System.out.println("Your current Hostname : " + hostname); return "http://" + hostname + ":" + ((Integer) Core.getSingleInstance().readDataPool( DP_HTTP_PORT, 8080)).toString(); } public void openBrowser() { try { Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getOobdURL())); myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(myIntent); } catch (ActivityNotFoundException e) { Toast.makeText( this, "No application can handle this request." + " Please install a webbrowser", Toast.LENGTH_LONG) .show(); e.printStackTrace(); } } @Override public String getMACAddress() { if (oobdMacAddress.equals("-")) {// not initialized? Then do it first getSystemIP(); } return oobdMacAddress; } @Override public InetAddress getSystemIP() { if (oobdIPAddress != null) { return oobdIPAddress; } try { Enumeration e = NetworkInterface.getNetworkInterfaces(); while (e.hasMoreElements()) { NetworkInterface n = (NetworkInterface) e.nextElement(); Enumeration ee = n.getInetAddresses(); while (ee.hasMoreElements()) { oobdIPAddress = (InetAddress) ee.nextElement(); System.out.println(oobdIPAddress.getHostAddress()); if (oobdIPAddress.isSiteLocalAddress()) { System.out .println("Your current local side IP address : " + oobdIPAddress); WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE); WifiInfo info = manager.getConnectionInfo(); oobdMacAddress = info.getMacAddress(); System.out.println("Your current MAC address : " + oobdMacAddress); return oobdIPAddress; } } } oobdIPAddress = InetAddress.getLocalHost(); System.out.println("Your current IP address : " + oobdIPAddress); return oobdIPAddress; } catch (UnknownHostException ex) { oobdMacAddress = "-"; oobdIPAddress = null; Log.v(this.getClass().getSimpleName(), ex.getMessage()); } catch (SocketException ex) { oobdMacAddress = "-"; oobdIPAddress = null; Log.v(this.getClass().getSimpleName(), ex.getMessage()); } return null; } public String generateUIFilePath(int pathID, String fileName) { System.err.println("Try to map file "+fileName); switch (pathID) { case FT_RAW: case FT_WEBPAGE: case FT_DATABASE: return fileName; case FT_KEY: return getFilesDir() + "/" + fileName; case FT_KEY_IMPORT: default: File myFile = new File(Environment.getExternalStorageDirectory() .getPath() + "/OOBD/" + fileName); if (myFile.exists()) { System.err.println("found as "+myFile.getAbsolutePath()); return myFile.getAbsolutePath(); } else { System.err.println("try to find as "+appProbs.get( OOBDConstants.PropName_ScriptDir, "") + "/" + fileName); myFile = new File(appProbs.get( OOBDConstants.PropName_ScriptDir, "") + "/" + fileName); if (myFile.exists()) { System.err.println("found as "+myFile.getAbsolutePath()); return myFile.getAbsolutePath(); } System.err.println("give up, report as "+fileName); return fileName; } } } public void displayToast(CharSequence text) { mToast.setText(text); mToast.show(); } /* replaces leading directory alias against their physical location */ String mapDirectory(String[] mapDir, String path) { int i = 0; while (i < mapDir.length) { if (path.toLowerCase().startsWith("/" + mapDir[i].toLowerCase() + "/")) { path = path.substring(mapDir[i].length() + 2); if (mapDir[i].toLowerCase().equalsIgnoreCase("theme") && path.toLowerCase().startsWith("default/")) { //map the theme folder to the actual theme path = core.readDataPool(DP_WEBUI_ACTUAL_THEME, "default") + "/" + path.substring("default/".length()); } return mapDir[i + 1] + path; } i += 2; } return null; } public InputStream generateResourceStream(int pathID, String resourceName) throws java.util.MissingResourceException { Log.v(this.getClass().getSimpleName(), "Try to load: " + resourceName + " with path ID : " + pathID); InputStream resource = null; /* switch (pathID) { case OOBDConstants.FT_PROPS: try { resource = new FileInputStream(generateUIFilePath(pathID, resourceName)); Log.v(this.getClass().getSimpleName(), "File " + resourceName + " loaded from /sdcard/oobd"); } catch (FileNotFoundException e) { Log.v(this.getClass().getSimpleName(), "File " + resourceName + " could not loaded from /sdcard/oobd", e); } return resource; case OOBDConstants.FT_WEBPAGE: String newPath = mapDirectory("libs", resourceName); if (!newPath.equals("")) { // CAUTION: This directory mapping is only temporary, as Android // does not // handle any webapp subdirectories. // this is just a dirty hack // resourceName="/../libs/"+newPath; resourceName = "/libs/" + newPath; } // please notice: here's no case "break"! case OOBDConstants.FT_DATABASE: case OOBDConstants.FT_SCRIPT: try { String filePath = generateUIFilePath(pathID, resourceName); Archive achive = Factory.getArchive(filePath); achive.bind(filePath); resource = achive.getInputStream(""); Log.v(this.getClass().getSimpleName(), "File " + resourceName + " loaded from /sdcard/oobd"); } catch (Exception e) { Log.v(this.getClass().getSimpleName(), "File " + resourceName + " could not loaded from /sdcard/oobd"); } return resource; case OOBDConstants.FT_KEY: try { resource = openFileInput(resourceName); Log.v(this.getClass().getSimpleName(), "Key File " + resourceName + " loaded"); } catch (Exception e) { Log.v(this.getClass().getSimpleName(), "Key File " + resourceName + " could not loaded", e); } return resource; default: throw new java.util.MissingResourceException("Resource not known", "OOBDApp", resourceName); } */ Archive scriptArchive = (Archive) core.readDataPool(DP_ACTIVE_ARCHIVE, null); try { switch (pathID) { case OOBDConstants.FT_WEBPAGE: appProbs = core.getSystemIF().loadPreferences(FT_PROPS, OOBDConstants.AppPrefsFileName); webRootDir = (String) core.readDataPool(DP_SCRIPTDIR, "") + "/"; webLibraryDir = (String) core.readDataPool(DP_WWW_LIB_DIR, "") + "/"; // in case the resource name points to a "executable" scriptengine, the engine get started // and the resourcename is corrected to the html start page to be used resourceName = core.startScriptEngineByURL(resourceName); scriptArchive = (Archive) core.readDataPool(DP_ACTIVE_ARCHIVE, null); String mapping = mapDirectory(new String[]{"libs", webLibraryDir + "libs/", "theme", webLibraryDir + "theme/"}, resourceName); if (mapping != null) { //its a mapped request core.writeDataPool(DP_LAST_OPENED_PATH, mapping); return new FileInputStream(generateUIFilePath(pathID, mapping)); } // let's see, if it's a passthrough request; String[] parts = resourceName.split("/", 3); //remember that resourceName starts with /, so the first split part should be empty if (parts.length > 2) { ArrayList<Archive> files = (ArrayList<Archive>) core.readDataPool(DP_LIST_OF_SCRIPTS, null); if (files != null) { for (Archive file : files) { if (parts[1].equals(file.getFileName())) { core.writeDataPool(DP_LAST_OPENED_PATH, parts[2]); return file.getInputStream(parts[2]); } } } } if (scriptArchive != null) { // if everything else fails, try to load the file out of the package core.writeDataPool(DP_LAST_OPENED_PATH, resourceName); return scriptArchive.getInputStream(resourceName); } break; case OOBDConstants.FT_PROPS: case OOBDConstants.FT_RAW: case OOBDConstants.FT_KEY_IMPORT: resource = new FileInputStream(generateUIFilePath(pathID, resourceName)); Log.v(this.getClass().getSimpleName(),"File " + resourceName + " loaded"); break; case OOBDConstants.FT_DATABASE: if (scriptArchive != null) { resource = scriptArchive.getInputStream(resourceName); } break; case OOBDConstants.FT_SCRIPT: appProbs = core.getSystemIF().loadPreferences(FT_PROPS, OOBDConstants.AppPrefsFileName); // save actual script directory to buffer it for later as webroot directory // resource = scriptArchive.getInputStream(scriptArchive.getProperty(OOBDConstants.MANIFEST_SCRIPTNAME, OOBDConstants.MANIFEST_SCRIPTNAME_DEFAULT)); resource = scriptArchive.getInputStream(scriptArchive.getProperty(OOBDConstants.MANIFEST_SCRIPTNAME, resourceName)); Log.v(this.getClass().getSimpleName(), "File " + resourceName + " loaded"); break; case OOBDConstants.FT_KEY: resource = new FileInputStream(getFilesDir() + "/" + resourceName); Log.v(this.getClass().getSimpleName(),"Key File " + resourceName + " loaded"); break; default: throw new java.util.MissingResourceException("Resource not known", "OOBDApp", resourceName); } } catch (Exception e) { Log.v(this.getClass().getSimpleName(), "generateResourceStream: File " + resourceName + " not loaded"); } return resource; } public void onCreate() { super.onCreate(); mInstance = this; mToast = Toast .makeText(getApplicationContext(), "", Toast.LENGTH_SHORT); // Core thisCore = new Core(MainActivity.getMyMainActivity(), this, // "Core"); // Log.v(this.getClass().getSimpleName(), "Core creation finalized" // + thisCore.toString()); } public void registerOobdCore(Core core) { this.core = core; Log.v(this.getClass().getSimpleName(), "Core registered in IFsystem"); } public HashMap<String, Class<?>> loadOobdClasses(String path, String classPrefix, Class<?> classType) { HashMap<String, Class<?>> myInstances = new HashMap<String, Class<?>>(); Class<?> tempClass = null; try { tempClass = Class.forName(path); myInstances.put(tempClass.getSimpleName(), tempClass); } catch (ClassNotFoundException e) { System.out.println("Cant load dynamic class " + path); e.printStackTrace(); } return myInstances; } public Core getCore() { return core; } public Object supplyHardwareHandle(Onion typ) { SharedPreferences preferences; preferences = this.getSharedPreferences("OOBD_SETTINGS", MODE_PRIVATE); if (typ != null) { String connectURL = typ.getOnionBase64String("connecturl"); String[] parts = connectURL.split("://"); if (parts.length != 2) { return null; } String protocol = parts[0]; String host = parts[1]; String proxyHost = preferences.getString( OOBDConstants.PropName_ProxyHost, null); int proxyPort = preferences.getInt( OOBDConstants.PropName_ProxyPort, 0); if (protocol.toLowerCase().startsWith("ws")) { try { Proxy thisProxy = Proxy.NO_PROXY; if (proxyHost != null && proxyPort != 0) { thisProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); } myComPort = new ComPort_Kadaver(new URI(connectURL), thisProxy, proxyHost, proxyPort); return myComPort; } catch (URISyntaxException ex) { Log.v(this.getClass().getSimpleName(), "could not open Websocket Interface", ex); return null; } } else if ("bt".equalsIgnoreCase(protocol)) { myComPort = new ComPort(Diagnose.getInstance(), host); return myComPort; } else if ("telnet".equalsIgnoreCase(protocol)) { Proxy thisProxy = null; if (proxyHost != null && proxyPort != 0) { thisProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); } myComPort = new ComPort_Telnet(connectURL); return myComPort; } else return null; } else { // todo Android always needs a comport object to have a list of the // possible devices for the settings screen // return new ComPort(Diagnose.getInstance(), BTDeviceName); return null; } } public String connectInfo() { if (myComPort == null) { return null; } else { return (myComPort.connectInfo()); } } public void closeHardwareHandle() { if (myComPort != null) { myComPort.close(); myComPort = null; } } public char[] getAppPassPhrase() { return PassPhraseProvider.getPassPhrase(); } public String getUserPassPhrase() { if (userPassPhrase.equals("")) { return ""; } else { try { return new String(EncodeDecodeAES.decrypt(new String( getAppPassPhrase()), userPassPhrase)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return ""; } } } public void setUserPassPhrase(String upp) { try { userPassPhrase = EncodeDecodeAES.encrypt(new String( getAppPassPhrase()), upp); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); userPassPhrase = ""; } } public void createEngineTempInputFile(OobdScriptengine eng) { File f = null; try { // do we have to delete a previous first? eng.removeTempInputFile(); // creates temporary file f = File.createTempFile("oobd", null, null); // deletes file when the virtual machine terminate f.deleteOnExit(); eng.setTempInputFile(f); } catch (Exception e) { // if any error occurs Log.v(this.getClass().getSimpleName(), "could not create temp file! ", e); } } public String doFileSelector(String path, final String extension, String message, Boolean save) { Log.w(this.getClass().getSimpleName(), "Procedure doFileSelector called, but senseless in android! "); return null; } public Preferences loadPreferences(int pathID, String filename) { Preferences myPrefs = null; try { Preferences prefsRoot; prefsRoot = Preferences.userNodeForPackage(this.getClass()); // prefsRoot.sync(); myPrefs = prefsRoot.node("com.oobd.preference." + filename); /* * if (myPrefs.keys().length == 0 && OOBDConstants.CorePrefsFileName * .equalsIgnoreCase(filename)) { // no entries yet // generate * system specific settings myPrefs.put("EngineClassPath", * "org.oobd.base.scriptengine.ScriptengineLua"); * myPrefs.put("ProtocolClassPath", * "org.oobd.base.protocol.ProtocolUDS"); * myPrefs.put("ConnectorClassPath", * "org.oobd.base.connector.ConnectorLocal"); * myPrefs.put("BusClassPath", "org.oobd.base.bus.BusCom"); * myPrefs.put("DatabaseClassPath", "org.oobd.base.db.AVLLookup"); * myPrefs.put("UIHandlerClassPath", * "org.oobd.ui.uihandler.UIHandler"); myPrefs.flush(); } */ return myPrefs; } catch (Exception e) { Log.v(this.getClass().getSimpleName(), "could not load property id " + filename); } return myPrefs; } public boolean savePreferences(int pathID, String filename, Preferences properties) { try { properties.flush(); return true; } catch (Exception e) { Log.v(this.getClass().getSimpleName(), "could not save property id " + filename, e); return false; } } public Hashtable<String, Class> getConnectorList() { Hashtable<String, Class> connectClasses = new Hashtable<String, Class>(); connectClasses.put(OOBDConstants.PropName_ConnectTypeBT, ComPort.class); connectClasses.put(OOBDConstants.PropName_ConnectTypeRemoteConnect, ComPort_Kadaver.class); connectClasses.put(OOBDConstants.PropName_ConnectTypeRemoteDiscovery, ComPort_Telnet.class); connectClasses.put(OOBDConstants.PropName_ConnectTypeTelnet, ComPort_Telnet.class); return connectClasses; } public DatagramSocket getUDPBroadcastSocket() { try { DatagramSocket socket = null; // WifiManager wifi = (WifiManager) getApplicationContext() // .getSystemService(Context.WIFI_SERVICE); // if (wifi != null) { // DhcpInfo dhcp = wifi.getDhcpInfo(); // if (dhcp != null) { // // int broadcast = (dhcp.ipAddress & dhcp.netmask) | // // ~dhcp.netmask; // int broadcast = dhcp.ipAddress; // byte[] quads = new byte[4]; // for (int k = 0; k < 4; k++) // quads[k] = (byte) ((broadcast >> k * 8) & 0xFF); // socket = new DatagramSocket(UDP_PORT, // InetAddress.getByAddress(quads)); // } // } if (socket == null) { socket = new DatagramSocket(UDP_PORT); } socket.setBroadcast(true); return socket; } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); return null; } } }