b2evolution PHP Cross Reference Blogging Systems

Source: /plugins/geoip_plugin/_geoip.plugin.php - 603 lines - 17862 bytes - Summary - Text - Print

Description: This file implements the Geo IP plugin. For the most recent and complete Plugin API documentation see {@link Plugin} in ../inc/plugins/_plugin.class.php.

   1  <?php
   2  /**

   3   * This file implements the Geo IP plugin.

   4   *

   5   * For the most recent and complete Plugin API documentation

   6   * see {@link Plugin} in ../inc/plugins/_plugin.class.php.

   7   *

   8   * This file is part of the evoCore framework - {@link http://evocore.net/}

   9   * See also {@link http://sourceforge.net/projects/evocms/}.

  10   *

  11   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}

  12   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.

  13   *

  14   * {@internal License choice

  15   * - If you have received this file as part of a package, please find the license.txt file in

  16   *   the same folder or the closest folder above for complete license terms.

  17   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)

  18   *   then you must choose one of the following licenses before using the file:

  19   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php

  20   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php

  21   * }}

  22   *

  23   * {@internal Open Source relicensing agreement:

  24   * Daniel HAHLER grants Francois PLANQUE the right to license

  25   * Daniel HAHLER's contributions to this file and the b2evolution project

  26   * under any OSI approved OSS license (http://www.opensource.org/licenses/).

  27   * }}

  28   *

  29   * @package plugins

  30   *

  31   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}

  32   * @author fplanque: Francois PLANQUE - {@link http://fplanque.net/}

  33   *

  34   * @version $Id: _geoip.plugin.php 13 2011-10-24 23:42:53Z fplanque $

  35   */
  36  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  37  
  38  
  39  /**

  40   * GeoIP Plugin

  41   *

  42   * This plugin detects a country of the user at the moment the account is created

  43   *

  44   * @package plugins

  45   */
  46  class geoip_plugin extends Plugin
  47  {
  48      /**

  49       * Variables below MUST be overriden by plugin implementations,

  50       * either in the subclass declaration or in the subclass constructor.

  51       */
  52      var $name = 'GeoIP';
  53      var $code = 'evo_GeoIP';
  54      var $priority = 50;
  55      var $version = '5.0.0';
  56      var $author = 'The b2evo Group';
  57  
  58      /*

  59       * These variables MAY be overriden.

  60       */
  61      var $number_of_installs = 1;
  62  
  63  
  64      /*

  65       * Path to GeoIP Database (file GeoIP.dat)

  66       */
  67      var $geoip_file_path = '';
  68      var $geoip_file_name = 'GeoIP.dat';
  69  
  70      /**

  71       * Init

  72       *

  73       * This gets called after a plugin has been registered/instantiated.

  74       */
  75  	function PluginInit( & $params )
  76      {
  77          $this->short_desc = 'GeoIP plugin to detect user\'s country by IP address';
  78          $this->long_desc = 'This plugin detects user\'s country at the moment the account is created';
  79  
  80          $this->geoip_file_path = dirname( __FILE__ ).'/'.$this->geoip_file_name;
  81      }
  82  
  83  
  84      /**

  85       * Get the settings that the plugin can use.

  86       *

  87       * Those settings are transfered into a Settings member object of the plugin

  88       * and can be edited in the backoffice (Settings / Plugins).

  89       *

  90       * @see Plugin::GetDefaultSettings()

  91       * @see PluginSettings

  92       * @see Plugin::PluginSettingsValidateSet()

  93       * @return array

  94       */
  95  	function GetDefaultSettings( & $params )
  96      {
  97          return array(
  98              'detect_registration' => array(
  99                  'label' => T_('Detect country on registration'),
 100                  'type' => 'radio',
 101                  'options' => array(
 102                          array( 'no', T_( 'No' ) ),
 103                          array( 'auto', T_( 'Auto select current country in list' ) ),
 104                          array( 'hide', T_( 'Hide country selector if a country has been detected' ) ),
 105                      ),
 106                  'field_lines' => true,
 107                  'note' => '',
 108                  'defaultvalue' => 'no',
 109                  ),
 110              'force_account_creation' => array(
 111                  'label' => T_('At account creation'),
 112                  'type' => 'checkbox',
 113                  'note' => T_('force country to the country detected by GeoIP'),
 114                  'defaultvalue' => '1',
 115                  ),
 116              );
 117      }
 118  
 119  
 120      /**

 121       * Check for existing of the file "GeoIP.dat" (GeoIP Country database)

 122       */
 123  	function BeforeEnable()
 124      {
 125          if( !file_exists( $this->geoip_file_path ) )
 126          {    // GeoIP DB doesn't exist in the right folder
 127              return sprintf( T_('GeoIP Country database not found. Download the <b>GeoLite Country DB in binary format</b> from here: <a %s>%s</a> and then upload the %s file to the folder: %s'),
 128                      'href="http://www.maxmind.com/app/geolite" target="_blank"',
 129                      'http://www.maxmind.com/app/geolite',
 130                      $this->geoip_file_name,
 131                      dirname( __FILE__ ) );
 132          }
 133  
 134          return true;
 135      }
 136  
 137  
 138      /**

 139       * Event handler: called at the end of {@link User::dbinsert() inserting

 140       * an user account into the database}, which means it has been created.

 141       *

 142       * @since 1.8.1

 143       * @param array Associative array of parameters

 144       *   - 'User': the related User (by reference)

 145       */
 146  	function AfterUserInsert( & $params )
 147      {
 148          $Country = $this->get_country_by_IP( $_SERVER['REMOTE_ADDR'] );
 149  
 150          if( !$Country )
 151          {    // No found country
 152              return false;
 153          }
 154  
 155          global $DB;
 156  
 157          $User = & $params['User'];
 158  
 159          // Update current user

 160          $user_update_sql = '';
 161          if( $this->Settings->get( 'force_account_creation' ) )
 162          {    // Force country to the country detected by GeoIP
 163              $user_update_sql = ', user_ctry_ID = '.$DB->quote( $Country->ID );
 164          }
 165          $DB->query( 'UPDATE T_users
 166                    SET user_reg_ctry_ID = '.$DB->quote( $Country->ID ).
 167                    $user_update_sql.'
 168                  WHERE user_ID = '.$DB->quote( $User->ID ) );
 169      }
 170  
 171  
 172      /**

 173       * Get country by IP address

 174       *

 175       * @param string IP in format xxx.xxx.xxx.xxx

 176       * @return object Country

 177       */
 178  	function get_country_by_IP( $IP )
 179      {
 180          if( function_exists('geoip_country_code_by_name') )
 181          {    // GeoIP extension
 182  
 183              // Get country code by user IP address

 184              $country_code = @geoip_country_code_by_name($IP);
 185          }
 186          else
 187          {    // Include GeoIP API
 188              require_once( dirname( __FILE__ ).'/geoip.inc' );
 189  
 190              // Open GeoIP database

 191              $GeoIP = geoip_open( $this->geoip_file_path, GEOIP_STANDARD );
 192  
 193              // Get country code by user IP address

 194              $country_code = geoip_country_code_by_addr( $GeoIP, $IP );
 195  
 196              // Close GeoIP DB

 197              geoip_close( $GeoIP );
 198          }
 199  
 200          if( ! $country_code )
 201          {    // No found country with current IP address
 202              return false;
 203          }
 204  
 205          global $DB;
 206  
 207          // Get country ID by code

 208          $SQL = new SQL();
 209          $SQL->SELECT( 'ctry_ID' );
 210          $SQL->FROM( 'T_regional__country' );
 211          $SQL->WHERE( 'ctry_code = '.$DB->quote( $country_code ) );
 212          $country_ID = $DB->get_var( $SQL->get() );
 213  
 214          if( !$country_ID )
 215          {    // No found country in the b2evo DB
 216              return false;
 217          }
 218  
 219          // Load Country class (PHP4):

 220          load_class( 'regional/model/_country.class.php', 'Country' );
 221  
 222          $CountryCache = & get_CountryCache();
 223          $Country = $CountryCache->get_by_ID( $country_ID, false );
 224  
 225          return $Country;
 226      }
 227  
 228  
 229      /**

 230       * This method should return a string that used as suffix

 231       *   for the field 'From Country' on the user profile page in the BackOffice

 232       *

 233       * @param array Associative array of parameters

 234       *   - 'User': the related User (by reference)

 235       * @return string Field suffix

 236       */
 237  	function GetUserFromCountrySuffix( & $params )
 238      {
 239          $User = $params['User'];
 240  
 241          $reload_icon = ' '.action_icon( T_('Ask GeoIP'), 'reload', '', T_('Ask GeoIP'), 3, 4, array( 'id' => 'geoip_load_country', 'class' => 'roundbutton roundbutton_text middle' ) )
 242  
 243          // JavaScript to load country by IP address

 244  ?>
 245  <script type="text/javascript">
 246  jQuery( document ).ready( function()
 247  {
 248      jQuery( '#geoip_load_country' ).click( function ()
 249      {
 250          var obj_this = jQuery( this );
 251          jQuery.post( '<?php echo $this->get_htsrv_url( 'load_country', array( 'user_ID' => $User->ID ), '&' ); ?>',
 252              function( result )
 253              {
 254                  obj_this.parent().html( ajax_debug_clear( result ) );
 255              }
 256          );
 257          return false;
 258      } );
 259  } );
 260  </script>
 261  <?php
 262  
 263          return $reload_icon;
 264      }
 265  
 266      /**

 267       * Return the list of Htsrv (HTTP-Services) provided by the plugin.

 268       *

 269       * This implements the plugin interface for the list of methods that are valid to

 270       * get called through htsrv/call_plugin.php.

 271       *

 272       * @return array

 273       */
 274  	function GetHtsrvMethods()
 275      {
 276          return array( 'load_country' );
 277      }
 278  
 279      /**

 280       * AJAX callback to load country.

 281       *

 282       * @param array Associative array of parameters

 283       *   - 'user_ID': User ID

 284       */
 285  	function htsrv_load_country( $params )
 286      {
 287          global $debug, $debug_jslog;
 288          // Do not append Debuglog to response!

 289          $debug = false;
 290          // Do not append Debug JSlog to response!

 291          $debug_jslog = false;
 292  
 293          $user_ID = $params['user_ID'];
 294  
 295          if( empty( $user_ID ) )
 296          {    // Bad request
 297              return;
 298          }
 299  
 300          $UserCache = & get_UserCache();
 301          if( ! ( $User = & $UserCache->get_by_ID( $user_ID ) ) )
 302          {    // No user exists
 303              return;
 304          }
 305  
 306          global $UserSettings;
 307          // Get Country by IP address

 308          $Country = $this->get_country_by_IP( int2ip( $UserSettings->get( 'created_fromIPv4', $User->ID ) ) );
 309  
 310          if( empty( $Country ) )
 311          {    // No found country
 312              echo sprintf( T_('No country found for IP address %s'), int2ip( $UserSettings->get( 'created_fromIPv4', $User->ID ) ) );
 313          }
 314          else
 315          {    // Display country name with flag and Update user's field 'From Country'
 316              load_funcs( 'regional/model/_regional.funcs.php' );
 317              country_flag( $Country->get( 'code' ), $Country->get_name() );
 318              echo ' '.$Country->get_name();
 319  
 320              // Update user

 321              global $DB;
 322              $DB->query( 'UPDATE T_users
 323                        SET user_reg_ctry_ID = '.$DB->quote( $Country->ID ).'
 324                      WHERE user_ID = '.$DB->quote( $User->ID ) );
 325          }
 326      }
 327  
 328  
 329      /**

 330       * Event handler: called at the end of {@link Comment::dbinsert() inserting

 331       * a comment into the database}, which means it has been created.

 332       *

 333       * @param array Associative array of parameters

 334       *   - 'Comment': the related Comment (by reference)

 335       *   - 'dbchanges': array with DB changes; a copy of {@link Comment::dbchanges()},

 336       *                  before they got applied (since 1.9)

 337       */
 338  	function AfterCommentInsert( & $params )
 339      {
 340          $Country = $this->get_country_by_IP( $_SERVER['REMOTE_ADDR'] );
 341  
 342          if( !$Country )
 343          {    // No found country
 344              return false;
 345          }
 346  
 347          global $DB;
 348  
 349          $Comment = $params['Comment'];
 350  
 351          // Update current comment

 352          $DB->query( 'UPDATE T_comments
 353                    SET comment_IP_ctry_ID = '.$DB->quote( $Country->ID ).'
 354                  WHERE comment_ID = '.$DB->quote( $Comment->ID ) );
 355      }
 356  
 357  
 358      /**

 359       * Event handler: Called at the begining of the "Register as new user" form.

 360       *

 361       * You might want to use this to inject antispam payload to use

 362       * in {@link Plugin::RegisterFormSent()}.

 363       *

 364       * @param array Associative array of parameters

 365       *   - 'Form': the comment form generating object (by reference)

 366       *   - 'inskin': boolean true if the form is displayed in skin

 367       */
 368  	function DisplayRegisterFormBefore( & $params )
 369      {
 370          global $Settings;
 371  
 372          $registration_require_country = (bool)$Settings->get('registration_require_country');
 373          if( !$registration_require_country )
 374          {    // Country is not required on registration form. Exit here.
 375              return;
 376          }
 377  
 378          $detect_registration = $this->Settings->get( 'detect_registration' );
 379          if( $detect_registration == 'no' )
 380          {    // No detect country on registration
 381              return;
 382          }
 383  
 384          $Country = $this->get_country_by_IP( $_SERVER['REMOTE_ADDR'] );
 385  
 386          if( !$Country )
 387          {    // No found country by IP address
 388              return;
 389          }
 390  
 391          switch( $detect_registration )
 392          {
 393              case 'auto':
 394                  // Auto select current country in list

 395                  $country = param( 'country', 'integer', 0 );
 396                  if( empty( $country ) )
 397                  {    // Set country ID if user didn't select country yet
 398                      set_param( 'country', $Country->ID );
 399                  }
 400                  break;
 401  
 402              case 'hide':
 403                  // Hide country selector if a country has been detected

 404                  if( ! isset( $params['Form'] ) )
 405                  {    // there's no Form where we add to, but we create our own form:
 406                      $Form = new Form( regenerate_url() );
 407  
 408                  }
 409                  else
 410                  {
 411                      $Form = & $params['Form'];
 412                  }
 413  
 414                  // Disable this setting temporary to hide a select list with countries

 415                  $Settings->set( 'registration_require_country', 0 );
 416  
 417                  // Append a hidden input element with autodetected country ID

 418                  $Form->hidden( 'country', $Country->ID );
 419                  break;
 420          }
 421      }
 422  
 423  
 424      /**

 425       * This method initializes an array that used as additional columns

 426       *   for the results table in the BackOffice

 427       *

 428       * @param array Associative array of parameters

 429       *   'table'   - Special name that used to know what plugin must use current table

 430       *   'column'  - DB field which contains IP address

 431       *   'Results' - Object

 432       */
 433  	function GetAdditionalColumnsTable( & $params )
 434      {
 435          $params = array_merge( array(
 436                  'table'   => '', // sessions, activity, ipranges
 437                  'column'  => '', // sess_ipaddress, comment_author_IP, aipr_IPv4start
 438                  'Results' => NULL
 439              ), $params );
 440  
 441          if( is_null( $params['Results'] ) || !is_object( $params['Results'] ) )
 442          { // Results must be object
 443              return;
 444          }
 445  
 446          if( in_array( $params['table'], array( 'sessions', 'activity', 'ipranges' ) ) )
 447          { // Display column only for required tables by GeoIP plugin
 448              $params['Results']->cols[] = array(
 449                  'th' => T_('Country'),
 450                  'order' => $params['column'],
 451                  'td' => '%geoip_get_country_by_IP( #'.$params['column'].'# )%',
 452              );
 453          }
 454      }
 455  
 456  
 457      /**

 458       * Event handler: Called when displaying the block in the "Tools" menu.

 459       *

 460       * @see Plugin::AdminToolPayload()

 461       */
 462  	function AdminToolPayload( $params )
 463      {
 464          $Form = new Form();
 465  
 466          $Form->begin_form( 'fform' );
 467  
 468          $Form->add_crumb( 'tools' );
 469          $Form->hidden_ctrl(); // needed to pass the "ctrl=tools" param

 470          $Form->hiddens_by_key( get_memorized() ); // needed to pass all other memorized params, especially "tab"

 471          $Form->hidden( 'action', 'geoip_find_country' );
 472  
 473          echo '<p>'.T_('This tool finds all users that do not have a registration country yet and then assigns them a registration country based on their registration IP.').'</p>';
 474  
 475          $Form->button( array(
 476                  'value' => T_('Find Registration Country for all Users NOW!')
 477              ) );
 478  
 479          if( !empty( $this->text_from_AdminTabAction ) )
 480          {    // Display a report of executed action
 481              echo '<p><b>'.T_('Report').':</b></p>';
 482              echo $this->text_from_AdminTabAction;
 483          }
 484  
 485          $Form->end_form();
 486      }
 487  
 488  
 489      /**

 490       * Event handler: Called when handling actions for the "Tools" menu.

 491       *

 492       * Use {@link $Messages} to add Messages for the user.

 493       *

 494       * @see Plugin::AdminToolAction()

 495       */
 496  	function AdminToolAction()
 497      {
 498          $action = param_action();
 499  
 500          if( !empty( $action ) )
 501          {    // If form is submitted
 502              global $DB;
 503  
 504              switch( $action )
 505              {
 506                  case 'geoip_find_country':
 507                  // Find and Assign Registration Country for all Users

 508  
 509                      $SQL = new SQL( 'Find all users without registration country' );
 510                      $SQL->SELECT( 'user_ID, uset_value' );
 511                      $SQL->FROM( 'T_users' );
 512                      $SQL->FROM_add( 'LEFT JOIN T_users__usersettings
 513                           ON user_ID = uset_user_ID
 514                          AND uset_name = "created_fromIPv4"' );
 515                      $SQL->WHERE( 'user_reg_ctry_ID IS NULL' );
 516                      $users = $DB->get_assoc( $SQL->get() );
 517  
 518                      $total_users = count( $users );
 519                      if( $total_users == 0 )
 520                      {    // No users
 521                          $this->text_from_AdminTabAction = T_('No found users without registration country.');
 522                          break;
 523                      }
 524                      $count_nofound_country = 0;
 525  
 526                      $users_report = '';
 527                      foreach( $users as $user_ID => $created_fromIPv4 )
 528                      {
 529                          $users_report .= sprintf( T_('User #%s, IP:%s' ), $user_ID, int2ip( $created_fromIPv4 ) );
 530                          if( empty( $created_fromIPv4 ) )
 531                          {    // No defined IP, Skip this user
 532                              $count_nofound_country++;
 533                              $users_report .= ' - <b class="orange">'.T_('IP is not defined!').'</b><br />';
 534                              continue;
 535                          }
 536  
 537                          // Get Country by IP address

 538                          $Country = $this->get_country_by_IP( int2ip( $created_fromIPv4 ) );
 539  
 540                          if( !$Country )
 541                          {    // No found country by IP address
 542                              $count_nofound_country++;
 543                              $users_report .= ' - <b class="red">'.T_('Country is not detected!').'</b><br />';
 544                              continue;
 545                          }
 546  
 547                          // Update user's registration country

 548                          $DB->query( 'UPDATE T_users
 549                                    SET user_reg_ctry_ID = '.$DB->quote( $Country->ID ).'
 550                                  WHERE user_ID = '.$DB->quote( $user_ID ) );
 551  
 552                          $users_report .= ' - '.sprintf( T_('Country: <b>%s</b>'), $Country->get( 'name' ) ).'<br />';
 553                      }
 554  
 555                      $this->text_from_AdminTabAction = '<div>'.sprintf( T_('Count of users without registration country: <b>%s</b>' ), $total_users ).'</div>';
 556                      if( $count_nofound_country > 0 )
 557                      {    // If some users have IP address with unknown country
 558                          $this->text_from_AdminTabAction .= '<div>'.sprintf( T_('Count of users whose country could not be identified: <b>%s</b>' ), $count_nofound_country ).'</div>';
 559                      }
 560                      $this->text_from_AdminTabAction .= '<div style="margin-top:20px">'.$users_report.'</div>';
 561  
 562                      break;
 563              }
 564          }
 565      }
 566  }
 567  
 568  
 569  /**

 570   * Get country by IP address (Used in the method GetAdditionalColumnsTable() in the table column)

 571   *

 572   * @param string|integer IP address

 573   * @return string Country with flag

 574   */
 575  function geoip_get_country_by_IP( $IP )
 576  {
 577      global $Plugins, $Timer;
 578  
 579      $Timer->resume( 'plugin_geoip' );
 580  
 581      $country = '';
 582  
 583      if( $Plugins && $geoip_Plugin = & $Plugins->get_by_code( 'evo_GeoIP' ) )
 584      {
 585          if( strlen( intval( $IP ) ) == strlen( $IP ) )
 586          { // IP is in integer format, We should convert it to normal IP
 587              $IP = int2ip( $IP );
 588          }
 589  
 590          if( $Country = & $geoip_Plugin->get_country_by_IP( $IP ) )
 591          { // Get country flag + name
 592              load_funcs( 'regional/model/_regional.funcs.php' );
 593              $country = country_flag( $Country->get( 'code' ), $Country->get_name(), 'w16px', 'flag', '', false ).
 594                  ' '.$Country->get_name();
 595          }
 596      }
 597  
 598      $Timer->pause( 'plugin_geoip' );
 599  
 600      return $country;
 601  }
 602  
 603  ?>

title

Description

title

Description

title

Description

title

title

Body