package de.tudarmstadt.informatik.hostage.ui2.fragment; import android.annotation.SuppressLint; import android.app.Fragment; import android.app.FragmentManager; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.echo.holographlibrary.Bar; import com.echo.holographlibrary.BarGraph; import com.echo.holographlibrary.Line; import com.echo.holographlibrary.LineGraph; import com.echo.holographlibrary.LinePoint; import com.echo.holographlibrary.PieGraph; import com.echo.holographlibrary.PieSlice; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import de.tudarmstadt.informatik.hostage.R; import de.tudarmstadt.informatik.hostage.logging.Record; import de.tudarmstadt.informatik.hostage.logging.UglyDbHelper; import de.tudarmstadt.informatik.hostage.ui.LogFilter; import de.tudarmstadt.informatik.hostage.ui2.activity.MainActivity; import de.tudarmstadt.informatik.hostage.ui2.adapter.StatisticListAdapter; import de.tudarmstadt.informatik.hostage.ui2.dialog.ChecklistDialog; import de.tudarmstadt.informatik.hostage.ui2.dialog.DateTimeDialogFragment; import de.tudarmstadt.informatik.hostage.ui2.helper.ColorSequenceGenerator; import de.tudarmstadt.informatik.hostage.ui2.model.PlotComparisonItem; import de.tudarmstadt.informatik.hostage.ui2.popup.AbstractPopup; import de.tudarmstadt.informatik.hostage.ui2.popup.AbstractPopupItem; import de.tudarmstadt.informatik.hostage.ui2.popup.SimplePopupItem; import de.tudarmstadt.informatik.hostage.ui2.popup.SimplePopupTable; import de.tudarmstadt.informatik.hostage.ui2.popup.SplitPopupItem; /** * Created by Julien on 16.02.14. */ public class StatisticsFragment extends Fragment implements ChecklistDialog.ChecklistDialogListener, DateTimeDialogFragment.DateTimeDialogFragmentListener { static final String FILTER_MENU_TITLE_BSSID = "BSSID"; static final String FILTER_MENU_TITLE_ESSID = "ESSID"; static final String FILTER_MENU_TITLE_PROTOCOLS = "Protocols"; static final String FILTER_MENU_TITLE_PROTOCOL = "Protocol"; static final String FILTER_MENU_TITLE_TIMESTAMP_BELOW = "Latest"; static final String FILTER_MENU_TITLE_TIMESTAMP_ABOVE = "Earliest"; static final String FILTER_MENU_TITLE_REMOVE = "Reset Filter"; static final String FILTER_MENU_POPUP_TITLE = "Filter by"; static final String MENU_TITLE_PROTOCOLS = "Protocols"; static final String MENU_TITLE_NETWORK = "Networks"; static final String MENU_TITLE_ATTACKS = "Attacks"; static final String MENU_POPUP_TITLE = "Visualize"; static final String CHART_TYPE_TITLE_BAR = "Bar Plot"; static final String CHART_TYPE_TITLE_PIE = "Pie Plot"; static final String CHART_TYPE_TITLE_LINE = "Line Plot"; static final String DIALOG_PROTOCOLS_TITLE = "Select protocol data to compare"; static final String DIALOG_NETWORK_TITLE = "Select network data to compare"; static final String DIALOG_ATTACK_TITLE = "Select attack data to compare"; static final String COMPARE_TITLE_AttacksPerProtocol = "Attacks per protocol"; static final String COMPARE_TITLE_UsesPerProtocol = "Uses per protocol"; static final String COMPARE_TITLE_AttacksPerDate = "Attacks per date"; static final String COMPARE_TITLE_AttacksPerTime = "Attacks per time"; static final String COMPARE_TITLE_AttacksPerBSSID = "Attacks per BSSID"; static final String COMPARE_TITLE_AttacksPerESSID = "Attacks per ESSID"; static final String FILTER_MENU_PROTOCOL_SINGLE_CHOICE_TITLE = "Select Protocol"; static final String TABLE_HEADER_VALUE_TITLE_ATTACKS_COUNT = "Attacks count"; static final String TABLE_HEADER_VALUE_TITLE_ATTACKS_PERCENTAGE = "% of all"; static final String OTHER_CHART_TITLE = "Other"; // MINIMAL 2 static int MAX_NUMBER_OF_CHART_OBJECTS = 6; private boolean wasBelowTimePicker; private LogFilter filter; private boolean showFilterButton; private PieGraph pieGraph; private LineGraph lineGraph; private BarGraph barGraph; private View rootView; private View currentPlotView; private ArrayList colorList; private ArrayList currentData; private UglyDbHelper dbh; private ListView legendListView; private String selectedCompareData = COMPARE_TITLE_AttacksPerProtocol; public enum ChartType { PIE_CHART(0), BAR_CHART(1), LINE_CHART(2); private int value; private ChartType(int value) { this.value = value; } static public ChartType create(int value){ if (value < 0 || value >= ChartType.values().length) return ChartType.PIE_CHART; return ChartType.values()[value]; } public String toString(){ if (this.equals(ChartType.create(0))){ return CHART_TYPE_TITLE_PIE; } if (this.equals(ChartType.create(1))){ return CHART_TYPE_TITLE_BAR; } return CHART_TYPE_TITLE_LINE; } } private ImageButton getFilterButton(){ return (ImageButton) this.rootView.findViewById(R.id.FilterButton); } public int getLayoutID(){ return R.layout.fragment_statistics; } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); getActivity().setTitle(getResources().getString(R.string.drawer_statistics)); dbh = new UglyDbHelper(this.getBaseContext()); // Get the message from the intent if (this.filter == null){ Intent intent = this.getActivity().getIntent(); LogFilter filter = intent.getParcelableExtra(LogFilter.LOG_FILTER_INTENT_KEY); if(filter == null){ this.clearFilter(); } else { this.filter = filter; } } this.rootView = inflater.inflate(this.getLayoutID(), container, false); this.configureRootView(this.rootView); return this.rootView; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); setRetainInstance(true); } @Override public void onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); LayoutInflater inflater = LayoutInflater.from(getActivity()); ViewGroup container = (ViewGroup) this.getView(); container.removeAllViewsInLayout(); this.rootView = inflater.inflate(this.getLayoutID(), container, false); container.addView(this.rootView); this.configureRootView(this.rootView); } private Context getBaseContext(){ return this.getActivity().getBaseContext(); } private Context getApplicationContext(){ return this.getActivity().getApplicationContext(); } public void configureRootView(View rootView){ LinearLayout plotLayout = (LinearLayout) rootView.findViewById(R.id.plot_layout); plotLayout.setWillNotDraw(false); plotLayout.removeAllViews(); plotLayout.setWillNotDraw(false); this.legendListView = (ListView) rootView.findViewById(R.id.legend_list_view); this.legendListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { StatisticsFragment.this.userTappedOnLegendItem(i); } }); rootView.setWillNotDraw(false); this.actualiseCurrentPlot(); ImageButton visualButton = (ImageButton) rootView.findViewById(R.id.plot_data_button); visualButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { StatisticsFragment.this.openBarSelectionMenuOnView(v); } }); ImageButton filterButton = this.getFilterButton(); filterButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { StatisticsFragment.this.openFilterMenuOnView(v); } }); if (this.currentPlotView instanceof BarGraph){ this.setTitle("" + this.getCurrentSelectedProtocol() + ": " +this.selectedCompareData); } else { this.setTitle(this.selectedCompareData); } } public void setTitle(String title){ TextView titleView = (TextView) this.rootView.findViewById(R.id.title_text_view); if (title != null && titleView != null){ titleView.setText(title); titleView.invalidate(); } } public String getTitle(){ TextView titleView = (TextView) this.rootView.findViewById(R.id.title_text_view); if (titleView != null){ return "" + titleView.getText(); } return ""; } public void onStart() { super.onStart(); this.actualiseCurrentPlot(); this.currentPlotView.invalidate(); if (this.currentPlotView instanceof BarGraph){ this.setTitle("" + this.getCurrentSelectedProtocol() + ": " +this.selectedCompareData); } else { this.setTitle(this.selectedCompareData); } } public void setChartType(ChartType type){ boolean shouldChange = true; this.clearFilter(); if (this.currentPlotView != null){ if (type == ChartType.PIE_CHART){ shouldChange = ! (this.currentPlotView instanceof PieGraph); // SET FILTER BUTTON HIDDEN ImageButton filterButton = this.getFilterButton(); if (filterButton != null) filterButton.setVisibility(View.GONE); } else { if (this.pieGraph != null) this.pieGraph.setVisibility(View.GONE); // SHOW FILTER BUTTON ImageButton filterButton = this.getFilterButton(); if (filterButton != null) filterButton.setVisibility(View.VISIBLE); } if (type == ChartType.LINE_CHART){ shouldChange = ! (this.currentPlotView instanceof LineGraph); } else { if (this.lineGraph != null) this.lineGraph.setVisibility(View.GONE); } if (type == ChartType.BAR_CHART){ shouldChange = ! (this.currentPlotView instanceof BarGraph); } else { if (this.barGraph != null) this.barGraph.setVisibility(View.GONE); } } if (shouldChange){ this.currentPlotView = this.getPlotViewForType(type); this.currentPlotView.setVisibility(View.VISIBLE); } this.actualiseCurrentPlot(); } public View getPlotViewForType(ChartType type){ switch (type){ case PIE_CHART: return this.getPieGraphView(); case LINE_CHART: return this.getLineGraphView(); default: return this.getBarGraphView(); } } public void actualiseLegendList(){ StatisticListAdapter adapter = new StatisticListAdapter(this.getApplicationContext(), this.currentData); if (this.currentPlotView instanceof LineGraph){ adapter.setValueFormatter(new StatisticListAdapter.ValueFormatter() { @Override public String convertValueToString(double value) { return String.format("%.02f", value) + " %"; } }); } else { adapter.setValueFormatter(new StatisticListAdapter.ValueFormatter() { @Override public String convertValueToString(double value) { int v = (int) value; return "" + v; } }); } this.legendListView.setAdapter(adapter); TextView tableHeaderTitleView = (TextView) this.rootView.findViewById(R.id.table_header_title_textview); TextView tableHeaderValueView = (TextView) this.rootView.findViewById(R.id.table_header_value_textview); if (this.currentPlotView instanceof LineGraph){ tableHeaderTitleView.setText(FILTER_MENU_TITLE_ESSID); tableHeaderValueView.setText(TABLE_HEADER_VALUE_TITLE_ATTACKS_PERCENTAGE); } if (this.currentPlotView instanceof PieGraph){ tableHeaderTitleView.setText(FILTER_MENU_TITLE_PROTOCOL); tableHeaderValueView.setText(TABLE_HEADER_VALUE_TITLE_ATTACKS_COUNT); } if (this.currentPlotView instanceof BarGraph){ tableHeaderValueView.setText(TABLE_HEADER_VALUE_TITLE_ATTACKS_COUNT); if (this.selectedCompareData.equals(COMPARE_TITLE_AttacksPerBSSID)){ tableHeaderTitleView.setText(FILTER_MENU_TITLE_BSSID); } else { tableHeaderTitleView.setText(FILTER_MENU_TITLE_ESSID); } } } /* * MENU * */ private void openBarSelectionMenuOnView(View anchorView){ SimplePopupTable visualiseMenu = new SimplePopupTable(this.getActivity(), new AbstractPopup.OnPopupItemClickListener() { public void onItemClick(Object ob) { if (ob instanceof AbstractPopupItem){ AbstractPopupItem item = (AbstractPopupItem) ob; StatisticsFragment.this.userSelectMenuItem(item); } } }); visualiseMenu.setTitle(MENU_POPUP_TITLE); int id = 0; for(String title : StatisticsFragment.this.getMenuTitles()){ SimplePopupItem item = new SimplePopupItem(this.getActivity()); item.setTitle(title); item.setItemId(id); item.setSelected(false); visualiseMenu.addItem(item); id++; } visualiseMenu.showOnView(anchorView); } private void userSelectMenuItem(AbstractPopupItem item){ // OPEN A DIALOG TO SPECIFY THE VISUALISE DATA if (item.getTitle().equals(MENU_TITLE_PROTOCOLS)){ ChartType chartType = ChartType.PIE_CHART; this.selectedCompareData = COMPARE_TITLE_AttacksPerProtocol; this.setChartType(chartType); this.setTitle(COMPARE_TITLE_AttacksPerProtocol); } if (item.getTitle().equals(MENU_TITLE_NETWORK)){ this.openNetworkDataDialog(); } if (item.getTitle().equals(MENU_TITLE_ATTACKS)){ this.openAttackDataDialog(); } } private ArrayList getMenuTitles(){ ArrayList titles = new ArrayList(); titles.add(MENU_TITLE_PROTOCOLS); titles.add(MENU_TITLE_NETWORK); titles.add(MENU_TITLE_ATTACKS); return titles; } /* * PLOT DATA DIALOGS * */ private void openProtocolDataDialog(){ ArrayList titles = this.getDialogProtocolDataTitle(); ChecklistDialog newFragment = new ChecklistDialog(DIALOG_PROTOCOLS_TITLE, titles, this.selectedData(titles), false , this); newFragment.show(this.getActivity().getFragmentManager(), DIALOG_PROTOCOLS_TITLE); } private void openNetworkDataDialog(){ ArrayList titles = this.getDialogNetworkDataTitle(); ChecklistDialog newFragment = new ChecklistDialog(DIALOG_NETWORK_TITLE, titles, this.selectedData(titles), false , this); newFragment.show(this.getActivity().getFragmentManager(), DIALOG_NETWORK_TITLE); } private void openAttackDataDialog(){ ArrayList titles = this.getDialogAttackDataTitle(); ChecklistDialog newFragment = new ChecklistDialog(DIALOG_ATTACK_TITLE, titles, this.selectedData(titles), false , this); newFragment.show(this.getActivity().getFragmentManager(), DIALOG_ATTACK_TITLE); } /* * * DIALOG ACTION METHODS * * */ public void onDialogPositiveClick(ChecklistDialog dialog) { String title = dialog.getTitle(); ArrayList titles =dialog.getSelectedItemTitles(); if (title.equals(FILTER_MENU_TITLE_PROTOCOLS)){ //titles = titles.size() == 0 ? this.protocolTitles() : titles; this.filter.setProtocols(titles); this.actualiseCurrentPlot(); return; } if (title.equals(FILTER_MENU_PROTOCOL_SINGLE_CHOICE_TITLE)){ if (titles.size() == 0){ titles = new ArrayList(); titles.add(this.protocolTitles().get(0)); } this.filter.setProtocols(titles); this.actualiseCurrentPlot(); String fragTitle = "" + this.getCurrentSelectedProtocol() + ": " + this.selectedCompareData; this.setTitle(fragTitle); return; } if (title.equals(FILTER_MENU_TITLE_ESSID)){ this.filter.setESSIDs(titles); this.actualiseCurrentPlot(); return; } if (title.equals(FILTER_MENU_TITLE_BSSID)){ this.filter.setBSSIDs(titles); this.actualiseCurrentPlot(); return; } if (titles.size() != 0){ String data = titles.get(0); this.setTitle(data); if (title.equals(DIALOG_PROTOCOLS_TITLE)){ ChartType chartType = ChartType.PIE_CHART; this.selectedCompareData = data; this.setChartType(chartType); } if (title.equals(DIALOG_ATTACK_TITLE)){ ChartType chartType = ChartType.LINE_CHART; this.selectedCompareData = data; this.setChartType(chartType); } if (title.equals(DIALOG_NETWORK_TITLE)){ ChartType chartType = ChartType.BAR_CHART; this.selectedCompareData = data; this.setChartType(chartType); String fragTitle = "" + this.getCurrentSelectedProtocol() + ": " + this.selectedCompareData; this.setTitle(fragTitle); } } } public void onDialogNegativeClick(ChecklistDialog dialog) { } /* * * DIALOG DATA * * */ private ArrayList getDialogProtocolDataTitle(){ ArrayList data = new ArrayList(); data.add(COMPARE_TITLE_AttacksPerProtocol); data.add(COMPARE_TITLE_UsesPerProtocol); return data; } private ArrayList getDialogAttackDataTitle(){ ArrayList data = new ArrayList(); data.add(COMPARE_TITLE_AttacksPerDate); data.add(COMPARE_TITLE_AttacksPerTime); return data; } private ArrayList getDialogNetworkDataTitle(){ ArrayList data = new ArrayList(); data.add(COMPARE_TITLE_AttacksPerESSID); data.add(COMPARE_TITLE_AttacksPerBSSID); return data; } private boolean[] selectedData(ArrayList data){ boolean[] selected = new boolean[data.size()]; // SET DEFAULT selected[0] = true; return selected; } /* * * FILTER BUTTON * * */ private void openFilterMenuOnView(View anchor){ SimplePopupTable filterMenu = new SimplePopupTable(this.getActivity(), new AbstractPopup.OnPopupItemClickListener() { public void onItemClick(Object ob) { if (ob instanceof AbstractPopupItem){ AbstractPopupItem item = (AbstractPopupItem) ob; StatisticsFragment.this.onFilterMenuItemSelected(item); } } }); filterMenu.setTitle(FILTER_MENU_POPUP_TITLE); for(String title : StatisticsFragment.this.filterMenuTitles()){ AbstractPopupItem item = null; if (title.equals(FILTER_MENU_TITLE_TIMESTAMP_BELOW)) continue; if (title.equals(FILTER_MENU_TITLE_TIMESTAMP_ABOVE)){ item = new SplitPopupItem(this.getActivity()); item.setValue(SplitPopupItem.RIGHT_TITLE, FILTER_MENU_TITLE_TIMESTAMP_BELOW); item.setValue(SplitPopupItem.LEFT_TITLE, FILTER_MENU_TITLE_TIMESTAMP_ABOVE); if (this.filter.hasBelowTimestamp()){ item.setValue(SplitPopupItem.RIGHT_SUBTITLE, this.getDateAsString(this.filter.belowTimestamp)); } if (this.filter.hasAboveTimestamp()){ item.setValue(SplitPopupItem.LEFT_SUBTITLE, this.getDateAsString(this.filter.aboveTimestamp)); } } else { item = new SimplePopupItem(this.getActivity()); item.setTitle(title); ((SimplePopupItem)item).setSelected(this.isFilterSetForTitle(title)); } filterMenu.addItem(item); } filterMenu.showOnView(anchor); } private void onFilterMenuItemSelected(AbstractPopupItem item){ if (item instanceof SplitPopupItem){ SplitPopupItem sItem = (SplitPopupItem) item; this.wasBelowTimePicker = sItem.wasRightTouch; if (this.wasBelowTimePicker){ this.openTimestampToFilterDialog(); } else { this.openTimestampFromFilterDialog(); } return; } String title = item.getTitle(); if (title.equals(FILTER_MENU_TITLE_ESSID)){ this.openESSIDFilterDialog(); } if (title.equals(FILTER_MENU_TITLE_BSSID)){ this.openBSSIDFilterDialog(); } if (title.equals(FILTER_MENU_TITLE_PROTOCOL)){ this.openFilterDialogSelectProtocol(); } if (title.equals(FILTER_MENU_TITLE_PROTOCOLS)){ this.openProtocolsFilterDialog(); } if (title.equals(FILTER_MENU_TITLE_REMOVE)){ this.clearFilter(); this.actualiseCurrentPlot(); } } private ArrayList filterMenuTitles(){ ArrayList titles = new ArrayList(); if (this.currentPlotView instanceof LineGraph){ titles.add(FILTER_MENU_TITLE_ESSID); titles.add(FILTER_MENU_TITLE_PROTOCOLS); titles.add(FILTER_MENU_TITLE_TIMESTAMP_ABOVE); if (this.filter.hasESSIDs() || this.filter.hasATimestamp() || (this.filter.getProtocols() != null && this.filter.hasProtocols() && this.filter.getProtocols().size() != this.protocolTitles().size())){ titles.add(FILTER_MENU_TITLE_REMOVE); } } else { titles.add(FILTER_MENU_TITLE_PROTOCOL); String protocol = this.getCurrentSelectedProtocol(); if (protocol.length() > 0){ if (this.selectedCompareData.equals(COMPARE_TITLE_AttacksPerBSSID)){ titles.add(FILTER_MENU_TITLE_BSSID); } else { // DEFAULT titles.add(FILTER_MENU_TITLE_ESSID); } } titles.add(FILTER_MENU_TITLE_TIMESTAMP_ABOVE); if (this.filter.hasATimestamp() || this.filter.hasESSIDs() || this.filter.hasBSSIDs() || (this.currentPlotView instanceof LineGraph && this.filter.hasProtocols())){ titles.add(FILTER_MENU_TITLE_REMOVE); } } return titles; } private void openProtocolsFilterDialog(){ ChecklistDialog newFragment = new ChecklistDialog(FILTER_MENU_TITLE_PROTOCOLS, this.protocolTitles(), this.selectedProtocols(), true , this); newFragment.show(this.getActivity().getFragmentManager(), FILTER_MENU_TITLE_PROTOCOLS); } private void openFilterDialogSelectProtocol(){ ArrayList titles = this.protocolTitles(); boolean[] selected = new boolean[titles.size()]; int i = 0; for (String title : titles){ selected[i] = title.equals(this.getCurrentSelectedProtocol()); i++; } ChecklistDialog newFragment = new ChecklistDialog(FILTER_MENU_PROTOCOL_SINGLE_CHOICE_TITLE, titles, selected, false , this); newFragment.show(this.getActivity().getFragmentManager(), FILTER_MENU_PROTOCOL_SINGLE_CHOICE_TITLE); } private void openESSIDFilterDialog(){ ChecklistDialog newFragment = new ChecklistDialog(FILTER_MENU_TITLE_ESSID, this.essids(), this.selectedESSIDs(), true , this); newFragment.show(this.getActivity().getFragmentManager(), FILTER_MENU_TITLE_ESSID); } private void openBSSIDFilterDialog(){ ChecklistDialog newFragment = new ChecklistDialog(FILTER_MENU_TITLE_BSSID, this.bssids(), this.selectedBSSIDs(), true , this); newFragment.show(this.getActivity().getFragmentManager(), FILTER_MENU_TITLE_BSSID); } private void openTimestampFromFilterDialog(){ this.wasBelowTimePicker = false; DateTimeDialogFragment newFragment = new DateTimeDialogFragment(this.getActivity()); newFragment.setDateChangeListener(this); newFragment.show(this.getActivity().getFragmentManager(), FILTER_MENU_TITLE_TIMESTAMP_ABOVE); if (this.filter.aboveTimestamp != Long.MIN_VALUE)newFragment.setDate(this.filter.aboveTimestamp); } private void openTimestampToFilterDialog(){ this.wasBelowTimePicker = true; DateTimeDialogFragment newFragment = new DateTimeDialogFragment(this.getActivity()); newFragment.setDateChangeListener(this); newFragment.show(this.getActivity().getFragmentManager(), FILTER_MENU_TITLE_TIMESTAMP_BELOW); if (this.filter.belowTimestamp != Long.MAX_VALUE) newFragment.setDate(this.filter.belowTimestamp); } public ArrayList essids(){ ArrayList records; if (this.currentPlotView instanceof BarGraph){ records = dbh.getUniqueESSIDRecordsForProtocol(this.getCurrentSelectedProtocol()); } else { records = dbh.getUniqueESSIDRecords(); } return records; } public boolean[] selectedESSIDs(){ ArrayList essids = this.essids(); boolean[] selected = new boolean[essids.size()]; int i = 0; for(String essid : essids){ selected[i] =(this.filter.getESSIDs().contains(essid)); i++; } return selected; } public ArrayList bssids(){ ArrayList records ; if (this.currentPlotView instanceof BarGraph){ records = dbh.getUniqueBSSIDRecordsForProtocol(this.getCurrentSelectedProtocol()); } else { records = dbh.getUniqueBSSIDRecords(); } return records; } public boolean[] selectedBSSIDs(){ ArrayList bssids = this.bssids(); boolean[] selected = new boolean[bssids.size()]; int i = 0; for(String bssid : bssids){ selected[i] =(this.filter.getBSSIDs().contains(bssid)); i++; } return selected; } public void onDateTimePickerPositiveClick(DateTimeDialogFragment dialog) { if(this.wasBelowTimePicker){ this.filter.setBelowTimestamp(dialog.getDate()); } else { this.filter.setAboveTimestamp(dialog.getDate()); } this.actualiseCurrentPlot(); } public void onDateTimePickerNegativeClick(DateTimeDialogFragment dialog) { if(this.wasBelowTimePicker){ this.filter.setBelowTimestamp(Long.MAX_VALUE); } else { this.filter.setAboveTimestamp(Long.MIN_VALUE); } this.actualiseCurrentPlot(); } /* * * PLOT TYPES * * **/ public PieGraph getPieGraphView(){ if (this.pieGraph == null) { this.pieGraph = new PieGraph(this.getApplicationContext()); LinearLayout plotLayout = (LinearLayout) this.rootView.findViewById(R.id.plot_layout); plotLayout.addView(this.pieGraph); this.pieGraph.setOnSliceClickedListener(new PieGraph.OnSliceClickedListener() { @Override public void onClick(int index) { StatisticsFragment.this.onSliceClick(index); } }); } return this.pieGraph; } public LineGraph getLineGraphView(){ if (this.lineGraph == null) { this.lineGraph = new LineGraph(this.getActivity()); LinearLayout plotLayout = (LinearLayout) this.rootView.findViewById(R.id.plot_layout); plotLayout.addView(this.lineGraph); this.lineGraph.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT )); } return this.lineGraph; } public BarGraph getBarGraphView(){ if (this.barGraph == null) { this.barGraph = new BarGraph(this.getActivity()); LinearLayout plotLayout = (LinearLayout) this.rootView.findViewById(R.id.plot_layout); this.barGraph.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT )); plotLayout.addView(this.barGraph); this.barGraph.setShowBarText(false); this.barGraph.setPopupImageID(R.drawable.popup_black); this.barGraph.setOnBarClickedListener(new BarGraph.OnBarClickedListener() { @Override public void onClick(int i) { StatisticsFragment.this.onBarClick(i); } }); } return this.barGraph; } /* * FEED PLOTS WITH DATA * */ public void setPieGraphData(PieGraph piegraph){ this.currentData = this.getPieData(); if (this.currentData == null){ this.currentData = new ArrayList(); } this.pieGraph.removeSlices(); for (PlotComparisonItem item : this.currentData){ PieSlice slice = new PieSlice(); slice.setColor(item.getColor()); Double value2 = (Double) item.getValue2(); float v = value2.floatValue(); slice.setValue(v); slice.setTitle(item.getTitle()); this.pieGraph.addSlice(slice); } this.pieGraph.invalidate(); } public void setLineGraphData(LineGraph linegraph){ this.currentData = this.getLineData(); if (this.currentData == null){ this.currentData = new ArrayList(); } this.lineGraph.removeAllLines(); double rangeMax_Y = 0; double rangeMin_Y = 0; double rangeMax_X = 0; double rangeMin_X = 0; int count = 0; for (PlotComparisonItem lineItem : this.currentData){ ArrayList data = lineItem.getOtherData(); int index = 0; Line l = new Line(); int lineColor = lineItem.getColor(); l.setColor(lineColor); for (PlotComparisonItem pointItem : data){ LinePoint p = new LinePoint(); p.setX(pointItem.getValue1()); Double value2 = pointItem.getValue2(); p.setY(value2); p.setColor(lineColor); l.addPoint(p); rangeMax_Y = Math.max(pointItem.getValue2(), rangeMax_Y); rangeMax_X = Math.max(pointItem.getValue1(), rangeMax_X); if (count != 0){ rangeMin_Y = Math.min(pointItem.getValue2(), rangeMin_Y); rangeMin_X = Math.min(pointItem.getValue1(), rangeMin_X); } else { rangeMin_Y = pointItem.getValue2(); rangeMin_X = pointItem.getValue1(); } index++; count++; } this.lineGraph.addLine(l); } // add a bit more space rangeMax_Y++; rangeMin_Y--; boolean shouldUseDate = this.selectedCompareData.equals(COMPARE_TITLE_AttacksPerDate); if (shouldUseDate){ this.lineGraph.resetXLimits(); if (this.filter.hasBelowTimestamp()){ rangeMax_X = Math.max(this.filter.belowTimestamp, rangeMax_X); } if (this.filter.hasAboveTimestamp()){ rangeMin_X = Math.min(this.filter.aboveTimestamp, rangeMin_X); } double stepRange = (rangeMax_X - rangeMin_X)/(60*60*24*1000); this.lineGraph.setxAxisStep(Math.max(1, (float) Math.min(stepRange, 4))); this.lineGraph.setRangeX(rangeMin_X , rangeMax_X); this.lineGraph.setConverter(new LineGraph.AxisDataConverter() { @Override public String convertDataForX_Position(double x) { return StatisticsFragment.this.getDateAsDayString((long)x); } @Override public String convertDataForY_Position(double y){ return "" + (long)y; } }); } else { this.lineGraph.setxAxisStep(12.f); this.lineGraph.setRangeX(0, 24); this.lineGraph.setConverter(null); } int maxY = (int)(rangeMax_Y - rangeMin_Y); this.lineGraph.setYAxisStep(Math.min(maxY, 5)); int yStep = (int)this.lineGraph.getyAxisStep(); if ((maxY % yStep) != 0) { maxY = maxY + (yStep - (maxY % yStep)); } this.lineGraph.setRangeY(rangeMin_Y, rangeMin_Y + maxY); this.lineGraph.setLineToFill(0); this.lineGraph.invalidate(); } public void setBarGraphData(BarGraph bargraph){ this.currentData = this.getBarData(); if (this.currentData == null){ this.currentData = new ArrayList(); } ArrayList bars = new ArrayList(); for (PlotComparisonItem item : this.currentData){ Bar d = new Bar(); d.setColor(item.getColor()); Long value2 = item.getValue2().longValue(); d.setName("" + value2); d.setValue(value2.floatValue()); bars.add(d); } this.barGraph.setBars(bars); this.barGraph.invalidate(); } /* * * FETCH & ACTUALISE RECORD DATA * * */ public ArrayList getFetchedRecords(){ if (this.filter == null) this.clearFilter(); return this.dbh.getRecordsForFilter(this.filter); } public void actualiseCurrentPlot(){ LinearLayout plotLayout = (LinearLayout) this.rootView.findViewById(R.id.plot_layout); View plot = this.currentPlotView; if (plot == null){ this.currentPlotView = this.getPieGraphView(); plot = this.currentPlotView; } if (plot.getParent() != null && !plot.getParent().equals(plotLayout)){ LinearLayout linLayout = (LinearLayout)plot.getParent(); linLayout.removeView(plot); plot.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT )); plotLayout.addView(plot); } if (plot.getVisibility() == View.GONE) plot.setVisibility(View.VISIBLE); if (plot instanceof PieGraph){ PieGraph pie = (PieGraph) plot; this.setPieGraphData(pie); // HIDE FILTER BUTTON ImageButton filterButton = this.getFilterButton(); if (filterButton != null) filterButton.setVisibility(View.GONE); } else { if (this.pieGraph != null){ this.pieGraph.setVisibility(View.GONE); if (this.pieGraph.getParent() != null){ plotLayout.removeView(this.pieGraph); } } // SHOW FILTER BUTTON ImageButton filterButton = this.getFilterButton(); if (filterButton != null) filterButton.setVisibility(View.VISIBLE); } if (plot instanceof BarGraph){ BarGraph bar = (BarGraph) plot; this.setBarGraphData(bar); } else { if (this.barGraph != null){ this.barGraph.setVisibility(View.GONE); if (this.barGraph.getParent() != null){ plotLayout.removeView(this.barGraph); } } } if (plot instanceof LineGraph){ LineGraph line = (LineGraph)plot; this.setLineGraphData(line); }else { if (this.lineGraph != null){ this.lineGraph.setVisibility(View.GONE); if (this.lineGraph.getParent() != null){ plotLayout.removeView(this.lineGraph); } } } plot.setVisibility(View.VISIBLE); if (plot.getParent() == null){ plotLayout.addView(plot); } this.actualiseLegendList(); this.currentPlotView.bringToFront(); this.currentPlotView.invalidate(); } public ArrayList getPieData(){ // DEFAULT return this.attacksPerProtocols(); } public ArrayList getBarData(){ String protocol = this.getCurrentSelectedProtocol(); if (protocol.length() > 0){ if (this.selectedCompareData.equals(COMPARE_TITLE_AttacksPerESSID)){ return this.attacksPerESSID(protocol); } // DEFAULT return this.attacksPerBSSID(protocol); } // Nothing available return new ArrayList(); } public ArrayList getLineData(){ return this.attacksPerTime(); } /* * DATA SOURCE * */ /*PROTOCOLS OVERVIEW*/ public ArrayList attacksPerProtocols(){ ArrayList plotItems = new ArrayList(); int index = 0; for (String title : this.getSelectedProtocolTitles()){ int attacksCount = this.dbh.getAttackPerProtocolCount(title); if (attacksCount == 0) continue; PlotComparisonItem item = new PlotComparisonItem(title,this.getColor(index), 0., (double) attacksCount); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s2.getValue2().compareTo(s1.getValue2()); } }); return this.resizeData(plotItems); } /*LINE PLOT DATA*/ public ArrayList attacksPerTime(){ HashMap > > lineMap = new HashMap>>(); boolean shouldUseDate = this.selectedCompareData.equals(COMPARE_TITLE_AttacksPerDate); ArrayList records = this.getFetchedRecords(); for (Record record : records){ long timestamp = record.getTimestamp(); long time = 0; if (shouldUseDate){ time = this.getDateFromMilliseconds(timestamp); } else { time = this.getDayHourFromDate(timestamp); } // GET CORRECT MAP HashMap > recordMap; String groupKey = record.getSsid(); if (lineMap.containsKey(groupKey)){ recordMap = lineMap.get(record.getSsid()); } else { recordMap = new HashMap >(); lineMap.put(groupKey, recordMap); } // GET LIST OF RECORDS ArrayList list; if (recordMap.containsKey(time)){ list = recordMap.get(time); } else { list = new ArrayList(); recordMap.put(time, list); } list.add(record); } ArrayList plotItems = new ArrayList(); int index = 0; for (String groupKey : lineMap.keySet()){ HashMap > recordMap = lineMap.get(groupKey); ArrayList singleLineItems = new ArrayList(); int numbOfAttacks = 0; for (long time : recordMap.keySet()){ ArrayListlist = recordMap.get(time); if (list.size() == 0) continue; PlotComparisonItem item = new PlotComparisonItem(this.getHourAsTimeString(time), 0 , (double)time, (double) list.size()); singleLineItems.add(item); numbOfAttacks +=list.size(); } Collections.sort(singleLineItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s1.getValue1().compareTo(s2.getValue1()); } }); double itemValue = (((double)numbOfAttacks / (double)records.size())*100.); PlotComparisonItem item = new PlotComparisonItem(groupKey, this.getColor(index), 0., itemValue); item.setOtherData(singleLineItems); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s2.getValue2().compareTo(s1.getValue2()); } }); return plotItems; } // BAR PLOT DATA public ArrayList attacksPerBSSID(String protocol){ LogFilter filter = new LogFilter(); ArrayList protocollist = new ArrayList(); filter.setAboveTimestamp(this.filter.getAboveTimestamp()); filter.setBelowTimestamp(this.filter.getBelowTimestamp()); filter.setBSSIDs(this.filter.getBSSIDs()); protocollist.add(protocol); filter.setProtocols(protocollist); ArrayList plotItems = new ArrayList(); HashMap recordMap = new HashMap(); ArrayList records = this.dbh.getRecordsForFilter(filter); for (Record record : records){ int count = 0; if (recordMap.containsKey(record.getBssid())){ count = recordMap.get(record.getBssid()); } count++; recordMap.put(record.getBssid(), count); } int index = 0; for (String key : recordMap.keySet()){ double value = (double)recordMap.get(key); if (value == 0.) continue; PlotComparisonItem item = new PlotComparisonItem(key, this.getColor(index), 0., value); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s2.getValue2().compareTo(s1.getValue2()); } }); return this.resizeData(plotItems); } public ArrayList attacksPerESSID(String protocol){ LogFilter filter = new LogFilter(); filter.setAboveTimestamp(this.filter.getAboveTimestamp()); filter.setBelowTimestamp(this.filter.getBelowTimestamp()); filter.setESSIDs(this.filter.getESSIDs()); ArrayList protocollist = new ArrayList(); protocollist.add(protocol); filter.setProtocols(protocollist); ArrayList plotItems = new ArrayList(); HashMap recordMap = new HashMap(); ArrayList records = this.dbh.getRecordsForFilter(filter); for (Record record : records){ int count = 0; if (recordMap.containsKey(record.getSsid())){ count = recordMap.get(record.getSsid()); } count++; recordMap.put(record.getSsid(), count); } int index = 0; for (String key : recordMap.keySet()){ double value = (double)recordMap.get(key); if (value == 0.) continue; PlotComparisonItem item = new PlotComparisonItem(key,this.getColor(index), 0. ,value); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s2.getValue2().compareTo(s1.getValue2()); } }); return this.resizeData(plotItems); } private ArrayList resizeData(ArrayList plotItems){ if (plotItems != null){ if (plotItems.size() > MAX_NUMBER_OF_CHART_OBJECTS && MAX_NUMBER_OF_CHART_OBJECTS > 1){ ArrayList copy = new ArrayList(); ArrayList others = new ArrayList(); double valueOfOthers = 0; for (int i = 0; i < plotItems.size(); i++){ if (i < MAX_NUMBER_OF_CHART_OBJECTS - 1){ PlotComparisonItem item = plotItems.get(i); item.setColor(this.getColor(i)); copy.add(plotItems.get(i)); } else { PlotComparisonItem item = plotItems.get(i); others.add(item); valueOfOthers+=item.getValue2(); } } PlotComparisonItem otherItem = new PlotComparisonItem(OTHER_CHART_TITLE, this.getOtherColor(), 0., valueOfOthers); otherItem.setOtherData(others); copy.add(otherItem); Collections.sort(copy, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s2.getValue2().compareTo(s1.getValue2()); } }); return copy; } } return plotItems; } /* * FILTER STUFF * */ private String getCurrentSelectedProtocol(){ ArrayList protocolTitles = this.getSelectedProtocolTitles(); if (protocolTitles != null && protocolTitles.size() != 0){ return protocolTitles.get(0); } return this.protocolTitles().get(0); } public ArrayList protocolTitles(){ ArrayList titles = new ArrayList(); for (String protocol : this.getResources().getStringArray( R.array.protocols)) { titles.add(protocol); } return titles; } public boolean[] selectedProtocols(){ ArrayList protocols = this.protocolTitles(); boolean[] selected = new boolean[protocols.size()]; int i = 0; for(String protocol : protocols){ selected[i] =(this.filter.protocols.contains(protocol)); i++; } return selected; } public ArrayList getSelectedProtocolTitles(){ ArrayList knownProtocols = this.protocolTitles(); if (this.filter.hasProtocols()){ ArrayList titles = new ArrayList(); int i =0; for (boolean b : this.selectedProtocols()){ if (b){ String title = knownProtocols.get(i); titles.add(title); } i++; } return titles; } return this.protocolTitles(); } /* * * COLOR STUFF * * */ public int getOtherColor(){ return Color.argb(255, 80, 80, 80); // grey } public Integer getColor(int index) { return ColorSequenceGenerator.getColorForIndex(index); } public LinearLayout getPlotLayout(){ if (this.rootView != null){ return (LinearLayout) this.rootView.findViewById(R.id.plot_layout); } else { return null; } } /** * * FILTER STUFF * * */ private boolean isFilterSetForTitle(String title){ if (title.equals(FILTER_MENU_TITLE_BSSID)){ return this.filter.hasBSSIDs(); } if (title.equals(FILTER_MENU_TITLE_ESSID)){ return this.filter.hasESSIDs(); } if (title.equals(FILTER_MENU_TITLE_PROTOCOLS)){ return (this.filter.getProtocols() != null && this.filter.hasProtocols() && this.filter.getProtocols().size() != this.protocolTitles().size()); } if (title.equals(FILTER_MENU_TITLE_TIMESTAMP_BELOW)){ return this.filter.hasBelowTimestamp(); } if (title.equals(FILTER_MENU_TITLE_TIMESTAMP_ABOVE)){ return this.filter.hasAboveTimestamp(); } return false; } private void clearFilter(){ if(filter == null) this.filter = new LogFilter(); this.filter.clear(); } /* * * DATE TRANSFORMATION * */ public long getDayHourFromDate(long timeInMillis){ Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis (timeInMillis); int hour = calendar.get(Calendar.HOUR_OF_DAY); int min = calendar.get(Calendar.MINUTE); return hour; } public long getDateFromMilliseconds(long timeInMillis){ long millisInDay = 60 * 60 * 24 * 1000; return (timeInMillis / millisInDay) * millisInDay; } /* * * */ private String getHourAsTimeString(long hour) { return "" + hour + ":00"; } static final DateFormat dateFormat = new SimpleDateFormat("d.M.yyyy"); @SuppressLint("SimpleDateFormat") private String getDateAsDayString(long timeStamp) { try { Date netDate = (new Date(timeStamp)); return dateFormat.format(netDate); } catch (Exception ex) { return "xx"; } } @SuppressLint("SimpleDateFormat") private String getDateAsString(long timeStamp) { try { DateFormat sdf = new SimpleDateFormat("H:mm dd/MM/yyyy"); Date netDate = (new Date(timeStamp)); return sdf.format(netDate); } catch (Exception ex) { return "xx"; } } /** * USERINTERACTION */ private void userTappedOnLegendItem(int index){ if (index < this.currentData.size()){ PlotComparisonItem item = this.currentData.get(index); ArrayList selectedData; String sortKey = null; selectedData = new ArrayList(); if (item.getOtherData() == null){ selectedData.add(item.getTitle()); } else { for (PlotComparisonItem other : item.getOtherData()){ selectedData.add(other.getTitle()); } } LogFilter filter = new LogFilter(); if (this.currentPlotView instanceof PieGraph){ filter.setProtocols(selectedData); } if (this.currentPlotView instanceof BarGraph){ if (this.selectedCompareData.equals(COMPARE_TITLE_AttacksPerESSID)){ filter.setESSIDs(selectedData); sortKey = "ESSID"; } else { filter.setBSSIDs(selectedData); sortKey = "BSSID"; } ArrayList currentSelectedProtocol = new ArrayList(); currentSelectedProtocol.add(this.getCurrentSelectedProtocol()); filter.setProtocols(currentSelectedProtocol); } if (this.currentPlotView instanceof LineGraph){ selectedData = new ArrayList(); selectedData.add(item.getTitle()); filter.setESSIDs(selectedData); filter.setProtocols(this.filter.getProtocols()); sortKey = "ESSID"; } if (this.filter.hasATimestamp()){ filter.setAboveTimestamp(this.filter.getAboveTimestamp()); filter.setBelowTimestamp(this.filter.getBelowTimestamp()); } this.pushRecordOverviewForFilter(filter, sortKey); } } public void onSliceClick(int index){ } public void onBarClick(int index){ this.userTappedOnLegendItem(index); } private void pushRecordOverviewForFilter(LogFilter filter, String sortKey){ FragmentManager fm = this.getActivity().getFragmentManager(); if (fm != null){ RecordOverviewFragment newFragment = new RecordOverviewFragment(); newFragment.setUpNavigatible(true); newFragment.setFilter(filter); if (sortKey != null && sortKey.length() != 0) newFragment.setGroupKey(sortKey); MainActivity.getInstance().injectFragment(newFragment); } } }