-
Notifications
You must be signed in to change notification settings - Fork 0
/
stats.py
171 lines (142 loc) · 4.62 KB
/
stats.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
""" This file contains code for generating statistics from raw data. """
import time
from lists import *
from numbers import *
from strings import *
def isBad(app):
""" Checks if an app contains a code which bypasses proper verification.
Arguments:
app -- dictionary with meta data of the app to check
Returns:
True if the app contains bad code, otherwise False
"""
properties = ['insecure_factories','allow_all_hostname_verifiers']
return anyMoreThanOne(app,properties)
def isNaive(app):
""" Checks if an app contains a custom verifier which is naive.
Arguments:
app -- dictionary with meta data of the app to check
Returns:
True if the app contains naive verifiers, otherwise False
"""
properties = ['naive_trustmanagers','naive_hostname_verifiers']
return anyMoreThanOne(app,properties)
def isCustom(app):
""" Checks if an app contains a custom verifier.
Arguments:
app -- dictionary with meta data of the app to check
Returns:
True if the app contains a custom verifier, otherwise False
"""
properties = ['trustmanagers','custom_hostname_verifiers']
return anyMoreThanOne(app,properties)
def isNative(app):
""" Checks if an app does not contain any custom verifiers or verification bypassing.
Arguments:
app -- dictionary with meta data of the app to check
Returns:
True if the app contains a no customization to cert verification, otherwise False
"""
return (not isCustom(app) and not isBad(app))
def initStats(stats):
""" Initialize a dictionary of statistics. """
fields = ['total', 'internet', 'trustmanagers', 'naive_trustmanagers',
'insecure_factories','custom_hostname_verifiers','naive_hostname_verifiers',
'allow_all_hostname_verifiers','ssl_error_handlers','unchecked','native', 'custom', 'naive', 'bad']
for field in fields:
if not field in stats:
stats[field] = 0
def fillStats(app, meta, stats):
""" Add an app into a collection of statistics.
Arguments:
app -- app doc ID
meta -- meta data for app
stats -- dictionary with statistics
"""
initStats(stats)
stats['total'] += 1
if meta['internet']:
stats['internet'] += 1
if moreThanOne(meta, 'trustmanagers'):
stats['trustmanagers'] += 1
if moreThanOne(meta, 'naive_trustmanagers'):
stats['naive_trustmanagers'] += 1
if moreThanOne(meta, 'insecure_factories'):
stats['insecure_factories'] += 1
if moreThanOne(meta, 'custom_hostname_verifiers'):
stats['custom_hostname_verifiers'] += 1
if moreThanOne(meta, 'naive_hostname_verifiers'):
stats['naive_hostname_verifiers'] += 1
if moreThanOne(meta, 'allow_all_hostname_verifiers'):
stats['allow_all_hostname_verifiers'] += 1
if moreThanOne(meta, 'ssl_error_handlers'):
stats['ssl_error_handlers'] += 1
if not 'trustmanagers' in meta:
stats['unchecked'] += 1
else:
if isBad(meta):
stats['bad'] += 1
elif isNaive(meta):
stats['naive'] += 1
elif isCustom(meta):
stats['custom'] += 1
else:
stats['native'] += 1
def calculateStatistics(apps):
""" Calculates the statistics of apps.
Arguments:
apps -- A dictionary with apps their meta data
Returns:
A dictionary with statistics:
- categories: statistics per category
- downloads: statistics per range of downloads
- ratings: statistics per rating
- years: statistics per year of release
- total: a summary
"""
categories = {}
total = {}
downloads = {'0-100':{}, '100-10,000':{}, '10,000-1,000,000':{}, '1,000,000-100,000,000':{}, '100,000,000+':{}}
years = {'Unknown':{},'2008':{},'2009':{},'2010':{},'2011':{},'2012':{},'2013':{}}
ratings = {'Unknown':{},'0-1':{},'1-2':{},'2-3':{},'3-4':{},'4-5':{}}
# init some dictionaries
for download in downloads:
initStats(downloads[download])
for year in years:
initStats(years[year])
for rating in ratings:
initStats(ratings[rating])
for app,meta in apps.iteritems():
_d = "{:,}+".format(int(meta['downloads']))
_t = meta['title']
_a = meta['creator']
try:
_a = meta['creator'].encode('utf-8')
except:
None
try:
_t = meta['title'].encode('utf-8')
except:
None
# total
fillStats(app, meta, total)
# year
year = time.strftime("%Y", meta['date']) if meta['date'] else 'Unknown'
fillStats(app, meta, years[year])
# rating
fillStats(app, meta, ratings[ratingRange(meta)])
# downloads
fillStats(app, meta, downloads[downloadRange(meta)])
# categories
for cat in meta['categories']:
category = cat[0]
if not category in categories:
categories[category] = {}
fillStats(app, meta, categories[category])
return {
'categories':categories,
'downloads':downloads,
'years':years,
'ratings':ratings,
'total':total
}