tor_extend 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/Change.log +12 -0
  2. data/ReadME.txt +190 -0
  3. data/doc/ReadME_txt.html +301 -0
  4. data/doc/Tor.html +140 -0
  5. data/doc/Tor/Bridge.html +145 -0
  6. data/doc/Tor/CachedDesc.html +472 -0
  7. data/doc/Tor/Constants.html +185 -0
  8. data/doc/Tor/Router.html +146 -0
  9. data/doc/Tor/StatsObj.html +1209 -0
  10. data/doc/Tor/TController.html +1111 -0
  11. data/doc/created.rid +7 -0
  12. data/doc/images/add.png +0 -0
  13. data/doc/images/brick.png +0 -0
  14. data/doc/images/brick_link.png +0 -0
  15. data/doc/images/bug.png +0 -0
  16. data/doc/images/bullet_black.png +0 -0
  17. data/doc/images/bullet_toggle_minus.png +0 -0
  18. data/doc/images/bullet_toggle_plus.png +0 -0
  19. data/doc/images/date.png +0 -0
  20. data/doc/images/delete.png +0 -0
  21. data/doc/images/find.png +0 -0
  22. data/doc/images/loadingAnimation.gif +0 -0
  23. data/doc/images/macFFBgHack.png +0 -0
  24. data/doc/images/package.png +0 -0
  25. data/doc/images/page_green.png +0 -0
  26. data/doc/images/page_white_text.png +0 -0
  27. data/doc/images/page_white_width.png +0 -0
  28. data/doc/images/plugin.png +0 -0
  29. data/doc/images/ruby.png +0 -0
  30. data/doc/images/tag_blue.png +0 -0
  31. data/doc/images/tag_green.png +0 -0
  32. data/doc/images/transparent.png +0 -0
  33. data/doc/images/wrench.png +0 -0
  34. data/doc/images/wrench_orange.png +0 -0
  35. data/doc/images/zoom.png +0 -0
  36. data/doc/index.html +90 -0
  37. data/doc/js/darkfish.js +153 -0
  38. data/doc/js/jquery.js +18 -0
  39. data/doc/js/navigation.js +142 -0
  40. data/doc/js/search.js +94 -0
  41. data/doc/js/search_index.js +1 -0
  42. data/doc/js/searcher.js +228 -0
  43. data/doc/lib/constants_rb.html +96 -0
  44. data/doc/lib/httpmod_rb.html +95 -0
  45. data/doc/lib/tcontroller_rb.html +93 -0
  46. data/doc/lib/tor_extend_rb.html +97 -0
  47. data/doc/lib/tstats_rb.html +93 -0
  48. data/doc/rdoc.css +543 -0
  49. data/doc/table_of_contents.html +159 -0
  50. data/lib/constants.rb +106 -0
  51. data/lib/httpmod.rb +89 -0
  52. data/lib/tcontroller.rb +475 -0
  53. data/lib/tor_extend.rb +189 -0
  54. data/lib/tstats.rb +514 -0
  55. data/tor_extend.gemspec +26 -0
  56. metadata +138 -0
@@ -0,0 +1,189 @@
1
+ # tor_extend library
2
+ # Author: Oluwaseun Remi-Omosowon (mailto:remi-omosowon@et.esiea-ouest.fr)
3
+ # Copyright: ...2011
4
+
5
+
6
+ # Tor includes the TController class, which inherits the methods from Bendiken's page[http://cypherpunk.rubyforge.org/tor/] Tor::Controller class and extends it with more methods.
7
+ # You are responsible for how you use the code. See the Unlicence in Bendiken's tor-ruby gem.
8
+ #
9
+ module Tor
10
+ require 'tor'
11
+ require 'active_record'
12
+ require 'builder'
13
+ require 'geoip'
14
+ require 'net/https'
15
+
16
+ # Tor::Constants module is loaded from constants.rb and other classes from seperate files
17
+ autoload :Constants, 'constants'
18
+ require 'tcontroller'
19
+ require 'tstats'
20
+ require 'httpmod'
21
+
22
+ # Tor::Router is a class for the active record database holding the ip-addresses, platform, fingerprint, country, latitude,longitude.
23
+ #
24
+ # <b>Transforming IP address to fingerprint</b>
25
+ # Tor::Router.where(:ipaddr=>"ipaddr")[0].fingerprint
26
+ #
27
+ class Router < ActiveRecord::Base
28
+ end
29
+
30
+ # Tor::Bridge is a class for the active record database holding the ip-addresses and port for the bridges discovered using the Tor::TController.getbridges.
31
+ #
32
+ # <b>Show all Bridges in the database</b>
33
+ # Tor::Bridge.all
34
+ #
35
+ class Bridge < ActiveRecord::Base
36
+ end
37
+
38
+ # Tor::CachedDesc is a class used to read cached descriptors into a database. The ip address, fingerprint, platform, country, latitude and longitude.
39
+ #
40
+ # @example Create database and read cached desciptor into it
41
+ # cached_descriptor = Tor::CachedDesc.new
42
+ # Tor::CachedDesc.dbconnect
43
+ # Tor::CachedDesc.dbconnect( { :adapter => "sqlite3",:database => "db.sqlite3"} )
44
+ # Tor::CachedDesc.readall("cached_descriptor_filename")
45
+ # Tor::CachedDesc.ors
46
+ # Tor::CachedDesc.ors.all
47
+ #
48
+ class CachedDesc
49
+
50
+
51
+ # This initialises the stat attribute of the CachedDesc class that can be used to get data from Tor::Router
52
+ #
53
+ def initialize(geoip_path)
54
+ @stat = StatsObj.new
55
+ # Tor::CachedDesc#geoipdb is an instance of GeoIP with the active database
56
+ @geoipdb = GeoIP.new(geoip_path[0])
57
+ # Tor::CachedDesc#geoipdb2 acts as a backup if records are not present in Tor::CachedDesc#geoipdb
58
+ @geoipdb2 = GeoIP.new(geoip_path[1])
59
+ end
60
+
61
+ # This initialises the stat attribute of the CachedDesc class that can be used to get data from Tor::Router
62
+ # It returns a Tor::StatsObj
63
+ #
64
+ def stat
65
+ @stat
66
+ end
67
+
68
+ # Tor::dbconnect() method connects using the optional database config passed as argument. It creates an sqlite3 file by default called db.sqlite3, and a table called routers.
69
+ # A table called routers is created in an existing database if it does not already exist.
70
+ #
71
+ # <b>Connecting to a database</b>
72
+ # Tor::CachedDesc.dbconnect
73
+ # Tor::CachedDesc.dbconnect( {:adapter => "sqlite3",:database => "db_name_here"} )
74
+ #
75
+ def dbconnect(*dbconfig)
76
+ dbconfig = [{:adapter => "sqlite3",:database => "db.sqlite3"}] if dbconfig.empty?
77
+ ActiveRecord::Base.establish_connection(dbconfig[0])
78
+ if !ActiveRecord::Base.connection.table_exists?('routers')
79
+ ActiveRecord::Schema.define do
80
+ create_table :routers do |t|
81
+ t.string :ipaddr
82
+ t.text :platform
83
+ t.string :fingerprint
84
+ t.string :city
85
+ t.string :country
86
+ t.string :country_code
87
+ t.string :continent
88
+ t.decimal :lat
89
+ t.decimal :lng
90
+ t.datetime :published_at
91
+ t.timestamps
92
+ end
93
+ create_table :bridges do |t|
94
+ t.string :ipaddr
95
+ t.integer :port
96
+ t.decimal :lat
97
+ t.decimal :lng
98
+ t.timestamps
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ # Returns the Router database class. Allows interation with the database as an instance of Active::Base if you know what you're doing.
105
+ #
106
+ # Display on ORs in the database.
107
+ # Cacheddec.or.all
108
+ #
109
+ def ors
110
+ Router
111
+ end
112
+
113
+
114
+ # This returns the Geoip record from one of the database files used in Tor::CachedDesc.
115
+ #
116
+ def get_geoiprecord(ipaddr)
117
+ or_geoip=@geoipdb.city(ipaddr)
118
+ or_geoip=@geoipdb2.city(ipaddr) if or_geoip==nil
119
+ or_geoip
120
+ end
121
+
122
+
123
+ # Read a file and put all the ralated information into the Tor::Router database.
124
+ #
125
+ def readall(filename)
126
+ cacheddesc = File.new(filename,'r:ISO-8859-1')
127
+ loopbreaker=false
128
+
129
+ until loopbreaker==true
130
+ fileline = cacheddesc.gets
131
+ fileline.chomp! if fileline != nil
132
+ case fileline
133
+ when /^published /
134
+ time_published = Time.parse fileline.sub("published ",'') # downloaded_at
135
+ when /^router /
136
+ or_ipaddr = fileline.scan(/\d+\.\d+\.\d+.\d+/)[0]
137
+ when /^platform /
138
+ case fileline
139
+ when /Windows/i
140
+ osplatform ="WINDOWS"
141
+ when /SunOS/i
142
+ osplatform ="SUN"
143
+ when /Linux/i,/Ubuntu/i
144
+ osplatform ="LINUX"
145
+ when /Unix/i, /BSD/i,/DragonFly/i,/Darwin/i
146
+ osplatform ="UNIX"
147
+ else
148
+ osplatform ="OTHER"
149
+ end
150
+
151
+ when /^opt fingerprint /
152
+ or_fingerprint=fileline.split("opt fingerprint ")[1].split.join # the fingerprint
153
+ # puts or_ipaddr
154
+ or_geoip=@geoipdb.city(or_ipaddr)
155
+ or_geoip=@geoipdb2.city(or_ipaddr) if or_geoip==nil # noticed that the august database returns nil for an address like 208.64.240.182, and smaller in size than July
156
+ if or_geoip.nil?
157
+ puts "#{or_ipaddr} not found in both geoip databases, try get an updated one, or older one."
158
+ else
159
+ or_city = or_geoip.city_name
160
+ or_country = or_geoip.country_name
161
+ orcountry_code = or_geoip.country_code2
162
+ orcontinent = or_geoip.continent_code
163
+ lng = or_geoip.longitude.to_f
164
+ lat = or_geoip.latitude.to_f
165
+ tmpr = Router.where(:ipaddr=>or_ipaddr).first
166
+ if tmpr.nil?
167
+ Router.create(:ipaddr=>or_ipaddr, :fingerprint=>or_fingerprint, :lat=>lat, :lng=>lng, :platform=>osplatform, :city=>or_city,
168
+ :country=>or_country, :continent=>orcontinent,:country_code=>orcountry_code,
169
+ :published_at=>time_published)
170
+ elsif time_published > tmpr.published_at
171
+ tmpr.fingerprint = or_fingerprint # Update fingerprint - Make sure you read newer files last
172
+ tmpr.lat = lat
173
+ tmpr.lng = lng
174
+ tmpr.platform=osplatform
175
+ tmpr.country=or_country
176
+ tmpr.save
177
+ end
178
+ end # if orgeoip.nil?
179
+ when nil
180
+ # gets returns nil for EOF
181
+ loopbreaker=true
182
+ cacheddesc.close
183
+ end
184
+ end # end of read file until eof
185
+
186
+ end
187
+ end
188
+
189
+ end # end of module
@@ -0,0 +1,514 @@
1
+ module Tor
2
+
3
+ # This class can be used to obtain a variety of statistics or data from Tor::Router.
4
+ # The same user have multiple IP addresses on different days, but the fingerprint might not change, especially not withing a month. Use uniq stats when available.
5
+ #
6
+ class StatsObj
7
+
8
+ # This returns a list of all countries that have contributed to the OR IP addresses in Tor::Router
9
+ # It can return only the those that have contributed to a particular platform
10
+ #
11
+ # @example Get Countries the that use Unix
12
+ # Tor::StatsObj.country_list
13
+ # Tor::StatsObj.country_list("UNIX")
14
+ # Tor::StatsObj.country_list( ["UNIX", "LINUX"] )
15
+ #
16
+ def country_list(*platform)
17
+ tmpresult = (platform.empty? or platform == ["ALL"]) ? Router.all : Router.where(:platform=>platform)
18
+ tmpresult.group_by{|c| c.country_code}.keys
19
+ end
20
+
21
+ # This returns a list of all continents that have contributed to the OR IP addresses in Tor::Router
22
+ # It can return only the those that have contributed to a particular platform
23
+ #
24
+ # @example Get Countries the that use Unix
25
+ # Tor::StatsObj.continent_list
26
+ # Tor::StatsObj.continent_list("UNIX")
27
+ # Tor::StatsObj.continent_list( ["UNIX", "LINUX"] )
28
+ #
29
+ def continent_list(*platform)
30
+ tmpresult = (platform.empty? or platform == ["ALL"]) ? Router.all : Router.where(:platform=>platform)
31
+ tmpresult.group_by{|c| c.continent}.keys
32
+ end
33
+
34
+ # This returns the number of OR IP addresses from the country with the code used as input (and optionally platform parameter).
35
+ #
36
+ # @example Get number of OR IP addr from continents
37
+ # Tor::StatsObj.country_count("FR")
38
+ # Tor::StatsObj.country_count("FR","UNIX")
39
+ # Tor::StatsObj.country_count( ["FR","DE"] ,[ "UNIX", "LINUX" ] )
40
+ #
41
+ def country_count(code,*platform)
42
+ rslt = (platform.empty? or platform == ["ALL"] ) ?
43
+ Router.where(:country_code=>code) :
44
+ Router.where(:country_code=>code,:platform=>platform)
45
+ rslt.count
46
+ end
47
+
48
+ # This returns the total number of uniq identities found in the database.
49
+ #
50
+ # <b>Get total number of routers in countries<b>.
51
+ # Tor::StatsObj.country_count_uniq(["GB","FR"])
52
+ # Tor::StatsObj.country_count_uniq("FR","WINDOWS")
53
+ # Tor::StatsObj.country_count_uniq(["GB","FR",DE],["UNIX",LINUX"] )
54
+ #
55
+ def country_count_uniq(countryfilter,*platform)
56
+ get_uniqid(countryfilter,*platform).count
57
+ end
58
+
59
+
60
+ # This returns the number of OR IP addresses from the continent with the code used as input (and optionally platform parameter).
61
+ #
62
+ # @example Get number of OR IP addr from continents
63
+ # Tor::StatsObj.continent_count("EU")
64
+ # Tor::StatsObj.continent_count("NA","UNIX")
65
+ # Tor::StatsObj.continent_count( ["EU","NA","SA"] ,[ "UNIX", "LINUX" ] )
66
+ #
67
+ def continent_count(code,*platform)
68
+ rslt = (platform.empty? or platform == ["ALL"] ) ? Router.where(:continent=>code) : Router.where(:continent=>code, :platform=>platform)
69
+ rslt.count # continent code "AF","EU","AS","NA","SA","OC"
70
+ end
71
+
72
+ # This returns the number of OR IP addresses from the continent with the code used as input (and optionally platform parameter).
73
+ #
74
+ # @example Get number of OR IP addr from continents
75
+ # Tor::StatsObj.continent_count("EU")
76
+ # Tor::StatsObj.continent_count("NA","UNIX")
77
+ # Tor::StatsObj.continent_count( ["EU","NA","SA"] ,[ "UNIX", "LINUX" ] )
78
+ #
79
+ def continent_count_uniq(code,*platform)
80
+ rslt = (platform.empty? or platform == ["ALL"] ) ?
81
+ Router.where(:id=> get_uniqid(country_list, *platform), :continent=>code) :
82
+ Router.where(:id=> get_uniqid(country_list, *platform), :continent=>code, :platform=>platform)
83
+ rslt.count # continent code "AF","EU","AS","NA","SA","OC"
84
+ end
85
+
86
+
87
+ # It takes an array of country codes as input, and produces a hash with the country codes as keys and the total number of ors from the country as value.
88
+ # An optional platform can also be set.
89
+ #
90
+ # @example Get country statistics
91
+ # Tor::StatsObj.country_stat(["EU","NA","SA"]) => {"EU" => country,total, .... "SA" => country,total }
92
+ # Tor::StatsObj.country_stat(["EU","NA","SA"], "LINUX")
93
+ # Tor::StatsObj.country_stat( Tor::StatsObj.country_list )
94
+ # Tor::StatsObj.country_stat( Tor::StatsObj.country_list(platform) )
95
+ #
96
+ # Note: Results of Tor::StatsObj.country_list can be used as argument for this Tor::StatsObj.country_stat.
97
+ #
98
+ def country_stat(countrycodes,*platform)
99
+ country_count_hash={}
100
+ if countrycodes.class==String
101
+ country_count_hash[countrycodes] = country_count(countrycodes,*platform)
102
+ else
103
+ countrycodes.each{|each_country| country_count_hash[each_country] = country_count(each_country,*platform)}
104
+ end
105
+ country_count_hash
106
+ end
107
+
108
+ # This retuns an array of all OR IP addresses from the Tor::Router using a filter of countries and optional platform parameter.
109
+ #
110
+ # @example Get all OR IP addresses from France
111
+ # Tor::StatsObj.country_getip("FR")
112
+ # Tor::StatsObj.country_getip(["FR",GB"], "WINDOWS")
113
+ # Tor::StatsObj.country_getip(["FR",GB"], ["WINDOWS", "LINUX"] )
114
+ #
115
+ def country_getip(country_filter,*platform)
116
+ if platform.empty? or platform == ["ALL"]
117
+ onionr = Router.where(:country_code=>country_filter)
118
+ else
119
+ onionr=Router.where(:country_code=>country_filter,:platform=>platform )
120
+ end
121
+ onion_ipaddr=onionr.collect{|each_country| each_country.ipaddr}
122
+ end
123
+
124
+ # This retuns an array of all OR fingerprints from the Tor::Router using a filter of countries and optional platform parameter.
125
+ #
126
+ # @example Get all OR IP fingerprints from France
127
+ # Tor::StatsObj.country_getingerprint("FR")
128
+ # Tor::StatsObj.country_getingerprint(["FR",GB"], "WINDOWS")
129
+ # Tor::StatsObj.country_getingerprint(["FR",GB"], ["WINDOWS", "LINUX"] )
130
+ #
131
+ def country_getfingerprint(country_filter,*platform)
132
+ if platform.empty? or platform == ["ALL"]
133
+ onionr = Router.where(:country_code=>country_filter)
134
+ else
135
+ onionr=Router.where(:country_code=>country_filter,:platform=>platform )
136
+ end
137
+ onion_ipaddr = onionr.collect{|each_country| each_country.fingerprint}
138
+ end
139
+
140
+ # This retuns an array of all OR fingerprints from Tor::Router using a filter of continents and optional platform parameter.
141
+ #
142
+ # @example Get all OR IP fingerprints from France
143
+ # Tor::StatsObj.continent_getfingerprint("EU")
144
+ # Tor::StatsObj.continent_getfingerprint(["AF",EU"], "WINDOWS")
145
+ # Tor::StatsObj.continent_getfingerprint(["NA","SA"], ["WINDOWS", "LINUX"] )
146
+ #
147
+ def continent_getfingerprint(continent_filter,*platform)
148
+ if platform.empty? or platform == ["ALL"]
149
+ onionr = Router.where(:continent=>continent_filter,:id=>get_uniqid(countryfilter,*platform))
150
+ else
151
+ onionr=Router.where(:continent=>continent_filter,:platform=>platform ,:id=>get_uniqid(countryfilter,*platform))
152
+ end
153
+ onion_ipaddr = onionr.collect{|each_country| each_country.fingerprint}
154
+ end
155
+
156
+ # It takes an array of country codes as input, and produces a hash with the country codes as keys and the total number of unique ors from the country as value.
157
+ # An optional platform can also be set.
158
+ #
159
+ # @example Get country statistics
160
+ # Tor::StatsObj.country_stat_uniq(["FR","GB","US"]) => {"FR" => total, .... "US" => total }
161
+ # Tor::StatsObj.country_stat_uniq([DE","FR"], "LINUX")
162
+ # Tor::StatsObj.country_stat_uniq( Tor::StatsObj.country_list )
163
+ # Tor::StatsObj.country_stat_uniq( Tor::StatsObj.country_list(platform) )
164
+ #
165
+ # Note: Results of Tor::StatsObj.country_list can be used as argument for this Tor::StatsObj.country_stat_uniq.
166
+ #
167
+ def country_stat_uniq(countrycodes,*platform)
168
+ # get_uniqid can be used for this, but this that will involve more calls to Tor::Router than necessary
169
+ country_count_hash={}
170
+ if countrycodes.class==String
171
+ country_count_hash[countrycodes] = country_count_uniq(countrycodes,*platform)
172
+ else
173
+ countrycodes.each{|each_country|
174
+ country_count_hash[each_country] = country_count_uniq(each_country,*platform) }
175
+ end
176
+ country_count_hash
177
+ end
178
+
179
+ # It takes an array of continent codes as input, and produces a hash with the continent codes as keys and the total number of ors from the country as value
180
+ #
181
+ # @example Get continents statistics
182
+ # Tor::StatsObj.continent_stat(["EU","NA","SA"]) => {"EU" => total, .... "SA" => total }
183
+ # Tor::StatsObj.continent_stat(["EU","NA","SA"], "LINUX")
184
+ # Tor::StatsObj.continent_stat( Tor::StatsObj.country_list )
185
+ #
186
+ # Note: Results of Tor::StatsObj.continent_list can be used as argument for this Tor::StatsObj.continent_stat.
187
+ #
188
+ def continent_stat(allcontinents,*platform)
189
+ continent_count_hash={}
190
+ if allcontinents.class==String
191
+ continent_count_hash[allcontinents] = continent_count(allcontinents,*platform)
192
+ else
193
+ allcontinents.each{|each_continent|
194
+ continent_count_hash[each_continent] = continent_count(each_continent,*platform)
195
+ }
196
+ end
197
+ continent_count_hash
198
+ end
199
+
200
+ # It takes an array of continent codes as input, and produces a hash with the continent codes as keys and the total number of ors from the country as value
201
+ #
202
+ # @example Get continents statistics
203
+ # Tor::StatsObj.continent_stat_uniq(["EU","NA","SA"]) => {"EU" => total, .... "SA" => total }
204
+ # Tor::StatsObj.continent_stat_uniq(["EU","NA","SA"], "LINUX")
205
+ # Tor::StatsObj.continent_stat_uniq( Tor::StatsObj.country_list )
206
+ #
207
+ # Note: Results of Tor::StatsObj.continent_list can be used as argument for this Tor::StatsObj.continent_stat_uniq.
208
+ #
209
+ def continent_stat_uniq(allcontinents,*platform)
210
+ continent_count_hash={}
211
+ if allcontinents.class==String
212
+ continent_count_hash[allcontinents] = continent_count_uniq(allcontinents,*platform)
213
+ else
214
+ allcontinents.each{|each_continent|
215
+ continent_count_hash[each_continent] = continent_count_uniq(each_continent,*platform)
216
+ }
217
+ end
218
+ continent_count_hash
219
+ end
220
+
221
+ # This returns the top n-countries. An optional platform parameter can be passed to this
222
+ # and returns an array of countries and total
223
+ #
224
+ # @example Top n-countries
225
+ # Tor::StatsObj.topcountries(n) => [[country,total]....[country,total]]
226
+ # Tor::StatsObj.topcountries(n, "UNIX")
227
+ # Tor::StatsObj.topcountries(n, ["UNIX","LINUX"])
228
+ #
229
+ def topcountries(num,*platform)
230
+ countryarray = country_list(*platform)
231
+ top_countries = country_stat(countryarray,*platform).sort_by{|k,v| v}
232
+ result = (num==0) ? top_countries.reverse : top_countries.last(num).reverse
233
+ end
234
+
235
+ # This returns the top n-countries. An optional platform parameter can be passed to this
236
+ # and returns an array of countries and total
237
+ #
238
+ # @example Top n-countries
239
+ # Tor::StatsObj.topcountries_uniq(n) => [[country,total]....[country,total]]
240
+ # Tor::StatsObj.topcountries_uniq(n, "UNIX")
241
+ # Tor::StatsObj.topcountries_uniq(n, ["UNIX","LINUX"])
242
+ #
243
+ def topcountries_uniq(num,*platform)
244
+ countryarray = country_list(*platform)
245
+ top_countries = country_stat_uniq(countryarray,*platform).sort_by{|k,v| v}
246
+ result = (num==0) ? top_countries.reverse : top_countries.last(num).reverse
247
+ end
248
+
249
+ # This returns the country name from the country code.
250
+ #
251
+ # @example Get country name from country code
252
+ # Tor::StatsObj.get_countryname("FR")
253
+ #
254
+ def get_countryname(ccode)
255
+ x=Router.where(:country_code=>ccode).first
256
+ (x.nil?) ? nil : x.country
257
+ end
258
+
259
+ # This returns the [latitude,longitude] from the country code. Using the constant Tor::Constants::COUNLATLNG,
260
+ # or alternatively if Tor::COUNLATLNG has been defined in a program.
261
+ #
262
+ def get_latlng(country_code)
263
+ countrylatlng = Constants::COUNLATLNG
264
+ if (defined? COUNLATLNG)
265
+ if (COUNLATLNG.keys.include? country_code)
266
+ lat= COUNLATLNG[country_code][:lat]
267
+ lng= COUNLATLNG[country_code][:lng]
268
+ end
269
+ elsif countrylatlng.keys.include? country_code
270
+ lat=countrylatlng[country_code][:lat]
271
+ lng=countrylatlng[country_code][:lng]
272
+ else
273
+ puts "#{country_code}, #{get_countryname(country_code)} - not in the country-latitude file, using cordinates(0,0)"
274
+ lat=0.0
275
+ lng=0.0
276
+ end
277
+ [lat,lng]
278
+ end
279
+
280
+
281
+ # This returns the id of uniq identities in the database
282
+ #
283
+ # @example Get Uniq id of ORs in the UK
284
+ #
285
+ # Tor::Stats.Obj.get_uniqid("GB")
286
+ # Tor::Stats.Obj.get_uniqid("GB","WINDOWS")
287
+ # Tor::Stats.Obj.get_uniqid(["GB","FR",DE"] , ["UNIX","LINUX"])
288
+ #
289
+ def get_uniqid(countryfilter,*platform)
290
+ if platform.empty? or platform==["ALL"] or platform==["All"]
291
+ torlocations = Router.where(:country_code=>countryfilter)
292
+ else
293
+ torlocations = Router.where(:platform=>platform,:country_code=>countryfilter)
294
+ end
295
+ identitygroup = torlocations.group_by{|c| c.fingerprint}
296
+ idarray = identitygroup.keys.collect{|eachidentitykey|
297
+ #Collect just the id of the most recent location of the fingerprint
298
+ identitygroup[eachidentitykey].max{|a,b| a.published_at <=> b.published_at}.id
299
+ }
300
+ end
301
+
302
+ # This method generates a KML using the locations in Tor::Router database.
303
+ # It takes a name for the KML document as input, and an optional platform parameter.
304
+ #
305
+ # @example Generate KML file
306
+ # Tor::StatsObj.genkml("KML doc name")
307
+ # Tor::StatsObj.genkml("KML platform name", ["WINDOWS","UNIX","LINUX", "OTHER"] )
308
+ # Tor::StatsObj.genkml("KML platform name", "LINUX" )
309
+ #
310
+ def genkml(mapname,*platform)
311
+ tour_hash= (defined? WORLDTOUR) ? WORLDTOUR : Constants::WORLDTOUR
312
+ attack_tour = (defined? ATTACK_TOUR) ? ATTACK_TOUR: Constants::ATTACK_TOUR
313
+
314
+ torcountry= topcountries_uniq(0,*platform) # collect{|country,count| country}
315
+ xml = Builder::XmlMarkup.new(:indent=>2)
316
+ xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
317
+ xml.kml("xmlns" => "http://www.opengis.net/kml/2.2",
318
+ "xmlns:gx"=>"http://www.google.com/kml/ext/2.2") do
319
+ y=1
320
+
321
+
322
+ xml.Document do
323
+ xml.name mapname
324
+
325
+ # define styles to use for placemarks and tour
326
+ xml.Style("id"=>"redplaces") do
327
+ xml.IconStyle do
328
+ xml.color "ff0000ff"
329
+ end
330
+ end
331
+ xml.Style("id"=>"greenplaces") do
332
+ xml.IconStyle do
333
+ xml.color "ff00ff00"
334
+ end
335
+ end
336
+ xml.Style("id"=>"blackplaces") do
337
+ xml.IconStyle do
338
+ xml.color "ff000000"
339
+ end
340
+ end
341
+ xml.Style("id"=>"blueplaces") do
342
+ xml.IconStyle do
343
+ xml.color "0000ff00"
344
+ end
345
+ end
346
+
347
+ xml.Folder("id"=>"torbridges") do
348
+ xml.name "Tor Bridges - #{Bridge.count}"
349
+ allbridges = Bridge.all
350
+ allbridges.each{|eachbridge|
351
+ brindex = 1 + allbridges.index(eachbridge)
352
+ placeid = "bridge#{brindex }"
353
+ xml.Placemark("id"=> placeid) do
354
+ xml.name "BR#{brindex.to_s}"
355
+ xml.description "#{eachbridge.ipaddr}:#{eachbridge.port}"
356
+ xml.styleUrl "#blueplaces"
357
+ xml.Point do
358
+ xml.extrude 1
359
+ xml.coordinates "#{eachbridge.lng},#{eachbridge.lat}"
360
+ end
361
+ end
362
+ }
363
+ end
364
+
365
+ # Google earth tour
366
+ xml.gx :Tour do
367
+ xml.name "Tor World"
368
+ xml.gx :Playlist do
369
+ tour_hash.keys.each{|each_centre|
370
+ xml.gx :FlyTo do
371
+ xml.gx :duration,1.0
372
+ xml.LookAt do
373
+ country_lat,country_lng= get_latlng(each_centre)
374
+ xml.longitude country_lng
375
+ xml.latitude country_lat
376
+ xml.range 4900000
377
+ end #end LookAt
378
+ end # end FlyTo
379
+
380
+
381
+ tour_hash[each_centre].each{|eachzone|
382
+ # toggle on
383
+ xml.gx :AnimatedUpdate do
384
+ xml.gx :duration,0.0
385
+ xml.Update do
386
+ xml.targetHref
387
+ xml.Change do
388
+ xml.Placemark("targetId"=> eachzone) do
389
+ xml.gx :balloonVisibility,1
390
+ end # end Placemark
391
+ end # end Change
392
+ end # end Update
393
+ end #end AnimatedUpdate
394
+ xml.gx :Wait do
395
+ xml.gx :duration,2.0
396
+ end
397
+
398
+ # toggle off
399
+ xml.gx :AnimatedUpdate do
400
+ xml.gx :duration,0.0
401
+ xml.Update do
402
+ xml.targetHref
403
+ xml.Change do
404
+ xml.Placemark("id"=> eachzone) do
405
+ xml.gx :balloonVisibility,0
406
+ end # end placemark
407
+ end # end Change
408
+ end # end Update
409
+ end # end AnimatedUpdate
410
+ xml.gx :Wait do
411
+ xml.gx :duration,2.0
412
+ end
413
+ } # eachzone
414
+ } #each_centre
415
+ end # end of gx:Playlist
416
+ end # end of gx:Tour
417
+
418
+
419
+ # Google earth attack tour
420
+ xml.gx :Tour do
421
+ xml.name "Tor - Attack"
422
+ xml.gx :Playlist do
423
+ xml.gx :FlyTo do
424
+ xml.gx :duration,1.0
425
+ xml.LookAt do
426
+ xml.longitude attack_tour[:lng]
427
+ xml.latitude attack_tour[:lat]
428
+ xml.range 2000000
429
+ end #end LookAt
430
+ end # end FlyTo
431
+
432
+
433
+ attack_tour["red"].each{|eachzone|
434
+ # toggle on
435
+ xml.gx :AnimatedUpdate do
436
+ xml.gx :duration,0.0
437
+ xml.Update do
438
+ xml.targetHref
439
+ xml.Change do
440
+ xml.Placemark("targetId"=> eachzone) do
441
+ xml.styleUrl "#redplaces"
442
+ end # end Placemark
443
+ end # end Change
444
+ end # end Update
445
+ end #end AnimatedUpdate
446
+ } # eachzone
447
+
448
+ attack_tour["black"].each{|eachzone|
449
+ # toggle on
450
+ xml.gx :AnimatedUpdate do
451
+ xml.gx :duration,2.0
452
+ xml.Update do
453
+ xml.targetHref
454
+ xml.Change do
455
+ xml.Placemark("targetId"=> eachzone) do
456
+ xml.styleUrl "#blackplaces"
457
+ end # end Placemark
458
+ end # end Change
459
+ end # end Update
460
+ end #end AnimatedUpdate
461
+ xml.gx :Wait do
462
+ xml.gx :duration,2.0
463
+ end
464
+ } # eachzone
465
+
466
+ end # end of gx:Playlist
467
+ end # end of gx:Tour
468
+
469
+ torcountry.each { |country_code,countrytotal|
470
+ countryname = get_countryname(country_code)
471
+ xml.Folder("id"=>country_code) do
472
+ xml.name "#{countryname}-#{countrytotal}"
473
+ xml.LookAt do
474
+ country_lat,country_lng = get_latlng(country_code)
475
+ xml.longitude country_lng
476
+ xml.latitude country_lat
477
+ xml.range 4500000
478
+ end
479
+ idarray = get_uniqid(country_code,*platform)
480
+ if platform.empty? or platform==["ALL"] or platform==["All"]
481
+ torlocations = Router.where(:id=>idarray,:country_code=>country_code)
482
+ else
483
+ torlocations = Router.where(:id=>idarray,:country_code=>country_code,:platform=>platform)
484
+ end
485
+ torplaces_sorted = torlocations.group_by{|c| [ c.lat, c.lng, c.country, c.city ] }.sort_by{|a,b| b.count}.reverse
486
+ torplaces_sorted.each{|lat_lng_country_city|
487
+ # Group by fingerprint here and get the size of the hash, and get the number of elements in the hash instead of get_uniqid
488
+ # but what if user is mobile? different isps, latitude-longitude, or lives the city or country
489
+ lat, lng, country, city = lat_lng_country_city[0]
490
+ pointtotal = lat_lng_country_city[1].count
491
+ placeid = "#{country_code}#{ 1 + torplaces_sorted.index(lat_lng_country_city)}"
492
+ xml.Placemark("id"=> placeid) do
493
+ strcount = (pointtotal == 1) ? 'OR' : 'ORs'
494
+ #xml.name "#{y}"
495
+ y += 1
496
+ kmlcity= (city.empty?) ? "#{country}" : "#{city}"
497
+ xml.description "#{pointtotal} #{strcount} in #{kmlcity} of #{countrytotal}(country total)"
498
+ xml.styleUrl "#greenplaces"
499
+ xml.Point do
500
+ xml.extrude 1
501
+ xml.coordinates "#{lng},#{lat}"
502
+ end
503
+ end
504
+ }
505
+ end
506
+ }
507
+ end
508
+ end
509
+ xml.target! #Return the xml file
510
+ end # end of genkml
511
+
512
+ end # end of class StatsObj
513
+
514
+ end