|
@@ -0,0 +1,504 @@
|
|
|
+package de.tudarmstadt.informatik.hostage.ui2.fragment;
|
|
|
+
|
|
|
+import android.annotation.SuppressLint;
|
|
|
+import android.app.Fragment;
|
|
|
+import android.content.Context;
|
|
|
+import android.content.Intent;
|
|
|
+import android.graphics.Color;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.view.LayoutInflater;
|
|
|
+import android.view.View;
|
|
|
+import android.view.ViewGroup;
|
|
|
+import android.widget.LinearLayout;
|
|
|
+
|
|
|
+import com.echo.holographlibrary.BarGraph;
|
|
|
+import com.echo.holographlibrary.LineGraph;
|
|
|
+import com.echo.holographlibrary.PieGraph;
|
|
|
+
|
|
|
+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.model.PlotComparisonItem;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Created by Julien on 16.02.14.
|
|
|
+ */
|
|
|
+public class StatisticsFragment extends Fragment {
|
|
|
+ static final String SELECTED_KEY = "Selected";
|
|
|
+ static final String OTHERS_KEY = "Other";
|
|
|
+
|
|
|
+ static final String FILTER_MENU_TITLE_BSSID = "BSSID";
|
|
|
+ static final String FILTER_MENU_TITLE_ESSID = "ESSID";
|
|
|
+ static final String FILTER_MENU_TITLE_PROTOCOLS = "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_SORTING = "Sort by";
|
|
|
+ static final String FILTER_MENU_TITLE_REMOVE = "Reset Filter";
|
|
|
+ static final String FILTER_MENU_TITLE_GROUP = "Group by";
|
|
|
+ static final String FILTER_MENU_POPUP_TITLE = "Filter by";
|
|
|
+
|
|
|
+ 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";
|
|
|
+
|
|
|
+ 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<Integer> colorList;
|
|
|
+
|
|
|
+ private ArrayList<Record> fetchedRecords;
|
|
|
+
|
|
|
+ private UglyDbHelper dbh;
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onCreate(Bundle savedInstanceState) {
|
|
|
+ super.onCreate(savedInstanceState);
|
|
|
+ setHasOptionsMenu(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getLayoutID(){
|
|
|
+ return R.layout.fragment_statistics;
|
|
|
+ }
|
|
|
+
|
|
|
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
+ Bundle savedInstanceState) {
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ View rootView = inflater.inflate(this.getLayoutID(), container, false);
|
|
|
+ this.rootView = rootView;
|
|
|
+ this.configureRootView(rootView);
|
|
|
+
|
|
|
+
|
|
|
+ return 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);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ *
|
|
|
+ * PLOT TYPES
|
|
|
+ *
|
|
|
+ * **/
|
|
|
+ public PieGraph getPieGraphView(){
|
|
|
+ if (this.pieGraph == null) {
|
|
|
+ this.pieGraph = new PieGraph(this.getApplicationContext());
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * ACTUALISE INPUT DATA
|
|
|
+ * */
|
|
|
+ this.setPieGraphData(this.pieGraph);
|
|
|
+ return this.pieGraph;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LineGraph getLineGraphView(){
|
|
|
+ if (this.lineGraph == null) {
|
|
|
+ this.lineGraph = new LineGraph(this.getApplicationContext());
|
|
|
+ }
|
|
|
+ this.setLineGraphData(this.lineGraph);
|
|
|
+ return this.lineGraph;
|
|
|
+ }
|
|
|
+
|
|
|
+ public BarGraph getBarGraphView(){
|
|
|
+ if (this.barGraph == null) {
|
|
|
+ this.barGraph = new BarGraph(this.getApplicationContext());
|
|
|
+ this.barGraph.setPopupImageID(R.drawable.popup_black);
|
|
|
+ }
|
|
|
+ this.setBarGraphData(this.barGraph);
|
|
|
+ return this.barGraph;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * FEED PLOTS WITH DATA
|
|
|
+ * */
|
|
|
+ public void setPieGraphData(PieGraph piegraph){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setLineGraphData(LineGraph linegraph){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setBarGraphData(BarGraph bargraph){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ *
|
|
|
+ * FETCH & ACTUALISE RECORD DATA
|
|
|
+ *
|
|
|
+ * */
|
|
|
+ public ArrayList<Record> getFetchedRecords(){
|
|
|
+ if (this.filter == null) this.clearFilter();
|
|
|
+ return this.dbh.getRecordsForFilter(this.filter);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void actualiseCurrentPlot(){
|
|
|
+ this.actualiseRecords();
|
|
|
+ this.actualisePlotData();
|
|
|
+ View plot = this.currentPlotView;
|
|
|
+ if (plot instanceof PieGraph){
|
|
|
+ this.setPieGraphData((PieGraph)plot);
|
|
|
+ }
|
|
|
+ if (plot instanceof BarGraph){
|
|
|
+ this.setBarGraphData((BarGraph) plot);
|
|
|
+ }
|
|
|
+ if (plot instanceof LineGraph){
|
|
|
+ this.setLineGraphData((LineGraph) plot);
|
|
|
+ }
|
|
|
+ plot.invalidate();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void actualiseRecords(){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void actualisePlotData(){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * SPECIFIC DATA STUFF
|
|
|
+ * */
|
|
|
+
|
|
|
+ /*PROTOCOLS OVERVIEW*/
|
|
|
+ public ArrayList<PlotComparisonItem> attacksPerProtocols(){
|
|
|
+ ArrayList<PlotComparisonItem> plotItems = new ArrayList<PlotComparisonItem>();
|
|
|
+ for (String title : this.getSelectedProtocolTitles()){
|
|
|
+ int attacksCount = this.dbh.getAttackPerProtocolCount(title);
|
|
|
+ PlotComparisonItem item = new PlotComparisonItem(title, title, attacksCount);
|
|
|
+ plotItems.add(item);
|
|
|
+ }
|
|
|
+ Collections.sort(plotItems, new Comparator<PlotComparisonItem>() {
|
|
|
+ @Override
|
|
|
+ public int compare(PlotComparisonItem s1, PlotComparisonItem s2) {
|
|
|
+ return s1.getTitle().compareToIgnoreCase(s2.getTitle());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return plotItems;
|
|
|
+ }
|
|
|
+ public ArrayList<PlotComparisonItem> usesPerProtocols(){
|
|
|
+ ArrayList<PlotComparisonItem> plotItems = new ArrayList<PlotComparisonItem>();
|
|
|
+ for (String title : this.getSelectedProtocolTitles()){
|
|
|
+ /*At the moment there is no possibillity to get the number of uses for each protocol*/
|
|
|
+
|
|
|
+ }
|
|
|
+ Collections.sort(plotItems, new Comparator<PlotComparisonItem>() {
|
|
|
+ @Override
|
|
|
+ public int compare(PlotComparisonItem s1, PlotComparisonItem s2) {
|
|
|
+ return s1.getTitle().compareToIgnoreCase(s2.getTitle());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return plotItems;
|
|
|
+ }
|
|
|
+ /*BAR PLOT DATA*/
|
|
|
+ public ArrayList<PlotComparisonItem> attacksPerDate(){
|
|
|
+ ArrayList<PlotComparisonItem> plotItems = new ArrayList<PlotComparisonItem>();
|
|
|
+ HashMap<Long, ArrayList<Record> > recordMap = new HashMap<Long, ArrayList<Record> >();
|
|
|
+
|
|
|
+ for (Record record : this.getFetchedRecords()){
|
|
|
+ long date = this.getdateFromMilliseconds(record.getTimestamp());
|
|
|
+ ArrayList<Record> list = recordMap.get(date);
|
|
|
+ if (list == null){
|
|
|
+ list = new ArrayList<Record>();
|
|
|
+ recordMap.put(date, list);
|
|
|
+ }
|
|
|
+ list.add(record);
|
|
|
+ }
|
|
|
+ for (long date : recordMap.keySet()){
|
|
|
+ ArrayList<Record> list = recordMap.get(date);
|
|
|
+ PlotComparisonItem item = new PlotComparisonItem(this.getDateAsDayString(date), date, list.size());
|
|
|
+ plotItems.add(item);
|
|
|
+ }
|
|
|
+ Collections.sort(plotItems, new Comparator<PlotComparisonItem>() {
|
|
|
+ @Override
|
|
|
+ public int compare(PlotComparisonItem s1, PlotComparisonItem s2) {
|
|
|
+ return s1.getTitle().compareToIgnoreCase(s2.getTitle());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return plotItems;
|
|
|
+ }
|
|
|
+ public ArrayList<PlotComparisonItem> attacksPerTime(){
|
|
|
+ ArrayList<PlotComparisonItem> plotItems = new ArrayList<PlotComparisonItem>();
|
|
|
+ HashMap<Long, ArrayList<Record> > recordMap = new HashMap<Long, ArrayList<Record> >();
|
|
|
+
|
|
|
+ for (Record record : this.getFetchedRecords()){
|
|
|
+ long date = this.getDayHourFromDate(record.getTimestamp());
|
|
|
+ ArrayList<Record> list = recordMap.get(date);
|
|
|
+ if (list == null){
|
|
|
+ list = new ArrayList<Record>();
|
|
|
+ recordMap.put(date, list);
|
|
|
+ }
|
|
|
+ list.add(record);
|
|
|
+ }
|
|
|
+ for (long time : recordMap.keySet()){
|
|
|
+ ArrayList<Record> list = recordMap.get(time);
|
|
|
+ PlotComparisonItem item = new PlotComparisonItem(this.getDateAsTimeString(time), time, list.size());
|
|
|
+ plotItems.add(item);
|
|
|
+ }
|
|
|
+ Collections.sort(plotItems, new Comparator<PlotComparisonItem>() {
|
|
|
+ @Override
|
|
|
+ public int compare(PlotComparisonItem s1, PlotComparisonItem s2) {
|
|
|
+ return s1.getTitle().compareToIgnoreCase(s2.getTitle());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return plotItems;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * FILTER STUFF
|
|
|
+ * */
|
|
|
+ public ArrayList<String> protocolTitles(){
|
|
|
+ ArrayList<String> titles = new ArrayList<String>();
|
|
|
+ for (String protocol : this.getResources().getStringArray(
|
|
|
+ R.array.protocols)) {
|
|
|
+ titles.add(protocol);
|
|
|
+ }
|
|
|
+ return titles;
|
|
|
+ }
|
|
|
+ public boolean[] selectedProtocols(){
|
|
|
+ ArrayList<String> 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<String> getSelectedProtocolTitles(){
|
|
|
+ ArrayList<String> knownProtocols = this.protocolTitles();
|
|
|
+ if (this.filter.hasProtocols()){
|
|
|
+ ArrayList<String> titles = new ArrayList<String>();
|
|
|
+ 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 ArrayList<Integer> getColorList(){
|
|
|
+ if (this.colorList == null){
|
|
|
+ this.colorList = new ArrayList<Integer>();
|
|
|
+ for (int i =0; i < 255; i++){
|
|
|
+ Integer color = this.generateColorForIndex(i);
|
|
|
+ this.colorList.add(color);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return this.colorList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getColor(int index){
|
|
|
+ if (index > this.colorList.size()) {
|
|
|
+ for (int i = this.colorList.size(); i<= index; i++){
|
|
|
+ Integer color = this.generateColorForIndex(i);
|
|
|
+ this.colorList.add(color);
|
|
|
+ }
|
|
|
+ return this.generateColorForIndex(index);
|
|
|
+ }
|
|
|
+ return this.colorList.get(index);
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer generateColorForIndex(int index){
|
|
|
+ int r[] = new int[]{0,0,0,1,1,1,1};
|
|
|
+ int g[] = new int[]{0,1,1,1,1,0,0};
|
|
|
+ int b[] = new int[]{1,1,0,0,1,1,0};
|
|
|
+
|
|
|
+ int a = index % 16;
|
|
|
+ int n = index % 7;
|
|
|
+
|
|
|
+ int R = Math.max( (r[n] * 255) - (a * 16) , 0);
|
|
|
+ int G = Math.max( (g[n] * 255) - ((Math.max(0,(a -1))) * 16), 0);
|
|
|
+ int B = Math.max( (b[n] * 255) - ((Math.max(0,(a -2))) * 16), 0);
|
|
|
+
|
|
|
+ return Color.rgb(R,G,B);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ *
|
|
|
+ * ACTUALISE PLOT VIEW
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+ public void setPlotView(View view){
|
|
|
+ LinearLayout plotLayout = this.getPlotLayout();
|
|
|
+ if (this.currentPlotView != null && plotLayout != null){
|
|
|
+ plotLayout.removeAllViews();
|
|
|
+ }
|
|
|
+ if (view != null && plotLayout != null){
|
|
|
+ this.currentPlotView = view;
|
|
|
+ view.setLayoutParams(plotLayout.getLayoutParams());
|
|
|
+ plotLayout.addView(view);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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.hasProtocols();
|
|
|
+ }
|
|
|
+ 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);
|
|
|
+ int min = calendar.get(Calendar.MINUTE);
|
|
|
+
|
|
|
+ return (hour*60*60)*1000;
|
|
|
+ }
|
|
|
+ public long getdateFromMilliseconds(long timeInMillis){
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
+ calendar.setTimeInMillis (timeInMillis);
|
|
|
+
|
|
|
+ int year = calendar.get(Calendar.YEAR) ;
|
|
|
+ int month = calendar.get(Calendar.MONTH);
|
|
|
+ int day = calendar.get(Calendar.DATE);
|
|
|
+
|
|
|
+ calendar.set(year, month, day, 0,0);
|
|
|
+ return calendar.getTimeInMillis();
|
|
|
+ }
|
|
|
+
|
|
|
+ static final DateFormat timeFormat = new SimpleDateFormat("H:mm");
|
|
|
+ @SuppressLint("SimpleDateFormat")
|
|
|
+ private String getDateAsTimeString(long timeStamp) {
|
|
|
+ try {
|
|
|
+ Date netDate = (new Date(timeStamp));
|
|
|
+ return timeFormat.format(netDate);
|
|
|
+ } catch (Exception ex) {
|
|
|
+ return "xx";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ static final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
|
|
|
+ @SuppressLint("SimpleDateFormat")
|
|
|
+ private String getDateAsDayString(long timeStamp) {
|
|
|
+ try {
|
|
|
+ Date netDate = (new Date(timeStamp));
|
|
|
+ return dateFormat.format(netDate);
|
|
|
+ } catch (Exception ex) {
|
|
|
+ return "xx";
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|