├── composer.json ├── composer.lock ├── includes ├── class-wc-geolocation-based-products-admin.php ├── class-wc-geolocation-based-products-frontend.php └── class-wc-geolocation-based-products-geolocate.php ├── languages └── woocommerce-geolocation-based-products.pot ├── license.txt ├── plugin-assets ├── css │ └── admin.css └── js │ ├── admin-settings.js │ └── admin-settings.min.js ├── readme.txt ├── uninstall.php ├── vendor ├── autoload.php ├── composer │ ├── ClassLoader.php │ ├── LICENSE │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ ├── autoload_static.php │ └── installed.json ├── geoip2 │ └── geoip2 │ │ ├── .gitignore │ │ ├── .gitmodules │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.dev.md │ │ ├── README.md │ │ ├── bin │ │ └── benchmark.php │ │ ├── box.json │ │ ├── composer.json │ │ ├── dev-bin │ │ ├── phar-test.php │ │ └── release.sh │ │ ├── phar-stub.php │ │ ├── phpunit.xml.dist │ │ ├── src │ │ ├── Compat │ │ │ └── JsonSerializable.php │ │ ├── Database │ │ │ └── Reader.php │ │ ├── Exception │ │ │ ├── AddressNotFoundException.php │ │ │ ├── AuthenticationException.php │ │ │ ├── GeoIp2Exception.php │ │ │ ├── HttpException.php │ │ │ ├── InvalidRequestException.php │ │ │ └── OutOfQueriesException.php │ │ ├── Model │ │ │ ├── AbstractModel.php │ │ │ ├── AnonymousIp.php │ │ │ ├── City.php │ │ │ ├── ConnectionType.php │ │ │ ├── Country.php │ │ │ ├── Domain.php │ │ │ ├── Enterprise.php │ │ │ ├── Insights.php │ │ │ └── Isp.php │ │ ├── ProviderInterface.php │ │ ├── Record │ │ │ ├── AbstractPlaceRecord.php │ │ │ ├── AbstractRecord.php │ │ │ ├── City.php │ │ │ ├── Continent.php │ │ │ ├── Country.php │ │ │ ├── Location.php │ │ │ ├── MaxMind.php │ │ │ ├── Postal.php │ │ │ ├── RepresentedCountry.php │ │ │ ├── Subdivision.php │ │ │ └── Traits.php │ │ └── WebService │ │ │ └── Client.php │ │ └── tests │ │ ├── GeoIp2 │ │ └── Test │ │ │ ├── Database │ │ │ └── ReaderTest.php │ │ │ ├── Model │ │ │ ├── CountryTest.php │ │ │ ├── InsightsTest.php │ │ │ └── NameTest.php │ │ │ └── WebService │ │ │ └── ClientTest.php │ │ └── bootstrap.php ├── maxmind-db │ └── reader │ │ ├── .coveralls-phpunit.xml.dist │ │ ├── .gitignore │ │ ├── .gitmodules │ │ ├── .travis-build.sh │ │ ├── .travis-install-prereqs.sh │ │ ├── .travis-test.sh │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── composer.json │ │ ├── dev-bin │ │ └── make-release.sh │ │ ├── examples │ │ └── benchmark.php │ │ ├── ext │ │ ├── .uncrustify.cfg │ │ ├── config.m4 │ │ ├── maxminddb.c │ │ ├── php_maxminddb.h │ │ └── tests │ │ │ └── 001-load.phpt │ │ ├── phpunit.xml.dist │ │ ├── src │ │ └── MaxMind │ │ │ └── Db │ │ │ ├── Reader.php │ │ │ └── Reader │ │ │ ├── Decoder.php │ │ │ ├── InvalidDatabaseException.php │ │ │ ├── Metadata.php │ │ │ └── Util.php │ │ └── tests │ │ ├── MaxMind │ │ └── Db │ │ │ └── Test │ │ │ ├── Reader │ │ │ ├── DecoderTest.php │ │ │ └── PointerTest.php │ │ │ └── ReaderTest.php │ │ └── bootstrap.php └── maxmind │ └── web-service-common │ ├── .gitignore │ ├── .travis.yml │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── composer.json │ ├── phpunit.xml.dist │ ├── src │ ├── Exception │ │ ├── AuthenticationException.php │ │ ├── HttpException.php │ │ ├── InsufficientFundsException.php │ │ ├── InvalidInputException.php │ │ ├── InvalidRequestException.php │ │ ├── IpAddressNotFoundException.php │ │ └── WebServiceException.php │ └── WebService │ │ ├── Client.php │ │ ├── Http │ │ ├── CurlRequest.php │ │ ├── Request.php │ │ └── RequestFactory.php │ │ └── cacert.pem │ └── tests │ ├── MaxMind │ └── Test │ │ └── WebService │ │ ├── ClientTest.php │ │ └── Http │ │ └── CurlRequestTest.php │ └── bootstrap.php ├── woo-includes ├── class-wc-dependencies.php └── woo-functions.php └── woocommerce-geolocation-based-products.php /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roykho/woocommerce-geolocation-based-products", 3 | "authors": [ 4 | { 5 | "name": "roykho", 6 | "email": "roykho77@gmail.com" 7 | } 8 | ], 9 | "require": { 10 | "geoip2/geoip2": "~2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "df07f340c654dbde04b864589f6fccaa", 8 | "content-hash": "cedcc4355a8535c77f2dcd6b46ed7a6d", 9 | "packages": [ 10 | { 11 | "name": "geoip2/geoip2", 12 | "version": "v2.4.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/maxmind/GeoIP2-php.git", 16 | "reference": "2edce6957126399039124459174d5dce24edfdae" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/2edce6957126399039124459174d5dce24edfdae", 21 | "reference": "2edce6957126399039124459174d5dce24edfdae", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "maxmind-db/reader": "~1.0", 26 | "maxmind/web-service-common": "~0.0.3", 27 | "php": ">=5.3.1" 28 | }, 29 | "require-dev": { 30 | "phpunit/phpunit": "4.2.*", 31 | "squizlabs/php_codesniffer": "2.*" 32 | }, 33 | "type": "library", 34 | "autoload": { 35 | "psr-4": { 36 | "GeoIp2\\": "src" 37 | } 38 | }, 39 | "notification-url": "https://packagist.org/downloads/", 40 | "license": [ 41 | "Apache-2.0" 42 | ], 43 | "authors": [ 44 | { 45 | "name": "Gregory J. Oschwald", 46 | "email": "goschwald@maxmind.com", 47 | "homepage": "http://www.maxmind.com/" 48 | } 49 | ], 50 | "description": "MaxMind GeoIP2 PHP API", 51 | "homepage": "https://github.com/maxmind/GeoIP2-php", 52 | "keywords": [ 53 | "IP", 54 | "geoip", 55 | "geoip2", 56 | "geolocation", 57 | "maxmind" 58 | ], 59 | "time": "2016-04-15 19:49:51" 60 | }, 61 | { 62 | "name": "maxmind-db/reader", 63 | "version": "v1.1.0", 64 | "source": { 65 | "type": "git", 66 | "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", 67 | "reference": "1383655533aa2f13a990b27b075fdde8b7bdd5ff" 68 | }, 69 | "dist": { 70 | "type": "zip", 71 | "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/1383655533aa2f13a990b27b075fdde8b7bdd5ff", 72 | "reference": "1383655533aa2f13a990b27b075fdde8b7bdd5ff", 73 | "shasum": "" 74 | }, 75 | "require": { 76 | "php": ">=5.3.1" 77 | }, 78 | "require-dev": { 79 | "phpunit/phpunit": "4.2.*", 80 | "satooshi/php-coveralls": "dev-master", 81 | "squizlabs/php_codesniffer": "2.*" 82 | }, 83 | "type": "library", 84 | "autoload": { 85 | "psr-0": { 86 | "MaxMind": "src/" 87 | } 88 | }, 89 | "notification-url": "https://packagist.org/downloads/", 90 | "license": [ 91 | "Apache-2.0" 92 | ], 93 | "authors": [ 94 | { 95 | "name": "Gregory J. Oschwald", 96 | "email": "goschwald@maxmind.com", 97 | "homepage": "http://www.maxmind.com/" 98 | } 99 | ], 100 | "description": "MaxMind DB Reader API", 101 | "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", 102 | "keywords": [ 103 | "database", 104 | "geoip", 105 | "geoip2", 106 | "geolocation", 107 | "maxmind" 108 | ], 109 | "time": "2016-01-04 15:38:11" 110 | }, 111 | { 112 | "name": "maxmind/web-service-common", 113 | "version": "v0.0.4", 114 | "source": { 115 | "type": "git", 116 | "url": "https://github.com/maxmind/web-service-common-php.git", 117 | "reference": "f26fce5281290973beeeca3e33847887177dd138" 118 | }, 119 | "dist": { 120 | "type": "zip", 121 | "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/f26fce5281290973beeeca3e33847887177dd138", 122 | "reference": "f26fce5281290973beeeca3e33847887177dd138", 123 | "shasum": "" 124 | }, 125 | "require": { 126 | "ext-curl": "*", 127 | "ext-json": "*", 128 | "php": ">=5.3" 129 | }, 130 | "require-dev": { 131 | "phpunit/phpunit": "4.6.*" 132 | }, 133 | "type": "library", 134 | "autoload": { 135 | "psr-4": { 136 | "MaxMind\\": "src" 137 | } 138 | }, 139 | "notification-url": "https://packagist.org/downloads/", 140 | "license": [ 141 | "Apache-2.0" 142 | ], 143 | "authors": [ 144 | { 145 | "name": "Gregory Oschwald", 146 | "email": "goschwald@maxmind.com" 147 | } 148 | ], 149 | "description": "Internal MaxMind Web Service API", 150 | "homepage": "https://github.com/maxmind/mm-web-service-api-php", 151 | "time": "2015-07-21 20:07:31" 152 | } 153 | ], 154 | "packages-dev": [], 155 | "aliases": [], 156 | "minimum-stability": "stable", 157 | "stability-flags": [], 158 | "prefer-stable": false, 159 | "prefer-lowest": false, 160 | "platform": [], 161 | "platform-dev": [] 162 | } 163 | -------------------------------------------------------------------------------- /includes/class-wc-geolocation-based-products-geolocate.php: -------------------------------------------------------------------------------- 1 | 'http://icanhazip.com', 14 | 'ipify' => 'http://api.ipify.org/', 15 | 'ipecho' => 'http://ipecho.net/plain', 16 | 'ident' => 'http://ident.me', 17 | 'whatismyipaddress' => 'http://bot.whatismyipaddress.com', 18 | 'ip.appspot' => 'http://ip.appspot.com', 19 | ); 20 | 21 | /** 22 | * Constructor. 23 | * 24 | * @since 1.4.0 25 | * @version 1.5.4 26 | * @return bool 27 | */ 28 | public function __construct() { 29 | /** URL to the geolocation database we're using */ 30 | $this->geolocation_db = apply_filters( 'wc_geolocation_based_products_database', 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz' ); 31 | 32 | add_filter( 'cron_schedules', array( $this, 'add_weekly_cron_schedule' ) ); 33 | add_action( 'wc_glbp_db_update', array( $this, 'update_database' ) ); 34 | 35 | if ( ! wp_next_scheduled( 'wc_glbp_db_update' ) ) { 36 | wp_schedule_event( time(), 'weekly', 'wc_glbp_db_update' ); 37 | } 38 | 39 | if ( ! file_exists( self::get_local_city_database_path() ) ) { 40 | $this->update_database(); 41 | } 42 | 43 | return true; 44 | } 45 | 46 | /** 47 | * Adds custom weekly schedule to cron. 48 | * 49 | * @access public 50 | * @since 1.4.0 51 | * @version 1.4.0 52 | * @param array $schedules 53 | * @return array $schedules 54 | */ 55 | public function add_weekly_cron_schedule( $schedules ) { 56 | $schedules['weekly'] = array( 57 | 'interval' => WEEK_IN_SECONDS, 58 | 'display' => __( 'Once Weekly', 'woocommerce-geolocation-based-products' ), 59 | ); 60 | 61 | return $schedules; 62 | } 63 | 64 | /** 65 | * Get current user IP Address. 66 | * @return string 67 | */ 68 | public function get_ip_address() { 69 | if ( isset( $_SERVER['X-Real-IP'] ) ) { 70 | return $_SERVER['X-Real-IP']; 71 | } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { 72 | // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2 73 | // Make sure we always only send through the first IP in the list which should always be the client IP. 74 | return trim( current( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ); 75 | } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { 76 | return $_SERVER['REMOTE_ADDR']; 77 | } 78 | return ''; 79 | } 80 | 81 | /** 82 | * Get user IP Address using a service. 83 | * @return string 84 | */ 85 | public function get_external_ip_address() { 86 | $transient_name = 'external_ip_address_' . $this->get_ip_address(); 87 | $external_ip_address = get_transient( $transient_name ); 88 | 89 | if ( false === $external_ip_address ) { 90 | $external_ip_address = '0.0.0.0'; 91 | $ip_lookup_services = apply_filters( 'wc_geolocation_based_products_ip_lookup_apis', $this->ip_lookup_apis ); 92 | $ip_lookup_services_keys = array_keys( $ip_lookup_services ); 93 | shuffle( $ip_lookup_services_keys ); 94 | 95 | foreach ( $ip_lookup_services_keys as $service_name ) { 96 | $service_endpoint = $ip_lookup_services[ $service_name ]; 97 | $response = wp_safe_remote_get( $service_endpoint, array( 'timeout' => 2 ) ); 98 | 99 | if ( ! is_wp_error( $response ) && $response['body'] ) { 100 | $external_ip_address = apply_filters( 'wc_geolocation_based_products_ip_lookup_api_response', wc_clean( $response['body'] ), $service_name ); 101 | break; 102 | } 103 | } 104 | 105 | set_transient( $transient_name, $external_ip_address, WEEK_IN_SECONDS ); 106 | } 107 | 108 | return $external_ip_address; 109 | } 110 | 111 | /** 112 | * Geolocate an IP address. 113 | * @param string $ip_address 114 | * @param bool $fallback 115 | * @return array 116 | */ 117 | public function geolocate_ip( $ip_address = '', $fallback = true ) { 118 | $ip_address = $ip_address ? $ip_address : self::get_ip_address(); 119 | $city_reader = new Reader( self::get_local_city_database_path() ); 120 | 121 | if ( ( '::1' === $ip_address || '127:0:0:1' === $ip_address ) && $fallback ) { 122 | // May be a local environment - find external IP 123 | return $this->geolocate_ip( $this->get_external_ip_address(), false ); 124 | } 125 | 126 | $city_record = $city_reader->city( $ip_address ); 127 | 128 | $country = sanitize_text_field( strtoupper( $city_record->country->isoCode ) ); 129 | $city = sanitize_text_field( strtoupper( $city_record->city->name ) ); 130 | $region = sanitize_text_field( strtoupper( $city_record->mostSpecificSubdivision->isoCode ) ); 131 | 132 | return array( 133 | 'country_code' => $country, 134 | 'city' => $city, 135 | 'region_code' => $region, 136 | ); 137 | } 138 | 139 | /** 140 | * Path to our local db. 141 | * @return string 142 | */ 143 | private function get_local_city_database_path() { 144 | $upload_dir = wp_upload_dir(); 145 | 146 | return apply_filters( 'wc_geolocation_based_products_local_city_db_path', $upload_dir['basedir'] . '/geoip_city.dat' ); 147 | } 148 | 149 | /** 150 | * Update geoip database. Adapted from https://wordpress.org/plugins/geoip-detect/. 151 | */ 152 | public function update_database() { 153 | $logger = new WC_Logger(); 154 | 155 | if ( ! is_callable( 'gzopen' ) ) { 156 | $logger->add( 'wc_geolocation_based_products', 'Server does not support gzopen' ); 157 | return; 158 | } 159 | 160 | require_once( ABSPATH . 'wp-admin/includes/file.php' ); 161 | 162 | $tmp_databases = array( 163 | 'city' => download_url( $this->geolocation_db ), 164 | ); 165 | 166 | foreach ( $tmp_databases as $tmp_database_path ) { 167 | if ( ! is_wp_error( $tmp_database_path ) ) { 168 | $gzhandle = @gzopen( $tmp_database_path, 'r' ); 169 | 170 | $handle = @fopen( self::get_local_city_database_path(), 'w' ); 171 | 172 | if ( $gzhandle && $handle ) { 173 | while ( $string = gzread( $gzhandle, 4096 ) ) { 174 | fwrite( $handle, $string, strlen( $string ) ); 175 | } 176 | gzclose( $gzhandle ); 177 | fclose( $handle ); 178 | } else { 179 | $logger->add( 'wc_geolocation_based_products', 'Unable to open database file' ); 180 | } 181 | @unlink( $tmp_database_path ); 182 | } else { 183 | $logger->add( 'wc_geolocation_based_products', 'Unable to download GeoIP Database: ' . $tmp_database_path->get_error_message() ); 184 | } 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /plugin-assets/css/admin.css: -------------------------------------------------------------------------------- 1 | table.wc-glbp-settings.widefat td.product-categories, table.wc-glbp-settings.widefat td.products { 2 | overflow: visible; 3 | } 4 | 5 | .wc-glbp-categories { 6 | display: none; 7 | } 8 | 9 | .wc-glbp-sort::before { 10 | content: "\e032"; 11 | font-family: "woocommerce"; 12 | text-align: center; 13 | line-height: 1; 14 | width: 17px; 15 | display: block; 16 | height: 100%; 17 | color: #999; 18 | cursor: move; 19 | position: relative; 20 | top: 5px; 21 | } 22 | 23 | .wc-glbp-sort { 24 | vertical-align: center; 25 | } 26 | -------------------------------------------------------------------------------- /plugin-assets/js/admin-settings.js: -------------------------------------------------------------------------------- 1 | jQuery( document ).ready( function( $ ) { 2 | 'use strict'; 3 | 4 | // create namespace to avoid any possible conflicts 5 | $.wc_geolocation_based_products_admin = { 6 | runTipTip: function() { 7 | // Remove any lingering tooltips 8 | $( '#tiptip_holder' ).removeAttr( 'style' ); 9 | $( '#tiptip_arrow' ).removeAttr( 'style' ); 10 | $( '.woocommerce-help-tip' ).tipTip({ 11 | 'attribute': 'data-tip', 12 | 'fadeIn': 50, 13 | 'fadeOut': 50, 14 | 'delay': 200 15 | }); 16 | }, 17 | 18 | reInitRows: function() { 19 | // re-init row positions 20 | $( 'table.wc-glbp-settings' ).find( 'tr.entry' ).each( function( row ) { 21 | 22 | // reinit row position disable 23 | rowPos = String( $( 'input.wc-glbp-disable', this ).prop( 'name' ) ); 24 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 25 | 26 | $( 'input.wc-glbp-disable', this ).prop( 'name', replacedName ); 27 | 28 | // reinit row position country 29 | var rowPos = String( $( 'input.wc-glbp-country', this ).prop( 'name' ) ), 30 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 31 | 32 | $( 'input.wc-glbp-country', this ).prop( 'name', replacedName ); 33 | 34 | // reinit row position region 35 | rowPos = String( $( 'input.wc-glbp-region', this ).prop( 'name' ) ); 36 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 37 | 38 | $( 'input.wc-glbp-region', this ).prop( 'name', replacedName ); 39 | 40 | // reinit row position city 41 | rowPos = String( $( 'input.wc-glbp-city', this ).prop( 'name' ) ); 42 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 43 | 44 | $( 'input.wc-glbp-city', this ).prop( 'name', replacedName ); 45 | 46 | // reinit row position products 47 | rowPos = String( $( 'input.wc-glbp-products, select.wc-glbp-products', this ).prop( 'name' ) ); 48 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 49 | 50 | $( 'input.wc-glbp-products, select.wc-glbp-products', this ).prop( 'name', replacedName ); 51 | 52 | // reinit row position product categories 53 | rowPos = String( $( 'select.wc-glbp-categories', this ).prop( 'name' ) ); 54 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 55 | 56 | $( 'select.wc-glbp-categories', this ).prop( 'name', replacedName ); 57 | 58 | // reinit row position show hide 59 | rowPos = String( $( 'select.wc-glbp-show-hide', this ).prop( 'name' ) ); 60 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 61 | 62 | $( 'select.wc-glbp-show-hide', this ).prop( 'name', replacedName ); 63 | 64 | // reinit row position test 65 | rowPos = String( $( 'input.wc-glbp-test', this ).prop( 'name' ) ); 66 | replacedName = rowPos.replace( /row\[\d+\]/, 'row[' + row + ']' ); 67 | 68 | $( 'input.wc-glbp-test', this ).prop( 'name', replacedName ); 69 | }); 70 | 71 | $.wc_geolocation_based_products_admin.runSortable(); 72 | }, 73 | 74 | runSortable: function() { 75 | $( 'table.wc-glbp-settings tbody' ).sortable({ 76 | opacity: 0.5, 77 | tolerance: "pointer", 78 | update: function( event, ui ) { 79 | $.wc_geolocation_based_products_admin.reInitRows(); 80 | } 81 | }); 82 | }, 83 | 84 | init: function() { 85 | // add row 86 | $( 'table.wc-glbp-settings' ).on( 'click', '.wc-glbp-insert-row', function( e ) { 87 | e.preventDefault(); 88 | 89 | var table = $( this ).parents( 'table.wc-glbp-settings' ), 90 | row = ''; 91 | 92 | row += ''; 93 | row += ''; 94 | 95 | row += ''; 96 | row += ''; 97 | row += ''; 98 | 99 | row += ''; 100 | row += ''; 101 | row += ''; 102 | 103 | row += ''; 104 | row += ''; 105 | row += ''; 106 | 107 | row += ''; 108 | row += ''; 109 | row += ''; 110 | 111 | row += ''; 112 | row += ''; 113 | row += ''; 114 | 115 | row += ''; 116 | row += ''; 128 | row += ''; 129 | 130 | row += ''; 131 | 132 | if ( wc_geolocation_based_products_local.wc_pre_30 ) { 133 | row += ''; 134 | } else { 135 | row += ''; 136 | } 137 | 138 | row += ''; 139 | 140 | row += ''; 141 | row += ''; 145 | row += ''; 146 | 147 | row += ''; 148 | row += ''; 149 | row += ''; 150 | row += ''; 151 | 152 | // append row to table 153 | table.find( 'tbody' ).append( row ); 154 | 155 | // re-init select2 156 | $( document.body ).trigger( 'wc-enhanced-select-init' ); 157 | 158 | // re-init row positions 159 | $.wc_geolocation_based_products_admin.reInitRows(); 160 | }); 161 | 162 | // remove row 163 | $( 'table.wc-glbp-settings' ).on( 'click', '.wc-glbp-remove-row', function( e ) { 164 | e.preventDefault(); 165 | 166 | var table = $( this ).parents( 'table.wc-glbp-settings' ); 167 | 168 | table.find( '.wc-glbp-remove-row-cb:checked' ).each( function() { 169 | // if last row, don't delete just remove options 170 | if ( table.find( 'tr.entry' ).length === 1 ) { 171 | // remove checkmark 172 | table.find( '.wc-glbp-remove-row-cb' ).prop( 'checked', false ); 173 | table.find( '.wc-glbp-test' ).prop( 'checked', false ); 174 | table.find( '.wc-glbp-disable' ).prop( 'checked', false ); 175 | 176 | // remove country field value 177 | table.find( '.wc-glbp-country' ).val( '' ); 178 | 179 | // remove region field value 180 | table.find( '.wc-glbp-region' ).val( '' ); 181 | 182 | // remove city field value 183 | table.find( '.wc-glbp-city' ).val( '' ); 184 | 185 | // reset select options 186 | table.find( 'select.wc-product-search' ).select2( 'val', '' ); 187 | 188 | // reset select options 189 | table.find( 'select.wc-enhanced-select' ).select2( 'val', '' ); 190 | } else { 191 | $( this ).parents( 'tr.entry' ).eq( 0 ).remove(); 192 | } 193 | }); 194 | 195 | // re-init row positions 196 | $.wc_geolocation_based_products_admin.reInitRows(); 197 | }); 198 | 199 | // test checkbox toggles 200 | $( 'table.wc-glbp-settings' ).on( 'click', '.wc-glbp-test', function() { 201 | // remove checkmark from all 202 | $( this ).parents( 'table.wc-glbp-settings' ).find( '.wc-glbp-test' ).not( this ).prop( 'checked', false ); 203 | 204 | return true; 205 | }); 206 | 207 | $.wc_geolocation_based_products_admin.runTipTip(); 208 | $.wc_geolocation_based_products_admin.runSortable(); 209 | } 210 | }; // close namespace 211 | 212 | // run init 213 | $.wc_geolocation_based_products_admin.init(); 214 | // end document ready 215 | }); 216 | -------------------------------------------------------------------------------- /plugin-assets/js/admin-settings.min.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function(a){"use strict";a.wc_geolocation_based_products_admin={runTipTip:function(){a("#tiptip_holder").removeAttr("style"),a("#tiptip_arrow").removeAttr("style"),a(".woocommerce-help-tip").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:200})},reInitRows:function(){a("table.wc-glbp-settings").find("tr.entry").each(function(b){c=String(a("input.wc-glbp-disable",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]"),a("input.wc-glbp-disable",this).prop("name",d);var c=String(a("input.wc-glbp-country",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]");a("input.wc-glbp-country",this).prop("name",d),c=String(a("input.wc-glbp-region",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]"),a("input.wc-glbp-region",this).prop("name",d),c=String(a("input.wc-glbp-city",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]"),a("input.wc-glbp-city",this).prop("name",d),c=String(a("input.wc-glbp-products, select.wc-glbp-products",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]"),a("input.wc-glbp-products, select.wc-glbp-products",this).prop("name",d),c=String(a("select.wc-glbp-categories",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]"),a("select.wc-glbp-categories",this).prop("name",d),c=String(a("select.wc-glbp-show-hide",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]"),a("select.wc-glbp-show-hide",this).prop("name",d),c=String(a("input.wc-glbp-test",this).prop("name")),d=c.replace(/row\[\d+\]/,"row["+b+"]"),a("input.wc-glbp-test",this).prop("name",d)}),a.wc_geolocation_based_products_admin.runSortable()},runSortable:function(){a("table.wc-glbp-settings tbody").sortable({opacity:.5,tolerance:"pointer",update:function(b,c){a.wc_geolocation_based_products_admin.reInitRows()}})},init:function(){a("table.wc-glbp-settings").on("click",".wc-glbp-insert-row",function(b){b.preventDefault();var c=a(this).parents("table.wc-glbp-settings"),d="";d+='',d+='',d+='',d+='',d+="",d+='',d+='',d+="",d+='',d+='',d+="",d+='',d+='',d+="",d+='',d+='',d+="",d+='',d+='",d+="",d+='',wc_geolocation_based_products_local.wc_pre_30?d+='':d+='',d+="",d+='',d+='",d+="",d+='',d+='',d+="",d+="",c.find("tbody").append(d),a(document.body).trigger("wc-enhanced-select-init"),a.wc_geolocation_based_products_admin.reInitRows()}),a("table.wc-glbp-settings").on("click",".wc-glbp-remove-row",function(b){b.preventDefault();var c=a(this).parents("table.wc-glbp-settings");c.find(".wc-glbp-remove-row-cb:checked").each(function(){1===c.find("tr.entry").length?(c.find(".wc-glbp-remove-row-cb").prop("checked",!1),c.find(".wc-glbp-test").prop("checked",!1),c.find(".wc-glbp-disable").prop("checked",!1),c.find(".wc-glbp-country").val(""),c.find(".wc-glbp-region").val(""),c.find(".wc-glbp-city").val(""),c.find("select.wc-product-search").select2("val",""),c.find("select.wc-enhanced-select").select2("val","")):a(this).parents("tr.entry").eq(0).remove()}),a.wc_geolocation_based_products_admin.reInitRows()}),a("table.wc-glbp-settings").on("click",".wc-glbp-test",function(){return a(this).parents("table.wc-glbp-settings").find(".wc-glbp-test").not(this).prop("checked",!1),!0}),a.wc_geolocation_based_products_admin.runTipTip(),a.wc_geolocation_based_products_admin.runSortable()}},a.wc_geolocation_based_products_admin.init()}); -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === WooCommerce Geolocation Based Products === 2 | Contributors: royho 3 | Tags: woocommerce, products, conditional products, location, geolocation, roy ho 4 | Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TPFCAQV2VEQE2 5 | WordPress requires at least: 3.9.1 6 | Tested up to: 4.9 7 | WooCommerce requires at least: 2.5.0 8 | Stable tag: 1.5.4 9 | Author URI: https://royho.me 10 | Plugin URI: https://wordpress.org/plugins/woocommerce-geolocation-based-products/ 11 | License: GPLv3 12 | License URI: http://www.gnu.org/licenses/gpl-3.0.html 13 | 14 | A WooCommerce plugin/extension that adds ability for your store to show/hide products based on visitors geolocation. 15 | 16 | == Description == 17 | 18 | This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com 19 | 20 | A WooCommerce plugin/extension that adds ability for your store to show/hide products based on visitors geolocation. 21 | 22 | You can add many different countries in which you want the settings to apply to. You do this by adding a rule and setting the 2 letter ISO country code in which you want to apply to. For example "US". You then can set which products and categories to show/hide. You may select more than one for each rule. 23 | 24 | You can also add a region. For example if you want to target anyone that is in the US and in California, you would enter the region code of CA for California. 25 | 26 | Furthermore, you can also filter by city. For example if you want to target anyone that is in the US and California but also in the city of Los Angeles, you would enter the city name Los Angeles in the field. 27 | 28 | You can also test out your settings as if you're visiting the site from another country. Enabling the testmode on a particular rule, your site will hide/show the products/categories per the rules of that row. Please note that you will need to use this especially when you're testing this on localhost as that IP may not always be valid. Be sure to turn off testmode when done testing and ready to go live. 29 | 30 | There is no active support for this plugin however you can post your questions to https://wordpress.org/support/plugin/woocommerce-geolocation-based-products. 31 | 32 | If you want to contribute or want to file a repeatable bug, please go to https://github.com/roykho/woocommerce-geolocation-based-products 33 | 34 | == Installation == 35 | 36 | = Minimum Requirements = 37 | 38 | * WordPress 3.9.1 or greater 39 | * PHP version 5.4.0 or greater 40 | * WooCommerce 2.5.0 or greater 41 | 42 | 1. Be sure WooCommerce plugin is already installed. 43 | 2. Upload the folder `woocommerce-geolocation-based-products` to the `/wp-content/plugins/` directory 44 | 3. Activate the plugin through the 'Plugins' menu in WordPress 45 | 4. Click on settings link to get to the settings page or get to the settings page by clicking on Geolocation link under WooCommerce Products Menu. 46 | 47 | = Note = 48 | 49 | Rules that are towards the bottom will supercede the rules above it. You can drag and drop the rules to rearrange the order. 50 | 51 | You can test each individual rule by checking the "test" checkbox. This will simulate your current location to match what is set for that rule. 52 | 53 | This plugin utilizes the MaxMind GeoIP API and thus will store a copy of the database on your site. This makes for a better experience for users. The API will download the database once a week to refresh any updated geolocation data. 54 | 55 | == Frequently Asked Questions == 56 | 57 | = This plugin does not seem to working = 58 | 59 | This plugin utilizes the IP address of the visitor to obtain location information. If this IP is somehow blocked or is unknown, there is no way for this plugin to know which country the visitor is from. Also this plugin may not show expected results if you have a caching plugin. 60 | 61 | = Where do I get support? = 62 | 63 | You can post your support question here https://wordpress.org/support/plugin/woocommerce-geolocation-based-products 64 | 65 | = How can I contribute or file a repeatable bug? = 66 | 67 | You can post a GitHub issue here https://github.com/roykho/woocommerce-geolocation-based-products 68 | 69 | == Screenshots == 70 | 71 | 1. This screen shot shows the options. 72 | 73 | == Upgrade Notice == 74 | 75 | = 1.5.4 = 76 | * Fix - Filter rules not working product filter widgets. 77 | * New - Filter to change the db path "wc_geolocation_based_products_local_city_db_path". 78 | * New - Filter to change the db URL "wc_geolocation_based_products_database". 79 | 80 | == Changelog == 81 | 82 | = 1.5.4 = 83 | * Fix - Filter rules not working product filter widgets. 84 | * New - Filter to change the db path "wc_geolocation_based_products_local_city_db_path". 85 | * New - Filter to change the db URL "wc_geolocation_based_products_database". 86 | 87 | = 1.5.3 = 88 | * Fix - Undefined index in product category widget. 89 | * Fix - WC 30 Compatibility. 90 | 91 | = 1.5.2 | 06-28-2016 = 92 | * Fix - Test mode not working. 93 | 94 | = 1.5.1 | 06-01-2016 = 95 | * Tweak - Performance. 96 | * Add - Show/hide ability when using featured products shortcode. 97 | 98 | = 1.5.0 | 05-02-2016 = 99 | * Add - Ability to show and hide products and categories by location 100 | 101 | = 1.4.1 | 04-30-2016 = 102 | * Update - Missing Vendor folder when uploading to repo 103 | 104 | = 1.4.0 | 04-29-2016 = 105 | * Update - Removed freegeoip infavor of MaxMind GeoIP 106 | * Update - Removed Chosen for Select2 107 | 108 | = 1.3.2 | 09-13-2015 = 109 | * Fix - Related, crosssell and upsell products were not hiding 110 | 111 | = 1.3.1 | 07-11-2015 = 112 | * Fix - Suppress error when geoip API returning an error at times 113 | * Fix - Category widget count sometimes displays a warning when debug is on 114 | 115 | = 1.3.0 | 06-25-2015 = 116 | * Removed - IP check API from ip-api.com 117 | * Added - IP check API from https://freegeoip.net 118 | 119 | = 1.2.0 | 04-30-2015 = 120 | * Fix - Excluded product categories showing in WooCommerce product category widget 121 | * Fix - Excluded products showing in WooCommerce products widget ( Fixed from WooCommerce 2.4 ) 122 | * Fix - Product category count was not updated from the excluded products and product categories 123 | * Fix - Tooltip was no longer popping up after WC 2.3 124 | * Fix - Hide excluded products and product categories from menus 125 | * Added - POT file 126 | 127 | = 1.1.3 | 12-29-2014 = 128 | * Update - Cleaned up code 129 | 130 | = 1.1.2 | 9-02-2014 = 131 | * Added - Instance variable for instance targetting 132 | 133 | = 1.1.1 | 8-27-2014 = 134 | * Added - missing dependency files to check WC active 135 | 136 | = 1.1.0 | 8-2-2014 = 137 | * Added - Ability to geolocate by region 138 | * Added - Ability to geolocate by city 139 | * Update - Test mode is now against each individual row of settings 140 | 141 | = 1.0.0 = 142 | Release 143 | -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/maxmind-db/reader/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/maxmind/web-service-common/src'), 10 | 'GeoIp2\\' => array($vendorDir . '/geoip2/geoip2/src'), 11 | ); 12 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | $path) { 33 | $loader->set($namespace, $path); 34 | } 35 | 36 | $map = require __DIR__ . '/autoload_psr4.php'; 37 | foreach ($map as $namespace => $path) { 38 | $loader->setPsr4($namespace, $path); 39 | } 40 | 41 | $classMap = require __DIR__ . '/autoload_classmap.php'; 42 | if ($classMap) { 43 | $loader->addClassMap($classMap); 44 | } 45 | } 46 | 47 | $loader->register(true); 48 | 49 | return $loader; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | =5.3" 21 | }, 22 | "require-dev": { 23 | "phpunit/phpunit": "4.6.*" 24 | }, 25 | "time": "2015-07-21 20:07:31", 26 | "type": "library", 27 | "installation-source": "dist", 28 | "autoload": { 29 | "psr-4": { 30 | "MaxMind\\": "src" 31 | } 32 | }, 33 | "notification-url": "https://packagist.org/downloads/", 34 | "license": [ 35 | "Apache-2.0" 36 | ], 37 | "authors": [ 38 | { 39 | "name": "Gregory Oschwald", 40 | "email": "goschwald@maxmind.com" 41 | } 42 | ], 43 | "description": "Internal MaxMind Web Service API", 44 | "homepage": "https://github.com/maxmind/mm-web-service-api-php" 45 | }, 46 | { 47 | "name": "maxmind-db/reader", 48 | "version": "v1.1.0", 49 | "version_normalized": "1.1.0.0", 50 | "source": { 51 | "type": "git", 52 | "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", 53 | "reference": "1383655533aa2f13a990b27b075fdde8b7bdd5ff" 54 | }, 55 | "dist": { 56 | "type": "zip", 57 | "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/1383655533aa2f13a990b27b075fdde8b7bdd5ff", 58 | "reference": "1383655533aa2f13a990b27b075fdde8b7bdd5ff", 59 | "shasum": "" 60 | }, 61 | "require": { 62 | "php": ">=5.3.1" 63 | }, 64 | "require-dev": { 65 | "phpunit/phpunit": "4.2.*", 66 | "satooshi/php-coveralls": "dev-master", 67 | "squizlabs/php_codesniffer": "2.*" 68 | }, 69 | "time": "2016-01-04 15:38:11", 70 | "type": "library", 71 | "installation-source": "dist", 72 | "autoload": { 73 | "psr-0": { 74 | "MaxMind": "src/" 75 | } 76 | }, 77 | "notification-url": "https://packagist.org/downloads/", 78 | "license": [ 79 | "Apache-2.0" 80 | ], 81 | "authors": [ 82 | { 83 | "name": "Gregory J. Oschwald", 84 | "email": "goschwald@maxmind.com", 85 | "homepage": "http://www.maxmind.com/" 86 | } 87 | ], 88 | "description": "MaxMind DB Reader API", 89 | "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", 90 | "keywords": [ 91 | "database", 92 | "geoip", 93 | "geoip2", 94 | "geolocation", 95 | "maxmind" 96 | ] 97 | }, 98 | { 99 | "name": "geoip2/geoip2", 100 | "version": "v2.4.0", 101 | "version_normalized": "2.4.0.0", 102 | "source": { 103 | "type": "git", 104 | "url": "https://github.com/maxmind/GeoIP2-php.git", 105 | "reference": "2edce6957126399039124459174d5dce24edfdae" 106 | }, 107 | "dist": { 108 | "type": "zip", 109 | "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/2edce6957126399039124459174d5dce24edfdae", 110 | "reference": "2edce6957126399039124459174d5dce24edfdae", 111 | "shasum": "" 112 | }, 113 | "require": { 114 | "maxmind-db/reader": "~1.0", 115 | "maxmind/web-service-common": "~0.0.3", 116 | "php": ">=5.3.1" 117 | }, 118 | "require-dev": { 119 | "phpunit/phpunit": "4.2.*", 120 | "squizlabs/php_codesniffer": "2.*" 121 | }, 122 | "time": "2016-04-15 19:49:51", 123 | "type": "library", 124 | "installation-source": "dist", 125 | "autoload": { 126 | "psr-4": { 127 | "GeoIp2\\": "src" 128 | } 129 | }, 130 | "notification-url": "https://packagist.org/downloads/", 131 | "license": [ 132 | "Apache-2.0" 133 | ], 134 | "authors": [ 135 | { 136 | "name": "Gregory J. Oschwald", 137 | "email": "goschwald@maxmind.com", 138 | "homepage": "http://www.maxmind.com/" 139 | } 140 | ], 141 | "description": "MaxMind GeoIP2 PHP API", 142 | "homepage": "https://github.com/maxmind/GeoIP2-php", 143 | "keywords": [ 144 | "IP", 145 | "geoip", 146 | "geoip2", 147 | "geolocation", 148 | "maxmind" 149 | ] 150 | } 151 | ] 152 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .gh-pages 3 | .idea 4 | GeoLite2-City.mmdb 5 | apigen.phar 6 | box.phar 7 | build 8 | composer.lock 9 | composer.phar 10 | phpunit.xml 11 | geoip2.phar 12 | geoip2-php.sublime-* 13 | t.php 14 | vendor/ 15 | *.sw? 16 | *.old 17 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "maxmind-db"] 2 | path = maxmind-db 3 | url = git://github.com/maxmind/MaxMind-DB.git 4 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | sudo: false 3 | language: php 4 | php: 5 | - '5.3' 6 | - '5.4' 7 | - '5.5' 8 | - '5.6' 9 | - '7.0' 10 | - hhvm 11 | - nightly 12 | matrix: 13 | allow_failures: 14 | - php: nightly 15 | before_install: 16 | - composer install --dev -n --prefer-source 17 | - phpenv rehash 18 | script: 19 | - mkdir -p build/logs 20 | - ./vendor/bin/phpcs --standard=PSR2 src/ 21 | - ./vendor/bin/phpunit -c phpunit.xml.dist 22 | after_script: 23 | - php vendor/bin/coveralls 24 | notifications: 25 | email: 26 | on_failure: always 27 | on_success: change 28 | recipients: 29 | - dev-ci@maxmind.com 30 | slack: 31 | rooms: 32 | secure: "OtowN1lGa5MAhn6gl87aB3kXXeOKLGIb4e9dBud/tPt/1sQDoZVj6m6VWtpsXh6iXL7lWetVbpmeZCydSRumgVMIy7+45uMQPvdoWBFCT+rq67yDb3gyvFknpjBuit0Q91lTDoGTUSgtqk+PSZX5LvDgT4b8WQFBb/dcB35hqis=\n" 33 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 2.4.0 (2016-04-15) 5 | ------------------ 6 | 7 | * Added support for the GeoIP2 Enterprise database. 8 | 9 | 2.3.3 (2015-09-24) 10 | ------------------ 11 | 12 | * Corrected case on `JsonSerializable` interface. Reported by Axel Etcheverry. 13 | Fixes #56. 14 | 15 | 2.3.2 (2015-09-23) 16 | ------------------ 17 | 18 | * `JsonSerializable` compatibility interface was moved to `GeoIp2\Compat` 19 | rather than the global namespace to prevent autoloading issues. Reported by 20 | Tomas Buteler. GitHub #54. 21 | * Missing documentation for the `$postal` property was added to the 22 | `GeoIp2\Model\City` class. Fix by Roy Sindre Norangshol. GitHub #51. 23 | * In the Phar distribution, source files for this module no longer have their 24 | documentation stripped, allowing IDE introspection to work properly. 25 | Reported by Dominic Black. GitHub #52. 26 | 27 | 2.3.1 (2015-06-30) 28 | ------------------ 29 | 30 | * Updated `maxmind/web-service-common` to version with fixes for PHP 5.3 and 31 | 5.4. 32 | 33 | 2.3.0 (2015-06-29) 34 | ------------------ 35 | 36 | * Support for demographics fields `averageIncome` and `populationDensity` in 37 | the `Location` record, returned by the Insights endpoint. 38 | * The `isAnonymousProxy` and `isSatelliteProvider` properties on 39 | `GeoIP2\Record\Traits` have been deprecated. Please use our [GeoIP2 40 | Anonymous IP database](https://www.maxmind.com/en/geoip2-anonymous-ip-database) 41 | to determine whether an IP address is used by an anonymizing service. 42 | 43 | 2.2.0-beta1 (2015-06-09) 44 | ------------------------ 45 | 46 | * Typo fix in documentation. 47 | 48 | 2.2.0-alpha2 (2015-06-01) 49 | ------------------------- 50 | 51 | * `maxmind-ws/web-service-common` was renamed to `maxmind/web-service-common`. 52 | 53 | 2.2.0-alpha1 (2015-05-22) 54 | ------------------------- 55 | 56 | * The library no longer uses Guzzle and instead uses curl directly. 57 | * Support for `timeout` and `connectTimout` were added to the `$options` array 58 | passed to the `GeoIp2\WebService\Client` constructor. Pull request by Will 59 | Bradley. GitHub #36. 60 | 61 | 2.1.1 (2014-12-03) 62 | ------------------ 63 | 64 | * The 2.1.0 Phar builds included a shebang line, causing issues when loading 65 | it as a library. This has been corrected. GitHub #33. 66 | 67 | 2.1.0 (2014-10-29) 68 | ------------------ 69 | 70 | * Update ApiGen dependency to version that isn't broken on case sensitive 71 | file systems. 72 | * Added support for the GeoIP2 Anonymous IP database. The 73 | `GeoIP2\Database\Reader` class now has an `anonymousIp` method which returns 74 | a `GeoIP2\Model\AnonymousIp` object. 75 | * Boolean attributes like those in the `GeoIP2\Record\Traits` class now return 76 | `false` instead of `null` when they were not true. 77 | 78 | 2.0.0 (2014-09-22) 79 | ------------------ 80 | 81 | * First production release. 82 | 83 | 0.9.0 (2014-09-15) 84 | ------------------ 85 | 86 | * IMPORTANT: The deprecated `omni()` and `cityIspOrg()` methods have been 87 | removed from `GeoIp2\WebService\Client`. 88 | 89 | 0.8.1 (2014-09-12) 90 | ------------------ 91 | 92 | * The check added to the `GeoIP2\Database\Reader` lookup methods in 0.8.0 did 93 | not work with the GeoIP2 City Database Subset by Continent with World 94 | Countries. This has been fixed. Fixes GitHub issue #23. 95 | 96 | 0.8.0 (2014-09-10) 97 | ------------------ 98 | 99 | * The `GeoIp2\Database\Reader` lookup methods (e.g., `city()`, `isp()`) now 100 | throw a `BadMethodCallException` if they are used with a database that 101 | does not match the method. In particular, doing a `city()` lookup on a 102 | GeoIP2 Country database will result in an exception, and vice versa. 103 | * A `metadata()` method has been added to the `GeoIP2\Database\Reader` class. 104 | This returns a `MaxMind\Db\Reader\Metadata` class with information about the 105 | database. 106 | * The name attribute was missing from the RepresentedCountry class. 107 | 108 | 0.7.0 (2014-07-22) 109 | ------------------ 110 | 111 | * The web service client API has been updated for the v2.1 release of the web 112 | service. In particular, the `cityIspOrg` and `omni` methods on 113 | `GeoIp2\WebService\Client` should be considered deprecated. The `city` 114 | method now provides all of the data formerly provided by `cityIspOrg`, and 115 | the `omni` method has been replaced by the `insights` method. 116 | * Support was added for GeoIP2 Connection Type, Domain and ISP databases. 117 | 118 | 119 | 0.6.3 (2014-05-12) 120 | ------------------ 121 | 122 | * With the previous Phar builds, some users received `phar error: invalid url 123 | or non-existent phar` errors. The correct alias is now used for the Phar, 124 | and this should no longer be an issue. 125 | 126 | 0.6.2 (2014-05-08) 127 | ------------------ 128 | 129 | * The Phar build was broken with Guzzle 3.9.0+. This has been fixed. 130 | 131 | 0.6.1 (2014-05-01) 132 | ------------------ 133 | 134 | * This API now officially supports HHVM. 135 | * The `maxmind-db/reader` dependency was updated to a version that does not 136 | require BC Math. 137 | * The Composer compatibility autoload rules are now targeted more narrowly. 138 | * A `box.json` file is included to build a Phar package. 139 | 140 | 0.6.0 (2014-02-19) 141 | ------------------ 142 | 143 | * This API is now licensed under the Apache License, Version 2.0. 144 | * Model and record classes now implement `JsonSerializable`. 145 | * `isset` now works with model and record classes. 146 | 147 | 0.5.0 (2013-10-21) 148 | ------------------ 149 | 150 | * Renamed $languages constructor parameters to $locales for both the Client 151 | and Reader classes. 152 | * Documentation and code clean-up (Ben Morel). 153 | * Added the interface `GeoIp2\ProviderInterface`, which is implemented by both 154 | `\GeoIp2\Database\Reader` and `\GeoIp2\WebService\Client`. 155 | 156 | 0.4.0 (2013-07-16) 157 | ------------------ 158 | 159 | * This is the first release with the GeoIP2 database reader. Please see the 160 | `README.md` file and the `\GeoIp2\Database\Reader` class. 161 | * The general exception classes were replaced with specific exception classes 162 | representing particular types of errors, such as an authentication error. 163 | 164 | 0.3.0 (2013-07-12) 165 | ------------------ 166 | 167 | * In namespaces and class names, "GeoIP2" was renamed to "GeoIp2" to improve 168 | consistency. 169 | 170 | 0.2.1 (2013-06-10) 171 | ------------------ 172 | 173 | * First official beta release. 174 | * Documentation updates and corrections. 175 | 176 | 0.2.0 (2013-05-29) 177 | ------------------ 178 | 179 | * `GenericException` was renamed to `GeoIP2Exception`. 180 | * We now support more languages. The new languages are de, es, fr, and pt-BR. 181 | * The REST API now returns a record with data about your account. There is 182 | a new `GeoIP\Records\MaxMind` class for this data. 183 | * The `continentCode` attribute on `Continent` was renamed to `code`. 184 | * Documentation updates. 185 | 186 | 0.1.1 (2013-05-14) 187 | ------------------ 188 | 189 | * Updated Guzzle version requirement. 190 | * Fixed Composer example in README.md. 191 | 192 | 193 | 0.1.0 (2013-05-13) 194 | ------------------ 195 | 196 | * Initial release. 197 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/README.dev.md: -------------------------------------------------------------------------------- 1 | Steps for releasing: 2 | 3 | 1. Update CHANGELOG.md with release and date. 4 | 2. Run `./dev-bin/release.sh`. This will build the phar, generate the docs, 5 | tag the release, and push it to origin. 6 | 3. Visit the [GitHub Releases page](https://github.com/maxmind/GeoIP2-php/releases) 7 | and update the release with the change and upload the `geoip2.phar` file 8 | to the release. 9 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/bin/benchmark.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 3 | city($ip); 17 | } catch (AddressNotFoundException $e) { 18 | } 19 | if ($i % 1000 == 0) { 20 | print($i . ' ' . $ip . "\n"); 21 | } 22 | } 23 | $endTime = microtime(true); 24 | 25 | $duration = $endTime - $startTime; 26 | print('Requests per second: ' . $count / $duration . "\n"); 27 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/box.json: -------------------------------------------------------------------------------- 1 | { 2 | "alias": "geoip2.phar", 3 | "main": "phar-stub.php", 4 | "output": "geoip2.phar", 5 | "compactors": [ 6 | "Herrera\\Box\\Compactor\\Composer", 7 | "Herrera\\Box\\Compactor\\Json", 8 | "Herrera\\Box\\Compactor\\Php" 9 | ], 10 | "files": [ 11 | "LICENSE" 12 | ], 13 | "finder": [ 14 | { 15 | "name": [ 16 | "LICENSE", 17 | "LICENSE.*", 18 | "*.php", 19 | "*.pem", 20 | "*.pem.md5" 21 | ], 22 | "exclude": [ 23 | "phpunit", 24 | "satooshi", 25 | "Tests", 26 | "tests", 27 | "yaml" 28 | ], 29 | "in": "vendor" 30 | } 31 | ], 32 | "finder-bin": [ 33 | { 34 | "name": [ 35 | "*.php" 36 | ], 37 | "in": "src" 38 | } 39 | ], 40 | "git-version": "git-version", 41 | "shebang": false, 42 | "stub": true 43 | } 44 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geoip2/geoip2", 3 | "description": "MaxMind GeoIP2 PHP API", 4 | "keywords": ["geoip", "geoip2", "geolocation", "ip", "maxmind"], 5 | "homepage": "https://github.com/maxmind/GeoIP2-php", 6 | "type": "library", 7 | "license": "Apache-2.0", 8 | "authors": [ 9 | { 10 | "name": "Gregory J. Oschwald", 11 | "email": "goschwald@maxmind.com", 12 | "homepage": "http://www.maxmind.com/" 13 | } 14 | ], 15 | "require": { 16 | "maxmind-db/reader": "~1.0", 17 | "maxmind/web-service-common": "~0.0.3", 18 | "php": ">=5.3.1" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "4.2.*", 22 | "squizlabs/php_codesniffer": "2.*" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "GeoIp2\\": "src" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/dev-bin/phar-test.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | city('81.2.69.160'); 9 | 10 | if ( $record->country->isoCode === 'GB' ) { 11 | exit(0); 12 | } 13 | 14 | print('Problem with Phar!'); 15 | exit(1); 16 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/dev-bin/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | VERSION=$(perl -MFile::Slurp::Tiny=read_file -MDateTime <now->ymd eq \$2; 10 | say \$1; 11 | EOF 12 | ) 13 | 14 | TAG="v$VERSION" 15 | 16 | if [ -f geoip2.phar ]; then 17 | rm geoip2.phar 18 | fi 19 | 20 | if [ -n "$(git status --porcelain)" ]; then 21 | echo ". is not clean." >&2 22 | exit 1 23 | fi 24 | 25 | if [ -d vendor ]; then 26 | rm -fr vendor 27 | fi 28 | 29 | php composer.phar self-update 30 | php composer.phar update --no-dev 31 | 32 | perl -pi -e "s/(?<=const VERSION = ').+?(?=';)/$TAG/g" src/WebService/Client.php 33 | 34 | if [ ! -f box.phar ]; then 35 | wget -O box.phar "https://github.com/box-project/box2/releases/download/2.5.0/box-2.5.0.phar" 36 | fi 37 | 38 | php box.phar build 39 | 40 | PHAR_TEST=$(./dev-bin/phar-test.php) 41 | if [[ -n $PHAR_TEST ]]; then 42 | echo "Phar test outputed non-empty string: $PHAR_TEST" 43 | exit 1 44 | fi 45 | 46 | # Download test deps 47 | php composer.phar update 48 | 49 | ./vendor/bin/phpunit 50 | 51 | if [ ! -d .gh-pages ]; then 52 | echo "Checking out gh-pages in .gh-pages" 53 | git clone -b gh-pages git@github.com:maxmind/GeoIP2-php.git .gh-pages 54 | pushd .gh-pages 55 | else 56 | echo "Updating .gh-pages" 57 | pushd .gh-pages 58 | git pull 59 | fi 60 | 61 | if [ -n "$(git status --porcelain)" ]; then 62 | echo ".gh-pages is not clean" >&2 63 | exit 1 64 | fi 65 | 66 | # We no longer have apigen as a dependency in Composer as releases are 67 | # sporadically deleted upstream and compatibility is often broken on patch 68 | # releases. 69 | if [ ! -f apigen.phar ]; then 70 | wget -O apigen.phar "https://github.com/apigen/apigen/releases/download/v4.0.0-RC3/apigen-4.0.0-RC3.phar" 71 | fi 72 | 73 | 74 | cat < apigen.neon 75 | destination: doc/$TAG 76 | 77 | source: 78 | - ../src 79 | 80 | title: "GeoIP2 PHP API $TAG" 81 | EOF 82 | 83 | php apigen.phar generate 84 | 85 | 86 | PAGE=index.md 87 | cat < $PAGE 88 | --- 89 | layout: default 90 | title: MaxMind GeoIP2 PHP API 91 | language: php 92 | version: $TAG 93 | --- 94 | 95 | EOF 96 | 97 | cat ../README.md >> $PAGE 98 | 99 | git add doc/ 100 | git commit -m "Updated for $TAG" -a 101 | 102 | read -e -p "Push to origin? " SHOULD_PUSH 103 | 104 | if [ "$SHOULD_PUSH" != "y" ]; then 105 | echo "Aborting" 106 | exit 1 107 | fi 108 | 109 | # If we don't push directly to github, the page doesn't get built for some 110 | # reason. 111 | git push git@github.com:maxmind/GeoIP2-php.git 112 | git push 113 | 114 | popd 115 | 116 | git add src/WebService/Client.php 117 | git commit -m 'update version number' 118 | git tag -a $TAG 119 | git push 120 | git push --tags 121 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/phar-stub.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ./tests/GeoIp2/Test/ 7 | 8 | 9 | 10 | 11 | 12 | ./src/GeoIp2/ 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Compat/JsonSerializable.php: -------------------------------------------------------------------------------- 1 | dbReader = new DbReader($filename); 53 | $this->locales = $locales; 54 | } 55 | 56 | /** 57 | * This method returns a GeoIP2 City model. 58 | * 59 | * @param string $ipAddress IPv4 or IPv6 address as a string. 60 | * 61 | * @return \GeoIp2\Model\City 62 | * 63 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 64 | * not in the database. 65 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 66 | * is corrupt or invalid 67 | */ 68 | public function city($ipAddress) 69 | { 70 | return $this->modelFor('City', 'City', $ipAddress); 71 | } 72 | 73 | /** 74 | * This method returns a GeoIP2 Country model. 75 | * 76 | * @param string $ipAddress IPv4 or IPv6 address as a string. 77 | * 78 | * @return \GeoIp2\Model\Country 79 | * 80 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 81 | * not in the database. 82 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 83 | * is corrupt or invalid 84 | */ 85 | public function country($ipAddress) 86 | { 87 | return $this->modelFor('Country', 'Country', $ipAddress); 88 | } 89 | 90 | /** 91 | * This method returns a GeoIP2 Anonymous IP model. 92 | * 93 | * @param string $ipAddress IPv4 or IPv6 address as a string. 94 | * 95 | * @return \GeoIp2\Model\AnonymousIp 96 | * 97 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 98 | * not in the database. 99 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 100 | * is corrupt or invalid 101 | */ 102 | public function anonymousIp($ipAddress) 103 | { 104 | return $this->flatModelFor( 105 | 'AnonymousIp', 106 | 'GeoIP2-Anonymous-IP', 107 | $ipAddress 108 | ); 109 | } 110 | 111 | /** 112 | * This method returns a GeoIP2 Connection Type model. 113 | * 114 | * @param string $ipAddress IPv4 or IPv6 address as a string. 115 | * 116 | * @return \GeoIp2\Model\ConnectionType 117 | * 118 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 119 | * not in the database. 120 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 121 | * is corrupt or invalid 122 | */ 123 | public function connectionType($ipAddress) 124 | { 125 | return $this->flatModelFor( 126 | 'ConnectionType', 127 | 'GeoIP2-Connection-Type', 128 | $ipAddress 129 | ); 130 | } 131 | 132 | /** 133 | * This method returns a GeoIP2 Domain model. 134 | * 135 | * @param string $ipAddress IPv4 or IPv6 address as a string. 136 | * 137 | * @return \GeoIp2\Model\Domain 138 | * 139 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 140 | * not in the database. 141 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 142 | * is corrupt or invalid 143 | */ 144 | public function domain($ipAddress) 145 | { 146 | return $this->flatModelFor( 147 | 'Domain', 148 | 'GeoIP2-Domain', 149 | $ipAddress 150 | ); 151 | } 152 | 153 | /** 154 | * This method returns a GeoIP2 Enterprise model. 155 | * 156 | * @param string $ipAddress IPv4 or IPv6 address as a string. 157 | * 158 | * @return \GeoIp2\Model\Enterprise 159 | * 160 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 161 | * not in the database. 162 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 163 | * is corrupt or invalid 164 | */ 165 | public function enterprise($ipAddress) 166 | { 167 | return $this->modelFor('Enterprise', 'Enterprise', $ipAddress); 168 | } 169 | 170 | /** 171 | * This method returns a GeoIP2 ISP model. 172 | * 173 | * @param string $ipAddress IPv4 or IPv6 address as a string. 174 | * 175 | * @return \GeoIp2\Model\Isp 176 | * 177 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address is 178 | * not in the database. 179 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database 180 | * is corrupt or invalid 181 | */ 182 | public function isp($ipAddress) 183 | { 184 | return $this->flatModelFor( 185 | 'Isp', 186 | 'GeoIP2-ISP', 187 | $ipAddress 188 | ); 189 | } 190 | 191 | private function modelFor($class, $type, $ipAddress) 192 | { 193 | $record = $this->getRecord($class, $type, $ipAddress); 194 | 195 | $record['traits']['ip_address'] = $ipAddress; 196 | $class = "GeoIp2\\Model\\" . $class; 197 | 198 | return new $class($record, $this->locales); 199 | } 200 | 201 | private function flatModelFor($class, $type, $ipAddress) 202 | { 203 | $record = $this->getRecord($class, $type, $ipAddress); 204 | 205 | $record['ip_address'] = $ipAddress; 206 | $class = "GeoIp2\\Model\\" . $class; 207 | 208 | return new $class($record); 209 | } 210 | 211 | private function getRecord($class, $type, $ipAddress) 212 | { 213 | if (strpos($this->metadata()->databaseType, $type) === false) { 214 | $method = lcfirst($class); 215 | throw new \BadMethodCallException( 216 | "The $method method cannot be used to open a " 217 | . $this->metadata()->databaseType . " database" 218 | ); 219 | } 220 | $record = $this->dbReader->get($ipAddress); 221 | if ($record === null) { 222 | throw new AddressNotFoundException( 223 | "The address $ipAddress is not in the database." 224 | ); 225 | } 226 | return $record; 227 | } 228 | 229 | /** 230 | * @throws \InvalidArgumentException if arguments are passed to the method. 231 | * @throws \BadMethodCallException if the database has been closed. 232 | * @return \MaxMind\Db\Reader\Metadata object for the database. 233 | */ 234 | public function metadata() 235 | { 236 | return $this->dbReader->metadata(); 237 | } 238 | 239 | /** 240 | * Closes the GeoIP2 database and returns the resources to the system. 241 | */ 242 | public function close() 243 | { 244 | $this->dbReader->close(); 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Exception/AddressNotFoundException.php: -------------------------------------------------------------------------------- 1 | uri = $uri; 23 | parent::__construct($message, $httpStatus, $previous); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Exception/InvalidRequestException.php: -------------------------------------------------------------------------------- 1 | error = $error; 24 | parent::__construct($message, $httpStatus, $uri, $previous); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Exception/OutOfQueriesException.php: -------------------------------------------------------------------------------- 1 | raw = $raw; 20 | } 21 | 22 | /** 23 | * @ignore 24 | */ 25 | protected function get($field) 26 | { 27 | if (isset($this->raw[$field])) { 28 | return $this->raw[$field]; 29 | } else { 30 | if (preg_match('/^is_/', $field)) { 31 | return false; 32 | } else { 33 | return null; 34 | } 35 | } 36 | } 37 | 38 | /** 39 | * @ignore 40 | */ 41 | public function __get($attr) 42 | { 43 | if ($attr != "instance" && property_exists($this, $attr)) { 44 | return $this->$attr; 45 | } 46 | 47 | throw new \RuntimeException("Unknown attribute: $attr"); 48 | } 49 | 50 | /** 51 | * @ignore 52 | */ 53 | public function __isset($attr) 54 | { 55 | return $attr != "instance" && isset($this->$attr); 56 | } 57 | 58 | public function jsonSerialize() 59 | { 60 | return $this->raw; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Model/AnonymousIp.php: -------------------------------------------------------------------------------- 1 | isAnonymous = $this->get('is_anonymous'); 44 | $this->isAnonymousVpn = $this->get('is_anonymous_vpn'); 45 | $this->isHostingProvider = $this->get('is_hosting_provider'); 46 | $this->isPublicProxy = $this->get('is_public_proxy'); 47 | $this->isTorExitNode = $this->get('is_tor_exit_node'); 48 | $this->ipAddress = $this->get('ip_address'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Model/City.php: -------------------------------------------------------------------------------- 1 | city = new \GeoIp2\Record\City($this->get('city'), $locales); 84 | $this->location = new \GeoIp2\Record\Location($this->get('location')); 85 | $this->postal = new \GeoIp2\Record\Postal($this->get('postal')); 86 | 87 | $this->createSubdivisions($raw, $locales); 88 | } 89 | 90 | private function createSubdivisions($raw, $locales) 91 | { 92 | if (!isset($raw['subdivisions'])) { 93 | return; 94 | } 95 | 96 | foreach ($raw['subdivisions'] as $sub) { 97 | array_push( 98 | $this->subdivisions, 99 | new \GeoIp2\Record\Subdivision($sub, $locales) 100 | ); 101 | } 102 | } 103 | 104 | /** 105 | * @ignore 106 | */ 107 | public function __get($attr) 108 | { 109 | if ($attr == 'mostSpecificSubdivision') { 110 | return $this->$attr(); 111 | } else { 112 | return parent::__get($attr); 113 | } 114 | } 115 | 116 | private function mostSpecificSubdivision() 117 | { 118 | return empty($this->subdivisions) ? 119 | new \GeoIp2\Record\Subdivision(array(), $this->locales) : 120 | end($this->subdivisions); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Model/ConnectionType.php: -------------------------------------------------------------------------------- 1 | connectionType = $this->get('connection_type'); 29 | $this->ipAddress = $this->get('ip_address'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Model/Country.php: -------------------------------------------------------------------------------- 1 | continent = new \GeoIp2\Record\Continent( 53 | $this->get('continent'), 54 | $locales 55 | ); 56 | $this->country = new \GeoIp2\Record\Country( 57 | $this->get('country'), 58 | $locales 59 | ); 60 | $this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind')); 61 | $this->registeredCountry = new \GeoIp2\Record\Country( 62 | $this->get('registered_country'), 63 | $locales 64 | ); 65 | $this->representedCountry = new \GeoIp2\Record\RepresentedCountry( 66 | $this->get('represented_country'), 67 | $locales 68 | ); 69 | $this->traits = new \GeoIp2\Record\Traits($this->get('traits')); 70 | 71 | $this->locales = $locales; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Model/Domain.php: -------------------------------------------------------------------------------- 1 | domain = $this->get('domain'); 29 | $this->ipAddress = $this->get('ip_address'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Model/Enterprise.php: -------------------------------------------------------------------------------- 1 | autonomousSystemNumber = $this->get('autonomous_system_number'); 38 | $this->autonomousSystemOrganization = 39 | $this->get('autonomous_system_organization'); 40 | $this->isp = $this->get('isp'); 41 | $this->organization = $this->get('organization'); 42 | 43 | $this->ipAddress = $this->get('ip_address'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/ProviderInterface.php: -------------------------------------------------------------------------------- 1 | locales = $locales; 15 | parent::__construct($record); 16 | } 17 | 18 | /** 19 | * @ignore 20 | */ 21 | public function __get($attr) 22 | { 23 | if ($attr == 'name') { 24 | return $this->name(); 25 | } else { 26 | return parent::__get($attr); 27 | } 28 | } 29 | 30 | private function name() 31 | { 32 | foreach ($this->locales as $locale) { 33 | if (isset($this->names[$locale])) { 34 | return $this->names[$locale]; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Record/AbstractRecord.php: -------------------------------------------------------------------------------- 1 | record = isset($record) ? $record : array(); 17 | } 18 | 19 | /** 20 | * @ignore 21 | */ 22 | public function __get($attr) 23 | { 24 | // XXX - kind of ugly but greatly reduces boilerplate code 25 | $key = $this->attributeToKey($attr); 26 | 27 | if ($this->__isset($attr)) { 28 | return $this->record[$key]; 29 | } elseif ($this->validAttribute($attr)) { 30 | if (preg_match('/^is_/', $key)) { 31 | return false; 32 | } else { 33 | return null; 34 | } 35 | } else { 36 | throw new \RuntimeException("Unknown attribute: $attr"); 37 | } 38 | } 39 | 40 | public function __isset($attr) 41 | { 42 | return $this->validAttribute($attr) && 43 | isset($this->record[$this->attributeToKey($attr)]); 44 | } 45 | 46 | private function attributeToKey($attr) 47 | { 48 | return strtolower(preg_replace('/([A-Z])/', '_\1', $attr)); 49 | } 50 | 51 | private function validAttribute($attr) 52 | { 53 | return in_array($attr, $this->validAttributes); 54 | } 55 | 56 | public function jsonSerialize() 57 | { 58 | return $this->record; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Record/City.php: -------------------------------------------------------------------------------- 1 | military 29 | * but this could expand to include other types in the future. 30 | */ 31 | class RepresentedCountry extends Country 32 | { 33 | protected $validAttributes = array( 34 | 'confidence', 35 | 'geonameId', 36 | 'isoCode', 37 | 'names', 38 | 'type' 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/Record/Subdivision.php: -------------------------------------------------------------------------------- 1 | The user type associated with the IP 66 | * address. This can be one of the following values:

67 | *
    68 | *
  • business 69 | *
  • cafe 70 | *
  • cellular 71 | *
  • college 72 | *
  • content_delivery_network 73 | *
  • dialup 74 | *
  • government 75 | *
  • hosting 76 | *
  • library 77 | *
  • military 78 | *
  • residential 79 | *
  • router 80 | *
  • school 81 | *
  • search_engine_spider 82 | *
  • traveler 83 | *
84 | *

85 | * This attribute is only available from the Insights web service end 86 | * point and the GeoIP2 Enterprise database. 87 | *

88 | */ 89 | class Traits extends AbstractRecord 90 | { 91 | /** 92 | * @ignore 93 | */ 94 | protected $validAttributes = array( 95 | 'autonomousSystemNumber', 96 | 'autonomousSystemOrganization', 97 | 'connectionType', 98 | 'domain', 99 | 'isAnonymousProxy', 100 | 'isLegitimateProxy', 101 | 'isSatelliteProvider', 102 | 'isp', 103 | 'ipAddress', 104 | 'organization', 105 | 'userType' 106 | ); 107 | } 108 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/src/WebService/Client.php: -------------------------------------------------------------------------------- 1 | locales = $locales; 72 | 73 | // This is for backwards compatibility. Do not remove except for a 74 | // major version bump. 75 | if (is_string($options)) { 76 | $options = array( 'host' => $options ); 77 | } 78 | 79 | if (!isset($options['host'])) { 80 | $options['host'] = 'geoip.maxmind.com'; 81 | } 82 | 83 | $options['userAgent'] = $this->userAgent(); 84 | 85 | $this->client = new WsClient($userId, $licenseKey, $options); 86 | } 87 | 88 | private function userAgent() 89 | { 90 | return 'GeoIP2-API/' . Client::VERSION; 91 | } 92 | 93 | /** 94 | * This method calls the GeoIP2 Precision: City endpoint. 95 | * 96 | * @param string $ipAddress IPv4 or IPv6 address as a string. If no 97 | * address is provided, the address that the web service is called 98 | * from will be used. 99 | * 100 | * @return \GeoIp2\Model\City 101 | * 102 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address you 103 | * provided is not in our database (e.g., a private address). 104 | * @throws \GeoIp2\Exception\AuthenticationException if there is a problem 105 | * with the user ID or license key that you provided. 106 | * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out 107 | * of queries. 108 | * @throws \GeoIp2\Exception\InvalidRequestException} if your request was 109 | * received by the web service but is invalid for some other reason. 110 | * This may indicate an issue with this API. Please report the error to 111 | * MaxMind. 112 | * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error 113 | * code or message was returned. This could indicate a problem with the 114 | * connection between your server and the web service or that the web 115 | * service returned an invalid document or 500 error code. 116 | * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent 117 | * class to the above exceptions. It will be thrown directly if a 200 118 | * status code is returned but the body is invalid. 119 | */ 120 | public function city($ipAddress = 'me') 121 | { 122 | return $this->responseFor('city', 'City', $ipAddress); 123 | } 124 | 125 | /** 126 | * This method calls the GeoIP2 Precision: Country endpoint. 127 | * 128 | * @param string $ipAddress IPv4 or IPv6 address as a string. If no 129 | * address is provided, the address that the web service is called 130 | * from will be used. 131 | * 132 | * @return \GeoIp2\Model\Country 133 | * 134 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address you 135 | * provided is not in our database (e.g., a private address). 136 | * @throws \GeoIp2\Exception\AuthenticationException if there is a problem 137 | * with the user ID or license key that you provided. 138 | * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out 139 | * of queries. 140 | * @throws \GeoIp2\Exception\InvalidRequestException} if your request was 141 | * received by the web service but is invalid for some other reason. 142 | * This may indicate an issue with this API. Please report the error to 143 | * MaxMind. 144 | * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error 145 | * code or message was returned. This could indicate a problem with the 146 | * connection between your server and the web service or that the web 147 | * service returned an invalid document or 500 error code. 148 | * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent 149 | * class to the above exceptions. It will be thrown directly if a 200 150 | * status code is returned but the body is invalid. 151 | */ 152 | public function country($ipAddress = 'me') 153 | { 154 | return $this->responseFor('country', 'Country', $ipAddress); 155 | } 156 | 157 | /** 158 | * This method calls the GeoIP2 Precision: Insights endpoint. 159 | * 160 | * @param string $ipAddress IPv4 or IPv6 address as a string. If no 161 | * address is provided, the address that the web service is called 162 | * from will be used. 163 | * 164 | * @return \GeoIp2\Model\Insights 165 | * 166 | * @throws \GeoIp2\Exception\AddressNotFoundException if the address you 167 | * provided is not in our database (e.g., a private address). 168 | * @throws \GeoIp2\Exception\AuthenticationException if there is a problem 169 | * with the user ID or license key that you provided. 170 | * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out 171 | * of queries. 172 | * @throws \GeoIp2\Exception\InvalidRequestException} if your request was 173 | * received by the web service but is invalid for some other reason. 174 | * This may indicate an issue with this API. Please report the error to 175 | * MaxMind. 176 | * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error 177 | * code or message was returned. This could indicate a problem with the 178 | * connection between your server and the web service or that the web 179 | * service returned an invalid document or 500 error code. 180 | * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent 181 | * class to the above exceptions. It will be thrown directly if a 200 182 | * status code is returned but the body is invalid. 183 | */ 184 | public function insights($ipAddress = 'me') 185 | { 186 | return $this->responseFor('insights', 'Insights', $ipAddress); 187 | } 188 | 189 | private function responseFor($endpoint, $class, $ipAddress) 190 | { 191 | $path = implode('/', array(self::$basePath, $endpoint, $ipAddress)); 192 | 193 | try { 194 | $body = $this->client->get('GeoIP2 ' . $class, $path); 195 | } catch (\MaxMind\Exception\IpAddressNotFoundException $ex) { 196 | throw new AddressNotFoundException( 197 | $ex->getMessage(), 198 | $ex->getStatusCode(), 199 | $ex 200 | ); 201 | } catch (\MaxMind\Exception\AuthenticationException $ex) { 202 | throw new AuthenticationException( 203 | $ex->getMessage(), 204 | $ex->getStatusCode(), 205 | $ex 206 | ); 207 | } catch (\MaxMind\Exception\InsufficientFundsException $ex) { 208 | throw new OutOfQueriesException( 209 | $ex->getMessage(), 210 | $ex->getStatusCode(), 211 | $ex 212 | ); 213 | } catch (\MaxMind\Exception\InvalidRequestException $ex) { 214 | throw new InvalidRequestException( 215 | $ex->getMessage(), 216 | $ex->getErrorCode(), 217 | $ex->getStatusCode(), 218 | $ex->getUri(), 219 | $ex 220 | ); 221 | } catch (\MaxMind\Exception\HttpException $ex) { 222 | throw new HttpException( 223 | $ex->getMessage(), 224 | $ex->getStatusCode(), 225 | $ex->getUri(), 226 | $ex 227 | ); 228 | } catch (\MaxMind\Exception\WebServiceException $ex) { 229 | throw new GeoIp2Exception( 230 | $ex->getMessage(), 231 | $ex->getCode(), 232 | $ex 233 | ); 234 | } 235 | 236 | $class = "GeoIp2\\Model\\" . $class; 237 | return new $class($body, $this->locales); 238 | 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/tests/GeoIp2/Test/Database/ReaderTest.php: -------------------------------------------------------------------------------- 1 | $method('81.2.69.160'); 15 | $this->assertSame('United Kingdom', $record->country->name); 16 | } 17 | $reader->close(); 18 | } 19 | 20 | public function testLocaleList() 21 | { 22 | 23 | foreach (array('City', 'Country') as $type) { 24 | $reader = new Reader( 25 | "maxmind-db/test-data/GeoIP2-$type-Test.mmdb", 26 | array('xx', 'ru', 'pt-BR', 'es', 'en') 27 | ); 28 | $method = lcfirst($type); 29 | 30 | $record = $reader->$method('81.2.69.160'); 31 | $this->assertSame('Великобритания', $record->country->name); 32 | } 33 | $reader->close(); 34 | } 35 | 36 | public function testHasIpAddress() 37 | { 38 | foreach (array('City', 'Country') as $type) { 39 | $reader = new Reader("maxmind-db/test-data/GeoIP2-$type-Test.mmdb"); 40 | $method = lcfirst($type); 41 | $record = $reader->$method('81.2.69.160'); 42 | $this->assertSame('81.2.69.160', $record->traits->ipAddress); 43 | } 44 | $reader->close(); 45 | } 46 | 47 | /** 48 | * @expectedException GeoIp2\Exception\AddressNotFoundException 49 | * @expectedExceptionMessage The address 10.10.10.10 is not in the database. 50 | */ 51 | public function testUnknownAddress() 52 | { 53 | $reader = new Reader('maxmind-db/test-data/GeoIP2-City-Test.mmdb'); 54 | $reader->city('10.10.10.10'); 55 | $reader->close(); 56 | } 57 | 58 | /** 59 | * @expectedException BadMethodCallException 60 | * @expectedExceptionMessage The country method cannot be used to open a GeoIP2-City database 61 | */ 62 | public function testIncorrectDatabase() 63 | { 64 | $reader = new Reader('maxmind-db/test-data/GeoIP2-City-Test.mmdb'); 65 | $reader->country('10.10.10.10'); 66 | $reader->close(); 67 | } 68 | 69 | /** 70 | * @expectedException BadMethodCallException 71 | * @expectedExceptionMessage The domain method cannot be used to open a GeoIP2-City database 72 | */ 73 | public function testIncorrectDatabaseFlat() 74 | { 75 | $reader = new Reader('maxmind-db/test-data/GeoIP2-City-Test.mmdb'); 76 | $reader->domain('10.10.10.10'); 77 | $reader->close(); 78 | } 79 | 80 | /** 81 | * @expectedException InvalidArgumentException 82 | * @expectedExceptionMessage is not a valid IP address 83 | */ 84 | public function testInvalidAddress() 85 | { 86 | $reader = new Reader('maxmind-db/test-data/GeoIP2-City-Test.mmdb'); 87 | $reader->city('invalid'); 88 | $reader->close(); 89 | } 90 | 91 | public function testAnonymousIp() 92 | { 93 | $reader = new Reader('maxmind-db/test-data/GeoIP2-Anonymous-IP-Test.mmdb'); 94 | $ipAddress = '1.2.0.1'; 95 | 96 | $record = $reader->anonymousIp($ipAddress); 97 | $this->assertSame(true, $record->isAnonymous); 98 | $this->assertSame(true, $record->isAnonymousVpn); 99 | $this->assertSame(false, $record->isHostingProvider); 100 | $this->assertSame(false, $record->isPublicProxy); 101 | $this->assertSame(false, $record->isTorExitNode); 102 | $this->assertSame($ipAddress, $record->ipAddress); 103 | $reader->close(); 104 | } 105 | 106 | public function testConnectionType() 107 | { 108 | $reader = new Reader('maxmind-db/test-data/GeoIP2-Connection-Type-Test.mmdb'); 109 | $ipAddress = '1.0.1.0'; 110 | 111 | $record = $reader->connectionType($ipAddress); 112 | $this->assertSame('Cable/DSL', $record->connectionType); 113 | $this->assertSame($ipAddress, $record->ipAddress); 114 | $reader->close(); 115 | } 116 | 117 | public function testDomain() 118 | { 119 | $reader = new Reader('maxmind-db/test-data/GeoIP2-Domain-Test.mmdb'); 120 | 121 | $ipAddress = '1.2.0.0'; 122 | $record = $reader->domain($ipAddress); 123 | $this->assertSame('maxmind.com', $record->domain); 124 | $this->assertSame($ipAddress, $record->ipAddress); 125 | $reader->close(); 126 | } 127 | 128 | public function testEnterprise() 129 | { 130 | $reader = new Reader('maxmind-db/test-data/GeoIP2-Enterprise-Test.mmdb'); 131 | 132 | $ipAddress = '74.209.24.0'; 133 | $record = $reader->enterprise($ipAddress); 134 | $this->assertSame(11, $record->city->confidence); 135 | $this->assertSame(99, $record->country->confidence); 136 | $this->assertSame(6252001, $record->country->geonameId); 137 | 138 | $this->assertSame(27, $record->location->accuracyRadius); 139 | 140 | $this->assertSame('Cable/DSL', $record->traits->connectionType); 141 | $this->assertSame(true, $record->traits->isLegitimateProxy); 142 | 143 | $this->assertSame($ipAddress, $record->traits->ipAddress); 144 | $reader->close(); 145 | } 146 | 147 | public function testIsp() 148 | { 149 | $reader = new Reader('maxmind-db/test-data/GeoIP2-ISP-Test.mmdb'); 150 | 151 | $ipAddress = '1.128.0.0'; 152 | $record = $reader->isp($ipAddress); 153 | $this->assertSame(1221, $record->autonomousSystemNumber); 154 | $this->assertSame( 155 | 'Telstra Pty Ltd', 156 | $record->autonomousSystemOrganization 157 | ); 158 | 159 | $this->assertSame('Telstra Internet', $record->isp); 160 | $this->assertSame('Telstra Internet', $record->organization); 161 | 162 | $this->assertSame($ipAddress, $record->ipAddress); 163 | $reader->close(); 164 | } 165 | 166 | public function testMetadata() 167 | { 168 | $reader = new Reader('maxmind-db/test-data/GeoIP2-City-Test.mmdb'); 169 | $this->assertSame('GeoIP2-City', $reader->metadata()->databaseType); 170 | 171 | $reader->close(); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/tests/GeoIp2/Test/Model/CountryTest.php: -------------------------------------------------------------------------------- 1 | array( 12 | 'code' => 'NA', 13 | 'geoname_id' => 42, 14 | 'names' => array('en' => 'North America'), 15 | ), 16 | 'country' => array( 17 | 'geoname_id' => 1, 18 | 'iso_code' => 'US', 19 | 'names' => array('en' => 'United States of America'), 20 | ), 21 | 'registered_country' => array( 22 | 'geoname_id' => 2, 23 | 'iso_code' => 'CA', 24 | 'names' => array('en' => 'Canada'), 25 | ), 26 | 'traits' => array( 27 | 'ip_address' => '1.2.3.4', 28 | ), 29 | ); 30 | 31 | private $model; 32 | 33 | public function setUp() 34 | { 35 | $this->model = new Country($this->raw, array('en')); 36 | } 37 | 38 | public function testObjects() 39 | { 40 | $this->assertInstanceOf( 41 | 'GeoIp2\Model\Country', 42 | $this->model, 43 | 'minimal GeoIp2::Model::Country object' 44 | ); 45 | $this->assertInstanceOf( 46 | 'GeoIp2\Record\Continent', 47 | $this->model->continent 48 | ); 49 | $this->assertInstanceOf( 50 | 'GeoIp2\Record\Country', 51 | $this->model->country 52 | ); 53 | $this->assertInstanceOf( 54 | 'GeoIp2\Record\Country', 55 | $this->model->registeredCountry 56 | ); 57 | $this->assertInstanceOf( 58 | 'GeoIp2\Record\RepresentedCountry', 59 | $this->model->representedCountry 60 | ); 61 | $this->assertInstanceOf( 62 | 'GeoIp2\Record\Traits', 63 | $this->model->traits 64 | ); 65 | } 66 | 67 | public function testValues() 68 | { 69 | 70 | $this->assertSame( 71 | 42, 72 | $this->model->continent->geonameId, 73 | 'continent geoname_id is 42' 74 | ); 75 | 76 | $this->assertSame( 77 | 'NA', 78 | $this->model->continent->code, 79 | 'continent code is NA' 80 | ); 81 | 82 | $this->assertSame( 83 | array('en' => 'North America'), 84 | $this->model->continent->names, 85 | 'continent names' 86 | ); 87 | 88 | $this->assertSame( 89 | 'North America', 90 | $this->model->continent->name, 91 | 'continent name is North America' 92 | ); 93 | 94 | $this->assertSame( 95 | 1, 96 | $this->model->country->geonameId, 97 | 'country geoname_id is 1' 98 | ); 99 | 100 | $this->assertSame( 101 | 'US', 102 | $this->model->country->isoCode, 103 | 'country iso_code is US' 104 | ); 105 | 106 | $this->assertSame( 107 | array('en' => 'United States of America'), 108 | $this->model->country->names, 109 | 'country name' 110 | ); 111 | 112 | $this->assertSame( 113 | $this->model->country->name, 114 | 'United States of America', 115 | 'country name is United States of America' 116 | ); 117 | 118 | $this->assertSame( 119 | null, 120 | $this->model->country->confidence, 121 | 'country confidence is undef' 122 | ); 123 | 124 | $this->assertSame( 125 | 2, 126 | $this->model->registeredCountry->geonameId, 127 | 'registered_country geoname_id is 2' 128 | ); 129 | 130 | $this->assertSame( 131 | 'CA', 132 | $this->model->registeredCountry->isoCode, 133 | 'registered_country iso_code is CA' 134 | ); 135 | 136 | $this->assertSame( 137 | array('en' => 'Canada'), 138 | $this->model->registeredCountry->names, 139 | 'registered_country names' 140 | ); 141 | 142 | $this->assertSame( 143 | 'Canada', 144 | $this->model->registeredCountry->name, 145 | 'registered_country name is Canada' 146 | ); 147 | 148 | foreach (array('isAnonymousProxy', 'isSatelliteProvider') as $meth) { 149 | $this->assertSame( 150 | false, 151 | $this->model->traits->$meth, 152 | "traits $meth returns 0 by default" 153 | ); 154 | } 155 | 156 | $this->assertSame( 157 | $this->raw, 158 | $this->model->raw, 159 | 'raw method returns raw input' 160 | ); 161 | } 162 | 163 | public function testJsonSerialize() 164 | { 165 | $this->assertSame( 166 | $this->raw, 167 | $this->model->jsonSerialize(), 168 | 'jsonSerialize returns initial array' 169 | ); 170 | 171 | $this->assertSame( 172 | $this->raw['country'], 173 | $this->model->country->jsonSerialize(), 174 | 'jsonSerialize returns initial array for the record' 175 | ); 176 | 177 | if (version_compare(PHP_VERSION, '5.4.0', '<')) { 178 | $this->markTestSkipped('Requires PHP 5.4+.'); 179 | } 180 | 181 | $this->assertSame( 182 | json_encode($this->raw), 183 | json_encode($this->model), 184 | 'json_encode can be called on the model object directly' 185 | ); 186 | 187 | $this->assertSame( 188 | json_encode($this->raw['country']), 189 | json_encode($this->model->country), 190 | 'json_encode can be called on the record object directly' 191 | ); 192 | } 193 | 194 | public function testIsSet() 195 | { 196 | $this->assertTrue(isset($this->model->traits), 'traits is set'); 197 | $this->assertFalse(isset($this->model->unknown), 'unknown is not set'); 198 | 199 | $this->assertTrue( 200 | isset($this->model->traits->ipAddress), 201 | 'ip_address is set' 202 | ); 203 | $this->assertFalse( 204 | isset($this->model->traits->unknown), 205 | 'unknown trait is not set' 206 | ); 207 | } 208 | 209 | /** 210 | * @expectedException RuntimeException 211 | * @expectedExceptionMessage Unknown attribute 212 | */ 213 | public function testUnknownRecord() 214 | { 215 | $this->model->unknownRecord; 216 | } 217 | 218 | /** 219 | * @expectedException RuntimeException 220 | * @expectedExceptionMessage Unknown attribute 221 | */ 222 | public function testUnknownTrait() 223 | { 224 | $this->model->traits->unknown; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/tests/GeoIp2/Test/Model/InsightsTest.php: -------------------------------------------------------------------------------- 1 | array( 15 | 'confidence' => 76, 16 | 'geoname_id' => 9876, 17 | 'names' => array('en' => 'Minneapolis'), 18 | ), 19 | 'continent' => array( 20 | 'code' => 'NA', 21 | 'geoname_id' => 42, 22 | 'names' => array('en' => 'North America'), 23 | ), 24 | 'country' => array( 25 | 'confidence' => 99, 26 | 'geoname_id' => 1, 27 | 'iso_code' => 'US', 28 | 'names' => array('en' => 'United States of America'), 29 | ), 30 | 'location' => array( 31 | 'average_income' => 24626, 32 | 'accuracy_radius' => 1500, 33 | 'latitude' => 44.98, 34 | 'longitude' => 93.2636, 35 | 'metro_code' => 765, 36 | 'population_density' => 1341, 37 | 'postal_code' => '55401', 38 | 'postal_confidence' => 33, 39 | 'time_zone' => 'America/Chicago', 40 | ), 41 | 'maxmind' => array( 42 | 'queries_remaining' => 22, 43 | ), 44 | 'registered_country' => array( 45 | 'geoname_id' => 2, 46 | 'iso_code' => 'CA', 47 | 'names' => array('en' => 'Canada'), 48 | ), 49 | 'represented_country' => array( 50 | 'geoname_id' => 3, 51 | 'iso_code' => 'GB', 52 | 'names' => array('en' => 'United Kingdom'), 53 | ), 54 | 'subdivisions' => array( 55 | array( 56 | 'confidence' => 88, 57 | 'geoname_id' => 574635, 58 | 'iso_code' => 'MN', 59 | 'names' => array('en' => 'Minnesota'), 60 | ) 61 | ), 62 | 'traits' => array( 63 | 'autonomous_system_number' => 1234, 64 | 'autonomous_system_organization' => 'AS Organization', 65 | 'domain' => 'example.com', 66 | 'ip_address' => '1.2.3.4', 67 | 'is_satellite_provider' => true, 68 | 'isp' => 'Comcast', 69 | 'organization' => 'Blorg', 70 | 'user_type' => 'college', 71 | ), 72 | ); 73 | 74 | $model = new Insights($raw, array('en')); 75 | 76 | $this->assertInstanceOf( 77 | 'GeoIp2\Model\Insights', 78 | $model, 79 | 'GeoIp2\Model\Insights object' 80 | ); 81 | 82 | $this->assertInstanceOf( 83 | 'GeoIp2\Record\City', 84 | $model->city, 85 | '$model->city' 86 | ); 87 | 88 | $this->assertInstanceOf( 89 | 'GeoIp2\Record\Continent', 90 | $model->continent, 91 | '$model->continent' 92 | ); 93 | 94 | $this->assertInstanceOf( 95 | 'GeoIp2\Record\Country', 96 | $model->country, 97 | '$model->country' 98 | ); 99 | 100 | $this->assertInstanceOf( 101 | 'GeoIp2\Record\Location', 102 | $model->location, 103 | '$model->location' 104 | ); 105 | 106 | $this->assertSame( 107 | 24626, 108 | $model->location->averageIncome, 109 | '$model->location->averageIncome is 24626' 110 | ); 111 | 112 | $this->assertSame( 113 | 1341, 114 | $model->location->populationDensity, 115 | '$model->location->populationDensity is 1341' 116 | ); 117 | 118 | $this->assertInstanceOf( 119 | 'GeoIp2\Record\Country', 120 | $model->registeredCountry, 121 | '$model->registeredCountry' 122 | ); 123 | 124 | $this->assertInstanceOf( 125 | 'GeoIp2\Record\RepresentedCountry', 126 | $model->representedCountry, 127 | '$model->representedCountry' 128 | ); 129 | 130 | $subdivisions = $model->subdivisions; 131 | foreach ($subdivisions as $subdiv) { 132 | $this->assertInstanceOf('GeoIp2\Record\Subdivision', $subdiv); 133 | } 134 | 135 | $this->assertInstanceOf( 136 | 'GeoIp2\Record\Subdivision', 137 | $model->mostSpecificSubdivision, 138 | '$model->mostSpecificSubdivision' 139 | ); 140 | 141 | $this->assertInstanceOf( 142 | 'GeoIp2\Record\Traits', 143 | $model->traits, 144 | '$model->traits' 145 | ); 146 | 147 | $this->assertSame( 148 | true, 149 | $model->traits->isSatelliteProvider, 150 | '$model->traits->isSatelliteProvider is true' 151 | ); 152 | 153 | $this->assertSame( 154 | false, 155 | $model->traits->isAnonymousProxy, 156 | '$model->traits->isAnonymousProxy is false' 157 | ); 158 | 159 | $this->assertSame( 160 | 22, 161 | $model->maxmind->queriesRemaining, 162 | 'queriesRemaining is correct' 163 | ); 164 | 165 | $this->assertSame( 166 | $raw, 167 | $model->raw, 168 | 'raw method returns raw input' 169 | ); 170 | } 171 | 172 | public function testEmptyObjects() 173 | { 174 | $raw = array('traits' => array('ip_address' => '5.6.7.8')); 175 | 176 | $model = new Insights($raw, array('en')); 177 | 178 | $this->assertInstanceOf( 179 | 'GeoIp2\Model\Insights', 180 | $model, 181 | 'GeoIp2\Model\Insights object with no data except traits.ipAddress' 182 | ); 183 | 184 | $this->assertInstanceOf( 185 | 'GeoIp2\Record\City', 186 | $model->city, 187 | '$model->city' 188 | ); 189 | 190 | $this->assertInstanceOf( 191 | 'GeoIp2\Record\Continent', 192 | $model->continent, 193 | '$model->continent' 194 | ); 195 | 196 | $this->assertInstanceOf( 197 | 'GeoIp2\Record\Country', 198 | $model->country, 199 | '$model->country' 200 | ); 201 | 202 | $this->assertInstanceOf( 203 | 'GeoIp2\Record\Location', 204 | $model->location, 205 | '$model->location' 206 | ); 207 | 208 | $this->assertInstanceOf( 209 | 'GeoIp2\Record\Country', 210 | $model->registeredCountry, 211 | '$model->registeredCountry' 212 | ); 213 | 214 | $this->assertInstanceOf( 215 | 'GeoIp2\Record\RepresentedCountry', 216 | $model->representedCountry, 217 | '$model->representedCountry' 218 | ); 219 | 220 | $this->assertCount( 221 | 0, 222 | $model->subdivisions, 223 | '$model->subdivisions returns an empty list' 224 | ); 225 | 226 | $this->assertInstanceOf( 227 | 'GeoIp2\Record\Subdivision', 228 | $model->mostSpecificSubdivision, 229 | '$model->mostSpecificSubdivision' 230 | ); 231 | 232 | $this->assertInstanceOf( 233 | 'GeoIp2\Record\Traits', 234 | $model->traits, 235 | '$model->traits' 236 | ); 237 | 238 | $this->assertSame( 239 | $raw, 240 | $model->raw, 241 | 'raw method returns raw input with no added empty values' 242 | ); 243 | } 244 | 245 | 246 | public function testUnknown() 247 | { 248 | $raw = array( 249 | 'new_top_level' => array('foo' => 42), 250 | 'city' => array( 251 | 'confidence' => 76, 252 | 'geoname_id_id' => 9876, 253 | 'names' => array('en' => 'Minneapolis'), 254 | 'population' => 50, 255 | ), 256 | 'traits' => array('ip_address' => '5.6.7.8') 257 | ); 258 | 259 | // checking whether there are exceptions with unknown keys 260 | $model = new Insights($raw, array('en')); 261 | 262 | $this->assertInstanceOf( 263 | 'GeoIp2\Model\Insights', 264 | $model, 265 | 'no exception when Insights model gets raw data with unknown keys' 266 | ); 267 | 268 | $this->assertSame( 269 | $raw, 270 | $model->raw, 271 | 'raw method returns raw input' 272 | ); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/tests/GeoIp2/Test/Model/NameTest.php: -------------------------------------------------------------------------------- 1 | array( 11 | 'code' => 'NA', 12 | 'geoname_id' => 42, 13 | 'names' => array( 14 | 'en' => 'North America', 15 | 'zh-CN' => '北美洲', 16 | ), 17 | ), 18 | 'country' => array( 19 | 'geoname_id' => 1, 20 | 'iso_code' => 'US', 21 | 'names' => array( 22 | 'en' => 'United States of America', 23 | 'ru' => 'объединяет государства', 24 | 'zh-CN' => '美国', 25 | ), 26 | ), 27 | 'traits' => array( 28 | 'ip_address' => '1.2.3.4', 29 | ), 30 | ); 31 | 32 | public function testFallback() 33 | { 34 | $model = new Country($this->raw, array('ru', 'zh-CN', 'en')); 35 | 36 | $this->assertSame( 37 | '北美洲', 38 | $model->continent->name, 39 | 'continent name is in Chinese (no Russian available)' 40 | ); 41 | 42 | $this->assertSame( 43 | 'объединяет государства', 44 | $model->country->name, 45 | 'country name is in Russian' 46 | ); 47 | } 48 | 49 | public function testTwoFallbacks() 50 | { 51 | $model = new Country($this->raw, array('ru', 'ja')); 52 | 53 | $this->assertSame( 54 | null, 55 | $model->continent->name, 56 | 'continent name is undef (no Russian or Japanese available)' 57 | ); 58 | 59 | $this->assertSame( 60 | 'объединяет государства', 61 | $model->country->name, 62 | 'country name is in Russian' 63 | ); 64 | } 65 | 66 | public function testNoFallbacks() 67 | { 68 | $model = new Country($this->raw, array('ja')); 69 | 70 | $this->assertSame( 71 | null, 72 | $model->continent->name, 73 | 'continent name is undef (no Japanese available) ' 74 | ); 75 | 76 | $this->assertSame( 77 | null, 78 | $model->country->name, 79 | 'country name is undef (no Japanese available) ' 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /vendor/geoip2/geoip2/tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('GeoIp2\Test', __DIR__); 8 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/.coveralls-phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ./tests/MaxMind/Db/Test/ 7 | 8 | 9 | 10 | 11 | 12 | ./src/MaxMind/Db/ 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.la 3 | *.lo 4 | *.o 5 | *.old 6 | *.sublime-* 7 | *.sw? 8 | .deps 9 | .gh-pages 10 | /.idea 11 | .libs/ 12 | _site 13 | ac*.m4 14 | autom4te.cache/ 15 | build/ 16 | composer.lock 17 | composer.phar 18 | config.[^mw]* 19 | configure* 20 | core 21 | install-sh 22 | libtool 23 | ltmain.sh 24 | Makefile* 25 | missing 26 | mkinstalldirs 27 | modules/ 28 | phpunit.xml 29 | run-tests.php 30 | t.php 31 | /test.php 32 | tmp-php.ini 33 | vendor/ 34 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tests/data"] 2 | path = tests/data 3 | url = git://github.com/maxmind/MaxMind-DB.git 4 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/.travis-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | if [ "hhvm" != $TRAVIS_PHP_VERSION ] 7 | then 8 | export CFLAGS="-L$HOME/libmaxminddb/lib" 9 | export CPPFLAGS="-I$HOME/libmaxminddb/include" 10 | cd ext 11 | phpize 12 | ./configure --with-maxminddb --enable-maxminddb-debug 13 | make clean 14 | make 15 | NO_INTERACTION=1 make test 16 | cd .. 17 | fi 18 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/.travis-install-prereqs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | git submodule update --init --recursive 7 | composer self-update 8 | composer install --dev -n --prefer-source 9 | if [ "hhvm" != "$TRAVIS_PHP_VERSION" ] 10 | then 11 | mkdir -p "$HOME/libmaxminddb" 12 | git clone --recursive git://github.com/maxmind/libmaxminddb 13 | cd libmaxminddb 14 | ./bootstrap 15 | ./configure --prefix="$HOME/libmaxminddb" 16 | make 17 | make install 18 | fi 19 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/.travis-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | mkdir -p build/logs 7 | ./vendor/bin/phpunit -c .coveralls-phpunit.xml.dist 8 | 9 | if [ "hhvm" != "$TRAVIS_PHP_VERSION" ] 10 | then 11 | echo "mbstring.internal_encoding=utf-8" >> ~/.phpenv/versions/"$(phpenv version-name)"/etc/php.ini 12 | echo "mbstring.func_overload = 7" >> ~/.phpenv/versions/"$(phpenv version-name)"/etc/php.ini 13 | ./vendor/bin/phpunit 14 | 15 | echo "extension = ext/modules/maxminddb.so" >> ~/.phpenv/versions/"$(phpenv version-name)"/etc/php.ini 16 | ./vendor/bin/phpunit 17 | fi 18 | 19 | ./vendor/bin/phpcs --standard=PSR2 src/ 20 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | - 7.0 9 | - hhvm 10 | 11 | before_install: 12 | - ./.travis-install-prereqs.sh 13 | 14 | install: 15 | - ./.travis-build.sh 16 | - phpenv rehash 17 | 18 | 19 | script: 20 | - ./.travis-test.sh 21 | 22 | after_script: 23 | - php vendor/bin/coveralls 24 | 25 | notifications: 26 | email: 27 | recipients: 28 | - dev-ci@maxmind.com 29 | on_success: change 30 | on_failure: always 31 | 32 | env: 33 | global: 34 | - secure: "RMIBN2tNKlrGA07coRW4B9m9jCobrYxDkEq3T3jGoGtXgQe/Mr3bI/4zQo7U3bvVTSF90lzkWbxATY45GQXRxWC7Ed2HI2jwUF96CXecdRhKiE9x051HsvXakvbODPLocV7/2LOZqz+eXCUeazLgRaSrIhAqMddFqMQSSM5STlc=" 35 | 36 | addons: 37 | coverity_scan: 38 | project: 39 | name: "maxmind/MaxMind-DB-Reader-php" 40 | description: "Build submitted via Travis CI" 41 | notification_email: dev-ci@maxmind.com 42 | build_command: "./.travis-build.sh" 43 | branch_pattern: .*coverity.* 44 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 1.1.0 (2016-01-04) 5 | ------------------ 6 | 7 | * The MaxMind DB extension now supports PHP 7. Pull request by John Boehr. 8 | GitHub #27. 9 | 10 | 1.0.3 (2015-03-13) 11 | ------------------ 12 | 13 | * All uses of `strlen` were removed. This should prevent issues in situations 14 | where the function is overloaded or otherwise broken. 15 | 16 | 1.0.2 (2015-01-19) 17 | ------------------ 18 | 19 | * Previously the MaxMind DB extension would cause a segfault if the Reader 20 | object's destructor was called without first having called the constructor. 21 | (Reported by Matthias Saou & Juan Peri. GitHub #20.) 22 | 23 | 1.0.1 (2015-01-12) 24 | ------------------ 25 | 26 | * In the last several releases, the version number in the extension was 27 | incorrect. This release is being done to correct it. No other code changes 28 | are included. 29 | 30 | 1.0.0 (2014-09-22) 31 | ------------------ 32 | 33 | * First production release. 34 | * In the pure PHP reader, a string length test after `fread()` was replaced 35 | with the difference between the start pointer and the end pointer. This 36 | provided a 15% speed increase. 37 | 38 | 0.3.3 (2014-09-15) 39 | ------------------ 40 | 41 | * Clarified behavior of 128-bit type in documentation. 42 | * Updated phpunit and fixed some test breakage from the newer version. 43 | 44 | 0.3.2 (2014-09-10) 45 | ------------------ 46 | 47 | * Fixed invalid reference to global class RuntimeException from namespaced 48 | code. Fixed by Steven Don. GitHub issue #15. 49 | * Additional documentation of `Metadata` class as well as misc. documentation 50 | cleanup. 51 | 52 | 0.3.1 (2014-05-01) 53 | ------------------ 54 | 55 | * The API now works when `mbstring.func_overload` is set. 56 | * BCMath is no longer required. If the decoder encounters a big integer, 57 | it will try to use GMP and then BCMath. If both of those fail, it will 58 | throw an exception. No databases released by MaxMind currently use big 59 | integers. 60 | * The API now officially supports HHVM when using the pure PHP reader. 61 | 62 | 0.3.0 (2014-02-19) 63 | ------------------ 64 | 65 | * This API is now licensed under the Apache License, Version 2.0. 66 | * The code for the C extension was cleaned up, fixing several potential 67 | issues. 68 | 69 | 0.2.0 (2013-10-21) 70 | ------------------ 71 | 72 | * Added optional C extension for using libmaxminddb in place of the pure PHP 73 | reader. 74 | * Significantly improved error handling in pure PHP reader. 75 | * Improved performance for IPv4 lookups in an IPv6 database. 76 | 77 | 0.1.0 (2013-07-16) 78 | ------------------ 79 | 80 | * Initial release 81 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/README.md: -------------------------------------------------------------------------------- 1 | # MaxMind DB Reader PHP API # 2 | 3 | ## Description ## 4 | 5 | This is the PHP API for reading MaxMind DB files. MaxMind DB is a binary file 6 | format that stores data indexed by IP address subnets (IPv4 or IPv6). 7 | 8 | ## Installation ## 9 | 10 | We recommend installing this package with [Composer](http://getcomposer.org/). 11 | 12 | ### Download Composer ### 13 | 14 | To download Composer, run in the root directory of your project: 15 | 16 | ```bash 17 | curl -sS https://getcomposer.org/installer | php 18 | ``` 19 | 20 | You should now have the file `composer.phar` in your project directory. 21 | 22 | ### Install Dependencies ### 23 | 24 | Run in your project root: 25 | 26 | ``` 27 | php composer.phar require maxmind-db/reader:~1.0 28 | ``` 29 | 30 | You should now have the files `composer.json` and `composer.lock` as well as 31 | the directory `vendor` in your project directory. If you use a version control 32 | system, `composer.json` should be added to it. 33 | 34 | ### Require Autoloader ### 35 | 36 | After installing the dependencies, you need to require the Composer autoloader 37 | from your code: 38 | 39 | ```php 40 | require 'vendor/autoload.php'; 41 | ``` 42 | 43 | ## Usage ## 44 | 45 | ## Example ## 46 | 47 | ```php 48 | get($ipAddress)); 59 | 60 | $reader->close() 61 | ``` 62 | 63 | ## Optional PHP C Extension ## 64 | 65 | MaxMind provides an optional C extension that is a drop-in replacement for for 66 | `MaxMind\Db\Reader`. In order to use this extension, you must install the 67 | Reader API as described above and install the extension as described below. If 68 | you are using an autoloader, no changes to your code should be necessary. 69 | 70 | ### Installing Extension ### 71 | 72 | First install [libmaxminddb](https://github.com/maxmind/libmaxminddb) as 73 | described in its [README.md 74 | file](https://github.com/maxmind/libmaxminddb/blob/master/README.md#installing-from-a-tarball). 75 | After successfully installing libmaxmindb, run the following commands from the 76 | top-level directory of this distribution: 77 | 78 | ``` 79 | cd ext 80 | phpize 81 | ./configure 82 | make 83 | make test 84 | sudo make install 85 | ``` 86 | 87 | You then must load your extension. The recommend method is to add the 88 | following to your `php.ini` file: 89 | 90 | ``` 91 | extension=maxminddb.so 92 | ``` 93 | 94 | Note: You may need to install the PHP development package on your OS such as 95 | php5-dev for Debian-based systems or php-devel for RedHat/Fedora-based ones. 96 | 97 | ## 128-bit Integer Support ## 98 | 99 | The MaxMind DB format includes 128-bit unsigned integer as a type. Although 100 | no MaxMind-distributed database currently makes use of this type, both the 101 | pure PHP reader and the C extension support this type. The pure PHP reader 102 | requires gmp or bcmath to read databases with 128-bit unsigned integers. 103 | 104 | The integer is currently returned as a hexadecimal string (prefixed with "0x") 105 | by the C extension and a decimal string (no prefix) by the pure PHP reader. 106 | Any change to make the reader implementations always return either a 107 | hexadecimal or decimal representation of the integer will NOT be considered a 108 | breaking change. 109 | 110 | ## Support ## 111 | 112 | Please report all issues with this code using the [GitHub issue tracker] 113 | (https://github.com/maxmind/MaxMind-DB-Reader-php/issues). 114 | 115 | If you are having an issue with a MaxMind service that is not specific to the 116 | client API, please see [our support page](http://www.maxmind.com/en/support). 117 | 118 | ## Requirements ## 119 | 120 | This library requires PHP 5.3 or greater. Older versions of PHP are not 121 | supported. The pure PHP reader included with this library is works and is 122 | tested with HHVM. 123 | 124 | The GMP or BCMath extension may be required to read some databases 125 | using the pure PHP API. 126 | 127 | ## Contributing ## 128 | 129 | Patches and pull requests are encouraged. All code should follow the PSR-1 and 130 | PSR-2 style guidelines. Please include unit tests whenever possible. 131 | 132 | ## Versioning ## 133 | 134 | The MaxMind DB Reader PHP API uses [Semantic Versioning](http://semver.org/). 135 | 136 | ## Copyright and License ## 137 | 138 | This software is Copyright (c) 2014 by MaxMind, Inc. 139 | 140 | This is free software, licensed under the Apache License, Version 2.0. 141 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "maxmind-db/reader", 3 | "description": "MaxMind DB Reader API", 4 | "keywords": ["database", "geoip", "geoip2", "geolocation", "maxmind"], 5 | "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", 6 | "type": "library", 7 | "license": "Apache-2.0", 8 | "authors": [ 9 | { 10 | "name": "Gregory J. Oschwald", 11 | "email": "goschwald@maxmind.com", 12 | "homepage": "http://www.maxmind.com/" 13 | } 14 | ], 15 | "require": { 16 | "php": ">=5.3.1" 17 | }, 18 | "require-dev": { 19 | "phpunit/phpunit": "4.2.*", 20 | "satooshi/php-coveralls": "dev-master", 21 | "squizlabs/php_codesniffer": "2.*" 22 | }, 23 | "autoload": { 24 | "psr-0": { 25 | "MaxMind": "src/" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/dev-bin/make-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | VERSION=$(perl -MFile::Slurp::Tiny=read_file -MDateTime <now->ymd eq \$2; 10 | say \$1; 11 | EOF 12 | ) 13 | 14 | perl -pi -e "s/(?<=#define PHP_MAXMINDDB_VERSION \")\d+\.\d+\.\d+(?=\")/$VERSION/" ext/php_maxminddb.h 15 | 16 | git diff 17 | 18 | if [ -n "$(git status --porcelain)" ]; then 19 | git commit -m "Bumped version to $VERSION" -a 20 | fi 21 | 22 | TAG="v$VERSION" 23 | echo "Creating tag $TAG" 24 | git tag -a -m "Release for $VERSION" "$TAG" 25 | 26 | 27 | read -p "Push to origin? (y/n) " SHOULD_PUSH 28 | 29 | if [ "$SHOULD_PUSH" != "y" ]; then 30 | echo "Aborting" 31 | exit 1 32 | fi 33 | 34 | git push 35 | git push --tags 36 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/examples/benchmark.php: -------------------------------------------------------------------------------- 1 | get($ip); 13 | if ($i % 1000 == 0) { 14 | print($i . ' ' . $ip . "\n"); 15 | // print_r($t); 16 | } 17 | } 18 | $endTime = microtime(true); 19 | 20 | $duration = $endTime - $startTime; 21 | print('Requests per second: ' . $count / $duration . "\n"); 22 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/ext/.uncrustify.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # uncrustify config file for the linux kernel 3 | # 4 | # - modified to use spaces instead of tabs 5 | # - added "sp_before_ptr_star = force" 6 | 7 | indent_with_tabs = 0 8 | indent_columns = 4 9 | indent_label = 2 # pos: absolute col, neg: relative column 10 | indent_case_brace = 4 11 | code_width = 80 12 | 13 | 14 | # 15 | # inter-symbol newlines 16 | # 17 | 18 | nl_enum_brace = remove # "enum {" vs "enum \n {" 19 | nl_union_brace = remove # "union {" vs "union \n {" 20 | nl_struct_brace = remove # "struct {" vs "struct \n {" 21 | nl_do_brace = remove # "do {" vs "do \n {" 22 | nl_if_brace = remove # "if () {" vs "if () \n {" 23 | nl_for_brace = remove # "for () {" vs "for () \n {" 24 | nl_else_brace = remove # "else {" vs "else \n {" 25 | nl_while_brace = remove # "while () {" vs "while () \n {" 26 | nl_switch_brace = remove # "switch () {" vs "switch () \n {" 27 | nl_brace_while = remove # "} while" vs "} \n while" - cuddle while 28 | nl_brace_else = remove # "} else" vs "} \n else" - cuddle else 29 | nl_func_var_def_blk = 0 # don't add newlines after a block of var declarations 30 | nl_fcall_brace = remove # "list_for_each() {" vs "list_for_each()\n{" 31 | nl_fdef_brace = force # "int foo() {" vs "int foo()\n{" 32 | nl_multi_line_define = true 33 | 34 | 35 | # 36 | # Source code modifications 37 | # 38 | 39 | mod_paren_on_return = remove # "return 1;" vs "return (1);" 40 | mod_full_brace_if = force # "if (a) a--;" vs "if (a) { a--; }" 41 | mod_full_brace_for = force # "for () a--;" vs "for () { a--; }" 42 | mod_full_brace_do = force # "do a--; while ();" vs "do { a--; } while ();" 43 | mod_full_brace_while = force # "while (a) a--;" vs "while (a) { a--; }" 44 | mod_full_brace_nl = 3 # don't remove if more than 3 newlines 45 | 46 | 47 | # 48 | # inter-character spacing options 49 | # 50 | 51 | # sp_return_paren = force # "return (1);" vs "return(1);" 52 | sp_sizeof_paren = remove # "sizeof (int)" vs "sizeof(int)" 53 | sp_before_sparen = force # "if (" vs "if(" 54 | sp_after_sparen = force # "if () {" vs "if (){" 55 | sp_after_cast = remove # "(int) a" vs "(int)a" 56 | sp_inside_braces = force # "{ 1 }" vs "{1}" 57 | sp_inside_braces_struct = force # "{ 1 }" vs "{1}" 58 | sp_inside_braces_enum = force # "{ 1 }" vs "{1}" 59 | sp_assign = force 60 | sp_arith = force 61 | sp_bool = force 62 | sp_compare = force 63 | sp_assign = force 64 | sp_after_comma = force 65 | sp_func_def_paren = remove # "int foo (){" vs "int foo(){" 66 | sp_func_call_paren = remove # "foo (" vs "foo(" 67 | sp_func_proto_paren = remove # "int foo ();" vs "int foo();" 68 | sp_before_ptr_star = force # "char *foo" vs "char* foo 69 | sp_between_ptr_star = remove # "char * *foo" vs "char **foo" 70 | 71 | # 72 | # Aligning stuff 73 | # 74 | 75 | align_with_tabs = FALSE # use tabs to align 76 | align_on_tabstop = FALSE # align on tabstops 77 | align_var_def_star_style = 1 # void *foo; 78 | align_var_struct_span = 0 79 | align_enum_equ_span = 4 # '=' in enum definition 80 | align_struct_init_span = 3 # align stuff in a structure init '= { }' 81 | align_right_cmt_span = 3 82 | align_nl_cont = true 83 | align_struct_init_span = 1 84 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/ext/config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(maxminddb, 2 | [Whether to enable the MaxMind DB Reader extension], 3 | [ --with-maxminddb Enable MaxMind DB Reader extension support]) 4 | 5 | PHP_ARG_ENABLE(maxminddb-debug, for MaxMind DB debug support, 6 | [ --enable-maxminddb-debug Enable enable MaxMind DB deubg support], no, no) 7 | 8 | if test $PHP_MAXMINDDB != "no"; then 9 | PHP_CHECK_LIBRARY(maxminddb, MMDB_open) 10 | 11 | if test $PHP_MAXMINDDB_DEBUG != "no"; then 12 | CFLAGS="$CFLAGS -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Werror" 13 | fi 14 | 15 | PHP_ADD_LIBRARY(maxminddb, 1, MAXMINDDB_SHARED_LIBADD) 16 | PHP_SUBST(MAXMINDDB_SHARED_LIBADD) 17 | 18 | PHP_NEW_EXTENSION(maxminddb, maxminddb.c, $ext_shared) 19 | fi 20 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/ext/php_maxminddb.h: -------------------------------------------------------------------------------- 1 | /* MaxMind, Inc., licenses this file to you under the Apache License, Version 2 | * 2.0 (the "License"); you may not use this file except in compliance with 3 | * the License. You may obtain a copy of the License at 4 | * 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | * License for the specific language governing permissions and limitations 11 | * under the License. 12 | */ 13 | 14 | #include 15 | 16 | #ifndef PHP_MAXMINDDB_H 17 | #define PHP_MAXMINDDB_H 1 18 | #define PHP_MAXMINDDB_VERSION "1.1.0" 19 | #define PHP_MAXMINDDB_EXTNAME "maxminddb" 20 | 21 | extern zend_module_entry maxminddb_module_entry; 22 | #define phpext_maxminddb_ptr &maxminddb_module_entry 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/ext/tests/001-load.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for maxminddb presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 9 | --EXPECT-- 10 | maxminddb extension is available 11 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ./tests/MaxMind/Db/Test/ 7 | 8 | 9 | 10 | 11 | 12 | ./src/MaxMind/Db/ 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php: -------------------------------------------------------------------------------- 1 | get method. 13 | */ 14 | class Reader 15 | { 16 | private static $DATA_SECTION_SEPARATOR_SIZE = 16; 17 | private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com"; 18 | private static $METADATA_START_MARKER_LENGTH = 14; 19 | 20 | private $decoder; 21 | private $fileHandle; 22 | private $fileSize; 23 | private $ipV4Start; 24 | private $metadata; 25 | 26 | /** 27 | * Constructs a Reader for the MaxMind DB format. The file passed to it must 28 | * be a valid MaxMind DB file such as a GeoIp2 database file. 29 | * 30 | * @param string $database 31 | * the MaxMind DB file to use. 32 | * @throws \InvalidArgumentException for invalid database path or unknown arguments 33 | * @throws \MaxMind\Db\Reader\InvalidDatabaseException 34 | * if the database is invalid or there is an error reading 35 | * from it. 36 | */ 37 | public function __construct($database) 38 | { 39 | if (func_num_args() != 1) { 40 | throw new \InvalidArgumentException( 41 | 'The constructor takes exactly one argument.' 42 | ); 43 | } 44 | 45 | if (!is_readable($database)) { 46 | throw new \InvalidArgumentException( 47 | "The file \"$database\" does not exist or is not readable." 48 | ); 49 | } 50 | $this->fileHandle = @fopen($database, 'rb'); 51 | if ($this->fileHandle === false) { 52 | throw new \InvalidArgumentException( 53 | "Error opening \"$database\"." 54 | ); 55 | } 56 | $this->fileSize = @filesize($database); 57 | if ($this->fileSize === false) { 58 | throw new \UnexpectedValueException( 59 | "Error determining the size of \"$database\"." 60 | ); 61 | } 62 | 63 | $start = $this->findMetadataStart($database); 64 | $metadataDecoder = new Decoder($this->fileHandle, $start); 65 | list($metadataArray) = $metadataDecoder->decode($start); 66 | $this->metadata = new Metadata($metadataArray); 67 | $this->decoder = new Decoder( 68 | $this->fileHandle, 69 | $this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE 70 | ); 71 | } 72 | 73 | /** 74 | * Looks up the address in the MaxMind DB. 75 | * 76 | * @param string $ipAddress 77 | * the IP address to look up. 78 | * @return array the record for the IP address. 79 | * @throws \BadMethodCallException if this method is called on a closed database. 80 | * @throws \InvalidArgumentException if something other than a single IP address is passed to the method. 81 | * @throws InvalidDatabaseException 82 | * if the database is invalid or there is an error reading 83 | * from it. 84 | */ 85 | public function get($ipAddress) 86 | { 87 | if (func_num_args() != 1) { 88 | throw new \InvalidArgumentException( 89 | 'Method takes exactly one argument.' 90 | ); 91 | } 92 | 93 | if (!is_resource($this->fileHandle)) { 94 | throw new \BadMethodCallException( 95 | 'Attempt to read from a closed MaxMind DB.' 96 | ); 97 | } 98 | 99 | if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) { 100 | throw new \InvalidArgumentException( 101 | "The value \"$ipAddress\" is not a valid IP address." 102 | ); 103 | } 104 | 105 | if ($this->metadata->ipVersion == 4 && strrpos($ipAddress, ':')) { 106 | throw new \InvalidArgumentException( 107 | "Error looking up $ipAddress. You attempted to look up an" 108 | . " IPv6 address in an IPv4-only database." 109 | ); 110 | } 111 | $pointer = $this->findAddressInTree($ipAddress); 112 | if ($pointer == 0) { 113 | return null; 114 | } 115 | return $this->resolveDataPointer($pointer); 116 | } 117 | 118 | private function findAddressInTree($ipAddress) 119 | { 120 | // XXX - could simplify. Done as a byte array to ease porting 121 | $rawAddress = array_merge(unpack('C*', inet_pton($ipAddress))); 122 | 123 | $bitCount = count($rawAddress) * 8; 124 | 125 | // The first node of the tree is always node 0, at the beginning of the 126 | // value 127 | $node = $this->startNode($bitCount); 128 | 129 | for ($i = 0; $i < $bitCount; $i++) { 130 | if ($node >= $this->metadata->nodeCount) { 131 | break; 132 | } 133 | $tempBit = 0xFF & $rawAddress[$i >> 3]; 134 | $bit = 1 & ($tempBit >> 7 - ($i % 8)); 135 | 136 | $node = $this->readNode($node, $bit); 137 | } 138 | if ($node == $this->metadata->nodeCount) { 139 | // Record is empty 140 | return 0; 141 | } elseif ($node > $this->metadata->nodeCount) { 142 | // Record is a data pointer 143 | return $node; 144 | } 145 | throw new InvalidDatabaseException("Something bad happened"); 146 | } 147 | 148 | 149 | private function startNode($length) 150 | { 151 | // Check if we are looking up an IPv4 address in an IPv6 tree. If this 152 | // is the case, we can skip over the first 96 nodes. 153 | if ($this->metadata->ipVersion == 6 && $length == 32) { 154 | return $this->ipV4StartNode(); 155 | } 156 | // The first node of the tree is always node 0, at the beginning of the 157 | // value 158 | return 0; 159 | } 160 | 161 | private function ipV4StartNode() 162 | { 163 | // This is a defensive check. There is no reason to call this when you 164 | // have an IPv4 tree. 165 | if ($this->metadata->ipVersion == 4) { 166 | return 0; 167 | } 168 | 169 | if ($this->ipV4Start != 0) { 170 | return $this->ipV4Start; 171 | } 172 | $node = 0; 173 | 174 | for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; $i++) { 175 | $node = $this->readNode($node, 0); 176 | } 177 | $this->ipV4Start = $node; 178 | return $node; 179 | } 180 | 181 | private function readNode($nodeNumber, $index) 182 | { 183 | $baseOffset = $nodeNumber * $this->metadata->nodeByteSize; 184 | 185 | // XXX - probably could condense this. 186 | switch ($this->metadata->recordSize) { 187 | case 24: 188 | $bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3); 189 | list(, $node) = unpack('N', "\x00" . $bytes); 190 | return $node; 191 | case 28: 192 | $middleByte = Util::read($this->fileHandle, $baseOffset + 3, 1); 193 | list(, $middle) = unpack('C', $middleByte); 194 | if ($index == 0) { 195 | $middle = (0xF0 & $middle) >> 4; 196 | } else { 197 | $middle = 0x0F & $middle; 198 | } 199 | $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 3); 200 | list(, $node) = unpack('N', chr($middle) . $bytes); 201 | return $node; 202 | case 32: 203 | $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4); 204 | list(, $node) = unpack('N', $bytes); 205 | return $node; 206 | default: 207 | throw new InvalidDatabaseException( 208 | 'Unknown record size: ' 209 | . $this->metadata->recordSize 210 | ); 211 | } 212 | } 213 | 214 | private function resolveDataPointer($pointer) 215 | { 216 | $resolved = $pointer - $this->metadata->nodeCount 217 | + $this->metadata->searchTreeSize; 218 | if ($resolved > $this->fileSize) { 219 | throw new InvalidDatabaseException( 220 | "The MaxMind DB file's search tree is corrupt" 221 | ); 222 | } 223 | 224 | list($data) = $this->decoder->decode($resolved); 225 | return $data; 226 | } 227 | 228 | /* 229 | * This is an extremely naive but reasonably readable implementation. There 230 | * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever 231 | * an issue, but I suspect it won't be. 232 | */ 233 | private function findMetadataStart($filename) 234 | { 235 | $handle = $this->fileHandle; 236 | $fstat = fstat($handle); 237 | $fileSize = $fstat['size']; 238 | $marker = self::$METADATA_START_MARKER; 239 | $markerLength = self::$METADATA_START_MARKER_LENGTH; 240 | 241 | for ($i = 0; $i < $fileSize - $markerLength + 1; $i++) { 242 | for ($j = 0; $j < $markerLength; $j++) { 243 | fseek($handle, $fileSize - $i - $j - 1); 244 | $matchBit = fgetc($handle); 245 | if ($matchBit != $marker[$markerLength - $j - 1]) { 246 | continue 2; 247 | } 248 | } 249 | return $fileSize - $i; 250 | } 251 | throw new InvalidDatabaseException( 252 | "Error opening database file ($filename). " . 253 | 'Is this a valid MaxMind DB file?' 254 | ); 255 | } 256 | 257 | /** 258 | * @throws \InvalidArgumentException if arguments are passed to the method. 259 | * @throws \BadMethodCallException if the database has been closed. 260 | * @return Metadata object for the database. 261 | */ 262 | public function metadata() 263 | { 264 | if (func_num_args()) { 265 | throw new \InvalidArgumentException( 266 | 'Method takes no arguments.' 267 | ); 268 | } 269 | 270 | // Not technically required, but this makes it consistent with 271 | // C extension and it allows us to change our implementation later. 272 | if (!is_resource($this->fileHandle)) { 273 | throw new \BadMethodCallException( 274 | 'Attempt to read from a closed MaxMind DB.' 275 | ); 276 | } 277 | 278 | return $this->metadata; 279 | } 280 | 281 | /** 282 | * Closes the MaxMind DB and returns resources to the system. 283 | * 284 | * @throws \Exception 285 | * if an I/O error occurs. 286 | */ 287 | public function close() 288 | { 289 | if (!is_resource($this->fileHandle)) { 290 | throw new \BadMethodCallException( 291 | 'Attempt to close a closed MaxMind DB.' 292 | ); 293 | } 294 | fclose($this->fileHandle); 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php: -------------------------------------------------------------------------------- 1 | 'extended', 19 | 1 => 'pointer', 20 | 2 => 'utf8_string', 21 | 3 => 'double', 22 | 4 => 'bytes', 23 | 5 => 'uint16', 24 | 6 => 'uint32', 25 | 7 => 'map', 26 | 8 => 'int32', 27 | 9 => 'uint64', 28 | 10 => 'uint128', 29 | 11 => 'array', 30 | 12 => 'container', 31 | 13 => 'end_marker', 32 | 14 => 'boolean', 33 | 15 => 'float', 34 | ); 35 | 36 | public function __construct( 37 | $fileStream, 38 | $pointerBase = 0, 39 | $pointerTestHack = false 40 | ) { 41 | $this->fileStream = $fileStream; 42 | $this->pointerBase = $pointerBase; 43 | $this->pointerTestHack = $pointerTestHack; 44 | 45 | $this->switchByteOrder = $this->isPlatformLittleEndian(); 46 | } 47 | 48 | 49 | public function decode($offset) 50 | { 51 | list(, $ctrlByte) = unpack( 52 | 'C', 53 | Util::read($this->fileStream, $offset, 1) 54 | ); 55 | $offset++; 56 | 57 | $type = $this->types[$ctrlByte >> 5]; 58 | 59 | // Pointers are a special case, we don't read the next $size bytes, we 60 | // use the size to determine the length of the pointer and then follow 61 | // it. 62 | if ($type == 'pointer') { 63 | list($pointer, $offset) = $this->decodePointer($ctrlByte, $offset); 64 | 65 | // for unit testing 66 | if ($this->pointerTestHack) { 67 | return array($pointer); 68 | } 69 | 70 | list($result) = $this->decode($pointer); 71 | 72 | return array($result, $offset); 73 | } 74 | 75 | if ($type == 'extended') { 76 | list(, $nextByte) = unpack( 77 | 'C', 78 | Util::read($this->fileStream, $offset, 1) 79 | ); 80 | 81 | $typeNum = $nextByte + 7; 82 | 83 | if ($typeNum < 8) { 84 | throw new InvalidDatabaseException( 85 | "Something went horribly wrong in the decoder. An extended type " 86 | . "resolved to a type number < 8 (" 87 | . $this->types[$typeNum] 88 | . ")" 89 | ); 90 | } 91 | 92 | $type = $this->types[$typeNum]; 93 | $offset++; 94 | } 95 | 96 | list($size, $offset) = $this->sizeFromCtrlByte($ctrlByte, $offset); 97 | 98 | return $this->decodeByType($type, $offset, $size); 99 | } 100 | 101 | private function decodeByType($type, $offset, $size) 102 | { 103 | switch ($type) { 104 | case 'map': 105 | return $this->decodeMap($size, $offset); 106 | case 'array': 107 | return $this->decodeArray($size, $offset); 108 | case 'boolean': 109 | return array($this->decodeBoolean($size), $offset); 110 | } 111 | 112 | $newOffset = $offset + $size; 113 | $bytes = Util::read($this->fileStream, $offset, $size); 114 | switch ($type) { 115 | case 'utf8_string': 116 | return array($this->decodeString($bytes), $newOffset); 117 | case 'double': 118 | $this->verifySize(8, $size); 119 | return array($this->decodeDouble($bytes), $newOffset); 120 | case 'float': 121 | $this->verifySize(4, $size); 122 | return array($this->decodeFloat($bytes), $newOffset); 123 | case 'bytes': 124 | return array($bytes, $newOffset); 125 | case 'uint16': 126 | case 'uint32': 127 | return array($this->decodeUint($bytes), $newOffset); 128 | case 'int32': 129 | return array($this->decodeInt32($bytes), $newOffset); 130 | case 'uint64': 131 | case 'uint128': 132 | return array($this->decodeBigUint($bytes, $size), $newOffset); 133 | default: 134 | throw new InvalidDatabaseException( 135 | "Unknown or unexpected type: " . $type 136 | ); 137 | } 138 | } 139 | 140 | private function verifySize($expected, $actual) 141 | { 142 | if ($expected != $actual) { 143 | throw new InvalidDatabaseException( 144 | "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)" 145 | ); 146 | } 147 | } 148 | 149 | private function decodeArray($size, $offset) 150 | { 151 | $array = array(); 152 | 153 | for ($i = 0; $i < $size; $i++) { 154 | list($value, $offset) = $this->decode($offset); 155 | array_push($array, $value); 156 | } 157 | 158 | return array($array, $offset); 159 | } 160 | 161 | private function decodeBoolean($size) 162 | { 163 | return $size == 0 ? false : true; 164 | } 165 | 166 | private function decodeDouble($bits) 167 | { 168 | // XXX - Assumes IEEE 754 double on platform 169 | list(, $double) = unpack('d', $this->maybeSwitchByteOrder($bits)); 170 | return $double; 171 | } 172 | 173 | private function decodeFloat($bits) 174 | { 175 | // XXX - Assumes IEEE 754 floats on platform 176 | list(, $float) = unpack('f', $this->maybeSwitchByteOrder($bits)); 177 | return $float; 178 | } 179 | 180 | private function decodeInt32($bytes) 181 | { 182 | $bytes = $this->zeroPadLeft($bytes, 4); 183 | list(, $int) = unpack('l', $this->maybeSwitchByteOrder($bytes)); 184 | return $int; 185 | } 186 | 187 | private function decodeMap($size, $offset) 188 | { 189 | 190 | $map = array(); 191 | 192 | for ($i = 0; $i < $size; $i++) { 193 | list($key, $offset) = $this->decode($offset); 194 | list($value, $offset) = $this->decode($offset); 195 | $map[$key] = $value; 196 | } 197 | 198 | return array($map, $offset); 199 | } 200 | 201 | private $pointerValueOffset = array( 202 | 1 => 0, 203 | 2 => 2048, 204 | 3 => 526336, 205 | 4 => 0, 206 | ); 207 | 208 | private function decodePointer($ctrlByte, $offset) 209 | { 210 | $pointerSize = (($ctrlByte >> 3) & 0x3) + 1; 211 | 212 | $buffer = Util::read($this->fileStream, $offset, $pointerSize); 213 | $offset = $offset + $pointerSize; 214 | 215 | $packed = $pointerSize == 4 216 | ? $buffer 217 | : (pack('C', $ctrlByte & 0x7)) . $buffer; 218 | 219 | $unpacked = $this->decodeUint($packed); 220 | $pointer = $unpacked + $this->pointerBase 221 | + $this->pointerValueOffset[$pointerSize]; 222 | 223 | return array($pointer, $offset); 224 | } 225 | 226 | private function decodeUint($bytes) 227 | { 228 | list(, $int) = unpack('N', $this->zeroPadLeft($bytes, 4)); 229 | return $int; 230 | } 231 | 232 | private function decodeBigUint($bytes, $byteLength) 233 | { 234 | $maxUintBytes = log(PHP_INT_MAX, 2) / 8; 235 | 236 | if ($byteLength == 0) { 237 | return 0; 238 | } 239 | 240 | $numberOfLongs = ceil($byteLength / 4); 241 | $paddedLength = $numberOfLongs * 4; 242 | $paddedBytes = $this->zeroPadLeft($bytes, $paddedLength); 243 | $unpacked = array_merge(unpack("N$numberOfLongs", $paddedBytes)); 244 | 245 | $integer = 0; 246 | 247 | // 2^32 248 | $twoTo32 = '4294967296'; 249 | 250 | foreach ($unpacked as $part) { 251 | // We only use gmp or bcmath if the final value is too big 252 | if ($byteLength <= $maxUintBytes) { 253 | $integer = ($integer << 32) + $part; 254 | } elseif (extension_loaded('gmp')) { 255 | $integer = gmp_strval(gmp_add(gmp_mul($integer, $twoTo32), $part)); 256 | } elseif (extension_loaded('bcmath')) { 257 | $integer = bcadd(bcmul($integer, $twoTo32), $part); 258 | } else { 259 | throw new \RuntimeException( 260 | 'The gmp or bcmath extension must be installed to read this database.' 261 | ); 262 | } 263 | } 264 | return $integer; 265 | } 266 | 267 | private function decodeString($bytes) 268 | { 269 | // XXX - NOOP. As far as I know, the end user has to explicitly set the 270 | // encoding in PHP. Strings are just bytes. 271 | return $bytes; 272 | } 273 | 274 | private function sizeFromCtrlByte($ctrlByte, $offset) 275 | { 276 | $size = $ctrlByte & 0x1f; 277 | $bytesToRead = $size < 29 ? 0 : $size - 28; 278 | $bytes = Util::read($this->fileStream, $offset, $bytesToRead); 279 | $decoded = $this->decodeUint($bytes); 280 | 281 | if ($size == 29) { 282 | $size = 29 + $decoded; 283 | } elseif ($size == 30) { 284 | $size = 285 + $decoded; 285 | } elseif ($size > 30) { 286 | $size = ($decoded & (0x0FFFFFFF >> (32 - (8 * $bytesToRead)))) 287 | + 65821; 288 | } 289 | 290 | return array($size, $offset + $bytesToRead); 291 | } 292 | 293 | private function zeroPadLeft($content, $desiredLength) 294 | { 295 | return str_pad($content, $desiredLength, "\x00", STR_PAD_LEFT); 296 | } 297 | 298 | private function maybeSwitchByteOrder($bytes) 299 | { 300 | return $this->switchByteOrder ? strrev($bytes) : $bytes; 301 | } 302 | 303 | private function isPlatformLittleEndian() 304 | { 305 | $testint = 0x00FF; 306 | $packed = pack('S', $testint); 307 | return $testint === current(unpack('v', $packed)); 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/src/MaxMind/Db/Reader/InvalidDatabaseException.php: -------------------------------------------------------------------------------- 1 | binaryFormatMajorVersion = 59 | $metadata['binary_format_major_version']; 60 | $this->binaryFormatMinorVersion = 61 | $metadata['binary_format_minor_version']; 62 | $this->buildEpoch = $metadata['build_epoch']; 63 | $this->databaseType = $metadata['database_type']; 64 | $this->languages = $metadata['languages']; 65 | $this->description = $metadata['description']; 66 | $this->ipVersion = $metadata['ip_version']; 67 | $this->nodeCount = $metadata['node_count']; 68 | $this->recordSize = $metadata['record_size']; 69 | $this->nodeByteSize = $this->recordSize / 4; 70 | $this->searchTreeSize = $this->nodeCount * $this->nodeByteSize; 71 | } 72 | 73 | public function __get($var) 74 | { 75 | return $this->$var; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Util.php: -------------------------------------------------------------------------------- 1 | assertEquals( 16 | array(array('long_key' => 'long_value1'), 22), 17 | $decoder->decode(0) 18 | ); 19 | 20 | $this->assertEquals( 21 | array(array('long_key' => 'long_value2'), 37), 22 | $decoder->decode(22) 23 | ); 24 | 25 | $this->assertEquals( 26 | array(array('long_key2' => 'long_value1'), 50), 27 | $decoder->decode(37) 28 | ); 29 | 30 | $this->assertEquals( 31 | array(array('long_key2' => 'long_value2'), 55), 32 | $decoder->decode(50) 33 | ); 34 | 35 | $this->assertEquals( 36 | array(array('long_key' => 'long_value1'), 57), 37 | $decoder->decode(55) 38 | ); 39 | 40 | $this->assertEquals( 41 | array(array('long_key2' => 'long_value2'), 59), 42 | $decoder->decode(57) 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/maxmind-db/reader/tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('MaxMind\Db\Test', __DIR__); 8 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .gh-pages 3 | .idea 4 | apigen.phar 5 | box.phar 6 | build 7 | composer.lock 8 | composer.phar 9 | phpunit.xml 10 | t.php 11 | vendor/ 12 | *.iml 13 | *.sw? 14 | *.old 15 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | - hhvm 9 | 10 | before_install: 11 | - composer self-update 12 | - composer install --dev -n --prefer-source 13 | - if [ "5.5" == $TRAVIS_PHP_VERSION ]; then pyrus install pear/PHP_CodeSniffer; fi 14 | - phpenv rehash 15 | 16 | script: 17 | - mkdir -p build/logs 18 | - if [ "5.5" == $TRAVIS_PHP_VERSION ]; then phpcs --standard=PSR2 src/; fi 19 | - ./vendor/bin/phpunit 20 | 21 | notifications: 22 | email: 23 | recipients: 24 | - dev@maxmind.com 25 | on_success: change 26 | on_failure: always 27 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 0.0.4 (2015-07-21) 5 | ------------------ 6 | 7 | * Added extremely basic tests for the curl calls. 8 | * Fixed broken POSTs. 9 | 10 | 0.0.3 (2015-06-30) 11 | ------------------ 12 | 13 | * Floats now work with the `timeout` and `connectTimeout` options. Fix by 14 | Benjamin Pick. GitHub PR #2. 15 | * `curl_error` is now used instead of `curl_strerror`. The latter is only 16 | available for PHP 5.5 or later. Fix by Benjamin Pick. GitHub PR #1. 17 | 18 | 19 | 0.0.2 (2015-06-09) 20 | ------------------ 21 | 22 | * An exception is now immediately thrown curl error rather than letting later 23 | status code checks throw an exception. This improves the exception message 24 | greatly. 25 | * If this library is inside a phar archive, the CA certs are copied out of the 26 | archive to a temporary file so that curl can use them. 27 | 28 | 0.0.1 (2015-06-01) 29 | ------------------ 30 | 31 | * Initial release. 32 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/README.md: -------------------------------------------------------------------------------- 1 | # MaxMind Web Service Common # 2 | 3 | This is _not_ intended for direct use by third parties. Rather, it is for 4 | shared code between MaxMind's various web service APIs. 5 | 6 | ## Requirements ## 7 | 8 | This code requires PHP 5.3 or greater. Older versions of PHP are not 9 | supported. This library works and is tested with HHVM. 10 | 11 | There are several other dependencies as defined in the `composer.json` file. 12 | 13 | ## Contributing ## 14 | 15 | Patches and pull requests are encouraged. All code should follow the PSR-2 16 | style guidelines. Please include unit tests whenever possible. 17 | 18 | ## Versioning ## 19 | 20 | This API uses [Semantic Versioning](http://semver.org/). 21 | 22 | ## Copyright and License ## 23 | 24 | This software is Copyright (c) 2015 by MaxMind, Inc. 25 | 26 | This is free software, licensed under the Apache License, Version 2.0. 27 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "maxmind/web-service-common", 3 | "description": "Internal MaxMind Web Service API", 4 | "minimum-stability": "stable", 5 | "homepage": "https://github.com/maxmind/mm-web-service-api-php", 6 | "type": "library", 7 | "license": "Apache-2.0", 8 | "authors": [ 9 | { 10 | "name": "Gregory Oschwald", 11 | "email": "goschwald@maxmind.com" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=5.3", 16 | "ext-curl": "*", 17 | "ext-json": "*" 18 | }, 19 | "require-dev": { 20 | "phpunit/phpunit": "4.6.*" 21 | }, 22 | "autoload": { 23 | "psr-4": { 24 | "MaxMind\\": "src" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ./tests/MaxMind/Test/ 7 | 8 | 9 | 10 | 11 | 12 | ./src/MaxMind/ 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php: -------------------------------------------------------------------------------- 1 | uri = $uri; 28 | parent::__construct($message, $httpStatus, $previous); 29 | } 30 | 31 | public function getUri() 32 | { 33 | return $this->uri; 34 | } 35 | 36 | public function getStatusCode() 37 | { 38 | return $this->getCode(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php: -------------------------------------------------------------------------------- 1 | error = $error; 30 | parent::__construct($message, $httpStatus, $uri, $previous); 31 | } 32 | 33 | public function getErrorCode() 34 | { 35 | return $this->error; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php: -------------------------------------------------------------------------------- 1 | url = $url; 24 | $this->options = $options; 25 | } 26 | 27 | /** 28 | * @param $body 29 | * @return array 30 | */ 31 | public function post($body) 32 | { 33 | $curl = $this->createCurl(); 34 | 35 | curl_setopt($curl, CURLOPT_POST, true); 36 | curl_setopt($curl, CURLOPT_POSTFIELDS, $body); 37 | 38 | return $this->execute($curl); 39 | } 40 | 41 | public function get() 42 | { 43 | $curl = $this->createCurl(); 44 | 45 | curl_setopt($curl, CURLOPT_HTTPGET, true); 46 | 47 | return $this->execute($curl); 48 | } 49 | 50 | /** 51 | * @return resource 52 | */ 53 | private function createCurl() 54 | { 55 | $curl = curl_init($this->url); 56 | 57 | $opts[CURLOPT_CAINFO] = $this->options['caBundle']; 58 | $opts[CURLOPT_SSL_VERIFYHOST] = 2; 59 | $opts[CURLOPT_FOLLOWLOCATION] = false; 60 | $opts[CURLOPT_SSL_VERIFYPEER] = true; 61 | $opts[CURLOPT_RETURNTRANSFER] = true; 62 | 63 | 64 | $opts[CURLOPT_HTTPHEADER] = $this->options['headers']; 65 | $opts[CURLOPT_USERAGENT] = $this->options['userAgent']; 66 | 67 | $connectTimeout = $this->options['connectTimeout']; 68 | if (defined('CURLOPT_CONNECTTIMEOUT_MS')) { 69 | $opts[CURLOPT_CONNECTTIMEOUT_MS] = ceil($connectTimeout * 1000); 70 | } else { 71 | $opts[CURLOPT_CONNECTTIMEOUT] = ceil($connectTimeout); 72 | } 73 | 74 | $timeout = $this->options['timeout']; 75 | if (defined('CURLOPT_TIMEOUT_MS')) { 76 | $opts[CURLOPT_TIMEOUT_MS] = ceil($timeout * 1000); 77 | } else { 78 | $opts[CURLOPT_TIMEOUT] = ceil($timeout); 79 | } 80 | 81 | curl_setopt_array($curl, $opts); 82 | return $curl; 83 | } 84 | 85 | private function execute($curl) 86 | { 87 | $body = curl_exec($curl); 88 | if ($errno = curl_errno($curl)) { 89 | $error_message = curl_error($curl); 90 | 91 | throw new HttpException( 92 | "cURL error ({$errno}): {$error_message}", 93 | 0, 94 | $this->url 95 | ); 96 | } 97 | 98 | $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); 99 | $contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE); 100 | curl_close($curl); 101 | 102 | return array($statusCode, $contentType, $body); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/src/WebService/Http/Request.php: -------------------------------------------------------------------------------- 1 | assertEquals( 13 | array('a' => 'b'), 14 | $this->withResponse( 15 | '200', 16 | 'application/json', 17 | '{"a":"b"}' 18 | ), 19 | 'received expected decoded response' 20 | ); 21 | } 22 | 23 | public function testOptions() 24 | { 25 | $this->runRequest( 26 | 'TestService', 27 | '/path', 28 | array(), 29 | 200, 30 | 'application/json', 31 | '{}', 32 | 3213, 33 | 'abcdefghij', 34 | array( 35 | 'caBundle' => '/path/to/ca.pem', 36 | 'timeout' => 100, 37 | 'connectTimeout' => 15, 38 | 'userAgent' => 'TestClient/1', 39 | 40 | ) 41 | ); 42 | } 43 | 44 | /** 45 | * @expectedException MaxMind\Exception\WebServiceException 46 | * @expectedExceptionMessage Received a 200 response for TestService but could not decode the response as JSON: Syntax error. Body: { 47 | */ 48 | public function test200WithInvalidJson() 49 | { 50 | $this->withResponse('200', 'application/json', '{'); 51 | } 52 | 53 | /** 54 | * @expectedException MaxMind\Exception\InsufficientFundsException 55 | * @expectedExceptionMessage out of credit 56 | */ 57 | public function testInsufficientFunds() 58 | { 59 | $this->withResponse( 60 | '402', 61 | 'application/json', 62 | '{"code":"INSUFFICIENT_FUNDS","error":"out of credit"}' 63 | ); 64 | } 65 | 66 | /** 67 | * @expectedException MaxMind\Exception\AuthenticationException 68 | * @expectedExceptionMessage Invalid auth 69 | * @dataProvider invalidAuthCodes 70 | */ 71 | public function testInvalidAuth($code) 72 | { 73 | $this->withResponse( 74 | '401', 75 | 'application/json', 76 | '{"code":"' . $code . '","error":"Invalid auth"}' 77 | ); 78 | } 79 | 80 | public function invalidAuthCodes() 81 | { 82 | return array( 83 | array('AUTHORIZATION_INVALID'), 84 | array('LICENSE_KEY_REQUIRED'), 85 | array('USER_ID_REQUIRED') 86 | ); 87 | } 88 | 89 | /** 90 | * @expectedException MaxMind\Exception\InvalidRequestException 91 | * @expectedExceptionMessage IP invalid 92 | */ 93 | public function testInvalidRequest() 94 | { 95 | $this->withResponse( 96 | '400', 97 | 'application/json', 98 | '{"code":"IP_ADDRESS_INVALID","error":"IP invalid"}' 99 | ); 100 | } 101 | 102 | /** 103 | * @expectedException MaxMind\Exception\WebServiceException 104 | * @expectedExceptionMessage Received a 400 error for TestService but could not decode the response as JSON: Syntax error. Body: {"blah"} 105 | */ 106 | public function test400WithInvalidJson() 107 | { 108 | $this->withResponse('400', 'application/json', '{"blah"}'); 109 | } 110 | 111 | /** 112 | * @expectedException MaxMind\Exception\HttpException 113 | * @expectedExceptionMessage Received a 400 error for TestService with no body 114 | */ 115 | public function test400WithNoBody() 116 | { 117 | $this->withResponse('400', 'application/json', ''); 118 | } 119 | 120 | /** 121 | * @expectedException MaxMind\Exception\HttpException 122 | * @expectedExceptionMessage Received a 400 error for TestService with the following body: text 123 | */ 124 | public function test400WithUnexpectedContentType() 125 | { 126 | $this->withResponse('400', 'text/plain', 'text'); 127 | } 128 | 129 | /** 130 | * @expectedException MaxMind\Exception\HttpException 131 | * @expectedExceptionMessage Error response contains JSON but it does not specify code or error keys: {"not":"expected"} 132 | */ 133 | public function test400WithUnexpectedJson() 134 | { 135 | $this->withResponse('400', 'application/json', '{"not":"expected"}'); 136 | } 137 | 138 | /** 139 | * @expectedException MaxMind\Exception\HttpException 140 | * @expectedExceptionMessage Received an unexpected HTTP status (300) for TestService 141 | */ 142 | public function test300() 143 | { 144 | $this->withResponse('300', 'application/json', ''); 145 | } 146 | 147 | /** 148 | * @expectedException MaxMind\Exception\HttpException 149 | * @expectedExceptionMessage Received a server error (500) for TestService 150 | */ 151 | public function test500() 152 | { 153 | $this->withResponse('500', 'application/json', ''); 154 | } 155 | 156 | // convenience method when you don't care about the request 157 | private function withResponse($statusCode, $contentType, $body) 158 | { 159 | return $this->runRequest( 160 | 'TestService', 161 | '/path', 162 | array(), 163 | $statusCode, 164 | $contentType, 165 | $body 166 | ); 167 | } 168 | 169 | private function runRequest( 170 | $service, 171 | $path, 172 | $requestContent, 173 | $statusCode, 174 | $contentType, 175 | $responseBody, 176 | $userId = 10, 177 | $licenseKey = '0123456789', 178 | $options = array() 179 | ) { 180 | $stub = $this->getMockForAbstractClass( 181 | 'MaxMind\\WebService\\Http\\Request' 182 | ); 183 | 184 | $stub->expects($this->once()) 185 | ->method('post') 186 | ->with($this->equalTo(json_encode($requestContent))) 187 | ->willReturn(array($statusCode, $contentType, $responseBody)); 188 | 189 | $factory = $this->getMockBuilder( 190 | 'MaxMind\\WebService\\Http\\RequestFactory' 191 | )->getMock(); 192 | 193 | $host = isset($options['host']) ? $options['host'] : 'api.maxmind.com'; 194 | 195 | $url = 'https://' . $host . $path; 196 | 197 | $headers = array( 198 | 'Content-Type: application/json', 199 | 'Authorization: Basic ' 200 | . base64_encode($userId . ':' . $licenseKey), 201 | 'Accept: application/json', 202 | ); 203 | 204 | $curlVersion = curl_version(); 205 | $userAgent = 'MaxMind-WS-API/' . Client::VERSION . ' PHP/' . PHP_VERSION 206 | . ' curl/' . $curlVersion['version']; 207 | if (isset($options['userAgent'])) { 208 | $userAgent = $options['userAgent'] . ' ' . $userAgent; 209 | } 210 | 211 | if (isset($options['caBundle'])) { 212 | $caBundle = $options['caBundle']; 213 | } else { 214 | $reflectionClass = new \ReflectionClass('MaxMind\\WebService\\Client'); 215 | $file = $reflectionClass->getFileName(); 216 | $caBundle = dirname($file) . '/cacert.pem'; 217 | } 218 | 219 | $factory->expects($this->once()) 220 | ->method('request') 221 | ->with( 222 | $this->equalTo($url), 223 | $this->equalTo( 224 | array( 225 | 'headers' => $headers, 226 | 'userAgent' => $userAgent, 227 | 'connectTimeout' => isset($options['connectTimeout']) 228 | ? $options['connectTimeout'] : null, 229 | 'timeout' => isset($options['timeout']) 230 | ? $options['timeout'] : null, 231 | 'caBundle' => $caBundle, 232 | ) 233 | ) 234 | )->willReturn($stub); 235 | 236 | $options['httpRequestFactory'] = $factory; 237 | $client = new Client( 238 | $userId, 239 | $licenseKey, 240 | $options 241 | ); 242 | 243 | return $client->post($service, $path, $requestContent); 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/tests/MaxMind/Test/WebService/Http/CurlRequestTest.php: -------------------------------------------------------------------------------- 1 | null, 18 | 'headers' => array(), 19 | 'userAgent' => 'Test', 20 | 'connectTimeout' => 0, 21 | 'timeout' => 0, 22 | ); 23 | 24 | /** 25 | * @expectedException MaxMind\Exception\HttpException 26 | * @expectedExceptionMessage cURL error (6): 27 | */ 28 | public function testGet() 29 | { 30 | $cr = new CurlRequest( 31 | 'invalid host', 32 | $this->options 33 | ); 34 | 35 | $cr->get(); 36 | } 37 | 38 | 39 | /** 40 | * @expectedException MaxMind\Exception\HttpException 41 | * @expectedExceptionMessage cURL error (6): 42 | */ 43 | public function testPost() 44 | { 45 | $cr = new CurlRequest( 46 | 'invalid host', 47 | $this->options 48 | ); 49 | 50 | $cr->post('POST BODY'); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vendor/maxmind/web-service-common/tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('MaxMind\Test', __DIR__); 8 | -------------------------------------------------------------------------------- /woo-includes/class-wc-dependencies.php: -------------------------------------------------------------------------------- 1 |

' . sprintf( __( 'WooCommerce Geolocation Based Products Plugin requires WooCommerce to be installed and active. You can download %s here.', 'woocommerce-geolocation-based-products' ), 'WooCommerce' ) . '

'; 115 | } 116 | 117 | /** 118 | * Show action links on the plugin screen 119 | * 120 | * @param mixed $links 121 | * @return array 122 | */ 123 | public function action_links( $links ) { 124 | return array_merge( $links, array( 125 | '' . __( 'Settings', 'woocommerce-geolocation-based-products' ) . '', 126 | ) ); 127 | } 128 | } 129 | 130 | if ( ! function_exists( 'woocommerce_geolocation_based_products_init' ) ) : 131 | add_action( 'plugins_loaded', 'woocommerce_geolocation_based_products_init', 0 ); 132 | endif; 133 | 134 | /** 135 | * init function 136 | * 137 | * @package WC_Geolocation_Based_Products 138 | * @since 1.0.0 139 | * @return bool 140 | */ 141 | function woocommerce_geolocation_based_products_init() { 142 | new WC_Geolocation_Based_Products(); 143 | 144 | return true; 145 | } 146 | 147 | endif; 148 | --------------------------------------------------------------------------------