//https://gist.github.com/komamitsu/1893396 package info.guardianproject.securereaderinterface.installer; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.widget.TextView; import info.guardianproject.securereaderinterface.FragmentActivityWithMenu; import info.guardianproject.securereaderinterface.R; import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD.Response.Status; public class HTTPDAppSender extends FragmentActivityWithMenu { private static class AppInfo { public String packageName; public int resIdIcon; public String title; public String description; public AppInfo(String packageName, String title, String description, int resIdIcon) { this.packageName = packageName; this.title = title; this.description = description; this.resIdIcon = resIdIcon; } } public AppInfo[] APPS_TO_DISPLAY; private static final HashMap<String, Integer> IMAGE_MAP; static { IMAGE_MAP = new HashMap<String, Integer>(); IMAGE_MAP.put("background_debut_light.png", R.drawable.background_debut_light); IMAGE_MAP.put("ic_share_promo.png", R.drawable.ic_share_promo); IMAGE_MAP.put("ic_action_logo.png", R.drawable.ic_action_logo); } private static final int PORT = 8080; private static final String LOGTAG = "HTTPDAPPSENDER"; private final Handler handler = new Handler(); private TextView textView; private MyHTTPD server; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); APPS_TO_DISPLAY = new AppInfo[] { new AppInfo("org.torproject.android", "", "", 0), null, new AppInfo("info.guardianproject.mrapp", "", "", 0), new AppInfo("info.guardianproject.otr.app.im", "", "", 0), new AppInfo("info.guardianproject.browser", "", "", 0) }; APPS_TO_DISPLAY[1] = new AppInfo(getPackageName(), "", "", 0); setContentView(R.layout.httpd_app_sender); textView = (TextView) findViewById(R.id.tvUrl); setMenuIdentifier(R.menu.activity_httpd_app_sender); setActionBarTitle(getString(R.string.title_activity_httpd_app_sender)); } private CharSequence getHtmlTemplate() throws IOException { InputStream inputStream = this.getResources().getAssets().open("app_share.html"); BufferedReader r = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder total = new StringBuilder(); String line; while ((line = r.readLine()) != null) { total.append(line); } return total; } @Override protected void onResume() { super.onResume(); // This could be the answer to setting it up automatically: // http://www.whitebyte.info/android/android-wifi-hotspot-manager-class // https://github.com/nickrussler/Android-Wifi-Hotspot-Manager-Class // WifiManager wifiManager = (WifiManager) // getSystemService(WIFI_SERVICE); // int ipAddress = wifiManager.getConnectionInfo().getIpAddress(); // final String formatedIpAddress = String.format("%d.%d.%d.%d", // (ipAddress & 0xff), (ipAddress >> 8 & 0xff), // (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); // Log.v(LOGTAG,"WifiManager IP: " + formatedIpAddress); // textView.setText("http://" + formatedIpAddress + ":" + PORT ); try { List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); for (NetworkInterface intf : interfaces) { List<InetAddress> addrs = Collections.list(intf.getInetAddresses()); for (InetAddress addr : addrs) { if (!addr.isLoopbackAddress() && addr.getAddress().length == 4 && !addr.getHostAddress().contains("0.0.0.0")) { String sAddr = addr.getHostAddress(); Log.v(LOGTAG, "Other IP: " + sAddr); // String aFormattedIP = String.format("%d.%d.%d.%d", // (sAddr & 0xff), (sAddr >> 8 & 0xff), // (sAddr >> 16 & 0xff), (sAddr >> 24 & 0xff)); textView.setText("http://" + sAddr + ":" + PORT); } } } } catch (Exception ex) { ex.printStackTrace(); } // for now eat exceptions try { server = new MyHTTPD(); server.start(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onPause() { super.onPause(); if (server != null) server.stop(); } private class MyHTTPD extends NanoHTTPD { public MyHTTPD() throws IOException { super(PORT); } @Override public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parms, Map<String, String> files) { Log.v(LOGTAG, "Request for: " + uri); if (uri.equals("/")) { StringBuilder responseText = new StringBuilder(); try { CharSequence template = getHtmlTemplate(); String templateStr = template.toString(); templateStr = templateStr.replaceAll("<!-- APPLICATION_NAME -->", getString(R.string.app_name)); Pattern pattern = Pattern.compile("<!-- BEGIN_APP_ROW -->(.*?)<!-- END_APP_ROW -->", Pattern.DOTALL); Matcher matcher = pattern.matcher(templateStr); // StringBuffer buffer = new StringBuffer(); if (matcher.find()) { String rowTemplate = matcher.group(1); StringBuilder strRows = new StringBuilder(); PackageManager packageManager = HTTPDAppSender.this.getPackageManager(); List<PackageInfo> packages = packageManager.getInstalledPackages(0); for (PackageInfo packageInfo : packages) { // Is it one of our packages? AppInfo info = getAppInfoFromPackageName(packageInfo.packageName); if (info != null) { strRows.append(generateRow(rowTemplate, packageInfo)); } } templateStr = templateStr.replace(matcher.group(), strRows); } responseText.append(templateStr); Log.v(LOGTAG, responseText.toString()); Response response = new Response(Status.OK, "text/html", responseText.toString()); return response; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else if (uri.startsWith("/image/")) { try { uri = uri.substring(7); if (IMAGE_MAP.containsKey(uri)) { int resId = IMAGE_MAP.get(uri); InputStream is = getResources().openRawResource(resId); long cb = 0; byte buf[] = new byte[1024]; int len; while ((len = is.read(buf)) > 0) cb += len; is.close(); is = getResources().openRawResource(resId); Response response = new Response(Status.OK, "image/png", is); response.addHeader("Content-Length", "" + cb); return response; } } catch (Exception e) { e.printStackTrace(); } } else if (uri.startsWith("/icon/")) { try { uri = uri.substring(6); PackageInfo packageInfo = this.getPackageInfoFromPackageName(uri); if (packageInfo != null) { Drawable logo = packageInfo.applicationInfo.loadLogo(getPackageManager()); if (logo == null) logo = packageInfo.applicationInfo.loadIcon(getPackageManager()); Bitmap bmp = drawableToBitmap(logo); ByteArrayOutputStream stream = new ByteArrayOutputStream(); if (bmp.compress(CompressFormat.PNG, 100, stream)) { long cb = stream.size(); InputStream is = new ByteArrayInputStream(stream.toByteArray()); Response response = new Response(Status.OK, "image/png", is); response.addHeader("Content-Length", "" + cb); return response; } } } catch (Exception e) { e.printStackTrace(); } } else { PackageManager packageManager = HTTPDAppSender.this.getPackageManager(); List<PackageInfo> packages = packageManager.getInstalledPackages(0); String requestedPackage = ""; if (uri.length() > 1) { // Remove the "/" requestedPackage = uri.substring(1); } // Strip the .apk we added to the request off if (requestedPackage.endsWith(".apk")) { requestedPackage = requestedPackage.substring(0, requestedPackage.length() - 4); } PackageInfo packageInfo = this.getPackageInfoFromPackageName(requestedPackage); if (packageInfo != null) { ApplicationInfo appInfo = packageInfo.applicationInfo; String pathToApk = appInfo.sourceDir; Log.v(LOGTAG, pathToApk); try { File apk = new File(pathToApk); FileInputStream fin = new FileInputStream(pathToApk); Response response = new Response(Status.OK, "application/vnd.android.package-archive", fin); response.addHeader("Content-Length", "" + apk.length()); return response; } catch (FileNotFoundException e) { e.printStackTrace(); } } } return null; } private AppInfo getAppInfoFromPackageName(String requestedPackage) { if (requestedPackage == null || requestedPackage.length() == 0) return null; for (AppInfo appInfo : APPS_TO_DISPLAY) { String allowedPackage = appInfo.packageName; if (requestedPackage.equals(allowedPackage)) { return appInfo; } } return null; } private PackageInfo getPackageInfoFromPackageName(String requestedPackage) { AppInfo info = getAppInfoFromPackageName(requestedPackage); if (info == null) return null; // Not one of our packages! PackageManager packageManager = HTTPDAppSender.this.getPackageManager(); List<PackageInfo> packages = packageManager.getInstalledPackages(0); for (PackageInfo packageInfo : packages) { if (requestedPackage.equals(packageInfo.packageName)) { return packageInfo; } } return null; } private String generateRow(String templateOriginal, PackageInfo packageInfo) { String appPath = packageInfo.applicationInfo.sourceDir; File appFile = new File(appPath); String title = (String) packageInfo.applicationInfo.loadLabel(getPackageManager()); if (title == null || title.length() == 0) title = packageInfo.applicationInfo.name; if (title == null || title.length() == 0) title = appFile.getName(); CharSequence description = packageInfo.applicationInfo.loadDescription(getPackageManager()); if (description == null) description = ""; String downloadUrl = packageInfo.packageName + ".apk"; String template = new String(templateOriginal); template = template.replaceAll("<!-- BEGIN_APP_TITLE -->(.*?)<!-- END_APP_TITLE -->(?s)", title); template = template.replaceAll("<!-- BEGIN_APP_INFO -->(.*?)<!-- END_APP_INFO -->(?s)", description.toString()); template = template.replaceAll("<!-- APP_ICON -->(?s)", "icon/" + packageInfo.packageName); template = template.replaceAll("<!-- APP_PACKAGE -->(?s)", "" + downloadUrl); return template; } public Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } // public InputStream bitmapToInputStream(Bitmap bitmap) // { // int size = bitmap.getHeight() * bitmap.getRowBytes(); // ByteBuffer buffer = ByteBuffer.allocate(size); // bitmap.copyPixelsToBuffer(buffer); // return new ByteArrayInputStream(buffer.array()); // } } }