Back to project page android_network_discovery.
The source code is released under:
GNU General Public License
If you think the Android project android_network_discovery listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2009-2010 Aubort Jean-Baptiste (Rorist) * Licensed under GNU's GPL 2, see README */// w ww . j a va 2s . c om package info.lamatricexiste.network; import info.lamatricexiste.network.Network.HostBean; import info.lamatricexiste.network.Network.NetInfo; import info.lamatricexiste.network.Utils.Db; import info.lamatricexiste.network.Utils.Help; import info.lamatricexiste.network.Utils.Prefs; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.TabActivity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.Bundle; import android.os.Vibrator; import android.preference.PreferenceManager; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.TabHost; import android.widget.TextView; import android.widget.Toast; @SuppressWarnings("deprecation") final public class ActivityPortscan extends TabActivity { private static final String REQ_SERVICE = "select service from services where port=? limit 1"; private static final String REQ_PROBES = "select service, regex from probes"; private static final int PROGRESS_MAX = 10000; private final String TAG = "ActivityPortscan"; private final String PLACEHOLDER = "placeholder"; private Context ctxt; private SharedPreferences prefs; private LayoutInflater mInflater; private ScanPortTask scanPortTask; private HostBean host; private PortsAdapter adapter_open; private PortsAdapter adapter_closed; private int cnt_open; private int cnt_closed; private List<String> knownServices; private TextView mTabOpen; private TextView mTabClosed; private Button btn_scan; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_PROGRESS); // To display the // progressbar requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.portscan); ctxt = getApplicationContext(); prefs = PreferenceManager.getDefaultSharedPreferences(ctxt); mInflater = LayoutInflater.from(ctxt); // Get Intent information Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { if (intent.hasExtra(HostBean.EXTRA)) { host = intent.getParcelableExtra(HostBean.EXTRA); } else { // Intents for 3rd party usage host = new HostBean(); host.ipAddress = extras.getString(HostBean.EXTRA_HOST); Log.d("IP", ""+host.ipAddress); host.hostname = extras.getString(HostBean.EXTRA_HOSTNAME); host.position = extras.getInt(HostBean.EXTRA_POSITION); host.portsOpen = intArrayToArrayList(extras .getIntArray(HostBean.EXTRA_PORTSO)); host.portsClosed = intArrayToArrayList(extras .getIntArray(HostBean.EXTRA_PORTSC)); Log.d("Open Ports", ""+host.portsOpen); host.responseTime = extras.getInt(HostBean.EXTRA_TIMEOUT, Integer.parseInt(Prefs.DEFAULT_TIMEOUT_PORTSCAN)); // FIXME: banners and services not supported (HashMap's) } } cnt_open = (host.portsOpen == null) ? 0 : host.portsOpen.size(); cnt_closed = (host.portsClosed == null) ? 0 : host.portsClosed.size(); // Logo // TODO: Support more types (based on what?) ImageView logo = (ImageView) findViewById(R.id.logo); if (host.deviceType == HostBean.TYPE_GATEWAY) { logo.setImageResource(R.drawable.router); } else { logo.setImageResource(R.drawable.computer); } // Title ((TextView) findViewById(R.id.host)).setSelected(true); // for marquee if (host.hostname != null && !host.hostname.equals(host.ipAddress)) { ((TextView) findViewById(R.id.host)).setText(host.hostname + " (" + host.ipAddress + ")"); } else { ((TextView) findViewById(R.id.host)).setText(host.ipAddress); } // MAC Address TextView hw = (TextView) findViewById(R.id.mac); if (host.hardwareAddress != null && !host.hardwareAddress.equals(NetInfo.NOMAC)) { hw.setText(host.hardwareAddress); } else { hw.setVisibility(View.GONE); } // Vendor name TextView nic = (TextView) findViewById(R.id.vendor); if (host.nicVendor != null && !host.hardwareAddress.equals(NetInfo.NOMAC)) { nic.setText(host.nicVendor); } else { nic.setVisibility(View.GONE); } // Scan btn_scan = (Button) findViewById(R.id.btn_scan); if (extras.getBoolean(ActivityNet.EXTRA_WIFI) == false) { btn_scan.setClickable(false); btn_scan.setEnabled(false); btn_scan.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.disabled, 0, 0); } else { btn_scan.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Log.i("ActivityPortScan","PortScan Started"); startScan(); } }); } // Back ((Button) findViewById(R.id.btn_back)) .setOnClickListener(new View.OnClickListener() { public void onClick(View v) { finish(); } }); // Tabs TabHost tabHost = getTabHost(); tabHost.addTab(tabHost .newTabSpec("tab_open") .setIndicator(getString(R.string.scan_open, cnt_open), getResources().getDrawable(R.drawable.open)) .setContent(R.id.list_open)); tabHost.addTab(tabHost .newTabSpec("tab_closed") .setIndicator(getString(R.string.scan_closed, cnt_closed), getResources().getDrawable(R.drawable.closed)) .setContent(R.id.list_closed)); tabHost.setCurrentTab(0); // Ugly hack to have the view holding the tabs mTabOpen = (TextView) tabHost.getTabWidget().getChildAt(0) .findViewById(android.R.id.title); mTabClosed = (TextView) tabHost.getTabWidget().getChildAt(1) .findViewById(android.R.id.title); // Lists adapter_open = new PortsAdapter(ctxt, preparePort(host.portsOpen), "open"); ListView list_open = (ListView) findViewById(R.id.list_open); list_open.setAdapter(adapter_open); list_open.setItemsCanFocus(true); adapter_closed = new PortsAdapter(ctxt, preparePort(host.portsClosed), "closed"); ListView list_closed = (ListView) findViewById(R.id.list_closed); list_closed.setAdapter(adapter_closed); list_closed.setItemsCanFocus(true); // TODO: Get from resource array ? knownServices = new ArrayList<String>(); // knownServices.add("sftp"); // knownServices.add("ftps"); // knownServices.add("ftp"); knownServices.add("ssh"); knownServices.add("telnet"); knownServices.add("http"); knownServices.add("https"); // Start scan if ports empty if (host.portsOpen == null && host.portsClosed == null) { startScan(); } } @Override protected void onStop() { if (scanPortTask != null) { scanPortTask.cancel(true); } super.onStop(); } // TODO: Handle orientation change without canceling the scan // @Override // public void onConfigurationChanged(Configuration newConfig) { // super.onConfigurationChanged(newConfig); // if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { // setContentView(R.layout.portscan_portrait); // } else { // setContentView(R.layout.portscan); // } // } @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, ActivityDiscovery.MENU_SCAN_SINGLE, 0, R.string.scan_single_title).setIcon( android.R.drawable.ic_menu_mylocation); menu.add(0, ActivityDiscovery.MENU_OPTIONS, 0, R.string.btn_options) .setIcon(android.R.drawable.ic_menu_preferences); menu.add(0, ActivityDiscovery.MENU_HELP, 0, R.string.preferences_help) .setIcon(android.R.drawable.ic_menu_help); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case ActivityDiscovery.MENU_SCAN_SINGLE: ActivityDiscovery.scanSingle(this, host.ipAddress); return true; case ActivityDiscovery.MENU_OPTIONS: startActivity(new Intent(ctxt, Prefs.class)); return true; case ActivityDiscovery.MENU_HELP: startActivity(new Intent(ctxt, Help.class)); return true; } return false; } static class ViewHolder { TextView port; TextView banner; Button btn_c; } // Custom ArrayAdapter public class PortsAdapter extends ArrayAdapter<String> { private String type; public PortsAdapter(Context context, List<String> objects, String type) { super(context, R.layout.list_port, R.id.list, objects); this.type = type; } @Override public View getView(final int position, View convertView, ViewGroup parent) { // Views final ViewHolder holder; // WTF if (convertView == null) { convertView = mInflater.inflate(R.layout.list_port, null); holder = new ViewHolder(); holder.port = (TextView) convertView.findViewById(R.id.list); holder.banner = (TextView) convertView .findViewById(R.id.banner); holder.btn_c = (Button) convertView .findViewById(R.id.list_connect); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // Port & Service final int port = (type == "open") ? host.portsOpen.get(position) : host.portsClosed.get(position); if (host.services != null) { final String service = host.services.get(port); holder.port.setText(port + "/tcp" + " (" + service + ")"); // Service is supported if (knownServices.contains(service)) { holder.btn_c.setText(R.string.scan_connect); holder.btn_c.setCompoundDrawablesWithIntrinsicBounds( R.drawable.connect, 0, 0, 0); holder.btn_c.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { openPortService(service, port); } }); } else { // No action for this service holder.btn_c.setText(null); holder.btn_c.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); holder.btn_c.setOnClickListener(null); } } else { holder.port.setText(port + "/tcp "); } // Banner if (host.banners != null && host.banners.get(port) != null) { holder.banner.setText(host.banners.get(port)); holder.banner.setVisibility(View.VISIBLE); holder.banner.setOnClickListener(new OnClickListener() { public void onClick(View v) { final AlertDialog.Builder dialog = new AlertDialog.Builder( ActivityPortscan.this); dialog.setTitle(getString(R.string.scan_banner_title, port)); dialog.setMessage(holder.banner.getText()); dialog.setNegativeButton(R.string.btn_close, null); dialog.show(); } }); } else { holder.banner.setVisibility(View.GONE); } return convertView; } } private void openPortService(String service, int port) { // Action for the service String pk = ""; String search = null; Intent intent = null; // if (service.equals("ftp") || service.equals("ftps") || // service.equals("sftp")) { // pk = "AndFTP"; // search = "market://search?q=andftp"; // intent = new Intent(Intent.ACTION_PICK); // // intent.setData(service.equals("ftp") ? Uri.parse("ftp://" + // // host.ipAddress) : Uri // // .parse("sftp://" + host.ipAddress)); // intent.setDataAndType(service.equals("ftp") ? Uri.parse("ftp://" + // host.ipAddress) // : Uri.parse("sftp://" + host.ipAddress), // "vnd.android.cursor.dir/lysesoft.andftp.uri"); // intent.putExtra("ftp_pasv", "true"); // // intent.putExtra("ftp_username", "anonymous"); // // intent.putExtra("ftp_password", "anonymous"); // // intent.putExtra("ftp_keyfile", "/sdcard/dsakey.txt"); // // intent.putExtra("ftp_keypass", ""); // // intent.putExtra("ftp_resume", "true"); // // intent.putExtra("ftp_encoding", "UTF8"); // } else if (service.equals("ssh")) { pk = "ConnectBot (ssh)"; Log.i("ActivityPortScan","SSH found for "+host.ipAddress); search = "market://search?q=pname:org.connectbot"; String user = prefs.getString(Prefs.KEY_SSH_USER, Prefs.DEFAULT_SSH_USER); intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("ssh://" + user + "@" + host.ipAddress + ":" + port + "/#" + user + "@" + host.ipAddress + ":" + port)); } else if (service.equals("telnet")) { pk = "ConnectBot (telnet)"; search = "market://search?q=pname:org.connectbot"; intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("telnet://" + host.ipAddress + ":" + port)); } else if (service.equals("http") || service.equals("https")) { intent = new Intent(Intent.ACTION_VIEW); Log.i("ActivityPortScan","HTTP found for "+host.ipAddress); intent.setData(Uri.parse(service + "://" + (host.hostname != null ? host.hostname : host.ipAddress) + ":" + port)); } else { makeToast(R.string.scan_noaction); } if (intent != null) { try { startActivity(intent); } catch (ActivityNotFoundException e) { if (search != null) { makeToast(getString(R.string.package_missing, pk)); try { startActivity(new Intent(Intent.ACTION_VIEW) .setData(Uri.parse(search))); } catch (ActivityNotFoundException e2) { Log.e(TAG, "Market not found !"); } } Log.e(TAG, e.getMessage()); } } } private class ScanPortTask extends AsyncPortscan { // FIXME: Create AbstractPortscan class private int progress_current = 0; private SQLiteDatabase dbServices; private SQLiteDatabase dbProbes; private String service; private Cursor c; @SuppressWarnings("static-access") ScanPortTask(Activity activity, String ip, int timeout) { super(activity, ip, timeout); WeakReference<Activity> a = new WeakReference<Activity>(activity); final Activity d = a.get(); if (d != null) { Db db = new Db(d.getApplicationContext()); dbServices = db.openDb(Db.DB_SERVICES); dbProbes = db.openDb(Db.DB_PROBES); } } @SuppressLint("UseSparseArrays") @Override protected void onPreExecute() { // Get start/end ports try { port_start = Integer.parseInt(prefs.getString( Prefs.KEY_PORT_START, Prefs.DEFAULT_PORT_START)); port_end = Integer.parseInt(prefs.getString(Prefs.KEY_PORT_END, Prefs.DEFAULT_PORT_END)); } catch (NumberFormatException e) { port_start = Integer.parseInt(Prefs.DEFAULT_PORT_START); port_end = Integer.parseInt(Prefs.DEFAULT_PORT_END); } nb_port = port_end - port_start + 2; // Initialize arrays and views host.banners = new HashMap<Integer, String>(); host.services = new HashMap<Integer, String>(); host.portsOpen = new ArrayList<Integer>(); host.portsClosed = new ArrayList<Integer>(); mTabOpen.setText(getString(R.string.scan_open, 0)); mTabClosed.setText(getString(R.string.scan_closed, 0)); setProgress(0); } @SuppressLint("UseValueOf") @Override protected void onProgressUpdate(Object... values) { if (!isCancelled()) { if (values.length == 3) { final Integer port = (Integer) values[0]; final int type = (Integer) values[1]; if (!port.equals(new Integer(0))) { if (type == AsyncPortscan.OPEN) { // Open if (values[2] != null) { host.banners.put(port, (String) values[2]); host.services.put(port, getPortService(port)); } if (findLocationAndAdd(host.portsOpen, port)) { host.services.put(port, getPortService(port)); adapter_open.add(PLACEHOLDER); cnt_open++; mTabOpen.setText(getString(R.string.scan_open, cnt_open)); } adapter_open.notifyDataSetChanged(); } else if (type == AsyncPortscan.CLOSED) { // Closed if (findLocationAndAdd(host.portsClosed, port)) { host.services.put(port, getPortService(port)); adapter_closed.add(PLACEHOLDER); cnt_closed++; mTabClosed.setText(getString( R.string.scan_closed, cnt_closed)); } adapter_closed.notifyDataSetChanged(); } else if (type == AsyncPortscan.UNREACHABLE) { cancel(true); makeToast(R.string.scan_host_unreachable); Log.e(TAG, "Host Unreachable: " + ipAddr + ":" + port); } // FIXME: do something ? else if (type == AsyncPortscan.TIMEOUT) { } else if (type == AsyncPortscan.FILTERED) { } } else { cancel(true); makeToast(R.string.scan_host_unreachable); Log.e(TAG, "Host Unreachable: " + ipAddr); } } progress_current++; setProgress(progress_current * PROGRESS_MAX / nb_port); } } @Override protected void onPostExecute(Void unused) { // Finishing if (prefs.getBoolean(Prefs.KEY_VIBRATE_FINISH, Prefs.DEFAULT_VIBRATE_FINISH) == true) { Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); v.vibrate(ActivityDiscovery.VIBRATE); } if (host.portsOpen.size() == 0) { makeToast(R.string.scan_noport); } if (dbServices != null) { dbServices.close(); } if (dbProbes != null) { dbProbes.close(); } stopScan(); makeToast(R.string.scan_finished); Intent intent = new Intent(); intent.putExtra(HostBean.EXTRA, host); setResult(RESULT_OK, intent); Log.i("The other finish","Finished in onPostExecute"); finish(); } @Override protected void onCancelled() { super.onCancelled(); makeToast(R.string.scan_canceled); if (dbServices != null) { dbServices.close(); } if (dbProbes != null) { dbProbes.close(); } stopScan(); } private String getPortService(int port) { service = null; // Determinate service with banners if (host.banners != null && host.banners.containsKey(port) && dbProbes != null) { try { Cursor c = dbProbes.rawQuery(REQ_PROBES, null); if (c.moveToFirst()) { do { try { final Pattern pattern = Pattern.compile(c .getString(1)); final Matcher matcher = pattern .matcher(host.banners.get(port)); if (matcher.find()) { service = c.getString(0); break; } } catch (PatternSyntaxException e) { // Log.e(TAG, e.getMessage()); } } while (c.moveToNext()); } c.close(); } catch (SQLiteException e) { Log.e(TAG, e.getMessage()); Editor edit = PreferenceManager .getDefaultSharedPreferences(ctxt).edit(); edit.putInt(Prefs.KEY_RESET_SERVICESDB, 1); edit.commit(); } } // Get the service from port number if (service == null && dbServices != null) { c = dbServices .rawQuery(REQ_SERVICE, new String[] { "" + port }); if (c.moveToFirst()) { service = c.getString(0); } else { service = getString(R.string.info_unknown); } c.close(); } return service; } } private boolean findLocationAndAdd(ArrayList<Integer> array, int value) { int index = 0; int size = array.size(); for (index = 0; index < size; index++) { int current = array.get(index); if (value > current) { continue; } else if (value < current) { // Add new value array.add(index, value); return true; } else if (value == current) { // Value already exists return false; } } if (index == size) { array.add(value); return true; } return false; } private void startScan() { if (!NetInfo.isConnected(ctxt)) { return; } makeToast(R.string.scan_start); //setProgressBarVisibility(true); //setProgressBarIndeterminateVisibility(true); adapter_open.clear(); adapter_closed.clear(); cnt_open = 0; cnt_closed = 0; scanPortTask = new ScanPortTask(this, host.ipAddress, getTimeout()); scanPortTask.execute(); btn_scan.setText(R.string.btn_discover_cancel); btn_scan.setCompoundDrawablesWithIntrinsicBounds(R.drawable.cancel, 0, 0, 0); btn_scan.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { scanPortTask.cancel(true); } }); } private void stopScan() { // Set result Intent intent = new Intent(); intent.putExtra(HostBean.EXTRA, host); setResult(RESULT_OK, intent); Log.i("Activity Portscan", "Finishing"); finish(); // Reset scan //setProgressBarVisibility(false); //setProgressBarIndeterminateVisibility(false); //setProgress(PROGRESS_MAX); btn_scan.setText(R.string.btn_scan); btn_scan.setCompoundDrawablesWithIntrinsicBounds(R.drawable.discover, 0, 0, 0); btn_scan.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { startScan(); } }); } private int getTimeout() { if (prefs.getBoolean(Prefs.KEY_TIMEOUT_FORCE, Prefs.DEFAULT_TIMEOUT_FORCE)) { return Integer.parseInt(prefs.getString(Prefs.KEY_TIMEOUT_PORTSCAN, Prefs.DEFAULT_TIMEOUT_PORTSCAN)); } return host.responseTime; } private List<String> preparePort(ArrayList<Integer> ports) { List<String> portsChar = new ArrayList<String>(); if (ports != null) { int len = ports.size(); for (int i = 0; i < len; i++) { portsChar.add(PLACEHOLDER); } } return portsChar; } private ArrayList<Integer> intArrayToArrayList(int[] intArray) { ArrayList<Integer> out = new ArrayList<Integer>(); if (intArray != null) { for (int i = 0; i < intArray.length; i++) { out.add(intArray[i]); } return out; } return null; } private void makeToast(String msg) { Toast.makeText(getApplicationContext(), (CharSequence) msg, Toast.LENGTH_SHORT).show(); } private void makeToast(int msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } }