package i2p.bote.android.service; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; import android.preference.PreferenceManager; import android.util.Log; import net.i2p.android.ui.I2PAndroidHelper; import net.i2p.client.I2PClient; import net.i2p.data.DataHelper; import net.i2p.util.FileUtil; import net.i2p.util.OrderedProperties; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import i2p.bote.android.Constants; import i2p.bote.android.R; public class Init { private final Context ctx; private final String myDir; public enum RouterChoice { INTERNAL, ANDROID, REMOTE } public Init(Context c) { ctx = c; // This needs to be changed so that we can have an alternative place myDir = c.getFilesDir().getAbsolutePath(); } /** * Parses settings and prepares the system for starting the Bote service. * @return the router choice. */ public RouterChoice initialize(I2PAndroidHelper helper) { // Set up the locations so Router and WorkingDir can find them // We do this again here, in the event settings were changed. System.setProperty("i2p.dir.base", myDir); System.setProperty("i2p.dir.config", myDir); System.setProperty("wrapper.logfile", myDir + "/wrapper.log"); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx); RouterChoice routerChoice; String i2cpHost, i2cpPort; if (prefs.getBoolean("i2pbote.router.auto", true)) { if (helper.isI2PAndroidInstalled()) routerChoice = RouterChoice.ANDROID; else routerChoice = RouterChoice.INTERNAL; i2cpHost = "internal"; i2cpPort = "internal"; } else { // Check manual settings String which = prefs.getString("i2pbote.router.use", "internal"); if ("remote".equals(which)) { routerChoice = RouterChoice.REMOTE; i2cpHost = prefs.getString("i2pbote.i2cp.tcp.host", "127.0.0.1"); i2cpPort = prefs.getString("i2pbote.i2cp.tcp.port", "7654"); } else { if ("android".equals(which)) routerChoice = RouterChoice.ANDROID; else // Internal router routerChoice = RouterChoice.INTERNAL; i2cpHost = "internal"; i2cpPort = "internal"; } } // Set the I2CP host/port System.setProperty(I2PClient.PROP_TCP_HOST, i2cpHost); System.setProperty(I2PClient.PROP_TCP_PORT, i2cpPort); if (routerChoice == RouterChoice.INTERNAL) { mergeResourceToFile(R.raw.router_config, "router.config", null); File certDir = new File(myDir, "certificates"); certDir.mkdir(); File certificates = new File(myDir, "certificates"); File[] allcertificates = certificates.listFiles(); if ( allcertificates != null) { for (File f : allcertificates) { Log.d(Constants.ANDROID_LOG_TAG, "Deleting old certificate file/dir " + f); FileUtil.rmdir(f, false); } } unzipResourceToDir(R.raw.certificates_zip, "certificates"); } return routerChoice; } /** * Load defaults from resource, * then add props from settings, * and write back * * @param f relative to base dir * @param overrides local overrides or null */ public void mergeResourceToFile(int resID, String f, Properties overrides) { InputStream in = null; InputStream fin = null; try { in = ctx.getResources().openRawResource(resID); Properties props = new OrderedProperties(); try { fin = new FileInputStream(new File(myDir, f)); DataHelper.loadProps(props, fin); } catch (IOException ioe) { } // write in default settings DataHelper.loadProps(props, in); // override with user settings if (overrides != null) props.putAll(overrides); File path = new File(myDir, f); DataHelper.storeProps(props, path); } catch (IOException ioe) { } catch (Resources.NotFoundException nfe) { } finally { if (in != null) try { in.close(); } catch (IOException ioe) { } if (fin != null) try { fin.close(); } catch (IOException ioe) { } } } /** * @param folder relative to base dir */ private void unzipResourceToDir(int resID, String folder) { InputStream in = null; FileOutputStream out = null; ZipInputStream zis = null; Log.d(Constants.ANDROID_LOG_TAG, "Creating files in '" + myDir + "/" + folder + "/' from resource"); try { // Context methods in = ctx.getResources().openRawResource(resID); zis = new ZipInputStream((in)); ZipEntry ze; while ((ze = zis.getNextEntry()) != null) { out = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int count; while ((count = zis.read(buffer)) != -1) { baos.write(buffer, 0, count); } String name = ze.getName(); File f = new File(myDir + "/" + folder +"/" + name); if (ze.isDirectory()) { Log.d(Constants.ANDROID_LOG_TAG, "Creating directory " + myDir + "/" + folder +"/" + name + " from resource"); f.mkdir(); } else { Log.d(Constants.ANDROID_LOG_TAG, "Creating file " + myDir + "/" + folder +"/" + name + " from resource"); byte[] bytes = baos.toByteArray(); out = new FileOutputStream(f); out.write(bytes); } } catch (IOException ioe) { } finally { if (out != null) { try { out.close(); } catch (IOException ioe) {} out = null; } } } } catch (IOException ioe) { } catch (Resources.NotFoundException nfe) { } finally { if (in != null) try { in.close(); } catch (IOException ioe) {} if (out != null) try { out.close(); } catch (IOException ioe) {} if (zis != null) try { zis.close(); } catch (IOException ioe) {} } } }