Antispam Bee - Version 2.6.0

Version Description

  • DE: Optimierungen fr WordPress 3.8
  • DE: Zusatzprfung auf Nicht-UTF-8-Zeichen in Kommentardaten
  • DE: Spamgrund als Spalte in der bersicht mit Spamkommentaren
  • EN: Optimizations for WordPress 3.8
  • EN: Clear invalid UTF-8 characters in comment fields
  • EN: Spam reason as a column in the table with spam comments
Download this release

Release Info

Developer sergej.mueller
Plugin Icon 128x128 Antispam Bee
Version 2.6.0
Comparing to
See all releases

Code changes from version 2.4.5 to 2.6.0

antispam_bee.php CHANGED
@@ -7,12 +7,12 @@ Description: Easy and extremely productive spam-fighting plugin with many sophis
7
  Author: Sergej Müller
8
  Author URI: http://wpcoder.de
9
  Plugin URI: http://antispambee.com
10
- Version: 2.4.5
11
  */
12
 
13
 
14
  /* Sicherheitsabfrage */
15
- if ( !class_exists('WP') ) {
16
  die();
17
  }
18
 
@@ -26,7 +26,7 @@ if ( !class_exists('WP') ) {
26
 
27
  class Antispam_Bee {
28
 
29
-
30
  /* Init */
31
  public static $defaults;
32
  private static $_base;
@@ -38,19 +38,28 @@ class Antispam_Bee {
38
  * "Konstruktor" der Klasse
39
  *
40
  * @since 0.1
41
- * @change 2.4.3
42
  */
43
 
44
  public static function init()
45
  {
 
 
 
 
 
 
 
 
 
46
  /* AJAX & Co. */
47
  if ( (defined('DOING_AJAX') && DOING_AJAX) or (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) ) {
48
  return;
49
  }
50
-
51
  /* Initialisierung */
52
  self::_init_internal_vars();
53
-
54
  /* Cronjob */
55
  if ( defined('DOING_CRON') ) {
56
  add_action(
@@ -82,7 +91,7 @@ class Antispam_Bee {
82
  )
83
  );
84
  add_action(
85
- 'right_now_discussion_table_end',
86
  array(
87
  __CLASS__,
88
  'add_dashboard_count'
@@ -105,13 +114,6 @@ class Antispam_Bee {
105
  'load_plugin_lang'
106
  )
107
  );
108
- add_action(
109
- 'admin_notices',
110
- array(
111
- __CLASS__,
112
- 'init_admin_notice'
113
- )
114
- );
115
  add_filter(
116
  'plugin_row_meta',
117
  array(
@@ -128,7 +130,7 @@ class Antispam_Bee {
128
  'init_action_links'
129
  )
130
  );
131
-
132
  /* Optionen */
133
  } else if ( self::_current_page('options') ) {
134
  add_action(
@@ -145,10 +147,10 @@ class Antispam_Bee {
145
  'init_plugin_sources'
146
  )
147
  );
148
-
149
  } else if ( self::_current_page('admin-post') ) {
150
  require_once( dirname(__FILE__). '/inc/gui.class.php' );
151
-
152
  add_action(
153
  'admin_post_ab_save_changes',
154
  array(
@@ -156,6 +158,33 @@ class Antispam_Bee {
156
  'save_changes'
157
  )
158
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  }
160
 
161
  /* Frontend */
@@ -191,15 +220,15 @@ class Antispam_Bee {
191
  );
192
  }
193
  }
194
-
195
-
196
-
197
-
198
  ############################
199
  ######## INSTALL #########
200
  ############################
201
-
202
-
203
  /**
204
  * Aktion bei der Aktivierung des Plugins
205
  *
@@ -222,8 +251,8 @@ class Antispam_Bee {
222
  self::init_scheduled_hook();
223
  }
224
  }
225
-
226
-
227
  /**
228
  * Aktion bei der Deaktivierung des Plugins
229
  *
@@ -235,8 +264,8 @@ class Antispam_Bee {
235
  {
236
  self::clear_scheduled_hook();
237
  }
238
-
239
-
240
  /**
241
  * Aktion beim Löschen des Plugins
242
  *
@@ -248,82 +277,86 @@ class Antispam_Bee {
248
  {
249
  /* Global */
250
  global $wpdb;
251
-
252
  /* Remove settings */
253
  delete_option('antispam_bee');
254
-
255
  /* Clean DB */
256
  $wpdb->query("OPTIMIZE TABLE `" .$wpdb->options. "`");
257
  }
258
-
259
-
260
-
261
-
262
  ############################
263
  ######### INTERN #########
264
  ############################
265
-
266
-
267
  /**
268
  * Initialisierung der internen Variablen
269
  *
270
  * @since 2.4
271
- * @change 2.4.5
272
  */
273
-
274
  private static function _init_internal_vars()
275
  {
276
  self::$_base = plugin_basename(__FILE__);
277
  self::$_secret = substr(md5(get_bloginfo('url')), 0, 5). '-comment';
278
-
279
  self::$defaults = array(
280
  'options' => array(
281
  /* Allgemein */
282
  'advanced_check' => 1,
 
283
  'spam_ip' => 1,
284
  'already_commented' => 1,
285
  'ignore_pings' => 0,
286
  'always_allowed' => 0,
287
-
288
  'dashboard_chart' => 1,
289
  'dashboard_count' => 0,
290
-
291
  /* Filter */
292
  'country_code' => 0,
293
  'country_black' => '',
294
  'country_white' => '',
295
-
296
  'translate_api' => 0,
297
  'translate_lang' => '',
298
-
299
- 'dnsbl_check' => 1,
300
-
 
301
  /* Erweitert */
302
  'flag_spam' => 1,
303
  'email_notify' => 1,
304
  'no_notice' => 1,
305
  'cronjob_enable' => 0,
306
  'cronjob_interval' => 0,
307
-
308
  'ignore_filter' => 0,
309
  'ignore_type' => 0,
310
-
311
  'reasons_enable' => 0,
312
  'ignore_reasons' => array()
313
  ),
314
  'reasons' => array(
315
- 'css' => 'CSS Hack',
316
- 'empty' => 'Empty Data',
317
- 'server' => 'Server IP',
318
- 'spamip' => 'Spam IP',
319
- 'country' => 'Country Check',
320
- 'dnsbl' => 'DNSBL Spam',
321
- 'lang' => 'Comment Language'
 
 
322
  )
323
  );
324
  }
325
-
326
-
327
  /**
328
  * Prüfung und Rückgabe eines Array-Keys
329
  *
@@ -334,17 +367,17 @@ class Antispam_Bee {
334
  * @param string $key Name des Keys
335
  * @return mixed Wert des angeforderten Keys
336
  */
337
-
338
  public static function get_key($array, $key)
339
  {
340
  if ( empty($array) or empty($key) or empty($array[$key]) ) {
341
  return null;
342
  }
343
-
344
  return $array[$key];
345
  }
346
-
347
-
348
  /**
349
  * Lokalisierung der Admin-Seiten
350
  *
@@ -366,10 +399,13 @@ class Antispam_Bee {
366
 
367
  case 'plugins':
368
  return ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'plugins.php' );
369
-
370
  case 'admin-post':
371
  return ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'admin-post.php' );
372
 
 
 
 
373
  default:
374
  return false;
375
  }
@@ -391,8 +427,8 @@ class Antispam_Bee {
391
  'antispam-bee/lang'
392
  );
393
  }
394
-
395
-
396
  /**
397
  * Hinzufügen des Links zu den Einstellungen
398
  *
@@ -442,65 +478,24 @@ class Antispam_Bee {
442
  if ( $file != self::$_base ) {
443
  return $input;
444
  }
445
-
446
  return array_merge(
447
  $input,
448
  array(
449
- '<a href="https://flattr.com/donation/give/to/sergej.mueller" target="_blank">Flattr</a>',
450
- '<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RDDW9FEHGLG6" target="_blank">PayPal</a>'
451
  )
452
  );
453
  }
454
-
455
-
456
- /**
457
- * Anzeige der Admin-Notiz
458
- *
459
- * @since 2.4.3
460
- * @change 2.4.3
461
- */
462
 
463
- public static function init_admin_notice() {
464
- /* Alles klar? */
465
- if ( self::_is_version($GLOBALS['wp_version'], '3.4') && self::_is_version(phpversion(), '5.1.2') ) {
466
- return;
467
- }
468
 
469
- /* Warnung */
470
- echo sprintf(
471
- '<div class="error"><p>%s</p></div>',
472
- esc_html__('Antispam Bee requires WordPress 3.4 and PHP 5.1.2', 'antispam_bee')
473
- );
474
- }
475
-
476
-
477
- /**
478
- * Vergleich der Versionen
479
- *
480
- * @since 2.4.3
481
- * @change 2.4.3
482
- *
483
- * @param integer $current Aktuelle Version
484
- * @param integer $required Mindestversion
485
- * @return boolean TRUE, wenn Voraussetzungen erfüllt
486
- */
487
 
488
- private static function _is_version($current, $required) {
489
- return version_compare(
490
- $current,
491
- $required. 'alpha',
492
- '>='
493
- );
494
- }
495
-
496
-
497
-
498
-
499
  ############################
500
  ####### RESSOURCEN #######
501
  ############################
502
-
503
-
504
  /**
505
  * Registrierung von Ressourcen (CSS & JS)
506
  *
@@ -551,7 +546,7 @@ class Antispam_Bee {
551
  'options_page'
552
  )
553
  );
554
-
555
  /* JS einbinden */
556
  add_action(
557
  'admin_print_scripts-' . $page,
@@ -569,7 +564,7 @@ class Antispam_Bee {
569
  'add_options_style'
570
  )
571
  );
572
-
573
  /* PHP laden */
574
  add_action(
575
  'load-' .$page,
@@ -605,48 +600,58 @@ class Antispam_Bee {
605
  {
606
  wp_enqueue_style('ab_style');
607
  }
608
-
609
-
610
  /**
611
  * Einbindung der GUI
612
  *
613
  * @since 2.4
614
  * @change 2.4
615
  */
616
-
617
  public static function init_options_page()
618
  {
619
  require_once( dirname(__FILE__). '/inc/gui.class.php' );
620
  }
621
-
622
-
623
-
624
-
625
  ############################
626
  ####### DASHBOARD ########
627
  ############################
628
-
629
-
630
  /**
631
  * Anzeige des Spam-Counters auf dem Dashboard
632
  *
633
  * @since 0.1
634
- * @change 2.4
635
  */
636
 
637
  public static function add_dashboard_count()
638
  {
639
  /* Aktiv? */
640
- if ( !self::get_option('dashboard_count') ) {
641
  return;
642
  }
643
-
 
 
 
644
  /* Ausgabe */
645
  echo sprintf(
646
- '<tr>
647
- <td class="b b-spam" style="font-size:18px">%s</td>
648
- <td class="last t">%s</td>
649
- </tr>',
 
 
 
 
 
 
 
650
  esc_html( self::_get_spam_count() ),
651
  esc_html__('Blocked', 'antispam_bee')
652
  );
@@ -657,13 +662,13 @@ class Antispam_Bee {
657
  * Initialisierung des Dashboard-Chart
658
  *
659
  * @since 1.9
660
- * @change 2.4
661
  */
662
 
663
  public static function add_dashboard_chart()
664
  {
665
  /* Filter */
666
- if ( !current_user_can('level_2') or !self::get_option('dashboard_chart') ) {
667
  return;
668
  }
669
 
@@ -698,18 +703,18 @@ class Antispam_Bee {
698
 
699
 
700
  /**
701
- * Ausgabe der Dashboard-CSS
702
  *
703
- * @since 1.9
704
- * @change 2.4.4
705
  */
706
 
707
  public static function add_dashboard_style()
708
  {
709
- /* Plugin-Info */
710
  $plugin = get_plugin_data(__FILE__);
711
-
712
- /* CSS registrieren */
713
  wp_register_style(
714
  'ab_chart',
715
  plugins_url('css/dashboard.min.css', __FILE__),
@@ -717,114 +722,117 @@ class Antispam_Bee {
717
  $plugin['Version']
718
  );
719
 
720
- /* CSS ausgeben */
721
  wp_print_styles('ab_chart');
722
  }
723
 
724
 
725
  /**
726
- * Ausgabe der Dashboard-JS
727
  *
728
- * @since 1.9
729
- * @change 2.4.4
730
  */
731
 
732
  public static function add_dashboard_script()
733
  {
734
- /* Init */
735
- $items = (array)self::get_option('daily_stats');
736
-
737
- /* Leer? */
738
- if ( empty($items) ) {
739
  return;
740
  }
741
 
742
- /* Sortieren */
743
- krsort($items, SORT_NUMERIC);
744
-
745
- /* Init */
746
- $output = array(
747
- 'created' => array(),
748
- 'count' => array()
749
- );
750
-
751
- /* Init */
752
- $i = 0;
753
-
754
- /* Zeilen loopen */
755
- foreach($items as $timestamp => $count) {
756
- array_push(
757
- $output['created'],
758
- ( $timestamp == strtotime('today', current_time('timestamp')) ? __('Today', 'antispam_bee') : date('d.m', $timestamp) )
759
- );
760
- array_push(
761
- $output['count'],
762
- (int)$count
763
- );
764
- }
765
-
766
- /* Zusammenfassen */
767
- $stats = array(
768
- 'created' => implode(',', $output['created']),
769
- 'count' => implode(',', $output['count'])
770
- );
771
-
772
- /* Plugin-Info */
773
  $plugin = get_plugin_data(__FILE__);
774
 
775
- /* JS einbinden */
776
  wp_register_script(
777
- 'ab_chart',
778
- plugins_url('js/dashboard.min.js', __FILE__),
779
- array('jquery'),
780
- $plugin['Version']
 
781
  );
782
  wp_register_script(
783
- 'google_jsapi',
784
- 'https://www.google.com/jsapi',
785
- false
 
 
786
  );
787
-
788
- /* Einbinden */
789
- wp_enqueue_script('google_jsapi');
790
- wp_enqueue_script('ab_chart');
791
-
792
- /* Übergeben */
793
- wp_localize_script(
794
- 'ab_chart',
795
- 'antispambee',
796
- $stats
797
  );
 
 
 
 
 
798
  }
799
 
800
 
801
  /**
802
- * Ausgabe des Dashboard-Chart
803
  *
804
- * @since 1.9
805
- * @change 2.4
806
  */
807
 
808
  public static function show_spam_chart()
809
  {
810
- /* Init */
811
  $items = (array)self::get_option('daily_stats');
812
-
813
- /* Ausgabe */
814
- echo sprintf(
815
- '<div id="ab_chart">%s</div>',
816
- ( empty($items) ? esc_html__('No data available.', 'antispam_bee') : '' )
817
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
  }
819
-
820
-
821
-
822
-
823
  ############################
824
  ######## OPTIONS #########
825
  ############################
826
-
827
-
828
  /**
829
  * Rückgabe der Optionen
830
  *
@@ -850,8 +858,8 @@ class Antispam_Bee {
850
 
851
  return $options;
852
  }
853
-
854
-
855
  /**
856
  * Rückgabe eines Optionsfeldes
857
  *
@@ -919,15 +927,15 @@ class Antispam_Bee {
919
  $options
920
  );
921
  }
922
-
923
-
924
-
925
-
926
  ############################
927
  ######## CRONJOBS ########
928
  ############################
929
-
930
-
931
  /**
932
  * Ausführung des täglichen Cronjobs
933
  *
@@ -951,8 +959,8 @@ class Antispam_Bee {
951
  /* Spam löschen */
952
  self::_delete_old_spam();
953
  }
954
-
955
-
956
  /**
957
  * Löschung alter Spamkommentare
958
  *
@@ -984,8 +992,8 @@ class Antispam_Bee {
984
  /* DB optimieren */
985
  $wpdb->query("OPTIMIZE TABLE `$wpdb->comments`");
986
  }
987
-
988
-
989
  /**
990
  * Initialisierung des Cronjobs
991
  *
@@ -995,7 +1003,7 @@ class Antispam_Bee {
995
 
996
  public static function init_scheduled_hook()
997
  {
998
- if ( !wp_next_scheduled('antispam_bee_daily_cronjob') ) {
999
  wp_schedule_event(
1000
  time(),
1001
  'daily',
@@ -1018,10 +1026,10 @@ class Antispam_Bee {
1018
  wp_clear_scheduled_hook('antispam_bee_daily_cronjob');
1019
  }
1020
  }
1021
-
1022
-
1023
-
1024
-
1025
  ############################
1026
  ###### SPAMPRÜFUNG #######
1027
  ############################
@@ -1059,8 +1067,8 @@ class Antispam_Bee {
1059
  $_POST['bee_spam'] = 1;
1060
  }
1061
  }
1062
-
1063
-
1064
  /**
1065
  * Prüfung der eingehenden Anfragen auf Spam
1066
  *
@@ -1070,7 +1078,7 @@ class Antispam_Bee {
1070
  * @param array $comment Unbehandelter Kommentar
1071
  * @return array $comment Behandelter Kommentar
1072
  */
1073
-
1074
  public static function handle_incoming_request($comment)
1075
  {
1076
  /* Server-Werte */
@@ -1087,14 +1095,14 @@ class Antispam_Bee {
1087
  /* Ping-Optionen */
1088
  $ping = array(
1089
  'types' => array('pingback', 'trackback', 'pings'),
1090
- 'allowed' => !self::get_option('ignore_pings')
1091
  );
1092
-
1093
  /* Kommentar */
1094
  if ( strpos($url, 'wp-comments-post.php') !== false && !empty($_POST) ) {
1095
  /* Filter ausführen */
1096
  $status = self::_verify_comment_request($comment);
1097
-
1098
  /* Spam lokalisiert */
1099
  if ( !empty($status['reason']) ) {
1100
  return self::_handle_spam_request(
@@ -1102,12 +1110,12 @@ class Antispam_Bee {
1102
  $status['reason']
1103
  );
1104
  }
1105
-
1106
  /* Trackback */
1107
  } else if ( in_array(self::get_key($comment, 'comment_type'), $ping['types']) && $ping['allowed'] ) {
1108
  /* Filter ausführen */
1109
  $status = self::_verify_trackback_request($comment);
1110
-
1111
  /* Spam lokalisiert */
1112
  if ( !empty($status['reason']) ) {
1113
  return self::_handle_spam_request(
@@ -1117,10 +1125,10 @@ class Antispam_Bee {
1117
  );
1118
  }
1119
  }
1120
-
1121
  return $comment;
1122
  }
1123
-
1124
 
1125
  /**
1126
  * Bereitet die Ersetzung des KOmmentarfeldes vor
@@ -1149,8 +1157,8 @@ class Antispam_Bee {
1149
  )
1150
  );
1151
  }
1152
-
1153
-
1154
  /**
1155
  * ersetzt das Kommentarfeld
1156
  *
@@ -1160,14 +1168,19 @@ class Antispam_Bee {
1160
  * @param string $data HTML-Code der Webseite
1161
  * @return string Behandelter HTML-Code
1162
  */
1163
-
1164
  public static function replace_comment_field($data)
1165
  {
1166
  /* Leer? */
1167
  if ( empty($data) ) {
1168
  return;
1169
  }
1170
-
 
 
 
 
 
1171
  /* Convert */
1172
  return preg_replace(
1173
  '#<textarea(.+?)name=["\']comment["\'](.+?)</textarea>#s',
@@ -1176,140 +1189,359 @@ class Antispam_Bee {
1176
  1
1177
  );
1178
  }
1179
-
1180
 
1181
- /**
1182
- * Kürzung der IP-Adressen
1183
- *
1184
- * @since 0.1
1185
- * @change 2.4
1186
- *
1187
- * @param string $ip Ungekürzte IP
1188
- * @return string $ip Gekürzte IP
1189
- */
1190
 
1191
- private static function _cut_ip($ip)
1192
- {
1193
- return str_replace(
1194
- strrchr(
1195
- $ip,
1196
- ( self::_is_ipv4($ip) ? '.' : ':' )
1197
- ),
1198
- '',
1199
- $ip
1200
- );
1201
- }
1202
-
1203
-
1204
- /**
1205
- * Dreht die IP-Adresse
1206
- *
1207
- * @since 2.4.5
1208
- * @change 2.4.5
1209
- *
1210
- * @param string $ip IP-Adresse
1211
- * @return string Gedrehte IP-Adresse
1212
- */
1213
-
1214
- private static function _reverse_ip($ip)
1215
- {
1216
- return implode(
1217
- '.',
1218
- array_reverse(
1219
- explode(
1220
- '.',
1221
- $ip
1222
- )
1223
- )
1224
- );
1225
- }
1226
-
1227
-
1228
  /**
1229
- * Prüfung auf Mobile
1230
  *
1231
- * @since 0.1
1232
- * @change 2.4
1233
  *
1234
- * @return boolean TRUE, wenn "wptouch" aktiv ist
 
1235
  */
1236
 
1237
- private static function _is_mobile()
1238
  {
1239
- return strpos(TEMPLATEPATH, 'wptouch');
1240
- }
1241
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1242
 
1243
- /**
1244
- * Prüfung auf eine IPv4-Adresse
1245
- *
1246
- * @since 2.4
1247
- * @change 2.4
1248
- *
1249
- * @param string $ip Zu prüfende IP
1250
- * @return integer Anzahl der Treffer
1251
- */
1252
-
1253
- private static function _is_ipv4($ip)
1254
- {
1255
- return preg_match('/^\d{1,3}(\.\d{1,3}){3,3}$/', $ip);
1256
- }
1257
 
1258
-
1259
  /**
1260
- * Prüfung einer IP auf ihre Existenz im lokalen Spam
1261
  *
1262
- * @since 2.0
1263
- * @change 2.4
1264
  *
1265
- * @param string $ip IP-Adresse
1266
- * @return boolean TRUE bei verdächtiger IP
1267
  */
1268
 
1269
- private static function _is_spam_ip($ip)
1270
  {
1271
- /* Keine IP? */
1272
- if ( empty($ip) ) {
1273
- return true;
 
 
 
 
 
 
 
 
 
 
 
1274
  }
1275
 
1276
- /* Global */
1277
- global $wpdb;
 
 
 
 
1278
 
1279
- /* Suchen */
1280
- $found = $wpdb->get_var(
1281
- $wpdb->prepare(
1282
- "SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = 'spam' AND `comment_author_IP` = %s LIMIT 1",
1283
- (string)$ip
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1284
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1285
  );
1286
 
1287
- /* Gefunden? */
1288
- if ( $found ) {
1289
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1290
  }
1291
 
1292
  return false;
1293
  }
1294
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1295
 
1296
  /**
1297
  * Prüfung auf erlaubten Ländercodes
1298
  *
1299
  * @since 0.1
1300
- * @change 2.4.5
1301
  *
1302
  * @param string $ip IP-Adresse
1303
  * @return boolean TRUE bei unerwünschten Ländercodes
1304
  */
1305
 
1306
- private static function _is_spam_country($ip)
1307
  {
1308
- /* Keine IP? */
1309
- if ( empty($ip) ) {
1310
- return true;
1311
- }
1312
-
1313
  /* Optionen */
1314
  $options = self::get_options();
1315
 
@@ -1338,7 +1570,7 @@ class Antispam_Bee {
1338
  sprintf(
1339
  'https://geoip.maxmind.com/a?l=%s&i=%s',
1340
  strrev('1Lbn0ZsL08e1'),
1341
- $ip
1342
  ),
1343
  'https'
1344
  )
@@ -1365,8 +1597,8 @@ class Antispam_Bee {
1365
  /* Whitelist */
1366
  return ( in_array($country, $white) ? false : true );
1367
  }
1368
-
1369
-
1370
  /**
1371
  * Prüfung auf DNSBL Spam
1372
  *
@@ -1379,87 +1611,59 @@ class Antispam_Bee {
1379
 
1380
  private static function _is_dnsbl_spam($ip)
1381
  {
1382
- /* Keine IP? */
1383
- if ( empty($ip) ) {
1384
- return true;
 
 
 
 
 
 
 
 
 
 
 
1385
  }
1386
-
1387
- /* Funktionscheck */
1388
- if ( ! function_exists('checkdnsrr') ) {
 
 
 
 
 
 
1389
  return false;
1390
  }
1391
-
1392
- return (bool) checkdnsrr(
1393
- self::_reverse_ip($ip). '.opm.tornevall.org.',
1394
- 'A'
1395
- );
1396
  }
1397
-
1398
-
1399
  /**
1400
- * Prüfung der Trackbacks
1401
  *
1402
- * @since 2.4
1403
- * @change 2.4.5
1404
  *
1405
- * @param array $comment Daten des Trackbacks
1406
- * @return array Array mit dem Verdachtsgrund [optional]
1407
  */
1408
-
1409
- private static function _verify_trackback_request($comment)
1410
- {
1411
- /* IP */
1412
- $ip = self::get_key($_SERVER, 'REMOTE_ADDR');
1413
-
1414
- /* Kommentarwerte */
1415
- $url = self::get_key($comment, 'comment_author_url');
1416
- $body = self::get_key($comment, 'comment_content');
1417
 
1418
- /* Leere Werte ? */
1419
- if ( empty($ip) or empty($url) or empty($body) ) {
1420
- return array(
1421
- 'reason' => 'empty'
1422
- );
1423
- }
1424
-
1425
- /* Optionen */
1426
- $options = self::get_options();
1427
-
1428
- /* DNSBL Spam */
1429
- if ( $options['dnsbl_check'] && self::_is_dnsbl_spam($ip) ) {
1430
- return array(
1431
- 'reason' => 'dnsbl'
1432
- );
1433
- }
1434
-
1435
- /* IP != Server */
1436
- if ( $options['advanced_check'] && self::_is_fake_ip($ip, parse_url($url, PHP_URL_HOST)) ) {
1437
- return array(
1438
- 'reason' => 'server'
1439
- );
1440
- }
1441
-
1442
- /* IP im Spam */
1443
- if ( $options['spam_ip'] && self::_is_spam_ip($ip) ) {
1444
- return array(
1445
- 'reason' => 'spamip'
1446
- );
1447
- }
1448
-
1449
- /* Country Code prüfen */
1450
- if ( $options['country_code'] && self::_is_spam_country($ip) ) {
1451
- return array(
1452
- 'reason' => 'country'
1453
- );
1454
- }
1455
  }
1456
-
1457
-
1458
  /**
1459
  * Prüfung auf eine bereits freigegebene E-Mail-Adresse
1460
  *
1461
  * @since 2.0
1462
- * @change 2.4
1463
  *
1464
  * @param string $email E-Mail-Adresse
1465
  * @return boolean TRUE bei einem gefundenen Eintrag
@@ -1467,16 +1671,11 @@ class Antispam_Bee {
1467
 
1468
  private static function _is_approved_email($email)
1469
  {
1470
- /* Leer? */
1471
- if ( empty($email) ) {
1472
- return false;
1473
- }
1474
-
1475
  /* Global */
1476
  global $wpdb;
1477
 
1478
  /* Suchen */
1479
- $found = $wpdb->get_var(
1480
  $wpdb->prepare(
1481
  "SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = '1' AND `comment_author_email` = %s LIMIT 1",
1482
  (string)$email
@@ -1484,19 +1683,19 @@ class Antispam_Bee {
1484
  );
1485
 
1486
  /* Gefunden? */
1487
- if ( $found ) {
1488
  return true;
1489
  }
1490
 
1491
  return false;
1492
  }
1493
-
1494
-
1495
  /**
1496
  * Prüfung auf eine gefälschte IP
1497
  *
1498
  * @since 2.0
1499
- * @change 2.4
1500
  *
1501
  * @param string $ip IP-Adresse
1502
  * @param string $host Host [optional]
@@ -1505,11 +1704,6 @@ class Antispam_Bee {
1505
 
1506
  private static function _is_fake_ip($ip, $host = false)
1507
  {
1508
- /* Leer? */
1509
- if ( empty($ip) ) {
1510
- return true;
1511
- }
1512
-
1513
  /* Remote Host */
1514
  $hostbyip = gethostbyaddr($ip);
1515
 
@@ -1517,7 +1711,7 @@ class Antispam_Bee {
1517
  if ( !self::_is_ipv4($ip) ) {
1518
  return $ip != $hostbyip;
1519
  }
1520
-
1521
  /* IPv4 / Kommentar */
1522
  if ( empty($host) ) {
1523
  $found = strpos(
@@ -1526,14 +1720,14 @@ class Antispam_Bee {
1526
  gethostbyname($hostbyip)
1527
  )
1528
  );
1529
-
1530
  /* IPv4 / Trackback */
1531
  } else {
1532
  /* IP-Vergleich */
1533
  if ( $hostbyip == $ip ) {
1534
  return true;
1535
  }
1536
-
1537
  /* Treffer suchen */
1538
  $found = strpos(
1539
  $ip,
@@ -1545,8 +1739,8 @@ class Antispam_Bee {
1545
 
1546
  return $found === false;
1547
  }
1548
-
1549
-
1550
  /**
1551
  * Prüfung auf unerwünschte Sprachen
1552
  *
@@ -1561,15 +1755,15 @@ class Antispam_Bee {
1561
  {
1562
  /* Init */
1563
  $lang = self::get_option('translate_lang');
1564
-
1565
  /* Formatieren */
1566
  $content = wp_strip_all_tags($content);
1567
-
1568
  /* Keine Daten? */
1569
  if ( empty($lang) or empty($content) ) {
1570
  return false;
1571
  }
1572
-
1573
  /* Formatieren */
1574
  $content = rawurlencode(
1575
  ( function_exists('mb_substr') ? mb_substr($content, 0, 200) : substr($content, 0, 200) )
@@ -1605,99 +1799,120 @@ class Antispam_Bee {
1605
 
1606
  return ( strtolower($matches[1]) != $lang );
1607
  }
1608
-
1609
-
1610
  /**
1611
- * Prüfung den Kommentar
1612
  *
1613
- * @since 2.4
1614
- * @change 2.4.5
1615
  *
1616
- * @param array $comment Daten des Kommentars
1617
- * @return array Array mit dem Verdachtsgrund [optional]
 
1618
  */
1619
-
1620
- private static function _verify_comment_request($comment)
1621
  {
1622
- /* IP */
1623
- $ip = self::get_key($_SERVER, 'REMOTE_ADDR');
1624
-
1625
- /* Kommentarwerte */
1626
- $body = self::get_key($comment, 'comment_content');
1627
- $email = self::get_key($comment, 'comment_author_email');
1628
-
1629
- /* Leere Werte ? */
1630
- if ( empty($ip) or empty($body) ) {
1631
- return array(
1632
- 'reason' => 'empty'
1633
- );
1634
- }
1635
-
1636
- /* Leere Werte ? */
1637
- if ( get_option('require_name_email') && empty($email) ) {
1638
- return array(
1639
- 'reason' => 'empty'
1640
- );
1641
- }
1642
-
1643
- /* Optionen */
1644
- $options = self::get_options();
1645
-
1646
- /* Bereits kommentiert? */
1647
- if ( $options['already_commented'] && !empty($email) && self::_is_approved_email($email) ) {
1648
- return;
1649
- }
1650
-
1651
- /* Bot erkannt */
1652
- if ( !empty($_POST['bee_spam']) ) {
1653
- return array(
1654
- 'reason' => 'css'
1655
- );
1656
- }
1657
-
1658
- /* DNSBL Spam */
1659
- if ( $options['dnsbl_check'] && self::_is_dnsbl_spam($ip) ) {
1660
- return array(
1661
- 'reason' => 'dnsbl'
1662
- );
1663
- }
1664
-
1665
- /* Erweiterter Schutz */
1666
- if ( $options['advanced_check'] && self::_is_fake_ip($ip) ) {
1667
- return array(
1668
- 'reason' => 'server'
1669
- );
1670
- }
1671
-
1672
- /* IP im Spam */
1673
- if ( $options['spam_ip'] && self::_is_spam_ip($ip) ) {
1674
- return array(
1675
- 'reason' => 'spamip'
1676
- );
1677
- }
1678
-
1679
- /* Country Code prüfen */
1680
- if ( $options['country_code'] && self::_is_spam_country($ip) ) {
1681
- return array(
1682
- 'reason' => 'country'
1683
- );
1684
- }
1685
-
1686
- /* Translate API */
1687
- if ( $options['translate_api'] && self::_is_lang_spam($body) ) {
1688
- return array(
1689
- 'reason' => 'lang'
1690
- );
1691
  }
 
 
1692
  }
1693
-
1694
-
1695
  /**
1696
- * Ausführung des Lösch-/Markier-Vorgangs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1697
  *
1698
  * @since 0.1
1699
  * @change 2.4
1700
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1701
  * @param array $comment Unbehandelte Kommentardaten
1702
  * @param string $reason Verdachtsgrund
1703
  * @param boolean $is_ping Ping (ja oder nein) [optional]
@@ -1708,7 +1923,7 @@ class Antispam_Bee {
1708
  {
1709
  /* Optionen */
1710
  $options = self::get_options();
1711
-
1712
  /* Einstellungen */
1713
  $spam_remove = !$options['flag_spam'];
1714
  $spam_notice = !$options['no_notice'];
@@ -1716,25 +1931,26 @@ class Antispam_Bee {
1716
  /* Filter-Einstellungen */
1717
  $ignore_filter = $options['ignore_filter'];
1718
  $ignore_type = $options['ignore_type'];
1719
- $ignore_reason = in_array($reason, $options['ignore_reasons']);
1720
 
1721
- /* Spam hochzählen */
 
1722
  self::_update_spam_count();
1723
  self::_update_daily_stats();
1724
 
1725
  /* Spam löschen */
1726
  if ( $spam_remove ) {
1727
- die('Spam deleted.');
1728
  }
1729
 
1730
  /* Typen behandeln */
1731
  if ( $ignore_filter && (( $ignore_type == 1 && $is_ping ) or ( $ignore_type == 2 && !$is_ping )) ) {
1732
- die('Spam deleted.');
1733
  }
1734
-
1735
  /* Spamgrund */
1736
  if ( $ignore_reason ) {
1737
- die('Spam deleted.');
1738
  }
1739
 
1740
  /* Spam-Grund */
@@ -1765,26 +1981,114 @@ class Antispam_Bee {
1765
  )
1766
  );
1767
 
1768
-
1769
- /* Notiz setzen */
1770
  if ( $spam_notice ) {
1771
- $comment['comment_content'] = sprintf(
1772
- '[MARKED AS SPAM BY ANTISPAM BEE | %s]%s%s',
1773
- self::$defaults['reasons'][self::$_reason],
1774
- "\n",
1775
- $comment['comment_content']
 
1776
  );
1777
  }
1778
 
1779
  return $comment;
1780
  }
1781
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1782
 
1783
  /**
1784
  * Versand einer Benachrichtigung via E-Mail
1785
  *
1786
  * @since 0.1
1787
- * @change 2.4.3
 
 
1788
  *
1789
  * @param intval $id ID des Kommentars
1790
  * @return intval $id ID des Kommentars
@@ -1794,7 +2098,7 @@ class Antispam_Bee {
1794
  {
1795
  /* Optionen */
1796
  $options = self::get_options();
1797
-
1798
  /* Keine Benachrichtigung? */
1799
  if ( !$options['email_notify'] ) {
1800
  return $id;
@@ -1802,14 +2106,14 @@ class Antispam_Bee {
1802
 
1803
  /* Kommentar */
1804
  $comment = get_comment($id, ARRAY_A);
1805
-
1806
  /* Keine Werte? */
1807
  if ( empty($comment) ) {
1808
  return $id;
1809
  }
1810
 
1811
  /* Parent-Post */
1812
- if ( !$post = get_post($comment['comment_post_ID']) ) {
1813
  return $id;
1814
  }
1815
 
@@ -1819,7 +2123,12 @@ class Antispam_Bee {
1819
  /* Betreff */
1820
  $subject = sprintf(
1821
  '[%s] %s',
1822
- get_bloginfo('name'),
 
 
 
 
 
1823
  __('Comment marked as spam', 'antispam_bee')
1824
  );
1825
 
@@ -1888,16 +2197,19 @@ class Antispam_Bee {
1888
  /* Send */
1889
  wp_mail(
1890
  get_bloginfo('admin_email'),
1891
- $subject,
 
 
 
1892
  $body
1893
  );
1894
 
1895
  return $id;
1896
  }
1897
-
1898
-
1899
-
1900
-
1901
  ############################
1902
  ####### STATISTIK ########
1903
  ############################
7
  Author: Sergej M&uuml;ller
8
  Author URI: http://wpcoder.de
9
  Plugin URI: http://antispambee.com
10
+ Version: 2.6.0
11
  */
12
 
13
 
14
  /* Sicherheitsabfrage */
15
+ if ( ! class_exists('WP') ) {
16
  die();
17
  }
18
 
26
 
27
  class Antispam_Bee {
28
 
29
+
30
  /* Init */
31
  public static $defaults;
32
  private static $_base;
38
  * "Konstruktor" der Klasse
39
  *
40
  * @since 0.1
41
+ * @change 2.6.0
42
  */
43
 
44
  public static function init()
45
  {
46
+ /* Delete spam reason */
47
+ add_action(
48
+ 'unspam_comment',
49
+ array(
50
+ __CLASS__,
51
+ 'delete_spam_reason_by_comment'
52
+ )
53
+ );
54
+
55
  /* AJAX & Co. */
56
  if ( (defined('DOING_AJAX') && DOING_AJAX) or (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) ) {
57
  return;
58
  }
59
+
60
  /* Initialisierung */
61
  self::_init_internal_vars();
62
+
63
  /* Cronjob */
64
  if ( defined('DOING_CRON') ) {
65
  add_action(
91
  )
92
  );
93
  add_action(
94
+ 'dashboard_glance_items',
95
  array(
96
  __CLASS__,
97
  'add_dashboard_count'
114
  'load_plugin_lang'
115
  )
116
  );
 
 
 
 
 
 
 
117
  add_filter(
118
  'plugin_row_meta',
119
  array(
130
  'init_action_links'
131
  )
132
  );
133
+
134
  /* Optionen */
135
  } else if ( self::_current_page('options') ) {
136
  add_action(
147
  'init_plugin_sources'
148
  )
149
  );
150
+
151
  } else if ( self::_current_page('admin-post') ) {
152
  require_once( dirname(__FILE__). '/inc/gui.class.php' );
153
+
154
  add_action(
155
  'admin_post_ab_save_changes',
156
  array(
158
  'save_changes'
159
  )
160
  );
161
+
162
+ } else if ( self::_current_page('edit-comments') ) {
163
+ if ( ! empty($_GET['comment_status']) && $_GET['comment_status'] === 'spam' && ! self::get_option('no_notice') ) {
164
+ /* Include file */
165
+ require_once( dirname(__FILE__). '/inc/columns.class.php' );
166
+
167
+ /* Load textdomain */
168
+ self::load_plugin_lang();
169
+
170
+ /* Add plugin columns */
171
+ add_filter(
172
+ 'manage_edit-comments_columns',
173
+ array(
174
+ 'Antispam_Bee_Columns',
175
+ 'register_plugin_columns'
176
+ )
177
+ );
178
+ add_filter(
179
+ 'manage_comments_custom_column',
180
+ array(
181
+ 'Antispam_Bee_Columns',
182
+ 'print_plugin_column'
183
+ ),
184
+ 10,
185
+ 2
186
+ );
187
+ }
188
  }
189
 
190
  /* Frontend */
220
  );
221
  }
222
  }
223
+
224
+
225
+
226
+
227
  ############################
228
  ######## INSTALL #########
229
  ############################
230
+
231
+
232
  /**
233
  * Aktion bei der Aktivierung des Plugins
234
  *
251
  self::init_scheduled_hook();
252
  }
253
  }
254
+
255
+
256
  /**
257
  * Aktion bei der Deaktivierung des Plugins
258
  *
264
  {
265
  self::clear_scheduled_hook();
266
  }
267
+
268
+
269
  /**
270
  * Aktion beim Löschen des Plugins
271
  *
277
  {
278
  /* Global */
279
  global $wpdb;
280
+
281
  /* Remove settings */
282
  delete_option('antispam_bee');
283
+
284
  /* Clean DB */
285
  $wpdb->query("OPTIMIZE TABLE `" .$wpdb->options. "`");
286
  }
287
+
288
+
289
+
290
+
291
  ############################
292
  ######### INTERN #########
293
  ############################
294
+
295
+
296
  /**
297
  * Initialisierung der internen Variablen
298
  *
299
  * @since 2.4
300
+ * @change 2.5.2
301
  */
302
+
303
  private static function _init_internal_vars()
304
  {
305
  self::$_base = plugin_basename(__FILE__);
306
  self::$_secret = substr(md5(get_bloginfo('url')), 0, 5). '-comment';
307
+
308
  self::$defaults = array(
309
  'options' => array(
310
  /* Allgemein */
311
  'advanced_check' => 1,
312
+ 'regexp_check' => 1,
313
  'spam_ip' => 1,
314
  'already_commented' => 1,
315
  'ignore_pings' => 0,
316
  'always_allowed' => 0,
317
+
318
  'dashboard_chart' => 1,
319
  'dashboard_count' => 0,
320
+
321
  /* Filter */
322
  'country_code' => 0,
323
  'country_black' => '',
324
  'country_white' => '',
325
+
326
  'translate_api' => 0,
327
  'translate_lang' => '',
328
+
329
+ 'dnsbl_check' => 0,
330
+ 'bbcode_check' => 1,
331
+
332
  /* Erweitert */
333
  'flag_spam' => 1,
334
  'email_notify' => 1,
335
  'no_notice' => 1,
336
  'cronjob_enable' => 0,
337
  'cronjob_interval' => 0,
338
+
339
  'ignore_filter' => 0,
340
  'ignore_type' => 0,
341
+
342
  'reasons_enable' => 0,
343
  'ignore_reasons' => array()
344
  ),
345
  'reasons' => array(
346
+ 'css' => 'CSS Hack',
347
+ 'empty' => 'Empty Data',
348
+ 'server' => 'Server IP',
349
+ 'localdb' => 'Local DB Spam',
350
+ 'country' => 'Country Check',
351
+ 'dnsbl' => 'DNSBL Spam',
352
+ 'bbcode' => 'BBCode',
353
+ 'lang' => 'Comment Language',
354
+ 'regexp' => 'RegExp'
355
  )
356
  );
357
  }
358
+
359
+
360
  /**
361
  * Prüfung und Rückgabe eines Array-Keys
362
  *
367
  * @param string $key Name des Keys
368
  * @return mixed Wert des angeforderten Keys
369
  */
370
+
371
  public static function get_key($array, $key)
372
  {
373
  if ( empty($array) or empty($key) or empty($array[$key]) ) {
374
  return null;
375
  }
376
+
377
  return $array[$key];
378
  }
379
+
380
+
381
  /**
382
  * Lokalisierung der Admin-Seiten
383
  *
399
 
400
  case 'plugins':
401
  return ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'plugins.php' );
402
+
403
  case 'admin-post':
404
  return ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'admin-post.php' );
405
 
406
+ case 'edit-comments':
407
+ return ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'edit-comments.php' );
408
+
409
  default:
410
  return false;
411
  }
427
  'antispam-bee/lang'
428
  );
429
  }
430
+
431
+
432
  /**
433
  * Hinzufügen des Links zu den Einstellungen
434
  *
478
  if ( $file != self::$_base ) {
479
  return $input;
480
  }
481
+
482
  return array_merge(
483
  $input,
484
  array(
485
+ '<a href="https://flattr.com/t/1323822" target="_blank">Flattr</a>',
486
+ '<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=5RDDW9FEHGLG6" target="_blank">PayPal</a>'
487
  )
488
  );
489
  }
 
 
 
 
 
 
 
 
490
 
 
 
 
 
 
491
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
 
493
+
 
 
 
 
 
 
 
 
 
 
494
  ############################
495
  ####### RESSOURCEN #######
496
  ############################
497
+
498
+
499
  /**
500
  * Registrierung von Ressourcen (CSS & JS)
501
  *
546
  'options_page'
547
  )
548
  );
549
+
550
  /* JS einbinden */
551
  add_action(
552
  'admin_print_scripts-' . $page,
564
  'add_options_style'
565
  )
566
  );
567
+
568
  /* PHP laden */
569
  add_action(
570
  'load-' .$page,
600
  {
601
  wp_enqueue_style('ab_style');
602
  }
603
+
604
+
605
  /**
606
  * Einbindung der GUI
607
  *
608
  * @since 2.4
609
  * @change 2.4
610
  */
611
+
612
  public static function init_options_page()
613
  {
614
  require_once( dirname(__FILE__). '/inc/gui.class.php' );
615
  }
616
+
617
+
618
+
619
+
620
  ############################
621
  ####### DASHBOARD ########
622
  ############################
623
+
624
+
625
  /**
626
  * Anzeige des Spam-Counters auf dem Dashboard
627
  *
628
  * @since 0.1
629
+ * @change 2.6.0
630
  */
631
 
632
  public static function add_dashboard_count()
633
  {
634
  /* Aktiv? */
635
+ if ( ! self::get_option('dashboard_count') ) {
636
  return;
637
  }
638
+
639
+ /* Add list item icon */
640
+ echo '<style>#dashboard_right_now .ab-count a:before {content: "\f117"}</style>';
641
+
642
  /* Ausgabe */
643
  echo sprintf(
644
+ '<li class="ab-count">
645
+ <a href="%s">
646
+ %s %s
647
+ </a>
648
+ </li>',
649
+ add_query_arg(
650
+ array(
651
+ 'page' => 'antispam_bee'
652
+ ),
653
+ admin_url('options-general.php')
654
+ ),
655
  esc_html( self::_get_spam_count() ),
656
  esc_html__('Blocked', 'antispam_bee')
657
  );
662
  * Initialisierung des Dashboard-Chart
663
  *
664
  * @since 1.9
665
+ * @change 2.5.6
666
  */
667
 
668
  public static function add_dashboard_chart()
669
  {
670
  /* Filter */
671
+ if ( ! current_user_can('publish_posts') OR ! self::get_option('dashboard_chart') ) {
672
  return;
673
  }
674
 
703
 
704
 
705
  /**
706
+ * Print dashboard styles
707
  *
708
+ * @since 1.9.0
709
+ * @change 2.5.8
710
  */
711
 
712
  public static function add_dashboard_style()
713
  {
714
+ /* Get plugin data */
715
  $plugin = get_plugin_data(__FILE__);
716
+
717
+ /* Register styles */
718
  wp_register_style(
719
  'ab_chart',
720
  plugins_url('css/dashboard.min.css', __FILE__),
722
  $plugin['Version']
723
  );
724
 
725
+ /* Embed styles */
726
  wp_print_styles('ab_chart');
727
  }
728
 
729
 
730
  /**
731
+ * Print dashboard scripts
732
  *
733
+ * @since 1.9.0
734
+ * @change 2.5.8
735
  */
736
 
737
  public static function add_dashboard_script()
738
  {
739
+ /* Get stats */
740
+ if ( ! self::get_option('daily_stats') ) {
 
 
 
741
  return;
742
  }
743
 
744
+ /* Get plugin data */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
  $plugin = get_plugin_data(__FILE__);
746
 
747
+ /* Register scripts */
748
  wp_register_script(
749
+ 'sm_raphael_js',
750
+ plugins_url('js/raphael.min.js', __FILE__),
751
+ array(),
752
+ $plugin['Version'],
753
+ true
754
  );
755
  wp_register_script(
756
+ 'sm_raphael_helper',
757
+ plugins_url('js/raphael.helper.min.js', __FILE__),
758
+ array(),
759
+ $plugin['Version'],
760
+ true
761
  );
762
+ wp_register_script(
763
+ 'ab_chart_js',
764
+ plugins_url('js/dashboard.min.js', __FILE__),
765
+ array('jquery'),
766
+ $plugin['Version'],
767
+ true
 
 
 
 
768
  );
769
+
770
+ /* Embed scripts */
771
+ wp_enqueue_script('sm_raphael_js');
772
+ wp_enqueue_script('sm_raphael_helper');
773
+ wp_enqueue_script('ab_chart_js');
774
  }
775
 
776
 
777
  /**
778
+ * Print dashboard html
779
  *
780
+ * @since 1.9.0
781
+ * @change 2.5.8
782
  */
783
 
784
  public static function show_spam_chart()
785
  {
786
+ /* Get stats */
787
  $items = (array)self::get_option('daily_stats');
788
+
789
+ /* Emty array? */
790
+ if ( empty($items) ) {
791
+ echo sprintf(
792
+ '<div id="ab_chart"><p>%s</p></div>',
793
+ esc_html__('No data available.', 'antispam_bee')
794
+ );
795
+
796
+ return;
797
+ }
798
+
799
+ /* Sort stats */
800
+ ksort($items, SORT_NUMERIC);
801
+
802
+ /* HTML start */
803
+ $html = "<table id=ab_chart_data>\n";
804
+
805
+
806
+ /* Timestamp table */
807
+ $html .= "<tfoot><tr>\n";
808
+ foreach($items as $date => $count) {
809
+ $html .= "<th>" .$date. "</th>\n";
810
+ }
811
+ $html .= "</tr></tfoot>\n";
812
+
813
+ /* Counter table */
814
+ $html .= "<tbody><tr>\n";
815
+ foreach($items as $date => $count) {
816
+ $html .= "<td>" .(int) $count. "</td>\n";
817
+ }
818
+ $html .= "</tr></tbody>\n";
819
+
820
+
821
+ /* HTML end */
822
+ $html .= "</table>\n";
823
+
824
+ /* Print html */
825
+ echo '<div id="ab_chart">' .$html. '</div>';
826
  }
827
+
828
+
829
+
830
+
831
  ############################
832
  ######## OPTIONS #########
833
  ############################
834
+
835
+
836
  /**
837
  * Rückgabe der Optionen
838
  *
858
 
859
  return $options;
860
  }
861
+
862
+
863
  /**
864
  * Rückgabe eines Optionsfeldes
865
  *
927
  $options
928
  );
929
  }
930
+
931
+
932
+
933
+
934
  ############################
935
  ######## CRONJOBS ########
936
  ############################
937
+
938
+
939
  /**
940
  * Ausführung des täglichen Cronjobs
941
  *
959
  /* Spam löschen */
960
  self::_delete_old_spam();
961
  }
962
+
963
+
964
  /**
965
  * Löschung alter Spamkommentare
966
  *
992
  /* DB optimieren */
993
  $wpdb->query("OPTIMIZE TABLE `$wpdb->comments`");
994
  }
995
+
996
+
997
  /**
998
  * Initialisierung des Cronjobs
999
  *
1003
 
1004
  public static function init_scheduled_hook()
1005
  {
1006
+ if ( ! wp_next_scheduled('antispam_bee_daily_cronjob') ) {
1007
  wp_schedule_event(
1008
  time(),
1009
  'daily',
1026
  wp_clear_scheduled_hook('antispam_bee_daily_cronjob');
1027
  }
1028
  }
1029
+
1030
+
1031
+
1032
+
1033
  ############################
1034
  ###### SPAMPRÜFUNG #######
1035
  ############################
1067
  $_POST['bee_spam'] = 1;
1068
  }
1069
  }
1070
+
1071
+
1072
  /**
1073
  * Prüfung der eingehenden Anfragen auf Spam
1074
  *
1078
  * @param array $comment Unbehandelter Kommentar
1079
  * @return array $comment Behandelter Kommentar
1080
  */
1081
+
1082
  public static function handle_incoming_request($comment)
1083
  {
1084
  /* Server-Werte */
1095
  /* Ping-Optionen */
1096
  $ping = array(
1097
  'types' => array('pingback', 'trackback', 'pings'),
1098
+ 'allowed' => !self::get_option('ignore_pings')
1099
  );
1100
+
1101
  /* Kommentar */
1102
  if ( strpos($url, 'wp-comments-post.php') !== false && !empty($_POST) ) {
1103
  /* Filter ausführen */
1104
  $status = self::_verify_comment_request($comment);
1105
+
1106
  /* Spam lokalisiert */
1107
  if ( !empty($status['reason']) ) {
1108
  return self::_handle_spam_request(
1110
  $status['reason']
1111
  );
1112
  }
1113
+
1114
  /* Trackback */
1115
  } else if ( in_array(self::get_key($comment, 'comment_type'), $ping['types']) && $ping['allowed'] ) {
1116
  /* Filter ausführen */
1117
  $status = self::_verify_trackback_request($comment);
1118
+
1119
  /* Spam lokalisiert */
1120
  if ( !empty($status['reason']) ) {
1121
  return self::_handle_spam_request(
1125
  );
1126
  }
1127
  }
1128
+
1129
  return $comment;
1130
  }
1131
+
1132
 
1133
  /**
1134
  * Bereitet die Ersetzung des KOmmentarfeldes vor
1157
  )
1158
  );
1159
  }
1160
+
1161
+
1162
  /**
1163
  * ersetzt das Kommentarfeld
1164
  *
1168
  * @param string $data HTML-Code der Webseite
1169
  * @return string Behandelter HTML-Code
1170
  */
1171
+
1172
  public static function replace_comment_field($data)
1173
  {
1174
  /* Leer? */
1175
  if ( empty($data) ) {
1176
  return;
1177
  }
1178
+
1179
+ /* Find the comment textarea */
1180
+ if ( ! preg_match('#<textarea.+?name=["\']comment["\']#s', $data) ) {
1181
+ return $data;
1182
+ }
1183
+
1184
  /* Convert */
1185
  return preg_replace(
1186
  '#<textarea(.+?)name=["\']comment["\'](.+?)</textarea>#s',
1189
  1
1190
  );
1191
  }
 
1192
 
 
 
 
 
 
 
 
 
 
1193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1194
  /**
1195
+ * Prüfung der Trackbacks
1196
  *
1197
+ * @since 2.4
1198
+ * @change 2.5.4
1199
  *
1200
+ * @param array $comment Daten des Trackbacks
1201
+ * @return array Array mit dem Verdachtsgrund [optional]
1202
  */
1203
 
1204
+ private static function _verify_trackback_request($comment)
1205
  {
1206
+ /* IP */
1207
+ $ip = self::get_key($_SERVER, 'REMOTE_ADDR');
1208
 
1209
+ /* Kommentarwerte */
1210
+ $url = self::get_key($comment, 'comment_author_url');
1211
+ $body = self::get_key($comment, 'comment_content');
1212
+
1213
+ /* Leere Werte ? */
1214
+ if ( empty($url) or empty($body) ) {
1215
+ return array(
1216
+ 'reason' => 'empty'
1217
+ );
1218
+ }
1219
+
1220
+ /* IP? */
1221
+ if ( empty($ip) or (function_exists('filter_var') && !filter_var($ip, FILTER_VALIDATE_IP)) ) {
1222
+ return array(
1223
+ 'reason' => 'empty'
1224
+ );
1225
+ }
1226
+
1227
+ /* Optionen */
1228
+ $options = self::get_options();
1229
+
1230
+ /* BBCode Spam */
1231
+ if ( $options['bbcode_check'] && self::_is_bbcode_spam($body) ) {
1232
+ return array(
1233
+ 'reason' => 'bbcode'
1234
+ );
1235
+ }
1236
+
1237
+ /* IP != Server */
1238
+ if ( $options['advanced_check'] && self::_is_fake_ip($ip, parse_url($url, PHP_URL_HOST)) ) {
1239
+ return array(
1240
+ 'reason' => 'server'
1241
+ );
1242
+ }
1243
+
1244
+ /* IP im lokalen Spam */
1245
+ if ( $options['spam_ip'] && self::_is_db_spam($ip, $url) ) {
1246
+ return array(
1247
+ 'reason' => 'localdb'
1248
+ );
1249
+ }
1250
+
1251
+ /* DNSBL Spam */
1252
+ if ( $options['dnsbl_check'] && self::_is_dnsbl_spam($ip) ) {
1253
+ return array(
1254
+ 'reason' => 'dnsbl'
1255
+ );
1256
+ }
1257
+
1258
+ /* Country Code prüfen */
1259
+ if ( $options['country_code'] && self::_is_country_spam($ip) ) {
1260
+ return array(
1261
+ 'reason' => 'country'
1262
+ );
1263
+ }
1264
+ }
1265
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1266
 
 
1267
  /**
1268
+ * Prüfung den Kommentar
1269
  *
1270
+ * @since 2.4
1271
+ * @change 2.5.6
1272
  *
1273
+ * @param array $comment Daten des Kommentars
1274
+ * @return array Array mit dem Verdachtsgrund [optional]
1275
  */
1276
 
1277
+ private static function _verify_comment_request($comment)
1278
  {
1279
+ /* IP */
1280
+ $ip = self::get_key($_SERVER, 'REMOTE_ADDR');
1281
+
1282
+ /* Kommentarwerte */
1283
+ $url = self::get_key($comment, 'comment_author_url');
1284
+ $body = self::get_key($comment, 'comment_content');
1285
+ $email = self::get_key($comment, 'comment_author_email');
1286
+ $author = self::get_key($comment, 'comment_author');
1287
+
1288
+ /* Leere Werte ? */
1289
+ if ( empty($body) ) {
1290
+ return array(
1291
+ 'reason' => 'empty'
1292
+ );
1293
  }
1294
 
1295
+ /* IP? */
1296
+ if ( empty($ip) or (function_exists('filter_var') && !filter_var($ip, FILTER_VALIDATE_IP)) ) {
1297
+ return array(
1298
+ 'reason' => 'empty'
1299
+ );
1300
+ }
1301
 
1302
+ /* Leere Werte ? */
1303
+ if ( get_option('require_name_email') && ( empty($email) OR empty($author) ) ) {
1304
+ return array(
1305
+ 'reason' => 'empty'
1306
+ );
1307
+ }
1308
+
1309
+ /* Optionen */
1310
+ $options = self::get_options();
1311
+
1312
+ /* Bereits kommentiert? */
1313
+ if ( $options['already_commented'] && !empty($email) && self::_is_approved_email($email) ) {
1314
+ return;
1315
+ }
1316
+
1317
+ /* Bot erkannt */
1318
+ if ( !empty($_POST['bee_spam']) ) {
1319
+ return array(
1320
+ 'reason' => 'css'
1321
+ );
1322
+ }
1323
+
1324
+ /* BBCode Spam */
1325
+ if ( $options['bbcode_check'] && self::_is_bbcode_spam($body) ) {
1326
+ return array(
1327
+ 'reason' => 'bbcode'
1328
+ );
1329
+ }
1330
+
1331
+ /* Erweiterter Schutz */
1332
+ if ( $options['advanced_check'] && self::_is_fake_ip($ip) ) {
1333
+ return array(
1334
+ 'reason' => 'server'
1335
+ );
1336
+ }
1337
+
1338
+ /* Regexp für Spam */
1339
+ if ( $options['regexp_check'] && self::_is_regexp_spam(
1340
+ array(
1341
+ 'ip' => $ip,
1342
+ 'host' => parse_url($url, PHP_URL_HOST),
1343
+ 'body' => $body,
1344
+ 'email' => $email,
1345
+ 'author' => $author
1346
  )
1347
+ ) ) {
1348
+ return array(
1349
+ 'reason' => 'regexp'
1350
+ );
1351
+ }
1352
+
1353
+ /* IP im lokalen Spam */
1354
+ if ( $options['spam_ip'] && self::_is_db_spam($ip, $url, $email) ) {
1355
+ return array(
1356
+ 'reason' => 'localdb'
1357
+ );
1358
+ }
1359
+
1360
+ /* DNSBL Spam */
1361
+ if ( $options['dnsbl_check'] && self::_is_dnsbl_spam($ip) ) {
1362
+ return array(
1363
+ 'reason' => 'dnsbl'
1364
+ );
1365
+ }
1366
+
1367
+ /* Country Code prüfen */
1368
+ if ( $options['country_code'] && self::_is_country_spam($ip) ) {
1369
+ return array(
1370
+ 'reason' => 'country'
1371
+ );
1372
+ }
1373
+
1374
+ /* Translate API */
1375
+ if ( $options['translate_api'] && self::_is_lang_spam($body) ) {
1376
+ return array(
1377
+ 'reason' => 'lang'
1378
+ );
1379
+ }
1380
+ }
1381
+
1382
+
1383
+ /**
1384
+ * Anwendung von Regexp, auch benutzerdefiniert
1385
+ *
1386
+ * @since 2.5.2
1387
+ * @change 2.5.6
1388
+ *
1389
+ * @param array $comment Array mit Kommentardaten
1390
+ * @return boolean TRUE bei verdächtigem Kommentar
1391
+ */
1392
+
1393
+ private static function _is_regexp_spam($comment)
1394
+ {
1395
+ /* Felder */
1396
+ $fields = array(
1397
+ 'ip',
1398
+ 'host',
1399
+ 'body',
1400
+ 'email',
1401
+ 'author'
1402
  );
1403
 
1404
+ /* Regexp */
1405
+ $patterns = array(
1406
+ 0 => array(
1407
+ 'host' => '^(www\.)?\d+\w+\.com$',
1408
+ 'body' => '^\w+\s\d+$',
1409
+ 'email' => '@gmail.com$'
1410
+ ),
1411
+ 1 => array(
1412
+ 'body' => '\<\!.+?mfunc.+?\>'
1413
+ )
1414
+ );
1415
+
1416
+ /* Spammy author */
1417
+ if ( $quoted_author = preg_quote($comment['author'], '/') ) {
1418
+ $patterns[] = array(
1419
+ 'body' => sprintf(
1420
+ '<a.+?>%s<\/a>$',
1421
+ $quoted_author
1422
+ )
1423
+ );
1424
+ $patterns[] = array(
1425
+ 'body' => sprintf(
1426
+ '%s https?:.+?$',
1427
+ $quoted_author
1428
+ )
1429
+ );
1430
+ $patterns[] = array(
1431
+ 'email' => '@gmail.com$',
1432
+ 'author' => '^[a-z0-9-\.]+\.[a-z]{2,6}$',
1433
+ 'host' => sprintf(
1434
+ '^%s$',
1435
+ $quoted_author
1436
+ )
1437
+ );
1438
+ }
1439
+
1440
+ /* Hook */
1441
+ $patterns = apply_filters(
1442
+ 'antispam_bee_patterns',
1443
+ $patterns
1444
+ );
1445
+
1446
+ /* Leer? */
1447
+ if ( ! $patterns ) {
1448
+ return false;
1449
+ }
1450
+
1451
+ /* Ausdrücke loopen */
1452
+ foreach ($patterns as $pattern) {
1453
+ $hits = array();
1454
+
1455
+ /* Felder loopen */
1456
+ foreach ($pattern as $field => $regexp) {
1457
+ /* Empty value? */
1458
+ if ( empty($field) OR !in_array($field, $fields) OR empty($regexp) ) {
1459
+ continue;
1460
+ }
1461
+
1462
+ /* Ignore non utf-8 chars */
1463
+ $comment[$field] = ( function_exists('iconv') ? iconv('utf-8', 'utf-8//TRANSLIT', $comment[$field]) : $comment[$field] );
1464
+
1465
+ /* Empty value? */
1466
+ if ( empty($comment[$field]) ) {
1467
+ continue;
1468
+ }
1469
+
1470
+ /* Perform regex */
1471
+ if ( preg_match('/' .$regexp. '/isu', $comment[$field]) ) {
1472
+ $hits[$field] = true;
1473
+ }
1474
+ }
1475
+
1476
+ if ( count($hits) === count($pattern) ) {
1477
+ return true;
1478
+ }
1479
  }
1480
 
1481
  return false;
1482
  }
1483
+
1484
+
1485
+ /**
1486
+ * Prüfung eines Kommentars auf seine Existenz im lokalen Spam
1487
+ *
1488
+ * @since 2.0.0
1489
+ * @change 2.5.4
1490
+ *
1491
+ * @param string $ip Kommentar-IP
1492
+ * @param string $url Kommentar-URL [optional]
1493
+ * @param string $email Kommentar-Email [optional]
1494
+ * @return boolean TRUE bei verdächtigem Kommentar
1495
+ */
1496
+
1497
+ private static function _is_db_spam($ip, $url = '', $email = '')
1498
+ {
1499
+ /* Global */
1500
+ global $wpdb;
1501
+
1502
+ /* Default */
1503
+ $filter = array('`comment_author_IP` = %s');
1504
+ $params = array($ip);
1505
+
1506
+ /* URL abgleichen */
1507
+ if ( ! empty($url) ) {
1508
+ $filter[] = '`comment_author_url` = %s';
1509
+ $params[] = $url;
1510
+ }
1511
+
1512
+ /* E-Mail abgleichen */
1513
+ if ( ! empty($email) ) {
1514
+ $filter[] = '`comment_author_email` = %s';
1515
+ $params[] = $email;
1516
+ }
1517
+
1518
+ /* Query ausführen */
1519
+ $result = $wpdb->get_var(
1520
+ $wpdb->prepare(
1521
+ sprintf(
1522
+ "SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = 'spam' AND (%s) LIMIT 1",
1523
+ implode(' OR ', $filter)
1524
+ ),
1525
+ $params
1526
+ )
1527
+ );
1528
+
1529
+ return !empty($result);
1530
+ }
1531
+
1532
 
1533
  /**
1534
  * Prüfung auf erlaubten Ländercodes
1535
  *
1536
  * @since 0.1
1537
+ * @change 2.5.1
1538
  *
1539
  * @param string $ip IP-Adresse
1540
  * @return boolean TRUE bei unerwünschten Ländercodes
1541
  */
1542
 
1543
+ private static function _is_country_spam($ip)
1544
  {
 
 
 
 
 
1545
  /* Optionen */
1546
  $options = self::get_options();
1547
 
1570
  sprintf(
1571
  'https://geoip.maxmind.com/a?l=%s&i=%s',
1572
  strrev('1Lbn0ZsL08e1'),
1573
+ self::_anonymize_ip($ip)
1574
  ),
1575
  'https'
1576
  )
1597
  /* Whitelist */
1598
  return ( in_array($country, $white) ? false : true );
1599
  }
1600
+
1601
+
1602
  /**
1603
  * Prüfung auf DNSBL Spam
1604
  *
1611
 
1612
  private static function _is_dnsbl_spam($ip)
1613
  {
1614
+ /* Start request */
1615
+ $response = wp_remote_get(
1616
+ esc_url_raw(
1617
+ sprintf(
1618
+ 'http://www.stopforumspam.com/api?ip=%s&f=json',
1619
+ $ip
1620
+ ),
1621
+ 'http'
1622
+ )
1623
+ );
1624
+
1625
+ /* Response error? */
1626
+ if ( is_wp_error($response) ) {
1627
+ return false;
1628
  }
1629
+
1630
+ /* Get JSON */
1631
+ $json = wp_remote_retrieve_body($response);
1632
+
1633
+ /* Decode JSON */
1634
+ $result = json_decode($json);
1635
+
1636
+ /* Empty data */
1637
+ if ( empty($result->success) ) {
1638
  return false;
1639
  }
1640
+
1641
+ /* Return status */
1642
+ return (bool) $result->ip->appears;
 
 
1643
  }
1644
+
1645
+
1646
  /**
1647
+ * Prüfung auf BBCode Spam
1648
  *
1649
+ * @since 2.5.1
1650
+ * @change 2.5.1
1651
  *
1652
+ * @param string $body Inhalt eines Kommentars
1653
+ * @return boolean TRUE bei BBCode im Inhalt
1654
  */
 
 
 
 
 
 
 
 
 
1655
 
1656
+ private static function _is_bbcode_spam($body)
1657
+ {
1658
+ return (bool) preg_match('/\[url[=\]].*\[\/url\]/is', $body);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1659
  }
1660
+
1661
+
1662
  /**
1663
  * Prüfung auf eine bereits freigegebene E-Mail-Adresse
1664
  *
1665
  * @since 2.0
1666
+ * @change 2.5.1
1667
  *
1668
  * @param string $email E-Mail-Adresse
1669
  * @return boolean TRUE bei einem gefundenen Eintrag
1671
 
1672
  private static function _is_approved_email($email)
1673
  {
 
 
 
 
 
1674
  /* Global */
1675
  global $wpdb;
1676
 
1677
  /* Suchen */
1678
+ $result = $wpdb->get_var(
1679
  $wpdb->prepare(
1680
  "SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = '1' AND `comment_author_email` = %s LIMIT 1",
1681
  (string)$email
1683
  );
1684
 
1685
  /* Gefunden? */
1686
+ if ( $result ) {
1687
  return true;
1688
  }
1689
 
1690
  return false;
1691
  }
1692
+
1693
+
1694
  /**
1695
  * Prüfung auf eine gefälschte IP
1696
  *
1697
  * @since 2.0
1698
+ * @change 2.5.1
1699
  *
1700
  * @param string $ip IP-Adresse
1701
  * @param string $host Host [optional]
1704
 
1705
  private static function _is_fake_ip($ip, $host = false)
1706
  {
 
 
 
 
 
1707
  /* Remote Host */
1708
  $hostbyip = gethostbyaddr($ip);
1709
 
1711
  if ( !self::_is_ipv4($ip) ) {
1712
  return $ip != $hostbyip;
1713
  }
1714
+
1715
  /* IPv4 / Kommentar */
1716
  if ( empty($host) ) {
1717
  $found = strpos(
1720
  gethostbyname($hostbyip)
1721
  )
1722
  );
1723
+
1724
  /* IPv4 / Trackback */
1725
  } else {
1726
  /* IP-Vergleich */
1727
  if ( $hostbyip == $ip ) {
1728
  return true;
1729
  }
1730
+
1731
  /* Treffer suchen */
1732
  $found = strpos(
1733
  $ip,
1739
 
1740
  return $found === false;
1741
  }
1742
+
1743
+
1744
  /**
1745
  * Prüfung auf unerwünschte Sprachen
1746
  *
1755
  {
1756
  /* Init */
1757
  $lang = self::get_option('translate_lang');
1758
+
1759
  /* Formatieren */
1760
  $content = wp_strip_all_tags($content);
1761
+
1762
  /* Keine Daten? */
1763
  if ( empty($lang) or empty($content) ) {
1764
  return false;
1765
  }
1766
+
1767
  /* Formatieren */
1768
  $content = rawurlencode(
1769
  ( function_exists('mb_substr') ? mb_substr($content, 0, 200) : substr($content, 0, 200) )
1799
 
1800
  return ( strtolower($matches[1]) != $lang );
1801
  }
1802
+
1803
+
1804
  /**
1805
+ * Kürzung der IP-Adressen
1806
  *
1807
+ * @since 0.1
1808
+ * @change 2.5.1
1809
  *
1810
+ * @param string $ip Original IP
1811
+ * @param boolean $cut_end Kürzen vom Ende?
1812
+ * @return string Gekürzte IP
1813
  */
1814
+
1815
+ private static function _cut_ip($ip, $cut_end = true)
1816
  {
1817
+ /* Trenner */
1818
+ $separator = ( self::_is_ipv4($ip) ? '.' : ':' );
1819
+
1820
+ return str_replace(
1821
+ ( $cut_end ? strrchr( $ip, $separator) : strstr( $ip, $separator) ),
1822
+ '',
1823
+ $ip
1824
+ );
1825
+ }
1826
+
1827
+
1828
+ /**
1829
+ * Anonymisierung der IP-Adressen
1830
+ *
1831
+ * @since 2.5.1
1832
+ * @change 2.5.1
1833
+ *
1834
+ * @param string $ip Original IP
1835
+ * @return string Anonyme IP
1836
+ */
1837
+
1838
+ private static function _anonymize_ip($ip)
1839
+ {
1840
+ if ( self::_is_ipv4($ip) ) {
1841
+ return self::_cut_ip($ip). '.0';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1842
  }
1843
+
1844
+ return self::_cut_ip($ip, false). ':0:0:0:0:0:0:0';
1845
  }
1846
+
1847
+
1848
  /**
1849
+ * Dreht die IP-Adresse
1850
+ *
1851
+ * @since 2.4.5
1852
+ * @change 2.4.5
1853
+ *
1854
+ * @param string $ip IP-Adresse
1855
+ * @return string Gedrehte IP-Adresse
1856
+ */
1857
+
1858
+ private static function _reverse_ip($ip)
1859
+ {
1860
+ return implode(
1861
+ '.',
1862
+ array_reverse(
1863
+ explode(
1864
+ '.',
1865
+ $ip
1866
+ )
1867
+ )
1868
+ );
1869
+ }
1870
+
1871
+
1872
+ /**
1873
+ * Prüfung auf eine IPv4-Adresse
1874
+ *
1875
+ * @since 2.4
1876
+ * @change 2.4
1877
+ *
1878
+ * @param string $ip Zu prüfende IP
1879
+ * @return integer Anzahl der Treffer
1880
+ */
1881
+
1882
+ private static function _is_ipv4($ip)
1883
+ {
1884
+ return preg_match('/^\d{1,3}(\.\d{1,3}){3,3}$/', $ip);
1885
+ }
1886
+
1887
+
1888
+ /**
1889
+ * Prüfung auf Mobile
1890
  *
1891
  * @since 0.1
1892
  * @change 2.4
1893
  *
1894
+ * @return boolean TRUE, wenn "wptouch" aktiv ist
1895
+ */
1896
+
1897
+ private static function _is_mobile()
1898
+ {
1899
+ return strpos(TEMPLATEPATH, 'wptouch');
1900
+ }
1901
+
1902
+
1903
+
1904
+
1905
+ ############################
1906
+ ##### SPAM-BEHANDLUNG ####
1907
+ ############################
1908
+
1909
+
1910
+ /**
1911
+ * Ausführung des Lösch-/Markier-Vorgangs
1912
+ *
1913
+ * @since 0.1
1914
+ * @change 2.6.0
1915
+ *
1916
  * @param array $comment Unbehandelte Kommentardaten
1917
  * @param string $reason Verdachtsgrund
1918
  * @param boolean $is_ping Ping (ja oder nein) [optional]
1923
  {
1924
  /* Optionen */
1925
  $options = self::get_options();
1926
+
1927
  /* Einstellungen */
1928
  $spam_remove = !$options['flag_spam'];
1929
  $spam_notice = !$options['no_notice'];
1931
  /* Filter-Einstellungen */
1932
  $ignore_filter = $options['ignore_filter'];
1933
  $ignore_type = $options['ignore_type'];
1934
+ $ignore_reason = in_array($reason, (array)$options['ignore_reasons']);
1935
 
1936
+ /* Spam merken */
1937
+ self::_update_spam_log($comment);
1938
  self::_update_spam_count();
1939
  self::_update_daily_stats();
1940
 
1941
  /* Spam löschen */
1942
  if ( $spam_remove ) {
1943
+ self::_go_in_peace();
1944
  }
1945
 
1946
  /* Typen behandeln */
1947
  if ( $ignore_filter && (( $ignore_type == 1 && $is_ping ) or ( $ignore_type == 2 && !$is_ping )) ) {
1948
+ self::_go_in_peace();
1949
  }
1950
+
1951
  /* Spamgrund */
1952
  if ( $ignore_reason ) {
1953
+ self::_go_in_peace();
1954
  }
1955
 
1956
  /* Spam-Grund */
1981
  )
1982
  );
1983
 
1984
+ /* Spam reason as comment meta */
 
1985
  if ( $spam_notice ) {
1986
+ add_filter(
1987
+ 'comment_post',
1988
+ array(
1989
+ __CLASS__,
1990
+ 'add_spam_reason_to_comment'
1991
+ )
1992
  );
1993
  }
1994
 
1995
  return $comment;
1996
  }
1997
+
1998
+
1999
+ /**
2000
+ * Logfile mit erkanntem Spam
2001
+ *
2002
+ * @since 2.5.7
2003
+ * @change 2.5.7
2004
+ *
2005
+ * @param array $comment Array mit Kommentardaten
2006
+ * @return mixed FALSE im Fehlerfall
2007
+ */
2008
+
2009
+ private static function _update_spam_log($comment)
2010
+ {
2011
+ /* Skip logfile? */
2012
+ if ( ! defined('ANTISPAM_BEE_LOG_FILE') OR ! ANTISPAM_BEE_LOG_FILE OR ! is_writable(ANTISPAM_BEE_LOG_FILE) ) {
2013
+ return false;
2014
+ }
2015
+
2016
+ /* Compose entry */
2017
+ $entry = sprintf(
2018
+ '%s comment for post=%d from host=%s marked as spam%s',
2019
+ current_time('mysql'),
2020
+ $comment['comment_post_ID'],
2021
+ self::get_key($_SERVER, 'REMOTE_ADDR'),
2022
+ PHP_EOL
2023
+ );
2024
+
2025
+ /* Write */
2026
+ file_put_contents(
2027
+ ANTISPAM_BEE_LOG_FILE,
2028
+ $entry,
2029
+ FILE_APPEND | LOCK_EX
2030
+ );
2031
+ }
2032
+
2033
+
2034
+ /**
2035
+ * Sendet den 403-Header und beendet die Verbindung
2036
+ *
2037
+ * @since 2.5.6
2038
+ * @change 2.5.6
2039
+ */
2040
+
2041
+ private static function _go_in_peace()
2042
+ {
2043
+ status_header(403);
2044
+ die('Spam deleted.');
2045
+ }
2046
+
2047
+
2048
+ /**
2049
+ * Add spam reason as comment data
2050
+ *
2051
+ * @since 2.6.0
2052
+ * @change 2.6.0
2053
+ *
2054
+ * @param integer $comment_id Comment ID
2055
+ */
2056
+
2057
+ public static function add_spam_reason_to_comment( $comment_id )
2058
+ {
2059
+ add_comment_meta(
2060
+ $comment_id,
2061
+ 'antispam_bee_reason',
2062
+ self::$_reason
2063
+ );
2064
+ }
2065
+
2066
+
2067
+ /**
2068
+ * Delete spam reason as comment data
2069
+ *
2070
+ * @since 2.6.0
2071
+ * @change 2.6.0
2072
+ *
2073
+ * @param integer $comment_id Comment ID
2074
+ */
2075
+
2076
+ public static function delete_spam_reason_by_comment( $comment_id )
2077
+ {
2078
+ delete_comment_meta(
2079
+ $comment_id,
2080
+ 'antispam_bee_reason'
2081
+ );
2082
+ }
2083
+
2084
 
2085
  /**
2086
  * Versand einer Benachrichtigung via E-Mail
2087
  *
2088
  * @since 0.1
2089
+ * @change 2.5.7
2090
+ *
2091
+ * @hook string antispam_bee_notification_subject Custom subject for notification mails
2092
  *
2093
  * @param intval $id ID des Kommentars
2094
  * @return intval $id ID des Kommentars
2098
  {
2099
  /* Optionen */
2100
  $options = self::get_options();
2101
+
2102
  /* Keine Benachrichtigung? */
2103
  if ( !$options['email_notify'] ) {
2104
  return $id;
2106
 
2107
  /* Kommentar */
2108
  $comment = get_comment($id, ARRAY_A);
2109
+
2110
  /* Keine Werte? */
2111
  if ( empty($comment) ) {
2112
  return $id;
2113
  }
2114
 
2115
  /* Parent-Post */
2116
+ if ( ! $post = get_post($comment['comment_post_ID']) ) {
2117
  return $id;
2118
  }
2119
 
2123
  /* Betreff */
2124
  $subject = sprintf(
2125
  '[%s] %s',
2126
+ stripslashes_deep(
2127
+ html_entity_decode(
2128
+ get_bloginfo('name'),
2129
+ ENT_QUOTES
2130
+ )
2131
+ ),
2132
  __('Comment marked as spam', 'antispam_bee')
2133
  );
2134
 
2197
  /* Send */
2198
  wp_mail(
2199
  get_bloginfo('admin_email'),
2200
+ apply_filters(
2201
+ 'antispam_bee_notification_subject',
2202
+ $subject
2203
+ ),
2204
  $body
2205
  );
2206
 
2207
  return $id;
2208
  }
2209
+
2210
+
2211
+
2212
+
2213
  ############################
2214
  ####### STATISTIK ########
2215
  ############################
css/dashboard.css CHANGED
@@ -1,4 +1,22 @@
 
 
1
  #ab_chart {
2
  color: #aaa;
3
- height: 120px;
4
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* @group Vorderseite */
2
+
3
  #ab_chart {
4
  color: #aaa;
5
+ height: 140px;
6
+ margin: 0 -4px;
7
+ text-align: center;
8
+ }
9
+ #ab_chart_data {
10
+ display: none;
11
+ }
12
+
13
+ #ab_widget .inside {
14
+ height: 1%;
15
+ margin: 0;
16
+ padding-bottom: 0;
17
+ overflow: hidden;
18
+ position: relative;
19
+ white-space: nowrap;
20
+ }
21
+
22
+ /* @end group */
css/dashboard.min.css CHANGED
@@ -1 +1 @@
1
- #ab_chart{color:#aaa;height:120px;}
1
+ #ab_chart{color:#aaa;height:140px;margin:0 -4px;text-align:center;}#ab_chart_data{display:none;}#ab_widget .inside{height:1%;margin:0;padding-bottom:0;overflow:hidden;position:relative;white-space:nowrap;}
css/styles.css CHANGED
@@ -1,22 +1,8 @@
1
- /* @group Icon */
2
-
3
- #icon-ab {
4
- width: 32px;
5
- height: 32px;
6
- background: url('../img/icon@2x.png');
7
- background-size: 100%;
8
- }
9
-
10
- /* @end group */
11
-
12
-
13
  /* @group Webfont */
14
 
15
  @font-face {
16
- font-family: 'fontello';
17
- src: url('../font/fontello.woff') format('woff');
18
- font-weight: normal;
19
- font-style: normal;
20
  }
21
 
22
  /* @end group */
@@ -31,18 +17,11 @@
31
  margin: 0;
32
  padding: 0;
33
  outline: 0;
34
-
35
  -webkit-box-sizing: border-box;
36
  -moz-box-sizing: border-box;
37
  box-sizing: border-box;
38
  }
39
- .ab-main,
40
- .ab-main input,
41
- .ab-main select {
42
- font-family: sans-serif;
43
- font-size: 12px;
44
- line-height: 16px;
45
- }
46
 
47
  /* @end group */
48
 
@@ -64,13 +43,14 @@
64
  .ab-wrap {
65
  color: #2f353e;
66
  height: 1%;
 
67
  overflow: hidden;
68
- padding: 20px 0 0 6px;
69
  text-rendering: optimizeLegibility;
70
  }
71
  .ab-column {
72
  float: left;
73
- margin: 0 20px 0 0;
74
  position: relative;
75
  }
76
 
@@ -87,7 +67,7 @@
87
  text-transform: uppercase;
88
  }
89
  .ab-column h3.icon:before {
90
- font: normal 30px/30px fontello;
91
  top: 4px;
92
  right: 20px;
93
  speak: none;
@@ -95,6 +75,7 @@
95
  color: #8e959c;
96
  position: absolute;
97
  text-align: center;
 
98
  }
99
  .ab-column.ab-arrow h3.icon:before {
100
  content: '\2387';
@@ -122,20 +103,14 @@
122
 
123
  .ab-column input[type="text"],
124
  .ab-column select {
125
- text-align: center;
126
  font-size: 11px;
127
- height: 15px;
128
- margin: 0 2px;
129
- border: 0;
130
- border-bottom: 1px solid;
131
  background: #f8f8f9;
132
  }
133
- .ab-column select {
134
- height: 18px;
135
- }
136
  .ab-column select[multiple] {
137
- width: 120px;
138
- height: 45px;
139
  }
140
  .ab-column input.ab-mini-field {
141
  width: 30px;
@@ -148,7 +123,6 @@
148
  color: #8e959c;
149
  margin: 0 0 0 7px;
150
  display: inline-block;
151
- font-size: 11px;
152
  text-transform: uppercase;
153
  }
154
 
@@ -159,7 +133,6 @@
159
 
160
  .ab-column > ul {
161
  padding: 0 20px 0 0;
162
- border-right: 1px solid #f8f8f9;
163
  }
164
  .ab-column:last-of-type > ul {
165
  border: 0;
@@ -167,16 +140,12 @@
167
  .ab-column > ul > li {
168
  width: 330px;
169
  margin: 0 0 36px;
170
- border: 1px solid #e0e5e9;
171
- padding: 10px 0 12px 20px;
172
  position: relative;
173
  background: #fff;
174
  list-style: none;
175
- box-shadow: 0 0 0 0 #fff, 0 0 0 3px #f8f8f9;
176
-
177
- -webkit-border-radius: 3px;
178
- -moz-border-radius: 3px;
179
  border-radius: 3px;
 
180
  }
181
 
182
  .ab-column > ul > li a {
@@ -189,19 +158,20 @@
189
  }
190
 
191
  .ab-column > ul > li input[type="checkbox"] {
192
- float: left;
193
- margin: 10px 10px 0 0;
194
  }
195
  .ab-column > ul > li label {
196
  cursor: default;
197
  display: inline-block;
198
- padding: 0 0 0 10px;
199
  overflow: hidden;
200
- border-left: 1px solid #f8f8f9;
201
  }
202
  .ab-column > ul > li label span {
203
  color: #8e959c;
204
  display: block;
 
 
205
  }
206
 
207
  /* @end group */
@@ -215,34 +185,35 @@
215
  content: '';
216
  position: absolute;
217
  }
218
- .ab-column.ab-arrow > ul > li:before {
219
- left: 165px;
220
- bottom: -24px;
 
221
  border-width: 10px 10px 0;
222
- border-color: #e0e5e9 transparent;
223
  border-style: solid;
224
  }
 
 
 
 
225
  .ab-column.ab-arrow > ul > li:after {
226
- left: 166px;
227
  bottom: -22px;
228
- border-width: 9px 9px 0;
229
- border-color: #fff transparent;
230
- border-style: solid;
231
  }
232
 
233
  .ab-column.ab-join > ul > li:before {
234
- left: 175px;
235
- bottom: -29px;
236
- height: 20px;
237
- border-right: 1px solid #e0e5e9;
238
  }
239
 
240
  .ab-column.ab-diff > ul > li:before {
241
- left: 165px;
242
- bottom: -20px;
243
- width: 20px;
244
  height: 0;
245
- border-bottom: 1px solid #e0e5e9;
246
  }
247
 
248
  /* @end group */
@@ -251,28 +222,16 @@
251
  /* @group Submit-Zeile */
252
 
253
  .ab-column.ab-submit {
254
- width: 352px;
255
- margin: 56px 41px 0 0;
256
  padding: 30px 0;
257
- border-top: 1px solid #e0e5e9;;
258
  }
259
  .ab-column.ab-submit > p {
260
  float: right;
261
  margin: 0;
262
- height: 24px;
263
- }
264
- .ab-column.ab-submit > p > a {
265
- float: left;
266
- line-height: 24px;
267
- }
268
- .ab-column.ab-submit > p > a:before {
269
- margin: 0 4px;
270
- content: '|';
271
- display: inline-block;
272
- }
273
- .ab-column.ab-submit > p > a:first-child:before {
274
- margin: 0;
275
- content: '';
276
  }
277
 
278
  /* @end group */
@@ -286,7 +245,7 @@
286
  }
287
 
288
  .ab-column > ul > li > ul {
289
- margin: 10px 10px 0 33px;
290
  display: none;
291
  list-style: none;
292
  }
@@ -296,33 +255,8 @@
296
  .ab-column > ul > li > ul label {
297
  margin: 0 0 0 7px;
298
  }
299
- .ab-column > ul > li > input[type="checkbox"]:checked + ul {
300
  display: block;
301
  }
302
 
303
- /* @end group */
304
-
305
-
306
- /* @group Updated-Fix */
307
-
308
- .settings_page_antispam_bee #setting-error-settings_updated + form {
309
- margin: -20px 0 0;
310
- }
311
-
312
- /* @end group */
313
-
314
-
315
- /* @group Media Queries */
316
-
317
- @media (min-width: 1252px) {
318
- .ab-diff > ul {
319
- border: 0;
320
- }
321
- }
322
- @media (-webkit-min-device-pixel-ratio: 2) {
323
- .ab-column select {
324
- height: 15px;
325
- }
326
- }
327
-
328
  /* @end group */
 
 
 
 
 
 
 
 
 
 
 
 
1
  /* @group Webfont */
2
 
3
  @font-face {
4
+ font-family: 'antispambee-icons';
5
+ src: url('../font/icons.woff') format('woff');
 
 
6
  }
7
 
8
  /* @end group */
17
  margin: 0;
18
  padding: 0;
19
  outline: 0;
20
+
21
  -webkit-box-sizing: border-box;
22
  -moz-box-sizing: border-box;
23
  box-sizing: border-box;
24
  }
 
 
 
 
 
 
 
25
 
26
  /* @end group */
27
 
43
  .ab-wrap {
44
  color: #2f353e;
45
  height: 1%;
46
+ margin: 0 0 0 -10px;
47
  overflow: hidden;
48
+ padding: 20px 0 0 0;
49
  text-rendering: optimizeLegibility;
50
  }
51
  .ab-column {
52
  float: left;
53
+ margin: 0 0 0 10px;
54
  position: relative;
55
  }
56
 
67
  text-transform: uppercase;
68
  }
69
  .ab-column h3.icon:before {
70
+ font: normal 30px/30px antispambee-icons;
71
  top: 4px;
72
  right: 20px;
73
  speak: none;
75
  color: #8e959c;
76
  position: absolute;
77
  text-align: center;
78
+ -webkit-font-smoothing: antialiased;
79
  }
80
  .ab-column.ab-arrow h3.icon:before {
81
  content: '\2387';
103
 
104
  .ab-column input[type="text"],
105
  .ab-column select {
106
+ height: 20px;
107
  font-size: 11px;
108
+ text-align: center;
 
 
 
109
  background: #f8f8f9;
110
  }
 
 
 
111
  .ab-column select[multiple] {
112
+ width: 150px;
113
+ height: 56px;
114
  }
115
  .ab-column input.ab-mini-field {
116
  width: 30px;
123
  color: #8e959c;
124
  margin: 0 0 0 7px;
125
  display: inline-block;
 
126
  text-transform: uppercase;
127
  }
128
 
133
 
134
  .ab-column > ul {
135
  padding: 0 20px 0 0;
 
136
  }
137
  .ab-column:last-of-type > ul {
138
  border: 0;
140
  .ab-column > ul > li {
141
  width: 330px;
142
  margin: 0 0 36px;
143
+ padding: 10px 0 12px 12px;
 
144
  position: relative;
145
  background: #fff;
146
  list-style: none;
 
 
 
 
147
  border-radius: 3px;
148
+ white-space: nowrap;
149
  }
150
 
151
  .ab-column > ul > li a {
158
  }
159
 
160
  .ab-column > ul > li input[type="checkbox"] {
161
+ display: inline-block;
162
+ margin: 0 8px 0 0;
163
  }
164
  .ab-column > ul > li label {
165
  cursor: default;
166
  display: inline-block;
 
167
  overflow: hidden;
168
+ line-height: 24px;
169
  }
170
  .ab-column > ul > li label span {
171
  color: #8e959c;
172
  display: block;
173
+ font-size: 12px;
174
+ line-height: 16px;
175
  }
176
 
177
  /* @end group */
185
  content: '';
186
  position: absolute;
187
  }
188
+
189
+ .ab-column.ab-arrow > ul > li:before,
190
+ .ab-column.ab-arrow > ul > li:after {
191
+ left: 157px;
192
  border-width: 10px 10px 0;
 
193
  border-style: solid;
194
  }
195
+ .ab-column.ab-arrow > ul > li:before {
196
+ bottom: -24px;
197
+ border-color: #fff transparent;
198
+ }
199
  .ab-column.ab-arrow > ul > li:after {
 
200
  bottom: -22px;
201
+ border-color: #f1f1f1 transparent;
 
 
202
  }
203
 
204
  .ab-column.ab-join > ul > li:before {
205
+ left: 171px;
206
+ bottom: -27px;
207
+ height: 18px;
208
+ border-right: 2px solid #fff;
209
  }
210
 
211
  .ab-column.ab-diff > ul > li:before {
212
+ left: 162px;
213
+ bottom: -19px;
214
+ width: 18px;
215
  height: 0;
216
+ border-bottom: 2px solid #fff;
217
  }
218
 
219
  /* @end group */
222
  /* @group Submit-Zeile */
223
 
224
  .ab-column.ab-submit {
225
+ width: 342px;
226
+ margin: 0 0 0 10px;
227
  padding: 30px 0;
228
+ border-top: 1px solid #e0e5e9;
229
  }
230
  .ab-column.ab-submit > p {
231
  float: right;
232
  margin: 0;
233
+ height: 28px;
234
+ line-height: 28px;
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
 
237
  /* @end group */
245
  }
246
 
247
  .ab-column > ul > li > ul {
248
+ margin: 10px 10px 0 26px;
249
  display: none;
250
  list-style: none;
251
  }
255
  .ab-column > ul > li > ul label {
256
  margin: 0 0 0 7px;
257
  }
258
+ .ab-column > ul > li > input[type="checkbox"]:checked ~ ul {
259
  display: block;
260
  }
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  /* @end group */
css/styles.min.css CHANGED
@@ -1 +1 @@
1
- #icon-ab{width:32px;height:32px;background:url('../img/icon@2x.png');background-size:100%}@font-face{font-family:'fontello';src:url('../font/fontello.woff') format('woff');font-weight:normal;font-style:normal}.ab-main *,.ab-main *:after,.ab-main *:before{border:0;margin:0;padding:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ab-main,.ab-main input,.ab-main select{font-family:sans-serif;font-size:12px;line-height:16px}.browsehappy{margin:0 0 20px;padding:10px;border:1px solid #e66f00;text-align:center}.ab-wrap{color:#2f353e;height:1%;overflow:hidden;padding:20px 0 0 6px;text-rendering:optimizeLegibility}.ab-column{float:left;margin:0 20px 0 0;position:relative}.ab-column h3{margin:0;font-size:14px;font-weight:normal;line-height:20px;text-transform:uppercase}.ab-column h3.icon:before{font:normal 30px/30px fontello;top:4px;right:20px;speak:none;width:1em;color:#8e959c;position:absolute;text-align:center}.ab-column.ab-arrow h3.icon:before{content:'\2387'}.ab-column.ab-join h3.icon:before{content:'\e795'}.ab-column.ab-diff h3.icon:before{content:'\e73c'}.ab-column h6{clear:both;color:#8e959c;margin:0 0 20px;font-size:10px;font-weight:normal;text-transform:uppercase}.ab-column input[type="text"],.ab-column select{text-align:center;font-size:11px;height:15px;margin:0 2px;border:0;border-bottom:1px solid;background:#f8f8f9}.ab-column select{height:18px}.ab-column select[multiple]{width:120px;height:45px}.ab-column input.ab-mini-field{width:30px}.ab-column input.ab-medium-field{width:120px}.ab-column input[type="text"]+label,.ab-column select+label{color:#8e959c;margin:0 0 0 7px;display:inline-block;font-size:11px;text-transform:uppercase}.ab-column>ul{padding:0 20px 0 0;border-right:1px solid #f8f8f9}.ab-column:last-of-type>ul{border:0}.ab-column>ul>li{width:330px;margin:0 0 36px;border:1px solid #e0e5e9;padding:10px 0 12px 20px;position:relative;background:#fff;list-style:none;box-shadow:0 0 0 0 #fff,0 0 0 3px #f8f8f9;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.ab-column>ul>li a{color:inherit;text-decoration:none;border-bottom:1px dotted #e0e5e9}.ab-column>ul>li a:hover{border-color:inherit}.ab-column>ul>li input[type="checkbox"]{float:left;margin:10px 10px 0 0}.ab-column>ul>li label{cursor:default;display:inline-block;padding:0 0 0 10px;overflow:hidden;border-left:1px solid #f8f8f9}.ab-column>ul>li label span{color:#8e959c;display:block}.ab-column>ul>li:after,.ab-column>ul>li:before{width:0;content:'';position:absolute}.ab-column.ab-arrow>ul>li:before{left:165px;bottom:-24px;border-width:10px 10px 0;border-color:#e0e5e9 transparent;border-style:solid}.ab-column.ab-arrow>ul>li:after{left:166px;bottom:-22px;border-width:9px 9px 0;border-color:#fff transparent;border-style:solid}.ab-column.ab-join>ul>li:before{left:175px;bottom:-29px;height:20px;border-right:1px solid #e0e5e9}.ab-column.ab-diff>ul>li:before{left:165px;bottom:-20px;width:20px;height:0;border-bottom:1px solid #e0e5e9}.ab-column.ab-submit{width:352px;margin:56px 41px 0 0;padding:30px 0;border-top:1px solid #e0e5e9}.ab-column.ab-submit>p{float:right;margin:0;height:24px}.ab-column.ab-submit>p>a{float:left;line-height:24px}.ab-column.ab-submit>p>a:before{margin:0 4px;content:'|';display:inline-block}.ab-column.ab-submit>p>a:first-child:before{margin:0;content:''}.ab-column>ul>li:last-of-type:after,.ab-column>ul>li:last-of-type:before{display:none}.ab-column>ul>li>ul{margin:10px 10px 0 33px;display:none;list-style:none}.ab-column>ul>li>ul li{padding:2px 0}.ab-column>ul>li>ul label{margin:0 0 0 7px}.ab-column>ul>li>input[type="checkbox"]:checked+ul{display:block}.settings_page_antispam_bee #setting-error-settings_updated+form{margin:-20px 0 0}@media(min-width:1252px){.ab-diff>ul{border:0}}@media(-webkit-min-device-pixel-ratio:2){.ab-column select{height:15px}}
1
+ @font-face{font-family:'antispambee-icons';src:url('../font/icons.woff') format('woff');}.ab-main *,.ab-main *:after,.ab-main *:before{border:0;margin:0;padding:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}.browsehappy{margin:0 0 20px;padding:10px;border:1px solid #e66f00;text-align:center;}.ab-wrap{color:#2f353e;height:1%;margin:0 0 0 -10px;overflow:hidden;padding:20px 0 0 0;text-rendering:optimizeLegibility;}.ab-column{float:left;margin:0 0 0 10px;position:relative;}.ab-column h3{margin:0;font-size:14px;font-weight:normal;line-height:20px;text-transform:uppercase;}.ab-column h3.icon:before{font:normal 30px/30px antispambee-icons;top:4px;right:20px;speak:none;width:1em;color:#8e959c;position:absolute;text-align:center;-webkit-font-smoothing:antialiased;}.ab-column.ab-arrow h3.icon:before{content:'\2387';}.ab-column.ab-join h3.icon:before{content:'\e795';}.ab-column.ab-diff h3.icon:before{content:'\e73c';}.ab-column h6{clear:both;color:#8e959c;margin:0 0 20px;font-size:10px;font-weight:normal;text-transform:uppercase;}.ab-column input[type="text"],.ab-column select{height:20px;font-size:11px;text-align:center;background:#f8f8f9;}.ab-column select[multiple]{width:150px;height:56px;}.ab-column input.ab-mini-field{width:30px;}.ab-column input.ab-medium-field{width:120px;}.ab-column input[type="text"]+label,.ab-column select+label{color:#8e959c;margin:0 0 0 7px;display:inline-block;text-transform:uppercase;}.ab-column>ul{padding:0 20px 0 0;}.ab-column:last-of-type>ul{border:0;}.ab-column>ul>li{width:330px;margin:0 0 36px;padding:10px 0 12px 12px;position:relative;background:#fff;list-style:none;border-radius:3px;white-space:nowrap;}.ab-column>ul>li a{color:inherit;text-decoration:none;border-bottom:1px dotted #e0e5e9;}.ab-column>ul>li a:hover{border-color:inherit;}.ab-column>ul>li input[type="checkbox"]{display:inline-block;margin:0 8px 0 0;}.ab-column>ul>li label{cursor:default;display:inline-block;overflow:hidden;line-height:24px;}.ab-column>ul>li label span{color:#8e959c;display:block;font-size:12px;line-height:16px;}.ab-column>ul>li:after,.ab-column>ul>li:before{width:0;content:'';position:absolute;}.ab-column.ab-arrow>ul>li:before,.ab-column.ab-arrow>ul>li:after{left:157px;border-width:10px 10px 0;border-style:solid;}.ab-column.ab-arrow>ul>li:before{bottom:-24px;border-color:#fff transparent;}.ab-column.ab-arrow>ul>li:after{bottom:-22px;border-color:#f1f1f1 transparent;}.ab-column.ab-join>ul>li:before{left:171px;bottom:-27px;height:18px;border-right:2px solid #fff;}.ab-column.ab-diff>ul>li:before{left:162px;bottom:-19px;width:18px;height:0;border-bottom:2px solid #fff;}.ab-column.ab-submit{width:342px;margin:0 0 0 10px;padding:30px 0;border-top:1px solid #e0e5e9;}.ab-column.ab-submit>p{float:right;margin:0;height:28px;line-height:28px;}.ab-column>ul>li:last-of-type:after,.ab-column>ul>li:last-of-type:before{display:none;}.ab-column>ul>li>ul{margin:10px 10px 0 26px;display:none;list-style:none;}.ab-column>ul>li>ul li{padding:2px 0;}.ab-column>ul>li>ul label{margin:0 0 0 7px;}.ab-column>ul>li>input[type="checkbox"]:checked ~ ul{display:block;}
font/{fontello.woff → icons.woff} RENAMED
File without changes
img/icon@2x.png DELETED
Binary file
inc/columns.class.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ /* Quit */
5
+ defined('ABSPATH') OR exit;
6
+
7
+
8
+ /**
9
+ * Antispam_Bee_Columns
10
+ */
11
+
12
+ final class Antispam_Bee_Columns {
13
+
14
+
15
+ /**
16
+ * Register plugin columns on comments screen
17
+ *
18
+ * @since 2.6.0
19
+ * @change 2.6.0
20
+ *
21
+ * @param array $columns Array with existing columns
22
+ * @return array Array with extended columns
23
+ */
24
+
25
+ public static function register_plugin_columns($columns)
26
+ {
27
+ return array_merge(
28
+ $columns,
29
+ array(
30
+ 'antispam_bee_reason' => esc_html__('Spam Reason', 'antispam_bee')
31
+ )
32
+ );
33
+ }
34
+
35
+
36
+ /**
37
+ * Display plugin column values on comments screen
38
+ *
39
+ * @since 2.6.0
40
+ * @change 2.6.0
41
+ *
42
+ * @param string $column Currently selected column
43
+ * @param integer $comment_id Comment ID
44
+ */
45
+
46
+ public static function print_plugin_column($column, $comment_id)
47
+ {
48
+ /* Only Antispam Bee column */
49
+ if ( $column !== 'antispam_bee_reason' ) {
50
+ return;
51
+ }
52
+
53
+ /* Init data */
54
+ $spam_reason = get_comment_meta($comment_id, $column , true);
55
+ $spam_reasons = Antispam_Bee::$defaults['reasons'];
56
+
57
+ /* Empty values? */
58
+ if ( empty($spam_reason) OR empty($spam_reasons[$spam_reason]) ) {
59
+ return;
60
+ }
61
+
62
+ /* Escape & Print */
63
+ echo esc_html__(
64
+ $spam_reasons[$spam_reason],
65
+ 'antispam_bee'
66
+ );
67
+ }
68
+ }
inc/gui.class.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
 
4
  /* Sicherheitsabfrage */
5
- if ( !class_exists('Antispam_Bee') ) {
6
  die();
7
  }
8
 
@@ -14,50 +14,52 @@ if ( !class_exists('Antispam_Bee') ) {
14
  */
15
 
16
  class Antispam_Bee_GUI extends Antispam_Bee {
17
-
18
-
19
  /**
20
  * Speicherung der GUI
21
  *
22
  * @since 0.1
23
- * @change 2.4.5
24
  */
25
-
26
  public static function save_changes()
27
  {
28
  /* Kein POST? */
29
  if ( empty($_POST) ) {
30
  wp_die(__('Cheatin&#8217; uh?'));
31
  }
32
-
33
  /* Referer prüfen */
34
  check_admin_referer('antispam_bee');
35
-
36
  /* Optionen ermitteln */
37
  $options = array(
38
  'flag_spam' => (int)(!empty($_POST['ab_flag_spam'])),
39
  'email_notify' => (int)(!empty($_POST['ab_email_notify'])),
40
  'cronjob_enable' => (int)(!empty($_POST['ab_cronjob_enable'])),
41
  'cronjob_interval' => (int)self::get_key($_POST, 'ab_cronjob_interval'),
42
-
43
  'no_notice' => (int)(!empty($_POST['ab_no_notice'])),
44
-
45
  'dashboard_count' => (int)(!empty($_POST['ab_dashboard_count'])),
46
  'dashboard_chart' => (int)(!empty($_POST['ab_dashboard_chart'])),
47
  'advanced_check' => (int)(!empty($_POST['ab_advanced_check'])),
 
48
  'spam_ip' => (int)(!empty($_POST['ab_spam_ip'])),
49
  'already_commented' => (int)(!empty($_POST['ab_already_commented'])),
50
  'always_allowed' => (int)(!empty($_POST['ab_always_allowed'])),
51
-
52
  'ignore_pings' => (int)(!empty($_POST['ab_ignore_pings'])),
53
  'ignore_filter' => (int)(!empty($_POST['ab_ignore_filter'])),
54
  'ignore_type' => (int)self::get_key($_POST, 'ab_ignore_type'),
55
-
56
  'reasons_enable' => (int)(!empty($_POST['ab_reasons_enable'])),
57
  'ignore_reasons' => (array)self::get_key($_POST, 'ab_ignore_reasons'),
58
 
 
59
  'dnsbl_check' => (int)(!empty($_POST['ab_dnsbl_check'])),
60
-
61
  'country_code' => (int)(!empty($_POST['ab_country_code'])),
62
  'country_black' => sanitize_text_field(self::get_key($_POST, 'ab_country_black')),
63
  'country_white' => sanitize_text_field(self::get_key($_POST, 'ab_country_white')),
@@ -70,7 +72,7 @@ class Antispam_Bee_GUI extends Antispam_Bee {
70
  if ( empty($options['cronjob_interval']) ) {
71
  $options['cronjob_enable'] = 0;
72
  }
73
-
74
 
75
  /* Translate API */
76
  if ( !empty($options['translate_lang']) ) {
@@ -81,7 +83,7 @@ class Antispam_Bee_GUI extends Antispam_Bee {
81
  if ( empty($options['translate_lang']) ) {
82
  $options['translate_api'] = 0;
83
  }
84
-
85
  /* Liste der Spamgründe */
86
  if ( empty($options['reasons_enable']) ) {
87
  $options['ignore_reasons'] = array();
@@ -120,7 +122,7 @@ class Antispam_Bee_GUI extends Antispam_Bee {
120
 
121
  /* Optionen speichern */
122
  self::update_options($options);
123
-
124
  /* Redirect */
125
  wp_safe_redirect(
126
  add_query_arg(
@@ -133,8 +135,8 @@ class Antispam_Bee_GUI extends Antispam_Bee {
133
 
134
  die();
135
  }
136
-
137
-
138
  /**
139
  * Generierung eine Selectbox
140
  *
@@ -146,53 +148,51 @@ class Antispam_Bee_GUI extends Antispam_Bee {
146
  * @param string $selected Selektierter Wert
147
  * @return string $html Erzeugtes HTML
148
  */
149
-
150
  private static function _build_select($name, $data, $selected)
151
  {
152
  /* Start HTML */
153
  $html = '<select name="' .$name. '">';
154
-
155
  /* Loop options */
156
  foreach( $data as $k => $v) {
157
  $html .= '<option value="' .esc_attr($k). '" ' .selected($selected, $k, false). '>' .esc_html__($v, 'antispam_bee'). '</option>';
158
  }
159
-
160
  /* Close HTML */
161
  $html .= '</select>';
162
-
163
  return $html;
164
  }
165
-
166
-
167
  /**
168
  * Anzeige der GUI
169
  *
170
  * @since 0.1
171
- * @change 2.4.5
172
  */
173
 
174
- function options_page() { ?>
175
  <div class="wrap" id="ab_main">
176
- <?php screen_icon('ab') ?>
177
-
178
  <h2>
179
  Antispam Bee
180
  </h2>
181
 
182
  <form action="<?php echo admin_url('admin-post.php') ?>" method="post">
183
  <input type="hidden" name="action" value="ab_save_changes" />
184
-
185
  <?php wp_nonce_field('antispam_bee') ?>
186
 
187
  <?php $options = self::get_options() ?>
188
-
189
  <div class="ab-wrap">
190
  <!--[if lt IE 9]>
191
  <p class="browsehappy">
192
  <a href="http://browsehappy.com">Browse Happy</a>
193
  </p>
194
  <![endif]-->
195
-
196
  <div class="ab-column ab-arrow">
197
  <h3 class="icon">
198
  <?php esc_html_e('Antispam filter', 'antispam_bee') ?>
@@ -200,47 +200,63 @@ class Antispam_Bee_GUI extends Antispam_Bee {
200
  <h6>
201
  <?php esc_html_e('Filter in the execution order', 'antispam_bee') ?>
202
  </h6>
203
-
204
  <ul>
205
  <li>
 
206
  <label for="ab_already_commented">
207
  <?php esc_html_e('Trust approved commentators', 'antispam_bee') ?>
208
  <span><?php esc_html_e('No check for already commenting users', 'antispam_bee') ?></span>
209
  </label>
210
- <input type="checkbox" name="ab_already_commented" id="ab_already_commented" value="1" <?php checked($options['already_commented'], 1) ?> />
211
  </li>
212
-
213
  <li>
214
- <label for="ab_dnsbl_check">
215
- <?php esc_html_e('Use a public antispam database', 'antispam_bee') ?>
216
- <span><?php esc_html_e('Matching the ip address with', 'antispam_bee') ?> <a href="http://opm.tornevall.org" target="_blank">Tornevall</a></span>
 
217
  </label>
218
- <input type="checkbox" name="ab_dnsbl_check" id="ab_dnsbl_check" value="1" <?php checked($options['dnsbl_check'], 1) ?> />
219
  </li>
220
-
221
  <li>
 
222
  <label for="ab_advanced_check">
223
  <?php esc_html_e('Validate the ip address of commentators', 'antispam_bee') ?>
224
  <span><?php esc_html_e('Validity check for used ip address', 'antispam_bee') ?></span>
225
  </label>
226
- <input type="checkbox" name="ab_advanced_check" id="ab_advanced_check" value="1" <?php checked($options['advanced_check'], 1) ?> />
227
  </li>
228
-
 
 
 
 
 
 
 
 
229
  <li>
 
230
  <label for="ab_spam_ip">
231
  <?php esc_html_e('Look in the local spam database', 'antispam_bee') ?>
232
  <span><?php esc_html_e('Already marked as spam? Yes? No?', 'antispam_bee') ?></span>
233
  </label>
234
- <input type="checkbox" name="ab_spam_ip" id="ab_spam_ip" value="1" <?php checked($options['spam_ip'], 1) ?> />
235
  </li>
236
-
 
 
 
 
 
 
 
 
237
  <li>
 
238
  <label for="ab_country_code">
239
  <?php esc_html_e('Block comments from specific countries', 'antispam_bee') ?>
240
  <span><?php esc_html_e('Filtering the requests depending on country', 'antispam_bee') ?></span>
241
  </label>
242
- <input type="checkbox" name="ab_country_code" id="ab_country_code" value="1" <?php checked($options['country_code'], 1) ?> />
243
-
244
  <ul>
245
  <li>
246
  <input type="text" name="ab_country_black" id="ab_country_black" value="<?php echo esc_attr($options['country_black']); ?>" class="ab-medium-field code" />
@@ -256,14 +272,14 @@ class Antispam_Bee_GUI extends Antispam_Bee {
256
  </li>
257
  </ul>
258
  </li>
259
-
260
  <li>
 
261
  <label for="ab_translate_api">
262
  <?php esc_html_e('Allow comments only in certain language', 'antispam_bee') ?>
263
  <span><?php esc_html_e('Detection and approval in specified language', 'antispam_bee') ?></span>
264
  </label>
265
- <input type="checkbox" name="ab_translate_api" id="ab_translate_api" value="1" <?php checked($options['translate_api'], 1) ?> />
266
-
267
  <ul>
268
  <li>
269
  <select name="ab_translate_lang">
@@ -279,8 +295,8 @@ class Antispam_Bee_GUI extends Antispam_Bee {
279
  </li>
280
  </ul>
281
  </div>
282
-
283
-
284
  <div class="ab-column ab-join">
285
  <h3 class="icon advanced">
286
  <?php esc_html_e('Advanced', 'antispam_bee') ?>
@@ -288,33 +304,34 @@ class Antispam_Bee_GUI extends Antispam_Bee {
288
  <h6>
289
  <?php esc_html_e('Other antispam tools', 'antispam_bee') ?>
290
  </h6>
291
-
292
  <ul>
293
  <li>
 
294
  <label for="ab_flag_spam">
295
  <?php esc_html_e('Mark as spam, do not delete', 'antispam_bee') ?>
296
  <span><?php esc_html_e('Keep the spam in my blog.', 'antispam_bee') ?></span>
297
  </label>
298
- <input type="checkbox" name="ab_flag_spam" id="ab_flag_spam" value="1" <?php checked($options['flag_spam'], 1) ?> />
299
  </li>
300
-
301
  <li>
 
302
  <label for="ab_email_notify">
303
  <?php esc_html_e('Notification by email', 'antispam_bee') ?>
304
  <span><?php esc_html_e('Sending an alert to the admin', 'antispam_bee') ?></span>
305
  </label>
306
- <input type="checkbox" name="ab_email_notify" id="ab_email_notify" value="1" <?php checked($options['email_notify'], 1) ?> />
307
  </li>
308
-
309
  <li>
 
310
  <label for="ab_no_notice">
311
- <?php esc_html_e('Not store the reason in the comment body', 'antispam_bee') ?>
312
- <span><?php esc_html_e('Filter name as reason for current suspicion', 'antispam_bee') ?></span>
313
  </label>
314
- <input type="checkbox" name="ab_no_notice" id="ab_no_notice" value="1" <?php checked($options['no_notice'], 1) ?> />
315
  </li>
316
-
317
  <li>
 
318
  <label>
319
  <?php echo sprintf(
320
  esc_html__('Delete existing spam after %s days', 'antispam_bee'),
@@ -322,10 +339,10 @@ class Antispam_Bee_GUI extends Antispam_Bee {
322
  ) ?>
323
  <span><?php esc_html_e('Cleaning up the database from old entries', 'antispam_bee') ?></span>
324
  </label>
325
- <input type="checkbox" name="ab_cronjob_enable" id="ab_cronjob_enable" value="1" <?php checked($options['cronjob_enable'], 1) ?> />
326
  </li>
327
-
328
  <li>
 
329
  <label>
330
  <?php echo sprintf(
331
  esc_html__('Limit on %s', 'antispam_bee'),
@@ -340,16 +357,15 @@ class Antispam_Bee_GUI extends Antispam_Bee {
340
  ); ?>
341
  <span><?php esc_html_e('Another type of spam will be deleted immediately', 'antispam_bee') ?></span>
342
  </label>
343
- <input type="checkbox" name="ab_ignore_filter" id="ab_ignore_filter" value="1" <?php checked($options['ignore_filter'], 1) ?> />
344
  </li>
345
-
346
  <li>
 
347
  <label for="ab_reasons_enable">
348
  <?php esc_html_e('Delete comments by spam reasons', 'antispam_bee') ?>
349
  <span><?php esc_html_e('Multiple choice by pressing Ctrl/CMD', 'antispam_bee') ?></span>
350
  </label>
351
- <input type="checkbox" name="ab_reasons_enable" id="ab_reasons_enable" value="1" <?php checked($options['reasons_enable'], 1) ?> />
352
-
353
  <ul>
354
  <li>
355
  <select name="ab_ignore_reasons[]" id="ab_ignore_reasons" size="2" multiple>
@@ -365,8 +381,8 @@ class Antispam_Bee_GUI extends Antispam_Bee {
365
  </li>
366
  </ul>
367
  </div>
368
-
369
-
370
  <div class="ab-column ab-diff">
371
  <h3 class="icon more">
372
  <?php esc_html_e('More', 'antispam_bee') ?>
@@ -374,52 +390,49 @@ class Antispam_Bee_GUI extends Antispam_Bee {
374
  <h6>
375
  <?php esc_html_e('A few little things', 'antispam_bee') ?>
376
  </h6>
377
-
378
  <ul>
379
  <li>
 
380
  <label for="ab_dashboard_chart">
381
  <?php esc_html_e('Statistics on the dashboard', 'antispam_bee') ?>
382
  <span><?php esc_html_e('Spam detection rate with daily values', 'antispam_bee') ?></span>
383
  </label>
384
- <input type="checkbox" name="ab_dashboard_chart" id="ab_dashboard_chart" value="1" <?php checked($options['dashboard_chart'], 1) ?> />
385
  </li>
386
-
387
  <li>
 
388
  <label for="ab_dashboard_count">
389
  <?php esc_html_e('Spam counter on the dashboard', 'antispam_bee') ?>
390
  <span><?php esc_html_e('Amount of identified spam comments', 'antispam_bee') ?></span>
391
  </label>
392
- <input type="checkbox" name="ab_dashboard_count" id="ab_dashboard_count" value="1" <?php checked($options['dashboard_count'], 1) ?> />
393
  </li>
394
-
395
  <li>
 
396
  <label for="ab_ignore_pings">
397
  <?php esc_html_e('Do not check trackbacks / pingbacks', 'antispam_bee') ?>
398
  <span><?php esc_html_e('No spam check for trackback notifications', 'antispam_bee') ?></span>
399
  </label>
400
- <input type="checkbox" name="ab_ignore_pings" id="ab_ignore_pings" value="1" <?php checked($options['ignore_pings'], 1) ?> />
401
  </li>
402
-
403
  <li>
 
404
  <label for="ab_always_allowed">
405
  <?php esc_html_e('Comment form used outside of posts', 'antispam_bee') ?>
406
  <span><?php esc_html_e('Check for comment forms on archive pages', 'antispam_bee') ?></span>
407
  </label>
408
- <input type="checkbox" name="ab_always_allowed" id="ab_always_allowed" value="1" <?php checked($options['always_allowed'], 1) ?> />
409
  </li>
410
  </ul>
411
  </div>
412
-
413
-
414
  <div class="ab-column ab-submit">
415
  <p>
416
- <?php if ( get_locale() == 'de_DE' ) { ?>
417
- <a href="http://playground.ebiene.de/antispam-bee-wordpress-plugin/" target="_blank">Dokumentation</a>
418
- <?php } ?>
419
- <a href="https://flattr.com/donation/give/to/sergej.mueller" target="_blank">Flattr</a><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RDDW9FEHGLG6" target="_blank">PayPal</a>
420
  </p>
421
-
422
- <input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
423
  </div>
424
  </div>
425
  </form>
2
 
3
 
4
  /* Sicherheitsabfrage */
5
+ if ( ! class_exists('Antispam_Bee') ) {
6
  die();
7
  }
8
 
14
  */
15
 
16
  class Antispam_Bee_GUI extends Antispam_Bee {
17
+
18
+
19
  /**
20
  * Speicherung der GUI
21
  *
22
  * @since 0.1
23
+ * @change 2.5.2
24
  */
25
+
26
  public static function save_changes()
27
  {
28
  /* Kein POST? */
29
  if ( empty($_POST) ) {
30
  wp_die(__('Cheatin&#8217; uh?'));
31
  }
32
+
33
  /* Referer prüfen */
34
  check_admin_referer('antispam_bee');
35
+
36
  /* Optionen ermitteln */
37
  $options = array(
38
  'flag_spam' => (int)(!empty($_POST['ab_flag_spam'])),
39
  'email_notify' => (int)(!empty($_POST['ab_email_notify'])),
40
  'cronjob_enable' => (int)(!empty($_POST['ab_cronjob_enable'])),
41
  'cronjob_interval' => (int)self::get_key($_POST, 'ab_cronjob_interval'),
42
+
43
  'no_notice' => (int)(!empty($_POST['ab_no_notice'])),
44
+
45
  'dashboard_count' => (int)(!empty($_POST['ab_dashboard_count'])),
46
  'dashboard_chart' => (int)(!empty($_POST['ab_dashboard_chart'])),
47
  'advanced_check' => (int)(!empty($_POST['ab_advanced_check'])),
48
+ 'regexp_check' => (int)(!empty($_POST['ab_regexp_check'])),
49
  'spam_ip' => (int)(!empty($_POST['ab_spam_ip'])),
50
  'already_commented' => (int)(!empty($_POST['ab_already_commented'])),
51
  'always_allowed' => (int)(!empty($_POST['ab_always_allowed'])),
52
+
53
  'ignore_pings' => (int)(!empty($_POST['ab_ignore_pings'])),
54
  'ignore_filter' => (int)(!empty($_POST['ab_ignore_filter'])),
55
  'ignore_type' => (int)self::get_key($_POST, 'ab_ignore_type'),
56
+
57
  'reasons_enable' => (int)(!empty($_POST['ab_reasons_enable'])),
58
  'ignore_reasons' => (array)self::get_key($_POST, 'ab_ignore_reasons'),
59
 
60
+ 'bbcode_check' => (int)(!empty($_POST['ab_bbcode_check'])),
61
  'dnsbl_check' => (int)(!empty($_POST['ab_dnsbl_check'])),
62
+
63
  'country_code' => (int)(!empty($_POST['ab_country_code'])),
64
  'country_black' => sanitize_text_field(self::get_key($_POST, 'ab_country_black')),
65
  'country_white' => sanitize_text_field(self::get_key($_POST, 'ab_country_white')),
72
  if ( empty($options['cronjob_interval']) ) {
73
  $options['cronjob_enable'] = 0;
74
  }
75
+
76
 
77
  /* Translate API */
78
  if ( !empty($options['translate_lang']) ) {
83
  if ( empty($options['translate_lang']) ) {
84
  $options['translate_api'] = 0;
85
  }
86
+
87
  /* Liste der Spamgründe */
88
  if ( empty($options['reasons_enable']) ) {
89
  $options['ignore_reasons'] = array();
122
 
123
  /* Optionen speichern */
124
  self::update_options($options);
125
+
126
  /* Redirect */
127
  wp_safe_redirect(
128
  add_query_arg(
135
 
136
  die();
137
  }
138
+
139
+
140
  /**
141
  * Generierung eine Selectbox
142
  *
148
  * @param string $selected Selektierter Wert
149
  * @return string $html Erzeugtes HTML
150
  */
151
+
152
  private static function _build_select($name, $data, $selected)
153
  {
154
  /* Start HTML */
155
  $html = '<select name="' .$name. '">';
156
+
157
  /* Loop options */
158
  foreach( $data as $k => $v) {
159
  $html .= '<option value="' .esc_attr($k). '" ' .selected($selected, $k, false). '>' .esc_html__($v, 'antispam_bee'). '</option>';
160
  }
161
+
162
  /* Close HTML */
163
  $html .= '</select>';
164
+
165
  return $html;
166
  }
167
+
168
+
169
  /**
170
  * Anzeige der GUI
171
  *
172
  * @since 0.1
173
+ * @change 2.6.0
174
  */
175
 
176
+ public static function options_page() { ?>
177
  <div class="wrap" id="ab_main">
 
 
178
  <h2>
179
  Antispam Bee
180
  </h2>
181
 
182
  <form action="<?php echo admin_url('admin-post.php') ?>" method="post">
183
  <input type="hidden" name="action" value="ab_save_changes" />
184
+
185
  <?php wp_nonce_field('antispam_bee') ?>
186
 
187
  <?php $options = self::get_options() ?>
188
+
189
  <div class="ab-wrap">
190
  <!--[if lt IE 9]>
191
  <p class="browsehappy">
192
  <a href="http://browsehappy.com">Browse Happy</a>
193
  </p>
194
  <![endif]-->
195
+
196
  <div class="ab-column ab-arrow">
197
  <h3 class="icon">
198
  <?php esc_html_e('Antispam filter', 'antispam_bee') ?>
200
  <h6>
201
  <?php esc_html_e('Filter in the execution order', 'antispam_bee') ?>
202
  </h6>
203
+
204
  <ul>
205
  <li>
206
+ <input type="checkbox" name="ab_already_commented" id="ab_already_commented" value="1" <?php checked($options['already_commented'], 1) ?> />
207
  <label for="ab_already_commented">
208
  <?php esc_html_e('Trust approved commentators', 'antispam_bee') ?>
209
  <span><?php esc_html_e('No check for already commenting users', 'antispam_bee') ?></span>
210
  </label>
 
211
  </li>
212
+
213
  <li>
214
+ <input type="checkbox" name="ab_bbcode_check" id="ab_bbcode_check" value="1" <?php checked($options['bbcode_check'], 1) ?> />
215
+ <label for="ab_bbcode_check">
216
+ <?php esc_html_e('BBCode is spam', 'antispam_bee') ?>
217
+ <span><?php esc_html_e('Review the comment contents for BBCode links', 'antispam_bee') ?></span>
218
  </label>
 
219
  </li>
220
+
221
  <li>
222
+ <input type="checkbox" name="ab_advanced_check" id="ab_advanced_check" value="1" <?php checked($options['advanced_check'], 1) ?> />
223
  <label for="ab_advanced_check">
224
  <?php esc_html_e('Validate the ip address of commentators', 'antispam_bee') ?>
225
  <span><?php esc_html_e('Validity check for used ip address', 'antispam_bee') ?></span>
226
  </label>
 
227
  </li>
228
+
229
+ <li>
230
+ <input type="checkbox" name="ab_regexp_check" id="ab_regexp_check" value="1" <?php checked($options['regexp_check'], 1) ?> />
231
+ <label for="ab_regexp_check">
232
+ <?php esc_html_e('Use regular expressions', 'antispam_bee') ?>
233
+ <span><?php _e('Predefined and custom patterns by <a href="https://gist.github.com/4242142" target="_blank">plugin hook</a>', 'antispam_bee') ?></span>
234
+ </label>
235
+ </li>
236
+
237
  <li>
238
+ <input type="checkbox" name="ab_spam_ip" id="ab_spam_ip" value="1" <?php checked($options['spam_ip'], 1) ?> />
239
  <label for="ab_spam_ip">
240
  <?php esc_html_e('Look in the local spam database', 'antispam_bee') ?>
241
  <span><?php esc_html_e('Already marked as spam? Yes? No?', 'antispam_bee') ?></span>
242
  </label>
 
243
  </li>
244
+
245
+ <li>
246
+ <input type="checkbox" name="ab_dnsbl_check" id="ab_dnsbl_check" value="1" <?php checked($options['dnsbl_check'], 1) ?> />
247
+ <label for="ab_dnsbl_check">
248
+ <?php esc_html_e('Use a public antispam database', 'antispam_bee') ?>
249
+ <span><?php _e('Matching the ip address with <a href="https://dnsbl.tornevall.org" target="_blank">Tornevall</a>', 'antispam_bee') ?></span>
250
+ </label>
251
+ </li>
252
+
253
  <li>
254
+ <input type="checkbox" name="ab_country_code" id="ab_country_code" value="1" <?php checked($options['country_code'], 1) ?> />
255
  <label for="ab_country_code">
256
  <?php esc_html_e('Block comments from specific countries', 'antispam_bee') ?>
257
  <span><?php esc_html_e('Filtering the requests depending on country', 'antispam_bee') ?></span>
258
  </label>
259
+
 
260
  <ul>
261
  <li>
262
  <input type="text" name="ab_country_black" id="ab_country_black" value="<?php echo esc_attr($options['country_black']); ?>" class="ab-medium-field code" />
272
  </li>
273
  </ul>
274
  </li>
275
+
276
  <li>
277
+ <input type="checkbox" name="ab_translate_api" id="ab_translate_api" value="1" <?php checked($options['translate_api'], 1) ?> />
278
  <label for="ab_translate_api">
279
  <?php esc_html_e('Allow comments only in certain language', 'antispam_bee') ?>
280
  <span><?php esc_html_e('Detection and approval in specified language', 'antispam_bee') ?></span>
281
  </label>
282
+
 
283
  <ul>
284
  <li>
285
  <select name="ab_translate_lang">
295
  </li>
296
  </ul>
297
  </div>
298
+
299
+
300
  <div class="ab-column ab-join">
301
  <h3 class="icon advanced">
302
  <?php esc_html_e('Advanced', 'antispam_bee') ?>
304
  <h6>
305
  <?php esc_html_e('Other antispam tools', 'antispam_bee') ?>
306
  </h6>
307
+
308
  <ul>
309
  <li>
310
+ <input type="checkbox" name="ab_flag_spam" id="ab_flag_spam" value="1" <?php checked($options['flag_spam'], 1) ?> />
311
  <label for="ab_flag_spam">
312
  <?php esc_html_e('Mark as spam, do not delete', 'antispam_bee') ?>
313
  <span><?php esc_html_e('Keep the spam in my blog.', 'antispam_bee') ?></span>
314
  </label>
 
315
  </li>
316
+
317
  <li>
318
+ <input type="checkbox" name="ab_email_notify" id="ab_email_notify" value="1" <?php checked($options['email_notify'], 1) ?> />
319
  <label for="ab_email_notify">
320
  <?php esc_html_e('Notification by email', 'antispam_bee') ?>
321
  <span><?php esc_html_e('Sending an alert to the admin', 'antispam_bee') ?></span>
322
  </label>
 
323
  </li>
324
+
325
  <li>
326
+ <input type="checkbox" name="ab_no_notice" id="ab_no_notice" value="1" <?php checked($options['no_notice'], 1) ?> />
327
  <label for="ab_no_notice">
328
+ <?php esc_html_e('Not save the spam reason', 'antispam_bee') ?>
329
+ <span><?php esc_html_e('Spam reason as table column in the spam overview', 'antispam_bee') ?></span>
330
  </label>
 
331
  </li>
332
+
333
  <li>
334
+ <input type="checkbox" name="ab_cronjob_enable" id="ab_cronjob_enable" value="1" <?php checked($options['cronjob_enable'], 1) ?> />
335
  <label>
336
  <?php echo sprintf(
337
  esc_html__('Delete existing spam after %s days', 'antispam_bee'),
339
  ) ?>
340
  <span><?php esc_html_e('Cleaning up the database from old entries', 'antispam_bee') ?></span>
341
  </label>
 
342
  </li>
343
+
344
  <li>
345
+ <input type="checkbox" name="ab_ignore_filter" id="ab_ignore_filter" value="1" <?php checked($options['ignore_filter'], 1) ?> />
346
  <label>
347
  <?php echo sprintf(
348
  esc_html__('Limit on %s', 'antispam_bee'),
357
  ); ?>
358
  <span><?php esc_html_e('Another type of spam will be deleted immediately', 'antispam_bee') ?></span>
359
  </label>
 
360
  </li>
361
+
362
  <li>
363
+ <input type="checkbox" name="ab_reasons_enable" id="ab_reasons_enable" value="1" <?php checked($options['reasons_enable'], 1) ?> />
364
  <label for="ab_reasons_enable">
365
  <?php esc_html_e('Delete comments by spam reasons', 'antispam_bee') ?>
366
  <span><?php esc_html_e('Multiple choice by pressing Ctrl/CMD', 'antispam_bee') ?></span>
367
  </label>
368
+
 
369
  <ul>
370
  <li>
371
  <select name="ab_ignore_reasons[]" id="ab_ignore_reasons" size="2" multiple>
381
  </li>
382
  </ul>
383
  </div>
384
+
385
+
386
  <div class="ab-column ab-diff">
387
  <h3 class="icon more">
388
  <?php esc_html_e('More', 'antispam_bee') ?>
390
  <h6>
391
  <?php esc_html_e('A few little things', 'antispam_bee') ?>
392
  </h6>
393
+
394
  <ul>
395
  <li>
396
+ <input type="checkbox" name="ab_dashboard_chart" id="ab_dashboard_chart" value="1" <?php checked($options['dashboard_chart'], 1) ?> />
397
  <label for="ab_dashboard_chart">
398
  <?php esc_html_e('Statistics on the dashboard', 'antispam_bee') ?>
399
  <span><?php esc_html_e('Spam detection rate with daily values', 'antispam_bee') ?></span>
400
  </label>
 
401
  </li>
402
+
403
  <li>
404
+ <input type="checkbox" name="ab_dashboard_count" id="ab_dashboard_count" value="1" <?php checked($options['dashboard_count'], 1) ?> />
405
  <label for="ab_dashboard_count">
406
  <?php esc_html_e('Spam counter on the dashboard', 'antispam_bee') ?>
407
  <span><?php esc_html_e('Amount of identified spam comments', 'antispam_bee') ?></span>
408
  </label>
 
409
  </li>
410
+
411
  <li>
412
+ <input type="checkbox" name="ab_ignore_pings" id="ab_ignore_pings" value="1" <?php checked($options['ignore_pings'], 1) ?> />
413
  <label for="ab_ignore_pings">
414
  <?php esc_html_e('Do not check trackbacks / pingbacks', 'antispam_bee') ?>
415
  <span><?php esc_html_e('No spam check for trackback notifications', 'antispam_bee') ?></span>
416
  </label>
 
417
  </li>
418
+
419
  <li>
420
+ <input type="checkbox" name="ab_always_allowed" id="ab_always_allowed" value="1" <?php checked($options['always_allowed'], 1) ?> />
421
  <label for="ab_always_allowed">
422
  <?php esc_html_e('Comment form used outside of posts', 'antispam_bee') ?>
423
  <span><?php esc_html_e('Check for comment forms on archive pages', 'antispam_bee') ?></span>
424
  </label>
 
425
  </li>
426
  </ul>
427
  </div>
428
+
429
+
430
  <div class="ab-column ab-submit">
431
  <p>
432
+ <?php if ( get_locale() == 'de_DE' ) { ?><a href="http://playground.ebiene.de/antispam-bee-wordpress-plugin/" target="_blank">Handbuch</a> &bull; <?php } ?><a href="https://flattr.com/t/1323822" target="_blank">Flattr</a> &bull; <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=5RDDW9FEHGLG6" target="_blank">PayPal</a>
 
 
 
433
  </p>
434
+
435
+ <input type="submit" class="button button-primary" value="<?php _e('Save Changes') ?>" />
436
  </div>
437
  </div>
438
  </form>
js/dashboard.js CHANGED
@@ -1,62 +1,113 @@
1
- google.load("visualization", "1", {packages:["corechart"]});
2
- google.setOnLoadCallback(drawChart);
3
 
4
- function drawChart() {
5
- /* Init */
6
- var id,
7
- rows = [],
8
- output = document.getElementById('ab_chart'),
9
- data = new google.visualization.DataTable();
10
-
11
- /* Leer? */
12
- if ( !output || !antispambee.created.length ) {
13
- return;
14
- }
15
-
16
- /* Extrahieren */
17
- var created = antispambee.created.split(','),
18
- count = antispambee.count.split(',');
19
-
20
- /* Loopen */
21
- for (id in created) {
22
- rows[id] = [created[id], parseInt(count[id], 10)];
23
- }
24
 
25
- data.addColumn('string', 'Date');
26
- data.addColumn('number', 'Spam');
27
- data.addRows(rows);
 
 
 
 
 
 
 
 
 
28
 
29
- var chart = new google.visualization.AreaChart(output);
30
- chart.draw(
31
- data,
32
- {
33
- width: parseInt(jQuery('#ab_chart').parent().width(), 10),
34
- height: 120,
35
- legend: 'none',
36
- pointSize: 6,
37
- lineWidth: 3,
38
- gridlineColor: '#ececec',
39
- colors:['#3399CC'],
40
- reverseCategories: true,
41
- backgroundColor: 'transparent',
42
- vAxis: {
43
- baselineColor: 'transparent',
44
- textPosition: 'in',
45
- textStyle: {
46
- color: '#8F8F8F',
47
- fontSize: 10
48
- }
49
- },
50
- hAxis: {
51
- textStyle: {
52
- color: '#3399CC',
53
- fontSize: 10
54
- }
55
- },
56
- chartArea: {
57
- width: "100%",
58
- height: "100%"
59
- }
60
- }
61
- );
62
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function () {
 
2
 
3
+ // Grab the data
4
+ var labels = [],
5
+ data = [];
6
+ jQuery("#ab_chart_data tfoot th").each(function () {
7
+ labels.push(jQuery(this).html());
8
+ });
9
+ jQuery("#ab_chart_data tbody td").each(function () {
10
+ data.push(jQuery(this).html());
11
+ });
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ // Draw
14
+ var width = jQuery('#ab_chart').parent().width() + 8,
15
+ height = 140,
16
+ leftgutter = 0,
17
+ bottomgutter = 22,
18
+ topgutter = 22,
19
+ color = '#0074a2',
20
+ r = Raphael("ab_chart", width, height),
21
+ txt = {font: 'bold 12px "Open Sans", sans-serif', fill: "#333"},
22
+ X = (width - leftgutter * 2) / labels.length,
23
+ max = Math.max.apply(Math, data),
24
+ Y = (height - bottomgutter - topgutter) / max;
25
 
26
+ /* Max Wert */
27
+ r
28
+ .text(16, 16, max)
29
+ .attr(
30
+ {
31
+ 'font': 'normal 10px "Open Sans", sans-serif',
32
+ fill: "#bbb"
33
+ }
34
+ );
35
+
36
+ var path = r.path().attr({stroke: color, "stroke-width": 2, "stroke-linejoin": "round"}),
37
+ bgp = r.path().attr({stroke: "none", opacity: .3, fill: color}),
38
+ label = r.set(),
39
+ lx = 0, ly = 0,
40
+ is_label_visible = false,
41
+ leave_timer,
42
+ blanket = r.set();
43
+ label.push(r.text(60, 12, "24× Spam").attr(txt));
44
+ label.push(r.text(60, 27, "23.12.2013").attr(txt).attr({fill: color}));
45
+ label.hide();
46
+ var frame = r.popup(100, 100, label, "right").attr({fill: "#fff", stroke: "#444", "stroke-width": 1}).hide();
47
+
48
+ var p, bgpp;
49
+ for (var i = 0, ii = labels.length; i < ii; i++) {
50
+ var y = Math.round(height - bottomgutter - Y * data[i]),
51
+ x = Math.round(leftgutter + X * (i + .5));
52
+ if (!i) {
53
+ p = ["M", x, y, "C", x, y];
54
+ bgpp = ["M", leftgutter + X * .5, height - bottomgutter, "L", x, y, "C", x, y];
55
+ }
56
+ if (i && i < ii - 1) {
57
+ var Y0 = Math.round(height - bottomgutter - Y * data[i - 1]),
58
+ X0 = Math.round(leftgutter + X * (i - .5)),
59
+ Y2 = Math.round(height - bottomgutter - Y * data[i + 1]),
60
+ X2 = Math.round(leftgutter + X * (i + 1.5));
61
+ var a = getAnchors(X0, Y0, x, y, X2, Y2);
62
+ p = p.concat([a.x1, a.y1, x, y, a.x2, a.y2]);
63
+ bgpp = bgpp.concat([a.x1, a.y1, x, y, a.x2, a.y2]);
64
+ }
65
+ var dot = r.circle(x, y, 4).attr({fill: "#fff", stroke: color, "stroke-width": 1});
66
+ blanket.push(r.rect(leftgutter + X * i, 0, X, height - bottomgutter).attr({stroke: "none", fill: '#fff', opacity: .2}));
67
+ var rect = blanket[blanket.length - 1];
68
+ (function (x, y, data, lbl, dot) {
69
+ var timer, i = 0;
70
+ rect.hover(function () {
71
+ clearTimeout(leave_timer);
72
+ var side = "right";
73
+ if (x + frame.getBBox().width > width) {
74
+ side = "left";
75
+ }
76
+ var ppp = r.popup(x, y, label, side, 1),
77
+ anim = Raphael.animation({
78
+ path: ppp.path,
79
+ transform: ["t", ppp.dx, ppp.dy]
80
+ }, 200 * is_label_visible);
81
+ lx = label[0].transform()[0][1] + ppp.dx;
82
+ ly = label[0].transform()[0][2] + ppp.dy;
83
+ frame.show().stop().animate(anim);
84
+
85
+ var date = new Date(lbl * 1000),
86
+ day = ( date.getDate() < 10 ? '0' : '' ) + date.getDate(),
87
+ month = ( date.getMonth() + 1 < 10 ? '0' : '' ) + (date.getMonth() + 1),
88
+ year = date.getFullYear();
89
+
90
+ label[0].attr({text: data + "× Spam"}).show().stop().animateWith(frame, anim, {transform: ["t", lx, ly]}, 200 * is_label_visible);
91
+ label[1].attr({text: ( day + '.' + month + '.' + year ) }).show().stop().animateWith(frame, anim, {transform: ["t", lx, ly]}, 200 * is_label_visible);
92
+ dot.attr("r", 6);
93
+ is_label_visible = true;
94
+ }, function () {
95
+ dot.attr("r", 4);
96
+ leave_timer = setTimeout(function () {
97
+ frame.hide();
98
+ label[0].hide();
99
+ label[1].hide();
100
+ is_label_visible = false;
101
+ }, 1);
102
+ });
103
+ })(x, y, data[i], labels[i], dot);
104
+ }
105
+ p = p.concat([x, y, x, y]);
106
+ bgpp = bgpp.concat([x, y, x, y, "L", x, height - bottomgutter, "z"]);
107
+ path.attr({path: p});
108
+ bgp.attr({path: bgpp});
109
+ frame.toFront();
110
+ label[0].toFront();
111
+ label[1].toFront();
112
+ blanket.toFront();
113
+ })();
js/dashboard.min.js CHANGED
@@ -1,3 +1,5 @@
1
- google.load("visualization","1",{packages:["corechart"]});google.setOnLoadCallback(drawChart);
2
- function drawChart(){var a,c=[],d=document.getElementById("ab_chart"),b=new google.visualization.DataTable;if(d&&antispambee.created.length){var e=antispambee.created.split(","),f=antispambee.count.split(",");for(a in e)c[a]=[e[a],parseInt(f[a],10)];b.addColumn("string","Date");b.addColumn("number","Spam");b.addRows(c);(new google.visualization.AreaChart(d)).draw(b,{width:parseInt(jQuery("#ab_chart").parent().width(),10),height:120,legend:"none",pointSize:6,lineWidth:3,gridlineColor:"#ececec",colors:["#3399CC"],
3
- reverseCategories:!0,backgroundColor:"transparent",vAxis:{baselineColor:"transparent",textPosition:"in",textStyle:{color:"#8F8F8F",fontSize:10}},hAxis:{textStyle:{color:"#3399CC",fontSize:10}},chartArea:{width:"100%",height:"100%"}})}};
 
 
1
+ (function(){var r=[],h=[];jQuery("#ab_chart_data tfoot th").each(function(){r.push(jQuery(this).html())});jQuery("#ab_chart_data tbody td").each(function(){h.push(jQuery(this).html())});var u=jQuery("#ab_chart").parent().width()+8,g=Raphael("ab_chart",u,140),a={font:'bold 12px "Open Sans", sans-serif',fill:"#333"},e=(u-0)/r.length,s=Math.max.apply(Math,h),v=96/s;g.text(16,16,s).attr({font:'normal 10px "Open Sans", sans-serif',fill:"#bbb"});var s=g.path().attr({stroke:"#0074a2","stroke-width":2,"stroke-linejoin":"round"}),
2
+ A=g.path().attr({stroke:"none",opacity:0.3,fill:"#0074a2"}),f=g.set(),w=0,x=0,q=!1,y,t=g.set();f.push(g.text(60,12,"24\u00d7 Spam").attr(a));f.push(g.text(60,27,"23.12.2013").attr(a).attr({fill:"#0074a2"}));f.hide();for(var n=g.popup(100,100,f,"right").attr({fill:"#fff",stroke:"#444","stroke-width":1}).hide(),k,p,a=0,z=r.length;a<z;a++){var c=Math.round(118-v*h[a]),b=Math.round(0+e*(a+0.5));a||(k=["M",b,c,"C",b,c],p=["M",0+0.5*e,118,"L",b,c,"C",b,c]);if(a&&a<z-1){var d=Math.round(118-v*h[a-1]),B=
3
+ Math.round(0+e*(a-0.5)),C=Math.round(118-v*h[a+1]),D=Math.round(0+e*(a+1.5)),d=getAnchors(B,d,b,c,D,C);k=k.concat([d.x1,d.y1,b,c,d.x2,d.y2]);p=p.concat([d.x1,d.y1,b,c,d.x2,d.y2])}d=g.circle(b,c,4).attr({fill:"#fff",stroke:"#0074a2","stroke-width":1});t.push(g.rect(0+e*a,0,e,118).attr({stroke:"none",fill:"#fff",opacity:0.2}));var E=t[t.length-1];(function(a,b,c,d,h){E.hover(function(){clearTimeout(y);var e="right";a+n.getBBox().width>u&&(e="left");var l=g.popup(a,b,f,e,1),e=Raphael.animation({path:l.path,
4
+ transform:["t",l.dx,l.dy]},200*q);w=f[0].transform()[0][1]+l.dx;x=f[0].transform()[0][2]+l.dy;n.show().stop().animate(e);var m=new Date(1E3*d),l=(10>m.getDate()?"0":"")+m.getDate(),k=(10>m.getMonth()+1?"0":"")+(m.getMonth()+1),m=m.getFullYear();f[0].attr({text:c+"× Spam"}).show().stop().animateWith(n,e,{transform:["t",w,x]},200*q);f[1].attr({text:l+"."+k+"."+m}).show().stop().animateWith(n,e,{transform:["t",w,x]},200*q);h.attr("r",6);q=!0},function(){h.attr("r",4);y=setTimeout(function(){n.hide();
5
+ f[0].hide();f[1].hide();q=!1},1)})})(b,c,h[a],r[a],d)}k=k.concat([b,c,b,c]);p=p.concat([b,c,b,c,"L",b,118,"z"]);s.attr({path:k});A.attr({path:p});n.toFront();f[0].toFront();f[1].toFront();t.toFront()})();
js/raphael.helper.js ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var tokenRegex = /\{([^\}]+)\}/g,
2
+ objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,
3
+ replacer = function (all, key, obj) {
4
+ var res = obj;
5
+ key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
6
+ name = name || quotedName;
7
+ if (res) {
8
+ if (name in res) {
9
+ res = res[name];
10
+ }
11
+ typeof res == "function" && isFunc && (res = res());
12
+ }
13
+ });
14
+ res = (res == null || res == obj ? all : res) + "";
15
+ return res;
16
+ },
17
+ fill = function (str, obj) {
18
+ return String(str).replace(tokenRegex, function (all, key) {
19
+ return replacer(all, key, obj);
20
+ });
21
+ };
22
+
23
+
24
+ Raphael.fn.popup = function (X, Y, set, pos, ret) {
25
+ pos = String(pos || "top-middle").split("-");
26
+ pos[1] = pos[1] || "middle";
27
+ var r = 5,
28
+ bb = set.getBBox(),
29
+ w = Math.round(bb.width),
30
+ h = Math.round(bb.height),
31
+ x = Math.round(bb.x) - r,
32
+ y = Math.round(bb.y) - r,
33
+ gap = Math.min(h / 2, w / 2, 10),
34
+ shapes = {
35
+ top: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}l-{right},0-{gap},{gap}-{gap}-{gap}-{left},0a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",
36
+ bottom: "M{x},{y}l{left},0,{gap}-{gap},{gap},{gap},{right},0a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",
37
+ right: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}l0-{bottom}-{gap}-{gap},{gap}-{gap},0-{top}a{r},{r},0,0,1,{r}-{r}z",
38
+ left: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}l0,{top},{gap},{gap}-{gap},{gap},0,{bottom}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z"
39
+ },
40
+ offset = {
41
+ hx0: X - (x + r + w - gap * 2),
42
+ hx1: X - (x + r + w / 2 - gap),
43
+ hx2: X - (x + r + gap),
44
+ vhy: Y - (y + r + h + r + gap),
45
+ "^hy": Y - (y - gap)
46
+
47
+ },
48
+ mask = [{
49
+ x: x + r,
50
+ y: y,
51
+ w: w,
52
+ w4: w / 4,
53
+ h4: h / 4,
54
+ right: 0,
55
+ left: w - gap * 2,
56
+ bottom: 0,
57
+ top: h - gap * 2,
58
+ r: r,
59
+ h: h,
60
+ gap: gap
61
+ }, {
62
+ x: x + r,
63
+ y: y,
64
+ w: w,
65
+ w4: w / 4,
66
+ h4: h / 4,
67
+ left: w / 2 - gap,
68
+ right: w / 2 - gap,
69
+ top: h / 2 - gap,
70
+ bottom: h / 2 - gap,
71
+ r: r,
72
+ h: h,
73
+ gap: gap
74
+ }, {
75
+ x: x + r,
76
+ y: y,
77
+ w: w,
78
+ w4: w / 4,
79
+ h4: h / 4,
80
+ left: 0,
81
+ right: w - gap * 2,
82
+ top: 0,
83
+ bottom: h - gap * 2,
84
+ r: r,
85
+ h: h,
86
+ gap: gap
87
+ }][pos[1] == "middle" ? 1 : (pos[1] == "top" || pos[1] == "left") * 2];
88
+ var dx = 0,
89
+ dy = 0,
90
+ out = this.path(fill(shapes[pos[0]], mask)).insertBefore(set);
91
+ switch (pos[0]) {
92
+ case "top":
93
+ dx = X - (x + r + mask.left + gap);
94
+ dy = Y - (y + r + h + r + gap);
95
+ break;
96
+ case "bottom":
97
+ dx = X - (x + r + mask.left + gap);
98
+ dy = Y - (y - gap);
99
+ break;
100
+ case "left":
101
+ dx = X - (x + r + w + r + gap);
102
+ dy = Y - (y + r + mask.top + gap);
103
+ break;
104
+ case "right":
105
+ dx = X - (x - gap);
106
+ dy = Y - (y + r + mask.top + gap);
107
+ break;
108
+ }
109
+ out.translate(dx, dy);
110
+ if (ret) {
111
+ ret = out.attr("path");
112
+ out.remove();
113
+ return {
114
+ path: ret,
115
+ dx: dx,
116
+ dy: dy
117
+ };
118
+ }
119
+ set.translate(dx, dy);
120
+ return out;
121
+ };
122
+
123
+
124
+ function getAnchors(p1x, p1y, p2x, p2y, p3x, p3y) {
125
+ var l1 = (p2x - p1x) / 2,
126
+ l2 = (p3x - p2x) / 2,
127
+ a = Math.atan((p2x - p1x) / Math.abs(p2y - p1y)),
128
+ b = Math.atan((p3x - p2x) / Math.abs(p2y - p3y));
129
+ a = p1y < p2y ? Math.PI - a : a;
130
+ b = p3y < p2y ? Math.PI - b : b;
131
+ var alpha = Math.PI / 2 - ((a + b) % (Math.PI * 2)) / 2,
132
+ dx1 = l1 * Math.sin(alpha + a),
133
+ dy1 = l1 * Math.cos(alpha + a),
134
+ dx2 = l2 * Math.sin(alpha + b),
135
+ dy2 = l2 * Math.cos(alpha + b);
136
+ return {
137
+ x1: p2x - dx1,
138
+ y1: p2y + dy1,
139
+ x2: p2x + dx2,
140
+ y2: p2y + dy2
141
+ };
142
+ }
js/raphael.helper.min.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ var tokenRegex=/\{([^\}]+)\}/g,objNotationRegex=/(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,replacer=function(c,h,g){var a=g;h.replace(objNotationRegex,function(c,b,f,d,g){b=b||d;a&&(b in a&&(a=a[b]),"function"==typeof a&&g&&(a=a()))});return a=(null==a||a==g?c:a)+""},fill=function(c,h){return String(c).replace(tokenRegex,function(c,a){return replacer(c,a,h)})};
2
+ Raphael.fn.popup=function(c,h,g,a,k){a=String(a||"top-middle").split("-");a[1]=a[1]||"middle";var b=g.getBBox(),f=Math.round(b.width),d=Math.round(b.height),l=Math.round(b.x)-5,b=Math.round(b.y)-5,e=Math.min(d/2,f/2,10),p=[{x:l+5,y:b,w:f,w4:f/4,h4:d/4,right:0,left:f-2*e,bottom:0,top:d-2*e,r:5,h:d,gap:e},{x:l+5,y:b,w:f,w4:f/4,h4:d/4,left:f/2-e,right:f/2-e,top:d/2-e,bottom:d/2-e,r:5,h:d,gap:e},{x:l+5,y:b,w:f,w4:f/4,h4:d/4,left:0,right:f-2*e,top:0,bottom:d-2*e,r:5,h:d,gap:e}]["middle"==a[1]?1:2*("top"==
3
+ a[1]||"left"==a[1])],m=0,n=0,q=this.path(fill({top:"M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}l-{right},0-{gap},{gap}-{gap}-{gap}-{left},0a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",bottom:"M{x},{y}l{left},0,{gap}-{gap},{gap},{gap},{right},0a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z",right:"M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}l0-{bottom}-{gap}-{gap},{gap}-{gap},0-{top}a{r},{r},0,0,1,{r}-{r}z",
4
+ left:"M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}l0,{top},{gap},{gap}-{gap},{gap},0,{bottom}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z"}[a[0]],p)).insertBefore(g);switch(a[0]){case "top":m=c-(l+5+p.left+e);n=h-(b+5+d+5+e);break;case "bottom":m=c-(l+5+p.left+e);n=h-(b-e);break;case "left":m=c-(l+5+f+5+e);n=h-(b+5+p.top+e);break;case "right":m=c-(l-e),n=h-(b+5+p.top+e)}q.translate(m,n);if(k)return k=q.attr("path"),q.remove(),
5
+ {path:k,dx:m,dy:n};g.translate(m,n);return q};function getAnchors(c,h,g,a,k,b){var f=(g-c)/2,d=(k-g)/2;c=Math.atan((g-c)/Math.abs(a-h));k=Math.atan((k-g)/Math.abs(a-b));c=h<a?Math.PI-c:c;k=b<a?Math.PI-k:k;b=Math.PI/2-(c+k)%(2*Math.PI)/2;h=f*Math.sin(b+c);f*=Math.cos(b+c);c=d*Math.sin(b+k);d*=Math.cos(b+k);return{x1:g-h,y1:a+f,x2:g+c,y2:a+d}};
js/raphael.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ // ┌────────────────────────────────────────────────────────────────────┐ \\
2
+ // │ Raphaël 2.1.0 - JavaScript Vector Library │ \\
3
+ // ├────────────────────────────────────────────────────────────────────┤ \\
4
+ // │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
5
+ // │ Copyright © 2008-2012 Sencha Labs (http://sencha.com) │ \\
6
+ // ├────────────────────────────────────────────────────────────────────┤ \\
7
+ // │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\
8
+ // └────────────────────────────────────────────────────────────────────┘ \\
9
+
10
+ (function(a){var b="0.3.4",c="hasOwnProperty",d=/[\.\/]/,e="*",f=function(){},g=function(a,b){return a-b},h,i,j={n:{}},k=function(a,b){var c=j,d=i,e=Array.prototype.slice.call(arguments,2),f=k.listeners(a),l=0,m=!1,n,o=[],p={},q=[],r=h,s=[];h=a,i=0;for(var t=0,u=f.length;t<u;t++)"zIndex"in f[t]&&(o.push(f[t].zIndex),f[t].zIndex<0&&(p[f[t].zIndex]=f[t]));o.sort(g);while(o[l]<0){n=p[o[l++]],q.push(n.apply(b,e));if(i){i=d;return q}}for(t=0;t<u;t++){n=f[t];if("zIndex"in n)if(n.zIndex==o[l]){q.push(n.apply(b,e));if(i)break;do{l++,n=p[o[l]],n&&q.push(n.apply(b,e));if(i)break}while(n)}else p[n.zIndex]=n;else{q.push(n.apply(b,e));if(i)break}}i=d,h=r;return q.length?q:null};k.listeners=function(a){var b=a.split(d),c=j,f,g,h,i,k,l,m,n,o=[c],p=[];for(i=0,k=b.length;i<k;i++){n=[];for(l=0,m=o.length;l<m;l++){c=o[l].n,g=[c[b[i]],c[e]],h=2;while(h--)f=g[h],f&&(n.push(f),p=p.concat(f.f||[]))}o=n}return p},k.on=function(a,b){var c=a.split(d),e=j;for(var g=0,h=c.length;g<h;g++)e=e.n,!e[c[g]]&&(e[c[g]]={n:{}}),e=e[c[g]];e.f=e.f||[];for(g=0,h=e.f.length;g<h;g++)if(e.f[g]==b)return f;e.f.push(b);return function(a){+a==+a&&(b.zIndex=+a)}},k.stop=function(){i=1},k.nt=function(a){if(a)return(new RegExp("(?:\\.|\\/|^)"+a+"(?:\\.|\\/|$)")).test(h);return h},k.off=k.unbind=function(a,b){var f=a.split(d),g,h,i,k,l,m,n,o=[j];for(k=0,l=f.length;k<l;k++)for(m=0;m<o.length;m+=i.length-2){i=[m,1],g=o[m].n;if(f[k]!=e)g[f[k]]&&i.push(g[f[k]]);else for(h in g)g[c](h)&&i.push(g[h]);o.splice.apply(o,i)}for(k=0,l=o.length;k<l;k++){g=o[k];while(g.n){if(b){if(g.f){for(m=0,n=g.f.length;m<n;m++)if(g.f[m]==b){g.f.splice(m,1);break}!g.f.length&&delete g.f}for(h in g.n)if(g.n[c](h)&&g.n[h].f){var p=g.n[h].f;for(m=0,n=p.length;m<n;m++)if(p[m]==b){p.splice(m,1);break}!p.length&&delete g.n[h].f}}else{delete g.f;for(h in g.n)g.n[c](h)&&g.n[h].f&&delete g.n[h].f}g=g.n}}},k.once=function(a,b){var c=function(){var d=b.apply(this,arguments);k.unbind(a,c);return d};return k.on(a,c)},k.version=b,k.toString=function(){return"You are running Eve "+b},typeof module!="undefined"&&module.exports?module.exports=k:typeof define!="undefined"?define("eve",[],function(){return k}):a.eve=k})(this),function(){function cF(a){for(var b=0;b<cy.length;b++)cy[b].el.paper==a&&cy.splice(b--,1)}function cE(b,d,e,f,h,i){e=Q(e);var j,k,l,m=[],o,p,q,t=b.ms,u={},v={},w={};if(f)for(y=0,z=cy.length;y<z;y++){var x=cy[y];if(x.el.id==d.id&&x.anim==b){x.percent!=e?(cy.splice(y,1),l=1):k=x,d.attr(x.totalOrigin);break}}else f=+v;for(var y=0,z=b.percents.length;y<z;y++){if(b.percents[y]==e||b.percents[y]>f*b.top){e=b.percents[y],p=b.percents[y-1]||0,t=t/b.top*(e-p),o=b.percents[y+1],j=b.anim[e];break}f&&d.attr(b.anim[b.percents[y]])}if(!!j){if(!k){for(var A in j)if(j[g](A))if(U[g](A)||d.paper.customAttributes[g](A)){u[A]=d.attr(A),u[A]==null&&(u[A]=T[A]),v[A]=j[A];switch(U[A]){case C:w[A]=(v[A]-u[A])/t;break;case"colour":u[A]=a.getRGB(u[A]);var B=a.getRGB(v[A]);w[A]={r:(B.r-u[A].r)/t,g:(B.g-u[A].g)/t,b:(B.b-u[A].b)/t};break;case"path":var D=bR(u[A],v[A]),E=D[1];u[A]=D[0],w[A]=[];for(y=0,z=u[A].length;y<z;y++){w[A][y]=[0];for(var F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(E[y][F]-u[A][y][F])/t}break;case"transform":var H=d._,I=ca(H[A],v[A]);if(I){u[A]=I.from,v[A]=I.to,w[A]=[],w[A].real=!0;for(y=0,z=u[A].length;y<z;y++){w[A][y]=[u[A][y][0]];for(F=1,G=u[A][y].length;F<G;F++)w[A][y][F]=(v[A][y][F]-u[A][y][F])/t}}else{var J=d.matrix||new cb,K={_:{transform:H.transform},getBBox:function(){return d.getBBox(1)}};u[A]=[J.a,J.b,J.c,J.d,J.e,J.f],b$(K,v[A]),v[A]=K._.transform,w[A]=[(K.matrix.a-J.a)/t,(K.matrix.b-J.b)/t,(K.matrix.c-J.c)/t,(K.matrix.d-J.d)/t,(K.matrix.e-J.e)/t,(K.matrix.f-J.f)/t]}break;case"csv":var L=r(j[A])[s](c),M=r(u[A])[s](c);if(A=="clip-rect"){u[A]=M,w[A]=[],y=M.length;while(y--)w[A][y]=(L[y]-u[A][y])/t}v[A]=L;break;default:L=[][n](j[A]),M=[][n](u[A]),w[A]=[],y=d.paper.customAttributes[A].length;while(y--)w[A][y]=((L[y]||0)-(M[y]||0))/t}}var O=j.easing,P=a.easing_formulas[O];if(!P){P=r(O).match(N);if(P&&P.length==5){var R=P;P=function(a){return cC(a,+R[1],+R[2],+R[3],+R[4],t)}}else P=bf}q=j.start||b.start||+(new Date),x={anim:b,percent:e,timestamp:q,start:q+(b.del||0),status:0,initstatus:f||0,stop:!1,ms:t,easing:P,from:u,diff:w,to:v,el:d,callback:j.callback,prev:p,next:o,repeat:i||b.times,origin:d.attr(),totalOrigin:h},cy.push(x);if(f&&!k&&!l){x.stop=!0,x.start=new Date-t*f;if(cy.length==1)return cA()}l&&(x.start=new Date-x.ms*f),cy.length==1&&cz(cA)}else k.initstatus=f,k.start=new Date-k.ms*f;eve("raphael.anim.start."+d.id,d,b)}}function cD(a,b){var c=[],d={};this.ms=b,this.times=1;if(a){for(var e in a)a[g](e)&&(d[Q(e)]=a[e],c.push(Q(e)));c.sort(bd)}this.anim=d,this.top=c[c.length-1],this.percents=c}function cC(a,b,c,d,e,f){function o(a,b){var c,d,e,f,j,k;for(e=a,k=0;k<8;k++){f=m(e)-a;if(z(f)<b)return e;j=(3*i*e+2*h)*e+g;if(z(j)<1e-6)break;e=e-f/j}c=0,d=1,e=a;if(e<c)return c;if(e>d)return d;while(c<d){f=m(e);if(z(f-a)<b)return e;a>f?c=e:d=e,e=(d-c)/2+c}return e}function n(a,b){var c=o(a,b);return((l*c+k)*c+j)*c}function m(a){return((i*a+h)*a+g)*a}var g=3*b,h=3*(d-b)-g,i=1-g-h,j=3*c,k=3*(e-c)-j,l=1-j-k;return n(a,1/(200*f))}function cq(){return this.x+q+this.y+q+this.width+" × "+this.height}function cp(){return this.x+q+this.y}function cb(a,b,c,d,e,f){a!=null?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function bH(b,c,d){b=a._path2curve(b),c=a._path2curve(c);var e,f,g,h,i,j,k,l,m,n,o=d?0:[];for(var p=0,q=b.length;p<q;p++){var r=b[p];if(r[0]=="M")e=i=r[1],f=j=r[2];else{r[0]=="C"?(m=[e,f].concat(r.slice(1)),e=m[6],f=m[7]):(m=[e,f,e,f,i,j,i,j],e=i,f=j);for(var s=0,t=c.length;s<t;s++){var u=c[s];if(u[0]=="M")g=k=u[1],h=l=u[2];else{u[0]=="C"?(n=[g,h].concat(u.slice(1)),g=n[6],h=n[7]):(n=[g,h,g,h,k,l,k,l],g=k,h=l);var v=bG(m,n,d);if(d)o+=v;else{for(var w=0,x=v.length;w<x;w++)v[w].segment1=p,v[w].segment2=s,v[w].bez1=m,v[w].bez2=n;o=o.concat(v)}}}}}return o}function bG(b,c,d){var e=a.bezierBBox(b),f=a.bezierBBox(c);if(!a.isBBoxIntersect(e,f))return d?0:[];var g=bB.apply(0,b),h=bB.apply(0,c),i=~~(g/5),j=~~(h/5),k=[],l=[],m={},n=d?0:[];for(var o=0;o<i+1;o++){var p=a.findDotsAtSegment.apply(a,b.concat(o/i));k.push({x:p.x,y:p.y,t:o/i})}for(o=0;o<j+1;o++)p=a.findDotsAtSegment.apply(a,c.concat(o/j)),l.push({x:p.x,y:p.y,t:o/j});for(o=0;o<i;o++)for(var q=0;q<j;q++){var r=k[o],s=k[o+1],t=l[q],u=l[q+1],v=z(s.x-r.x)<.001?"y":"x",w=z(u.x-t.x)<.001?"y":"x",x=bD(r.x,r.y,s.x,s.y,t.x,t.y,u.x,u.y);if(x){if(m[x.x.toFixed(4)]==x.y.toFixed(4))continue;m[x.x.toFixed(4)]=x.y.toFixed(4);var y=r.t+z((x[v]-r[v])/(s[v]-r[v]))*(s.t-r.t),A=t.t+z((x[w]-t[w])/(u[w]-t[w]))*(u.t-t.t);y>=0&&y<=1&&A>=0&&A<=1&&(d?n++:n.push({x:x.x,y:x.y,t1:y,t2:A}))}}return n}function bF(a,b){return bG(a,b,1)}function bE(a,b){return bG(a,b)}function bD(a,b,c,d,e,f,g,h){if(!(x(a,c)<y(e,g)||y(a,c)>x(e,g)||x(b,d)<y(f,h)||y(b,d)>x(f,h))){var i=(a*d-b*c)*(e-g)-(a-c)*(e*h-f*g),j=(a*d-b*c)*(f-h)-(b-d)*(e*h-f*g),k=(a-c)*(f-h)-(b-d)*(e-g);if(!k)return;var l=i/k,m=j/k,n=+l.toFixed(2),o=+m.toFixed(2);if(n<+y(a,c).toFixed(2)||n>+x(a,c).toFixed(2)||n<+y(e,g).toFixed(2)||n>+x(e,g).toFixed(2)||o<+y(b,d).toFixed(2)||o>+x(b,d).toFixed(2)||o<+y(f,h).toFixed(2)||o>+x(f,h).toFixed(2))return;return{x:l,y:m}}}function bC(a,b,c,d,e,f,g,h,i){if(!(i<0||bB(a,b,c,d,e,f,g,h)<i)){var j=1,k=j/2,l=j-k,m,n=.01;m=bB(a,b,c,d,e,f,g,h,l);while(z(m-i)>n)k/=2,l+=(m<i?1:-1)*k,m=bB(a,b,c,d,e,f,g,h,l);return l}}function bB(a,b,c,d,e,f,g,h,i){i==null&&(i=1),i=i>1?1:i<0?0:i;var j=i/2,k=12,l=[-0.1252,.1252,-0.3678,.3678,-0.5873,.5873,-0.7699,.7699,-0.9041,.9041,-0.9816,.9816],m=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],n=0;for(var o=0;o<k;o++){var p=j*l[o]+j,q=bA(p,a,c,e,g),r=bA(p,b,d,f,h),s=q*q+r*r;n+=m[o]*w.sqrt(s)}return j*n}function bA(a,b,c,d,e){var f=-3*b+9*c-9*d+3*e,g=a*f+6*b-12*c+6*d;return a*g-3*b+3*c}function by(a,b){var c=[];for(var d=0,e=a.length;e-2*!b>d;d+=2){var f=[{x:+a[d-2],y:+a[d-1]},{x:+a[d],y:+a[d+1]},{x:+a[d+2],y:+a[d+3]},{x:+a[d+4],y:+a[d+5]}];b?d?e-4==d?f[3]={x:+a[0],y:+a[1]}:e-2==d&&(f[2]={x:+a[0],y:+a[1]},f[3]={x:+a[2],y:+a[3]}):f[0]={x:+a[e-2],y:+a[e-1]}:e-4==d?f[3]=f[2]:d||(f[0]={x:+a[d],y:+a[d+1]}),c.push(["C",(-f[0].x+6*f[1].x+f[2].x)/6,(-f[0].y+6*f[1].y+f[2].y)/6,(f[1].x+6*f[2].x-f[3].x)/6,(f[1].y+6*f[2].y-f[3].y)/6,f[2].x,f[2].y])}return c}function bx(){return this.hex}function bv(a,b,c){function d(){var e=Array.prototype.slice.call(arguments,0),f=e.join("␀"),h=d.cache=d.cache||{},i=d.count=d.count||[];if(h[g](f)){bu(i,f);return c?c(h[f]):h[f]}i.length>=1e3&&delete h[i.shift()],i.push(f),h[f]=a[m](b,e);return c?c(h[f]):h[f]}return d}function bu(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return a.push(a.splice(c,1)[0])}function bm(a){if(Object(a)!==a)return a;var b=new a.constructor;for(var c in a)a[g](c)&&(b[c]=bm(a[c]));return b}function a(c){if(a.is(c,"function"))return b?c():eve.on("raphael.DOMload",c);if(a.is(c,E))return a._engine.create[m](a,c.splice(0,3+a.is(c[0],C))).add(c);var d=Array.prototype.slice.call(arguments,0);if(a.is(d[d.length-1],"function")){var e=d.pop();return b?e.call(a._engine.create[m](a,d)):eve.on("raphael.DOMload",function(){e.call(a._engine.create[m](a,d))})}return a._engine.create[m](a,arguments)}a.version="2.1.0",a.eve=eve;var b,c=/[, ]+/,d={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},e=/\{(\d+)\}/g,f="prototype",g="hasOwnProperty",h={doc:document,win:window},i={was:Object.prototype[g].call(h.win,"Raphael"),is:h.win.Raphael},j=function(){this.ca=this.customAttributes={}},k,l="appendChild",m="apply",n="concat",o="createTouch"in h.doc,p="",q=" ",r=String,s="split",t="click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[s](q),u={mousedown:"touchstart",mousemove:"touchmove",mouseup:"touchend"},v=r.prototype.toLowerCase,w=Math,x=w.max,y=w.min,z=w.abs,A=w.pow,B=w.PI,C="number",D="string",E="array",F="toString",G="fill",H=Object.prototype.toString,I={},J="push",K=a._ISURL=/^url\(['"]?([^\)]+?)['"]?\)$/i,L=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,M={NaN:1,Infinity:1,"-Infinity":1},N=/^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,O=w.round,P="setAttribute",Q=parseFloat,R=parseInt,S=r.prototype.toUpperCase,T=a._availableAttrs={"arrow-end":"none","arrow-start":"none",blur:0,"clip-rect":"0 0 1e9 1e9",cursor:"default",cx:0,cy:0,fill:"#fff","fill-opacity":1,font:'10px "Arial"',"font-family":'"Arial"',"font-size":"10","font-style":"normal","font-weight":400,gradient:0,height:0,href:"http://raphaeljs.com/","letter-spacing":0,opacity:1,path:"M0,0",r:0,rx:0,ry:0,src:"",stroke:"#000","stroke-dasharray":"","stroke-linecap":"butt","stroke-linejoin":"butt","stroke-miterlimit":0,"stroke-opacity":1,"stroke-width":1,target:"_blank","text-anchor":"middle",title:"Raphael",transform:"",width:0,x:0,y:0},U=a._availableAnimAttrs={blur:C,"clip-rect":"csv",cx:C,cy:C,fill:"colour","fill-opacity":C,"font-size":C,height:C,opacity:C,path:"path",r:C,rx:C,ry:C,stroke:"colour","stroke-opacity":C,"stroke-width":C,transform:"transform",width:C,x:C,y:C},V=/[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]/g,W=/[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/,X={hs:1,rg:1},Y=/,?([achlmqrstvxz]),?/gi,Z=/([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,$=/([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,_=/(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/ig,ba=a._radial_gradient=/^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/,bb={},bc=function(a,b){return a.key-b.key},bd=function(a,b){return Q(a)-Q(b)},be=function(){},bf=function(a){return a},bg=a._rectPath=function(a,b,c,d,e){if(e)return[["M",a+e,b],["l",c-e*2,0],["a",e,e,0,0,1,e,e],["l",0,d-e*2],["a",e,e,0,0,1,-e,e],["l",e*2-c,0],["a",e,e,0,0,1,-e,-e],["l",0,e*2-d],["a",e,e,0,0,1,e,-e],["z"]];return[["M",a,b],["l",c,0],["l",0,d],["l",-c,0],["z"]]},bh=function(a,b,c,d){d==null&&(d=c);return[["M",a,b],["m",0,-d],["a",c,d,0,1,1,0,2*d],["a",c,d,0,1,1,0,-2*d],["z"]]},bi=a._getPath={path:function(a){return a.attr("path")},circle:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.r)},ellipse:function(a){var b=a.attrs;return bh(b.cx,b.cy,b.rx,b.ry)},rect:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height,b.r)},image:function(a){var b=a.attrs;return bg(b.x,b.y,b.width,b.height)},text:function(a){var b=a._getBBox();return bg(b.x,b.y,b.width,b.height)}},bj=a.mapPath=function(a,b){if(!b)return a;var c,d,e,f,g,h,i;a=bR(a);for(e=0,g=a.length;e<g;e++){i=a[e];for(f=1,h=i.length;f<h;f+=2)c=b.x(i[f],i[f+1]),d=b.y(i[f],i[f+1]),i[f]=c,i[f+1]=d}return a};a._g=h,a.type=h.win.SVGAngle||h.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML";if(a.type=="VML"){var bk=h.doc.createElement("div"),bl;bk.innerHTML='<v:shape adj="1"/>',bl=bk.firstChild,bl.style.behavior="url(#default#VML)";if(!bl||typeof bl.adj!="object")return a.type=p;bk=null}a.svg=!(a.vml=a.type=="VML"),a._Paper=j,a.fn=k=j.prototype=a.prototype,a._id=0,a._oid=0,a.is=function(a,b){b=v.call(b);if(b=="finite")return!M[g](+a);if(b=="array")return a instanceof Array;return b=="null"&&a===null||b==typeof a&&a!==null||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||H.call(a).slice(8,-1).toLowerCase()==b},a.angle=function(b,c,d,e,f,g){if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return(180+w.atan2(-i,-h)*180/B+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)},a.rad=function(a){return a%360*B/180},a.deg=function(a){return a*180/B%360},a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,E)){var e=b.length;while(e--)if(z(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(f<d)return c-f;if(f>b-d)return c-f+b}return c};var bn=a.createUUID=function(a,b){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=w.random()*16|0,c=a=="x"?b:b&3|8;return c.toString(16)});a.setWindow=function(b){eve("raphael.setWindow",a,h.win,b),h.win=b,h.doc=h.win.document,a._engine.initWin&&a._engine.initWin(h.win)};var bo=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("<body>"),e.close(),d=e.body}catch(f){d=createPopup().document.body}var g=d.createTextRange();bo=bv(function(a){try{d.style.color=r(a).replace(c,p);var b=g.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b.toString(16)).slice(-6)}catch(e){return"none"}})}else{var i=h.doc.createElement("i");i.title="Raphaël Colour Picker",i.style.display="none",h.doc.body.appendChild(i),bo=bv(function(a){i.style.color=a;return h.doc.defaultView.getComputedStyle(i,p).getPropertyValue("color")})}return bo(b)},bp=function(){return"hsb("+[this.h,this.s,this.b]+")"},bq=function(){return"hsl("+[this.h,this.s,this.l]+")"},br=function(){return this.hex},bs=function(b,c,d){c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b&&(d=b.b,c=b.g,b=b.r);if(c==null&&a.is(b,D)){var e=a.getRGB(b);b=e.r,c=e.g,d=e.b}if(b>1||c>1||d>1)b/=255,c/=255,d/=255;return[b,c,d]},bt=function(b,c,d,e){b*=255,c*=255,d*=255;var f={r:b,g:c,b:d,hex:a.rgb(b,c,d),toString:br};a.is(e,"finite")&&(f.opacity=e);return f};a.color=function(b){var c;a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b?(c=a.hsb2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b?(c=a.hsl2rgb(b),b.r=c.r,b.g=c.g,b.b=c.b,b.hex=c.hex):(a.is(b,"string")&&(b=a.getRGB(b)),a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b?(c=a.rgb2hsl(b),b.h=c.h,b.s=c.s,b.l=c.l,c=a.rgb2hsb(b),b.v=c.b):(b={hex:"none"},b.r=b.g=b.b=b.h=b.s=b.v=b.l=-1)),b.toString=br;return b},a.hsb2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"b"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;a=a%360/60,i=c*b,h=i*(1-z(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.hsl2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"l"in a&&(c=a.l,b=a.s,a=a.h);if(a>1||b>1||c>1)a/=360,b/=100,c/=100;a*=360;var e,f,g,h,i;a=a%360/60,i=2*b*(c<.5?c:1-c),h=i*(1-z(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a];return bt(e,f,g,d)},a.rgb2hsb=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;f=x(a,b,c),g=f-y(a,b,c),d=g==0?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=(d+360)%6*60/360,e=g==0?0:g/f;return{h:d,s:e,b:f,toString:bp}},a.rgb2hsl=function(a,b,c){c=bs(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;g=x(a,b,c),h=y(a,b,c),i=g-h,d=i==0?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=(d+360)%6*60/360,f=(g+h)/2,e=i==0?0:f<.5?i/(2*f):i/(2-2*f);return{h:d,s:e,l:f,toString:bq}},a._path2string=function(){return this.join(",").replace(Y,"$1")};var bw=a._preload=function(a,b){var c=h.doc.createElement("img");c.style.cssText="position:absolute;left:-9999em;top:-9999em",c.onload=function(){b.call(this),this.onload=null,h.doc.body.removeChild(this)},c.onerror=function(){h.doc.body.removeChild(this)},h.doc.body.appendChild(c),c.src=a};a.getRGB=bv(function(b){if(!b||!!((b=r(b)).indexOf("-")+1))return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:bx};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none",toString:bx};!X[g](b.toLowerCase().substring(0,2))&&b.charAt()!="#"&&(b=bo(b));var c,d,e,f,h,i,j,k=b.match(L);if(k){k[2]&&(f=R(k[2].substring(5),16),e=R(k[2].substring(3,5),16),d=R(k[2].substring(1,3),16)),k[3]&&(f=R((i=k[3].charAt(3))+i,16),e=R((i=k[3].charAt(2))+i,16),d=R((i=k[3].charAt(1))+i,16)),k[4]&&(j=k[4][s](W),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),k[1].toLowerCase().slice(0,4)=="rgba"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100));if(k[5]){j=k[5][s](W),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsba"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,f,h)}if(k[6]){j=k[6][s](W),d=Q(j[0]),j[0].slice(-1)=="%"&&(d*=2.55),e=Q(j[1]),j[1].slice(-1)=="%"&&(e*=2.55),f=Q(j[2]),j[2].slice(-1)=="%"&&(f*=2.55),(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360),k[1].toLowerCase().slice(0,4)=="hsla"&&(h=Q(j[3])),j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,f,h)}k={r:d,g:e,b:f,toString:bx},k.hex="#"+(16777216|f|e<<8|d<<16).toString(16).slice(1),a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:bx}},a),a.hsb=bv(function(b,c,d){return a.hsb2rgb(b,c,d).hex}),a.hsl=bv(function(b,c,d){return a.hsl2rgb(b,c,d).hex}),a.rgb=bv(function(a,b,c){return"#"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b}));return c.hex},a.getColor.reset=function(){delete this.start},a.parsePathString=function(b){if(!b)return null;var c=bz(b);if(c.arr)return bJ(c.arr);var d={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},e=[];a.is(b,E)&&a.is(b[0],E)&&(e=bJ(b)),e.length||r(b).replace(Z,function(a,b,c){var f=[],g=b.toLowerCase();c.replace(_,function(a,b){b&&f.push(+b)}),g=="m"&&f.length>2&&(e.push([b][n](f.splice(0,2))),g="l",b=b=="m"?"l":"L");if(g=="r")e.push([b][n](f));else while(f.length>=d[g]){e.push([b][n](f.splice(0,d[g])));if(!d[g])break}}),e.toString=a._path2string,c.arr=bJ(e);return e},a.parseTransformString=bv(function(b){if(!b)return null;var c={r:3,s:4,t:2,m:6},d=[];a.is(b,E)&&a.is(b[0],E)&&(d=bJ(b)),d.length||r(b).replace($,function(a,b,c){var e=[],f=v.call(b);c.replace(_,function(a,b){b&&e.push(+b)}),d.push([b][n](e))}),d.toString=a._path2string;return d});var bz=function(a){var b=bz.ps=bz.ps||{};b[a]?b[a].sleep=100:b[a]={sleep:100},setTimeout(function(){for(var c in b)b[g](c)&&c!=a&&(b[c].sleep--,!b[c].sleep&&delete b[c])});return b[a]};a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=A(j,3),l=A(j,2),m=i*i,n=m*i,o=k*a+l*3*i*c+j*3*i*i*e+n*g,p=k*b+l*3*i*d+j*3*i*i*f+n*h,q=a+2*i*(c-a)+m*(e-2*c+a),r=b+2*i*(d-b)+m*(f-2*d+b),s=c+2*i*(e-c)+m*(g-2*e+c),t=d+2*i*(f-d)+m*(h-2*f+d),u=j*a+i*c,v=j*b+i*d,x=j*e+i*g,y=j*f+i*h,z=90-w.atan2(q-s,r-t)*180/B;(q>s||r<t)&&(z+=180);return{x:o,y:p,m:{x:q,y:r},n:{x:s,y:t},start:{x:u,y:v},end:{x:x,y:y},alpha:z}},a.bezierBBox=function(b,c,d,e,f,g,h,i){a.is(b,"array")||(b=[b,c,d,e,f,g,h,i]);var j=bQ.apply(null,b);return{x:j.min.x,y:j.min.y,x2:j.max.x,y2:j.max.y,width:j.max.x-j.min.x,height:j.max.y-j.min.y}},a.isPointInsideBBox=function(a,b,c){return b>=a.x&&b<=a.x2&&c>=a.y&&c<=a.y2},a.isBBoxIntersect=function(b,c){var d=a.isPointInsideBBox;return d(c,b.x,b.y)||d(c,b.x2,b.y)||d(c,b.x,b.y2)||d(c,b.x2,b.y2)||d(b,c.x,c.y)||d(b,c.x2,c.y)||d(b,c.x,c.y2)||d(b,c.x2,c.y2)||(b.x<c.x2&&b.x>c.x||c.x<b.x2&&c.x>b.x)&&(b.y<c.y2&&b.y>c.y||c.y<b.y2&&c.y>b.y)},a.pathIntersection=function(a,b){return bH(a,b)},a.pathIntersectionNumber=function(a,b){return bH(a,b,1)},a.isPointInsidePath=function(b,c,d){var e=a.pathBBox(b);return a.isPointInsideBBox(e,c,d)&&bH(b,[["M",c,d],["H",e.x2+10]],1)%2==1},a._removedFactory=function(a){return function(){eve("raphael.log",null,"Raphaël: you are calling to method “"+a+"” of removed object",a)}};var bI=a.pathBBox=function(a){var b=bz(a);if(b.bbox)return b.bbox;if(!a)return{x:0,y:0,width:0,height:0,x2:0,y2:0};a=bR(a);var c=0,d=0,e=[],f=[],g;for(var h=0,i=a.length;h<i;h++){g=a[h];if(g[0]=="M")c=g[1],d=g[2],e.push(c),f.push(d);else{var j=bQ(c,d,g[1],g[2],g[3],g[4],g[5],g[6]);e=e[n](j.min.x,j.max.x),f=f[n](j.min.y,j.max.y),c=g[5],d=g[6]}}var k=y[m](0,e),l=y[m](0,f),o=x[m](0,e),p=x[m](0,f),q={x:k,y:l,x2:o,y2:p,width:o-k,height:p-l};b.bbox=bm(q);return q},bJ=function(b){var c=bm(b);c.toString=a._path2string;return c},bK=a._pathToRelative=function(b){var c=bz(b);if(c.rel)return bJ(c.rel);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]=="M"&&(e=b[0][1],f=b[0][2],g=e,h=f,i++,d.push(["M",e,f]));for(var j=i,k=b.length;j<k;j++){var l=d[j]=[],m=b[j];if(m[0]!=v.call(m[0])){l[0]=v.call(m[0]);switch(l[0]){case"a":l[1]=m[1],l[2]=m[2],l[3]=m[3],l[4]=m[4],l[5]=m[5],l[6]=+(m[6]-e).toFixed(3),l[7]=+(m[7]-f).toFixed(3);break;case"v":l[1]=+(m[1]-f).toFixed(3);break;case"m":g=m[1],h=m[2];default:for(var n=1,o=m.length;n<o;n++)l[n]=+(m[n]-(n%2?e:f)).toFixed(3)}}else{l=d[j]=[],m[0]=="m"&&(g=m[1]+e,h=m[2]+f);for(var p=0,q=m.length;p<q;p++)d[j][p]=m[p]}var r=d[j].length;switch(d[j][0]){case"z":e=g,f=h;break;case"h":e+=+d[j][r-1];break;case"v":f+=+d[j][r-1];break;default:e+=+d[j][r-2],f+=+d[j][r-1]}}d.toString=a._path2string,c.rel=bJ(d);return d},bL=a._pathToAbsolute=function(b){var c=bz(b);if(c.abs)return bJ(c.abs);if(!a.is(b,E)||!a.is(b&&b[0],E))b=a.parsePathString(b);if(!b||!b.length)return[["M",0,0]];var d=[],e=0,f=0,g=0,h=0,i=0;b[0][0]=="M"&&(e=+b[0][1],f=+b[0][2],g=e,h=f,i++,d[0]=["M",e,f]);var j=b.length==3&&b[0][0]=="M"&&b[1][0].toUpperCase()=="R"&&b[2][0].toUpperCase()=="Z";for(var k,l,m=i,o=b.length;m<o;m++){d.push(k=[]),l=b[m];if(l[0]!=S.call(l[0])){k[0]=S.call(l[0]);switch(k[0]){case"A":k[1]=l[1],k[2]=l[2],k[3]=l[3],k[4]=l[4],k[5]=l[5],k[6]=+(l[6]+e),k[7]=+(l[7]+f);break;case"V":k[1]=+l[1]+f;break;case"H":k[1]=+l[1]+e;break;case"R":var p=[e,f][n](l.slice(1));for(var q=2,r=p.length;q<r;q++)p[q]=+p[q]+e,p[++q]=+p[q]+f;d.pop(),d=d[n](by(p,j));break;case"M":g=+l[1]+e,h=+l[2]+f;default:for(q=1,r=l.length;q<r;q++)k[q]=+l[q]+(q%2?e:f)}}else if(l[0]=="R")p=[e,f][n](l.slice(1)),d.pop(),d=d[n](by(p,j)),k=["R"][n](l.slice(-2));else for(var s=0,t=l.length;s<t;s++)k[s]=l[s];switch(k[0]){case"Z":e=g,f=h;break;case"H":e=k[1];break;case"V":f=k[1];break;case"M":g=k[k.length-2],h=k[k.length-1];default:e=k[k.length-2],f=k[k.length-1]}}d.toString=a._path2string,c.abs=bJ(d);return d},bM=function(a,b,c,d){return[a,b,c,d,c,d]},bN=function(a,b,c,d,e,f){var g=1/3,h=2/3;return[g*a+h*c,g*b+h*d,g*e+h*c,g*f+h*d,e,f]},bO=function(a,b,c,d,e,f,g,h,i,j){var k=B*120/180,l=B/180*(+e||0),m=[],o,p=bv(function(a,b,c){var d=a*w.cos(c)-b*w.sin(c),e=a*w.sin(c)+b*w.cos(c);return{x:d,y:e}});if(!j){o=p(a,b,-l),a=o.x,b=o.y,o=p(h,i,-l),h=o.x,i=o.y;var q=w.cos(B/180*e),r=w.sin(B/180*e),t=(a-h)/2,u=(b-i)/2,v=t*t/(c*c)+u*u/(d*d);v>1&&(v=w.sqrt(v),c=v*c,d=v*d);var x=c*c,y=d*d,A=(f==g?-1:1)*w.sqrt(z((x*y-x*u*u-y*t*t)/(x*u*u+y*t*t))),C=A*c*u/d+(a+h)/2,D=A*-d*t/c+(b+i)/2,E=w.asin(((b-D)/d).toFixed(9)),F=w.asin(((i-D)/d).toFixed(9));E=a<C?B-E:E,F=h<C?B-F:F,E<0&&(E=B*2+E),F<0&&(F=B*2+F),g&&E>F&&(E=E-B*2),!g&&F>E&&(F=F-B*2)}else E=j[0],F=j[1],C=j[2],D=j[3];var G=F-E;if(z(G)>k){var H=F,I=h,J=i;F=E+k*(g&&F>E?1:-1),h=C+c*w.cos(F),i=D+d*w.sin(F),m=bO(h,i,c,d,e,0,g,I,J,[F,H,C,D])}G=F-E;var K=w.cos(E),L=w.sin(E),M=w.cos(F),N=w.sin(F),O=w.tan(G/4),P=4/3*c*O,Q=4/3*d*O,R=[a,b],S=[a+P*L,b-Q*K],T=[h+P*N,i-Q*M],U=[h,i];S[0]=2*R[0]-S[0],S[1]=2*R[1]-S[1];if(j)return[S,T,U][n](m);m=[S,T,U][n](m).join()[s](",");var V=[];for(var W=0,X=m.length;W<X;W++)V[W]=W%2?p(m[W-1],m[W],l).y:p(m[W],m[W+1],l).x;return V},bP=function(a,b,c,d,e,f,g,h,i){var j=1-i;return{x:A(j,3)*a+A(j,2)*3*i*c+j*3*i*i*e+A(i,3)*g,y:A(j,3)*b+A(j,2)*3*i*d+j*3*i*i*f+A(i,3)*h}},bQ=bv(function(a,b,c,d,e,f,g,h){var i=e-2*c+a-(g-2*e+c),j=2*(c-a)-2*(e-c),k=a-c,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,o=[b,h],p=[a,g],q;z(l)>"1e12"&&(l=.5),z(n)>"1e12"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y)),i=f-2*d+b-(h-2*f+d),j=2*(d-b)-2*(f-d),k=b-d,l=(-j+w.sqrt(j*j-4*i*k))/2/i,n=(-j-w.sqrt(j*j-4*i*k))/2/i,z(l)>"1e12"&&(l=.5),z(n)>"1e12"&&(n=.5),l>0&&l<1&&(q=bP(a,b,c,d,e,f,g,h,l),p.push(q.x),o.push(q.y)),n>0&&n<1&&(q=bP(a,b,c,d,e,f,g,h,n),p.push(q.x),o.push(q.y));return{min:{x:y[m](0,p),y:y[m](0,o)},max:{x:x[m](0,p),y:x[m](0,o)}}}),bR=a._path2curve=bv(function(a,b){var c=!b&&bz(a);if(!b&&c.curve)return bJ(c.curve);var d=bL(a),e=b&&bL(b),f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},h=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1],b.Y=a[2];break;case"A":a=["C"][n](bO[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x)),d=b.y+(b.y-(b.by||b.y)),a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x)),b.qy=b.y+(b.y-(b.qy||b.y)),a=["C"][n](bN(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1],b.qy=a[2],a=["C"][n](bN(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](bM(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](bM(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](bM(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](bM(b.x,b.y,b.X,b.Y))}return a},i=function(a,b){if(a[b].length>7){a[b].shift();var c=a[b];while(c.length)a.splice(b++,0,["C"][n](c.splice(0,6)));a.splice(b,1),l=x(d.length,e&&e.length||0)}},j=function(a,b,c,f,g){a&&b&&a[g][0]=="M"&&b[g][0]!="M"&&(b.splice(g,0,["M",f.x,f.y]),c.bx=0,c.by=0,c.x=a[g][1],c.y=a[g][2],l=x(d.length,e&&e.length||0))};for(var k=0,l=x(d.length,e&&e.length||0);k<l;k++){d[k]=h(d[k],f),i(d,k),e&&(e[k]=h(e[k],g)),e&&i(e,k),j(d,e,f,g,k),j(e,d,g,f,k);var o=d[k],p=e&&e[k],q=o.length,r=e&&p.length;f.x=o[q-2],f.y=o[q-1],f.bx=Q(o[q-4])||f.x,f.by=Q(o[q-3])||f.y,g.bx=e&&(Q(p[r-4])||g.x),g.by=e&&(Q(p[r-3])||g.y),g.x=e&&p[r-2],g.y=e&&p[r-1]}e||(c.curve=bJ(d));return e?[d,e]:d},null,bJ),bS=a._parseDots=bv(function(b){var c=[];for(var d=0,e=b.length;d<e;d++){var f={},g=b[d].match(/^([^:]*):?([\d\.]*)/);f.color=a.getRGB(g[1]);if(f.color.error)return null;f.color=f.color.hex,g[2]&&(f.offset=g[2]+"%"),c.push(f)}for(d=1,e=c.length-1;d<e;d++)if(!c[d].offset){var h=Q(c[d-1].offset||0),i=0;for(var j=d+1;j<e;j++)if(c[j].offset){i=c[j].offset;break}i||(i=100,j=e),i=Q(i);var k=(i-h)/(j-d+1);for(;d<j;d++)h+=k,c[d].offset=h+"%"}return c}),bT=a._tear=function(a,b){a==b.top&&(b.top=a.prev),a==b.bottom&&(b.bottom=a.next),a.next&&(a.next.prev=a.prev),a.prev&&(a.prev.next=a.next)},bU=a._tofront=function(a,b){b.top!==a&&(bT(a,b),a.next=null,a.prev=b.top,b.top.next=a,b.top=a)},bV=a._toback=function(a,b){b.bottom!==a&&(bT(a,b),a.next=b.bottom,a.prev=null,b.bottom.prev=a,b.bottom=a)},bW=a._insertafter=function(a,b,c){bT(a,c),b==c.top&&(c.top=a),b.next&&(b.next.prev=a),a.next=b.next,a.prev=b,b.next=a},bX=a._insertbefore=function(a,b,c){bT(a,c),b==c.bottom&&(c.bottom=a),b.prev&&(b.prev.next=a),a.prev=b.prev,b.prev=a,a.next=b},bY=a.toMatrix=function(a,b){var c=bI(a),d={_:{transform:p},getBBox:function(){return c}};b$(d,b);return d.matrix},bZ=a.transformPath=function(a,b){return bj(a,bY(a,b))},b$=a._extractTransform=function(b,c){if(c==null)return b._.transform;c=r(c).replace(/\.{3}|\u2026/g,b._.transform||p);var d=a.parseTransformString(c),e=0,f=0,g=0,h=1,i=1,j=b._,k=new cb;j.transform=d||[];if(d)for(var l=0,m=d.length;l<m;l++){var n=d[l],o=n.length,q=r(n[0]).toLowerCase(),s=n[0]!=q,t=s?k.invert():0,u,v,w,x,y;q=="t"&&o==3?s?(u=t.x(0,0),v=t.y(0,0),w=t.x(n[1],n[2]),x=t.y(n[1],n[2]),k.translate(w-u,x-v)):k.translate(n[1],n[2]):q=="r"?o==2?(y=y||b.getBBox(1),k.rotate(n[1],y.x+y.width/2,y.y+y.height/2),e+=n[1]):o==4&&(s?(w=t.x(n[2],n[3]),x=t.y(n[2],n[3]),k.rotate(n[1],w,x)):k.rotate(n[1],n[2],n[3]),e+=n[1]):q=="s"?o==2||o==3?(y=y||b.getBBox(1),k.scale(n[1],n[o-1],y.x+y.width/2,y.y+y.height/2),h*=n[1],i*=n[o-1]):o==5&&(s?(w=t.x(n[3],n[4]),x=t.y(n[3],n[4]),k.scale(n[1],n[2],w,x)):k.scale(n[1],n[2],n[3],n[4]),h*=n[1],i*=n[2]):q=="m"&&o==7&&k.add(n[1],n[2],n[3],n[4],n[5],n[6]),j.dirtyT=1,b.matrix=k}b.matrix=k,j.sx=h,j.sy=i,j.deg=e,j.dx=f=k.e,j.dy=g=k.f,h==1&&i==1&&!e&&j.bbox?(j.bbox.x+=+f,j.bbox.y+=+g):j.dirtyT=1},b_=function(a){var b=a[0];switch(b.toLowerCase()){case"t":return[b,0,0];case"m":return[b,1,0,0,1,0,0];case"r":return a.length==4?[b,0,a[2],a[3]]:[b,0];case"s":return a.length==5?[b,1,1,a[3],a[4]]:a.length==3?[b,1,1]:[b,1]}},ca=a._equaliseTransform=function(b,c){c=r(c).replace(/\.{3}|\u2026/g,b),b=a.parseTransformString(b)||[],c=a.parseTransformString(c)||[];var d=x(b.length,c.length),e=[],f=[],g=0,h,i,j,k;for(;g<d;g++){j=b[g]||b_(c[g]),k=c[g]||b_(j);if(j[0]!=k[0]||j[0].toLowerCase()=="r"&&(j[2]!=k[2]||j[3]!=k[3])||j[0].toLowerCase()=="s"&&(j[3]!=k[3]||j[4]!=k[4]))return;e[g]=[],f[g]=[];for(h=0,i=x(j.length,k.length);h<i;h++)h in j&&(e[g][h]=j[h]),h in k&&(f[g][h]=k[h])}return{from:e,to:f}};a._getContainer=function(b,c,d,e){var f;f=e==null&&!a.is(b,"object")?h.doc.getElementById(b):b;if(f!=null){if(f.tagName)return c==null?{container:f,width:f.style.pixelWidth||f.offsetWidth,height:f.style.pixelHeight||f.offsetHeight}:{container:f,width:c,height:d};return{container:1,x:b,y:c,width:d,height:e}}},a.pathToRelative=bK,a._engine={},a.path2curve=bR,a.matrix=function(a,b,c,d,e,f){return new cb(a,b,c,d,e,f)},function(b){function d(a){var b=w.sqrt(c(a));a[0]&&(a[0]/=b),a[1]&&(a[1]/=b)}function c(a){return a[0]*a[0]+a[1]*a[1]}b.add=function(a,b,c,d,e,f){var g=[[],[],[]],h=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],i=[[a,c,e],[b,d,f],[0,0,1]],j,k,l,m;a&&a instanceof cb&&(i=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]);for(j=0;j<3;j++)for(k=0;k<3;k++){m=0;for(l=0;l<3;l++)m+=h[j][l]*i[l][k];g[j][k]=m}this.a=g[0][0],this.b=g[1][0],this.c=g[0][1],this.d=g[1][1],this.e=g[0][2],this.f=g[1][2]},b.invert=function(){var a=this,b=a.a*a.d-a.b*a.c;return new cb(a.d/b,-a.b/b,-a.c/b,a.a/b,(a.c*a.f-a.d*a.e)/b,(a.b*a.e-a.a*a.f)/b)},b.clone=function(){return new cb(this.a,this.b,this.c,this.d,this.e,this.f)},b.translate=function(a,b){this.add(1,0,0,1,a,b)},b.scale=function(a,b,c,d){b==null&&(b=a),(c||d)&&this.add(1,0,0,1,c,d),this.add(a,0,0,b,0,0),(c||d)&&this.add(1,0,0,1,-c,-d)},b.rotate=function(b,c,d){b=a.rad(b),c=c||0,d=d||0;var e=+w.cos(b).toFixed(9),f=+w.sin(b).toFixed(9);this.add(e,f,-f,e,c,d),this.add(1,0,0,1,-c,-d)},b.x=function(a,b){return a*this.a+b*this.c+this.e},b.y=function(a,b){return a*this.b+b*this.d+this.f},b.get=function(a){return+this[r.fromCharCode(97+a)].toFixed(4)},b.toString=function(){return a.svg?"matrix("+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+")":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},b.toFilter=function(){return"progid:DXImageTransform.Microsoft.Matrix(M11="+this.get(0)+", M12="+this.get(2)+", M21="+this.get(1)+", M22="+this.get(3)+", Dx="+this.get(4)+", Dy="+this.get(5)+", sizingmethod='auto expand')"},b.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},b.split=function(){var b={};b.dx=this.e,b.dy=this.f;var e=[[this.a,this.c],[this.b,this.d]];b.scalex=w.sqrt(c(e[0])),d(e[0]),b.shear=e[0][0]*e[1][0]+e[0][1]*e[1][1],e[1]=[e[1][0]-e[0][0]*b.shear,e[1][1]-e[0][1]*b.shear],b.scaley=w.sqrt(c(e[1])),d(e[1]),b.shear/=b.scaley;var f=-e[0][1],g=e[1][1];g<0?(b.rotate=a.deg(w.acos(g)),f<0&&(b.rotate=360-b.rotate)):b.rotate=a.deg(w.asin(f)),b.isSimple=!+b.shear.toFixed(9)&&(b.scalex.toFixed(9)==b.scaley.toFixed(9)||!b.rotate),b.isSuperSimple=!+b.shear.toFixed(9)&&b.scalex.toFixed(9)==b.scaley.toFixed(9)&&!b.rotate,b.noRotation=!+b.shear.toFixed(9)&&!b.rotate;return b},b.toTransformString=function(a){var b=a||this[s]();if(b.isSimple){b.scalex=+b.scalex.toFixed(4),b.scaley=+b.scaley.toFixed(4),b.rotate=+b.rotate.toFixed(4);return(b.dx||b.dy?"t"+[b.dx,b.dy]:p)+(b.scalex!=1||b.scaley!=1?"s"+[b.scalex,b.scaley,0,0]:p)+(b.rotate?"r"+[b.rotate,0,0]:p)}return"m"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(cb.prototype);var cc=navigator.userAgent.match(/Version\/(.*?)\s/)||navigator.userAgent.match(/Chrome\/(\d+)/);navigator.vendor=="Apple Computer, Inc."&&(cc&&cc[1]<4||navigator.platform.slice(0,2)=="iP")||navigator.vendor=="Google Inc."&&cc&&cc[1]<8?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});setTimeout(function(){a.remove()})}:k.safari=be;var cd=function(){this.returnValue=!1},ce=function(){return this.originalEvent.preventDefault()},cf=function(){this.cancelBubble=!0},cg=function(){return this.originalEvent.stopPropagation()},ch=function(){if(h.doc.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,f=function(e){var f=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,i=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,j=e.clientX+i,k=e.clientY+f;if(o&&u[g](b))for(var l=0,m=e.targetTouches&&e.targetTouches.length;l<m;l++)if(e.targetTouches[l].target==a){var n=e;e=e.targetTouches[l],e.originalEvent=n,e.preventDefault=ce,e.stopPropagation=cg;break}return c.call(d,e,j,k)};a.addEventListener(e,f,!1);return function(){a.removeEventListener(e,f,!1);return!0}};if(h.doc.attachEvent)return function(a,b,c,d){var e=function(a){a=a||h.win.event;var b=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f=a.clientX+e,g=a.clientY+b;a.preventDefault=a.preventDefault||cd,a.stopPropagation=a.stopPropagation||cf;return c.call(d,a,f,g)};a.attachEvent("on"+b,e);var f=function(){a.detachEvent("on"+b,e);return!0};return f}}(),ci=[],cj=function(a){var b=a.clientX,c=a.clientY,d=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,e=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft,f,g=ci.length;while(g--){f=ci[g];if(o){var i=a.touches.length,j;while(i--){j=a.touches[i];if(j.identifier==f.el._drag.id){b=j.clientX,c=j.clientY,(a.originalEvent?a.originalEvent:a).preventDefault();break}}}else a.preventDefault();var k=f.el.node,l,m=k.nextSibling,n=k.parentNode,p=k.style.display;h.win.opera&&n.removeChild(k),k.style.display="none",l=f.el.paper.getElementByPoint(b,c),k.style.display=p,h.win.opera&&(m?n.insertBefore(k,m):n.appendChild(k)),l&&eve("raphael.drag.over."+f.el.id,f.el,l),b+=e,c+=d,eve("raphael.drag.move."+f.el.id,f.move_scope||f.el,b-f.el._drag.x,c-f.el._drag.y,b,c,a)}},ck=function(b){a.unmousemove(cj).unmouseup(ck);var c=ci.length,d;while(c--)d=ci[c],d.el._drag={},eve("raphael.drag.end."+d.el.id,d.end_scope||d.start_scope||d.move_scope||d.el,b);ci=[]},cl=a.el={};for(var cm=t.length;cm--;)(function(b){a[b]=cl[b]=function(c,d){a.is(c,"function")&&(this.events=this.events||[],this.events.push({name:b,f:c,unbind:ch(this.shape||this.node||h.doc,b,c,d||this)}));return this},a["un"+b]=cl["un"+b]=function(a){var c=this.events||[],d=c.length;while(d--)if(c[d].name==b&&c[d].f==a){c[d].unbind(),c.splice(d,1),!c.length&&delete this.events;return this}return this}})(t[cm]);cl.data=function(b,c){var d=bb[this.id]=bb[this.id]||{};if(arguments.length==1){if(a.is(b,"object")){for(var e in b)b[g](e)&&this.data(e,b[e]);return this}eve("raphael.data.get."+this.id,this,d[b],b);return d[b]}d[b]=c,eve("raphael.data.set."+this.id,this,c,b);return this},cl.removeData=function(a){a==null?bb[this.id]={}:bb[this.id]&&delete bb[this.id][a];return this},cl.hover=function(a,b,c,d){return this.mouseover(a,c).mouseout(b,d||c)},cl.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)};var cn=[];cl.drag=function(b,c,d,e,f,g){function i(i){(i.originalEvent||i).preventDefault();var j=h.doc.documentElement.scrollTop||h.doc.body.scrollTop,k=h.doc.documentElement.scrollLeft||h.doc.body.scrollLeft;this._drag.x=i.clientX+k,this._drag.y=i.clientY+j,this._drag.id=i.identifier,!ci.length&&a.mousemove(cj).mouseup(ck),ci.push({el:this,move_scope:e,start_scope:f,end_scope:g}),c&&eve.on("raphael.drag.start."+this.id,c),b&&eve.on("raphael.drag.move."+this.id,b),d&&eve.on("raphael.drag.end."+this.id,d),eve("raphael.drag.start."+this.id,f||e||this,i.clientX+k,i.clientY+j,i)}this._drag={},cn.push({el:this,start:i}),this.mousedown(i);return this},cl.onDragOver=function(a){a?eve.on("raphael.drag.over."+this.id,a):eve.unbind("raphael.drag.over."+this.id)},cl.undrag=function(){var b=cn.length;while(b--)cn[b].el==this&&(this.unmousedown(cn[b].start),cn.splice(b,1),eve.unbind("raphael.drag.*."+this.id));!cn.length&&a.unmousemove(cj).unmouseup(ck)},k.circle=function(b,c,d){var e=a._engine.circle(this,b||0,c||0,d||0);this.__set__&&this.__set__.push(e);return e},k.rect=function(b,c,d,e,f){var g=a._engine.rect(this,b||0,c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.ellipse=function(b,c,d,e){var f=a._engine.ellipse(this,b||0,c||0,d||0,e||0);this.__set__&&this.__set__.push(f);return f},k.path=function(b){b&&!a.is(b,D)&&!a.is(b[0],E)&&(b+=p);var c=a._engine.path(a.format[m](a,arguments),this);this.__set__&&this.__set__.push(c);return c},k.image=function(b,c,d,e,f){var g=a._engine.image(this,b||"about:blank",c||0,d||0,e||0,f||0);this.__set__&&this.__set__.push(g);return g},k.text=function(b,c,d){var e=a._engine.text(this,b||0,c||0,r(d));this.__set__&&this.__set__.push(e);return e},k.set=function(b){!a.is(b,"array")&&(b=Array.prototype.splice.call(arguments,0,arguments.length));var c=new cG(b);this.__set__&&this.__set__.push(c);return c},k.setStart=function(a){this.__set__=a||this.set()},k.setFinish=function(a){var b=this.__set__;delete this.__set__;return b},k.setSize=function(b,c){return a._engine.setSize.call(this,b,c)},k.setViewBox=function(b,c,d,e,f){return a._engine.setViewBox.call(this,b,c,d,e,f)},k.top=k.bottom=null,k.raphael=a;var co=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,g=e.clientLeft||d.clientLeft||0,i=b.top+(h.win.pageYOffset||e.scrollTop||d.scrollTop)-f,j=b.left+(h.win.pageXOffset||e.scrollLeft||d.scrollLeft)-g;return{y:i,x:j}};k.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=h.doc.elementFromPoint(a,b);if(h.win.opera&&e.tagName=="svg"){var f=co(d),g=d.createSVGRect();g.x=a-f.x,g.y=b-f.y,g.width=g.height=1;var i=d.getIntersectionList(g,null);i.length&&(e=i[i.length-1])}if(!e)return null;while(e.parentNode&&e!=d.parentNode&&!e.raphael)e=e.parentNode;e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null;return e},k.getById=function(a){var b=this.bottom;while(b){if(b.id==a)return b;b=b.next}return null},k.forEach=function(a,b){var c=this.bottom;while(c){if(a.call(b,c)===!1)return this;c=c.next}return this},k.getElementsByPoint=function(a,b){var c=this.set();this.forEach(function(d){d.isPointInside(a,b)&&c.push(d)});return c},cl.isPointInside=function(b,c){var d=this.realPath=this.realPath||bi[this.type](this);return a.isPointInsidePath(d,b,c)},cl.getBBox=function(a){if(this.removed)return{};var b=this._;if(a){if(b.dirty||!b.bboxwt)this.realPath=bi[this.type](this),b.bboxwt=bI(this.realPath),b.bboxwt.toString=cq,b.dirty=0;return b.bboxwt}if(b.dirty||b.dirtyT||!b.bbox){if(b.dirty||!this.realPath)b.bboxwt=0,this.realPath=bi[this.type](this);b.bbox=bI(bj(this.realPath,this.matrix)),b.bbox.toString=cq,b.dirty=b.dirtyT=0}return b.bbox},cl.clone=function(){if(this.removed)return null;var a=this.paper[this.type]().attr(this.attr());this.__set__&&this.__set__.push(a);return a},cl.glow=function(a){if(this.type=="text")return null;a=a||{};var b={width:(a.width||10)+(+this.attr("stroke-width")||1),fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||"#000"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||bi[this.type](this);f=this.matrix?bj(f,this.matrix):f;for(var g=1;g<c+1;g++)e.push(d.path(f).attr({stroke:b.color,fill:b.fill?b.color:"none","stroke-linejoin":"round","stroke-linecap":"round","stroke-width":+(b.width/c*g).toFixed(3),opacity:+(b.opacity/c).toFixed(3)}));return e.insertBefore(this).translate(b.offsetx,b.offsety)};var cr={},cs=function(b,c,d,e,f,g,h,i,j){return j==null?bB(b,c,d,e,f,g,h,i):a.findDotsAtSegment(b,c,d,e,f,g,h,i,bC(b,c,d,e,f,g,h,i,j))},ct=function(b,c){return function(d,e,f){d=bR(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;o<p;o++){i=d[o];if(i[0]=="M")g=+i[1],h=+i[2];else{j=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6]);if(n+j>e){if(c&&!l.start){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),k+=["C"+m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k,k=["M"+m.x,m.y+"C"+m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!b&&!c){m=cs(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j,g=+i[5],h=+i[6]}k+=i.shift()+i}l.end=k,m=b?n:c?l:a.findDotsAtSegment(g,h,i[0],i[1],i[2],i[3],i[4],i[5],1),m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cu=ct(1),cv=ct(),cw=ct(0,1);a.getTotalLength=cu,a.getPointAtLength=cv,a.getSubpath=function(a,b,c){if(this.getTotalLength(a)-c<1e-6)return cw(a,b).end;var d=cw(a,c,1);return b?cw(d,b).end:d},cl.getTotalLength=function(){if(this.type=="path"){if(this.node.getTotalLength)return this.node.getTotalLength();return cu(this.attrs.path)}},cl.getPointAtLength=function(a){if(this.type=="path")return cv(this.attrs.path,a)},cl.getSubpath=function(b,c){if(this.type=="path")return a.getSubpath(this.attrs.path,b,c)};var cx=a.easing_formulas={linear:function(a){return a},"<":function(a){return A(a,1.7)},">":function(a){return A(a,.48)},"<>":function(a){var b=.48-a/1.04,c=w.sqrt(.1734+b*b),d=c-b,e=A(z(d),1/3)*(d<0?-1:1),f=-c-b,g=A(z(f),1/3)*(f<0?-1:1),h=e+g+.5;return(1-h)*3*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==!!a)return a;return A(2,-10*a)*w.sin((a-.075)*2*B/.3)+1},bounce:function(a){var b=7.5625,c=2.75,d;a<1/c?d=b*a*a:a<2/c?(a-=1.5/c,d=b*a*a+.75):a<2.5/c?(a-=2.25/c,d=b*a*a+.9375):(a-=2.625/c,d=b*a*a+.984375);return d}};cx.easeIn=cx["ease-in"]=cx["<"],cx.easeOut=cx["ease-out"]=cx[">"],cx.easeInOut=cx["ease-in-out"]=cx["<>"],cx["back-in"]=cx.backIn,cx["back-out"]=cx.backOut;var cy=[],cz=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,16)},cA=function(){var b=+(new Date),c=0;for(;c<cy.length;c++){var d=cy[c];if(d.el.removed||d.paused)continue;var e=b-d.start,f=d.ms,h=d.easing,i=d.from,j=d.diff,k=d.to,l=d.t,m=d.el,o={},p,r={},s;d.initstatus?(e=(d.initstatus*d.anim.top-d.prev)/(d.percent-d.prev)*f,d.status=d.initstatus,delete d.initstatus,d.stop&&cy.splice(c--,1)):d.status=(d.prev+(d.percent-d.prev)*(e/f))/d.anim.top;if(e<0)continue;if(e<f){var t=h(e/f);for(var u in i)if(i[g](u)){switch(U[u]){case C:p=+i[u]+t*f*j[u];break;case"colour":p="rgb("+[cB(O(i[u].r+t*f*j[u].r)),cB(O(i[u].g+t*f*j[u].g)),cB(O(i[u].b+t*f*j[u].b))].join(",")+")";break;case"path":p=[];for(var v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(var x=1,y=i[u][v].length;x<y;x++)p[v][x]=+i[u][v][x]+t*f*j[u][v][x];p[v]=p[v].join(q)}p=p.join(q);break;case"transform":if(j[u].real){p=[];for(v=0,w=i[u].length;v<w;v++){p[v]=[i[u][v][0]];for(x=1,y=i[u][v].length;x<y;x++)p[v][x]=i[u][v][x]+t*f*j[u][v][x]}}else{var z=function(a){return+i[u][a]+t*f*j[u][a]};p=[["m",z(0),z(1),z(2),z(3),z(4),z(5)]]}break;case"csv":if(u=="clip-rect"){p=[],v=4;while(v--)p[v]=+i[u][v]+t*f*j[u][v]}break;default:var A=[][n](i[u]);p=[],v=m.paper.customAttributes[u].length;while(v--)p[v]=+A[v]+t*f*j[u][v]}o[u]=p}m.attr(o),function(a,b,c){setTimeout(function(){eve("raphael.anim.frame."+a,b,c)})}(m.id,m,d.anim)}else{(function(b,c,d){setTimeout(function(){eve("raphael.anim.frame."+c.id,c,d),eve("raphael.anim.finish."+c.id,c,d),a.is(b,"function")&&b.call(c)})})(d.callback,m,d.anim),m.attr(k),cy.splice(c--,1);if(d.repeat>1&&!d.next){for(s in k)k[g](s)&&(r[s]=d.totalOrigin[s]);d.el.attr(r),cE(d.anim,d.el,d.anim.percents[0],null,d.totalOrigin,d.repeat-1)}d.next&&!d.stop&&cE(d.anim,d.el,d.next,null,d.totalOrigin,d.repeat)}}a.svg&&m&&m.paper&&m.paper.safari(),cy.length&&cz(cA)},cB=function(a){return a>255?255:a<0?0:a};cl.animateWith=function(b,c,d,e,f,g){var h=this;if(h.removed){g&&g.call(h);return h}var i=d instanceof cD?d:a.animation(d,e,f,g),j,k;cE(i,h,i.percents[0],null,h.attr());for(var l=0,m=cy.length;l<m;l++)if(cy[l].anim==c&&cy[l].el==b){cy[m-1].start=cy[l].start;break}return h},cl.onAnimation=function(a){a?eve.on("raphael.anim.frame."+this.id,a):eve.unbind("raphael.anim.frame."+this.id);return this},cD.prototype.delay=function(a){var b=new cD(this.anim,this.ms);b.times=this.times,b.del=+a||0;return b},cD.prototype.repeat=function(a){var b=new cD(this.anim,this.ms);b.del=this.del,b.times=w.floor(x(a,0))||1;return b},a.animation=function(b,c,d,e){if(b instanceof cD)return b;if(a.is(d,"function")||!d)e=e||d||null,d=null;b=Object(b),c=+c||0;var f={},h,i;for(i in b)b[g](i)&&Q(i)!=i&&Q(i)+"%"!=i&&(h=!0,f[i]=b[i]);if(!h)return new cD(b,c);d&&(f.easing=d),e&&(f.callback=e);return new cD({100:f},c)},cl.animate=function(b,c,d,e){var f=this;if(f.removed){e&&e.call(f);return f}var g=b instanceof cD?b:a.animation(b,c,d,e);cE(g,f,g.percents[0],null,f.attr());return f},cl.setTime=function(a,b){a&&b!=null&&this.status(a,y(b,a.ms)/a.ms);return this},cl.status=function(a,b){var c=[],d=0,e,f;if(b!=null){cE(a,this,-1,y(b,1));return this}e=cy.length;for(;d<e;d++){f=cy[d];if(f.el.id==this.id&&(!a||f.anim==a)){if(a)return f.status;c.push({anim:f.anim,status:f.status})}}if(a)return 0;return c},cl.pause=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve("raphael.anim.pause."+this.id,this,cy[b].anim)!==!1&&(cy[b].paused=!0);return this},cl.resume=function(a){for(var b=0;b<cy.length;b++)if(cy[b].el.id==this.id&&(!a||cy[b].anim==a)){var c=cy[b];eve("raphael.anim.resume."+this.id,this,c.anim)!==!1&&(delete c.paused,this.status(c.anim,c.status))}return this},cl.stop=function(a){for(var b=0;b<cy.length;b++)cy[b].el.id==this.id&&(!a||cy[b].anim==a)&&eve("raphael.anim.stop."+this.id,this,cy[b].anim)!==!1&&cy.splice(b--,1);return this},eve.on("raphael.remove",cF),eve.on("raphael.clear",cF),cl.toString=function(){return"Raphaël’s object"};var cG=function(a){this.items=[],this.length=0,this.type="set";if(a)for(var b=0,c=a.length;b<c;b++)a[b]&&(a[b].constructor==cl.constructor||a[b].constructor==cG)&&(this[this.items.length]=this.items[this.items.length]=a[b],this.length++)},cH=cG.prototype;cH.push=function(){var a,b;for(var c=0,d=arguments.length;c<d;c++)a=arguments[c],a&&(a.constructor==cl.constructor||a.constructor==cG)&&(b=this.items.length,this[b]=this.items[b]=a,this.length++);return this},cH.pop=function(){this.length&&delete this[this.length--];return this.items.pop()},cH.forEach=function(a,b){for(var c=0,d=this.items.length;c<d;c++)if(a.call(b,this.items[c],c)===!1)return this;return this};for(var cI in cl)cl[g](cI)&&(cH[cI]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a][m](c,b)})}}(cI));cH.attr=function(b,c){if(b&&a.is(b,E)&&a.is(b[0],"object"))for(var d=0,e=b.length;d<e;d++)this.items[d].attr(b[d]);else for(var f=0,g=this.items.length;f<g;f++)this.items[f].attr(b,c);return this},cH.clear=function(){while(this.length)this.pop()},cH.splice=function(a,b,c){a=a<0?x(this.length+a,0):a,b=x(0,y(this.length-a,b));var d=[],e=[],f=[],g;for(g=2;g<arguments.length;g++)f.push(arguments[g]);for(g=0;g<b;g++)e.push(this[a+g]);for(;g<this.length-a;g++)d.push(this[a+g]);var h=f.length;for(g=0;g<h+d.length;g++)this.items[a+g]=this[a+g]=g<h?f[g]:d[g-h];g=this.items.length=this.length-=b-h;while(this[g])delete this[g++];return new cG(e)},cH.exclude=function(a){for(var b=0,c=this.length;b<c;b++)if(this[b]==a){this.splice(b,1);return!0}},cH.animate=function(b,c,d,e){(a.is(d,"function")||!d)&&(e=d||null);var f=this.items.length,g=f,h,i=this,j;if(!f)return this;e&&(j=function(){!--f&&e.call(i)}),d=a.is(d,D)?d:j;var k=a.animation(b,c,d,j);h=this.items[--g].animate(k);while(g--)this.items[g]&&!this.items[g].removed&&this.items[g].animateWith(h,k,k);return this},cH.insertAfter=function(a){var b=this.items.length;while(b--)this.items[b].insertAfter(a);return this},cH.getBBox=function(){var a=[],b=[],c=[],d=[];for(var e=this.items.length;e--;)if(!this.items[e].removed){var f=this.items[e].getBBox();a.push(f.x),b.push(f.y),c.push(f.x+f.width),d.push(f.y+f.height)}a=y[m](0,a),b=y[m](0,b),c=x[m](0,c),d=x[m](0,d);return{x:a,y:b,x2:c,y2:d,width:c-a,height:d-b}},cH.clone=function(a){a=new cG;for(var b=0,c=this.items.length;b<c;b++)a.push(this.items[b].clone());return a},cH.toString=function(){return"Raphaël‘s set"},a.registerFont=function(a){if(!a.face)return a;this.fonts=this.fonts||{};var b={w:a.w,face:{},glyphs:{}},c=a.face["font-family"];for(var d in a.face)a.face[g](d)&&(b.face[d]=a.face[d]);this.fonts[c]?this.fonts[c].push(b):this.fonts[c]=[b];if(!a.svg){b.face["units-per-em"]=R(a.face["units-per-em"],10);for(var e in a.glyphs)if(a.glyphs[g](e)){var f=a.glyphs[e];b.glyphs[e]={w:f.w,k:{},d:f.d&&"M"+f.d.replace(/[mlcxtrv]/g,function(a){return{l:"L",c:"C",x:"z",t:"m",r:"l",v:"c"}[a]||"M"})+"z"};if(f.k)for(var h in f.k)f[g](h)&&(b.glyphs[e].k[h]=f.k[h])}}return a},k.getFont=function(b,c,d,e){e=e||"normal",d=d||"normal",c=+c||{normal:400,bold:700,lighter:300,bolder:800}[c]||400;if(!!a.fonts){var f=a.fonts[b];if(!f){var h=new RegExp("(^|\\s)"+b.replace(/[^\w\d\s+!~.:_-]/g,p)+"(\\s|$)","i");for(var i in a.fonts)if(a.fonts[g](i)&&h.test(i)){f=a.fonts[i];break}}var j;if(f)for(var k=0,l=f.length;k<l;k++){j=f[k];if(j.face["font-weight"]==c&&(j.face["font-style"]==d||!j.face["font-style"])&&j.face["font-stretch"]==e)break}return j}},k.print=function(b,d,e,f,g,h,i){h=h||"middle",i=x(y(i||0,1),-1);var j=r(e)[s](p),k=0,l=0,m=p,n;a.is(f,e)&&(f=this.getFont(f));if(f){n=(g||16)/f.face["units-per-em"];var o=f.face.bbox[s](c),q=+o[0],t=o[3]-o[1],u=0,v=+o[1]+(h=="baseline"?t+ +f.face.descent:t/2);for(var w=0,z=j.length;w<z;w++){if(j[w]=="\n")k=0,B=0,l=0,u+=t;else{var A=l&&f.glyphs[j[w-1]]||{},B=f.glyphs[j[w]];k+=l?(A.w||f.w)+(A.k&&A.k[j[w]]||0)+f.w*i:0,l=1}B&&B.d&&(m+=a.transformPath(B.d,["t",k*n,u*n,"s",n,n,q,v,"t",(b-q)/n,(d-v)/n]))}}return this.path(m).attr({fill:"#000",stroke:"none"})},k.add=function(b){if(a.is(b,"array")){var c=this.set(),e=0,f=b.length,h;for(;e<f;e++)h=b[e]||{},d[g](h.type)&&c.push(this[h.type]().attr(h))}return c},a.format=function(b,c){var d=a.is(c,E)?[0][n](c):arguments;b&&a.is(b,D)&&d.length-1&&(b=b.replace(e,function(a,b){return d[++b]==null?p:d[b]}));return b||p},a.fullfill=function(){var a=/\{([^\}]+)\}/g,b=/(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,c=function(a,c,d){var e=d;c.replace(b,function(a,b,c,d,f){b=b||d,e&&(b in e&&(e=e[b]),typeof e=="function"&&f&&(e=e()))}),e=(e==null||e==d?a:e)+"";return e};return function(b,d){return String(b).replace(a,function(a,b){return c(a,b,d)})}}(),a.ninja=function(){i.was?h.win.Raphael=i.is:delete Raphael;return a},a.st=cH,function(b,c,d){function e(){/in/.test(b.readyState)?setTimeout(e,9):a.eve("raphael.DOMload")}b.readyState==null&&b.addEventListener&&(b.addEventListener(c,d=function(){b.removeEventListener(c,d,!1),b.readyState="complete"},!1),b.readyState="loading"),e()}(document,"DOMContentLoaded"),i.was?h.win.Raphael=a:Raphael=a,eve.on("raphael.DOMload",function(){b=!0})}(),window.Raphael.svg&&function(a){var b="hasOwnProperty",c=String,d=parseFloat,e=parseInt,f=Math,g=f.max,h=f.abs,i=f.pow,j=/[, ]+/,k=a.eve,l="",m=" ",n="http://www.w3.org/1999/xlink",o={block:"M5,0 0,2.5 5,5z",classic:"M5,0 0,2.5 5,5 3.5,3 3.5,2z",diamond:"M2.5,0 5,2.5 2.5,5 0,2.5z",open:"M6,1 1,3.5 6,6",oval:"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"},p={};a.toString=function(){return"Your browser supports SVG.\nYou are running Raphaël "+this.version};var q=function(d,e){if(e){typeof d=="string"&&(d=q(d));for(var f in e)e[b](f)&&(f.substring(0,6)=="xlink:"?d.setAttributeNS(n,f.substring(6),c(e[f])):d.setAttribute(f,c(e[f])))}else d=a._g.doc.createElementNS("http://www.w3.org/2000/svg",d),d.style&&(d.style.webkitTapHighlightColor="rgba(0,0,0,0)");return d},r=function(b,e){var j="linear",k=b.id+e,m=.5,n=.5,o=b.node,p=b.paper,r=o.style,s=a._g.doc.getElementById(k);if(!s){e=c(e).replace(a._radial_gradient,function(a,b,c){j="radial";if(b&&c){m=d(b),n=d(c);var e=(n>.5)*2-1;i(m-.5,2)+i(n-.5,2)>.25&&(n=f.sqrt(.25-i(m-.5,2))*e+.5)&&n!=.5&&(n=n.toFixed(5)-1e-5*e)}return l}),e=e.split(/\s*\-\s*/);if(j=="linear"){var t=e.shift();t=-d(t);if(isNaN(t))return null;var u=[0,0,f.cos(a.rad(t)),f.sin(a.rad(t))],v=1/(g(h(u[2]),h(u[3]))||1);u[2]*=v,u[3]*=v,u[2]<0&&(u[0]=-u[2],u[2]=0),u[3]<0&&(u[1]=-u[3],u[3]=0)}var w=a._parseDots(e);if(!w)return null;k=k.replace(/[\(\)\s,\xb0#]/g,"_"),b.gradient&&k!=b.gradient.id&&(p.defs.removeChild(b.gradient),delete b.gradient);if(!b.gradient){s=q(j+"Gradient",{id:k}),b.gradient=s,q(s,j=="radial"?{fx:m,fy:n}:{x1:u[0],y1:u[1],x2:u[2],y2:u[3],gradientTransform:b.matrix.invert()}),p.defs.appendChild(s);for(var x=0,y=w.length;x<y;x++)s.appendChild(q("stop",{offset:w[x].offset?w[x].offset:x?"100%":"0%","stop-color":w[x].color||"#fff"}))}}q(o,{fill:"url(#"+k+")",opacity:1,"fill-opacity":1}),r.fill=l,r.opacity=1,r.fillOpacity=1;return 1},s=function(a){var b=a.getBBox(1);q(a.pattern,{patternTransform:a.matrix.invert()+" translate("+b.x+","+b.y+")"})},t=function(d,e,f){if(d.type=="path"){var g=c(e).toLowerCase().split("-"),h=d.paper,i=f?"end":"start",j=d.node,k=d.attrs,m=k["stroke-width"],n=g.length,r="classic",s,t,u,v,w,x=3,y=3,z=5;while(n--)switch(g[n]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":r=g[n];break;case"wide":y=5;break;case"narrow":y=2;break;case"long":x=5;break;case"short":x=2}r=="open"?(x+=2,y+=2,z+=2,u=1,v=f?4:1,w={fill:"none",stroke:k.stroke}):(v=u=x/2,w={fill:k.stroke,stroke:"none"}),d._.arrows?f?(d._.arrows.endPath&&p[d._.arrows.endPath]--,d._.arrows.endMarker&&p[d._.arrows.endMarker]--):(d._.arrows.startPath&&p[d._.arrows.startPath]--,d._.arrows.startMarker&&p[d._.arrows.startMarker]--):d._.arrows={};if(r!="none"){var A="raphael-marker-"+r,B="raphael-marker-"+i+r+x+y;a._g.doc.getElementById(A)?p[A]++:(h.defs.appendChild(q(q("path"),{"stroke-linecap":"round",d:o[r],id:A})),p[A]=1);var C=a._g.doc.getElementById(B),D;C?(p[B]++,D=C.getElementsByTagName("use")[0]):(C=q(q("marker"),{id:B,markerHeight:y,markerWidth:x,orient:"auto",refX:v,refY:y/2}),D=q(q("use"),{"xlink:href":"#"+A,transform:(f?"rotate(180 "+x/2+" "+y/2+") ":l)+"scale("+x/z+","+y/z+")","stroke-width":(1/((x/z+y/z)/2)).toFixed(4)}),C.appendChild(D),h.defs.appendChild(C),p[B]=1),q(D,w);var F=u*(r!="diamond"&&r!="oval");f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-F*m):(s=F*m,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),w={},w["marker-"+i]="url(#"+B+")";if(t||s)w.d=Raphael.getSubpath(k.path,s,t);q(j,w),d._.arrows[i+"Path"]=A,d._.arrows[i+"Marker"]=B,d._.arrows[i+"dx"]=F,d._.arrows[i+"Type"]=r,d._.arrows[i+"String"]=e}else f?(s=d._.arrows.startdx*m||0,t=a.getTotalLength(k.path)-s):(s=0,t=a.getTotalLength(k.path)-(d._.arrows.enddx*m||0)),d._.arrows[i+"Path"]&&q(j,{d:Raphael.getSubpath(k.path,s,t)}),delete d._.arrows[i+"Path"],delete d._.arrows[i+"Marker"],delete d._.arrows[i+"dx"],delete d._.arrows[i+"Type"],delete d._.arrows[i+"String"];for(w in p)if(p[b](w)&&!p[w]){var G=a._g.doc.getElementById(w);G&&G.parentNode.removeChild(G)}}},u={"":[0],none:[0],"-":[3,1],".":[1,1],"-.":[3,1,1,1],"-..":[3,1,1,1,1,1],". ":[1,3],"- ":[4,3],"--":[8,3],"- .":[4,3,1,3],"--.":[8,3,1,3],"--..":[8,3,1,3,1,3]},v=function(a,b,d){b=u[c(b).toLowerCase()];if(b){var e=a.attrs["stroke-width"]||"1",f={round:e,square:e,butt:0}[a.attrs["stroke-linecap"]||d["stroke-linecap"]]||0,g=[],h=b.length;while(h--)g[h]=b[h]*e+(h%2?1:-1)*f;q(a.node,{"stroke-dasharray":g.join(",")})}},w=function(d,f){var i=d.node,k=d.attrs,m=i.style.visibility;i.style.visibility="hidden";for(var o in f)if(f[b](o)){if(!a._availableAttrs[b](o))continue;var p=f[o];k[o]=p;switch(o){case"blur":d.blur(p);break;case"href":case"title":case"target":var u=i.parentNode;if(u.tagName.toLowerCase()!="a"){var w=q("a");u.insertBefore(w,i),w.appendChild(i),u=w}o=="target"?u.setAttributeNS(n,"show",p=="blank"?"new":p):u.setAttributeNS(n,o,p);break;case"cursor":i.style.cursor=p;break;case"transform":d.transform(p);break;case"arrow-start":t(d,p);break;case"arrow-end":t(d,p,1);break;case"clip-rect":var x=c(p).split(j);if(x.length==4){d.clip&&d.clip.parentNode.parentNode.removeChild(d.clip.parentNode);var z=q("clipPath"),A=q("rect");z.id=a.createUUID(),q(A,{x:x[0],y:x[1],width:x[2],height:x[3]}),z.appendChild(A),d.paper.defs.appendChild(z),q(i,{"clip-path":"url(#"+z.id+")"}),d.clip=A}if(!p){var B=i.getAttribute("clip-path");if(B){var C=a._g.doc.getElementById(B.replace(/(^url\(#|\)$)/g,l));C&&C.parentNode.removeChild(C),q(i,{"clip-path":l}),delete d.clip}}break;case"path":d.type=="path"&&(q(i,{d:p?k.path=a._pathToAbsolute(p):"M0,0"}),d._.dirty=1,d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1)));break;case"width":i.setAttribute(o,p),d._.dirty=1;if(k.fx)o="x",p=k.x;else break;case"x":k.fx&&(p=-k.x-(k.width||0));case"rx":if(o=="rx"&&d.type=="rect")break;case"cx":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"height":i.setAttribute(o,p),d._.dirty=1;if(k.fy)o="y",p=k.y;else break;case"y":k.fy&&(p=-k.y-(k.height||0));case"ry":if(o=="ry"&&d.type=="rect")break;case"cy":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"r":d.type=="rect"?q(i,{rx:p,ry:p}):i.setAttribute(o,p),d._.dirty=1;break;case"src":d.type=="image"&&i.setAttributeNS(n,"href",p);break;case"stroke-width":if(d._.sx!=1||d._.sy!=1)p/=g(h(d._.sx),h(d._.sy))||1;d.paper._vbSize&&(p*=d.paper._vbSize),i.setAttribute(o,p),k["stroke-dasharray"]&&v(d,k["stroke-dasharray"],f),d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"stroke-dasharray":v(d,p,f);break;case"fill":var D=c(p).match(a._ISURL);if(D){z=q("pattern");var F=q("image");z.id=a.createUUID(),q(z,{x:0,y:0,patternUnits:"userSpaceOnUse",height:1,width:1}),q(F,{x:0,y:0,"xlink:href":D[1]}),z.appendChild(F),function(b){a._preload(D[1],function(){var a=this.offsetWidth,c=this.offsetHeight;q(b,{width:a,height:c}),q(F,{width:a,height:c}),d.paper.safari()})}(z),d.paper.defs.appendChild(z),q(i,{fill:"url(#"+z.id+")"}),d.pattern=z,d.pattern&&s(d);break}var G=a.getRGB(p);if(!G.error)delete f.gradient,delete k.gradient,!a.is(k.opacity,"undefined")&&a.is(f.opacity,"undefined")&&q(i,{opacity:k.opacity}),!a.is(k["fill-opacity"],"undefined")&&a.is(f["fill-opacity"],"undefined")&&q(i,{"fill-opacity":k["fill-opacity"]});else if((d.type=="circle"||d.type=="ellipse"||c(p).charAt()!="r")&&r(d,p)){if("opacity"in k||"fill-opacity"in k){var H=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l));if(H){var I=H.getElementsByTagName("stop");q(I[I.length-1],{"stop-opacity":("opacity"in k?k.opacity:1)*("fill-opacity"in k?k["fill-opacity"]:1)})}}k.gradient=p,k.fill="none";break}G[b]("opacity")&&q(i,{"fill-opacity":G.opacity>1?G.opacity/100:G.opacity});case"stroke":G=a.getRGB(p),i.setAttribute(o,G.hex),o=="stroke"&&G[b]("opacity")&&q(i,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity}),o=="stroke"&&d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"gradient":(d.type=="circle"||d.type=="ellipse"||c(p).charAt()!="r")&&r(d,p);break;case"opacity":k.gradient&&!k[b]("stroke-opacity")&&q(i,{"stroke-opacity":p>1?p/100:p});case"fill-opacity":if(k.gradient){H=a._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l)),H&&(I=H.getElementsByTagName("stop"),q(I[I.length-1],{"stop-opacity":p}));break};default:o=="font-size"&&(p=e(p,10)+"px");var J=o.replace(/(\-.)/g,function(a){return a.substring(1).toUpperCase()});i.style[J]=p,d._.dirty=1,i.setAttribute(o,p)}}y(d,f),i.style.visibility=m},x=1.2,y=function(d,f){if(d.type=="text"&&!!(f[b]("text")||f[b]("font")||f[b]("font-size")||f[b]("x")||f[b]("y"))){var g=d.attrs,h=d.node,i=h.firstChild?e(a._g.doc.defaultView.getComputedStyle(h.firstChild,l).getPropertyValue("font-size"),10):10;if(f[b]("text")){g.text=f.text;while(h.firstChild)h.removeChild(h.firstChild);var j=c(f.text).split("\n"),k=[],m;for(var n=0,o=j.length;n<o;n++)m=q("tspan"),n&&q(m,{dy:i*x,x:g.x}),m.appendChild(a._g.doc.createTextNode(j[n])),h.appendChild(m),k[n]=m}else{k=h.getElementsByTagName("tspan");for(n=0,o=k.length;n<o;n++)n?q(k[n],{dy:i*x,x:g.x}):q(k[0],{dy:0})}q(h,{x:g.x,y:g.y}),d._.dirty=1;var p=d._getBBox(),r=g.y-(p.y+p.height/2);r&&a.is(r,"finite")&&q(k[0],{dy:r})}},z=function(b,c){var d=0,e=0;this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.matrix=a.matrix(),this.realPath=null,this.paper=c,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},A=a.el;z.prototype=A,A.constructor=z,a._engine.path=function(a,b){var c=q("path");b.canvas&&b.canvas.appendChild(c);var d=new z(c,b);d.type="path",w(d,{fill:"none",stroke:"#000",path:a});return d},A.rotate=function(a,b,e){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this.transform(this._.transform.concat([["r",a,b,e]]));return this},A.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3])),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]]));return this},A.translate=function(a,b){if(this.removed)return this;a=c(a).split(j),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this.transform(this._.transform.concat([["t",a,b]]));return this},A.transform=function(c){var d=this._;if(c==null)return d.transform;a._extractTransform(this,c),this.clip&&q(this.clip,{transform:this.matrix.invert()}),this.pattern&&s(this),this.node&&q(this.node,{transform:this.matrix});if(d.sx!=1||d.sy!=1){var e=this.attrs[b]("stroke-width")?this.attrs["stroke-width"]:1;this.attr({"stroke-width":e})}return this},A.hide=function(){!this.removed&&this.paper.safari(this.node.style.display="none");return this},A.show=function(){!this.removed&&this.paper.safari(this.node.style.display="");return this},A.remove=function(){if(!this.removed&&!!this.node.parentNode){var b=this.paper;b.__set__&&b.__set__.exclude(this),k.unbind("raphael.*.*."+this.id),this.gradient&&b.defs.removeChild(this.gradient),a._tear(this,b),this.node.parentNode.tagName.toLowerCase()=="a"?this.node.parentNode.parentNode.removeChild(this.node.parentNode):this.node.parentNode.removeChild(this.node);for(var c in this)this[c]=typeof this[c]=="function"?a._removedFactory(c):null;this.removed=!0}},A._getBBox=function(){if(this.node.style.display=="none"){this.show();var a=!0}var b={};try{b=this.node.getBBox()}catch(c){}finally{b=b||{}}a&&this.hide();return b},A.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill=="none"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,"string")){if(c=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;if(c=="transform")return this._.transform;var g=c.split(j),h={};for(var i=0,l=g.length;i<l;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return l-1?h:h[g[0]]}if(d==null&&a.is(c,"array")){h={};for(i=0,l=c.length;i<l;i++)h[c[i]]=this.attr(c[i]);return h}if(d!=null){var m={};m[c]=d}else c!=null&&a.is(c,"object")&&(m=c);for(var n in m)k("raphael.attr."+n+"."+this.id,this,m[n]);for(n in this.paper.customAttributes)if(this.paper.customAttributes[b](n)&&m[b](n)&&a.is(this.paper.customAttributes[n],"function")){var o=this.paper.customAttributes[n].apply(this,[].concat(m[n]));this.attrs[n]=m[n];for(var p in o)o[b](p)&&(m[p]=o[p])}w(this,m);return this},A.toFront=function(){if(this.removed)return this;this.node.parentNode.tagName.toLowerCase()=="a"?this.node.parentNode.parentNode.appendChild(this.node.parentNode):this.node.parentNode.appendChild(this.node);var b=this.paper;b.top!=this&&a._tofront(this,b);return this},A.toBack=function(){if(this.removed)return this;var b=this.node.parentNode;b.tagName.toLowerCase()=="a"?b.parentNode.insertBefore(this.node.parentNode,this.node.parentNode.parentNode.firstChild):b.firstChild!=this.node&&b.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper);var c=this.paper;return this},A.insertAfter=function(b){if(this.removed)return this;var c=b.node||b[b.length-1].node;c.nextSibling?c.parentNode.insertBefore(this.node,c.nextSibling):c.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},A.insertBefore=function(b){if(this.removed)return this;var c=b.node||b[0].node;c.parentNode.insertBefore(this.node,c),a._insertbefore(this,b,this.paper);return this},A.blur=function(b){var c=this;if(+b!==0){var d=q("filter"),e=q("feGaussianBlur");c.attrs.blur=b,d.id=a.createUUID(),q(e,{stdDeviation:+b||1.5}),d.appendChild(e),c.paper.defs.appendChild(d),c._blur=d,q(c.node,{filter:"url(#"+d.id+")"})}else c._blur&&(c._blur.parentNode.removeChild(c._blur),delete c._blur,delete c.attrs.blur),c.node.removeAttribute("filter")},a._engine.circle=function(a,b,c,d){var e=q("circle");a.canvas&&a.canvas.appendChild(e);var f=new z(e,a);f.attrs={cx:b,cy:c,r:d,fill:"none",stroke:"#000"},f.type="circle",q(e,f.attrs);return f},a._engine.rect=function(a,b,c,d,e,f){var g=q("rect");a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:b,y:c,width:d,height:e,r:f||0,rx:f||0,ry:f||0,fill:"none",stroke:"#000"},h.type="rect",q(g,h.attrs);return h},a._engine.ellipse=function(a,b,c,d,e){var f=q("ellipse");a.canvas&&a.canvas.appendChild(f);var g=new z(f,a);g.attrs={cx:b,cy:c,rx:d,ry:e,fill:"none",stroke:"#000"},g.type="ellipse",q(f,g.attrs);return g},a._engine.image=function(a,b,c,d,e,f){var g=q("image");q(g,{x:c,y:d,width:e,height:f,preserveAspectRatio:"none"}),g.setAttributeNS(n,"href",b),a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);h.attrs={x:c,y:d,width:e,height:f,src:b},h.type="image";return h},a._engine.text=function(b,c,d,e){var f=q("text");b.canvas&&b.canvas.appendChild(f);var g=new z(f,b);g.attrs={x:c,y:d,"text-anchor":"middle",text:e,font:a._availableAttrs.font,stroke:"none",fill:"#000"},g.type="text",w(g,g.attrs);return g},a._engine.setSize=function(a,b){this.width=a||this.width,this.height=b||this.height,this.canvas.setAttribute("width",this.width),this.canvas.setAttribute("height",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox);return this},a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b&&b.container,d=b.x,e=b.y,f=b.width,g=b.height;if(!c)throw new Error("SVG container not found.");var h=q("svg"),i="overflow:hidden;",j;d=d||0,e=e||0,f=f||512,g=g||342,q(h,{height:g,version:1.1,width:f,xmlns:"http://www.w3.org/2000/svg"}),c==1?(h.style.cssText=i+"position:absolute;left:"+d+"px;top:"+e+"px",a._g.doc.body.appendChild(h),j=1):(h.style.cssText=i+"position:relative",c.firstChild?c.insertBefore(h,c.firstChild):c.appendChild(h)),c=new a._Paper,c.width=f,c.height=g,c.canvas=h,c.clear(),c._left=c._top=0,j&&(c.renderfix=function(){}),c.renderfix();return c},a._engine.setViewBox=function(a,b,c,d,e){k("raphael.setViewBox",this,this._viewBox,[a,b,c,d,e]);var f=g(c/this.width,d/this.height),h=this.top,i=e?"meet":"xMinYMin",j,l;a==null?(this._vbSize&&(f=1),delete this._vbSize,j="0 0 "+this.width+m+this.height):(this._vbSize=f,j=a+m+b+m+c+m+d),q(this.canvas,{viewBox:j,preserveAspectRatio:i});while(f&&h)l="stroke-width"in h.attrs?h.attrs["stroke-width"]:1,h.attr({"stroke-width":l}),h._.dirty=1,h._.dirtyT=1,h=h.prev;this._viewBox=[a,b,c,d,!!e];return this},a.prototype.renderfix=function(){var a=this.canvas,b=a.style,c;try{c=a.getScreenCTM()||a.createSVGMatrix()}catch(d){c=a.createSVGMatrix()}var e=-c.e%1,f=-c.f%1;if(e||f)e&&(this._left=(this._left+e)%1,b.left=this._left+"px"),f&&(this._top=(this._top+f)%1,b.top=this._top+"px")},a.prototype.clear=function(){a.eve("raphael.clear",this);var b=this.canvas;while(b.firstChild)b.removeChild(b.firstChild);this.bottom=this.top=null,(this.desc=q("desc")).appendChild(a._g.doc.createTextNode("Created with Raphaël "+a.version)),b.appendChild(this.desc),b.appendChild(this.defs=q("defs"))},a.prototype.remove=function(){k("raphael.remove",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]=="function"?a._removedFactory(b):null};var B=a.st;for(var C in A)A[b](C)&&!B[b](C)&&(B[C]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(C))}(window.Raphael),window.Raphael.vml&&function(a){var b="hasOwnProperty",c=String,d=parseFloat,e=Math,f=e.round,g=e.max,h=e.min,i=e.abs,j="fill",k=/[, ]+/,l=a.eve,m=" progid:DXImageTransform.Microsoft",n=" ",o="",p={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},q=/([clmz]),?([^clmz]*)/gi,r=/ progid:\S+Blur\([^\)]+\)/g,s=/-?[^,\s-]+/g,t="position:absolute;left:0;top:0;width:1px;height:1px",u=21600,v={path:1,rect:1,image:1},w={circle:1,ellipse:1},x=function(b){var d=/[ahqstv]/ig,e=a._pathToAbsolute;c(b).match(d)&&(e=a._path2curve),d=/[clmz]/g;if(e==a._pathToAbsolute&&!c(b).match(d)){var g=c(b).replace(q,function(a,b,c){var d=[],e=b.toLowerCase()=="m",g=p[b];c.replace(s,function(a){e&&d.length==2&&(g+=d+p[b=="m"?"l":"L"],d=[]),d.push(f(a*u))});return g+d});return g}var h=e(b),i,j;g=[];for(var k=0,l=h.length;k<l;k++){i=h[k],j=h[k][0].toLowerCase(),j=="z"&&(j="x");for(var m=1,r=i.length;m<r;m++)j+=f(i[m]*u)+(m!=r-1?",":o);g.push(j)}return g.join(n)},y=function(b,c,d){var e=a.matrix();e.rotate(-b,.5,.5);return{dx:e.x(c,d),dy:e.y(c,d)}},z=function(a,b,c,d,e,f){var g=a._,h=a.matrix,k=g.fillpos,l=a.node,m=l.style,o=1,p="",q,r=u/b,s=u/c;m.visibility="hidden";if(!!b&&!!c){l.coordsize=i(r)+n+i(s),m.rotation=f*(b*c<0?-1:1);if(f){var t=y(f,d,e);d=t.dx,e=t.dy}b<0&&(p+="x"),c<0&&(p+=" y")&&(o=-1),m.flip=p,l.coordorigin=d*-r+n+e*-s;if(k||g.fillsize){var v=l.getElementsByTagName(j);v=v&&v[0],l.removeChild(v),k&&(t=y(f,h.x(k[0],k[1]),h.y(k[0],k[1])),v.position=t.dx*o+n+t.dy*o),g.fillsize&&(v.size=g.fillsize[0]*i(b)+n+g.fillsize[1]*i(c)),l.appendChild(v)}m.visibility="visible"}};a.toString=function(){return"Your browser doesn’t support SVG. Falling down to VML.\nYou are running Raphaël "+this.version};var A=function(a,b,d){var e=c(b).toLowerCase().split("-"),f=d?"end":"start",g=e.length,h="classic",i="medium",j="medium";while(g--)switch(e[g]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":h=e[g];break;case"wide":case"narrow":j=e[g];break;case"long":case"short":i=e[g]}var k=a.node.getElementsByTagName("stroke")[0];k[f+"arrow"]=h,k[f+"arrowlength"]=i,k[f+"arrowwidth"]=j},B=function(e,i){e.attrs=e.attrs||{};var l=e.node,m=e.attrs,p=l.style,q,r=v[e.type]&&(i.x!=m.x||i.y!=m.y||i.width!=m.width||i.height!=m.height||i.cx!=m.cx||i.cy!=m.cy||i.rx!=m.rx||i.ry!=m.ry||i.r!=m.r),s=w[e.type]&&(m.cx!=i.cx||m.cy!=i.cy||m.r!=i.r||m.rx!=i.rx||m.ry!=i.ry),t=e;for(var y in i)i[b](y)&&(m[y]=i[y]);r&&(m.path=a._getPath[e.type](e),e._.dirty=1),i.href&&(l.href=i.href),i.title&&(l.title=i.title),i.target&&(l.target=i.target),i.cursor&&(p.cursor=i.cursor),"blur"in i&&e.blur(i.blur);if(i.path&&e.type=="path"||r)l.path=x(~c(m.path).toLowerCase().indexOf("r")?a._pathToAbsolute(m.path):m.path),e.type=="image"&&(e._.fillpos=[m.x,m.y],e._.fillsize=[m.width,m.height],z(e,1,1,0,0,0));"transform"in i&&e.transform(i.transform);if(s){var B=+m.cx,D=+m.cy,E=+m.rx||+m.r||0,G=+m.ry||+m.r||0;l.path=a.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x",f((B-E)*u),f((D-G)*u),f((B+E)*u),f((D+G)*u),f(B*u))}if("clip-rect"in i){var H=c(i["clip-rect"]).split(k);if(H.length==4){H[2]=+H[2]+ +H[0],H[3]=+H[3]+ +H[1];var I=l.clipRect||a._g.doc.createElement("div"),J=I.style;J.clip=a.format("rect({1}px {2}px {3}px {0}px)",H),l.clipRect||(J.position="absolute",J.top=0,J.left=0,J.width=e.paper.width+"px",J.height=e.paper.height+"px",l.parentNode.insertBefore(I,l),I.appendChild(l),l.clipRect=I)}i["clip-rect"]||l.clipRect&&(l.clipRect.style.clip="auto")}if(e.textpath){var K=e.textpath.style;i.font&&(K.font=i.font),i["font-family"]&&(K.fontFamily='"'+i["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g,o)+'"'),i["font-size"]&&(K.fontSize=i["font-size"]),i["font-weight"]&&(K.fontWeight=i["font-weight"]),i["font-style"]&&(K.fontStyle=i["font-style"])}"arrow-start"in i&&A(t,i["arrow-start"]),"arrow-end"in i&&A(t,i["arrow-end"],1);if(i.opacity!=null||i["stroke-width"]!=null||i.fill!=null||i.src!=null||i.stroke!=null||i["stroke-width"]!=null||i["stroke-opacity"]!=null||i["fill-opacity"]!=null||i["stroke-dasharray"]!=null||i["stroke-miterlimit"]!=null||i["stroke-linejoin"]!=null||i["stroke-linecap"]!=null){var L=l.getElementsByTagName(j),M=!1;L=L&&L[0],!L&&(M=L=F(j)),e.type=="image"&&i.src&&(L.src=i.src),i.fill&&(L.on=!0);if(L.on==null||i.fill=="none"||i.fill===null)L.on=!1;if(L.on&&i.fill){var N=c(i.fill).match(a._ISURL);if(N){L.parentNode==l&&l.removeChild(L),L.rotate=!0,L.src=N[1],L.type="tile";var O=e.getBBox(1);L.position=O.x+n+O.y,e._.fillpos=[O.x,O.y],a._preload(N[1],function(){e._.fillsize=[this.offsetWidth,this.offsetHeight]})}else L.color=a.getRGB(i.fill).hex,L.src=o,L.type="solid",a.getRGB(i.fill).error&&(t.type in{circle:1,ellipse:1}||c(i.fill).charAt()!="r")&&C(t,i.fill,L)&&(m.fill="none",m.gradient=i.fill,L.rotate=!1)}if("fill-opacity"in i||"opacity"in i){var P=((+m["fill-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+a.getRGB(i.fill).o+1||2)-1);P=h(g(P,0),1),L.opacity=P,L.src&&(L.color="none")}l.appendChild(L);var Q=l.getElementsByTagName("stroke")&&l.getElementsByTagName("stroke")[0],T=!1;!Q&&(T=Q=F("stroke"));if(i.stroke&&i.stroke!="none"||i["stroke-width"]||i["stroke-opacity"]!=null||i["stroke-dasharray"]||i["stroke-miterlimit"]||i["stroke-linejoin"]||i["stroke-linecap"])Q.on=!0;(i.stroke=="none"||i.stroke===null||Q.on==null||i.stroke==0||i["stroke-width"]==0)&&(Q.on=!1);var U=a.getRGB(i.stroke);Q.on&&i.stroke&&(Q.color=U.hex),P=((+m["stroke-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+U.o+1||2)-1);var V=(d(i["stroke-width"])||1)*.75;P=h(g(P,0),1),i["stroke-width"]==null&&(V=m["stroke-width"]),i["stroke-width"]&&(Q.weight=V),V&&V<1&&(P*=V)&&(Q.weight=1),Q.opacity=P,i["stroke-linejoin"]&&(Q.joinstyle=i["stroke-linejoin"]||"miter"),Q.miterlimit=i["stroke-miterlimit"]||8,i["stroke-linecap"]&&(Q.endcap=i["stroke-linecap"]=="butt"?"flat":i["stroke-linecap"]=="square"?"square":"round");if(i["stroke-dasharray"]){var W={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};Q.dashstyle=W[b](i["stroke-dasharray"])?W[i["stroke-dasharray"]]:o}T&&l.appendChild(Q)}if(t.type=="text"){t.paper.canvas.style.display=o;var X=t.paper.span,Y=100,Z=m.font&&m.font.match(/\d+(?:\.\d*)?(?=px)/);p=X.style,m.font&&(p.font=m.font),m["font-family"]&&(p.fontFamily=m["font-family"]),m["font-weight"]&&(p.fontWeight=m["font-weight"]),m["font-style"]&&(p.fontStyle=m["font-style"]),Z=d(m["font-size"]||Z&&Z[0])||10,p.fontSize=Z*Y+"px",t.textpath.string&&(X.innerHTML=c(t.textpath.string).replace(/</g,"&#60;").replace(/&/g,"&#38;").replace(/\n/g,"<br>"));var $=X.getBoundingClientRect();t.W=m.w=($.right-$.left)/Y,t.H=m.h=($.bottom-$.top)/Y,t.X=m.x,t.Y=m.y+t.H/2,("x"in i||"y"in i)&&(t.path.v=a.format("m{0},{1}l{2},{1}",f(m.x*u),f(m.y*u),f(m.x*u)+1));var _=["x","y","text","font","font-family","font-weight","font-style","font-size"];for(var ba=0,bb=_.length;ba<bb;ba++)if(_[ba]in i){t._.dirty=1;break}switch(m["text-anchor"]){case"start":t.textpath.style["v-text-align"]="left",t.bbx=t.W/2;break;case"end":t.textpath.style["v-text-align"]="right",t.bbx=-t.W/2;break;default:t.textpath.style["v-text-align"]="center",t.bbx=0}t.textpath.style["v-text-kern"]=!0}},C=function(b,f,g){b.attrs=b.attrs||{};var h=b.attrs,i=Math.pow,j,k,l="linear",m=".5 .5";b.attrs.gradient=f,f=c(f).replace(a._radial_gradient,function(a,b,c){l="radial",b&&c&&(b=d(b),c=d(c),i(b-.5,2)+i(c-.5,2)>.25&&(c=e.sqrt(.25-i(b-.5,2))*((c>.5)*2-1)+.5),m=b+n+c);return o}),f=f.split(/\s*\-\s*/);if(l=="linear"){var p=f.shift();p=-d(p);if(isNaN(p))return null}var q=a._parseDots(f);if(!q)return null;b=b.shape||b.node;if(q.length){b.removeChild(g),g.on=!0,g.method="none",g.color=q[0].color,g.color2=q[q.length-1].color;var r=[];for(var s=0,t=q.length;s<t;s++)q[s].offset&&r.push(q[s].offset+n+q[s].color);g.colors=r.length?r.join():"0% "+g.color,l=="radial"?(g.type="gradientTitle",g.focus="100%",g.focussize="0 0",g.focusposition=m,g.angle=0):(g.type="gradient",g.angle=(270-p)%360),b.appendChild(g)}return 1},D=function(b,c){this[0]=this.node=b,b.raphael=!0,this.id=a._oid++,b.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=c,this.matrix=a.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!c.bottom&&(c.bottom=this),this.prev=c.top,c.top&&(c.top.next=this),c.top=this,this.next=null},E=a.el;D.prototype=E,E.constructor=D,E.transform=function(b){if(b==null)return this._.transform;var d=this.paper._viewBoxShift,e=d?"s"+[d.scale,d.scale]+"-1-1t"+[d.dx,d.dy]:o,f;d&&(f=b=c(b).replace(/\.{3}|\u2026/g,this._.transform||o)),a._extractTransform(this,e+b);var g=this.matrix.clone(),h=this.skew,i=this.node,j,k=~c(this.attrs.fill).indexOf("-"),l=!c(this.attrs.fill).indexOf("url(");g.translate(-0.5,-0.5);if(l||k||this.type=="image"){h.matrix="1 0 0 1",h.offset="0 0",j=g.split();if(k&&j.noRotation||!j.isSimple){i.style.filter=g.toFilter();var m=this.getBBox(),p=this.getBBox(1),q=m.x-p.x,r=m.y-p.y;i.coordorigin=q*-u+n+r*-u,z(this,1,1,q,r,0)}else i.style.filter=o,z(this,j.scalex,j.scaley,j.dx,j.dy,j.rotate)}else i.style.filter=o,h.matrix=c(g),h.offset=g.offset();f&&(this._.transform=f);return this},E.rotate=function(a,b,e){if(this.removed)return this;if(a!=null){a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2])),a=d(a[0]),e==null&&(b=e);if(b==null||e==null){var f=this.getBBox(1);b=f.x+f.width/2,e=f.y+f.height/2}this._.dirtyT=1,this.transform(this._.transform.concat([["r",a,b,e]]));return this}},E.translate=function(a,b){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1])),a=d(a[0])||0,b=+b||0,this._.bbox&&(this._.bbox.x+=a,this._.bbox.y+=b),this.transform(this._.transform.concat([["t",a,b]]));return this},E.scale=function(a,b,e,f){if(this.removed)return this;a=c(a).split(k),a.length-1&&(b=d(a[1]),e=d(a[2]),f=d(a[3]),isNaN(e)&&(e=null),isNaN(f)&&(f=null)),a=d(a[0]),b==null&&(b=a),f==null&&(e=f);if(e==null||f==null)var g=this.getBBox(1);e=e==null?g.x+g.width/2:e,f=f==null?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,b,e,f]])),this._.dirtyT=1;return this},E.hide=function(){!this.removed&&(this.node.style.display="none");return this},E.show=function(){!this.removed&&(this.node.style.display=o);return this},E._getBBox=function(){if(this.removed)return{};return{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}},E.remove=function(){if(!this.removed&&!!this.node.parentNode){this.paper.__set__&&this.paper.__set__.exclude(this),a.eve.unbind("raphael.*.*."+this.id),a._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var b in this)this[b]=typeof this[b]=="function"?a._removedFactory(b):null;this.removed=!0}},E.attr=function(c,d){if(this.removed)return this;if(c==null){var e={};for(var f in this.attrs)this.attrs[b](f)&&(e[f]=this.attrs[f]);e.gradient&&e.fill=="none"&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform;return e}if(d==null&&a.is(c,"string")){if(c==j&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;var g=c.split(k),h={};for(var i=0,m=g.length;i<m;i++)c=g[i],c in this.attrs?h[c]=this.attrs[c]:a.is(this.paper.customAttributes[c],"function")?h[c]=this.paper.customAttributes[c].def:h[c]=a._availableAttrs[c];return m-1?h:h[g[0]]}if(this.attrs&&d==null&&a.is(c,"array")){h={};for(i=0,m=c.length;i<m;i++)h[c[i]]=this.attr(c[i]);return h}var n;d!=null&&(n={},n[c]=d),d==null&&a.is(c,"object")&&(n=c);for(var o in n)l("raphael.attr."+o+"."+this.id,this,n[o]);if(n){for(o in this.paper.customAttributes)if(this.paper.customAttributes[b](o)&&n[b](o)&&a.is(this.paper.customAttributes[o],"function")){var p=this.paper.customAttributes[o].apply(this,[].concat(n[o]));this.attrs[o]=n[o];for(var q in p)p[b](q)&&(n[q]=p[q])}n.text&&this.type=="text"&&(this.textpath.string=n.text),B(this,n)}return this},E.toFront=function(){!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&a._tofront(this,this.paper);return this},E.toBack=function(){if(this.removed)return this;this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),a._toback(this,this.paper));return this},E.insertAfter=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[b.length-1]),b.node.nextSibling?b.node.parentNode.insertBefore(this.node,b.node.nextSibling):b.node.parentNode.appendChild(this.node),a._insertafter(this,b,this.paper);return this},E.insertBefore=function(b){if(this.removed)return this;b.constructor==a.st.constructor&&(b=b[0]),b.node.parentNode.insertBefore(this.node,b.node),a._insertbefore(this,b,this.paper);return this},E.blur=function(b){var c=this.node.runtimeStyle,d=c.filter;d=d.replace(r,o),+b!==0?(this.attrs.blur=b,c.filter=d+n+m+".Blur(pixelradius="+(+b||1.5)+")",c.margin=a.format("-{0}px 0 0 -{0}px",f(+b||1.5))):(c.filter=d,c.margin=0,delete this.attrs.blur)},a._engine.path=function(a,b){var c=F("shape");c.style.cssText=t,c.coordsize=u+n+u,c.coordorigin=b.coordorigin;var d=new D(c,b),e={fill:"none",stroke:"#000"};a&&(e.path=a),d.type="path",d.path=[],d.Path=o,B(d,e),b.canvas.appendChild(c);var f=F("skew");f.on=!0,c.appendChild(f),d.skew=f,d.transform(o);return d},a._engine.rect=function(b,c,d,e,f,g){var h=a._rectPath(c,d,e,f,g),i=b.path(h),j=i.attrs;i.X=j.x=c,i.Y=j.y=d,i.W=j.width=e,i.H=j.height=f,j.r=g,j.path=h,i.type="rect";return i},a._engine.ellipse=function(a,b,c,d,e){var f=a.path(),g=f.attrs;f.X=b-d,f.Y=c-e,f.W=d*2,f.H=e*2,f.type="ellipse",B(f,{cx:b,cy:c,rx:d,ry:e});return f},a._engine.circle=function(a,b,c,d){var e=a.path(),f=e.attrs;e.X=b-d,e.Y=c-d,e.W=e.H=d*2,e.type="circle",B(e,{cx:b,cy:c,r:d});return e},a._engine.image=function(b,c,d,e,f,g){var h=a._rectPath(d,e,f,g),i=b.path(h).attr({stroke:"none"}),k=i.attrs,l=i.node,m=l.getElementsByTagName(j)[0];k.src=c,i.X=k.x=d,i.Y=k.y=e,i.W=k.width=f,i.H=k.height=g,k.path=h,i.type="image",m.parentNode==l&&l.removeChild(m),m.rotate=!0,m.src=c,m.type="tile",i._.fillpos=[d,e],i._.fillsize=[f,g],l.appendChild(m),z(i,1,1,0,0,0);return i},a._engine.text=function(b,d,e,g){var h=F("shape"),i=F("path"),j=F("textpath");d=d||0,e=e||0,g=g||"",i.v=a.format("m{0},{1}l{2},{1}",f(d*u),f(e*u),f(d*u)+1),i.textpathok=!0,j.string=c(g),j.on=!0,h.style.cssText=t,h.coordsize=u+n+u,h.coordorigin="0 0";var k=new D(h,b),l={fill:"#000",stroke:"none",font:a._availableAttrs.font,text:g};k.shape=h,k.path=i,k.textpath=j,k.type="text",k.attrs.text=c(g),k.attrs.x=d,k.attrs.y=e,k.attrs.w=1,k.attrs.h=1,B(k,l),h.appendChild(j),h.appendChild(i),b.canvas.appendChild(h);var m=F("skew");m.on=!0,h.appendChild(m),k.skew=m,k.transform(o);return k},a._engine.setSize=function(b,c){var d=this.canvas.style;this.width=b,this.height=c,b==+b&&(b+="px"),c==+c&&(c+="px"),d.width=b,d.height=c,d.clip="rect(0 "+b+" "+c+" 0)",this._viewBox&&a._engine.setViewBox.apply(this,this._viewBox);return this},a._engine.setViewBox=function(b,c,d,e,f){a.eve("raphael.setViewBox",this,this._viewBox,[b,c,d,e,f]);var h=this.width,i=this.height,j=1/g(d/h,e/i),k,l;f&&(k=i/e,l=h/d,d*k<h&&(b-=(h-d*k)/2/k),e*l<i&&(c-=(i-e*l)/2/l)),this._viewBox=[b,c,d,e,!!f],this._viewBoxShift={dx:-b,dy:-c,scale:j},this.forEach(function(a){a.transform("...")});return this};var F;a._engine.initWin=function(a){var b=a.document;b.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{!b.namespaces.rvml&&b.namespaces.add("rvml","urn:schemas-microsoft-com:vml"),F=function(a){return b.createElement("<rvml:"+a+' class="rvml">')}}catch(c){F=function(a){return b.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}},a._engine.initWin(a._g.win),a._engine.create=function(){var b=a._getContainer.apply(0,arguments),c=b.container,d=b.height,e,f=b.width,g=b.x,h=b.y;if(!c)throw new Error("VML container not found.");var i=new a._Paper,j=i.canvas=a._g.doc.createElement("div"),k=j.style;g=g||0,h=h||0,f=f||512,d=d||342,i.width=f,i.height=d,f==+f&&(f+="px"),d==+d&&(d+="px"),i.coordsize=u*1e3+n+u*1e3,i.coordorigin="0 0",i.span=a._g.doc.createElement("span"),i.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;",j.appendChild(i.span),k.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d),c==1?(a._g.doc.body.appendChild(j),k.left=g+"px",k.top=h+"px",k.position="absolute"):c.firstChild?c.insertBefore(j,c.firstChild):c.appendChild(j),i.renderfix=function(){};return i},a.prototype.clear=function(){a.eve("raphael.clear",this),this.canvas.innerHTML=o,this.span=a._g.doc.createElement("span"),this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;",this.canvas.appendChild(this.span),this.bottom=this.top=null},a.prototype.remove=function(){a.eve("raphael.remove",this),this.canvas.parentNode.removeChild(this.canvas);for(var b in this)this[b]=typeof this[b]=="function"?a._removedFactory(b):null;return!0};var G=a.st;for(var H in E)E[b](H)&&!G[b](H)&&(G[H]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(H))}(window.Raphael)
js/scripts.js CHANGED
@@ -3,20 +3,18 @@ jQuery(document).ready(
3
  function ab_flag_spam() {
4
  var $$ = $('#ab_flag_spam'),
5
  nextAll = $$.parent('li').nextAll();
6
-
7
  nextAll.css(
8
  'visibility',
9
  ( $$.is(':checked') ? 'visible' : 'hidden' )
10
  );
11
  }
12
-
13
-
14
  $('#ab_flag_spam').on(
15
  'change',
16
  ab_flag_spam
17
  );
18
-
19
-
20
  ab_flag_spam();
21
  }
22
  );
3
  function ab_flag_spam() {
4
  var $$ = $('#ab_flag_spam'),
5
  nextAll = $$.parent('li').nextAll();
6
+
7
  nextAll.css(
8
  'visibility',
9
  ( $$.is(':checked') ? 'visible' : 'hidden' )
10
  );
11
  }
12
+
 
13
  $('#ab_flag_spam').on(
14
  'change',
15
  ab_flag_spam
16
  );
17
+
 
18
  ab_flag_spam();
19
  }
20
  );
lang/antispam_bee-de_DE.mo CHANGED
Binary file
lang/antispam_bee-de_DE.po CHANGED
@@ -39,8 +39,8 @@ msgstr "CSS Hack"
39
  msgid "Server IP"
40
  msgstr "Server IP"
41
 
42
- msgid "Spam IP"
43
- msgstr "Spam IP"
44
 
45
  msgid "Comment Language"
46
  msgstr "Sprache"
@@ -51,6 +51,9 @@ msgstr "Ländercode"
51
  msgid "DNSBL Spam"
52
  msgstr "DNSBL Spam"
53
 
 
 
 
54
  msgid "Approve it"
55
  msgstr "Freigeben"
56
 
@@ -84,9 +87,6 @@ msgstr "Simples, äußerst effektives Plugin zur Bekämpfung von Spam-Kommentare
84
  msgid "http://antispambee.com"
85
  msgstr "http://antispambee.de"
86
 
87
- msgid "Antispam Bee requires WordPress 3.4 and PHP 5.1.2"
88
- msgstr "Antispam Bee setzt WordPress 3.4 und PHP 5.1.2 voraus"
89
-
90
  msgid "Comments"
91
  msgstr "Kommentare"
92
 
@@ -125,11 +125,17 @@ msgstr "Genehmigten Kommentatoren vertrauen"
125
  msgid "No check for already commenting users"
126
  msgstr "Keine Prüfung bereits kommentierender Nutzer"
127
 
 
 
 
 
 
 
128
  msgid "Use a public antispam database"
129
  msgstr "Öffentliche Spamdatenbank berücksichtigen"
130
 
131
- msgid "Matching the ip address with"
132
- msgstr "Abgleich der IP-Adresse mit"
133
 
134
  msgid "Validate the ip address of commentators"
135
  msgstr "IP-Adresse des Kommentators validieren"
@@ -137,6 +143,12 @@ msgstr "IP-Adresse des Kommentators validieren"
137
  msgid "Validity check for used ip address"
138
  msgstr "Kontrolle auf Gültigkeit verwendeter Kennung"
139
 
 
 
 
 
 
 
140
  msgid "Look in the local spam database"
141
  msgstr "Lokale Spamdatenbank einbeziehen"
142
 
@@ -174,11 +186,11 @@ msgstr "Bei Spam via E-Mail informieren"
174
  msgid "Sending an alert to the admin"
175
  msgstr "Versand der Benachrichtigung an den Admin"
176
 
177
- msgid "Not store the reason in the comment body"
178
- msgstr "Spamgrund im Kommentar nicht speichern"
179
 
180
- msgid "Filter name as reason for current suspicion"
181
- msgstr "Zugeschlagener Filter als Verdachtsgrund"
182
 
183
  msgid "Delete existing spam after %s days"
184
  msgstr "Vorhandenen Spam nach %s Tagen löschen"
39
  msgid "Server IP"
40
  msgstr "Server IP"
41
 
42
+ msgid "Local DB Spam"
43
+ msgstr "Lokale Spamdatenbank"
44
 
45
  msgid "Comment Language"
46
  msgstr "Sprache"
51
  msgid "DNSBL Spam"
52
  msgstr "DNSBL Spam"
53
 
54
+ msgid "RegExp"
55
+ msgstr "Regulärer Ausdruck"
56
+
57
  msgid "Approve it"
58
  msgstr "Freigeben"
59
 
87
  msgid "http://antispambee.com"
88
  msgstr "http://antispambee.de"
89
 
 
 
 
90
  msgid "Comments"
91
  msgstr "Kommentare"
92
 
125
  msgid "No check for already commenting users"
126
  msgstr "Keine Prüfung bereits kommentierender Nutzer"
127
 
128
+ msgid "BBCode is spam"
129
+ msgstr "BBCode als Spam einstufen"
130
+
131
+ msgid "Review the comment contents for BBCode links"
132
+ msgstr "Analyse der Kommentarinhalte auf BBCode-Links"
133
+
134
  msgid "Use a public antispam database"
135
  msgstr "Öffentliche Spamdatenbank berücksichtigen"
136
 
137
+ msgid "Matching the ip address with <a href=\"https://dnsbl.tornevall.org\" target=\"_blank\">Tornevall</a>"
138
+ msgstr "Beachte den <a href=\"http://playground.ebiene.de/antispam-bee-wordpress-plugin/#dnsbl_check\" target=\"_blank\">Datenschutzhinweis</a> für die Option"
139
 
140
  msgid "Validate the ip address of commentators"
141
  msgstr "IP-Adresse des Kommentators validieren"
143
  msgid "Validity check for used ip address"
144
  msgstr "Kontrolle auf Gültigkeit verwendeter Kennung"
145
 
146
+ msgid "Use regular expressions"
147
+ msgstr "Reguläre Ausdrücke anwenden"
148
+
149
+ msgid "Predefined and custom patterns by <a href=\"https://gist.github.com/4242142\" target=\"_blank\">plugin hook</a>"
150
+ msgstr "Vordefinierte und eigene Muster via <a href=\"http://playground.ebiene.de/antispam-bee-wordpress-plugin/#regexp_check\" target=\"_blank\">Plugin-Hook</a>"
151
+
152
  msgid "Look in the local spam database"
153
  msgstr "Lokale Spamdatenbank einbeziehen"
154
 
186
  msgid "Sending an alert to the admin"
187
  msgstr "Versand der Benachrichtigung an den Admin"
188
 
189
+ msgid "Not save the spam reason"
190
+ msgstr "Spamgrund zum Kommentar nicht speichern"
191
 
192
+ msgid "Spam reason as table column in the spam overview"
193
+ msgstr "Verdachtsgrund-Spalte in der Spam-Übersicht"
194
 
195
  msgid "Delete existing spam after %s days"
196
  msgstr "Vorhandenen Spam nach %s Tagen löschen"
lang/antispam_bee-fr_FR.mo ADDED
Binary file
lang/antispam_bee-fr_FR.po ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Antispam Bee\n"
4
+ "POT-Creation-Date: \n"
5
+ "PO-Revision-Date: \n"
6
+ "Last-Translator: Sergej Müller\n"
7
+ "Language-Team: Sergej Müller\n"
8
+ "Language: fr_FR\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=utf-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Poedit-SourceCharset: utf-8\n"
13
+ "X-Poedit-KeywordsList: __;_e\n"
14
+ "X-Poedit-Basepath: .\n"
15
+ "X-Generator: Poedit 1.5.7\n"
16
+ "X-Poedit-SearchPath-0: .\n"
17
+
18
+ msgid "No data available."
19
+ msgstr "Aucune donnée disponible."
20
+
21
+ msgid "New spam comment on your post"
22
+ msgstr "Nouveau spam sur l'article"
23
+
24
+ msgid "Comment"
25
+ msgstr "Commentaire"
26
+
27
+ msgid "Type"
28
+ msgstr "Type"
29
+
30
+ msgid "Spam Reason"
31
+ msgstr "Raison de détection"
32
+
33
+ msgid "Empty Data"
34
+ msgstr "Pas de données"
35
+
36
+ msgid "CSS Hack"
37
+ msgstr "Hack CSS"
38
+
39
+ msgid "Server IP"
40
+ msgstr "IP du serveur"
41
+
42
+ msgid "Local DB Spam"
43
+ msgstr "Spam BD locale"
44
+
45
+ msgid "Comment Language"
46
+ msgstr "Langue du commentaire"
47
+
48
+ msgid "Country Check"
49
+ msgstr "Vérification du pays"
50
+
51
+ msgid "DNSBL Spam"
52
+ msgstr "Spam DNSBL"
53
+
54
+ msgid "RegExp"
55
+ msgstr "Expression régulière"
56
+
57
+ msgid "Approve it"
58
+ msgstr "Approuver"
59
+
60
+ msgid "Delete it"
61
+ msgstr "Supprimer"
62
+
63
+ msgid "Trash it"
64
+ msgstr "Dans la corbeille"
65
+
66
+ msgid "Spam list"
67
+ msgstr "Liste des spams"
68
+
69
+ msgid "Notify message by Antispam Bee"
70
+ msgstr "Message de notification par Antispam Bee"
71
+
72
+ msgid "Content removed by Antispam Bee"
73
+ msgstr "Contenu supprimé par Antispam Bee"
74
+
75
+ msgid "Last check"
76
+ msgstr "Dernière vérification"
77
+
78
+ msgid "Blocked"
79
+ msgstr "Bloqué"
80
+
81
+ msgid "Today"
82
+ msgstr "Aujourd'hui"
83
+
84
+ msgid "Easy and extremely productive spam-fighting plugin with many sophisticated solutions. Includes protection again trackback spam."
85
+ msgstr "Extension simple et très efficace pour lutter contre les commentaires indésirables comportant des solutions sophistiquées. Inclus une protection contre le spam trackback."
86
+
87
+ msgid "http://antispambee.com"
88
+ msgstr "http://antispambee.com"
89
+
90
+ msgid "Comments"
91
+ msgstr "Commentaires"
92
+
93
+ msgid "Comment marked as spam"
94
+ msgstr "Commentaire marqué comme spam"
95
+
96
+ # Langues
97
+ msgid "Language"
98
+ msgstr "Langue"
99
+
100
+ msgid "English"
101
+ msgstr "Anglais"
102
+
103
+ msgid "German"
104
+ msgstr "Allemand"
105
+
106
+ msgid "French"
107
+ msgstr "Français"
108
+
109
+ msgid "Italian"
110
+ msgstr "Italien"
111
+
112
+ msgid "Spanish"
113
+ msgstr "Espagnol"
114
+
115
+ # Antispam-Filter
116
+ msgid "Antispam filter"
117
+ msgstr "Filtre antispam"
118
+
119
+ msgid "Filter in the execution order"
120
+ msgstr "Ordre d'exécution du filtrage"
121
+
122
+ msgid "Trust approved commentators"
123
+ msgstr "Faire confiance aux commentateurs approuvés"
124
+
125
+ msgid "No check for already commenting users"
126
+ msgstr "Pas de vérification pour utilisateurs connus"
127
+
128
+ msgid "BBCode is spam"
129
+ msgstr "Le BBCode est considéré comme spam"
130
+
131
+ msgid "Review the comment contents for BBCode links"
132
+ msgstr "Rechercher les liens BBCode dans le commentaire"
133
+
134
+ msgid "Use a public antispam database"
135
+ msgstr "Banque de données de spams publique"
136
+
137
+ msgid "Matching the ip address with <a href=\"https://dnsbl.tornevall.org\" target=\"_blank\">Tornevall</a>"
138
+ msgstr "Correspondance de l'IP en utilisant <a href=\"https://dnsbl.tornevall.org\" target=\"_blank\">Tornevall</a>"
139
+
140
+ msgid "Validate the ip address of commentators"
141
+ msgstr "Valider l'adresse IP des commentateurs"
142
+
143
+ msgid "Validity check for used ip address"
144
+ msgstr "Vérification de la validité pour les IP utilisées"
145
+
146
+ msgid "Use regular expressions"
147
+ msgstr "Utiliser des expressions régulières"
148
+
149
+ msgid "Predefined and custom patterns by <a href=\"https://gist.github.com/4242142\" target=\"_blank\">plugin hook</a>"
150
+ msgstr "Motifs prédéfinis et personnalisés par le <a href=\"https://gist.github.com/4242142\" target=\"_blank\">plugin hook</a>"
151
+
152
+ msgid "Look in the local spam database"
153
+ msgstr "Vérifier dans la base de données locale des spams"
154
+
155
+ msgid "Already marked as spam? Yes? No?"
156
+ msgstr "Le spam a-t-il déjà été reconnu ?"
157
+
158
+ msgid "Block comments from specific countries"
159
+ msgstr "Bloquer selon le pays"
160
+
161
+ msgid "Filtering the requests depending on country"
162
+ msgstr "Filtrage selon le pays d'origine du commentaire"
163
+
164
+ msgid "Allow comments only in certain language"
165
+ msgstr "N'accepter des commentaires qu'en une langue"
166
+
167
+ msgid "Detection and approval in specified language"
168
+ msgstr "Détection et autorisation d'une langue spécifiée"
169
+
170
+ # Erweitert
171
+ msgid "Advanced"
172
+ msgstr "Avancé"
173
+
174
+ msgid "Other antispam tools"
175
+ msgstr "Autres outils antispam"
176
+
177
+ msgid "Mark as spam, do not delete"
178
+ msgstr "Marquer comme spam et ne pas supprimer"
179
+
180
+ msgid "Keep the spam in my blog."
181
+ msgstr "Conserver le commentaire indésirable"
182
+
183
+ msgid "Notification by email"
184
+ msgstr "Notification par courriel"
185
+
186
+ msgid "Sending an alert to the admin"
187
+ msgstr "Avertir l'administrateur par courriel"
188
+
189
+ msgid "Not save the spam reason"
190
+ msgstr "Ne pas stocker la raison de détection"
191
+
192
+ msgid "Spam reason as table column in the spam overview"
193
+ msgstr "Raison dans la colonne du tableau d'aperçu"
194
+
195
+ msgid "Delete existing spam after %s days"
196
+ msgstr "Supprimer les spams après %s jours"
197
+
198
+ msgid "Cleaning up the database from old entries"
199
+ msgstr "Nettoyage de la base de données"
200
+
201
+ msgid "Limit on %s"
202
+ msgstr "Limiter aux %s"
203
+
204
+ msgid "Another type of spam will be deleted immediately"
205
+ msgstr "Autre type de spam supprimé immédiatemment"
206
+
207
+ msgid "Delete comments by spam reasons"
208
+ msgstr "Supprimer les commentaires selon détection"
209
+
210
+ msgid "Multiple choice by pressing Ctrl/CMD"
211
+ msgstr "Choix multiples en maintenant la touche Ctrl/CMD"
212
+
213
+ # Sonstiges
214
+ msgid "More"
215
+ msgstr "Plus"
216
+
217
+ msgid "A few little things"
218
+ msgstr "Options moins significatives"
219
+
220
+ msgid "Statistics on the dashboard"
221
+ msgstr "Statistiques sur le tableau de bord"
222
+
223
+ msgid "Spam detection rate with daily values"
224
+ msgstr "Taux de détection de spam avec valeurs quotidiennes"
225
+
226
+ msgid "Spam counter on the dashboard"
227
+ msgstr "Compteur de spam sur le tableau de bord"
228
+
229
+ msgid "Amount of identified spam comments"
230
+ msgstr "Nombre de commentaires indésirables identifiés"
231
+
232
+ msgid "Do not check trackbacks / pingbacks"
233
+ msgstr "Ignorer les trackbacks et pingbacks"
234
+
235
+ msgid "No spam check for trackback notifications"
236
+ msgstr "Pas de spam pour les notifications de trackback"
237
+
238
+ msgid "Comment form used outside of posts"
239
+ msgstr "Commentaires présents dans les archives"
240
+
241
+ msgid "Check for comment forms on archive pages"
242
+ msgstr "Vérification des commentaires dans les archives"
243
+
244
+ #~ msgid "Marked as spam by Antispam Bee / Spam reason"
245
+ #~ msgstr "Marqué comme spam par Antispam Bee / Raison du spam"
246
+
247
+ #~ msgid "Spam IP"
248
+ #~ msgstr "IP du spam"
249
+
250
+ #~ msgid "Not store the reason in the comment body"
251
+ #~ msgstr "Ne pas sauvegarder la raison du spam"
252
+
253
+ #~ msgid "Filter name as reason for current suspicion"
254
+ #~ msgstr "Filtre utilisé considéré comme raison du spam"
lang/antispam_bee-ru_RU.mo CHANGED
Binary file
lang/antispam_bee-ru_RU.po CHANGED
@@ -3,8 +3,8 @@ msgstr ""
3
  "Project-Id-Version: Antispam Bee\n"
4
  "Report-Msgid-Bugs-To: \n"
5
  "POT-Creation-Date: 2012-11-21 22:20+0300\n"
6
- "PO-Revision-Date: 2012-11-21 23:27+0300\n"
7
- "Last-Translator: Andrey Ananin\n"
8
  "Language-Team: Andrey Ananin\n"
9
  "Language: \n"
10
  "MIME-Version: 1.0\n"
@@ -24,8 +24,8 @@ msgid "Settings"
24
  msgstr "Настройки"
25
 
26
  #: ../antispam_bee.php:472
27
- msgid "Antispam Bee requires WordPress 3.4 and PHP 5.1.2"
28
- msgstr "Для работы Antispam Bee требуются WordPress 3.4 и PHP 5.1.2"
29
 
30
  #: ../antispam_bee.php:651
31
  msgid "Blocked"
@@ -108,13 +108,19 @@ msgstr "Доверять одобренным комментаторам"
108
  msgid "No check for already commenting users"
109
  msgstr "Не проверять для пользов. с коммент."
110
 
 
 
 
 
 
 
111
  #: ../inc/gui.class.php:215
112
  msgid "Use a public antispam database"
113
  msgstr "Использовать общую БД антиспама"
114
 
115
  #: ../inc/gui.class.php:216
116
- msgid "Matching the ip address with"
117
- msgstr "Проверять IP-адрес в"
118
 
119
  #: ../inc/gui.class.php:223
120
  msgid "Validate the ip address of commentators"
3
  "Project-Id-Version: Antispam Bee\n"
4
  "Report-Msgid-Bugs-To: \n"
5
  "POT-Creation-Date: 2012-11-21 22:20+0300\n"
6
+ "PO-Revision-Date: 2013-12-20 11:18+0100\n"
7
+ "Last-Translator: Sergej Müller\n"
8
  "Language-Team: Andrey Ananin\n"
9
  "Language: \n"
10
  "MIME-Version: 1.0\n"
24
  msgstr "Настройки"
25
 
26
  #: ../antispam_bee.php:472
27
+ msgid "Antispam Bee requires WordPress 3.4 and PHP 5.2.4"
28
+ msgstr "Для работы Antispam Bee требуются WordPress 3.4 и PHP 5.2.4"
29
 
30
  #: ../antispam_bee.php:651
31
  msgid "Blocked"
108
  msgid "No check for already commenting users"
109
  msgstr "Не проверять для пользов. с коммент."
110
 
111
+ msgid "BBCode is spam"
112
+ msgstr "BBCod это спам"
113
+
114
+ msgid "Review the comment contents for BBCode links"
115
+ msgstr "Просматривание коммент. на BBCode ссылки"
116
+
117
  #: ../inc/gui.class.php:215
118
  msgid "Use a public antispam database"
119
  msgstr "Использовать общую БД антиспама"
120
 
121
  #: ../inc/gui.class.php:216
122
+ msgid "Matching the ip address with <a href=\"https://dnsbl.tornevall.org\" target=\"_blank\">Tornevall</a>"
123
+ msgstr "Проверять IP-адрес в <a href=\"https://dnsbl.tornevall.org\" target=\"_blank\">Tornevall</a>"
124
 
125
  #: ../inc/gui.class.php:223
126
  msgid "Validate the ip address of commentators"
lang/antispam_bee-sl_SI.mo ADDED
Binary file
lang/antispam_bee-sl_SI.po ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Antispam Bee\n"
4
+ "POT-Creation-Date: \n"
5
+ "PO-Revision-Date: 2014-01-29 15:19+0100\n"
6
+ "Last-Translator: Sergej Müller\n"
7
+ "Language-Team: ARNES\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=utf-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Poedit-Language: Slovenian\n"
12
+ "X-Poedit-Country: SLOVENIA\n"
13
+ "X-Poedit-SourceCharset: utf-8\n"
14
+ "X-Poedit-KeywordsList: __;_e\n"
15
+ "X-Poedit-Basepath: .\n"
16
+ "X-Poedit-SearchPath-0: .\n"
17
+
18
+ msgid "No data available."
19
+ msgstr "Ni podatkov."
20
+
21
+ msgid "New spam comment on your post"
22
+ msgstr "Nova nezaželena vsebina na vašem prispevku"
23
+
24
+ msgid "Comment"
25
+ msgstr "Komentar"
26
+
27
+ msgid "Type"
28
+ msgstr "Tip"
29
+
30
+ msgid "Spam Reason"
31
+ msgstr "Vzrok nezaželene oglasne vsebine"
32
+
33
+ msgid "Empty Data"
34
+ msgstr "Prazna vsebina"
35
+
36
+ msgid "CSS Hack"
37
+ msgstr "CSS vdor"
38
+
39
+ msgid "Server IP"
40
+ msgstr "IP naslov strežnika"
41
+
42
+ msgid "Local DB Spam"
43
+ msgstr "Lokalna zbirka podatkov nezaželene vsebine"
44
+
45
+ msgid "Comment Language"
46
+ msgstr "Jezik komentarja"
47
+
48
+ msgid "Country Check"
49
+ msgstr "Preverba države"
50
+
51
+ msgid "DNSBL Spam"
52
+ msgstr "Nezaželena vsebina DNSBL"
53
+
54
+ msgid "RegExp"
55
+ msgstr "Regularni izraz"
56
+
57
+ msgid "Approve it"
58
+ msgstr "Potrdi"
59
+
60
+ msgid "Delete it"
61
+ msgstr "Izbriši"
62
+
63
+ msgid "Trash it"
64
+ msgstr "Premakni v smeti"
65
+
66
+ msgid "Spam list"
67
+ msgstr "Seznam nezaželene vsebine"
68
+
69
+ msgid "Notify message by Antispam Bee"
70
+ msgstr "Antispam Bee obvestilo"
71
+
72
+ msgid "Content removed by Antispam Bee"
73
+ msgstr "Antispam Bee je odstranil vsebino"
74
+
75
+ msgid "Last check"
76
+ msgstr "Zadnja preverba"
77
+
78
+ msgid "Blocked"
79
+ msgstr "Onemogočenih"
80
+
81
+ msgid "Today"
82
+ msgstr "Danes"
83
+
84
+ msgid "Easy and extremely productive spam-fighting plugin with many sophisticated solutions. Includes protection again trackback spam."
85
+ msgstr "Preprost, napreden in izjemno učinkovit vtičnik v boju proti nezaželeni oglasni vsebini (spam)."
86
+
87
+ msgid "http://antispambee.com"
88
+ msgstr "http://antispambee.com"
89
+
90
+ msgid "Comments"
91
+ msgstr "Komentarji"
92
+
93
+ msgid "Comment marked as spam"
94
+ msgstr "Komentar označen kot nezaželena vsebina"
95
+
96
+ # Sprachen
97
+ msgid "Language"
98
+ msgstr "Jezik"
99
+
100
+ msgid "English"
101
+ msgstr "Angleščina"
102
+
103
+ msgid "German"
104
+ msgstr "Nemščina"
105
+
106
+ msgid "French"
107
+ msgstr "Francoščina"
108
+
109
+ msgid "Italian"
110
+ msgstr "Italijanščina"
111
+
112
+ msgid "Spanish"
113
+ msgstr "Španščina"
114
+
115
+ # Antispam-Filter
116
+ msgid "Antispam filter"
117
+ msgstr "Pravila Antispam"
118
+
119
+ msgid "Filter in the execution order"
120
+ msgstr "Filtri v vrstnem redu izvrševanja"
121
+
122
+ msgid "Trust approved commentators"
123
+ msgstr "Zaupanja vredni komentatorji"
124
+
125
+ msgid "No check for already commenting users"
126
+ msgstr "Ne preverjaj avtorjev, ki so že komentirali"
127
+
128
+ msgid "BBCode is spam"
129
+ msgstr "Obravnavaj kodo BBCode kot nezaželeo vsebino"
130
+
131
+ msgid "Review the comment contents for BBCode links"
132
+ msgstr "Preveri vsebino komentarjev, če vsebujejo povezave BBCode"
133
+
134
+ msgid "Use a public antispam database"
135
+ msgstr "Uporabi javno podatkovno zbirko z nezaželeno vsebino"
136
+
137
+ msgid "Matching the ip address with <a href=\"https://dnsbl.tornevall.org\" target=\"_blank\">Tornevall</a>"
138
+ msgstr "IP naslov preveri v podatkovni bazi <a href=\"https://dnsbl.tornevall.org\" target=\"_blank\">Tornevall</a>"
139
+
140
+ msgid "Validate the ip address of commentators"
141
+ msgstr "Preveri veljavnost naslovov IP komentatorjev"
142
+
143
+ msgid "Validity check for used ip address"
144
+ msgstr "Preverjanje veljavnosti uporabljenih naslovov IP"
145
+
146
+ msgid "Use regular expressions"
147
+ msgstr "Uporabi regularne izraze"
148
+
149
+ msgid "Predefined and custom patterns by <a href=\"https://gist.github.com/4242142\" target=\"_blank\">plugin hook</a>"
150
+ msgstr "Vnaprej pripravljeni in lastni vzorci prek <a href=\"https://gist.github.com/4242142\" target=\"_blank\">vtičnika</a>"
151
+
152
+ msgid "Look in the local spam database"
153
+ msgstr "Uporabi lokalno podatkovno zbirko"
154
+
155
+ msgid "Already marked as spam? Yes? No?"
156
+ msgstr "Išči v zbriki lastnega spletišča"
157
+
158
+ msgid "Block comments from specific countries"
159
+ msgstr "Onemogoči komentarje iz določenih držav"
160
+
161
+ msgid "Filtering the requests depending on country"
162
+ msgstr "Filtriranje zahtevkov glede na državo izvora"
163
+
164
+ msgid "Allow comments only in certain language"
165
+ msgstr "Dovoli komentarje v zgolj določenih jezikih"
166
+
167
+ msgid "Detection and approval in specified language"
168
+ msgstr "Zaznavanje in odobritev v določenem jeziku"
169
+
170
+ # Erweitert
171
+ msgid "Advanced"
172
+ msgstr "Napredne nastavitve"
173
+
174
+ msgid "Other antispam tools"
175
+ msgstr "Dodatna orodja proti nezaželeni vsebini"
176
+
177
+ msgid "Mark as spam, do not delete"
178
+ msgstr "Le označi kot nezaželeno, ne izbriši"
179
+
180
+ msgid "Keep the spam in my blog."
181
+ msgstr "Obdrži nezaželeno vzebino na spletišču"
182
+
183
+ msgid "Notification by email"
184
+ msgstr "Pošlji obvestilo ob prejetju neželene vsebine"
185
+
186
+ msgid "Sending an alert to the admin"
187
+ msgstr "Pošiljanje obvestil administratorju"
188
+
189
+ msgid "Not save the spam reason"
190
+ msgstr "Razlog za izbris komentarja"
191
+
192
+ msgid "Spam reason as table column in the spam overview"
193
+ msgstr "Prikaži razlog v pregledu nezaželene vsebino"
194
+
195
+ msgid "Delete existing spam after %s days"
196
+ msgstr "Neželeno vsebino izbriši čez %s dni"
197
+
198
+ msgid "Cleaning up the database from old entries"
199
+ msgstr "Izbris starih vnosov iz podatkovne zbirke"
200
+
201
+ msgid "Limit on %s"
202
+ msgstr "Omejitev velja le za %s"
203
+
204
+ msgid "Another type of spam will be deleted immediately"
205
+ msgstr "Ostala nezaželena vsebina bo izbrisana takoj"
206
+
207
+ msgid "Delete comments by spam reasons"
208
+ msgstr "Pri vnaprej določenih pogojih izbriši takoj"
209
+
210
+ msgid "Multiple choice by pressing Ctrl/CMD"
211
+ msgstr "S CTRL lahko izberete tudi več pogojev"
212
+
213
+ # Sonstiges
214
+ msgid "More"
215
+ msgstr "Ostale nastavitve"
216
+
217
+ msgid "A few little things"
218
+ msgstr "Manj pomembne nastavitve"
219
+
220
+ msgid "Statistics on the dashboard"
221
+ msgstr "Prikaz statistike na Nadzorni plošči"
222
+
223
+ msgid "Spam detection rate with daily values"
224
+ msgstr "Prikaz prepoznane vsebine na dnevni ravni"
225
+
226
+ msgid "Spam counter on the dashboard"
227
+ msgstr "Prikaz števca nezaželene vsebine na Nadzorni plošči"
228
+
229
+ msgid "Amount of identified spam comments"
230
+ msgstr "Količina prepoznane nezaželene vsebine"
231
+
232
+ msgid "Do not check trackbacks / pingbacks"
233
+ msgstr "Ne preverjaj povratnih sledi/pingbackov"
234
+
235
+ msgid "No spam check for trackback notifications"
236
+ msgstr "Ne preverjaj obvestil o povratnih sledeh"
237
+
238
+ msgid "Comment form used outside of posts"
239
+ msgstr "Komentarji so omogočeni tudi izven prispevkov"
240
+
241
+ msgid "Check for comment forms on archive pages"
242
+ msgstr "Preverjanje komentarjev na arhiviranih straneh"
243
+
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: sergej.mueller
3
  Tags: antispam, spam, comments, trackback
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RDDW9FEHGLG6
5
- Requires at least: 3.4
6
- Tested up to: 3.5
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -18,9 +18,6 @@ Say Goodbye zu Spam in deinem Blog. Kostenlos, werbefrei und datenschutzkonform.
18
 
19
  Blog-Spam bekämpfen ist die Stärke von *Antispam Bee*. Seit Jahren wird das Plugin darauf trainiert, Spam-Kommentare zuverlässig zu erkennen (auf Wunsch auch sofort zu beseitigen). Dabei greift *Antispam Bee* auf unterschiedliche Techniken zu, die sich zur Identifizierung von Spam-Nachrichten bewährt haben.
20
 
21
- Im Vergleich zum - für die meisten Blogger kostenpflichtigen - Plugin Akismet, überträgt *Antispam Bee* keine Blog- und Kommentardaten an einen entfernten Server. Ob ein Kommentar böswillig ist, entscheidet das kostenlose Plugin vor Ort im heimischen Blog. Hierfür stehen dem Nutzer zahlreiche Funktionen zur Verfügung, die per Mausklick ein- und abgeschaltet werden können.
22
-
23
- Als Unterstützung der Erkennung greift *Antispam Bee* auf eine öffentlich zugängliche und seit mehreren Jahren gepflegte [Datenbank](http://opm.tornevall.org) mit aktuellen Spammer-Referenzen zu. Anhand der IP-Adresse des Kommentators kann schnell und unbürokratisch entschieden werden, ob der Kommentar-Absender ein in der Welt bekannter Spam-Vertreiber ist. Aber auch dieser Filter kann im Antispam-Plugin jedezeit deaktiviert werden.
24
 
25
  = Pluspunkte =
26
  * Aktive Weiterentwicklung seit 2009
@@ -33,19 +30,23 @@ Als Unterstützung der Erkennung greift *Antispam Bee* auf eine öffentlich zug
33
  * Alle Funktionen vom Nutzer steuerbar
34
  * Statistik der letzten 30 Tage als Dashboard-Widget
35
 
 
36
  = Einstellungen =
37
  Nach der Aktivierung nimmt *Antispam Bee* den regulären Betrieb auf, indem vordefinierte Schutzmechanismen scharf geschaltet werden. Es empfiehlt sich jedoch, die Seite mit Plugin-Einstellungen aufzurufen und sich mit wirkungsvollen Optionen auseinander zu setzen. Alle Optionsschalter sind in der [Online-Dokumentation](http://playground.ebiene.de/antispam-bee-wordpress-plugin/) detailliert vorgestellt.
38
 
39
  Die meisten Auswahlmöglichkeiten innerhalb der Optionsseite sind konfigurierbare Antispam-Filter, die der Blog-Administrator nach Bedarf aktiviert. Zahlreiche Wahlmöglichkeiten steuern hingegen die Benachrichtigungs- und die automatische Löschfunktion des Plugins. Die *Antispam Bee* Optionen in der Kurzfassung:
40
 
41
  * Genehmigten Kommentatoren vertrauen
42
- * Öffentliche Spamdatenbank berücksichtigen
43
  * IP-Adresse des Kommentators validieren
 
44
  * Lokale Spamdatenbank einbeziehen
 
45
  * Bestimmte Länder blockieren bzw. erlauben
46
  * Kommentare nur in einer Sprache zulassen
47
  * Erkannten Spam kennzeichnen, nicht löschen
48
  * Bei Spam via E-Mail informieren
 
49
  * Spamgrund im Kommentar nicht speichern
50
  * Vorhandenen Spam nach X Tagen löschen
51
  * Aufbewahrung der Spam-Kommentare für einen Typ
@@ -55,30 +56,116 @@ Die meisten Auswahlmöglichkeiten innerhalb der Optionsseite sind konfigurierbar
55
  * Eingehende Ping- und Trackbacks ignorieren
56
  * Kommentarformular befindet sich auf Archivseiten
57
 
58
- Installiert, probiert die bewährte Antispam-Lösung für WordPress aus. Anmeldefrei und ohne lästige Captchas.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  = Unterstützung =
61
- * Per [Flattr](https://flattr.com/donation/give/to/sergej.mueller)
62
  * Per [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RDDW9FEHGLG6)
63
 
64
- = Systemanforderungen =
65
- * PHP 5.1.2
66
- * WordPress 3.4
67
 
68
- = Dokumentation =
69
  * [Antispam Bee: Antispam für WordPress](http://playground.ebiene.de/antispam-bee-wordpress-plugin/)
70
 
 
 
 
 
 
71
  = Autor =
72
- * [Google+](https://plus.google.com/110569673423509816572 "Google+")
73
- * [Plugins](http://wpcoder.de "Plugins")
 
 
 
74
 
75
- = Inkompatibilität =
76
- * Disqus
77
- * Jetpack Comments
78
 
79
 
80
  == Changelog ==
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  = 2.4.5 =
83
  * Überarbeitetes Layout der Einstellungen
84
  * Streichung von Project Honey Pot
2
  Contributors: sergej.mueller
3
  Tags: antispam, spam, comments, trackback
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RDDW9FEHGLG6
5
+ Requires at least: 3.8
6
+ Tested up to: 3.9
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
18
 
19
  Blog-Spam bekämpfen ist die Stärke von *Antispam Bee*. Seit Jahren wird das Plugin darauf trainiert, Spam-Kommentare zuverlässig zu erkennen (auf Wunsch auch sofort zu beseitigen). Dabei greift *Antispam Bee* auf unterschiedliche Techniken zu, die sich zur Identifizierung von Spam-Nachrichten bewährt haben.
20
 
 
 
 
21
 
22
  = Pluspunkte =
23
  * Aktive Weiterentwicklung seit 2009
30
  * Alle Funktionen vom Nutzer steuerbar
31
  * Statistik der letzten 30 Tage als Dashboard-Widget
32
 
33
+
34
  = Einstellungen =
35
  Nach der Aktivierung nimmt *Antispam Bee* den regulären Betrieb auf, indem vordefinierte Schutzmechanismen scharf geschaltet werden. Es empfiehlt sich jedoch, die Seite mit Plugin-Einstellungen aufzurufen und sich mit wirkungsvollen Optionen auseinander zu setzen. Alle Optionsschalter sind in der [Online-Dokumentation](http://playground.ebiene.de/antispam-bee-wordpress-plugin/) detailliert vorgestellt.
36
 
37
  Die meisten Auswahlmöglichkeiten innerhalb der Optionsseite sind konfigurierbare Antispam-Filter, die der Blog-Administrator nach Bedarf aktiviert. Zahlreiche Wahlmöglichkeiten steuern hingegen die Benachrichtigungs- und die automatische Löschfunktion des Plugins. Die *Antispam Bee* Optionen in der Kurzfassung:
38
 
39
  * Genehmigten Kommentatoren vertrauen
40
+ * BBCode als Spam einstufen
41
  * IP-Adresse des Kommentators validieren
42
+ * Reguläre Ausdrücke anwenden
43
  * Lokale Spamdatenbank einbeziehen
44
+ * Öffentliche Spamdatenbank berücksichtigen
45
  * Bestimmte Länder blockieren bzw. erlauben
46
  * Kommentare nur in einer Sprache zulassen
47
  * Erkannten Spam kennzeichnen, nicht löschen
48
  * Bei Spam via E-Mail informieren
49
+ * Optionale Logdatei mit Spam-Einträgen z.B. für [Fail2Ban](http://cup.wpcoder.de/fail2ban-ip-firewall/)
50
  * Spamgrund im Kommentar nicht speichern
51
  * Vorhandenen Spam nach X Tagen löschen
52
  * Aufbewahrung der Spam-Kommentare für einen Typ
56
  * Eingehende Ping- und Trackbacks ignorieren
57
  * Kommentarformular befindet sich auf Archivseiten
58
 
59
+
60
+ = Datenschutz =
61
+ In Blogs innerhalb der EU-Länder darf die Option *"Öffentliche Spamdatenbank berücksichtigen"* nicht aktiviert werden, da das Antispam-Plugin ungekürzte IP-Adressen der Kommentatoren dafür verwendet, diese in der öffentlichen Spammer-Datenbank nachzuschlagen und als Spam zu identifizieren. Technisch ist die Verschlüsselung der IP nicht möglich, da Spammer-Datenbanken mit vollständigen, unverschlüsselten IP-Adressen arbeiten. [Weitere Details](http://playground.ebiene.de/antispam-bee-wordpress-plugin/#dnsbl_check)
62
+
63
+
64
+ = Schlusswort =
65
+ Installiert, probiert die bewährte Antispam-Lösung für WordPress aus.
66
+ Anmeldefrei und ohne lästige Captchas.
67
+
68
+
69
+ = Support =
70
+ Freundlich formulierte Fragen rund um das Plugin werden per E-Mail beantwortet.
71
+
72
+
73
+ = Systemanforderungen =
74
+ * PHP 5.2.4
75
+ * WordPress 3.8
76
+
77
+
78
+ = Inkompatibilität =
79
+ * Disqus
80
+ * Jetpack Comments
81
+ * AJAX-Kommentarformulare
82
+
83
 
84
  = Unterstützung =
85
+ * Per [Flattr](https://flattr.com/t/1323822)
86
  * Per [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RDDW9FEHGLG6)
87
 
 
 
 
88
 
89
+ = Handbuch =
90
  * [Antispam Bee: Antispam für WordPress](http://playground.ebiene.de/antispam-bee-wordpress-plugin/)
91
 
92
+
93
+ = Website =
94
+ * [antispambee.de](http://antispambee.de)
95
+
96
+
97
  = Autor =
98
+ * [Twitter](https://twitter.com/wpSEO)
99
+ * [Google+](https://plus.google.com/110569673423509816572)
100
+ * [Plugins](http://wpcoder.de)
101
+
102
+
103
 
 
 
 
104
 
105
 
106
  == Changelog ==
107
 
108
+ = 2.6.0 =
109
+ * DE: Optimierungen für WordPress 3.8
110
+ * DE: Zusatzprüfung auf Nicht-UTF-8-Zeichen in Kommentardaten
111
+ * DE: Spamgrund als Spalte in der Übersicht mit Spamkommentaren
112
+ * EN: Optimizations for WordPress 3.8
113
+ * EN: Clear invalid UTF-8 characters in comment fields
114
+ * EN: Spam reason as a column in the table with spam comments
115
+
116
+ = 2.5.9 =
117
+ * DE: Anpassung des Dashboard-Skriptes für die Zusammenarbeit mit [Statify](http://statify.de)
118
+ * EN: Dashboard widget changes to work with [Statify](http://statify.de)
119
+
120
+ = 2.5.8 =
121
+ * DE: Umstellung von TornevallDNSBL zu [Stop Forum Spam](http://www.stopforumspam.com)
122
+ * DE: Neue JS-Bibliothek für das Dashboard-Widget
123
+ * DE: [Mehr Informationen auf Google+](https://plus.google.com/110569673423509816572/posts/VCFr3fDAYDs)
124
+ * EN: Switch from TornevallDNSBL to [Stop Forum Spam](http://www.stopforumspam.com)
125
+ * EN: New JS library for the Antispam Bee dashboard chart
126
+
127
+ = 2.5.7 =
128
+ * DE: Optionale Spam-Logdatei z.B. für [Fail2Ban](http://cup.wpcoder.de/fail2ban-ip-firewall/)
129
+ * DE: Filter `antispam_bee_notification_subject` für eigenen Betreff in Benachrichtigungen
130
+ * DE: Detaillierte Informationen zum Update auf [Google+](https://plus.google.com/110569673423509816572/posts/iCfip2ggYt9)
131
+ * EN: Optional logfile with spam entries e.g. for [Fail2Ban](https://gist.github.com/sergejmueller/5622883)
132
+ * EN: Filter `antispam_bee_notification_subject` for a custom subject in notifications
133
+
134
+ = 2.5.6 =
135
+ * DE: Neue Erkennungsmuster für Spam hinzugefügt / [Google+](https://plus.google.com/110569673423509816572/posts/9BSURheN3as)
136
+ * EN: Added new detection/patterns for spam comments
137
+
138
+ = 2.5.5 =
139
+ * Deutsch: Erkennung und Ausfilterung von Spam-Kommentaren, die versuchen, [Sicherheitslücken von W3 Total Cache und WP Super Cache](http://blog.sucuri.net/2013/05/w3-total-cache-and-wp-super-cache-vulnerability-being-targeted-in-the-wild.html) auszunutzen. [Ausführlicher auf Google+](https://plus.google.com/110569673423509816572/posts/afWWQbUh4at).
140
+ * English: Detection and filtering of spam comments that try to exploit the latest [W3 Total Cache and WP Super Cache Vulnerability](http://blog.sucuri.net/2013/05/w3-total-cache-and-wp-super-cache-vulnerability-being-targeted-in-the-wild.html).
141
+
142
+ = 2.5.4 =
143
+ * Jubiläumsausgabe: [Details zum Update](https://plus.google.com/110569673423509816572/posts/3dq9Re5vTY5)
144
+ * Neues Maskottchen für Antispam Bee
145
+ * Erweiterte Prüfung eingehender Kommentare in lokaler Blog-Spamdatenbank auf IP, URL und E-Mail-Adresse
146
+
147
+ = 2.5.3 =
148
+ * Optimierung des Regulären Ausdrucks
149
+
150
+ = 2.5.2 =
151
+ * Neu: [Reguläre Ausdrücke anwenden](http://playground.ebiene.de/antispam-bee-wordpress-plugin/#regexp_check) mit vordefinierten und eigenen Erkennungsmustern
152
+ * Änderung der Filter-Reihenfolge
153
+ * Verbesserungen an der Sprachdatei
154
+ * [Hintergrundinformationen zum Update](https://plus.google.com/110569673423509816572/posts/CwtbSoMkGrT)
155
+
156
+ = 2.5.1 =
157
+ * [BBCode im Kommentar als Spamgrund](http://playground.ebiene.de/antispam-bee-wordpress-plugin/#bbcode_check)
158
+ * IP-Anonymisierung bei der Länderprüfung
159
+ * [Mehr Transparenz](https://plus.google.com/110569673423509816572/posts/ZMU6RfyRK29) durch hinzugefügte Datenschutzhinweise
160
+ * PHP 5.2.4 als Voraussetzung (ist zugleich die Voraussetzung für WP 3.4)
161
+
162
+ = 2.5.0 =
163
+ * [Edition 2012](https://plus.google.com/110569673423509816572/posts/6JUC6PHXd6A)
164
+
165
+ = 2.4.6 =
166
+ * Russische Übersetzung
167
+ * Veränderung der Secret-Zeichenfolge
168
+
169
  = 2.4.5 =
170
  * Überarbeitetes Layout der Einstellungen
171
  * Streichung von Project Honey Pot
screenshot-1.png DELETED
Binary file