├── LICENSE ├── README.md ├── WPML_GEOIP_admin_page.class.php ├── WPML_GeoIP_IPResolver.class.php ├── changelog.txt ├── database └── GeoIP.dat ├── js └── browser-redirect-geoip.js ├── lib └── geoip-api-php │ ├── .gitignore │ ├── ChangeLog │ ├── LICENSE │ ├── README.md │ ├── admin │ └── generate_geoipregionvars.php │ ├── benchmark.php │ ├── composer.json │ ├── geoip.inc │ ├── geoipcity.inc │ ├── geoipregionvars.php │ ├── sample-v6.php │ ├── sample.php │ ├── sample_asn-v6.php │ ├── sample_city-v6.php │ ├── sample_city.php │ ├── sample_distributed.php │ ├── sample_domain.php │ ├── sample_netspeed.php │ ├── sample_netspeedcell.php │ ├── sample_org.php │ ├── sample_region.php │ └── timezone │ ├── make_time_zone_php_code.pl │ ├── test_timezone.php │ └── timezone.php └── wpml-geoip-browser-language-redirect.php /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GeoIP Redirector for WPML 2 | ======================================= 3 | 4 | 5 | This is a WordPress plugin that changes the browser language redirect in WPML from simple browser language detection to 6 | using a GeoIP database (MaxMind) to pinpoint user location more exactly. 7 | 8 | ## Usage 9 | 10 | * Install this as a plugin 11 | * Make sure WPML is enabled and that you have enabled the "Browser language redirect" in the WordPress admin, under WPML > Languages > Browser language redirect > Redirect visitors based on browser language only if translations exist (Enable this option) 12 | * Set up your language mappings in the plugin UI 13 | -------------------------------------------------------------------------------- /WPML_GEOIP_admin_page.class.php: -------------------------------------------------------------------------------- 1 | language_mappings = $language_mappings; 12 | $this->default_language = $default_language; 13 | } 14 | 15 | 16 | function display_wpml_geo_redirect_admin_page(){ 17 | ?> 18 | 19 |
20 |
21 |

WPML GEO Redirect

22 | 23 | display_feedback_admin_notices() ?> 24 | 25 |
26 | '; 28 | echo " 29 | Country Code / Language Code 30 | Remove 31 | "; 32 | $table_row = $this->display_language_mapping_rows( $this->language_mappings ); 33 | 34 | $this->display_add_new_country_mapping_row( $table_row ); 35 | $this->display_select_default_language_row( $table_row , $this->default_language ); 36 | echo ""; 37 | 38 | wp_nonce_field( 'wpml_geo_redirect_update_action' ); 39 | submit_button(); 40 | ?> 41 |
42 |
43 | 44 | 59 |
60 |

Configuration data was updated.

61 |
62 | 67 |
68 |

There has been an error. Country codes need to be unique.

69 |
70 | 75 |
76 |

There has been a form submission error.

77 |
78 | $lang_code){ 90 | 91 | echo ''; 92 | echo ''; 93 | echo $this->display_icl_language_flag( $country_code ); 94 | echo " "; 95 | echo $this->display_mm_country_code_dropdown( $table_row , $country_code ); 96 | echo " => "; 97 | echo $this->display_language_code_dropdown( $table_row , $lang_code ); 98 | echo ''; 99 | echo ''; 100 | echo ''; 101 | echo ''; 102 | echo ''; 103 | 104 | $table_row++; 105 | } 106 | return $table_row; 107 | } 108 | 109 | 110 | private function display_icl_language_flag( $country_code ){ 111 | 112 | if( defined( 'WPML_GEO_REDIRECT_SHOW_FLAGS' ) && 113 | file_exists( ICL_PLUGIN_PATH . '/res/flags/' . strtolower( $country_code ) .'.png' )){ 114 | 115 | $url = ICL_PLUGIN_URL . '/res/flags/' . strtolower( $country_code ) .'.png'; 116 | return $img_tag = ''.$country_code.''; 117 | } 118 | return false; 119 | } 120 | 121 | 122 | private function display_mm_country_code_dropdown( $table_row=0 , $country_code_param=null , $remove_saved_codes=false ){ 123 | 124 | $mm_country_codes = array( 125 | 'AP','EU','AD','AE','AF','AG','AI','AL','AM','CW','AO','AQ','AR','AS','AT','AU','AW','AZ','BA','BB','BD','BE','BF','BG', 126 | 'BH','BI','BJ','BM','BN','BO','BR','BS','BT','BV','BW','BY','BZ','CA','CC','CD','CF','CG','CH','CI','CK','CL','CM','CN', 127 | 'CO','CR','CU','CV','CX','CY','CZ','DE','DJ','DK','DM','DO','DZ','EC','EE','EG','EH','ER','ES','ET','FI','FJ','FK','FM', 128 | 'FO','FR','SX','GA','GB','GD','GE','GF','GH','GI','GL','GM','GN','GP','GQ','GR','GS','GT','GU','GW','GY','HK','HM','HN', 129 | 'HR','HT','HU','ID','IE','IL','IN','IO','IQ','IR','IS','IT','JM','JO','JP','KE','KG','KH','KI','KM','KN','KP','KR','KW', 130 | 'KY','KZ','LA','LB','LC','LI','LK','LR','LS','LT','LU','LV','LY','MA','MC','MD','MG','MH','MK','ML','MM','MN','MO','MP', 131 | 'MQ','MR','MS','MT','MU','MV','MW','MX','MY','MZ','NA','NC','NE','NF','NG','NI','NL','NO','NP','NR','NU','NZ','OM','PA', 132 | 'PE','PF','PG','PH','PK','PL','PM','PN','PR','PS','PT','PW','PY','QA','RE','RO','RU','RW','SA','SB','SC','SD','SE','SG', 133 | 'SH','SI','SJ','SK','SL','SM','SN','SO','SR','ST','SV','SY','SZ','TC','TD','TF','TG','TH','TJ','TK','TM','TN','TO','TL', 134 | 'TR','TT','TV','TW','TZ','UA','UG','UM','US','UY','UZ','VA','VC','VE','VG','VI','VN','VU','WF','WS','YE','YT','RS','ZA', 135 | 'ZM','ME','ZW','AX','GG','IM','JE','BL','MF','BQ','SS' 136 | ); 137 | 138 | /* For new country row - no need to show codes already used */ 139 | if( $remove_saved_codes ){ 140 | $mm_country_codes = array_diff( $mm_country_codes , array_keys( $this->language_mappings ) ); 141 | } 142 | 143 | asort( $mm_country_codes ); 144 | 145 | $select_name = 'language_mappings[' . $table_row . '][country]'; 146 | $output = '"; 157 | 158 | return $output; 159 | } 160 | 161 | 162 | private function selected_html( $value_1 , $value_2 ){ 163 | return $selected = ($value_1 == $value_2 ? 'selected="selected"' : null); 164 | } 165 | 166 | 167 | private function display_language_code_dropdown( $table_row=0 , $lang_code_param='' , $is_default=false ){ 168 | 169 | global $sitepress_settings; 170 | 171 | $args['skip_missing'] = intval($sitepress_settings['automatic_redirect'] == 1); 172 | $languages = apply_filters( 'wpml_active_languages', null, $args ); 173 | 174 | $select_name = $is_default === true ? 'default_redirect_language' : 'language_mappings['. $table_row .'][language]'; 175 | 176 | $output = '"; 185 | 186 | return $output; 187 | } 188 | 189 | 190 | private function display_add_new_country_mapping_row( $table_row ){ 191 | 192 | echo ''; 193 | echo ''; 194 | echo $this->display_mm_country_code_dropdown( $table_row, null, true ); 195 | echo " => "; 196 | echo $this->display_language_code_dropdown( $table_row ); 197 | echo ''; 198 | echo ''; 199 | echo " "; 200 | echo ''; 201 | echo ''; 202 | 203 | } 204 | 205 | 206 | private function display_select_default_language_row( $table_row , $default_language ){ 207 | 208 | echo ''; 209 | echo ''; 210 | echo "Any other place on this planet"; 211 | echo " => "; 212 | echo $this->display_language_code_dropdown( $table_row , $default_language , true ); 213 | echo ''; 214 | echo ''; 215 | 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /WPML_GeoIP_IPResolver.class.php: -------------------------------------------------------------------------------- 1 | WPML Code 34 | /* 35 | $this->language_mappings = array( 36 | 'SE' => 'sv', //Sweden 37 | 'NO' => 'nb', //Norway 38 | 'FI' => 'fi', //Finland 39 | 'DK' => 'da', //Denmark 40 | 'US' => 'en', //USA 41 | 'CA' => 'en' //Canada 42 | ); */ 43 | 44 | $this->language_mappings = get_option( 'wpml_geo_redirect_language_mappings' ); 45 | 46 | //Set the default WPML language which is used if no matching language is found 47 | //$this->default_language = 'sv'; 48 | $this->default_language = get_option( 'wpml_geo_redirect_default_language' ); 49 | 50 | //Make sure to not redeclare the GeoIP API if it is loaded already. 51 | if(!function_exists('geoip_country_code_by_addr')) 52 | { 53 | include_once('lib/geoip-api-php/geoip.inc'); 54 | include_once('lib/geoip-api-php/geoipregionvars.php'); 55 | include_once('lib/geoip-api-php/timezone/timezone.php'); 56 | } 57 | 58 | //MaxMind gets cranky when we don't use the full path 59 | $this->db = geoip_open(plugin_dir_path(__FILE__) . '/database/GeoIP.dat', GEOIP_STANDARD); 60 | } 61 | /** 62 | * Returns a WPML-compatible country code from an IP address 63 | * 64 | * @param $ip 65 | * @param bool $as_json 66 | * @return string 67 | */ 68 | function ip_to_wpml_country_code($ip, $as_json = true) 69 | { 70 | //This returns empty string if something went wrong 71 | $country_code = @geoip_country_code_by_addr($this->db, $ip); 72 | 73 | //Try to match against language mappings 74 | foreach($this->language_mappings as $maxmind_code => $wpml_code) 75 | { 76 | if($maxmind_code == $country_code) 77 | return $this->return_country_code($wpml_code); 78 | } 79 | 80 | //We didn't match anything, return the default code 81 | return $this->return_country_code($this->default_language); 82 | } 83 | 84 | function return_country_code($country_code) 85 | { 86 | return json_encode(array('country_code' => $country_code)); 87 | } 88 | 89 | function set_json_header() 90 | { 91 | //http://stackoverflow.com/a/11112311/2572827 92 | header('Content-Type: application/json'); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | Version 1.1 2 | - Checked compatibility with WPML 3.1.4 3 | - Added utilities for debugging the javascript 4 | - General code cleanup 5 | 6 | Version 1.0 7 | - Initial release -------------------------------------------------------------------------------- /database/GeoIP.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khromov/wp-wpml-geoip-browser-language-redirect/f288413c90e3acc75cfa772ccfa0d4c2365c7202/database/GeoIP.dat -------------------------------------------------------------------------------- /js/browser-redirect-geoip.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function() 2 | { 3 | var GEOIP_DEBUG = false; 4 | 5 | if(GEOIP_DEBUG) 6 | { 7 | //IE 8/9 fix 8 | if(!window.console) 9 | { 10 | var console = { 11 | log : function(){}, 12 | warn : function(){}, 13 | error : function(){}, 14 | time : function(){}, 15 | timeEnd : function(){} 16 | } 17 | } 18 | } 19 | 20 | if (jQuery.cookie != undefined) 21 | { 22 | if(GEOIP_DEBUG) 23 | console.log("Initializing geoip script"); 24 | 25 | // Check if cookie are enabled 26 | jQuery.cookie('wpml_browser_redirect_test', '1'); 27 | var cookie_enabled = jQuery.cookie('wpml_browser_redirect_test') == 1; 28 | jQuery.removeCookie('wpml_browser_redirect_test'); 29 | 30 | //Only attempt redirection of cookies can be placed with jQuery.cookie 31 | if (cookie_enabled) 32 | { 33 | if(GEOIP_DEBUG) 34 | console.log("cookies enabled"); 35 | 36 | var cookie_params = wpml_browser_redirect_params.cookie; 37 | var pageLanguage = wpml_browser_redirect_params.pageLanguage; 38 | var cookie_name = cookie_params.name; 39 | 40 | //Check if we already did a redirect, and if we didn't... 41 | if (!jQuery.cookie(cookie_name)) 42 | { 43 | if(GEOIP_DEBUG) 44 | console.log("We have not redirected yet."); 45 | 46 | //Get the country code to use by IP 47 | jQuery.ajax({ 48 | type: 'GET', 49 | data: {'wpml_geoip' : 1}, 50 | async: false, 51 | success: function (ret) 52 | { 53 | browserLanguage = ret.country_code 54 | } 55 | }); 56 | 57 | // Build cookie options 58 | var cookie_options = { 59 | expires: cookie_params.expiration / 24, 60 | path: cookie_params.path ? cookie_params.path : '/', 61 | domain: cookie_params.domain ? cookie_params.domain : '' 62 | }; 63 | 64 | // Set the cookie so that the check is made only on the first visit 65 | jQuery.cookie(cookie_name, browserLanguage, cookie_options); 66 | 67 | // Compare page language and browser language 68 | if (pageLanguage != browserLanguage) 69 | { 70 | if(GEOIP_DEBUG) 71 | console.log("Page language is not correct for the user"); 72 | 73 | var redirectUrl; 74 | // First try to find the redirect url from parameters passed to javascript 75 | var languageUrls = wpml_browser_redirect_params.languageUrls; 76 | 77 | if (languageUrls[browserLanguage] != undefined) 78 | { 79 | if(GEOIP_DEBUG) 80 | console.log("Found redirection in conditional 1"); 81 | 82 | redirectUrl = languageUrls[browserLanguage]; 83 | } 84 | else if (languageUrls[browserLanguage.substr(0, 2)] != undefined) 85 | { 86 | if(GEOIP_DEBUG) 87 | console.log("Found redirection in conditional 2"); 88 | 89 | redirectUrl = languageUrls[browserLanguage]; 90 | } 91 | else 92 | { 93 | if(GEOIP_DEBUG) 94 | console.log("The user should have been redirected, but we could not find the localized version of the page."); 95 | } 96 | 97 | //Finally do the redirect, if this pages language exists 98 | if (redirectUrl != undefined) 99 | { 100 | if(GEOIP_DEBUG) 101 | console.log("Redirecting user!"); 102 | 103 | window.location = redirectUrl; 104 | } 105 | } 106 | else 107 | { 108 | if(GEOIP_DEBUG) 109 | console.log("User not redirected because he is already on the right language."); 110 | } 111 | } 112 | else 113 | { 114 | if(GEOIP_DEBUG) 115 | console.log("User has already been redirected."); 116 | } 117 | } 118 | } 119 | }); -------------------------------------------------------------------------------- /lib/geoip-api-php/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .gh-pages 3 | composer.lock 4 | composer.phar 5 | phpunit.xml 6 | vendor/ 7 | *.sw? 8 | t.php 9 | *.old 10 | -------------------------------------------------------------------------------- /lib/geoip-api-php/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khromov/wp-wpml-geoip-browser-language-redirect/f288413c90e3acc75cfa772ccfa0d4c2365c7202/lib/geoip-api-php/ChangeLog -------------------------------------------------------------------------------- /lib/geoip-api-php/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | -------------------------------------------------------------------------------- /lib/geoip-api-php/README.md: -------------------------------------------------------------------------------- 1 | # MaxMind GeoIP PHP API # 2 | 3 | ## Requirements ## 4 | 5 | This module has no external dependencies. You only need a MaxMind GeoIP 6 | database. To download a free GeoIP Standard Country database, please see 7 | our [GeoLite page](http://dev.maxmind.com/geoip/geolite). 8 | 9 | ## Installing with Composer ## 10 | 11 | ### Define Your Dependencies ### 12 | 13 | We recommend installing this package with [Composer](http://getcomposer.org/). 14 | To do this, add ```geoip/geoip``` to your ```composer.json``` file. 15 | 16 | ```json 17 | { 18 | "require": { 19 | "geoip/geoip": "~1.13" 20 | } 21 | } 22 | ``` 23 | 24 | ### Install Composer ### 25 | 26 | Run in your project root: 27 | 28 | ``` 29 | curl -s http://getcomposer.org/installer | php 30 | ``` 31 | 32 | ### Install Dependencies ### 33 | 34 | Run in your project root: 35 | 36 | ``` 37 | php composer.phar install 38 | ``` 39 | 40 | ### Require Autoloader ### 41 | 42 | You can autoload all dependencies by adding this to your code: 43 | ``` 44 | require 'vendor/autoload.php'; 45 | ``` 46 | 47 | ## Installing without Composer ## 48 | 49 | Place the 'geoip.inc' file in the `include_path` as specified in your 50 | `php.ini` file or place it in the same directory as your PHP scripts. 51 | 52 | ## Usage ## 53 | 54 | Gets country name by hostname : 55 | 56 | ```php 57 | include("geoip.inc"); 58 | 59 | $gi = geoip_open("/usr/local/share/GeoIP/GeoIP.dat",GEOIP_STANDARD); 60 | 61 | echo geoip_country_code_by_addr($gi, "24.24.24.24") . "\t" . 62 | geoip_country_name_by_addr($gi, "24.24.24.24") . "\n"; 63 | echo geoip_country_code_by_addr($gi, "80.24.24.24") . "\t" . 64 | geoip_country_name_by_addr($gi, "80.24.24.24") . "\n"; 65 | 66 | geoip_close($gi); 67 | ``` 68 | 69 | ## Memory Caching ## 70 | 71 | To enable memory caching, pass `GEOIP_SHARED_MEMORY` or `GEOIP_MEMORY_CACHE` 72 | as the second argument of `geoip_open`. 73 | 74 | `GEOIP_SHARED_MEMORY` requires php >= 4.0.4 compiled with `--enable-shmop` 75 | configure time. See (http://us2.php.net/manual/en/ref.shmop.php). 76 | In addition, you should call `geoip_load_shared_mem` before calling 77 | `geoip_open`. See `sample_city.php` for an example of shared memory caching. 78 | 79 | ## Support ## 80 | 81 | For help with this API or our databases, please see [our support page] 82 | (http://www.maxmind.com/en/support). 83 | 84 | ## Copyright and License ## 85 | 86 | This software is Copyright (c) 2013 by MaxMind, Inc. 87 | 88 | This is free software, licensed under the GNU Lesser General Public License 89 | version 2.1 or later. 90 | 91 | ## Thanks ## 92 | 93 | Thanks to Jim Winstead. 94 | -------------------------------------------------------------------------------- /lib/geoip-api-php/admin/generate_geoipregionvars.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | array(\n"; 10 | $keys2 = array_keys($values[$a0]); 11 | $values2 = array_values($values[$a0]); 12 | for ($a1 = 0;$a1 < sizeof($keys2);$a1++){ 13 | print "\"" . $keys2[$a1] . "\" => \"" . $values2[$a1] . "\""; 14 | if ($a1 < sizeof($keys2)-1){print ",\n";} 15 | } 16 | if ($a0 < sizeof($keys)-1){ 17 | print "),\n";} 18 | else{ 19 | print ")\n";} 20 | } 21 | print "\$fips = array(\n"; 22 | $fips = get_fips_10_4_subcountry_codes(); 23 | $keys = array_keys($fips); 24 | $values = array_values($fips); 25 | for ($a0 = 0;$a0 < sizeof($keys);$a0++){ 26 | print "\"" . $keys[$a0] . "\" => array(\n"; 27 | $keys2 = array_keys($values[$a0]); 28 | $values2 = array_values($values[$a0]); 29 | for ($a1 = 0;$a1 < sizeof($keys2);$a1++){ 30 | #setsubstr($value2[$a1],strlen($value2[$a1])-1,1,","); 31 | print "\"" . $keys2[$a1] . "\" => \"" . $values2[$a1] . "\""; 32 | if ($a1 < sizeof($keys2)-1){print ",\n";} 33 | } 34 | if ($a0 < sizeof($keys)-1){ 35 | print "),\n";} 36 | else{ 37 | print ")\n";} 38 | } 39 | print ");\n"; 40 | function get_iso_3166_2_subcountry_codes(){ 41 | $f = fopen("../iso3166_2","r"); 42 | $str = fgets($f,4096); 43 | while (!feof($f)){ 44 | $str = fgets($f,4096); 45 | $substrs = explode(",",$str); 46 | list($country,$region,$name) = $substrs; 47 | if (count($substrs) > 3){ 48 | for ($a0 = 3;$a0 < count($substrs);$a0++){ 49 | $name = $name .",". $substrs[$a0]; 50 | } 51 | } 52 | if ($name){ 53 | $name = substr($name,1,strlen($name)-3); 54 | $a[$country][$region] = $name;} 55 | } 56 | fclose($f); 57 | return $a; 58 | } 59 | 60 | function get_fips_10_4_subcountry_codes(){ 61 | $f = fopen("../fips10_4","r"); 62 | $str = fgets($f,4096); 63 | while (!feof($f)){ 64 | $str = fgets($f,4096); 65 | $substrs = explode(",",$str); 66 | list($country,$region,$name) = $substrs; 67 | if (count($substrs) > 3){ 68 | for ($a0 = 3;$a0 < count($substrs);$a0++){ 69 | $name = $name .",". $substrs[$a0]; 70 | } 71 | } 72 | if ($name){ 73 | $name = substr($name,1,strlen($name)-3); 74 | $a[$country][$region] = $name;} 75 | } 76 | fclose($f); 77 | return $a; 78 | } 79 | 80 | ?> 81 | -------------------------------------------------------------------------------- /lib/geoip-api-php/benchmark.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 0){$result = $result . ".";} 18 | $a2 = rand(1, 254); 19 | $result = $result . $a2; 20 | } 21 | return $result; 22 | } 23 | function ftime(){ 24 | $a = gettimeofday(); 25 | return $a[sec] + ($a[usec]*0.000001); 26 | } 27 | function testgeoipdatabase($type,$flags,$msg,$numlookups){ 28 | $gi = geoip_open($this->dbfilename[$type],$flags); 29 | if ($gi == null){ 30 | print "error: " . $this->dbfilename[$type] . " does not exist\n" ; 31 | return; 32 | } 33 | $t1 = $this->ftime(); 34 | $i4 = 0; 35 | for ($i2 = 0;$i2 < $numlookups;$i2++){ 36 | switch ($type) { 37 | case GEOIP_COUNTRY_DATABASE: 38 | geoip_country_code_by_addr($gi,$this->randomipaddress()); 39 | break; 40 | case GEOIP_REGION_DATABASE: 41 | geoip_region_by_addr($gi,$this->randomipaddress()); 42 | break; 43 | case GEOIP_CITY_DATABASE: 44 | GeoIP_record_by_addr($gi,$this->randomipaddress()); 45 | break; 46 | } 47 | } 48 | $t2 = $this->ftime(); 49 | $t3 = $t2-$t1; 50 | print $msg . "\n"; 51 | print $numlookups . " lookups made in " . $t3 . " seconds \n"; 52 | geoip_close($gi); 53 | } 54 | } 55 | 56 | 57 | $mainapp = new mainappc(); 58 | 59 | 60 | $mainapp->testgeoipdatabase(GEOIP_COUNTRY_DATABASE,GEOIP_STANDARD,"Geoip Country ",10000); 61 | $mainapp->testgeoipdatabase(GEOIP_COUNTRY_DATABASE,GEOIP_MEMORY_CACHE,"Geoip Country with memory cache",10000); 62 | $mainapp->testgeoipdatabase(GEOIP_REGION_DATABASE,GEOIP_STANDARD,"Geoip Region ",10000); 63 | $mainapp->testgeoipdatabase(GEOIP_REGION_DATABASE,GEOIP_MEMORY_CACHE,"Geoip Region with memory cache",10000); 64 | $mainapp->testgeoipdatabase(GEOIP_CITY_DATABASE,GEOIP_STANDARD,"Geoip City ",10000); 65 | $mainapp->testgeoipdatabase(GEOIP_CITY_DATABASE,GEOIP_MEMORY_CACHE,"Geoip City with memory cache",10000); 66 | 67 | ?> 68 | -------------------------------------------------------------------------------- /lib/geoip-api-php/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geoip/geoip", 3 | "description": "MaxMind GeoIP PHP API", 4 | "keywords": [ "geoip", "geolocation", "maxmind" ], 5 | "homepage": "http://dev.maxmind.com/geoip/legacy/downloadable", 6 | "type": "library", 7 | "license": "LGPL 2.1+", 8 | "authors": [ 9 | { 10 | "name": "MaxMind, Inc.", 11 | "email": "support@maxmind.com", 12 | "homepage": "http://www.maxmind.com/" 13 | } 14 | ], 15 | "autoload": { 16 | "files": ["geoip.inc", "geoipcity.inc"] 17 | }, 18 | "conflict": { 19 | "ext-geoip": "*" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/geoip-api-php/geoip.inc: -------------------------------------------------------------------------------- 1 | 0, "AP" => 1, "EU" => 2, "AD" => 3, "AE" => 4, "AF" => 5, 83 | "AG" => 6, "AI" => 7, "AL" => 8, "AM" => 9, "CW" => 10, "AO" => 11, 84 | "AQ" => 12, "AR" => 13, "AS" => 14, "AT" => 15, "AU" => 16, "AW" => 17, 85 | "AZ" => 18, "BA" => 19, "BB" => 20, "BD" => 21, "BE" => 22, "BF" => 23, 86 | "BG" => 24, "BH" => 25, "BI" => 26, "BJ" => 27, "BM" => 28, "BN" => 29, 87 | "BO" => 30, "BR" => 31, "BS" => 32, "BT" => 33, "BV" => 34, "BW" => 35, 88 | "BY" => 36, "BZ" => 37, "CA" => 38, "CC" => 39, "CD" => 40, "CF" => 41, 89 | "CG" => 42, "CH" => 43, "CI" => 44, "CK" => 45, "CL" => 46, "CM" => 47, 90 | "CN" => 48, "CO" => 49, "CR" => 50, "CU" => 51, "CV" => 52, "CX" => 53, 91 | "CY" => 54, "CZ" => 55, "DE" => 56, "DJ" => 57, "DK" => 58, "DM" => 59, 92 | "DO" => 60, "DZ" => 61, "EC" => 62, "EE" => 63, "EG" => 64, "EH" => 65, 93 | "ER" => 66, "ES" => 67, "ET" => 68, "FI" => 69, "FJ" => 70, "FK" => 71, 94 | "FM" => 72, "FO" => 73, "FR" => 74, "SX" => 75, "GA" => 76, "GB" => 77, 95 | "GD" => 78, "GE" => 79, "GF" => 80, "GH" => 81, "GI" => 82, "GL" => 83, 96 | "GM" => 84, "GN" => 85, "GP" => 86, "GQ" => 87, "GR" => 88, "GS" => 89, 97 | "GT" => 90, "GU" => 91, "GW" => 92, "GY" => 93, "HK" => 94, "HM" => 95, 98 | "HN" => 96, "HR" => 97, "HT" => 98, "HU" => 99, "ID" => 100, "IE" => 101, 99 | "IL" => 102, "IN" => 103, "IO" => 104, "IQ" => 105, "IR" => 106, "IS" => 107, 100 | "IT" => 108, "JM" => 109, "JO" => 110, "JP" => 111, "KE" => 112, "KG" => 113, 101 | "KH" => 114, "KI" => 115, "KM" => 116, "KN" => 117, "KP" => 118, "KR" => 119, 102 | "KW" => 120, "KY" => 121, "KZ" => 122, "LA" => 123, "LB" => 124, "LC" => 125, 103 | "LI" => 126, "LK" => 127, "LR" => 128, "LS" => 129, "LT" => 130, "LU" => 131, 104 | "LV" => 132, "LY" => 133, "MA" => 134, "MC" => 135, "MD" => 136, "MG" => 137, 105 | "MH" => 138, "MK" => 139, "ML" => 140, "MM" => 141, "MN" => 142, "MO" => 143, 106 | "MP" => 144, "MQ" => 145, "MR" => 146, "MS" => 147, "MT" => 148, "MU" => 149, 107 | "MV" => 150, "MW" => 151, "MX" => 152, "MY" => 153, "MZ" => 154, "NA" => 155, 108 | "NC" => 156, "NE" => 157, "NF" => 158, "NG" => 159, "NI" => 160, "NL" => 161, 109 | "NO" => 162, "NP" => 163, "NR" => 164, "NU" => 165, "NZ" => 166, "OM" => 167, 110 | "PA" => 168, "PE" => 169, "PF" => 170, "PG" => 171, "PH" => 172, "PK" => 173, 111 | "PL" => 174, "PM" => 175, "PN" => 176, "PR" => 177, "PS" => 178, "PT" => 179, 112 | "PW" => 180, "PY" => 181, "QA" => 182, "RE" => 183, "RO" => 184, "RU" => 185, 113 | "RW" => 186, "SA" => 187, "SB" => 188, "SC" => 189, "SD" => 190, "SE" => 191, 114 | "SG" => 192, "SH" => 193, "SI" => 194, "SJ" => 195, "SK" => 196, "SL" => 197, 115 | "SM" => 198, "SN" => 199, "SO" => 200, "SR" => 201, "ST" => 202, "SV" => 203, 116 | "SY" => 204, "SZ" => 205, "TC" => 206, "TD" => 207, "TF" => 208, "TG" => 209, 117 | "TH" => 210, "TJ" => 211, "TK" => 212, "TM" => 213, "TN" => 214, "TO" => 215, 118 | "TL" => 216, "TR" => 217, "TT" => 218, "TV" => 219, "TW" => 220, "TZ" => 221, 119 | "UA" => 222, "UG" => 223, "UM" => 224, "US" => 225, "UY" => 226, "UZ" => 227, 120 | "VA" => 228, "VC" => 229, "VE" => 230, "VG" => 231, "VI" => 232, "VN" => 233, 121 | "VU" => 234, "WF" => 235, "WS" => 236, "YE" => 237, "YT" => 238, "RS" => 239, 122 | "ZA" => 240, "ZM" => 241, "ME" => 242, "ZW" => 243, "A1" => 244, "A2" => 245, 123 | "O1" => 246, "AX" => 247, "GG" => 248, "IM" => 249, "JE" => 250, "BL" => 251, 124 | "MF" => 252, "BQ" => 253, "SS" => 254 125 | ); 126 | var $GEOIP_COUNTRY_CODES = array( 127 | "","AP","EU","AD","AE","AF","AG","AI","AL","AM","CW", 128 | "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB", 129 | "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO", 130 | "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD", 131 | "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR", 132 | "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO", 133 | "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ", 134 | "FK","FM","FO","FR","SX","GA","GB","GD","GE","GF", 135 | "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT", 136 | "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID", 137 | "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO", 138 | "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW", 139 | "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT", 140 | "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML", 141 | "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV", 142 | "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI", 143 | "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF", 144 | "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW", 145 | "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD", 146 | "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO", 147 | "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH", 148 | "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW", 149 | "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE", 150 | "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA", 151 | "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE", 152 | "BL","MF", "BQ", "SS", "O1" ); 153 | var $GEOIP_COUNTRY_CODES3 = array( 154 | "","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","CUW", 155 | "AGO","ATA","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB", 156 | "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL", 157 | "BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK","COD", 158 | "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI", 159 | "CUB","CPV","CXR","CYP","CZE","DEU","DJI","DNK","DMA","DOM", 160 | "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI", 161 | "FLK","FSM","FRO","FRA","SXM","GAB","GBR","GRD","GEO","GUF", 162 | "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","SGS","GTM", 163 | "GUM","GNB","GUY","HKG","HMD","HND","HRV","HTI","HUN","IDN", 164 | "IRL","ISR","IND","IOT","IRQ","IRN","ISL","ITA","JAM","JOR", 165 | "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT", 166 | "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU", 167 | "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI", 168 | "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV", 169 | "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC", 170 | "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF", 171 | "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW", 172 | "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN", 173 | "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM", 174 | "SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF","TGO","THA", 175 | "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN", 176 | "TZA","UKR","UGA","UMI","USA","URY","UZB","VAT","VCT","VEN", 177 | "VGB","VIR","VNM","VUT","WLF","WSM","YEM","MYT","SRB","ZAF", 178 | "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY", 179 | "BLM","MAF", "BES", "SSD", "O1" 180 | ); 181 | var $GEOIP_COUNTRY_NAMES = array( 182 | "","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Curacao", 183 | "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados", 184 | "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia", 185 | "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the", 186 | "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica", 187 | "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic", 188 | "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji", 189 | "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana", 190 | "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala", 191 | "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia", 192 | "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan", 193 | "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait", 194 | "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania", 195 | "Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali", 196 | "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives", 197 | "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua", 198 | "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia", 199 | "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau", 200 | "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan", 201 | "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname", 202 | "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand", 203 | "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan", 204 | "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela", 205 | "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa", 206 | "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey", 207 | "Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba", 208 | "South Sudan", "Other" 209 | ); 210 | 211 | var $GEOIP_CONTINENT_CODES = array( 212 | "--", "AS","EU","EU","AS","AS","NA","NA","EU","AS","NA", 213 | "AF","AN","SA","OC","EU","OC","NA","AS","EU","NA", 214 | "AS","EU","AF","EU","AS","AF","AF","NA","AS","SA", 215 | "SA","NA","AS","AN","AF","EU","NA","NA","AS","AF", 216 | "AF","AF","EU","AF","OC","SA","AF","AS","SA","NA", 217 | "NA","AF","AS","AS","EU","EU","AF","EU","NA","NA", 218 | "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC", 219 | "SA","OC","EU","EU","NA","AF","EU","NA","AS","SA", 220 | "AF","EU","NA","AF","AF","NA","AF","EU","AN","NA", 221 | "OC","AF","SA","AS","AN","NA","EU","NA","EU","AS", 222 | "EU","AS","AS","AS","AS","AS","EU","EU","NA","AS", 223 | "AS","AF","AS","AS","OC","AF","NA","AS","AS","AS", 224 | "NA","AS","AS","AS","NA","EU","AS","AF","AF","EU", 225 | "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF", 226 | "AS","AS","AS","OC","NA","AF","NA","EU","AF","AS", 227 | "AF","NA","AS","AF","AF","OC","AF","OC","AF","NA", 228 | "EU","EU","AS","OC","OC","OC","AS","NA","SA","OC", 229 | "OC","AS","AS","EU","NA","OC","NA","AS","EU","OC", 230 | "SA","AS","AF","EU","EU","AF","AS","OC","AF","AF", 231 | "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF", 232 | "SA","AF","NA","AS","AF","NA","AF","AN","AF","AS", 233 | "AS","OC","AS","AF","OC","AS","EU","NA","OC","AS", 234 | "AF","EU","AF","OC","NA","SA","AS","EU","NA","SA", 235 | "NA","NA","AS","OC","OC","OC","AS","AF","EU","AF", 236 | "AF","EU","AF","--","--","--","EU","EU","EU","EU", 237 | "NA","NA","NA", "AF", "--" 238 | ); 239 | 240 | } 241 | function geoip_load_shared_mem ($file) { 242 | 243 | $fp = fopen($file, "rb"); 244 | if (!$fp) { 245 | print "error opening $file: $php_errormsg\n"; 246 | exit; 247 | } 248 | $s_array = fstat($fp); 249 | $size = $s_array['size']; 250 | if ($shmid = @shmop_open (GEOIP_SHM_KEY, "w", 0, 0)) { 251 | shmop_delete ($shmid); 252 | shmop_close ($shmid); 253 | } 254 | $shmid = shmop_open (GEOIP_SHM_KEY, "c", 0644, $size); 255 | shmop_write ($shmid, fread($fp, $size), 0); 256 | shmop_close ($shmid); 257 | } 258 | 259 | function _setup_segments($gi){ 260 | $gi->databaseType = GEOIP_COUNTRY_EDITION; 261 | $gi->record_length = STANDARD_RECORD_LENGTH; 262 | if ($gi->flags & GEOIP_SHARED_MEMORY) { 263 | $offset = @shmop_size ($gi->shmid) - 3; 264 | for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) { 265 | $delim = @shmop_read ($gi->shmid, $offset, 3); 266 | $offset += 3; 267 | if ($delim == (chr(255).chr(255).chr(255))) { 268 | $gi->databaseType = ord(@shmop_read ($gi->shmid, $offset, 1)); 269 | $offset++; 270 | 271 | if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){ 272 | $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0; 273 | } else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){ 274 | $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1; 275 | } else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)|| 276 | ($gi->databaseType == GEOIP_CITY_EDITION_REV1) 277 | || ($gi->databaseType == GEOIP_ORG_EDITION) 278 | || ($gi->databaseType == GEOIP_ORG_EDITION_V6) 279 | || ($gi->databaseType == GEOIP_DOMAIN_EDITION) 280 | || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6) 281 | || ($gi->databaseType == GEOIP_ISP_EDITION) 282 | || ($gi->databaseType == GEOIP_ISP_EDITION_V6) 283 | || ($gi->databaseType == GEOIP_USERTYPE_EDITION) 284 | || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6) 285 | || ($gi->databaseType == GEOIP_LOCATIONA_EDITION) 286 | || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION) 287 | || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6) 288 | || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6) 289 | || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1) 290 | || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6) 291 | || ($gi->databaseType == GEOIP_ASNUM_EDITION) 292 | || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)){ 293 | $gi->databaseSegments = 0; 294 | $buf = @shmop_read ($gi->shmid, $offset, SEGMENT_RECORD_LENGTH); 295 | for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){ 296 | $gi->databaseSegments += (ord($buf[$j]) << ($j * 8)); 297 | } 298 | if (($gi->databaseType == GEOIP_ORG_EDITION) 299 | || ($gi->databaseType == GEOIP_ORG_EDITION_V6) 300 | || ($gi->databaseType == GEOIP_DOMAIN_EDITION) 301 | || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6) 302 | || ($gi->databaseType == GEOIP_ISP_EDITION) 303 | || ($gi->databaseType == GEOIP_ISP_EDITION_V6)) { 304 | $gi->record_length = ORG_RECORD_LENGTH; 305 | } 306 | } 307 | break; 308 | } else { 309 | $offset -= 4; 310 | } 311 | } 312 | if (($gi->databaseType == GEOIP_COUNTRY_EDITION)|| 313 | ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)|| 314 | ($gi->databaseType == GEOIP_PROXY_EDITION)|| 315 | ($gi->databaseType == GEOIP_NETSPEED_EDITION)){ 316 | $gi->databaseSegments = GEOIP_COUNTRY_BEGIN; 317 | } 318 | } else { 319 | $filepos = ftell($gi->filehandle); 320 | fseek($gi->filehandle, -3, SEEK_END); 321 | for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) { 322 | $delim = fread($gi->filehandle,3); 323 | if ($delim == (chr(255).chr(255).chr(255))){ 324 | $gi->databaseType = ord(fread($gi->filehandle,1)); 325 | if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){ 326 | $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0; 327 | } 328 | else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){ 329 | $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1; 330 | } else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0) 331 | || ($gi->databaseType == GEOIP_CITY_EDITION_REV1) 332 | || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6) 333 | || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6) 334 | || ($gi->databaseType == GEOIP_ORG_EDITION) 335 | || ($gi->databaseType == GEOIP_DOMAIN_EDITION) 336 | || ($gi->databaseType == GEOIP_ISP_EDITION) 337 | || ($gi->databaseType == GEOIP_ORG_EDITION_V6) 338 | || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6) 339 | || ($gi->databaseType == GEOIP_ISP_EDITION_V6) 340 | || ($gi->databaseType == GEOIP_LOCATIONA_EDITION) 341 | || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION) 342 | || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6) 343 | || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6) 344 | || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1) 345 | || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6) 346 | || ($gi->databaseType == GEOIP_USERTYPE_EDITION) 347 | || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6) 348 | || ($gi->databaseType == GEOIP_ASNUM_EDITION) 349 | || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)){ 350 | $gi->databaseSegments = 0; 351 | $buf = fread($gi->filehandle,SEGMENT_RECORD_LENGTH); 352 | for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){ 353 | $gi->databaseSegments += (ord($buf[$j]) << ($j * 8)); 354 | } 355 | if ( ( $gi->databaseType == GEOIP_ORG_EDITION ) 356 | || ( $gi->databaseType == GEOIP_DOMAIN_EDITION ) 357 | || ( $gi->databaseType == GEOIP_ISP_EDITION ) 358 | || ( $gi->databaseType == GEOIP_ORG_EDITION_V6 ) 359 | || ( $gi->databaseType == GEOIP_DOMAIN_EDITION_V6 ) 360 | || ( $gi->databaseType == GEOIP_ISP_EDITION_V6 )) { 361 | $gi->record_length = ORG_RECORD_LENGTH; 362 | } 363 | } 364 | break; 365 | } else { 366 | fseek($gi->filehandle, -4, SEEK_CUR); 367 | } 368 | } 369 | if (($gi->databaseType == GEOIP_COUNTRY_EDITION)|| 370 | ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)|| 371 | ($gi->databaseType == GEOIP_PROXY_EDITION)|| 372 | ($gi->databaseType == GEOIP_NETSPEED_EDITION)){ 373 | $gi->databaseSegments = GEOIP_COUNTRY_BEGIN; 374 | } 375 | fseek($gi->filehandle,$filepos,SEEK_SET); 376 | } 377 | return $gi; 378 | } 379 | 380 | function geoip_open($filename, $flags) { 381 | $gi = new GeoIP; 382 | $gi->flags = $flags; 383 | if ($gi->flags & GEOIP_SHARED_MEMORY) { 384 | $gi->shmid = @shmop_open (GEOIP_SHM_KEY, "a", 0, 0); 385 | } else { 386 | $gi->filehandle = fopen($filename,"rb") or die( "Can not open $filename\n" ); 387 | if ($gi->flags & GEOIP_MEMORY_CACHE) { 388 | $s_array = fstat($gi->filehandle); 389 | $gi->memory_buffer = fread($gi->filehandle, $s_array['size']); 390 | } 391 | } 392 | 393 | $gi = _setup_segments($gi); 394 | return $gi; 395 | } 396 | 397 | function geoip_close($gi) { 398 | if ($gi->flags & GEOIP_SHARED_MEMORY) { 399 | return true; 400 | } 401 | 402 | return fclose($gi->filehandle); 403 | } 404 | 405 | function geoip_country_id_by_name_v6($gi, $name) { 406 | $rec = dns_get_record($name, DNS_AAAA); 407 | if ( !$rec ) { 408 | return false; 409 | } 410 | $addr = $rec[0]["ipv6"]; 411 | if (!$addr || $addr == $name) { 412 | return false; 413 | } 414 | return geoip_country_id_by_addr_v6($gi, $addr); 415 | } 416 | 417 | function geoip_country_id_by_name($gi, $name) { 418 | $addr = gethostbyname($name); 419 | if (!$addr || $addr == $name) { 420 | return false; 421 | } 422 | return geoip_country_id_by_addr($gi, $addr); 423 | } 424 | 425 | function geoip_country_code_by_name_v6($gi, $name) { 426 | $country_id = geoip_country_id_by_name_v6($gi,$name); 427 | if ($country_id !== false) { 428 | return $gi->GEOIP_COUNTRY_CODES[$country_id]; 429 | } 430 | return false; 431 | } 432 | 433 | function geoip_country_code_by_name($gi, $name) { 434 | $country_id = geoip_country_id_by_name($gi,$name); 435 | if ($country_id !== false) { 436 | return $gi->GEOIP_COUNTRY_CODES[$country_id]; 437 | } 438 | return false; 439 | } 440 | 441 | function geoip_country_name_by_name_v6($gi, $name) { 442 | $country_id = geoip_country_id_by_name_v6($gi,$name); 443 | if ($country_id !== false) { 444 | return $gi->GEOIP_COUNTRY_NAMES[$country_id]; 445 | } 446 | return false; 447 | } 448 | 449 | function geoip_country_name_by_name($gi, $name) { 450 | $country_id = geoip_country_id_by_name($gi,$name); 451 | if ($country_id !== false) { 452 | return $gi->GEOIP_COUNTRY_NAMES[$country_id]; 453 | } 454 | return false; 455 | } 456 | 457 | function geoip_country_id_by_addr_v6($gi, $addr) { 458 | $ipnum = inet_pton($addr); 459 | return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN; 460 | } 461 | 462 | function geoip_country_id_by_addr($gi, $addr) { 463 | $ipnum = ip2long($addr); 464 | return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN; 465 | } 466 | 467 | function geoip_country_code_by_addr_v6($gi, $addr) { 468 | $country_id = geoip_country_id_by_addr_v6($gi,$addr); 469 | if ($country_id !== false) { 470 | return $gi->GEOIP_COUNTRY_CODES[$country_id]; 471 | } 472 | return false; 473 | } 474 | 475 | function geoip_country_code_by_addr($gi, $addr) { 476 | if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) { 477 | $record = geoip_record_by_addr($gi,$addr); 478 | if ( $record !== false ) { 479 | return $record->country_code; 480 | } 481 | } else { 482 | $country_id = geoip_country_id_by_addr($gi,$addr); 483 | if ($country_id !== false) { 484 | return $gi->GEOIP_COUNTRY_CODES[$country_id]; 485 | } 486 | } 487 | return false; 488 | } 489 | 490 | function geoip_country_name_by_addr_v6($gi, $addr) { 491 | $country_id = geoip_country_id_by_addr_v6($gi,$addr); 492 | if ($country_id !== false) { 493 | return $gi->GEOIP_COUNTRY_NAMES[$country_id]; 494 | } 495 | return false; 496 | } 497 | 498 | function geoip_country_name_by_addr($gi, $addr) { 499 | if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) { 500 | $record = geoip_record_by_addr($gi,$addr); 501 | return $record->country_name; 502 | } else { 503 | $country_id = geoip_country_id_by_addr($gi,$addr); 504 | if ($country_id !== false) { 505 | return $gi->GEOIP_COUNTRY_NAMES[$country_id]; 506 | } 507 | } 508 | return false; 509 | } 510 | 511 | function _geoip_seek_country_v6($gi, $ipnum) { 512 | 513 | # arrays from unpack start with offset 1 514 | # yet another php mystery. array_merge work around 515 | # this broken behaviour 516 | $v6vec = array_merge(unpack( "C16", $ipnum)); 517 | 518 | $offset = 0; 519 | for ($depth = 127; $depth >= 0; --$depth) { 520 | if ($gi->flags & GEOIP_MEMORY_CACHE) { 521 | // workaround php's broken substr, strpos, etc handling with 522 | // mbstring.func_overload and mbstring.internal_encoding 523 | $enc = mb_internal_encoding(); 524 | mb_internal_encoding('ISO-8859-1'); 525 | 526 | $buf = substr($gi->memory_buffer, 527 | 2 * $gi->record_length * $offset, 528 | 2 * $gi->record_length); 529 | 530 | mb_internal_encoding($enc); 531 | } elseif ($gi->flags & GEOIP_SHARED_MEMORY) { 532 | $buf = @shmop_read ($gi->shmid, 533 | 2 * $gi->record_length * $offset, 534 | 2 * $gi->record_length ); 535 | } else { 536 | fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0 537 | or die("fseek failed"); 538 | $buf = fread($gi->filehandle, 2 * $gi->record_length); 539 | } 540 | $x = array(0,0); 541 | for ($i = 0; $i < 2; ++$i) { 542 | for ($j = 0; $j < $gi->record_length; ++$j) { 543 | $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8); 544 | } 545 | } 546 | 547 | $bnum = 127 - $depth; 548 | $idx = $bnum >> 3; 549 | $b_mask = 1 << ( $bnum & 7 ^ 7 ); 550 | if (($v6vec[$idx] & $b_mask) > 0) { 551 | if ($x[1] >= $gi->databaseSegments) { 552 | return $x[1]; 553 | } 554 | $offset = $x[1]; 555 | } else { 556 | if ($x[0] >= $gi->databaseSegments) { 557 | return $x[0]; 558 | } 559 | $offset = $x[0]; 560 | } 561 | } 562 | trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR); 563 | return false; 564 | } 565 | 566 | function _geoip_seek_country($gi, $ipnum) { 567 | $offset = 0; 568 | for ($depth = 31; $depth >= 0; --$depth) { 569 | if ($gi->flags & GEOIP_MEMORY_CACHE) { 570 | // workaround php's broken substr, strpos, etc handling with 571 | // mbstring.func_overload and mbstring.internal_encoding 572 | $enc = mb_internal_encoding(); 573 | mb_internal_encoding('ISO-8859-1'); 574 | 575 | $buf = substr($gi->memory_buffer, 576 | 2 * $gi->record_length * $offset, 577 | 2 * $gi->record_length); 578 | 579 | mb_internal_encoding($enc); 580 | } elseif ($gi->flags & GEOIP_SHARED_MEMORY) { 581 | $buf = @shmop_read ($gi->shmid, 582 | 2 * $gi->record_length * $offset, 583 | 2 * $gi->record_length ); 584 | } else { 585 | fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0 586 | or die("fseek failed"); 587 | $buf = fread($gi->filehandle, 2 * $gi->record_length); 588 | } 589 | $x = array(0,0); 590 | for ($i = 0; $i < 2; ++$i) { 591 | for ($j = 0; $j < $gi->record_length; ++$j) { 592 | $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8); 593 | } 594 | } 595 | if ($ipnum & (1 << $depth)) { 596 | if ($x[1] >= $gi->databaseSegments) { 597 | return $x[1]; 598 | } 599 | $offset = $x[1]; 600 | } else { 601 | if ($x[0] >= $gi->databaseSegments) { 602 | return $x[0]; 603 | } 604 | $offset = $x[0]; 605 | } 606 | } 607 | trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR); 608 | return false; 609 | } 610 | 611 | function _common_get_org($gi, $seek_org){ 612 | $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments; 613 | if ($gi->flags & GEOIP_SHARED_MEMORY) { 614 | $org_buf = @shmop_read ($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH); 615 | } else { 616 | fseek($gi->filehandle, $record_pointer, SEEK_SET); 617 | $org_buf = fread($gi->filehandle,MAX_ORG_RECORD_LENGTH); 618 | } 619 | // workaround php's broken substr, strpos, etc handling with 620 | // mbstring.func_overload and mbstring.internal_encoding 621 | $enc = mb_internal_encoding(); 622 | mb_internal_encoding('ISO-8859-1'); 623 | $org_buf = substr($org_buf, 0, strpos($org_buf, "\0")); 624 | mb_internal_encoding($enc); 625 | return $org_buf; 626 | } 627 | 628 | function _get_org_v6($gi,$ipnum){ 629 | $seek_org = _geoip_seek_country_v6($gi,$ipnum); 630 | if ($seek_org == $gi->databaseSegments) { 631 | return NULL; 632 | } 633 | return _common_get_org($gi, $seek_org); 634 | } 635 | 636 | function _get_org($gi,$ipnum){ 637 | $seek_org = _geoip_seek_country($gi,$ipnum); 638 | if ($seek_org == $gi->databaseSegments) { 639 | return NULL; 640 | } 641 | return _common_get_org($gi, $seek_org); 642 | } 643 | 644 | 645 | 646 | function geoip_name_by_addr_v6 ($gi,$addr) { 647 | if ($addr == NULL) { 648 | return 0; 649 | } 650 | $ipnum = inet_pton($addr); 651 | return _get_org_v6($gi, $ipnum); 652 | } 653 | 654 | function geoip_name_by_addr ($gi,$addr) { 655 | if ($addr == NULL) { 656 | return 0; 657 | } 658 | $ipnum = ip2long($addr); 659 | return _get_org($gi, $ipnum); 660 | } 661 | 662 | function geoip_org_by_addr ($gi,$addr) { 663 | return geoip_name_by_addr($gi, $addr); 664 | } 665 | 666 | function _get_region($gi,$ipnum){ 667 | if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){ 668 | $seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV0; 669 | if ($seek_region >= 1000){ 670 | $country_code = "US"; 671 | $region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65); 672 | } else { 673 | $country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region]; 674 | $region = ""; 675 | } 676 | return array ($country_code,$region); 677 | } else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1) { 678 | $seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV1; 679 | //print $seek_region; 680 | if ($seek_region < US_OFFSET){ 681 | $country_code = ""; 682 | $region = ""; 683 | } else if ($seek_region < CANADA_OFFSET) { 684 | $country_code = "US"; 685 | $region = chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65); 686 | } else if ($seek_region < WORLD_OFFSET) { 687 | $country_code = "CA"; 688 | $region = chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65); 689 | } else { 690 | $country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE]; 691 | $region = ""; 692 | } 693 | return array ($country_code,$region); 694 | } 695 | } 696 | 697 | function geoip_region_by_addr ($gi,$addr) { 698 | if ($addr == NULL) { 699 | return 0; 700 | } 701 | $ipnum = ip2long($addr); 702 | return _get_region($gi, $ipnum); 703 | } 704 | 705 | function getdnsattributes ($l,$ip){ 706 | $r = new Net_DNS_Resolver(); 707 | $r->nameservers = array("ws1.maxmind.com"); 708 | $p = $r->search($l."." . $ip .".s.maxmind.com","TXT","IN"); 709 | $str = is_object($p->answer[0])?$p->answer[0]->string():''; 710 | $str = substr( $str, 1, -1 ); 711 | return $str; 712 | } 713 | 714 | ?> 715 | -------------------------------------------------------------------------------- /lib/geoip-api-php/geoipcity.inc: -------------------------------------------------------------------------------- 1 | country_code = $value; 75 | } 76 | if ($key == "ci"){ 77 | $record->city = $value; 78 | } 79 | if ($key == "re"){ 80 | $record->region = $value; 81 | } 82 | if ($key == "ac"){ 83 | $record->areacode = $value; 84 | } 85 | if ($key == "dm" || $key == "me" ){ 86 | $record->dmacode = $value; 87 | $record->metrocode = $value; 88 | } 89 | if ($key == "is"){ 90 | $record->isp = $value; 91 | } 92 | if ($key == "or"){ 93 | $record->org = $value; 94 | } 95 | if ($key == "zi"){ 96 | $record->postal_code = $value; 97 | } 98 | if ($key == "la"){ 99 | $record->latitude = $value; 100 | } 101 | if ($key == "lo"){ 102 | $record->longitude = $value; 103 | } 104 | } 105 | $number = $GLOBALS['GEOIP_COUNTRY_CODE_TO_NUMBER'][$record->country_code]; 106 | $record->country_code3 = $GLOBALS['GEOIP_COUNTRY_CODES3'][$number]; 107 | $record->country_name = $GLOBALS['GEOIP_COUNTRY_NAMES'][$number]; 108 | if ($record->region != "") { 109 | if (($record->country_code == "US") || ($record->country_code == "CA")){ 110 | $record->regionname = $GLOBALS['ISO'][$record->country_code][$record->region]; 111 | } else { 112 | $record->regionname = $GLOBALS['FIPS'][$record->country_code][$record->region]; 113 | } 114 | } 115 | return $record; 116 | } 117 | 118 | 119 | function _get_record_v6($gi,$ipnum){ 120 | $seek_country = _geoip_seek_country_v6($gi,$ipnum); 121 | if ($seek_country == $gi->databaseSegments) { 122 | return NULL; 123 | } 124 | return _common_get_record($gi, $seek_country); 125 | } 126 | 127 | function _common_get_record($gi, $seek_country){ 128 | // workaround php's broken substr, strpos, etc handling with 129 | // mbstring.func_overload and mbstring.internal_encoding 130 | $enc = mb_internal_encoding(); 131 | mb_internal_encoding('ISO-8859-1'); 132 | 133 | $record_pointer = $seek_country + (2 * $gi->record_length - 1) * $gi->databaseSegments; 134 | 135 | if ($gi->flags & GEOIP_MEMORY_CACHE) { 136 | $record_buf = substr($gi->memory_buffer,$record_pointer,FULL_RECORD_LENGTH); 137 | } elseif ($gi->flags & GEOIP_SHARED_MEMORY){ 138 | $record_buf = @shmop_read($gi->shmid,$record_pointer,FULL_RECORD_LENGTH); 139 | } else { 140 | fseek($gi->filehandle, $record_pointer, SEEK_SET); 141 | $record_buf = fread($gi->filehandle,FULL_RECORD_LENGTH); 142 | } 143 | $record = new geoiprecord; 144 | $record_buf_pos = 0; 145 | $char = ord(substr($record_buf,$record_buf_pos,1)); 146 | $record->country_code = $gi->GEOIP_COUNTRY_CODES[$char]; 147 | $record->country_code3 = $gi->GEOIP_COUNTRY_CODES3[$char]; 148 | $record->country_name = $gi->GEOIP_COUNTRY_NAMES[$char]; 149 | $record->continent_code = $gi->GEOIP_CONTINENT_CODES[$char]; 150 | $record_buf_pos++; 151 | $str_length = 0; 152 | // Get region 153 | $char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); 154 | while ($char != 0){ 155 | $str_length++; 156 | $char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); 157 | } 158 | if ($str_length > 0){ 159 | $record->region = substr($record_buf,$record_buf_pos,$str_length); 160 | } 161 | $record_buf_pos += $str_length + 1; 162 | $str_length = 0; 163 | // Get city 164 | $char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); 165 | while ($char != 0){ 166 | $str_length++; 167 | $char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); 168 | } 169 | if ($str_length > 0){ 170 | $record->city = substr($record_buf,$record_buf_pos,$str_length); 171 | } 172 | $record_buf_pos += $str_length + 1; 173 | $str_length = 0; 174 | // Get postal code 175 | $char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); 176 | while ($char != 0){ 177 | $str_length++; 178 | $char = ord(substr($record_buf,$record_buf_pos+$str_length,1)); 179 | } 180 | if ($str_length > 0){ 181 | $record->postal_code = substr($record_buf,$record_buf_pos,$str_length); 182 | } 183 | $record_buf_pos += $str_length + 1; 184 | $str_length = 0; 185 | // Get latitude and longitude 186 | $latitude = 0; 187 | $longitude = 0; 188 | for ($j = 0;$j < 3; ++$j){ 189 | $char = ord(substr($record_buf,$record_buf_pos++,1)); 190 | $latitude += ($char << ($j * 8)); 191 | } 192 | $record->latitude = ($latitude/10000) - 180; 193 | for ($j = 0;$j < 3; ++$j){ 194 | $char = ord(substr($record_buf,$record_buf_pos++,1)); 195 | $longitude += ($char << ($j * 8)); 196 | } 197 | $record->longitude = ($longitude/10000) - 180; 198 | if (GEOIP_CITY_EDITION_REV1 == $gi->databaseType){ 199 | $metroarea_combo = 0; 200 | if ($record->country_code == "US"){ 201 | for ($j = 0;$j < 3;++$j){ 202 | $char = ord(substr($record_buf,$record_buf_pos++,1)); 203 | $metroarea_combo += ($char << ($j * 8)); 204 | } 205 | $record->metro_code = $record->dma_code = floor($metroarea_combo/1000); 206 | $record->area_code = $metroarea_combo%1000; 207 | } 208 | } 209 | mb_internal_encoding($enc); 210 | return $record; 211 | } 212 | 213 | function GeoIP_record_by_addr_v6 ($gi,$addr){ 214 | if ($addr == NULL){ 215 | return 0; 216 | } 217 | $ipnum = inet_pton($addr); 218 | return _get_record_v6($gi, $ipnum); 219 | } 220 | 221 | function _get_record($gi,$ipnum){ 222 | $seek_country = _geoip_seek_country($gi,$ipnum); 223 | if ($seek_country == $gi->databaseSegments) { 224 | return NULL; 225 | } 226 | return _common_get_record($gi, $seek_country); 227 | } 228 | 229 | function GeoIP_record_by_addr ($gi,$addr){ 230 | if ($addr == NULL){ 231 | return 0; 232 | } 233 | $ipnum = ip2long($addr); 234 | return _get_record($gi, $ipnum); 235 | } 236 | 237 | ?> 238 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample-v6.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 33 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 21 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_asn-v6.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 18 | 19 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_city-v6.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | country_code . " " . $record->country_code3 . " " . $record->country_name . "\n"; 22 | print $record->region . " " . $GEOIP_REGION_NAME[$record->country_code][$record->region] . "\n"; 23 | print $record->city . "\n"; 24 | print $record->postal_code . "\n"; 25 | print $record->latitude . "\n"; 26 | print $record->longitude . "\n"; 27 | print $record->metro_code . "\n"; 28 | print $record->area_code . "\n"; 29 | print $record->continent_code . "\n"; 30 | 31 | geoip_close($gi); 32 | 33 | ?> 34 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_city.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | country_code . " " . $record->country_code3 . " " . $record->country_name . "\n"; 22 | print $record->region . " " . $GEOIP_REGION_NAME[$record->country_code][$record->region] . "\n"; 23 | print $record->city . "\n"; 24 | print $record->postal_code . "\n"; 25 | print $record->latitude . "\n"; 26 | print $record->longitude . "\n"; 27 | print $record->metro_code . "\n"; 28 | print $record->area_code . "\n"; 29 | print $record->continent_code . "\n"; 30 | 31 | geoip_close($gi); 32 | 33 | ?> 34 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_distributed.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | country_code . "\n"; 19 | print "country code3: " . $r->country_code3 . "\n"; 20 | print "country name: " . $r->country_name . "\n"; 21 | print "city: " . $r->city . "\n"; 22 | print "region: " . $r->region . "\n"; 23 | print "region name: " . $r->regionname . "\n"; 24 | print "postal_code: " . $r->postal_code . "\n"; 25 | print "latitude: " . $r->latitude . "\n"; 26 | print "longitude: " . $r->longitude . "\n"; 27 | print "area code: " . $r->areacode . "\n"; 28 | print "dma code: " . $r->dmacode . "\n"; 29 | print "isp: " . $r->isp . "\n"; 30 | print "org: " . $r->org . "\n"; 31 | ?> 32 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_domain.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 17 | 18 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_netspeed.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 24 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_netspeedcell.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 15 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_org.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 23 | 24 | -------------------------------------------------------------------------------- /lib/geoip-api-php/sample_region.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 21 | -------------------------------------------------------------------------------- /lib/geoip-api-php/timezone/make_time_zone_php_code.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my $old_country; 6 | my $old_region; 7 | 8 | # Obtain timezone.txt from http://www.maxmind.com/timezone.txt 9 | open(FILE,"timezone.txt"); 10 | my $str = ; 11 | print ") { 16 | $str =~ s!\s*$!!; 17 | my ($country,$region,$timezone) = split("\t",$str); 18 | #print $country . "," . $region . "," . $timezone . "\n"; 19 | if ($country ne $old_country) { 20 | if ($old_region ne "") { 21 | print " }\n"; 22 | print " break;\n"; 23 | } 24 | print "case " . qq(") . $country . qq(") . ":\n"; 25 | if ($region ne "") { 26 | print " switch (\$region) {\n"; 27 | } 28 | } 29 | if ($region ne "") { 30 | print " case " . qq(") . $region . qq(") . ":\n "; 31 | } 32 | print qq( \$timezone = ") . $timezone . qq(") . ";\n"; 33 | if ($region ne "") { 34 | print " break;\n"; 35 | } else { 36 | print " break;\n"; 37 | } 38 | $old_country = $country; 39 | $old_region = $region; 40 | } 41 | print " }\n"; 42 | print " return \$timezone;\n"; 43 | 44 | print "}\n"; 45 | 46 | print "?>\n"; 47 | 48 | close(FILE); 49 | -------------------------------------------------------------------------------- /lib/geoip-api-php/timezone/test_timezone.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 6 | -------------------------------------------------------------------------------- /lib/geoip-api-php/timezone/timezone.php: -------------------------------------------------------------------------------- 1 | 2275 | -------------------------------------------------------------------------------- /wpml-geoip-browser-language-redirect.php: -------------------------------------------------------------------------------- 1 | redirect_user( $location . '&feedback=form_submission_error' ); 42 | } 43 | 44 | // Put whatever comes as country-language code combo into an array 45 | $data_for_option = array(); 46 | 47 | foreach( $_POST['language_mappings'] as $val ){ 48 | 49 | if( $val['country'] != 'country_code_ddown_label' ) { 50 | 51 | if( array_key_exists ( $val['country'] , $data_for_option ) ){ 52 | $this->redirect_user( $location . '&feedback=duplicate_key' ); 53 | } 54 | 55 | $data_for_option[ $val['country'] ] = $val['language']; 56 | } 57 | } 58 | 59 | 60 | // Remove any country code marked for removal 61 | if( isset( $_POST['remove_country_code'] ) ){ 62 | foreach( $_POST['remove_country_code'] as $country_code ){ 63 | unset( $data_for_option[$country_code] ); 64 | } 65 | } 66 | 67 | // Save in DB and redirect 68 | update_option( 'wpml_geo_redirect_default_language' , trim( $_POST['default_redirect_language'] ) ); 69 | update_option( 'wpml_geo_redirect_language_mappings' , $data_for_option ); 70 | 71 | $this->redirect_user( $location . '&feedback=success' ); 72 | } 73 | 74 | } 75 | 76 | 77 | function redirect_user( $location ){ 78 | header("Location: $location"); 79 | exit(); 80 | } 81 | 82 | 83 | function add_admin_page_wpml_geo_redirect(){ 84 | 85 | add_options_page( 86 | 'WPML GEO Redirect', 87 | 'WPML GEO Redirect', 88 | 'manage_options', 89 | 'wpml_geo_redirect_settings', 90 | array( $this, 'wpml_geo_redirect_admin_page' ) ); 91 | } 92 | 93 | 94 | function wpml_geo_redirect_admin_page(){ 95 | 96 | $this->set_wp_options_with_default_values_if_necessary(); 97 | 98 | $language_mappings = get_option( 'wpml_geo_redirect_language_mappings' ); 99 | $default_language = get_option( 'wpml_geo_redirect_default_language' ); 100 | 101 | include 'WPML_GEOIP_admin_page.class.php'; 102 | 103 | $admin_page = new WPML_geoip_admin_page( $language_mappings , $default_language ); 104 | $admin_page->display_wpml_geo_redirect_admin_page(); 105 | 106 | } 107 | 108 | private function set_wp_options_with_default_values_if_necessary(){ 109 | 110 | if ( null === get_option( 'wpml_geo_redirect_language_mappings' , null ) ) { 111 | $languages = apply_filters( 'wpml_active_languages', NULL, 'orderby=id&order=desc' ); 112 | 113 | if ( !empty( $languages ) ) { 114 | $arr = array_keys( $languages ); 115 | $default_language_mapping = array( 'SE' => $arr[0] ); 116 | add_option( 'wpml_geo_redirect_language_mappings' , $default_language_mapping ); 117 | } 118 | } 119 | if ( null === get_option( 'wpml_geo_redirect_default_language' , null ) ) { 120 | $default_language = apply_filters('wpml_default_language', NULL); 121 | add_option('wpml_geo_redirect_default_language', $default_language); 122 | } 123 | 124 | } 125 | 126 | 127 | /** Unload old browser redirect and add new one **/ 128 | function enqueue_scripts() 129 | { 130 | global $sitepress, $sitepress_settings; 131 | 132 | //De-register old script 133 | wp_deregister_script('wpml-browser-redirect'); 134 | 135 | //Register new one 136 | wp_enqueue_script('wpml-browser-redirect', plugins_url('js/browser-redirect-geoip.js', __FILE__) , array('jquery', 'jquery.cookie')); 137 | 138 | $args['skip_missing'] = intval($sitepress_settings['automatic_redirect'] == 1); 139 | 140 | //Build multi language urls array 141 | $languages = apply_filters( 'wpml_active_languages', null, $args ); 142 | $language_urls = array(); 143 | foreach($languages as $language) 144 | $language_urls[$language['language_code']] = $language['url']; 145 | 146 | //print_r($languages); 147 | 148 | //Cookie parameters 149 | $http_host = $_SERVER['HTTP_HOST'] == 'localhost' ? '' : $_SERVER['HTTP_HOST']; 150 | $cookie = array( 151 | 'name' => '_icl_visitor_lang_js', 152 | 'domain' => (defined('COOKIE_DOMAIN') && COOKIE_DOMAIN? COOKIE_DOMAIN : $http_host), 153 | 'path' => (defined('COOKIEPATH') && COOKIEPATH ? COOKIEPATH : '/'), 154 | 'expiration' => $sitepress_settings['remember_language'] 155 | ); 156 | 157 | 158 | // Send params to javascript 159 | $params = array( 160 | 'ajax_url' => plugins_url('ajax.php', __FILE__), 161 | 'cookie' => $cookie, 162 | 'pageLanguage' => defined('ICL_LANGUAGE_CODE')? ICL_LANGUAGE_CODE : get_bloginfo('language'), 163 | 'languageUrls' => $language_urls, 164 | ); 165 | 166 | //Let's add the data! 167 | wp_localize_script('wpml-browser-redirect', 'wpml_browser_redirect_params', $params); 168 | } 169 | 170 | /** 171 | * Register vars 172 | * 173 | * @param $vars 174 | * @return array 175 | */ 176 | function register_vars($vars) 177 | { 178 | $vars[] = 'wpml_geoip'; 179 | return $vars; 180 | } 181 | 182 | /** 183 | * Checks for our magic var and performs actual work. 184 | */ 185 | function register_endpoints() 186 | { 187 | if(intval(get_query_var('wpml_geoip')) == 1) 188 | { 189 | include('WPML_GeoIP_IPResolver.class.php'); 190 | $ipr = new WPML_GeoIP_IPResolver(); 191 | 192 | $ipr->set_json_header(); 193 | if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) { 194 | $tmp_ip_array = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); 195 | $tmp_ip = $tmp_ip_array[0]; 196 | } else { 197 | $tmp_ip = $_SERVER['REMOTE_ADDR']; 198 | } 199 | echo $ipr->ip_to_wpml_country_code($tmp_ip); 200 | die(); 201 | } 202 | } 203 | } 204 | 205 | $wpml_gblr = new WPML_GeoIP_Browser_Language_Redirect(); 206 | --------------------------------------------------------------------------------