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,159 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
6
+
7
+ <title>Table of Contents</title>
8
+
9
+ <link type="text/css" media="screen" href="./rdoc.css" rel="stylesheet">
10
+
11
+ <script type="text/javascript">
12
+ var rdoc_rel_prefix = "./";
13
+ </script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="./js/jquery.js"></script>
16
+ <script type="text/javascript" charset="utf-8" src="./js/navigation.js"></script>
17
+ <script type="text/javascript" charset="utf-8" src="./js/search_index.js"></script>
18
+ <script type="text/javascript" charset="utf-8" src="./js/search.js"></script>
19
+ <script type="text/javascript" charset="utf-8" src="./js/searcher.js"></script>
20
+ <script type="text/javascript" charset="utf-8" src="./js/darkfish.js"></script>
21
+
22
+
23
+ <body class="indexpage">
24
+ <h1>Table of Contents</h1>
25
+
26
+ <h2>Pages</h2>
27
+ <ul>
28
+ <li class="file">
29
+ <a href="ReadME_txt.html">ReadME</a>
30
+ </li>
31
+
32
+ </ul>
33
+
34
+ <h2 id="classes">Classes/Modules</h2>
35
+ <ul>
36
+ <li class="module">
37
+ <a href="Tor.html">Tor</a>
38
+ </li>
39
+ <li class="class">
40
+ <a href="Tor/Bridge.html">Tor::Bridge</a>
41
+ </li>
42
+ <li class="class">
43
+ <a href="Tor/CachedDesc.html">Tor::CachedDesc</a>
44
+ </li>
45
+ <li class="module">
46
+ <a href="Tor/Constants.html">Tor::Constants</a>
47
+ </li>
48
+ <li class="class">
49
+ <a href="Tor/Router.html">Tor::Router</a>
50
+ </li>
51
+ <li class="class">
52
+ <a href="Tor/StatsObj.html">Tor::StatsObj</a>
53
+ </li>
54
+ <li class="class">
55
+ <a href="Tor/TController.html">Tor::TController</a>
56
+ </li>
57
+
58
+ </ul>
59
+
60
+ <h2 id="methods">Methods</h2>
61
+ <ul>
62
+
63
+ <li class="method"><a href="Tor/CachedDesc.html#method-c-new">::new &mdash; Tor::CachedDesc</a>
64
+
65
+ <li class="method"><a href="Tor/TController.html#method-i-attach_stream">#attach_stream &mdash; Tor::TController</a>
66
+
67
+ <li class="method"><a href="Tor/TController.html#method-i-bridges">#bridges &mdash; Tor::TController</a>
68
+
69
+ <li class="method"><a href="Tor/TController.html#method-i-cir_status">#cir_status &mdash; Tor::TController</a>
70
+
71
+ <li class="method"><a href="Tor/TController.html#method-i-closeallcircuits">#closeallcircuits &mdash; Tor::TController</a>
72
+
73
+ <li class="method"><a href="Tor/TController.html#method-i-closecircuit">#closecircuit &mdash; Tor::TController</a>
74
+
75
+ <li class="method"><a href="Tor/StatsObj.html#method-i-continent_count">#continent_count &mdash; Tor::StatsObj</a>
76
+
77
+ <li class="method"><a href="Tor/StatsObj.html#method-i-continent_count_uniq">#continent_count_uniq &mdash; Tor::StatsObj</a>
78
+
79
+ <li class="method"><a href="Tor/StatsObj.html#method-i-continent_getfingerprint">#continent_getfingerprint &mdash; Tor::StatsObj</a>
80
+
81
+ <li class="method"><a href="Tor/StatsObj.html#method-i-continent_list">#continent_list &mdash; Tor::StatsObj</a>
82
+
83
+ <li class="method"><a href="Tor/StatsObj.html#method-i-continent_stat">#continent_stat &mdash; Tor::StatsObj</a>
84
+
85
+ <li class="method"><a href="Tor/StatsObj.html#method-i-continent_stat_uniq">#continent_stat_uniq &mdash; Tor::StatsObj</a>
86
+
87
+ <li class="method"><a href="Tor/StatsObj.html#method-i-country_count">#country_count &mdash; Tor::StatsObj</a>
88
+
89
+ <li class="method"><a href="Tor/StatsObj.html#method-i-country_count_uniq">#country_count_uniq &mdash; Tor::StatsObj</a>
90
+
91
+ <li class="method"><a href="Tor/StatsObj.html#method-i-country_getfingerprint">#country_getfingerprint &mdash; Tor::StatsObj</a>
92
+
93
+ <li class="method"><a href="Tor/StatsObj.html#method-i-country_getip">#country_getip &mdash; Tor::StatsObj</a>
94
+
95
+ <li class="method"><a href="Tor/StatsObj.html#method-i-country_list">#country_list &mdash; Tor::StatsObj</a>
96
+
97
+ <li class="method"><a href="Tor/StatsObj.html#method-i-country_stat">#country_stat &mdash; Tor::StatsObj</a>
98
+
99
+ <li class="method"><a href="Tor/StatsObj.html#method-i-country_stat_uniq">#country_stat_uniq &mdash; Tor::StatsObj</a>
100
+
101
+ <li class="method"><a href="Tor/CachedDesc.html#method-i-dbconnect">#dbconnect &mdash; Tor::CachedDesc</a>
102
+
103
+ <li class="method"><a href="Tor/TController.html#method-i-ds">#ds &mdash; Tor::TController</a>
104
+
105
+ <li class="method"><a href="Tor/TController.html#method-i-extendcir">#extendcir &mdash; Tor::TController</a>
106
+
107
+ <li class="method"><a href="Tor/TController.html#method-i-extendcir_slowly">#extendcir_slowly &mdash; Tor::TController</a>
108
+
109
+ <li class="method"><a href="Tor/StatsObj.html#method-i-genkml">#genkml &mdash; Tor::StatsObj</a>
110
+
111
+ <li class="method"><a href="Tor/TController.html#method-i-get_bridges">#get_bridges &mdash; Tor::TController</a>
112
+
113
+ <li class="method"><a href="Tor/StatsObj.html#method-i-get_countryname">#get_countryname &mdash; Tor::StatsObj</a>
114
+
115
+ <li class="method"><a href="Tor/TController.html#method-i-get_entryguards">#get_entryguards &mdash; Tor::TController</a>
116
+
117
+ <li class="method"><a href="Tor/CachedDesc.html#method-i-get_geoiprecord">#get_geoiprecord &mdash; Tor::CachedDesc</a>
118
+
119
+ <li class="method"><a href="Tor/TController.html#method-i-get_httperrors">#get_httperrors &mdash; Tor::TController</a>
120
+
121
+ <li class="method"><a href="Tor/StatsObj.html#method-i-get_latlng">#get_latlng &mdash; Tor::StatsObj</a>
122
+
123
+ <li class="method"><a href="Tor/TController.html#method-i-get_purposeip">#get_purposeip &mdash; Tor::TController</a>
124
+
125
+ <li class="method"><a href="Tor/StatsObj.html#method-i-get_uniqid">#get_uniqid &mdash; Tor::StatsObj</a>
126
+
127
+ <li class="method"><a href="Tor/TController.html#method-i-getconf">#getconf &mdash; Tor::TController</a>
128
+
129
+ <li class="method"><a href="Tor/TController.html#method-i-getinfo">#getinfo &mdash; Tor::TController</a>
130
+
131
+ <li class="method"><a href="Tor/TController.html#method-i-net_status">#net_status &mdash; Tor::TController</a>
132
+
133
+ <li class="method"><a href="Tor/TController.html#method-i-newstreams">#newstreams &mdash; Tor::TController</a>
134
+
135
+ <li class="method"><a href="Tor/CachedDesc.html#method-i-ors">#ors &mdash; Tor::CachedDesc</a>
136
+
137
+ <li class="method"><a href="Tor/CachedDesc.html#method-i-readall">#readall &mdash; Tor::CachedDesc</a>
138
+
139
+ <li class="method"><a href="Tor/TController.html#method-i-setconf">#setconf &mdash; Tor::TController</a>
140
+
141
+ <li class="method"><a href="Tor/TController.html#method-i-signal">#signal &mdash; Tor::TController</a>
142
+
143
+ <li class="method"><a href="Tor/TController.html#method-i-sr">#sr &mdash; Tor::TController</a>
144
+
145
+ <li class="method"><a href="Tor/CachedDesc.html#method-i-stat">#stat &mdash; Tor::CachedDesc</a>
146
+
147
+ <li class="method"><a href="Tor/StatsObj.html#method-i-topcountries">#topcountries &mdash; Tor::StatsObj</a>
148
+
149
+ <li class="method"><a href="Tor/StatsObj.html#method-i-topcountries_uniq">#topcountries_uniq &mdash; Tor::StatsObj</a>
150
+
151
+ </ul>
152
+
153
+
154
+ <footer id="validator-badges">
155
+ <p><a href="http://validator.w3.org/check/referer">[Validate]</a>
156
+ <p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 3.11.
157
+ <p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
158
+ </footer>
159
+
@@ -0,0 +1,106 @@
1
+
2
+ # This module contains constants for the Tor module such as a COUNLATLNG
3
+ module Tor::Constants
4
+
5
+
6
+ # This maps the coordinates of each country to its country code.
7
+ #
8
+ # *Get* *Coordinates* *for* *countries*
9
+ # Tor::Constants::COUNLATLNG["FR"] =>{:lat=>46.0, :lng=>2.0}
10
+ # Tor::Constants::COUNLATLNG["GB"] =>{:lat=>54.0, :lng=>-2.0}
11
+ # Tor::Constants::COUNLATLNG["FR"][:lat] =>46.0
12
+ # Tor::Constants::COUNLATLNG["GB"][lng] =>-2.0
13
+ #
14
+ # A1 and A2 - anonymous proxies and satelite providers - added using cordinates (0,0)
15
+ # IM, AX, JE added from the CIA factbook, the others from the Maxmind page
16
+ # <b>NOTE:</b> See the following links for more details
17
+ # CIA Factbook online [https://www.cia.gov/library/publications/the-world-factbook/fields/2011.html]
18
+ # Maxmind(2007) - Average Latitude and longitude for countries [http://www.maxmind.com/app/country_latlon]
19
+ COUNLATLNG = {
20
+ "AD"=>{:lat=>42.5, :lng=>1.5}, "AE"=>{:lat=>24.0, :lng=>54.0}, "AF"=>{:lat=>33.0, :lng=>65.0}, "AG"=>{:lat=>17.05, :lng=>-61.8},"AI"=>{:lat=>18.25, :lng=>-63.1667},
21
+ "AL"=>{:lat=>41.0, :lng=>20.0}, "AM"=>{:lat=>40.0, :lng=>45.0},"AN"=>{:lat=>12.25, :lng=>-68.75}, "AO"=>{:lat=>-12.5, :lng=>18.5},
22
+ "AP"=>{:lat=>35.0, :lng=>105.0}, "AQ"=>{:lat=>-90.0, :lng=>0.0}, "AR"=>{:lat=>-34.0, :lng=>-64.0}, "AS"=>{:lat=>-14.3333, :lng=>-170.0},
23
+ "AT"=>{:lat=>47.3333, :lng=>13.3333}, "AU"=>{:lat=>-27.0, :lng=>133.0}, "AW"=>{:lat=>12.5, :lng=>-69.9667}, "AZ"=>{:lat=>40.5, :lng=>47.5},
24
+ "BA"=>{:lat=>44.0, :lng=>18.0}, "BB"=>{:lat=>13.1667, :lng=>-59.5333}, "BD"=>{:lat=>24.0, :lng=>90.0}, "BE"=>{:lat=>50.8333, :lng=>4.0},
25
+ "BF"=>{:lat=>13.0, :lng=>-2.0}, "BG"=>{:lat=>43.0, :lng=>25.0}, "BH"=>{:lat=>26.0, :lng=>50.55}, "BI"=>{:lat=>-3.5, :lng=>30.0},
26
+ "BJ"=>{:lat=>9.5, :lng=>2.25}, "BM"=>{:lat=>32.3333, :lng=>-64.75}, "BN"=>{:lat=>4.5, :lng=>114.6667}, "BO"=>{:lat=>-17.0, :lng=>-65.0},
27
+ "BR"=>{:lat=>-10.0, :lng=>-55.0}, "BS"=>{:lat=>24.25, :lng=>-76.0}, "BT"=>{:lat=>27.5, :lng=>90.5}, "BV"=>{:lat=>-54.4333, :lng=>3.4},
28
+ "BW"=>{:lat=>-22.0, :lng=>24.0}, "BY"=>{:lat=>53.0, :lng=>28.0}, "BZ"=>{:lat=>17.25, :lng=>-88.75}, "CA"=>{:lat=>60.0, :lng=>-95.0},
29
+ "CC"=>{:lat=>-12.5, :lng=>96.8333}, "CD"=>{:lat=>0.0, :lng=>25.0}, "CF"=>{:lat=>7.0, :lng=>21.0}, "CG"=>{:lat=>-1.0, :lng=>15.0},
30
+ "CH"=>{:lat=>47.0, :lng=>8.0}, "CI"=>{:lat=>8.0, :lng=>-5.0}, "CK"=>{:lat=>-21.2333, :lng=>-159.7667}, "CL"=>{:lat=>-30.0, :lng=>-71.0},
31
+ "CM"=>{:lat=>6.0, :lng=>12.0}, "CN"=>{:lat=>35.0, :lng=>105.0}, "CO"=>{:lat=>4.0, :lng=>-72.0}, "CR"=>{:lat=>10.0, :lng=>-84.0},
32
+ "CU"=>{:lat=>21.5, :lng=>-80.0}, "CV"=>{:lat=>16.0, :lng=>-24.0}, "CX"=>{:lat=>-10.5, :lng=>105.6667}, "CY"=>{:lat=>35.0, :lng=>33.0},
33
+ "CZ"=>{:lat=>49.75, :lng=>15.5}, "DE"=>{:lat=>51.0, :lng=>9.0}, "DJ"=>{:lat=>11.5, :lng=>43.0}, "DK"=>{:lat=>56.0, :lng=>10.0},
34
+ "DM"=>{:lat=>15.4167, :lng=>-61.3333}, "DO"=>{:lat=>19.0, :lng=>-70.6667}, "DZ"=>{:lat=>28.0, :lng=>3.0}, "EC"=>{:lat=>-2.0, :lng=>-77.5},
35
+ "EE"=>{:lat=>59.0, :lng=>26.0}, "EG"=>{:lat=>27.0, :lng=>30.0}, "EH"=>{:lat=>24.5, :lng=>-13.0}, "ER"=>{:lat=>15.0, :lng=>39.0},
36
+ "ES"=>{:lat=>40.0, :lng=>-4.0}, "ET"=>{:lat=>8.0, :lng=>38.0}, "EU"=>{:lat=>47.0, :lng=>8.0}, "FI"=>{:lat=>64.0, :lng=>26.0},
37
+ "FJ"=>{:lat=>-18.0, :lng=>175.0}, "FK"=>{:lat=>-51.75, :lng=>-59.0}, "FM"=>{:lat=>6.9167, :lng=>158.25}, "FO"=>{:lat=>62.0, :lng=>-7.0},
38
+ "FR"=>{:lat=>46.0, :lng=>2.0}, "GA"=>{:lat=>-1.0, :lng=>11.75}, "GB"=>{:lat=>54.0, :lng=>-2.0}, "GD"=>{:lat=>12.1167, :lng=>-61.6667},
39
+ "GE"=>{:lat=>42.0, :lng=>43.5}, "GF"=>{:lat=>4.0, :lng=>-53.0}, "GH"=>{:lat=>8.0, :lng=>-2.0}, "GI"=>{:lat=>36.1833, :lng=>-5.3667},
40
+ "GL"=>{:lat=>72.0, :lng=>-40.0}, "GM"=>{:lat=>13.4667, :lng=>-16.5667}, "GN"=>{:lat=>11.0, :lng=>-10.0}, "GP"=>{:lat=>16.25,:lng=>-61.5833},
41
+ "GQ"=>{:lat=>2.0, :lng=>10.0}, "GR"=>{:lat=>39.0, :lng=>22.0}, "GS"=>{:lat=>-54.5, :lng=>-37.0}, "GT"=>{:lat=>15.5, :lng=>-90.25},
42
+ "GU"=>{:lat=>13.4667, :lng=>144.7833}, "GW"=>{:lat=>12.0, :lng=>-15.0}, "GY"=>{:lat=>5.0, :lng=>-59.0}, "HK"=>{:lat=>22.25, :lng=>114.1667}, "HM"=>{:lat=>-53.1, :lng=>72.5167}, "HN"=>{:lat=>15.0, :lng=>-86.5}, "HR"=>{:lat=>45.1667, :lng=>15.5}, "HT"=>{:lat=>19.0, :lng=>-72.4167},
43
+ "HU"=>{:lat=>47.0, :lng=>20.0}, "ID"=>{:lat=>-5.0, :lng=>120.0}, "IE"=>{:lat=>53.0, :lng=>-8.0}, "IL"=>{:lat=>31.5, :lng=>34.75},
44
+ "IN"=>{:lat=>20.0, :lng=>77.0}, "IO"=>{:lat=>-6.0, :lng=>71.5}, "IQ"=>{:lat=>33.0, :lng=>44.0}, "IR"=>{:lat=>32.0, :lng=>53.0},
45
+ "IS"=>{:lat=>65.0, :lng=>-18.0}, "IT"=>{:lat=>42.8333, :lng=>12.8333}, "JM"=>{:lat=>18.25, :lng=>-77.5}, "JO"=>{:lat=>31.0, :lng=>36.0},
46
+ "JP"=>{:lat=>36.0, :lng=>138.0}, "KE"=>{:lat=>1.0, :lng=>38.0}, "KG"=>{:lat=>41.0, :lng=>75.0}, "KH"=>{:lat=>13.0, :lng=>105.0},
47
+ "KI"=>{:lat=>1.4167, :lng=>173.0}, "KM"=>{:lat=>-12.1667, :lng=>44.25}, "KN"=>{:lat=>17.3333, :lng=>-62.75}, "KP"=>{:lat=>40.0, :lng=>127.0},
48
+ "KR"=>{:lat=>37.0, :lng=>127.5}, "KW"=>{:lat=>29.3375, :lng=>47.6581}, "KY"=>{:lat=>19.5, :lng=>-80.5}, "KZ"=>{:lat=>48.0, :lng=>68.0},
49
+ "LA"=>{:lat=>18.0, :lng=>105.0}, "LB"=>{:lat=>33.8333, :lng=>35.8333}, "LC"=>{:lat=>13.8833, :lng=>-61.1333}, "LI"=>{:lat=>47.1667, :lng=>9.5333},
50
+ "LK"=>{:lat=>7.0, :lng=>81.0}, "LR"=>{:lat=>6.5, :lng=>-9.5}, "LS"=>{:lat=>-29.5, :lng=>28.5}, "LT"=>{:lat=>56.0, :lng=>24.0},
51
+ "LU"=>{:lat=>49.75, :lng=>6.1667}, "LV"=>{:lat=>57.0, :lng=>25.0}, "LY"=>{:lat=>25.0, :lng=>17.0}, "MA"=>{:lat=>32.0, :lng=>-5.0},
52
+ "MC"=>{:lat=>43.7333, :lng=>7.4}, "MD"=>{:lat=>47.0, :lng=>29.0}, "ME"=>{:lat=>42.0, :lng=>19.0}, "MG"=>{:lat=>-20.0, :lng=>47.0},
53
+ "MH"=>{:lat=>9.0, :lng=>168.0}, "MK"=>{:lat=>41.8333, :lng=>22.0}, "ML"=>{:lat=>17.0, :lng=>-4.0}, "MM"=>{:lat=>22.0, :lng=>98.0},
54
+ "MN"=>{:lat=>46.0, :lng=>105.0}, "MO"=>{:lat=>22.1667, :lng=>113.55}, "MP"=>{:lat=>15.2, :lng=>145.75}, "MQ"=>{:lat=>14.6667, :lng=>-61.0},
55
+ "MR"=>{:lat=>20.0, :lng=>-12.0}, "MS"=>{:lat=>16.75, :lng=>-62.2}, "MT"=>{:lat=>35.8333, :lng=>14.5833}, "MU"=>{:lat=>-20.2833, :lng=>57.55},
56
+ "MV"=>{:lat=>3.25, :lng=>73.0}, "MW"=>{:lat=>-13.5, :lng=>34.0}, "MX"=>{:lat=>23.0, :lng=>-102.0}, "MY"=>{:lat=>2.5, :lng=>112.5},
57
+ "MZ"=>{:lat=>-18.25, :lng=>35.0}, "NA"=>{:lat=>-22.0, :lng=>17.0}, "NC"=>{:lat=>-21.5, :lng=>165.5}, "NE"=>{:lat=>16.0, :lng=>8.0},
58
+ "NF"=>{:lat=>-29.0333, :lng=>167.95}, "NG"=>{:lat=>10.0, :lng=>8.0}, "NI"=>{:lat=>13.0, :lng=>-85.0}, "NL"=>{:lat=>52.5, :lng=>5.75},
59
+ "NO"=>{:lat=>62.0, :lng=>10.0}, "NP"=>{:lat=>28.0, :lng=>84.0}, "NR"=>{:lat=>-0.5333, :lng=>166.9167}, "NU"=>{:lat=>-19.0333, :lng=>-169.8667},
60
+ "NZ"=>{:lat=>-41.0, :lng=>174.0}, "OM"=>{:lat=>21.0, :lng=>57.0}, "PA"=>{:lat=>9.0, :lng=>-80.0}, "PE"=>{:lat=>-10.0, :lng=>-76.0},
61
+ "PF"=>{:lat=>-15.0, :lng=>-140.0}, "PG"=>{:lat=>-6.0, :lng=>147.0}, "PH"=>{:lat=>13.0, :lng=>122.0}, "PK"=>{:lat=>30.0, :lng=>70.0},
62
+ "PL"=>{:lat=>52.0, :lng=>20.0}, "PM"=>{:lat=>46.8333, :lng=>-56.3333}, "PR"=>{:lat=>18.25, :lng=>-66.5}, "PS"=>{:lat=>32.0, :lng=>35.25},
63
+ "PT"=>{:lat=>39.5, :lng=>-8.0}, "PW"=>{:lat=>7.5, :lng=>134.5}, "PY"=>{:lat=>-23.0, :lng=>-58.0}, "QA"=>{:lat=>25.5, :lng=>51.25},
64
+ "RE"=>{:lat=>-21.1, :lng=>55.6}, "RO"=>{:lat=>46.0, :lng=>25.0}, "RS"=>{:lat=>44.0, :lng=>21.0}, "RU"=>{:lat=>60.0, :lng=>100.0},
65
+ "RW"=>{:lat=>-2.0, :lng=>30.0}, "SA"=>{:lat=>25.0, :lng=>45.0}, "SB"=>{:lat=>-8.0, :lng=>159.0}, "SC"=>{:lat=>-4.5833, :lng=>55.6667},
66
+ "SD"=>{:lat=>15.0, :lng=>30.0}, "SE"=>{:lat=>62.0, :lng=>15.0}, "SG"=>{:lat=>1.3667, :lng=>103.8}, "SH"=>{:lat=>-15.9333, :lng=>-5.7},
67
+ "SI"=>{:lat=>46.0, :lng=>15.0}, "SJ"=>{:lat=>78.0, :lng=>20.0}, "SK"=>{:lat=>48.6667, :lng=>19.5}, "SL"=>{:lat=>8.5, :lng=>-11.5},
68
+ "SM"=>{:lat=>43.7667, :lng=>12.4167}, "SN"=>{:lat=>14.0, :lng=>-14.0}, "SO"=>{:lat=>10.0, :lng=>49.0}, "SR"=>{:lat=>4.0, :lng=>-56.0},
69
+ "ST"=>{:lat=>1.0, :lng=>7.0}, "SV"=>{:lat=>13.8333, :lng=>-88.9167}, "SY"=>{:lat=>35.0, :lng=>38.0}, "SZ"=>{:lat=>-26.5, :lng=>31.5},
70
+ "TC"=>{:lat=>21.75, :lng=>-71.5833}, "TD"=>{:lat=>15.0, :lng=>19.0}, "TF"=>{:lat=>-43.0, :lng=>67.0}, "TG"=>{:lat=>8.0, :lng=>1.1667},
71
+ "TH"=>{:lat=>15.0, :lng=>100.0}, "TJ"=>{:lat=>39.0, :lng=>71.0}, "TK"=>{:lat=>-9.0, :lng=>-172.0}, "TM"=>{:lat=>40.0, :lng=>60.0},
72
+ "TN"=>{:lat=>34.0, :lng=>9.0}, "TO"=>{:lat=>-20.0, :lng=>-175.0}, "TR"=>{:lat=>39.0, :lng=>35.0}, "TT"=>{:lat=>11.0, :lng=>-61.0},
73
+ "TV"=>{:lat=>-8.0, :lng=>178.0}, "TW"=>{:lat=>23.5, :lng=>121.0}, "TZ"=>{:lat=>-6.0, :lng=>35.0}, "UA"=>{:lat=>49.0, :lng=>32.0},
74
+ "UG"=>{:lat=>1.0, :lng=>32.0}, "UM"=>{:lat=>19.2833, :lng=>166.6}, "US"=>{:lat=>38.0, :lng=>-97.0}, "UY"=>{:lat=>-33.0, :lng=>-56.0},
75
+ "UZ"=>{:lat=>41.0, :lng=>64.0}, "VA"=>{:lat=>41.9, :lng=>12.45}, "VC"=>{:lat=>13.25, :lng=>-61.2}, "VE"=>{:lat=>8.0, :lng=>-66.0},
76
+ "VG"=>{:lat=>18.5, :lng=>-64.5}, "VI"=>{:lat=>18.3333, :lng=>-64.8333}, "VN"=>{:lat=>16.0, :lng=>106.0}, "VU"=>{:lat=>-16.0, :lng=>167.0},
77
+ "WF"=>{:lat=>-13.3, :lng=>-176.2}, "WS"=>{:lat=>-13.5833, :lng=>-172.3333}, "YE"=>{:lat=>15.0, :lng=>48.0}, "YT"=>{:lat=>-12.8333, :lng=>45.1667},
78
+ "ZA"=>{:lat=>-29.0, :lng=>24.0}, "ZM"=>{:lat=>-15.0, :lng=>30.0}, "ZW"=>{:lat=>-20.0, :lng=>30.0}, "JE"=>{:lat=>49.25, :lng=>-2.16},
79
+ "IM"=>{:lat=>54.25, :lng=>4.5}, "AX"=>{:lat=>60.25, :lng=> 20},"A1"=>{:lat=>0, :lng=> 0},"A2"=>{:lat=>0, :lng=> 0}
80
+ }
81
+
82
+ # This determines where the tour goes to and which placemark ballons come up
83
+ # centres: South Africa, Benin, Switz, Ukraine, India, Australia, Paraguay, United States,France
84
+ #
85
+ WORLDTOUR={"ZA" => ["ZA1","NA1","KE1"],
86
+ "BJ" => ["BJ1","A11","NG1","CI1","SN1","DZ1","MA1","EG1","TN1"],
87
+ "CH" => ["FR1","ES1","LU1","GB1","BE1","NL1","DE1","IT1","IE1","AT1","SE1","DK1","UA1"],
88
+ "UA" => ["SA1","TR1","SY1","RU1","IR1"],
89
+ "IN" => ["IN1","KZ1","CN1","TH1","PK1"],
90
+ "AU" => ["AU1","NC1"],
91
+ "PY" => ["PY1","BR1","AR1","CL1"],
92
+ "US" => ["US1","US2","US3","US4","CA1","MX1"],
93
+ "FR" => ["FR1"] }
94
+
95
+ # FR1 is the centre, by default, centres 1 to 90 are read by default, and 91-200 change to black after 2seconds
96
+ # This can be changed using a the mix-in features of Ruby, using the keys {:lat , :lng,"red", "black"}
97
+ ATTACK_TOUR = {:lat => 46.0,
98
+ :lng => 2.0,
99
+ "red"=> (1..90).collect{|eachnum| "FR" + eachnum.to_s},
100
+ "black"=> (91..200).collect{|eachnum| "FR" + eachnum.to_s} }
101
+ #"red"=> ["FR240", "FR221", "FR46", "FR72", "FR226","FR4","FR179","FR182",],
102
+ #"black"=> ["FR92", "FR159", "FR196", "FR210", "FR17","218", "FR175","FR41" ] }
103
+
104
+ # This determines how long the program Tor::TController.extendcir_slowly() waits between each extension.
105
+ EXTEND_DELAY = 2.0
106
+ end
@@ -0,0 +1,89 @@
1
+ # httpmod functions - extends net/http
2
+
3
+ module Net #:nodoc:
4
+ class HTTP #:nodoc:
5
+
6
+ # Sends an HTTPRequest object REQUEST to the HTTP proxy such as polipo, and attach all new streams to the circuit specified in torctrl_cir.
7
+ # torctrl_cir = {:torctrl, :cirnum,:hop}
8
+ # Tor config must already be set to allow leaky circuits and attaching streams to the nodes other than the 3rd node.
9
+ # Similar to HTTP.request
10
+ # When called with a block, yields an HTTPResponse object.
11
+ # The body of this response will not have been read yet;
12
+ # the caller can process it using HTTPResponse#read_body,
13
+ # if desired.
14
+ #
15
+ # Returns a HTTPResponse object.
16
+ #
17
+ # This method never raises Net::* exceptions.
18
+ # The method has been implemented, but a circuit have been built to successfullty attach a stream to it.
19
+ #
20
+ def request_tor(req,torctrl_cir, body = nil, &block)
21
+ unless started?
22
+ start {
23
+ req['connection'] ||= 'close'
24
+ return request(req, body, &block)
25
+ }
26
+ end
27
+ if proxy_user()
28
+ req.proxy_basic_auth proxy_user(), proxy_pass() unless use_ssl?
29
+ end
30
+ req.set_body_internal body
31
+ res = transport_request_tor(req, torctrl_cir, &block)
32
+ if sspi_auth?(res)
33
+ sspi_auth(req)
34
+ res = transport_request_tor(req, torctrl_cir, &block)
35
+ end
36
+ res
37
+ end
38
+
39
+ # Sends an HTTPRequest object GET REQUEST to the HTTP proxy such as polipo, and attach all new streams to the circuit specified in torctrl_cir.
40
+ # torctrl_cir = {:torctrl, :cirnum,:hop}
41
+ # Tor config must already be set to allow leaky circuits and attaching streams to the nodes other than the 3rd node.
42
+ # Similar to HTTP.request_get
43
+ # The method has been implemented, but a circuit have been built to successfullty attach a stream to it.
44
+ #
45
+ def request_torget(path, torctrl_cir, initheader = nil, &block)
46
+ request_tor(Get.new(path, initheader),torctrl_cir, &block)
47
+ end
48
+
49
+ private
50
+
51
+ # This transports requests to the proxy specified in the HTTP request, and then attaches all new streams to a prespecified circuit.
52
+ # It works behind the scene when making requests using HTTP.request_torget and HTTP.request_tor
53
+ # Further development in progress.
54
+ # - Must create new stream if cirnum==0
55
+ # - Attempt to recreate the same circuit if the circuit is closed. support sending Circuit instance in the hash instead of just cirnum
56
+ # ...more work to be done probably be used to make a browser for Tor, with limited functionality. No flash/javascript/cookies to start with, so no tracking.
57
+ #
58
+ def transport_request_tor(req, torctrl_cir) #:nodoc:
59
+ # torctrl_cir = {:torctrl, :cirnum,:hop}
60
+ tcontrl = torctrl_cir[:torctrl]
61
+ cir_num = torctrl_cir[:cirnum]
62
+ hop_count = torctrl_cir[:hop] ? torctrl_cir[:hop] : 0
63
+
64
+ begin_transport req
65
+ req.exec @socket, @curr_http_version, edit_path(req.path)
66
+
67
+ #Get all new streams since the request was sent
68
+ b = tcontrl.newstreams
69
+ # attach all new streams to cir_num
70
+ b.each{|k|
71
+ tcontrl.attach_stream(k, cir_num,hop_count)
72
+ }
73
+
74
+ begin
75
+ res = HTTPResponse.read_new(@socket)
76
+ end while res.kind_of?(HTTPContinue)
77
+ res.reading_body(@socket, req.response_body_permitted?) {
78
+ yield res if block_given?
79
+ }
80
+ end_transport req, res
81
+ res
82
+ rescue => exception
83
+ D "Conn close because of error #{exception}"
84
+ @socket.close if @socket and not @socket.closed?
85
+ raise exception
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,475 @@
1
+ module Tor
2
+
3
+ require 'socksify/http'
4
+
5
+
6
+ # Tor:TController is an extension of the Tor::Controller class, providing more methods.
7
+ # It inherits all methods from Tor::Controller and can be used to interact with Tor.
8
+ #
9
+ # <b>TController examples</b>
10
+ #
11
+ # require 'tor_extend'
12
+ # Tor::TController.new(:host=>@getbridge_config[:torcontrolhost],
13
+ # :port=>@getbridge_config[:torcontrolport])
14
+ # Tor::TController.new(:host=>"127.0.0.1",:port=>9051)
15
+ # Tor::TController.connect
16
+ # Tor::TController.authenticate("\"tor_control_password\"")
17
+ # Tor::TController.sr(:signal,"HUP")
18
+ # Tor::TController.sr(:signal,"newnym")
19
+ # Tor::TController.getinfo("ns/all")
20
+ # Tor::TController.net_status
21
+ # Tor::TController.closecircuit(15)
22
+ # Tor::TController.closeallcircuits
23
+ # Tor::TController.signal("reload"
24
+ # Tor::TController.extendcir(0,['or1','or2','or3'])
25
+ # Tor::TController.setconf("__DisablePredictedCircuits",1)
26
+ # Tor::TController.setconf("__LeaveStreamsUnattached",1)
27
+ # Tor::TController.getconf("ORPort")
28
+ # Tor::TController.getconf("__LeaveStreamsUnattached")
29
+ # Tor::TController.get_bridges( {:type=>'http',:port=>9050,:addr=>'127.0.0.1'} )
30
+ #
31
+ #
32
+ # For more details, visit [https://github.com/bendiken/tor-ruby#readme], [https://gitweb.torproject.org/torspec.git/tree]
33
+ #
34
+ class TController < Tor::Controller
35
+
36
+ # This returns the circuit-status in an array, or an empty array on failure
37
+ #
38
+ # <b>Get the circuit-status from Tor</b>.
39
+ #
40
+ # Tor::TController.cir_status
41
+ # ["46 BUILT ORa,ORb,ORc PURPOSE=GENERAL"]
42
+ def cir_status
43
+ cirstatus=getinfo("circuit-status")
44
+ end
45
+
46
+
47
+ # This attempts to close a single circuit.
48
+ #
49
+ # <b>Closing circuits</b>
50
+ # Tor::TController.closecircuit(15)
51
+ def closecircuit (circnum)
52
+ errorstate,ans=sr(:closecircuit," #{circnum}")
53
+ end
54
+
55
+ # This attempts to close all open circuits.
56
+ #
57
+ # <b>Closing all circuits</b>
58
+ #
59
+ # Tor::TController.closeallcircuits
60
+ def closeallcircuits
61
+ x=cir_status
62
+ if !x.empty?
63
+ x.each{|eachcircuit|
64
+ circnum = eachcircuit.match(/^\d+/)
65
+ closecircuit(circnum)
66
+ }
67
+ end
68
+ end
69
+
70
+ # Returns the an array of of directory servers from the consensus.
71
+ #
72
+ # Tor::TController.ds => [w.x.y.z:port, ...]
73
+ #
74
+ def ds
75
+ reply=[]
76
+ s = getinfo("ns/all")
77
+ case version
78
+ when /0.2.[01]/
79
+ z=2
80
+ when/0.2.2/
81
+ z = 4 # To accommodate r, s , w and p]
82
+ end
83
+ s.collect!{|eachs| eachs.start_with?("r ") ? eachs : nil }
84
+ s.delete nil
85
+ s.each{|eachs|
86
+ dsport=eachs.split[8].to_i
87
+ rip=eachs.split[6]
88
+ reply << "#{rip}:#{dsport}" if dsport!= 0
89
+ }
90
+ reply
91
+ end
92
+
93
+
94
+ # This creates/extends a circuit over multiple nodes. A new circuit is created if cir_num == 0.
95
+ #
96
+ # <b>Creating a new circuit</b>
97
+ #
98
+ # create_circ = Tor::TController.extendcir(0,['or1','or2','or3'])
99
+ def extendcir(circnum,or_list)
100
+ argor=" #{circnum} #{or_list.join(',')}"
101
+ extendcir=send_command(:extendcircuit,argor)
102
+ circuit_id=nil
103
+ readterm=true
104
+ while readterm do
105
+ case msg=read_reply
106
+ when /^\d+ CIRC \d+ BUILT/,/250 / #/^\d+ CIRC \d+ BUILT/
107
+ circuit_id=msg.scan(/\d+\Z/)[0]
108
+ readterm=false
109
+ when /^5\d\d /
110
+ readterm=false
111
+ when /^\d+ /
112
+ puts msg #like extended launched
113
+ else
114
+ puts msg,"\n"
115
+ end
116
+ end
117
+ #sr(:signal,"newnym")
118
+ circuit_id
119
+ end
120
+
121
+ # This builds a circuit to each member of the array argument, skipping any node that fails to connect.
122
+ # It returns the circuit number, and the longest successful circuit that was successfully built.
123
+ # There is a delay of 2.0 seconds after each extension, but this can be altered by defining Tor::EXTEND_DELAY constant.
124
+ #
125
+ # <b>Create a circuit as long as possible using 10 elements in an array</b>
126
+ # testarray = [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
127
+ # Tor::TController.extendcir_slowly(testarray)
128
+ def extendcir_slowly(orarray)
129
+ ordelay = defined?(EXTEND_DELAY) ? EXTEND_DELAY : Constants::EXTEND_DELAY
130
+ cirnum = 0
131
+ circuit = []
132
+ orarray.each{|eachor|
133
+ cirnum=extendcir(cirnum,[eachor])
134
+ sleep(ordelay) # wait for a few seconds, and check if the circuit is was successful
135
+ p=cir_status.detect{|i| i =~ (/^#{cirnum} / )}
136
+ case p
137
+ when /FAILED/,nil
138
+ puts "cirnum=nil"
139
+ if eachor != circuit.last
140
+ cirnum = extendcir(0,circuit)
141
+ sleep(circuit.count)
142
+ elsif circuit.empty?
143
+ return nil # failed to build circuit at start, make sure orarray[0] is up
144
+ end
145
+ when /EXTENDED/, /BUILT/
146
+ circuit << eachor
147
+ puts "Extended! cirnum = #{cirnum}, circuit length = #{circuit.count}"
148
+ when /LAUNCHED/
149
+ sleep(1)
150
+ puts x=cir_status.detect{|a| a =~ /^#{cirnum}/}
151
+ circuit << eachor if (x =~ /BUILT/) or (x =~/EXTENDED/)
152
+ end
153
+ }
154
+ [cirnum,circuit]
155
+ end
156
+
157
+ # This gets 3 bridge IP addresses from the Tor bridge website. proxyconfig is optional.
158
+ # default proxyconfig = {:type=>'tor' ,:port=>9050,:addr=>'127.0.0.1'}
159
+ # The return format is fo the form:
160
+ # [HTTPcode, [{:bridgeip, :bridgeport},{:bridgeip, :bridgeport},{:bridgeip, :bridgeport}].
161
+ # The types can be one of 'tor', 'polipo', 'socks', 'http', 'https',nil, 'none'.
162
+ # torctrl_cirnum must have the form:
163
+ # torctrl_cirnum ={:torctrl=>Tor::TController, :cirnum=>cirnum,:hop=>hopcount}
164
+ #
165
+ # <b>Get 3 bridges</b>
166
+ #
167
+ # Tor::TController.get_bridges( {:proxytype=>'tor',:proxyport=>9050,:proxyaddr=>'127.0.0.1'} )
168
+ def get_bridges(url, cacheddesc, *config)
169
+ if config.empty?
170
+ proxyconfig={:type=>'tor' ,:port=>9050,:addr=>'127.0.0.1'}
171
+ else
172
+ proxyconfig = config[0]
173
+ end
174
+ if ! defined?(@myhttperrors)
175
+ @myhttperrors=0
176
+ end
177
+ case proxyconfig[:type]
178
+ when /none/i,nil
179
+ http_session=Net::HTTP.new(url.host,url.port)
180
+ when /socks/i,/tor/i
181
+ http_session=Net::HTTP.SOCKSProxy(proxyconfig[:addr], proxyconfig[:port]).new(url.host,url.port)
182
+ when /http/i,/https/i,/polipo/i
183
+ http_session=Net::HTTP::Proxy(proxyconfig[:addr], proxyconfig[:port]).new(url.host,url.port)
184
+ end
185
+ if url.scheme=="https"
186
+ http_session.use_ssl = true
187
+ http_session.verify_mode = OpenSSL::SSL::VERIFY_NONE
188
+ else
189
+ http_session.use_ssl=false
190
+ end
191
+ bridges=[]
192
+ # Rescue from http error
193
+ begin
194
+ resp = http_session.get2 url.path # Let Tor choose circuit itself
195
+ # Additional code will be added shortly to attach the stream to the circuit directly
196
+ puts "#{resp.code} HTTP response"
197
+ #puts resp.body
198
+ respcode= resp.code=="200" ? 200:nil
199
+ if resp.code == "200"
200
+ torbridgeip=resp.body.scan(/\d+\.\d+\.\d+\.\d+\:\d+/)
201
+ torbridgeip.each{|eachbridge|
202
+ bridgeip,bridgeport= eachbridge.split(':')
203
+ x=Bridge.where(:ipaddr=>bridgeip, :port =>bridgeport)
204
+ if x.empty?
205
+ if (bridge_geoip=cacheddesc.get_geoiprecord(bridgeip)).nil?
206
+ Bridge.create(:ipaddr=>bridgeip, :port =>bridgeport,
207
+ :lat=>0, :lng=>0)
208
+ else
209
+ Bridge.create(:ipaddr=>bridgeip, :port =>bridgeport,
210
+ :lat=>bridge_geoip.latitude.to_f,
211
+ :lng=>bridge_geoip.longitude.to_f )
212
+ end
213
+ end
214
+ }
215
+ end
216
+ bridges = torbridgeip
217
+ rescue
218
+ @myhttperrors +=1
219
+ respcode=nil
220
+ bridges=[]
221
+ end
222
+ bridges #Return array of all bridges
223
+ end
224
+
225
+ # Returns all the brdiges in the database as an array.
226
+ #
227
+ # Tor::TController.bridges => [{:ipaddr, :port, :lat, :lng},...]
228
+ def bridges
229
+ Bridges.all
230
+ end
231
+
232
+ # This returns all the new streams that have not been assigned to a circuit
233
+ def newstreams
234
+ reply=[]
235
+ getinfo("stream-status").each{|eachstream|
236
+ case eachstream
237
+ when /\d+ NEW 0/
238
+ # It might be simpler to use this /\d+ NEW/
239
+ reply << eachstream.scan(/\d+/)[0]
240
+ end
241
+ }
242
+ reply
243
+ end
244
+
245
+ # This attaches streams to circuits. No documentation yet.
246
+ def attach_stream(stream_no, cir_num ,hop_count)
247
+ puts "attachstream"
248
+ if hop_count==0
249
+ sr(:attachstream,"#{stream_no} #{cir_num}")
250
+ else
251
+ sr(:attachstream,"#{stream_no} #{cir_num} HOP=#{hop_count}")
252
+ end
253
+ end
254
+
255
+
256
+ # This gets enty guards from the control port of tor using the getinfo "entry-guards" command
257
+ # and returns just the fingerprints in an array.
258
+ #
259
+ # <b>Get entry-guards</b>
260
+ #
261
+ # Tor::TController.get_entryguards #=> ["$abc123","$def456"...]
262
+ def get_entryguards
263
+ rslt = getinfo "entry-guards"
264
+ reply = rslt.collect{|eachguard|
265
+ case eachguard
266
+ when / unusable/
267
+ nil
268
+ else
269
+ "$"+ eachguard.split(/[~ =]/)[0]
270
+ end
271
+ }
272
+ reply.delete(nil)
273
+ reply
274
+ end
275
+
276
+ # This returns the number of HTTP errors from the Tor::TController.get_bridges command
277
+ #
278
+ def get_httperrors
279
+ @myhttperrors
280
+ end
281
+
282
+ # This gets the IP addresses for ORs based on the characteristics of the OR.
283
+ # Example of the properties include: _Fast_, _Guard_, _HSDir_, _Named_, _Running_, _Stable_, _V2Dir_, _Valid_, _Exit_.
284
+ #
285
+ # <b>Get all Exit, Fast and entry Guard ORs</b>
286
+ #
287
+ # Tor::TController.get_purposeip("Exit") #=> ["a.b.c.d","e.f.g.h"...]
288
+ # Tor::TController.get_purposeip("fast exit")
289
+ # Tor::TController.get_purposeip("Guard")
290
+ def get_purposeip(nodetype)
291
+ reply=[]
292
+ s = getinfo("ns/all")
293
+ ctr_i= s.size / 2
294
+ ctr_i.times{|j|
295
+ rip=s[j*2].split[6]
296
+ x=Router.where(:ipaddr=>rip)
297
+ if !x.empty?
298
+ finprint = "$" + x[0].fingerprint
299
+ matcharray=nodetype.split.collect{|eachtype|
300
+ if eachtype.start_with? '!'
301
+ matchme = eachtype[1..(eachtype.length-1)]
302
+ rslt = !(s[j*2+1] =~ (/#{matchme}/i))
303
+ rslt ? rslt : nil #return nil if false, or return the number
304
+ else
305
+ s[j*2+1] =~ (/#{eachtype}/i)
306
+ end
307
+ }
308
+ reply << finprint if !matcharray.include? nil
309
+ end
310
+ }
311
+ reply
312
+ end
313
+
314
+ # This gets a configuration from Tor. The arguments of this command might be case sensitive. It returns the protocol error message if it fails.
315
+ #
316
+ # <b>Get the present ORport Tor is using</b>
317
+ #
318
+ # Tor::TController.getconf("ORPort") #=>"9001"
319
+ # Tor::TController.getconf("__LeaveStreamsUnattached") #=>"1"
320
+ #
321
+ # For more details, see [https://gitweb.torproject.org/torspec.git/blob/HEAD:/control-spec.txt]
322
+ def getconf(confname)
323
+ send_command(:getconf, confname)
324
+ reply=[]
325
+ case msg=read_reply
326
+ when /250 /
327
+ msg.split(/250 \S*=/).last
328
+ else
329
+ msg
330
+ end
331
+ end
332
+
333
+
334
+ # This method sends the "GETINFO" protocol message with the arguments.
335
+ #
336
+ # <b>Getting more information from Tor</b>
337
+ #
338
+ # Tor::TController.getinfo("ns/all")
339
+ def getinfo(*args)
340
+ errorcode,ans = sr(:getinfo,*args)
341
+ ans
342
+ end
343
+
344
+ # This returns an array of hash tables with the fingerprints of all onion routers that have not been marked as down.
345
+ #
346
+ # <b>Get the network status from Tor</b>
347
+ #
348
+ # Tor::TController.net_status => [ {:fingerprint=>"$ABCD"},{:fingerprint=>"$EFGH"}...]
349
+ def net_status
350
+ case version
351
+ when /0.2.[01]/
352
+ net_status1
353
+ when/0.2.2/
354
+ net_status2
355
+ end
356
+ end
357
+
358
+ private
359
+ def net_status1 #:nodoc:
360
+ nstatus_array=getinfo("network-status")
361
+ sorted_networkstatus=[]
362
+ if !nstatus_array.empty?
363
+ netstatus=nstatus_array[0]
364
+ fingerprint=netstatus.split(/\S+=/)
365
+ fingerprint.delete_at(0) #delete the fingerprint stored for nickname=network-status
366
+ fingerprint.each{|eachfingerprint|
367
+ tmpfarray = eachfingerprint.split
368
+ tmpb=tmpfarray.collect{|element|
369
+ element.start_with?("!") ? nil:element
370
+ }
371
+ tmpb.delete(nil)
372
+ if tmpb.empty?
373
+ net_status = nil
374
+ else
375
+ sorted_networkstatus << {:fingerprint=>tmpb[0] }
376
+ end
377
+ }
378
+ end
379
+ sorted_networkstatus
380
+ end
381
+
382
+ def net_status2 #:nodoc:
383
+ @myhttperrors=0
384
+ nstatus_array=getinfo("network-status")
385
+ sorted_networkstatus=[]
386
+ if !nstatus_array.empty?
387
+ netstatus=nstatus_array[0]
388
+ fingerprint=netstatus.split.collect{|asd|
389
+ element = asd.split(/[=~]/)[0]
390
+ element.start_with?("!") ? nil:element
391
+ }
392
+ fingerprint.delete(nil)
393
+ #fingerprint.delete_at(0) #delete the fingerprint stored for nickname=network-status
394
+ fingerprint.each{|eachfingerprint|
395
+ sorted_networkstatus << {:fingerprint=>eachfingerprint }
396
+ }
397
+ end
398
+ sorted_networkstatus
399
+ end
400
+
401
+ public
402
+ # This sets a configuration in Tor to a value.
403
+ #
404
+ # <b>Setting Tor config</b>
405
+ #
406
+ # Tor::TController.setconf("__DisablePredictedCircuits",1) =>["OK", []]
407
+ # Tor::TController.setconf("__LeaveStreamsUnattached",1) =>["OK", []]
408
+ # Tor::TController.setconf("ORPort",9001) =>["OK", []]
409
+ def setconf(confname,value)
410
+ sr(:setconf,"#{confname}=#{value}")
411
+ end
412
+
413
+ # This method sends "signals" protocol message with the arguments.
414
+ #
415
+ # <b>Reload Tor config from file</b>
416
+ #
417
+ # Tor::TController.signal("RELOAD")
418
+ # Tor::TController.signal("HUP")
419
+ def signal(args)
420
+ reply=[]
421
+ case (args)
422
+ when /NEWNYM/i,/CLEARDNSCACHE/i,/RELOAD/i,/HUP/i,/DUMP/i,/USR1/i,/DEBUG/i,/USR2/i,/shutdown/i,/INT/i
423
+ errorcode,reply=sr(:signal, args)
424
+ close if args =~ /shutdown/i or args =~ /INT/i
425
+ when /HALT/i,/TERM/i
426
+ send_command(:signal, "HALT")
427
+ close
428
+ else
429
+ puts "#{args} not recognised by the at library development. Sending the signal nonetheless"
430
+ reply=sr(:signal,args)
431
+ end
432
+ reply
433
+ end
434
+
435
+ # This sends commands and returns the protocol response code along with an array
436
+ # containing the results with the following format \[errorcode,\[array_of_results]].
437
+ #
438
+ # <b>Send and receive commands</b>.
439
+ #
440
+ # Tor::TController.sr(:signal,"reload")
441
+ # Tor::TController.sr(:signal,"newnym")
442
+ def sr(command, *args)
443
+ send_command(command, *args)
444
+ reply=[]
445
+ readterm=true
446
+ while readterm do
447
+ # Read as much as possible until '250 OK' or error 5YZ
448
+ case msg=read_reply
449
+ when /^250 OK/
450
+ readterm=false
451
+ puts errorstate="OK"
452
+ when /^250[\+,\-,\s]/
453
+ reply << msg.split(/^\d+[\+,\-,\s]\S*=/).last unless msg=~/250\+/
454
+ errorstate = "OK"
455
+ when /^\./
456
+ when /^5\d\d /
457
+ if errorstate == "OK" # if a "2yz " code came before this then msg is part of response
458
+ reply << msg
459
+ else
460
+ puts msg
461
+ errorstate = msg.match(/^5\d\d/)
462
+ readterm=false
463
+ end
464
+ else
465
+ reply << msg
466
+ end
467
+ end
468
+ reply.delete(nil)
469
+ reply = errorstate=="OK" ? reply : []
470
+ [errorstate,reply]
471
+ end
472
+
473
+
474
+ end # end of class
475
+ end # end of module