iQ Block Country - Version 1.1

Version Description

  • Added statistics to the plugin.
  • You can view the last 15 hosts that were blocked including the url they visited.
  • You can view the top 15 of countries that were blocked in the past 30 days.
  • You can view the top 15 of hosts that were blocked in the past 30 days.
  • You can view the top URL's that were most blocked in the past 30 days.
Download this release

Release Info

Developer iqpascal
Plugin Icon 128x128 iQ Block Country
Version 1.1
Comparing to
See all releases

Version 1.1

Files changed (258) hide show
  1. chosen-sprite.png +0 -0
  2. chosen-sprite@2x.png +0 -0
  3. chosen.css +420 -0
  4. chosen.jquery.js +1132 -0
  5. icons/ad.png +0 -0
  6. icons/ae.png +0 -0
  7. icons/af.png +0 -0
  8. icons/ag.png +0 -0
  9. icons/ai.png +0 -0
  10. icons/al.png +0 -0
  11. icons/am.png +0 -0
  12. icons/an.png +0 -0
  13. icons/ao.png +0 -0
  14. icons/ar.png +0 -0
  15. icons/as.png +0 -0
  16. icons/at.png +0 -0
  17. icons/au.png +0 -0
  18. icons/aw.png +0 -0
  19. icons/ax.png +0 -0
  20. icons/az.png +0 -0
  21. icons/ba.png +0 -0
  22. icons/bb.png +0 -0
  23. icons/bd.png +0 -0
  24. icons/be.png +0 -0
  25. icons/bf.png +0 -0
  26. icons/bg.png +0 -0
  27. icons/bh.png +0 -0
  28. icons/bi.png +0 -0
  29. icons/bj.png +0 -0
  30. icons/bm.png +0 -0
  31. icons/bn.png +0 -0
  32. icons/bo.png +0 -0
  33. icons/br.png +0 -0
  34. icons/bs.png +0 -0
  35. icons/bt.png +0 -0
  36. icons/bv.png +0 -0
  37. icons/bw.png +0 -0
  38. icons/by.png +0 -0
  39. icons/bz.png +0 -0
  40. icons/ca.png +0 -0
  41. icons/catalonia.png +0 -0
  42. icons/cc.png +0 -0
  43. icons/cd.png +0 -0
  44. icons/cf.png +0 -0
  45. icons/cg.png +0 -0
  46. icons/ch.png +0 -0
  47. icons/ci.png +0 -0
  48. icons/ck.png +0 -0
  49. icons/cl.png +0 -0
  50. icons/cm.png +0 -0
  51. icons/cn.png +0 -0
  52. icons/co.png +0 -0
  53. icons/cr.png +0 -0
  54. icons/cs.png +0 -0
  55. icons/cu.png +0 -0
  56. icons/cv.png +0 -0
  57. icons/cx.png +0 -0
  58. icons/cy.png +0 -0
  59. icons/cz.png +0 -0
  60. icons/de.png +0 -0
  61. icons/dj.png +0 -0
  62. icons/dk.png +0 -0
  63. icons/dm.png +0 -0
  64. icons/do.png +0 -0
  65. icons/dz.png +0 -0
  66. icons/ec.png +0 -0
  67. icons/ee.png +0 -0
  68. icons/eg.png +0 -0
  69. icons/eh.png +0 -0
  70. icons/england.png +0 -0
  71. icons/er.png +0 -0
  72. icons/es.png +0 -0
  73. icons/et.png +0 -0
  74. icons/eu.png +0 -0
  75. icons/fam.png +0 -0
  76. icons/fi.png +0 -0
  77. icons/fj.png +0 -0
  78. icons/fk.png +0 -0
  79. icons/fm.png +0 -0
  80. icons/fo.png +0 -0
  81. icons/fr.png +0 -0
  82. icons/ga.png +0 -0
  83. icons/gb.png +0 -0
  84. icons/gd.png +0 -0
  85. icons/ge.png +0 -0
  86. icons/gf.png +0 -0
  87. icons/gh.png +0 -0
  88. icons/gi.png +0 -0
  89. icons/gl.png +0 -0
  90. icons/gm.png +0 -0
  91. icons/gn.png +0 -0
  92. icons/gp.png +0 -0
  93. icons/gq.png +0 -0
  94. icons/gr.png +0 -0
  95. icons/gs.png +0 -0
  96. icons/gt.png +0 -0
  97. icons/gu.png +0 -0
  98. icons/gw.png +0 -0
  99. icons/gy.png +0 -0
  100. icons/hk.png +0 -0
  101. icons/hm.png +0 -0
  102. icons/hn.png +0 -0
  103. icons/hr.png +0 -0
  104. icons/ht.png +0 -0
  105. icons/hu.png +0 -0
  106. icons/id.png +0 -0
  107. icons/ie.png +0 -0
  108. icons/il.png +0 -0
  109. icons/in.png +0 -0
  110. icons/io.png +0 -0
  111. icons/iq.png +0 -0
  112. icons/ir.png +0 -0
  113. icons/is.png +0 -0
  114. icons/it.png +0 -0
  115. icons/jm.png +0 -0
  116. icons/jo.png +0 -0
  117. icons/jp.png +0 -0
  118. icons/ke.png +0 -0
  119. icons/kg.png +0 -0
  120. icons/kh.png +0 -0
  121. icons/ki.png +0 -0
  122. icons/km.png +0 -0
  123. icons/kn.png +0 -0
  124. icons/kp.png +0 -0
  125. icons/kr.png +0 -0
  126. icons/kw.png +0 -0
  127. icons/ky.png +0 -0
  128. icons/kz.png +0 -0
  129. icons/la.png +0 -0
  130. icons/lb.png +0 -0
  131. icons/lc.png +0 -0
  132. icons/li.png +0 -0
  133. icons/lk.png +0 -0
  134. icons/lr.png +0 -0
  135. icons/ls.png +0 -0
  136. icons/lt.png +0 -0
  137. icons/lu.png +0 -0
  138. icons/lv.png +0 -0
  139. icons/ly.png +0 -0
  140. icons/ma.png +0 -0
  141. icons/mc.png +0 -0
  142. icons/md.png +0 -0
  143. icons/me.png +0 -0
  144. icons/mg.png +0 -0
  145. icons/mh.png +0 -0
  146. icons/mk.png +0 -0
  147. icons/ml.png +0 -0
  148. icons/mm.png +0 -0
  149. icons/mn.png +0 -0
  150. icons/mo.png +0 -0
  151. icons/mp.png +0 -0
  152. icons/mq.png +0 -0
  153. icons/mr.png +0 -0
  154. icons/ms.png +0 -0
  155. icons/mt.png +0 -0
  156. icons/mu.png +0 -0
  157. icons/mv.png +0 -0
  158. icons/mw.png +0 -0
  159. icons/mx.png +0 -0
  160. icons/my.png +0 -0
  161. icons/mz.png +0 -0
  162. icons/na.png +0 -0
  163. icons/nc.png +0 -0
  164. icons/ne.png +0 -0
  165. icons/nf.png +0 -0
  166. icons/ng.png +0 -0
  167. icons/ni.png +0 -0
  168. icons/nl.png +0 -0
  169. icons/no.png +0 -0
  170. icons/np.png +0 -0
  171. icons/nr.png +0 -0
  172. icons/nu.png +0 -0
  173. icons/nz.png +0 -0
  174. icons/om.png +0 -0
  175. icons/pa.png +0 -0
  176. icons/pe.png +0 -0
  177. icons/pf.png +0 -0
  178. icons/pg.png +0 -0
  179. icons/ph.png +0 -0
  180. icons/pk.png +0 -0
  181. icons/pl.png +0 -0
  182. icons/pm.png +0 -0
  183. icons/pn.png +0 -0
  184. icons/pr.png +0 -0
  185. icons/ps.png +0 -0
  186. icons/pt.png +0 -0
  187. icons/pw.png +0 -0
  188. icons/py.png +0 -0
  189. icons/qa.png +0 -0
  190. icons/re.png +0 -0
  191. icons/ro.png +0 -0
  192. icons/rs.png +0 -0
  193. icons/ru.png +0 -0
  194. icons/rw.png +0 -0
  195. icons/sa.png +0 -0
  196. icons/sb.png +0 -0
  197. icons/sc.png +0 -0
  198. icons/scotland.png +0 -0
  199. icons/sd.png +0 -0
  200. icons/se.png +0 -0
  201. icons/sg.png +0 -0
  202. icons/sh.png +0 -0
  203. icons/si.png +0 -0
  204. icons/sj.png +0 -0
  205. icons/sk.png +0 -0
  206. icons/sl.png +0 -0
  207. icons/sm.png +0 -0
  208. icons/sn.png +0 -0
  209. icons/so.png +0 -0
  210. icons/sr.png +0 -0
  211. icons/st.png +0 -0
  212. icons/sv.png +0 -0
  213. icons/sy.png +0 -0
  214. icons/sz.png +0 -0
  215. icons/tc.png +0 -0
  216. icons/td.png +0 -0
  217. icons/tf.png +0 -0
  218. icons/tg.png +0 -0
  219. icons/th.png +0 -0
  220. icons/tj.png +0 -0
  221. icons/tk.png +0 -0
  222. icons/tl.png +0 -0
  223. icons/tm.png +0 -0
  224. icons/tn.png +0 -0
  225. icons/to.png +0 -0
  226. icons/tr.png +0 -0
  227. icons/tt.png +0 -0
  228. icons/tv.png +0 -0
  229. icons/tw.png +0 -0
  230. icons/tz.png +0 -0
  231. icons/ua.png +0 -0
  232. icons/ug.png +0 -0
  233. icons/um.png +0 -0
  234. icons/us.png +0 -0
  235. icons/uy.png +0 -0
  236. icons/uz.png +0 -0
  237. icons/va.png +0 -0
  238. icons/vc.png +0 -0
  239. icons/ve.png +0 -0
  240. icons/vg.png +0 -0
  241. icons/vi.png +0 -0
  242. icons/vn.png +0 -0
  243. icons/vu.png +0 -0
  244. icons/wales.png +0 -0
  245. icons/wf.png +0 -0
  246. icons/ws.png +0 -0
  247. icons/ye.png +0 -0
  248. icons/yt.png +0 -0
  249. icons/za.png +0 -0
  250. icons/zm.png +0 -0
  251. icons/zw.png +0 -0
  252. iq-block-country.php +277 -0
  253. libs/blockcountry-checks.php +167 -0
  254. libs/blockcountry-logging.php +62 -0
  255. libs/blockcountry-settings.php +431 -0
  256. libs/blockcountry-validation.php +55 -0
  257. libs/geoip.inc +770 -0
  258. readme.txt +271 -0
chosen-sprite.png ADDED
Binary file
chosen-sprite@2x.png ADDED
Binary file
chosen.css ADDED
@@ -0,0 +1,420 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* @group Base */
2
+ .chzn-container {
3
+ position: relative;
4
+ display: inline-block;
5
+ vertical-align: middle;
6
+ font-size: 13px;
7
+ zoom: 1;
8
+ *display: inline;
9
+ }
10
+ .chzn-container .chzn-drop {
11
+ position: absolute;
12
+ top: 100%;
13
+ left: -9999px;
14
+ z-index: 1010;
15
+ -webkit-box-sizing: border-box;
16
+ -moz-box-sizing: border-box;
17
+ box-sizing: border-box;
18
+ width: 100%;
19
+ border: 1px solid #aaa;
20
+ border-top: 0;
21
+ background: #fff;
22
+ box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
23
+ }
24
+ .chzn-container.chzn-with-drop .chzn-drop {
25
+ left: 0;
26
+ }
27
+
28
+ /* @end */
29
+ /* @group Single Chosen */
30
+ .chzn-container-single .chzn-single {
31
+ position: relative;
32
+ display: block;
33
+ overflow: hidden;
34
+ padding: 0 0 0 8px;
35
+ height: 23px;
36
+ border: 1px solid #aaa;
37
+ border-radius: 5px;
38
+ background-color: #fff;
39
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
40
+ background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
41
+ background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
42
+ background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
43
+ background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
44
+ background-clip: padding-box;
45
+ box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);
46
+ color: #444;
47
+ text-decoration: none;
48
+ white-space: nowrap;
49
+ line-height: 24px;
50
+ }
51
+ .chzn-container-single .chzn-default {
52
+ color: #999;
53
+ }
54
+ .chzn-container-single .chzn-single span {
55
+ display: block;
56
+ overflow: hidden;
57
+ margin-right: 26px;
58
+ text-overflow: ellipsis;
59
+ white-space: nowrap;
60
+ }
61
+ .chzn-container-single .chzn-single-with-deselect span {
62
+ margin-right: 38px;
63
+ }
64
+ .chzn-container-single .chzn-single abbr {
65
+ position: absolute;
66
+ top: 6px;
67
+ right: 26px;
68
+ display: block;
69
+ width: 12px;
70
+ height: 12px;
71
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
72
+ font-size: 1px;
73
+ }
74
+ .chzn-container-single .chzn-single abbr:hover {
75
+ background-position: -42px -10px;
76
+ }
77
+ .chzn-container-single.chzn-disabled .chzn-single abbr:hover {
78
+ background-position: -42px -10px;
79
+ }
80
+ .chzn-container-single .chzn-single div {
81
+ position: absolute;
82
+ top: 0;
83
+ right: 0;
84
+ display: block;
85
+ width: 18px;
86
+ height: 100%;
87
+ }
88
+ .chzn-container-single .chzn-single div b {
89
+ display: block;
90
+ width: 100%;
91
+ height: 100%;
92
+ background: url('chosen-sprite.png') no-repeat 0px 2px;
93
+ }
94
+ .chzn-container-single .chzn-search {
95
+ position: relative;
96
+ z-index: 1010;
97
+ margin: 0;
98
+ padding: 3px 4px;
99
+ white-space: nowrap;
100
+ }
101
+ .chzn-container-single .chzn-search input {
102
+ -webkit-box-sizing: border-box;
103
+ -moz-box-sizing: border-box;
104
+ box-sizing: border-box;
105
+ margin: 1px 0;
106
+ padding: 4px 20px 4px 5px;
107
+ width: 100%;
108
+ outline: 0;
109
+ border: 1px solid #aaa;
110
+ background: white url('chosen-sprite.png') no-repeat 100% -20px;
111
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
112
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
113
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
114
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
115
+ background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
116
+ font-size: 1em;
117
+ font-family: sans-serif;
118
+ }
119
+ .chzn-container-single .chzn-drop {
120
+ margin-top: -1px;
121
+ border-radius: 0 0 4px 4px;
122
+ background-clip: padding-box;
123
+ }
124
+ .chzn-container-single.chzn-container-single-nosearch .chzn-search {
125
+ position: absolute;
126
+ left: -9999px;
127
+ }
128
+
129
+ /* @end */
130
+ /* @group Results */
131
+ .chzn-container .chzn-results {
132
+ position: relative;
133
+ overflow-x: hidden;
134
+ overflow-y: auto;
135
+ margin: 0 4px 4px 0;
136
+ padding: 0 0 0 4px;
137
+ max-height: 240px;
138
+ -webkit-overflow-scrolling: touch;
139
+ }
140
+ .chzn-container .chzn-results li {
141
+ display: none;
142
+ margin: 0;
143
+ padding: 5px 6px;
144
+ list-style: none;
145
+ line-height: 15px;
146
+ }
147
+ .chzn-container .chzn-results li.active-result {
148
+ display: list-item;
149
+ cursor: pointer;
150
+ }
151
+ .chzn-container .chzn-results li.disabled-result {
152
+ display: list-item;
153
+ color: #ccc;
154
+ cursor: default;
155
+ }
156
+ .chzn-container .chzn-results li.highlighted {
157
+ background-color: #3875d7;
158
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
159
+ background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
160
+ background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
161
+ background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
162
+ background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
163
+ color: #fff;
164
+ }
165
+ .chzn-container .chzn-results li.no-results {
166
+ display: list-item;
167
+ background: #f4f4f4;
168
+ }
169
+ .chzn-container .chzn-results li.group-result {
170
+ display: list-item;
171
+ color: #999;
172
+ font-weight: bold;
173
+ cursor: default;
174
+ }
175
+ .chzn-container .chzn-results li.group-option {
176
+ padding-left: 15px;
177
+ }
178
+ .chzn-container .chzn-results li em {
179
+ font-style: normal;
180
+ text-decoration: underline;
181
+ }
182
+
183
+ /* @end */
184
+ /* @group Multi Chosen */
185
+ .chzn-container-multi .chzn-choices {
186
+ position: relative;
187
+ overflow: hidden;
188
+ -webkit-box-sizing: border-box;
189
+ -moz-box-sizing: border-box;
190
+ box-sizing: border-box;
191
+ margin: 0;
192
+ padding: 0;
193
+ width: 100%;
194
+ height: auto !important;
195
+ height: 1%;
196
+ border: 1px solid #aaa;
197
+ background-color: #fff;
198
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
199
+ background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
200
+ background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
201
+ background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
202
+ background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
203
+ cursor: text;
204
+ }
205
+ .chzn-container-multi .chzn-choices li {
206
+ float: left;
207
+ list-style: none;
208
+ }
209
+ .chzn-container-multi .chzn-choices li.search-field {
210
+ margin: 0;
211
+ padding: 0;
212
+ white-space: nowrap;
213
+ }
214
+ .chzn-container-multi .chzn-choices li.search-field input {
215
+ margin: 1px 0;
216
+ padding: 5px;
217
+ height: 15px;
218
+ outline: 0;
219
+ border: 0 !important;
220
+ background: transparent !important;
221
+ box-shadow: none;
222
+ color: #666;
223
+ font-size: 100%;
224
+ font-family: sans-serif;
225
+ }
226
+ .chzn-container-multi .chzn-choices li.search-field .default {
227
+ color: #999;
228
+ }
229
+ .chzn-container-multi .chzn-choices li.search-choice {
230
+ position: relative;
231
+ margin: 3px 0 3px 5px;
232
+ padding: 3px 20px 3px 5px;
233
+ border: 1px solid #aaa;
234
+ border-radius: 3px;
235
+ background-color: #e4e4e4;
236
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
237
+ background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
238
+ background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
239
+ background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
240
+ background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
241
+ background-clip: padding-box;
242
+ box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);
243
+ color: #333;
244
+ line-height: 13px;
245
+ cursor: default;
246
+ }
247
+ .chzn-container-multi .chzn-choices li.search-choice .search-choice-close {
248
+ position: absolute;
249
+ top: 4px;
250
+ right: 3px;
251
+ display: block;
252
+ width: 12px;
253
+ height: 12px;
254
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
255
+ font-size: 1px;
256
+ }
257
+ .chzn-container-multi .chzn-choices li.search-choice .search-choice-close:hover {
258
+ background-position: -42px -10px;
259
+ }
260
+ .chzn-container-multi .chzn-choices li.search-choice-disabled {
261
+ padding-right: 5px;
262
+ border: 1px solid #ccc;
263
+ background-color: #e4e4e4;
264
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
265
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
266
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
267
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
268
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
269
+ color: #666;
270
+ }
271
+ .chzn-container-multi .chzn-choices li.search-choice-focus {
272
+ background: #d4d4d4;
273
+ }
274
+ .chzn-container-multi .chzn-choices li.search-choice-focus .search-choice-close {
275
+ background-position: -42px -10px;
276
+ }
277
+ .chzn-container-multi .chzn-results {
278
+ margin: 0;
279
+ padding: 0;
280
+ }
281
+ .chzn-container-multi .chzn-drop .result-selected {
282
+ display: list-item;
283
+ color: #ccc;
284
+ cursor: default;
285
+ }
286
+
287
+ /* @end */
288
+ /* @group Active */
289
+ .chzn-container-active .chzn-single {
290
+ border: 1px solid #5897fb;
291
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
292
+ }
293
+ .chzn-container-active.chzn-with-drop .chzn-single {
294
+ border: 1px solid #aaa;
295
+ -moz-border-radius-bottomright: 0;
296
+ border-bottom-right-radius: 0;
297
+ -moz-border-radius-bottomleft: 0;
298
+ border-bottom-left-radius: 0;
299
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
300
+ background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%);
301
+ background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%);
302
+ background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%);
303
+ background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
304
+ box-shadow: 0 1px 0 #fff inset;
305
+ }
306
+ .chzn-container-active.chzn-with-drop .chzn-single div {
307
+ border-left: none;
308
+ background: transparent;
309
+ }
310
+ .chzn-container-active.chzn-with-drop .chzn-single div b {
311
+ background-position: -18px 2px;
312
+ }
313
+ .chzn-container-active .chzn-choices {
314
+ border: 1px solid #5897fb;
315
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
316
+ }
317
+ .chzn-container-active .chzn-choices li.search-field input {
318
+ color: #111 !important;
319
+ }
320
+
321
+ /* @end */
322
+ /* @group Disabled Support */
323
+ .chzn-disabled {
324
+ opacity: 0.5 !important;
325
+ cursor: default;
326
+ }
327
+ .chzn-disabled .chzn-single {
328
+ cursor: default;
329
+ }
330
+ .chzn-disabled .chzn-choices .search-choice .search-choice-close {
331
+ cursor: default;
332
+ }
333
+
334
+ /* @end */
335
+ /* @group Right to Left */
336
+ .chzn-rtl {
337
+ text-align: right;
338
+ }
339
+ .chzn-rtl .chzn-single {
340
+ overflow: visible;
341
+ padding: 0 8px 0 0;
342
+ }
343
+ .chzn-rtl .chzn-single span {
344
+ margin-right: 0;
345
+ margin-left: 26px;
346
+ direction: rtl;
347
+ }
348
+ .chzn-rtl .chzn-single-with-deselect span {
349
+ margin-left: 38px;
350
+ }
351
+ .chzn-rtl .chzn-single div {
352
+ right: auto;
353
+ left: 3px;
354
+ }
355
+ .chzn-rtl .chzn-single abbr {
356
+ right: auto;
357
+ left: 26px;
358
+ }
359
+ .chzn-rtl .chzn-choices li {
360
+ float: right;
361
+ }
362
+ .chzn-rtl .chzn-choices li.search-field input {
363
+ direction: rtl;
364
+ }
365
+ .chzn-rtl .chzn-choices li.search-choice {
366
+ margin: 3px 5px 3px 0;
367
+ padding: 3px 5px 3px 19px;
368
+ }
369
+ .chzn-rtl .chzn-choices li.search-choice .search-choice-close {
370
+ right: auto;
371
+ left: 4px;
372
+ }
373
+ .chzn-rtl.chzn-container-single-nosearch .chzn-search,
374
+ .chzn-rtl .chzn-drop {
375
+ left: 9999px;
376
+ }
377
+ .chzn-rtl.chzn-container-single .chzn-results {
378
+ margin: 0 0 4px 4px;
379
+ padding: 0 4px 0 0;
380
+ }
381
+ .chzn-rtl .chzn-results li.group-option {
382
+ padding-right: 15px;
383
+ padding-left: 0;
384
+ }
385
+ .chzn-rtl.chzn-container-active.chzn-with-drop .chzn-single div {
386
+ border-right: none;
387
+ }
388
+ .chzn-rtl .chzn-search input {
389
+ padding: 4px 5px 4px 20px;
390
+ background: white url('chosen-sprite.png') no-repeat -30px -20px;
391
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
392
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
393
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
394
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
395
+ background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
396
+ direction: rtl;
397
+ }
398
+ .chzn-rtl.chzn-container-single .chzn-single div b {
399
+ background-position: 6px 2px;
400
+ }
401
+ .chzn-rtl.chzn-container-single.chzn-with-drop .chzn-single div b {
402
+ background-position: -12px 2px;
403
+ }
404
+
405
+ /* @end */
406
+ /* @group Retina compatibility */
407
+ @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
408
+ .chzn-rtl .chzn-search input,
409
+ .chzn-container-single .chzn-single abbr,
410
+ .chzn-container-single .chzn-single div b,
411
+ .chzn-container-single .chzn-search input,
412
+ .chzn-container-multi .chzn-choices .search-choice .search-choice-close,
413
+ .chzn-container .chzn-results-scroll-down span,
414
+ .chzn-container .chzn-results-scroll-up span {
415
+ background-image: url('chosen-sprite@2x.png') !important;
416
+ background-size: 52px 37px !important;
417
+ background-repeat: no-repeat !important;
418
+ }
419
+ }
420
+ /* @end */
chosen.jquery.js ADDED
@@ -0,0 +1,1132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Chosen, a Select Box Enhancer for jQuery and Prototype
2
+ // by Patrick Filler for Harvest, http://getharvest.com
3
+ //
4
+ // Version 0.13.0
5
+ // Full source at https://github.com/harvesthq/chosen
6
+ // Copyright (c) 2011 Harvest http://getharvest.com
7
+
8
+ // MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
9
+ // This file is generated by `grunt build`, do not edit it by hand.
10
+ (function() {
11
+ var SelectParser;
12
+
13
+ SelectParser = (function() {
14
+ function SelectParser() {
15
+ this.options_index = 0;
16
+ this.parsed = [];
17
+ }
18
+
19
+ SelectParser.prototype.add_node = function(child) {
20
+ if (child.nodeName.toUpperCase() === "OPTGROUP") {
21
+ return this.add_group(child);
22
+ } else {
23
+ return this.add_option(child);
24
+ }
25
+ };
26
+
27
+ SelectParser.prototype.add_group = function(group) {
28
+ var group_position, option, _i, _len, _ref, _results;
29
+
30
+ group_position = this.parsed.length;
31
+ this.parsed.push({
32
+ array_index: group_position,
33
+ group: true,
34
+ label: this.escapeExpression(group.label),
35
+ children: 0,
36
+ disabled: group.disabled
37
+ });
38
+ _ref = group.childNodes;
39
+ _results = [];
40
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
41
+ option = _ref[_i];
42
+ _results.push(this.add_option(option, group_position, group.disabled));
43
+ }
44
+ return _results;
45
+ };
46
+
47
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
48
+ if (option.nodeName.toUpperCase() === "OPTION") {
49
+ if (option.text !== "") {
50
+ if (group_position != null) {
51
+ this.parsed[group_position].children += 1;
52
+ }
53
+ this.parsed.push({
54
+ array_index: this.parsed.length,
55
+ options_index: this.options_index,
56
+ value: option.value,
57
+ text: option.text,
58
+ html: option.innerHTML,
59
+ selected: option.selected,
60
+ disabled: group_disabled === true ? group_disabled : option.disabled,
61
+ group_array_index: group_position,
62
+ classes: option.className,
63
+ style: option.style.cssText
64
+ });
65
+ } else {
66
+ this.parsed.push({
67
+ array_index: this.parsed.length,
68
+ options_index: this.options_index,
69
+ empty: true
70
+ });
71
+ }
72
+ return this.options_index += 1;
73
+ }
74
+ };
75
+
76
+ SelectParser.prototype.escapeExpression = function(text) {
77
+ var map, unsafe_chars;
78
+
79
+ if ((text == null) || text === false) {
80
+ return "";
81
+ }
82
+ if (!/[\&\<\>\"\'\`]/.test(text)) {
83
+ return text;
84
+ }
85
+ map = {
86
+ "<": "&lt;",
87
+ ">": "&gt;",
88
+ '"': "&quot;",
89
+ "'": "&#x27;",
90
+ "`": "&#x60;"
91
+ };
92
+ unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
93
+ return text.replace(unsafe_chars, function(chr) {
94
+ return map[chr] || "&amp;";
95
+ });
96
+ };
97
+
98
+ return SelectParser;
99
+
100
+ })();
101
+
102
+ SelectParser.select_to_array = function(select) {
103
+ var child, parser, _i, _len, _ref;
104
+
105
+ parser = new SelectParser();
106
+ _ref = select.childNodes;
107
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
108
+ child = _ref[_i];
109
+ parser.add_node(child);
110
+ }
111
+ return parser.parsed;
112
+ };
113
+
114
+ this.SelectParser = SelectParser;
115
+
116
+ }).call(this);
117
+
118
+ (function() {
119
+ var AbstractChosen, root;
120
+
121
+ root = this;
122
+
123
+ AbstractChosen = (function() {
124
+ function AbstractChosen(form_field, options) {
125
+ this.form_field = form_field;
126
+ this.options = options != null ? options : {};
127
+ if (!AbstractChosen.browser_is_supported()) {
128
+ return;
129
+ }
130
+ this.is_multiple = this.form_field.multiple;
131
+ this.set_default_text();
132
+ this.set_default_values();
133
+ this.setup();
134
+ this.set_up_html();
135
+ this.register_observers();
136
+ this.finish_setup();
137
+ }
138
+
139
+ AbstractChosen.prototype.set_default_values = function() {
140
+ var _this = this;
141
+
142
+ this.click_test_action = function(evt) {
143
+ return _this.test_active_click(evt);
144
+ };
145
+ this.activate_action = function(evt) {
146
+ return _this.activate_field(evt);
147
+ };
148
+ this.active_field = false;
149
+ this.mouse_on_container = false;
150
+ this.results_showing = false;
151
+ this.result_highlighted = null;
152
+ this.result_single_selected = null;
153
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
154
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
155
+ this.disable_search = this.options.disable_search || false;
156
+ this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
157
+ this.group_search = this.options.group_search != null ? this.options.group_search : true;
158
+ this.search_contains = this.options.search_contains || false;
159
+ this.single_backstroke_delete = this.options.single_backstroke_delete || false;
160
+ this.max_selected_options = this.options.max_selected_options || Infinity;
161
+ return this.inherit_select_classes = this.options.inherit_select_classes || false;
162
+ };
163
+
164
+ AbstractChosen.prototype.set_default_text = function() {
165
+ if (this.form_field.getAttribute("data-placeholder")) {
166
+ this.default_text = this.form_field.getAttribute("data-placeholder");
167
+ } else if (this.is_multiple) {
168
+ this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
169
+ } else {
170
+ this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
171
+ }
172
+ return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
173
+ };
174
+
175
+ AbstractChosen.prototype.mouse_enter = function() {
176
+ return this.mouse_on_container = true;
177
+ };
178
+
179
+ AbstractChosen.prototype.mouse_leave = function() {
180
+ return this.mouse_on_container = false;
181
+ };
182
+
183
+ AbstractChosen.prototype.input_focus = function(evt) {
184
+ var _this = this;
185
+
186
+ if (this.is_multiple) {
187
+ if (!this.active_field) {
188
+ return setTimeout((function() {
189
+ return _this.container_mousedown();
190
+ }), 50);
191
+ }
192
+ } else {
193
+ if (!this.active_field) {
194
+ return this.activate_field();
195
+ }
196
+ }
197
+ };
198
+
199
+ AbstractChosen.prototype.input_blur = function(evt) {
200
+ var _this = this;
201
+
202
+ if (!this.mouse_on_container) {
203
+ this.active_field = false;
204
+ return setTimeout((function() {
205
+ return _this.blur_test();
206
+ }), 100);
207
+ }
208
+ };
209
+
210
+ AbstractChosen.prototype.results_option_build = function(options) {
211
+ var content, data, _i, _len, _ref;
212
+
213
+ content = '';
214
+ _ref = this.results_data;
215
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
216
+ data = _ref[_i];
217
+ if (data.group && (data.search_match || data.group_match)) {
218
+ content += this.result_add_group(data);
219
+ } else if (!data.empty && data.search_match) {
220
+ content += this.result_add_option(data);
221
+ }
222
+ if (options != null ? options.first : void 0) {
223
+ if (data.selected && this.is_multiple) {
224
+ this.choice_build(data);
225
+ } else if (data.selected && !this.is_multiple) {
226
+ this.single_set_selected_text(data.text);
227
+ }
228
+ }
229
+ }
230
+ return content;
231
+ };
232
+
233
+ AbstractChosen.prototype.result_add_option = function(option) {
234
+ var classes, style;
235
+
236
+ classes = [];
237
+ if (!option.disabled && !(option.selected && this.is_multiple)) {
238
+ classes.push("active-result");
239
+ }
240
+ if (option.disabled && !(option.selected && this.is_multiple)) {
241
+ classes.push("disabled-result");
242
+ }
243
+ if (option.selected) {
244
+ classes.push("result-selected");
245
+ }
246
+ if (option.group_array_index != null) {
247
+ classes.push("group-option");
248
+ }
249
+ if (option.classes !== "") {
250
+ classes.push(option.classes);
251
+ }
252
+ style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : "";
253
+ return "<li class=\"" + (classes.join(' ')) + "\"" + style + " data-option-array-index=\"" + option.array_index + "\">" + option.search_text + "</li>";
254
+ };
255
+
256
+ AbstractChosen.prototype.result_add_group = function(group) {
257
+ return "<li class=\"group-result\">" + group.search_text + "</li>";
258
+ };
259
+
260
+ AbstractChosen.prototype.results_update_field = function() {
261
+ this.set_default_text();
262
+ if (!this.is_multiple) {
263
+ this.results_reset_cleanup();
264
+ }
265
+ this.result_clear_highlight();
266
+ this.result_single_selected = null;
267
+ this.results_build();
268
+ if (this.results_showing) {
269
+ return this.winnow_results();
270
+ }
271
+ };
272
+
273
+ AbstractChosen.prototype.results_toggle = function() {
274
+ if (this.results_showing) {
275
+ return this.results_hide();
276
+ } else {
277
+ return this.results_show();
278
+ }
279
+ };
280
+
281
+ AbstractChosen.prototype.results_search = function(evt) {
282
+ if (this.results_showing) {
283
+ return this.winnow_results();
284
+ } else {
285
+ return this.results_show();
286
+ }
287
+ };
288
+
289
+ AbstractChosen.prototype.winnow_results = function() {
290
+ var option, regex, regexAnchor, results, searchText, startpos, text, zregex, _i, _len, _ref;
291
+
292
+ this.no_results_clear();
293
+ results = 0;
294
+ searchText = this.get_search_text();
295
+ regexAnchor = this.search_contains ? "" : "^";
296
+ regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
297
+ zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
298
+ _ref = this.results_data;
299
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
300
+ option = _ref[_i];
301
+ if (!option.empty) {
302
+ if (option.group) {
303
+ option.group_match = false;
304
+ }
305
+ if (!(option.group && !this.group_search)) {
306
+ option.search_match = false;
307
+ option.search_text = option.group ? option.label : option.html;
308
+ option.search_match = this.search_string_match(option.search_text, regex);
309
+ if (option.search_match) {
310
+ results += 1;
311
+ }
312
+ if (option.search_match) {
313
+ if (searchText.length) {
314
+ startpos = option.search_text.search(zregex);
315
+ text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
316
+ option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
317
+ }
318
+ if (option.group_array_index != null) {
319
+ this.results_data[option.group_array_index].group_match = true;
320
+ }
321
+ } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
322
+ option.search_match = true;
323
+ }
324
+ }
325
+ }
326
+ }
327
+ if (results < 1 && searchText.length) {
328
+ this.update_results_content("");
329
+ this.result_clear_highlight();
330
+ return this.no_results(searchText);
331
+ } else {
332
+ this.update_results_content(this.results_option_build());
333
+ return this.winnow_results_set_highlight();
334
+ }
335
+ };
336
+
337
+ AbstractChosen.prototype.search_string_match = function(search_string, regex) {
338
+ var part, parts, _i, _len;
339
+
340
+ if (regex.test(search_string)) {
341
+ return true;
342
+ } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
343
+ parts = search_string.replace(/\[|\]/g, "").split(" ");
344
+ if (parts.length) {
345
+ for (_i = 0, _len = parts.length; _i < _len; _i++) {
346
+ part = parts[_i];
347
+ if (regex.test(part)) {
348
+ return true;
349
+ }
350
+ }
351
+ }
352
+ }
353
+ };
354
+
355
+ AbstractChosen.prototype.choices_count = function() {
356
+ var option, _i, _len, _ref;
357
+
358
+ if (this.selected_option_count != null) {
359
+ return this.selected_option_count;
360
+ }
361
+ this.selected_option_count = 0;
362
+ _ref = this.form_field.options;
363
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
364
+ option = _ref[_i];
365
+ if (option.selected) {
366
+ this.selected_option_count += 1;
367
+ }
368
+ }
369
+ return this.selected_option_count;
370
+ };
371
+
372
+ AbstractChosen.prototype.choices_click = function(evt) {
373
+ evt.preventDefault();
374
+ if (!(this.results_showing || this.is_disabled)) {
375
+ return this.results_show();
376
+ }
377
+ };
378
+
379
+ AbstractChosen.prototype.keyup_checker = function(evt) {
380
+ var stroke, _ref;
381
+
382
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
383
+ this.search_field_scale();
384
+ switch (stroke) {
385
+ case 8:
386
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
387
+ return this.keydown_backstroke();
388
+ } else if (!this.pending_backstroke) {
389
+ this.result_clear_highlight();
390
+ return this.results_search();
391
+ }
392
+ break;
393
+ case 13:
394
+ evt.preventDefault();
395
+ if (this.results_showing) {
396
+ return this.result_select(evt);
397
+ }
398
+ break;
399
+ case 27:
400
+ if (this.results_showing) {
401
+ this.results_hide();
402
+ }
403
+ return true;
404
+ case 9:
405
+ case 38:
406
+ case 40:
407
+ case 16:
408
+ case 91:
409
+ case 17:
410
+ break;
411
+ default:
412
+ return this.results_search();
413
+ }
414
+ };
415
+
416
+ AbstractChosen.prototype.container_width = function() {
417
+ if (this.options.width != null) {
418
+ return this.options.width;
419
+ } else {
420
+ return "" + this.form_field.offsetWidth + "px";
421
+ }
422
+ };
423
+
424
+ AbstractChosen.browser_is_supported = function() {
425
+ var _ref;
426
+
427
+ if (window.navigator.appName === "Microsoft Internet Explorer") {
428
+ return (null !== (_ref = document.documentMode) && _ref >= 8);
429
+ }
430
+ return true;
431
+ };
432
+
433
+ AbstractChosen.default_multiple_text = "Select Some Options";
434
+
435
+ AbstractChosen.default_single_text = "Select an Option";
436
+
437
+ AbstractChosen.default_no_result_text = "No results match";
438
+
439
+ return AbstractChosen;
440
+
441
+ })();
442
+
443
+ root.AbstractChosen = AbstractChosen;
444
+
445
+ }).call(this);
446
+
447
+ (function() {
448
+ var $, Chosen, root, _ref,
449
+ __hasProp = {}.hasOwnProperty,
450
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
451
+
452
+ root = this;
453
+
454
+ $ = jQuery;
455
+
456
+ $.fn.extend({
457
+ chosen: function(options) {
458
+ if (!AbstractChosen.browser_is_supported()) {
459
+ return this;
460
+ }
461
+ return this.each(function(input_field) {
462
+ var $this;
463
+
464
+ $this = $(this);
465
+ if (!$this.hasClass("chzn-done")) {
466
+ return $this.data('chosen', new Chosen(this, options));
467
+ }
468
+ });
469
+ }
470
+ });
471
+
472
+ Chosen = (function(_super) {
473
+ __extends(Chosen, _super);
474
+
475
+ function Chosen() {
476
+ _ref = Chosen.__super__.constructor.apply(this, arguments);
477
+ return _ref;
478
+ }
479
+
480
+ Chosen.prototype.setup = function() {
481
+ this.form_field_jq = $(this.form_field);
482
+ this.current_selectedIndex = this.form_field.selectedIndex;
483
+ return this.is_rtl = this.form_field_jq.hasClass("chzn-rtl");
484
+ };
485
+
486
+ Chosen.prototype.finish_setup = function() {
487
+ return this.form_field_jq.addClass("chzn-done");
488
+ };
489
+
490
+ Chosen.prototype.set_up_html = function() {
491
+ var container_classes, container_props;
492
+
493
+ container_classes = ["chzn-container"];
494
+ container_classes.push("chzn-container-" + (this.is_multiple ? "multi" : "single"));
495
+ if (this.inherit_select_classes && this.form_field.className) {
496
+ container_classes.push(this.form_field.className);
497
+ }
498
+ if (this.is_rtl) {
499
+ container_classes.push("chzn-rtl");
500
+ }
501
+ container_props = {
502
+ 'class': container_classes.join(' '),
503
+ 'style': "width: " + (this.container_width()) + ";",
504
+ 'title': this.form_field.title
505
+ };
506
+ if (this.form_field.id.length) {
507
+ container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chzn";
508
+ }
509
+ this.container = $("<div />", container_props);
510
+ if (this.is_multiple) {
511
+ this.container.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop"><ul class="chzn-results"></ul></div>');
512
+ } else {
513
+ this.container.html('<a href="javascript:void(0)" class="chzn-single chzn-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>');
514
+ }
515
+ this.form_field_jq.hide().after(this.container);
516
+ this.dropdown = this.container.find('div.chzn-drop').first();
517
+ this.search_field = this.container.find('input').first();
518
+ this.search_results = this.container.find('ul.chzn-results').first();
519
+ this.search_field_scale();
520
+ this.search_no_results = this.container.find('li.no-results').first();
521
+ if (this.is_multiple) {
522
+ this.search_choices = this.container.find('ul.chzn-choices').first();
523
+ this.search_container = this.container.find('li.search-field').first();
524
+ } else {
525
+ this.search_container = this.container.find('div.chzn-search').first();
526
+ this.selected_item = this.container.find('.chzn-single').first();
527
+ }
528
+ this.results_build();
529
+ this.set_tab_index();
530
+ this.set_label_behavior();
531
+ return this.form_field_jq.trigger("liszt:ready", {
532
+ chosen: this
533
+ });
534
+ };
535
+
536
+ Chosen.prototype.register_observers = function() {
537
+ var _this = this;
538
+
539
+ this.container.mousedown(function(evt) {
540
+ _this.container_mousedown(evt);
541
+ });
542
+ this.container.mouseup(function(evt) {
543
+ _this.container_mouseup(evt);
544
+ });
545
+ this.container.mouseenter(function(evt) {
546
+ _this.mouse_enter(evt);
547
+ });
548
+ this.container.mouseleave(function(evt) {
549
+ _this.mouse_leave(evt);
550
+ });
551
+ this.search_results.mouseup(function(evt) {
552
+ _this.search_results_mouseup(evt);
553
+ });
554
+ this.search_results.mouseover(function(evt) {
555
+ _this.search_results_mouseover(evt);
556
+ });
557
+ this.search_results.mouseout(function(evt) {
558
+ _this.search_results_mouseout(evt);
559
+ });
560
+ this.search_results.bind('mousewheel DOMMouseScroll', function(evt) {
561
+ _this.search_results_mousewheel(evt);
562
+ });
563
+ this.form_field_jq.bind("liszt:updated", function(evt) {
564
+ _this.results_update_field(evt);
565
+ });
566
+ this.form_field_jq.bind("liszt:activate", function(evt) {
567
+ _this.activate_field(evt);
568
+ });
569
+ this.form_field_jq.bind("liszt:open", function(evt) {
570
+ _this.container_mousedown(evt);
571
+ });
572
+ this.search_field.blur(function(evt) {
573
+ _this.input_blur(evt);
574
+ });
575
+ this.search_field.keyup(function(evt) {
576
+ _this.keyup_checker(evt);
577
+ });
578
+ this.search_field.keydown(function(evt) {
579
+ _this.keydown_checker(evt);
580
+ });
581
+ this.search_field.focus(function(evt) {
582
+ _this.input_focus(evt);
583
+ });
584
+ if (this.is_multiple) {
585
+ return this.search_choices.click(function(evt) {
586
+ _this.choices_click(evt);
587
+ });
588
+ } else {
589
+ return this.container.click(function(evt) {
590
+ evt.preventDefault();
591
+ });
592
+ }
593
+ };
594
+
595
+ Chosen.prototype.search_field_disabled = function() {
596
+ this.is_disabled = this.form_field_jq[0].disabled;
597
+ if (this.is_disabled) {
598
+ this.container.addClass('chzn-disabled');
599
+ this.search_field[0].disabled = true;
600
+ if (!this.is_multiple) {
601
+ this.selected_item.unbind("focus", this.activate_action);
602
+ }
603
+ return this.close_field();
604
+ } else {
605
+ this.container.removeClass('chzn-disabled');
606
+ this.search_field[0].disabled = false;
607
+ if (!this.is_multiple) {
608
+ return this.selected_item.bind("focus", this.activate_action);
609
+ }
610
+ }
611
+ };
612
+
613
+ Chosen.prototype.container_mousedown = function(evt) {
614
+ if (!this.is_disabled) {
615
+ if (evt && evt.type === "mousedown" && !this.results_showing) {
616
+ evt.preventDefault();
617
+ }
618
+ if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
619
+ if (!this.active_field) {
620
+ if (this.is_multiple) {
621
+ this.search_field.val("");
622
+ }
623
+ $(document).click(this.click_test_action);
624
+ this.results_show();
625
+ } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chzn-single").length)) {
626
+ evt.preventDefault();
627
+ this.results_toggle();
628
+ }
629
+ return this.activate_field();
630
+ }
631
+ }
632
+ };
633
+
634
+ Chosen.prototype.container_mouseup = function(evt) {
635
+ if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
636
+ return this.results_reset(evt);
637
+ }
638
+ };
639
+
640
+ Chosen.prototype.search_results_mousewheel = function(evt) {
641
+ var delta, _ref1, _ref2;
642
+
643
+ delta = -((_ref1 = evt.originalEvent) != null ? _ref1.wheelDelta : void 0) || ((_ref2 = evt.originialEvent) != null ? _ref2.detail : void 0);
644
+ if (delta != null) {
645
+ evt.preventDefault();
646
+ if (evt.type === 'DOMMouseScroll') {
647
+ delta = delta * 40;
648
+ }
649
+ return this.search_results.scrollTop(delta + this.search_results.scrollTop());
650
+ }
651
+ };
652
+
653
+ Chosen.prototype.blur_test = function(evt) {
654
+ if (!this.active_field && this.container.hasClass("chzn-container-active")) {
655
+ return this.close_field();
656
+ }
657
+ };
658
+
659
+ Chosen.prototype.close_field = function() {
660
+ $(document).unbind("click", this.click_test_action);
661
+ this.active_field = false;
662
+ this.results_hide();
663
+ this.container.removeClass("chzn-container-active");
664
+ this.clear_backstroke();
665
+ this.show_search_field_default();
666
+ return this.search_field_scale();
667
+ };
668
+
669
+ Chosen.prototype.activate_field = function() {
670
+ this.container.addClass("chzn-container-active");
671
+ this.active_field = true;
672
+ this.search_field.val(this.search_field.val());
673
+ return this.search_field.focus();
674
+ };
675
+
676
+ Chosen.prototype.test_active_click = function(evt) {
677
+ if (this.container.is($(evt.target).closest('.chzn-container'))) {
678
+ return this.active_field = true;
679
+ } else {
680
+ return this.close_field();
681
+ }
682
+ };
683
+
684
+ Chosen.prototype.results_build = function() {
685
+ this.parsing = true;
686
+ this.selected_option_count = null;
687
+ this.results_data = root.SelectParser.select_to_array(this.form_field);
688
+ if (this.is_multiple) {
689
+ this.search_choices.find("li.search-choice").remove();
690
+ } else if (!this.is_multiple) {
691
+ this.single_set_selected_text();
692
+ if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
693
+ this.search_field[0].readOnly = true;
694
+ this.container.addClass("chzn-container-single-nosearch");
695
+ } else {
696
+ this.search_field[0].readOnly = false;
697
+ this.container.removeClass("chzn-container-single-nosearch");
698
+ }
699
+ }
700
+ this.update_results_content(this.results_option_build({
701
+ first: true
702
+ }));
703
+ this.search_field_disabled();
704
+ this.show_search_field_default();
705
+ this.search_field_scale();
706
+ return this.parsing = false;
707
+ };
708
+
709
+ Chosen.prototype.result_do_highlight = function(el) {
710
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
711
+
712
+ if (el.length) {
713
+ this.result_clear_highlight();
714
+ this.result_highlight = el;
715
+ this.result_highlight.addClass("highlighted");
716
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
717
+ visible_top = this.search_results.scrollTop();
718
+ visible_bottom = maxHeight + visible_top;
719
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
720
+ high_bottom = high_top + this.result_highlight.outerHeight();
721
+ if (high_bottom >= visible_bottom) {
722
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
723
+ } else if (high_top < visible_top) {
724
+ return this.search_results.scrollTop(high_top);
725
+ }
726
+ }
727
+ };
728
+
729
+ Chosen.prototype.result_clear_highlight = function() {
730
+ if (this.result_highlight) {
731
+ this.result_highlight.removeClass("highlighted");
732
+ }
733
+ return this.result_highlight = null;
734
+ };
735
+
736
+ Chosen.prototype.results_show = function() {
737
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
738
+ this.form_field_jq.trigger("liszt:maxselected", {
739
+ chosen: this
740
+ });
741
+ return false;
742
+ }
743
+ this.container.addClass("chzn-with-drop");
744
+ this.form_field_jq.trigger("liszt:showing_dropdown", {
745
+ chosen: this
746
+ });
747
+ this.results_showing = true;
748
+ this.search_field.focus();
749
+ this.search_field.val(this.search_field.val());
750
+ return this.winnow_results();
751
+ };
752
+
753
+ Chosen.prototype.update_results_content = function(content) {
754
+ return this.search_results.html(content);
755
+ };
756
+
757
+ Chosen.prototype.results_hide = function() {
758
+ if (this.results_showing) {
759
+ this.result_clear_highlight();
760
+ this.container.removeClass("chzn-with-drop");
761
+ this.form_field_jq.trigger("liszt:hiding_dropdown", {
762
+ chosen: this
763
+ });
764
+ }
765
+ return this.results_showing = false;
766
+ };
767
+
768
+ Chosen.prototype.set_tab_index = function(el) {
769
+ var ti;
770
+
771
+ if (this.form_field_jq.attr("tabindex")) {
772
+ ti = this.form_field_jq.attr("tabindex");
773
+ this.form_field_jq.attr("tabindex", -1);
774
+ return this.search_field.attr("tabindex", ti);
775
+ }
776
+ };
777
+
778
+ Chosen.prototype.set_label_behavior = function() {
779
+ var _this = this;
780
+
781
+ this.form_field_label = this.form_field_jq.parents("label");
782
+ if (!this.form_field_label.length && this.form_field.id.length) {
783
+ this.form_field_label = $("label[for='" + this.form_field.id + "']");
784
+ }
785
+ if (this.form_field_label.length > 0) {
786
+ return this.form_field_label.click(function(evt) {
787
+ if (_this.is_multiple) {
788
+ return _this.container_mousedown(evt);
789
+ } else {
790
+ return _this.activate_field();
791
+ }
792
+ });
793
+ }
794
+ };
795
+
796
+ Chosen.prototype.show_search_field_default = function() {
797
+ if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
798
+ this.search_field.val(this.default_text);
799
+ return this.search_field.addClass("default");
800
+ } else {
801
+ this.search_field.val("");
802
+ return this.search_field.removeClass("default");
803
+ }
804
+ };
805
+
806
+ Chosen.prototype.search_results_mouseup = function(evt) {
807
+ var target;
808
+
809
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
810
+ if (target.length) {
811
+ this.result_highlight = target;
812
+ this.result_select(evt);
813
+ return this.search_field.focus();
814
+ }
815
+ };
816
+
817
+ Chosen.prototype.search_results_mouseover = function(evt) {
818
+ var target;
819
+
820
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
821
+ if (target) {
822
+ return this.result_do_highlight(target);
823
+ }
824
+ };
825
+
826
+ Chosen.prototype.search_results_mouseout = function(evt) {
827
+ if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
828
+ return this.result_clear_highlight();
829
+ }
830
+ };
831
+
832
+ Chosen.prototype.choice_build = function(item) {
833
+ var choice, close_link,
834
+ _this = this;
835
+
836
+ choice = $('<li />', {
837
+ "class": "search-choice"
838
+ }).html("<span>" + item.html + "</span>");
839
+ if (item.disabled) {
840
+ choice.addClass('search-choice-disabled');
841
+ } else {
842
+ close_link = $('<a />', {
843
+ href: '#',
844
+ "class": 'search-choice-close',
845
+ rel: item.array_index
846
+ });
847
+ close_link.click(function(evt) {
848
+ return _this.choice_destroy_link_click(evt);
849
+ });
850
+ choice.append(close_link);
851
+ }
852
+ return this.search_container.before(choice);
853
+ };
854
+
855
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
856
+ evt.preventDefault();
857
+ evt.stopPropagation();
858
+ if (!this.is_disabled) {
859
+ return this.choice_destroy($(evt.target));
860
+ }
861
+ };
862
+
863
+ Chosen.prototype.choice_destroy = function(link) {
864
+ if (this.result_deselect(link.attr("rel"))) {
865
+ this.show_search_field_default();
866
+ if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
867
+ this.results_hide();
868
+ }
869
+ link.parents('li').first().remove();
870
+ return this.search_field_scale();
871
+ }
872
+ };
873
+
874
+ Chosen.prototype.results_reset = function() {
875
+ this.form_field.options[0].selected = true;
876
+ this.selected_option_count = null;
877
+ this.single_set_selected_text();
878
+ this.show_search_field_default();
879
+ this.results_reset_cleanup();
880
+ this.form_field_jq.trigger("change");
881
+ if (this.active_field) {
882
+ return this.results_hide();
883
+ }
884
+ };
885
+
886
+ Chosen.prototype.results_reset_cleanup = function() {
887
+ this.current_selectedIndex = this.form_field.selectedIndex;
888
+ return this.selected_item.find("abbr").remove();
889
+ };
890
+
891
+ Chosen.prototype.result_select = function(evt) {
892
+ var high, item;
893
+
894
+ if (this.result_highlight) {
895
+ high = this.result_highlight;
896
+ this.result_clear_highlight();
897
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
898
+ this.form_field_jq.trigger("liszt:maxselected", {
899
+ chosen: this
900
+ });
901
+ return false;
902
+ }
903
+ if (this.is_multiple) {
904
+ high.removeClass("active-result");
905
+ } else {
906
+ this.search_results.find(".result-selected").removeClass("result-selected");
907
+ this.result_single_selected = high;
908
+ }
909
+ high.addClass("result-selected");
910
+ item = this.results_data[high[0].getAttribute("data-option-array-index")];
911
+ item.selected = true;
912
+ this.form_field.options[item.options_index].selected = true;
913
+ this.selected_option_count = null;
914
+ if (this.is_multiple) {
915
+ this.choice_build(item);
916
+ } else {
917
+ this.single_set_selected_text(item.text);
918
+ }
919
+ if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
920
+ this.results_hide();
921
+ }
922
+ this.search_field.val("");
923
+ if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
924
+ this.form_field_jq.trigger("change", {
925
+ 'selected': this.form_field.options[item.options_index].value
926
+ });
927
+ }
928
+ this.current_selectedIndex = this.form_field.selectedIndex;
929
+ return this.search_field_scale();
930
+ }
931
+ };
932
+
933
+ Chosen.prototype.single_set_selected_text = function(text) {
934
+ if (text == null) {
935
+ text = this.default_text;
936
+ }
937
+ if (text === this.default_text) {
938
+ this.selected_item.addClass("chzn-default");
939
+ } else {
940
+ this.single_deselect_control_build();
941
+ this.selected_item.removeClass("chzn-default");
942
+ }
943
+ return this.selected_item.find("span").text(text);
944
+ };
945
+
946
+ Chosen.prototype.result_deselect = function(pos) {
947
+ var result_data;
948
+
949
+ result_data = this.results_data[pos];
950
+ if (!this.form_field.options[result_data.options_index].disabled) {
951
+ result_data.selected = false;
952
+ this.form_field.options[result_data.options_index].selected = false;
953
+ this.selected_option_count = null;
954
+ this.result_clear_highlight();
955
+ if (this.results_showing) {
956
+ this.winnow_results();
957
+ }
958
+ this.form_field_jq.trigger("change", {
959
+ deselected: this.form_field.options[result_data.options_index].value
960
+ });
961
+ this.search_field_scale();
962
+ return true;
963
+ } else {
964
+ return false;
965
+ }
966
+ };
967
+
968
+ Chosen.prototype.single_deselect_control_build = function() {
969
+ if (!this.allow_single_deselect) {
970
+ return;
971
+ }
972
+ if (!this.selected_item.find("abbr").length) {
973
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
974
+ }
975
+ return this.selected_item.addClass("chzn-single-with-deselect");
976
+ };
977
+
978
+ Chosen.prototype.get_search_text = function() {
979
+ if (this.search_field.val() === this.default_text) {
980
+ return "";
981
+ } else {
982
+ return $('<div/>').text($.trim(this.search_field.val())).html();
983
+ }
984
+ };
985
+
986
+ Chosen.prototype.winnow_results_set_highlight = function() {
987
+ var do_high, selected_results;
988
+
989
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
990
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
991
+ if (do_high != null) {
992
+ return this.result_do_highlight(do_high);
993
+ }
994
+ };
995
+
996
+ Chosen.prototype.no_results = function(terms) {
997
+ var no_results_html;
998
+
999
+ no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
1000
+ no_results_html.find("span").first().html(terms);
1001
+ return this.search_results.append(no_results_html);
1002
+ };
1003
+
1004
+ Chosen.prototype.no_results_clear = function() {
1005
+ return this.search_results.find(".no-results").remove();
1006
+ };
1007
+
1008
+ Chosen.prototype.keydown_arrow = function() {
1009
+ var next_sib;
1010
+
1011
+ if (this.results_showing && this.result_highlight) {
1012
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
1013
+ if (next_sib) {
1014
+ return this.result_do_highlight(next_sib);
1015
+ }
1016
+ } else {
1017
+ return this.results_show();
1018
+ }
1019
+ };
1020
+
1021
+ Chosen.prototype.keyup_arrow = function() {
1022
+ var prev_sibs;
1023
+
1024
+ if (!this.results_showing && !this.is_multiple) {
1025
+ return this.results_show();
1026
+ } else if (this.result_highlight) {
1027
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
1028
+ if (prev_sibs.length) {
1029
+ return this.result_do_highlight(prev_sibs.first());
1030
+ } else {
1031
+ if (this.choices_count() > 0) {
1032
+ this.results_hide();
1033
+ }
1034
+ return this.result_clear_highlight();
1035
+ }
1036
+ }
1037
+ };
1038
+
1039
+ Chosen.prototype.keydown_backstroke = function() {
1040
+ var next_available_destroy;
1041
+
1042
+ if (this.pending_backstroke) {
1043
+ this.choice_destroy(this.pending_backstroke.find("a").first());
1044
+ return this.clear_backstroke();
1045
+ } else {
1046
+ next_available_destroy = this.search_container.siblings("li.search-choice").last();
1047
+ if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
1048
+ this.pending_backstroke = next_available_destroy;
1049
+ if (this.single_backstroke_delete) {
1050
+ return this.keydown_backstroke();
1051
+ } else {
1052
+ return this.pending_backstroke.addClass("search-choice-focus");
1053
+ }
1054
+ }
1055
+ }
1056
+ };
1057
+
1058
+ Chosen.prototype.clear_backstroke = function() {
1059
+ if (this.pending_backstroke) {
1060
+ this.pending_backstroke.removeClass("search-choice-focus");
1061
+ }
1062
+ return this.pending_backstroke = null;
1063
+ };
1064
+
1065
+ Chosen.prototype.keydown_checker = function(evt) {
1066
+ var stroke, _ref1;
1067
+
1068
+ stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
1069
+ this.search_field_scale();
1070
+ if (stroke !== 8 && this.pending_backstroke) {
1071
+ this.clear_backstroke();
1072
+ }
1073
+ switch (stroke) {
1074
+ case 8:
1075
+ this.backstroke_length = this.search_field.val().length;
1076
+ break;
1077
+ case 9:
1078
+ if (this.results_showing && !this.is_multiple) {
1079
+ this.result_select(evt);
1080
+ }
1081
+ this.mouse_on_container = false;
1082
+ break;
1083
+ case 13:
1084
+ evt.preventDefault();
1085
+ break;
1086
+ case 38:
1087
+ evt.preventDefault();
1088
+ this.keyup_arrow();
1089
+ break;
1090
+ case 40:
1091
+ evt.preventDefault();
1092
+ this.keydown_arrow();
1093
+ break;
1094
+ }
1095
+ };
1096
+
1097
+ Chosen.prototype.search_field_scale = function() {
1098
+ var div, f_width, h, style, style_block, styles, w, _i, _len;
1099
+
1100
+ if (this.is_multiple) {
1101
+ h = 0;
1102
+ w = 0;
1103
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
1104
+ styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
1105
+ for (_i = 0, _len = styles.length; _i < _len; _i++) {
1106
+ style = styles[_i];
1107
+ style_block += style + ":" + this.search_field.css(style) + ";";
1108
+ }
1109
+ div = $('<div />', {
1110
+ 'style': style_block
1111
+ });
1112
+ div.text(this.search_field.val());
1113
+ $('body').append(div);
1114
+ w = div.width() + 25;
1115
+ div.remove();
1116
+ f_width = this.container.outerWidth();
1117
+ if (w > f_width - 10) {
1118
+ w = f_width - 10;
1119
+ }
1120
+ return this.search_field.css({
1121
+ 'width': w + 'px'
1122
+ });
1123
+ }
1124
+ };
1125
+
1126
+ return Chosen;
1127
+
1128
+ })(AbstractChosen);
1129
+
1130
+ root.Chosen = Chosen;
1131
+
1132
+ }).call(this);
icons/ad.png ADDED
Binary file
icons/ae.png ADDED
Binary file
icons/af.png ADDED
Binary file
icons/ag.png ADDED
Binary file
icons/ai.png ADDED
Binary file
icons/al.png ADDED
Binary file
icons/am.png ADDED
Binary file
icons/an.png ADDED
Binary file
icons/ao.png ADDED
Binary file
icons/ar.png ADDED
Binary file
icons/as.png ADDED
Binary file
icons/at.png ADDED
Binary file
icons/au.png ADDED
Binary file
icons/aw.png ADDED
Binary file
icons/ax.png ADDED
Binary file
icons/az.png ADDED
Binary file
icons/ba.png ADDED
Binary file
icons/bb.png ADDED
Binary file
icons/bd.png ADDED
Binary file
icons/be.png ADDED
Binary file
icons/bf.png ADDED
Binary file
icons/bg.png ADDED
Binary file
icons/bh.png ADDED
Binary file
icons/bi.png ADDED
Binary file
icons/bj.png ADDED
Binary file
icons/bm.png ADDED
Binary file
icons/bn.png ADDED
Binary file
icons/bo.png ADDED
Binary file
icons/br.png ADDED
Binary file
icons/bs.png ADDED
Binary file
icons/bt.png ADDED
Binary file
icons/bv.png ADDED
Binary file
icons/bw.png ADDED
Binary file
icons/by.png ADDED
Binary file
icons/bz.png ADDED
Binary file
icons/ca.png ADDED
Binary file
icons/catalonia.png ADDED
Binary file
icons/cc.png ADDED
Binary file
icons/cd.png ADDED
Binary file
icons/cf.png ADDED
Binary file
icons/cg.png ADDED
Binary file
icons/ch.png ADDED
Binary file
icons/ci.png ADDED
Binary file
icons/ck.png ADDED
Binary file
icons/cl.png ADDED
Binary file
icons/cm.png ADDED
Binary file
icons/cn.png ADDED
Binary file
icons/co.png ADDED
Binary file
icons/cr.png ADDED
Binary file
icons/cs.png ADDED
Binary file
icons/cu.png ADDED
Binary file
icons/cv.png ADDED
Binary file
icons/cx.png ADDED
Binary file
icons/cy.png ADDED
Binary file
icons/cz.png ADDED
Binary file
icons/de.png ADDED
Binary file
icons/dj.png ADDED
Binary file
icons/dk.png ADDED
Binary file
icons/dm.png ADDED
Binary file
icons/do.png ADDED
Binary file
icons/dz.png ADDED
Binary file
icons/ec.png ADDED
Binary file
icons/ee.png ADDED
Binary file
icons/eg.png ADDED
Binary file
icons/eh.png ADDED
Binary file
icons/england.png ADDED
Binary file
icons/er.png ADDED
Binary file
icons/es.png ADDED
Binary file
icons/et.png ADDED
Binary file
icons/eu.png ADDED
Binary file
icons/fam.png ADDED
Binary file
icons/fi.png ADDED
Binary file
icons/fj.png ADDED
Binary file
icons/fk.png ADDED
Binary file
icons/fm.png ADDED
Binary file
icons/fo.png ADDED
Binary file
icons/fr.png ADDED
Binary file
icons/ga.png ADDED
Binary file
icons/gb.png ADDED
Binary file
icons/gd.png ADDED
Binary file
icons/ge.png ADDED
Binary file
icons/gf.png ADDED
Binary file
icons/gh.png ADDED
Binary file
icons/gi.png ADDED
Binary file
icons/gl.png ADDED
Binary file
icons/gm.png ADDED
Binary file
icons/gn.png ADDED
Binary file
icons/gp.png ADDED
Binary file
icons/gq.png ADDED
Binary file
icons/gr.png ADDED
Binary file
icons/gs.png ADDED
Binary file
icons/gt.png ADDED
Binary file
icons/gu.png ADDED
Binary file
icons/gw.png ADDED
Binary file
icons/gy.png ADDED
Binary file
icons/hk.png ADDED
Binary file
icons/hm.png ADDED
Binary file
icons/hn.png ADDED
Binary file
icons/hr.png ADDED
Binary file
icons/ht.png ADDED
Binary file
icons/hu.png ADDED
Binary file
icons/id.png ADDED
Binary file
icons/ie.png ADDED
Binary file
icons/il.png ADDED
Binary file
icons/in.png ADDED
Binary file
icons/io.png ADDED
Binary file
icons/iq.png ADDED
Binary file
icons/ir.png ADDED
Binary file
icons/is.png ADDED
Binary file
icons/it.png ADDED
Binary file
icons/jm.png ADDED
Binary file
icons/jo.png ADDED
Binary file
icons/jp.png ADDED
Binary file
icons/ke.png ADDED
Binary file
icons/kg.png ADDED
Binary file
icons/kh.png ADDED
Binary file
icons/ki.png ADDED
Binary file
icons/km.png ADDED
Binary file
icons/kn.png ADDED
Binary file
icons/kp.png ADDED
Binary file
icons/kr.png ADDED
Binary file
icons/kw.png ADDED
Binary file
icons/ky.png ADDED
Binary file
icons/kz.png ADDED
Binary file
icons/la.png ADDED
Binary file
icons/lb.png ADDED
Binary file
icons/lc.png ADDED
Binary file
icons/li.png ADDED
Binary file
icons/lk.png ADDED
Binary file
icons/lr.png ADDED
Binary file
icons/ls.png ADDED
Binary file
icons/lt.png ADDED
Binary file
icons/lu.png ADDED
Binary file
icons/lv.png ADDED
Binary file
icons/ly.png ADDED
Binary file
icons/ma.png ADDED
Binary file
icons/mc.png ADDED
Binary file
icons/md.png ADDED
Binary file
icons/me.png ADDED
Binary file
icons/mg.png ADDED
Binary file
icons/mh.png ADDED
Binary file
icons/mk.png ADDED
Binary file
icons/ml.png ADDED
Binary file
icons/mm.png ADDED
Binary file
icons/mn.png ADDED
Binary file
icons/mo.png ADDED
Binary file
icons/mp.png ADDED
Binary file
icons/mq.png ADDED
Binary file
icons/mr.png ADDED
Binary file
icons/ms.png ADDED
Binary file
icons/mt.png ADDED
Binary file
icons/mu.png ADDED
Binary file
icons/mv.png ADDED
Binary file
icons/mw.png ADDED
Binary file
icons/mx.png ADDED
Binary file
icons/my.png ADDED
Binary file
icons/mz.png ADDED
Binary file
icons/na.png ADDED
Binary file
icons/nc.png ADDED
Binary file
icons/ne.png ADDED
Binary file
icons/nf.png ADDED
Binary file
icons/ng.png ADDED
Binary file
icons/ni.png ADDED
Binary file
icons/nl.png ADDED
Binary file
icons/no.png ADDED
Binary file
icons/np.png ADDED
Binary file
icons/nr.png ADDED
Binary file
icons/nu.png ADDED
Binary file
icons/nz.png ADDED
Binary file
icons/om.png ADDED
Binary file
icons/pa.png ADDED
Binary file
icons/pe.png ADDED
Binary file
icons/pf.png ADDED
Binary file
icons/pg.png ADDED
Binary file
icons/ph.png ADDED
Binary file
icons/pk.png ADDED
Binary file
icons/pl.png ADDED
Binary file
icons/pm.png ADDED
Binary file
icons/pn.png ADDED
Binary file
icons/pr.png ADDED
Binary file
icons/ps.png ADDED
Binary file
icons/pt.png ADDED
Binary file
icons/pw.png ADDED
Binary file
icons/py.png ADDED
Binary file
icons/qa.png ADDED
Binary file
icons/re.png ADDED
Binary file
icons/ro.png ADDED
Binary file
icons/rs.png ADDED
Binary file
icons/ru.png ADDED
Binary file
icons/rw.png ADDED
Binary file
icons/sa.png ADDED
Binary file
icons/sb.png ADDED
Binary file
icons/sc.png ADDED
Binary file
icons/scotland.png ADDED
Binary file
icons/sd.png ADDED
Binary file
icons/se.png ADDED
Binary file
icons/sg.png ADDED
Binary file
icons/sh.png ADDED
Binary file
icons/si.png ADDED
Binary file
icons/sj.png ADDED
Binary file
icons/sk.png ADDED
Binary file
icons/sl.png ADDED
Binary file
icons/sm.png ADDED
Binary file
icons/sn.png ADDED
Binary file
icons/so.png ADDED
Binary file
icons/sr.png ADDED
Binary file
icons/st.png ADDED
Binary file
icons/sv.png ADDED
Binary file
icons/sy.png ADDED
Binary file
icons/sz.png ADDED
Binary file
icons/tc.png ADDED
Binary file
icons/td.png ADDED
Binary file
icons/tf.png ADDED
Binary file
icons/tg.png ADDED
Binary file
icons/th.png ADDED
Binary file
icons/tj.png ADDED
Binary file
icons/tk.png ADDED
Binary file
icons/tl.png ADDED
Binary file
icons/tm.png ADDED
Binary file
icons/tn.png ADDED
Binary file
icons/to.png ADDED
Binary file
icons/tr.png ADDED
Binary file
icons/tt.png ADDED
Binary file
icons/tv.png ADDED
Binary file
icons/tw.png ADDED
Binary file
icons/tz.png ADDED
Binary file
icons/ua.png ADDED
Binary file
icons/ug.png ADDED
Binary file
icons/um.png ADDED
Binary file
icons/us.png ADDED
Binary file
icons/uy.png ADDED
Binary file
icons/uz.png ADDED
Binary file
icons/va.png ADDED
Binary file
icons/vc.png ADDED
Binary file
icons/ve.png ADDED
Binary file
icons/vg.png ADDED
Binary file
icons/vi.png ADDED
Binary file
icons/vn.png ADDED
Binary file
icons/vu.png ADDED
Binary file
icons/wales.png ADDED
Binary file
icons/wf.png ADDED
Binary file
icons/ws.png ADDED
Binary file
icons/ye.png ADDED
Binary file
icons/yt.png ADDED
Binary file
icons/za.png ADDED
Binary file
icons/zm.png ADDED
Binary file
icons/zw.png ADDED
Binary file
iq-block-country.php ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: iQ Block Country
4
+ Plugin URI: http://www.redeo.nl/2013/12/iq-block-country-wordpress-plugin-blocks-countries/
5
+ Version: 1.1
6
+ Author: Pascal
7
+ Author URI: http://www.redeo.nl/
8
+ Description: Block visitors from visiting your website and backend website based on which country their IP address is from. The Maxmind GeoIP lite database is used for looking up from which country an ip address is from.
9
+ License: GPL2
10
+ */
11
+
12
+ /* This script uses GeoLite Country from MaxMind (http://www.maxmind.com) which is available under terms of GPL/LGPL */
13
+
14
+ /* Copyright 2010-2013 Pascal (email : pascal@redeo.nl)
15
+
16
+ This program is free software; you can redistribute it and/or modify
17
+ it under the terms of the GNU General Public License, version 2, as
18
+ published by the Free Software Foundation.
19
+
20
+ This program is distributed in the hope that it will be useful,
21
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
+ GNU General Public License for more details.
24
+
25
+ You should have received a copy of the GNU General Public License
26
+ along with this program; if not, write to the Free Software
27
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
+ */
29
+
30
+ /*
31
+ *
32
+ * This software is dedicated to my one true love.
33
+ * Luvya :)
34
+ *
35
+ */
36
+
37
+ /*
38
+ * Try to make this plugin the first plugin that is loaded.
39
+ * Because we output header info we don't want other plugins to send output first.
40
+ */
41
+ function iqblockcountry_this_plugin_first()
42
+ {
43
+ $wp_path_to_this_file = preg_replace('/(.*)plugins\/(.*)$/', WP_PLUGIN_DIR."/$2", __FILE__);
44
+ $this_plugin = plugin_basename(trim($wp_path_to_this_file));
45
+ $active_plugins = get_option('active_plugins');
46
+ $this_plugin_key = array_search($this_plugin, $active_plugins);
47
+ if ($this_plugin_key) { // if it's 0 it's the first plugin already, no need to continue
48
+ array_splice($active_plugins, $this_plugin_key, 1);
49
+ array_unshift($active_plugins, $this_plugin);
50
+ update_option('active_plugins', $active_plugins);
51
+ }
52
+ }
53
+
54
+ /*
55
+ * Download the GeoIP database from MaxMind
56
+ */
57
+ function iqblockcountry_downloadgeodatabase($version, $displayerror)
58
+ {
59
+
60
+ if( !class_exists( 'WP_Http' ) )
61
+ include_once( ABSPATH . WPINC. '/class-http.php' );
62
+
63
+ if ($version == 6)
64
+ {
65
+ $url = IPV6DB;
66
+ $geofile = IPV6DBFILE;
67
+ }
68
+ else
69
+ {
70
+ $url = IPV4DB;
71
+ $geofile = IPV4DBFILE;
72
+ }
73
+
74
+ $request = new WP_Http ();
75
+ $result = $request->request ( $url );
76
+ $content = array ();
77
+
78
+ if ((in_array ( '403', $result ['response'] )) && (preg_match('/Rate limited exceeded, please try again in 24 hours./', $result['body'] )) ) {
79
+ if($displayerror){
80
+ ?>
81
+ <p>Error occured: Could not download the GeoIP database from <?php echo $url;?><br />
82
+ MaxMind has blocked requests from your IP address for 24 hours. Please check again in 24 hours or download this file from your own PC<br />
83
+ unzip this file and upload it (via FTP for instance) to:<br /> <strong><?php echo $geofile;?></strong></p>
84
+ <?php
85
+ }
86
+ }
87
+ elseif ((isset ( $result->errors )) || (! (in_array ( '200', $result ['response'] )))) {
88
+ if($displayerror){
89
+ ?>
90
+ <p>Error occured: Could not download the GeoIP database from <?php echo $url;?><br />
91
+ Please download this file from your own PC unzip this file and upload it (via FTP for instance) to:<br />
92
+ <strong><?php echo $geofile;?></strong></p>
93
+ <?php
94
+ }
95
+ } else {
96
+
97
+ /* Download file */
98
+ if (file_exists ( $geofile . ".gz" )) { unlink ( $geofile . ".gz" ); }
99
+ $content = $result ['body'];
100
+ $fp = fopen ( $geofile . ".gz", "w" );
101
+ fwrite ( $fp, "$content" );
102
+ fclose ( $fp );
103
+
104
+ /* Unzip this file and throw it away afterwards*/
105
+ $zd = gzopen ( $geofile . ".gz", "r" );
106
+ $buffer = gzread ( $zd, 2000000 );
107
+ gzclose ( $zd );
108
+ if (file_exists ( $geofile . ".gz" )) { unlink ( $geofile . ".gz" ); }
109
+
110
+ /* Write this file to the GeoIP database file */
111
+ if (file_exists ( $geofile )) { unlink ( $geofile ); }
112
+ $fp = fopen ( $geofile, "w" );
113
+ fwrite ( $fp, "$buffer" );
114
+ fclose ( $fp );
115
+ update_option('blockcountry_lastupdate' , time());
116
+ if($displayerror){
117
+ print "<p>Finished downloading</p>";
118
+ }
119
+ }
120
+ if (! (file_exists ( IPV4DBFILE ))) {
121
+ if($displayerror){
122
+ ?>
123
+ <p>Fatal error: GeoIP <?php echo IPV4DBFILE ?> database does not exists. This plugin will not work until the database file is present.</p>
124
+ <?php
125
+ }
126
+ }
127
+ }
128
+
129
+ /*
130
+ * Get list of countries from Geo Database
131
+ */
132
+ function iqblockcountry_get_countries()
133
+ {
134
+ global $countrylist;
135
+
136
+ $countrylist = array();
137
+ if (!class_exists('GeoIP'))
138
+ {
139
+ include_once("libs/geoip.inc");
140
+ }
141
+ if (class_exists('GeoIP'))
142
+ {
143
+ /* Create an array with all countries that the database knows */
144
+ $geo = new GeoIP ();
145
+ $countrycodes = $geo->GEOIP_COUNTRY_CODE_TO_NUMBER;
146
+ $countries = $geo->GEOIP_COUNTRY_NAMES;
147
+ $countrylist = array ();
148
+ foreach ( $countrycodes as $key => $value ) {
149
+ if (!empty($value))
150
+ {
151
+ $countrylist [$key] = $countries [$value];
152
+ }
153
+ }
154
+ array_multisort($countrylist);
155
+
156
+ return $countrylist;
157
+ }
158
+
159
+ return $countylist;
160
+ }
161
+
162
+ /*
163
+ * Retrieves the IP address from the HTTP Headers
164
+ */
165
+
166
+ function iqblockcountry_get_ipaddress() {
167
+ global $ip_address;
168
+
169
+ $ip_address = "";
170
+ if (empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
171
+ $ip_address = $_SERVER["REMOTE_ADDR"];
172
+ } else {
173
+ $ip_address = $_SERVER["HTTP_X_FORWARDED_FOR"];
174
+ }
175
+ return $ip_address;
176
+ }
177
+
178
+ function iqblockcountry_upgrade()
179
+ {
180
+ /* Check if update is necessary */
181
+ $dbversion = get_option( 'blockcountry_version' );
182
+
183
+ if ($dbversion != "" && version_compare($dbversion, "1.0.10", '<') )
184
+ {
185
+ iqblockcountry_install_db();
186
+ add_option( "blockcountry_dbversion", DBVERSION );
187
+ // Get banlist option and convert to backend banlist
188
+ update_option('blockcountry_version',VERSION);
189
+ $frontendbanlist = get_option('blockcountry_banlist');
190
+ update_option('blockcountry_backendbanlist',$frontendbanlist);
191
+ update_option('blockcountry_backendnrblocks', 0);
192
+ update_option('blockcountry_frontendnrblocks', 0);
193
+ update_option('blockcountry_header', 'on');
194
+ }
195
+ elseif ($dbversion != "" && version_compare($dbversion, "1.0.10", '=') )
196
+ {
197
+ iqblockcountry_install_db();
198
+ add_option( "blockcountry_dbversion", DBVERSION );
199
+ update_option('blockcountry_backendnrblocks', 0);
200
+ update_option('blockcountry_frontendnrblocks', 0);
201
+ update_option('blockcountry_header', 'on');
202
+ update_option('blockcountry_version',VERSION);
203
+ }
204
+ elseif ($dbversion != "" && version_compare($dbversion, "1.0.11", '=') )
205
+ {
206
+ iqblockcountry_install_db();
207
+ add_option( "blockcountry_dbversion", DBVERSION );
208
+ update_option('blockcountry_version',VERSION);
209
+ }
210
+ elseif ($dbversion == "")
211
+ {
212
+ iqblockcountry_install_db();
213
+ add_option( "blockcountry_dbversion", DBVERSION );
214
+ update_option('blockcountry_lastupdate' , 0);
215
+ update_option('blockcountry_blockfrontend' , 'on');
216
+ update_option('blockcountry_version',VERSION);
217
+ update_option('blockcountry_backendnrblocks', 0);
218
+ update_option('blockcountry_frontendnrblocks', 0);
219
+ update_option('blockcountry_header', 'on');
220
+ $frontendbanlist = get_option('blockcountry_banlist');
221
+ update_option('blockcountry_backendbanlist',$frontendbanlist);
222
+ }
223
+ iqblockcountry_update_db_check();
224
+
225
+ }
226
+
227
+ /*
228
+ * Include libraries
229
+ */
230
+ require_once('libs/blockcountry-checks.php');
231
+ require_once('libs/blockcountry-settings.php');
232
+ require_once('libs/blockcountry-validation.php');
233
+ require_once('libs/blockcountry-logging.php');
234
+
235
+ /*
236
+ * Main plugin works.
237
+ */
238
+ define("CHOSENJS", plugins_url('/chosen.jquery.js', __FILE__));
239
+ define("CHOSENCSS", plugins_url('/chosen.css', __FILE__));
240
+ define("IPV6DB","http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz");
241
+ define("IPV4DB","http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz");
242
+ define("IPV4DBFILE",WP_PLUGIN_DIR . "/" . dirname ( plugin_basename ( __FILE__ ) ) . "/GeoIP.dat");
243
+ define("IPV6DBFILE",WP_PLUGIN_DIR . "/" . dirname ( plugin_basename ( __FILE__ ) ) . "/GeoIPv6.dat");
244
+ define("VERSION","1.1d");
245
+ define("DBVERSION","110");
246
+ define("PLUGINPATH",plugin_dir_path( __FILE__ ));
247
+
248
+
249
+ register_activation_hook(__file__, 'iqblockcountry_this_plugin_first');
250
+ register_activation_hook(__file__, 'iqblockcountry_set_defaults');
251
+ register_uninstall_hook(__file__, 'iqblockcountry_uninstall');
252
+
253
+ // Check if upgrade is necessary
254
+ iqblockcountry_upgrade();
255
+
256
+ /* Clean logging database */
257
+ iqblockcountry_clean_db();
258
+
259
+ /*
260
+ * Check first if users want to block the backend.
261
+ */
262
+ if ((iqblockcountry_is_login_page() || is_admin()) && get_option('blockcountry_blockbackend'))
263
+ {
264
+ add_action ( 'login_head', 'iqblockcountry_checkCountry', 1 );
265
+ }
266
+ /*
267
+ * Check first if users want to block the frontend.
268
+ */
269
+ if (get_option('blockcountry_blockfrontend'))
270
+ {
271
+ add_action ( 'wp_head', 'iqblockcountry_checkCountry', 1 );
272
+ }
273
+
274
+ add_action ( 'admin_menu', 'iqblockcountry_create_menu' );
275
+ add_action ( 'admin_init', 'iqblockcountry_checkupdatedb' );
276
+
277
+ ?>
libs/blockcountry-checks.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ function iqblockcountry_check_ipaddress($ip_address)
5
+ {
6
+ if (!class_exists('GeoIP'))
7
+ {
8
+ include_once("geoip.inc");
9
+ }
10
+
11
+ if ((file_exists ( IPV4DBFILE )) && function_exists('geoip_open')) {
12
+
13
+ $ipv4 = FALSE;
14
+ $ipv6 = FALSE;
15
+ if (iqblockcountry_is_valid_ipv4($ip_address)) { $ipv4 = TRUE; }
16
+ if (iqblockcountry_is_valid_ipv6($ip_address)) { $ipv6 = TRUE; }
17
+
18
+ if ($ipv4)
19
+ {
20
+ $gi = geoip_open ( IPV4DBFILE, GEOIP_STANDARD );
21
+ $country = geoip_country_code_by_addr ( $gi, $ip_address );
22
+ geoip_close ( $gi );
23
+ }
24
+ elseif ($ipv6)
25
+ {
26
+ if (file_exists ( IPV6DBFILE )) {
27
+ $gi = geoip_open(IPV6DBFILE,GEOIP_STANDARD);
28
+ $country = geoip_country_code_by_addr_v6 ( $gi, $ip_address );
29
+ geoip_close($gi);
30
+ }
31
+ else {
32
+ $country = 'ipv6';
33
+ }
34
+ }
35
+ else { $country = "Unknown"; }
36
+ }
37
+ else { $country = "Unknown"; }
38
+
39
+ return $country;
40
+ }
41
+
42
+ /*
43
+ * Check country against bad countries, whitelist and blacklist
44
+ */
45
+ function iqblockcountry_check($country,$badcountries,$ip_address)
46
+ {
47
+ $blocked = FALSE;
48
+ if (is_array ( $badcountries ) && in_array ( $country, $badcountries )) {
49
+ $blocked = TRUE;
50
+ }
51
+
52
+ if (!iqblockcountry_is_login_page() )
53
+ {
54
+ $frontendwhitelist = get_option ( 'blockcountry_frontendwhitelist' );
55
+ if (preg_match('/;/',$frontendwhitelist))
56
+ {
57
+ $arr = explode(";", $frontendwhitelist);
58
+ if (is_array ( $arr ) && in_array ( $ip_address, $arr)) {
59
+ $blocked = FALSE;
60
+ }
61
+ }
62
+ $frontendblacklist = get_option ( 'blockcountry_frontendblacklist' );
63
+ if (preg_match('/;/',$frontendblacklist))
64
+ {
65
+ $arr = explode(";", $frontendblacklist);
66
+ if (is_array ( $arr ) && in_array ( $ip_address, $arr)) {
67
+ $blocked = TRUE;
68
+ }
69
+ }
70
+ }
71
+ return $blocked;
72
+ }
73
+
74
+ /*
75
+ * Does the real check of visitor IP against MaxMind database.
76
+ * Looks up country in the Maxmind database and if needed blocks IP.
77
+ */
78
+ function iqblockcountry_CheckCountry() {
79
+
80
+ $ip_address = "";
81
+ if (empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
82
+ $ip_address = $_SERVER["REMOTE_ADDR"];
83
+ } else {
84
+ $ip_address = $_SERVER["HTTP_X_FORWARDED_FOR"];
85
+ }
86
+
87
+ $ip_address = iqblockcountry_get_ipaddress();
88
+ $country = iqblockcountry_check_ipaddress($ip_address);
89
+
90
+ if ((iqblockcountry_is_login_page() || is_admin()) && get_option('blockcountry_blockbackend'))
91
+ {
92
+ $badcountries = get_option( 'blockcountry_backendbanlist' );
93
+ }
94
+ else
95
+ {
96
+ $badcountries = get_option( 'blockcountry_banlist' );
97
+ }
98
+ $blocklogin = get_option ( 'blockcountry_blocklogin' );
99
+ if ( ((is_user_logged_in()) && ($blocklogin != "on")) || (!(is_user_logged_in())) ) {
100
+
101
+ /* Check ip address against banlist, whitelist and blacklist */
102
+ if (iqblockcountry_check($country,$badcountries,$ip_address))
103
+ {
104
+ $blockmessage = get_option ( 'blockcountry_blockmessage' );
105
+ $header = get_option('blockcountry_header');
106
+ if (!empty($header) && ($header))
107
+ {
108
+ // Prevent as much as possible that this error message is cached:
109
+ header("Cache-Control: no-store, no-cache, must-revalidate");
110
+ header("Cache-Control: post-check=0, pre-check=0", false);
111
+ header("Pragma: no-cache");
112
+ header("Expires: Sat, 26 Jul 2012 05:00:00 GMT");
113
+
114
+ header ( 'HTTP/1.1 403 Forbidden' );
115
+ }
116
+ // Display block message
117
+ print "$blockmessage";
118
+
119
+ if ((iqblockcountry_is_login_page() || is_admin()) && get_option('blockcountry_blockbackend'))
120
+ {
121
+ $blocked = get_option('blockcountry_backendnrblocks');
122
+ if (empty($blocked)) { $blocked = 0; }
123
+ $blocked++;
124
+ update_option('blockcountry_backendnrblocks', $blocked);
125
+ iqblockcountry_logging($ip_address, $country, "B");
126
+ }
127
+ else
128
+ {
129
+ $blocked = get_option('blockcountry_frontendnrblocks');
130
+ if (empty($blocked)) { $blocked = 0; }
131
+ $blocked++;
132
+ update_option('blockcountry_frontendnrblocks', $blocked);
133
+ iqblockcountry_logging($ip_address, $country, "F");
134
+ }
135
+
136
+ exit ();
137
+ }
138
+
139
+ }
140
+
141
+ }
142
+
143
+
144
+ /*
145
+ * Check if page is the login page
146
+ */
147
+ function iqblockcountry_is_login_page() {
148
+ return !strncmp($_SERVER['REQUEST_URI'], '/wp-login.php', strlen('/wp-login.php'));
149
+ }
150
+
151
+ /*
152
+ * Check if Geo databases needs to be updated.
153
+ */
154
+ function iqblockcountry_checkupdatedb()
155
+ {
156
+ $lastupdate = get_option('blockcountry_lastupdate');
157
+ if (empty($lastupdate)) { $lastupdate = 0; }
158
+ $time = $lastupdate + 86400 * 31;
159
+
160
+ if(time() > $time)
161
+ {
162
+ iqblockcountry_downloadgeodatabase("4", false);
163
+ iqblockcountry_downloadgeodatabase("6", false);
164
+ update_option('blockcountry_lastupdate' , time());
165
+
166
+ }
167
+ }
libs/blockcountry-logging.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function iqblockcountry_install_db() {
4
+ global $wpdb;
5
+
6
+ $table_name = $wpdb->prefix . "iqblock_logging";
7
+
8
+ $sql = "CREATE TABLE IF NOT EXISTS $table_name (
9
+ id mediumint(9) NOT NULL AUTO_INCREMENT,
10
+ datetime datetime NOT NULL,
11
+ ipaddress tinytext NOT NULL,
12
+ country tinytext NOT NULL,
13
+ url varchar(250) DEFAULT '/' NOT NULL,
14
+ banned enum('F','B') NOT NULL,
15
+ PRIMARY KEY (id),
16
+ UNIQUE KEY id (id)
17
+ );";
18
+
19
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
20
+ dbDelta( $sql );
21
+ }
22
+
23
+ function iqblockcountry_uninstall_db() {
24
+ global $wpdb;
25
+
26
+ $table_name = $wpdb->prefix . "iqblock_logging";
27
+
28
+ $sql = "DROP TABLE IF EXISTS `$table_name`;";
29
+
30
+ $wpdb->query($sql);
31
+
32
+ delete_option( "blockcountry_dbversion");
33
+ }
34
+
35
+ function iqblockcountry_clean_db()
36
+ {
37
+ global $wpdb;
38
+
39
+ $table_name = $wpdb->prefix . "iqblock_logging";
40
+ $sql = "DELETE FROM " . $table_name . " WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) >= datetime;";
41
+ $wpdb->query($sql);
42
+
43
+ }
44
+
45
+
46
+ function iqblockcountry_update_db_check() {
47
+ if (get_site_option( 'blockcountry_dbversion' ) != DBVERSION) {
48
+ iqblockcountry_install_db();
49
+ update_option( "blockcountry_dbversion", DBVERSION );
50
+ }
51
+ }
52
+
53
+ function iqblockcountry_logging($ipaddress,$country,$banend)
54
+ {
55
+ require_once( ABSPATH . 'wp-config.php');
56
+ global $wpdb;
57
+
58
+ $urlRequested = (isset($_SERVER["REQUEST_URI"]) ? $_SERVER["REQUEST_URI"] : '/' );
59
+
60
+ $table_name = $wpdb->prefix . "iqblock_logging";
61
+ $wpdb->insert($table_name,array ('datetime' => current_time('mysql'), 'ipaddress' => $ipaddress, 'country' => $country, 'banned' => $banend,'url' => $urlRequested));
62
+ }
libs/blockcountry-settings.php ADDED
@@ -0,0 +1,431 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * Create the wp-admin menu for iQ Block Country
5
+ */
6
+ function iqblockcountry_create_menu()
7
+ {
8
+ //create new menu option in the settings department
9
+ add_submenu_page ( 'options-general.php', 'iQ Block Country', 'iQ Block Country', 'administrator', __FILE__, 'iqblockcountry_settings_page' );
10
+ //call register settings function
11
+ add_action ( 'admin_init', 'iqblockcountry_register_mysettings' );
12
+ }
13
+
14
+ /*
15
+ * Register all settings.
16
+ */
17
+ function iqblockcountry_register_mysettings()
18
+ {
19
+ //register our settings
20
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_banlist' );
21
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_backendbanlist' );
22
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_backendblacklist','iqblockcountry_validate_ip');
23
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_backendwhitelist','iqblockcountry_validate_ip');
24
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_frontendblacklist','iqblockcountry_validate_ip');
25
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_frontendwhitelist','iqblockcountry_validate_ip');
26
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_blockmessage' );
27
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_blocklogin' );
28
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_blockfrontend' );
29
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_blockbackend' );
30
+ register_setting ( 'iqblockcountry-settings-group', 'blockcountry_header');
31
+ }
32
+
33
+ /*
34
+ * Set default values when activating this plugin.
35
+ */
36
+ function iqblockcountry_set_defaults()
37
+ {
38
+
39
+ update_option('blockcountry_version',VERSION);
40
+ update_option('blockcountry_lastupdate' , 0);
41
+ update_option('blockcountry_blockfrontend' , 'on');
42
+ update_option('blockcountry_backendnrblocks', 0);
43
+ update_option('blockcountry_frontendnrblocks', 0);
44
+ update_option('blockcountry_header', 'on');
45
+ iqblockcountry_install_db();
46
+
47
+ }
48
+
49
+
50
+ function iqblockcountry_uninstall() //deletes all the database entries that the plugin has created
51
+ {
52
+ iqblockcountry_uninstall_db();
53
+ delete_option('blockcountry_banlist' );
54
+ delete_option('blockcountry_backendbanlist' );
55
+ delete_option('blockcountry_backendblacklist' );
56
+ delete_option('blockcountry_backendwhitelist' );
57
+ delete_option('blockcountry_frontendblacklist' );
58
+ delete_option('blockcountry_frontendwhitelist' );
59
+ delete_option('blockcountry_blockmessage' );
60
+ delete_option('blockcountry_backendnrblocks' );
61
+ delete_option('blockcountry_frontendnrblocks' );
62
+ delete_option('blockcountry_blocklogin' );
63
+ delete_option('blockcountry_blockfrontend' );
64
+ delete_option('blockcountry_blockbackend' );
65
+ delete_option('blockcountry_lastupdate');
66
+ delete_option('blockcountry_version');
67
+ delete_option('blockcountry_header');
68
+ }
69
+
70
+
71
+ function iqblockcountry_settings_tools() {
72
+ ?>
73
+ <h3>Check which country belongs to an IP Address according to the current database.</h3>
74
+
75
+ <form name="ipcheck" action="#ipcheck" method="post">
76
+ <input type="hidden" name="action" value="ipcheck" />
77
+ IP Address to check: <input type="text" name="ipaddress" lenth="50" />
78
+ <?php
79
+ if ( isset($_POST['action']) && $_POST[ 'action' ] == 'ipcheck') {
80
+ if (isset($_POST['ipaddress']) && !empty($_POST['ipaddress']))
81
+ {
82
+ $ip_address = $_POST['ipaddress'];
83
+ $country = iqblockcountry_check_ipaddress($ip_address);
84
+ $countrylist = iqblockcountry_get_countries();
85
+ if ($country == "Unknown" || $country == "ipv6" || $country == "")
86
+ {
87
+ echo "<p>No country for $ip_address could be found. Or $ip_address is not a valid IPv4 or IPv6 IP address</p>";
88
+ }
89
+ else {
90
+ $displaycountry = $countrylist[$country];
91
+ echo "<p>IP Adress $ip_address belongs to $displaycountry.</p>";
92
+ $haystack = get_option('blockcountry_banlist');
93
+ if (is_array($haystack) && in_array ( $country, $haystack )) {
94
+ print "This country is not permitted to visit the frontend of this website.<br />";
95
+ }
96
+ $haystack = get_option('blockcountry_backendbanlist');
97
+ if (is_array($haystack) && in_array ( $country, $haystack )) {
98
+ print "This country is not permitted to visit the backend of this website.<br />";
99
+ }
100
+ }
101
+ }
102
+ }
103
+ echo '<div class="submit"><input type="submit" name="test" value="' . __( 'Check IP address', 'iq-block-country' ) . '" /></div>';
104
+ wp_nonce_field('iq-block-country');
105
+ ?>
106
+ </form>
107
+
108
+ <hr />
109
+ <h3>Download GeoIP database</h3>
110
+ <?php
111
+ $dateformat = get_option('date_format');
112
+ $time = get_option('blockcountry_lastupdate');
113
+
114
+ $lastupdated = date($dateformat,$time);
115
+
116
+ echo "<strong>The GeoIP database is updated once a month. Last update: " . $lastupdated . ".</strong>.<br />
117
+ If you need a manual update please press buttons below to update.";
118
+ ?>
119
+
120
+ <form name="download_geoip" action="#download" method="post">
121
+ <input type="hidden" name="action" value="download" />
122
+ <?php
123
+ echo '<div class="submit"><input type="submit" name="test" value="' . __( 'Download new GeoIP Database', 'iq-block-country' ) . '" /></div>';
124
+ wp_nonce_field('iq-block-country');
125
+ echo '</form>';
126
+ ?>
127
+ <form name="download_geoip6" action="#download6" method="post">
128
+ <input type="hidden" name="action" value="download6" />
129
+ <?php
130
+ echo '<div class="submit"><input type="submit" name="test" value="' . __( 'Download new GeoIP IPv6 Database', 'iq-block-country' ) . '" /></div>';
131
+ wp_nonce_field('iq-block-country');
132
+ echo '</form>';
133
+
134
+ if ( isset($_POST['action']) && $_POST[ 'action' ] == 'download') {
135
+ echo "Downloading....";
136
+ iqblockcountry_downloadgeodatabase('4', true);
137
+ }
138
+ if ( isset($_POST['action']) && $_POST[ 'action' ] == 'download6') {
139
+ echo "Downloading....";
140
+ iqblockcountry_downloadgeodatabase('6', true);
141
+ }
142
+
143
+ }
144
+
145
+ /*
146
+ * Settings home
147
+ */
148
+ function iqblockcountry_settings_home()
149
+ {
150
+ ?>
151
+ <h3>Statistics</h3>
152
+
153
+ <?php $blocked = get_option('blockcountry_backendnrblocks'); ?>
154
+ <p><?php echo $blocked; ?> visitors blocked from the backend.</p>
155
+ <?php $blocked = get_option('blockcountry_frontendnrblocks'); ?>
156
+ <p><?php echo $blocked; ?> visitors blocked from the frontend.</p>
157
+
158
+ <hr />
159
+
160
+ <h3>Basic Options</h3>
161
+
162
+ <form method="post" action="options.php">
163
+ <?php
164
+ settings_fields ( 'iqblockcountry-settings-group' );
165
+ if (!class_exists('GeoIP'))
166
+ {
167
+ include_once("geoip.inc");
168
+ }
169
+ if (class_exists('GeoIP'))
170
+ {
171
+
172
+ $countrylist = iqblockcountry_get_countries();
173
+
174
+ $ip_address = iqblockcountry_get_ipaddress();
175
+ $country = iqblockcountry_check_ipaddress($ip_address);
176
+ if ($country == "Unknown" || $country == "ipv6" || $country == "")
177
+ { $displaycountry = "Unknown"; }
178
+ else { $displaycountry = $countrylist[$country]; }
179
+
180
+
181
+ ?>
182
+
183
+ <script language="javascript" type="text/javascript" src=<?php echo "\"" . CHOSENJS . "\""?>></script>
184
+ <link rel="stylesheet" href=<?php echo "\"" . CHOSENCSS . "\""?> type="text/css" />
185
+ <script>
186
+ jQuery(document).ready(function(){
187
+ jQuery(".chosen").data("placeholder","Select country...").chosen();
188
+ });
189
+ </script>
190
+
191
+
192
+ <table class="form-table" cellspacing="2" cellpadding="5" width="100%">
193
+
194
+ <tr valign="top">
195
+ <th width="30%">Message to display when people are blocked:</th>
196
+ <td width="70%">
197
+ <?php
198
+ $blockmessage = get_option ( 'blockcountry_blockmessage' );
199
+ if (empty($blockmessage)) { $blockmessage = "Forbidden - Users from your country are not permitted to browse this site."; }
200
+ ?>
201
+ <textarea cols="100" rows="3" name="blockcountry_blockmessage"><?php echo $blockmessage; ?></textarea>
202
+ </td></tr>
203
+
204
+ <tr valign="top">
205
+ <th width="30%">Do not block users that are logged in from visiting frontend website:</th>
206
+ <td width="70%">
207
+ <input type="checkbox" name="blockcountry_blocklogin" <?php checked('on', get_option('blockcountry_blocklogin'), true); ?> />
208
+ </td></tr>
209
+
210
+ <tr valign="top">
211
+ <th width="30%">Block users from visiting the frontend of your website:</th>
212
+ <td width="70%">
213
+ <input type="checkbox" name="blockcountry_blockfrontend" <?php checked('on', get_option('blockcountry_blockfrontend'), true); ?> />
214
+ </td></tr>
215
+
216
+ <tr valign="top">
217
+ <th scope="row" width="30%">Select the countries that should be blocked from visiting your frontend:<br />
218
+ Use the CTRL key to select multiple countries</th>
219
+ <td width="70%">
220
+ <select class="chosen" name="blockcountry_banlist[]" multiple="true" style="width:600px;">
221
+ <?php
222
+ $haystack = get_option('blockcountry_banlist');
223
+ foreach ( $countrylist as $key => $value ) {
224
+ print "<option value=\"$key\"";
225
+ if (is_array($haystack) && in_array ( $key, $haystack )) {
226
+ print " selected=\"selected\" ";
227
+ }
228
+ print ">$value</option>\n";
229
+ }
230
+ ?>
231
+ </select>
232
+ </td></tr>
233
+ <tr valign="top">
234
+ <th width="30%">Frontend whitelist IPv4 and/or IPv6 addresses:<br />Use a semicolon (;) to separate IP addresses</th>
235
+ <td width="70%">
236
+ <?php
237
+ $frontendwhitelist = get_option ( 'blockcountry_frontendwhitelist' );
238
+ ?>
239
+ <textarea cols="70" rows="5" name="blockcountry_frontendwhitelist"><?php echo $frontendwhitelist; ?></textarea>
240
+ </td></tr>
241
+ <tr valign="top">
242
+ <th width="30%">Frontend blacklist IPv4 and/or IPv6 IP addresses:<br />Use a semicolon (;) to separate IP addresses</th>
243
+ <td width="70%">
244
+ <?php
245
+ $frontendblacklist = get_option ( 'blockcountry_frontendblacklist' );
246
+ ?>
247
+ <textarea cols="70" rows="5" name="blockcountry_frontendblacklist"><?php echo $frontendblacklist; ?></textarea>
248
+ </td></tr>
249
+ <tr valign="top">
250
+ <th width="30%">Block users from visiting the backend (administrator) of your website:</th>
251
+ <td width="70%">
252
+ <input type="checkbox" name="blockcountry_blockbackend" <?php checked('on', get_option('blockcountry_blockbackend'), true); ?> />
253
+ </td></tr>
254
+ <tr>
255
+ <th width="30%"></th>
256
+ <th width="70%">
257
+ Your IP address is <i><?php echo $ip_address ?></i>. The country that is listed for this IP address is <em><?php echo $displaycountry ?></em>.<br />
258
+ Do <strong>NOT</strong> set the 'Block users from visiting the backend (administrator) of your website' and also select <?php echo $displaycountry ?> below.<br />
259
+ <strong>You will NOT be able to login the next time if you DO block your own country from visiting the backend.</strong>
260
+ </th>
261
+ </tr>
262
+ </td></tr>
263
+ <tr valign="top">
264
+ <th scope="row" width="30%">Select the countries that should be blocked from visiting your backend:<br />
265
+ Use the x behind the country to remove a country from this blocklist.</th>
266
+ <td width="70%">
267
+
268
+ <select class="chosen" name="blockcountry_backendbanlist[]" multiple="true" style="width:600px;">
269
+ <?php
270
+ $haystack = get_option ( 'blockcountry_backendbanlist' );
271
+ foreach ( $countrylist as $key => $value ) {
272
+ print "<option value=\"$key\"";
273
+ if (is_array($haystack) && in_array ( $key, $haystack )) {
274
+ print " selected=\"selected\" ";
275
+ }
276
+ print ">$value</option>\n";
277
+ }
278
+ ?>
279
+ </select>
280
+ </td></tr>
281
+ <tr valign="top">
282
+ <th width="30%">Send headers when user is blocked:<br />
283
+ <em>Under normal circumstances you should keep this selected! Only if you have "Cannot modify header information - headers already sent" errors or if you know what you are doing uncheck this.</em></th>
284
+ <td width="70%">
285
+ <input type="checkbox" name="blockcountry_header" <?php checked('on', get_option('blockcountry_header'), true); ?> />
286
+ </td></tr>
287
+
288
+ <tr><td></td><td>
289
+ <p class="submit"><input type="submit" class="button-primary"
290
+ value="<?php _e ( 'Save Changes' )?>" /></p>
291
+ </td></tr>
292
+ </table>
293
+ </form>
294
+ <?php
295
+ }
296
+ else
297
+ {
298
+ print "<p>You are missing the GeoIP class. Perhaps geoip.inc is missing?</p>";
299
+ }
300
+
301
+ echo '<p>This product includes GeoLite data created by MaxMind, available from ';
302
+ echo '<a href="http://www.maxmind.com/">http://www.maxmind.com/</a>.</p>';
303
+
304
+ echo '<p>If you like this plugin please link back to <a href="http://www.redeo.nl/">redeo.nl</a>! :-)</p>';
305
+
306
+ }
307
+
308
+ /*
309
+ * Function: Display logging
310
+ */
311
+ function iqblockcountry_settings_logging()
312
+ {
313
+ ?>
314
+ <h3>Last 15 blocked visits</h3>
315
+ <?php
316
+ global $wpdb;
317
+
318
+ $table_name = $wpdb->prefix . "iqblock_logging";
319
+ $format = get_option('date_format') . ' ' . get_option('time_format');
320
+ $countrylist = iqblockcountry_get_countries();
321
+ echo '<table class="widefat">';
322
+ echo '<thead><tr><th>Date / time</th><th>IP Address</th><th>Hostname</th><th>URL</th><th>Country</th><th>Frontend/backend</th></tr></thead>';
323
+
324
+ foreach ($wpdb->get_results( "SELECT * FROM $table_name ORDER BY datetime DESC LIMIT 15" ) as $row)
325
+ {
326
+ $countryimage = "icons/" . strtolower($row->country) . ".png";
327
+ $countryurl = '<img src="' . plugins_url( $countryimage , dirname(__FILE__) ) . '" > ';
328
+ echo "<tbody><tr><td>";
329
+ $datetime = strtotime($row->datetime);
330
+ $mysqldate = date($format, $datetime);
331
+ echo $mysqldate . '</td><td>' . $row->ipaddress . '</td><td>' . gethostbyaddr( $row->ipaddress ) . '</td><td>' . $row->url . '</td><td>' . $countryurl . $countrylist[$row->country] . '<td>';
332
+ if ($row->banned == "F") echo "Frontend"; else { echo "Backend"; }
333
+ echo "</td></tr></tbody>";
334
+ }
335
+ echo '</table>';
336
+
337
+
338
+ echo '<hr>';
339
+ echo '<h3>Top countries that are blocked</h3>';
340
+ echo '<table class="widefat">';
341
+ echo '<thead><tr><th>Country</th><th># of blocked attempts</th></tr></thead>';
342
+
343
+ foreach ($wpdb->get_results( "SELECT count(country) AS count,country FROM $table_name GROUP BY country ORDER BY count(country) DESC LIMIT 15" ) as $row)
344
+ {
345
+ $countryimage = "icons/" . strtolower($row->country) . ".png";
346
+ $countryurl = '<img src="' . plugins_url( $countryimage , dirname(__FILE__) ) . '" > ';
347
+ echo "<tbody><tr><td>" . $countryurl . $countrylist[$row->country] . "</td><td>" . $row->count . "</td></tr></tbody>";
348
+ }
349
+ echo '</table>';
350
+
351
+ echo '<hr>';
352
+ echo '<h3>Top hosts that are blocked</h3>';
353
+ echo '<table class="widefat">';
354
+ echo '<thead><tr><th>IP Adress</th><th>Hostname</th><th># of blocked attempts</th></tr></thead>';
355
+
356
+ foreach ($wpdb->get_results( "SELECT count(ipaddress) AS count,ipaddress FROM $table_name GROUP BY ipaddress ORDER BY count(ipaddress) DESC LIMIT 15" ) as $row)
357
+ {
358
+ echo "<tbody><tr><td>" . $row->ipaddress . "</td><td>" . gethostbyaddr($row->ipaddress) . "</td><td>" . $row->count . "</td></tr></tbody>";
359
+ }
360
+ echo '</table>';
361
+
362
+ echo '<hr>';
363
+ echo '<h3>Top URLs that are blocked</h3>';
364
+ echo '<table class="widefat">';
365
+ echo '<thead><tr><th>URL</th><th># of blocked attempts</th></tr></thead>';
366
+
367
+ foreach ($wpdb->get_results( "SELECT count(url) AS count,url FROM $table_name GROUP BY url ORDER BY count(url) DESC LIMIT 15" ) as $row)
368
+ {
369
+ echo "<tbody><tr><td>" . $row->url . "</td><td>" . $row->count . "</td></tr></tbody>";
370
+ }
371
+ echo '</table>';
372
+
373
+ }
374
+
375
+
376
+ /*
377
+ * Create the settings page.
378
+ */
379
+ function iqblockcountry_settings_page() {
380
+
381
+
382
+ if( isset( $_GET[ 'tab' ] ) ) {
383
+ $active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'home';
384
+ }
385
+ else
386
+ {
387
+ $active_tab = 'home';
388
+ }
389
+ ?>
390
+
391
+ <h2 class="nav-tab-wrapper">
392
+ <a href="?page=iq-block-country/libs/blockcountry-settings.php&tab=home" class="nav-tab <?php echo $active_tab == 'home' ? 'nav-tab-active' : ''; ?>">Home</a>
393
+ <a href="?page=iq-block-country/libs/blockcountry-settings.php&tab=tools" class="nav-tab <?php echo $active_tab == 'tools' ? 'nav-tab-active' : ''; ?>">Tools</a>
394
+ <a href="?page=iq-block-country/libs/blockcountry-settings.php&tab=logging" class="nav-tab <?php echo $active_tab == 'logging' ? 'nav-tab-active' : ''; ?>">Logging</a>
395
+ </h2>
396
+
397
+
398
+ <div class="wrap">
399
+ <h2>iQ Block Country</h2>
400
+
401
+ <hr />
402
+ <?php
403
+ if ($active_tab == "tools")
404
+ {
405
+ iqblockcountry_settings_tools();
406
+ }
407
+ elseif ($active_tab == "logging")
408
+ {
409
+ iqblockcountry_settings_logging();
410
+ }
411
+ else
412
+ {
413
+ iqblockcountry_settings_home();
414
+ }
415
+ ?>
416
+
417
+
418
+ <?php
419
+ /* Check if the Geo Database exists otherwise try to download it */
420
+ if (! (file_exists ( IPV4DBFILE ))) {
421
+ ?>
422
+ <hr>
423
+ <p>GeoIP database does not exists. Trying to download it...</p>
424
+ <?php
425
+
426
+ iqblockcountry_downloadgeodatabase('4', true);
427
+ iqblockcountry_downloadgeodatabase('6', true);
428
+ }
429
+
430
+ }
431
+
libs/blockcountry-validation.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * Check of an IP address is a valid IPv4 address
5
+ */
6
+ function iqblockcountry_is_valid_ipv4($ipv4)
7
+ {
8
+ if(filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === FALSE) {
9
+ return false;
10
+ }
11
+
12
+ return true;
13
+ }
14
+
15
+ /*
16
+ * Check of an IP address is a valid IPv6 address
17
+ */
18
+ function iqblockcountry_is_valid_ipv6($ipv6)
19
+ {
20
+ if(filter_var($ipv6, FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) === FALSE) {
21
+ return false;
22
+ }
23
+
24
+ return true;
25
+ }
26
+
27
+
28
+ /*
29
+ * Sanitize callback. Check if supplied IP address list is valid IPv4 or IPv6
30
+ */
31
+ function iqblockcountry_validate_ip($input)
32
+ {
33
+ $validips = "";
34
+ if (preg_match('/;/',$input))
35
+ {
36
+ $arr = explode(";", $input);
37
+ foreach ($arr as $value) {
38
+ if (iqblockcountry_is_valid_ipv4($value) || iqblockcountry_is_valid_ipv6($value))
39
+ {
40
+ $validips .= $value . ";";
41
+ }
42
+
43
+ }
44
+ }
45
+ else
46
+ {
47
+ if (iqblockcountry_is_valid_ipv4($input) || iqblockcountry_is_valid_ipv6($input))
48
+ {
49
+ $validips = $input . ";";
50
+ }
51
+ }
52
+ return $validips;
53
+
54
+ }
55
+
libs/geoip.inc ADDED
@@ -0,0 +1,770 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
4
+ /* geoip.inc
5
+ *
6
+ * Copyright (C) 2007 MaxMind LLC
7
+ *
8
+ * This library is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; either
11
+ * version 2.1 of the License, or (at your option) any later version.
12
+ *
13
+ * This library is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ * Lesser General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Lesser General Public
19
+ * License along with this library; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
+ */
22
+
23
+ define("GEOIP_COUNTRY_BEGIN", 16776960);
24
+ define("GEOIP_STATE_BEGIN_REV0", 16700000);
25
+ define("GEOIP_STATE_BEGIN_REV1", 16000000);
26
+ define("GEOIP_STANDARD", 0);
27
+ define("GEOIP_MEMORY_CACHE", 1);
28
+ define("GEOIP_SHARED_MEMORY", 2);
29
+ define("STRUCTURE_INFO_MAX_SIZE", 20);
30
+ define("DATABASE_INFO_MAX_SIZE", 100);
31
+ define("GEOIP_COUNTRY_EDITION", 1);
32
+ define("GEOIP_PROXY_EDITION", 8);
33
+ define("GEOIP_ASNUM_EDITION", 9);
34
+ define("GEOIP_NETSPEED_EDITION", 10);
35
+ define("GEOIP_REGION_EDITION_REV0", 7);
36
+ define("GEOIP_REGION_EDITION_REV1", 3);
37
+ define("GEOIP_CITY_EDITION_REV0", 6);
38
+ define("GEOIP_CITY_EDITION_REV1", 2);
39
+ define("GEOIP_ORG_EDITION", 5);
40
+ define("GEOIP_ISP_EDITION", 4);
41
+ define("SEGMENT_RECORD_LENGTH", 3);
42
+ define("STANDARD_RECORD_LENGTH", 3);
43
+ define("ORG_RECORD_LENGTH", 4);
44
+ define("MAX_RECORD_LENGTH", 4);
45
+ define("MAX_ORG_RECORD_LENGTH", 300);
46
+ define("GEOIP_SHM_KEY", 0x4f415401);
47
+ define("US_OFFSET", 1);
48
+ define("CANADA_OFFSET", 677);
49
+ define("WORLD_OFFSET", 1353);
50
+ define("FIPS_RANGE", 360);
51
+ define("GEOIP_UNKNOWN_SPEED", 0);
52
+ define("GEOIP_DIALUP_SPEED", 1);
53
+ define("GEOIP_CABLEDSL_SPEED", 2);
54
+ define("GEOIP_CORPORATE_SPEED", 3);
55
+ define("GEOIP_DOMAIN_EDITION", 11);
56
+ define("GEOIP_COUNTRY_EDITION_V6", 12);
57
+ define("GEOIP_LOCATIONA_EDITION", 13);
58
+ define("GEOIP_ACCURACYRADIUS_EDITION", 14);
59
+ define("GEOIP_CITYCOMBINED_EDITION", 15);
60
+ define("GEOIP_CITY_EDITION_REV1_V6", 30);
61
+ define("GEOIP_CITY_EDITION_REV0_V6", 31);
62
+ define("GEOIP_NETSPEED_EDITION_REV1", 32);
63
+ define("GEOIP_NETSPEED_EDITION_REV1_V6", 33);
64
+ define("GEOIP_USERTYPE_EDITION", 28);
65
+ define("GEOIP_USERTYPE_EDITION_V6", 29);
66
+ define("GEOIP_ASNUM_EDITION_V6", 21);
67
+ define("GEOIP_ISP_EDITION_V6", 22);
68
+ define("GEOIP_ORG_EDITION_V6", 23);
69
+ define("GEOIP_DOMAIN_EDITION_V6", 24);
70
+
71
+ define("CITYCOMBINED_FIXED_RECORD", 7);
72
+
73
+ class GeoIP
74
+ {
75
+ public $flags;
76
+ public $filehandle;
77
+ public $memory_buffer;
78
+ public $databaseType;
79
+ public $databaseSegments;
80
+ public $record_length;
81
+ public $shmid;
82
+ public $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
83
+ "" => 0, "AP" => 1, "EU" => 2, "AD" => 3, "AE" => 4, "AF" => 5,
84
+ "AG" => 6, "AI" => 7, "AL" => 8, "AM" => 9, "CW" => 10, "AO" => 11,
85
+ "AQ" => 12, "AR" => 13, "AS" => 14, "AT" => 15, "AU" => 16, "AW" => 17,
86
+ "AZ" => 18, "BA" => 19, "BB" => 20, "BD" => 21, "BE" => 22, "BF" => 23,
87
+ "BG" => 24, "BH" => 25, "BI" => 26, "BJ" => 27, "BM" => 28, "BN" => 29,
88
+ "BO" => 30, "BR" => 31, "BS" => 32, "BT" => 33, "BV" => 34, "BW" => 35,
89
+ "BY" => 36, "BZ" => 37, "CA" => 38, "CC" => 39, "CD" => 40, "CF" => 41,
90
+ "CG" => 42, "CH" => 43, "CI" => 44, "CK" => 45, "CL" => 46, "CM" => 47,
91
+ "CN" => 48, "CO" => 49, "CR" => 50, "CU" => 51, "CV" => 52, "CX" => 53,
92
+ "CY" => 54, "CZ" => 55, "DE" => 56, "DJ" => 57, "DK" => 58, "DM" => 59,
93
+ "DO" => 60, "DZ" => 61, "EC" => 62, "EE" => 63, "EG" => 64, "EH" => 65,
94
+ "ER" => 66, "ES" => 67, "ET" => 68, "FI" => 69, "FJ" => 70, "FK" => 71,
95
+ "FM" => 72, "FO" => 73, "FR" => 74, "SX" => 75, "GA" => 76, "GB" => 77,
96
+ "GD" => 78, "GE" => 79, "GF" => 80, "GH" => 81, "GI" => 82, "GL" => 83,
97
+ "GM" => 84, "GN" => 85, "GP" => 86, "GQ" => 87, "GR" => 88, "GS" => 89,
98
+ "GT" => 90, "GU" => 91, "GW" => 92, "GY" => 93, "HK" => 94, "HM" => 95,
99
+ "HN" => 96, "HR" => 97, "HT" => 98, "HU" => 99, "ID" => 100, "IE" => 101,
100
+ "IL" => 102, "IN" => 103, "IO" => 104, "IQ" => 105, "IR" => 106, "IS" => 107,
101
+ "IT" => 108, "JM" => 109, "JO" => 110, "JP" => 111, "KE" => 112, "KG" => 113,
102
+ "KH" => 114, "KI" => 115, "KM" => 116, "KN" => 117, "KP" => 118, "KR" => 119,
103
+ "KW" => 120, "KY" => 121, "KZ" => 122, "LA" => 123, "LB" => 124, "LC" => 125,
104
+ "LI" => 126, "LK" => 127, "LR" => 128, "LS" => 129, "LT" => 130, "LU" => 131,
105
+ "LV" => 132, "LY" => 133, "MA" => 134, "MC" => 135, "MD" => 136, "MG" => 137,
106
+ "MH" => 138, "MK" => 139, "ML" => 140, "MM" => 141, "MN" => 142, "MO" => 143,
107
+ "MP" => 144, "MQ" => 145, "MR" => 146, "MS" => 147, "MT" => 148, "MU" => 149,
108
+ "MV" => 150, "MW" => 151, "MX" => 152, "MY" => 153, "MZ" => 154, "NA" => 155,
109
+ "NC" => 156, "NE" => 157, "NF" => 158, "NG" => 159, "NI" => 160, "NL" => 161,
110
+ "NO" => 162, "NP" => 163, "NR" => 164, "NU" => 165, "NZ" => 166, "OM" => 167,
111
+ "PA" => 168, "PE" => 169, "PF" => 170, "PG" => 171, "PH" => 172, "PK" => 173,
112
+ "PL" => 174, "PM" => 175, "PN" => 176, "PR" => 177, "PS" => 178, "PT" => 179,
113
+ "PW" => 180, "PY" => 181, "QA" => 182, "RE" => 183, "RO" => 184, "RU" => 185,
114
+ "RW" => 186, "SA" => 187, "SB" => 188, "SC" => 189, "SD" => 190, "SE" => 191,
115
+ "SG" => 192, "SH" => 193, "SI" => 194, "SJ" => 195, "SK" => 196, "SL" => 197,
116
+ "SM" => 198, "SN" => 199, "SO" => 200, "SR" => 201, "ST" => 202, "SV" => 203,
117
+ "SY" => 204, "SZ" => 205, "TC" => 206, "TD" => 207, "TF" => 208, "TG" => 209,
118
+ "TH" => 210, "TJ" => 211, "TK" => 212, "TM" => 213, "TN" => 214, "TO" => 215,
119
+ "TL" => 216, "TR" => 217, "TT" => 218, "TV" => 219, "TW" => 220, "TZ" => 221,
120
+ "UA" => 222, "UG" => 223, "UM" => 224, "US" => 225, "UY" => 226, "UZ" => 227,
121
+ "VA" => 228, "VC" => 229, "VE" => 230, "VG" => 231, "VI" => 232, "VN" => 233,
122
+ "VU" => 234, "WF" => 235, "WS" => 236, "YE" => 237, "YT" => 238, "RS" => 239,
123
+ "ZA" => 240, "ZM" => 241, "ME" => 242, "ZW" => 243, "A1" => 244, "A2" => 245,
124
+ "O1" => 246, "AX" => 247, "GG" => 248, "IM" => 249, "JE" => 250, "BL" => 251,
125
+ "MF" => 252, "BQ" => 253, "SS" => 254
126
+ );
127
+
128
+ public $GEOIP_COUNTRY_CODES = array(
129
+ "","AP","EU","AD","AE","AF","AG","AI","AL","AM","CW",
130
+ "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
131
+ "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
132
+ "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
133
+ "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
134
+ "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
135
+ "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
136
+ "FK","FM","FO","FR","SX","GA","GB","GD","GE","GF",
137
+ "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
138
+ "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
139
+ "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
140
+ "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
141
+ "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
142
+ "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
143
+ "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
144
+ "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
145
+ "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
146
+ "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
147
+ "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
148
+ "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
149
+ "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
150
+ "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
151
+ "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
152
+ "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
153
+ "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
154
+ "BL","MF", "BQ", "SS", "O1"
155
+ );
156
+
157
+ public $GEOIP_COUNTRY_CODES3 = array(
158
+ "","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","CUW",
159
+ "AGO","ATA","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB",
160
+ "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL",
161
+ "BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK","COD",
162
+ "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI",
163
+ "CUB","CPV","CXR","CYP","CZE","DEU","DJI","DNK","DMA","DOM",
164
+ "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI",
165
+ "FLK","FSM","FRO","FRA","SXM","GAB","GBR","GRD","GEO","GUF",
166
+ "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","SGS","GTM",
167
+ "GUM","GNB","GUY","HKG","HMD","HND","HRV","HTI","HUN","IDN",
168
+ "IRL","ISR","IND","IOT","IRQ","IRN","ISL","ITA","JAM","JOR",
169
+ "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT",
170
+ "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
171
+ "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI",
172
+ "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV",
173
+ "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC",
174
+ "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF",
175
+ "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW",
176
+ "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN",
177
+ "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM",
178
+ "SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF","TGO","THA",
179
+ "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN",
180
+ "TZA","UKR","UGA","UMI","USA","URY","UZB","VAT","VCT","VEN",
181
+ "VGB","VIR","VNM","VUT","WLF","WSM","YEM","MYT","SRB","ZAF",
182
+ "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY",
183
+ "BLM","MAF", "BES", "SSD", "O1"
184
+ );
185
+
186
+ public $GEOIP_COUNTRY_NAMES = array(
187
+ "","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Curacao",
188
+ "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
189
+ "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
190
+ "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
191
+ "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
192
+ "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
193
+ "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
194
+ "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
195
+ "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
196
+ "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
197
+ "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
198
+ "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
199
+ "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
200
+ "Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
201
+ "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
202
+ "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
203
+ "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
204
+ "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
205
+ "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
206
+ "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
207
+ "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
208
+ "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
209
+ "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
210
+ "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
211
+ "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
212
+ "Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba",
213
+ "South Sudan", "Other"
214
+ );
215
+
216
+ public $GEOIP_CONTINENT_CODES = array(
217
+ "--", "AS","EU","EU","AS","AS","NA","NA","EU","AS","NA",
218
+ "AF","AN","SA","OC","EU","OC","NA","AS","EU","NA",
219
+ "AS","EU","AF","EU","AS","AF","AF","NA","AS","SA",
220
+ "SA","NA","AS","AN","AF","EU","NA","NA","AS","AF",
221
+ "AF","AF","EU","AF","OC","SA","AF","AS","SA","NA",
222
+ "NA","AF","AS","AS","EU","EU","AF","EU","NA","NA",
223
+ "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC",
224
+ "SA","OC","EU","EU","NA","AF","EU","NA","AS","SA",
225
+ "AF","EU","NA","AF","AF","NA","AF","EU","AN","NA",
226
+ "OC","AF","SA","AS","AN","NA","EU","NA","EU","AS",
227
+ "EU","AS","AS","AS","AS","AS","EU","EU","NA","AS",
228
+ "AS","AF","AS","AS","OC","AF","NA","AS","AS","AS",
229
+ "NA","AS","AS","AS","NA","EU","AS","AF","AF","EU",
230
+ "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF",
231
+ "AS","AS","AS","OC","NA","AF","NA","EU","AF","AS",
232
+ "AF","NA","AS","AF","AF","OC","AF","OC","AF","NA",
233
+ "EU","EU","AS","OC","OC","OC","AS","NA","SA","OC",
234
+ "OC","AS","AS","EU","NA","OC","NA","AS","EU","OC",
235
+ "SA","AS","AF","EU","EU","AF","AS","OC","AF","AF",
236
+ "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF",
237
+ "SA","AF","NA","AS","AF","NA","AF","AN","AF","AS",
238
+ "AS","OC","AS","AF","OC","AS","EU","NA","OC","AS",
239
+ "AF","EU","AF","OC","NA","SA","AS","EU","NA","SA",
240
+ "NA","NA","AS","OC","OC","OC","AS","AF","EU","AF",
241
+ "AF","EU","AF","--","--","--","EU","EU","EU","EU",
242
+ "NA","NA","NA", "AF", "--"
243
+ );
244
+ }
245
+
246
+ function geoip_load_shared_mem ($file)
247
+ {
248
+ $fp = fopen($file, "rb");
249
+ if (!$fp) {
250
+ print "error opening $file: $php_errormsg\n";
251
+ exit;
252
+ }
253
+ $s_array = fstat($fp);
254
+ $size = $s_array['size'];
255
+ if (($shmid = @shmop_open(GEOIP_SHM_KEY, "w", 0, 0))) {
256
+ shmop_delete($shmid);
257
+ shmop_close($shmid);
258
+ }
259
+ $shmid = shmop_open(GEOIP_SHM_KEY, "c", 0644, $size);
260
+ shmop_write($shmid, fread($fp, $size), 0);
261
+ shmop_close($shmid);
262
+ }
263
+
264
+ function _setup_segments($gi)
265
+ {
266
+ $gi->databaseType = GEOIP_COUNTRY_EDITION;
267
+ $gi->record_length = STANDARD_RECORD_LENGTH;
268
+ if ($gi->flags & GEOIP_SHARED_MEMORY) {
269
+ $offset = @shmop_size($gi->shmid) - 3;
270
+ for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
271
+ $delim = @shmop_read($gi->shmid, $offset, 3);
272
+ $offset += 3;
273
+ if ($delim == (chr(255).chr(255).chr(255))) {
274
+ $gi->databaseType = ord(@shmop_read($gi->shmid, $offset, 1));
275
+ if ($gi->databaseType >= 106) {
276
+ $gi->databaseType -= 105;
277
+ }
278
+ $offset++;
279
+
280
+ if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
281
+ $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
282
+ } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
283
+ $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
284
+ } elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
285
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
286
+ || ($gi->databaseType == GEOIP_ORG_EDITION)
287
+ || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
288
+ || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
289
+ || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
290
+ || ($gi->databaseType == GEOIP_ISP_EDITION)
291
+ || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
292
+ || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
293
+ || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
294
+ || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
295
+ || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
296
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
297
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
298
+ || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
299
+ || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
300
+ || ($gi->databaseType == GEOIP_ASNUM_EDITION)
301
+ || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)) {
302
+ $gi->databaseSegments = 0;
303
+ $buf = @shmop_read($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
304
+ for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
305
+ $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
306
+ }
307
+ if (($gi->databaseType == GEOIP_ORG_EDITION)
308
+ || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
309
+ || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
310
+ || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
311
+ || ($gi->databaseType == GEOIP_ISP_EDITION)
312
+ || ($gi->databaseType == GEOIP_ISP_EDITION_V6)) {
313
+ $gi->record_length = ORG_RECORD_LENGTH;
314
+ }
315
+ }
316
+ break;
317
+ } else {
318
+ $offset -= 4;
319
+ }
320
+ }
321
+ if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
322
+ ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)||
323
+ ($gi->databaseType == GEOIP_PROXY_EDITION)||
324
+ ($gi->databaseType == GEOIP_NETSPEED_EDITION)) {
325
+ $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
326
+ }
327
+ } else {
328
+ $filepos = ftell($gi->filehandle);
329
+ fseek($gi->filehandle, -3, SEEK_END);
330
+ for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
331
+ $delim = fread($gi->filehandle, 3);
332
+ if ($delim == (chr(255) . chr(255) . chr(255))) {
333
+ $gi->databaseType = ord(fread($gi->filehandle, 1));
334
+ if ($gi->databaseType >= 106) {
335
+ $gi->databaseType -= 105;
336
+ }
337
+ if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
338
+ $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
339
+ } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
340
+ $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
341
+ } elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
342
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
343
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
344
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
345
+ || ($gi->databaseType == GEOIP_ORG_EDITION)
346
+ || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
347
+ || ($gi->databaseType == GEOIP_ISP_EDITION)
348
+ || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
349
+ || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
350
+ || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
351
+ || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
352
+ || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
353
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
354
+ || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
355
+ || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
356
+ || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
357
+ || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
358
+ || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
359
+ || ($gi->databaseType == GEOIP_ASNUM_EDITION)
360
+ || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)) {
361
+ $gi->databaseSegments = 0;
362
+ $buf = fread($gi->filehandle, SEGMENT_RECORD_LENGTH);
363
+ for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
364
+ $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
365
+ }
366
+ if (( $gi->databaseType == GEOIP_ORG_EDITION )
367
+ || ( $gi->databaseType == GEOIP_DOMAIN_EDITION )
368
+ || ( $gi->databaseType == GEOIP_ISP_EDITION )
369
+ || ( $gi->databaseType == GEOIP_ORG_EDITION_V6 )
370
+ || ( $gi->databaseType == GEOIP_DOMAIN_EDITION_V6 )
371
+ || ( $gi->databaseType == GEOIP_ISP_EDITION_V6 )) {
372
+ $gi->record_length = ORG_RECORD_LENGTH;
373
+ }
374
+ }
375
+ break;
376
+ } else {
377
+ fseek($gi->filehandle, -4, SEEK_CUR);
378
+ }
379
+ }
380
+ if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
381
+ ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)||
382
+ ($gi->databaseType == GEOIP_PROXY_EDITION)||
383
+ ($gi->databaseType == GEOIP_NETSPEED_EDITION)) {
384
+ $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
385
+ }
386
+ fseek($gi->filehandle, $filepos, SEEK_SET);
387
+ }
388
+ return $gi;
389
+ }
390
+
391
+ if ( !function_exists ('geoip_open')) {
392
+ function geoip_open($filename, $flags)
393
+ {
394
+ $gi = new GeoIP;
395
+ $gi->flags = $flags;
396
+ if ($gi->flags & GEOIP_SHARED_MEMORY) {
397
+ $gi->shmid = @shmop_open(GEOIP_SHM_KEY, "a", 0, 0);
398
+ } else {
399
+ $gi->filehandle = fopen($filename, "rb") or die("Can not open $filename\n");
400
+ if ($gi->flags & GEOIP_MEMORY_CACHE) {
401
+ $s_array = fstat($gi->filehandle);
402
+ $gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
403
+ }
404
+ }
405
+
406
+ $gi = _setup_segments($gi);
407
+ return $gi;
408
+ }
409
+ }
410
+
411
+ if ( !function_exists ('geoip_close')) {
412
+ function geoip_close($gi)
413
+ {
414
+ if ($gi->flags & GEOIP_SHARED_MEMORY) {
415
+ return true;
416
+ }
417
+
418
+ return fclose($gi->filehandle);
419
+ }
420
+ }
421
+
422
+ function geoip_country_id_by_name_v6($gi, $name)
423
+ {
424
+ $rec = dns_get_record($name, DNS_AAAA);
425
+ if (!$rec) {
426
+ return false;
427
+ }
428
+ $addr = $rec[0]["ipv6"];
429
+ if (!$addr || $addr == $name) {
430
+ return false;
431
+ }
432
+ return geoip_country_id_by_addr_v6($gi, $addr);
433
+ }
434
+
435
+ function geoip_country_id_by_name($gi, $name)
436
+ {
437
+ $addr = gethostbyname($name);
438
+ if (!$addr || $addr == $name) {
439
+ return false;
440
+ }
441
+ return geoip_country_id_by_addr($gi, $addr);
442
+ }
443
+
444
+ if ( !function_exists ('geoip_country_code_by_name_v6')) {
445
+ function geoip_country_code_by_name_v6($gi, $name)
446
+ {
447
+ $country_id = geoip_country_id_by_name_v6($gi, $name);
448
+ if ($country_id !== false) {
449
+ return $gi->GEOIP_COUNTRY_CODES[$country_id];
450
+ }
451
+ return false;
452
+ }
453
+ }
454
+ if ( !function_exists ('geoip_country_code_by_name')) {
455
+ function geoip_country_code_by_name($gi, $name)
456
+ {
457
+ $country_id = geoip_country_id_by_name($gi, $name);
458
+ if ($country_id !== false) {
459
+ return $gi->GEOIP_COUNTRY_CODES[$country_id];
460
+ }
461
+ return false;
462
+ }
463
+ }
464
+
465
+ if ( !function_exists ('geoip_country_name_by_name_v6')) {
466
+ function geoip_country_name_by_name_v6($gi, $name)
467
+ {
468
+ $country_id = geoip_country_id_by_name_v6($gi, $name);
469
+ if ($country_id !== false) {
470
+ return $gi->GEOIP_COUNTRY_NAMES[$country_id];
471
+ }
472
+ return false;
473
+ }
474
+ }
475
+
476
+ if ( !function_exists ('geoip_country_name_by_name')) {
477
+ function geoip_country_name_by_name($gi, $name)
478
+ {
479
+ $country_id = geoip_country_id_by_name($gi, $name);
480
+ if ($country_id !== false) {
481
+ return $gi->GEOIP_COUNTRY_NAMES[$country_id];
482
+ }
483
+ return false;
484
+ }
485
+ }
486
+
487
+ if ( !function_exists ('geoip_country_id_by_addr_v6')) {
488
+ function geoip_country_id_by_addr_v6($gi, $addr)
489
+ {
490
+ $ipnum = inet_pton($addr);
491
+ return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
492
+ }
493
+ }
494
+
495
+ if ( !function_exists ('geoip_country_id_by_addr')) {
496
+ function geoip_country_id_by_addr($gi, $addr)
497
+ {
498
+ $ipnum = ip2long($addr);
499
+ return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
500
+ }
501
+ }
502
+
503
+ function geoip_country_code_by_addr_v6($gi, $addr)
504
+ {
505
+ $country_id = geoip_country_id_by_addr_v6($gi, $addr);
506
+ if ($country_id !== false) {
507
+ return $gi->GEOIP_COUNTRY_CODES[$country_id];
508
+ }
509
+ return false;
510
+ }
511
+
512
+ function geoip_country_code_by_addr($gi, $addr)
513
+ {
514
+ if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
515
+ $record = geoip_record_by_addr($gi, $addr);
516
+ if ($record !== false) {
517
+ return $record->country_code;
518
+ }
519
+ } else {
520
+ $country_id = geoip_country_id_by_addr($gi, $addr);
521
+ if ($country_id !== false) {
522
+ return $gi->GEOIP_COUNTRY_CODES[$country_id];
523
+ }
524
+ }
525
+ return false;
526
+ }
527
+
528
+ function geoip_country_name_by_addr_v6($gi, $addr)
529
+ {
530
+ $country_id = geoip_country_id_by_addr_v6($gi, $addr);
531
+ if ($country_id !== false) {
532
+ return $gi->GEOIP_COUNTRY_NAMES[$country_id];
533
+ }
534
+ return false;
535
+ }
536
+
537
+ function geoip_country_name_by_addr($gi, $addr)
538
+ {
539
+ if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
540
+ $record = geoip_record_by_addr($gi, $addr);
541
+ return $record->country_name;
542
+ } else {
543
+ $country_id = geoip_country_id_by_addr($gi, $addr);
544
+ if ($country_id !== false) {
545
+ return $gi->GEOIP_COUNTRY_NAMES[$country_id];
546
+ }
547
+ }
548
+ return false;
549
+ }
550
+
551
+ function _geoip_seek_country_v6($gi, $ipnum)
552
+ {
553
+ # arrays from unpack start with offset 1
554
+ # yet another php mystery. array_merge work around
555
+ # this broken behaviour
556
+ $v6vec = array_merge(unpack("C16", $ipnum));
557
+
558
+ $offset = 0;
559
+ for ($depth = 127; $depth >= 0; --$depth) {
560
+ if ($gi->flags & GEOIP_MEMORY_CACHE) {
561
+ $buf = _safe_substr(
562
+ $gi->memory_buffer,
563
+ 2 * $gi->record_length * $offset,
564
+ 2 * $gi->record_length
565
+ );
566
+ } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
567
+ $buf = @shmop_read(
568
+ $gi->shmid,
569
+ 2 * $gi->record_length * $offset,
570
+ 2 * $gi->record_length
571
+ );
572
+ } else {
573
+ fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
574
+ or die("fseek failed");
575
+ $buf = fread($gi->filehandle, 2 * $gi->record_length);
576
+ }
577
+ $x = array(0, 0);
578
+ for ($i = 0; $i < 2; ++$i) {
579
+ for ($j = 0; $j < $gi->record_length; ++$j) {
580
+ $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
581
+ }
582
+ }
583
+
584
+ $bnum = 127 - $depth;
585
+ $idx = $bnum >> 3;
586
+ $b_mask = 1 << ( $bnum & 7 ^ 7 );
587
+ if (($v6vec[$idx] & $b_mask) > 0) {
588
+ if ($x[1] >= $gi->databaseSegments) {
589
+ return $x[1];
590
+ }
591
+ $offset = $x[1];
592
+ } else {
593
+ if ($x[0] >= $gi->databaseSegments) {
594
+ return $x[0];
595
+ }
596
+ $offset = $x[0];
597
+ }
598
+ }
599
+ trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
600
+ return false;
601
+ }
602
+
603
+ function _geoip_seek_country($gi, $ipnum)
604
+ {
605
+ $offset = 0;
606
+ for ($depth = 31; $depth >= 0; --$depth) {
607
+ if ($gi->flags & GEOIP_MEMORY_CACHE) {
608
+ $buf = _safe_substr(
609
+ $gi->memory_buffer,
610
+ 2 * $gi->record_length * $offset,
611
+ 2 * $gi->record_length
612
+ );
613
+ } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
614
+ $buf = @shmop_read(
615
+ $gi->shmid,
616
+ 2 * $gi->record_length * $offset,
617
+ 2 * $gi->record_length
618
+ );
619
+ } else {
620
+ fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
621
+ or die("fseek failed");
622
+ $buf = fread($gi->filehandle, 2 * $gi->record_length);
623
+ }
624
+ $x = array(0, 0);
625
+ for ($i = 0; $i < 2; ++$i) {
626
+ for ($j = 0; $j < $gi->record_length; ++$j) {
627
+ $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
628
+ }
629
+ }
630
+ if ($ipnum & (1 << $depth)) {
631
+ if ($x[1] >= $gi->databaseSegments) {
632
+ return $x[1];
633
+ }
634
+ $offset = $x[1];
635
+ } else {
636
+ if ($x[0] >= $gi->databaseSegments) {
637
+ return $x[0];
638
+ }
639
+ $offset = $x[0];
640
+ }
641
+ }
642
+ trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
643
+ return false;
644
+ }
645
+
646
+ function _common_get_org($gi, $seek_org)
647
+ {
648
+ $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
649
+ if ($gi->flags & GEOIP_SHARED_MEMORY) {
650
+ $org_buf = @shmop_read($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
651
+ } else {
652
+ fseek($gi->filehandle, $record_pointer, SEEK_SET);
653
+ $org_buf = fread($gi->filehandle, MAX_ORG_RECORD_LENGTH);
654
+ }
655
+ $org_buf = _safe_substr($org_buf, 0, strpos($org_buf, "\0"));
656
+ return $org_buf;
657
+ }
658
+
659
+ function _get_org_v6($gi, $ipnum)
660
+ {
661
+ $seek_org = _geoip_seek_country_v6($gi, $ipnum);
662
+ if ($seek_org == $gi->databaseSegments) {
663
+ return null;
664
+ }
665
+ return _common_get_org($gi, $seek_org);
666
+ }
667
+
668
+ function _get_org($gi, $ipnum)
669
+ {
670
+ $seek_org = _geoip_seek_country($gi, $ipnum);
671
+ if ($seek_org == $gi->databaseSegments) {
672
+ return null;
673
+ }
674
+ return _common_get_org($gi, $seek_org);
675
+ }
676
+
677
+
678
+
679
+ function geoip_name_by_addr_v6 ($gi, $addr)
680
+ {
681
+ if ($addr == null) {
682
+ return 0;
683
+ }
684
+ $ipnum = inet_pton($addr);
685
+ return _get_org_v6($gi, $ipnum);
686
+ }
687
+
688
+ function geoip_name_by_addr ($gi, $addr)
689
+ {
690
+ if ($addr == null) {
691
+ return 0;
692
+ }
693
+ $ipnum = ip2long($addr);
694
+ return _get_org($gi, $ipnum);
695
+ }
696
+
697
+ function geoip_org_by_addr ($gi, $addr)
698
+ {
699
+ return geoip_name_by_addr($gi, $addr);
700
+ }
701
+
702
+ function _get_region($gi, $ipnum)
703
+ {
704
+ if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
705
+ $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV0;
706
+ if ($seek_region >= 1000) {
707
+ $country_code = "US";
708
+ $region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65);
709
+ } else {
710
+ $country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
711
+ $region = "";
712
+ }
713
+ return array ($country_code,$region);
714
+ } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
715
+ $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV1;
716
+ if ($seek_region < US_OFFSET) {
717
+ $country_code = "";
718
+ $region = "";
719
+ } elseif ($seek_region < CANADA_OFFSET) {
720
+ $country_code = "US";
721
+ $region = chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65);
722
+ } elseif ($seek_region < WORLD_OFFSET) {
723
+ $country_code = "CA";
724
+ $region = chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65);
725
+ } else {
726
+ $country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
727
+ $region = "";
728
+ }
729
+ return array ($country_code,$region);
730
+ }
731
+ }
732
+
733
+ function geoip_region_by_addr ($gi, $addr)
734
+ {
735
+ if ($addr == null) {
736
+ return 0;
737
+ }
738
+ $ipnum = ip2long($addr);
739
+ return _get_region($gi, $ipnum);
740
+ }
741
+
742
+ function getdnsattributes ($l, $ip)
743
+ {
744
+ $r = new Net_DNS_Resolver();
745
+ $r->nameservers = array("ws1.maxmind.com");
746
+ $p = $r->search($l . "." . $ip . ".s.maxmind.com", "TXT", "IN");
747
+ $str = is_object($p->answer[0]) ? $p->answer[0]->string() : '';
748
+ $str = substr($str, 1, -1);
749
+ return $str;
750
+ }
751
+
752
+ function _safe_substr($string, $start, $length)
753
+ {
754
+ // workaround php's broken substr, strpos, etc handling with
755
+ // mbstring.func_overload and mbstring.internal_encoding
756
+ $mbExists = extension_loaded('mbstring');
757
+
758
+ if ($mbExists) {
759
+ $enc = mb_internal_encoding();
760
+ mb_internal_encoding('ISO-8859-1');
761
+ }
762
+
763
+ $buf = substr($string, $start, $length);
764
+
765
+ if ($mbExists) {
766
+ mb_internal_encoding($enc);
767
+ }
768
+
769
+ return $buf;
770
+ }
readme.txt ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === iQ Block Country ===
2
+ Contributors: iqpascal,williewonka
3
+ Donate link: http://www.unicef.org/
4
+ Tags: spam, block, countries, country, comments, ban, geo, geo blocking, geo ip, block country, block countries, ban countries, ban country, blacklist, whitelist
5
+ Requires at least: 3.5.2
6
+ Tested up to: 3.8
7
+ Stable tag: 1.1
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Block visitors from countries you don't want on your website. Based on which country an ip address is from.
12
+
13
+ == Description ==
14
+
15
+ If you want to block people from certain (obscure) countries that have no business visiting your
16
+ blog and perhaps only leave spam comments or other harmful actions than this is the plugin for you.
17
+
18
+ Choose which countries you want to ban from visiting your blog. Any visitors from that country get
19
+ a HTTP/403 error with the standard message "Forbidden - Users from your country are not permitted
20
+ to browse this site." The message is customizable an can be styled with CSS.
21
+
22
+ If you only want to block other countries from visiting your backend (administrator) website than this plugin is also something for you.
23
+
24
+ If you want to block users from both your frontend website as well as your backend website than this plugin is really something for you!
25
+
26
+ Users that are blocked will not be able to do harmful things to your blog like post comment spam.
27
+
28
+ This plugin uses the GeoLite database from Maxmind. It has a 99.5% accuracy so that is pretty good for a free database. If you need higher accuracy you can buy a license from MaxMind directly.
29
+
30
+ Once you setup this plugin it will try to download the GeoIP database from Maxmind so you will
31
+ always have a recent version of the database when installing this plugin.
32
+
33
+
34
+ == Installation ==
35
+
36
+ 1. Unzip the archive and put the `iq-block-country` folder into your plugins folder (/wp-content/plugins/).
37
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
38
+ 3. Go to the settings page and choose which countries you want to ban. Use the ctrl key to select
39
+ multiple countries
40
+ 4. Check if it downloaded the GeoIP database from MaxMind otherwise follow instructions on screen.
41
+
42
+ == Frequently Asked Questions ==
43
+
44
+ = How come that I still see visitors from countries that I blocked in Statpress or other statistics software? =
45
+
46
+ It’s true that you might see hits from countries that you have blocked in your statistics software.
47
+ That is the way it works, certain plugins may be run before iQ Block Country is run so it may log visitors to pages.
48
+
49
+ This however does not mean this plugin does not work, it just means somebody tried to access a certain page or pages and that that fact is logged.
50
+
51
+ If you are worried this plugin does not work you could try to block your own country or your own ip address and afterwards visit your frontend website and see if it actually works. Also if you have access to the logfiles of the webserver that hosts your website you can see that these visitors are actually denied with a HTTP error 403.
52
+
53
+ = This plugin does not work, I blocked a country and still see visitors! =
54
+
55
+ Well, this plugin does in fact work but is limited to the data MaxMind provides. Also in your statistics software or logfiles you probably will see log entries from countries that you have blocked. See the "How come I still see visitors..." FAQ for that.
56
+
57
+ If you think you have a visitor from a country you have blocked lookup that specific IP address on the MaxMind website (http://www.maxmind.com/app/locate_demo_ip) and see which country MaxMind thinks it is. If this is not the same country you may wish to block the country that MaxMind thinks it is.
58
+
59
+ = Whoops I made a whoops and blocked my own country from visiting the backend. Now I cannot login... HELP! =
60
+
61
+ I am afraid this can only be solved by editing your MySQL database,directly editing the rows in the wp_options table. You can use a tool like PHPMyAdmin for that.
62
+
63
+ If you don't know how to do this please ask your hosting provider if they can help, or ask me if I can help you out!
64
+
65
+ = Why do you not make something that can override that it blocks my country from the backend. =
66
+
67
+ Well, if you can use a manual override so can the people that want to 'visit' your backend.
68
+
69
+ This plugin is meant to keep people out. Perhaps you keep a key to your house somewhere hidden in your garden but this plugin does not have a key somewhere hidden... So if you locked yourself out you need to call a locksmith (or pick the lock yourself of course!)
70
+
71
+ = How can I style the banned message? =
72
+
73
+ You can style the message by using CSS in the textbox. You are also able to include images, so you could visualize that people are banned from your site.
74
+
75
+ You can also provide a link to another page explaining why they might be banned. Only culprit is that it cannot be a page on the same domain name as people would be banned from that page as well.
76
+
77
+ = Does this plugin also work with IPv6? =
78
+
79
+ Since v1.0.7 this plugin supports IPv6. But as IPv6 is still scarce it may not work as well as IPv4.
80
+ Some IPv6 blocks may not be in the right country in the MaxMind database.
81
+
82
+ There are no guarantees blocking IPv6 works but as far as I was able to test IPv6 blocking it
83
+ works just fine.
84
+
85
+ If you want IPv6 support be sure to press the "Download new GeoIP IPv6 database" button. At this
86
+ time the IPv6 database is not downloaded automatically.
87
+
88
+ = Does this plugin work with caching? =
89
+
90
+ In some circumstances: No
91
+
92
+ The plugin does it best to prevent caching of the "You are blocked" message. However most caching software can be forced to cache anyway. You may or may not be able to control the behavior of the caching method.
93
+
94
+ The plugin does it bests to avoid caching but under circumstances the message does get cached.
95
+ Either change the behavior of your caching software or disable the plugin.
96
+
97
+ = How can I select multiple countries at once? =
98
+
99
+ You can press the CTRL key and select several countries.
100
+
101
+ Perhaps also a handy function is that you can type in a part of the name of the country!
102
+
103
+ = How can I get a new version of the GeoIP database? =
104
+
105
+ Since v1.0.9 every time you login to the backend of your website the plugin checks if the current
106
+ databases are over a month old. If they are they will be automatically updated to the current
107
+ version of Maxmind.
108
+
109
+ If this is not soon enough for you you can also press the two buttons "Download new GeoIP database" on the bottom of the options page. This will download them instantly. However you do not need to download the databases more than once a month since the lite database is only updated once a month.
110
+
111
+ You can also remove the file GeoIP.dat from the plugin directory and after removal go to
112
+ the settings page of this plugin. When it sees the GeoIP database is missing it will
113
+ try to download it for you.
114
+
115
+ However you can also download the GeoIP database yourself from Maxmind and overwrite
116
+ the existing database.
117
+
118
+ Maxmind updates the GeoLite database every month.
119
+
120
+ = Help it gives some error about not being able to download the GeoIP database? =
121
+
122
+ Follow the instructions on screen. It will probably tell you that you have to manually
123
+ download the GeoIP database from Maxmind from the following url:
124
+
125
+ http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
126
+
127
+ If you also need IPv6 you can download the IPv6 database on the following url:
128
+
129
+ http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz
130
+
131
+ It will also give you the location it expects the GeoIP.dat file. So go ahead and download it and unzip the file.
132
+
133
+ Afterwards upload it to this specific location with for instance FTP,SFTP or FTPS.
134
+
135
+ = Why does downloading the GeoIP.dat.gz fail? =
136
+
137
+ For instance Maxmind limits the number of downloads per day. They do this by IP address so if you or somebody else who has a website at the same server your site is running on already downloaded the new database you may be blocked for 24 hours by MaxMind. If you are blocked because of too many requests this plugin tries to detect it and display an error message that you should try again later. So no worries try a day later again.
138
+
139
+ Other possible faults are your webhosting company not allowing downloads on HTTP port 80.
140
+
141
+ If your download fails try to download it from home or work and upload it via FTP,sFTP or FTPS to the location that is displayed.
142
+
143
+ = I get "Cannot modify header information - headers already sent" errors =
144
+
145
+ This is possible if another plugin or your template sends out header information before this plugin does. You can deactivate and reactivate this plugin, it will try to load as the first plugin upon activation.
146
+
147
+ If this does not help you out deselect "Send headers when user is blocked". This will no longer send headers but only display the block message. This however will mess up your website if you use caching software for your website.
148
+
149
+ == Changelog ==
150
+
151
+ = 1.1 =
152
+
153
+ * Added statistics to the plugin.
154
+ * You can view the last 15 hosts that were blocked including the url they visited.
155
+ * You can view the top 15 of countries that were blocked in the past 30 days.
156
+ * You can view the top 15 of hosts that were blocked in the past 30 days.
157
+ * You can view the top URL's that were most blocked in the past 30 days.
158
+
159
+ = 1.0.12 =
160
+
161
+ * The block message size box is now larger so there is more room for styling the message.
162
+ * Whitelist of IPvX IP addresses for the frontend. Use a semicolon to separate IP addresses.
163
+ * Blacklist of IPvX IP addresses for the frontend. Use a semicolon to separate IP addresses.
164
+
165
+ = 1.0.11 =
166
+
167
+ * You are now able to lookup which country belongs to an ip address in the backend. If the IP address is from a country that is banned this will be displayed.
168
+ * New way of selecting countries you wish to block upon multiple request. The selection box is now in sort of facebook style.
169
+ * Choose if you want to sent out headers or not. For people who get "Cannot modify header information - headers already sent" errors.
170
+ * Counter added for how many visitors where blocked from frontend and backend website.
171
+ * Code cleanup
172
+
173
+ = 1.0.10 =
174
+
175
+ * You can select different countries to block from your frontend website and your backend website.
176
+ * Made it more visible what IP you are logged in from, which country it is from and that you should not block your own country from your backend site.
177
+ * Minor changes to the settings page.
178
+ * A bit of code cleanup for future improvements.
179
+
180
+ = 1.0.9 =
181
+
182
+ * Bugfix release. The backend was not blocked in multi-site (network) setup.
183
+
184
+ = 1.0.8 =
185
+ * Automatically download new GeoIP updates from Maxmind. This is checked each time you login on the Wordpress admin site (Code by williewonka)
186
+ * Also block login attempts to the wp-admin site (Code by williewonka)
187
+ * Send no cache headers with the output.
188
+
189
+ = 1.0.7 =
190
+ * The plugin now detects if your IP address is blocked by MaxMind when downloading the GeoIP database and if so has an adjusted error message.
191
+ * New option: New checkbox to allow you to not block users that are logged in despite if they come from a blocked country. Use wisely :-)
192
+ * First version of IPv6 support.
193
+ * New Download IPv6 database button. Press "Download new GeoIP IPv6 database" if you need IPv6 support.
194
+
195
+ = 1.0.6 =
196
+ * Fixed error when not being able to download the GeoIP.dat.gz file from Maxmind it would not display the correct path.
197
+
198
+ = 1.0.5 =
199
+ * Corrected php opening tags (Reported by Phil from msiii.net)
200
+ * Sorted list of countries (As suggested by Phil from msiii.net)
201
+ * You can now customize the message that users get when they are blocked.
202
+ * We moved from http://www.trinyx.nl/ to http://www.redeo.nl/. Please update your links :-)
203
+
204
+ = 1.0.4 =
205
+ * Added a button to download the new GeoIP database.
206
+
207
+ = 1.0.3 =
208
+ * FAQ updated
209
+ * Try to make sure this plugin is loaded first to avoid "headers already sent" trouble.
210
+
211
+ = 1.0.2 =
212
+ * PHP 5.2 or higher required
213
+ * Fixed an include bug when other plugins also use the MaxMind database. Thanks to Marcus from LunaWorX for finding this bug.
214
+
215
+ = 1.0.1 =
216
+ * Included the necessary geoip.inc file.. *duh*
217
+
218
+ = 1.0 =
219
+ * Initial release
220
+
221
+ == Upgrade Notice ==
222
+
223
+ = 1.1 =
224
+
225
+ An additional database table was added for the statistics.
226
+
227
+ = 1.0.12 =
228
+
229
+ None. If you wish to fill up the blacklist or whitelist option fill those boxes.
230
+
231
+ = 1.0.11 =
232
+
233
+ None.
234
+
235
+ = 1.0.10 =
236
+
237
+ When upgrading from v1.0.8 or v1.0.9 the current value of your block list is copied to the block list of your backend site.
238
+
239
+ = 1.0.9 =
240
+
241
+ See upgrade notice from 1.0.8 if you upgrade from a release prior to 1.0.8.
242
+
243
+ = 1.0.8 =
244
+
245
+ This plugin adds some new checkbox settings so you can choose if you want to block users from your frontend website, your backend website or both. By default only the frontend site is blocked. If you wish to alter this behaviour go to your settings page.
246
+
247
+ = 1.0.7 =
248
+
249
+ You can now use the "Do not block users who are logged in" checkbox if you like. Also if you need IPv6 support you need to press the "Download new GeoIP IPv6 database".
250
+
251
+ = 1.0.5 =
252
+
253
+ None, this is just a minor update
254
+
255
+ = 1.0.4 =
256
+
257
+ None, this is just a minor update.
258
+
259
+ = 1.0.3 =
260
+
261
+ This baby should just upgrade fine. You may want to deactivate and reactivate this plugin to make (pretty) sure this plugin is loaded first. This especially recommended if you have problems with 'headers already sent' notices.
262
+
263
+ = 1.0.2 =
264
+
265
+ PHP 5.2 or higher is now required.
266
+
267
+ Just upgrade if you have PHP 5.2 or higher.
268
+
269
+ = 1.0.1 =
270
+
271
+ Critical upgrade for this plugin to work as it was missing a necessary file.