Spider Blocker - Version 1.0.6

Version Description

Download this release

Release Info

Developer niteoweb
Plugin Icon 128x128 Spider Blocker
Version 1.0.6
Comparing to
See all releases

Code changes from version 1.0.4 to 1.0.6

Files changed (1) hide show
  1. index.php +490 -365
index.php CHANGED
@@ -3,378 +3,503 @@ namespace Niteoweb\SpiderBlocker;
3
  /**
4
  * Plugin Name: Spider Blocker
5
  * Description: Spider Blocker will block most common bots that consume bandwidth and slow down your server.
6
- * Version: 1.0.4
7
- * Runtime: 5.3
8
- * Author: NiteoWeb Ltd.
9
- * Author URI: www.niteoweb.com
10
  */
11
 
12
- if (version_compare(PHP_VERSION, '5.3.0', '<')) {
13
- ?>
14
- <div id="error-page">
15
- <p>This plugin requires PHP 5.3.0 or higher. Please contact your hosting provider about upgrading your
16
- server software. Your PHP version is <b><?php echo PHP_VERSION; ?></b></p>
17
- </div>
18
- <?php
19
- die();
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
 
23
- class SpiderBlocker
24
- {
25
-
26
- public $default_bots = 'a:36:{i:0;O:8:"stdClass":4:{s:4:"name";s:10:"Ahrefs Bot";s:2:"re";s:9:"AhrefsBot";s:4:"desc";s:25:"https://ahrefs.com/robot/";s:5:"state";b:1;}i:1;O:8:"stdClass":4:{s:4:"name";s:8:"MJ12 bot";s:2:"re";s:7:"MJ12bot";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:2;O:8:"stdClass":4:{s:4:"name";s:9:"Roger Bot";s:2:"re";s:8:"Rogerbot";s:4:"desc";s:40:"http://moz.com/help/pro/rogerbot-crawler";s:5:"state";b:1;}i:3;O:8:"stdClass":4:{s:4:"name";s:11:"Semrush Bot";s:2:"re";s:10:"SemrushBot";s:4:"desc";s:31:"http://www.semrush.com/bot.html";s:5:"state";b:1;}i:4;O:8:"stdClass":4:{s:4:"name";s:11:"ia_archiver";s:2:"re";s:11:"ia_archiver";s:4:"desc";s:36:"http://archive.org/about/exclude.php";s:5:"state";b:1;}i:5;O:8:"stdClass":4:{s:4:"name";s:8:"ScoutJet";s:2:"re";s:8:"ScoutJet";s:4:"desc";s:19:"http://scoutjet.com";s:5:"state";b:1;}i:6;O:8:"stdClass":4:{s:4:"name";s:7:"sistrix";s:2:"re";s:7:"sistrix";s:4:"desc";s:26:"http://crawler.sistrix.net";s:5:"state";b:1;}i:7;O:8:"stdClass":4:{s:4:"name";s:16:"SearchmetricsBot";s:2:"re";s:16:"SearchmetricsBot";s:4:"desc";s:50:"http://www.searchmetrics.com/en/searchmetrics-bot/";s:5:"state";b:1;}i:8;O:8:"stdClass":4:{s:4:"name";s:14:"SEOkicks-Robot";s:2:"re";s:14:"SEOkicks-Robot";s:4:"desc";s:33:"http://www.seokicks.de/robot.html";s:5:"state";b:1;}i:9;O:8:"stdClass":4:{s:4:"name";s:16:"Lipperhey Spider";s:2:"re";s:16:"Lipperhey Spider";s:4:"desc";s:43:"http://www.lipperhey.com/en/website-spider/";s:5:"state";b:1;}i:10;O:8:"stdClass":4:{s:4:"name";s:6:"Exabot";s:2:"re";s:6:"Exabot";s:4:"desc";s:44:"http://www.exalead.com/search/webmasterguide";s:5:"state";b:1;}i:11;O:8:"stdClass":4:{s:4:"name";s:6:"NC Bot";s:2:"re";s:5:"NCBot";s:4:"desc";s:55:"https://twitter.com/NetComber/status/334476871691550721";s:5:"state";b:1;}i:12;O:8:"stdClass":4:{s:4:"name";s:15:"BacklinkCrawler";s:2:"re";s:15:"BacklinkCrawler";s:4:"desc";s:40:"http://www.backlinktest.com/crawler.html";s:5:"state";b:1;}i:13;O:8:"stdClass":4:{s:4:"name";s:15:"archive.org Bot";s:2:"re";s:15:"archive.org_bot";s:4:"desc";s:42:"http://archive.org/details/archive.org_bot";s:5:"state";b:1;}i:14;O:8:"stdClass":4:{s:4:"name";s:12:"MeanPath Bot";s:2:"re";s:11:"meanpathbot";s:4:"desc";s:37:"https://meanpath.com/meanpathbot.html";s:5:"state";b:1;}i:15;O:8:"stdClass":4:{s:4:"name";s:18:"PagesInventory Bot";s:2:"re";s:14:"PagesInventory";s:4:"desc";s:56:"http://www.botsvsbrowsers.com/details/1002332/index.html";s:5:"state";b:1;}i:16;O:8:"stdClass":4:{s:4:"name";s:12:"Aboundex Bot";s:2:"re";s:11:"Aboundexbot";s:4:"desc";s:32:"http://www.aboundex.com/crawler/";s:5:"state";b:1;}i:17;O:8:"stdClass":4:{s:4:"name";s:15:"SeoProfiler Bot";s:2:"re";s:5:"spbot";s:4:"desc";s:31:"http://www.seoprofiler.com/bot/";s:5:"state";b:1;}i:18;O:8:"stdClass":4:{s:4:"name";s:11:"Linkdex Bot";s:2:"re";s:10:"linkdexbot";s:4:"desc";s:34:"http://www.linkdex.com/about/bots/";s:5:"state";b:1;}i:19;O:8:"stdClass":4:{s:4:"name";s:7:"Gigabot";s:2:"re";s:7:"Gigabot";s:4:"desc";s:45:"http://www.useragentstring.com/pages/Gigabot/";s:5:"state";b:1;}i:20;O:8:"stdClass":4:{s:4:"name";s:6:"DotBot";s:2:"re";s:6:"dotbot";s:4:"desc";s:35:"http://en.wikipedia.org/wiki/DotBot";s:5:"state";b:1;}i:21;O:8:"stdClass":4:{s:4:"name";s:5:"Nutch";s:2:"re";s:5:"Nutch";s:4:"desc";s:32:"http://nutch.apache.org/bot.html";s:5:"state";b:1;}i:22;O:8:"stdClass":4:{s:4:"name";s:8:"BLEX Bot";s:2:"re";s:7:"BLEXBot";s:4:"desc";s:27:"http://webmeup-crawler.com/";s:5:"state";b:1;}i:23;O:8:"stdClass":4:{s:4:"name";s:6:"Ezooms";s:2:"re";s:6:"Ezooms";s:4:"desc";s:49:"http://graphicline.co.za/blogs/what-is-ezooms-bot";s:5:"state";b:1;}i:24;O:8:"stdClass":4:{s:4:"name";s:11:"Majestic 12";s:2:"re";s:11:"Majestic-12";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:25;O:8:"stdClass":4:{s:4:"name";s:12:"Majestic SEO";s:2:"re";s:12:"Majestic-SEO";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:26;O:8:"stdClass":4:{s:4:"name";s:7:"DSearch";s:2:"re";s:7:"DSearch";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:27;O:8:"stdClass":4:{s:4:"name";s:10:"Blekko Bot";s:2:"re";s:9:"BlekkoBot";s:4:"desc";s:33:"http://blekko.com/about/blekkobot";s:5:"state";b:1;}i:28;O:8:"stdClass":4:{s:4:"name";s:6:"Yandex";s:2:"re";s:6:"Yandex";s:4:"desc";s:41:"http://help.yandex.com/search/?id=1112030";s:5:"state";b:0;}i:29;O:8:"stdClass":4:{s:4:"name";s:10:"Google Bot";s:2:"re";s:9:"googlebot";s:4:"desc";s:57:"https://support.google.com/webmasters/answer/182072?hl=en";s:5:"state";b:0;}i:30;O:8:"stdClass":4:{s:4:"name";s:18:"Feedfetcher Google";s:2:"re";s:18:"Feedfetcher-Google";s:4:"desc";s:51:"https://support.google.com/webmasters/answer/178852";s:5:"state";b:0;}i:31;O:8:"stdClass":4:{s:4:"name";s:8:"Bing Bot";s:2:"re";s:7:"BingBot";s:4:"desc";s:36:"http://en.wikipedia.org/wiki/Bingbot";s:5:"state";b:0;}i:32;O:8:"stdClass":4:{s:4:"name";s:9:"Nerdy Bot";s:2:"re";s:8:"NerdyBot";s:4:"desc";s:20:"http://nerdybot.com/";s:5:"state";b:1;}i:33;O:8:"stdClass":4:{s:4:"name";s:9:"James BOT";s:2:"re";s:8:"JamesBOT";s:4:"desc";s:32:"http://cognitiveseo.com/bot.html";s:5:"state";b:1;}i:34;O:8:"stdClass":4:{s:4:"name";s:7:"Tin Eye";s:2:"re";s:6:"TinEye";s:4:"desc";s:34:"http://www.tineye.com/crawler.html";s:5:"state";b:1;}i:35;O:8:"stdClass":4:{s:5:"state";b:1;s:2:"re";s:11:"Baiduspider";s:4:"name";s:5:"Baidu";s:4:"desc";s:47:"http://www.baidu.com/search/robots_english.html";}}';
27
- protected $option_name = 'Niteoweb.SpiderBlocker.Bots';
28
- protected $nonce = 'Niteoweb.SpiderBlocker.Nonce';
29
-
30
- function __construct()
31
- {
32
- if (is_admin()) {
33
- add_action('admin_notices', array(&$this, 'activatePluginNotice'));
34
- add_action('admin_menu', array(&$this, 'adminMenu'));
35
- add_action('wp_ajax_NSB-get_list', array(&$this, 'loadList'));
36
- add_action('wp_ajax_NSB-set_list', array(&$this, 'saveList'));
37
- add_action('wp_ajax_NSB-reset_list', array(&$this, 'resetList'));
38
- }
39
- add_action('generate_rewrite_rules', array(&$this, "generateRewriteRules"));
40
-
41
- }
42
-
43
- /**
44
- * @codeCoverageIgnore
45
- * @return bool
46
- */
47
- static function isHtaccessWritable()
48
- {
49
- $home_path = function_exists('get_home_path') ? get_home_path() : ABSPATH;
50
- $htaccess_file = $home_path . '.htaccess';
51
-
52
- return is_writable($htaccess_file);
53
- }
54
-
55
- /**
56
- * @codeCoverageIgnore
57
- * @param int $mod octet value for chmod
58
- * @return bool
59
- */
60
- static function chmodHtaccess($mod = 0644)
61
- {
62
- $home_path = function_exists('get_home_path') ? get_home_path() : ABSPATH;
63
- $htaccess_file = $home_path . '.htaccess';
64
-
65
- return chmod($htaccess_file, $mod);
66
- }
67
-
68
- function generateRewriteRules()
69
- {
70
- global $wp_rewrite;
71
-
72
- // Protect plugin from direct access
73
- $wp_rewrite->add_external_rule('wp-content/plugins/spider_blocker/index.php', 'index.php%{REQUEST_URI}');
74
- $wp_rewrite->add_external_rule('wp-content/plugins/spider_blocker/readme.txt', 'index.php%{REQUEST_URI}');
75
- $wp_rewrite->add_external_rule('wp-content/plugins/spider_blocker/', 'index.php%{REQUEST_URI}');
76
- }
77
-
78
- function adminMenu()
79
- {
80
- add_management_page(
81
- 'SpiderBlocker', 'SpiderBlocker', 'manage_options', 'ni_spider_block', array(
82
- &$this,
83
- 'viewHandler'
84
- )
85
- );
86
- }
87
-
88
- /**
89
- * @codeCoverageIgnore
90
- */
91
- function activatePluginNotice()
92
- {
93
- if (get_option($this->option_name) === false) {
94
- update_option($this->option_name, $this->default_bots);
95
- ?>
96
- <div class="notice notice-success">
97
- <p>SpiderBlocker plugin has enabled blocking of some bots, please review settings by visiting <a
98
- href="<?php echo admin_url('tools.php?page=ni_spider_block'); ?>">Setting page</a>!</p>
99
- </div>
100
- <?php
101
- }
102
- }
103
-
104
- /**
105
- * @codeCoverageIgnore
106
- */
107
- function activatePlugin()
108
- {
109
- if (!apache_get_version() || !SpiderBlocker::modRewriteEnabled()) {
110
- ?>
111
- <div id="error-page">
112
- <p>This plugin requires Apache2 server with mod_rewrite support. Please contact your hosting provider
113
- about
114
- upgrading your server software. Your Apache version is <b><?php echo apache_get_version(); ?></b>
115
- </p>
116
- </div>
117
- <?php
118
- die();
119
- }
120
-
121
- if (!SpiderBlocker::isHtaccessWritable()) {
122
- $state = SpiderBlocker::chmodHtaccess();
123
- if (!SpiderBlocker::isHtaccessWritable() || !$state) {
124
- ?>
125
- <div id="error-page">
126
- <p>This plugin requires <b>.htaccess</b> file that is writable by the server. Please enable write
127
- access
128
- for file <b><?php echo ABSPATH . '.htaccess'; ?></b>.</p>
129
- </div>
130
- <?php
131
- die();
132
- }
133
- }
134
- $this->generateBlockRules();
135
-
136
- }
137
-
138
- function generateBlockRules()
139
- {
140
- global $wp_rewrite;
141
-
142
- $home_path = function_exists('get_home_path') ? get_home_path() : ABSPATH;
143
- $htaccess_file = $home_path . '.htaccess';
144
-
145
- if ((!file_exists($htaccess_file) && is_writable($home_path)) || is_writable($htaccess_file)) {
146
- if ($this->modRewriteEnabled()) {
147
- insert_with_markers($htaccess_file, 'NiteowebSpiderBlocker', $this->getRules());
148
- }
149
- }
150
-
151
- $wp_rewrite->flush_rules();
152
- }
153
-
154
- static function modRewriteEnabled()
155
- {
156
- return function_exists('apache_mod_loaded') ? apache_mod_loaded('mod_rewrite', false) : false;
157
- }
158
-
159
- /**
160
- * Generate block rules based on enabled bots
161
- *
162
- * @return array
163
- */
164
- function getRules()
165
- {
166
- $list = array();
167
- foreach ($this->getBots() as $bot) {
168
- if ($bot->state) {
169
- $list[] = 'SetEnvIfNoCase User-Agent "' . $bot->re . '" block_bot';
170
- }
171
-
172
- }
173
- $list[] = "<Limit GET POST HEAD>";
174
- $list[] = "Order Allow,Deny";
175
- $list[] = "Allow from all";
176
- $list[] = "Deny from env=block_bot";
177
- $list[] = "</Limit>";
178
-
179
- return $list;
180
- }
181
-
182
- private function getBots()
183
- {
184
- return maybe_unserialize(get_option($this->option_name, $this->default_bots));
185
- }
186
-
187
- function loadList()
188
- {
189
- check_ajax_referer($this->nonce, 'nonce');
190
- wp_send_json_success($this->getBots());
191
- }
192
-
193
- function resetList()
194
- {
195
- check_ajax_referer($this->nonce, 'nonce');
196
- delete_option($this->option_name);
197
- $this->generateBlockRules();
198
- wp_send_json_success($this->getBots());
199
- }
200
-
201
- function removeBlockRules()
202
- {
203
- global $wp_rewrite;
204
- delete_option($this->option_name);
205
- $home_path = function_exists('get_home_path') ? get_home_path() : ABSPATH;
206
- $htaccess_file = $home_path . '.htaccess';
207
- $empty = array();
208
- if ((!file_exists($htaccess_file) && is_writable($home_path)) || is_writable($htaccess_file)) {
209
- if ($this->modRewriteEnabled()) {
210
- insert_with_markers($htaccess_file, 'NiteowebSpiderBlocker', $empty);
211
- }
212
- }
213
-
214
- $wp_rewrite->flush_rules();
215
- }
216
-
217
- function saveList()
218
- {
219
-
220
- check_ajax_referer($this->nonce, 'nonce');
221
- $data = json_decode(stripcslashes($_POST['data']));
222
-
223
- if (json_last_error()) {
224
- if (function_exists('json_last_error_msg')) {
225
- wp_send_json_error(json_last_error_msg());
226
- } else {
227
- wp_send_json_error('Failed parsing JSON');
228
- }
229
-
230
- }
231
- if (get_option($this->option_name) !== false) {
232
- update_option($this->option_name, maybe_serialize($data));
233
- } else {
234
- add_option($this->option_name, maybe_serialize($data), null, 'no');
235
- }
236
-
237
- $this->generateBlockRules();
238
- wp_send_json_success($this->getBots());
239
-
240
- }
241
-
242
- /**
243
- * @codeCoverageIgnore
244
- */
245
- function viewHandler()
246
- {
247
-
248
- add_thickbox();
249
- wp_enqueue_script( 'spider_blocker_angularjs', plugin_dir_url( __FILE__ ) . 'static/angular.js' );
250
- wp_enqueue_script( 'spider_blocker_app', plugin_dir_url( __FILE__ ) . 'static/app.js' );
251
- wp_enqueue_style( 'spider_blocker_app', plugin_dir_url( __FILE__ ) . 'static/app.css' );
252
- ?>
253
- <script>
254
- window.sb_nonce="<?php echo wp_create_nonce($this->nonce); ?>";
255
- </script>
256
- <h1>Spider Blocker</h1>
257
- <hr/>
258
- <div ng-app="spiderBlockApp">
259
- <div ng-controller="NotificationsCtrl">
260
- <div class="notice notice-{{ n.state }} fixed" ng-repeat="n in notifications"
261
- style="top: {{3.5*($index+1)}}em">
262
- <p>{{n.msg}}
263
- <a ng-click="removeNotification(notification)">
264
- <span class="dashicons dashicons-no-alt"></span>
265
- </a>
266
- </p>
267
- </div>
268
- </div>
269
-
270
-
271
- <div ng-controller="BotListCtrl">
272
- <h2>Add New Bot</h2>
273
-
274
- <form name="add_form" ng-submit="add()">
275
- <table class="form-table">
276
- <tbody>
277
- <tr>
278
- <th scope="row"><label>User Agent</label></th>
279
- <td><input bots="bots" ng-model='bot.re' class="regular-text"
280
- required/></td>
281
- </tr>
282
- <tr>
283
- <th scope="row"><label>Bot Name</label></th>
284
- <td><input type="text" ng-model='bot.name' class="regular-text" required/></td>
285
- </tr>
286
- <tr>
287
- <tr>
288
- <th scope="row"><label>Bot Description URL</label></th>
289
- <td><input type="url" ng-model='bot.desc' class="regular-text" placeholder="http://"/>
290
- </td>
291
- </tr>
292
- </tbody>
293
- </table>
294
- <p class="submit"><input ng-disabled="add_form.$invalid" type="submit"
295
- class="button button-primary" value="Add Bot"></p>
296
- </form>
297
- <h2>List of bots</h2>
298
- <ng-form class="search-box">
299
- <input size="35" type="search" id="ua-search-input" ng-model="query" placeholder="Filter...">
300
- </ng-form>
301
- <table class="wp-list-table widefat bots">
302
- <thead>
303
- <tr>
304
-
305
- <th scope="col" class="manage-column column-description">
306
- <a href=""
307
- ng-click="predicate = 're'; reverse=false">User
308
- Agent <span class="dashicons dashicons-sort"></span></a></th>
309
-
310
- <th scope="col" class="manage-column column-name">Name</th>
311
- <th scope="col" class="manage-column column-state">
312
- <a href=""
313
- ng-click="predicate = 'state'; reverse=false">State <span
314
- class="dashicons dashicons-sort"></span></a>
315
- </th>
316
- <th scope="col" id="action" class="manage-column column-action">Action</th>
317
- </tr>
318
- </thead>
319
-
320
- <tfoot>
321
- <tr>
322
-
323
- <th scope="col" class="manage-column column-description"><a href=""
324
- ng-click="predicate = 're'; reverse=false">User
325
- Agent</a></th>
326
-
327
- <th scope="col" class="manage-column column-name">Name</th>
328
- <th scope="col" class="manage-column column-state"><a href=""
329
- ng-click="predicate = 'state'; reverse=false">State</a>
330
- </th>
331
- <th scope="col" id="action" class="manage-column column-action">Action</th>
332
- </tr>
333
- </tfoot>
334
-
335
- <tbody id="the-list">
336
- <tr id="spider-blocker" ng-repeat="bot in bots | filter:query | orderBy:predicate:reverse"
337
- ng-class="{'active': bot.state}">
338
-
339
- <th class="bot-re"> {{ bot.re }}</th>
340
- <td class="bot-title"><strong>{{ bot.name }}</strong> <a target="_blank"
341
- ng-href="{{bot.desc}}">{{
342
- bot.desc }}</a></td>
343
- <th class="expression" ng-class="{'blocked':bot.state}"> {{ bot.state?"Blocked":"Allowed"
344
- }}
345
- </th>
346
- <td class="actions">
347
- <input ng-hide="bot.state" type="button" ng-click="bot.state=true"
348
- class="button button-primary" value="Block">
349
- <input ng-show="bot.state" type="button" ng-click="bot.state=false"
350
- class="button button-secondary" value="Allow">
351
- <input type="button" ng-click="remove(bot.re)" class="button button-secondary"
352
- value="Remove">
353
- </td>
354
- </tr>
355
- </tbody>
356
- </table>
357
- <div id="rules-export-import" style="display:none;">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  <textarea
359
- style="-webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;width: 100%;height: 99%;"
360
- json-text ng-model="bots"></textarea>
361
- </div>
362
- <p class="submit">
363
- <input type="button" class="button button-primary" ng-click="save()" value="Save">
364
- <input type="button" class="button button-primary" ng-click="reset()" value="Reset to Defaults">
365
- <a href="#TB_inline?width=540&height=360&inlineId=rules-export-import"
366
- class="thickbox button button-secondary">Import/Export Definitions</a>
367
- </p>
368
-
369
- </div>
370
- </div>
371
- <?php
372
- }
 
 
373
  }
374
 
375
  // Inside WordPress
376
- if (defined('ABSPATH')) {
377
- $NiteowebSpiderBlocker_ins = new SpiderBlocker;
378
- register_activation_hook(__FILE__, array(&$NiteowebSpiderBlocker_ins, 'activatePlugin'));
379
- register_deactivation_hook(__FILE__, array(&$NiteowebSpiderBlocker_ins, 'removeBlockRules'));
380
  }
3
  /**
4
  * Plugin Name: Spider Blocker
5
  * Description: Spider Blocker will block most common bots that consume bandwidth and slow down your server.
6
+ * Version: 1.0.6
7
+ * Runtime: 5.3+
8
+ * Author: Easy Blog Networks
9
+ * Author URI: www.easyblognetworks.com
10
  */
11
 
12
+ if ( ! function_exists( 'apache_get_version' ) ) {
13
+ function apache_get_version() {
14
+ if ( stristr( $_ENV["SERVER_SOFTWARE"], 'Apache' ) ) {
15
+ return $_ENV["SERVER_SOFTWARE"];
16
+ }
17
+
18
+ return false;
19
+ }
20
+ }
21
+
22
+ if ( version_compare( PHP_VERSION, '5.3.0', '<' ) ) {
23
+ ?>
24
+ <div id="error-page">
25
+ <p>This plugin requires PHP 5.3.0 or higher. Please contact your hosting provider about upgrading your
26
+ server software. Your PHP version is <b><?php echo PHP_VERSION; ?></b></p>
27
+ </div>
28
+ <?php
29
+ die();
30
  }
31
 
32
 
33
+ class SpiderBlocker {
34
+
35
+ public $default_bots = 'a:36:{i:0;O:8:"stdClass":4:{s:4:"name";s:10:"Ahrefs Bot";s:2:"re";s:9:"AhrefsBot";s:4:"desc";s:25:"https://ahrefs.com/robot/";s:5:"state";b:1;}i:1;O:8:"stdClass":4:{s:4:"name";s:8:"MJ12 bot";s:2:"re";s:7:"MJ12bot";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:2;O:8:"stdClass":4:{s:4:"name";s:9:"Roger Bot";s:2:"re";s:8:"Rogerbot";s:4:"desc";s:40:"http://moz.com/help/pro/rogerbot-crawler";s:5:"state";b:1;}i:3;O:8:"stdClass":4:{s:4:"name";s:11:"Semrush Bot";s:2:"re";s:10:"SemrushBot";s:4:"desc";s:31:"http://www.semrush.com/bot.html";s:5:"state";b:1;}i:4;O:8:"stdClass":4:{s:4:"name";s:11:"ia_archiver";s:2:"re";s:11:"ia_archiver";s:4:"desc";s:36:"http://archive.org/about/exclude.php";s:5:"state";b:1;}i:5;O:8:"stdClass":4:{s:4:"name";s:8:"ScoutJet";s:2:"re";s:8:"ScoutJet";s:4:"desc";s:19:"http://scoutjet.com";s:5:"state";b:1;}i:6;O:8:"stdClass":4:{s:4:"name";s:7:"sistrix";s:2:"re";s:7:"sistrix";s:4:"desc";s:26:"http://crawler.sistrix.net";s:5:"state";b:1;}i:7;O:8:"stdClass":4:{s:4:"name";s:16:"SearchmetricsBot";s:2:"re";s:16:"SearchmetricsBot";s:4:"desc";s:50:"http://www.searchmetrics.com/en/searchmetrics-bot/";s:5:"state";b:1;}i:8;O:8:"stdClass":4:{s:4:"name";s:14:"SEOkicks-Robot";s:2:"re";s:14:"SEOkicks-Robot";s:4:"desc";s:33:"http://www.seokicks.de/robot.html";s:5:"state";b:1;}i:9;O:8:"stdClass":4:{s:4:"name";s:16:"Lipperhey Spider";s:2:"re";s:16:"Lipperhey Spider";s:4:"desc";s:43:"http://www.lipperhey.com/en/website-spider/";s:5:"state";b:1;}i:10;O:8:"stdClass":4:{s:4:"name";s:6:"Exabot";s:2:"re";s:6:"Exabot";s:4:"desc";s:44:"http://www.exalead.com/search/webmasterguide";s:5:"state";b:1;}i:11;O:8:"stdClass":4:{s:4:"name";s:6:"NC Bot";s:2:"re";s:5:"NCBot";s:4:"desc";s:55:"https://twitter.com/NetComber/status/334476871691550721";s:5:"state";b:1;}i:12;O:8:"stdClass":4:{s:4:"name";s:15:"BacklinkCrawler";s:2:"re";s:15:"BacklinkCrawler";s:4:"desc";s:40:"http://www.backlinktest.com/crawler.html";s:5:"state";b:1;}i:13;O:8:"stdClass":4:{s:4:"name";s:15:"archive.org Bot";s:2:"re";s:15:"archive.org_bot";s:4:"desc";s:42:"http://archive.org/details/archive.org_bot";s:5:"state";b:1;}i:14;O:8:"stdClass":4:{s:4:"name";s:12:"MeanPath Bot";s:2:"re";s:11:"meanpathbot";s:4:"desc";s:37:"https://meanpath.com/meanpathbot.html";s:5:"state";b:1;}i:15;O:8:"stdClass":4:{s:4:"name";s:18:"PagesInventory Bot";s:2:"re";s:14:"PagesInventory";s:4:"desc";s:56:"http://www.botsvsbrowsers.com/details/1002332/index.html";s:5:"state";b:1;}i:16;O:8:"stdClass":4:{s:4:"name";s:12:"Aboundex Bot";s:2:"re";s:11:"Aboundexbot";s:4:"desc";s:32:"http://www.aboundex.com/crawler/";s:5:"state";b:1;}i:17;O:8:"stdClass":4:{s:4:"name";s:15:"SeoProfiler Bot";s:2:"re";s:5:"spbot";s:4:"desc";s:31:"http://www.seoprofiler.com/bot/";s:5:"state";b:1;}i:18;O:8:"stdClass":4:{s:4:"name";s:11:"Linkdex Bot";s:2:"re";s:10:"linkdexbot";s:4:"desc";s:34:"http://www.linkdex.com/about/bots/";s:5:"state";b:1;}i:19;O:8:"stdClass":4:{s:4:"name";s:7:"Gigabot";s:2:"re";s:7:"Gigabot";s:4:"desc";s:45:"http://www.useragentstring.com/pages/Gigabot/";s:5:"state";b:1;}i:20;O:8:"stdClass":4:{s:4:"name";s:6:"DotBot";s:2:"re";s:6:"dotbot";s:4:"desc";s:35:"http://en.wikipedia.org/wiki/DotBot";s:5:"state";b:1;}i:21;O:8:"stdClass":4:{s:4:"name";s:5:"Nutch";s:2:"re";s:5:"Nutch";s:4:"desc";s:32:"http://nutch.apache.org/bot.html";s:5:"state";b:1;}i:22;O:8:"stdClass":4:{s:4:"name";s:8:"BLEX Bot";s:2:"re";s:7:"BLEXBot";s:4:"desc";s:27:"http://webmeup-crawler.com/";s:5:"state";b:1;}i:23;O:8:"stdClass":4:{s:4:"name";s:6:"Ezooms";s:2:"re";s:6:"Ezooms";s:4:"desc";s:49:"http://graphicline.co.za/blogs/what-is-ezooms-bot";s:5:"state";b:1;}i:24;O:8:"stdClass":4:{s:4:"name";s:11:"Majestic 12";s:2:"re";s:11:"Majestic-12";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:25;O:8:"stdClass":4:{s:4:"name";s:12:"Majestic SEO";s:2:"re";s:12:"Majestic-SEO";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:26;O:8:"stdClass":4:{s:4:"name";s:7:"DSearch";s:2:"re";s:7:"DSearch";s:4:"desc";s:56:"http://www.majestic12.co.uk/projects/dsearch/mj12bot.php";s:5:"state";b:1;}i:27;O:8:"stdClass":4:{s:4:"name";s:10:"Blekko Bot";s:2:"re";s:9:"BlekkoBot";s:4:"desc";s:33:"http://blekko.com/about/blekkobot";s:5:"state";b:1;}i:28;O:8:"stdClass":4:{s:4:"name";s:6:"Yandex";s:2:"re";s:6:"Yandex";s:4:"desc";s:41:"http://help.yandex.com/search/?id=1112030";s:5:"state";b:0;}i:29;O:8:"stdClass":4:{s:4:"name";s:10:"Google Bot";s:2:"re";s:9:"googlebot";s:4:"desc";s:57:"https://support.google.com/webmasters/answer/182072?hl=en";s:5:"state";b:0;}i:30;O:8:"stdClass":4:{s:4:"name";s:18:"Feedfetcher Google";s:2:"re";s:18:"Feedfetcher-Google";s:4:"desc";s:51:"https://support.google.com/webmasters/answer/178852";s:5:"state";b:0;}i:31;O:8:"stdClass":4:{s:4:"name";s:8:"Bing Bot";s:2:"re";s:7:"BingBot";s:4:"desc";s:36:"http://en.wikipedia.org/wiki/Bingbot";s:5:"state";b:0;}i:32;O:8:"stdClass":4:{s:4:"name";s:9:"Nerdy Bot";s:2:"re";s:8:"NerdyBot";s:4:"desc";s:20:"http://nerdybot.com/";s:5:"state";b:1;}i:33;O:8:"stdClass":4:{s:4:"name";s:9:"James BOT";s:2:"re";s:8:"JamesBOT";s:4:"desc";s:32:"http://cognitiveseo.com/bot.html";s:5:"state";b:1;}i:34;O:8:"stdClass":4:{s:4:"name";s:7:"Tin Eye";s:2:"re";s:6:"TinEye";s:4:"desc";s:34:"http://www.tineye.com/crawler.html";s:5:"state";b:1;}i:35;O:8:"stdClass":4:{s:5:"state";b:1;s:2:"re";s:11:"Baiduspider";s:4:"name";s:5:"Baidu";s:4:"desc";s:47:"http://www.baidu.com/search/robots_english.html";}}';
36
+ protected $option_name = 'Niteoweb.SpiderBlocker.Bots';
37
+ protected $nonce = 'Niteoweb.SpiderBlocker.Nonce';
38
+
39
+ function __construct() {
40
+ if ( is_admin() ) {
41
+ add_action( 'admin_notices', array( &$this, 'activatePluginNotice' ) );
42
+ add_action( 'admin_menu', array( &$this, 'adminMenu' ) );
43
+ add_action( 'wp_ajax_NSB-get_list', array( &$this, 'loadList' ) );
44
+ add_action( 'wp_ajax_NSB-set_list', array( &$this, 'saveList' ) );
45
+ add_action( 'wp_ajax_NSB-reset_list', array( &$this, 'resetList' ) );
46
+ }
47
+ add_action( 'generate_rewrite_rules', array( &$this, "generateRewriteRules" ) );
48
+
49
+ }
50
+
51
+ function generateRewriteRules() {
52
+ global $wp_rewrite;
53
+
54
+ // Protect plugin from direct access
55
+ $wp_rewrite->add_external_rule( $this->pluginURL() . 'index.php', 'index.php%{REQUEST_URI}' );
56
+ $wp_rewrite->add_external_rule( $this->pluginURL() . 'readme.txt', 'index.php%{REQUEST_URI}' );
57
+ $wp_rewrite->add_external_rule( $this->pluginURL(), 'index.php%{REQUEST_URI}' );
58
+ }
59
+
60
+ /**
61
+ * @codeCoverageIgnore
62
+ * @return string
63
+ */
64
+ private function pluginURL() {
65
+ $url = wp_make_link_relative( plugin_dir_url( __FILE__ ) );
66
+ $url = ltrim( $url, "/" );
67
+
68
+ return $url;
69
+ }
70
+
71
+ function adminMenu() {
72
+ add_management_page(
73
+ 'SpiderBlocker', 'SpiderBlocker', 'manage_options', 'ni_spider_block', array(
74
+ &$this,
75
+ 'viewHandler'
76
+ )
77
+ );
78
+ }
79
+
80
+ /**
81
+ * @codeCoverageIgnore
82
+ */
83
+ function activatePluginNotice() {
84
+ if ( get_option( $this->option_name ) === false ) {
85
+ update_option( $this->option_name, $this->default_bots );
86
+ ?>
87
+ <div class="notice notice-success">
88
+ <p>SpiderBlocker plugin has enabled blocking of some bots, please review settings by visiting <a
89
+ href="<?php echo admin_url( 'tools.php?page=ni_spider_block' ); ?>">Setting page</a>!</p>
90
+ </div>
91
+ <?php
92
+ }
93
+ }
94
+
95
+ /**
96
+ * @codeCoverageIgnore
97
+ */
98
+ function activatePlugin() {
99
+ if ( ! apache_get_version() ) {
100
+ ?>
101
+ <div id="error-page">
102
+ <p>This plugin requires Apache2 server with mod_rewrite support. Please contact your hosting provider
103
+ about
104
+ upgrading your server software. Your Apache version is <b><?php echo apache_get_version(); ?></b>
105
+ </p>
106
+ </div>
107
+ <?php
108
+ die();
109
+ }
110
+
111
+ if ( ! SpiderBlocker::isHtaccessWritable() ) {
112
+ $state = SpiderBlocker::chmodHtaccess();
113
+ if ( ! SpiderBlocker::isHtaccessWritable() || ! $state ) {
114
+ ?>
115
+ <div id="error-page">
116
+ <p>This plugin requires <b>.htaccess</b> file that is writable by the server. Please enable write
117
+ access
118
+ for file <b><?php echo ABSPATH . '.htaccess'; ?></b>.</p>
119
+ </div>
120
+ <?php
121
+ die();
122
+ }
123
+ }
124
+ $this->generateBlockRules();
125
+
126
+ }
127
+
128
+ /**
129
+ * @codeCoverageIgnore
130
+ * @return bool
131
+ */
132
+ static function isHtaccessWritable() {
133
+ $home_path = function_exists( 'get_home_path' ) ? get_home_path() : ABSPATH;
134
+ $htaccess_file = $home_path . '.htaccess';
135
+
136
+ return is_writable( $htaccess_file );
137
+ }
138
+
139
+ /**
140
+ * @codeCoverageIgnore
141
+ *
142
+ * @param int $mod octet value for chmod
143
+ *
144
+ * @return bool
145
+ */
146
+ static function chmodHtaccess( $mod = 0644 ) {
147
+ $home_path = function_exists( 'get_home_path' ) ? get_home_path() : ABSPATH;
148
+ $htaccess_file = $home_path . '.htaccess';
149
+
150
+ return chmod( $htaccess_file, $mod );
151
+ }
152
+
153
+ function generateBlockRules() {
154
+ global $wp_rewrite;
155
+
156
+ $home_path = function_exists( 'get_home_path' ) ? get_home_path() : ABSPATH;
157
+ $htaccess_file = $home_path . '.htaccess';
158
+
159
+ if ( ( ! file_exists( $htaccess_file ) && is_writable( $home_path ) ) || is_writable( $htaccess_file ) ) {
160
+ insert_with_markers( $htaccess_file, 'NiteowebSpiderBlocker', $this->getRules() );
161
+ }
162
+
163
+ $wp_rewrite->flush_rules();
164
+ }
165
+
166
+ /**
167
+ * Generate block rules based on enabled bots
168
+ *
169
+ * @return array
170
+ */
171
+ function getRules() {
172
+ $list = array();
173
+ foreach ( $this->getBots() as $bot ) {
174
+ if ( $bot->state ) {
175
+ $list[] = 'SetEnvIfNoCase User-Agent "' . $bot->re . '" block_bot';
176
+ }
177
+
178
+ }
179
+ $list[] = "<Limit GET POST HEAD>";
180
+ $list[] = "Order Allow,Deny";
181
+ $list[] = "Allow from all";
182
+ $list[] = "Deny from env=block_bot";
183
+ $list[] = "</Limit>";
184
+
185
+ return $list;
186
+ }
187
+
188
+ private function getBots() {
189
+ return maybe_unserialize( get_option( $this->option_name, $this->default_bots ) );
190
+ }
191
+
192
+ function loadList() {
193
+ check_ajax_referer( $this->nonce, 'nonce' );
194
+ wp_send_json_success( $this->getBots() );
195
+ }
196
+
197
+ function resetList() {
198
+ check_ajax_referer( $this->nonce, 'nonce' );
199
+ delete_option( $this->option_name );
200
+ $this->generateBlockRules();
201
+ wp_send_json_success( $this->getBots() );
202
+ }
203
+
204
+ function removeBlockRules() {
205
+ global $wp_rewrite;
206
+ delete_option( $this->option_name );
207
+ $home_path = function_exists( 'get_home_path' ) ? get_home_path() : ABSPATH;
208
+ $htaccess_file = $home_path . '.htaccess';
209
+ $empty = array();
210
+ if ( ( ! file_exists( $htaccess_file ) && is_writable( $home_path ) ) || is_writable( $htaccess_file ) ) {
211
+ insert_with_markers( $htaccess_file, 'NiteowebSpiderBlocker', $empty );
212
+ }
213
+
214
+ $wp_rewrite->flush_rules();
215
+ }
216
+
217
+ function saveList() {
218
+
219
+ check_ajax_referer( $this->nonce, 'nonce' );
220
+ $data = json_decode( stripcslashes( $_POST['data'] ) );
221
+
222
+ if ( json_last_error() ) {
223
+ if ( function_exists( 'json_last_error_msg' ) ) {
224
+ wp_send_json_error( json_last_error_msg() );
225
+ } else {
226
+ wp_send_json_error( 'Failed parsing JSON' );
227
+ }
228
+
229
+ }
230
+ if ( get_option( $this->option_name ) !== false ) {
231
+ update_option( $this->option_name, maybe_serialize( $data ) );
232
+ } else {
233
+ add_option( $this->option_name, maybe_serialize( $data ), null, 'no' );
234
+ }
235
+
236
+ $this->generateBlockRules();
237
+ wp_send_json_success( $this->getBots() );
238
+
239
+ }
240
+
241
+ /**
242
+ * @codeCoverageIgnore
243
+ */
244
+ function viewHandler() {
245
+
246
+ add_thickbox();
247
+ var_dump($this->pluginURL());
248
+ ?>
249
+ <style>
250
+ .notice.fixed {
251
+ position: fixed;
252
+ right: 1em;
253
+ top: 3.5em;
254
+ }
255
+
256
+ tr.active {
257
+ background-color: rgba(54, 204, 255, 0.05);
258
+ }
259
+
260
+ .active th.bot-re {
261
+ border-left: 4px solid #2ea2cc;
262
+ }
263
+ </style>
264
+ <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js" type="text/javascript"></script>
265
+ <script>
266
+ window.sb_nonce = "<?php echo wp_create_nonce($this->nonce); ?>";
267
+ -(function () {
268
+ var spiderBlockApp = angular.module('spiderBlockApp', []);
269
+
270
+ spiderBlockApp.directive('jsonText', function () {
271
+ return {
272
+ restrict: 'A',
273
+ require: 'ngModel',
274
+ link: function (scope, element, attr, ngModel) {
275
+ function into(input) {
276
+ return angular.fromJson(input);
277
+ }
278
+
279
+ function out(data) {
280
+ return angular.toJson(data, true);
281
+ }
282
+
283
+ ngModel.$parsers.push(into);
284
+ ngModel.$formatters.push(out);
285
+ }
286
+ };
287
+ });
288
+ spiderBlockApp.controller('NotificationsCtrl', function ($scope, $rootScope, $timeout) {
289
+ $scope.notifications = [];
290
+
291
+ $rootScope.$on('notification', function (event, data) {
292
+ $scope.notifications.push(data);
293
+ $timeout(function () {
294
+ $scope.removeNotification(data);
295
+ }, 3000);
296
+ });
297
+
298
+ $scope.removeNotification = function (notification) {
299
+ var index;
300
+ if ($scope.notifications !== undefined) {
301
+ index = $scope.notifications.indexOf(notification);
302
+ $scope.notifications.splice(index, 1);
303
+ }
304
+ }
305
+ });
306
+ spiderBlockApp.controller('BotListCtrl', function ($scope, $http, $rootScope) {
307
+ var wp_ajax = function (_req) {
308
+ _req.nonce = window.sb_nonce;
309
+ return $http({
310
+ method: 'POST',
311
+ url: ajaxurl,
312
+ data: jQuery.param(_req),
313
+ headers: {'Content-Type': 'application/x-www-form-urlencoded'}
314
+ })
315
+ };
316
+
317
+ var find_bot = function (re) {
318
+ for (var i = $scope.bots.length - 1; i >= 0; i--) {
319
+ if ($scope.bots[i]['re'] == re) {
320
+ return i;
321
+ }
322
+ }
323
+ return null;
324
+ };
325
+
326
+ $scope.bot = {"state": true};
327
+
328
+ wp_ajax({
329
+ action: 'NSB-get_list'
330
+ }).success(function (res) {
331
+ $scope.bots = res.data;
332
+ });
333
+
334
+ $scope.save = function () {
335
+ wp_ajax({
336
+ action: 'NSB-set_list',
337
+ data: angular.toJson($scope.bots)
338
+ }).success(function (res) {
339
+ if (res.success) {
340
+ $scope.bots = res.data;
341
+ $rootScope.$emit('notification', {
342
+ state: 'success',
343
+ msg: 'List of bots was saved and new blocklist applied!'
344
+ });
345
+ } else {
346
+ $rootScope.$emit('notification', {state: 'errror', msg: res.data});
347
+ }
348
+ });
349
+ };
350
+
351
+ $scope.reset = function () {
352
+ wp_ajax({
353
+ action: 'NSB-reset_list'
354
+ }).success(function (res) {
355
+ $scope.bots = res.data;
356
+ $rootScope.$emit('notification', {
357
+ state: 'success',
358
+ msg: 'List of bots was reset to defaults!'
359
+ });
360
+ });
361
+ };
362
+
363
+ $scope.add = function () {
364
+ $scope.bots.push($scope.bot);
365
+ $rootScope.$emit('notification', {
366
+ state: 'success',
367
+ msg: 'Bot ' + $scope.bot.name + ' was added!'
368
+ });
369
+ $scope.bot = {"state": true};
370
+ };
371
+
372
+ $scope.remove = function (at) {
373
+ $rootScope.$emit('notification', {state: 'success', msg: 'Bot was removed!'});
374
+ $scope.bots.splice(find_bot(at), 1);
375
+ };
376
+ });
377
+ })(angular, document, jQuery);
378
+ </script>
379
+ <h1>Spider Blocker</h1>
380
+ <hr/>
381
+ <div ng-app="spiderBlockApp">
382
+ <div ng-controller="NotificationsCtrl">
383
+ <div class="notice notice-{{ n.state }} fixed" ng-repeat="n in notifications"
384
+ style="top: {{3.5*($index+1)}}em">
385
+ <p>{{n.msg}}
386
+ <a ng-click="removeNotification(notification)">
387
+ <span class="dashicons dashicons-no-alt"></span>
388
+ </a>
389
+ </p>
390
+ </div>
391
+ </div>
392
+
393
+
394
+ <div ng-controller="BotListCtrl">
395
+ <h2>Add New Bot</h2>
396
+
397
+ <form name="add_form" ng-submit="add()">
398
+ <table class="form-table">
399
+ <tbody>
400
+ <tr>
401
+ <th scope="row"><label>User Agent</label></th>
402
+ <td><input bots="bots" ng-model='bot.re' class="regular-text"
403
+ required/></td>
404
+ </tr>
405
+ <tr>
406
+ <th scope="row"><label>Bot Name</label></th>
407
+ <td><input type="text" ng-model='bot.name' class="regular-text" required/></td>
408
+ </tr>
409
+ <tr>
410
+ <tr>
411
+ <th scope="row"><label>Bot Description URL</label></th>
412
+ <td><input type="url" ng-model='bot.desc' class="regular-text" placeholder="http://"/>
413
+ </td>
414
+ </tr>
415
+ </tbody>
416
+ </table>
417
+ <p class="submit"><input ng-disabled="add_form.$invalid" type="submit"
418
+ class="button button-primary" value="Add Bot"></p>
419
+ </form>
420
+ <h2>List of bots</h2>
421
+ <ng-form class="search-box">
422
+ <input size="35" type="search" id="ua-search-input" ng-model="query" placeholder="Filter...">
423
+ </ng-form>
424
+ <table class="wp-list-table widefat bots">
425
+ <thead>
426
+ <tr>
427
+
428
+ <th scope="col" class="manage-column column-description">
429
+ <a href=""
430
+ ng-click="predicate = 're'; reverse=false">User
431
+ Agent <span class="dashicons dashicons-sort"></span></a></th>
432
+
433
+ <th scope="col" class="manage-column column-name">Name</th>
434
+ <th scope="col" class="manage-column column-state">
435
+ <a href=""
436
+ ng-click="predicate = 'state'; reverse=false">State <span
437
+ class="dashicons dashicons-sort"></span></a>
438
+ </th>
439
+ <th scope="col" id="action" class="manage-column column-action">Action</th>
440
+ </tr>
441
+ </thead>
442
+
443
+ <tfoot>
444
+ <tr>
445
+
446
+ <th scope="col" class="manage-column column-description"><a href=""
447
+ ng-click="predicate = 're'; reverse=false">User
448
+ Agent</a></th>
449
+
450
+ <th scope="col" class="manage-column column-name">Name</th>
451
+ <th scope="col" class="manage-column column-state"><a href=""
452
+ ng-click="predicate = 'state'; reverse=false">State</a>
453
+ </th>
454
+ <th scope="col" id="action" class="manage-column column-action">Action</th>
455
+ </tr>
456
+ </tfoot>
457
+
458
+ <tbody id="the-list">
459
+ <tr id="spider-blocker" ng-repeat="bot in bots | filter:query | orderBy:predicate:reverse"
460
+ ng-class="{'active': bot.state}">
461
+
462
+ <th class="bot-re"> {{ bot.re }}</th>
463
+ <td class="bot-title"><strong>{{ bot.name }}</strong> <a target="_blank"
464
+ ng-href="{{bot.desc}}">{{
465
+ bot.desc }}</a></td>
466
+ <th class="expression" ng-class="{'blocked':bot.state}"> {{ bot.state?"Blocked":"Allowed"
467
+ }}
468
+ </th>
469
+ <td class="actions">
470
+ <input ng-hide="bot.state" type="button" ng-click="bot.state=true"
471
+ class="button button-primary" value="Block">
472
+ <input ng-show="bot.state" type="button" ng-click="bot.state=false"
473
+ class="button button-secondary" value="Allow">
474
+ <input type="button" ng-click="remove(bot.re)" class="button button-secondary"
475
+ value="Remove">
476
+ </td>
477
+ </tr>
478
+ </tbody>
479
+ </table>
480
+ <div id="rules-export-import" style="display:none;">
481
  <textarea
482
+ style="-webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;width: 100%;height: 99%;"
483
+ json-text ng-model="bots"></textarea>
484
+ </div>
485
+ <p class="submit">
486
+ <input type="button" class="button button-primary" ng-click="save()" value="Save">
487
+ <input type="button" class="button button-primary" ng-click="reset()" value="Reset to Defaults">
488
+ <a href="#TB_inline?width=540&height=360&inlineId=rules-export-import"
489
+ class="thickbox button button-secondary">Import/Export Definitions</a>
490
+ </p>
491
+
492
+ </div>
493
+ </div>
494
+ <?php
495
+ }
496
+
497
+
498
  }
499
 
500
  // Inside WordPress
501
+ if ( defined( 'ABSPATH' ) ) {
502
+ $NiteowebSpiderBlocker_ins = new SpiderBlocker;
503
+ register_activation_hook( __FILE__, array( &$NiteowebSpiderBlocker_ins, 'activatePlugin' ) );
504
+ register_deactivation_hook( __FILE__, array( &$NiteowebSpiderBlocker_ins, 'removeBlockRules' ) );
505
  }