net.yolosec.upckeygen.ui.NetworkFragment.java Source code

Java tutorial

Introduction

Here is the source code for net.yolosec.upckeygen.ui.NetworkFragment.java

Source

/*
 * Copyright 2012 Rui Arajo, Lus Fonseca
 *
 * This file is part of Router Keygen.
 *
 * Router Keygen 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.
 * 
 * Router Keygen 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 Router Keygen.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.yolosec.upckeygen.ui;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewSwitcher;

import net.yolosec.upckeygen.BuildConfig;
import net.yolosec.upckeygen.R;
import net.yolosec.upckeygen.algorithms.Keygen;
import net.yolosec.upckeygen.algorithms.KeygenMonitor;
import net.yolosec.upckeygen.algorithms.WiFiKey;
import net.yolosec.upckeygen.algorithms.WiFiNetwork;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class NetworkFragment extends Fragment {
    public static final String NETWORK_ID = "vulnerable_network";
    private static final String TAG = "NetworkFragment";
    private static final String PASSWORD_LIST = "password_list";
    private WiFiNetwork wifiNetwork;
    private KeygenThread thread;
    private ViewSwitcher root;
    private TextView messages;
    private ArrayList<WiFiKey> passwordList;

    public NetworkFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments().containsKey(NETWORK_ID)) {
            wifiNetwork = getArguments().getParcelable(NETWORK_ID);
            restoreMissingKeygens();
            thread = new KeygenThread(wifiNetwork);
        }
        if (savedInstanceState != null) {
            final ArrayList<Parcelable> arList = savedInstanceState.getParcelableArrayList(PASSWORD_LIST);
            if (arList != null) {
                for (Parcelable p : arList) {
                    if (p instanceof WiFiKey) {
                        final WiFiKey key = (WiFiKey) p;
                        passwordList.add(key);
                    }
                }
            }
        }
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        root = (ViewSwitcher) inflater.inflate(R.layout.fragment_network, container, false);
        messages = (TextView) root.findViewById(R.id.loading_text);
        final View autoConnect = root.findViewById(R.id.auto_connect);
        // Auto connect service unavailable for manual calculations
        if (wifiNetwork.getScanResult() == null)
            autoConnect.setVisibility(View.GONE);
        else {
            final int level = wifiNetwork.getLevel();
        }
        if (passwordList != null)
            displayResults();
        return root;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (passwordList != null) {
            outState.putParcelableArrayList(PASSWORD_LIST, passwordList);
        }
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (passwordList == null) {
            if (thread.getStatus() == Status.FINISHED || thread.getStatus() == Status.RUNNING)
                thread = new KeygenThread(wifiNetwork);
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
                thread.execute();
            } else {
                thread.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            }
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        if (thread != null) {
            //This thread can be null if there was a previosly calculated
            //password list
            thread.cancel();
        }
    }

    /**
     * Some devices seem to have bugs with the parcelable implementation
     * So we try to restore missing objects here.
     */
    private void restoreMissingKeygens() {
        boolean foundMissingKeygen = false;
        for (Keygen keygen : wifiNetwork.getKeygens()) {
            if (keygen == null) {
                foundMissingKeygen = true;
                break;
            }
        }
        if (foundMissingKeygen) {
            //If any is missing, simply replace them all.
            wifiNetwork.setKeygens(null);
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        if (wifiNetwork.getSupportState() != Keygen.UNSUPPORTED)
            inflater.inflate(R.menu.share_keys, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    private String buildShareString() {
        final StringBuilder message = new StringBuilder(wifiNetwork.getSsidName());
        message.append("\n");
        for (WiFiKey password : passwordList) {
            message.append(password.getKey());
            message.append('\n');
        }
        return message.toString();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_share:
            try {
                if (passwordList == null)
                    return true;
                Intent i = new Intent(Intent.ACTION_SEND);
                i.setType("text/plain");
                i.putExtra(Intent.EXTRA_SUBJECT, wifiNetwork.getSsidName() + getString(R.string.share_msg_begin));
                i.putExtra(Intent.EXTRA_TEXT, buildShareString());
                startActivity(Intent.createChooser(i, getString(R.string.share_title)));
            } catch (Exception e) {
                Toast.makeText(getActivity(), R.string.msg_err_sendto, Toast.LENGTH_SHORT).show();
            }
            return true;
        case R.id.menu_save_sd:
            if (passwordList == null)
                return true;

            final String toCopy = buildShareString();
            try {
                if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
                    android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getActivity()
                            .getSystemService(Context.CLIPBOARD_SERVICE);
                    clipboard.setText(toCopy);
                } else {
                    android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getActivity()
                            .getSystemService(Context.CLIPBOARD_SERVICE);
                    android.content.ClipData clip = android.content.ClipData.newPlainText("Copied Text", toCopy);
                    clipboard.setPrimaryClip(clip);
                }

                Toast.makeText(getActivity(), getString(R.string.msg_copied, wifiNetwork.getSsidName()),
                        Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                Log.e(TAG, "Copy to clipboard failed", e);
            }
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void displayResults() {
        if (passwordList.isEmpty()) {
            root.findViewById(R.id.loading_spinner).setVisibility(View.GONE);
            messages.setText(R.string.msg_errnomatches);

        } else {
            WiFiKey wiFiKey = passwordList.get(0);
            boolean isUbee = TextUtils.isEmpty(wiFiKey.getSerial());

            final ListView list = (ListView) root.findViewById(R.id.list_keys);
            Collections.sort(passwordList, new Comparator<WiFiKey>() {
                @Override
                public int compare(WiFiKey lhs, WiFiKey rhs) {
                    if (lhs.getBandType() != rhs.getBandType()) {
                        return lhs.getBandType() < rhs.getBandType() ? -1 : 1;
                    }

                    final String serialL = lhs.getSerial();
                    final String serialR = rhs.getSerial();
                    if (serialL == null && serialR != null) {
                        return -1;
                    } else if (serialL != null && serialR == null) {
                        return 1;
                    } else if (serialL != null && !serialL.equals(serialR)) {
                        return serialL.compareTo(serialR);
                    }

                    return lhs.getKey().compareTo(rhs.getKey());
                }
            });

            list.setOnItemClickListener(new OnItemClickListener() {
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    final WiFiKey key = (WiFiKey) parent.getItemAtPosition(position);
                    Toast.makeText(getActivity(), getString(R.string.msg_copied, key.getKey()), Toast.LENGTH_SHORT)
                            .show();

                    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
                        android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getActivity()
                                .getSystemService(Context.CLIPBOARD_SERVICE);
                        clipboard.setText(key.getKey());
                    } else {
                        android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getActivity()
                                .getSystemService(Context.CLIPBOARD_SERVICE);
                        android.content.ClipData clip = android.content.ClipData.newPlainText("key", key.getKey());
                        clipboard.setPrimaryClip(clip);
                    }

                    openWifiSettings();
                }
            });
            if (isUbee) {
                list.setAdapter(
                        new WiFiKeyUbeeAdapter(getActivity(), android.R.layout.simple_list_item_1, passwordList));
            } else {
                list.setAdapter(
                        new WiFiKeyAdapter(getActivity(), android.R.layout.simple_list_item_1, passwordList));
            }

            root.showNext();
        }
    }

    /**
     * Try to open wifi settings activity.
     * Tries to different actions.
     */
    private void openWifiSettings() {
        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
        final PackageManager packageManager = getActivity().getPackageManager();
        if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
            startActivity(intent);
            return;
        }
        intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
        if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
            startActivity(intent);
        }
    }

    private void getPrefs() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
    }

    private class KeygenThread extends AsyncTask<Void, Integer, List<WiFiKey>> implements KeygenMonitor {
        private final static int SHOW_TOAST = 0;
        private final static int SHOW_MESSAGE_WITH_SPINNER = 1;
        private final static int SHOW_MESSAGE_NO_SPINNER = 2;
        private final static int CHANGE_DETERMINATE = 3;
        private final static int KEYGEN_PROGRESSED = 4;
        private final static int KEY_COMPUTED = 5;
        private final WiFiNetwork wifiNetwork;
        private volatile int numKeys = 0;
        private boolean spinnerDeterminate = false;

        private KeygenThread(WiFiNetwork wifiNetwork) {
            this.wifiNetwork = wifiNetwork;
        }

        @Override
        protected void onPostExecute(List<WiFiKey> result) {
            if (getActivity() == null)
                return;
            if (result == null)
                return;
            passwordList = new ArrayList<>(result);
            displayResults();
        }

        @Override
        protected void onPreExecute() {
            if (wifiNetwork.getSupportState() == Keygen.UNSUPPORTED) {
                root.findViewById(R.id.loading_spinner).setVisibility(View.GONE);
                messages.setText(R.string.msg_unspported);
                cancel(true);
            }
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            if (getActivity() == null)
                return;
            for (int i = 0; i < values.length; i += 2) {
                switch (values[i]) {
                case SHOW_TOAST:
                    Toast.makeText(getActivity(), values[i + 1], Toast.LENGTH_SHORT).show();

                    break;
                case SHOW_MESSAGE_NO_SPINNER:
                    messages.setText(values[i + 1]);
                    root.findViewById(R.id.loading_spinner).setVisibility(View.GONE);
                    break;

                case SHOW_MESSAGE_WITH_SPINNER:
                    messages.setText(values[i + 1]);
                    root.findViewById(R.id.loading_spinner).setVisibility(View.VISIBLE);
                    break;

                case CHANGE_DETERMINATE: {
                    spinnerDeterminate = values[i + 1] > 0;
                    final ProgressBar spinner = (ProgressBar) root.findViewById(R.id.loading_spinner);
                    final ProgressBar progressBar = (ProgressBar) root.findViewById(R.id.loading_progress);
                    spinner.setVisibility(spinnerDeterminate ? View.GONE : View.VISIBLE);
                    progressBar.setVisibility(spinnerDeterminate ? View.VISIBLE : View.GONE);
                    if (spinnerDeterminate) {
                        progressBar.setMax(1000);
                        progressBar.setProgress(0);
                    }
                }
                    break;

                case KEY_COMPUTED:
                    messages.setText(NetworkFragment.this.getString(R.string.dialog_nativecalc_msg) + " "
                            + NetworkFragment.this.getString(R.string.key_computed, values[i + 1]));
                    break;

                case KEYGEN_PROGRESSED: {
                    if (spinnerDeterminate) {
                        final ProgressBar spinner = (ProgressBar) root.findViewById(R.id.loading_progress);
                        spinner.setProgress(values[i + 1]);
                    }
                }
                    break;
                }
            }
        }

        public void cancel() {
            for (Keygen keygen : wifiNetwork.getKeygens())
                keygen.setStopRequested(true);
            cancel(true);
        }

        @Override
        protected List<WiFiKey> doInBackground(Void... params) {
            final List<WiFiKey> result = new ArrayList<>();
            for (Keygen keygen : wifiNetwork.getKeygens()) {
                try {
                    final List<WiFiKey> keygenResult = calcKeys(keygen);
                    if (keygenResult != null)
                        result.addAll(keygenResult);
                } catch (Exception e) {
                    Log.e(NetworkFragment.class.getSimpleName(), String.format("Error, ssid=%s, mac=%s",
                            wifiNetwork.getSsidName(), wifiNetwork.getMacAddress()));
                }
            }
            return result;
        }

        private List<WiFiKey> calcKeys(Keygen keygen) {
            if (keygen.keygenSupportsProgress()) {
                keygen.setMonitor(this);
                publishProgress(CHANGE_DETERMINATE, 1);
            } else {
                publishProgress(CHANGE_DETERMINATE, 0);
            }

            long begin = System.currentTimeMillis();
            final List<WiFiKey> result = keygen.getKeysExt();
            long end = System.currentTimeMillis() - begin;
            if (BuildConfig.DEBUG)
                Log.d(TAG, "Time to solve:" + end);

            final int errorCode = keygen.getErrorCode();
            if (errorCode != 0) {
                if (result == null)
                    publishProgress(SHOW_MESSAGE_NO_SPINNER, errorCode);
                else
                    publishProgress(SHOW_TOAST, errorCode);
            }
            return result;
        }

        @Override
        public void onKeyComputed() {
            numKeys += 1;
            publishProgress(KEY_COMPUTED, numKeys);
        }

        @Override
        public void onKeygenProgressed(double progress) {
            publishProgress(KEYGEN_PROGRESSED, (int) (progress * 1000));
        }
    }
}