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.AdapterView; 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.adapter.StatisticListAdapter; 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"; static final String OTHER_CHART_TITLE = "Other"; // MINIMAL 2 static int MAX_NUMBER_OF_CHART_OBJECTS = 5; 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; 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); LinearLayout plotLayout = (LinearLayout) rootView.findViewById(R.id.plot_layout); plotLayout.setWillNotDraw(false); container.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.userTappedOnItem(i); } }); this.rootView = rootView; rootView.setWillNotDraw(false); 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); plotLayout.setWillNotDraw(false); plotLayout.removeAllViews(); this.actualiseCurrentPlot(); } public void setTitle(String title){ TextView titleView = (TextView) this.rootView.findViewById(R.id.title_text_view); if (title != null && titleView != null){ titleView.setText(title); } } 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(); } public void setChartType(ChartType type){ boolean shouldChange = true; if (this.currentPlotView != null){ if (type == ChartType.PIE_CHART){ shouldChange = ! (this.currentPlotView instanceof PieGraph); } else { this.pieGraph.setVisibility(View.INVISIBLE); } if (type == ChartType.LINE_CHART){ shouldChange = ! (this.currentPlotView instanceof LineGraph); } else { this.lineGraph.setVisibility(View.INVISIBLE); } if (type == ChartType.BAR_CHART){ shouldChange = ! (this.currentPlotView instanceof BarGraph); } else { this.barGraph.setVisibility(View.INVISIBLE); } } 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); this.legendListView.setAdapter(adapter); } /** * * PLOT TOUCH HANDLING * * */ public void onSliceClick(int index){ this.userTappedOnItem(index); } public void onBarClick(int index){ this.userTappedOnItem(index); } /* * * 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); } 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); plotLayout.addView(this.barGraph); 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(); } int index = 0; this.lineGraph.removeAllLines(); Line l = new Line(); for (PlotComparisonItem item : this.currentData){ LinePoint p = new LinePoint(); p.setX(index); Double value2 = (Double) item.getValue2(); p.setY(value2.floatValue()); index++; } this.lineGraph.addLine(l); this.lineGraph.setRangeY(0, index); this.lineGraph.setLineToFill(0); this.lineGraph.invalidate(); } public void setBarGraphData(BarGraph bargraph){ this.currentData = this.getLinedata(); 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()); d.setName(item.getTitle()); Double value2 = (Double) item.getValue2(); d.setValue(value2.floatValue()); } 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(){ View plot = this.currentPlotView; if (plot == null){ this.currentPlotView = this.getPieGraphView(); plot = this.currentPlotView; } if (plot.getVisibility() == View.INVISIBLE) plot.setVisibility(View.VISIBLE); if (plot instanceof PieGraph){ PieGraph pie = (PieGraph) plot; this.setPieGraphData(pie); } else { if (this.pieGraph != null) this.pieGraph.setVisibility(View.INVISIBLE); } if (plot instanceof BarGraph){ BarGraph bar = (BarGraph) plot; this.setBarGraphData(bar); } else { if (this.barGraph != null) this.barGraph.setVisibility(View.INVISIBLE); } if (plot instanceof LineGraph){ LineGraph line = (LineGraph)plot; this.setLineGraphData(line); }else { if (this.lineGraph != null) this.lineGraph.setVisibility(View.INVISIBLE); } plot.setVisibility(View.VISIBLE); this.actualiseLegendList(); this.currentPlotView.invalidate(); } public ArrayList getPieData(){ // DEFAULT return this.attacksPerProtocols(); } public ArrayList getBarData(){ ArrayList protocolTitles = this.getSelectedProtocolTitles(); // DEFAULT if (protocolTitles != null && protocolTitles.size() != 0){ String protocol = this.getSelectedProtocolTitles().get(0); return this.attacksPerBSSID(protocol); } // Nothing available return new ArrayList(); } public ArrayList getLinedata(){ // DEFAULT return this.attacksPerDate(); } /* * SPECIFIC DATA STUFF * */ /*PROTOCOLS OVERVIEW*/ public ArrayList attacksPerProtocols(){ ArrayList plotItems = new ArrayList(); int index = 0; for (String title : this.getSelectedProtocolTitles()){ int attacksCount = this.dbh.getAttackPerProtocolCount(title); 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 s1.getValue2().compareTo(s2.getValue2()); } }); return this.resizeData(plotItems); } public ArrayList usesPerProtocol(){ ArrayList plotItems = new ArrayList(); 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() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s1.getTitle().compareToIgnoreCase(s2.getTitle()); } }); return plotItems; } /*LINE PLOT DATA*/ public ArrayList attacksPerDate(){ ArrayList plotItems = new ArrayList(); HashMap > recordMap = new HashMap >(); for (Record record : this.getFetchedRecords()){ long date = this.getdateFromMilliseconds(record.getTimestamp()); ArrayList list = recordMap.get(date); if (list == null){ list = new ArrayList(); recordMap.put(date, list); } list.add(record); } int index = 0; for (long date : recordMap.keySet()){ ArrayList list = recordMap.get(date); PlotComparisonItem item = new PlotComparisonItem(this.getDateAsDayString(date), this.getColor(index), (double) date, (double)list.size()); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s1.getValue1().compareTo(s2.getValue1()); } }); return plotItems; } public ArrayList attacksPerTime(){ ArrayList plotItems = new ArrayList(); HashMap > recordMap = new HashMap >(); for (Record record : this.getFetchedRecords()){ long date = this.getDayHourFromDate(record.getTimestamp()); ArrayList list = recordMap.get(date); if (list == null){ list = new ArrayList(); recordMap.put(date, list); } list.add(record); } int index = 0; for (long time : recordMap.keySet()){ ArrayList list = recordMap.get(time); PlotComparisonItem item = new PlotComparisonItem(this.getDateAsTimeString(time), this.getColor(index) , (double)time, (double) list.size()); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s1.getValue1().compareTo(s2.getValue1()); } }); return plotItems; } // BAR PLOT DATA public ArrayList attacksPerBSSID(String protocol){ LogFilter filter = new LogFilter(); 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 = recordMap.get(record.getBssid()); count++; recordMap.put(record.getBssid(), count); } int index = 0; for (String key : recordMap.keySet()){ PlotComparisonItem item = new PlotComparisonItem(key, this.getColor(index), 0., (double)recordMap.get(key)); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s1.getValue2().compareTo(s2.getValue2()); } }); return this.resizeData(plotItems); } public ArrayList attacksPerESSID(String protocol){ LogFilter filter = new LogFilter(); 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 = recordMap.get(record.getSsid()); count++; recordMap.put(record.getSsid(), count); } int index = 0; for (String key : recordMap.keySet()){ PlotComparisonItem item = new PlotComparisonItem(key,this.getColor(index), 0. , (double)recordMap.get(key)); plotItems.add(item); index++; } Collections.sort(plotItems, new Comparator() { @Override public int compare(PlotComparisonItem s1, PlotComparisonItem s2) { return s1.getValue2().compareTo(s2.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); return copy; } } return plotItems; } /* * FILTER STUFF * */ 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,0,0,0); } public ArrayList getColorList(){ if (this.colorList == null){ this.colorList = new ArrayList(); 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 (this.colorList == null) this.colorList = new ArrayList(); 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) - ((Math.max(0,(a ))) * 16), 0); int G = Math.max( (g[n] * 255) - ((Math.max(0,(a ))) * 16), 0); int B = Math.max( (b[n] * 255) - ((Math.max(0,(a ))) * 16), 0); return Color.argb(255,R,G,B); } 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"; } } /** * USERINTERACTION */ private void userTappedOnItem(int index){ if (index < this.currentData.size()){ PlotComparisonItem item = this.currentData.get(index); ArrayList selectedData; 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){ // TODO set data for BSSID / ESSID } if (this.currentPlotView instanceof LineGraph){ // TODO set data for BSSID / ESSID } } } private void pushRecordOverviewForFilter(LogFilter filter){ } }