[
  {
    "path": ".gitignore",
    "content": "*.ap_\n\n# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\nout/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n# Android Studio captures folder\ncaptures/\n\n# Intellij\n*.iml\n.idea/workspace.xml\n\n# Keystore files\n*.jks\n"
  },
  {
    "path": "Android-code/.gitignore",
    "content": "*.iml\n.gradle\n.idea\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n/app/src/test\n/app/src/androidTest\n/app/src/debug/\n/app/src/release/\n/app/build"
  },
  {
    "path": "Android-code/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "Android-code/app/build.gradle",
    "content": "buildscript {\n    repositories {\n        maven { url 'https://maven.fabric.io/public' }\n    }\n\n    dependencies {\n        classpath 'io.fabric.tools:gradle:1.+'\n    }\n}\napply plugin: 'com.android.application'\napply plugin: 'io.fabric'\n\nrepositories {\n    maven { url 'https://maven.fabric.io/public' }\n}\n\n\nandroid {\n    compileSdkVersion 24\n    buildToolsVersion \"24.0.2\"\n\n    defaultConfig {\n        applicationId \"com.vasilkoff.easyvpnfree\"\n        minSdkVersion 17\n        targetSdkVersion 24\n        versionCode 50\n        versionName \"1.6\"\n        setProperty(\"archivesBaseName\", \"easyvpnfree-$versionName-$versionCode\")\n    }\n\n    lintOptions {\n        disable 'MissingTranslation'\n    }\n\n    productFlavors {\n        free {\n            applicationId \"com.vasilkoff.easyvpnfree\"\n            resValue \"string\", \"app_name\", \"Easy VPN Free\"\n            resValue \"string\", \"notification_title\", \"Easy VPN Free - %s\"\n        }\n\n        pro {\n            applicationId \"com.vasilkoff.easyvpn\"\n            resValue \"string\", \"app_name\", \"Easy VPN\"\n            resValue \"string\", \"notification_title\", \"Easy VPN - %s\"\n        }\n\n        underground {\n            applicationId \"com.vasilkoff.easyvpnunderground\"\n            resValue \"string\", \"app_name\", \"Easy VPN\"\n            resValue \"string\", \"notification_title\", \"Easy VPN - %s\"\n        }\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            shrinkResources false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n//            ndk {\n//              //abiFilters \"armeabi\" \"x86\"\n//                abiFilters \"armeabi-v7a\", \"armeabi\", \"arm64-v8a\" // includes ARM SO files only, so no x86 SO file\n//            }\n        }\n    }\n}\n\n\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    compile 'com.android.support:appcompat-v7:24.2.1'\n    compile 'com.android.support:support-v4:24.2.1'\n    compile 'com.android.support:design:24.2.1'\n    compile 'com.android.support:recyclerview-v7:24.2.1'\n    compile 'com.android.support:cardview-v7:24.2.1'\n\n    compile 'com.daimajia.numberprogressbar:library:1.2@aar'\n    compile 'com.amitshekhar.android:android-networking:0.2.0'\n    compile 'com.google.code.gson:gson:2.7'\n    compile 'org.mapsforge:mapsforge-map-android:0.6.1'\n    compile 'com.caverock:androidsvg:1.2.2-beta-1'\n    testCompile 'junit:junit:4.12'\n    compile('com.crashlytics.sdk.android:crashlytics:2.6.5@aar') {\n        transitive = true\n    }\n    compile 'com.google.android.gms:play-services-analytics:10.0.1'\n}"
  },
  {
    "path": "Android-code/app/fabric.properties",
    "content": "#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public.\n#Wed Dec 14 11:21:31 EET 2016\napiSecret=27f37b51b9f4db8a01ed83314a725d24366fde53dbe7c0ea1df76514132181ff\n"
  },
  {
    "path": "Android-code/app/google-services.json",
    "content": "{\n  \"project_info\": {\n    \"project_number\": \"1067063466316\",\n    \"project_id\": \"easy-vpn-free\"\n  },\n  \"client\": [\n    {\n      \"client_info\": {\n        \"mobilesdk_app_id\": \"1:1067063466316:android:4ff3282175fe4450\",\n        \"android_client_info\": {\n          \"package_name\": \"com.vasilkoff.easyvpnfree\"\n        }\n      },\n      \"oauth_client\": [],\n      \"api_key\": [\n        {\n          \"current_key\": \"AIzaSyDIDrdo6WD-2RE5dNYGV2XIFcc7qhN9A80\"\n        }\n      ],\n      \"services\": {\n        \"analytics_service\": {\n          \"status\": 2,\n          \"analytics_property\": {\n            \"tracking_id\": \"UA-89622148-1\"\n          }\n        },\n        \"appinvite_service\": {\n          \"status\": 1,\n          \"other_platform_oauth_client\": []\n        },\n        \"ads_service\": {\n          \"status\": 1\n        }\n      }\n    }\n  ],\n  \"configuration_version\": \"1\"\n}"
  },
  {
    "path": "Android-code/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/Vasilkoff/Library/Android/sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "Android-code/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.vasilkoff.easyvpnfree\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"com.android.vending.BILLING\" />\n    <uses-permission android:name=\"android.permission.WAKE_LOCK\" />\n\n    <application\n        android:name=\".App\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".activity.LauncherActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\".activity.LoaderActivity\"\n            android:noHistory=\"true\" />\n        <activity android:name=\".activity.HomeActivity\">\n\n        </activity>\n        <activity android:name=\".activity.ServersListActivity\" />\n        <activity\n            android:name=\".activity.ServerActivity\"\n            android:launchMode=\"singleTop\" />\n        <activity android:name=\".activity.AboutActivity\" />\n        <activity\n            android:name=\".activity.ServersInfo\"\n            android:theme=\"@style/AppTheme.PopUp\" />\n        <activity\n            android:name=\".activity.MyPreferencesActivity\"\n            android:label=\"@string/action_settings\"\n            android:noHistory=\"true\" />\n\n        <service\n            android:name=\"de.blinkt.openvpn.core.OpenVPNService\"\n            android:permission=\"android.permission.BIND_VPN_SERVICE\">\n            <intent-filter>\n                <action android:name=\"android.net.VpnService\" />\n            </intent-filter>\n        </service>\n\n        <meta-data\n            android:name=\"io.fabric.ApiKey\"\n            android:value=\"f3381de560e52052038ffb42a852d4b4df492896\" />\n\n        <!--\n      Optionally, register AnalyticsReceiver and AnalyticsService to support background\n      dispatching on non-Google Play devices\n        -->\n        <receiver\n            android:name=\"com.google.android.gms.analytics.AnalyticsReceiver\"\n            android:enabled=\"true\">\n            <intent-filter>\n                <action android:name=\"com.google.android.gms.analytics.ANALYTICS_DISPATCH\" />\n            </intent-filter>\n        </receiver>\n\n        <service\n            android:name=\"com.google.android.gms.analytics.AnalyticsService\"\n            android:enabled=\"true\"\n            android:exported=\"false\" />\n\n        <!--\n             Optionally, register CampaignTrackingReceiver and CampaignTrackingService to enable\n             installation campaign reporting\n        -->\n        <receiver\n            android:name=\"com.google.android.gms.analytics.CampaignTrackingReceiver\"\n            android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"com.android.vending.INSTALL_REFERRER\" />\n            </intent-filter>\n        </receiver>\n\n        <service android:name=\"com.google.android.gms.analytics.CampaignTrackingService\" />\n\n        <activity android:name=\".activity.BookmarkServerListActivity\"></activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "Android-code/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl",
    "content": "/*\n * Copyright (C) 2012 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.android.vending.billing;\n\nimport android.os.Bundle;\n\n/**\n * InAppBillingService is the service that provides in-app billing version 3 and beyond.\n * This service provides the following features:\n * 1. Provides a new API to get details of in-app items published for the app including\n *    price, type, title and description.\n * 2. The purchase flow is synchronous and purchase information is available immediately\n *    after it completes.\n * 3. Purchase information of in-app purchases is maintained within the Google Play system\n *    till the purchase is consumed.\n * 4. An API to consume a purchase of an inapp item. All purchases of one-time\n *    in-app items are consumable and thereafter can be purchased again.\n * 5. An API to get current purchases of the user immediately. This will not contain any\n *    consumed purchases.\n *\n * All calls will give a response code with the following possible values\n * RESULT_OK = 0 - success\n * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog\n * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested\n * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase\n * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API\n * RESULT_ERROR = 6 - Fatal error during the API action\n * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned\n * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned\n */\ninterface IInAppBillingService {\n    /**\n     * Checks support for the requested billing API version, package and in-app type.\n     * Minimum API version supported by this interface is 3.\n     * @param apiVersion the billing version which the app is using\n     * @param packageName the package name of the calling app\n     * @param type type of the in-app item being purchased \"inapp\" for one-time purchases\n     *        and \"subs\" for subscription.\n     * @return RESULT_OK(0) on success, corresponding result code on failures\n     */\n    int isBillingSupported(int apiVersion, String packageName, String type);\n\n    /**\n     * Provides details of a list of SKUs\n     * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle\n     * with a list JSON strings containing the productId, price, title and description.\n     * This API can be called with a maximum of 20 SKUs.\n     * @param apiVersion billing API version that the Third-party is using\n     * @param packageName the package name of the calling app\n     * @param skusBundle bundle containing a StringArrayList of SKUs with key \"ITEM_ID_LIST\"\n     * @return Bundle containing the following key-value pairs\n     *         \"RESPONSE_CODE\" with int value, RESULT_OK(0) if success, other response codes on\n     *              failure as listed above.\n     *         \"DETAILS_LIST\" with a StringArrayList containing purchase information\n     *              in JSON format similar to:\n     *              '{ \"productId\" : \"exampleSku\", \"type\" : \"inapp\", \"price\" : \"$5.00\",\n     *                 \"title : \"Example Title\", \"description\" : \"This is an example description\" }'\n     */\n    Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);\n\n    /**\n     * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,\n     * the type, a unique purchase token and an optional developer payload.\n     * @param apiVersion billing API version that the app is using\n     * @param packageName package name of the calling app\n     * @param sku the SKU of the in-app item as published in the developer console\n     * @param type the type of the in-app item (\"inapp\" for one-time purchases\n     *        and \"subs\" for subscription).\n     * @param developerPayload optional argument to be sent back with the purchase information\n     * @return Bundle containing the following key-value pairs\n     *         \"RESPONSE_CODE\" with int value, RESULT_OK(0) if success, other response codes on\n     *              failure as listed above.\n     *         \"BUY_INTENT\" - PendingIntent to start the purchase flow\n     *\n     * The Pending intent should be launched with startIntentSenderForResult. When purchase flow\n     * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.\n     * If the purchase is successful, the result data will contain the following key-value pairs\n     *         \"RESPONSE_CODE\" with int value, RESULT_OK(0) if success, other response codes on\n     *              failure as listed above.\n     *         \"INAPP_PURCHASE_DATA\" - String in JSON format similar to\n     *              '{\"orderId\":\"12999763169054705758.1371079406387615\",\n     *                \"packageName\":\"com.example.app\",\n     *                \"productId\":\"exampleSku\",\n     *                \"purchaseTime\":1345678900000,\n     *                \"purchaseToken\" : \"122333444455555\",\n     *                \"developerPayload\":\"example developer payload\" }'\n     *         \"INAPP_DATA_SIGNATURE\" - String containing the signature of the purchase data that\n     *                                  was signed with the private key of the developer\n     *                                  TODO: change this to app-specific keys.\n     */\n    Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,\n        String developerPayload);\n\n    /**\n     * Returns the current SKUs owned by the user of the type and package name specified along with\n     * purchase information and a signature of the data to be validated.\n     * This will return all SKUs that have been purchased in V3 and managed items purchased using\n     * V1 and V2 that have not been consumed.\n     * @param apiVersion billing API version that the app is using\n     * @param packageName package name of the calling app\n     * @param type the type of the in-app items being requested\n     *        (\"inapp\" for one-time purchases and \"subs\" for subscription).\n     * @param continuationToken to be set as null for the first call, if the number of owned\n     *        skus are too many, a continuationToken is returned in the response bundle.\n     *        This method can be called again with the continuation token to get the next set of\n     *        owned skus.\n     * @return Bundle containing the following key-value pairs\n     *         \"RESPONSE_CODE\" with int value, RESULT_OK(0) if success, other response codes on\n     *              failure as listed above.\n     *         \"INAPP_PURCHASE_ITEM_LIST\" - StringArrayList containing the list of SKUs\n     *         \"INAPP_PURCHASE_DATA_LIST\" - StringArrayList containing the purchase information\n     *         \"INAPP_DATA_SIGNATURE_LIST\"- StringArrayList containing the signatures\n     *                                      of the purchase information\n     *         \"INAPP_CONTINUATION_TOKEN\" - String containing a continuation token for the\n     *                                      next set of in-app purchases. Only set if the\n     *                                      user has more owned skus than the current list.\n     */\n    Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);\n\n    /**\n     * Consume the last purchase of the given SKU. This will result in this item being removed\n     * from all subsequent responses to getPurchases() and allow re-purchase of this item.\n     * @param apiVersion billing API version that the app is using\n     * @param packageName package name of the calling app\n     * @param purchaseToken token in the purchase information JSON that identifies the purchase\n     *        to be consumed\n     * @return 0 if consumption succeeded. Appropriate error values for failures.\n     */\n    int consumePurchase(int apiVersion, String packageName, String purchaseToken);\n}\n"
  },
  {
    "path": "Android-code/app/src/main/assets/countries.json",
    "content": "[{\"CountryName\":\"Somaliland\",\"CapitalName\":\"Hargeisa\",\"CapitalLatitude\":\"9.55\",\"CapitalLongitude\":\"44.050000\",\"CountryCode\":\"NULL\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"South Georgia and South Sandwich Islands\",\"CapitalName\":\"King Edward Point\",\"CapitalLatitude\":\"-54.283333\",\"CapitalLongitude\":\"-36.500000\",\"CountryCode\":\"GS\",\"ContinentName\":\"Antarctica\"},{\"CountryName\":\"French Southern and Antarctic Lands\",\"CapitalName\":\"Port-aux-FranÃ§ais\",\"CapitalLatitude\":\"-49.35\",\"CapitalLongitude\":\"70.216667\",\"CountryCode\":\"TF\",\"ContinentName\":\"Antarctica\"},{\"CountryName\":\"Palestine\",\"CapitalName\":\"Jerusalem\",\"CapitalLatitude\":\"31.7731264\",\"CapitalLongitude\":\"35.36258698\",\"CountryCode\":\"PS\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Aland Islands\",\"CapitalName\":\"Mariehamn\",\"CapitalLatitude\":\"60.116667\",\"CapitalLongitude\":\"19.900000\",\"CountryCode\":\"AX\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Nauru\",\"CapitalName\":\"Yaren\",\"CapitalLatitude\":\"-0.5477\",\"CapitalLongitude\":\"166.920867\",\"CountryCode\":\"NR\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Saint Martin\",\"CapitalName\":\"Marigot\",\"CapitalLatitude\":\"18.0731\",\"CapitalLongitude\":\"-63.082200\",\"CountryCode\":\"MF\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Tokelau\",\"CapitalName\":\"Atafu\",\"CapitalLatitude\":\"-9.166667\",\"CapitalLongitude\":\"-171.833333\",\"CountryCode\":\"TK\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Western Sahara\",\"CapitalName\":\"El-AaiÃºn\",\"CapitalLatitude\":\"27.153611\",\"CapitalLongitude\":\"-13.203333\",\"CountryCode\":\"EH\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Afghanistan\",\"CapitalName\":\"Kabul\",\"CapitalLatitude\":\"34.516666666666666\",\"CapitalLongitude\":\"69.183333\",\"CountryCode\":\"AF\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Albania\",\"CapitalName\":\"Tirana\",\"CapitalLatitude\":\"41.31666666666667\",\"CapitalLongitude\":\"19.816667\",\"CountryCode\":\"AL\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Algeria\",\"CapitalName\":\"Algiers\",\"CapitalLatitude\":\"36.75\",\"CapitalLongitude\":\"3.050000\",\"CountryCode\":\"DZ\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"American Samoa\",\"CapitalName\":\"Pago Pago\",\"CapitalLatitude\":\"-14.266666666666667\",\"CapitalLongitude\":\"-170.700000\",\"CountryCode\":\"AS\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Andorra\",\"CapitalName\":\"Andorra la Vella\",\"CapitalLatitude\":\"42.5\",\"CapitalLongitude\":\"1.516667\",\"CountryCode\":\"AD\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Angola\",\"CapitalName\":\"Luanda\",\"CapitalLatitude\":\"-8.833333333333334\",\"CapitalLongitude\":\"13.216667\",\"CountryCode\":\"AO\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Anguilla\",\"CapitalName\":\"The Valley\",\"CapitalLatitude\":\"18.216666666666665\",\"CapitalLongitude\":\"-63.050000\",\"CountryCode\":\"AI\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Antigua and Barbuda\",\"CapitalName\":\"Saint John's\",\"CapitalLatitude\":\"17.116666666666667\",\"CapitalLongitude\":\"-61.850000\",\"CountryCode\":\"AG\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Argentina\",\"CapitalName\":\"Buenos Aires\",\"CapitalLatitude\":\"-34.583333333333336\",\"CapitalLongitude\":\"-58.666667\",\"CountryCode\":\"AR\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Armenia\",\"CapitalName\":\"Yerevan\",\"CapitalLatitude\":\"40.166666666666664\",\"CapitalLongitude\":\"44.500000\",\"CountryCode\":\"AM\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Aruba\",\"CapitalName\":\"Oranjestad\",\"CapitalLatitude\":\"12.516666666666667\",\"CapitalLongitude\":\"-70.033333\",\"CountryCode\":\"AW\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Australia\",\"CapitalName\":\"Canberra\",\"CapitalLatitude\":\"-35.266666666666666\",\"CapitalLongitude\":\"149.133333\",\"CountryCode\":\"AU\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Austria\",\"CapitalName\":\"Vienna\",\"CapitalLatitude\":\"48.2\",\"CapitalLongitude\":\"16.366667\",\"CountryCode\":\"AT\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Azerbaijan\",\"CapitalName\":\"Baku\",\"CapitalLatitude\":\"40.38333333333333\",\"CapitalLongitude\":\"49.866667\",\"CountryCode\":\"AZ\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Bahamas\",\"CapitalName\":\"Nassau\",\"CapitalLatitude\":\"25.083333333333332\",\"CapitalLongitude\":\"-77.350000\",\"CountryCode\":\"BS\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Bahrain\",\"CapitalName\":\"Manama\",\"CapitalLatitude\":\"26.233333333333334\",\"CapitalLongitude\":\"50.566667\",\"CountryCode\":\"BH\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Bangladesh\",\"CapitalName\":\"Dhaka\",\"CapitalLatitude\":\"23.716666666666665\",\"CapitalLongitude\":\"90.400000\",\"CountryCode\":\"BD\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Barbados\",\"CapitalName\":\"Bridgetown\",\"CapitalLatitude\":\"13.1\",\"CapitalLongitude\":\"-59.616667\",\"CountryCode\":\"BB\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Belarus\",\"CapitalName\":\"Minsk\",\"CapitalLatitude\":\"53.9\",\"CapitalLongitude\":\"27.566667\",\"CountryCode\":\"BY\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Belgium\",\"CapitalName\":\"Brussels\",\"CapitalLatitude\":\"50.833333333333336\",\"CapitalLongitude\":\"4.333333\",\"CountryCode\":\"BE\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Belize\",\"CapitalName\":\"Belmopan\",\"CapitalLatitude\":\"17.25\",\"CapitalLongitude\":\"-88.766667\",\"CountryCode\":\"BZ\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Benin\",\"CapitalName\":\"Porto-Novo\",\"CapitalLatitude\":\"6.483333333333333\",\"CapitalLongitude\":\"2.616667\",\"CountryCode\":\"BJ\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Bermuda\",\"CapitalName\":\"Hamilton\",\"CapitalLatitude\":\"32.28333333333333\",\"CapitalLongitude\":\"-64.783333\",\"CountryCode\":\"BM\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Bhutan\",\"CapitalName\":\"Thimphu\",\"CapitalLatitude\":\"27.466666666666665\",\"CapitalLongitude\":\"89.633333\",\"CountryCode\":\"BT\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Bolivia\",\"CapitalName\":\"La Paz\",\"CapitalLatitude\":\"-16.5\",\"CapitalLongitude\":\"-68.150000\",\"CountryCode\":\"BO\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Bosnia and Herzegovina\",\"CapitalName\":\"Sarajevo\",\"CapitalLatitude\":\"43.86666666666667\",\"CapitalLongitude\":\"18.416667\",\"CountryCode\":\"BA\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Botswana\",\"CapitalName\":\"Gaborone\",\"CapitalLatitude\":\"-24.633333333333333\",\"CapitalLongitude\":\"25.900000\",\"CountryCode\":\"BW\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Brazil\",\"CapitalName\":\"Brasilia\",\"CapitalLatitude\":\"-15.783333333333333\",\"CapitalLongitude\":\"-47.916667\",\"CountryCode\":\"BR\",\"ContinentName\":\"South America\"},{\"CountryName\":\"British Virgin Islands\",\"CapitalName\":\"Road Town\",\"CapitalLatitude\":\"18.416666666666668\",\"CapitalLongitude\":\"-64.616667\",\"CountryCode\":\"VG\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Brunei Darussalam\",\"CapitalName\":\"Bandar Seri Begawan\",\"CapitalLatitude\":\"4.883333333333333\",\"CapitalLongitude\":\"114.933333\",\"CountryCode\":\"BN\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Bulgaria\",\"CapitalName\":\"Sofia\",\"CapitalLatitude\":\"42.68333333333333\",\"CapitalLongitude\":\"23.316667\",\"CountryCode\":\"BG\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Burkina Faso\",\"CapitalName\":\"Ouagadougou\",\"CapitalLatitude\":\"12.366666666666667\",\"CapitalLongitude\":\"-1.516667\",\"CountryCode\":\"BF\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Myanmar\",\"CapitalName\":\"Rangoon\",\"CapitalLatitude\":\"16.8\",\"CapitalLongitude\":\"96.150000\",\"CountryCode\":\"MM\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Burundi\",\"CapitalName\":\"Bujumbura\",\"CapitalLatitude\":\"-3.3666666666666667\",\"CapitalLongitude\":\"29.350000\",\"CountryCode\":\"BI\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Cambodia\",\"CapitalName\":\"Phnom Penh\",\"CapitalLatitude\":\"11.55\",\"CapitalLongitude\":\"104.916667\",\"CountryCode\":\"KH\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Cameroon\",\"CapitalName\":\"Yaounde\",\"CapitalLatitude\":\"3.8666666666666667\",\"CapitalLongitude\":\"11.516667\",\"CountryCode\":\"CM\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Canada\",\"CapitalName\":\"Ottawa\",\"CapitalLatitude\":\"45.416666666666664\",\"CapitalLongitude\":\"-75.700000\",\"CountryCode\":\"CA\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Cape Verde\",\"CapitalName\":\"Praia\",\"CapitalLatitude\":\"14.916666666666666\",\"CapitalLongitude\":\"-23.516667\",\"CountryCode\":\"CV\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Cayman Islands\",\"CapitalName\":\"George Town\",\"CapitalLatitude\":\"19.3\",\"CapitalLongitude\":\"-81.383333\",\"CountryCode\":\"KY\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Central African Republic\",\"CapitalName\":\"Bangui\",\"CapitalLatitude\":\"4.366666666666666\",\"CapitalLongitude\":\"18.583333\",\"CountryCode\":\"CF\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Chad\",\"CapitalName\":\"N'Djamena\",\"CapitalLatitude\":\"12.1\",\"CapitalLongitude\":\"15.033333\",\"CountryCode\":\"TD\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Chile\",\"CapitalName\":\"Santiago\",\"CapitalLatitude\":\"-33.45\",\"CapitalLongitude\":\"-70.666667\",\"CountryCode\":\"CL\",\"ContinentName\":\"South America\"},{\"CountryName\":\"China\",\"CapitalName\":\"Beijing\",\"CapitalLatitude\":\"39.916666666666664\",\"CapitalLongitude\":\"116.383333\",\"CountryCode\":\"CN\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Christmas Island\",\"CapitalName\":\"The Settlement\",\"CapitalLatitude\":\"-10.416666666666666\",\"CapitalLongitude\":\"105.716667\",\"CountryCode\":\"CX\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Cocos Islands\",\"CapitalName\":\"West Island\",\"CapitalLatitude\":\"-12.166666666666666\",\"CapitalLongitude\":\"96.833333\",\"CountryCode\":\"CC\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Colombia\",\"CapitalName\":\"Bogota\",\"CapitalLatitude\":\"4.6\",\"CapitalLongitude\":\"-74.083333\",\"CountryCode\":\"CO\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Comoros\",\"CapitalName\":\"Moroni\",\"CapitalLatitude\":\"-11.7\",\"CapitalLongitude\":\"43.233333\",\"CountryCode\":\"KM\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Democratic Republic of the Congo\",\"CapitalName\":\"Kinshasa\",\"CapitalLatitude\":\"-4.316666666666666\",\"CapitalLongitude\":\"15.300000\",\"CountryCode\":\"CD\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Republic of Congo\",\"CapitalName\":\"Brazzaville\",\"CapitalLatitude\":\"-4.25\",\"CapitalLongitude\":\"15.283333\",\"CountryCode\":\"CG\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Cook Islands\",\"CapitalName\":\"Avarua\",\"CapitalLatitude\":\"-21.2\",\"CapitalLongitude\":\"-159.766667\",\"CountryCode\":\"CK\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Costa Rica\",\"CapitalName\":\"San Jose\",\"CapitalLatitude\":\"9.933333333333334\",\"CapitalLongitude\":\"-84.083333\",\"CountryCode\":\"CR\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Cote d'Ivoire\",\"CapitalName\":\"Yamoussoukro\",\"CapitalLatitude\":\"6.816666666666666\",\"CapitalLongitude\":\"-5.266667\",\"CountryCode\":\"CI\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Croatia\",\"CapitalName\":\"Zagreb\",\"CapitalLatitude\":\"45.8\",\"CapitalLongitude\":\"16.000000\",\"CountryCode\":\"HR\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Cuba\",\"CapitalName\":\"Havana\",\"CapitalLatitude\":\"23.116666666666667\",\"CapitalLongitude\":\"-82.350000\",\"CountryCode\":\"CU\",\"ContinentName\":\"North America\"},{\"CountryName\":\"CuraÃ§ao\",\"CapitalName\":\"Willemstad\",\"CapitalLatitude\":\"12.1\",\"CapitalLongitude\":\"-68.916667\",\"CountryCode\":\"CW\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Cyprus\",\"CapitalName\":\"Nicosia\",\"CapitalLatitude\":\"35.166666666666664\",\"CapitalLongitude\":\"33.366667\",\"CountryCode\":\"CY\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Czech Republic\",\"CapitalName\":\"Prague\",\"CapitalLatitude\":\"50.083333333333336\",\"CapitalLongitude\":\"14.466667\",\"CountryCode\":\"CZ\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Denmark\",\"CapitalName\":\"Copenhagen\",\"CapitalLatitude\":\"55.666666666666664\",\"CapitalLongitude\":\"12.583333\",\"CountryCode\":\"DK\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Djibouti\",\"CapitalName\":\"Djibouti\",\"CapitalLatitude\":\"11.583333333333334\",\"CapitalLongitude\":\"43.150000\",\"CountryCode\":\"DJ\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Dominica\",\"CapitalName\":\"Roseau\",\"CapitalLatitude\":\"15.3\",\"CapitalLongitude\":\"-61.400000\",\"CountryCode\":\"DM\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Dominican Republic\",\"CapitalName\":\"Santo Domingo\",\"CapitalLatitude\":\"18.466666666666665\",\"CapitalLongitude\":\"-69.900000\",\"CountryCode\":\"DO\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Ecuador\",\"CapitalName\":\"Quito\",\"CapitalLatitude\":\"-0.21666666666666667\",\"CapitalLongitude\":\"-78.500000\",\"CountryCode\":\"EC\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Egypt\",\"CapitalName\":\"Cairo\",\"CapitalLatitude\":\"30.05\",\"CapitalLongitude\":\"31.250000\",\"CountryCode\":\"EG\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"El Salvador\",\"CapitalName\":\"San Salvador\",\"CapitalLatitude\":\"13.7\",\"CapitalLongitude\":\"-89.200000\",\"CountryCode\":\"SV\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Equatorial Guinea\",\"CapitalName\":\"Malabo\",\"CapitalLatitude\":\"3.75\",\"CapitalLongitude\":\"8.783333\",\"CountryCode\":\"GQ\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Eritrea\",\"CapitalName\":\"Asmara\",\"CapitalLatitude\":\"15.333333333333334\",\"CapitalLongitude\":\"38.933333\",\"CountryCode\":\"ER\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Estonia\",\"CapitalName\":\"Tallinn\",\"CapitalLatitude\":\"59.43333333333333\",\"CapitalLongitude\":\"24.716667\",\"CountryCode\":\"EE\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Ethiopia\",\"CapitalName\":\"Addis Ababa\",\"CapitalLatitude\":\"9.033333333333333\",\"CapitalLongitude\":\"38.700000\",\"CountryCode\":\"ET\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Falkland Islands\",\"CapitalName\":\"Stanley\",\"CapitalLatitude\":\"-51.7\",\"CapitalLongitude\":\"-57.850000\",\"CountryCode\":\"FK\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Faroe Islands\",\"CapitalName\":\"Torshavn\",\"CapitalLatitude\":\"62\",\"CapitalLongitude\":\"-6.766667\",\"CountryCode\":\"FO\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Fiji\",\"CapitalName\":\"Suva\",\"CapitalLatitude\":\"-18.133333333333333\",\"CapitalLongitude\":\"178.416667\",\"CountryCode\":\"FJ\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Finland\",\"CapitalName\":\"Helsinki\",\"CapitalLatitude\":\"60.166666666666664\",\"CapitalLongitude\":\"24.933333\",\"CountryCode\":\"FI\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"France\",\"CapitalName\":\"Paris\",\"CapitalLatitude\":\"48.86666666666667\",\"CapitalLongitude\":\"2.333333\",\"CountryCode\":\"FR\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"French Polynesia\",\"CapitalName\":\"Papeete\",\"CapitalLatitude\":\"-17.533333333333335\",\"CapitalLongitude\":\"-149.566667\",\"CountryCode\":\"PF\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Gabon\",\"CapitalName\":\"Libreville\",\"CapitalLatitude\":\"0.38333333333333336\",\"CapitalLongitude\":\"9.450000\",\"CountryCode\":\"GA\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"The Gambia\",\"CapitalName\":\"Banjul\",\"CapitalLatitude\":\"13.45\",\"CapitalLongitude\":\"-16.566667\",\"CountryCode\":\"GM\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Georgia\",\"CapitalName\":\"Tbilisi\",\"CapitalLatitude\":\"41.68333333333333\",\"CapitalLongitude\":\"44.833333\",\"CountryCode\":\"GE\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Germany\",\"CapitalName\":\"Berlin\",\"CapitalLatitude\":\"52.516666666666666\",\"CapitalLongitude\":\"13.400000\",\"CountryCode\":\"DE\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Ghana\",\"CapitalName\":\"Accra\",\"CapitalLatitude\":\"5.55\",\"CapitalLongitude\":\"-0.216667\",\"CountryCode\":\"GH\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Gibraltar\",\"CapitalName\":\"Gibraltar\",\"CapitalLatitude\":\"36.13333333333333\",\"CapitalLongitude\":\"-5.350000\",\"CountryCode\":\"GI\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Greece\",\"CapitalName\":\"Athens\",\"CapitalLatitude\":\"37.983333333333334\",\"CapitalLongitude\":\"23.733333\",\"CountryCode\":\"GR\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Greenland\",\"CapitalName\":\"Nuuk\",\"CapitalLatitude\":\"64.18333333333334\",\"CapitalLongitude\":\"-51.750000\",\"CountryCode\":\"GL\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Grenada\",\"CapitalName\":\"Saint George's\",\"CapitalLatitude\":\"12.05\",\"CapitalLongitude\":\"-61.750000\",\"CountryCode\":\"GD\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Guam\",\"CapitalName\":\"Hagatna\",\"CapitalLatitude\":\"13.466666666666667\",\"CapitalLongitude\":\"144.733333\",\"CountryCode\":\"GU\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Guatemala\",\"CapitalName\":\"Guatemala City\",\"CapitalLatitude\":\"14.616666666666667\",\"CapitalLongitude\":\"-90.516667\",\"CountryCode\":\"GT\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Guernsey\",\"CapitalName\":\"Saint Peter Port\",\"CapitalLatitude\":\"49.45\",\"CapitalLongitude\":\"-2.533333\",\"CountryCode\":\"GG\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Guinea\",\"CapitalName\":\"Conakry\",\"CapitalLatitude\":\"9.5\",\"CapitalLongitude\":\"-13.700000\",\"CountryCode\":\"GN\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Guinea-Bissau\",\"CapitalName\":\"Bissau\",\"CapitalLatitude\":\"11.85\",\"CapitalLongitude\":\"-15.583333\",\"CountryCode\":\"GW\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Guyana\",\"CapitalName\":\"Georgetown\",\"CapitalLatitude\":\"6.8\",\"CapitalLongitude\":\"-58.150000\",\"CountryCode\":\"GY\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Haiti\",\"CapitalName\":\"Port-au-Prince\",\"CapitalLatitude\":\"18.533333333333335\",\"CapitalLongitude\":\"-72.333333\",\"CountryCode\":\"HT\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Vatican City\",\"CapitalName\":\"Vatican City\",\"CapitalLatitude\":\"41.9\",\"CapitalLongitude\":\"12.450000\",\"CountryCode\":\"VA\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Honduras\",\"CapitalName\":\"Tegucigalpa\",\"CapitalLatitude\":\"14.1\",\"CapitalLongitude\":\"-87.216667\",\"CountryCode\":\"HN\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Hungary\",\"CapitalName\":\"Budapest\",\"CapitalLatitude\":\"47.5\",\"CapitalLongitude\":\"19.083333\",\"CountryCode\":\"HU\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Iceland\",\"CapitalName\":\"Reykjavik\",\"CapitalLatitude\":\"64.15\",\"CapitalLongitude\":\"-21.950000\",\"CountryCode\":\"IS\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"India\",\"CapitalName\":\"New Delhi\",\"CapitalLatitude\":\"28.6\",\"CapitalLongitude\":\"77.200000\",\"CountryCode\":\"IN\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Indonesia\",\"CapitalName\":\"Jakarta\",\"CapitalLatitude\":\"-6.166666666666667\",\"CapitalLongitude\":\"106.816667\",\"CountryCode\":\"ID\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Iran\",\"CapitalName\":\"Tehran\",\"CapitalLatitude\":\"35.7\",\"CapitalLongitude\":\"51.416667\",\"CountryCode\":\"IR\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Iraq\",\"CapitalName\":\"Baghdad\",\"CapitalLatitude\":\"33.333333333333336\",\"CapitalLongitude\":\"44.400000\",\"CountryCode\":\"IQ\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Ireland\",\"CapitalName\":\"Dublin\",\"CapitalLatitude\":\"53.31666666666667\",\"CapitalLongitude\":\"-6.233333\",\"CountryCode\":\"IE\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Isle of Man\",\"CapitalName\":\"Douglas\",\"CapitalLatitude\":\"54.15\",\"CapitalLongitude\":\"-4.483333\",\"CountryCode\":\"IM\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Israel\",\"CapitalName\":\"Jerusalem\",\"CapitalLatitude\":\"31.76787255\",\"CapitalLongitude\":\"35.0220108\",\"CountryCode\":\"IL\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Italy\",\"CapitalName\":\"Rome\",\"CapitalLatitude\":\"41.9\",\"CapitalLongitude\":\"12.483333\",\"CountryCode\":\"IT\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Jamaica\",\"CapitalName\":\"Kingston\",\"CapitalLatitude\":\"18\",\"CapitalLongitude\":\"-76.800000\",\"CountryCode\":\"JM\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Japan\",\"CapitalName\":\"Tokyo\",\"CapitalLatitude\":\"35.68333333333333\",\"CapitalLongitude\":\"139.750000\",\"CountryCode\":\"JP\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Jersey\",\"CapitalName\":\"Saint Helier\",\"CapitalLatitude\":\"49.18333333333333\",\"CapitalLongitude\":\"-2.100000\",\"CountryCode\":\"JE\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Jordan\",\"CapitalName\":\"Amman\",\"CapitalLatitude\":\"31.95\",\"CapitalLongitude\":\"35.933333\",\"CountryCode\":\"JO\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Kazakhstan\",\"CapitalName\":\"Astana\",\"CapitalLatitude\":\"51.166666666666664\",\"CapitalLongitude\":\"71.416667\",\"CountryCode\":\"KZ\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Kenya\",\"CapitalName\":\"Nairobi\",\"CapitalLatitude\":\"-1.2833333333333332\",\"CapitalLongitude\":\"36.816667\",\"CountryCode\":\"KE\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Kiribati\",\"CapitalName\":\"Tarawa\",\"CapitalLatitude\":\"-0.8833333333333333\",\"CapitalLongitude\":\"169.533333\",\"CountryCode\":\"KI\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"North Korea\",\"CapitalName\":\"Pyongyang\",\"CapitalLatitude\":\"39.016666666666666\",\"CapitalLongitude\":\"125.750000\",\"CountryCode\":\"KP\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"South Korea\",\"CapitalName\":\"Seoul\",\"CapitalLatitude\":\"37.55\",\"CapitalLongitude\":\"126.983333\",\"CountryCode\":\"KR\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Kosovo\",\"CapitalName\":\"Pristina\",\"CapitalLatitude\":\"42.666666666666664\",\"CapitalLongitude\":\"21.166667\",\"CountryCode\":\"KO\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Kuwait\",\"CapitalName\":\"Kuwait City\",\"CapitalLatitude\":\"29.366666666666667\",\"CapitalLongitude\":\"47.966667\",\"CountryCode\":\"KW\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Kyrgyzstan\",\"CapitalName\":\"Bishkek\",\"CapitalLatitude\":\"42.86666666666667\",\"CapitalLongitude\":\"74.600000\",\"CountryCode\":\"KG\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Laos\",\"CapitalName\":\"Vientiane\",\"CapitalLatitude\":\"17.966666666666665\",\"CapitalLongitude\":\"102.600000\",\"CountryCode\":\"LA\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Latvia\",\"CapitalName\":\"Riga\",\"CapitalLatitude\":\"56.95\",\"CapitalLongitude\":\"24.100000\",\"CountryCode\":\"LV\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Lebanon\",\"CapitalName\":\"Beirut\",\"CapitalLatitude\":\"33.86666666666667\",\"CapitalLongitude\":\"35.500000\",\"CountryCode\":\"LB\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Lesotho\",\"CapitalName\":\"Maseru\",\"CapitalLatitude\":\"-29.316666666666666\",\"CapitalLongitude\":\"27.483333\",\"CountryCode\":\"LS\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Liberia\",\"CapitalName\":\"Monrovia\",\"CapitalLatitude\":\"6.3\",\"CapitalLongitude\":\"-10.800000\",\"CountryCode\":\"LR\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Libya\",\"CapitalName\":\"Tripoli\",\"CapitalLatitude\":\"32.88333333333333\",\"CapitalLongitude\":\"13.166667\",\"CountryCode\":\"LY\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Liechtenstein\",\"CapitalName\":\"Vaduz\",\"CapitalLatitude\":\"47.13333333333333\",\"CapitalLongitude\":\"9.516667\",\"CountryCode\":\"LI\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Lithuania\",\"CapitalName\":\"Vilnius\",\"CapitalLatitude\":\"54.68333333333333\",\"CapitalLongitude\":\"25.316667\",\"CountryCode\":\"LT\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Luxembourg\",\"CapitalName\":\"Luxembourg\",\"CapitalLatitude\":\"49.6\",\"CapitalLongitude\":\"6.116667\",\"CountryCode\":\"LU\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Macedonia\",\"CapitalName\":\"Skopje\",\"CapitalLatitude\":\"42\",\"CapitalLongitude\":\"21.433333\",\"CountryCode\":\"MK\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Madagascar\",\"CapitalName\":\"Antananarivo\",\"CapitalLatitude\":\"-18.916666666666668\",\"CapitalLongitude\":\"47.516667\",\"CountryCode\":\"MG\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Malawi\",\"CapitalName\":\"Lilongwe\",\"CapitalLatitude\":\"-13.966666666666667\",\"CapitalLongitude\":\"33.783333\",\"CountryCode\":\"MW\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Malaysia\",\"CapitalName\":\"Kuala Lumpur\",\"CapitalLatitude\":\"3.1666666666666665\",\"CapitalLongitude\":\"101.700000\",\"CountryCode\":\"MY\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Maldives\",\"CapitalName\":\"Male\",\"CapitalLatitude\":\"4.166666666666667\",\"CapitalLongitude\":\"73.500000\",\"CountryCode\":\"MV\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Mali\",\"CapitalName\":\"Bamako\",\"CapitalLatitude\":\"12.65\",\"CapitalLongitude\":\"-8.000000\",\"CountryCode\":\"ML\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Malta\",\"CapitalName\":\"Valletta\",\"CapitalLatitude\":\"35.88333333333333\",\"CapitalLongitude\":\"14.500000\",\"CountryCode\":\"MT\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Marshall Islands\",\"CapitalName\":\"Majuro\",\"CapitalLatitude\":\"7.1\",\"CapitalLongitude\":\"171.383333\",\"CountryCode\":\"MH\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Mauritania\",\"CapitalName\":\"Nouakchott\",\"CapitalLatitude\":\"18.066666666666666\",\"CapitalLongitude\":\"-15.966667\",\"CountryCode\":\"MR\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Mauritius\",\"CapitalName\":\"Port Louis\",\"CapitalLatitude\":\"-20.15\",\"CapitalLongitude\":\"57.483333\",\"CountryCode\":\"MU\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Mexico\",\"CapitalName\":\"Mexico City\",\"CapitalLatitude\":\"19.433333333333334\",\"CapitalLongitude\":\"-99.133333\",\"CountryCode\":\"MX\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Federated States of Micronesia\",\"CapitalName\":\"Palikir\",\"CapitalLatitude\":\"6.916666666666667\",\"CapitalLongitude\":\"158.150000\",\"CountryCode\":\"FM\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Moldova\",\"CapitalName\":\"Chisinau\",\"CapitalLatitude\":\"47\",\"CapitalLongitude\":\"28.850000\",\"CountryCode\":\"MD\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Monaco\",\"CapitalName\":\"Monaco\",\"CapitalLatitude\":\"43.733333333333334\",\"CapitalLongitude\":\"7.416667\",\"CountryCode\":\"MC\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Mongolia\",\"CapitalName\":\"Ulaanbaatar\",\"CapitalLatitude\":\"47.916666666666664\",\"CapitalLongitude\":\"106.916667\",\"CountryCode\":\"MN\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Montenegro\",\"CapitalName\":\"Podgorica\",\"CapitalLatitude\":\"42.43333333333333\",\"CapitalLongitude\":\"19.266667\",\"CountryCode\":\"ME\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Montserrat\",\"CapitalName\":\"Plymouth\",\"CapitalLatitude\":\"16.7\",\"CapitalLongitude\":\"-62.216667\",\"CountryCode\":\"MS\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Morocco\",\"CapitalName\":\"Rabat\",\"CapitalLatitude\":\"34.016666666666666\",\"CapitalLongitude\":\"-6.816667\",\"CountryCode\":\"MA\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Mozambique\",\"CapitalName\":\"Maputo\",\"CapitalLatitude\":\"-25.95\",\"CapitalLongitude\":\"32.583333\",\"CountryCode\":\"MZ\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Namibia\",\"CapitalName\":\"Windhoek\",\"CapitalLatitude\":\"-22.566666666666666\",\"CapitalLongitude\":\"17.083333\",\"CountryCode\":\"NA\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Nepal\",\"CapitalName\":\"Kathmandu\",\"CapitalLatitude\":\"27.716666666666665\",\"CapitalLongitude\":\"85.316667\",\"CountryCode\":\"NP\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Netherlands\",\"CapitalName\":\"Amsterdam\",\"CapitalLatitude\":\"52.35\",\"CapitalLongitude\":\"4.916667\",\"CountryCode\":\"NL\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"New Caledonia\",\"CapitalName\":\"Noumea\",\"CapitalLatitude\":\"-22.266666666666666\",\"CapitalLongitude\":\"166.450000\",\"CountryCode\":\"NC\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"New Zealand\",\"CapitalName\":\"Wellington\",\"CapitalLatitude\":\"-41.3\",\"CapitalLongitude\":\"174.783333\",\"CountryCode\":\"NZ\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Nicaragua\",\"CapitalName\":\"Managua\",\"CapitalLatitude\":\"12.133333333333333\",\"CapitalLongitude\":\"-86.250000\",\"CountryCode\":\"NI\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Niger\",\"CapitalName\":\"Niamey\",\"CapitalLatitude\":\"13.516666666666667\",\"CapitalLongitude\":\"2.116667\",\"CountryCode\":\"NE\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Nigeria\",\"CapitalName\":\"Abuja\",\"CapitalLatitude\":\"9.083333333333334\",\"CapitalLongitude\":\"7.533333\",\"CountryCode\":\"NG\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Niue\",\"CapitalName\":\"Alofi\",\"CapitalLatitude\":\"-19.016666666666666\",\"CapitalLongitude\":\"-169.916667\",\"CountryCode\":\"NU\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Norfolk Island\",\"CapitalName\":\"Kingston\",\"CapitalLatitude\":\"-29.05\",\"CapitalLongitude\":\"167.966667\",\"CountryCode\":\"NF\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Northern Mariana Islands\",\"CapitalName\":\"Saipan\",\"CapitalLatitude\":\"15.2\",\"CapitalLongitude\":\"145.750000\",\"CountryCode\":\"MP\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Norway\",\"CapitalName\":\"Oslo\",\"CapitalLatitude\":\"59.916666666666664\",\"CapitalLongitude\":\"10.750000\",\"CountryCode\":\"NO\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Oman\",\"CapitalName\":\"Muscat\",\"CapitalLatitude\":\"23.616666666666667\",\"CapitalLongitude\":\"58.583333\",\"CountryCode\":\"OM\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Pakistan\",\"CapitalName\":\"Islamabad\",\"CapitalLatitude\":\"33.68333333333333\",\"CapitalLongitude\":\"73.050000\",\"CountryCode\":\"PK\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Palau\",\"CapitalName\":\"Melekeok\",\"CapitalLatitude\":\"7.483333333333333\",\"CapitalLongitude\":\"134.633333\",\"CountryCode\":\"PW\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Panama\",\"CapitalName\":\"Panama City\",\"CapitalLatitude\":\"8.966666666666667\",\"CapitalLongitude\":\"-79.533333\",\"CountryCode\":\"PA\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Papua New Guinea\",\"CapitalName\":\"Port Moresby\",\"CapitalLatitude\":\"-9.45\",\"CapitalLongitude\":\"147.183333\",\"CountryCode\":\"PG\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Paraguay\",\"CapitalName\":\"Asuncion\",\"CapitalLatitude\":\"-25.266666666666666\",\"CapitalLongitude\":\"-57.666667\",\"CountryCode\":\"PY\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Peru\",\"CapitalName\":\"Lima\",\"CapitalLatitude\":\"-12.05\",\"CapitalLongitude\":\"-77.050000\",\"CountryCode\":\"PE\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Philippines\",\"CapitalName\":\"Manila\",\"CapitalLatitude\":\"14.6\",\"CapitalLongitude\":\"120.966667\",\"CountryCode\":\"PH\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Pitcairn Islands\",\"CapitalName\":\"Adamstown\",\"CapitalLatitude\":\"-25.066666666666666\",\"CapitalLongitude\":\"-130.083333\",\"CountryCode\":\"PN\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Poland\",\"CapitalName\":\"Warsaw\",\"CapitalLatitude\":\"52.25\",\"CapitalLongitude\":\"21.000000\",\"CountryCode\":\"PL\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Portugal\",\"CapitalName\":\"Lisbon\",\"CapitalLatitude\":\"38.71666666666667\",\"CapitalLongitude\":\"-9.133333\",\"CountryCode\":\"PT\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Puerto Rico\",\"CapitalName\":\"San Juan\",\"CapitalLatitude\":\"18.466666666666665\",\"CapitalLongitude\":\"-66.116667\",\"CountryCode\":\"PR\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Qatar\",\"CapitalName\":\"Doha\",\"CapitalLatitude\":\"25.283333333333335\",\"CapitalLongitude\":\"51.533333\",\"CountryCode\":\"QA\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Romania\",\"CapitalName\":\"Bucharest\",\"CapitalLatitude\":\"44.43333333333333\",\"CapitalLongitude\":\"26.100000\",\"CountryCode\":\"RO\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Russia\",\"CapitalName\":\"Moscow\",\"CapitalLatitude\":\"55.75\",\"CapitalLongitude\":\"37.600000\",\"CountryCode\":\"RU\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Rwanda\",\"CapitalName\":\"Kigali\",\"CapitalLatitude\":\"-1.95\",\"CapitalLongitude\":\"30.050000\",\"CountryCode\":\"RW\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Saint Barthelemy\",\"CapitalName\":\"Gustavia\",\"CapitalLatitude\":\"17.883333333333333\",\"CapitalLongitude\":\"-62.850000\",\"CountryCode\":\"BL\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Saint Helena\",\"CapitalName\":\"Jamestown\",\"CapitalLatitude\":\"-15.933333333333334\",\"CapitalLongitude\":\"-5.716667\",\"CountryCode\":\"SH\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Saint Kitts and Nevis\",\"CapitalName\":\"Basseterre\",\"CapitalLatitude\":\"17.3\",\"CapitalLongitude\":\"-62.716667\",\"CountryCode\":\"KN\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Saint Lucia\",\"CapitalName\":\"Castries\",\"CapitalLatitude\":\"14\",\"CapitalLongitude\":\"-61.000000\",\"CountryCode\":\"LC\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Saint Pierre and Miquelon\",\"CapitalName\":\"Saint-Pierre\",\"CapitalLatitude\":\"46.766666666666666\",\"CapitalLongitude\":\"-56.183333\",\"CountryCode\":\"PM\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Saint Vincent and the Grenadines\",\"CapitalName\":\"Kingstown\",\"CapitalLatitude\":\"13.133333333333333\",\"CapitalLongitude\":\"-61.216667\",\"CountryCode\":\"VC\",\"ContinentName\":\"Central America\"},{\"CountryName\":\"Samoa\",\"CapitalName\":\"Apia\",\"CapitalLatitude\":\"-13.816666666666666\",\"CapitalLongitude\":\"-171.766667\",\"CountryCode\":\"WS\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"San Marino\",\"CapitalName\":\"San Marino\",\"CapitalLatitude\":\"43.93333333333333\",\"CapitalLongitude\":\"12.416667\",\"CountryCode\":\"SM\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Sao Tome and Principe\",\"CapitalName\":\"Sao Tome\",\"CapitalLatitude\":\"0.3333333333333333\",\"CapitalLongitude\":\"6.733333\",\"CountryCode\":\"ST\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Saudi Arabia\",\"CapitalName\":\"Riyadh\",\"CapitalLatitude\":\"24.65\",\"CapitalLongitude\":\"46.700000\",\"CountryCode\":\"SA\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Senegal\",\"CapitalName\":\"Dakar\",\"CapitalLatitude\":\"14.733333333333333\",\"CapitalLongitude\":\"-17.633333\",\"CountryCode\":\"SN\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Serbia\",\"CapitalName\":\"Belgrade\",\"CapitalLatitude\":\"44.833333333333336\",\"CapitalLongitude\":\"20.500000\",\"CountryCode\":\"RS\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Seychelles\",\"CapitalName\":\"Victoria\",\"CapitalLatitude\":\"-4.616666666666667\",\"CapitalLongitude\":\"55.450000\",\"CountryCode\":\"SC\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Sierra Leone\",\"CapitalName\":\"Freetown\",\"CapitalLatitude\":\"8.483333333333333\",\"CapitalLongitude\":\"-13.233333\",\"CountryCode\":\"SL\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Singapore\",\"CapitalName\":\"Singapore\",\"CapitalLatitude\":\"1.2833333333333332\",\"CapitalLongitude\":\"103.850000\",\"CountryCode\":\"SG\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Sint Maarten\",\"CapitalName\":\"Philipsburg\",\"CapitalLatitude\":\"18.016666666666666\",\"CapitalLongitude\":\"-63.033333\",\"CountryCode\":\"SX\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Slovakia\",\"CapitalName\":\"Bratislava\",\"CapitalLatitude\":\"48.15\",\"CapitalLongitude\":\"17.116667\",\"CountryCode\":\"SK\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Slovenia\",\"CapitalName\":\"Ljubljana\",\"CapitalLatitude\":\"46.05\",\"CapitalLongitude\":\"14.516667\",\"CountryCode\":\"SI\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Solomon Islands\",\"CapitalName\":\"Honiara\",\"CapitalLatitude\":\"-9.433333333333334\",\"CapitalLongitude\":\"159.950000\",\"CountryCode\":\"SB\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Somalia\",\"CapitalName\":\"Mogadishu\",\"CapitalLatitude\":\"2.066666666666667\",\"CapitalLongitude\":\"45.333333\",\"CountryCode\":\"SO\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"South Africa\",\"CapitalName\":\"Pretoria\",\"CapitalLatitude\":\"-25.7\",\"CapitalLongitude\":\"28.216667\",\"CountryCode\":\"ZA\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"South Sudan\",\"CapitalName\":\"Juba\",\"CapitalLatitude\":\"4.85\",\"CapitalLongitude\":\"31.616667\",\"CountryCode\":\"SS\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Spain\",\"CapitalName\":\"Madrid\",\"CapitalLatitude\":\"40.4\",\"CapitalLongitude\":\"-3.683333\",\"CountryCode\":\"ES\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Sri Lanka\",\"CapitalName\":\"Colombo\",\"CapitalLatitude\":\"6.916666666666667\",\"CapitalLongitude\":\"79.833333\",\"CountryCode\":\"LK\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Sudan\",\"CapitalName\":\"Khartoum\",\"CapitalLatitude\":\"15.6\",\"CapitalLongitude\":\"32.533333\",\"CountryCode\":\"SD\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Suriname\",\"CapitalName\":\"Paramaribo\",\"CapitalLatitude\":\"5.833333333333333\",\"CapitalLongitude\":\"-55.166667\",\"CountryCode\":\"SR\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Svalbard\",\"CapitalName\":\"Longyearbyen\",\"CapitalLatitude\":\"78.21666666666667\",\"CapitalLongitude\":\"15.633333\",\"CountryCode\":\"SJ\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Swaziland\",\"CapitalName\":\"Mbabane\",\"CapitalLatitude\":\"-26.316666666666666\",\"CapitalLongitude\":\"31.133333\",\"CountryCode\":\"SZ\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Sweden\",\"CapitalName\":\"Stockholm\",\"CapitalLatitude\":\"59.333333333333336\",\"CapitalLongitude\":\"18.050000\",\"CountryCode\":\"SE\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Switzerland\",\"CapitalName\":\"Bern\",\"CapitalLatitude\":\"46.916666666666664\",\"CapitalLongitude\":\"7.466667\",\"CountryCode\":\"CH\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Syria\",\"CapitalName\":\"Damascus\",\"CapitalLatitude\":\"33.5\",\"CapitalLongitude\":\"36.300000\",\"CountryCode\":\"SY\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Taiwan\",\"CapitalName\":\"Taipei\",\"CapitalLatitude\":\"25.033333333333335\",\"CapitalLongitude\":\"121.516667\",\"CountryCode\":\"TW\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Tajikistan\",\"CapitalName\":\"Dushanbe\",\"CapitalLatitude\":\"38.55\",\"CapitalLongitude\":\"68.766667\",\"CountryCode\":\"TJ\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Tanzania\",\"CapitalName\":\"Dar es Salaam\",\"CapitalLatitude\":\"-6.8\",\"CapitalLongitude\":\"39.283333\",\"CountryCode\":\"TZ\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Thailand\",\"CapitalName\":\"Bangkok\",\"CapitalLatitude\":\"13.75\",\"CapitalLongitude\":\"100.516667\",\"CountryCode\":\"TH\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Timor-Leste\",\"CapitalName\":\"Dili\",\"CapitalLatitude\":\"-8.583333333333334\",\"CapitalLongitude\":\"125.600000\",\"CountryCode\":\"TL\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Togo\",\"CapitalName\":\"Lome\",\"CapitalLatitude\":\"6.116666666666666\",\"CapitalLongitude\":\"1.216667\",\"CountryCode\":\"TG\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Tonga\",\"CapitalName\":\"Nuku'alofa\",\"CapitalLatitude\":\"-21.133333333333333\",\"CapitalLongitude\":\"-175.200000\",\"CountryCode\":\"TO\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Trinidad and Tobago\",\"CapitalName\":\"Port of Spain\",\"CapitalLatitude\":\"10.65\",\"CapitalLongitude\":\"-61.516667\",\"CountryCode\":\"TT\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Tunisia\",\"CapitalName\":\"Tunis\",\"CapitalLatitude\":\"36.8\",\"CapitalLongitude\":\"10.183333\",\"CountryCode\":\"TN\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Turkey\",\"CapitalName\":\"Ankara\",\"CapitalLatitude\":\"39.93333333333333\",\"CapitalLongitude\":\"32.866667\",\"CountryCode\":\"TR\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Turkmenistan\",\"CapitalName\":\"Ashgabat\",\"CapitalLatitude\":\"37.95\",\"CapitalLongitude\":\"58.383333\",\"CountryCode\":\"TM\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Turks and Caicos Islands\",\"CapitalName\":\"Grand Turk\",\"CapitalLatitude\":\"21.466666666666665\",\"CapitalLongitude\":\"-71.133333\",\"CountryCode\":\"TC\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Tuvalu\",\"CapitalName\":\"Funafuti\",\"CapitalLatitude\":\"-8.516666666666667\",\"CapitalLongitude\":\"179.216667\",\"CountryCode\":\"TV\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Uganda\",\"CapitalName\":\"Kampala\",\"CapitalLatitude\":\"0.31666666666666665\",\"CapitalLongitude\":\"32.550000\",\"CountryCode\":\"UG\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Ukraine\",\"CapitalName\":\"Kyiv\",\"CapitalLatitude\":\"50.43333333333333\",\"CapitalLongitude\":\"30.516667\",\"CountryCode\":\"UA\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"United Arab Emirates\",\"CapitalName\":\"Abu Dhabi\",\"CapitalLatitude\":\"24.466666666666665\",\"CapitalLongitude\":\"54.366667\",\"CountryCode\":\"AE\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"United Kingdom\",\"CapitalName\":\"London\",\"CapitalLatitude\":\"51.5\",\"CapitalLongitude\":\"-0.083333\",\"CountryCode\":\"GB\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"United States\",\"CapitalName\":\"Washington\",\"CapitalLatitude\":\"38.883333\",\"CapitalLongitude\":\"-77.009003\",\"CountryCode\":\"US\",\"ContinentName\":\"US\"},{\"CountryName\":\"Uruguay\",\"CapitalName\":\"Montevideo\",\"CapitalLatitude\":\"-34.85\",\"CapitalLongitude\":\"-56.166667\",\"CountryCode\":\"UY\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Uzbekistan\",\"CapitalName\":\"Tashkent\",\"CapitalLatitude\":\"41.31666666666667\",\"CapitalLongitude\":\"69.250000\",\"CountryCode\":\"UZ\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Vanuatu\",\"CapitalName\":\"Port-Vila\",\"CapitalLatitude\":\"-17.733333333333334\",\"CapitalLongitude\":\"168.316667\",\"CountryCode\":\"VU\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Venezuela\",\"CapitalName\":\"Caracas\",\"CapitalLatitude\":\"10.483333333333333\",\"CapitalLongitude\":\"-66.866667\",\"CountryCode\":\"VE\",\"ContinentName\":\"South America\"},{\"CountryName\":\"Viet Nam\",\"CapitalName\":\"Hanoi\",\"CapitalLatitude\":\"21.033333333333335\",\"CapitalLongitude\":\"105.850000\",\"CountryCode\":\"VN\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"US Virgin Islands\",\"CapitalName\":\"Charlotte Amalie\",\"CapitalLatitude\":\"18.35\",\"CapitalLongitude\":\"-64.933333\",\"CountryCode\":\"VI\",\"ContinentName\":\"North America\"},{\"CountryName\":\"Wallis and Futuna\",\"CapitalName\":\"Mata-Utu\",\"CapitalLatitude\":\"-13.95\",\"CapitalLongitude\":\"-171.933333\",\"CountryCode\":\"WF\",\"ContinentName\":\"Australia\"},{\"CountryName\":\"Yemen\",\"CapitalName\":\"Sanaa\",\"CapitalLatitude\":\"15.35\",\"CapitalLongitude\":\"44.200000\",\"CountryCode\":\"YE\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Zambia\",\"CapitalName\":\"Lusaka\",\"CapitalLatitude\":\"-15.416666666666666\",\"CapitalLongitude\":\"28.283333\",\"CountryCode\":\"ZM\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Zimbabwe\",\"CapitalName\":\"Harare\",\"CapitalLatitude\":\"-17.816666666666666\",\"CapitalLongitude\":\"31.033333\",\"CountryCode\":\"ZW\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"US Minor Outlying Islands\",\"CapitalName\":\"Washington\",\"CapitalLatitude\":\"-77.009003\",\"CapitalLongitude\":\"38.883333\",\"CountryCode\":\"-77.000000\",\"ContinentName\":\"UM\"},{\"CountryName\":\"Antarctica\",\"CapitalName\":\"N/A\",\"CapitalLatitude\":\"0\",\"CapitalLongitude\":\"0.000000\",\"CountryCode\":\"AQ\",\"ContinentName\":\"Antarctica\"},{\"CountryName\":\"Northern Cyprus\",\"CapitalName\":\"North Nicosia\",\"CapitalLatitude\":\"35.183333\",\"CapitalLongitude\":\"33.366667\",\"CountryCode\":\"NULL\",\"ContinentName\":\"Europe\"},{\"CountryName\":\"Hong Kong\",\"CapitalName\":\"N/A\",\"CapitalLatitude\":\"22.396428\",\"CapitalLongitude\":\"114.109497\",\"CountryCode\":\"HK\",\"ContinentName\":\"Asia\"},{\"CountryName\":\"Heard Island and McDonald Islands\",\"CapitalName\":\"N/A\",\"CapitalLatitude\":\"0\",\"CapitalLongitude\":\"0.000000\",\"CountryCode\":\"HM\",\"ContinentName\":\"Antarctica\"},{\"CountryName\":\"British Indian Ocean Territory\",\"CapitalName\":\"Diego Garcia\",\"CapitalLatitude\":\"-7.3\",\"CapitalLongitude\":\"72.400000\",\"CountryCode\":\"IO\",\"ContinentName\":\"Africa\"},{\"CountryName\":\"Macau\",\"CapitalName\":\"N/A\",\"CapitalLatitude\":\"0\",\"CapitalLongitude\":\"0.000000\",\"CountryCode\":\"MO\",\"ContinentName\":\"Asia\"}]"
  },
  {
    "path": "Android-code/app/src/main/assets/full_licenses.html",
    "content": "<!--\n  ~ Copyright (c) 2012-2016 Arne Schwabe\n  ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n  -->\n\n<h2 id=\"ics-openvpn\">OpenVPN for Android</h2>\n<p>\nThe name ics-openvpn and OpenVPN for Android refer to the same program.\nOpenVPN for Android is distributed under the GPL license version 2 (see Below)\nwith the following clarification/additional terms of what constitues \"deriviate work\": </p>\n\n<p>Using/including any part of ics-openvpn, especially using/including any part of the\nde.blinkt.openvpn class hierarchy, creates derivative work of ics-openvpn.\nAadditionally, the normal definitions of derivative work apply.</p>\n\n<p>  Special exception for linking ics-openvpn with OpenSSL:</p>\n\n<p>  In addition, as a special exception, Arne Schwabe gives\n  permission to link the code of this program with the OpenSSL\n  library (or with modified versions of OpenSSL that use the same\n  license as OpenSSL), and distribute linked combinations including\n  the two.  You must obey the GNU General Public License in all\n  respects for all of the code used other than OpenSSL.  If you modify\n  this file, you may extend this exception to your version of the\n  file, but you are not obligated to do so.  If you do not wish to\n  do so, delete this exception statement from your version.</p>\n\n<h2 id=\"lzo\">LZO license</h2>\n<p>  LZO is Copyright (C) Markus F.X.J. Oberhumer,\n  and is licensed under the GPL.</p>\n\n<p>  Special exception for linking OpenVPN with both OpenSSL and LZO:</p>\n\n<p>  Hereby I grant a special exception to the OpenVPN project \n  (http://openvpn.net/) to link the LZO library with \n  the OpenSSL library (http://www.openssl.org).\n \n  Markus F.X.J. Oberhumer\n</p>\n<h2> Google Breakpad</h2>\n <p>Copyright (c) 2006, Google Inc.<br />\n     All rights reserved.</p>\n\n    <p>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:</p>\n\n    <p>1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.</p>\n    <p>2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.</p>\n    <p>3. Neither the name of the &lt;ORGANIZATION&gt; nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.</p>\n\n    <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>\n\n<h2>Bouncy Castle</h2>\n<p>\nCopyright (c) 2000-2013 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)\n<p>\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software \nand associated documentation files (the \"Software\"), to deal in the Software without restriction, \nincluding without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n<p>\nThe above copyright notice and this permission notice shall be included in all copies or substantial\nportions of the Software.\n<p>\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\nINCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n\n\n    <h2 id=\"GPL2\">GPL Version 2, June 1991</h2>\n\n    <p>Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br />\n     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p>\n\n    <p>Everyone is permitted to copy and distribute verbatim copies<br />\n     of this license document, but changing it is not allowed.</p>\n\n    <p><strong>Preamble</strong></p>\n\n    <p>The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.</p>\n\n    <p>When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.</p>\n\n    <p>To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.</p>\n\n    <p>For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</p>\n\n    <p>We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.</p>\n\n    <p>Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.</p>\n\n    <p>Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.</p>\n\n    <p>The precise terms and conditions for copying, distribution and modification follow.</p>\n\n    <p><strong>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</strong></p>\n\n    <p><strong>0</strong>. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The \"Program\", below, refers to any such program or work, and a \"work based on the Program\" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term \"modification\".) Each licensee is addressed as \"you\".</p>\n\n    <p>Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.</p>\n\n    <p><strong>1</strong>. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.</p>\n\n    <p>You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.</p>\n\n    <p><strong>2</strong>. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:</p>\n\n    <blockquote>\n      <p>a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.</p>\n\n      <p>b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.</p>\n\n      <p>c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)</p>\n    </blockquote>\n\n    <p>These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.</p>\n\n    <p>Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.</p>\n\n    <p>In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.</p>\n\n    <p><strong>3</strong>. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:</p>\n\n    <blockquote>\n      <p>a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,</p>\n\n      <p>b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,</p>\n\n      <p>c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)</p>\n    </blockquote>\n\n    <p>The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.</p>\n\n    <p>If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.</p>\n\n    <p><strong>4</strong>. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.</p>\n\n    <p><strong>5</strong>. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.</p>\n\n    <p><strong>6</strong>. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.</p>\n\n    <p><strong>7</strong>. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.</p>\n\n    <p>If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.</p>\n\n    <p>It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.</p>\n\n    <p>This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.</p>\n\n    <p><strong>8</strong>. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.</p>\n\n    <p><strong>9</strong>. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</p>\n\n    <p>Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and \"any later version\", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.</p>\n\n    <p><strong>10</strong>. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.</p>\n\n    <p><strong>NO WARRANTY</strong></p>\n\n    <p><strong>11</strong>. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</p>\n\n    <p><strong>12</strong>. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>\n\n<p>END OF TERMS AND CONDITIONS</p>\n\n<h2 id=\"#openssl\">OpenSSL</h2>\n<p>  The OpenSSL toolkit stays under a dual license, i.e. both the conditions of\n  the OpenSSL License and the original SSLeay license apply to the toolkit.\n  See below for the actual license texts. Actually both licenses are BSD-style\n  Open Source licenses. In case of any license issues related to OpenSSL\n  please contact openssl-core@openssl.org.</p>\n<pre>\n/* ====================================================================\n * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer. \n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n</pre>\n\n<h3> Original SSLeay License</h3>\n<pre>\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n</pre>\n"
  },
  {
    "path": "Android-code/app/src/main/assets/world_map.geo.json",
    "content": "{\"type\":\"FeatureCollection\",\"features\":[\n{\"type\":\"Feature\",\"id\":\"AFG\",\"properties\":{\"name\":\"Afghanistan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[61.210817,35.650072],[62.230651,35.270664],[62.984662,35.404041],[63.193538,35.857166],[63.982896,36.007957],[64.546479,36.312073],[64.746105,37.111818],[65.588948,37.305217],[65.745631,37.661164],[66.217385,37.39379],[66.518607,37.362784],[67.075782,37.356144],[67.83,37.144994],[68.135562,37.023115],[68.859446,37.344336],[69.196273,37.151144],[69.518785,37.608997],[70.116578,37.588223],[70.270574,37.735165],[70.376304,38.138396],[70.806821,38.486282],[71.348131,38.258905],[71.239404,37.953265],[71.541918,37.905774],[71.448693,37.065645],[71.844638,36.738171],[72.193041,36.948288],[72.63689,37.047558],[73.260056,37.495257],[73.948696,37.421566],[74.980002,37.41999],[75.158028,37.133031],[74.575893,37.020841],[74.067552,36.836176],[72.920025,36.720007],[71.846292,36.509942],[71.262348,36.074388],[71.498768,35.650563],[71.613076,35.153203],[71.115019,34.733126],[71.156773,34.348911],[70.881803,33.988856],[69.930543,34.02012],[70.323594,33.358533],[69.687147,33.105499],[69.262522,32.501944],[69.317764,31.901412],[68.926677,31.620189],[68.556932,31.71331],[67.792689,31.58293],[67.683394,31.303154],[66.938891,31.304911],[66.381458,30.738899],[66.346473,29.887943],[65.046862,29.472181],[64.350419,29.560031],[64.148002,29.340819],[63.550261,29.468331],[62.549857,29.318572],[60.874248,29.829239],[61.781222,30.73585],[61.699314,31.379506],[60.941945,31.548075],[60.863655,32.18292],[60.536078,32.981269],[60.9637,33.528832],[60.52843,33.676446],[60.803193,34.404102],[61.210817,35.650072]]]}},\n{\"type\":\"Feature\",\"id\":\"AGO\",\"properties\":{\"name\":\"Angola\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[16.326528,-5.87747],[16.57318,-6.622645],[16.860191,-7.222298],[17.089996,-7.545689],[17.47297,-8.068551],[18.134222,-7.987678],[18.464176,-7.847014],[19.016752,-7.988246],[19.166613,-7.738184],[19.417502,-7.155429],[20.037723,-7.116361],[20.091622,-6.94309],[20.601823,-6.939318],[20.514748,-7.299606],[21.728111,-7.290872],[21.746456,-7.920085],[21.949131,-8.305901],[21.801801,-8.908707],[21.875182,-9.523708],[22.208753,-9.894796],[22.155268,-11.084801],[22.402798,-10.993075],[22.837345,-11.017622],[23.456791,-10.867863],[23.912215,-10.926826],[24.017894,-11.237298],[23.904154,-11.722282],[24.079905,-12.191297],[23.930922,-12.565848],[24.016137,-12.911046],[21.933886,-12.898437],[21.887843,-16.08031],[22.562478,-16.898451],[23.215048,-17.523116],[21.377176,-17.930636],[18.956187,-17.789095],[18.263309,-17.309951],[14.209707,-17.353101],[14.058501,-17.423381],[13.462362,-16.971212],[12.814081,-16.941343],[12.215461,-17.111668],[11.734199,-17.301889],[11.640096,-16.673142],[11.778537,-15.793816],[12.123581,-14.878316],[12.175619,-14.449144],[12.500095,-13.5477],[12.738479,-13.137906],[13.312914,-12.48363],[13.633721,-12.038645],[13.738728,-11.297863],[13.686379,-10.731076],[13.387328,-10.373578],[13.120988,-9.766897],[12.87537,-9.166934],[12.929061,-8.959091],[13.236433,-8.562629],[12.93304,-7.596539],[12.728298,-6.927122],[12.227347,-6.294448],[12.322432,-6.100092],[12.735171,-5.965682],[13.024869,-5.984389],[13.375597,-5.864241],[16.326528,-5.87747]]],[[[12.436688,-5.684304],[12.182337,-5.789931],[11.914963,-5.037987],[12.318608,-4.60623],[12.62076,-4.438023],[12.995517,-4.781103],[12.631612,-4.991271],[12.468004,-5.248362],[12.436688,-5.684304]]]]}},\n{\"type\":\"Feature\",\"id\":\"ALB\",\"properties\":{\"name\":\"Albania\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[20.590247,41.855404],[20.463175,41.515089],[20.605182,41.086226],[21.02004,40.842727],[20.99999,40.580004],[20.674997,40.435],[20.615,40.110007],[20.150016,39.624998],[19.98,39.694993],[19.960002,39.915006],[19.406082,40.250773],[19.319059,40.72723],[19.40355,41.409566],[19.540027,41.719986],[19.371769,41.877548],[19.304486,42.195745],[19.738051,42.688247],[19.801613,42.500093],[20.0707,42.58863],[20.283755,42.32026],[20.52295,42.21787],[20.590247,41.855404]]]}},\n{\"type\":\"Feature\",\"id\":\"ARE\",\"properties\":{\"name\":\"United Arab Emirates\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[51.579519,24.245497],[51.757441,24.294073],[51.794389,24.019826],[52.577081,24.177439],[53.404007,24.151317],[54.008001,24.121758],[54.693024,24.797892],[55.439025,25.439145],[56.070821,26.055464],[56.261042,25.714606],[56.396847,24.924732],[55.886233,24.920831],[55.804119,24.269604],[55.981214,24.130543],[55.528632,23.933604],[55.525841,23.524869],[55.234489,23.110993],[55.208341,22.70833],[55.006803,22.496948],[52.000733,23.001154],[51.617708,24.014219],[51.579519,24.245497]]]}},\n{\"type\":\"Feature\",\"id\":\"ARG\",\"properties\":{\"name\":\"Argentina\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-65.5,-55.2],[-66.45,-55.25],[-66.95992,-54.89681],[-67.56244,-54.87001],[-68.63335,-54.8695],[-68.63401,-52.63637],[-68.25,-53.1],[-67.75,-53.85],[-66.45,-54.45],[-65.05,-54.7],[-65.5,-55.2]]],[[[-64.964892,-22.075862],[-64.377021,-22.798091],[-63.986838,-21.993644],[-62.846468,-22.034985],[-62.685057,-22.249029],[-60.846565,-23.880713],[-60.028966,-24.032796],[-58.807128,-24.771459],[-57.777217,-25.16234],[-57.63366,-25.603657],[-58.618174,-27.123719],[-57.60976,-27.395899],[-56.486702,-27.548499],[-55.695846,-27.387837],[-54.788795,-26.621786],[-54.625291,-25.739255],[-54.13005,-25.547639],[-53.628349,-26.124865],[-53.648735,-26.923473],[-54.490725,-27.474757],[-55.162286,-27.881915],[-56.2909,-28.852761],[-57.625133,-30.216295],[-57.874937,-31.016556],[-58.14244,-32.044504],[-58.132648,-33.040567],[-58.349611,-33.263189],[-58.427074,-33.909454],[-58.495442,-34.43149],[-57.22583,-35.288027],[-57.362359,-35.97739],[-56.737487,-36.413126],[-56.788285,-36.901572],[-57.749157,-38.183871],[-59.231857,-38.72022],[-61.237445,-38.928425],[-62.335957,-38.827707],[-62.125763,-39.424105],[-62.330531,-40.172586],[-62.145994,-40.676897],[-62.745803,-41.028761],[-63.770495,-41.166789],[-64.73209,-40.802677],[-65.118035,-41.064315],[-64.978561,-42.058001],[-64.303408,-42.359016],[-63.755948,-42.043687],[-63.458059,-42.563138],[-64.378804,-42.873558],[-65.181804,-43.495381],[-65.328823,-44.501366],[-65.565269,-45.036786],[-66.509966,-45.039628],[-67.293794,-45.551896],[-67.580546,-46.301773],[-66.597066,-47.033925],[-65.641027,-47.236135],[-65.985088,-48.133289],[-67.166179,-48.697337],[-67.816088,-49.869669],[-68.728745,-50.264218],[-69.138539,-50.73251],[-68.815561,-51.771104],[-68.149995,-52.349983],[-68.571545,-52.299444],[-69.498362,-52.142761],[-71.914804,-52.009022],[-72.329404,-51.425956],[-72.309974,-50.67701],[-72.975747,-50.74145],[-73.328051,-50.378785],[-73.415436,-49.318436],[-72.648247,-48.878618],[-72.331161,-48.244238],[-72.447355,-47.738533],[-71.917258,-46.884838],[-71.552009,-45.560733],[-71.659316,-44.973689],[-71.222779,-44.784243],[-71.329801,-44.407522],[-71.793623,-44.207172],[-71.464056,-43.787611],[-71.915424,-43.408565],[-72.148898,-42.254888],[-71.746804,-42.051386],[-71.915734,-40.832339],[-71.680761,-39.808164],[-71.413517,-38.916022],[-70.814664,-38.552995],[-71.118625,-37.576827],[-71.121881,-36.658124],[-70.364769,-36.005089],[-70.388049,-35.169688],[-69.817309,-34.193571],[-69.814777,-33.273886],[-70.074399,-33.09121],[-70.535069,-31.36501],[-69.919008,-30.336339],[-70.01355,-29.367923],[-69.65613,-28.459141],[-69.001235,-27.521214],[-68.295542,-26.89934],[-68.5948,-26.506909],[-68.386001,-26.185016],[-68.417653,-24.518555],[-67.328443,-24.025303],[-66.985234,-22.986349],[-67.106674,-22.735925],[-66.273339,-21.83231],[-64.964892,-22.075862]]]]}},\n{\"type\":\"Feature\",\"id\":\"ARM\",\"properties\":{\"name\":\"Armenia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[43.582746,41.092143],[44.97248,41.248129],[45.179496,40.985354],[45.560351,40.81229],[45.359175,40.561504],[45.891907,40.218476],[45.610012,39.899994],[46.034534,39.628021],[46.483499,39.464155],[46.50572,38.770605],[46.143623,38.741201],[45.735379,39.319719],[45.739978,39.473999],[45.298145,39.471751],[45.001987,39.740004],[44.79399,39.713003],[44.400009,40.005],[43.656436,40.253564],[43.752658,40.740201],[43.582746,41.092143]]]}},\n{\"type\":\"Feature\",\"id\":\"ATA\",\"properties\":{\"name\":\"Antarctica\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-59.572095,-80.040179],[-59.865849,-80.549657],[-60.159656,-81.000327],[-62.255393,-80.863178],[-64.488125,-80.921934],[-65.741666,-80.588827],[-65.741666,-80.549657],[-66.290031,-80.255773],[-64.037688,-80.294944],[-61.883246,-80.39287],[-61.138976,-79.981371],[-60.610119,-79.628679],[-59.572095,-80.040179]]],[[[-159.208184,-79.497059],[-161.127601,-79.634209],[-162.439847,-79.281465],[-163.027408,-78.928774],[-163.066604,-78.869966],[-163.712896,-78.595667],[-163.105801,-78.223338],[-161.245113,-78.380176],[-160.246208,-78.693645],[-159.482405,-79.046338],[-159.208184,-79.497059]]],[[[-45.154758,-78.04707],[-43.920828,-78.478103],[-43.48995,-79.08556],[-43.372438,-79.516645],[-43.333267,-80.026123],[-44.880537,-80.339644],[-46.506174,-80.594357],[-48.386421,-80.829485],[-50.482107,-81.025442],[-52.851988,-80.966685],[-54.164259,-80.633528],[-53.987991,-80.222028],[-51.853134,-79.94773],[-50.991326,-79.614623],[-50.364595,-79.183487],[-49.914131,-78.811209],[-49.306959,-78.458569],[-48.660616,-78.047018],[-48.660616,-78.047019],[-48.151396,-78.04707],[-46.662857,-77.831476],[-45.154758,-78.04707]]],[[[-121.211511,-73.50099],[-119.918851,-73.657725],[-118.724143,-73.481353],[-119.292119,-73.834097],[-120.232217,-74.08881],[-121.62283,-74.010468],[-122.621735,-73.657778],[-122.621735,-73.657777],[-122.406245,-73.324619],[-121.211511,-73.50099]]],[[[-125.559566,-73.481353],[-124.031882,-73.873268],[-124.619469,-73.834097],[-125.912181,-73.736118],[-127.28313,-73.461769],[-127.28313,-73.461768],[-126.558472,-73.246226],[-125.559566,-73.481353]]],[[[-98.98155,-71.933334],[-97.884743,-72.070535],[-96.787937,-71.952971],[-96.20035,-72.521205],[-96.983765,-72.442864],[-98.198083,-72.482035],[-99.432013,-72.442864],[-100.783455,-72.50162],[-101.801868,-72.305663],[-102.330725,-71.894164],[-101.703967,-71.717792],[-100.430919,-71.854993],[-98.98155,-71.933334]]],[[[-68.451346,-70.955823],[-68.333834,-71.406493],[-68.510128,-71.798407],[-68.784297,-72.170736],[-69.959471,-72.307885],[-71.075889,-72.503842],[-72.388134,-72.484257],[-71.8985,-72.092343],[-73.073622,-72.229492],[-74.19004,-72.366693],[-74.953895,-72.072757],[-75.012625,-71.661258],[-73.915819,-71.269345],[-73.915819,-71.269344],[-73.230331,-71.15178],[-72.074717,-71.190951],[-71.780962,-70.681473],[-71.72218,-70.309196],[-71.741791,-69.505782],[-71.173815,-69.035475],[-70.253252,-68.87874],[-69.724447,-69.251017],[-69.489422,-69.623346],[-69.058518,-70.074016],[-68.725541,-70.505153],[-68.451346,-70.955823]]],[[[-58.614143,-64.152467],[-59.045073,-64.36801],[-59.789342,-64.211223],[-60.611928,-64.309202],[-61.297416,-64.54433],[-62.0221,-64.799094],[-62.51176,-65.09303],[-62.648858,-65.484942],[-62.590128,-65.857219],[-62.120079,-66.190326],[-62.805567,-66.425505],[-63.74569,-66.503847],[-64.294106,-66.837004],[-64.881693,-67.150474],[-65.508425,-67.58161],[-65.665082,-67.953887],[-65.312545,-68.365335],[-64.783715,-68.678908],[-63.961103,-68.913984],[-63.1973,-69.227556],[-62.785955,-69.619419],[-62.570516,-69.991747],[-62.276736,-70.383661],[-61.806661,-70.716768],[-61.512906,-71.089045],[-61.375809,-72.010074],[-61.081977,-72.382351],[-61.003661,-72.774265],[-60.690269,-73.166179],[-60.827367,-73.695242],[-61.375809,-74.106742],[-61.96337,-74.439848],[-63.295201,-74.576997],[-63.74569,-74.92974],[-64.352836,-75.262847],[-65.860987,-75.635124],[-67.192818,-75.79191],[-68.446282,-76.007452],[-69.797724,-76.222995],[-70.600724,-76.634494],[-72.206776,-76.673665],[-73.969536,-76.634494],[-75.555977,-76.712887],[-77.24037,-76.712887],[-76.926979,-77.104802],[-75.399294,-77.28107],[-74.282876,-77.55542],[-73.656119,-77.908112],[-74.772536,-78.221633],[-76.4961,-78.123654],[-77.925858,-78.378419],[-77.984666,-78.789918],[-78.023785,-79.181833],[-76.848637,-79.514939],[-76.633224,-79.887216],[-75.360097,-80.259545],[-73.244852,-80.416331],[-71.442946,-80.69063],[-70.013163,-81.004151],[-68.191646,-81.317672],[-65.704279,-81.474458],[-63.25603,-81.748757],[-61.552026,-82.042692],[-59.691416,-82.37585],[-58.712121,-82.846106],[-58.222487,-83.218434],[-57.008117,-82.865691],[-55.362894,-82.571755],[-53.619771,-82.258235],[-51.543644,-82.003521],[-49.76135,-81.729171],[-47.273931,-81.709586],[-44.825708,-81.846735],[-42.808363,-82.081915],[-42.16202,-81.65083],[-40.771433,-81.356894],[-38.244818,-81.337309],[-36.26667,-81.121715],[-34.386397,-80.906172],[-32.310296,-80.769023],[-30.097098,-80.592651],[-28.549802,-80.337938],[-29.254901,-79.985195],[-29.685805,-79.632503],[-29.685805,-79.260226],[-31.624808,-79.299397],[-33.681324,-79.456132],[-35.639912,-79.456132],[-35.914107,-79.083855],[-35.77701,-78.339248],[-35.326546,-78.123654],[-33.896763,-77.888526],[-32.212369,-77.65345],[-30.998051,-77.359515],[-29.783732,-77.065579],[-28.882779,-76.673665],[-27.511752,-76.497345],[-26.160336,-76.360144],[-25.474822,-76.281803],[-23.927552,-76.24258],[-22.458598,-76.105431],[-21.224694,-75.909474],[-20.010375,-75.674346],[-18.913543,-75.439218],[-17.522982,-75.125698],[-16.641589,-74.79254],[-15.701491,-74.498604],[-15.40771,-74.106742],[-16.46532,-73.871614],[-16.112784,-73.460114],[-15.446855,-73.146542],[-14.408805,-72.950585],[-13.311973,-72.715457],[-12.293508,-72.401936],[-11.510067,-72.010074],[-11.020433,-71.539767],[-10.295774,-71.265416],[-9.101015,-71.324224],[-8.611381,-71.65733],[-7.416622,-71.696501],[-7.377451,-71.324224],[-6.868232,-70.93231],[-5.790985,-71.030289],[-5.536375,-71.402617],[-4.341667,-71.461373],[-3.048981,-71.285053],[-1.795492,-71.167438],[-0.659489,-71.226246],[-0.228637,-71.637745],[0.868195,-71.304639],[1.886686,-71.128267],[3.022638,-70.991118],[4.139055,-70.853917],[5.157546,-70.618789],[6.273912,-70.462055],[7.13572,-70.246512],[7.742866,-69.893769],[8.48711,-70.148534],[9.525135,-70.011333],[10.249845,-70.48164],[10.817821,-70.834332],[11.953824,-70.638375],[12.404287,-70.246512],[13.422778,-69.972162],[14.734998,-70.030918],[15.126757,-70.403247],[15.949342,-70.030918],[17.026589,-69.913354],[18.201711,-69.874183],[19.259373,-69.893769],[20.375739,-70.011333],[21.452985,-70.07014],[21.923034,-70.403247],[22.569403,-70.697182],[23.666184,-70.520811],[24.841357,-70.48164],[25.977309,-70.48164],[27.093726,-70.462055],[28.09258,-70.324854],[29.150242,-70.20729],[30.031583,-69.93294],[30.971733,-69.75662],[31.990172,-69.658641],[32.754053,-69.384291],[33.302443,-68.835642],[33.870419,-68.502588],[34.908495,-68.659271],[35.300202,-69.012014],[36.16201,-69.247142],[37.200035,-69.168748],[37.905108,-69.52144],[38.649404,-69.776205],[39.667894,-69.541077],[40.020431,-69.109941],[40.921358,-68.933621],[41.959434,-68.600514],[42.938702,-68.463313],[44.113876,-68.267408],[44.897291,-68.051866],[45.719928,-67.816738],[46.503343,-67.601196],[47.44344,-67.718759],[48.344419,-67.366068],[48.990736,-67.091718],[49.930885,-67.111303],[50.753471,-66.876175],[50.949325,-66.523484],[51.791547,-66.249133],[52.614133,-66.053176],[53.613038,-65.89639],[54.53355,-65.818049],[55.414943,-65.876805],[56.355041,-65.974783],[57.158093,-66.249133],[57.255968,-66.680218],[58.137361,-67.013324],[58.744508,-67.287675],[59.939318,-67.405239],[60.605221,-67.679589],[61.427806,-67.953887],[62.387489,-68.012695],[63.19049,-67.816738],[64.052349,-67.405239],[64.992447,-67.620729],[65.971715,-67.738345],[66.911864,-67.855909],[67.891133,-67.934302],[68.890038,-67.934302],[69.712624,-68.972791],[69.673453,-69.227556],[69.555941,-69.678226],[68.596258,-69.93294],[67.81274,-70.305268],[67.949889,-70.697182],[69.066307,-70.677545],[68.929157,-71.069459],[68.419989,-71.441788],[67.949889,-71.853287],[68.71377,-72.166808],[69.869307,-72.264787],[71.024895,-72.088415],[71.573285,-71.696501],[71.906288,-71.324224],[72.454627,-71.010703],[73.08141,-70.716768],[73.33602,-70.364024],[73.864877,-69.874183],[74.491557,-69.776205],[75.62756,-69.737034],[76.626465,-69.619419],[77.644904,-69.462684],[78.134539,-69.07077],[78.428371,-68.698441],[79.113859,-68.326216],[80.093127,-68.071503],[80.93535,-67.875546],[81.483792,-67.542388],[82.051767,-67.366068],[82.776426,-67.209282],[83.775331,-67.30726],[84.676206,-67.209282],[85.655527,-67.091718],[86.752359,-67.150474],[87.477017,-66.876175],[87.986289,-66.209911],[88.358411,-66.484261],[88.828408,-66.954568],[89.67063,-67.150474],[90.630365,-67.228867],[91.5901,-67.111303],[92.608539,-67.189696],[93.548637,-67.209282],[94.17542,-67.111303],[95.017591,-67.170111],[95.781472,-67.385653],[96.682399,-67.248504],[97.759646,-67.248504],[98.68021,-67.111303],[99.718182,-67.248504],[100.384188,-66.915346],[100.893356,-66.58224],[101.578896,-66.30789],[102.832411,-65.563284],[103.478676,-65.700485],[104.242557,-65.974783],[104.90846,-66.327527],[106.181561,-66.934931],[107.160881,-66.954568],[108.081393,-66.954568],[109.15864,-66.837004],[110.235835,-66.699804],[111.058472,-66.425505],[111.74396,-66.13157],[112.860378,-66.092347],[113.604673,-65.876805],[114.388088,-66.072762],[114.897308,-66.386283],[115.602381,-66.699804],[116.699161,-66.660633],[117.384701,-66.915346],[118.57946,-67.170111],[119.832924,-67.268089],[120.871,-67.189696],[121.654415,-66.876175],[122.320369,-66.562654],[123.221296,-66.484261],[124.122274,-66.621462],[125.160247,-66.719389],[126.100396,-66.562654],[127.001427,-66.562654],[127.882768,-66.660633],[128.80328,-66.758611],[129.704259,-66.58224],[130.781454,-66.425505],[131.799945,-66.386283],[132.935896,-66.386283],[133.85646,-66.288304],[134.757387,-66.209963],[135.031582,-65.72007],[135.070753,-65.308571],[135.697485,-65.582869],[135.873805,-66.033591],[136.206705,-66.44509],[136.618049,-66.778197],[137.460271,-66.954568],[138.596223,-66.895761],[139.908442,-66.876175],[140.809421,-66.817367],[142.121692,-66.817367],[143.061842,-66.797782],[144.374061,-66.837004],[145.490427,-66.915346],[146.195552,-67.228867],[145.999699,-67.601196],[146.646067,-67.895131],[147.723263,-68.130259],[148.839629,-68.385024],[150.132314,-68.561292],[151.483705,-68.71813],[152.502247,-68.874813],[153.638199,-68.894502],[154.284567,-68.561292],[155.165857,-68.835642],[155.92979,-69.149215],[156.811132,-69.384291],[158.025528,-69.482269],[159.181013,-69.599833],[159.670699,-69.991747],[160.80665,-70.226875],[161.570479,-70.579618],[162.686897,-70.736353],[163.842434,-70.716768],[164.919681,-70.775524],[166.11444,-70.755938],[167.309095,-70.834332],[168.425616,-70.971481],[169.463589,-71.20666],[170.501665,-71.402617],[171.20679,-71.696501],[171.089227,-72.088415],[170.560422,-72.441159],[170.109958,-72.891829],[169.75737,-73.24452],[169.287321,-73.65602],[167.975101,-73.812806],[167.387489,-74.165498],[166.094803,-74.38104],[165.644391,-74.772954],[164.958851,-75.145283],[164.234193,-75.458804],[163.822797,-75.870303],[163.568239,-76.24258],[163.47026,-76.693302],[163.489897,-77.065579],[164.057873,-77.457442],[164.273363,-77.82977],[164.743464,-78.182514],[166.604126,-78.319611],[166.995781,-78.750748],[165.193876,-78.907483],[163.666217,-79.123025],[161.766385,-79.162248],[160.924162,-79.730482],[160.747894,-80.200737],[160.316964,-80.573066],[159.788211,-80.945395],[161.120016,-81.278501],[161.629287,-81.690001],[162.490992,-82.062278],[163.705336,-82.395435],[165.095949,-82.708956],[166.604126,-83.022477],[168.895665,-83.335998],[169.404782,-83.825891],[172.283934,-84.041433],[172.477049,-84.117914],[173.224083,-84.41371],[175.985672,-84.158997],[178.277212,-84.472518],[180,-84.71338],[-179.942499,-84.721443],[-179.058677,-84.139412],[-177.256772,-84.452933],[-177.140807,-84.417941],[-176.084673,-84.099259],[-175.947235,-84.110449],[-175.829882,-84.117914],[-174.382503,-84.534323],[-173.116559,-84.117914],[-172.889106,-84.061019],[-169.951223,-83.884647],[-168.999989,-84.117914],[-168.530199,-84.23739],[-167.022099,-84.570497],[-164.182144,-84.82521],[-161.929775,-85.138731],[-158.07138,-85.37391],[-155.192253,-85.09956],[-150.942099,-85.295517],[-148.533073,-85.609038],[-145.888918,-85.315102],[-143.107718,-85.040752],[-142.892279,-84.570497],[-146.829068,-84.531274],[-150.060732,-84.296146],[-150.902928,-83.904232],[-153.586201,-83.68869],[-153.409907,-83.23802],[-153.037759,-82.82652],[-152.665637,-82.454192],[-152.861517,-82.042692],[-154.526299,-81.768394],[-155.29018,-81.41565],[-156.83745,-81.102129],[-154.408787,-81.160937],[-152.097662,-81.004151],[-150.648293,-81.337309],[-148.865998,-81.043373],[-147.22075,-80.671045],[-146.417749,-80.337938],[-146.770286,-79.926439],[-148.062947,-79.652089],[-149.531901,-79.358205],[-151.588416,-79.299397],[-153.390322,-79.162248],[-155.329376,-79.064269],[-155.975668,-78.69194],[-157.268302,-78.378419],[-158.051768,-78.025676],[-158.365134,-76.889207],[-157.875474,-76.987238],[-156.974573,-77.300759],[-155.329376,-77.202728],[-153.742832,-77.065579],[-152.920247,-77.496664],[-151.33378,-77.398737],[-150.00195,-77.183143],[-148.748486,-76.908845],[-147.612483,-76.575738],[-146.104409,-76.47776],[-146.143528,-76.105431],[-146.496091,-75.733154],[-146.20231,-75.380411],[-144.909624,-75.204039],[-144.322037,-75.537197],[-142.794353,-75.34124],[-141.638764,-75.086475],[-140.209007,-75.06689],[-138.85759,-74.968911],[-137.5062,-74.733783],[-136.428901,-74.518241],[-135.214583,-74.302699],[-134.431194,-74.361455],[-133.745654,-74.439848],[-132.257168,-74.302699],[-130.925311,-74.479019],[-129.554284,-74.459433],[-128.242038,-74.322284],[-126.890622,-74.420263],[-125.402082,-74.518241],[-124.011496,-74.479019],[-122.562152,-74.498604],[-121.073613,-74.518241],[-119.70256,-74.479019],[-118.684145,-74.185083],[-117.469801,-74.028348],[-116.216312,-74.243891],[-115.021552,-74.067519],[-113.944331,-73.714828],[-113.297988,-74.028348],[-112.945452,-74.38104],[-112.299083,-74.714198],[-111.261059,-74.420263],[-110.066325,-74.79254],[-108.714909,-74.910103],[-107.559346,-75.184454],[-106.149148,-75.125698],[-104.876074,-74.949326],[-103.367949,-74.988497],[-102.016507,-75.125698],[-100.645531,-75.302018],[-100.1167,-74.870933],[-100.763043,-74.537826],[-101.252703,-74.185083],[-102.545337,-74.106742],[-103.113313,-73.734413],[-103.328752,-73.362084],[-103.681289,-72.61753],[-102.917485,-72.754679],[-101.60524,-72.813436],[-100.312528,-72.754679],[-99.13738,-72.911414],[-98.118889,-73.20535],[-97.688037,-73.558041],[-96.336595,-73.616849],[-95.043961,-73.4797],[-93.672907,-73.283743],[-92.439003,-73.166179],[-91.420564,-73.401307],[-90.088733,-73.322914],[-89.226951,-72.558722],[-88.423951,-73.009393],[-87.268337,-73.185764],[-86.014822,-73.087786],[-85.192236,-73.4797],[-83.879991,-73.518871],[-82.665646,-73.636434],[-81.470913,-73.851977],[-80.687447,-73.4797],[-80.295791,-73.126956],[-79.296886,-73.518871],[-77.925858,-73.420892],[-76.907367,-73.636434],[-76.221879,-73.969541],[-74.890049,-73.871614],[-73.852024,-73.65602],[-72.833533,-73.401307],[-71.619215,-73.264157],[-70.209042,-73.146542],[-68.935916,-73.009393],[-67.956622,-72.79385],[-67.369061,-72.480329],[-67.134036,-72.049244],[-67.251548,-71.637745],[-67.56494,-71.245831],[-67.917477,-70.853917],[-68.230843,-70.462055],[-68.485452,-70.109311],[-68.544209,-69.717397],[-68.446282,-69.325535],[-67.976233,-68.953206],[-67.5845,-68.541707],[-67.427843,-68.149844],[-67.62367,-67.718759],[-67.741183,-67.326845],[-67.251548,-66.876175],[-66.703184,-66.58224],[-66.056815,-66.209963],[-65.371327,-65.89639],[-64.568276,-65.602506],[-64.176542,-65.171423],[-63.628152,-64.897073],[-63.001394,-64.642308],[-62.041686,-64.583552],[-61.414928,-64.270031],[-60.709855,-64.074074],[-59.887269,-63.95651],[-59.162585,-63.701745],[-58.594557,-63.388224],[-57.811143,-63.27066],[-57.223582,-63.525425],[-57.59573,-63.858532],[-58.614143,-64.152467]]]]}},\n{\"type\":\"Feature\",\"id\":\"ATF\",\"properties\":{\"name\":\"French Southern and Antarctic Lands\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[68.935,-48.625],[69.58,-48.94],[70.525,-49.065],[70.56,-49.255],[70.28,-49.71],[68.745,-49.775],[68.72,-49.2425],[68.8675,-48.83],[68.935,-48.625]]]}},\n{\"type\":\"Feature\",\"id\":\"AUS\",\"properties\":{\"name\":\"Australia\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[145.397978,-40.792549],[146.364121,-41.137695],[146.908584,-41.000546],[147.689259,-40.808258],[148.289068,-40.875438],[148.359865,-42.062445],[148.017301,-42.407024],[147.914052,-43.211522],[147.564564,-42.937689],[146.870343,-43.634597],[146.663327,-43.580854],[146.048378,-43.549745],[145.43193,-42.693776],[145.29509,-42.03361],[144.718071,-41.162552],[144.743755,-40.703975],[145.397978,-40.792549]]],[[[143.561811,-13.763656],[143.922099,-14.548311],[144.563714,-14.171176],[144.894908,-14.594458],[145.374724,-14.984976],[145.271991,-15.428205],[145.48526,-16.285672],[145.637033,-16.784918],[145.888904,-16.906926],[146.160309,-17.761655],[146.063674,-18.280073],[146.387478,-18.958274],[147.471082,-19.480723],[148.177602,-19.955939],[148.848414,-20.39121],[148.717465,-20.633469],[149.28942,-21.260511],[149.678337,-22.342512],[150.077382,-22.122784],[150.482939,-22.556142],[150.727265,-22.402405],[150.899554,-23.462237],[151.609175,-24.076256],[152.07354,-24.457887],[152.855197,-25.267501],[153.136162,-26.071173],[153.161949,-26.641319],[153.092909,-27.2603],[153.569469,-28.110067],[153.512108,-28.995077],[153.339095,-29.458202],[153.069241,-30.35024],[153.089602,-30.923642],[152.891578,-31.640446],[152.450002,-32.550003],[151.709117,-33.041342],[151.343972,-33.816023],[151.010555,-34.31036],[150.714139,-35.17346],[150.32822,-35.671879],[150.075212,-36.420206],[149.946124,-37.109052],[149.997284,-37.425261],[149.423882,-37.772681],[148.304622,-37.809061],[147.381733,-38.219217],[146.922123,-38.606532],[146.317922,-39.035757],[145.489652,-38.593768],[144.876976,-38.417448],[145.032212,-37.896188],[144.485682,-38.085324],[143.609974,-38.809465],[142.745427,-38.538268],[142.17833,-38.380034],[141.606582,-38.308514],[140.638579,-38.019333],[139.992158,-37.402936],[139.806588,-36.643603],[139.574148,-36.138362],[139.082808,-35.732754],[138.120748,-35.612296],[138.449462,-35.127261],[138.207564,-34.384723],[137.71917,-35.076825],[136.829406,-35.260535],[137.352371,-34.707339],[137.503886,-34.130268],[137.890116,-33.640479],[137.810328,-32.900007],[136.996837,-33.752771],[136.372069,-34.094766],[135.989043,-34.890118],[135.208213,-34.47867],[135.239218,-33.947953],[134.613417,-33.222778],[134.085904,-32.848072],[134.273903,-32.617234],[132.990777,-32.011224],[132.288081,-31.982647],[131.326331,-31.495803],[129.535794,-31.590423],[128.240938,-31.948489],[127.102867,-32.282267],[126.148714,-32.215966],[125.088623,-32.728751],[124.221648,-32.959487],[124.028947,-33.483847],[123.659667,-33.890179],[122.811036,-33.914467],[122.183064,-34.003402],[121.299191,-33.821036],[120.580268,-33.930177],[119.893695,-33.976065],[119.298899,-34.509366],[119.007341,-34.464149],[118.505718,-34.746819],[118.024972,-35.064733],[117.295507,-35.025459],[116.625109,-35.025097],[115.564347,-34.386428],[115.026809,-34.196517],[115.048616,-33.623425],[115.545123,-33.487258],[115.714674,-33.259572],[115.679379,-32.900369],[115.801645,-32.205062],[115.689611,-31.612437],[115.160909,-30.601594],[114.997043,-30.030725],[115.040038,-29.461095],[114.641974,-28.810231],[114.616498,-28.516399],[114.173579,-28.118077],[114.048884,-27.334765],[113.477498,-26.543134],[113.338953,-26.116545],[113.778358,-26.549025],[113.440962,-25.621278],[113.936901,-25.911235],[114.232852,-26.298446],[114.216161,-25.786281],[113.721255,-24.998939],[113.625344,-24.683971],[113.393523,-24.384764],[113.502044,-23.80635],[113.706993,-23.560215],[113.843418,-23.059987],[113.736552,-22.475475],[114.149756,-21.755881],[114.225307,-22.517488],[114.647762,-21.82952],[115.460167,-21.495173],[115.947373,-21.068688],[116.711615,-20.701682],[117.166316,-20.623599],[117.441545,-20.746899],[118.229559,-20.374208],[118.836085,-20.263311],[118.987807,-20.044203],[119.252494,-19.952942],[119.805225,-19.976506],[120.85622,-19.683708],[121.399856,-19.239756],[121.655138,-18.705318],[122.241665,-18.197649],[122.286624,-17.798603],[122.312772,-17.254967],[123.012574,-16.4052],[123.433789,-17.268558],[123.859345,-17.069035],[123.503242,-16.596506],[123.817073,-16.111316],[124.258287,-16.327944],[124.379726,-15.56706],[124.926153,-15.0751],[125.167275,-14.680396],[125.670087,-14.51007],[125.685796,-14.230656],[126.125149,-14.347341],[126.142823,-14.095987],[126.582589,-13.952791],[127.065867,-13.817968],[127.804633,-14.276906],[128.35969,-14.86917],[128.985543,-14.875991],[129.621473,-14.969784],[129.4096,-14.42067],[129.888641,-13.618703],[130.339466,-13.357376],[130.183506,-13.10752],[130.617795,-12.536392],[131.223495,-12.183649],[131.735091,-12.302453],[132.575298,-12.114041],[132.557212,-11.603012],[131.824698,-11.273782],[132.357224,-11.128519],[133.019561,-11.376411],[133.550846,-11.786515],[134.393068,-12.042365],[134.678632,-11.941183],[135.298491,-12.248606],[135.882693,-11.962267],[136.258381,-12.049342],[136.492475,-11.857209],[136.95162,-12.351959],[136.685125,-12.887223],[136.305407,-13.29123],[135.961758,-13.324509],[136.077617,-13.724278],[135.783836,-14.223989],[135.428664,-14.715432],[135.500184,-14.997741],[136.295175,-15.550265],[137.06536,-15.870762],[137.580471,-16.215082],[138.303217,-16.807604],[138.585164,-16.806622],[139.108543,-17.062679],[139.260575,-17.371601],[140.215245,-17.710805],[140.875463,-17.369069],[141.07111,-16.832047],[141.274095,-16.38887],[141.398222,-15.840532],[141.702183,-15.044921],[141.56338,-14.561333],[141.63552,-14.270395],[141.519869,-13.698078],[141.65092,-12.944688],[141.842691,-12.741548],[141.68699,-12.407614],[141.928629,-11.877466],[142.118488,-11.328042],[142.143706,-11.042737],[142.51526,-10.668186],[142.79731,-11.157355],[142.866763,-11.784707],[143.115947,-11.90563],[143.158632,-12.325656],[143.522124,-12.834358],[143.597158,-13.400422],[143.561811,-13.763656]]]]}},\n{\"type\":\"Feature\",\"id\":\"AUT\",\"properties\":{\"name\":\"Austria\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[16.979667,48.123497],[16.903754,47.714866],[16.340584,47.712902],[16.534268,47.496171],[16.202298,46.852386],[16.011664,46.683611],[15.137092,46.658703],[14.632472,46.431817],[13.806475,46.509306],[12.376485,46.767559],[12.153088,47.115393],[11.164828,46.941579],[11.048556,46.751359],[10.442701,46.893546],[9.932448,46.920728],[9.47997,47.10281],[9.632932,47.347601],[9.594226,47.525058],[9.896068,47.580197],[10.402084,47.302488],[10.544504,47.566399],[11.426414,47.523766],[12.141357,47.703083],[12.62076,47.672388],[12.932627,47.467646],[13.025851,47.637584],[12.884103,48.289146],[13.243357,48.416115],[13.595946,48.877172],[14.338898,48.555305],[14.901447,48.964402],[15.253416,49.039074],[16.029647,48.733899],[16.499283,48.785808],[16.960288,48.596982],[16.879983,48.470013],[16.979667,48.123497]]]}},\n{\"type\":\"Feature\",\"id\":\"AZE\",\"properties\":{\"name\":\"Azerbaijan\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[45.001987,39.740004],[45.298145,39.471751],[45.739978,39.473999],[45.735379,39.319719],[46.143623,38.741201],[45.457722,38.874139],[44.952688,39.335765],[44.79399,39.713003],[45.001987,39.740004]]],[[[47.373315,41.219732],[47.815666,41.151416],[47.987283,41.405819],[48.584353,41.80887],[49.110264,41.282287],[49.618915,40.572924],[50.08483,40.526157],[50.392821,40.256561],[49.569202,40.176101],[49.395259,39.399482],[49.223228,39.049219],[48.856532,38.815486],[48.883249,38.320245],[48.634375,38.270378],[48.010744,38.794015],[48.355529,39.288765],[48.060095,39.582235],[47.685079,39.508364],[46.50572,38.770605],[46.483499,39.464155],[46.034534,39.628021],[45.610012,39.899994],[45.891907,40.218476],[45.359175,40.561504],[45.560351,40.81229],[45.179496,40.985354],[44.97248,41.248129],[45.217426,41.411452],[45.962601,41.123873],[46.501637,41.064445],[46.637908,41.181673],[46.145432,41.722802],[46.404951,41.860675],[46.686071,41.827137],[47.373315,41.219732]]]]}},\n{\"type\":\"Feature\",\"id\":\"BDI\",\"properties\":{\"name\":\"Burundi\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[29.339998,-4.499983],[29.276384,-3.293907],[29.024926,-2.839258],[29.632176,-2.917858],[29.938359,-2.348487],[30.469696,-2.413858],[30.527677,-2.807632],[30.743013,-3.034285],[30.752263,-3.35933],[30.50556,-3.568567],[30.116333,-4.090138],[29.753512,-4.452389],[29.339998,-4.499983]]]}},\n{\"type\":\"Feature\",\"id\":\"BEL\",\"properties\":{\"name\":\"Belgium\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[3.314971,51.345781],[4.047071,51.267259],[4.973991,51.475024],[5.606976,51.037298],[6.156658,50.803721],[6.043073,50.128052],[5.782417,50.090328],[5.674052,49.529484],[4.799222,49.985373],[4.286023,49.907497],[3.588184,50.378992],[3.123252,50.780363],[2.658422,50.796848],[2.513573,51.148506],[3.314971,51.345781]]]}},\n{\"type\":\"Feature\",\"id\":\"BEN\",\"properties\":{\"name\":\"Benin\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[2.691702,6.258817],[1.865241,6.142158],[1.618951,6.832038],[1.664478,9.12859],[1.463043,9.334624],[1.425061,9.825395],[1.077795,10.175607],[0.772336,10.470808],[0.899563,10.997339],[1.24347,11.110511],[1.447178,11.547719],[1.935986,11.64115],[2.154474,11.94015],[2.490164,12.233052],[2.848643,12.235636],[3.61118,11.660167],[3.572216,11.327939],[3.797112,10.734746],[3.60007,10.332186],[3.705438,10.06321],[3.220352,9.444153],[2.912308,9.137608],[2.723793,8.506845],[2.749063,7.870734],[2.691702,6.258817]]]}},\n{\"type\":\"Feature\",\"id\":\"BFA\",\"properties\":{\"name\":\"Burkina Faso\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-2.827496,9.642461],[-3.511899,9.900326],[-3.980449,9.862344],[-4.330247,9.610835],[-4.779884,9.821985],[-4.954653,10.152714],[-5.404342,10.370737],[-5.470565,10.95127],[-5.197843,11.375146],[-5.220942,11.713859],[-4.427166,12.542646],[-4.280405,13.228444],[-4.006391,13.472485],[-3.522803,13.337662],[-3.103707,13.541267],[-2.967694,13.79815],[-2.191825,14.246418],[-2.001035,14.559008],[-1.066363,14.973815],[-0.515854,15.116158],[-0.266257,14.924309],[0.374892,14.928908],[0.295646,14.444235],[0.429928,13.988733],[0.993046,13.33575],[1.024103,12.851826],[2.177108,12.625018],[2.154474,11.94015],[1.935986,11.64115],[1.447178,11.547719],[1.24347,11.110511],[0.899563,10.997339],[0.023803,11.018682],[-0.438702,11.098341],[-0.761576,10.93693],[-1.203358,11.009819],[-2.940409,10.96269],[-2.963896,10.395335],[-2.827496,9.642461]]]}},\n{\"type\":\"Feature\",\"id\":\"BGD\",\"properties\":{\"name\":\"Bangladesh\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[92.672721,22.041239],[92.652257,21.324048],[92.303234,21.475485],[92.368554,20.670883],[92.082886,21.192195],[92.025215,21.70157],[91.834891,22.182936],[91.417087,22.765019],[90.496006,22.805017],[90.586957,22.392794],[90.272971,21.836368],[89.847467,22.039146],[89.70205,21.857116],[89.418863,21.966179],[89.031961,22.055708],[88.876312,22.879146],[88.52977,23.631142],[88.69994,24.233715],[88.084422,24.501657],[88.306373,24.866079],[88.931554,25.238692],[88.209789,25.768066],[88.563049,26.446526],[89.355094,26.014407],[89.832481,25.965082],[89.920693,25.26975],[90.872211,25.132601],[91.799596,25.147432],[92.376202,24.976693],[91.915093,24.130414],[91.46773,24.072639],[91.158963,23.503527],[91.706475,22.985264],[91.869928,23.624346],[92.146035,23.627499],[92.672721,22.041239]]]}},\n{\"type\":\"Feature\",\"id\":\"BGR\",\"properties\":{\"name\":\"Bulgaria\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[22.65715,44.234923],[22.944832,43.823785],[23.332302,43.897011],[24.100679,43.741051],[25.569272,43.688445],[26.065159,43.943494],[27.2424,44.175986],[27.970107,43.812468],[28.558081,43.707462],[28.039095,43.293172],[27.673898,42.577892],[27.99672,42.007359],[27.135739,42.141485],[26.117042,41.826905],[26.106138,41.328899],[25.197201,41.234486],[24.492645,41.583896],[23.692074,41.309081],[22.952377,41.337994],[22.881374,41.999297],[22.380526,42.32026],[22.545012,42.461362],[22.436595,42.580321],[22.604801,42.898519],[22.986019,43.211161],[22.500157,43.642814],[22.410446,44.008063],[22.65715,44.234923]]]}},\n{\"type\":\"Feature\",\"id\":\"BHS\",\"properties\":{\"name\":\"The Bahamas\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-77.53466,23.75975],[-77.78,23.71],[-78.03405,24.28615],[-78.40848,24.57564],[-78.19087,25.2103],[-77.89,25.17],[-77.54,24.34],[-77.53466,23.75975]]],[[[-77.82,26.58],[-78.91,26.42],[-78.98,26.79],[-78.51,26.87],[-77.85,26.84],[-77.82,26.58]]],[[[-77,26.59],[-77.17255,25.87918],[-77.35641,26.00735],[-77.34,26.53],[-77.78802,26.92516],[-77.79,27.04],[-77,26.59]]]]}},\n{\"type\":\"Feature\",\"id\":\"BIH\",\"properties\":{\"name\":\"Bosnia and Herzegovina\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[19.005486,44.860234],[19.36803,44.863],[19.11761,44.42307],[19.59976,44.03847],[19.454,43.5681],[19.21852,43.52384],[19.03165,43.43253],[18.70648,43.20011],[18.56,42.65],[17.674922,43.028563],[17.297373,43.446341],[16.916156,43.667722],[16.456443,44.04124],[16.23966,44.351143],[15.750026,44.818712],[15.959367,45.233777],[16.318157,45.004127],[16.534939,45.211608],[17.002146,45.233777],[17.861783,45.06774],[18.553214,45.08159],[19.005486,44.860234]]]}},\n{\"type\":\"Feature\",\"id\":\"BLR\",\"properties\":{\"name\":\"Belarus\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[23.484128,53.912498],[24.450684,53.905702],[25.536354,54.282423],[25.768433,54.846963],[26.588279,55.167176],[26.494331,55.615107],[27.10246,55.783314],[28.176709,56.16913],[29.229513,55.918344],[29.371572,55.670091],[29.896294,55.789463],[30.873909,55.550976],[30.971836,55.081548],[30.757534,54.811771],[31.384472,54.157056],[31.791424,53.974639],[31.731273,53.794029],[32.405599,53.618045],[32.693643,53.351421],[32.304519,53.132726],[31.497644,53.167427],[31.305201,53.073996],[31.540018,52.742052],[31.785998,52.101678],[30.927549,52.042353],[30.619454,51.822806],[30.555117,51.319503],[30.157364,51.416138],[29.254938,51.368234],[28.992835,51.602044],[28.617613,51.427714],[28.241615,51.572227],[27.454066,51.592303],[26.337959,51.832289],[25.327788,51.910656],[24.553106,51.888461],[24.005078,51.617444],[23.527071,51.578454],[23.508002,52.023647],[23.199494,52.486977],[23.799199,52.691099],[23.804935,53.089731],[23.527536,53.470122],[23.484128,53.912498]]]}},\n{\"type\":\"Feature\",\"id\":\"BLZ\",\"properties\":{\"name\":\"Belize\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-89.14308,17.808319],[-89.150909,17.955468],[-89.029857,18.001511],[-88.848344,17.883198],[-88.490123,18.486831],[-88.300031,18.499982],[-88.296336,18.353273],[-88.106813,18.348674],[-88.123479,18.076675],[-88.285355,17.644143],[-88.197867,17.489475],[-88.302641,17.131694],[-88.239518,17.036066],[-88.355428,16.530774],[-88.551825,16.265467],[-88.732434,16.233635],[-88.930613,15.887273],[-89.229122,15.886938],[-89.150806,17.015577],[-89.14308,17.808319]]]}},\n{\"type\":\"Feature\",\"id\":\"BMU\",\"properties\":{\"name\":\"Bermuda\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-64.7799734332998,32.3072000581802],[-64.7873319183061,32.3039237143428],[-64.7946942710173,32.3032682700388],[-64.8094297981283,32.3098175728414],[-64.8167896352437,32.3058845718466],[-64.8101968029642,32.3022833180511],[-64.7962291465484,32.2934409732427],[-64.7815086336978,32.2868973114514],[-64.7997025513437,32.2796896417328],[-64.8066707691087,32.2747767569465],[-64.8225587873683,32.2669111289395],[-64.8287548840306,32.2669075473817],[-64.8306732143498,32.2583944840235],[-64.8399924854972,32.254782282336],[-64.8566090462354,32.2547740387514],[-64.8682296789446,32.2616393614322],[-64.8628241459563,32.2724481933959],[-64.8748651338951,32.2757120264753],[-64.8717752856644,32.2819371582026],[-64.8671422127295,32.2930760547989],[-64.8559068764437,32.2960321186471],[-64.8597429072279,32.3015842021933],[-64.8439233486717,32.3140553852543],[-64.8350242329311,32.3242161760006],[-64.8338690593672,32.3294587561557],[-64.8520298651164,32.3110911879954],[-64.8635922932573,32.3048469433363],[-64.8686668994079,32.30910745083],[-64.8721354593415,32.3041908606301],[-64.8779667328485,32.3038632800462],[-64.8780046844321,32.2907757831692],[-64.8849776658292,32.2819261366004],[-64.8783230004629,32.2613001418681],[-64.863194968877,32.2465799485801],[-64.8519819555722,32.2485519134663],[-64.842311980074,32.2492123317296],[-64.8388242605209,32.2475773472534],[-64.8334002575532,32.2462714714698],[-64.8256389530584,32.2472637398594],[-64.8205697556026,32.2531698880328],[-64.8105087275579,32.2561208974156],[-64.7900177727338,32.2659446936992],[-64.7745415970416,32.2718413023427],[-64.7644742436426,32.2855931353214],[-64.7551803442276,32.2908326702531],[-64.7423982971436,32.2996734994024],[-64.7206991797682,32.3137542201258],[-64.7117851247134,32.3176823360806],[-64.6962778813133,32.3275029115532],[-64.6768921127452,32.3324095397555],[-64.6567136927777,32.3451776458469],[-64.6532168823499,32.3494356627941],[-64.6605720384429,32.3589423487763],[-64.65125819471,32.3615600906466],[-64.6462011670816,32.36975169749],[-64.6613227512832,32.3763135008721],[-64.6690666074397,32.388444543924],[-64.6834270548595,32.3854968316788],[-64.6954617672714,32.3763221285869],[-64.70438689565,32.3704254760469],[-64.7117569982798,32.368132600249],[-64.7061764744404,32.3600110593559],[-64.700531552697,32.3590601356818],[-64.6940348033967,32.3640708659835],[-64.6895164826082,32.3633598579866],[-64.6864150099255,32.3547797587266],[-64.6824635995504,32.3540628176846],[-64.6835876652835,32.3626447677968],[-64.6801998697415,32.3631199096979],[-64.6672170444687,32.3597751617473],[-64.6598811264978,32.3497625771755],[-64.6737331235384,32.3390281851635],[-64.6887090648183,32.3342439408053],[-64.706732854446,32.3429010723036],[-64.7149301576112,32.3552188753513],[-64.7185967666669,32.3552239212394],[-64.7214189847314,32.3518830231342],[-64.7270616067222,32.3466461715475],[-64.734962460882,32.3442819830499],[-64.7383521549094,32.3407216514918],[-64.7411729976333,32.3311790864627],[-64.7423019216485,32.323311561213],[-64.7462482354281,32.318538611581],[-64.7566773739613,32.3130509130175],[-64.768738200563,32.3088369816572],[-64.7799734332998,32.3072000581802]]]}},\n{\"type\":\"Feature\",\"id\":\"BOL\",\"properties\":{\"name\":\"Bolivia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-62.846468,-22.034985],[-63.986838,-21.993644],[-64.377021,-22.798091],[-64.964892,-22.075862],[-66.273339,-21.83231],[-67.106674,-22.735925],[-67.82818,-22.872919],[-68.219913,-21.494347],[-68.757167,-20.372658],[-68.442225,-19.405068],[-68.966818,-18.981683],[-69.100247,-18.260125],[-69.590424,-17.580012],[-68.959635,-16.500698],[-69.389764,-15.660129],[-69.160347,-15.323974],[-69.339535,-14.953195],[-68.948887,-14.453639],[-68.929224,-13.602684],[-68.88008,-12.899729],[-68.66508,-12.5613],[-69.529678,-10.951734],[-68.786158,-11.03638],[-68.271254,-11.014521],[-68.048192,-10.712059],[-67.173801,-10.306812],[-66.646908,-9.931331],[-65.338435,-9.761988],[-65.444837,-10.511451],[-65.321899,-10.895872],[-65.402281,-11.56627],[-64.316353,-12.461978],[-63.196499,-12.627033],[-62.80306,-13.000653],[-62.127081,-13.198781],[-61.713204,-13.489202],[-61.084121,-13.479384],[-60.503304,-13.775955],[-60.459198,-14.354007],[-60.264326,-14.645979],[-60.251149,-15.077219],[-60.542966,-15.09391],[-60.15839,-16.258284],[-58.24122,-16.299573],[-58.388058,-16.877109],[-58.280804,-17.27171],[-57.734558,-17.552468],[-57.498371,-18.174188],[-57.676009,-18.96184],[-57.949997,-19.400004],[-57.853802,-19.969995],[-58.166392,-20.176701],[-58.183471,-19.868399],[-59.115042,-19.356906],[-60.043565,-19.342747],[-61.786326,-19.633737],[-62.265961,-20.513735],[-62.291179,-21.051635],[-62.685057,-22.249029],[-62.846468,-22.034985]]]}},\n{\"type\":\"Feature\",\"id\":\"BRA\",\"properties\":{\"name\":\"Brazil\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-57.625133,-30.216295],[-56.2909,-28.852761],[-55.162286,-27.881915],[-54.490725,-27.474757],[-53.648735,-26.923473],[-53.628349,-26.124865],[-54.13005,-25.547639],[-54.625291,-25.739255],[-54.428946,-25.162185],[-54.293476,-24.5708],[-54.29296,-24.021014],[-54.652834,-23.839578],[-55.027902,-24.001274],[-55.400747,-23.956935],[-55.517639,-23.571998],[-55.610683,-22.655619],[-55.797958,-22.35693],[-56.473317,-22.0863],[-56.88151,-22.282154],[-57.937156,-22.090176],[-57.870674,-20.732688],[-58.166392,-20.176701],[-57.853802,-19.969995],[-57.949997,-19.400004],[-57.676009,-18.96184],[-57.498371,-18.174188],[-57.734558,-17.552468],[-58.280804,-17.27171],[-58.388058,-16.877109],[-58.24122,-16.299573],[-60.15839,-16.258284],[-60.542966,-15.09391],[-60.251149,-15.077219],[-60.264326,-14.645979],[-60.459198,-14.354007],[-60.503304,-13.775955],[-61.084121,-13.479384],[-61.713204,-13.489202],[-62.127081,-13.198781],[-62.80306,-13.000653],[-63.196499,-12.627033],[-64.316353,-12.461978],[-65.402281,-11.56627],[-65.321899,-10.895872],[-65.444837,-10.511451],[-65.338435,-9.761988],[-66.646908,-9.931331],[-67.173801,-10.306812],[-68.048192,-10.712059],[-68.271254,-11.014521],[-68.786158,-11.03638],[-69.529678,-10.951734],[-70.093752,-11.123972],[-70.548686,-11.009147],[-70.481894,-9.490118],[-71.302412,-10.079436],[-72.184891,-10.053598],[-72.563033,-9.520194],[-73.226713,-9.462213],[-73.015383,-9.032833],[-73.571059,-8.424447],[-73.987235,-7.52383],[-73.723401,-7.340999],[-73.724487,-6.918595],[-73.120027,-6.629931],[-73.219711,-6.089189],[-72.964507,-5.741251],[-72.891928,-5.274561],[-71.748406,-4.593983],[-70.928843,-4.401591],[-70.794769,-4.251265],[-69.893635,-4.298187],[-69.444102,-1.556287],[-69.420486,-1.122619],[-69.577065,-0.549992],[-70.020656,-0.185156],[-70.015566,0.541414],[-69.452396,0.706159],[-69.252434,0.602651],[-69.218638,0.985677],[-69.804597,1.089081],[-69.816973,1.714805],[-67.868565,1.692455],[-67.53781,2.037163],[-67.259998,1.719999],[-67.065048,1.130112],[-66.876326,1.253361],[-66.325765,0.724452],[-65.548267,0.789254],[-65.354713,1.095282],[-64.611012,1.328731],[-64.199306,1.492855],[-64.083085,1.916369],[-63.368788,2.2009],[-63.422867,2.411068],[-64.269999,2.497006],[-64.408828,3.126786],[-64.368494,3.79721],[-64.816064,4.056445],[-64.628659,4.148481],[-63.888343,4.02053],[-63.093198,3.770571],[-62.804533,4.006965],[-62.08543,4.162124],[-60.966893,4.536468],[-60.601179,4.918098],[-60.733574,5.200277],[-60.213683,5.244486],[-59.980959,5.014061],[-60.111002,4.574967],[-59.767406,4.423503],[-59.53804,3.958803],[-59.815413,3.606499],[-59.974525,2.755233],[-59.718546,2.24963],[-59.646044,1.786894],[-59.030862,1.317698],[-58.540013,1.268088],[-58.429477,1.463942],[-58.11345,1.507195],[-57.660971,1.682585],[-57.335823,1.948538],[-56.782704,1.863711],[-56.539386,1.899523],[-55.995698,1.817667],[-55.9056,2.021996],[-56.073342,2.220795],[-55.973322,2.510364],[-55.569755,2.421506],[-55.097587,2.523748],[-54.524754,2.311849],[-54.088063,2.105557],[-53.778521,2.376703],[-53.554839,2.334897],[-53.418465,2.053389],[-52.939657,2.124858],[-52.556425,2.504705],[-52.249338,3.241094],[-51.657797,4.156232],[-51.317146,4.203491],[-51.069771,3.650398],[-50.508875,1.901564],[-49.974076,1.736483],[-49.947101,1.04619],[-50.699251,0.222984],[-50.388211,-0.078445],[-48.620567,-0.235489],[-48.584497,-1.237805],[-47.824956,-0.581618],[-46.566584,-0.941028],[-44.905703,-1.55174],[-44.417619,-2.13775],[-44.581589,-2.691308],[-43.418791,-2.38311],[-41.472657,-2.912018],[-39.978665,-2.873054],[-38.500383,-3.700652],[-37.223252,-4.820946],[-36.452937,-5.109404],[-35.597796,-5.149504],[-35.235389,-5.464937],[-34.89603,-6.738193],[-34.729993,-7.343221],[-35.128212,-8.996401],[-35.636967,-9.649282],[-37.046519,-11.040721],[-37.683612,-12.171195],[-38.423877,-13.038119],[-38.673887,-13.057652],[-38.953276,-13.79337],[-38.882298,-15.667054],[-39.161092,-17.208407],[-39.267339,-17.867746],[-39.583521,-18.262296],[-39.760823,-19.599113],[-40.774741,-20.904512],[-40.944756,-21.937317],[-41.754164,-22.370676],[-41.988284,-22.97007],[-43.074704,-22.967693],[-44.647812,-23.351959],[-45.352136,-23.796842],[-46.472093,-24.088969],[-47.648972,-24.885199],[-48.495458,-25.877025],[-48.641005,-26.623698],[-48.474736,-27.175912],[-48.66152,-28.186135],[-48.888457,-28.674115],[-49.587329,-29.224469],[-50.696874,-30.984465],[-51.576226,-31.777698],[-52.256081,-32.24537],[-52.7121,-33.196578],[-53.373662,-33.768378],[-53.650544,-33.202004],[-53.209589,-32.727666],[-53.787952,-32.047243],[-54.572452,-31.494511],[-55.60151,-30.853879],[-55.973245,-30.883076],[-56.976026,-30.109686],[-57.625133,-30.216295]]]}},\n{\"type\":\"Feature\",\"id\":\"BRN\",\"properties\":{\"name\":\"Brunei\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[114.204017,4.525874],[114.599961,4.900011],[115.45071,5.44773],[115.4057,4.955228],[115.347461,4.316636],[114.869557,4.348314],[114.659596,4.007637],[114.204017,4.525874]]]}},\n{\"type\":\"Feature\",\"id\":\"BTN\",\"properties\":{\"name\":\"Bhutan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[91.696657,27.771742],[92.103712,27.452614],[92.033484,26.83831],[91.217513,26.808648],[90.373275,26.875724],[89.744528,26.719403],[88.835643,27.098966],[88.814248,27.299316],[89.47581,28.042759],[90.015829,28.296439],[90.730514,28.064954],[91.258854,28.040614],[91.696657,27.771742]]]}},\n{\"type\":\"Feature\",\"id\":\"BWA\",\"properties\":{\"name\":\"Botswana\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[25.649163,-18.536026],[25.850391,-18.714413],[26.164791,-19.293086],[27.296505,-20.39152],[27.724747,-20.499059],[27.727228,-20.851802],[28.02137,-21.485975],[28.794656,-21.639454],[29.432188,-22.091313],[28.017236,-22.827754],[27.11941,-23.574323],[26.786407,-24.240691],[26.485753,-24.616327],[25.941652,-24.696373],[25.765849,-25.174845],[25.664666,-25.486816],[25.025171,-25.71967],[24.211267,-25.670216],[23.73357,-25.390129],[23.312097,-25.26869],[22.824271,-25.500459],[22.579532,-25.979448],[22.105969,-26.280256],[21.605896,-26.726534],[20.889609,-26.828543],[20.66647,-26.477453],[20.758609,-25.868136],[20.165726,-24.917962],[19.895768,-24.76779],[19.895458,-21.849157],[20.881134,-21.814327],[20.910641,-18.252219],[21.65504,-18.219146],[23.196858,-17.869038],[23.579006,-18.281261],[24.217365,-17.889347],[24.520705,-17.887125],[25.084443,-17.661816],[25.264226,-17.73654],[25.649163,-18.536026]]]}},\n{\"type\":\"Feature\",\"id\":\"CAF\",\"properties\":{\"name\":\"Central African Republic\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[15.27946,7.421925],[16.106232,7.497088],[16.290562,7.754307],[16.456185,7.734774],[16.705988,7.508328],[17.96493,7.890914],[18.389555,8.281304],[18.911022,8.630895],[18.81201,8.982915],[19.094008,9.074847],[20.059685,9.012706],[21.000868,9.475985],[21.723822,10.567056],[22.231129,10.971889],[22.864165,11.142395],[22.977544,10.714463],[23.554304,10.089255],[23.55725,9.681218],[23.394779,9.265068],[23.459013,8.954286],[23.805813,8.666319],[24.567369,8.229188],[25.114932,7.825104],[25.124131,7.500085],[25.796648,6.979316],[26.213418,6.546603],[26.465909,5.946717],[27.213409,5.550953],[27.374226,5.233944],[27.044065,5.127853],[26.402761,5.150875],[25.650455,5.256088],[25.278798,5.170408],[25.128833,4.927245],[24.805029,4.897247],[24.410531,5.108784],[23.297214,4.609693],[22.84148,4.710126],[22.704124,4.633051],[22.405124,4.02916],[21.659123,4.224342],[20.927591,4.322786],[20.290679,4.691678],[19.467784,5.031528],[18.932312,4.709506],[18.542982,4.201785],[18.453065,3.504386],[17.8099,3.560196],[17.133042,3.728197],[16.537058,3.198255],[16.012852,2.26764],[15.907381,2.557389],[15.862732,3.013537],[15.405396,3.335301],[15.03622,3.851367],[14.950953,4.210389],[14.478372,4.732605],[14.558936,5.030598],[14.459407,5.451761],[14.53656,6.226959],[14.776545,6.408498],[15.27946,7.421925]]]}},\n{\"type\":\"Feature\",\"id\":\"CAN\",\"properties\":{\"name\":\"Canada\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-63.6645,46.55001],[-62.9393,46.41587],[-62.01208,46.44314],[-62.50391,46.03339],[-62.87433,45.96818],[-64.1428,46.39265],[-64.39261,46.72747],[-64.01486,47.03601],[-63.6645,46.55001]]],[[[-61.806305,49.10506],[-62.29318,49.08717],[-63.58926,49.40069],[-64.51912,49.87304],[-64.17322,49.95718],[-62.85829,49.70641],[-61.835585,49.28855],[-61.806305,49.10506]]],[[[-123.510002,48.510011],[-124.012891,48.370846],[-125.655013,48.825005],[-125.954994,49.179996],[-126.850004,49.53],[-127.029993,49.814996],[-128.059336,49.994959],[-128.444584,50.539138],[-128.358414,50.770648],[-127.308581,50.552574],[-126.695001,50.400903],[-125.755007,50.295018],[-125.415002,49.950001],[-124.920768,49.475275],[-123.922509,49.062484],[-123.510002,48.510011]]],[[[-56.134036,50.68701],[-56.795882,49.812309],[-56.143105,50.150117],[-55.471492,49.935815],[-55.822401,49.587129],[-54.935143,49.313011],[-54.473775,49.556691],[-53.476549,49.249139],[-53.786014,48.516781],[-53.086134,48.687804],[-52.958648,48.157164],[-52.648099,47.535548],[-53.069158,46.655499],[-53.521456,46.618292],[-54.178936,46.807066],[-53.961869,47.625207],[-54.240482,47.752279],[-55.400773,46.884994],[-55.997481,46.91972],[-55.291219,47.389562],[-56.250799,47.632545],[-57.325229,47.572807],[-59.266015,47.603348],[-59.419494,47.899454],[-58.796586,48.251525],[-59.231625,48.523188],[-58.391805,49.125581],[-57.35869,50.718274],[-56.73865,51.287438],[-55.870977,51.632094],[-55.406974,51.588273],[-55.600218,51.317075],[-56.134036,50.68701]]],[[[-132.710008,54.040009],[-131.74999,54.120004],[-132.04948,52.984621],[-131.179043,52.180433],[-131.57783,52.182371],[-132.180428,52.639707],[-132.549992,53.100015],[-133.054611,53.411469],[-133.239664,53.85108],[-133.180004,54.169975],[-132.710008,54.040009]]],[[[-79.26582,62.158675],[-79.65752,61.63308],[-80.09956,61.7181],[-80.36215,62.01649],[-80.315395,62.085565],[-79.92939,62.3856],[-79.52002,62.36371],[-79.26582,62.158675]]],[[[-81.89825,62.7108],[-83.06857,62.15922],[-83.77462,62.18231],[-83.99367,62.4528],[-83.25048,62.91409],[-81.87699,62.90458],[-81.89825,62.7108]]],[[[-85.161308,65.657285],[-84.975764,65.217518],[-84.464012,65.371772],[-83.882626,65.109618],[-82.787577,64.766693],[-81.642014,64.455136],[-81.55344,63.979609],[-80.817361,64.057486],[-80.103451,63.725981],[-80.99102,63.411246],[-82.547178,63.651722],[-83.108798,64.101876],[-84.100417,63.569712],[-85.523405,63.052379],[-85.866769,63.637253],[-87.221983,63.541238],[-86.35276,64.035833],[-86.224886,64.822917],[-85.883848,65.738778],[-85.161308,65.657285]]],[[[-75.86588,67.14886],[-76.98687,67.09873],[-77.2364,67.58809],[-76.81166,68.14856],[-75.89521,68.28721],[-75.1145,68.01036],[-75.10333,67.58202],[-75.21597,67.44425],[-75.86588,67.14886]]],[[[-95.647681,69.10769],[-96.269521,68.75704],[-97.617401,69.06003],[-98.431801,68.9507],[-99.797401,69.40003],[-98.917401,69.71003],[-98.218261,70.14354],[-97.157401,69.86003],[-96.557401,69.68003],[-96.257401,69.49003],[-95.647681,69.10769]]],[[[-90.5471,69.49766],[-90.55151,68.47499],[-89.21515,69.25873],[-88.01966,68.61508],[-88.31749,67.87338],[-87.35017,67.19872],[-86.30607,67.92146],[-85.57664,68.78456],[-85.52197,69.88211],[-84.10081,69.80539],[-82.62258,69.65826],[-81.28043,69.16202],[-81.2202,68.66567],[-81.96436,68.13253],[-81.25928,67.59716],[-81.38653,67.11078],[-83.34456,66.41154],[-84.73542,66.2573],[-85.76943,66.55833],[-86.0676,66.05625],[-87.03143,65.21297],[-87.32324,64.77563],[-88.48296,64.09897],[-89.91444,64.03273],[-90.70398,63.61017],[-90.77004,62.96021],[-91.93342,62.83508],[-93.15698,62.02469],[-94.24153,60.89865],[-94.62931,60.11021],[-94.6846,58.94882],[-93.21502,58.78212],[-92.76462,57.84571],[-92.29703,57.08709],[-90.89769,57.28468],[-89.03953,56.85172],[-88.03978,56.47162],[-87.32421,55.99914],[-86.07121,55.72383],[-85.01181,55.3026],[-83.36055,55.24489],[-82.27285,55.14832],[-82.4362,54.28227],[-82.12502,53.27703],[-81.40075,52.15788],[-79.91289,51.20842],[-79.14301,51.53393],[-78.60191,52.56208],[-79.12421,54.14145],[-79.82958,54.66772],[-78.22874,55.13645],[-77.0956,55.83741],[-76.54137,56.53423],[-76.62319,57.20263],[-77.30226,58.05209],[-78.51688,58.80458],[-77.33676,59.85261],[-77.77272,60.75788],[-78.10687,62.31964],[-77.41067,62.55053],[-75.69621,62.2784],[-74.6682,62.18111],[-73.83988,62.4438],[-72.90853,62.10507],[-71.67708,61.52535],[-71.37369,61.13717],[-69.59042,61.06141],[-69.62033,60.22125],[-69.2879,58.95736],[-68.37455,58.80106],[-67.64976,58.21206],[-66.20178,58.76731],[-65.24517,59.87071],[-64.58352,60.33558],[-63.80475,59.4426],[-62.50236,58.16708],[-61.39655,56.96745],[-61.79866,56.33945],[-60.46853,55.77548],[-59.56962,55.20407],[-57.97508,54.94549],[-57.3332,54.6265],[-56.93689,53.78032],[-56.15811,53.64749],[-55.75632,53.27036],[-55.68338,52.14664],[-56.40916,51.7707],[-57.12691,51.41972],[-58.77482,51.0643],[-60.03309,50.24277],[-61.72366,50.08046],[-63.86251,50.29099],[-65.36331,50.2982],[-66.39905,50.22897],[-67.23631,49.51156],[-68.51114,49.06836],[-69.95362,47.74488],[-71.10458,46.82171],[-70.25522,46.98606],[-68.65,48.3],[-66.55243,49.1331],[-65.05626,49.23278],[-64.17099,48.74248],[-65.11545,48.07085],[-64.79854,46.99297],[-64.47219,46.23849],[-63.17329,45.73902],[-61.52072,45.88377],[-60.51815,47.00793],[-60.4486,46.28264],[-59.80287,45.9204],[-61.03988,45.26525],[-63.25471,44.67014],[-64.24656,44.26553],[-65.36406,43.54523],[-66.1234,43.61867],[-66.16173,44.46512],[-64.42549,45.29204],[-66.02605,45.25931],[-67.13741,45.13753],[-67.79134,45.70281],[-67.79046,47.06636],[-68.23444,47.35486],[-68.905,47.185],[-69.237216,47.447781],[-69.99997,46.69307],[-70.305,45.915],[-70.66,45.46],[-71.08482,45.30524],[-71.405,45.255],[-71.50506,45.0082],[-73.34783,45.00738],[-74.867,45.00048],[-75.31821,44.81645],[-76.375,44.09631],[-76.5,44.018459],[-76.820034,43.628784],[-77.737885,43.629056],[-78.72028,43.625089],[-79.171674,43.466339],[-79.01,43.27],[-78.92,42.965],[-78.939362,42.863611],[-80.247448,42.3662],[-81.277747,42.209026],[-82.439278,41.675105],[-82.690089,41.675105],[-83.02981,41.832796],[-83.142,41.975681],[-83.12,42.08],[-82.9,42.43],[-82.43,42.98],[-82.137642,43.571088],[-82.337763,44.44],[-82.550925,45.347517],[-83.592851,45.816894],[-83.469551,45.994686],[-83.616131,46.116927],[-83.890765,46.116927],[-84.091851,46.275419],[-84.14212,46.512226],[-84.3367,46.40877],[-84.6049,46.4396],[-84.543749,46.538684],[-84.779238,46.637102],[-84.87608,46.900083],[-85.652363,47.220219],[-86.461991,47.553338],[-87.439793,47.94],[-88.378114,48.302918],[-89.272917,48.019808],[-89.6,48.01],[-90.83,48.27],[-91.64,48.14],[-92.61,48.45],[-93.63087,48.60926],[-94.32914,48.67074],[-94.64,48.84],[-94.81758,49.38905],[-95.15609,49.38425],[-95.15907,49],[-97.22872,49.0007],[-100.65,49],[-104.04826,48.99986],[-107.05,49],[-110.05,49],[-113,49],[-116.04818,49],[-117.03121,49],[-120,49],[-122.84,49],[-122.97421,49.002538],[-124.91024,49.98456],[-125.62461,50.41656],[-127.43561,50.83061],[-127.99276,51.71583],[-127.85032,52.32961],[-129.12979,52.75538],[-129.30523,53.56159],[-130.51497,54.28757],[-130.53611,54.80278],[-129.98,55.285],[-130.00778,55.91583],[-131.70781,56.55212],[-132.73042,57.69289],[-133.35556,58.41028],[-134.27111,58.86111],[-134.945,59.27056],[-135.47583,59.78778],[-136.47972,59.46389],[-137.4525,58.905],[-138.34089,59.56211],[-139.039,60],[-140.013,60.27682],[-140.99778,60.30639],[-140.9925,66.00003],[-140.986,69.712],[-139.12052,69.47102],[-137.54636,68.99002],[-136.50358,68.89804],[-135.62576,69.31512],[-134.41464,69.62743],[-132.92925,69.50534],[-131.43136,69.94451],[-129.79471,70.19369],[-129.10773,69.77927],[-128.36156,70.01286],[-128.13817,70.48384],[-127.44712,70.37721],[-125.75632,69.48058],[-124.42483,70.1584],[-124.28968,69.39969],[-123.06108,69.56372],[-122.6835,69.85553],[-121.47226,69.79778],[-119.94288,69.37786],[-117.60268,69.01128],[-116.22643,68.84151],[-115.2469,68.90591],[-113.89794,68.3989],[-115.30489,67.90261],[-113.49727,67.68815],[-110.798,67.80612],[-109.94619,67.98104],[-108.8802,67.38144],[-107.79239,67.88736],[-108.81299,68.31164],[-108.16721,68.65392],[-106.95,68.7],[-106.15,68.8],[-105.34282,68.56122],[-104.33791,68.018],[-103.22115,68.09775],[-101.45433,67.64689],[-99.90195,67.80566],[-98.4432,67.78165],[-98.5586,68.40394],[-97.66948,68.57864],[-96.11991,68.23939],[-96.12588,67.29338],[-95.48943,68.0907],[-94.685,68.06383],[-94.23282,69.06903],[-95.30408,69.68571],[-96.47131,70.08976],[-96.39115,71.19482],[-95.2088,71.92053],[-93.88997,71.76015],[-92.87818,71.31869],[-91.51964,70.19129],[-92.40692,69.69997],[-90.5471,69.49766]]],[[[-114.16717,73.12145],[-114.66634,72.65277],[-112.44102,72.9554],[-111.05039,72.4504],[-109.92035,72.96113],[-109.00654,72.63335],[-108.18835,71.65089],[-107.68599,72.06548],[-108.39639,73.08953],[-107.51645,73.23598],[-106.52259,73.07601],[-105.40246,72.67259],[-104.77484,71.6984],[-104.46476,70.99297],[-102.78537,70.49776],[-100.98078,70.02432],[-101.08929,69.58447],[-102.73116,69.50402],[-102.09329,69.11962],[-102.43024,68.75282],[-104.24,68.91],[-105.96,69.18],[-107.12254,69.11922],[-109,68.78],[-111.534149,68.630059],[-113.3132,68.53554],[-113.85496,69.00744],[-115.22,69.28],[-116.10794,69.16821],[-117.34,69.96],[-116.67473,70.06655],[-115.13112,70.2373],[-113.72141,70.19237],[-112.4161,70.36638],[-114.35,70.6],[-116.48684,70.52045],[-117.9048,70.54056],[-118.43238,70.9092],[-116.11311,71.30918],[-117.65568,71.2952],[-119.40199,71.55859],[-118.56267,72.30785],[-117.86642,72.70594],[-115.18909,73.31459],[-114.16717,73.12145]]],[[[-104.5,73.42],[-105.38,72.76],[-106.94,73.46],[-106.6,73.6],[-105.26,73.64],[-104.5,73.42]]],[[[-76.34,73.102685],[-76.251404,72.826385],[-77.314438,72.855545],[-78.39167,72.876656],[-79.486252,72.742203],[-79.775833,72.802902],[-80.876099,73.333183],[-80.833885,73.693184],[-80.353058,73.75972],[-78.064438,73.651932],[-76.34,73.102685]]],[[[-86.562179,73.157447],[-85.774371,72.534126],[-84.850112,73.340278],[-82.31559,73.750951],[-80.600088,72.716544],[-80.748942,72.061907],[-78.770639,72.352173],[-77.824624,72.749617],[-75.605845,72.243678],[-74.228616,71.767144],[-74.099141,71.33084],[-72.242226,71.556925],[-71.200015,70.920013],[-68.786054,70.525024],[-67.91497,70.121948],[-66.969033,69.186087],[-68.805123,68.720198],[-66.449866,68.067163],[-64.862314,67.847539],[-63.424934,66.928473],[-61.851981,66.862121],[-62.163177,66.160251],[-63.918444,64.998669],[-65.14886,65.426033],[-66.721219,66.388041],[-68.015016,66.262726],[-68.141287,65.689789],[-67.089646,65.108455],[-65.73208,64.648406],[-65.320168,64.382737],[-64.669406,63.392927],[-65.013804,62.674185],[-66.275045,62.945099],[-68.783186,63.74567],[-67.369681,62.883966],[-66.328297,62.280075],[-66.165568,61.930897],[-68.877367,62.330149],[-71.023437,62.910708],[-72.235379,63.397836],[-71.886278,63.679989],[-73.378306,64.193963],[-74.834419,64.679076],[-74.818503,64.389093],[-77.70998,64.229542],[-78.555949,64.572906],[-77.897281,65.309192],[-76.018274,65.326969],[-73.959795,65.454765],[-74.293883,65.811771],[-73.944912,66.310578],[-72.651167,67.284576],[-72.92606,67.726926],[-73.311618,68.069437],[-74.843307,68.554627],[-76.869101,68.894736],[-76.228649,69.147769],[-77.28737,69.76954],[-78.168634,69.826488],[-78.957242,70.16688],[-79.492455,69.871808],[-81.305471,69.743185],[-84.944706,69.966634],[-87.060003,70.260001],[-88.681713,70.410741],[-89.51342,70.762038],[-88.467721,71.218186],[-89.888151,71.222552],[-90.20516,72.235074],[-89.436577,73.129464],[-88.408242,73.537889],[-85.826151,73.803816],[-86.562179,73.157447]]],[[[-100.35642,73.84389],[-99.16387,73.63339],[-97.38,73.76],[-97.12,73.47],[-98.05359,72.99052],[-96.54,72.56],[-96.72,71.66],[-98.35966,71.27285],[-99.32286,71.35639],[-100.01482,71.73827],[-102.5,72.51],[-102.48,72.83],[-100.43836,72.70588],[-101.54,73.36],[-100.35642,73.84389]]],[[[-93.196296,72.771992],[-94.269047,72.024596],[-95.409856,72.061881],[-96.033745,72.940277],[-96.018268,73.43743],[-95.495793,73.862417],[-94.503658,74.134907],[-92.420012,74.100025],[-90.509793,73.856732],[-92.003965,72.966244],[-93.196296,72.771992]]],[[[-120.46,71.383602],[-123.09219,70.90164],[-123.62,71.34],[-125.928949,71.868688],[-125.5,72.292261],[-124.80729,73.02256],[-123.94,73.68],[-124.91775,74.29275],[-121.53788,74.44893],[-120.10978,74.24135],[-117.55564,74.18577],[-116.58442,73.89607],[-115.51081,73.47519],[-116.76794,73.22292],[-119.22,72.52],[-120.46,71.82],[-120.46,71.383602]]],[[[-93.612756,74.979997],[-94.156909,74.592347],[-95.608681,74.666864],[-96.820932,74.927623],[-96.288587,75.377828],[-94.85082,75.647218],[-93.977747,75.29649],[-93.612756,74.979997]]],[[[-98.5,76.72],[-97.735585,76.25656],[-97.704415,75.74344],[-98.16,75],[-99.80874,74.89744],[-100.88366,75.05736],[-100.86292,75.64075],[-102.50209,75.5638],[-102.56552,76.3366],[-101.48973,76.30537],[-99.98349,76.64634],[-98.57699,76.58859],[-98.5,76.72]]],[[[-108.21141,76.20168],[-107.81943,75.84552],[-106.92893,76.01282],[-105.881,75.9694],[-105.70498,75.47951],[-106.31347,75.00527],[-109.7,74.85],[-112.22307,74.41696],[-113.74381,74.39427],[-113.87135,74.72029],[-111.79421,75.1625],[-116.31221,75.04343],[-117.7104,75.2222],[-116.34602,76.19903],[-115.40487,76.47887],[-112.59056,76.14134],[-110.81422,75.54919],[-109.0671,75.47321],[-110.49726,76.42982],[-109.5811,76.79417],[-108.54859,76.67832],[-108.21141,76.20168]]],[[[-94.684086,77.097878],[-93.573921,76.776296],[-91.605023,76.778518],[-90.741846,76.449597],[-90.969661,76.074013],[-89.822238,75.847774],[-89.187083,75.610166],[-87.838276,75.566189],[-86.379192,75.482421],[-84.789625,75.699204],[-82.753445,75.784315],[-81.128531,75.713983],[-80.057511,75.336849],[-79.833933,74.923127],[-80.457771,74.657304],[-81.948843,74.442459],[-83.228894,74.564028],[-86.097452,74.410032],[-88.15035,74.392307],[-89.764722,74.515555],[-92.422441,74.837758],[-92.768285,75.38682],[-92.889906,75.882655],[-93.893824,76.319244],[-95.962457,76.441381],[-97.121379,76.751078],[-96.745123,77.161389],[-94.684086,77.097878]]],[[[-116.198587,77.645287],[-116.335813,76.876962],[-117.106051,76.530032],[-118.040412,76.481172],[-119.899318,76.053213],[-121.499995,75.900019],[-122.854924,76.116543],[-122.854925,76.116543],[-121.157535,76.864508],[-119.103939,77.51222],[-117.570131,77.498319],[-116.198587,77.645287]]],[[[-93.840003,77.519997],[-94.295608,77.491343],[-96.169654,77.555111],[-96.436304,77.834629],[-94.422577,77.820005],[-93.720656,77.634331],[-93.840003,77.519997]]],[[[-110.186938,77.697015],[-112.051191,77.409229],[-113.534279,77.732207],[-112.724587,78.05105],[-111.264443,78.152956],[-109.854452,77.996325],[-110.186938,77.697015]]],[[[-109.663146,78.601973],[-110.881314,78.40692],[-112.542091,78.407902],[-112.525891,78.550555],[-111.50001,78.849994],[-110.963661,78.804441],[-109.663146,78.601973]]],[[[-95.830295,78.056941],[-97.309843,77.850597],[-98.124289,78.082857],[-98.552868,78.458105],[-98.631984,78.87193],[-97.337231,78.831984],[-96.754399,78.765813],[-95.559278,78.418315],[-95.830295,78.056941]]],[[[-100.060192,78.324754],[-99.670939,77.907545],[-101.30394,78.018985],[-102.949809,78.343229],[-105.176133,78.380332],[-104.210429,78.67742],[-105.41958,78.918336],[-105.492289,79.301594],[-103.529282,79.165349],[-100.825158,78.800462],[-100.060192,78.324754]]],[[[-87.02,79.66],[-85.81435,79.3369],[-87.18756,79.0393],[-89.03535,78.28723],[-90.80436,78.21533],[-92.87669,78.34333],[-93.95116,78.75099],[-93.93574,79.11373],[-93.14524,79.3801],[-94.974,79.37248],[-96.07614,79.70502],[-96.70972,80.15777],[-96.01644,80.60233],[-95.32345,80.90729],[-94.29843,80.97727],[-94.73542,81.20646],[-92.40984,81.25739],[-91.13289,80.72345],[-89.45,80.509322],[-87.81,80.32],[-87.02,79.66]]],[[[-68.5,83.106322],[-65.82735,83.02801],[-63.68,82.9],[-61.85,82.6286],[-61.89388,82.36165],[-64.334,81.92775],[-66.75342,81.72527],[-67.65755,81.50141],[-65.48031,81.50657],[-67.84,80.9],[-69.4697,80.61683],[-71.18,79.8],[-73.2428,79.63415],[-73.88,79.430162],[-76.90773,79.32309],[-75.52924,79.19766],[-76.22046,79.01907],[-75.39345,78.52581],[-76.34354,78.18296],[-77.88851,77.89991],[-78.36269,77.50859],[-79.75951,77.20968],[-79.61965,76.98336],[-77.91089,77.022045],[-77.88911,76.777955],[-80.56125,76.17812],[-83.17439,76.45403],[-86.11184,76.29901],[-87.6,76.42],[-89.49068,76.47239],[-89.6161,76.95213],[-87.76739,77.17833],[-88.26,77.9],[-87.65,77.970222],[-84.97634,77.53873],[-86.34,78.18],[-87.96192,78.37181],[-87.15198,78.75867],[-85.37868,78.9969],[-85.09495,79.34543],[-86.50734,79.73624],[-86.93179,80.25145],[-84.19844,80.20836],[-83.408696,80.1],[-81.84823,80.46442],[-84.1,80.58],[-87.59895,80.51627],[-89.36663,80.85569],[-90.2,81.26],[-91.36786,81.5531],[-91.58702,81.89429],[-90.1,82.085],[-88.93227,82.11751],[-86.97024,82.27961],[-85.5,82.652273],[-84.260005,82.6],[-83.18,82.32],[-82.42,82.86],[-81.1,83.02],[-79.30664,83.13056],[-76.25,83.172059],[-75.71878,83.06404],[-72.83153,83.23324],[-70.665765,83.169781],[-68.5,83.106322]]]]}},\n{\"type\":\"Feature\",\"id\":\"CHE\",\"properties\":{\"name\":\"Switzerland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[9.594226,47.525058],[9.632932,47.347601],[9.47997,47.10281],[9.932448,46.920728],[10.442701,46.893546],[10.363378,46.483571],[9.922837,46.314899],[9.182882,46.440215],[8.966306,46.036932],[8.489952,46.005151],[8.31663,46.163642],[7.755992,45.82449],[7.273851,45.776948],[6.843593,45.991147],[6.5001,46.429673],[6.022609,46.27299],[6.037389,46.725779],[6.768714,47.287708],[6.736571,47.541801],[7.192202,47.449766],[7.466759,47.620582],[8.317301,47.61358],[8.522612,47.830828],[9.594226,47.525058]]]}},\n{\"type\":\"Feature\",\"id\":\"CHL\",\"properties\":{\"name\":\"Chile\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-68.63401,-52.63637],[-68.63335,-54.8695],[-67.56244,-54.87001],[-66.95992,-54.89681],[-67.29103,-55.30124],[-68.14863,-55.61183],[-68.639991,-55.580018],[-69.2321,-55.49906],[-69.95809,-55.19843],[-71.00568,-55.05383],[-72.2639,-54.49514],[-73.2852,-53.95752],[-74.66253,-52.83749],[-73.8381,-53.04743],[-72.43418,-53.7154],[-71.10773,-54.07433],[-70.59178,-53.61583],[-70.26748,-52.93123],[-69.34565,-52.5183],[-68.63401,-52.63637]]],[[[-68.219913,-21.494347],[-67.82818,-22.872919],[-67.106674,-22.735925],[-66.985234,-22.986349],[-67.328443,-24.025303],[-68.417653,-24.518555],[-68.386001,-26.185016],[-68.5948,-26.506909],[-68.295542,-26.89934],[-69.001235,-27.521214],[-69.65613,-28.459141],[-70.01355,-29.367923],[-69.919008,-30.336339],[-70.535069,-31.36501],[-70.074399,-33.09121],[-69.814777,-33.273886],[-69.817309,-34.193571],[-70.388049,-35.169688],[-70.364769,-36.005089],[-71.121881,-36.658124],[-71.118625,-37.576827],[-70.814664,-38.552995],[-71.413517,-38.916022],[-71.680761,-39.808164],[-71.915734,-40.832339],[-71.746804,-42.051386],[-72.148898,-42.254888],[-71.915424,-43.408565],[-71.464056,-43.787611],[-71.793623,-44.207172],[-71.329801,-44.407522],[-71.222779,-44.784243],[-71.659316,-44.973689],[-71.552009,-45.560733],[-71.917258,-46.884838],[-72.447355,-47.738533],[-72.331161,-48.244238],[-72.648247,-48.878618],[-73.415436,-49.318436],[-73.328051,-50.378785],[-72.975747,-50.74145],[-72.309974,-50.67701],[-72.329404,-51.425956],[-71.914804,-52.009022],[-69.498362,-52.142761],[-68.571545,-52.299444],[-69.461284,-52.291951],[-69.94278,-52.537931],[-70.845102,-52.899201],[-71.006332,-53.833252],[-71.429795,-53.856455],[-72.557943,-53.53141],[-73.702757,-52.835069],[-73.702757,-52.83507],[-74.946763,-52.262754],[-75.260026,-51.629355],[-74.976632,-51.043396],[-75.479754,-50.378372],[-75.608015,-48.673773],[-75.18277,-47.711919],[-74.126581,-46.939253],[-75.644395,-46.647643],[-74.692154,-45.763976],[-74.351709,-44.103044],[-73.240356,-44.454961],[-72.717804,-42.383356],[-73.3889,-42.117532],[-73.701336,-43.365776],[-74.331943,-43.224958],[-74.017957,-41.794813],[-73.677099,-39.942213],[-73.217593,-39.258689],[-73.505559,-38.282883],[-73.588061,-37.156285],[-73.166717,-37.12378],[-72.553137,-35.50884],[-71.861732,-33.909093],[-71.43845,-32.418899],[-71.668721,-30.920645],[-71.370083,-30.095682],[-71.489894,-28.861442],[-70.905124,-27.64038],[-70.724954,-25.705924],[-70.403966,-23.628997],[-70.091246,-21.393319],[-70.16442,-19.756468],[-70.372572,-18.347975],[-69.858444,-18.092694],[-69.590424,-17.580012],[-69.100247,-18.260125],[-68.966818,-18.981683],[-68.442225,-19.405068],[-68.757167,-20.372658],[-68.219913,-21.494347]]]]}},\n{\"type\":\"Feature\",\"id\":\"CHN\",\"properties\":{\"name\":\"China\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[110.339188,18.678395],[109.47521,18.197701],[108.655208,18.507682],[108.626217,19.367888],[109.119056,19.821039],[110.211599,20.101254],[110.786551,20.077534],[111.010051,19.69593],[110.570647,19.255879],[110.339188,18.678395]]],[[[127.657407,49.76027],[129.397818,49.4406],[130.582293,48.729687],[130.987282,47.790132],[132.506672,47.78897],[133.373596,48.183442],[135.026311,48.47823],[134.500814,47.57844],[134.112362,47.212467],[133.769644,46.116927],[133.097127,45.144066],[131.883454,45.321162],[131.025212,44.967953],[131.288555,44.11152],[131.144688,42.92999],[130.633866,42.903015],[130.640016,42.395009],[129.994267,42.985387],[129.596669,42.424982],[128.052215,41.994285],[128.208433,41.466772],[127.343783,41.503152],[126.869083,41.816569],[126.182045,41.107336],[125.079942,40.569824],[124.265625,39.928493],[122.86757,39.637788],[122.131388,39.170452],[121.054554,38.897471],[121.585995,39.360854],[121.376757,39.750261],[122.168595,40.422443],[121.640359,40.94639],[120.768629,40.593388],[119.639602,39.898056],[119.023464,39.252333],[118.042749,39.204274],[117.532702,38.737636],[118.059699,38.061476],[118.87815,37.897325],[118.911636,37.448464],[119.702802,37.156389],[120.823457,37.870428],[121.711259,37.481123],[122.357937,37.454484],[122.519995,36.930614],[121.104164,36.651329],[120.637009,36.11144],[119.664562,35.609791],[119.151208,34.909859],[120.227525,34.360332],[120.620369,33.376723],[121.229014,32.460319],[121.908146,31.692174],[121.891919,30.949352],[121.264257,30.676267],[121.503519,30.142915],[122.092114,29.83252],[121.938428,29.018022],[121.684439,28.225513],[121.125661,28.135673],[120.395473,27.053207],[119.585497,25.740781],[118.656871,24.547391],[117.281606,23.624501],[115.890735,22.782873],[114.763827,22.668074],[114.152547,22.22376],[113.80678,22.54834],[113.241078,22.051367],[111.843592,21.550494],[110.785466,21.397144],[110.444039,20.341033],[109.889861,20.282457],[109.627655,21.008227],[109.864488,21.395051],[108.522813,21.715212],[108.05018,21.55238],[107.04342,21.811899],[106.567273,22.218205],[106.725403,22.794268],[105.811247,22.976892],[105.329209,23.352063],[104.476858,22.81915],[103.504515,22.703757],[102.706992,22.708795],[102.170436,22.464753],[101.652018,22.318199],[101.80312,21.174367],[101.270026,21.201652],[101.180005,21.436573],[101.150033,21.849984],[100.416538,21.558839],[99.983489,21.742937],[99.240899,22.118314],[99.531992,22.949039],[98.898749,23.142722],[98.660262,24.063286],[97.60472,23.897405],[97.724609,25.083637],[98.671838,25.918703],[98.712094,26.743536],[98.68269,27.508812],[98.246231,27.747221],[97.911988,28.335945],[97.327114,28.261583],[96.248833,28.411031],[96.586591,28.83098],[96.117679,29.452802],[95.404802,29.031717],[94.56599,29.277438],[93.413348,28.640629],[92.503119,27.896876],[91.696657,27.771742],[91.258854,28.040614],[90.730514,28.064954],[90.015829,28.296439],[89.47581,28.042759],[88.814248,27.299316],[88.730326,28.086865],[88.120441,27.876542],[86.954517,27.974262],[85.82332,28.203576],[85.011638,28.642774],[84.23458,28.839894],[83.898993,29.320226],[83.337115,29.463732],[82.327513,30.115268],[81.525804,30.422717],[81.111256,30.183481],[79.721367,30.882715],[78.738894,31.515906],[78.458446,32.618164],[79.176129,32.48378],[79.208892,32.994395],[78.811086,33.506198],[78.912269,34.321936],[77.837451,35.49401],[76.192848,35.898403],[75.896897,36.666806],[75.158028,37.133031],[74.980002,37.41999],[74.829986,37.990007],[74.864816,38.378846],[74.257514,38.606507],[73.928852,38.505815],[73.675379,39.431237],[73.960013,39.660008],[73.822244,39.893973],[74.776862,40.366425],[75.467828,40.562072],[76.526368,40.427946],[76.904484,41.066486],[78.187197,41.185316],[78.543661,41.582243],[80.11943,42.123941],[80.25999,42.349999],[80.18015,42.920068],[80.866206,43.180362],[79.966106,44.917517],[81.947071,45.317027],[82.458926,45.53965],[83.180484,47.330031],[85.16429,47.000956],[85.720484,47.452969],[85.768233,48.455751],[86.598776,48.549182],[87.35997,49.214981],[87.751264,49.297198],[88.013832,48.599463],[88.854298,48.069082],[90.280826,47.693549],[90.970809,46.888146],[90.585768,45.719716],[90.94554,45.286073],[92.133891,45.115076],[93.480734,44.975472],[94.688929,44.352332],[95.306875,44.241331],[95.762455,43.319449],[96.349396,42.725635],[97.451757,42.74889],[99.515817,42.524691],[100.845866,42.663804],[101.83304,42.514873],[103.312278,41.907468],[104.522282,41.908347],[104.964994,41.59741],[106.129316,42.134328],[107.744773,42.481516],[109.243596,42.519446],[110.412103,42.871234],[111.129682,43.406834],[111.829588,43.743118],[111.667737,44.073176],[111.348377,44.457442],[111.873306,45.102079],[112.436062,45.011646],[113.463907,44.808893],[114.460332,45.339817],[115.985096,45.727235],[116.717868,46.388202],[117.421701,46.672733],[118.874326,46.805412],[119.66327,46.69268],[119.772824,47.048059],[118.866574,47.74706],[118.064143,48.06673],[117.295507,47.697709],[116.308953,47.85341],[115.742837,47.726545],[115.485282,48.135383],[116.191802,49.134598],[116.678801,49.888531],[117.879244,49.510983],[119.288461,50.142883],[119.279366,50.582908],[120.18205,51.643566],[120.738191,51.964115],[120.725789,52.516226],[120.177089,52.753886],[121.003085,53.251401],[122.245748,53.431726],[123.571507,53.458804],[125.068211,53.161045],[125.946349,52.792799],[126.564399,51.784255],[126.939157,51.353894],[127.287456,50.739797],[127.657407,49.76027]]]]}},\n{\"type\":\"Feature\",\"id\":\"CIV\",\"properties\":{\"name\":\"Ivory Coast\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-2.856125,4.994476],[-3.311084,4.984296],[-4.00882,5.179813],[-4.649917,5.168264],[-5.834496,4.993701],[-6.528769,4.705088],[-7.518941,4.338288],[-7.712159,4.364566],[-7.635368,5.188159],[-7.539715,5.313345],[-7.570153,5.707352],[-7.993693,6.12619],[-8.311348,6.193033],[-8.60288,6.467564],[-8.385452,6.911801],[-8.485446,7.395208],[-8.439298,7.686043],[-8.280703,7.68718],[-8.221792,8.123329],[-8.299049,8.316444],[-8.203499,8.455453],[-7.8321,8.575704],[-8.079114,9.376224],[-8.309616,9.789532],[-8.229337,10.12902],[-8.029944,10.206535],[-7.89959,10.297382],[-7.622759,10.147236],[-6.850507,10.138994],[-6.666461,10.430811],[-6.493965,10.411303],[-6.205223,10.524061],[-6.050452,10.096361],[-5.816926,10.222555],[-5.404342,10.370737],[-4.954653,10.152714],[-4.779884,9.821985],[-4.330247,9.610835],[-3.980449,9.862344],[-3.511899,9.900326],[-2.827496,9.642461],[-2.56219,8.219628],[-2.983585,7.379705],[-3.24437,6.250472],[-2.810701,5.389051],[-2.856125,4.994476]]]}},\n{\"type\":\"Feature\",\"id\":\"CMR\",\"properties\":{\"name\":\"Cameroon\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[13.075822,2.267097],[12.951334,2.321616],[12.35938,2.192812],[11.751665,2.326758],[11.276449,2.261051],[9.649158,2.283866],[9.795196,3.073404],[9.404367,3.734527],[8.948116,3.904129],[8.744924,4.352215],[8.488816,4.495617],[8.500288,4.771983],[8.757533,5.479666],[9.233163,6.444491],[9.522706,6.453482],[10.118277,7.03877],[10.497375,7.055358],[11.058788,6.644427],[11.745774,6.981383],[11.839309,7.397042],[12.063946,7.799808],[12.218872,8.305824],[12.753672,8.717763],[12.955468,9.417772],[13.1676,9.640626],[13.308676,10.160362],[13.57295,10.798566],[14.415379,11.572369],[14.468192,11.904752],[14.577178,12.085361],[14.181336,12.483657],[14.213531,12.802035],[14.495787,12.859396],[14.893386,12.219048],[14.960152,11.555574],[14.923565,10.891325],[15.467873,9.982337],[14.909354,9.992129],[14.627201,9.920919],[14.171466,10.021378],[13.954218,9.549495],[14.544467,8.965861],[14.979996,8.796104],[15.120866,8.38215],[15.436092,7.692812],[15.27946,7.421925],[14.776545,6.408498],[14.53656,6.226959],[14.459407,5.451761],[14.558936,5.030598],[14.478372,4.732605],[14.950953,4.210389],[15.03622,3.851367],[15.405396,3.335301],[15.862732,3.013537],[15.907381,2.557389],[16.012852,2.26764],[15.940919,1.727673],[15.146342,1.964015],[14.337813,2.227875],[13.075822,2.267097]]]}},\n{\"type\":\"Feature\",\"id\":\"COD\",\"properties\":{\"name\":\"Democratic Republic of the Congo\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[30.83386,3.509166],[30.773347,2.339883],[31.174149,2.204465],[30.85267,1.849396],[30.468508,1.583805],[30.086154,1.062313],[29.875779,0.59738],[29.819503,-0.20531],[29.587838,-0.587406],[29.579466,-1.341313],[29.291887,-1.620056],[29.254835,-2.21511],[29.117479,-2.292211],[29.024926,-2.839258],[29.276384,-3.293907],[29.339998,-4.499983],[29.519987,-5.419979],[29.419993,-5.939999],[29.620032,-6.520015],[30.199997,-7.079981],[30.740015,-8.340007],[30.346086,-8.238257],[29.002912,-8.407032],[28.734867,-8.526559],[28.449871,-9.164918],[28.673682,-9.605925],[28.49607,-10.789884],[28.372253,-11.793647],[28.642417,-11.971569],[29.341548,-12.360744],[29.616001,-12.178895],[29.699614,-13.257227],[28.934286,-13.248958],[28.523562,-12.698604],[28.155109,-12.272481],[27.388799,-12.132747],[27.16442,-11.608748],[26.553088,-11.92444],[25.75231,-11.784965],[25.418118,-11.330936],[24.78317,-11.238694],[24.314516,-11.262826],[24.257155,-10.951993],[23.912215,-10.926826],[23.456791,-10.867863],[22.837345,-11.017622],[22.402798,-10.993075],[22.155268,-11.084801],[22.208753,-9.894796],[21.875182,-9.523708],[21.801801,-8.908707],[21.949131,-8.305901],[21.746456,-7.920085],[21.728111,-7.290872],[20.514748,-7.299606],[20.601823,-6.939318],[20.091622,-6.94309],[20.037723,-7.116361],[19.417502,-7.155429],[19.166613,-7.738184],[19.016752,-7.988246],[18.464176,-7.847014],[18.134222,-7.987678],[17.47297,-8.068551],[17.089996,-7.545689],[16.860191,-7.222298],[16.57318,-6.622645],[16.326528,-5.87747],[13.375597,-5.864241],[13.024869,-5.984389],[12.735171,-5.965682],[12.322432,-6.100092],[12.182337,-5.789931],[12.436688,-5.684304],[12.468004,-5.248362],[12.631612,-4.991271],[12.995517,-4.781103],[13.25824,-4.882957],[13.600235,-4.500138],[14.144956,-4.510009],[14.209035,-4.793092],[14.582604,-4.970239],[15.170992,-4.343507],[15.75354,-3.855165],[16.00629,-3.535133],[15.972803,-2.712392],[16.407092,-1.740927],[16.865307,-1.225816],[17.523716,-0.74383],[17.638645,-0.424832],[17.663553,-0.058084],[17.82654,0.288923],[17.774192,0.855659],[17.898835,1.741832],[18.094276,2.365722],[18.393792,2.900443],[18.453065,3.504386],[18.542982,4.201785],[18.932312,4.709506],[19.467784,5.031528],[20.290679,4.691678],[20.927591,4.322786],[21.659123,4.224342],[22.405124,4.02916],[22.704124,4.633051],[22.84148,4.710126],[23.297214,4.609693],[24.410531,5.108784],[24.805029,4.897247],[25.128833,4.927245],[25.278798,5.170408],[25.650455,5.256088],[26.402761,5.150875],[27.044065,5.127853],[27.374226,5.233944],[27.979977,4.408413],[28.428994,4.287155],[28.696678,4.455077],[29.159078,4.389267],[29.715995,4.600805],[29.9535,4.173699],[30.83386,3.509166]]]}},\n{\"type\":\"Feature\",\"id\":\"COG\",\"properties\":{\"name\":\"Republic of the Congo\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[12.995517,-4.781103],[12.62076,-4.438023],[12.318608,-4.60623],[11.914963,-5.037987],[11.093773,-3.978827],[11.855122,-3.426871],[11.478039,-2.765619],[11.820964,-2.514161],[12.495703,-2.391688],[12.575284,-1.948511],[13.109619,-2.42874],[13.992407,-2.470805],[14.29921,-1.998276],[14.425456,-1.333407],[14.316418,-0.552627],[13.843321,0.038758],[14.276266,1.19693],[14.026669,1.395677],[13.282631,1.314184],[13.003114,1.830896],[13.075822,2.267097],[14.337813,2.227875],[15.146342,1.964015],[15.940919,1.727673],[16.012852,2.26764],[16.537058,3.198255],[17.133042,3.728197],[17.8099,3.560196],[18.453065,3.504386],[18.393792,2.900443],[18.094276,2.365722],[17.898835,1.741832],[17.774192,0.855659],[17.82654,0.288923],[17.663553,-0.058084],[17.638645,-0.424832],[17.523716,-0.74383],[16.865307,-1.225816],[16.407092,-1.740927],[15.972803,-2.712392],[16.00629,-3.535133],[15.75354,-3.855165],[15.170992,-4.343507],[14.582604,-4.970239],[14.209035,-4.793092],[14.144956,-4.510009],[13.600235,-4.500138],[13.25824,-4.882957],[12.995517,-4.781103]]]}},\n{\"type\":\"Feature\",\"id\":\"COL\",\"properties\":{\"name\":\"Colombia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-75.373223,-0.152032],[-75.801466,0.084801],[-76.292314,0.416047],[-76.57638,0.256936],[-77.424984,0.395687],[-77.668613,0.825893],[-77.855061,0.809925],[-78.855259,1.380924],[-78.990935,1.69137],[-78.617831,1.766404],[-78.662118,2.267355],[-78.42761,2.629556],[-77.931543,2.696606],[-77.510431,3.325017],[-77.12769,3.849636],[-77.496272,4.087606],[-77.307601,4.667984],[-77.533221,5.582812],[-77.318815,5.845354],[-77.476661,6.691116],[-77.881571,7.223771],[-77.753414,7.70984],[-77.431108,7.638061],[-77.242566,7.935278],[-77.474723,8.524286],[-77.353361,8.670505],[-76.836674,8.638749],[-76.086384,9.336821],[-75.6746,9.443248],[-75.664704,9.774003],[-75.480426,10.61899],[-74.906895,11.083045],[-74.276753,11.102036],[-74.197223,11.310473],[-73.414764,11.227015],[-72.627835,11.731972],[-72.238195,11.95555],[-71.75409,12.437303],[-71.399822,12.376041],[-71.137461,12.112982],[-71.331584,11.776284],[-71.973922,11.608672],[-72.227575,11.108702],[-72.614658,10.821975],[-72.905286,10.450344],[-73.027604,9.73677],[-73.304952,9.152],[-72.78873,9.085027],[-72.660495,8.625288],[-72.439862,8.405275],[-72.360901,8.002638],[-72.479679,7.632506],[-72.444487,7.423785],[-72.198352,7.340431],[-71.960176,6.991615],[-70.674234,7.087785],[-70.093313,6.960376],[-69.38948,6.099861],[-68.985319,6.206805],[-68.265052,6.153268],[-67.695087,6.267318],[-67.34144,6.095468],[-67.521532,5.55687],[-67.744697,5.221129],[-67.823012,4.503937],[-67.621836,3.839482],[-67.337564,3.542342],[-67.303173,3.318454],[-67.809938,2.820655],[-67.447092,2.600281],[-67.181294,2.250638],[-66.876326,1.253361],[-67.065048,1.130112],[-67.259998,1.719999],[-67.53781,2.037163],[-67.868565,1.692455],[-69.816973,1.714805],[-69.804597,1.089081],[-69.218638,0.985677],[-69.252434,0.602651],[-69.452396,0.706159],[-70.015566,0.541414],[-70.020656,-0.185156],[-69.577065,-0.549992],[-69.420486,-1.122619],[-69.444102,-1.556287],[-69.893635,-4.298187],[-70.394044,-3.766591],[-70.692682,-3.742872],[-70.047709,-2.725156],[-70.813476,-2.256865],[-71.413646,-2.342802],[-71.774761,-2.16979],[-72.325787,-2.434218],[-73.070392,-2.308954],[-73.659504,-1.260491],[-74.122395,-1.002833],[-74.441601,-0.53082],[-75.106625,-0.057205],[-75.373223,-0.152032]]]}},\n{\"type\":\"Feature\",\"id\":\"CRI\",\"properties\":{\"name\":\"Costa Rica\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-82.965783,8.225028],[-83.508437,8.446927],[-83.711474,8.656836],[-83.596313,8.830443],[-83.632642,9.051386],[-83.909886,9.290803],[-84.303402,9.487354],[-84.647644,9.615537],[-84.713351,9.908052],[-84.97566,10.086723],[-84.911375,9.795992],[-85.110923,9.55704],[-85.339488,9.834542],[-85.660787,9.933347],[-85.797445,10.134886],[-85.791709,10.439337],[-85.659314,10.754331],[-85.941725,10.895278],[-85.71254,11.088445],[-85.561852,11.217119],[-84.903003,10.952303],[-84.673069,11.082657],[-84.355931,10.999226],[-84.190179,10.79345],[-83.895054,10.726839],[-83.655612,10.938764],[-83.40232,10.395438],[-83.015677,9.992982],[-82.546196,9.566135],[-82.932891,9.476812],[-82.927155,9.07433],[-82.719183,8.925709],[-82.868657,8.807266],[-82.829771,8.626295],[-82.913176,8.423517],[-82.965783,8.225028]]]}},\n{\"type\":\"Feature\",\"id\":\"CUB\",\"properties\":{\"name\":\"Cuba\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-82.268151,23.188611],[-81.404457,23.117271],[-80.618769,23.10598],[-79.679524,22.765303],[-79.281486,22.399202],[-78.347434,22.512166],[-77.993296,22.277194],[-77.146422,21.657851],[-76.523825,21.20682],[-76.19462,21.220565],[-75.598222,21.016624],[-75.67106,20.735091],[-74.933896,20.693905],[-74.178025,20.284628],[-74.296648,20.050379],[-74.961595,19.923435],[-75.63468,19.873774],[-76.323656,19.952891],[-77.755481,19.855481],[-77.085108,20.413354],[-77.492655,20.673105],[-78.137292,20.739949],[-78.482827,21.028613],[-78.719867,21.598114],[-79.285,21.559175],[-80.217475,21.827324],[-80.517535,22.037079],[-81.820943,22.192057],[-82.169992,22.387109],[-81.795002,22.636965],[-82.775898,22.68815],[-83.494459,22.168518],[-83.9088,22.154565],[-84.052151,21.910575],[-84.54703,21.801228],[-84.974911,21.896028],[-84.447062,22.20495],[-84.230357,22.565755],[-83.77824,22.788118],[-83.267548,22.983042],[-82.510436,23.078747],[-82.268151,23.188611]]]}},\n{\"type\":\"Feature\",\"id\":\"-99\",\"properties\":{\"name\":\"Northern Cyprus\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[32.73178,35.140026],[32.802474,35.145504],[32.946961,35.386703],[33.667227,35.373216],[34.576474,35.671596],[33.900804,35.245756],[33.973617,35.058506],[33.86644,35.093595],[33.675392,35.017863],[33.525685,35.038688],[33.475817,35.000345],[33.455922,35.101424],[33.383833,35.162712],[33.190977,35.173125],[32.919572,35.087833],[32.73178,35.140026]]]}},\n{\"type\":\"Feature\",\"id\":\"CYP\",\"properties\":{\"name\":\"Cyprus\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[33.973617,35.058506],[34.004881,34.978098],[32.979827,34.571869],[32.490296,34.701655],[32.256667,35.103232],[32.73178,35.140026],[32.919572,35.087833],[33.190977,35.173125],[33.383833,35.162712],[33.455922,35.101424],[33.475817,35.000345],[33.525685,35.038688],[33.675392,35.017863],[33.86644,35.093595],[33.973617,35.058506]]]}},\n{\"type\":\"Feature\",\"id\":\"CZE\",\"properties\":{\"name\":\"Czech Republic\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[16.960288,48.596982],[16.499283,48.785808],[16.029647,48.733899],[15.253416,49.039074],[14.901447,48.964402],[14.338898,48.555305],[13.595946,48.877172],[13.031329,49.307068],[12.521024,49.547415],[12.415191,49.969121],[12.240111,50.266338],[12.966837,50.484076],[13.338132,50.733234],[14.056228,50.926918],[14.307013,51.117268],[14.570718,51.002339],[15.016996,51.106674],[15.490972,50.78473],[16.238627,50.697733],[16.176253,50.422607],[16.719476,50.215747],[16.868769,50.473974],[17.554567,50.362146],[17.649445,50.049038],[18.392914,49.988629],[18.853144,49.49623],[18.554971,49.495015],[18.399994,49.315001],[18.170498,49.271515],[18.104973,49.043983],[17.913512,48.996493],[17.886485,48.903475],[17.545007,48.800019],[17.101985,48.816969],[16.960288,48.596982]]]}},\n{\"type\":\"Feature\",\"id\":\"DEU\",\"properties\":{\"name\":\"Germany\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[9.921906,54.983104],[9.93958,54.596642],[10.950112,54.363607],[10.939467,54.008693],[11.956252,54.196486],[12.51844,54.470371],[13.647467,54.075511],[14.119686,53.757029],[14.353315,53.248171],[14.074521,52.981263],[14.4376,52.62485],[14.685026,52.089947],[14.607098,51.745188],[15.016996,51.106674],[14.570718,51.002339],[14.307013,51.117268],[14.056228,50.926918],[13.338132,50.733234],[12.966837,50.484076],[12.240111,50.266338],[12.415191,49.969121],[12.521024,49.547415],[13.031329,49.307068],[13.595946,48.877172],[13.243357,48.416115],[12.884103,48.289146],[13.025851,47.637584],[12.932627,47.467646],[12.62076,47.672388],[12.141357,47.703083],[11.426414,47.523766],[10.544504,47.566399],[10.402084,47.302488],[9.896068,47.580197],[9.594226,47.525058],[8.522612,47.830828],[8.317301,47.61358],[7.466759,47.620582],[7.593676,48.333019],[8.099279,49.017784],[6.65823,49.201958],[6.18632,49.463803],[6.242751,49.902226],[6.043073,50.128052],[6.156658,50.803721],[5.988658,51.851616],[6.589397,51.852029],[6.84287,52.22844],[7.092053,53.144043],[6.90514,53.482162],[7.100425,53.693932],[7.936239,53.748296],[8.121706,53.527792],[8.800734,54.020786],[8.572118,54.395646],[8.526229,54.962744],[9.282049,54.830865],[9.921906,54.983104]]]}},\n{\"type\":\"Feature\",\"id\":\"DJI\",\"properties\":{\"name\":\"Djibouti\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[43.081226,12.699639],[43.317852,12.390148],[43.286381,11.974928],[42.715874,11.735641],[43.145305,11.46204],[42.776852,10.926879],[42.55493,11.10511],[42.31414,11.0342],[41.75557,11.05091],[41.73959,11.35511],[41.66176,11.6312],[42,12.1],[42.35156,12.54223],[42.779642,12.455416],[43.081226,12.699639]]]}},\n{\"type\":\"Feature\",\"id\":\"DNK\",\"properties\":{\"name\":\"Denmark\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[12.690006,55.609991],[12.089991,54.800015],[11.043543,55.364864],[10.903914,55.779955],[12.370904,56.111407],[12.690006,55.609991]]],[[[10.912182,56.458621],[10.667804,56.081383],[10.369993,56.190007],[9.649985,55.469999],[9.921906,54.983104],[9.282049,54.830865],[8.526229,54.962744],[8.120311,55.517723],[8.089977,56.540012],[8.256582,56.809969],[8.543438,57.110003],[9.424469,57.172066],[9.775559,57.447941],[10.580006,57.730017],[10.546106,57.215733],[10.25,56.890016],[10.369993,56.609982],[10.912182,56.458621]]]]}},\n{\"type\":\"Feature\",\"id\":\"DOM\",\"properties\":{\"name\":\"Dominican Republic\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-71.712361,19.714456],[-71.587304,19.884911],[-70.806706,19.880286],[-70.214365,19.622885],[-69.950815,19.648],[-69.76925,19.293267],[-69.222126,19.313214],[-69.254346,19.015196],[-68.809412,18.979074],[-68.317943,18.612198],[-68.689316,18.205142],[-69.164946,18.422648],[-69.623988,18.380713],[-69.952934,18.428307],[-70.133233,18.245915],[-70.517137,18.184291],[-70.669298,18.426886],[-70.99995,18.283329],[-71.40021,17.598564],[-71.657662,17.757573],[-71.708305,18.044997],[-71.687738,18.31666],[-71.945112,18.6169],[-71.701303,18.785417],[-71.624873,19.169838],[-71.712361,19.714456]]]}},\n{\"type\":\"Feature\",\"id\":\"DZA\",\"properties\":{\"name\":\"Algeria\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[11.999506,23.471668],[8.572893,21.565661],[5.677566,19.601207],[4.267419,19.155265],[3.158133,19.057364],[3.146661,19.693579],[2.683588,19.85623],[2.060991,20.142233],[1.823228,20.610809],[-1.550055,22.792666],[-4.923337,24.974574],[-8.6844,27.395744],[-8.665124,27.589479],[-8.66559,27.656426],[-8.674116,28.841289],[-7.059228,29.579228],[-6.060632,29.7317],[-5.242129,30.000443],[-4.859646,30.501188],[-3.690441,30.896952],[-3.647498,31.637294],[-3.06898,31.724498],[-2.616605,32.094346],[-1.307899,32.262889],[-1.124551,32.651522],[-1.388049,32.864015],[-1.733455,33.919713],[-1.792986,34.527919],[-2.169914,35.168396],[-1.208603,35.714849],[-0.127454,35.888662],[0.503877,36.301273],[1.466919,36.605647],[3.161699,36.783905],[4.815758,36.865037],[5.32012,36.716519],[6.26182,37.110655],[7.330385,37.118381],[7.737078,36.885708],[8.420964,36.946427],[8.217824,36.433177],[8.376368,35.479876],[8.140981,34.655146],[7.524482,34.097376],[7.612642,33.344115],[8.430473,32.748337],[8.439103,32.506285],[9.055603,32.102692],[9.48214,30.307556],[9.805634,29.424638],[9.859998,28.95999],[9.683885,28.144174],[9.756128,27.688259],[9.629056,27.140953],[9.716286,26.512206],[9.319411,26.094325],[9.910693,25.365455],[9.948261,24.936954],[10.303847,24.379313],[10.771364,24.562532],[11.560669,24.097909],[11.999506,23.471668]]]}},\n{\"type\":\"Feature\",\"id\":\"ECU\",\"properties\":{\"name\":\"Ecuador\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-80.302561,-3.404856],[-79.770293,-2.657512],[-79.986559,-2.220794],[-80.368784,-2.685159],[-80.967765,-2.246943],[-80.764806,-1.965048],[-80.933659,-1.057455],[-80.58337,-0.906663],[-80.399325,-0.283703],[-80.020898,0.36034],[-80.09061,0.768429],[-79.542762,0.982938],[-78.855259,1.380924],[-77.855061,0.809925],[-77.668613,0.825893],[-77.424984,0.395687],[-76.57638,0.256936],[-76.292314,0.416047],[-75.801466,0.084801],[-75.373223,-0.152032],[-75.233723,-0.911417],[-75.544996,-1.56161],[-76.635394,-2.608678],[-77.837905,-3.003021],[-78.450684,-3.873097],[-78.639897,-4.547784],[-79.205289,-4.959129],[-79.624979,-4.454198],[-80.028908,-4.346091],[-80.442242,-4.425724],[-80.469295,-4.059287],[-80.184015,-3.821162],[-80.302561,-3.404856]]]}},\n{\"type\":\"Feature\",\"id\":\"EGY\",\"properties\":{\"name\":\"Egypt\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[34.9226,29.50133],[34.64174,29.09942],[34.42655,28.34399],[34.15451,27.8233],[33.92136,27.6487],[33.58811,27.97136],[33.13676,28.41765],[32.42323,29.85108],[32.32046,29.76043],[32.73482,28.70523],[33.34876,27.69989],[34.10455,26.14227],[34.47387,25.59856],[34.79507,25.03375],[35.69241,23.92671],[35.49372,23.75237],[35.52598,23.10244],[36.69069,22.20485],[36.86623,22],[32.9,22],[29.02,22],[25,22],[25,25.6825],[25,29.238655],[24.70007,30.04419],[24.95762,30.6616],[24.80287,31.08929],[25.16482,31.56915],[26.49533,31.58568],[27.45762,31.32126],[28.45048,31.02577],[28.91353,30.87005],[29.68342,31.18686],[30.09503,31.4734],[30.97693,31.55586],[31.68796,31.4296],[31.96041,30.9336],[32.19247,31.26034],[32.99392,31.02407],[33.7734,30.96746],[34.26544,31.21936],[34.9226,29.50133]]]}},\n{\"type\":\"Feature\",\"id\":\"ERI\",\"properties\":{\"name\":\"Eritrea\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[42.35156,12.54223],[42.00975,12.86582],[41.59856,13.45209],[41.155194,13.77332],[40.8966,14.11864],[40.026219,14.519579],[39.34061,14.53155],[39.0994,14.74064],[38.51295,14.50547],[37.90607,14.95943],[37.59377,14.2131],[36.42951,14.42211],[36.323189,14.822481],[36.75386,16.291874],[36.85253,16.95655],[37.16747,17.26314],[37.904,17.42754],[38.41009,17.998307],[38.990623,16.840626],[39.26611,15.922723],[39.814294,15.435647],[41.179275,14.49108],[41.734952,13.921037],[42.276831,13.343992],[42.589576,13.000421],[43.081226,12.699639],[42.779642,12.455416],[42.35156,12.54223]]]}},\n{\"type\":\"Feature\",\"id\":\"ESP\",\"properties\":{\"name\":\"Spain\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-9.034818,41.880571],[-8.984433,42.592775],[-9.392884,43.026625],[-7.97819,43.748338],[-6.754492,43.567909],[-5.411886,43.57424],[-4.347843,43.403449],[-3.517532,43.455901],[-1.901351,43.422802],[-1.502771,43.034014],[0.338047,42.579546],[0.701591,42.795734],[1.826793,42.343385],[2.985999,42.473015],[3.039484,41.89212],[2.091842,41.226089],[0.810525,41.014732],[0.721331,40.678318],[0.106692,40.123934],[-0.278711,39.309978],[0.111291,38.738514],[-0.467124,38.292366],[-0.683389,37.642354],[-1.438382,37.443064],[-2.146453,36.674144],[-3.415781,36.6589],[-4.368901,36.677839],[-4.995219,36.324708],[-5.37716,35.94685],[-5.866432,36.029817],[-6.236694,36.367677],[-6.520191,36.942913],[-7.453726,37.097788],[-7.537105,37.428904],[-7.166508,37.803894],[-7.029281,38.075764],[-7.374092,38.373059],[-7.098037,39.030073],[-7.498632,39.629571],[-7.066592,39.711892],[-7.026413,40.184524],[-6.86402,40.330872],[-6.851127,41.111083],[-6.389088,41.381815],[-6.668606,41.883387],[-7.251309,41.918346],[-7.422513,41.792075],[-8.013175,41.790886],[-8.263857,42.280469],[-8.671946,42.134689],[-9.034818,41.880571]]]}},\n{\"type\":\"Feature\",\"id\":\"EST\",\"properties\":{\"name\":\"Estonia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[24.312863,57.793424],[24.428928,58.383413],[24.061198,58.257375],[23.42656,58.612753],[23.339795,59.18724],[24.604214,59.465854],[25.864189,59.61109],[26.949136,59.445803],[27.981114,59.475388],[28.131699,59.300825],[27.420166,58.724581],[27.716686,57.791899],[27.288185,57.474528],[26.463532,57.476389],[25.60281,57.847529],[25.164594,57.970157],[24.312863,57.793424]]]}},\n{\"type\":\"Feature\",\"id\":\"ETH\",\"properties\":{\"name\":\"Ethiopia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[37.90607,14.95943],[38.51295,14.50547],[39.0994,14.74064],[39.34061,14.53155],[40.02625,14.51959],[40.8966,14.11864],[41.1552,13.77333],[41.59856,13.45209],[42.00975,12.86582],[42.35156,12.54223],[42,12.1],[41.66176,11.6312],[41.73959,11.35511],[41.75557,11.05091],[42.31414,11.0342],[42.55493,11.10511],[42.776852,10.926879],[42.55876,10.57258],[42.92812,10.02194],[43.29699,9.54048],[43.67875,9.18358],[46.94834,7.99688],[47.78942,8.003],[44.9636,5.00162],[43.66087,4.95755],[42.76967,4.25259],[42.12861,4.23413],[41.855083,3.918912],[41.1718,3.91909],[40.76848,4.25702],[39.85494,3.83879],[39.559384,3.42206],[38.89251,3.50074],[38.67114,3.61607],[38.43697,3.58851],[38.120915,3.598605],[36.855093,4.447864],[36.159079,4.447864],[35.817448,4.776966],[35.817448,5.338232],[35.298007,5.506],[34.70702,6.59422],[34.25032,6.82607],[34.0751,7.22595],[33.56829,7.71334],[32.95418,7.78497],[33.2948,8.35458],[33.8255,8.37916],[33.97498,8.68456],[33.96162,9.58358],[34.25745,10.63009],[34.73115,10.91017],[34.83163,11.31896],[35.26049,12.08286],[35.86363,12.57828],[36.27022,13.56333],[36.42951,14.42211],[37.59377,14.2131],[37.90607,14.95943]]]}},\n{\"type\":\"Feature\",\"id\":\"FIN\",\"properties\":{\"name\":\"Finland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[28.59193,69.064777],[28.445944,68.364613],[29.977426,67.698297],[29.054589,66.944286],[30.21765,65.80598],[29.54443,64.948672],[30.444685,64.204453],[30.035872,63.552814],[31.516092,62.867687],[31.139991,62.357693],[30.211107,61.780028],[28.069998,60.503517],[26.255173,60.423961],[24.496624,60.057316],[22.869695,59.846373],[22.290764,60.391921],[21.322244,60.72017],[21.544866,61.705329],[21.059211,62.607393],[21.536029,63.189735],[22.442744,63.81781],[24.730512,64.902344],[25.398068,65.111427],[25.294043,65.534346],[23.903379,66.006927],[23.56588,66.396051],[23.539473,67.936009],[21.978535,68.616846],[20.645593,69.106247],[21.244936,69.370443],[22.356238,68.841741],[23.66205,68.891247],[24.735679,68.649557],[25.689213,69.092114],[26.179622,69.825299],[27.732292,70.164193],[29.015573,69.766491],[28.59193,69.064777]]]}},\n{\"type\":\"Feature\",\"id\":\"FJI\",\"properties\":{\"name\":\"Fiji\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[178.3736,-17.33992],[178.71806,-17.62846],[178.55271,-18.15059],[177.93266,-18.28799],[177.38146,-18.16432],[177.28504,-17.72465],[177.67087,-17.38114],[178.12557,-17.50481],[178.3736,-17.33992]]],[[[179.364143,-16.801354],[178.725059,-17.012042],[178.596839,-16.63915],[179.096609,-16.433984],[179.413509,-16.379054],[180,-16.067133],[180,-16.555217],[179.364143,-16.801354]]],[[[-179.917369,-16.501783],[-180,-16.555217],[-180,-16.067133],[-179.79332,-16.020882],[-179.917369,-16.501783]]]]}},\n{\"type\":\"Feature\",\"id\":\"FLK\",\"properties\":{\"name\":\"Falkland Islands\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-61.2,-51.85],[-60,-51.25],[-59.15,-51.5],[-58.55,-51.1],[-57.75,-51.55],[-58.05,-51.9],[-59.4,-52.2],[-59.85,-51.85],[-60.7,-52.3],[-61.2,-51.85]]]}},\n{\"type\":\"Feature\",\"id\":\"FRA\",\"properties\":{\"name\":\"France\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[9.560016,42.152492],[9.229752,41.380007],[8.775723,41.583612],[8.544213,42.256517],[8.746009,42.628122],[9.390001,43.009985],[9.560016,42.152492]]],[[[3.588184,50.378992],[4.286023,49.907497],[4.799222,49.985373],[5.674052,49.529484],[5.897759,49.442667],[6.18632,49.463803],[6.65823,49.201958],[8.099279,49.017784],[7.593676,48.333019],[7.466759,47.620582],[7.192202,47.449766],[6.736571,47.541801],[6.768714,47.287708],[6.037389,46.725779],[6.022609,46.27299],[6.5001,46.429673],[6.843593,45.991147],[6.802355,45.70858],[7.096652,45.333099],[6.749955,45.028518],[7.007562,44.254767],[7.549596,44.127901],[7.435185,43.693845],[6.529245,43.128892],[4.556963,43.399651],[3.100411,43.075201],[2.985999,42.473015],[1.826793,42.343385],[0.701591,42.795734],[0.338047,42.579546],[-1.502771,43.034014],[-1.901351,43.422802],[-1.384225,44.02261],[-1.193798,46.014918],[-2.225724,47.064363],[-2.963276,47.570327],[-4.491555,47.954954],[-4.59235,48.68416],[-3.295814,48.901692],[-1.616511,48.644421],[-1.933494,49.776342],[-0.989469,49.347376],[1.338761,50.127173],[1.639001,50.946606],[2.513573,51.148506],[2.658422,50.796848],[3.123252,50.780363],[3.588184,50.378992]]]]}},\n{\"type\":\"Feature\",\"id\":\"GAB\",\"properties\":{\"name\":\"Gabon\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[11.093773,-3.978827],[10.066135,-2.969483],[9.405245,-2.144313],[8.797996,-1.111301],[8.830087,-0.779074],[9.04842,-0.459351],[9.291351,0.268666],[9.492889,1.01012],[9.830284,1.067894],[11.285079,1.057662],[11.276449,2.261051],[11.751665,2.326758],[12.35938,2.192812],[12.951334,2.321616],[13.075822,2.267097],[13.003114,1.830896],[13.282631,1.314184],[14.026669,1.395677],[14.276266,1.19693],[13.843321,0.038758],[14.316418,-0.552627],[14.425456,-1.333407],[14.29921,-1.998276],[13.992407,-2.470805],[13.109619,-2.42874],[12.575284,-1.948511],[12.495703,-2.391688],[11.820964,-2.514161],[11.478039,-2.765619],[11.855122,-3.426871],[11.093773,-3.978827]]]}},\n{\"type\":\"Feature\",\"id\":\"GBR\",\"properties\":{\"name\":\"United Kingdom\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-5.661949,54.554603],[-6.197885,53.867565],[-6.95373,54.073702],[-7.572168,54.059956],[-7.366031,54.595841],[-7.572168,55.131622],[-6.733847,55.17286],[-5.661949,54.554603]]],[[[-3.005005,58.635],[-4.073828,57.553025],[-3.055002,57.690019],[-1.959281,57.6848],[-2.219988,56.870017],[-3.119003,55.973793],[-2.085009,55.909998],[-2.005676,55.804903],[-1.114991,54.624986],[-0.430485,54.464376],[0.184981,53.325014],[0.469977,52.929999],[1.681531,52.73952],[1.559988,52.099998],[1.050562,51.806761],[1.449865,51.289428],[0.550334,50.765739],[-0.787517,50.774989],[-2.489998,50.500019],[-2.956274,50.69688],[-3.617448,50.228356],[-4.542508,50.341837],[-5.245023,49.96],[-5.776567,50.159678],[-4.30999,51.210001],[-3.414851,51.426009],[-3.422719,51.426848],[-4.984367,51.593466],[-5.267296,51.9914],[-4.222347,52.301356],[-4.770013,52.840005],[-4.579999,53.495004],[-3.093831,53.404547],[-3.09208,53.404441],[-2.945009,53.985],[-3.614701,54.600937],[-3.630005,54.615013],[-4.844169,54.790971],[-5.082527,55.061601],[-4.719112,55.508473],[-5.047981,55.783986],[-5.586398,55.311146],[-5.644999,56.275015],[-6.149981,56.78501],[-5.786825,57.818848],[-5.009999,58.630013],[-4.211495,58.550845],[-3.005005,58.635]]]]}},\n{\"type\":\"Feature\",\"id\":\"GEO\",\"properties\":{\"name\":\"Georgia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[41.554084,41.535656],[41.703171,41.962943],[41.45347,42.645123],[40.875469,43.013628],[40.321394,43.128634],[39.955009,43.434998],[40.076965,43.553104],[40.922185,43.382159],[42.394395,43.220308],[43.756017,42.740828],[43.9312,42.554974],[44.537623,42.711993],[45.470279,42.502781],[45.77641,42.092444],[46.404951,41.860675],[46.145432,41.722802],[46.637908,41.181673],[46.501637,41.064445],[45.962601,41.123873],[45.217426,41.411452],[44.97248,41.248129],[43.582746,41.092143],[42.619549,41.583173],[41.554084,41.535656]]]}},\n{\"type\":\"Feature\",\"id\":\"GHA\",\"properties\":{\"name\":\"Ghana\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[1.060122,5.928837],[-0.507638,5.343473],[-1.063625,5.000548],[-1.964707,4.710462],[-2.856125,4.994476],[-2.810701,5.389051],[-3.24437,6.250472],[-2.983585,7.379705],[-2.56219,8.219628],[-2.827496,9.642461],[-2.963896,10.395335],[-2.940409,10.96269],[-1.203358,11.009819],[-0.761576,10.93693],[-0.438702,11.098341],[0.023803,11.018682],[-0.049785,10.706918],[0.36758,10.191213],[0.365901,9.465004],[0.461192,8.677223],[0.712029,8.312465],[0.490957,7.411744],[0.570384,6.914359],[0.836931,6.279979],[1.060122,5.928837]]]}},\n{\"type\":\"Feature\",\"id\":\"GIN\",\"properties\":{\"name\":\"Guinea\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-8.439298,7.686043],[-8.722124,7.711674],[-8.926065,7.309037],[-9.208786,7.313921],[-9.403348,7.526905],[-9.33728,7.928534],[-9.755342,8.541055],[-10.016567,8.428504],[-10.230094,8.406206],[-10.505477,8.348896],[-10.494315,8.715541],[-10.65477,8.977178],[-10.622395,9.26791],[-10.839152,9.688246],[-11.117481,10.045873],[-11.917277,10.046984],[-12.150338,9.858572],[-12.425929,9.835834],[-12.596719,9.620188],[-12.711958,9.342712],[-13.24655,8.903049],[-13.685154,9.494744],[-14.074045,9.886167],[-14.330076,10.01572],[-14.579699,10.214467],[-14.693232,10.656301],[-14.839554,10.876572],[-15.130311,11.040412],[-14.685687,11.527824],[-14.382192,11.509272],[-14.121406,11.677117],[-13.9008,11.678719],[-13.743161,11.811269],[-13.828272,12.142644],[-13.718744,12.247186],[-13.700476,12.586183],[-13.217818,12.575874],[-12.499051,12.33209],[-12.278599,12.35444],[-12.203565,12.465648],[-11.658301,12.386583],[-11.513943,12.442988],[-11.456169,12.076834],[-11.297574,12.077971],[-11.036556,12.211245],[-10.87083,12.177887],[-10.593224,11.923975],[-10.165214,11.844084],[-9.890993,12.060479],[-9.567912,12.194243],[-9.327616,12.334286],[-9.127474,12.30806],[-8.905265,12.088358],[-8.786099,11.812561],[-8.376305,11.393646],[-8.581305,11.136246],[-8.620321,10.810891],[-8.407311,10.909257],[-8.282357,10.792597],[-8.335377,10.494812],[-8.029944,10.206535],[-8.229337,10.12902],[-8.309616,9.789532],[-8.079114,9.376224],[-7.8321,8.575704],[-8.203499,8.455453],[-8.299049,8.316444],[-8.221792,8.123329],[-8.280703,7.68718],[-8.439298,7.686043]]]}},\n{\"type\":\"Feature\",\"id\":\"GMB\",\"properties\":{\"name\":\"Gambia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-16.841525,13.151394],[-16.713729,13.594959],[-15.624596,13.623587],[-15.39877,13.860369],[-15.081735,13.876492],[-14.687031,13.630357],[-14.376714,13.62568],[-14.046992,13.794068],[-13.844963,13.505042],[-14.277702,13.280585],[-14.712197,13.298207],[-15.141163,13.509512],[-15.511813,13.27857],[-15.691001,13.270353],[-15.931296,13.130284],[-16.841525,13.151394]]]}},\n{\"type\":\"Feature\",\"id\":\"GNB\",\"properties\":{\"name\":\"Guinea Bissau\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-15.130311,11.040412],[-15.66418,11.458474],[-16.085214,11.524594],[-16.314787,11.806515],[-16.308947,11.958702],[-16.613838,12.170911],[-16.677452,12.384852],[-16.147717,12.547762],[-15.816574,12.515567],[-15.548477,12.62817],[-13.700476,12.586183],[-13.718744,12.247186],[-13.828272,12.142644],[-13.743161,11.811269],[-13.9008,11.678719],[-14.121406,11.677117],[-14.382192,11.509272],[-14.685687,11.527824],[-15.130311,11.040412]]]}},\n{\"type\":\"Feature\",\"id\":\"GNQ\",\"properties\":{\"name\":\"Equatorial Guinea\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[9.492889,1.01012],[9.305613,1.160911],[9.649158,2.283866],[11.276449,2.261051],[11.285079,1.057662],[9.830284,1.067894],[9.492889,1.01012]]]}},\n{\"type\":\"Feature\",\"id\":\"GRC\",\"properties\":{\"name\":\"Greece\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[23.69998,35.705004],[24.246665,35.368022],[25.025015,35.424996],[25.769208,35.354018],[25.745023,35.179998],[26.290003,35.29999],[26.164998,35.004995],[24.724982,34.919988],[24.735007,35.084991],[23.514978,35.279992],[23.69998,35.705004]]],[[[26.604196,41.562115],[26.294602,40.936261],[26.056942,40.824123],[25.447677,40.852545],[24.925848,40.947062],[23.714811,40.687129],[24.407999,40.124993],[23.899968,39.962006],[23.342999,39.960998],[22.813988,40.476005],[22.626299,40.256561],[22.849748,39.659311],[23.350027,39.190011],[22.973099,38.970903],[23.530016,38.510001],[24.025025,38.219993],[24.040011,37.655015],[23.115003,37.920011],[23.409972,37.409991],[22.774972,37.30501],[23.154225,36.422506],[22.490028,36.41],[21.670026,36.844986],[21.295011,37.644989],[21.120034,38.310323],[20.730032,38.769985],[20.217712,39.340235],[20.150016,39.624998],[20.615,40.110007],[20.674997,40.435],[20.99999,40.580004],[21.02004,40.842727],[21.674161,40.931275],[22.055378,41.149866],[22.597308,41.130487],[22.76177,41.3048],[22.952377,41.337994],[23.692074,41.309081],[24.492645,41.583896],[25.197201,41.234486],[26.106138,41.328899],[26.117042,41.826905],[26.604196,41.562115]]]]}},\n{\"type\":\"Feature\",\"id\":\"GRL\",\"properties\":{\"name\":\"Greenland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-46.76379,82.62796],[-43.40644,83.22516],[-39.89753,83.18018],[-38.62214,83.54905],[-35.08787,83.64513],[-27.10046,83.51966],[-20.84539,82.72669],[-22.69182,82.34165],[-26.51753,82.29765],[-31.9,82.2],[-31.39646,82.02154],[-27.85666,82.13178],[-24.84448,81.78697],[-22.90328,82.09317],[-22.07175,81.73449],[-23.16961,81.15271],[-20.62363,81.52462],[-15.76818,81.91245],[-12.77018,81.71885],[-12.20855,81.29154],[-16.28533,80.58004],[-16.85,80.35],[-20.04624,80.17708],[-17.73035,80.12912],[-18.9,79.4],[-19.70499,78.75128],[-19.67353,77.63859],[-18.47285,76.98565],[-20.03503,76.94434],[-21.67944,76.62795],[-19.83407,76.09808],[-19.59896,75.24838],[-20.66818,75.15585],[-19.37281,74.29561],[-21.59422,74.22382],[-20.43454,73.81713],[-20.76234,73.46436],[-22.17221,73.30955],[-23.56593,73.30663],[-22.31311,72.62928],[-22.29954,72.18409],[-24.27834,72.59788],[-24.79296,72.3302],[-23.44296,72.08016],[-22.13281,71.46898],[-21.75356,70.66369],[-23.53603,70.471],[-24.30702,70.85649],[-25.54341,71.43094],[-25.20135,70.75226],[-26.36276,70.22646],[-23.72742,70.18401],[-22.34902,70.12946],[-25.02927,69.2588],[-27.74737,68.47046],[-30.67371,68.12503],[-31.77665,68.12078],[-32.81105,67.73547],[-34.20196,66.67974],[-36.35284,65.9789],[-37.04378,65.93768],[-38.37505,65.69213],[-39.81222,65.45848],[-40.66899,64.83997],[-40.68281,64.13902],[-41.1887,63.48246],[-42.81938,62.68233],[-42.41666,61.90093],[-42.86619,61.07404],[-43.3784,60.09772],[-44.7875,60.03676],[-46.26364,60.85328],[-48.26294,60.85843],[-49.23308,61.40681],[-49.90039,62.38336],[-51.63325,63.62691],[-52.14014,64.27842],[-52.27659,65.1767],[-53.66166,66.09957],[-53.30161,66.8365],[-53.96911,67.18899],[-52.9804,68.35759],[-51.47536,68.72958],[-51.08041,69.14781],[-50.87122,69.9291],[-52.013585,69.574925],[-52.55792,69.42616],[-53.45629,69.283625],[-54.68336,69.61003],[-54.75001,70.28932],[-54.35884,70.821315],[-53.431315,70.835755],[-51.39014,70.56978],[-53.10937,71.20485],[-54.00422,71.54719],[-55,71.406537],[-55.83468,71.65444],[-54.71819,72.58625],[-55.32634,72.95861],[-56.12003,73.64977],[-57.32363,74.71026],[-58.59679,75.09861],[-58.58516,75.51727],[-61.26861,76.10238],[-63.39165,76.1752],[-66.06427,76.13486],[-68.50438,76.06141],[-69.66485,76.37975],[-71.40257,77.00857],[-68.77671,77.32312],[-66.76397,77.37595],[-71.04293,77.63595],[-73.297,78.04419],[-73.15938,78.43271],[-69.37345,78.91388],[-65.7107,79.39436],[-65.3239,79.75814],[-68.02298,80.11721],[-67.15129,80.51582],[-63.68925,81.21396],[-62.23444,81.3211],[-62.65116,81.77042],[-60.28249,82.03363],[-57.20744,82.19074],[-54.13442,82.19962],[-53.04328,81.88833],[-50.39061,82.43883],[-48.00386,82.06481],[-46.59984,81.985945],[-44.523,81.6607],[-46.9007,82.19979],[-46.76379,82.62796]]]}},\n{\"type\":\"Feature\",\"id\":\"GTM\",\"properties\":{\"name\":\"Guatemala\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-90.095555,13.735338],[-90.608624,13.909771],[-91.23241,13.927832],[-91.689747,14.126218],[-92.22775,14.538829],[-92.20323,14.830103],[-92.087216,15.064585],[-92.229249,15.251447],[-91.74796,16.066565],[-90.464473,16.069562],[-90.438867,16.41011],[-90.600847,16.470778],[-90.711822,16.687483],[-91.08167,16.918477],[-91.453921,17.252177],[-91.002269,17.254658],[-91.00152,17.817595],[-90.067934,17.819326],[-89.14308,17.808319],[-89.150806,17.015577],[-89.229122,15.886938],[-88.930613,15.887273],[-88.604586,15.70638],[-88.518364,15.855389],[-88.225023,15.727722],[-88.68068,15.346247],[-89.154811,15.066419],[-89.22522,14.874286],[-89.145535,14.678019],[-89.353326,14.424133],[-89.587343,14.362586],[-89.534219,14.244816],[-89.721934,14.134228],[-90.064678,13.88197],[-90.095555,13.735338]]]}},\n{\"type\":\"Feature\",\"id\":\"GUF\",\"properties\":{\"name\":\"French Guiana\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-52.556425,2.504705],[-52.939657,2.124858],[-53.418465,2.053389],[-53.554839,2.334897],[-53.778521,2.376703],[-54.088063,2.105557],[-54.524754,2.311849],[-54.27123,2.738748],[-54.184284,3.194172],[-54.011504,3.62257],[-54.399542,4.212611],[-54.478633,4.896756],[-53.958045,5.756548],[-53.618453,5.646529],[-52.882141,5.409851],[-51.823343,4.565768],[-51.657797,4.156232],[-52.249338,3.241094],[-52.556425,2.504705]]]}},\n{\"type\":\"Feature\",\"id\":\"GUY\",\"properties\":{\"name\":\"Guyana\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-59.758285,8.367035],[-59.101684,7.999202],[-58.482962,7.347691],[-58.454876,6.832787],[-58.078103,6.809094],[-57.542219,6.321268],[-57.147436,5.97315],[-57.307246,5.073567],[-57.914289,4.812626],[-57.86021,4.576801],[-58.044694,4.060864],[-57.601569,3.334655],[-57.281433,3.333492],[-57.150098,2.768927],[-56.539386,1.899523],[-56.782704,1.863711],[-57.335823,1.948538],[-57.660971,1.682585],[-58.11345,1.507195],[-58.429477,1.463942],[-58.540013,1.268088],[-59.030862,1.317698],[-59.646044,1.786894],[-59.718546,2.24963],[-59.974525,2.755233],[-59.815413,3.606499],[-59.53804,3.958803],[-59.767406,4.423503],[-60.111002,4.574967],[-59.980959,5.014061],[-60.213683,5.244486],[-60.733574,5.200277],[-61.410303,5.959068],[-61.139415,6.234297],[-61.159336,6.696077],[-60.543999,6.856584],[-60.295668,7.043911],[-60.637973,7.415],[-60.550588,7.779603],[-59.758285,8.367035]]]}},\n{\"type\":\"Feature\",\"id\":\"HND\",\"properties\":{\"name\":\"Honduras\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-87.316654,12.984686],[-87.489409,13.297535],[-87.793111,13.38448],[-87.723503,13.78505],[-87.859515,13.893312],[-88.065343,13.964626],[-88.503998,13.845486],[-88.541231,13.980155],[-88.843073,14.140507],[-89.058512,14.340029],[-89.353326,14.424133],[-89.145535,14.678019],[-89.22522,14.874286],[-89.154811,15.066419],[-88.68068,15.346247],[-88.225023,15.727722],[-88.121153,15.688655],[-87.901813,15.864458],[-87.61568,15.878799],[-87.522921,15.797279],[-87.367762,15.84694],[-86.903191,15.756713],[-86.440946,15.782835],[-86.119234,15.893449],[-86.001954,16.005406],[-85.683317,15.953652],[-85.444004,15.885749],[-85.182444,15.909158],[-84.983722,15.995923],[-84.52698,15.857224],[-84.368256,15.835158],[-84.063055,15.648244],[-83.773977,15.424072],[-83.410381,15.270903],[-83.147219,14.995829],[-83.489989,15.016267],[-83.628585,14.880074],[-83.975721,14.749436],[-84.228342,14.748764],[-84.449336,14.621614],[-84.649582,14.666805],[-84.820037,14.819587],[-84.924501,14.790493],[-85.052787,14.551541],[-85.148751,14.560197],[-85.165365,14.35437],[-85.514413,14.079012],[-85.698665,13.960078],[-85.801295,13.836055],[-86.096264,14.038187],[-86.312142,13.771356],[-86.520708,13.778487],[-86.755087,13.754845],[-86.733822,13.263093],[-86.880557,13.254204],[-87.005769,13.025794],[-87.316654,12.984686]]]}},\n{\"type\":\"Feature\",\"id\":\"HRV\",\"properties\":{\"name\":\"Croatia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[18.829838,45.908878],[19.072769,45.521511],[19.390476,45.236516],[19.005486,44.860234],[18.553214,45.08159],[17.861783,45.06774],[17.002146,45.233777],[16.534939,45.211608],[16.318157,45.004127],[15.959367,45.233777],[15.750026,44.818712],[16.23966,44.351143],[16.456443,44.04124],[16.916156,43.667722],[17.297373,43.446341],[17.674922,43.028563],[18.56,42.65],[18.450016,42.479991],[17.50997,42.849995],[16.930006,43.209998],[16.015385,43.507215],[15.174454,44.243191],[15.37625,44.317915],[14.920309,44.738484],[14.901602,45.07606],[14.258748,45.233777],[13.952255,44.802124],[13.656976,45.136935],[13.679403,45.484149],[13.71506,45.500324],[14.411968,45.466166],[14.595109,45.634941],[14.935244,45.471695],[15.327675,45.452316],[15.323954,45.731783],[15.67153,45.834154],[15.768733,46.238108],[16.564808,46.503751],[16.882515,46.380632],[17.630066,45.951769],[18.456062,45.759481],[18.829838,45.908878]]]}},\n{\"type\":\"Feature\",\"id\":\"HTI\",\"properties\":{\"name\":\"Haiti\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-73.189791,19.915684],[-72.579673,19.871501],[-71.712361,19.714456],[-71.624873,19.169838],[-71.701303,18.785417],[-71.945112,18.6169],[-71.687738,18.31666],[-71.708305,18.044997],[-72.372476,18.214961],[-72.844411,18.145611],[-73.454555,18.217906],[-73.922433,18.030993],[-74.458034,18.34255],[-74.369925,18.664908],[-73.449542,18.526053],[-72.694937,18.445799],[-72.334882,18.668422],[-72.79165,19.101625],[-72.784105,19.483591],[-73.415022,19.639551],[-73.189791,19.915684]]]}},\n{\"type\":\"Feature\",\"id\":\"HUN\",\"properties\":{\"name\":\"Hungary\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[16.202298,46.852386],[16.534268,47.496171],[16.340584,47.712902],[16.903754,47.714866],[16.979667,48.123497],[17.488473,47.867466],[17.857133,47.758429],[18.696513,47.880954],[18.777025,48.081768],[19.174365,48.111379],[19.661364,48.266615],[19.769471,48.202691],[20.239054,48.327567],[20.473562,48.56285],[20.801294,48.623854],[21.872236,48.319971],[22.085608,48.422264],[22.64082,48.15024],[22.710531,47.882194],[22.099768,47.672439],[21.626515,46.994238],[21.021952,46.316088],[20.220192,46.127469],[19.596045,46.17173],[18.829838,45.908878],[18.456062,45.759481],[17.630066,45.951769],[16.882515,46.380632],[16.564808,46.503751],[16.370505,46.841327],[16.202298,46.852386]]]}},\n{\"type\":\"Feature\",\"id\":\"IDN\",\"properties\":{\"name\":\"Indonesia\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[120.715609,-10.239581],[120.295014,-10.25865],[118.967808,-9.557969],[119.90031,-9.36134],[120.425756,-9.665921],[120.775502,-9.969675],[120.715609,-10.239581]]],[[[124.43595,-10.140001],[123.579982,-10.359987],[123.459989,-10.239995],[123.550009,-9.900016],[123.980009,-9.290027],[124.968682,-8.89279],[125.07002,-9.089987],[125.08852,-9.393173],[124.43595,-10.140001]]],[[[117.900018,-8.095681],[118.260616,-8.362383],[118.87846,-8.280683],[119.126507,-8.705825],[117.970402,-8.906639],[117.277731,-9.040895],[116.740141,-9.032937],[117.083737,-8.457158],[117.632024,-8.449303],[117.900018,-8.095681]]],[[[122.903537,-8.094234],[122.756983,-8.649808],[121.254491,-8.933666],[119.924391,-8.810418],[119.920929,-8.444859],[120.715092,-8.236965],[121.341669,-8.53674],[122.007365,-8.46062],[122.903537,-8.094234]]],[[[108.623479,-6.777674],[110.539227,-6.877358],[110.759576,-6.465186],[112.614811,-6.946036],[112.978768,-7.594213],[114.478935,-7.776528],[115.705527,-8.370807],[114.564511,-8.751817],[113.464734,-8.348947],[112.559672,-8.376181],[111.522061,-8.302129],[110.58615,-8.122605],[109.427667,-7.740664],[108.693655,-7.6416],[108.277763,-7.766657],[106.454102,-7.3549],[106.280624,-6.9249],[105.365486,-6.851416],[106.051646,-5.895919],[107.265009,-5.954985],[108.072091,-6.345762],[108.486846,-6.421985],[108.623479,-6.777674]]],[[[134.724624,-6.214401],[134.210134,-6.895238],[134.112776,-6.142467],[134.290336,-5.783058],[134.499625,-5.445042],[134.727002,-5.737582],[134.724624,-6.214401]]],[[[127.249215,-3.459065],[126.874923,-3.790983],[126.183802,-3.607376],[125.989034,-3.177273],[127.000651,-3.129318],[127.249215,-3.459065]]],[[[130.471344,-3.093764],[130.834836,-3.858472],[129.990547,-3.446301],[129.155249,-3.362637],[128.590684,-3.428679],[127.898891,-3.393436],[128.135879,-2.84365],[129.370998,-2.802154],[130.471344,-3.093764]]],[[[134.143368,-1.151867],[134.422627,-2.769185],[135.457603,-3.367753],[136.293314,-2.307042],[137.440738,-1.703513],[138.329727,-1.702686],[139.184921,-2.051296],[139.926684,-2.409052],[141.00021,-2.600151],[141.017057,-5.859022],[141.033852,-9.117893],[140.143415,-8.297168],[139.127767,-8.096043],[138.881477,-8.380935],[137.614474,-8.411683],[138.039099,-7.597882],[138.668621,-7.320225],[138.407914,-6.232849],[137.92784,-5.393366],[135.98925,-4.546544],[135.164598,-4.462931],[133.66288,-3.538853],[133.367705,-4.024819],[132.983956,-4.112979],[132.756941,-3.746283],[132.753789,-3.311787],[131.989804,-2.820551],[133.066845,-2.460418],[133.780031,-2.479848],[133.696212,-2.214542],[132.232373,-2.212526],[131.836222,-1.617162],[130.94284,-1.432522],[130.519558,-0.93772],[131.867538,-0.695461],[132.380116,-0.369538],[133.985548,-0.78021],[134.143368,-1.151867]]],[[[125.240501,1.419836],[124.437035,0.427881],[123.685505,0.235593],[122.723083,0.431137],[121.056725,0.381217],[120.183083,0.237247],[120.04087,-0.519658],[120.935905,-1.408906],[121.475821,-0.955962],[123.340565,-0.615673],[123.258399,-1.076213],[122.822715,-0.930951],[122.38853,-1.516858],[121.508274,-1.904483],[122.454572,-3.186058],[122.271896,-3.5295],[123.170963,-4.683693],[123.162333,-5.340604],[122.628515,-5.634591],[122.236394,-5.282933],[122.719569,-4.464172],[121.738234,-4.851331],[121.489463,-4.574553],[121.619171,-4.188478],[120.898182,-3.602105],[120.972389,-2.627643],[120.305453,-2.931604],[120.390047,-4.097579],[120.430717,-5.528241],[119.796543,-5.6734],[119.366906,-5.379878],[119.653606,-4.459417],[119.498835,-3.494412],[119.078344,-3.487022],[118.767769,-2.801999],[119.180974,-2.147104],[119.323394,-1.353147],[119.825999,0.154254],[120.035702,0.566477],[120.885779,1.309223],[121.666817,1.013944],[122.927567,0.875192],[124.077522,0.917102],[125.065989,1.643259],[125.240501,1.419836]]],[[[128.688249,1.132386],[128.635952,0.258486],[128.12017,0.356413],[127.968034,-0.252077],[128.379999,-0.780004],[128.100016,-0.899996],[127.696475,-0.266598],[127.39949,1.011722],[127.600512,1.810691],[127.932378,2.174596],[128.004156,1.628531],[128.594559,1.540811],[128.688249,1.132386]]],[[[117.875627,1.827641],[118.996747,0.902219],[117.811858,0.784242],[117.478339,0.102475],[117.521644,-0.803723],[116.560048,-1.487661],[116.533797,-2.483517],[116.148084,-4.012726],[116.000858,-3.657037],[114.864803,-4.106984],[114.468652,-3.495704],[113.755672,-3.43917],[113.256994,-3.118776],[112.068126,-3.478392],[111.703291,-2.994442],[111.04824,-3.049426],[110.223846,-2.934032],[110.070936,-1.592874],[109.571948,-1.314907],[109.091874,-0.459507],[108.952658,0.415375],[109.069136,1.341934],[109.66326,2.006467],[109.830227,1.338136],[110.514061,0.773131],[111.159138,0.976478],[111.797548,0.904441],[112.380252,1.410121],[112.859809,1.49779],[113.80585,1.217549],[114.621355,1.430688],[115.134037,2.821482],[115.519078,3.169238],[115.865517,4.306559],[117.015214,4.306094],[117.882035,4.137551],[117.313232,3.234428],[118.04833,2.28769],[117.875627,1.827641]]],[[[105.817655,-5.852356],[104.710384,-5.873285],[103.868213,-5.037315],[102.584261,-4.220259],[102.156173,-3.614146],[101.399113,-2.799777],[100.902503,-2.050262],[100.141981,-0.650348],[99.26374,0.183142],[98.970011,1.042882],[98.601351,1.823507],[97.699598,2.453184],[97.176942,3.308791],[96.424017,3.86886],[95.380876,4.970782],[95.293026,5.479821],[95.936863,5.439513],[97.484882,5.246321],[98.369169,4.26837],[99.142559,3.59035],[99.693998,3.174329],[100.641434,2.099381],[101.658012,2.083697],[102.498271,1.3987],[103.07684,0.561361],[103.838396,0.104542],[103.437645,-0.711946],[104.010789,-1.059212],[104.369991,-1.084843],[104.53949,-1.782372],[104.887893,-2.340425],[105.622111,-2.428844],[106.108593,-3.061777],[105.857446,-4.305525],[105.817655,-5.852356]]]]}},\n{\"type\":\"Feature\",\"id\":\"IND\",\"properties\":{\"name\":\"India\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[77.837451,35.49401],[78.912269,34.321936],[78.811086,33.506198],[79.208892,32.994395],[79.176129,32.48378],[78.458446,32.618164],[78.738894,31.515906],[79.721367,30.882715],[81.111256,30.183481],[80.476721,29.729865],[80.088425,28.79447],[81.057203,28.416095],[81.999987,27.925479],[83.304249,27.364506],[84.675018,27.234901],[85.251779,26.726198],[86.024393,26.630985],[87.227472,26.397898],[88.060238,26.414615],[88.174804,26.810405],[88.043133,27.445819],[88.120441,27.876542],[88.730326,28.086865],[88.814248,27.299316],[88.835643,27.098966],[89.744528,26.719403],[90.373275,26.875724],[91.217513,26.808648],[92.033484,26.83831],[92.103712,27.452614],[91.696657,27.771742],[92.503119,27.896876],[93.413348,28.640629],[94.56599,29.277438],[95.404802,29.031717],[96.117679,29.452802],[96.586591,28.83098],[96.248833,28.411031],[97.327114,28.261583],[97.402561,27.882536],[97.051989,27.699059],[97.133999,27.083774],[96.419366,27.264589],[95.124768,26.573572],[95.155153,26.001307],[94.603249,25.162495],[94.552658,24.675238],[94.106742,23.850741],[93.325188,24.078556],[93.286327,23.043658],[93.060294,22.703111],[93.166128,22.27846],[92.672721,22.041239],[92.146035,23.627499],[91.869928,23.624346],[91.706475,22.985264],[91.158963,23.503527],[91.46773,24.072639],[91.915093,24.130414],[92.376202,24.976693],[91.799596,25.147432],[90.872211,25.132601],[89.920693,25.26975],[89.832481,25.965082],[89.355094,26.014407],[88.563049,26.446526],[88.209789,25.768066],[88.931554,25.238692],[88.306373,24.866079],[88.084422,24.501657],[88.69994,24.233715],[88.52977,23.631142],[88.876312,22.879146],[89.031961,22.055708],[88.888766,21.690588],[88.208497,21.703172],[86.975704,21.495562],[87.033169,20.743308],[86.499351,20.151638],[85.060266,19.478579],[83.941006,18.30201],[83.189217,17.671221],[82.192792,17.016636],[82.191242,16.556664],[81.692719,16.310219],[80.791999,15.951972],[80.324896,15.899185],[80.025069,15.136415],[80.233274,13.835771],[80.286294,13.006261],[79.862547,12.056215],[79.857999,10.357275],[79.340512,10.308854],[78.885345,9.546136],[79.18972,9.216544],[78.277941,8.933047],[77.941165,8.252959],[77.539898,7.965535],[76.592979,8.899276],[76.130061,10.29963],[75.746467,11.308251],[75.396101,11.781245],[74.864816,12.741936],[74.616717,13.992583],[74.443859,14.617222],[73.534199,15.990652],[73.119909,17.92857],[72.820909,19.208234],[72.824475,20.419503],[72.630533,21.356009],[71.175273,20.757441],[70.470459,20.877331],[69.16413,22.089298],[69.644928,22.450775],[69.349597,22.84318],[68.176645,23.691965],[68.842599,24.359134],[71.04324,24.356524],[70.844699,25.215102],[70.282873,25.722229],[70.168927,26.491872],[69.514393,26.940966],[70.616496,27.989196],[71.777666,27.91318],[72.823752,28.961592],[73.450638,29.976413],[74.42138,30.979815],[74.405929,31.692639],[75.258642,32.271105],[74.451559,32.7649],[74.104294,33.441473],[73.749948,34.317699],[74.240203,34.748887],[75.757061,34.504923],[76.871722,34.653544],[77.837451,35.49401]]]}},\n{\"type\":\"Feature\",\"id\":\"IRL\",\"properties\":{\"name\":\"Ireland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-6.197885,53.867565],[-6.032985,53.153164],[-6.788857,52.260118],[-8.561617,51.669301],[-9.977086,51.820455],[-9.166283,52.864629],[-9.688525,53.881363],[-8.327987,54.664519],[-7.572168,55.131622],[-7.366031,54.595841],[-7.572168,54.059956],[-6.95373,54.073702],[-6.197885,53.867565]]]}},\n{\"type\":\"Feature\",\"id\":\"IRN\",\"properties\":{\"name\":\"Iran\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[53.921598,37.198918],[54.800304,37.392421],[55.511578,37.964117],[56.180375,37.935127],[56.619366,38.121394],[57.330434,38.029229],[58.436154,37.522309],[59.234762,37.412988],[60.377638,36.527383],[61.123071,36.491597],[61.210817,35.650072],[60.803193,34.404102],[60.52843,33.676446],[60.9637,33.528832],[60.536078,32.981269],[60.863655,32.18292],[60.941945,31.548075],[61.699314,31.379506],[61.781222,30.73585],[60.874248,29.829239],[61.369309,29.303276],[61.771868,28.699334],[62.72783,28.259645],[62.755426,27.378923],[63.233898,27.217047],[63.316632,26.756532],[61.874187,26.239975],[61.497363,25.078237],[59.616134,25.380157],[58.525761,25.609962],[57.397251,25.739902],[56.970766,26.966106],[56.492139,27.143305],[55.72371,26.964633],[54.71509,26.480658],[53.493097,26.812369],[52.483598,27.580849],[51.520763,27.86569],[50.852948,28.814521],[50.115009,30.147773],[49.57685,29.985715],[48.941333,30.31709],[48.567971,29.926778],[48.014568,30.452457],[48.004698,30.985137],[47.685286,30.984853],[47.849204,31.709176],[47.334661,32.469155],[46.109362,33.017287],[45.416691,33.967798],[45.64846,34.748138],[46.151788,35.093259],[46.07634,35.677383],[45.420618,35.977546],[44.77267,37.17045],[44.225756,37.971584],[44.421403,38.281281],[44.109225,39.428136],[44.79399,39.713003],[44.952688,39.335765],[45.457722,38.874139],[46.143623,38.741201],[46.50572,38.770605],[47.685079,39.508364],[48.060095,39.582235],[48.355529,39.288765],[48.010744,38.794015],[48.634375,38.270378],[48.883249,38.320245],[49.199612,37.582874],[50.147771,37.374567],[50.842354,36.872814],[52.264025,36.700422],[53.82579,36.965031],[53.921598,37.198918]]]}},\n{\"type\":\"Feature\",\"id\":\"IRQ\",\"properties\":{\"name\":\"Iraq\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[45.420618,35.977546],[46.07634,35.677383],[46.151788,35.093259],[45.64846,34.748138],[45.416691,33.967798],[46.109362,33.017287],[47.334661,32.469155],[47.849204,31.709176],[47.685286,30.984853],[48.004698,30.985137],[48.014568,30.452457],[48.567971,29.926778],[47.974519,29.975819],[47.302622,30.05907],[46.568713,29.099025],[44.709499,29.178891],[41.889981,31.190009],[40.399994,31.889992],[39.195468,32.161009],[38.792341,33.378686],[41.006159,34.419372],[41.383965,35.628317],[41.289707,36.358815],[41.837064,36.605854],[42.349591,37.229873],[42.779126,37.385264],[43.942259,37.256228],[44.293452,37.001514],[44.772699,37.170445],[45.420618,35.977546]]]}},\n{\"type\":\"Feature\",\"id\":\"ISL\",\"properties\":{\"name\":\"Iceland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-14.508695,66.455892],[-14.739637,65.808748],[-13.609732,65.126671],[-14.909834,64.364082],[-17.794438,63.678749],[-18.656246,63.496383],[-19.972755,63.643635],[-22.762972,63.960179],[-21.778484,64.402116],[-23.955044,64.89113],[-22.184403,65.084968],[-22.227423,65.378594],[-24.326184,65.611189],[-23.650515,66.262519],[-22.134922,66.410469],[-20.576284,65.732112],[-19.056842,66.276601],[-17.798624,65.993853],[-16.167819,66.526792],[-14.508695,66.455892]]]}},\n{\"type\":\"Feature\",\"id\":\"ISR\",\"properties\":{\"name\":\"Israel\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[35.719918,32.709192],[35.545665,32.393992],[35.18393,32.532511],[34.974641,31.866582],[35.225892,31.754341],[34.970507,31.616778],[34.927408,31.353435],[35.397561,31.489086],[35.420918,31.100066],[34.922603,29.501326],[34.265433,31.219361],[34.556372,31.548824],[34.488107,31.605539],[34.752587,32.072926],[34.955417,32.827376],[35.098457,33.080539],[35.126053,33.0909],[35.460709,33.08904],[35.552797,33.264275],[35.821101,33.277426],[35.836397,32.868123],[35.700798,32.716014],[35.719918,32.709192]]]}},\n{\"type\":\"Feature\",\"id\":\"ITA\",\"properties\":{\"name\":\"Italy\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[15.520376,38.231155],[15.160243,37.444046],[15.309898,37.134219],[15.099988,36.619987],[14.335229,36.996631],[13.826733,37.104531],[12.431004,37.61295],[12.570944,38.126381],[13.741156,38.034966],[14.761249,38.143874],[15.520376,38.231155]]],[[[9.210012,41.209991],[9.809975,40.500009],[9.669519,39.177376],[9.214818,39.240473],[8.806936,38.906618],[8.428302,39.171847],[8.388253,40.378311],[8.159998,40.950007],[8.709991,40.899984],[9.210012,41.209991]]],[[[12.376485,46.767559],[13.806475,46.509306],[13.69811,46.016778],[13.93763,45.591016],[13.141606,45.736692],[12.328581,45.381778],[12.383875,44.885374],[12.261453,44.600482],[12.589237,44.091366],[13.526906,43.587727],[14.029821,42.761008],[15.14257,41.95514],[15.926191,41.961315],[16.169897,41.740295],[15.889346,41.541082],[16.785002,41.179606],[17.519169,40.877143],[18.376687,40.355625],[18.480247,40.168866],[18.293385,39.810774],[17.73838,40.277671],[16.869596,40.442235],[16.448743,39.795401],[17.17149,39.4247],[17.052841,38.902871],[16.635088,38.843572],[16.100961,37.985899],[15.684087,37.908849],[15.687963,38.214593],[15.891981,38.750942],[16.109332,38.964547],[15.718814,39.544072],[15.413613,40.048357],[14.998496,40.172949],[14.703268,40.60455],[14.060672,40.786348],[13.627985,41.188287],[12.888082,41.25309],[12.106683,41.704535],[11.191906,42.355425],[10.511948,42.931463],[10.200029,43.920007],[9.702488,44.036279],[8.888946,44.366336],[8.428561,44.231228],[7.850767,43.767148],[7.435185,43.693845],[7.549596,44.127901],[7.007562,44.254767],[6.749955,45.028518],[7.096652,45.333099],[6.802355,45.70858],[6.843593,45.991147],[7.273851,45.776948],[7.755992,45.82449],[8.31663,46.163642],[8.489952,46.005151],[8.966306,46.036932],[9.182882,46.440215],[9.922837,46.314899],[10.363378,46.483571],[10.442701,46.893546],[11.048556,46.751359],[11.164828,46.941579],[12.153088,47.115393],[12.376485,46.767559]]]]}},\n{\"type\":\"Feature\",\"id\":\"JAM\",\"properties\":{\"name\":\"Jamaica\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-77.569601,18.490525],[-76.896619,18.400867],[-76.365359,18.160701],[-76.199659,17.886867],[-76.902561,17.868238],[-77.206341,17.701116],[-77.766023,17.861597],[-78.337719,18.225968],[-78.217727,18.454533],[-77.797365,18.524218],[-77.569601,18.490525]]]}},\n{\"type\":\"Feature\",\"id\":\"JOR\",\"properties\":{\"name\":\"Jordan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[35.545665,32.393992],[35.719918,32.709192],[36.834062,32.312938],[38.792341,33.378686],[39.195468,32.161009],[39.004886,32.010217],[37.002166,31.508413],[37.998849,30.5085],[37.66812,30.338665],[37.503582,30.003776],[36.740528,29.865283],[36.501214,29.505254],[36.068941,29.197495],[34.956037,29.356555],[34.922603,29.501326],[35.420918,31.100066],[35.397561,31.489086],[35.545252,31.782505],[35.545665,32.393992]]]}},\n{\"type\":\"Feature\",\"id\":\"JPN\",\"properties\":{\"name\":\"Japan\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[134.638428,34.149234],[134.766379,33.806335],[134.203416,33.201178],[133.79295,33.521985],[133.280268,33.28957],[133.014858,32.704567],[132.363115,32.989382],[132.371176,33.463642],[132.924373,34.060299],[133.492968,33.944621],[133.904106,34.364931],[134.638428,34.149234]]],[[[140.976388,37.142074],[140.59977,36.343983],[140.774074,35.842877],[140.253279,35.138114],[138.975528,34.6676],[137.217599,34.606286],[135.792983,33.464805],[135.120983,33.849071],[135.079435,34.596545],[133.340316,34.375938],[132.156771,33.904933],[130.986145,33.885761],[132.000036,33.149992],[131.33279,31.450355],[130.686318,31.029579],[130.20242,31.418238],[130.447676,32.319475],[129.814692,32.61031],[129.408463,33.296056],[130.353935,33.604151],[130.878451,34.232743],[131.884229,34.749714],[132.617673,35.433393],[134.608301,35.731618],[135.677538,35.527134],[136.723831,37.304984],[137.390612,36.827391],[138.857602,37.827485],[139.426405,38.215962],[140.05479,39.438807],[139.883379,40.563312],[140.305783,41.195005],[141.368973,41.37856],[141.914263,39.991616],[141.884601,39.180865],[140.959489,38.174001],[140.976388,37.142074]]],[[[143.910162,44.1741],[144.613427,43.960883],[145.320825,44.384733],[145.543137,43.262088],[144.059662,42.988358],[143.18385,41.995215],[141.611491,42.678791],[141.067286,41.584594],[139.955106,41.569556],[139.817544,42.563759],[140.312087,43.333273],[141.380549,43.388825],[141.671952,44.772125],[141.967645,45.551483],[143.14287,44.510358],[143.910162,44.1741]]]]}},\n{\"type\":\"Feature\",\"id\":\"KAZ\",\"properties\":{\"name\":\"Kazakhstan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[70.962315,42.266154],[70.388965,42.081308],[69.070027,41.384244],[68.632483,40.668681],[68.259896,40.662325],[67.985856,41.135991],[66.714047,41.168444],[66.510649,41.987644],[66.023392,41.994646],[66.098012,42.99766],[64.900824,43.728081],[63.185787,43.650075],[62.0133,43.504477],[61.05832,44.405817],[60.239972,44.784037],[58.689989,45.500014],[58.503127,45.586804],[55.928917,44.995858],[55.968191,41.308642],[55.455251,41.259859],[54.755345,42.043971],[54.079418,42.324109],[52.944293,42.116034],[52.50246,41.783316],[52.446339,42.027151],[52.692112,42.443895],[52.501426,42.792298],[51.342427,43.132975],[50.891292,44.031034],[50.339129,44.284016],[50.305643,44.609836],[51.278503,44.514854],[51.316899,45.245998],[52.16739,45.408391],[53.040876,45.259047],[53.220866,46.234646],[53.042737,46.853006],[52.042023,46.804637],[51.191945,47.048705],[50.034083,46.60899],[49.10116,46.39933],[48.593241,46.561034],[48.694734,47.075628],[48.057253,47.743753],[47.315231,47.715847],[46.466446,48.394152],[47.043672,49.152039],[46.751596,49.356006],[47.54948,50.454698],[48.577841,49.87476],[48.702382,50.605128],[50.766648,51.692762],[52.328724,51.718652],[54.532878,51.02624],[55.716941,50.621717],[56.777961,51.043551],[58.363291,51.063653],[59.642282,50.545442],[59.932807,50.842194],[61.337424,50.79907],[61.588003,51.272659],[59.967534,51.96042],[60.927269,52.447548],[60.739993,52.719986],[61.699986,52.979996],[60.978066,53.664993],[61.436591,54.006265],[65.178534,54.354228],[65.666876,54.601267],[68.1691,54.970392],[69.068167,55.38525],[70.865267,55.169734],[71.180131,54.133285],[72.22415,54.376655],[73.508516,54.035617],[73.425679,53.48981],[74.384845,53.546861],[76.8911,54.490524],[76.525179,54.177003],[77.800916,53.404415],[80.03556,50.864751],[80.568447,51.388336],[81.945986,50.812196],[83.383004,51.069183],[83.935115,50.889246],[84.416377,50.3114],[85.11556,50.117303],[85.54127,49.692859],[86.829357,49.826675],[87.35997,49.214981],[86.598776,48.549182],[85.768233,48.455751],[85.720484,47.452969],[85.16429,47.000956],[83.180484,47.330031],[82.458926,45.53965],[81.947071,45.317027],[79.966106,44.917517],[80.866206,43.180362],[80.18015,42.920068],[80.25999,42.349999],[79.643645,42.496683],[79.142177,42.856092],[77.658392,42.960686],[76.000354,42.988022],[75.636965,42.8779],[74.212866,43.298339],[73.645304,43.091272],[73.489758,42.500894],[71.844638,42.845395],[71.186281,42.704293],[70.962315,42.266154]]]}},\n{\"type\":\"Feature\",\"id\":\"KEN\",\"properties\":{\"name\":\"Kenya\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[40.993,-0.85829],[41.58513,-1.68325],[40.88477,-2.08255],[40.63785,-2.49979],[40.26304,-2.57309],[40.12119,-3.27768],[39.80006,-3.68116],[39.60489,-4.34653],[39.20222,-4.67677],[37.7669,-3.67712],[37.69869,-3.09699],[34.07262,-1.05982],[33.903711,-0.95],[33.893569,0.109814],[34.18,0.515],[34.6721,1.17694],[35.03599,1.90584],[34.59607,3.05374],[34.47913,3.5556],[34.005,4.249885],[34.620196,4.847123],[35.298007,5.506],[35.817448,5.338232],[35.817448,4.776966],[36.159079,4.447864],[36.855093,4.447864],[38.120915,3.598605],[38.43697,3.58851],[38.67114,3.61607],[38.89251,3.50074],[39.559384,3.42206],[39.85494,3.83879],[40.76848,4.25702],[41.1718,3.91909],[41.855083,3.918912],[40.98105,2.78452],[40.993,-0.85829]]]}},\n{\"type\":\"Feature\",\"id\":\"KGZ\",\"properties\":{\"name\":\"Kyrgyzstan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[70.962315,42.266154],[71.186281,42.704293],[71.844638,42.845395],[73.489758,42.500894],[73.645304,43.091272],[74.212866,43.298339],[75.636965,42.8779],[76.000354,42.988022],[77.658392,42.960686],[79.142177,42.856092],[79.643645,42.496683],[80.25999,42.349999],[80.11943,42.123941],[78.543661,41.582243],[78.187197,41.185316],[76.904484,41.066486],[76.526368,40.427946],[75.467828,40.562072],[74.776862,40.366425],[73.822244,39.893973],[73.960013,39.660008],[73.675379,39.431237],[71.784694,39.279463],[70.549162,39.604198],[69.464887,39.526683],[69.55961,40.103211],[70.648019,39.935754],[71.014198,40.244366],[71.774875,40.145844],[73.055417,40.866033],[71.870115,41.3929],[71.157859,41.143587],[70.420022,41.519998],[71.259248,42.167711],[70.962315,42.266154]]]}},\n{\"type\":\"Feature\",\"id\":\"KHM\",\"properties\":{\"name\":\"Cambodia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[103.49728,10.632555],[103.09069,11.153661],[102.584932,12.186595],[102.348099,13.394247],[102.988422,14.225721],[104.281418,14.416743],[105.218777,14.273212],[106.043946,13.881091],[106.496373,14.570584],[107.382727,14.202441],[107.614548,13.535531],[107.491403,12.337206],[105.810524,11.567615],[106.24967,10.961812],[105.199915,10.88931],[104.334335,10.486544],[103.49728,10.632555]]]}},\n{\"type\":\"Feature\",\"id\":\"KOR\",\"properties\":{\"name\":\"South Korea\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[128.349716,38.612243],[129.21292,37.432392],[129.46045,36.784189],[129.468304,35.632141],[129.091377,35.082484],[128.18585,34.890377],[127.386519,34.475674],[126.485748,34.390046],[126.37392,34.93456],[126.559231,35.684541],[126.117398,36.725485],[126.860143,36.893924],[126.174759,37.749686],[126.237339,37.840378],[126.68372,37.804773],[127.073309,38.256115],[127.780035,38.304536],[128.205746,38.370397],[128.349716,38.612243]]]}},\n{\"type\":\"Feature\",\"id\":\"CS-KM\",\"properties\":{\"name\":\"Kosovo\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[20.76216,42.05186],[20.71731,41.84711],[20.59023,41.85541],[20.52295,42.21787],[20.28374,42.32025],[20.0707,42.58863],[20.25758,42.81275],[20.49679,42.88469],[20.63508,43.21671],[20.81448,43.27205],[20.95651,43.13094],[21.143395,43.068685],[21.27421,42.90959],[21.43866,42.86255],[21.63302,42.67717],[21.77505,42.6827],[21.66292,42.43922],[21.54332,42.32025],[21.576636,42.245224],[21.3527,42.2068],[20.76216,42.05186]]]}},\n{\"type\":\"Feature\",\"id\":\"KWT\",\"properties\":{\"name\":\"Kuwait\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[47.974519,29.975819],[48.183189,29.534477],[48.093943,29.306299],[48.416094,28.552004],[47.708851,28.526063],[47.459822,29.002519],[46.568713,29.099025],[47.302622,30.05907],[47.974519,29.975819]]]}},\n{\"type\":\"Feature\",\"id\":\"LAO\",\"properties\":{\"name\":\"Laos\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[105.218777,14.273212],[105.544338,14.723934],[105.589039,15.570316],[104.779321,16.441865],[104.716947,17.428859],[103.956477,18.240954],[103.200192,18.309632],[102.998706,17.961695],[102.413005,17.932782],[102.113592,18.109102],[101.059548,17.512497],[101.035931,18.408928],[101.282015,19.462585],[100.606294,19.508344],[100.548881,20.109238],[100.115988,20.41785],[100.329101,20.786122],[101.180005,21.436573],[101.270026,21.201652],[101.80312,21.174367],[101.652018,22.318199],[102.170436,22.464753],[102.754896,21.675137],[103.203861,20.766562],[104.435,20.758733],[104.822574,19.886642],[104.183388,19.624668],[103.896532,19.265181],[105.094598,18.666975],[105.925762,17.485315],[106.556008,16.604284],[107.312706,15.908538],[107.564525,15.202173],[107.382727,14.202441],[106.496373,14.570584],[106.043946,13.881091],[105.218777,14.273212]]]}},\n{\"type\":\"Feature\",\"id\":\"LBN\",\"properties\":{\"name\":\"Lebanon\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[35.821101,33.277426],[35.552797,33.264275],[35.460709,33.08904],[35.126053,33.0909],[35.482207,33.90545],[35.979592,34.610058],[35.998403,34.644914],[36.448194,34.593935],[36.61175,34.201789],[36.06646,33.824912],[35.821101,33.277426]]]}},\n{\"type\":\"Feature\",\"id\":\"LBR\",\"properties\":{\"name\":\"Liberia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-7.712159,4.364566],[-7.974107,4.355755],[-9.004794,4.832419],[-9.91342,5.593561],[-10.765384,6.140711],[-11.438779,6.785917],[-11.199802,7.105846],[-11.146704,7.396706],[-10.695595,7.939464],[-10.230094,8.406206],[-10.016567,8.428504],[-9.755342,8.541055],[-9.33728,7.928534],[-9.403348,7.526905],[-9.208786,7.313921],[-8.926065,7.309037],[-8.722124,7.711674],[-8.439298,7.686043],[-8.485446,7.395208],[-8.385452,6.911801],[-8.60288,6.467564],[-8.311348,6.193033],[-7.993693,6.12619],[-7.570153,5.707352],[-7.539715,5.313345],[-7.635368,5.188159],[-7.712159,4.364566]]]}},\n{\"type\":\"Feature\",\"id\":\"LBY\",\"properties\":{\"name\":\"Libya\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[14.8513,22.86295],[14.143871,22.491289],[13.581425,23.040506],[11.999506,23.471668],[11.560669,24.097909],[10.771364,24.562532],[10.303847,24.379313],[9.948261,24.936954],[9.910693,25.365455],[9.319411,26.094325],[9.716286,26.512206],[9.629056,27.140953],[9.756128,27.688259],[9.683885,28.144174],[9.859998,28.95999],[9.805634,29.424638],[9.48214,30.307556],[9.970017,30.539325],[10.056575,30.961831],[9.950225,31.37607],[10.636901,31.761421],[10.94479,32.081815],[11.432253,32.368903],[11.488787,33.136996],[12.66331,32.79278],[13.08326,32.87882],[13.91868,32.71196],[15.24563,32.26508],[15.71394,31.37626],[16.61162,31.18218],[18.02109,30.76357],[19.08641,30.26639],[19.57404,30.52582],[20.05335,30.98576],[19.82033,31.75179],[20.13397,32.2382],[20.85452,32.7068],[21.54298,32.8432],[22.89576,32.63858],[23.2368,32.19149],[23.60913,32.18726],[23.9275,32.01667],[24.92114,31.89936],[25.16482,31.56915],[24.80287,31.08929],[24.95762,30.6616],[24.70007,30.04419],[25,29.238655],[25,25.6825],[25,22],[25,20.00304],[23.85,20],[23.83766,19.58047],[19.84926,21.49509],[15.86085,23.40972],[14.8513,22.86295]]]}},\n{\"type\":\"Feature\",\"id\":\"LKA\",\"properties\":{\"name\":\"Sri Lanka\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[81.787959,7.523055],[81.637322,6.481775],[81.21802,6.197141],[80.348357,5.96837],[79.872469,6.763463],[79.695167,8.200843],[80.147801,9.824078],[80.838818,9.268427],[81.304319,8.564206],[81.787959,7.523055]]]}},\n{\"type\":\"Feature\",\"id\":\"LSO\",\"properties\":{\"name\":\"Lesotho\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[28.978263,-28.955597],[29.325166,-29.257387],[29.018415,-29.743766],[28.8484,-30.070051],[28.291069,-30.226217],[28.107205,-30.545732],[27.749397,-30.645106],[26.999262,-29.875954],[27.532511,-29.242711],[28.074338,-28.851469],[28.5417,-28.647502],[28.978263,-28.955597]]]}},\n{\"type\":\"Feature\",\"id\":\"LTU\",\"properties\":{\"name\":\"Lithuania\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[22.731099,54.327537],[22.651052,54.582741],[22.757764,54.856574],[22.315724,55.015299],[21.268449,55.190482],[21.0558,56.031076],[22.201157,56.337802],[23.878264,56.273671],[24.860684,56.372528],[25.000934,56.164531],[25.533047,56.100297],[26.494331,55.615107],[26.588279,55.167176],[25.768433,54.846963],[25.536354,54.282423],[24.450684,53.905702],[23.484128,53.912498],[23.243987,54.220567],[22.731099,54.327537]]]}},\n{\"type\":\"Feature\",\"id\":\"LUX\",\"properties\":{\"name\":\"Luxembourg\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[6.043073,50.128052],[6.242751,49.902226],[6.18632,49.463803],[5.897759,49.442667],[5.674052,49.529484],[5.782417,50.090328],[6.043073,50.128052]]]}},\n{\"type\":\"Feature\",\"id\":\"LVA\",\"properties\":{\"name\":\"Latvia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[21.0558,56.031076],[21.090424,56.783873],[21.581866,57.411871],[22.524341,57.753374],[23.318453,57.006236],[24.12073,57.025693],[24.312863,57.793424],[25.164594,57.970157],[25.60281,57.847529],[26.463532,57.476389],[27.288185,57.474528],[27.770016,57.244258],[27.855282,56.759326],[28.176709,56.16913],[27.10246,55.783314],[26.494331,55.615107],[25.533047,56.100297],[25.000934,56.164531],[24.860684,56.372528],[23.878264,56.273671],[22.201157,56.337802],[21.0558,56.031076]]]}},\n{\"type\":\"Feature\",\"id\":\"MAR\",\"properties\":{\"name\":\"Morocco\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-5.193863,35.755182],[-4.591006,35.330712],[-3.640057,35.399855],[-2.604306,35.179093],[-2.169914,35.168396],[-1.792986,34.527919],[-1.733455,33.919713],[-1.388049,32.864015],[-1.124551,32.651522],[-1.307899,32.262889],[-2.616605,32.094346],[-3.06898,31.724498],[-3.647498,31.637294],[-3.690441,30.896952],[-4.859646,30.501188],[-5.242129,30.000443],[-6.060632,29.7317],[-7.059228,29.579228],[-8.674116,28.841289],[-8.66559,27.656426],[-8.817809,27.656426],[-8.817828,27.656426],[-8.794884,27.120696],[-9.413037,27.088476],[-9.735343,26.860945],[-10.189424,26.860945],[-10.551263,26.990808],[-11.392555,26.883424],[-11.71822,26.104092],[-12.030759,26.030866],[-12.500963,24.770116],[-13.89111,23.691009],[-14.221168,22.310163],[-14.630833,21.86094],[-14.750955,21.5006],[-17.002962,21.420734],[-17.020428,21.42231],[-16.973248,21.885745],[-16.589137,22.158234],[-16.261922,22.67934],[-16.326414,23.017768],[-15.982611,23.723358],[-15.426004,24.359134],[-15.089332,24.520261],[-14.824645,25.103533],[-14.800926,25.636265],[-14.43994,26.254418],[-13.773805,26.618892],[-13.139942,27.640148],[-13.121613,27.654148],[-12.618837,28.038186],[-11.688919,28.148644],[-10.900957,28.832142],[-10.399592,29.098586],[-9.564811,29.933574],[-9.814718,31.177736],[-9.434793,32.038096],[-9.300693,32.564679],[-8.657476,33.240245],[-7.654178,33.697065],[-6.912544,34.110476],[-6.244342,35.145865],[-5.929994,35.759988],[-5.193863,35.755182]]]}},\n{\"type\":\"Feature\",\"id\":\"MDA\",\"properties\":{\"name\":\"Moldova\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[26.619337,48.220726],[26.857824,48.368211],[27.522537,48.467119],[28.259547,48.155562],[28.670891,48.118149],[29.122698,47.849095],[29.050868,47.510227],[29.415135,47.346645],[29.559674,46.928583],[29.908852,46.674361],[29.83821,46.525326],[30.024659,46.423937],[29.759972,46.349988],[29.170654,46.379262],[29.072107,46.517678],[28.862972,46.437889],[28.933717,46.25883],[28.659987,45.939987],[28.485269,45.596907],[28.233554,45.488283],[28.054443,45.944586],[28.160018,46.371563],[28.12803,46.810476],[27.551166,47.405117],[27.233873,47.826771],[26.924176,48.123264],[26.619337,48.220726]]]}},\n{\"type\":\"Feature\",\"id\":\"MDG\",\"properties\":{\"name\":\"Madagascar\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[49.543519,-12.469833],[49.808981,-12.895285],[50.056511,-13.555761],[50.217431,-14.758789],[50.476537,-15.226512],[50.377111,-15.706069],[50.200275,-16.000263],[49.860606,-15.414253],[49.672607,-15.710204],[49.863344,-16.451037],[49.774564,-16.875042],[49.498612,-17.106036],[49.435619,-17.953064],[49.041792,-19.118781],[48.548541,-20.496888],[47.930749,-22.391501],[47.547723,-23.781959],[47.095761,-24.94163],[46.282478,-25.178463],[45.409508,-25.601434],[44.833574,-25.346101],[44.03972,-24.988345],[43.763768,-24.460677],[43.697778,-23.574116],[43.345654,-22.776904],[43.254187,-22.057413],[43.433298,-21.336475],[43.893683,-21.163307],[43.89637,-20.830459],[44.374325,-20.072366],[44.464397,-19.435454],[44.232422,-18.961995],[44.042976,-18.331387],[43.963084,-17.409945],[44.312469,-16.850496],[44.446517,-16.216219],[44.944937,-16.179374],[45.502732,-15.974373],[45.872994,-15.793454],[46.312243,-15.780018],[46.882183,-15.210182],[47.70513,-14.594303],[48.005215,-14.091233],[47.869047,-13.663869],[48.293828,-13.784068],[48.84506,-13.089175],[48.863509,-12.487868],[49.194651,-12.040557],[49.543519,-12.469833]]]}},\n{\"type\":\"Feature\",\"id\":\"MEX\",\"properties\":{\"name\":\"Mexico\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-97.140008,25.869997],[-97.528072,24.992144],[-97.702946,24.272343],[-97.776042,22.93258],[-97.872367,22.444212],[-97.699044,21.898689],[-97.38896,21.411019],[-97.189333,20.635433],[-96.525576,19.890931],[-96.292127,19.320371],[-95.900885,18.828024],[-94.839063,18.562717],[-94.42573,18.144371],[-93.548651,18.423837],[-92.786114,18.524839],[-92.037348,18.704569],[-91.407903,18.876083],[-90.77187,19.28412],[-90.53359,19.867418],[-90.451476,20.707522],[-90.278618,20.999855],[-89.601321,21.261726],[-88.543866,21.493675],[-87.658417,21.458846],[-87.05189,21.543543],[-86.811982,21.331515],[-86.845908,20.849865],[-87.383291,20.255405],[-87.621054,19.646553],[-87.43675,19.472403],[-87.58656,19.04013],[-87.837191,18.259816],[-88.090664,18.516648],[-88.300031,18.499982],[-88.490123,18.486831],[-88.848344,17.883198],[-89.029857,18.001511],[-89.150909,17.955468],[-89.14308,17.808319],[-90.067934,17.819326],[-91.00152,17.817595],[-91.002269,17.254658],[-91.453921,17.252177],[-91.08167,16.918477],[-90.711822,16.687483],[-90.600847,16.470778],[-90.438867,16.41011],[-90.464473,16.069562],[-91.74796,16.066565],[-92.229249,15.251447],[-92.087216,15.064585],[-92.20323,14.830103],[-92.22775,14.538829],[-93.359464,15.61543],[-93.875169,15.940164],[-94.691656,16.200975],[-95.250227,16.128318],[-96.053382,15.752088],[-96.557434,15.653515],[-97.263592,15.917065],[-98.01303,16.107312],[-98.947676,16.566043],[-99.697397,16.706164],[-100.829499,17.171071],[-101.666089,17.649026],[-101.918528,17.91609],[-102.478132,17.975751],[-103.50099,18.292295],[-103.917527,18.748572],[-104.99201,19.316134],[-105.493038,19.946767],[-105.731396,20.434102],[-105.397773,20.531719],[-105.500661,20.816895],[-105.270752,21.076285],[-105.265817,21.422104],[-105.603161,21.871146],[-105.693414,22.26908],[-106.028716,22.773752],[-106.90998,23.767774],[-107.915449,24.548915],[-108.401905,25.172314],[-109.260199,25.580609],[-109.444089,25.824884],[-109.291644,26.442934],[-109.801458,26.676176],[-110.391732,27.162115],[-110.641019,27.859876],[-111.178919,27.941241],[-111.759607,28.467953],[-112.228235,28.954409],[-112.271824,29.266844],[-112.809594,30.021114],[-113.163811,30.786881],[-113.148669,31.170966],[-113.871881,31.567608],[-114.205737,31.524045],[-114.776451,31.799532],[-114.9367,31.393485],[-114.771232,30.913617],[-114.673899,30.162681],[-114.330974,29.750432],[-113.588875,29.061611],[-113.424053,28.826174],[-113.271969,28.754783],[-113.140039,28.411289],[-112.962298,28.42519],[-112.761587,27.780217],[-112.457911,27.525814],[-112.244952,27.171727],[-111.616489,26.662817],[-111.284675,25.73259],[-110.987819,25.294606],[-110.710007,24.826004],[-110.655049,24.298595],[-110.172856,24.265548],[-109.771847,23.811183],[-109.409104,23.364672],[-109.433392,23.185588],[-109.854219,22.818272],[-110.031392,22.823078],[-110.295071,23.430973],[-110.949501,24.000964],[-111.670568,24.484423],[-112.182036,24.738413],[-112.148989,25.470125],[-112.300711,26.012004],[-112.777297,26.32196],[-113.464671,26.768186],[-113.59673,26.63946],[-113.848937,26.900064],[-114.465747,27.14209],[-115.055142,27.722727],[-114.982253,27.7982],[-114.570366,27.741485],[-114.199329,28.115003],[-114.162018,28.566112],[-114.931842,29.279479],[-115.518654,29.556362],[-115.887365,30.180794],[-116.25835,30.836464],[-116.721526,31.635744],[-117.12776,32.53534],[-115.99135,32.61239],[-114.72139,32.72083],[-114.815,32.52528],[-113.30498,32.03914],[-111.02361,31.33472],[-109.035,31.34194],[-108.24194,31.34222],[-108.24,31.754854],[-106.50759,31.75452],[-106.1429,31.39995],[-105.63159,31.08383],[-105.03737,30.64402],[-104.70575,30.12173],[-104.45697,29.57196],[-103.94,29.27],[-103.11,28.97],[-102.48,29.76],[-101.6624,29.7793],[-100.9576,29.38071],[-100.45584,28.69612],[-100.11,28.11],[-99.52,27.54],[-99.3,26.84],[-99.02,26.37],[-98.24,26.06],[-97.53,25.84],[-97.140008,25.869997]]]}},\n{\"type\":\"Feature\",\"id\":\"MKD\",\"properties\":{\"name\":\"Macedonia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[20.59023,41.85541],[20.71731,41.84711],[20.76216,42.05186],[21.3527,42.2068],[21.576636,42.245224],[21.91708,42.30364],[22.380526,42.32026],[22.881374,41.999297],[22.952377,41.337994],[22.76177,41.3048],[22.597308,41.130487],[22.055378,41.149866],[21.674161,40.931275],[21.02004,40.842727],[20.60518,41.08622],[20.46315,41.51509],[20.59023,41.85541]]]}},\n{\"type\":\"Feature\",\"id\":\"MLI\",\"properties\":{\"name\":\"Mali\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-12.17075,14.616834],[-11.834208,14.799097],[-11.666078,15.388208],[-11.349095,15.411256],[-10.650791,15.132746],[-10.086846,15.330486],[-9.700255,15.264107],[-9.550238,15.486497],[-5.537744,15.50169],[-5.315277,16.201854],[-5.488523,16.325102],[-5.971129,20.640833],[-6.453787,24.956591],[-4.923337,24.974574],[-1.550055,22.792666],[1.823228,20.610809],[2.060991,20.142233],[2.683588,19.85623],[3.146661,19.693579],[3.158133,19.057364],[4.267419,19.155265],[4.27021,16.852227],[3.723422,16.184284],[3.638259,15.56812],[2.749993,15.409525],[1.385528,15.323561],[1.015783,14.968182],[0.374892,14.928908],[-0.266257,14.924309],[-0.515854,15.116158],[-1.066363,14.973815],[-2.001035,14.559008],[-2.191825,14.246418],[-2.967694,13.79815],[-3.103707,13.541267],[-3.522803,13.337662],[-4.006391,13.472485],[-4.280405,13.228444],[-4.427166,12.542646],[-5.220942,11.713859],[-5.197843,11.375146],[-5.470565,10.95127],[-5.404342,10.370737],[-5.816926,10.222555],[-6.050452,10.096361],[-6.205223,10.524061],[-6.493965,10.411303],[-6.666461,10.430811],[-6.850507,10.138994],[-7.622759,10.147236],[-7.89959,10.297382],[-8.029944,10.206535],[-8.335377,10.494812],[-8.282357,10.792597],[-8.407311,10.909257],[-8.620321,10.810891],[-8.581305,11.136246],[-8.376305,11.393646],[-8.786099,11.812561],[-8.905265,12.088358],[-9.127474,12.30806],[-9.327616,12.334286],[-9.567912,12.194243],[-9.890993,12.060479],[-10.165214,11.844084],[-10.593224,11.923975],[-10.87083,12.177887],[-11.036556,12.211245],[-11.297574,12.077971],[-11.456169,12.076834],[-11.513943,12.442988],[-11.467899,12.754519],[-11.553398,13.141214],[-11.927716,13.422075],[-12.124887,13.994727],[-12.17075,14.616834]]]}},\n{\"type\":\"Feature\",\"id\":\"MLT\",\"properties\":{\"name\":\"Malta\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[14.566171,35.852721],[14.532684,35.820191],[14.436463,35.821664],[14.352334,35.872281],[14.3513,35.978399],[14.448348,35.957444],[14.537025,35.886285],[14.566171,35.852721]]],[[[14.313473,36.027569],[14.253632,36.012143],[14.194204,36.042245],[14.180354,36.060383],[14.263243,36.075809],[14.303758,36.062295],[14.320914,36.03625],[14.313473,36.027569]]]]}},\n{\"type\":\"Feature\",\"id\":\"MMR\",\"properties\":{\"name\":\"Myanmar\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[99.543309,20.186598],[98.959676,19.752981],[98.253724,19.708203],[97.797783,18.62708],[97.375896,18.445438],[97.859123,17.567946],[98.493761,16.837836],[98.903348,16.177824],[98.537376,15.308497],[98.192074,15.123703],[98.430819,14.622028],[99.097755,13.827503],[99.212012,13.269294],[99.196354,12.804748],[99.587286,11.892763],[99.038121,10.960546],[98.553551,9.93296],[98.457174,10.675266],[98.764546,11.441292],[98.428339,12.032987],[98.509574,13.122378],[98.103604,13.64046],[97.777732,14.837286],[97.597072,16.100568],[97.16454,16.928734],[96.505769,16.427241],[95.369352,15.71439],[94.808405,15.803454],[94.188804,16.037936],[94.533486,17.27724],[94.324817,18.213514],[93.540988,19.366493],[93.663255,19.726962],[93.078278,19.855145],[92.368554,20.670883],[92.303234,21.475485],[92.652257,21.324048],[92.672721,22.041239],[93.166128,22.27846],[93.060294,22.703111],[93.286327,23.043658],[93.325188,24.078556],[94.106742,23.850741],[94.552658,24.675238],[94.603249,25.162495],[95.155153,26.001307],[95.124768,26.573572],[96.419366,27.264589],[97.133999,27.083774],[97.051989,27.699059],[97.402561,27.882536],[97.327114,28.261583],[97.911988,28.335945],[98.246231,27.747221],[98.68269,27.508812],[98.712094,26.743536],[98.671838,25.918703],[97.724609,25.083637],[97.60472,23.897405],[98.660262,24.063286],[98.898749,23.142722],[99.531992,22.949039],[99.240899,22.118314],[99.983489,21.742937],[100.416538,21.558839],[101.150033,21.849984],[101.180005,21.436573],[100.329101,20.786122],[100.115988,20.41785],[99.543309,20.186598]]]}},\n{\"type\":\"Feature\",\"id\":\"MNE\",\"properties\":{\"name\":\"Montenegro\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[19.801613,42.500093],[19.738051,42.688247],[19.30449,42.19574],[19.37177,41.87755],[19.16246,41.95502],[18.88214,42.28151],[18.45,42.48],[18.56,42.65],[18.70648,43.20011],[19.03165,43.43253],[19.21852,43.52384],[19.48389,43.35229],[19.63,43.21378],[19.95857,43.10604],[20.3398,42.89852],[20.25758,42.81275],[20.0707,42.58863],[19.801613,42.500093]]]}},\n{\"type\":\"Feature\",\"id\":\"MNG\",\"properties\":{\"name\":\"Mongolia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[87.751264,49.297198],[88.805567,49.470521],[90.713667,50.331812],[92.234712,50.802171],[93.104219,50.49529],[94.147566,50.480537],[94.815949,50.013433],[95.814028,49.977467],[97.259728,49.726061],[98.231762,50.422401],[97.82574,51.010995],[98.861491,52.047366],[99.981732,51.634006],[100.88948,51.516856],[102.065223,51.259921],[102.255909,50.510561],[103.676545,50.089966],[104.621552,50.275329],[105.886591,50.406019],[106.888804,50.274296],[107.868176,49.793705],[108.475167,49.282548],[109.402449,49.292961],[110.662011,49.130128],[111.581231,49.377968],[112.89774,49.543565],[114.362456,50.248303],[114.96211,50.140247],[115.485695,49.805177],[116.678801,49.888531],[116.191802,49.134598],[115.485282,48.135383],[115.742837,47.726545],[116.308953,47.85341],[117.295507,47.697709],[118.064143,48.06673],[118.866574,47.74706],[119.772824,47.048059],[119.66327,46.69268],[118.874326,46.805412],[117.421701,46.672733],[116.717868,46.388202],[115.985096,45.727235],[114.460332,45.339817],[113.463907,44.808893],[112.436062,45.011646],[111.873306,45.102079],[111.348377,44.457442],[111.667737,44.073176],[111.829588,43.743118],[111.129682,43.406834],[110.412103,42.871234],[109.243596,42.519446],[107.744773,42.481516],[106.129316,42.134328],[104.964994,41.59741],[104.522282,41.908347],[103.312278,41.907468],[101.83304,42.514873],[100.845866,42.663804],[99.515817,42.524691],[97.451757,42.74889],[96.349396,42.725635],[95.762455,43.319449],[95.306875,44.241331],[94.688929,44.352332],[93.480734,44.975472],[92.133891,45.115076],[90.94554,45.286073],[90.585768,45.719716],[90.970809,46.888146],[90.280826,47.693549],[88.854298,48.069082],[88.013832,48.599463],[87.751264,49.297198]]]}},\n{\"type\":\"Feature\",\"id\":\"MOZ\",\"properties\":{\"name\":\"Mozambique\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[34.559989,-11.52002],[35.312398,-11.439146],[36.514082,-11.720938],[36.775151,-11.594537],[37.471284,-11.568751],[37.827645,-11.268769],[38.427557,-11.285202],[39.52103,-10.896854],[40.316589,-10.317096],[40.478387,-10.765441],[40.437253,-11.761711],[40.560811,-12.639177],[40.59962,-14.201975],[40.775475,-14.691764],[40.477251,-15.406294],[40.089264,-16.100774],[39.452559,-16.720891],[38.538351,-17.101023],[37.411133,-17.586368],[36.281279,-18.659688],[35.896497,-18.84226],[35.1984,-19.552811],[34.786383,-19.784012],[34.701893,-20.497043],[35.176127,-21.254361],[35.373428,-21.840837],[35.385848,-22.14],[35.562546,-22.09],[35.533935,-23.070788],[35.371774,-23.535359],[35.60747,-23.706563],[35.458746,-24.12261],[35.040735,-24.478351],[34.215824,-24.816314],[33.01321,-25.357573],[32.574632,-25.727318],[32.660363,-26.148584],[32.915955,-26.215867],[32.83012,-26.742192],[32.071665,-26.73382],[31.985779,-26.29178],[31.837778,-25.843332],[31.752408,-25.484284],[31.930589,-24.369417],[31.670398,-23.658969],[31.191409,-22.25151],[32.244988,-21.116489],[32.508693,-20.395292],[32.659743,-20.30429],[32.772708,-19.715592],[32.611994,-19.419383],[32.654886,-18.67209],[32.849861,-17.979057],[32.847639,-16.713398],[32.328239,-16.392074],[31.852041,-16.319417],[31.636498,-16.07199],[31.173064,-15.860944],[30.338955,-15.880839],[30.274256,-15.507787],[30.179481,-14.796099],[33.214025,-13.97186],[33.7897,-14.451831],[34.064825,-14.35995],[34.459633,-14.61301],[34.517666,-15.013709],[34.307291,-15.478641],[34.381292,-16.18356],[35.03381,-16.8013],[35.339063,-16.10744],[35.771905,-15.896859],[35.686845,-14.611046],[35.267956,-13.887834],[34.907151,-13.565425],[34.559989,-13.579998],[34.280006,-12.280025],[34.559989,-11.52002]]]}},\n{\"type\":\"Feature\",\"id\":\"MRT\",\"properties\":{\"name\":\"Mauritania\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-12.17075,14.616834],[-12.830658,15.303692],[-13.435738,16.039383],[-14.099521,16.304302],[-14.577348,16.598264],[-15.135737,16.587282],[-15.623666,16.369337],[-16.12069,16.455663],[-16.463098,16.135036],[-16.549708,16.673892],[-16.270552,17.166963],[-16.146347,18.108482],[-16.256883,19.096716],[-16.377651,19.593817],[-16.277838,20.092521],[-16.536324,20.567866],[-17.063423,20.999752],[-16.845194,21.333323],[-12.929102,21.327071],[-13.118754,22.77122],[-12.874222,23.284832],[-11.937224,23.374594],[-11.969419,25.933353],[-8.687294,25.881056],[-8.6844,27.395744],[-4.923337,24.974574],[-6.453787,24.956591],[-5.971129,20.640833],[-5.488523,16.325102],[-5.315277,16.201854],[-5.537744,15.50169],[-9.550238,15.486497],[-9.700255,15.264107],[-10.086846,15.330486],[-10.650791,15.132746],[-11.349095,15.411256],[-11.666078,15.388208],[-11.834208,14.799097],[-12.17075,14.616834]]]}},\n{\"type\":\"Feature\",\"id\":\"MWI\",\"properties\":{\"name\":\"Malawi\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[34.559989,-11.52002],[34.280006,-12.280025],[34.559989,-13.579998],[34.907151,-13.565425],[35.267956,-13.887834],[35.686845,-14.611046],[35.771905,-15.896859],[35.339063,-16.10744],[35.03381,-16.8013],[34.381292,-16.18356],[34.307291,-15.478641],[34.517666,-15.013709],[34.459633,-14.61301],[34.064825,-14.35995],[33.7897,-14.451831],[33.214025,-13.97186],[32.688165,-13.712858],[32.991764,-12.783871],[33.306422,-12.435778],[33.114289,-11.607198],[33.31531,-10.79655],[33.485688,-10.525559],[33.231388,-9.676722],[32.759375,-9.230599],[33.739729,-9.417151],[33.940838,-9.693674],[34.280006,-10.16],[34.559989,-11.52002]]]}},\n{\"type\":\"Feature\",\"id\":\"MYS\",\"properties\":{\"name\":\"Malaysia\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[101.075516,6.204867],[101.154219,5.691384],[101.814282,5.810808],[102.141187,6.221636],[102.371147,6.128205],[102.961705,5.524495],[103.381215,4.855001],[103.438575,4.181606],[103.332122,3.726698],[103.429429,3.382869],[103.502448,2.791019],[103.854674,2.515454],[104.247932,1.631141],[104.228811,1.293048],[103.519707,1.226334],[102.573615,1.967115],[101.390638,2.760814],[101.27354,3.270292],[100.695435,3.93914],[100.557408,4.76728],[100.196706,5.312493],[100.30626,6.040562],[100.085757,6.464489],[100.259596,6.642825],[101.075516,6.204867]]],[[[118.618321,4.478202],[117.882035,4.137551],[117.015214,4.306094],[115.865517,4.306559],[115.519078,3.169238],[115.134037,2.821482],[114.621355,1.430688],[113.80585,1.217549],[112.859809,1.49779],[112.380252,1.410121],[111.797548,0.904441],[111.159138,0.976478],[110.514061,0.773131],[109.830227,1.338136],[109.66326,2.006467],[110.396135,1.663775],[111.168853,1.850637],[111.370081,2.697303],[111.796928,2.885897],[112.995615,3.102395],[113.712935,3.893509],[114.204017,4.525874],[114.659596,4.007637],[114.869557,4.348314],[115.347461,4.316636],[115.4057,4.955228],[115.45071,5.44773],[116.220741,6.143191],[116.725103,6.924771],[117.129626,6.928053],[117.643393,6.422166],[117.689075,5.98749],[118.347691,5.708696],[119.181904,5.407836],[119.110694,5.016128],[118.439727,4.966519],[118.618321,4.478202]]]]}},\n{\"type\":\"Feature\",\"id\":\"NAM\",\"properties\":{\"name\":\"Namibia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[16.344977,-28.576705],[15.601818,-27.821247],[15.210472,-27.090956],[14.989711,-26.117372],[14.743214,-25.39292],[14.408144,-23.853014],[14.385717,-22.656653],[14.257714,-22.111208],[13.868642,-21.699037],[13.352498,-20.872834],[12.826845,-19.673166],[12.608564,-19.045349],[11.794919,-18.069129],[11.734199,-17.301889],[12.215461,-17.111668],[12.814081,-16.941343],[13.462362,-16.971212],[14.058501,-17.423381],[14.209707,-17.353101],[18.263309,-17.309951],[18.956187,-17.789095],[21.377176,-17.930636],[23.215048,-17.523116],[24.033862,-17.295843],[24.682349,-17.353411],[25.07695,-17.578823],[25.084443,-17.661816],[24.520705,-17.887125],[24.217365,-17.889347],[23.579006,-18.281261],[23.196858,-17.869038],[21.65504,-18.219146],[20.910641,-18.252219],[20.881134,-21.814327],[19.895458,-21.849157],[19.895768,-24.76779],[19.894734,-28.461105],[19.002127,-28.972443],[18.464899,-29.045462],[17.836152,-28.856378],[17.387497,-28.783514],[17.218929,-28.355943],[16.824017,-28.082162],[16.344977,-28.576705]]]}},\n{\"type\":\"Feature\",\"id\":\"NCL\",\"properties\":{\"name\":\"New Caledonia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[165.77999,-21.080005],[166.599991,-21.700019],[167.120011,-22.159991],[166.740035,-22.399976],[166.189732,-22.129708],[165.474375,-21.679607],[164.829815,-21.14982],[164.167995,-20.444747],[164.029606,-20.105646],[164.459967,-20.120012],[165.020036,-20.459991],[165.460009,-20.800022],[165.77999,-21.080005]]]}},\n{\"type\":\"Feature\",\"id\":\"NER\",\"properties\":{\"name\":\"Niger\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[2.154474,11.94015],[2.177108,12.625018],[1.024103,12.851826],[0.993046,13.33575],[0.429928,13.988733],[0.295646,14.444235],[0.374892,14.928908],[1.015783,14.968182],[1.385528,15.323561],[2.749993,15.409525],[3.638259,15.56812],[3.723422,16.184284],[4.27021,16.852227],[4.267419,19.155265],[5.677566,19.601207],[8.572893,21.565661],[11.999506,23.471668],[13.581425,23.040506],[14.143871,22.491289],[14.8513,22.86295],[15.096888,21.308519],[15.471077,21.048457],[15.487148,20.730415],[15.903247,20.387619],[15.685741,19.95718],[15.300441,17.92795],[15.247731,16.627306],[13.972202,15.684366],[13.540394,14.367134],[13.956699,13.996691],[13.954477,13.353449],[14.595781,13.330427],[14.495787,12.859396],[14.213531,12.802035],[14.181336,12.483657],[13.995353,12.461565],[13.318702,13.556356],[13.083987,13.596147],[12.302071,13.037189],[11.527803,13.32898],[10.989593,13.387323],[10.701032,13.246918],[10.114814,13.277252],[9.524928,12.851102],[9.014933,12.826659],[7.804671,13.343527],[7.330747,13.098038],[6.820442,13.115091],[6.445426,13.492768],[5.443058,13.865924],[4.368344,13.747482],[4.107946,13.531216],[3.967283,12.956109],[3.680634,12.552903],[3.61118,11.660167],[2.848643,12.235636],[2.490164,12.233052],[2.154474,11.94015]]]}},\n{\"type\":\"Feature\",\"id\":\"NGA\",\"properties\":{\"name\":\"Nigeria\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[8.500288,4.771983],[7.462108,4.412108],[7.082596,4.464689],[6.698072,4.240594],[5.898173,4.262453],[5.362805,4.887971],[5.033574,5.611802],[4.325607,6.270651],[3.57418,6.2583],[2.691702,6.258817],[2.749063,7.870734],[2.723793,8.506845],[2.912308,9.137608],[3.220352,9.444153],[3.705438,10.06321],[3.60007,10.332186],[3.797112,10.734746],[3.572216,11.327939],[3.61118,11.660167],[3.680634,12.552903],[3.967283,12.956109],[4.107946,13.531216],[4.368344,13.747482],[5.443058,13.865924],[6.445426,13.492768],[6.820442,13.115091],[7.330747,13.098038],[7.804671,13.343527],[9.014933,12.826659],[9.524928,12.851102],[10.114814,13.277252],[10.701032,13.246918],[10.989593,13.387323],[11.527803,13.32898],[12.302071,13.037189],[13.083987,13.596147],[13.318702,13.556356],[13.995353,12.461565],[14.181336,12.483657],[14.577178,12.085361],[14.468192,11.904752],[14.415379,11.572369],[13.57295,10.798566],[13.308676,10.160362],[13.1676,9.640626],[12.955468,9.417772],[12.753672,8.717763],[12.218872,8.305824],[12.063946,7.799808],[11.839309,7.397042],[11.745774,6.981383],[11.058788,6.644427],[10.497375,7.055358],[10.118277,7.03877],[9.522706,6.453482],[9.233163,6.444491],[8.757533,5.479666],[8.500288,4.771983]]]}},\n{\"type\":\"Feature\",\"id\":\"NIC\",\"properties\":{\"name\":\"Nicaragua\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-85.71254,11.088445],[-86.058488,11.403439],[-86.52585,11.806877],[-86.745992,12.143962],[-87.167516,12.458258],[-87.668493,12.90991],[-87.557467,13.064552],[-87.392386,12.914018],[-87.316654,12.984686],[-87.005769,13.025794],[-86.880557,13.254204],[-86.733822,13.263093],[-86.755087,13.754845],[-86.520708,13.778487],[-86.312142,13.771356],[-86.096264,14.038187],[-85.801295,13.836055],[-85.698665,13.960078],[-85.514413,14.079012],[-85.165365,14.35437],[-85.148751,14.560197],[-85.052787,14.551541],[-84.924501,14.790493],[-84.820037,14.819587],[-84.649582,14.666805],[-84.449336,14.621614],[-84.228342,14.748764],[-83.975721,14.749436],[-83.628585,14.880074],[-83.489989,15.016267],[-83.147219,14.995829],[-83.233234,14.899866],[-83.284162,14.676624],[-83.182126,14.310703],[-83.4125,13.970078],[-83.519832,13.567699],[-83.552207,13.127054],[-83.498515,12.869292],[-83.473323,12.419087],[-83.626104,12.32085],[-83.719613,11.893124],[-83.650858,11.629032],[-83.85547,11.373311],[-83.808936,11.103044],[-83.655612,10.938764],[-83.895054,10.726839],[-84.190179,10.79345],[-84.355931,10.999226],[-84.673069,11.082657],[-84.903003,10.952303],[-85.561852,11.217119],[-85.71254,11.088445]]]}},\n{\"type\":\"Feature\",\"id\":\"NLD\",\"properties\":{\"name\":\"Netherlands\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[6.074183,53.510403],[6.90514,53.482162],[7.092053,53.144043],[6.84287,52.22844],[6.589397,51.852029],[5.988658,51.851616],[6.156658,50.803721],[5.606976,51.037298],[4.973991,51.475024],[4.047071,51.267259],[3.314971,51.345755],[3.830289,51.620545],[4.705997,53.091798],[6.074183,53.510403]]]}},\n{\"type\":\"Feature\",\"id\":\"NOR\",\"properties\":{\"name\":\"Norway\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[28.165547,71.185474],[31.293418,70.453788],[30.005435,70.186259],[31.101079,69.55808],[29.399581,69.156916],[28.59193,69.064777],[29.015573,69.766491],[27.732292,70.164193],[26.179622,69.825299],[25.689213,69.092114],[24.735679,68.649557],[23.66205,68.891247],[22.356238,68.841741],[21.244936,69.370443],[20.645593,69.106247],[20.025269,69.065139],[19.87856,68.407194],[17.993868,68.567391],[17.729182,68.010552],[16.768879,68.013937],[16.108712,67.302456],[15.108411,66.193867],[13.55569,64.787028],[13.919905,64.445421],[13.571916,64.049114],[12.579935,64.066219],[11.930569,63.128318],[11.992064,61.800362],[12.631147,61.293572],[12.300366,60.117933],[11.468272,59.432393],[11.027369,58.856149],[10.356557,59.469807],[8.382,58.313288],[7.048748,58.078884],[5.665835,58.588155],[5.308234,59.663232],[4.992078,61.970998],[5.9129,62.614473],[8.553411,63.454008],[10.527709,64.486038],[12.358347,65.879726],[14.761146,67.810642],[16.435927,68.563205],[19.184028,69.817444],[21.378416,70.255169],[23.023742,70.202072],[24.546543,71.030497],[26.37005,70.986262],[28.165547,71.185474]]],[[[24.72412,77.85385],[22.49032,77.44493],[20.72601,77.67704],[21.41611,77.93504],[20.8119,78.25463],[22.88426,78.45494],[23.28134,78.07954],[24.72412,77.85385]]],[[[18.25183,79.70175],[21.54383,78.95611],[19.02737,78.5626],[18.47172,77.82669],[17.59441,77.63796],[17.1182,76.80941],[15.91315,76.77045],[13.76259,77.38035],[14.66956,77.73565],[13.1706,78.02493],[11.22231,78.8693],[10.44453,79.65239],[13.17077,80.01046],[13.71852,79.66039],[15.14282,79.67431],[15.52255,80.01608],[16.99085,80.05086],[18.25183,79.70175]]],[[[25.447625,80.40734],[27.407506,80.056406],[25.924651,79.517834],[23.024466,79.400012],[20.075188,79.566823],[19.897266,79.842362],[18.462264,79.85988],[17.368015,80.318896],[20.455992,80.598156],[21.907945,80.357679],[22.919253,80.657144],[25.447625,80.40734]]]]}},\n{\"type\":\"Feature\",\"id\":\"NPL\",\"properties\":{\"name\":\"Nepal\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[88.120441,27.876542],[88.043133,27.445819],[88.174804,26.810405],[88.060238,26.414615],[87.227472,26.397898],[86.024393,26.630985],[85.251779,26.726198],[84.675018,27.234901],[83.304249,27.364506],[81.999987,27.925479],[81.057203,28.416095],[80.088425,28.79447],[80.476721,29.729865],[81.111256,30.183481],[81.525804,30.422717],[82.327513,30.115268],[83.337115,29.463732],[83.898993,29.320226],[84.23458,28.839894],[85.011638,28.642774],[85.82332,28.203576],[86.954517,27.974262],[88.120441,27.876542]]]}},\n{\"type\":\"Feature\",\"id\":\"NZL\",\"properties\":{\"name\":\"New Zealand\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[173.020375,-40.919052],[173.247234,-41.331999],[173.958405,-40.926701],[174.247587,-41.349155],[174.248517,-41.770008],[173.876447,-42.233184],[173.22274,-42.970038],[172.711246,-43.372288],[173.080113,-43.853344],[172.308584,-43.865694],[171.452925,-44.242519],[171.185138,-44.897104],[170.616697,-45.908929],[169.831422,-46.355775],[169.332331,-46.641235],[168.411354,-46.619945],[167.763745,-46.290197],[166.676886,-46.219917],[166.509144,-45.852705],[167.046424,-45.110941],[168.303763,-44.123973],[168.949409,-43.935819],[169.667815,-43.555326],[170.52492,-43.031688],[171.12509,-42.512754],[171.569714,-41.767424],[171.948709,-41.514417],[172.097227,-40.956104],[172.79858,-40.493962],[173.020375,-40.919052]]],[[[174.612009,-36.156397],[175.336616,-37.209098],[175.357596,-36.526194],[175.808887,-36.798942],[175.95849,-37.555382],[176.763195,-37.881253],[177.438813,-37.961248],[178.010354,-37.579825],[178.517094,-37.695373],[178.274731,-38.582813],[177.97046,-39.166343],[177.206993,-39.145776],[176.939981,-39.449736],[177.032946,-39.879943],[176.885824,-40.065978],[176.508017,-40.604808],[176.01244,-41.289624],[175.239567,-41.688308],[175.067898,-41.425895],[174.650973,-41.281821],[175.22763,-40.459236],[174.900157,-39.908933],[173.824047,-39.508854],[173.852262,-39.146602],[174.574802,-38.797683],[174.743474,-38.027808],[174.697017,-37.381129],[174.292028,-36.711092],[174.319004,-36.534824],[173.840997,-36.121981],[173.054171,-35.237125],[172.636005,-34.529107],[173.007042,-34.450662],[173.551298,-35.006183],[174.32939,-35.265496],[174.612009,-36.156397]]]]}},\n{\"type\":\"Feature\",\"id\":\"OMN\",\"properties\":{\"name\":\"Oman\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[58.861141,21.114035],[58.487986,20.428986],[58.034318,20.481437],[57.826373,20.243002],[57.665762,19.736005],[57.7887,19.06757],[57.694391,18.94471],[57.234264,18.947991],[56.609651,18.574267],[56.512189,18.087113],[56.283521,17.876067],[55.661492,17.884128],[55.269939,17.632309],[55.2749,17.228354],[54.791002,16.950697],[54.239253,17.044981],[53.570508,16.707663],[53.108573,16.651051],[52.782184,17.349742],[52.00001,19.000003],[54.999982,19.999994],[55.666659,22.000001],[55.208341,22.70833],[55.234489,23.110993],[55.525841,23.524869],[55.528632,23.933604],[55.981214,24.130543],[55.804119,24.269604],[55.886233,24.920831],[56.396847,24.924732],[56.84514,24.241673],[57.403453,23.878594],[58.136948,23.747931],[58.729211,23.565668],[59.180502,22.992395],[59.450098,22.660271],[59.80806,22.533612],[59.806148,22.310525],[59.442191,21.714541],[59.282408,21.433886],[58.861141,21.114035]]],[[[56.391421,25.895991],[56.261042,25.714606],[56.070821,26.055464],[56.362017,26.395934],[56.485679,26.309118],[56.391421,25.895991]]]]}},\n{\"type\":\"Feature\",\"id\":\"PAK\",\"properties\":{\"name\":\"Pakistan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[75.158028,37.133031],[75.896897,36.666806],[76.192848,35.898403],[77.837451,35.49401],[76.871722,34.653544],[75.757061,34.504923],[74.240203,34.748887],[73.749948,34.317699],[74.104294,33.441473],[74.451559,32.7649],[75.258642,32.271105],[74.405929,31.692639],[74.42138,30.979815],[73.450638,29.976413],[72.823752,28.961592],[71.777666,27.91318],[70.616496,27.989196],[69.514393,26.940966],[70.168927,26.491872],[70.282873,25.722229],[70.844699,25.215102],[71.04324,24.356524],[68.842599,24.359134],[68.176645,23.691965],[67.443667,23.944844],[67.145442,24.663611],[66.372828,25.425141],[64.530408,25.237039],[62.905701,25.218409],[61.497363,25.078237],[61.874187,26.239975],[63.316632,26.756532],[63.233898,27.217047],[62.755426,27.378923],[62.72783,28.259645],[61.771868,28.699334],[61.369309,29.303276],[60.874248,29.829239],[62.549857,29.318572],[63.550261,29.468331],[64.148002,29.340819],[64.350419,29.560031],[65.046862,29.472181],[66.346473,29.887943],[66.381458,30.738899],[66.938891,31.304911],[67.683394,31.303154],[67.792689,31.58293],[68.556932,31.71331],[68.926677,31.620189],[69.317764,31.901412],[69.262522,32.501944],[69.687147,33.105499],[70.323594,33.358533],[69.930543,34.02012],[70.881803,33.988856],[71.156773,34.348911],[71.115019,34.733126],[71.613076,35.153203],[71.498768,35.650563],[71.262348,36.074388],[71.846292,36.509942],[72.920025,36.720007],[74.067552,36.836176],[74.575893,37.020841],[75.158028,37.133031]]]}},\n{\"type\":\"Feature\",\"id\":\"PAN\",\"properties\":{\"name\":\"Panama\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-77.881571,7.223771],[-78.214936,7.512255],[-78.429161,8.052041],[-78.182096,8.319182],[-78.435465,8.387705],[-78.622121,8.718124],[-79.120307,8.996092],[-79.557877,8.932375],[-79.760578,8.584515],[-80.164481,8.333316],[-80.382659,8.298409],[-80.480689,8.090308],[-80.00369,7.547524],[-80.276671,7.419754],[-80.421158,7.271572],[-80.886401,7.220541],[-81.059543,7.817921],[-81.189716,7.647906],[-81.519515,7.70661],[-81.721311,8.108963],[-82.131441,8.175393],[-82.390934,8.292362],[-82.820081,8.290864],[-82.850958,8.073823],[-82.965783,8.225028],[-82.913176,8.423517],[-82.829771,8.626295],[-82.868657,8.807266],[-82.719183,8.925709],[-82.927155,9.07433],[-82.932891,9.476812],[-82.546196,9.566135],[-82.187123,9.207449],[-82.207586,8.995575],[-81.808567,8.950617],[-81.714154,9.031955],[-81.439287,8.786234],[-80.947302,8.858504],[-80.521901,9.111072],[-79.9146,9.312765],[-79.573303,9.61161],[-79.021192,9.552931],[-79.05845,9.454565],[-78.500888,9.420459],[-78.055928,9.24773],[-77.729514,8.946844],[-77.353361,8.670505],[-77.474723,8.524286],[-77.242566,7.935278],[-77.431108,7.638061],[-77.753414,7.70984],[-77.881571,7.223771]]]}},\n{\"type\":\"Feature\",\"id\":\"PER\",\"properties\":{\"name\":\"Peru\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-69.590424,-17.580012],[-69.858444,-18.092694],[-70.372572,-18.347975],[-71.37525,-17.773799],[-71.462041,-17.363488],[-73.44453,-16.359363],[-75.237883,-15.265683],[-76.009205,-14.649286],[-76.423469,-13.823187],[-76.259242,-13.535039],[-77.106192,-12.222716],[-78.092153,-10.377712],[-79.036953,-8.386568],[-79.44592,-7.930833],[-79.760578,-7.194341],[-80.537482,-6.541668],[-81.249996,-6.136834],[-80.926347,-5.690557],[-81.410943,-4.736765],[-81.09967,-4.036394],[-80.302561,-3.404856],[-80.184015,-3.821162],[-80.469295,-4.059287],[-80.442242,-4.425724],[-80.028908,-4.346091],[-79.624979,-4.454198],[-79.205289,-4.959129],[-78.639897,-4.547784],[-78.450684,-3.873097],[-77.837905,-3.003021],[-76.635394,-2.608678],[-75.544996,-1.56161],[-75.233723,-0.911417],[-75.373223,-0.152032],[-75.106625,-0.057205],[-74.441601,-0.53082],[-74.122395,-1.002833],[-73.659504,-1.260491],[-73.070392,-2.308954],[-72.325787,-2.434218],[-71.774761,-2.16979],[-71.413646,-2.342802],[-70.813476,-2.256865],[-70.047709,-2.725156],[-70.692682,-3.742872],[-70.394044,-3.766591],[-69.893635,-4.298187],[-70.794769,-4.251265],[-70.928843,-4.401591],[-71.748406,-4.593983],[-72.891928,-5.274561],[-72.964507,-5.741251],[-73.219711,-6.089189],[-73.120027,-6.629931],[-73.724487,-6.918595],[-73.723401,-7.340999],[-73.987235,-7.52383],[-73.571059,-8.424447],[-73.015383,-9.032833],[-73.226713,-9.462213],[-72.563033,-9.520194],[-72.184891,-10.053598],[-71.302412,-10.079436],[-70.481894,-9.490118],[-70.548686,-11.009147],[-70.093752,-11.123972],[-69.529678,-10.951734],[-68.66508,-12.5613],[-68.88008,-12.899729],[-68.929224,-13.602684],[-68.948887,-14.453639],[-69.339535,-14.953195],[-69.160347,-15.323974],[-69.389764,-15.660129],[-68.959635,-16.500698],[-69.590424,-17.580012]]]}},\n{\"type\":\"Feature\",\"id\":\"PHL\",\"properties\":{\"name\":\"Philippines\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[126.376814,8.414706],[126.478513,7.750354],[126.537424,7.189381],[126.196773,6.274294],[125.831421,7.293715],[125.363852,6.786485],[125.683161,6.049657],[125.396512,5.581003],[124.219788,6.161355],[123.93872,6.885136],[124.243662,7.36061],[123.610212,7.833527],[123.296071,7.418876],[122.825506,7.457375],[122.085499,6.899424],[121.919928,7.192119],[122.312359,8.034962],[122.942398,8.316237],[123.487688,8.69301],[123.841154,8.240324],[124.60147,8.514158],[124.764612,8.960409],[125.471391,8.986997],[125.412118,9.760335],[126.222714,9.286074],[126.306637,8.782487],[126.376814,8.414706]]],[[[123.982438,10.278779],[123.623183,9.950091],[123.309921,9.318269],[122.995883,9.022189],[122.380055,9.713361],[122.586089,9.981045],[122.837081,10.261157],[122.947411,10.881868],[123.49885,10.940624],[123.337774,10.267384],[124.077936,11.232726],[123.982438,10.278779]]],[[[118.504581,9.316383],[117.174275,8.3675],[117.664477,9.066889],[118.386914,9.6845],[118.987342,10.376292],[119.511496,11.369668],[119.689677,10.554291],[119.029458,10.003653],[118.504581,9.316383]]],[[[121.883548,11.891755],[122.483821,11.582187],[123.120217,11.58366],[123.100838,11.165934],[122.637714,10.741308],[122.00261,10.441017],[121.967367,10.905691],[122.03837,11.415841],[121.883548,11.891755]]],[[[125.502552,12.162695],[125.783465,11.046122],[125.011884,11.311455],[125.032761,10.975816],[125.277449,10.358722],[124.801819,10.134679],[124.760168,10.837995],[124.459101,10.88993],[124.302522,11.495371],[124.891013,11.415583],[124.87799,11.79419],[124.266762,12.557761],[125.227116,12.535721],[125.502552,12.162695]]],[[[121.527394,13.06959],[121.26219,12.20556],[120.833896,12.704496],[120.323436,13.466413],[121.180128,13.429697],[121.527394,13.06959]]],[[[121.321308,18.504065],[121.937601,18.218552],[122.246006,18.47895],[122.336957,18.224883],[122.174279,17.810283],[122.515654,17.093505],[122.252311,16.262444],[121.662786,15.931018],[121.50507,15.124814],[121.728829,14.328376],[122.258925,14.218202],[122.701276,14.336541],[123.950295,13.782131],[123.855107,13.237771],[124.181289,12.997527],[124.077419,12.536677],[123.298035,13.027526],[122.928652,13.55292],[122.671355,13.185836],[122.03465,13.784482],[121.126385,13.636687],[120.628637,13.857656],[120.679384,14.271016],[120.991819,14.525393],[120.693336,14.756671],[120.564145,14.396279],[120.070429,14.970869],[119.920929,15.406347],[119.883773,16.363704],[120.286488,16.034629],[120.390047,17.599081],[120.715867,18.505227],[121.321308,18.504065]]]]}},\n{\"type\":\"Feature\",\"id\":\"PNG\",\"properties\":{\"name\":\"Papua New Guinea\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[155.880026,-6.819997],[155.599991,-6.919991],[155.166994,-6.535931],[154.729192,-5.900828],[154.514114,-5.139118],[154.652504,-5.042431],[154.759991,-5.339984],[155.062918,-5.566792],[155.547746,-6.200655],[156.019965,-6.540014],[155.880026,-6.819997]]],[[[151.982796,-5.478063],[151.459107,-5.56028],[151.30139,-5.840728],[150.754447,-6.083763],[150.241197,-6.317754],[149.709963,-6.316513],[148.890065,-6.02604],[148.318937,-5.747142],[148.401826,-5.437756],[149.298412,-5.583742],[149.845562,-5.505503],[149.99625,-5.026101],[150.139756,-5.001348],[150.236908,-5.53222],[150.807467,-5.455842],[151.089672,-5.113693],[151.647881,-4.757074],[151.537862,-4.167807],[152.136792,-4.14879],[152.338743,-4.312966],[152.318693,-4.867661],[151.982796,-5.478063]]],[[[147.191874,-7.388024],[148.084636,-8.044108],[148.734105,-9.104664],[149.306835,-9.071436],[149.266631,-9.514406],[150.038728,-9.684318],[149.738798,-9.872937],[150.801628,-10.293687],[150.690575,-10.582713],[150.028393,-10.652476],[149.78231,-10.393267],[148.923138,-10.280923],[147.913018,-10.130441],[147.135443,-9.492444],[146.567881,-8.942555],[146.048481,-8.067414],[144.744168,-7.630128],[143.897088,-7.91533],[143.286376,-8.245491],[143.413913,-8.983069],[142.628431,-9.326821],[142.068259,-9.159596],[141.033852,-9.117893],[141.017057,-5.859022],[141.00021,-2.600151],[142.735247,-3.289153],[144.583971,-3.861418],[145.27318,-4.373738],[145.829786,-4.876498],[145.981922,-5.465609],[147.648073,-6.083659],[147.891108,-6.614015],[146.970905,-6.721657],[147.191874,-7.388024]]],[[[153.140038,-4.499983],[152.827292,-4.766427],[152.638673,-4.176127],[152.406026,-3.789743],[151.953237,-3.462062],[151.384279,-3.035422],[150.66205,-2.741486],[150.939965,-2.500002],[151.479984,-2.779985],[151.820015,-2.999972],[152.239989,-3.240009],[152.640017,-3.659983],[153.019994,-3.980015],[153.140038,-4.499983]]]]}},\n{\"type\":\"Feature\",\"id\":\"POL\",\"properties\":{\"name\":\"Poland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[15.016996,51.106674],[14.607098,51.745188],[14.685026,52.089947],[14.4376,52.62485],[14.074521,52.981263],[14.353315,53.248171],[14.119686,53.757029],[14.8029,54.050706],[16.363477,54.513159],[17.622832,54.851536],[18.620859,54.682606],[18.696255,54.438719],[19.66064,54.426084],[20.892245,54.312525],[22.731099,54.327537],[23.243987,54.220567],[23.484128,53.912498],[23.527536,53.470122],[23.804935,53.089731],[23.799199,52.691099],[23.199494,52.486977],[23.508002,52.023647],[23.527071,51.578454],[24.029986,50.705407],[23.922757,50.424881],[23.426508,50.308506],[22.51845,49.476774],[22.776419,49.027395],[22.558138,49.085738],[21.607808,49.470107],[20.887955,49.328772],[20.415839,49.431453],[19.825023,49.217125],[19.320713,49.571574],[18.909575,49.435846],[18.853144,49.49623],[18.392914,49.988629],[17.649445,50.049038],[17.554567,50.362146],[16.868769,50.473974],[16.719476,50.215747],[16.176253,50.422607],[16.238627,50.697733],[15.490972,50.78473],[15.016996,51.106674]]]}},\n{\"type\":\"Feature\",\"id\":\"PRI\",\"properties\":{\"name\":\"Puerto Rico\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-66.282434,18.514762],[-65.771303,18.426679],[-65.591004,18.228035],[-65.847164,17.975906],[-66.599934,17.981823],[-67.184162,17.946553],[-67.242428,18.37446],[-67.100679,18.520601],[-66.282434,18.514762]]]}},\n{\"type\":\"Feature\",\"id\":\"PRK\",\"properties\":{\"name\":\"North Korea\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[130.640016,42.395009],[130.780007,42.220007],[130.400031,42.280004],[129.965949,41.941368],[129.667362,41.601104],[129.705189,40.882828],[129.188115,40.661808],[129.0104,40.485436],[128.633368,40.189847],[127.967414,40.025413],[127.533436,39.75685],[127.50212,39.323931],[127.385434,39.213472],[127.783343,39.050898],[128.349716,38.612243],[128.205746,38.370397],[127.780035,38.304536],[127.073309,38.256115],[126.68372,37.804773],[126.237339,37.840378],[126.174759,37.749686],[125.689104,37.94001],[125.568439,37.752089],[125.27533,37.669071],[125.240087,37.857224],[124.981033,37.948821],[124.712161,38.108346],[124.985994,38.548474],[125.221949,38.665857],[125.132859,38.848559],[125.38659,39.387958],[125.321116,39.551385],[124.737482,39.660344],[124.265625,39.928493],[125.079942,40.569824],[126.182045,41.107336],[126.869083,41.816569],[127.343783,41.503152],[128.208433,41.466772],[128.052215,41.994285],[129.596669,42.424982],[129.994267,42.985387],[130.640016,42.395009]]]}},\n{\"type\":\"Feature\",\"id\":\"PRT\",\"properties\":{\"name\":\"Portugal\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-9.034818,41.880571],[-8.671946,42.134689],[-8.263857,42.280469],[-8.013175,41.790886],[-7.422513,41.792075],[-7.251309,41.918346],[-6.668606,41.883387],[-6.389088,41.381815],[-6.851127,41.111083],[-6.86402,40.330872],[-7.026413,40.184524],[-7.066592,39.711892],[-7.498632,39.629571],[-7.098037,39.030073],[-7.374092,38.373059],[-7.029281,38.075764],[-7.166508,37.803894],[-7.537105,37.428904],[-7.453726,37.097788],[-7.855613,36.838269],[-8.382816,36.97888],[-8.898857,36.868809],[-8.746101,37.651346],[-8.839998,38.266243],[-9.287464,38.358486],[-9.526571,38.737429],[-9.446989,39.392066],[-9.048305,39.755093],[-8.977353,40.159306],[-8.768684,40.760639],[-8.790853,41.184334],[-8.990789,41.543459],[-9.034818,41.880571]]]}},\n{\"type\":\"Feature\",\"id\":\"PRY\",\"properties\":{\"name\":\"Paraguay\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-62.685057,-22.249029],[-62.291179,-21.051635],[-62.265961,-20.513735],[-61.786326,-19.633737],[-60.043565,-19.342747],[-59.115042,-19.356906],[-58.183471,-19.868399],[-58.166392,-20.176701],[-57.870674,-20.732688],[-57.937156,-22.090176],[-56.88151,-22.282154],[-56.473317,-22.0863],[-55.797958,-22.35693],[-55.610683,-22.655619],[-55.517639,-23.571998],[-55.400747,-23.956935],[-55.027902,-24.001274],[-54.652834,-23.839578],[-54.29296,-24.021014],[-54.293476,-24.5708],[-54.428946,-25.162185],[-54.625291,-25.739255],[-54.788795,-26.621786],[-55.695846,-27.387837],[-56.486702,-27.548499],[-57.60976,-27.395899],[-58.618174,-27.123719],[-57.63366,-25.603657],[-57.777217,-25.16234],[-58.807128,-24.771459],[-60.028966,-24.032796],[-60.846565,-23.880713],[-62.685057,-22.249029]]]}},\n{\"type\":\"Feature\",\"id\":\"QAT\",\"properties\":{\"name\":\"Qatar\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[50.810108,24.754743],[50.743911,25.482424],[51.013352,26.006992],[51.286462,26.114582],[51.589079,25.801113],[51.6067,25.21567],[51.389608,24.627386],[51.112415,24.556331],[50.810108,24.754743]]]}},\n{\"type\":\"Feature\",\"id\":\"ROU\",\"properties\":{\"name\":\"Romania\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[22.710531,47.882194],[23.142236,48.096341],[23.760958,47.985598],[24.402056,47.981878],[24.866317,47.737526],[25.207743,47.891056],[25.945941,47.987149],[26.19745,48.220881],[26.619337,48.220726],[26.924176,48.123264],[27.233873,47.826771],[27.551166,47.405117],[28.12803,46.810476],[28.160018,46.371563],[28.054443,45.944586],[28.233554,45.488283],[28.679779,45.304031],[29.149725,45.464925],[29.603289,45.293308],[29.626543,45.035391],[29.141612,44.82021],[28.837858,44.913874],[28.558081,43.707462],[27.970107,43.812468],[27.2424,44.175986],[26.065159,43.943494],[25.569272,43.688445],[24.100679,43.741051],[23.332302,43.897011],[22.944832,43.823785],[22.65715,44.234923],[22.474008,44.409228],[22.705726,44.578003],[22.459022,44.702517],[22.145088,44.478422],[21.562023,44.768947],[21.483526,45.18117],[20.874313,45.416375],[20.762175,45.734573],[20.220192,46.127469],[21.021952,46.316088],[21.626515,46.994238],[22.099768,47.672439],[22.710531,47.882194]]]}},\n{\"type\":\"Feature\",\"id\":\"RUS\",\"properties\":{\"name\":\"Russia\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[143.648007,50.7476],[144.654148,48.976391],[143.173928,49.306551],[142.558668,47.861575],[143.533492,46.836728],[143.505277,46.137908],[142.747701,46.740765],[142.09203,45.966755],[141.906925,46.805929],[142.018443,47.780133],[141.904445,48.859189],[142.1358,49.615163],[142.179983,50.952342],[141.594076,51.935435],[141.682546,53.301966],[142.606934,53.762145],[142.209749,54.225476],[142.654786,54.365881],[142.914616,53.704578],[143.260848,52.74076],[143.235268,51.75666],[143.648007,50.7476]]],[[[22.731099,54.327537],[20.892245,54.312525],[19.66064,54.426084],[19.888481,54.86616],[21.268449,55.190482],[22.315724,55.015299],[22.757764,54.856574],[22.651052,54.582741],[22.731099,54.327537]]],[[[-175.01425,66.58435],[-174.33983,66.33556],[-174.57182,67.06219],[-171.85731,66.91308],[-169.89958,65.97724],[-170.89107,65.54139],[-172.53025,65.43791],[-172.555,64.46079],[-172.95533,64.25269],[-173.89184,64.2826],[-174.65392,64.63125],[-175.98353,64.92288],[-176.20716,65.35667],[-177.22266,65.52024],[-178.35993,65.39052],[-178.90332,65.74044],[-178.68611,66.11211],[-179.88377,65.87456],[-179.43268,65.40411],[-180,64.979709],[-180,68.963636],[-177.55,68.2],[-174.92825,67.20589],[-175.01425,66.58435]]],[[[180,70.832199],[178.903425,70.78114],[178.7253,71.0988],[180,71.515714],[180,70.832199]]],[[[-178.69378,70.89302],[-180,70.832199],[-180,71.515714],[-179.871875,71.55762],[-179.02433,71.55553],[-177.577945,71.26948],[-177.663575,71.13277],[-178.69378,70.89302]]],[[[143.60385,73.21244],[142.08763,73.20544],[140.038155,73.31692],[139.86312,73.36983],[140.81171,73.76506],[142.06207,73.85758],[143.48283,73.47525],[143.60385,73.21244]]],[[[150.73167,75.08406],[149.575925,74.68892],[147.977465,74.778355],[146.11919,75.17298],[146.358485,75.49682],[148.22223,75.345845],[150.73167,75.08406]]],[[[145.086285,75.562625],[144.3,74.82],[140.61381,74.84768],[138.95544,74.61148],[136.97439,75.26167],[137.51176,75.94917],[138.831075,76.13676],[141.471615,76.09289],[145.086285,75.562625]]],[[[57.535693,70.720464],[56.944979,70.632743],[53.677375,70.762658],[53.412017,71.206662],[51.601895,71.474759],[51.455754,72.014881],[52.478275,72.229442],[52.444169,72.774731],[54.427614,73.627548],[53.50829,73.749814],[55.902459,74.627486],[55.631933,75.081412],[57.868644,75.60939],[61.170044,76.251883],[64.498368,76.439055],[66.210977,76.809782],[68.15706,76.939697],[68.852211,76.544811],[68.180573,76.233642],[64.637326,75.737755],[61.583508,75.260885],[58.477082,74.309056],[56.986786,73.333044],[55.419336,72.371268],[55.622838,71.540595],[57.535693,70.720464]]],[[[106.97013,76.97419],[107.24,76.48],[108.1538,76.72335],[111.07726,76.71],[113.33151,76.22224],[114.13417,75.84764],[113.88539,75.32779],[112.77918,75.03186],[110.15125,74.47673],[109.4,74.18],[110.64,74.04],[112.11919,73.78774],[113.01954,73.97693],[113.52958,73.33505],[113.96881,73.59488],[115.56782,73.75285],[118.77633,73.58772],[119.02,73.12],[123.20066,72.97122],[123.25777,73.73503],[125.38,73.56],[126.97644,73.56549],[128.59126,73.03871],[129.05157,72.39872],[128.46,71.98],[129.71599,71.19304],[131.28858,70.78699],[132.2535,71.8363],[133.85766,71.38642],[135.56193,71.65525],[137.49755,71.34763],[138.23409,71.62803],[139.86983,71.48783],[139.14791,72.41619],[140.46817,72.84941],[149.5,72.2],[150.35118,71.60643],[152.9689,70.84222],[157.00688,71.03141],[158.99779,70.86672],[159.83031,70.45324],[159.70866,69.72198],[160.94053,69.43728],[162.27907,69.64204],[164.05248,69.66823],[165.94037,69.47199],[167.83567,69.58269],[169.57763,68.6938],[170.81688,69.01363],[170.0082,69.65276],[170.45345,70.09703],[173.64391,69.81743],[175.72403,69.87725],[178.6,69.4],[180,68.963636],[180,64.979709],[179.99281,64.97433],[178.7072,64.53493],[177.41128,64.60821],[178.313,64.07593],[178.90825,63.25197],[179.37034,62.98262],[179.48636,62.56894],[179.22825,62.3041],[177.3643,62.5219],[174.56929,61.76915],[173.68013,61.65261],[172.15,60.95],[170.6985,60.33618],[170.33085,59.88177],[168.90046,60.57355],[166.29498,59.78855],[165.84,60.16],[164.87674,59.7316],[163.53929,59.86871],[163.21711,59.21101],[162.01733,58.24328],[162.05297,57.83912],[163.19191,57.61503],[163.05794,56.15924],[162.12958,56.12219],[161.70146,55.28568],[162.11749,54.85514],[160.36877,54.34433],[160.02173,53.20257],[158.53094,52.95868],[158.23118,51.94269],[156.78979,51.01105],[156.42,51.7],[155.99182,53.15895],[155.43366,55.38103],[155.91442,56.76792],[156.75815,57.3647],[156.81035,57.83204],[158.36433,58.05575],[160.15064,59.31477],[161.87204,60.343],[163.66969,61.1409],[164.47355,62.55061],[163.25842,62.46627],[162.65791,61.6425],[160.12148,60.54423],[159.30232,61.77396],[156.72068,61.43442],[154.21806,59.75818],[155.04375,59.14495],[152.81185,58.88385],[151.26573,58.78089],[151.33815,59.50396],[149.78371,59.65573],[148.54481,59.16448],[145.48722,59.33637],[142.19782,59.03998],[138.95848,57.08805],[135.12619,54.72959],[136.70171,54.60355],[137.19342,53.97732],[138.1647,53.75501],[138.80463,54.25455],[139.90151,54.18968],[141.34531,53.08957],[141.37923,52.23877],[140.59742,51.23967],[140.51308,50.04553],[140.06193,48.44671],[138.55472,46.99965],[138.21971,46.30795],[136.86232,45.1435],[135.51535,43.989],[134.86939,43.39821],[133.53687,42.81147],[132.90627,42.79849],[132.27807,43.28456],[130.93587,42.55274],[130.78,42.22],[130.64,42.395],[130.633866,42.903015],[131.144688,42.92999],[131.288555,44.11152],[131.02519,44.96796],[131.883454,45.321162],[133.09712,45.14409],[133.769644,46.116927],[134.11235,47.21248],[134.50081,47.57845],[135.026311,48.47823],[133.373596,48.183442],[132.50669,47.78896],[130.98726,47.79013],[130.582293,48.729687],[129.397818,49.4406],[127.6574,49.76027],[127.287456,50.739797],[126.939157,51.353894],[126.564399,51.784255],[125.946349,52.792799],[125.068211,53.161045],[123.57147,53.4588],[122.245748,53.431726],[121.003085,53.251401],[120.177089,52.753886],[120.725789,52.516226],[120.7382,51.96411],[120.18208,51.64355],[119.27939,50.58292],[119.288461,50.142883],[117.879244,49.510983],[116.678801,49.888531],[115.485695,49.805177],[114.96211,50.140247],[114.362456,50.248303],[112.89774,49.543565],[111.581231,49.377968],[110.662011,49.130128],[109.402449,49.292961],[108.475167,49.282548],[107.868176,49.793705],[106.888804,50.274296],[105.886591,50.406019],[104.62158,50.27532],[103.676545,50.089966],[102.25589,50.51056],[102.06521,51.25991],[100.88948,51.516856],[99.981732,51.634006],[98.861491,52.047366],[97.82574,51.010995],[98.231762,50.422401],[97.25976,49.72605],[95.81402,49.97746],[94.815949,50.013433],[94.147566,50.480537],[93.10421,50.49529],[92.234712,50.802171],[90.713667,50.331812],[88.805567,49.470521],[87.751264,49.297198],[87.35997,49.214981],[86.829357,49.826675],[85.54127,49.692859],[85.11556,50.117303],[84.416377,50.3114],[83.935115,50.889246],[83.383004,51.069183],[81.945986,50.812196],[80.568447,51.388336],[80.03556,50.864751],[77.800916,53.404415],[76.525179,54.177003],[76.8911,54.490524],[74.38482,53.54685],[73.425679,53.48981],[73.508516,54.035617],[72.22415,54.376655],[71.180131,54.133285],[70.865267,55.169734],[69.068167,55.38525],[68.1691,54.970392],[65.66687,54.60125],[65.178534,54.354228],[61.4366,54.00625],[60.978066,53.664993],[61.699986,52.979996],[60.739993,52.719986],[60.927269,52.447548],[59.967534,51.96042],[61.588003,51.272659],[61.337424,50.79907],[59.932807,50.842194],[59.642282,50.545442],[58.36332,51.06364],[56.77798,51.04355],[55.71694,50.62171],[54.532878,51.02624],[52.328724,51.718652],[50.766648,51.692762],[48.702382,50.605128],[48.577841,49.87476],[47.54948,50.454698],[46.751596,49.356006],[47.043672,49.152039],[46.466446,48.394152],[47.31524,47.71585],[48.05725,47.74377],[48.694734,47.075628],[48.59325,46.56104],[49.10116,46.39933],[48.64541,45.80629],[47.67591,45.64149],[46.68201,44.6092],[47.59094,43.66016],[47.49252,42.98658],[48.58437,41.80888],[47.987283,41.405819],[47.815666,41.151416],[47.373315,41.219732],[46.686071,41.827137],[46.404951,41.860675],[45.7764,42.09244],[45.470279,42.502781],[44.537623,42.711993],[43.93121,42.55496],[43.75599,42.74083],[42.3944,43.2203],[40.92219,43.38215],[40.076965,43.553104],[39.955009,43.434998],[38.68,44.28],[37.53912,44.65721],[36.67546,45.24469],[37.40317,45.40451],[38.23295,46.24087],[37.67372,46.63657],[39.14767,47.04475],[39.1212,47.26336],[38.223538,47.10219],[38.255112,47.5464],[38.77057,47.82562],[39.738278,47.898937],[39.89562,48.23241],[39.67465,48.78382],[40.080789,49.30743],[40.06904,49.60105],[38.594988,49.926462],[38.010631,49.915662],[37.39346,50.383953],[36.626168,50.225591],[35.356116,50.577197],[35.37791,50.77394],[35.022183,51.207572],[34.224816,51.255993],[34.141978,51.566413],[34.391731,51.768882],[33.7527,52.335075],[32.715761,52.238465],[32.412058,52.288695],[32.15944,52.06125],[31.78597,52.10168],[31.540018,52.742052],[31.305201,53.073996],[31.49764,53.16743],[32.304519,53.132726],[32.693643,53.351421],[32.405599,53.618045],[31.731273,53.794029],[31.791424,53.974639],[31.384472,54.157056],[30.757534,54.811771],[30.971836,55.081548],[30.873909,55.550976],[29.896294,55.789463],[29.371572,55.670091],[29.229513,55.918344],[28.176709,56.16913],[27.855282,56.759326],[27.770016,57.244258],[27.288185,57.474528],[27.716686,57.791899],[27.42015,58.72457],[28.131699,59.300825],[27.98112,59.47537],[29.1177,60.02805],[28.07,60.50352],[30.211107,61.780028],[31.139991,62.357693],[31.516092,62.867687],[30.035872,63.552814],[30.444685,64.204453],[29.54443,64.948672],[30.21765,65.80598],[29.054589,66.944286],[29.977426,67.698297],[28.445944,68.364613],[28.59193,69.064777],[29.39955,69.15692],[31.10108,69.55811],[32.13272,69.90595],[33.77547,69.30142],[36.51396,69.06342],[40.29234,67.9324],[41.05987,67.45713],[41.12595,66.79158],[40.01583,66.26618],[38.38295,65.99953],[33.91871,66.75961],[33.18444,66.63253],[34.81477,65.90015],[34.878574,65.436213],[34.94391,64.41437],[36.23129,64.10945],[37.01273,63.84983],[37.14197,64.33471],[36.539579,64.76446],[37.17604,65.14322],[39.59345,64.52079],[40.4356,64.76446],[39.7626,65.49682],[42.09309,66.47623],[43.01604,66.41858],[43.94975,66.06908],[44.53226,66.75634],[43.69839,67.35245],[44.18795,67.95051],[43.45282,68.57079],[46.25,68.25],[46.82134,67.68997],[45.55517,67.56652],[45.56202,67.01005],[46.34915,66.66767],[47.89416,66.88455],[48.13876,67.52238],[50.22766,67.99867],[53.71743,68.85738],[54.47171,68.80815],[53.48582,68.20131],[54.72628,68.09702],[55.44268,68.43866],[57.31702,68.46628],[58.802,68.88082],[59.94142,68.27844],[61.07784,68.94069],[60.03,69.52],[60.55,69.85],[63.504,69.54739],[64.888115,69.234835],[68.51216,68.09233],[69.18068,68.61563],[68.16444,69.14436],[68.13522,69.35649],[66.93008,69.45461],[67.25976,69.92873],[66.72492,70.70889],[66.69466,71.02897],[68.54006,71.9345],[69.19636,72.84336],[69.94,73.04],[72.58754,72.77629],[72.79603,72.22006],[71.84811,71.40898],[72.47011,71.09019],[72.79188,70.39114],[72.5647,69.02085],[73.66787,68.4079],[73.2387,67.7404],[71.28,66.32],[72.42301,66.17267],[72.82077,66.53267],[73.92099,66.78946],[74.18651,67.28429],[75.052,67.76047],[74.46926,68.32899],[74.93584,68.98918],[73.84236,69.07146],[73.60187,69.62763],[74.3998,70.63175],[73.1011,71.44717],[74.89082,72.12119],[74.65926,72.83227],[75.15801,72.85497],[75.68351,72.30056],[75.28898,71.33556],[76.35911,71.15287],[75.90313,71.87401],[77.57665,72.26717],[79.65202,72.32011],[81.5,71.75],[80.61071,72.58285],[80.51109,73.6482],[82.25,73.85],[84.65526,73.80591],[86.8223,73.93688],[86.00956,74.45967],[87.16682,75.11643],[88.31571,75.14393],[90.26,75.64],[92.90058,75.77333],[93.23421,76.0472],[95.86,76.14],[96.67821,75.91548],[98.92254,76.44689],[100.75967,76.43028],[101.03532,76.86189],[101.99084,77.28754],[104.3516,77.69792],[106.06664,77.37389],[104.705,77.1274],[106.97013,76.97419]]],[[[105.07547,78.30689],[99.43814,77.921],[101.2649,79.23399],[102.08635,79.34641],[102.837815,79.28129],[105.37243,78.71334],[105.07547,78.30689]]],[[[51.136187,80.54728],[49.793685,80.415428],[48.894411,80.339567],[48.754937,80.175468],[47.586119,80.010181],[46.502826,80.247247],[47.072455,80.559424],[44.846958,80.58981],[46.799139,80.771918],[48.318477,80.78401],[48.522806,80.514569],[49.09719,80.753986],[50.039768,80.918885],[51.522933,80.699726],[51.136187,80.54728]]],[[[99.93976,78.88094],[97.75794,78.7562],[94.97259,79.044745],[93.31288,79.4265],[92.5454,80.14379],[91.18107,80.34146],[93.77766,81.0246],[95.940895,81.2504],[97.88385,80.746975],[100.186655,79.780135],[99.93976,78.88094]]]]}},\n{\"type\":\"Feature\",\"id\":\"RWA\",\"properties\":{\"name\":\"Rwanda\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[30.419105,-1.134659],[30.816135,-1.698914],[30.758309,-2.28725],[30.469696,-2.413858],[29.938359,-2.348487],[29.632176,-2.917858],[29.024926,-2.839258],[29.117479,-2.292211],[29.254835,-2.21511],[29.291887,-1.620056],[29.579466,-1.341313],[29.821519,-1.443322],[30.419105,-1.134659]]]}},\n{\"type\":\"Feature\",\"id\":\"ESH\",\"properties\":{\"name\":\"Western Sahara\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-8.794884,27.120696],[-8.817828,27.656426],[-8.66559,27.656426],[-8.665124,27.589479],[-8.6844,27.395744],[-8.687294,25.881056],[-11.969419,25.933353],[-11.937224,23.374594],[-12.874222,23.284832],[-13.118754,22.77122],[-12.929102,21.327071],[-16.845194,21.333323],[-17.063423,20.999752],[-17.020428,21.42231],[-17.002962,21.420734],[-14.750955,21.5006],[-14.630833,21.86094],[-14.221168,22.310163],[-13.89111,23.691009],[-12.500963,24.770116],[-12.030759,26.030866],[-11.71822,26.104092],[-11.392555,26.883424],[-10.551263,26.990808],[-10.189424,26.860945],[-9.735343,26.860945],[-9.413037,27.088476],[-8.794884,27.120696]]]}},\n{\"type\":\"Feature\",\"id\":\"SAU\",\"properties\":{\"name\":\"Saudi Arabia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[42.779332,16.347891],[42.649573,16.774635],[42.347989,17.075806],[42.270888,17.474722],[41.754382,17.833046],[41.221391,18.6716],[40.939341,19.486485],[40.247652,20.174635],[39.801685,20.338862],[39.139399,21.291905],[39.023696,21.986875],[39.066329,22.579656],[38.492772,23.688451],[38.02386,24.078686],[37.483635,24.285495],[37.154818,24.858483],[37.209491,25.084542],[36.931627,25.602959],[36.639604,25.826228],[36.249137,26.570136],[35.640182,27.37652],[35.130187,28.063352],[34.632336,28.058546],[34.787779,28.607427],[34.83222,28.957483],[34.956037,29.356555],[36.068941,29.197495],[36.501214,29.505254],[36.740528,29.865283],[37.503582,30.003776],[37.66812,30.338665],[37.998849,30.5085],[37.002166,31.508413],[39.004886,32.010217],[39.195468,32.161009],[40.399994,31.889992],[41.889981,31.190009],[44.709499,29.178891],[46.568713,29.099025],[47.459822,29.002519],[47.708851,28.526063],[48.416094,28.552004],[48.807595,27.689628],[49.299554,27.461218],[49.470914,27.109999],[50.152422,26.689663],[50.212935,26.277027],[50.113303,25.943972],[50.239859,25.60805],[50.527387,25.327808],[50.660557,24.999896],[50.810108,24.754743],[51.112415,24.556331],[51.389608,24.627386],[51.579519,24.245497],[51.617708,24.014219],[52.000733,23.001154],[55.006803,22.496948],[55.208341,22.70833],[55.666659,22.000001],[54.999982,19.999994],[52.00001,19.000003],[49.116672,18.616668],[48.183344,18.166669],[47.466695,17.116682],[47.000005,16.949999],[46.749994,17.283338],[46.366659,17.233315],[45.399999,17.333335],[45.216651,17.433329],[44.062613,17.410359],[43.791519,17.319977],[43.380794,17.579987],[43.115798,17.08844],[43.218375,16.66689],[42.779332,16.347891]]]}},\n{\"type\":\"Feature\",\"id\":\"SDN\",\"properties\":{\"name\":\"Sudan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[33.963393,9.464285],[33.824963,9.484061],[33.842131,9.981915],[33.721959,10.325262],[33.206938,10.720112],[33.086766,11.441141],[33.206938,12.179338],[32.743419,12.248008],[32.67475,12.024832],[32.073892,11.97333],[32.314235,11.681484],[32.400072,11.080626],[31.850716,10.531271],[31.352862,9.810241],[30.837841,9.707237],[29.996639,10.290927],[29.618957,10.084919],[29.515953,9.793074],[29.000932,9.604232],[28.966597,9.398224],[27.97089,9.398224],[27.833551,9.604232],[27.112521,9.638567],[26.752006,9.466893],[26.477328,9.55273],[25.962307,10.136421],[25.790633,10.411099],[25.069604,10.27376],[24.794926,9.810241],[24.537415,8.917538],[24.194068,8.728696],[23.88698,8.61973],[23.805813,8.666319],[23.459013,8.954286],[23.394779,9.265068],[23.55725,9.681218],[23.554304,10.089255],[22.977544,10.714463],[22.864165,11.142395],[22.87622,11.38461],[22.50869,11.67936],[22.49762,12.26024],[22.28801,12.64605],[21.93681,12.58818],[22.03759,12.95546],[22.29658,13.37232],[22.18329,13.78648],[22.51202,14.09318],[22.30351,14.32682],[22.56795,14.94429],[23.02459,15.68072],[23.88689,15.61084],[23.83766,19.58047],[23.85,20],[25,20.00304],[25,22],[29.02,22],[32.9,22],[36.86623,22],[37.18872,21.01885],[36.96941,20.83744],[37.1147,19.80796],[37.48179,18.61409],[37.86276,18.36786],[38.41009,17.998307],[37.904,17.42754],[37.16747,17.26314],[36.85253,16.95655],[36.75389,16.29186],[36.32322,14.82249],[36.42951,14.42211],[36.27022,13.56333],[35.86363,12.57828],[35.26049,12.08286],[34.83163,11.31896],[34.73115,10.91017],[34.25745,10.63009],[33.96162,9.58358],[33.963393,9.464285]]]}},\n{\"type\":\"Feature\",\"id\":\"SSD\",\"properties\":{\"name\":\"South Sudan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[33.963393,9.464285],[33.97498,8.68456],[33.8255,8.37916],[33.2948,8.35458],[32.95418,7.78497],[33.56829,7.71334],[34.0751,7.22595],[34.25032,6.82607],[34.70702,6.59422],[35.298007,5.506],[34.620196,4.847123],[34.005,4.249885],[33.39,3.79],[32.68642,3.79232],[31.88145,3.55827],[31.24556,3.7819],[30.83385,3.50917],[29.95349,4.1737],[29.715995,4.600805],[29.159078,4.389267],[28.696678,4.455077],[28.428994,4.287155],[27.979977,4.408413],[27.374226,5.233944],[27.213409,5.550953],[26.465909,5.946717],[26.213418,6.546603],[25.796648,6.979316],[25.124131,7.500085],[25.114932,7.825104],[24.567369,8.229188],[23.88698,8.61973],[24.194068,8.728696],[24.537415,8.917538],[24.794926,9.810241],[25.069604,10.27376],[25.790633,10.411099],[25.962307,10.136421],[26.477328,9.55273],[26.752006,9.466893],[27.112521,9.638567],[27.833551,9.604232],[27.97089,9.398224],[28.966597,9.398224],[29.000932,9.604232],[29.515953,9.793074],[29.618957,10.084919],[29.996639,10.290927],[30.837841,9.707237],[31.352862,9.810241],[31.850716,10.531271],[32.400072,11.080626],[32.314235,11.681484],[32.073892,11.97333],[32.67475,12.024832],[32.743419,12.248008],[33.206938,12.179338],[33.086766,11.441141],[33.206938,10.720112],[33.721959,10.325262],[33.842131,9.981915],[33.824963,9.484061],[33.963393,9.464285]]]}},\n{\"type\":\"Feature\",\"id\":\"SEN\",\"properties\":{\"name\":\"Senegal\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-16.713729,13.594959],[-17.126107,14.373516],[-17.625043,14.729541],[-17.185173,14.919477],[-16.700706,15.621527],[-16.463098,16.135036],[-16.12069,16.455663],[-15.623666,16.369337],[-15.135737,16.587282],[-14.577348,16.598264],[-14.099521,16.304302],[-13.435738,16.039383],[-12.830658,15.303692],[-12.17075,14.616834],[-12.124887,13.994727],[-11.927716,13.422075],[-11.553398,13.141214],[-11.467899,12.754519],[-11.513943,12.442988],[-11.658301,12.386583],[-12.203565,12.465648],[-12.278599,12.35444],[-12.499051,12.33209],[-13.217818,12.575874],[-13.700476,12.586183],[-15.548477,12.62817],[-15.816574,12.515567],[-16.147717,12.547762],[-16.677452,12.384852],[-16.841525,13.151394],[-15.931296,13.130284],[-15.691001,13.270353],[-15.511813,13.27857],[-15.141163,13.509512],[-14.712197,13.298207],[-14.277702,13.280585],[-13.844963,13.505042],[-14.046992,13.794068],[-14.376714,13.62568],[-14.687031,13.630357],[-15.081735,13.876492],[-15.39877,13.860369],[-15.624596,13.623587],[-16.713729,13.594959]]]}},\n{\"type\":\"Feature\",\"id\":\"SLB\",\"properties\":{\"name\":\"Solomon Islands\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[162.119025,-10.482719],[162.398646,-10.826367],[161.700032,-10.820011],[161.319797,-10.204751],[161.917383,-10.446701],[162.119025,-10.482719]]],[[[160.852229,-9.872937],[160.462588,-9.89521],[159.849447,-9.794027],[159.640003,-9.63998],[159.702945,-9.24295],[160.362956,-9.400304],[160.688518,-9.610162],[160.852229,-9.872937]]],[[[161.679982,-9.599982],[161.529397,-9.784312],[160.788253,-8.917543],[160.579997,-8.320009],[160.920028,-8.320009],[161.280006,-9.120011],[161.679982,-9.599982]]],[[[159.875027,-8.33732],[159.917402,-8.53829],[159.133677,-8.114181],[158.586114,-7.754824],[158.21115,-7.421872],[158.359978,-7.320018],[158.820001,-7.560003],[159.640003,-8.020027],[159.875027,-8.33732]]],[[[157.538426,-7.34782],[157.33942,-7.404767],[156.90203,-7.176874],[156.491358,-6.765943],[156.542828,-6.599338],[157.14,-7.021638],[157.538426,-7.34782]]]]}},\n{\"type\":\"Feature\",\"id\":\"SLE\",\"properties\":{\"name\":\"Sierra Leone\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-11.438779,6.785917],[-11.708195,6.860098],[-12.428099,7.262942],[-12.949049,7.798646],[-13.124025,8.163946],[-13.24655,8.903049],[-12.711958,9.342712],[-12.596719,9.620188],[-12.425929,9.835834],[-12.150338,9.858572],[-11.917277,10.046984],[-11.117481,10.045873],[-10.839152,9.688246],[-10.622395,9.26791],[-10.65477,8.977178],[-10.494315,8.715541],[-10.505477,8.348896],[-10.230094,8.406206],[-10.695595,7.939464],[-11.146704,7.396706],[-11.199802,7.105846],[-11.438779,6.785917]]]}},\n{\"type\":\"Feature\",\"id\":\"SLV\",\"properties\":{\"name\":\"El Salvador\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-87.793111,13.38448],[-87.904112,13.149017],[-88.483302,13.163951],[-88.843228,13.259734],[-89.256743,13.458533],[-89.812394,13.520622],[-90.095555,13.735338],[-90.064678,13.88197],[-89.721934,14.134228],[-89.534219,14.244816],[-89.587343,14.362586],[-89.353326,14.424133],[-89.058512,14.340029],[-88.843073,14.140507],[-88.541231,13.980155],[-88.503998,13.845486],[-88.065343,13.964626],[-87.859515,13.893312],[-87.723503,13.78505],[-87.793111,13.38448]]]}},\n{\"type\":\"Feature\",\"id\":\"-99\",\"properties\":{\"name\":\"Somaliland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[48.93813,9.451749],[48.486736,8.837626],[47.78942,8.003],[46.948328,7.996877],[43.67875,9.18358],[43.296975,9.540477],[42.92812,10.02194],[42.55876,10.57258],[42.776852,10.926879],[43.145305,11.46204],[43.47066,11.27771],[43.666668,10.864169],[44.117804,10.445538],[44.614259,10.442205],[45.556941,10.698029],[46.645401,10.816549],[47.525658,11.127228],[48.021596,11.193064],[48.378784,11.375482],[48.948206,11.410622],[48.942005,11.394266],[48.938491,10.982327],[48.938233,9.9735],[48.93813,9.451749]]]}},\n{\"type\":\"Feature\",\"id\":\"SOM\",\"properties\":{\"name\":\"Somalia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[49.72862,11.5789],[50.25878,11.67957],[50.73202,12.0219],[51.1112,12.02464],[51.13387,11.74815],[51.04153,11.16651],[51.04531,10.6409],[50.83418,10.27972],[50.55239,9.19874],[50.07092,8.08173],[49.4527,6.80466],[48.59455,5.33911],[47.74079,4.2194],[46.56476,2.85529],[45.56399,2.04576],[44.06815,1.05283],[43.13597,0.2922],[42.04157,-0.91916],[41.81095,-1.44647],[41.58513,-1.68325],[40.993,-0.85829],[40.98105,2.78452],[41.855083,3.918912],[42.12861,4.23413],[42.76967,4.25259],[43.66087,4.95755],[44.9636,5.00162],[47.78942,8.003],[48.486736,8.837626],[48.93813,9.451749],[48.938233,9.9735],[48.938491,10.982327],[48.942005,11.394266],[48.948205,11.410617],[49.26776,11.43033],[49.72862,11.5789]]]}},\n{\"type\":\"Feature\",\"id\":\"SRB\",\"properties\":{\"name\":\"Republic of Serbia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[20.874313,45.416375],[21.483526,45.18117],[21.562023,44.768947],[22.145088,44.478422],[22.459022,44.702517],[22.705726,44.578003],[22.474008,44.409228],[22.65715,44.234923],[22.410446,44.008063],[22.500157,43.642814],[22.986019,43.211161],[22.604801,42.898519],[22.436595,42.580321],[22.545012,42.461362],[22.380526,42.32026],[21.91708,42.30364],[21.576636,42.245224],[21.54332,42.32025],[21.66292,42.43922],[21.77505,42.6827],[21.63302,42.67717],[21.43866,42.86255],[21.27421,42.90959],[21.143395,43.068685],[20.95651,43.13094],[20.81448,43.27205],[20.63508,43.21671],[20.49679,42.88469],[20.25758,42.81275],[20.3398,42.89852],[19.95857,43.10604],[19.63,43.21378],[19.48389,43.35229],[19.21852,43.52384],[19.454,43.5681],[19.59976,44.03847],[19.11761,44.42307],[19.36803,44.863],[19.00548,44.86023],[19.390476,45.236516],[19.072769,45.521511],[18.82982,45.90888],[19.596045,46.17173],[20.220192,46.127469],[20.762175,45.734573],[20.874313,45.416375]]]}},\n{\"type\":\"Feature\",\"id\":\"SUR\",\"properties\":{\"name\":\"Suriname\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-57.147436,5.97315],[-55.949318,5.772878],[-55.84178,5.953125],[-55.03325,6.025291],[-53.958045,5.756548],[-54.478633,4.896756],[-54.399542,4.212611],[-54.006931,3.620038],[-54.181726,3.18978],[-54.269705,2.732392],[-54.524754,2.311849],[-55.097587,2.523748],[-55.569755,2.421506],[-55.973322,2.510364],[-56.073342,2.220795],[-55.9056,2.021996],[-55.995698,1.817667],[-56.539386,1.899523],[-57.150098,2.768927],[-57.281433,3.333492],[-57.601569,3.334655],[-58.044694,4.060864],[-57.86021,4.576801],[-57.914289,4.812626],[-57.307246,5.073567],[-57.147436,5.97315]]]}},\n{\"type\":\"Feature\",\"id\":\"SVK\",\"properties\":{\"name\":\"Slovakia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[18.853144,49.49623],[18.909575,49.435846],[19.320713,49.571574],[19.825023,49.217125],[20.415839,49.431453],[20.887955,49.328772],[21.607808,49.470107],[22.558138,49.085738],[22.280842,48.825392],[22.085608,48.422264],[21.872236,48.319971],[20.801294,48.623854],[20.473562,48.56285],[20.239054,48.327567],[19.769471,48.202691],[19.661364,48.266615],[19.174365,48.111379],[18.777025,48.081768],[18.696513,47.880954],[17.857133,47.758429],[17.488473,47.867466],[16.979667,48.123497],[16.879983,48.470013],[16.960288,48.596982],[17.101985,48.816969],[17.545007,48.800019],[17.886485,48.903475],[17.913512,48.996493],[18.104973,49.043983],[18.170498,49.271515],[18.399994,49.315001],[18.554971,49.495015],[18.853144,49.49623]]]}},\n{\"type\":\"Feature\",\"id\":\"SVN\",\"properties\":{\"name\":\"Slovenia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[13.806475,46.509306],[14.632472,46.431817],[15.137092,46.658703],[16.011664,46.683611],[16.202298,46.852386],[16.370505,46.841327],[16.564808,46.503751],[15.768733,46.238108],[15.67153,45.834154],[15.323954,45.731783],[15.327675,45.452316],[14.935244,45.471695],[14.595109,45.634941],[14.411968,45.466166],[13.71506,45.500324],[13.93763,45.591016],[13.69811,46.016778],[13.806475,46.509306]]]}},\n{\"type\":\"Feature\",\"id\":\"SWE\",\"properties\":{\"name\":\"Sweden\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[22.183173,65.723741],[21.213517,65.026005],[21.369631,64.413588],[19.778876,63.609554],[17.847779,62.7494],[17.119555,61.341166],[17.831346,60.636583],[18.787722,60.081914],[17.869225,58.953766],[16.829185,58.719827],[16.44771,57.041118],[15.879786,56.104302],[14.666681,56.200885],[14.100721,55.407781],[12.942911,55.361737],[12.625101,56.30708],[11.787942,57.441817],[11.027369,58.856149],[11.468272,59.432393],[12.300366,60.117933],[12.631147,61.293572],[11.992064,61.800362],[11.930569,63.128318],[12.579935,64.066219],[13.571916,64.049114],[13.919905,64.445421],[13.55569,64.787028],[15.108411,66.193867],[16.108712,67.302456],[16.768879,68.013937],[17.729182,68.010552],[17.993868,68.567391],[19.87856,68.407194],[20.025269,69.065139],[20.645593,69.106247],[21.978535,68.616846],[23.539473,67.936009],[23.56588,66.396051],[23.903379,66.006927],[22.183173,65.723741]],[[17.061767,57.385783],[17.210083,57.326521],[16.430053,56.179196],[16.364135,56.556455],[17.061767,57.385783]],[[19.357910,57.958588],[18.803100,57.651279],[18.825073,57.444949],[18.995361,57.441993],[18.951416,57.370976],[18.693237,57.305756],[18.709716,57.204734],[18.462524,57.127295],[18.319702,56.926992],[18.105468,56.891003],[18.187866,57.109402],[18.072509,57.267163],[18.154907,57.394664],[18.094482,57.545312],[18.660278,57.929434],[19.039306,57.941098],[19.105224,57.993543],[19.374389,57.996454],[19.357910,57.958588]],[[20.846557,63.823710],[21.066284,63.829768],[20.972900,63.715670],[20.824584,63.579121],[20.695495,63.591340],[20.819091,63.714454],[20.799865,63.780059],[20.846557,63.823710]]]]}},\n{\"type\":\"Feature\",\"id\":\"SWZ\",\"properties\":{\"name\":\"Swaziland\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[32.071665,-26.73382],[31.86806,-27.177927],[31.282773,-27.285879],[30.685962,-26.743845],[30.676609,-26.398078],[30.949667,-26.022649],[31.04408,-25.731452],[31.333158,-25.660191],[31.837778,-25.843332],[31.985779,-26.29178],[32.071665,-26.73382]]]}},\n{\"type\":\"Feature\",\"id\":\"SYR\",\"properties\":{\"name\":\"Syria\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[38.792341,33.378686],[36.834062,32.312938],[35.719918,32.709192],[35.700798,32.716014],[35.836397,32.868123],[35.821101,33.277426],[36.06646,33.824912],[36.61175,34.201789],[36.448194,34.593935],[35.998403,34.644914],[35.905023,35.410009],[36.149763,35.821535],[36.41755,36.040617],[36.685389,36.259699],[36.739494,36.81752],[37.066761,36.623036],[38.167727,36.90121],[38.699891,36.712927],[39.52258,36.716054],[40.673259,37.091276],[41.212089,37.074352],[42.349591,37.229873],[41.837064,36.605854],[41.289707,36.358815],[41.383965,35.628317],[41.006159,34.419372],[38.792341,33.378686]]]}},\n{\"type\":\"Feature\",\"id\":\"TCD\",\"properties\":{\"name\":\"Chad\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[14.495787,12.859396],[14.595781,13.330427],[13.954477,13.353449],[13.956699,13.996691],[13.540394,14.367134],[13.97217,15.68437],[15.247731,16.627306],[15.300441,17.92795],[15.685741,19.95718],[15.903247,20.387619],[15.487148,20.730415],[15.47106,21.04845],[15.096888,21.308519],[14.8513,22.86295],[15.86085,23.40972],[19.84926,21.49509],[23.83766,19.58047],[23.88689,15.61084],[23.02459,15.68072],[22.56795,14.94429],[22.30351,14.32682],[22.51202,14.09318],[22.18329,13.78648],[22.29658,13.37232],[22.03759,12.95546],[21.93681,12.58818],[22.28801,12.64605],[22.49762,12.26024],[22.50869,11.67936],[22.87622,11.38461],[22.864165,11.142395],[22.231129,10.971889],[21.723822,10.567056],[21.000868,9.475985],[20.059685,9.012706],[19.094008,9.074847],[18.81201,8.982915],[18.911022,8.630895],[18.389555,8.281304],[17.96493,7.890914],[16.705988,7.508328],[16.456185,7.734774],[16.290562,7.754307],[16.106232,7.497088],[15.27946,7.421925],[15.436092,7.692812],[15.120866,8.38215],[14.979996,8.796104],[14.544467,8.965861],[13.954218,9.549495],[14.171466,10.021378],[14.627201,9.920919],[14.909354,9.992129],[15.467873,9.982337],[14.923565,10.891325],[14.960152,11.555574],[14.89336,12.21905],[14.495787,12.859396]]]}},\n{\"type\":\"Feature\",\"id\":\"TGO\",\"properties\":{\"name\":\"Togo\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[1.865241,6.142158],[1.060122,5.928837],[0.836931,6.279979],[0.570384,6.914359],[0.490957,7.411744],[0.712029,8.312465],[0.461192,8.677223],[0.365901,9.465004],[0.36758,10.191213],[-0.049785,10.706918],[0.023803,11.018682],[0.899563,10.997339],[0.772336,10.470808],[1.077795,10.175607],[1.425061,9.825395],[1.463043,9.334624],[1.664478,9.12859],[1.618951,6.832038],[1.865241,6.142158]]]}},\n{\"type\":\"Feature\",\"id\":\"THA\",\"properties\":{\"name\":\"Thailand\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[102.584932,12.186595],[101.687158,12.64574],[100.83181,12.627085],[100.978467,13.412722],[100.097797,13.406856],[100.018733,12.307001],[99.478921,10.846367],[99.153772,9.963061],[99.222399,9.239255],[99.873832,9.207862],[100.279647,8.295153],[100.459274,7.429573],[101.017328,6.856869],[101.623079,6.740622],[102.141187,6.221636],[101.814282,5.810808],[101.154219,5.691384],[101.075516,6.204867],[100.259596,6.642825],[100.085757,6.464489],[99.690691,6.848213],[99.519642,7.343454],[98.988253,7.907993],[98.503786,8.382305],[98.339662,7.794512],[98.150009,8.350007],[98.25915,8.973923],[98.553551,9.93296],[99.038121,10.960546],[99.587286,11.892763],[99.196354,12.804748],[99.212012,13.269294],[99.097755,13.827503],[98.430819,14.622028],[98.192074,15.123703],[98.537376,15.308497],[98.903348,16.177824],[98.493761,16.837836],[97.859123,17.567946],[97.375896,18.445438],[97.797783,18.62708],[98.253724,19.708203],[98.959676,19.752981],[99.543309,20.186598],[100.115988,20.41785],[100.548881,20.109238],[100.606294,19.508344],[101.282015,19.462585],[101.035931,18.408928],[101.059548,17.512497],[102.113592,18.109102],[102.413005,17.932782],[102.998706,17.961695],[103.200192,18.309632],[103.956477,18.240954],[104.716947,17.428859],[104.779321,16.441865],[105.589039,15.570316],[105.544338,14.723934],[105.218777,14.273212],[104.281418,14.416743],[102.988422,14.225721],[102.348099,13.394247],[102.584932,12.186595]]]}},\n{\"type\":\"Feature\",\"id\":\"TJK\",\"properties\":{\"name\":\"Tajikistan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[71.014198,40.244366],[70.648019,39.935754],[69.55961,40.103211],[69.464887,39.526683],[70.549162,39.604198],[71.784694,39.279463],[73.675379,39.431237],[73.928852,38.505815],[74.257514,38.606507],[74.864816,38.378846],[74.829986,37.990007],[74.980002,37.41999],[73.948696,37.421566],[73.260056,37.495257],[72.63689,37.047558],[72.193041,36.948288],[71.844638,36.738171],[71.448693,37.065645],[71.541918,37.905774],[71.239404,37.953265],[71.348131,38.258905],[70.806821,38.486282],[70.376304,38.138396],[70.270574,37.735165],[70.116578,37.588223],[69.518785,37.608997],[69.196273,37.151144],[68.859446,37.344336],[68.135562,37.023115],[67.83,37.144994],[68.392033,38.157025],[68.176025,38.901553],[67.44222,39.140144],[67.701429,39.580478],[68.536416,39.533453],[69.011633,40.086158],[69.329495,40.727824],[70.666622,40.960213],[70.45816,40.496495],[70.601407,40.218527],[71.014198,40.244366]]]}},\n{\"type\":\"Feature\",\"id\":\"TKM\",\"properties\":{\"name\":\"Turkmenistan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[61.210817,35.650072],[61.123071,36.491597],[60.377638,36.527383],[59.234762,37.412988],[58.436154,37.522309],[57.330434,38.029229],[56.619366,38.121394],[56.180375,37.935127],[55.511578,37.964117],[54.800304,37.392421],[53.921598,37.198918],[53.735511,37.906136],[53.880929,38.952093],[53.101028,39.290574],[53.357808,39.975286],[52.693973,40.033629],[52.915251,40.876523],[53.858139,40.631034],[54.736845,40.951015],[54.008311,41.551211],[53.721713,42.123191],[52.91675,41.868117],[52.814689,41.135371],[52.50246,41.783316],[52.944293,42.116034],[54.079418,42.324109],[54.755345,42.043971],[55.455251,41.259859],[55.968191,41.308642],[57.096391,41.32231],[56.932215,41.826026],[57.78653,42.170553],[58.629011,42.751551],[59.976422,42.223082],[60.083341,41.425146],[60.465953,41.220327],[61.547179,41.26637],[61.882714,41.084857],[62.37426,40.053886],[63.518015,39.363257],[64.170223,38.892407],[65.215999,38.402695],[66.54615,37.974685],[66.518607,37.362784],[66.217385,37.39379],[65.745631,37.661164],[65.588948,37.305217],[64.746105,37.111818],[64.546479,36.312073],[63.982896,36.007957],[63.193538,35.857166],[62.984662,35.404041],[62.230651,35.270664],[61.210817,35.650072]]]}},\n{\"type\":\"Feature\",\"id\":\"TLS\",\"properties\":{\"name\":\"East Timor\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[124.968682,-8.89279],[125.086246,-8.656887],[125.947072,-8.432095],[126.644704,-8.398247],[126.957243,-8.273345],[127.335928,-8.397317],[126.967992,-8.668256],[125.925885,-9.106007],[125.08852,-9.393173],[125.07002,-9.089987],[124.968682,-8.89279]]]}},\n{\"type\":\"Feature\",\"id\":\"TTO\",\"properties\":{\"name\":\"Trinidad and Tobago\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-61.68,10.76],[-61.105,10.89],[-60.895,10.855],[-60.935,10.11],[-61.77,10],[-61.95,10.09],[-61.66,10.365],[-61.68,10.76]]]}},\n{\"type\":\"Feature\",\"id\":\"TUN\",\"properties\":{\"name\":\"Tunisia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[9.48214,30.307556],[9.055603,32.102692],[8.439103,32.506285],[8.430473,32.748337],[7.612642,33.344115],[7.524482,34.097376],[8.140981,34.655146],[8.376368,35.479876],[8.217824,36.433177],[8.420964,36.946427],[9.509994,37.349994],[10.210002,37.230002],[10.18065,36.724038],[11.028867,37.092103],[11.100026,36.899996],[10.600005,36.41],[10.593287,35.947444],[10.939519,35.698984],[10.807847,34.833507],[10.149593,34.330773],[10.339659,33.785742],[10.856836,33.76874],[11.108501,33.293343],[11.488787,33.136996],[11.432253,32.368903],[10.94479,32.081815],[10.636901,31.761421],[9.950225,31.37607],[10.056575,30.961831],[9.970017,30.539325],[9.48214,30.307556]]]}},\n{\"type\":\"Feature\",\"id\":\"TUR\",\"properties\":{\"name\":\"Turkey\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[36.913127,41.335358],[38.347665,40.948586],[39.512607,41.102763],[40.373433,41.013673],[41.554084,41.535656],[42.619549,41.583173],[43.582746,41.092143],[43.752658,40.740201],[43.656436,40.253564],[44.400009,40.005],[44.79399,39.713003],[44.109225,39.428136],[44.421403,38.281281],[44.225756,37.971584],[44.772699,37.170445],[44.293452,37.001514],[43.942259,37.256228],[42.779126,37.385264],[42.349591,37.229873],[41.212089,37.074352],[40.673259,37.091276],[39.52258,36.716054],[38.699891,36.712927],[38.167727,36.90121],[37.066761,36.623036],[36.739494,36.81752],[36.685389,36.259699],[36.41755,36.040617],[36.149763,35.821535],[35.782085,36.274995],[36.160822,36.650606],[35.550936,36.565443],[34.714553,36.795532],[34.026895,36.21996],[32.509158,36.107564],[31.699595,36.644275],[30.621625,36.677865],[30.391096,36.262981],[29.699976,36.144357],[28.732903,36.676831],[27.641187,36.658822],[27.048768,37.653361],[26.318218,38.208133],[26.8047,38.98576],[26.170785,39.463612],[27.28002,40.420014],[28.819978,40.460011],[29.240004,41.219991],[31.145934,41.087622],[32.347979,41.736264],[33.513283,42.01896],[35.167704,42.040225],[36.913127,41.335358]]],[[[27.192377,40.690566],[26.358009,40.151994],[26.043351,40.617754],[26.056942,40.824123],[26.294602,40.936261],[26.604196,41.562115],[26.117042,41.826905],[27.135739,42.141485],[27.99672,42.007359],[28.115525,41.622886],[28.988443,41.299934],[28.806438,41.054962],[27.619017,40.999823],[27.192377,40.690566]]]]}},\n{\"type\":\"Feature\",\"id\":\"TWN\",\"properties\":{\"name\":\"Taiwan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[121.777818,24.394274],[121.175632,22.790857],[120.74708,21.970571],[120.220083,22.814861],[120.106189,23.556263],[120.69468,24.538451],[121.495044,25.295459],[121.951244,24.997596],[121.777818,24.394274]]]}},\n{\"type\":\"Feature\",\"id\":\"TZA\",\"properties\":{\"name\":\"United Republic of Tanzania\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[33.903711,-0.95],[34.07262,-1.05982],[37.69869,-3.09699],[37.7669,-3.67712],[39.20222,-4.67677],[38.74054,-5.90895],[38.79977,-6.47566],[39.44,-6.84],[39.47,-7.1],[39.19469,-7.7039],[39.25203,-8.00781],[39.18652,-8.48551],[39.53574,-9.11237],[39.9496,-10.0984],[40.31659,-10.3171],[39.521,-10.89688],[38.427557,-11.285202],[37.82764,-11.26879],[37.47129,-11.56876],[36.775151,-11.594537],[36.514082,-11.720938],[35.312398,-11.439146],[34.559989,-11.52002],[34.28,-10.16],[33.940838,-9.693674],[33.73972,-9.41715],[32.759375,-9.230599],[32.191865,-8.930359],[31.556348,-8.762049],[31.157751,-8.594579],[30.74,-8.34],[30.2,-7.08],[29.62,-6.52],[29.419993,-5.939999],[29.519987,-5.419979],[29.339998,-4.499983],[29.753512,-4.452389],[30.11632,-4.09012],[30.50554,-3.56858],[30.75224,-3.35931],[30.74301,-3.03431],[30.52766,-2.80762],[30.46967,-2.41383],[30.758309,-2.28725],[30.816135,-1.698914],[30.419105,-1.134659],[30.76986,-1.01455],[31.86617,-1.02736],[33.903711,-0.95]]]}},\n{\"type\":\"Feature\",\"id\":\"UGA\",\"properties\":{\"name\":\"Uganda\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[31.86617,-1.02736],[30.76986,-1.01455],[30.419105,-1.134659],[29.821519,-1.443322],[29.579466,-1.341313],[29.587838,-0.587406],[29.8195,-0.2053],[29.875779,0.59738],[30.086154,1.062313],[30.468508,1.583805],[30.85267,1.849396],[31.174149,2.204465],[30.77332,2.33989],[30.83385,3.50917],[31.24556,3.7819],[31.88145,3.55827],[32.68642,3.79232],[33.39,3.79],[34.005,4.249885],[34.47913,3.5556],[34.59607,3.05374],[35.03599,1.90584],[34.6721,1.17694],[34.18,0.515],[33.893569,0.109814],[33.903711,-0.95],[31.86617,-1.02736]]]}},\n{\"type\":\"Feature\",\"id\":\"UKR\",\"properties\":{\"name\":\"Ukraine\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[31.785998,52.101678],[32.159412,52.061267],[32.412058,52.288695],[32.715761,52.238465],[33.7527,52.335075],[34.391731,51.768882],[34.141978,51.566413],[34.224816,51.255993],[35.022183,51.207572],[35.377924,50.773955],[35.356116,50.577197],[36.626168,50.225591],[37.39346,50.383953],[38.010631,49.915662],[38.594988,49.926462],[40.069058,49.601055],[40.080789,49.30743],[39.674664,48.783818],[39.895632,48.232405],[39.738278,47.898937],[38.770585,47.825608],[38.255112,47.5464],[38.223538,47.10219],[37.425137,47.022221],[36.759855,46.6987],[35.823685,46.645964],[34.962342,46.273197],[35.020788,45.651219],[35.510009,45.409993],[36.529998,45.46999],[36.334713,45.113216],[35.239999,44.939996],[33.882511,44.361479],[33.326421,44.564877],[33.546924,45.034771],[32.454174,45.327466],[32.630804,45.519186],[33.588162,45.851569],[33.298567,46.080598],[31.74414,46.333348],[31.675307,46.706245],[30.748749,46.5831],[30.377609,46.03241],[29.603289,45.293308],[29.149725,45.464925],[28.679779,45.304031],[28.233554,45.488283],[28.485269,45.596907],[28.659987,45.939987],[28.933717,46.25883],[28.862972,46.437889],[29.072107,46.517678],[29.170654,46.379262],[29.759972,46.349988],[30.024659,46.423937],[29.83821,46.525326],[29.908852,46.674361],[29.559674,46.928583],[29.415135,47.346645],[29.050868,47.510227],[29.122698,47.849095],[28.670891,48.118149],[28.259547,48.155562],[27.522537,48.467119],[26.857824,48.368211],[26.619337,48.220726],[26.19745,48.220881],[25.945941,47.987149],[25.207743,47.891056],[24.866317,47.737526],[24.402056,47.981878],[23.760958,47.985598],[23.142236,48.096341],[22.710531,47.882194],[22.64082,48.15024],[22.085608,48.422264],[22.280842,48.825392],[22.558138,49.085738],[22.776419,49.027395],[22.51845,49.476774],[23.426508,50.308506],[23.922757,50.424881],[24.029986,50.705407],[23.527071,51.578454],[24.005078,51.617444],[24.553106,51.888461],[25.327788,51.910656],[26.337959,51.832289],[27.454066,51.592303],[28.241615,51.572227],[28.617613,51.427714],[28.992835,51.602044],[29.254938,51.368234],[30.157364,51.416138],[30.555117,51.319503],[30.619454,51.822806],[30.927549,52.042353],[31.785998,52.101678]]]}},\n{\"type\":\"Feature\",\"id\":\"URY\",\"properties\":{\"name\":\"Uruguay\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-57.625133,-30.216295],[-56.976026,-30.109686],[-55.973245,-30.883076],[-55.60151,-30.853879],[-54.572452,-31.494511],[-53.787952,-32.047243],[-53.209589,-32.727666],[-53.650544,-33.202004],[-53.373662,-33.768378],[-53.806426,-34.396815],[-54.935866,-34.952647],[-55.67409,-34.752659],[-56.215297,-34.859836],[-57.139685,-34.430456],[-57.817861,-34.462547],[-58.427074,-33.909454],[-58.349611,-33.263189],[-58.132648,-33.040567],[-58.14244,-32.044504],[-57.874937,-31.016556],[-57.625133,-30.216295]]]}},\n{\"type\":\"Feature\",\"id\":\"USA\",\"properties\":{\"name\":\"United States of America\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-155.54211,19.08348],[-155.68817,18.91619],[-155.93665,19.05939],[-155.90806,19.33888],[-156.07347,19.70294],[-156.02368,19.81422],[-155.85008,19.97729],[-155.91907,20.17395],[-155.86108,20.26721],[-155.78505,20.2487],[-155.40214,20.07975],[-155.22452,19.99302],[-155.06226,19.8591],[-154.80741,19.50871],[-154.83147,19.45328],[-155.22217,19.23972],[-155.54211,19.08348]]],[[[-156.07926,20.64397],[-156.41445,20.57241],[-156.58673,20.783],[-156.70167,20.8643],[-156.71055,20.92676],[-156.61258,21.01249],[-156.25711,20.91745],[-155.99566,20.76404],[-156.07926,20.64397]]],[[[-156.75824,21.17684],[-156.78933,21.06873],[-157.32521,21.09777],[-157.25027,21.21958],[-156.75824,21.17684]]],[[[-157.65283,21.32217],[-157.70703,21.26442],[-157.7786,21.27729],[-158.12667,21.31244],[-158.2538,21.53919],[-158.29265,21.57912],[-158.0252,21.71696],[-157.94161,21.65272],[-157.65283,21.32217]]],[[[-159.34512,21.982],[-159.46372,21.88299],[-159.80051,22.06533],[-159.74877,22.1382],[-159.5962,22.23618],[-159.36569,22.21494],[-159.34512,21.982]]],[[[-94.81758,49.38905],[-94.64,48.84],[-94.32914,48.67074],[-93.63087,48.60926],[-92.61,48.45],[-91.64,48.14],[-90.83,48.27],[-89.6,48.01],[-89.272917,48.019808],[-88.378114,48.302918],[-87.439793,47.94],[-86.461991,47.553338],[-85.652363,47.220219],[-84.87608,46.900083],[-84.779238,46.637102],[-84.543749,46.538684],[-84.6049,46.4396],[-84.3367,46.40877],[-84.14212,46.512226],[-84.091851,46.275419],[-83.890765,46.116927],[-83.616131,46.116927],[-83.469551,45.994686],[-83.592851,45.816894],[-82.550925,45.347517],[-82.337763,44.44],[-82.137642,43.571088],[-82.43,42.98],[-82.9,42.43],[-83.12,42.08],[-83.142,41.975681],[-83.02981,41.832796],[-82.690089,41.675105],[-82.439278,41.675105],[-81.277747,42.209026],[-80.247448,42.3662],[-78.939362,42.863611],[-78.92,42.965],[-79.01,43.27],[-79.171674,43.466339],[-78.72028,43.625089],[-77.737885,43.629056],[-76.820034,43.628784],[-76.5,44.018459],[-76.375,44.09631],[-75.31821,44.81645],[-74.867,45.00048],[-73.34783,45.00738],[-71.50506,45.0082],[-71.405,45.255],[-71.08482,45.30524],[-70.66,45.46],[-70.305,45.915],[-69.99997,46.69307],[-69.237216,47.447781],[-68.905,47.185],[-68.23444,47.35486],[-67.79046,47.06636],[-67.79134,45.70281],[-67.13741,45.13753],[-66.96466,44.8097],[-68.03252,44.3252],[-69.06,43.98],[-70.11617,43.68405],[-70.645476,43.090238],[-70.81489,42.8653],[-70.825,42.335],[-70.495,41.805],[-70.08,41.78],[-70.185,42.145],[-69.88497,41.92283],[-69.96503,41.63717],[-70.64,41.475],[-71.12039,41.49445],[-71.86,41.32],[-72.295,41.27],[-72.87643,41.22065],[-73.71,40.931102],[-72.24126,41.11948],[-71.945,40.93],[-73.345,40.63],[-73.982,40.628],[-73.952325,40.75075],[-74.25671,40.47351],[-73.96244,40.42763],[-74.17838,39.70926],[-74.90604,38.93954],[-74.98041,39.1964],[-75.20002,39.24845],[-75.52805,39.4985],[-75.32,38.96],[-75.071835,38.782032],[-75.05673,38.40412],[-75.37747,38.01551],[-75.94023,37.21689],[-76.03127,37.2566],[-75.72205,37.93705],[-76.23287,38.319215],[-76.35,39.15],[-76.542725,38.717615],[-76.32933,38.08326],[-76.989998,38.239992],[-76.30162,37.917945],[-76.25874,36.9664],[-75.9718,36.89726],[-75.86804,36.55125],[-75.72749,35.55074],[-76.36318,34.80854],[-77.397635,34.51201],[-78.05496,33.92547],[-78.55435,33.86133],[-79.06067,33.49395],[-79.20357,33.15839],[-80.301325,32.509355],[-80.86498,32.0333],[-81.33629,31.44049],[-81.49042,30.72999],[-81.31371,30.03552],[-80.98,29.18],[-80.535585,28.47213],[-80.53,28.04],[-80.056539,26.88],[-80.088015,26.205765],[-80.13156,25.816775],[-80.38103,25.20616],[-80.68,25.08],[-81.17213,25.20126],[-81.33,25.64],[-81.71,25.87],[-82.24,26.73],[-82.70515,27.49504],[-82.85526,27.88624],[-82.65,28.55],[-82.93,29.1],[-83.70959,29.93656],[-84.1,30.09],[-85.10882,29.63615],[-85.28784,29.68612],[-85.7731,30.15261],[-86.4,30.4],[-87.53036,30.27433],[-88.41782,30.3849],[-89.18049,30.31598],[-89.593831,30.159994],[-89.413735,29.89419],[-89.43,29.48864],[-89.21767,29.29108],[-89.40823,29.15961],[-89.77928,29.30714],[-90.15463,29.11743],[-90.880225,29.148535],[-91.626785,29.677],[-92.49906,29.5523],[-93.22637,29.78375],[-93.84842,29.71363],[-94.69,29.48],[-95.60026,28.73863],[-96.59404,28.30748],[-97.14,27.83],[-97.37,27.38],[-97.38,26.69],[-97.33,26.21],[-97.14,25.87],[-97.53,25.84],[-98.24,26.06],[-99.02,26.37],[-99.3,26.84],[-99.52,27.54],[-100.11,28.11],[-100.45584,28.69612],[-100.9576,29.38071],[-101.6624,29.7793],[-102.48,29.76],[-103.11,28.97],[-103.94,29.27],[-104.45697,29.57196],[-104.70575,30.12173],[-105.03737,30.64402],[-105.63159,31.08383],[-106.1429,31.39995],[-106.50759,31.75452],[-108.24,31.754854],[-108.24194,31.34222],[-109.035,31.34194],[-111.02361,31.33472],[-113.30498,32.03914],[-114.815,32.52528],[-114.72139,32.72083],[-115.99135,32.61239],[-117.12776,32.53534],[-117.295938,33.046225],[-117.944,33.621236],[-118.410602,33.740909],[-118.519895,34.027782],[-119.081,34.078],[-119.438841,34.348477],[-120.36778,34.44711],[-120.62286,34.60855],[-120.74433,35.15686],[-121.71457,36.16153],[-122.54747,37.55176],[-122.51201,37.78339],[-122.95319,38.11371],[-123.7272,38.95166],[-123.86517,39.76699],[-124.39807,40.3132],[-124.17886,41.14202],[-124.2137,41.99964],[-124.53284,42.76599],[-124.14214,43.70838],[-124.020535,44.615895],[-123.89893,45.52341],[-124.079635,46.86475],[-124.39567,47.72017],[-124.68721,48.184433],[-124.566101,48.379715],[-123.12,48.04],[-122.58736,47.096],[-122.34,47.36],[-122.5,48.18],[-122.84,49],[-120,49],[-117.03121,49],[-116.04818,49],[-113,49],[-110.05,49],[-107.05,49],[-104.04826,48.99986],[-100.65,49],[-97.22872,49.0007],[-95.15907,49],[-95.15609,49.38425],[-94.81758,49.38905]]],[[[-153.006314,57.115842],[-154.00509,56.734677],[-154.516403,56.992749],[-154.670993,57.461196],[-153.76278,57.816575],[-153.228729,57.968968],[-152.564791,57.901427],[-152.141147,57.591059],[-153.006314,57.115842]]],[[[-165.579164,59.909987],[-166.19277,59.754441],[-166.848337,59.941406],[-167.455277,60.213069],[-166.467792,60.38417],[-165.67443,60.293607],[-165.579164,59.909987]]],[[[-171.731657,63.782515],[-171.114434,63.592191],[-170.491112,63.694975],[-169.682505,63.431116],[-168.689439,63.297506],[-168.771941,63.188598],[-169.52944,62.976931],[-170.290556,63.194438],[-170.671386,63.375822],[-171.553063,63.317789],[-171.791111,63.405846],[-171.731657,63.782515]]],[[[-155.06779,71.147776],[-154.344165,70.696409],[-153.900006,70.889989],[-152.210006,70.829992],[-152.270002,70.600006],[-150.739992,70.430017],[-149.720003,70.53001],[-147.613362,70.214035],[-145.68999,70.12001],[-144.920011,69.989992],[-143.589446,70.152514],[-142.07251,69.851938],[-140.985988,69.711998],[-140.992499,66.000029],[-140.99777,60.306397],[-140.012998,60.276838],[-139.039,60.000007],[-138.34089,59.56211],[-137.4525,58.905],[-136.47972,59.46389],[-135.47583,59.78778],[-134.945,59.27056],[-134.27111,58.86111],[-133.355549,58.410285],[-132.73042,57.69289],[-131.70781,56.55212],[-130.00778,55.91583],[-129.979994,55.284998],[-130.53611,54.802753],[-131.085818,55.178906],[-131.967211,55.497776],[-132.250011,56.369996],[-133.539181,57.178887],[-134.078063,58.123068],[-135.038211,58.187715],[-136.628062,58.212209],[-137.800006,58.499995],[-139.867787,59.537762],[-140.825274,59.727517],[-142.574444,60.084447],[-143.958881,59.99918],[-145.925557,60.45861],[-147.114374,60.884656],[-148.224306,60.672989],[-148.018066,59.978329],[-148.570823,59.914173],[-149.727858,59.705658],[-150.608243,59.368211],[-151.716393,59.155821],[-151.859433,59.744984],[-151.409719,60.725803],[-150.346941,61.033588],[-150.621111,61.284425],[-151.895839,60.727198],[-152.57833,60.061657],[-154.019172,59.350279],[-153.287511,58.864728],[-154.232492,58.146374],[-155.307491,57.727795],[-156.308335,57.422774],[-156.556097,56.979985],[-158.117217,56.463608],[-158.433321,55.994154],[-159.603327,55.566686],[-160.28972,55.643581],[-161.223048,55.364735],[-162.237766,55.024187],[-163.069447,54.689737],[-164.785569,54.404173],[-164.942226,54.572225],[-163.84834,55.039431],[-162.870001,55.348043],[-161.804175,55.894986],[-160.563605,56.008055],[-160.07056,56.418055],[-158.684443,57.016675],[-158.461097,57.216921],[-157.72277,57.570001],[-157.550274,58.328326],[-157.041675,58.918885],[-158.194731,58.615802],[-158.517218,58.787781],[-159.058606,58.424186],[-159.711667,58.93139],[-159.981289,58.572549],[-160.355271,59.071123],[-161.355003,58.670838],[-161.968894,58.671665],[-162.054987,59.266925],[-161.874171,59.633621],[-162.518059,59.989724],[-163.818341,59.798056],[-164.662218,60.267484],[-165.346388,60.507496],[-165.350832,61.073895],[-166.121379,61.500019],[-165.734452,62.074997],[-164.919179,62.633076],[-164.562508,63.146378],[-163.753332,63.219449],[-163.067224,63.059459],[-162.260555,63.541936],[-161.53445,63.455817],[-160.772507,63.766108],[-160.958335,64.222799],[-161.518068,64.402788],[-160.777778,64.788604],[-161.391926,64.777235],[-162.45305,64.559445],[-162.757786,64.338605],[-163.546394,64.55916],[-164.96083,64.446945],[-166.425288,64.686672],[-166.845004,65.088896],[-168.11056,65.669997],[-166.705271,66.088318],[-164.47471,66.57666],[-163.652512,66.57666],[-163.788602,66.077207],[-161.677774,66.11612],[-162.489715,66.735565],[-163.719717,67.116395],[-164.430991,67.616338],[-165.390287,68.042772],[-166.764441,68.358877],[-166.204707,68.883031],[-164.430811,68.915535],[-163.168614,69.371115],[-162.930566,69.858062],[-161.908897,70.33333],[-160.934797,70.44769],[-159.039176,70.891642],[-158.119723,70.824721],[-156.580825,71.357764],[-155.06779,71.147776]]]]}},\n{\"type\":\"Feature\",\"id\":\"UZB\",\"properties\":{\"name\":\"Uzbekistan\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[66.518607,37.362784],[66.54615,37.974685],[65.215999,38.402695],[64.170223,38.892407],[63.518015,39.363257],[62.37426,40.053886],[61.882714,41.084857],[61.547179,41.26637],[60.465953,41.220327],[60.083341,41.425146],[59.976422,42.223082],[58.629011,42.751551],[57.78653,42.170553],[56.932215,41.826026],[57.096391,41.32231],[55.968191,41.308642],[55.928917,44.995858],[58.503127,45.586804],[58.689989,45.500014],[60.239972,44.784037],[61.05832,44.405817],[62.0133,43.504477],[63.185787,43.650075],[64.900824,43.728081],[66.098012,42.99766],[66.023392,41.994646],[66.510649,41.987644],[66.714047,41.168444],[67.985856,41.135991],[68.259896,40.662325],[68.632483,40.668681],[69.070027,41.384244],[70.388965,42.081308],[70.962315,42.266154],[71.259248,42.167711],[70.420022,41.519998],[71.157859,41.143587],[71.870115,41.3929],[73.055417,40.866033],[71.774875,40.145844],[71.014198,40.244366],[70.601407,40.218527],[70.45816,40.496495],[70.666622,40.960213],[69.329495,40.727824],[69.011633,40.086158],[68.536416,39.533453],[67.701429,39.580478],[67.44222,39.140144],[68.176025,38.901553],[68.392033,38.157025],[67.83,37.144994],[67.075782,37.356144],[66.518607,37.362784]]]}},\n{\"type\":\"Feature\",\"id\":\"VEN\",\"properties\":{\"name\":\"Venezuela\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-71.331584,11.776284],[-71.360006,11.539994],[-71.94705,11.423282],[-71.620868,10.96946],[-71.633064,10.446494],[-72.074174,9.865651],[-71.695644,9.072263],[-71.264559,9.137195],[-71.039999,9.859993],[-71.350084,10.211935],[-71.400623,10.968969],[-70.155299,11.375482],[-70.293843,11.846822],[-69.943245,12.162307],[-69.5843,11.459611],[-68.882999,11.443385],[-68.233271,10.885744],[-68.194127,10.554653],[-67.296249,10.545868],[-66.227864,10.648627],[-65.655238,10.200799],[-64.890452,10.077215],[-64.329479,10.389599],[-64.318007,10.641418],[-63.079322,10.701724],[-61.880946,10.715625],[-62.730119,10.420269],[-62.388512,9.948204],[-61.588767,9.873067],[-60.830597,9.38134],[-60.671252,8.580174],[-60.150096,8.602757],[-59.758285,8.367035],[-60.550588,7.779603],[-60.637973,7.415],[-60.295668,7.043911],[-60.543999,6.856584],[-61.159336,6.696077],[-61.139415,6.234297],[-61.410303,5.959068],[-60.733574,5.200277],[-60.601179,4.918098],[-60.966893,4.536468],[-62.08543,4.162124],[-62.804533,4.006965],[-63.093198,3.770571],[-63.888343,4.02053],[-64.628659,4.148481],[-64.816064,4.056445],[-64.368494,3.79721],[-64.408828,3.126786],[-64.269999,2.497006],[-63.422867,2.411068],[-63.368788,2.2009],[-64.083085,1.916369],[-64.199306,1.492855],[-64.611012,1.328731],[-65.354713,1.095282],[-65.548267,0.789254],[-66.325765,0.724452],[-66.876326,1.253361],[-67.181294,2.250638],[-67.447092,2.600281],[-67.809938,2.820655],[-67.303173,3.318454],[-67.337564,3.542342],[-67.621836,3.839482],[-67.823012,4.503937],[-67.744697,5.221129],[-67.521532,5.55687],[-67.34144,6.095468],[-67.695087,6.267318],[-68.265052,6.153268],[-68.985319,6.206805],[-69.38948,6.099861],[-70.093313,6.960376],[-70.674234,7.087785],[-71.960176,6.991615],[-72.198352,7.340431],[-72.444487,7.423785],[-72.479679,7.632506],[-72.360901,8.002638],[-72.439862,8.405275],[-72.660495,8.625288],[-72.78873,9.085027],[-73.304952,9.152],[-73.027604,9.73677],[-72.905286,10.450344],[-72.614658,10.821975],[-72.227575,11.108702],[-71.973922,11.608672],[-71.331584,11.776284]]]}},\n{\"type\":\"Feature\",\"id\":\"VNM\",\"properties\":{\"name\":\"Vietnam\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[108.05018,21.55238],[106.715068,20.696851],[105.881682,19.75205],[105.662006,19.058165],[106.426817,18.004121],[107.361954,16.697457],[108.269495,16.079742],[108.877107,15.276691],[109.33527,13.426028],[109.200136,11.666859],[108.36613,11.008321],[107.220929,10.364484],[106.405113,9.53084],[105.158264,8.59976],[104.795185,9.241038],[105.076202,9.918491],[104.334335,10.486544],[105.199915,10.88931],[106.24967,10.961812],[105.810524,11.567615],[107.491403,12.337206],[107.614548,13.535531],[107.382727,14.202441],[107.564525,15.202173],[107.312706,15.908538],[106.556008,16.604284],[105.925762,17.485315],[105.094598,18.666975],[103.896532,19.265181],[104.183388,19.624668],[104.822574,19.886642],[104.435,20.758733],[103.203861,20.766562],[102.754896,21.675137],[102.170436,22.464753],[102.706992,22.708795],[103.504515,22.703757],[104.476858,22.81915],[105.329209,23.352063],[105.811247,22.976892],[106.725403,22.794268],[106.567273,22.218205],[107.04342,21.811899],[108.05018,21.55238]]]}},\n{\"type\":\"Feature\",\"id\":\"VUT\",\"properties\":{\"name\":\"Vanuatu\"},\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[[[167.844877,-16.466333],[167.515181,-16.59785],[167.180008,-16.159995],[167.216801,-15.891846],[167.844877,-16.466333]]],[[[167.107712,-14.93392],[167.270028,-15.740021],[167.001207,-15.614602],[166.793158,-15.668811],[166.649859,-15.392704],[166.629137,-14.626497],[167.107712,-14.93392]]]]}},\n{\"type\":\"Feature\",\"id\":\"PSE\",\"properties\":{\"name\":\"West Bank\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[35.545665,32.393992],[35.545252,31.782505],[35.397561,31.489086],[34.927408,31.353435],[34.970507,31.616778],[35.225892,31.754341],[34.974641,31.866582],[35.18393,32.532511],[35.545665,32.393992]]]}},\n{\"type\":\"Feature\",\"id\":\"YEM\",\"properties\":{\"name\":\"Yemen\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[53.108573,16.651051],[52.385206,16.382411],[52.191729,15.938433],[52.168165,15.59742],[51.172515,15.17525],[49.574576,14.708767],[48.679231,14.003202],[48.238947,13.94809],[47.938914,14.007233],[47.354454,13.59222],[46.717076,13.399699],[45.877593,13.347764],[45.62505,13.290946],[45.406459,13.026905],[45.144356,12.953938],[44.989533,12.699587],[44.494576,12.721653],[44.175113,12.58595],[43.482959,12.6368],[43.222871,13.22095],[43.251448,13.767584],[43.087944,14.06263],[42.892245,14.802249],[42.604873,15.213335],[42.805015,15.261963],[42.702438,15.718886],[42.823671,15.911742],[42.779332,16.347891],[43.218375,16.66689],[43.115798,17.08844],[43.380794,17.579987],[43.791519,17.319977],[44.062613,17.410359],[45.216651,17.433329],[45.399999,17.333335],[46.366659,17.233315],[46.749994,17.283338],[47.000005,16.949999],[47.466695,17.116682],[48.183344,18.166669],[49.116672,18.616668],[52.00001,19.000003],[52.782184,17.349742],[53.108573,16.651051]]]}},\n{\"type\":\"Feature\",\"id\":\"ZAF\",\"properties\":{\"name\":\"South Africa\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[31.521001,-29.257387],[31.325561,-29.401978],[30.901763,-29.909957],[30.622813,-30.423776],[30.055716,-31.140269],[28.925553,-32.172041],[28.219756,-32.771953],[27.464608,-33.226964],[26.419452,-33.61495],[25.909664,-33.66704],[25.780628,-33.944646],[25.172862,-33.796851],[24.677853,-33.987176],[23.594043,-33.794474],[22.988189,-33.916431],[22.574157,-33.864083],[21.542799,-34.258839],[20.689053,-34.417175],[20.071261,-34.795137],[19.616405,-34.819166],[19.193278,-34.462599],[18.855315,-34.444306],[18.424643,-33.997873],[18.377411,-34.136521],[18.244499,-33.867752],[18.25008,-33.281431],[17.92519,-32.611291],[18.24791,-32.429131],[18.221762,-31.661633],[17.566918,-30.725721],[17.064416,-29.878641],[17.062918,-29.875954],[16.344977,-28.576705],[16.824017,-28.082162],[17.218929,-28.355943],[17.387497,-28.783514],[17.836152,-28.856378],[18.464899,-29.045462],[19.002127,-28.972443],[19.894734,-28.461105],[19.895768,-24.76779],[20.165726,-24.917962],[20.758609,-25.868136],[20.66647,-26.477453],[20.889609,-26.828543],[21.605896,-26.726534],[22.105969,-26.280256],[22.579532,-25.979448],[22.824271,-25.500459],[23.312097,-25.26869],[23.73357,-25.390129],[24.211267,-25.670216],[25.025171,-25.71967],[25.664666,-25.486816],[25.765849,-25.174845],[25.941652,-24.696373],[26.485753,-24.616327],[26.786407,-24.240691],[27.11941,-23.574323],[28.017236,-22.827754],[29.432188,-22.091313],[29.839037,-22.102216],[30.322883,-22.271612],[30.659865,-22.151567],[31.191409,-22.25151],[31.670398,-23.658969],[31.930589,-24.369417],[31.752408,-25.484284],[31.837778,-25.843332],[31.333158,-25.660191],[31.04408,-25.731452],[30.949667,-26.022649],[30.676609,-26.398078],[30.685962,-26.743845],[31.282773,-27.285879],[31.86806,-27.177927],[32.071665,-26.73382],[32.83012,-26.742192],[32.580265,-27.470158],[32.462133,-28.301011],[32.203389,-28.752405],[31.521001,-29.257387]],[[28.978263,-28.955597],[28.5417,-28.647502],[28.074338,-28.851469],[27.532511,-29.242711],[26.999262,-29.875954],[27.749397,-30.645106],[28.107205,-30.545732],[28.291069,-30.226217],[28.8484,-30.070051],[29.018415,-29.743766],[29.325166,-29.257387],[28.978263,-28.955597]]]}},\n{\"type\":\"Feature\",\"id\":\"ZMB\",\"properties\":{\"name\":\"Zambia\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[32.759375,-9.230599],[33.231388,-9.676722],[33.485688,-10.525559],[33.31531,-10.79655],[33.114289,-11.607198],[33.306422,-12.435778],[32.991764,-12.783871],[32.688165,-13.712858],[33.214025,-13.97186],[30.179481,-14.796099],[30.274256,-15.507787],[29.516834,-15.644678],[28.947463,-16.043051],[28.825869,-16.389749],[28.467906,-16.4684],[27.598243,-17.290831],[27.044427,-17.938026],[26.706773,-17.961229],[26.381935,-17.846042],[25.264226,-17.73654],[25.084443,-17.661816],[25.07695,-17.578823],[24.682349,-17.353411],[24.033862,-17.295843],[23.215048,-17.523116],[22.562478,-16.898451],[21.887843,-16.08031],[21.933886,-12.898437],[24.016137,-12.911046],[23.930922,-12.565848],[24.079905,-12.191297],[23.904154,-11.722282],[24.017894,-11.237298],[23.912215,-10.926826],[24.257155,-10.951993],[24.314516,-11.262826],[24.78317,-11.238694],[25.418118,-11.330936],[25.75231,-11.784965],[26.553088,-11.92444],[27.16442,-11.608748],[27.388799,-12.132747],[28.155109,-12.272481],[28.523562,-12.698604],[28.934286,-13.248958],[29.699614,-13.257227],[29.616001,-12.178895],[29.341548,-12.360744],[28.642417,-11.971569],[28.372253,-11.793647],[28.49607,-10.789884],[28.673682,-9.605925],[28.449871,-9.164918],[28.734867,-8.526559],[29.002912,-8.407032],[30.346086,-8.238257],[30.740015,-8.340007],[31.157751,-8.594579],[31.556348,-8.762049],[32.191865,-8.930359],[32.759375,-9.230599]]]}},\n{\"type\":\"Feature\",\"id\":\"ZWE\",\"properties\":{\"name\":\"Zimbabwe\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[31.191409,-22.25151],[30.659865,-22.151567],[30.322883,-22.271612],[29.839037,-22.102216],[29.432188,-22.091313],[28.794656,-21.639454],[28.02137,-21.485975],[27.727228,-20.851802],[27.724747,-20.499059],[27.296505,-20.39152],[26.164791,-19.293086],[25.850391,-18.714413],[25.649163,-18.536026],[25.264226,-17.73654],[26.381935,-17.846042],[26.706773,-17.961229],[27.044427,-17.938026],[27.598243,-17.290831],[28.467906,-16.4684],[28.825869,-16.389749],[28.947463,-16.043051],[29.516834,-15.644678],[30.274256,-15.507787],[30.338955,-15.880839],[31.173064,-15.860944],[31.636498,-16.07199],[31.852041,-16.319417],[32.328239,-16.392074],[32.847639,-16.713398],[32.849861,-17.979057],[32.654886,-18.67209],[32.611994,-19.419383],[32.772708,-19.715592],[32.659743,-20.30429],[32.508693,-20.395292],[32.244988,-21.116489],[31.191409,-22.25151]]]}}\n]}"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/App.java",
    "content": "package com.vasilkoff.easyvpnfree;\n\nimport android.app.Application;\nimport android.content.Context;\nimport android.content.res.Configuration;\n\nimport com.crashlytics.android.Crashlytics;\nimport com.crashlytics.android.answers.Answers;\nimport com.google.android.gms.analytics.GoogleAnalytics;\nimport com.google.android.gms.analytics.Tracker;\n\nimport io.fabric.sdk.android.Fabric;\n\npublic class App extends Application {\n\n    private static App instance;\n    private Tracker mTracker;\n    private static final String PROPERTY_ID = \"UA-89622148-1\";\n    private static final String PROPERTY_ID_PRO = \"UA-89641705-1\";\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        if (!BuildConfig.DEBUG)\n            Fabric.with(this, new Crashlytics());\n\n        instance = this;\n    }\n\n    synchronized public Tracker getDefaultTracker() {\n        if (mTracker == null) {\n            GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);\n            mTracker = analytics.newTracker(BuildConfig.FLAVOR == \"pro\" ? PROPERTY_ID_PRO : PROPERTY_ID);\n        }\n        return mTracker;\n    }\n\n    @Override\n    protected void attachBaseContext(Context base) {\n        super.attachBaseContext(base);\n    }\n\n    public static String getResourceString(int resId) {\n        return instance.getString(resId);\n    }\n\n    public static App getInstance() {\n        return instance;\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/AboutActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\n\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.os.Bundle;\nimport android.widget.TextView;\n\nimport com.vasilkoff.easyvpnfree.R;\n\npublic class AboutActivity extends BaseActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_about);\n        try {\n            PackageInfo pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);\n            int versionNumber = pinfo.versionCode;\n            String versionName = pinfo.versionName;\n            String appName =  AboutActivity.this.getString(R.string.app_name);\n            TextView versionText = (TextView)findViewById(R.id.appVersion);\n            versionText.setText(\n                    String.format(\"%s version %s build %d\",\n                            appName,\n                            versionName,\n                            versionNumber\n                            )\n            );\n        } catch (PackageManager.NameNotFoundException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/BaseActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.content.Intent;\n\nimport android.support.v4.widget.DrawerLayout;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.Toolbar;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.FrameLayout;\n\n\nimport com.androidnetworking.AndroidNetworking;\nimport com.androidnetworking.common.Priority;\nimport com.androidnetworking.error.ANError;\nimport com.androidnetworking.interfaces.JSONArrayRequestListener;\nimport com.crashlytics.android.answers.Answers;\nimport com.crashlytics.android.answers.CustomEvent;\nimport com.google.android.gms.analytics.HitBuilders;\nimport com.google.android.gms.analytics.Tracker;\nimport com.vasilkoff.easyvpnfree.App;\nimport com.vasilkoff.easyvpnfree.BuildConfig;\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.database.DBHelper;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.CountriesNames;\nimport com.vasilkoff.easyvpnfree.util.PropertiesService;\n\nimport com.vasilkoff.easyvpnfree.util.TotalTraffic;\nimport com.vasilkoff.easyvpnfree.util.iap.IabHelper;\nimport com.vasilkoff.easyvpnfree.util.iap.IabResult;\nimport com.vasilkoff.easyvpnfree.util.iap.Inventory;\nimport com.vasilkoff.easyvpnfree.util.iap.Purchase;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Random;\n\nimport de.blinkt.openvpn.core.VpnStatus;\n\n/**\n * Created by Kusenko on 20.10.2016.\n */\n\npublic abstract class BaseActivity extends AppCompatActivity {\n\n    private DrawerLayout fullLayout;\n    private Toolbar toolbar;\n\n    static final int ADBLOCK_REQUEST = 10001;\n    static final int PREMIUM_SERVERS_REQUEST = 10002;\n    public static Server connectedServer = null;\n    boolean hideCurrentConnection = false;\n    IabHelper iapHelper;\n    public static final String IAP_TAG = \"IAP\";\n    static final String TEST_ITEM_SKU = \"android.test.purchased\";\n    static final String ADBLOCK_ITEM_SKU = \"adblock\";\n    static final String MORE_SERVERS_ITEM_SKU = \"more_servers\";\n    static String key = \"\";\n\n    static boolean availableFilterAds = false;\n    static boolean premiumServers = false;\n\n    static String adblockSKU;\n    static String moreServersSKU;\n    static String currentSKU;\n\n    int widthWindow ;\n    int heightWindow;\n\n    static DBHelper dbHelper;\n    Map<String, String> localeCountries;\n\n    static Tracker mTracker;\n\n    @Override\n    public void setContentView(int layoutResID)\n    {\n        if (BuildConfig.FLAVOR == \"pro\" || BuildConfig.FLAVOR == \"underground\") {\n            availableFilterAds = true;\n            premiumServers = true;\n        }\n\n        fullLayout = (DrawerLayout) getLayoutInflater().inflate(R.layout.activity_base, null);\n        FrameLayout activityContainer = (FrameLayout) fullLayout.findViewById(R.id.activity_content);\n        getLayoutInflater().inflate(layoutResID, activityContainer, true);\n        super.setContentView(fullLayout);\n\n        toolbar = (Toolbar) findViewById(R.id.toolbar);\n\n        if (useToolbar()) {\n            setSupportActionBar(toolbar);\n        } else {\n            toolbar.setVisibility(View.GONE);\n        }\n\n        if (useHomeButton()) {\n            if (getSupportActionBar() != null){\n                getSupportActionBar().setDisplayHomeAsUpEnabled(true);\n                getSupportActionBar().setDisplayShowHomeEnabled(true);\n            }\n        }\n\n        if (BuildConfig.DEBUG) {\n            moreServersSKU = TEST_ITEM_SKU;\n            adblockSKU = TEST_ITEM_SKU;\n        } else {\n            moreServersSKU = MORE_SERVERS_ITEM_SKU;\n            adblockSKU = ADBLOCK_ITEM_SKU;\n        }\n\n\n\n        dbHelper = new DBHelper(this);\n\n        DisplayMetrics dm = new DisplayMetrics();\n        getWindowManager().getDefaultDisplay().getMetrics(dm);\n\n        widthWindow = dm.widthPixels;\n        heightWindow = dm.heightPixels;\n\n        localeCountries = CountriesNames.getCountries();\n\n        App application = (App) getApplication();\n        mTracker = application.getDefaultTracker();\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        TotalTraffic.saveTotal();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        if (iapHelper != null) iapHelper.dispose();\n        iapHelper = null;\n    }\n\n    private void initPurchaseHelper() {\n        if (iapHelper == null) {\n            iapHelper = new IabHelper(this, getString(R.string.base64EncodedPublicKey));\n            iapHelper.enableDebugLogging(BuildConfig.DEBUG);\n\n            iapHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {\n                @Override\n                public void onIabSetupFinished(IabResult result) {\n                    if (result.isSuccess()) {\n                        // Have we been disposed of in the meantime? If so, quit.\n                        if (iapHelper == null) return;\n\n                        // IAB is fully set up. Now, let's get an inventory of stuff we own.\n                        Log.d(IAP_TAG, \"Setup successful. Querying inventory.\");\n\n                        checkPurchase();\n                    } else {\n                        Log.d(IAP_TAG, \"Oh noes, there was a problem.\");\n                    }\n                }\n            });\n        }\n    }\n\n    private void checkPurchase() {\n        iapHelper.flagEndAsync();\n        if(iapHelper.isSetupDone() && !iapHelper.isAsyncInProgress() && !iapHelper.isDisposed()) {\n            iapHelper.queryInventoryAsync(mGotInventoryListener);\n        }\n    }\n\n    void launchPurchase(String sku, int request) {\n        currentSKU = sku;\n        String base64EncodedPublicKey = getString(R.string.base64EncodedPublicKey);\n        Random random = new Random();\n        key = base64EncodedPublicKey.substring(random.nextInt(base64EncodedPublicKey.length() - 2));\n\n        iapHelper.flagEndAsync();\n        if (iapHelper.isSetupDone() && !iapHelper.isAsyncInProgress() && !iapHelper.isDisposed()) {\n            iapHelper.launchPurchaseFlow(this,\n                    sku, request,\n                    mPurchaseFinishedListener,\n                    key + sku);\n        }\n    }\n\n\n    /** Verifies the developer payload of a purchase. */\n    boolean verifyDeveloperPayload(Purchase p, String sku) {\n        String responsePayload = p.getDeveloperPayload();\n        String computedPayload = key + sku;\n\n        return responsePayload != null && responsePayload.equals(computedPayload);\n    }\n\n    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {\n        @Override\n        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {\n            if (result.isFailure()) {\n                Log.d(IAP_TAG, \"Purchase finished: \" + result + \", purchase: \" + inventory);\n            } else {\n                if (inventory.hasPurchase(adblockSKU)) {\n                    availableFilterAds = true;\n                }\n                if (inventory.hasPurchase(moreServersSKU)) {\n                    premiumServers = true;\n                }\n            }\n        }\n    };\n\n    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {\n        @Override\n        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {\n            if (result.isFailure()) {\n                Log.d(IAP_TAG, \"Oh noes, there was a problem.\");\n                return;\n            } else {\n                if (purchase.getSku().equals(currentSKU) && verifyDeveloperPayload(purchase, currentSKU)) {\n                    availableFilterAds = true;\n                }\n            }\n        }\n    };\n\n    protected boolean useToolbar()\n    {\n        return true;\n    }\n\n    protected boolean useHomeButton()\n    {\n        return true;\n    }\n\n    protected boolean useMenu()\n    {\n        return true;\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n\n        if (BuildConfig.FLAVOR == \"free\") {\n            initPurchaseHelper();\n        }\n\n        mTracker.setScreenName(getClass().getSimpleName());\n        mTracker.send(new HitBuilders.ScreenViewBuilder().build());\n\n        if (!BuildConfig.DEBUG)\n            Answers.getInstance().logCustom(new CustomEvent(\"Viewed activity\")\n                    .putCustomAttribute(\"activity\", getClass().getSimpleName()));\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.menu_main, menu);\n\n        for (int i = 0; i < menu.size(); i++) {\n            if (menu.getItem(i).getItemId() == R.id.actionCurrentServer\n                    && (connectedServer == null || hideCurrentConnection || !VpnStatus.isVPNActive()))\n                menu.getItem(i).setVisible(false);\n\n            if (premiumServers && menu.getItem(i).getItemId() == R.id.actionGetMoreServers)\n                menu.getItem(i).setTitle(getString(R.string.current_servers_list));\n\n            if (BuildConfig.FLAVOR == \"underground\" && menu.getItem(i).getItemId() == R.id.actionShare)\n                menu.getItem(i).setVisible(false);\n        }\n\n        return useMenu();\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case android.R.id.home:\n                onBackPressed();\n                return true;\n            case R.id.actionRefresh:\n                startActivity(new Intent(getApplicationContext(), LoaderActivity.class));\n                finish();\n                return true;\n            case R.id.actionAbout:\n                startActivity(new Intent(getApplicationContext(), AboutActivity.class));\n                return true;\n            case R.id.actionShare:\n                sendTouchButton(\"Share\");\n                Intent sendIntent = new Intent();\n                sendIntent.setAction(Intent.ACTION_SEND);\n                sendIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_text));\n                sendIntent.setType(\"text/plain\");\n                startActivity(sendIntent);\n                return true;\n            case R.id.actionCurrentServer:\n                if (connectedServer != null)\n                    startActivity(new Intent(this, ServerActivity.class));\n                return true;\n            case R.id.actionGetMoreServers:\n                if (premiumServers) {\n                    startActivity(new Intent(this, ServersInfo.class));\n                } else {\n                    sendTouchButton(\"GetMoreServers\");\n                    launchPurchase(moreServersSKU, PREMIUM_SERVERS_REQUEST);\n                }\n                return true;\n            case R.id.action_settings:\n                sendTouchButton(\"Settings\");\n                startActivity(new Intent(this, MyPreferencesActivity.class));\n                return true;\n            case R.id.action_bookmarks:\n                startActivity(new Intent(this, BookmarkServerListActivity.class));\n                return true;\n        }\n\n        return super.onOptionsItemSelected(item);\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        if (resultCode == RESULT_OK) {\n            switch (requestCode) {\n                case PREMIUM_SERVERS_REQUEST:\n                    Log.d(IAP_TAG, \"onActivityResult(\" + requestCode + \",\" + resultCode + \",\" + data);\n\n                    if (iapHelper == null) return;\n\n                    if (iapHelper.handleActivityResult(requestCode, resultCode, data)) {\n                        Log.d(IAP_TAG, \"onActivityResult handled by IABUtil.\");\n                        Intent intent = new Intent(getApplicationContext(), LoaderActivity.class);\n                        intent.putExtra(\"firstPremiumLoad\", true);\n                        startActivity(intent);\n                        finish();\n                    }\n                    break;\n            }\n        }\n    }\n\n    public Server getRandomServer() {\n        Server randomServer;\n        if (PropertiesService.getCountryPriority()) {\n            randomServer = dbHelper.getGoodRandomServer(PropertiesService.getSelectedCountry());\n        } else {\n            randomServer = dbHelper.getGoodRandomServer(null);\n        }\n        return randomServer;\n    }\n\n    public void newConnecting(Server server, boolean fastConnection, boolean autoConnection) {\n        if (server != null) {\n            Intent intent = new Intent(this, ServerActivity.class);\n            intent.putExtra(Server.class.getCanonicalName(), server);\n            intent.putExtra(\"fastConnection\", fastConnection);\n            intent.putExtra(\"autoConnection\", autoConnection);\n            startActivity(intent);\n        }\n    }\n\n    public static void sendTouchButton(String button) {\n        if (!BuildConfig.DEBUG)\n            Answers.getInstance().logCustom(new CustomEvent(\"Touches buttons\")\n                .putCustomAttribute(\"Button\", button));\n\n        mTracker.send(new HitBuilders.EventBuilder()\n            .setCategory(\"Touches buttons\")\n            .setAction(button)\n            .build());\n    }\n\n    protected void ipInfoResult() {}\n\n    protected void getIpInfo(Server server) {\n        List<Server> serverList = new ArrayList<Server>();\n        serverList.add(server);\n        getIpInfo(serverList);\n    }\n\n    protected void getIpInfo(final List<Server> serverList) {\n        JSONArray jsonArray = new JSONArray();\n\n        for (Server server : serverList) {\n            JSONObject jsonObject = new JSONObject();\n            try {\n                jsonObject.put(\"query\", server.getIp());\n                jsonObject.put(\"lang\", Locale.getDefault().getLanguage());\n\n                jsonArray.put(jsonObject);\n            } catch (JSONException e) {\n                e.printStackTrace();\n            }\n        }\n\n        AndroidNetworking.post(getString(R.string.url_check_ip_batch))\n                .addJSONArrayBody(jsonArray)\n                .setTag(\"getIpInfo\")\n                .setPriority(Priority.MEDIUM)\n                .build()\n                .getAsJSONArray(new JSONArrayRequestListener() {\n                    @Override\n                    public void onResponse(JSONArray response) {\n                        if (dbHelper.setIpInfo(response, serverList))\n                            ipInfoResult();\n                    }\n                    @Override\n                    public void onError(ANError error) {\n\n                    }\n                });\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/BookmarkServerListActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\n\nimport android.os.Bundle;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.adapter.BookmarkServerListAdapter;\nimport com.vasilkoff.easyvpnfree.model.Server;\n\nimport java.util.List;\n\npublic class BookmarkServerListActivity extends BaseActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_bookmark_server_list);\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        final List<Server> serverList = dbHelper.getBookmarks();\n        BookmarkServerListAdapter adapter = new BookmarkServerListAdapter(serverList, this, dbHelper);\n\n        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.bookmarkRv);\n        LinearLayoutManager llm = new LinearLayoutManager(this);\n        recyclerView.setLayoutManager(llm);\n        recyclerView.setAdapter(adapter);\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/HomeActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.content.Intent;\nimport android.content.res.Configuration;\nimport android.graphics.drawable.BitmapDrawable;\nimport android.graphics.drawable.Drawable;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.support.v4.content.ContextCompat;\n\n\nimport android.text.method.LinkMovementMethod;\nimport android.text.util.Linkify;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\n\nimport android.widget.AdapterView;\nimport android.widget.ArrayAdapter;\n\nimport android.widget.LinearLayout;\nimport android.widget.ListView;\nimport android.widget.PopupWindow;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.crashlytics.android.answers.Answers;\n\nimport com.crashlytics.android.answers.CustomEvent;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\nimport com.vasilkoff.easyvpnfree.BuildConfig;\nimport com.vasilkoff.easyvpnfree.R;\n\nimport com.vasilkoff.easyvpnfree.model.Country;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.BitmapGenerator;\n\nimport com.vasilkoff.easyvpnfree.util.ConnectionQuality;\nimport com.vasilkoff.easyvpnfree.util.LoadData;\nimport com.vasilkoff.easyvpnfree.util.PropertiesService;\nimport com.vasilkoff.easyvpnfree.util.map.MapCreator;\nimport com.vasilkoff.easyvpnfree.util.map.MyMarker;\n\n\nimport org.mapsforge.core.graphics.Bitmap;\nimport org.mapsforge.core.model.LatLong;\nimport org.mapsforge.core.model.Point;\nimport org.mapsforge.map.android.graphics.AndroidGraphicFactory;\nimport org.mapsforge.map.android.view.MapView;\nimport org.mapsforge.map.layer.Layers;\nimport org.mapsforge.map.layer.overlay.Marker;\n\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\n\nimport java.util.List;\n\n\n\n\npublic class HomeActivity extends BaseActivity {\n\n    private MapView mapView;\n\n    public static final String EXTRA_COUNTRY = \"country\";\n    private PopupWindow popupWindow;\n    private RelativeLayout homeContextRL;\n\n    private List<Server> countryList;\n    private final String COUNTRY_FILE_NAME = \"countries.json\";\n\n    private List<Country> countryLatLonList = null;\n\n    private Layers layers;\n    private List<Marker> markerList;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_home);\n\n        homeContextRL = (RelativeLayout) findViewById(R.id.homeContextRL);\n        countryList = dbHelper.getUniqueCountries();\n\n        long totalServ = dbHelper.getCount();\n        if (!BuildConfig.DEBUG)\n            Answers.getInstance().logCustom(new CustomEvent(\"Total servers\")\n                .putCustomAttribute(\"Total servers\", totalServ));\n\n        String totalServers = String.format(getResources().getString(R.string.total_servers), totalServ);\n        ((TextView) findViewById(R.id.homeTotalServers)).setText(totalServers);\n\n        initMap();\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        invalidateOptionsMenu();\n\n        initDetailsServerOnMap();\n\n        if (PropertiesService.getShowNote()) {\n            homeContextRL.post(new Runnable() {\n                @Override\n                public void run() {\n                    showNote();\n                }\n            });\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        mapView.destroyAll();\n        AndroidGraphicFactory.clearResourceMemoryCache();\n        super.onDestroy();\n    }\n\n    private void initMap() {\n        AndroidGraphicFactory.createInstance(getApplication());\n        mapView = new MapView(this);\n\n        mapView.setClickable(true);\n        mapView.getMapScaleBar().setVisible(false);\n        mapView.setBuiltInZoomControls(false);\n        mapView.setZoomLevelMin((byte) 2);\n        mapView.setZoomLevelMax((byte) 10);\n\n        mapView.setZoomLevel((byte) 2);\n        mapView.getModel().displayModel.setBackgroundColor(ContextCompat.getColor(this, R.color.mapBackground));\n\n        layers = mapView.getLayerManager().getLayers();\n\n        MapCreator mapCreator = new MapCreator(this, layers);\n        mapCreator.parseGeoJson(\"world_map.geo.json\");\n\n        initServerOnMap(layers);\n\n        LinearLayout map = (LinearLayout) findViewById(R.id.map);\n        map.addView(mapView);\n    }\n\n\n    @Override\n    protected boolean useHomeButton() {\n        return false;\n    }\n\n    public void homeOnClick(View view) {\n        switch (view.getId()) {\n            case R.id.homeBtnChooseCountry:\n                sendTouchButton(\"homeBtnChooseCountry\");\n                chooseCountry();\n                break;\n            case R.id.homeBtnRandomConnection:\n                sendTouchButton(\"homeBtnRandomConnection\");\n                Server randomServer = getRandomServer();\n                if (randomServer != null) {\n                    newConnecting(randomServer, true, true);\n                } else {\n                    String randomError = String.format(getResources().getString(R.string.error_random_country), PropertiesService.getSelectedCountry());\n                    Toast.makeText(this, randomError, Toast.LENGTH_LONG).show();\n                }\n                break;\n        }\n\n    }\n\n    private void chooseCountry() {\n        View view = initPopUp(R.layout.pop_up_choose_country, 0.6f, 0.8f, 0.8f, 0.7f);\n\n        final List<String> countryListName = new ArrayList<String>();\n        for (Server server : countryList) {\n            String localeCountryName = localeCountries.get(server.getCountryShort()) != null ?\n                    localeCountries.get(server.getCountryShort()) : server.getCountryLong();\n            countryListName.add(localeCountryName);\n        }\n\n        ListView lvCountry = (ListView) view.findViewById(R.id.homeCountryList);\n        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,\n                android.R.layout.simple_list_item_1, countryListName);\n\n        lvCountry.setAdapter(adapter);\n        lvCountry.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n            @Override\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                popupWindow.dismiss();\n                onSelectCountry(countryList.get(position));\n            }\n        });\n\n        popupWindow.showAtLocation(homeContextRL, Gravity.CENTER,0, 0);\n    }\n\n    private void showNote() {\n        View view = initPopUp(R.layout.pop_up_note, 0.6f, 0.5f, 0.9f, 0.4f);\n        ((TextView) view.findViewById(R.id.noteLink)).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                Intent in=new Intent(Intent.ACTION_VIEW, Uri.parse(\"http://www.vpngate.net/en/join.aspx\"));\n                startActivity(in);\n            }\n        });\n\n        popupWindow.showAtLocation(homeContextRL, Gravity.CENTER,0, 0);\n\n        PropertiesService.setShowNote(false);\n    }\n\n    private View initPopUp(int resourse,\n                            float landPercentW,\n                            float landPercentH,\n                            float portraitPercentW,\n                            float portraitPercentH) {\n\n        LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);\n        View view = inflater.inflate(resourse, null);\n\n        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {\n            popupWindow = new PopupWindow(\n                    view,\n                    (int)(widthWindow * landPercentW),\n                    (int)(heightWindow * landPercentH)\n            );\n        } else {\n            popupWindow = new PopupWindow(\n                    view,\n                    (int)(widthWindow * portraitPercentW),\n                    (int)(heightWindow * portraitPercentH)\n            );\n        }\n\n\n        popupWindow.setOutsideTouchable(false);\n        popupWindow.setFocusable(true);\n        popupWindow.setBackgroundDrawable(new BitmapDrawable());\n\n        return view;\n    }\n\n    private void onSelectCountry(Server server) {\n        Intent intent = new Intent(getApplicationContext(), ServersListActivity.class);\n        intent.putExtra(EXTRA_COUNTRY, server.getCountryShort());\n        startActivity(intent);\n    }\n\n    private void initDetailsServerOnMap() {\n        if (markerList != null && markerList.size() > 0) {\n            for (Marker marker : markerList) {\n                layers.remove(marker);\n            }\n        }\n        List<Server> serverList = dbHelper.getServersWithGPS();\n\n        markerList = new ArrayList<Marker>();\n        for (Server server : serverList) {\n            LatLong position = new LatLong(server.getLat(), server.getLon());\n            Bitmap bitmap = AndroidGraphicFactory.convertToBitmap(ContextCompat.getDrawable(this,\n                    getResources().getIdentifier(ConnectionQuality.getSimplePointIcon(server.getQuality()),\n                            \"drawable\",\n                            getPackageName())));\n            Marker serverMarker = new Marker(position, bitmap, 0, 0);\n            markerList.add(serverMarker);\n            layers.add(serverMarker);\n        }\n    }\n\n    private void initServerOnMap(Layers layers) {\n        Type listType = new TypeToken<ArrayList<Country>>(){}.getType();\n        countryLatLonList =  new Gson().fromJson(LoadData.fromFile(COUNTRY_FILE_NAME, this), listType);\n\n        for (Server server : countryList) {\n            for (Country country : countryLatLonList) {\n                if (server.getCountryShort().equals(country.getCountryCode())) {\n                    LatLong position = new LatLong(country.getCapitalLatitude(), country.getCapitalLongitude());\n                    Bitmap bitmap = AndroidGraphicFactory.convertToBitmap(ContextCompat.getDrawable(this,\n                            getResources().getIdentifier(ConnectionQuality.getPointIcon(server.getQuality()),\n                                    \"drawable\",\n                                    getPackageName())));\n\n                    MyMarker countryMarker = new MyMarker(position, bitmap, 0, 0, server) {\n                        @Override\n                        public boolean onTap(LatLong geoPoint, Point viewPosition,\n                                             Point tapPoint) {\n\n                            if (contains(viewPosition, tapPoint)) {\n                                onSelectCountry((Server)getRelationObject());\n                                return true;\n                            }\n                            return false;\n                        }\n                    };\n\n                    layers.add(countryMarker);\n\n\n                    String localeCountryName = localeCountries.get(country.getCountryCode()) != null ?\n                            localeCountries.get(country.getCountryCode()) : country.getCountryName();\n\n                    Drawable drawable = new BitmapDrawable(getResources(), BitmapGenerator.getTextAsBitmap(localeCountryName, 20, ContextCompat.getColor(this,R.color.mapNameCountry)));\n                    Bitmap bitmapName = AndroidGraphicFactory.convertToBitmap(drawable);\n\n                    Marker countryNameMarker = new Marker(position, bitmapName, 0, bitmap.getHeight() / 2);\n\n                    layers.add(countryNameMarker);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/LauncherActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.app.Activity;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v7.app.AlertDialog;\n\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.util.NetworkState;\n\npublic class LauncherActivity extends Activity {\n    private static boolean loadStatus = false;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        if (NetworkState.isOnline()) {\n            if (loadStatus) {\n                Intent myIntent = new Intent(this, HomeActivity.class);\n                startActivity(myIntent);\n                finish();\n            } else {\n                loadStatus = true;\n                Intent myIntent = new Intent(this, LoaderActivity.class);\n                startActivity(myIntent);\n                finish();\n            }\n        } else {\n            AlertDialog.Builder builder = new AlertDialog.Builder(this);\n            builder.setTitle(getString(R.string.network_error))\n                    .setMessage(getString(R.string.network_error_message))\n                    .setNegativeButton(getString(R.string.ok),\n                            new DialogInterface.OnClickListener() {\n                                public void onClick(DialogInterface dialog, int id) {\n                                    dialog.cancel();\n                                    onBackPressed();\n                                }\n                            });\n            AlertDialog alert = builder.create();\n            alert.show();\n        }\n\n\n\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/LoaderActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.content.Intent;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.os.Bundle;\n\nimport android.view.View;\nimport android.widget.TextView;\n\nimport com.androidnetworking.AndroidNetworking;\nimport com.androidnetworking.common.Priority;\nimport com.androidnetworking.error.ANError;\nimport com.androidnetworking.interfaces.DownloadListener;\nimport com.androidnetworking.interfaces.DownloadProgressListener;\nimport com.crashlytics.android.answers.Answers;\nimport com.crashlytics.android.answers.CustomEvent;\nimport com.daimajia.numberprogressbar.NumberProgressBar;\n\nimport com.vasilkoff.easyvpnfree.BuildConfig;\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.PropertiesService;\nimport com.vasilkoff.easyvpnfree.util.Stopwatch;\n\nimport java.io.BufferedReader;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\n\nimport okhttp3.OkHttpClient;\n\npublic class LoaderActivity extends BaseActivity {\n\n    private NumberProgressBar progressBar;\n    private TextView commentsText;\n\n    private Handler updateHandler;\n\n    private final int LOAD_ERROR = 0;\n    private final int DOWNLOAD_PROGRESS = 1;\n    private final int PARSE_PROGRESS = 2;\n    private final int LOADING_SUCCESS = 3;\n    private final int SWITCH_TO_RESULT = 4;\n    private final String BASE_URL = \"http://www.vpngate.net/api/iphone/\";\n    private final String BASE_FILE_NAME = \"vpngate.csv\";\n\n    private boolean premiumStage = true;\n\n    private final String PREMIUM_URL = \"http://easyvpn.vasilkoff.com/?type=csv\";\n    private final String PREMIUM_FILE_NAME = \"premiumServers.csv\";\n\n    private int percentDownload = 0;\n    private Stopwatch stopwatch;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_loader);\n\n        progressBar = (NumberProgressBar)findViewById(R.id.number_progress_bar);\n        commentsText = (TextView)findViewById(R.id.commentsText);\n\n        if (getIntent().getBooleanExtra(\"firstPremiumLoad\", false))\n            ((TextView)findViewById(R.id.loaderPremiumText)).setVisibility(View.VISIBLE);\n\n        progressBar.setMax(100);\n\n        updateHandler = new Handler(new Handler.Callback() {\n            @Override\n            public boolean handleMessage(Message msg) {\n                switch (msg.arg1) {\n                    case LOAD_ERROR: {\n                        commentsText.setText(msg.arg2);\n                        progressBar.setProgress(100);\n                    } break;\n                    case DOWNLOAD_PROGRESS: {\n                        commentsText.setText(R.string.downloading_csv_text);\n                        progressBar.setProgress(msg.arg2);\n\n                    } break;\n                    case PARSE_PROGRESS: {\n                        commentsText.setText(R.string.parsing_csv_text);\n                        progressBar.setProgress(msg.arg2);\n                    } break;\n                    case LOADING_SUCCESS: {\n                        commentsText.setText(R.string.successfully_loaded);\n                        progressBar.setProgress(100);\n                        Message end = new Message();\n                        end.arg1 = SWITCH_TO_RESULT;\n                        updateHandler.sendMessageDelayed(end,500);\n                    } break;\n                    case SWITCH_TO_RESULT: {\n                        if (!BuildConfig.DEBUG)\n                            Answers.getInstance().logCustom(new CustomEvent(\"Time servers loading\")\n                                .putCustomAttribute(\"Time servers loading\", stopwatch.getElapsedTime()));\n\n                        if (PropertiesService.getConnectOnStart()) {\n                            Server randomServer = getRandomServer();\n                            if (randomServer != null) {\n                                newConnecting(randomServer, true, true);\n                            } else {\n                                startActivity(new Intent(LoaderActivity.this, HomeActivity.class));\n                            }\n                        } else {\n                            startActivity(new Intent(LoaderActivity.this, HomeActivity.class));\n                        }\n                    }\n                }\n                return true;\n            }\n        });\n        progressBar.setProgress(0);\n\n\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        downloadCSVFile(BASE_URL, BASE_FILE_NAME);\n    }\n\n    @Override\n    protected boolean useHomeButton() {\n        return false;\n    }\n\n    @Override\n    protected boolean useMenu() {\n        return false;\n    }\n\n    private void downloadCSVFile(String url, String fileName) {\n        stopwatch = new Stopwatch();\n\n        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()\n                .connectTimeout(60, TimeUnit.SECONDS)\n                .readTimeout(60, TimeUnit.SECONDS)\n                .writeTimeout(60, TimeUnit.SECONDS)\n                .build();\n\n        AndroidNetworking.download(url, getCacheDir().getPath(), fileName)\n                .setTag(\"downloadCSV\")\n                .setPriority(Priority.MEDIUM)\n                .setOkHttpClient(okHttpClient)\n                .build()\n                .setDownloadProgressListener(new DownloadProgressListener() {\n                    @Override\n                    public void onProgress(long bytesDownloaded, long totalBytes) {\n                        if(totalBytes <= 0) {\n                            // when we dont know the file size, assume it is 1200000 bytes :)\n                            totalBytes = 1200000;\n                        }\n\n                        if (!premiumServers || !premiumStage) {\n                            if (percentDownload <= 90)\n                            percentDownload = percentDownload + (int)((100 * bytesDownloaded) / totalBytes);\n                        } else {\n                            percentDownload = (int)((100 * bytesDownloaded) / totalBytes);\n                        }\n\n                        Message msg = new Message();\n                        msg.arg1 = DOWNLOAD_PROGRESS;\n                        msg.arg2 = percentDownload;\n                        updateHandler.sendMessage(msg);\n                    }\n                })\n                .startDownload(new DownloadListener() {\n                    @Override\n                    public void onDownloadComplete() {\n                        if (premiumServers && premiumStage) {\n                            premiumStage = false;\n                            downloadCSVFile(PREMIUM_URL, PREMIUM_FILE_NAME);\n                        } else {\n                            parseCSVFile(BASE_FILE_NAME);\n                        }\n                    }\n                    @Override\n                    public void onError(ANError error) {\n                        Message msg = new Message();\n                        msg.arg1 = LOAD_ERROR;\n                        msg.arg2 = R.string.network_error;\n                        updateHandler.sendMessage(msg);\n                    }\n                });\n    }\n\n    private void parseCSVFile(String fileName) {\n        BufferedReader reader = null;\n        try {\n            reader = new BufferedReader(new FileReader(getCacheDir().getPath().concat(\"/\").concat(fileName)));\n        } catch (IOException e) {\n            e.printStackTrace();\n            Message msg = new Message();\n            msg.arg1 = LOAD_ERROR;\n            msg.arg2 = R.string.csv_file_error;\n            updateHandler.sendMessage(msg);\n        }\n        if (reader != null) {\n            try {\n                int startLine = 2;\n                int type = 0;\n\n                if (premiumServers && premiumStage) {\n                    startLine = 0;\n                    type = 1;\n                } else {\n                    dbHelper.clearTable();\n                }\n\n                int counter = 0;\n                String line = null;\n                while ((line = reader.readLine()) != null) {\n                    if (counter >= startLine) {\n                        dbHelper.putLine(line, type);\n                    }\n                    counter++;\n                    if (!premiumServers || !premiumStage) {\n                        Message msg = new Message();\n                        msg.arg1 = PARSE_PROGRESS;\n                        msg.arg2 = counter;// we know that the server returns 100 records\n                        updateHandler.sendMessage(msg);\n                    }\n                }\n\n                if (premiumServers && !premiumStage) {\n                    premiumStage = true;\n                    parseCSVFile(PREMIUM_FILE_NAME);\n                } else {\n                    Message end = new Message();\n                    end.arg1 = LOADING_SUCCESS;\n                    updateHandler.sendMessageDelayed(end,200);\n                }\n\n            } catch (Exception e) {\n                e.printStackTrace();\n                Message msg = new Message();\n                msg.arg1 = LOAD_ERROR;\n                msg.arg2 = R.string.csv_file_error_parsing;\n                updateHandler.sendMessage(msg);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/MyPreferencesActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.os.Bundle;\nimport android.preference.ListPreference;\nimport android.preference.PreferenceActivity;\nimport android.preference.PreferenceCategory;\nimport android.preference.PreferenceFragment;\nimport android.support.v7.widget.Toolbar;\nimport android.view.View;\n\nimport com.google.android.gms.analytics.HitBuilders;\nimport com.google.android.gms.analytics.Tracker;\nimport com.vasilkoff.easyvpnfree.App;\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.database.DBHelper;\nimport com.vasilkoff.easyvpnfree.model.Country;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.CountriesNames;\nimport com.vasilkoff.easyvpnfree.util.PropertiesService;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.vasilkoff.easyvpnfree.R.id.toolbar;\n\n/**\n * Created by Kusenko on 13.12.2016.\n */\n\npublic class MyPreferencesActivity extends PreferenceActivity {\n    private Toolbar toolbar;\n    Tracker mTracker;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_preference);\n        toolbar = (Toolbar) findViewById(R.id.preferenceToolbar);\n        toolbar.setTitle(R.string.app_name);\n        toolbar.setNavigationOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                finish();\n            }\n        });\n        getFragmentManager().beginTransaction().replace(R.id.preferenceContent, new MyPreferenceFragment()).commit();\n        App application = (App) getApplication();\n        mTracker = application.getDefaultTracker();\n    }\n\n    public static class MyPreferenceFragment extends PreferenceFragment\n    {\n        @Override\n        public void onCreate(final Bundle savedInstanceState)\n        {\n            super.onCreate(savedInstanceState);\n            addPreferencesFromResource(R.xml.preferences);\n\n            DBHelper dbHelper = new DBHelper(getActivity().getApplicationContext());\n            List<Server> countryList = dbHelper.getUniqueCountries();\n            CharSequence entriesValues[] = new CharSequence[countryList.size()];\n            CharSequence entries[] = new CharSequence[countryList.size()];\n\n            for (int i = 0; i < countryList.size(); i++) {\n                entriesValues[i] = countryList.get(i).getCountryLong();\n                String localeCountryName = CountriesNames.getCountries().get(countryList.get(i).getCountryShort()) != null ?\n                        CountriesNames.getCountries().get(countryList.get(i).getCountryShort()) :\n                        countryList.get(i).getCountryLong();\n                entries[i] = localeCountryName;\n            }\n\n            ListPreference listPreference = (ListPreference) findPreference(\"selectedCountry\");\n            if (entries.length == 0) {\n                PreferenceCategory countryPriorityCategory = (PreferenceCategory) findPreference(\"countryPriorityCategory\");\n                getPreferenceScreen().removePreference(countryPriorityCategory);\n            } else {\n                listPreference.setEntries(entries);\n                listPreference.setEntryValues(entriesValues);\n                if (PropertiesService.getSelectedCountry() == null)\n                    listPreference.setValueIndex(0);\n            }\n        }\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        mTracker.setScreenName(\"Preference\");\n        mTracker.send(new HitBuilders.ScreenViewBuilder().build());\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/ServerActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.app.Activity;\nimport android.content.ActivityNotFoundException;\nimport android.content.BroadcastReceiver;\nimport android.content.ComponentName;\nimport android.content.Context;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.content.ServiceConnection;\nimport android.graphics.drawable.BitmapDrawable;\nimport android.net.Uri;\nimport android.net.VpnService;\nimport android.os.AsyncTask;\nimport android.os.IBinder;\nimport android.support.v4.content.ContextCompat;\nimport android.view.ViewGroup.LayoutParams;\n\nimport android.os.Bundle;\n\n\nimport android.support.v7.app.AlertDialog;\nimport android.util.Base64;\nimport android.util.Log;\n\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.animation.AnimationUtils;\nimport android.widget.Button;\nimport android.widget.CheckBox;\nimport android.widget.CompoundButton;\nimport android.widget.ImageButton;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.PopupWindow;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\n\nimport com.crashlytics.android.answers.Answers;\nimport com.crashlytics.android.answers.CustomEvent;\nimport com.vasilkoff.easyvpnfree.BuildConfig;\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.ConnectionQuality;\nimport com.vasilkoff.easyvpnfree.util.PropertiesService;\nimport com.vasilkoff.easyvpnfree.util.Stopwatch;\nimport com.vasilkoff.easyvpnfree.util.TotalTraffic;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.math.BigDecimal;\nimport java.math.RoundingMode;\nimport java.util.concurrent.TimeUnit;\n\nimport de.blinkt.openvpn.VpnProfile;\nimport de.blinkt.openvpn.core.ConfigParser;\nimport de.blinkt.openvpn.core.OpenVPNService;\nimport de.blinkt.openvpn.core.ProfileManager;\nimport de.blinkt.openvpn.core.VPNLaunchHelper;\nimport de.blinkt.openvpn.core.VpnStatus;\n\npublic class ServerActivity extends BaseActivity {\n\n    private static final int START_VPN_PROFILE = 70;\n    private BroadcastReceiver br;\n    private BroadcastReceiver trafficReceiver;\n    public final static String BROADCAST_ACTION = \"de.blinkt.openvpn.VPN_STATUS\";\n\n    private static OpenVPNService mVPNService;\n    private VpnProfile vpnProfile;\n\n    private Server currentServer = null;\n    private Button unblockCheck;\n    private CheckBox adbBlockCheck;\n    private Button serverConnect;\n    private TextView lastLog;\n    private ProgressBar connectingProgress;\n    private PopupWindow popupWindow;\n    private LinearLayout parentLayout;\n    private TextView trafficInTotally;\n    private TextView trafficOutTotally;\n    private TextView trafficIn;\n    private TextView trafficOut;\n    private ImageButton bookmark;\n\n    private static boolean filterAds = false;\n    private static boolean defaultFilterAds = true;\n\n    private boolean autoConnection;\n    private boolean fastConnection;\n    private Server autoServer;\n\n    private boolean statusConnection = false;\n    private boolean firstData = true;\n\n    private WaitConnectionAsync waitConnection;\n    private boolean inBackground;\n    private static Stopwatch stopwatch;\n    private boolean isBindedService = false;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_server);\n\n        bookmark = (ImageButton) findViewById(R.id.serverBookmark);\n        parentLayout = (LinearLayout) findViewById(R.id.serverParentLayout);\n        unblockCheck = (Button) findViewById(R.id.serverUnblockCheck);\n        adbBlockCheck = (CheckBox) findViewById(R.id.serverBlockingCheck);\n        connectingProgress = (ProgressBar) findViewById(R.id.serverConnectingProgress);\n        lastLog = (TextView) findViewById(R.id.serverStatus);\n        serverConnect = (Button) findViewById(R.id.serverConnect);\n\n        String totalIn = String.format(getResources().getString(R.string.traffic_in),\n                TotalTraffic.getTotalTraffic().get(0));\n        trafficInTotally = (TextView) findViewById(R.id.serverTrafficInTotally);\n        trafficInTotally.setText(totalIn);\n\n        String totalOut = String.format(getResources().getString(R.string.traffic_out),\n                TotalTraffic.getTotalTraffic().get(1));\n        trafficOutTotally = (TextView) findViewById(R.id.serverTrafficOutTotally);\n        trafficOutTotally.setText(totalOut);\n\n        trafficIn = (TextView) findViewById(R.id.serverTrafficIn);\n        trafficIn.setText(\"\");\n        trafficOut = (TextView) findViewById(R.id.serverTrafficOut);\n        trafficOut.setText(\"\");\n\n        br = new BroadcastReceiver() {\n            @Override\n            public void onReceive(Context context, Intent intent) {\n                receiveStatus(context, intent);\n            }\n        };\n\n        registerReceiver(br, new IntentFilter(BROADCAST_ACTION));\n\n        trafficReceiver = new BroadcastReceiver() {\n            @Override\n            public void onReceive(Context context, Intent intent) {\n                receiveTraffic(context, intent);\n            }\n        };\n\n        registerReceiver(trafficReceiver, new IntentFilter(TotalTraffic.TRAFFIC_ACTION));\n\n\n\n        unblockCheck.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                sendTouchButton(\"adsFiltering\");\n                launchPurchase(adblockSKU, ADBLOCK_REQUEST);\n            }\n        });\n\n        adbBlockCheck.setChecked(defaultFilterAds);\n        adbBlockCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {\n            @Override\n            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {\n                if (!checkStatus())\n                    defaultFilterAds = isChecked;\n            }\n        });\n\n        lastLog.setText(R.string.server_not_connected);\n\n        initView(getIntent());\n\n        checkAvailableFilter();\n    }\n\n    private void initView(Intent intent) {\n\n        autoConnection = intent.getBooleanExtra(\"autoConnection\", false);\n        fastConnection = intent.getBooleanExtra(\"fastConnection\", false);\n        currentServer = (Server)intent.getParcelableExtra(Server.class.getCanonicalName());\n\n        if (currentServer == null) {\n            if (connectedServer != null) {\n                currentServer = connectedServer;\n            } else {\n                onBackPressed();\n                return;\n            }\n        }\n\n        int bookmarkBg = dbHelper.checkBookmark(currentServer) ?\n                R.drawable.ic_bookmark_red :\n                R.drawable.ic_bookmark_grey;\n        bookmark.setBackground(ContextCompat.getDrawable(this, bookmarkBg));\n\n        String code = currentServer.getCountryShort().toLowerCase();\n        if (code.equals(\"do\"))\n            code = \"dom\";\n\n        ((ImageView) findViewById(R.id.serverFlag))\n                .setImageResource(\n                        getResources().getIdentifier(code,\n                                \"drawable\",\n                                getPackageName()));\n\n        String localeCountryName = localeCountries.get(currentServer.getCountryShort()) != null ?\n                localeCountries.get(currentServer.getCountryShort()) : currentServer.getCountryLong();\n        ((TextView) findViewById(R.id.serverCountry)).setText(localeCountryName);\n        ((TextView) findViewById(R.id.serverIP)).setText(currentServer.getIp());\n        ((TextView) findViewById(R.id.serverCity)).setText(currentServer.getCity());\n        ((TextView) findViewById(R.id.serverSessions)).setText(currentServer.getNumVpnSessions());\n        ((ImageView) findViewById(R.id.serverImageConnect))\n                .setImageResource(\n                        getResources().getIdentifier(ConnectionQuality.getConnectIcon(currentServer.getQuality()),\n                                \"drawable\",\n                                getPackageName()));\n\n        String ping = currentServer.getPing() + \" \" +  getString(R.string.ms);\n        ((TextView) findViewById(R.id.serverPing)).setText(ping);\n\n        double speedValue = (double) Integer.parseInt(currentServer.getSpeed()) / 1048576;\n        speedValue = new BigDecimal(speedValue).setScale(3, RoundingMode.UP).doubleValue();\n        String speed = String.valueOf(speedValue) + \" \" + getString(R.string.mbps);\n        ((TextView) findViewById(R.id.serverSpeed)).setText(speed);\n\n        if (checkStatus()) {\n            adbBlockCheck.setEnabled(false);\n            adbBlockCheck.setChecked(filterAds);\n            serverConnect.setText(getString(R.string.server_btn_disconnect));\n            ((TextView) findViewById(R.id.serverStatus)).setText(VpnStatus.getLastCleanLogMessage(getApplicationContext()));\n        } else {\n            serverConnect.setText(getString(R.string.server_btn_connect));\n        }\n    }\n\n    @Override\n    protected void onNewIntent(Intent intent) {\n        super.onNewIntent(intent);\n\n        initView(intent);\n    }\n\n    private void receiveTraffic(Context context, Intent intent) {\n        if (checkStatus()) {\n            String in = \"\";\n            String out = \"\";\n            if (firstData) {\n                firstData = false;\n            } else {\n                in = String.format(getResources().getString(R.string.traffic_in),\n                        intent.getStringExtra(TotalTraffic.DOWNLOAD_SESSION));\n                out = String.format(getResources().getString(R.string.traffic_out),\n                        intent.getStringExtra(TotalTraffic.UPLOAD_SESSION));\n            }\n\n            trafficIn.setText(in);\n            trafficOut.setText(out);\n\n            String inTotal = String.format(getResources().getString(R.string.traffic_in),\n                    intent.getStringExtra(TotalTraffic.DOWNLOAD_ALL));\n            trafficInTotally.setText(inTotal);\n\n            String outTotal = String.format(getResources().getString(R.string.traffic_out),\n                    intent.getStringExtra(TotalTraffic.UPLOAD_ALL));\n            trafficOutTotally.setText(outTotal);\n        }\n    }\n\n    private void receiveStatus(Context context, Intent intent) {\n        if (checkStatus()) {\n            changeServerStatus(VpnStatus.ConnectionStatus.valueOf(intent.getStringExtra(\"status\")));\n            lastLog.setText(VpnStatus.getLastCleanLogMessage(getApplicationContext()));\n        }\n\n        if (intent.getStringExtra(\"detailstatus\").equals(\"NOPROCESS\")) {\n            try {\n                TimeUnit.SECONDS.sleep(1);\n                if (!VpnStatus.isVPNActive())\n                    prepareStopVPN();\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    private void checkAvailableFilter() {\n        if (availableFilterAds) {\n            adbBlockCheck.setVisibility(View.VISIBLE);\n            unblockCheck.setVisibility(View.GONE);\n        } else {\n            adbBlockCheck.setVisibility(View.GONE);\n            unblockCheck.setVisibility(View.VISIBLE);\n        }\n\n    }\n\n    @Override\n    public void onBackPressed() {\n        super.onBackPressed();\n\n        if (waitConnection != null)\n            waitConnection.cancel(false);\n\n        if (isTaskRoot()) {\n            startActivity(new Intent(this, HomeActivity.class));\n            finish();\n        }\n    }\n\n    private boolean checkStatus() {\n        if (connectedServer != null && connectedServer.getHostName().equals(currentServer.getHostName())) {\n            return VpnStatus.isVPNActive();\n        }\n\n        return false;\n    }\n\n    private void changeServerStatus(VpnStatus.ConnectionStatus status) {\n        switch (status) {\n            case LEVEL_CONNECTED:\n                statusConnection = true;\n                connectingProgress.setVisibility(View.GONE);\n\n                if (!inBackground) {\n                    if (PropertiesService.getDownloaded() >= 104857600 && PropertiesService.getShowRating()\n                            && BuildConfig.FLAVOR != \"underground\") {\n                        PropertiesService.setShowRating(false);\n                        showRating();\n                    } else {\n                        chooseAction();\n                    }\n                }\n\n                serverConnect.setText(getString(R.string.server_btn_disconnect));\n                break;\n            case LEVEL_NOTCONNECTED:\n                serverConnect.setText(getString(R.string.server_btn_connect));\n                break;\n            default:\n                serverConnect.setText(getString(R.string.server_btn_disconnect));\n                statusConnection = false;\n                connectingProgress.setVisibility(View.VISIBLE);\n        }\n    }\n\n    private void prepareVpn() {\n        connectingProgress.setVisibility(View.VISIBLE);\n        if (loadVpnProfile()) {\n            waitConnection = new WaitConnectionAsync();\n            waitConnection.execute();\n            serverConnect.setText(getString(R.string.server_btn_disconnect));\n            startVpn();\n        } else {\n            connectingProgress.setVisibility(View.GONE);\n            Toast.makeText(this, getString(R.string.server_error_loading_profile), Toast.LENGTH_SHORT).show();\n        }\n    }\n\n    public void serverOnClick(View view) {\n        switch (view.getId()) {\n            case R.id.serverConnect:\n                sendTouchButton(\"serverConnect\");\n                if (checkStatus()) {\n                    stopVpn();\n                } else {\n                    prepareVpn();\n                }\n                break;\n            case R.id.serverBtnCheckIp:\n                sendTouchButton(\"serverBtnCheckIp\");\n                Intent browse = new Intent( Intent.ACTION_VIEW , Uri.parse(getString(R.string.url_check_ip)));\n                startActivity(browse);\n                break;\n            case R.id.serverBookmark:\n                sendTouchButton(\"serverBookmark\");\n\n                bookmark.startAnimation(AnimationUtils.loadAnimation(this, R.anim.scale));\n                if (dbHelper.checkBookmark(currentServer)) {\n                    dbHelper.delBookmark(currentServer);\n                    bookmark.setBackground(ContextCompat.getDrawable(this, R.drawable.ic_bookmark_grey));\n                } else {\n                    dbHelper.setBookmark(currentServer);\n                    bookmark.setBackground(ContextCompat.getDrawable(this, R.drawable.ic_bookmark_red));\n                }\n                break;\n        }\n\n    }\n\n    private boolean loadVpnProfile() {\n        byte[] data;\n        try {\n            data = Base64.decode(currentServer.getConfigData(), Base64.DEFAULT);\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n\n        ConfigParser cp = new ConfigParser();\n        InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(data));\n        try {\n            cp.parseConfig(isr);\n            vpnProfile = cp.convertProfile();\n            vpnProfile.mName = currentServer.getCountryLong();\n\n            filterAds = adbBlockCheck.isChecked();\n            if (filterAds) {\n                vpnProfile.mOverrideDNS = true;\n                vpnProfile.mDNS1 = \"198.101.242.72\";\n                vpnProfile.mDNS2 = \"23.253.163.53\";\n            }\n\n            ProfileManager.getInstance(this).addProfile(vpnProfile);\n        } catch (IOException | ConfigParser.ConfigParseError e) {\n            e.printStackTrace();\n            return false;\n        }\n\n        return true;\n    }\n\n    private void prepareStopVPN() {\n        if (!BuildConfig.DEBUG) {\n            try {\n                String download = trafficIn.getText().toString();\n                download = download.substring(download.lastIndexOf(\":\") + 2);\n\n                Answers.getInstance().logCustom(new CustomEvent(\"Connection info\")\n                        .putCustomAttribute(\"Country\", connectedServer.getCountryLong())\n                        .putCustomAttribute(\"Download\", download)\n                        .putCustomAttribute(\"Time\", stopwatch.getElapsedTime()));\n            } catch (Exception e) {\n\n            }\n        }\n\n        statusConnection = false;\n        if (waitConnection != null)\n            waitConnection.cancel(false);\n        connectingProgress.setVisibility(View.GONE);\n        adbBlockCheck.setEnabled(availableFilterAds);\n        lastLog.setText(R.string.server_not_connected);\n        serverConnect.setText(getString(R.string.server_btn_connect));\n        connectedServer = null;\n    }\n\n    private void stopVpn() {\n        //prepareStopVPN();\n        ProfileManager.setConntectedVpnProfileDisconnected(this);\n        if (mVPNService != null && mVPNService.getManagement() != null)\n            mVPNService.getManagement().stopVPN(false);\n\n    }\n\n    private void startVpn() {\n        stopwatch = new Stopwatch();\n        connectedServer = currentServer;\n        hideCurrentConnection = true;\n        adbBlockCheck.setEnabled(false);\n\n        Intent intent = VpnService.prepare(this);\n\n        if (intent != null) {\n            VpnStatus.updateStateString(\"USER_VPN_PERMISSION\", \"\", R.string.state_user_vpn_permission,\n                    VpnStatus.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT);\n            // Start the query\n            try {\n                startActivityForResult(intent, START_VPN_PROFILE);\n            } catch (ActivityNotFoundException ane) {\n                // Shame on you Sony! At least one user reported that\n                // an official Sony Xperia Arc S image triggers this exception\n                VpnStatus.logError(R.string.no_vpn_support_image);\n            }\n        } else {\n            onActivityResult(START_VPN_PROFILE, Activity.RESULT_OK, null);\n        }\n    }\n\n    @Override\n    protected void ipInfoResult() {\n        ((TextView) findViewById(R.id.serverCity)).setText(currentServer.getCity());\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        inBackground = false;\n\n        if (currentServer.getCity() == null)\n            getIpInfo(currentServer);\n\n        if (connectedServer != null && currentServer.getIp().equals(connectedServer.getIp())) {\n            hideCurrentConnection = true;\n            invalidateOptionsMenu();\n        }\n\n\n        Intent intent = new Intent(this, OpenVPNService.class);\n        intent.setAction(OpenVPNService.START_SERVICE);\n        isBindedService = bindService(intent, mConnection, Context.BIND_AUTO_CREATE);\n\n        if (checkStatus()) {\n            try {\n                TimeUnit.SECONDS.sleep(1);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n            if (!checkStatus()) {\n                connectedServer = null;\n                serverConnect.setText(getString(R.string.server_btn_connect));\n                lastLog.setText(R.string.server_not_connected);\n            }\n        } else {\n            serverConnect.setText(getString(R.string.server_btn_connect));\n            if (autoConnection) {\n                prepareVpn();\n            }\n        }\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        inBackground = true;\n\n        if (isBindedService) {\n            isBindedService = false;\n            unbindService(mConnection);\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        unregisterReceiver(br);\n        unregisterReceiver(trafficReceiver);\n        if ( popupWindow != null && popupWindow.isShowing() ){\n            popupWindow.dismiss();\n        }\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        super.onActivityResult(requestCode, resultCode, data);\n\n        if (resultCode == RESULT_OK) {\n            switch (requestCode) {\n                case START_VPN_PROFILE :\n                    VPNLaunchHelper.startOpenVpn(vpnProfile, getBaseContext());\n                    break;\n                case ADBLOCK_REQUEST:\n                    Log.d(IAP_TAG, \"onActivityResult(\" + requestCode + \",\" + resultCode + \",\" + data);\n\n                    if (iapHelper == null) return;\n\n                    if (iapHelper.handleActivityResult(requestCode, resultCode, data)) {\n                        Log.d(IAP_TAG, \"onActivityResult handled by IABUtil.\");\n                        checkAvailableFilter();\n                    }\n                    break;\n            }\n        }\n    }\n\n    private void chooseAction() {\n        LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);\n        View view = inflater.inflate(R.layout.pop_up_success_conected,null);\n\n        popupWindow = new PopupWindow(\n                view,\n                LayoutParams.WRAP_CONTENT,\n                LayoutParams.WRAP_CONTENT\n        );\n\n        popupWindow.setOutsideTouchable(false);\n        popupWindow.setFocusable(true);\n        popupWindow.setBackgroundDrawable(new BitmapDrawable());\n\n        Button marketButton = (Button)view.findViewById(R.id.successPopUpBtnPlayMarket);\n        marketButton.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                sendTouchButton(\"successPopUpBtnPlayMarket\");\n                final String appPackageName = getPackageName();\n                try {\n                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(\"market://details?id=\" + appPackageName)));\n                } catch (android.content.ActivityNotFoundException anfe) {\n                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(\"http://play.google.com/store/apps/details?id=\" + appPackageName)));\n                }\n            }\n        });\n        if (BuildConfig.FLAVOR == \"underground\")\n            marketButton.setVisibility(View.GONE);\n\n        ((Button)view.findViewById(R.id.successPopUpBtnBrowser)).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                sendTouchButton(\"successPopUpBtnBrowser\");\n                startActivity( new Intent( Intent.ACTION_VIEW, Uri.parse(\"http://google.com\")));\n            }\n        });\n        ((Button)view.findViewById(R.id.successPopUpBtnDesktop)).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                sendTouchButton(\"successPopUpBtnDesktop\");\n                Intent startMain = new Intent(Intent.ACTION_MAIN);\n                startMain.addCategory(Intent.CATEGORY_HOME);\n                startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n                startActivity(startMain);\n            }\n        });\n        ((Button)view.findViewById(R.id.successPopUpBtnClose)).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                sendTouchButton(\"successPopUpBtnClose\");\n                popupWindow.dismiss();\n            }\n        });\n\n\n        popupWindow.showAtLocation(parentLayout, Gravity.CENTER,0, 0);\n\n    }\n\n    private void showRating() {\n        LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);\n        View view = inflater.inflate(R.layout.pop_up_rating,null);\n\n        popupWindow = new PopupWindow(\n                view,\n                LayoutParams.WRAP_CONTENT,\n                LayoutParams.WRAP_CONTENT\n        );\n\n        popupWindow.setOutsideTouchable(false);\n        popupWindow.setFocusable(true);\n        popupWindow.setBackgroundDrawable(new BitmapDrawable());\n\n        ((Button)view.findViewById(R.id.ratingBtnSure)).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                popupWindow.dismiss();\n                final String appPackageName = getPackageName();\n                try {\n                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(\"market://details?id=\" + appPackageName)));\n                } catch (android.content.ActivityNotFoundException anfe) {\n                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(\"http://play.google.com/store/apps/details?id=\" + appPackageName)));\n                }\n            }\n        });\n        ((Button)view.findViewById(R.id.ratingBtnNot)).setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                popupWindow.dismiss();\n            }\n        });\n\n\n        popupWindow.showAtLocation(parentLayout, Gravity.CENTER,0, 0);\n\n    }\n\n    private ServiceConnection mConnection = new ServiceConnection() {\n\n        @Override\n        public void onServiceConnected(ComponentName className,\n                                       IBinder service) {\n            // We've bound to LocalService, cast the IBinder and get LocalService instance\n            OpenVPNService.LocalBinder binder = (OpenVPNService.LocalBinder) service;\n            mVPNService = binder.getService();\n        }\n\n        @Override\n        public void onServiceDisconnected(ComponentName arg0) {\n            mVPNService = null;\n        }\n\n    };\n\n    private class WaitConnectionAsync extends AsyncTask<Void, Void, Void>\n    {\n        @Override\n        protected Void doInBackground(Void... params) {\n            try {\n                TimeUnit.SECONDS.sleep(PropertiesService.getAutomaticSwitchingSeconds());\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n            return null;\n        }\n\n        @Override\n        protected void onPostExecute(Void aVoid) {\n            super.onPostExecute(aVoid);\n            if (!statusConnection) {\n                if (currentServer != null)\n                    dbHelper.setInactive(currentServer.getIp());\n\n                if (fastConnection) {\n                    stopVpn();\n                    newConnecting(getRandomServer(), true, true);\n                } else if (PropertiesService.getAutomaticSwitching()){\n                    if (!inBackground)\n                        showAlert();\n                }\n            }\n        }\n    }\n\n    private void showAlert() {\n        AlertDialog.Builder builder = new AlertDialog.Builder(this);\n        builder.setMessage(getString(R.string.try_another_server_text))\n                .setPositiveButton(getString(R.string.try_another_server_ok),\n                        new DialogInterface.OnClickListener() {\n                            public void onClick(DialogInterface dialog, int id) {\n                                dialog.cancel();\n                                stopVpn();\n                                autoServer = dbHelper.getSimilarServer(currentServer.getCountryLong(), currentServer.getIp());\n                                if (autoServer != null) {\n                                    newConnecting(autoServer, false, true);\n                                } else {\n                                    onBackPressed();\n                                }\n                            }\n                        })\n                .setNegativeButton(getString(R.string.try_another_server_no),\n                        new DialogInterface.OnClickListener() {\n                            public void onClick(DialogInterface dialog, int id) {\n                                if (!statusConnection) {\n                                    waitConnection = new WaitConnectionAsync();\n                                    waitConnection.execute();\n                                }\n                                dialog.cancel();\n                            }\n                        });\n        AlertDialog alert = builder.create();\n        alert.show();\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/ServersInfo.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.util.DisplayMetrics;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.database.DBHelper;\n\npublic class ServersInfo extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_servers_info);\n\n        DisplayMetrics dm = new DisplayMetrics();\n        getWindowManager().getDefaultDisplay().getMetrics(dm);\n\n        int widthWindow = dm.widthPixels;\n        int heightWindow = dm.heightPixels;\n\n        if (getResources().getConfiguration().orientation == 1) {\n            getWindow().setLayout((int)(widthWindow * 0.7), (int)(heightWindow * 0.3));\n        } else {\n            getWindow().setLayout((int)(widthWindow * 0.4), (int)(heightWindow * 0.5));\n        }\n\n        DBHelper dbHelper = new DBHelper(this);\n\n        String basicServers = String.format(getResources().getString(R.string.info_basic), dbHelper.getCountBasic());\n        ((TextView) findViewById(R.id.infoBasic)).setText(basicServers);\n\n        String additionalServers = String.format(getResources().getString(R.string.info_additional), dbHelper.getCountAdditional());\n        ((TextView) findViewById(R.id.infoAdditional)).setText(additionalServers);\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/activity/ServersListActivity.java",
    "content": "package com.vasilkoff.easyvpnfree.activity;\n\nimport android.content.Intent;\n\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.ListView;\n\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.adapter.ServerListAdapter;\nimport com.vasilkoff.easyvpnfree.model.Server;\n\nimport java.util.List;\n\nimport de.blinkt.openvpn.core.VpnStatus;\n\npublic class ServersListActivity extends BaseActivity {\n    private ListView listView;\n    private ServerListAdapter serverListAdapter;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_servers_list);\n\n        if (!VpnStatus.isVPNActive())\n            connectedServer = null;\n\n        listView = (ListView) findViewById(R.id.list);\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n\n        invalidateOptionsMenu();\n\n        buildList();\n    }\n\n    @Override\n    protected void ipInfoResult() {\n        serverListAdapter.notifyDataSetChanged();\n    }\n\n    private void buildList() {\n        String country = getIntent().getStringExtra(HomeActivity.EXTRA_COUNTRY);\n        final List<Server> serverList = dbHelper.getServersByCountryCode(country);\n        serverListAdapter = new ServerListAdapter(this, serverList);\n\n        listView.setAdapter(serverListAdapter);\n        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n            @Override\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                Server server = serverList.get(position);\n                BaseActivity.sendTouchButton(\"detailsServer\");\n                Intent intent = new Intent(ServersListActivity.this, ServerActivity.class);\n                intent.putExtra(Server.class.getCanonicalName(), server);\n                ServersListActivity.this.startActivity(intent);\n            }\n        });\n\n        getIpInfo(serverList);\n    }\n}"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/adapter/BookmarkServerListAdapter.java",
    "content": "package com.vasilkoff.easyvpnfree.adapter;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.support.v7.widget.RecyclerView;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Button;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.activity.ServerActivity;\nimport com.vasilkoff.easyvpnfree.database.DBHelper;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.ConnectionQuality;\nimport com.vasilkoff.easyvpnfree.util.CountriesNames;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by Kusenko on 22.01.2017.\n */\n\npublic class BookmarkServerListAdapter extends RecyclerView.Adapter<BookmarkServerListAdapter.BookmarkHolder>{\n\n    private List<Server> serverList = new ArrayList<Server>();\n    private Context context;\n    private Map<String, String> localeCountries;\n    private DBHelper dbHelper;\n\n    public BookmarkServerListAdapter(List<Server> serverList, Context context, DBHelper dbHelper) {\n        this.serverList = serverList;\n        this.context = context;\n        this.dbHelper = dbHelper;\n        localeCountries = CountriesNames.getCountries();\n    }\n\n    @Override\n    public BookmarkHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.bookmark_server_row, parent, false);\n\n        return new BookmarkHolder(v);\n    }\n\n    @Override\n    public void onBindViewHolder(BookmarkHolder holder, final int position) {\n        final Server server = serverList.get(position);\n\n        String code = server.getCountryShort().toLowerCase();\n        if (code.equals(\"do\"))\n            code = \"dom\";\n\n        holder.flag.setImageResource(\n                context.getResources().getIdentifier(code,\n                        \"drawable\",\n                        context.getPackageName()));\n        holder.quality.setImageResource(\n                context.getResources().getIdentifier(ConnectionQuality.getConnectIcon(server.getQuality()),\n                        \"drawable\",\n                        context.getPackageName()));\n        holder.host.setText(server.getHostName());\n        holder.ip.setText(server.getIp());\n        holder.city.setText(server.getCity());\n\n        String localeCountryName = localeCountries.get(server.getCountryShort()) != null ?\n                localeCountries.get(server.getCountryShort()) : server.getCountryLong();\n        holder.country.setText(localeCountryName);\n\n        holder.delete.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dbHelper.delBookmark(server);\n                serverList.remove(position);\n                notifyDataSetChanged();\n            }\n        });\n\n    }\n\n    @Override\n    public int getItemCount() {\n        return serverList.size();\n    }\n\n    class BookmarkHolder extends RecyclerView.ViewHolder {\n        ImageView flag;\n        ImageView quality;\n        TextView host;\n        TextView ip;\n        TextView city;\n        TextView country;\n        Button delete;\n\n        public BookmarkHolder(View v) {\n            super(v);\n            flag = (ImageView) v.findViewById(R.id.bookmarkFlag);\n            quality = (ImageView) v.findViewById(R.id.bookmarkConnect);\n            host = (TextView) v.findViewById(R.id.bookmarkHostName);\n            ip = (TextView) v.findViewById(R.id.bookmarkIP);\n            city = (TextView) v.findViewById(R.id.bookmarkCity);\n            country = (TextView) v.findViewById(R.id.bookmarkCountry);\n            delete = (Button) v.findViewById(R.id.bookmarkDelete);\n\n            v.setOnClickListener(new View.OnClickListener() {\n                @Override\n                public void onClick(View v) {\n                    Intent intent = new Intent(context, ServerActivity.class);\n                    intent.putExtra(Server.class.getCanonicalName(), serverList.get(getAdapterPosition()));\n                    context.startActivity(intent);\n                }\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/adapter/ServerListAdapter.java",
    "content": "package com.vasilkoff.easyvpnfree.adapter;\n\nimport android.content.Context;\nimport android.support.v4.content.ContextCompat;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.activity.BaseActivity;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.ConnectionQuality;\nimport com.vasilkoff.easyvpnfree.util.CountriesNames;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by Vasilkoff on 27/09/16.\n */\npublic class ServerListAdapter extends BaseAdapter {\n\n    private LayoutInflater inflater;\n    private List<Server> serverList = new ArrayList<Server>();\n    private Context context;\n    private Map<String, String> localeCountries;\n\n    public ServerListAdapter(Context c, List<Server> serverList) {\n        inflater = LayoutInflater.from(c);\n        context = c;\n        this.serverList =  serverList;\n        localeCountries = CountriesNames.getCountries();\n    }\n\n\n    @Override\n    public int getCount() {\n        return serverList.size();\n    }\n\n\n    @Override\n    public Server getItem(int position) {\n        return serverList.get(position);\n    }\n\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n\n    @Override\n    public View getView(int position, View v, ViewGroup parent) {\n\n        v = inflater.inflate(R.layout.layout_server_record_row, parent, false);\n\n        final Server server = getItem(position);\n\n        String code = server.getCountryShort().toLowerCase();\n        if (code.equals(\"do\"))\n            code = \"dom\";\n\n\n        ((ImageView) v.findViewById(R.id.imageFlag))\n                .setImageResource(\n                        context.getResources().getIdentifier(code,\n                                \"drawable\",\n                                context.getPackageName()));\n        ((ImageView) v.findViewById(R.id.imageConnect))\n                .setImageResource(\n                        context.getResources().getIdentifier(ConnectionQuality.getConnectIcon(server.getQuality()),\n                                \"drawable\",\n                                context.getPackageName()));\n\n        ((TextView) v.findViewById(R.id.textHostName)).setText(server.getHostName());\n        ((TextView) v.findViewById(R.id.textIP)).setText(server.getIp());\n        ((TextView) v.findViewById(R.id.textCity)).setText(server.getCity());\n\n        String localeCountryName = localeCountries.get(server.getCountryShort()) != null ?\n                localeCountries.get(server.getCountryShort()) : server.getCountryLong();\n        ((TextView) v.findViewById(R.id.textCountry)).setText(localeCountryName);\n\n        if (BaseActivity.connectedServer != null && BaseActivity.connectedServer.getHostName().equals(server.getHostName())) {\n            v.setBackgroundColor(ContextCompat.getColor(context, R.color.activeServer));\n        }\n\n        if (server.getType() == 1) {\n            v.setBackgroundColor(ContextCompat.getColor(context, R.color.additionalServer));\n        }\n\n        return v;\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/database/DBHelper.java",
    "content": "package com.vasilkoff.easyvpnfree.database;\n\nimport android.content.ContentValues;\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.database.sqlite.SQLiteDatabase;\nimport android.database.sqlite.SQLiteOpenHelper;\nimport android.database.sqlite.SQLiteStatement;\nimport android.util.Log;\n\nimport com.vasilkoff.easyvpnfree.model.Country;\nimport com.vasilkoff.easyvpnfree.model.Server;\nimport com.vasilkoff.easyvpnfree.util.ConnectionQuality;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Random;\n\n/**\n * Created by Kusenko on 29.09.2016.\n */\n\npublic class DBHelper  extends SQLiteOpenHelper {\n\n    private static final int DATABASE_VERSION = 6;\n    private static final String DATABASE_NAME = \"Records.db\";\n    private static final String TABLE_SERVERS = \"servers\";\n    private static final String TABLE_BOOKMARK_SERVERS = \"bookmark_servers\";\n    private static final String TAG = \"DBHelper\";\n\n    private static final String KEY_ID = \"_id\";\n    private static final String KEY_HOST_NAME = \"hostName\";\n    private static final String KEY_IP = \"ip\";\n    private static final String KEY_SCORE = \"score\";\n    private static final String KEY_PING = \"ping\";\n    private static final String KEY_SPEED = \"speed\";\n    private static final String KEY_COUNTRY_LONG = \"countryLong\";\n    private static final String KEY_COUNTRY_SHORT = \"countryShort\";\n    private static final String KEY_NUM_VPN_SESSIONS = \"numVpnSessions\";\n    private static final String KEY_UPTIME = \"uptime\";\n    private static final String KEY_TOTAL_USERS = \"totalUsers\";\n    private static final String KEY_TOTAL_TRAFFIC = \"totalTraffic\";\n    private static final String KEY_LOG_TYPE = \"logType\";\n    private static final String KEY_OPERATOR = \"operator\";\n    private static final String KEY_MESSAGE = \"message\";\n    private static final String KEY_CONFIG_DATA = \"configData\";\n    private static final String KEY_TYPE = \"type\";\n    private static final String KEY_QUALITY = \"quality\";\n    private static final String KEY_CITY = \"city\";\n    private static final String KEY_REGION_NAME = \"regionName\";\n    private static final String KEY_LAT = \"lat\";\n    private static final String KEY_LON = \"lon\";\n\n\n    public DBHelper(Context context) {\n        super(context, DATABASE_NAME, null, DATABASE_VERSION);\n    }\n\n    @Override\n    public void onCreate(SQLiteDatabase db) {\n        createTable(db, TABLE_SERVERS);\n        createTable(db, TABLE_BOOKMARK_SERVERS);\n    }\n\n    @Override\n    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {\n        db.execSQL(\"drop table if exists \" + TABLE_SERVERS);\n        db.execSQL(\"drop table if exists \" + TABLE_BOOKMARK_SERVERS);\n        onCreate(db);\n    }\n\n    private void createTable(SQLiteDatabase db, String name) {\n        db.execSQL(\"create table \" + name + \"(\"\n                + KEY_ID + \" integer primary key,\"\n                + KEY_HOST_NAME + \" text,\"\n                + KEY_IP + \" text,\"\n                + KEY_SCORE + \" text,\"\n                + KEY_PING + \" text,\"\n                + KEY_SPEED + \" text,\"\n                + KEY_COUNTRY_LONG + \" text,\"\n                + KEY_COUNTRY_SHORT + \" text,\"\n                + KEY_NUM_VPN_SESSIONS + \" text,\"\n                + KEY_UPTIME + \" text,\"\n                + KEY_TOTAL_USERS + \" text,\"\n                + KEY_TOTAL_TRAFFIC + \" text,\"\n                + KEY_LOG_TYPE + \" text,\"\n                + KEY_OPERATOR + \" text,\"\n                + KEY_MESSAGE + \" text,\"\n                + KEY_CONFIG_DATA + \" text,\"\n                + KEY_QUALITY + \" integer,\"\n                + KEY_CITY + \" text,\"\n                + KEY_TYPE + \" integer,\"\n                + KEY_REGION_NAME + \" text,\"\n                + KEY_LAT + \" real,\"\n                + KEY_LON + \" real,\"\n                + \"UNIQUE (\"\n                + KEY_HOST_NAME\n                + \") ON CONFLICT IGNORE\"\n                + \")\");\n    }\n\n    public void setInactive(String ip) {\n        SQLiteDatabase db = this.getWritableDatabase();\n        ContentValues values = new ContentValues();\n        values.put(KEY_QUALITY, 0);\n        db.update(TABLE_SERVERS, values, KEY_IP + \" = ?\", new String[] {ip});\n\n        db.close();\n    }\n\n    public boolean setIpInfo(JSONArray response, List<Server> serverList) {\n        boolean result = false;\n        SQLiteDatabase db = this.getWritableDatabase();\n        for (int i = 0; i < response.length(); i++) {\n            try {\n                JSONObject ipInfo = new JSONObject(response.get(i).toString());\n                String city = ipInfo.get(KEY_CITY).toString();\n\n                ContentValues values = new ContentValues();\n                values.put(KEY_CITY, city);\n                values.put(KEY_REGION_NAME, ipInfo.get(KEY_REGION_NAME).toString());\n                values.put(KEY_LAT, ipInfo.getDouble(KEY_LAT));\n                values.put(KEY_LON, ipInfo.getDouble(KEY_LON));\n\n                db.update(TABLE_SERVERS, values, KEY_IP + \" = ?\", new String[] {ipInfo.get(\"query\").toString()});\n\n                serverList.get(i).setCity(city);\n                result = true;\n            } catch (JSONException e) {\n                result = false;\n                e.printStackTrace();\n            }\n        }\n        db.close();\n\n        return result;\n    }\n\n    public void clearTable() {\n        SQLiteDatabase db = this.getWritableDatabase();\n        db.delete(TABLE_SERVERS, null, null);\n        db.close();\n    }\n\n    public void setBookmark(Server server) {\n        SQLiteDatabase db = this.getWritableDatabase();\n        ContentValues contentValues = new ContentValues();\n\n        contentValues.put(KEY_HOST_NAME, server.getHostName());\n        contentValues.put(KEY_IP, server.getIp());\n        contentValues.put(KEY_SCORE, server.getScore());\n        contentValues.put(KEY_PING, server.getPing());\n        contentValues.put(KEY_SPEED, server.getSpeed());\n        contentValues.put(KEY_COUNTRY_LONG, server.getCountryLong());\n        contentValues.put(KEY_COUNTRY_SHORT, server.getCountryShort());\n        contentValues.put(KEY_NUM_VPN_SESSIONS, server.getNumVpnSessions());\n        contentValues.put(KEY_UPTIME, server.getUptime());\n        contentValues.put(KEY_TOTAL_USERS, server.getTotalUsers());\n        contentValues.put(KEY_TOTAL_TRAFFIC, server.getTotalTraffic());\n        contentValues.put(KEY_LOG_TYPE, server.getLogType());\n        contentValues.put(KEY_OPERATOR, server.getOperator());\n        contentValues.put(KEY_MESSAGE, server.getMessage());\n        contentValues.put(KEY_CONFIG_DATA, server.getConfigData());\n        contentValues.put(KEY_TYPE, server.getType());\n        contentValues.put(KEY_QUALITY, server.getQuality());\n        contentValues.put(KEY_CITY, server.getCity());\n\n        db.insert(TABLE_BOOKMARK_SERVERS, null, contentValues);\n        db.close();\n    }\n\n    public void delBookmark(Server server) {\n        SQLiteDatabase db = this.getWritableDatabase();\n        db.delete(TABLE_BOOKMARK_SERVERS, KEY_IP + \" = ?\", new String[] {server.getIp()});\n        db.close();\n    }\n\n    public List<Server> getBookmarks() {\n        List<Server> serverList = new ArrayList<Server>();\n        SQLiteDatabase db = this.getWritableDatabase();\n        Cursor cursor = db.query(TABLE_BOOKMARK_SERVERS, null, null, null, null, null, null);\n\n        if (cursor.moveToFirst()) {\n            do {\n                serverList.add(parseServer(cursor));\n            } while (cursor.moveToNext());\n        } else {\n            Log.d(TAG ,\"0 rows\");\n        }\n\n        cursor.close();\n        db.close();\n\n        return serverList;\n    }\n\n    public boolean checkBookmark(Server server) {\n        boolean result = false;\n        SQLiteDatabase db = this.getWritableDatabase();\n        Cursor cursor = db.query(TABLE_BOOKMARK_SERVERS,\n                null,\n                KEY_IP + \"=?\",\n                new String[]{server.getIp()},\n                null,\n                null,\n                null);\n\n        if (cursor.moveToFirst()) {\n            result = true;\n        } else {\n            Log.d(TAG ,\"0 rows\");\n        }\n\n        cursor.close();\n        db.close();\n\n        return result;\n    }\n\n    public void putLine(String line, int type) {\n        String[] data = line.split(\",\");\n        if (data.length == 15) {\n            SQLiteDatabase db = this.getWritableDatabase();\n            ContentValues contentValues = new ContentValues();\n\n            contentValues.put(KEY_HOST_NAME, data[0]);\n            contentValues.put(KEY_IP, data[1]);\n            contentValues.put(KEY_SCORE, data[2]);\n            contentValues.put(KEY_PING, data[3]);\n            contentValues.put(KEY_SPEED, data[4]);\n            contentValues.put(KEY_COUNTRY_LONG, data[5]);\n            contentValues.put(KEY_COUNTRY_SHORT, data[6]);\n            contentValues.put(KEY_NUM_VPN_SESSIONS, data[7]);\n            contentValues.put(KEY_UPTIME, data[8]);\n            contentValues.put(KEY_TOTAL_USERS, data[9]);\n            contentValues.put(KEY_TOTAL_TRAFFIC, data[10]);\n            contentValues.put(KEY_LOG_TYPE, data[11]);\n            contentValues.put(KEY_OPERATOR, data[12]);\n            contentValues.put(KEY_MESSAGE, data[13]);\n            contentValues.put(KEY_CONFIG_DATA, data[14]);\n            contentValues.put(KEY_TYPE, type);\n\n            contentValues.put(KEY_QUALITY,\n                    ConnectionQuality.getConnectionQuality(data[4], data[7], data[3]));\n\n            db.insert(TABLE_SERVERS, null, contentValues);\n            db.close();\n        }\n    }\n\n    public long getCount() {\n        SQLiteDatabase db = this.getWritableDatabase();\n        SQLiteStatement statement = db.compileStatement(\"SELECT COUNT(*) FROM \" + TABLE_SERVERS);\n        long count = statement.simpleQueryForLong();\n        db.close();\n        return count;\n    }\n\n    public long getCountBasic() {\n        SQLiteDatabase db = this.getWritableDatabase();\n        SQLiteStatement statement = db.compileStatement(\"SELECT COUNT(*) FROM \"\n                + TABLE_SERVERS\n                + \" WHERE \"\n                + KEY_TYPE\n                + \" = 0\");\n        long count = statement.simpleQueryForLong();\n        db.close();\n        return count;\n    }\n\n    public long getCountAdditional() {\n        SQLiteDatabase db = this.getWritableDatabase();\n        SQLiteStatement statement = db.compileStatement(\"SELECT COUNT(*) FROM \"\n                + TABLE_SERVERS\n                + \" WHERE \"\n                + KEY_TYPE\n                + \" = 1\");\n        long count = statement.simpleQueryForLong();\n        db.close();\n        return count;\n    }\n\n    public List<Server> getUniqueCountries() {\n        List<Server> countryList = new ArrayList<Server>();\n        SQLiteDatabase db = this.getWritableDatabase();\n        Cursor cursor = db.query(TABLE_SERVERS,\n                null,\n                null,\n                null,\n                KEY_COUNTRY_LONG,\n                \"MAX(\" + KEY_QUALITY + \")\",\n                null);\n\n        if (cursor.moveToFirst()) {\n            do {\n                countryList.add(parseServer(cursor));\n            } while (cursor.moveToNext());\n        } else {\n            Log.d(TAG ,\"0 rows\");\n        }\n\n        cursor.close();\n        db.close();\n\n        return countryList;\n    }\n\n    public List<Server> getServersWithGPS() {\n        List<Server> serverList = new ArrayList<Server>();\n        SQLiteDatabase db = this.getWritableDatabase();\n        Cursor cursor = db.rawQuery(\"SELECT * FROM \"\n                + TABLE_SERVERS\n                + \" WHERE \"\n                + KEY_LAT\n                + \" <> 0\", null);\n\n        if (cursor.moveToFirst()) {\n            do {\n                serverList.add(parseServer(cursor));\n            } while (cursor.moveToNext());\n        } else {\n            Log.d(TAG ,\"0 rows\");\n        }\n\n        cursor.close();\n        db.close();\n\n        return serverList;\n    }\n\n    public List<Server> getServersByCountryCode(String country) {\n        List<Server> serverList = new ArrayList<Server>();\n        if (country != null) {\n            SQLiteDatabase db = this.getWritableDatabase();\n            Cursor cursor = db.query(TABLE_SERVERS,\n                    null,\n                    KEY_COUNTRY_SHORT + \"=?\",\n                    new String[]{country},\n                    null,\n                    null,\n                    KEY_QUALITY + \" DESC\");\n\n            if (cursor.moveToFirst()) {\n                do {\n                    serverList.add(parseServer(cursor));\n                } while (cursor.moveToNext());\n            } else {\n                Log.d(TAG ,\"0 rows\");\n            }\n\n            cursor.close();\n            db.close();\n        }\n\n        return serverList;\n    }\n\n    private Server parseGoodRandomServer(Cursor cursor, SQLiteDatabase db) {\n        List<Server> serverListExcellent = new ArrayList<Server>();\n        List<Server> serverListGood = new ArrayList<Server>();\n        List<Server> serverListBad = new ArrayList<Server>();\n\n        if (cursor.moveToFirst()) {\n            do {\n                switch (cursor.getInt(16)) {\n                    case 1:\n                        serverListBad.add(parseServer(cursor));\n                        break;\n                    case 2:\n                        serverListGood.add(parseServer(cursor));\n                        break;\n                    case 3:\n                        serverListExcellent.add(parseServer(cursor));\n                        break;\n                }\n\n            } while (cursor.moveToNext());\n        } else {\n            Log.d(TAG ,\"0 rows\");\n        }\n\n        cursor.close();\n        db.close();\n\n        Random random = new Random();\n        if (serverListExcellent.size() > 0) {\n            return serverListExcellent.get(random.nextInt(serverListExcellent.size()));\n        } else if (serverListGood.size() > 0) {\n            return serverListGood.get(random.nextInt(serverListGood.size()));\n        } else if (serverListBad.size() > 0) {\n            return serverListBad.get(random.nextInt(serverListBad.size()));\n        }\n\n        return null;\n    }\n\n    public Server getSimilarServer(String country, String ip) {\n        SQLiteDatabase db = this.getWritableDatabase();\n        Cursor cursor = db.rawQuery(\"SELECT * FROM \"\n                + TABLE_SERVERS\n                + \" WHERE \"\n                + KEY_QUALITY\n                + \" <> 1 AND \"\n                + KEY_COUNTRY_LONG\n                + \" = ? AND \"\n                + KEY_IP\n                + \" <> ?\", new String[] {country, ip});\n\n\n        return parseGoodRandomServer(cursor, db);\n    }\n\n    public Server getGoodRandomServer(String country) {\n        SQLiteDatabase db = this.getWritableDatabase();\n        Cursor cursor;\n        if (country != null) {\n            cursor = db.rawQuery(\"SELECT * FROM \"\n                    + TABLE_SERVERS\n                    + \" WHERE \"\n                    + KEY_QUALITY\n                    + \" <> 0 AND \"\n                    + KEY_COUNTRY_LONG\n                    + \" = ?\", new String[] {country});\n        } else {\n            cursor = db.rawQuery(\"SELECT * FROM \"\n                    + TABLE_SERVERS\n                    + \" WHERE \"\n                    + KEY_QUALITY\n                    + \" <> 0\", null);\n        }\n\n        return parseGoodRandomServer(cursor, db);\n    }\n\n    private Server parseServer(Cursor cursor) {\n        return new Server(\n                cursor.getString(1),\n                cursor.getString(2),\n                cursor.getString(3),\n                cursor.getString(4),\n                cursor.getString(5),\n                cursor.getString(6),\n                cursor.getString(7),\n                cursor.getString(8),\n                cursor.getString(9),\n                cursor.getString(10),\n                cursor.getString(11),\n                cursor.getString(12),\n                cursor.getString(13),\n                cursor.getString(14),\n                cursor.getString(15),\n                cursor.getInt(16),\n                cursor.getString(17),\n                cursor.getInt(18),\n                cursor.getString(19),\n                cursor.getDouble(20),\n                cursor.getDouble(21)\n        );\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/model/Country.java",
    "content": "package com.vasilkoff.easyvpnfree.model;\n\n/**\n * Created by Kusenko on 01.10.2016.\n */\n\npublic class Country {\n\n    private String CountryName;\n    private String CapitalName;\n    private double CapitalLatitude;\n    private double CapitalLongitude;\n    private String CountryCode;\n\n    public Country(String countryName, String capitalName, double capitalLatitude, double capitalLongitude, String countryCode) {\n        CountryName = countryName;\n        CapitalName = capitalName;\n        CapitalLatitude = capitalLatitude;\n        CapitalLongitude = capitalLongitude;\n        CountryCode = countryCode;\n    }\n\n    public String getCountryName() {\n        return CountryName;\n    }\n\n    public String getCapitalName() {\n        return CapitalName;\n    }\n\n    public double getCapitalLatitude() {\n        return CapitalLatitude;\n    }\n\n    public double getCapitalLongitude() {\n        return CapitalLongitude;\n    }\n\n    public String getCountryCode() {\n        return CountryCode;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/model/Server.java",
    "content": "package com.vasilkoff.easyvpnfree.model;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\n\n/**\n * Created by Kusenko on 29.09.2016.\n */\n\npublic class Server implements Parcelable {\n\n    private String hostName;\n    private String ip;\n    private String score;\n    private String ping;\n    private String speed;\n    private String countryLong;\n    private String countryShort;\n    private String numVpnSessions;\n    private String uptime;\n    private String totalUsers;\n    private String totalTraffic;\n    private String logType;\n    private String operator;\n    private String message;\n    private String configData;\n    private int quality;\n    private String city;\n    private int type;\n    private String regionName;\n    private double lat;\n    private double lon;\n\n    public Server(String hostName, String ip, String score, String ping, String speed, String countryLong, String countryShort, String numVpnSessions, String uptime, String totalUsers, String totalTraffic, String logType, String operator, String message, String configData, int quality, String city, int type, String regionName, double lat, double lon) {\n        this.hostName = hostName;\n        this.ip = ip;\n        this.score = score;\n        this.ping = ping;\n        this.speed = speed;\n        this.countryLong = countryLong;\n        this.countryShort = countryShort;\n        this.numVpnSessions = numVpnSessions;\n        this.uptime = uptime;\n        this.totalUsers = totalUsers;\n        this.totalTraffic = totalTraffic;\n        this.logType = logType;\n        this.operator = operator;\n        this.message = message;\n        this.configData = configData;\n        this.quality = quality;\n        this.city = city;\n        this.type = type;\n        this.regionName = regionName;\n        this.lat = lat;\n        this.lon = lon;\n    }\n\n    protected Server(Parcel in) {\n        hostName = in.readString();\n        ip = in.readString();\n        score = in.readString();\n        ping = in.readString();\n        speed = in.readString();\n        countryLong = in.readString();\n        countryShort = in.readString();\n        numVpnSessions = in.readString();\n        uptime = in.readString();\n        totalUsers = in.readString();\n        totalTraffic = in.readString();\n        logType = in.readString();\n        operator = in.readString();\n        message = in.readString();\n        configData = in.readString();\n        quality = in.readInt();\n        city = in.readString();\n        type = in.readInt();\n        regionName = in.readString();\n        lat = in.readDouble();\n        lon = in.readDouble();\n    }\n\n    public static final Creator<Server> CREATOR = new Creator<Server>() {\n        @Override\n        public Server createFromParcel(Parcel in) {\n            return new Server(in);\n        }\n\n        @Override\n        public Server[] newArray(int size) {\n            return new Server[size];\n        }\n    };\n\n    public String getHostName() {\n        return hostName;\n    }\n\n    public void setHostName(String hostName) {\n        this.hostName = hostName;\n    }\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public String getScore() {\n        return score;\n    }\n\n    public void setScore(String score) {\n        this.score = score;\n    }\n\n    public String getPing() {\n        return ping;\n    }\n\n    public void setPing(String ping) {\n        this.ping = ping;\n    }\n\n    public String getSpeed() {\n        return speed;\n    }\n\n    public void setSpeed(String speed) {\n        this.speed = speed;\n    }\n\n    public String getCountryLong() {\n        return countryLong;\n    }\n\n    public void setCountryLong(String countryLong) {\n        this.countryLong = countryLong;\n    }\n\n    public String getCountryShort() {\n        return countryShort;\n    }\n\n    public void setCountryShort(String countryShort) {\n        this.countryShort = countryShort;\n    }\n\n    public String getNumVpnSessions() {\n        return numVpnSessions;\n    }\n\n    public void setNumVpnSessions(String numVpnSessions) {\n        this.numVpnSessions = numVpnSessions;\n    }\n\n    public String getUptime() {\n        return uptime;\n    }\n\n    public void setUptime(String uptime) {\n        this.uptime = uptime;\n    }\n\n    public String getTotalUsers() {\n        return totalUsers;\n    }\n\n    public void setTotalUsers(String totalUsers) {\n        this.totalUsers = totalUsers;\n    }\n\n    public String getTotalTraffic() {\n        return totalTraffic;\n    }\n\n    public void setTotalTraffic(String totalTraffic) {\n        this.totalTraffic = totalTraffic;\n    }\n\n    public String getLogType() {\n        return logType;\n    }\n\n    public void setLogType(String logType) {\n        this.logType = logType;\n    }\n\n    public String getOperator() {\n        return operator;\n    }\n\n    public void setOperator(String operator) {\n        this.operator = operator;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n    public String getConfigData() {\n        return configData;\n    }\n\n    public void setConfigData(String configData) {\n        this.configData = configData;\n    }\n\n    public int getQuality() {\n        return quality;\n    }\n\n    public void setQuality(int quality) {\n        this.quality = quality;\n    }\n\n    public String getCity() {\n        return city;\n    }\n\n    public void setCity(String city) {\n        this.city = city;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public String getRegionName() {\n        return regionName;\n    }\n\n    public void setRegionName(String regionName) {\n        this.regionName = regionName;\n    }\n\n    public double getLat() {\n        return lat;\n    }\n\n    public void setLat(double lat) {\n        this.lat = lat;\n    }\n\n    public double getLon() {\n        return lon;\n    }\n\n    public void setLon(double lon) {\n        this.lon = lon;\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n        dest.writeString(hostName);\n        dest.writeString(ip);\n        dest.writeString(score);\n        dest.writeString(ping);\n        dest.writeString(speed);\n        dest.writeString(countryLong);\n        dest.writeString(countryShort);\n        dest.writeString(numVpnSessions);\n        dest.writeString(uptime);\n        dest.writeString(totalUsers);\n        dest.writeString(totalTraffic);\n        dest.writeString(logType);\n        dest.writeString(operator);\n        dest.writeString(message);\n        dest.writeString(configData);\n        dest.writeInt(quality);\n        dest.writeString(city);\n        dest.writeInt(type);\n        dest.writeString(regionName);\n        dest.writeDouble(lat);\n        dest.writeDouble(lon);\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/BitmapGenerator.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport android.graphics.Bitmap;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\n\npublic class BitmapGenerator {\n\n    private  static Paint paint = new Paint();\n\n    public static Bitmap getTextAsBitmap(String text, float textSize, int textColor) {\n        String textUp = text.toUpperCase();\n        paint.setTextSize(textSize);\n        paint.setColor(textColor);\n        paint.setTextAlign(Paint.Align.LEFT);\n        float baseline = -paint.ascent(); // ascent() is negative\n        int width = (int) (paint.measureText(textUp) + 0.5f); // round\n        int height = (int) (baseline + paint.descent() + 25.5f);\n        Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);\n        Canvas canvas = new Canvas(image);\n        canvas.drawText(textUp, 0, baseline, paint);\n        return image;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/ConnectionQuality.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\n/**\n * Created by Kusenko on 09.12.2016.\n */\n\npublic class ConnectionQuality {\n\n    private static final String CONNECT_BAD = \"ic_connect_bad\";\n    private static final String CONNECT_GOOD = \"ic_connect_good\";\n    private static final String CONNECT_EXCELLENT = \"ic_connect_excellent\";\n    private static final String CONNECT_INACTIVE = \"ic_connect_inactive\";\n\n    private static final String POINT_BAD = \"ic_point_red\";\n    private static final String POINT_GOOD = \"ic_point_yellow\";\n    private static final String POINT_EXCELLENT = \"ic_point_green\";\n    private static final String POINT_INACTIVE = \"ic_point_grey\";\n\n    private static final String SIMPLE_POINT_BAD = \"ic_simple_point_red\";\n    private static final String SIMPLE_POINT_GOOD = \"ic_simple_point_yellow\";\n    private static final String SIMPLE_POINT_EXCELLENT = \"ic_simple_point_green\";\n    private static final String SIMPLE_POINT_INACTIVE = \"ic_simple_point_grey\";\n\n    public static String getConnectIcon(int quality) {\n        switch (quality) {\n            case 0:\n                return CONNECT_INACTIVE;\n            case 1:\n                return CONNECT_BAD;\n            case 2:\n                return CONNECT_GOOD;\n            case 3:\n                return CONNECT_EXCELLENT;\n            default:\n                return CONNECT_INACTIVE;\n        }\n    }\n\n    public static String getPointIcon(int quality) {\n        switch (quality) {\n            case 0:\n                return POINT_INACTIVE;\n            case 1:\n                return POINT_BAD;\n            case 2:\n                return POINT_GOOD;\n            case 3:\n                return POINT_EXCELLENT;\n            default:\n                return POINT_INACTIVE;\n        }\n    }\n\n    public static String getSimplePointIcon(int quality) {\n        switch (quality) {\n            case 0:\n                return SIMPLE_POINT_INACTIVE;\n            case 1:\n                return SIMPLE_POINT_BAD;\n            case 2:\n                return SIMPLE_POINT_GOOD;\n            case 3:\n                return SIMPLE_POINT_EXCELLENT;\n            default:\n                return SIMPLE_POINT_INACTIVE;\n        }\n    }\n\n    public static int getConnectionQuality(String speedStr, String sessionsStr, String pingStr) {\n\n        int speed = Integer.parseInt(speedStr);\n        int sessions = Integer.parseInt(sessionsStr);\n\n        int ping = 0;\n        if (!(pingStr.equals(\"-\") || pingStr.equals(\"\"))) {\n            ping = Integer.parseInt(pingStr);\n        }\n\n        if (speed > 10000000 && ping < 30 && (sessions != 0 && sessions < 100)) {\n            return 3;\n        } else if (speed < 1000000 || ping > 100 || (sessions == 0 || sessions > 150)) {\n            return 1;\n        } else {\n            return 2;\n        }\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/CountriesNames.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\n\n/**\n * Created by Kusenko on 26.12.2016.\n */\n\npublic class CountriesNames {\n\n    public static Map<String, String> getCountries() {\n        Map<String, String> countries = new HashMap<String, String>();\n\n        String[] isoCountries = Locale.getISOCountries();\n        for (String country : isoCountries) {\n            Locale locale = new Locale(\"\", country);\n            String iso = locale.getISO3Country();\n            String code = locale.getCountry();\n            String name = locale.getDisplayCountry();\n\n            if (!\"\".equals(iso) && !\"\".equals(code)\n                    && !\"\".equals(name)) {\n                countries.put(code, name);\n            }\n        }\n\n        return countries;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/LoadData.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport android.content.Context;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\npublic class LoadData {\n\n    public static String fromFile(String nameFile, Context context) {\n        String data = null;\n        try {\n\n            InputStream is = context.getAssets().open(nameFile);\n\n            int size = is.available();\n\n            byte[] buffer = new byte[size];\n\n            is.read(buffer);\n\n            is.close();\n\n            data = new String(buffer, \"UTF-8\");\n\n\n        } catch (IOException ex) {\n            ex.printStackTrace();\n            return null;\n        }\n        return data;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/NetworkState.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport android.content.Context;\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\n\nimport com.vasilkoff.easyvpnfree.App;\n\n\npublic class NetworkState {\n\n    public static boolean isOnline()\n    {\n        ConnectivityManager cm =\n                (ConnectivityManager) App.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);\n        NetworkInfo netInfo = cm.getActiveNetworkInfo();\n        if (netInfo != null && netInfo.isConnectedOrConnecting())\n        {\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/NumberPickerPreference.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.preference.DialogPreference;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.FrameLayout;\nimport android.widget.NumberPicker;\n\n/**\n * Created by Kusenko on 19.12.2016.\n */\n\npublic class NumberPickerPreference extends DialogPreference {\n\n    // allowed range\n    public static final int MAX_VALUE = 120;\n    public static final int MIN_VALUE = 10;\n    // enable or disable the 'circular behavior'\n    public static final boolean WRAP_SELECTOR_WHEEL = true;\n\n    private NumberPicker picker;\n    private int value;\n\n    public NumberPickerPreference(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n    }\n\n    @Override\n    protected View onCreateDialogView() {\n        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(\n                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        layoutParams.gravity = Gravity.CENTER;\n\n        picker = new NumberPicker(getContext());\n        picker.setLayoutParams(layoutParams);\n\n        FrameLayout dialogView = new FrameLayout(getContext());\n        dialogView.addView(picker);\n\n        return dialogView;\n    }\n\n    @Override\n    protected void onBindDialogView(View view) {\n        super.onBindDialogView(view);\n        picker.setMinValue(MIN_VALUE);\n        picker.setMaxValue(MAX_VALUE);\n        picker.setWrapSelectorWheel(WRAP_SELECTOR_WHEEL);\n        picker.setValue(getValue());\n    }\n\n    @Override\n    protected void onDialogClosed(boolean positiveResult) {\n        if (positiveResult) {\n            picker.clearFocus();\n            int newValue = picker.getValue();\n            if (callChangeListener(newValue)) {\n                setValue(newValue);\n            }\n        }\n    }\n\n    @Override\n    protected Object onGetDefaultValue(TypedArray a, int index) {\n        return a.getInt(index, MIN_VALUE);\n    }\n\n    @Override\n    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {\n        setValue(restorePersistedValue ? getPersistedInt(MIN_VALUE) : (Integer) defaultValue);\n    }\n\n    public void setValue(int value) {\n        this.value = value;\n        persistInt(this.value);\n    }\n\n    public int getValue() {\n        return this.value;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/PropertiesService.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport android.preference.PreferenceManager;\n\nimport com.vasilkoff.easyvpnfree.App;\n\n/**\n * Created by Kusenko on 16.12.2016.\n */\n\npublic class PropertiesService {\n\n    private static SharedPreferences prefs;\n    private static final String DOWNLOADED_DATA_KEY = \"downloaded_data\";\n    private static final String UPLOADED_DATA_KEY = \"uploaded_data\";\n    private static final String AUTOMATIC_SWITCHING = \"automaticSwitching\";\n    private static final String COUNTRY_PRIORITY = \"countryPriority\";\n    private static final String CONNECT_ON_START = \"connectOnStart\";\n    private static final String AUTOMATIC_SWITCHING_SECONDS = \"automaticSwitchingSeconds\";\n    private static final String SELECTED_COUNTRY = \"selectedCountry\";\n    private static final String SHOW_RATING = \"show_rating\";\n    private static final String SHOW_NOTE = \"show_note\";\n\n    private synchronized static SharedPreferences getPrefs(){\n        if (prefs == null) {\n            prefs = PreferenceManager.getDefaultSharedPreferences(App.getInstance());\n        }\n        return prefs;\n    }\n\n    public static long getDownloaded(){\n        return getPrefs().getLong(DOWNLOADED_DATA_KEY, 0);\n    }\n\n    public static void setDownloaded(long count){\n        getPrefs().edit().putLong(DOWNLOADED_DATA_KEY, count).apply();\n    }\n\n    public static long getUploaded(){\n        return getPrefs().getLong(UPLOADED_DATA_KEY, 0);\n    }\n\n    public static void setUploaded(long count){\n        getPrefs().edit().putLong(UPLOADED_DATA_KEY, count).apply();\n    }\n\n    public static boolean getConnectOnStart(){\n        return getPrefs().getBoolean(CONNECT_ON_START, false);\n    }\n\n    public static boolean getAutomaticSwitching(){\n        return getPrefs().getBoolean(AUTOMATIC_SWITCHING, true);\n    }\n\n    public static int getAutomaticSwitchingSeconds(){\n        return getPrefs().getInt(AUTOMATIC_SWITCHING_SECONDS, 40);\n    }\n\n    public static boolean getCountryPriority(){\n        return getPrefs().getBoolean(COUNTRY_PRIORITY, false);\n    }\n\n    public static String getSelectedCountry(){\n        return getPrefs().getString(SELECTED_COUNTRY, null);\n    }\n\n    public static boolean getShowRating(){\n        return getPrefs().getBoolean(SHOW_RATING, true);\n    }\n\n    public static void setShowRating(boolean showRating){\n        getPrefs().edit().putBoolean(SHOW_RATING, showRating).apply();\n    }\n\n    public static boolean getShowNote(){\n        return getPrefs().getBoolean(SHOW_NOTE, true);\n    }\n\n    public static void setShowNote(boolean showNote){\n        getPrefs().edit().putBoolean(SHOW_NOTE, showNote).apply();\n    }\n\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/Stopwatch.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.TimeZone;\n\npublic class Stopwatch {\n\n    private SimpleDateFormat sdf = new SimpleDateFormat(\"HH:mm:ss\");\n    private Calendar calendar = Calendar.getInstance();\n    private long startTime = System.currentTimeMillis();\n\n    public Stopwatch() {\n        sdf.setTimeZone(TimeZone.getTimeZone(\"UTC\"));\n    }\n\n    public long getDiff() {\n        return System.currentTimeMillis() - startTime;\n    }\n\n    public String getElapsedTime() {\n        calendar.setTimeInMillis(getDiff());\n        return sdf.format(calendar.getTime());\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/TotalTraffic.java",
    "content": "package com.vasilkoff.easyvpnfree.util;\n\nimport android.content.Context;\nimport android.content.Intent;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport de.blinkt.openvpn.core.OpenVPNService;\n\n/**\n * Created by Kusenko on 16.12.2016.\n */\n\npublic class TotalTraffic {\n\n    public static final String TRAFFIC_ACTION = \"traffic_action\";\n\n    public static final String DOWNLOAD_ALL = \"download_all\";\n    public static final String DOWNLOAD_SESSION = \"download_session\";\n    public static final String UPLOAD_ALL = \"upload_all\";\n    public static final String UPLOAD_SESSION = \"upload_session\";\n\n    public static long inTotal;\n    public static long outTotal;\n\n\n    public static void calcTraffic(Context context, long in, long out, long diffIn, long diffOut) {\n        List<String> totalTraffic = getTotalTraffic(diffIn, diffOut);\n\n        Intent traffic = new Intent();\n        traffic.setAction(TRAFFIC_ACTION);\n        traffic.putExtra(DOWNLOAD_ALL, totalTraffic.get(0));\n        traffic.putExtra(DOWNLOAD_SESSION, OpenVPNService.humanReadableByteCount(in, false));\n        traffic.putExtra(UPLOAD_ALL, totalTraffic.get(1));\n        traffic.putExtra(UPLOAD_SESSION, OpenVPNService.humanReadableByteCount(out, false));\n\n        context.sendBroadcast(traffic);\n    }\n\n    public static List<String> getTotalTraffic() {\n        return getTotalTraffic(0, 0);\n    }\n\n    public static List<String> getTotalTraffic(long in, long out) {\n        List<String> totalTraffic = new ArrayList<String>();\n\n        if (inTotal == 0)\n            inTotal = PropertiesService.getDownloaded();\n\n        if (outTotal == 0)\n            outTotal = PropertiesService.getUploaded();\n\n        inTotal = inTotal + in;\n        outTotal = outTotal + out;\n\n        totalTraffic.add(OpenVPNService.humanReadableByteCount(inTotal, false));\n        totalTraffic.add(OpenVPNService.humanReadableByteCount(outTotal, false));\n\n        return totalTraffic;\n    }\n\n    public static void saveTotal() {\n        if (inTotal != 0)\n            PropertiesService.setDownloaded(inTotal);\n\n        if (outTotal != 0)\n            PropertiesService.setUploaded(outTotal);\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/Base64.java",
    "content": "// Portions copyright 2002, Google, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\n// This code was converted from code at http://iharder.sourceforge.net/base64/\n// Lots of extraneous features were removed.\n/* The original code said:\n * <p>\n * I am placing this code in the Public Domain. Do with it as you will.\n * This software comes with no guarantees or warranties but with\n * plenty of well-wishing instead!\n * Please visit\n * <a href=\"http://iharder.net/xmlizable\">http://iharder.net/xmlizable</a>\n * periodically to check for updates or to contribute improvements.\n * </p>\n *\n * @author Robert Harder\n * @author rharder@usa.net\n * @version 1.3\n */\n\n/**\n * Base64 converter class. This code is not a complete MIME encoder;\n * it simply converts binary data to base64 data and back.\n *\n * <p>Note {@link CharBase64} is a GWT-compatible implementation of this\n * class.\n */\npublic class Base64 {\n    /** Specify encoding (value is {@code true}). */\n    public final static boolean ENCODE = true;\n\n    /** Specify decoding (value is {@code false}). */\n    public final static boolean DECODE = false;\n\n    /** The equals sign (=) as a byte. */\n    private final static byte EQUALS_SIGN = (byte) '=';\n\n    /** The new line character (\\n) as a byte. */\n    private final static byte NEW_LINE = (byte) '\\n';\n\n    /**\n     * The 64 valid Base64 values.\n     */\n    private final static byte[] ALPHABET =\n        {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',\n        (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',\n        (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',\n        (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',\n        (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',\n        (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',\n        (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',\n        (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',\n        (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',\n        (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',\n        (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',\n        (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',\n        (byte) '9', (byte) '+', (byte) '/'};\n\n    /**\n     * The 64 valid web safe Base64 values.\n     */\n    private final static byte[] WEBSAFE_ALPHABET =\n        {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',\n        (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',\n        (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',\n        (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',\n        (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',\n        (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',\n        (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',\n        (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',\n        (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',\n        (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',\n        (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',\n        (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',\n        (byte) '9', (byte) '-', (byte) '_'};\n\n    /**\n     * Translates a Base64 value to either its 6-bit reconstruction value\n     * or a negative number indicating some other meaning.\n     **/\n    private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal  0 -  8\n        -5, -5, // Whitespace: Tab and Linefeed\n        -9, -9, // Decimal 11 - 12\n        -5, // Whitespace: Carriage Return\n        -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26\n        -9, -9, -9, -9, -9, // Decimal 27 - 31\n        -5, // Whitespace: Space\n        -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42\n        62, // Plus sign at decimal 43\n        -9, -9, -9, // Decimal 44 - 46\n        63, // Slash at decimal 47\n        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine\n        -9, -9, -9, // Decimal 58 - 60\n        -1, // Equals sign at decimal 61\n        -9, -9, -9, // Decimal 62 - 64\n        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'\n        14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'\n        -9, -9, -9, -9, -9, -9, // Decimal 91 - 96\n        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'\n        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'\n        -9, -9, -9, -9, -9 // Decimal 123 - 127\n        /*  ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 128 - 139\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 140 - 152\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 153 - 165\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 166 - 178\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 179 - 191\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 192 - 204\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 205 - 217\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 218 - 230\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 231 - 243\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9         // Decimal 244 - 255 */\n    };\n\n    /** The web safe decodabet */\n    private final static byte[] WEBSAFE_DECODABET =\n        {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal  0 -  8\n        -5, -5, // Whitespace: Tab and Linefeed\n        -9, -9, // Decimal 11 - 12\n        -5, // Whitespace: Carriage Return\n        -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26\n        -9, -9, -9, -9, -9, // Decimal 27 - 31\n        -5, // Whitespace: Space\n        -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44\n        62, // Dash '-' sign at decimal 45\n        -9, -9, // Decimal 46-47\n        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine\n        -9, -9, -9, // Decimal 58 - 60\n        -1, // Equals sign at decimal 61\n        -9, -9, -9, // Decimal 62 - 64\n        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'\n        14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'\n        -9, -9, -9, -9, // Decimal 91-94\n        63, // Underscore '_' at decimal 95\n        -9, // Decimal 96\n        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'\n        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'\n        -9, -9, -9, -9, -9 // Decimal 123 - 127\n        /*  ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 128 - 139\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 140 - 152\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 153 - 165\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 166 - 178\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 179 - 191\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 192 - 204\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 205 - 217\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 218 - 230\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 231 - 243\n        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9         // Decimal 244 - 255 */\n        };\n\n    // Indicates white space in encoding\n    private final static byte WHITE_SPACE_ENC = -5;\n    // Indicates equals sign in encoding\n    private final static byte EQUALS_SIGN_ENC = -1;\n\n    /** Defeats instantiation. */\n    private Base64() {\n    }\n\n    /* ********  E N C O D I N G   M E T H O D S  ******** */\n\n    /**\n     * Encodes up to three bytes of the array <var>source</var>\n     * and writes the resulting four Base64 bytes to <var>destination</var>.\n     * The source and destination arrays can be manipulated\n     * anywhere along their length by specifying\n     * <var>srcOffset</var> and <var>destOffset</var>.\n     * This method does not check to make sure your arrays\n     * are large enough to accommodate <var>srcOffset</var> + 3 for\n     * the <var>source</var> array or <var>destOffset</var> + 4 for\n     * the <var>destination</var> array.\n     * The actual number of significant bytes in your array is\n     * given by <var>numSigBytes</var>.\n     *\n     * @param source the array to convert\n     * @param srcOffset the index where conversion begins\n     * @param numSigBytes the number of significant bytes in your array\n     * @param destination the array to hold the conversion\n     * @param destOffset the index where output will be put\n     * @param alphabet is the encoding alphabet\n     * @return the <var>destination</var> array\n     * @since 1.3\n     */\n    private static byte[] encode3to4(byte[] source, int srcOffset,\n            int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) {\n        //           1         2         3\n        // 01234567890123456789012345678901 Bit position\n        // --------000000001111111122222222 Array position from threeBytes\n        // --------|    ||    ||    ||    | Six bit groups to index alphabet\n        //          >>18  >>12  >> 6  >> 0  Right shift necessary\n        //                0x3f  0x3f  0x3f  Additional AND\n\n        // Create buffer with zero-padding if there are only one or two\n        // significant bytes passed in the array.\n        // We have to shift left 24 in order to flush out the 1's that appear\n        // when Java treats a value as negative that is cast from a byte to an int.\n        int inBuff =\n                (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)\n                | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)\n                | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);\n\n        switch (numSigBytes) {\n            case 3:\n                destination[destOffset] = alphabet[(inBuff >>> 18)];\n                destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];\n                destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];\n                destination[destOffset + 3] = alphabet[(inBuff) & 0x3f];\n                return destination;\n            case 2:\n                destination[destOffset] = alphabet[(inBuff >>> 18)];\n                destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];\n                destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];\n                destination[destOffset + 3] = EQUALS_SIGN;\n                return destination;\n            case 1:\n                destination[destOffset] = alphabet[(inBuff >>> 18)];\n                destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];\n                destination[destOffset + 2] = EQUALS_SIGN;\n                destination[destOffset + 3] = EQUALS_SIGN;\n                return destination;\n            default:\n                return destination;\n        } // end switch\n    } // end encode3to4\n\n    /**\n     * Encodes a byte array into Base64 notation.\n     * Equivalent to calling\n     * {@code encodeBytes(source, 0, source.length)}\n     *\n     * @param source The data to convert\n     * @since 1.4\n     */\n    public static String encode(byte[] source) {\n        return encode(source, 0, source.length, ALPHABET, true);\n    }\n\n    /**\n     * Encodes a byte array into web safe Base64 notation.\n     *\n     * @param source The data to convert\n     * @param doPadding is {@code true} to pad result with '=' chars\n     *        if it does not fall on 3 byte boundaries\n     */\n    public static String encodeWebSafe(byte[] source, boolean doPadding) {\n        return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding);\n    }\n\n    /**\n     * Encodes a byte array into Base64 notation.\n     *\n     * @param source the data to convert\n     * @param off offset in array where conversion should begin\n     * @param len length of data to convert\n     * @param alphabet the encoding alphabet\n     * @param doPadding is {@code true} to pad result with '=' chars\n     * if it does not fall on 3 byte boundaries\n     * @since 1.4\n     */\n    public static String encode(byte[] source, int off, int len, byte[] alphabet,\n            boolean doPadding) {\n        byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE);\n        int outLen = outBuff.length;\n\n        // If doPadding is false, set length to truncate '='\n        // padding characters\n        while (doPadding == false && outLen > 0) {\n            if (outBuff[outLen - 1] != '=') {\n                break;\n            }\n            outLen -= 1;\n        }\n\n        return new String(outBuff, 0, outLen);\n    }\n\n    /**\n     * Encodes a byte array into Base64 notation.\n     *\n     * @param source the data to convert\n     * @param off offset in array where conversion should begin\n     * @param len length of data to convert\n     * @param alphabet is the encoding alphabet\n     * @param maxLineLength maximum length of one line.\n     * @return the BASE64-encoded byte array\n     */\n    public static byte[] encode(byte[] source, int off, int len, byte[] alphabet,\n            int maxLineLength) {\n        int lenDiv3 = (len + 2) / 3; // ceil(len / 3)\n        int len43 = lenDiv3 * 4;\n        byte[] outBuff = new byte[len43 // Main 4:3\n                                  + (len43 / maxLineLength)]; // New lines\n\n        int d = 0;\n        int e = 0;\n        int len2 = len - 2;\n        int lineLength = 0;\n        for (; d < len2; d += 3, e += 4) {\n\n            // The following block of code is the same as\n            // encode3to4( source, d + off, 3, outBuff, e, alphabet );\n            // but inlined for faster encoding (~20% improvement)\n            int inBuff =\n                    ((source[d + off] << 24) >>> 8)\n                    | ((source[d + 1 + off] << 24) >>> 16)\n                    | ((source[d + 2 + off] << 24) >>> 24);\n            outBuff[e] = alphabet[(inBuff >>> 18)];\n            outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f];\n            outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f];\n            outBuff[e + 3] = alphabet[(inBuff) & 0x3f];\n\n            lineLength += 4;\n            if (lineLength == maxLineLength) {\n                outBuff[e + 4] = NEW_LINE;\n                e++;\n                lineLength = 0;\n            } // end if: end of line\n        } // end for: each piece of array\n\n        if (d < len) {\n            encode3to4(source, d + off, len - d, outBuff, e, alphabet);\n\n            lineLength += 4;\n            if (lineLength == maxLineLength) {\n                // Add a last newline\n                outBuff[e + 4] = NEW_LINE;\n                e++;\n            }\n            e += 4;\n        }\n\n        assert (e == outBuff.length);\n        return outBuff;\n    }\n\n\n    /* ********  D E C O D I N G   M E T H O D S  ******** */\n\n\n    /**\n     * Decodes four bytes from array <var>source</var>\n     * and writes the resulting bytes (up to three of them)\n     * to <var>destination</var>.\n     * The source and destination arrays can be manipulated\n     * anywhere along their length by specifying\n     * <var>srcOffset</var> and <var>destOffset</var>.\n     * This method does not check to make sure your arrays\n     * are large enough to accommodate <var>srcOffset</var> + 4 for\n     * the <var>source</var> array or <var>destOffset</var> + 3 for\n     * the <var>destination</var> array.\n     * This method returns the actual number of bytes that\n     * were converted from the Base64 encoding.\n     *\n     *\n     * @param source the array to convert\n     * @param srcOffset the index where conversion begins\n     * @param destination the array to hold the conversion\n     * @param destOffset the index where output will be put\n     * @param decodabet the decodabet for decoding Base64 content\n     * @return the number of decoded bytes converted\n     * @since 1.3\n     */\n    private static int decode4to3(byte[] source, int srcOffset,\n            byte[] destination, int destOffset, byte[] decodabet) {\n        // Example: Dk==\n        if (source[srcOffset + 2] == EQUALS_SIGN) {\n            int outBuff =\n                    ((decodabet[source[srcOffset]] << 24) >>> 6)\n                    | ((decodabet[source[srcOffset + 1]] << 24) >>> 12);\n\n            destination[destOffset] = (byte) (outBuff >>> 16);\n            return 1;\n        } else if (source[srcOffset + 3] == EQUALS_SIGN) {\n            // Example: DkL=\n            int outBuff =\n                    ((decodabet[source[srcOffset]] << 24) >>> 6)\n                    | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)\n                    | ((decodabet[source[srcOffset + 2]] << 24) >>> 18);\n\n            destination[destOffset] = (byte) (outBuff >>> 16);\n            destination[destOffset + 1] = (byte) (outBuff >>> 8);\n            return 2;\n        } else {\n            // Example: DkLE\n            int outBuff =\n                    ((decodabet[source[srcOffset]] << 24) >>> 6)\n                    | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)\n                    | ((decodabet[source[srcOffset + 2]] << 24) >>> 18)\n                    | ((decodabet[source[srcOffset + 3]] << 24) >>> 24);\n\n            destination[destOffset] = (byte) (outBuff >> 16);\n            destination[destOffset + 1] = (byte) (outBuff >> 8);\n            destination[destOffset + 2] = (byte) (outBuff);\n            return 3;\n        }\n    } // end decodeToBytes\n\n\n    /**\n     * Decodes data from Base64 notation.\n     *\n     * @param s the string to decode (decoded in default encoding)\n     * @return the decoded data\n     * @since 1.4\n     */\n    public static byte[] decode(String s) throws Base64DecoderException {\n        byte[] bytes = s.getBytes();\n        return decode(bytes, 0, bytes.length);\n    }\n\n    /**\n     * Decodes data from web safe Base64 notation.\n     * Web safe encoding uses '-' instead of '+', '_' instead of '/'\n     *\n     * @param s the string to decode (decoded in default encoding)\n     * @return the decoded data\n     */\n    public static byte[] decodeWebSafe(String s) throws Base64DecoderException {\n        byte[] bytes = s.getBytes();\n        return decodeWebSafe(bytes, 0, bytes.length);\n    }\n\n    /**\n     * Decodes Base64 content in byte array format and returns\n     * the decoded byte array.\n     *\n     * @param source The Base64 encoded data\n     * @return decoded data\n     * @since 1.3\n     * @throws Base64DecoderException\n     */\n    public static byte[] decode(byte[] source) throws Base64DecoderException {\n        return decode(source, 0, source.length);\n    }\n\n    /**\n     * Decodes web safe Base64 content in byte array format and returns\n     * the decoded data.\n     * Web safe encoding uses '-' instead of '+', '_' instead of '/'\n     *\n     * @param source the string to decode (decoded in default encoding)\n     * @return the decoded data\n     */\n    public static byte[] decodeWebSafe(byte[] source)\n            throws Base64DecoderException {\n        return decodeWebSafe(source, 0, source.length);\n    }\n\n    /**\n     * Decodes Base64 content in byte array format and returns\n     * the decoded byte array.\n     *\n     * @param source the Base64 encoded data\n     * @param off    the offset of where to begin decoding\n     * @param len    the length of characters to decode\n     * @return decoded data\n     * @since 1.3\n     * @throws Base64DecoderException\n     */\n    public static byte[] decode(byte[] source, int off, int len)\n            throws Base64DecoderException {\n        return decode(source, off, len, DECODABET);\n    }\n\n    /**\n     * Decodes web safe Base64 content in byte array format and returns\n     * the decoded byte array.\n     * Web safe encoding uses '-' instead of '+', '_' instead of '/'\n     *\n     * @param source the Base64 encoded data\n     * @param off    the offset of where to begin decoding\n     * @param len    the length of characters to decode\n     * @return decoded data\n     */\n    public static byte[] decodeWebSafe(byte[] source, int off, int len)\n            throws Base64DecoderException {\n        return decode(source, off, len, WEBSAFE_DECODABET);\n    }\n\n    /**\n     * Decodes Base64 content using the supplied decodabet and returns\n     * the decoded byte array.\n     *\n     * @param source the Base64 encoded data\n     * @param off the offset of where to begin decoding\n     * @param len the length of characters to decode\n     * @param decodabet the decodabet for decoding Base64 content\n     * @return decoded data\n     */\n    public static byte[] decode(byte[] source, int off, int len, byte[] decodabet)\n            throws Base64DecoderException {\n        int len34 = len * 3 / 4;\n        byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output\n        int outBuffPosn = 0;\n\n        byte[] b4 = new byte[4];\n        int b4Posn = 0;\n        int i = 0;\n        byte sbiCrop = 0;\n        byte sbiDecode = 0;\n        for (i = 0; i < len; i++) {\n            sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits\n            sbiDecode = decodabet[sbiCrop];\n\n            if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better\n                if (sbiDecode >= EQUALS_SIGN_ENC) {\n                    // An equals sign (for padding) must not occur at position 0 or 1\n                    // and must be the last byte[s] in the encoded value\n                    if (sbiCrop == EQUALS_SIGN) {\n                        int bytesLeft = len - i;\n                        byte lastByte = (byte) (source[len - 1 + off] & 0x7f);\n                        if (b4Posn == 0 || b4Posn == 1) {\n                            throw new Base64DecoderException(\n                                    \"invalid padding byte '=' at byte offset \" + i);\n                        } else if ((b4Posn == 3 && bytesLeft > 2)\n                                || (b4Posn == 4 && bytesLeft > 1)) {\n                            throw new Base64DecoderException(\n                                    \"padding byte '=' falsely signals end of encoded value \"\n                                            + \"at offset \" + i);\n                        } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) {\n                            throw new Base64DecoderException(\n                                    \"encoded value has invalid trailing byte\");\n                        }\n                        break;\n                    }\n\n                    b4[b4Posn++] = sbiCrop;\n                    if (b4Posn == 4) {\n                        outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);\n                        b4Posn = 0;\n                    }\n                }\n            } else {\n                throw new Base64DecoderException(\"Bad Base64 input character at \" + i\n                        + \": \" + source[i + off] + \"(decimal)\");\n            }\n        }\n\n        // Because web safe encoding allows non padding base64 encodes, we\n        // need to pad the rest of the b4 buffer with equal signs when\n        // b4Posn != 0.  There can be at most 2 equal signs at the end of\n        // four characters, so the b4 buffer must have two or three\n        // characters.  This also catches the case where the input is\n        // padded with EQUALS_SIGN\n        if (b4Posn != 0) {\n            if (b4Posn == 1) {\n                throw new Base64DecoderException(\"single trailing character at offset \"\n                        + (len - 1));\n            }\n            b4[b4Posn++] = EQUALS_SIGN;\n            outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);\n        }\n\n        byte[] out = new byte[outBuffPosn];\n        System.arraycopy(outBuff, 0, out, 0, outBuffPosn);\n        return out;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/Base64DecoderException.java",
    "content": "// Copyright 2002, Google, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\n/**\n * Exception thrown when encountering an invalid Base64 input character.\n *\n * @author nelson\n */\npublic class Base64DecoderException extends Exception {\n    public Base64DecoderException() {\n        super();\n    }\n\n    public Base64DecoderException(String s) {\n        super(s);\n    }\n\n    private static final long serialVersionUID = 1L;\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/IabException.java",
    "content": "/* Copyright (c) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\n/**\n * Exception thrown when something went wrong with in-app billing.\n * An IabException has an associated IabResult (an error).\n * To get the IAB result that caused this exception to be thrown,\n * call {@link #getResult()}.\n */\npublic class IabException extends Exception {\n    IabResult mResult;\n\n    public IabException(IabResult r) {\n        this(r, null);\n    }\n    public IabException(int response, String message) {\n        this(new IabResult(response, message));\n    }\n    public IabException(IabResult r, Exception cause) {\n        super(r.getMessage(), cause);\n        mResult = r;\n    }\n    public IabException(int response, String message, Exception cause) {\n        this(new IabResult(response, message), cause);\n    }\n\n    /** Returns the IAB result (error) that this exception signals. */\n    public IabResult getResult() { return mResult; }\n}"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/IabHelper.java",
    "content": "/* Copyright (c) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\nimport android.app.Activity;\nimport android.app.PendingIntent;\nimport android.content.ComponentName;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentSender.SendIntentException;\nimport android.content.ServiceConnection;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.IBinder;\nimport android.os.RemoteException;\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.android.vending.billing.IInAppBillingService;\n\nimport org.json.JSONException;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\n/**\n * Provides convenience methods for in-app billing. You can create one instance of this\n * class for your application and use it to process in-app billing operations.\n * It provides synchronous (blocking) and asynchronous (non-blocking) methods for\n * many common in-app billing operations, as well as automatic signature\n * verification.\n *\n * After instantiating, you must perform setup in order to start using the object.\n * To perform setup, call the {@link #startSetup} method and provide a listener;\n * that listener will be notified when setup is complete, after which (and not before)\n * you may call other methods.\n *\n * After setup is complete, you will typically want to request an inventory of owned\n * items and subscriptions. See {@link #queryInventory}, {@link #queryInventoryAsync}\n * and related methods.\n *\n * When you are done with this object, don't forget to call {@link #dispose}\n * to ensure proper cleanup. This object holds a binding to the in-app billing\n * service, which will leak unless you dispose of it correctly. If you created\n * the object on an Activity's onCreate method, then the recommended\n * place to dispose of it is the Activity's onDestroy method.\n *\n * A note about threading: When using this object from a background thread, you may\n * call the blocking versions of methods; when using from a UI thread, call\n * only the asynchronous versions and handle the results via callbacks.\n * Also, notice that you can only call one asynchronous operation at a time;\n * attempting to start a second asynchronous operation while the first one\n * has not yet completed will result in an exception being thrown.\n *\n * @author Bruno Oliveira (Google)\n *\n */\npublic class IabHelper {\n    // Is debug logging enabled?\n    boolean mDebugLog = false;\n    String mDebugTag = \"IabHelper\";\n\n    // Is setup done?\n    boolean mSetupDone = false;\n\n    // Has this object been disposed of? (If so, we should ignore callbacks, etc)\n    boolean mDisposed = false;\n\n    // Are subscriptions supported?\n    boolean mSubscriptionsSupported = false;\n\n    // Is an asynchronous operation in progress?\n    // (only one at a time can be in progress)\n    boolean mAsyncInProgress = false;\n\n    // (for logging/debugging)\n    // if mAsyncInProgress == true, what asynchronous operation is in progress?\n    String mAsyncOperation = \"\";\n\n    // Context we were passed during initialization\n    Context mContext;\n\n    // Connection to the service\n    IInAppBillingService mService;\n    ServiceConnection mServiceConn;\n\n    // The request code used to launch purchase flow\n    int mRequestCode;\n\n    // The item type of the current purchase flow\n    String mPurchasingItemType;\n\n    // Public key for verifying signature, in base64 encoding\n    String mSignatureBase64 = null;\n\n    // Billing response codes\n    public static final int BILLING_RESPONSE_RESULT_OK = 0;\n    public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1;\n    public static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3;\n    public static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE = 4;\n    public static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5;\n    public static final int BILLING_RESPONSE_RESULT_ERROR = 6;\n    public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;\n    public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;\n\n    // IAB Helper error codes\n    public static final int IABHELPER_ERROR_BASE = -1000;\n    public static final int IABHELPER_REMOTE_EXCEPTION = -1001;\n    public static final int IABHELPER_BAD_RESPONSE = -1002;\n    public static final int IABHELPER_VERIFICATION_FAILED = -1003;\n    public static final int IABHELPER_SEND_INTENT_FAILED = -1004;\n    public static final int IABHELPER_USER_CANCELLED = -1005;\n    public static final int IABHELPER_UNKNOWN_PURCHASE_RESPONSE = -1006;\n    public static final int IABHELPER_MISSING_TOKEN = -1007;\n    public static final int IABHELPER_UNKNOWN_ERROR = -1008;\n    public static final int IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE = -1009;\n    public static final int IABHELPER_INVALID_CONSUMPTION = -1010;\n\n    // Keys for the responses from InAppBillingService\n    public static final String RESPONSE_CODE = \"RESPONSE_CODE\";\n    public static final String RESPONSE_GET_SKU_DETAILS_LIST = \"DETAILS_LIST\";\n    public static final String RESPONSE_BUY_INTENT = \"BUY_INTENT\";\n    public static final String RESPONSE_INAPP_PURCHASE_DATA = \"INAPP_PURCHASE_DATA\";\n    public static final String RESPONSE_INAPP_SIGNATURE = \"INAPP_DATA_SIGNATURE\";\n    public static final String RESPONSE_INAPP_ITEM_LIST = \"INAPP_PURCHASE_ITEM_LIST\";\n    public static final String RESPONSE_INAPP_PURCHASE_DATA_LIST = \"INAPP_PURCHASE_DATA_LIST\";\n    public static final String RESPONSE_INAPP_SIGNATURE_LIST = \"INAPP_DATA_SIGNATURE_LIST\";\n    public static final String INAPP_CONTINUATION_TOKEN = \"INAPP_CONTINUATION_TOKEN\";\n\n    // Item types\n    public static final String ITEM_TYPE_INAPP = \"inapp\";\n    public static final String ITEM_TYPE_SUBS = \"subs\";\n\n    // some fields on the getSkuDetails response bundle\n    public static final String GET_SKU_DETAILS_ITEM_LIST = \"ITEM_ID_LIST\";\n    public static final String GET_SKU_DETAILS_ITEM_TYPE_LIST = \"ITEM_TYPE_LIST\";\n\n    /**\n     * Creates an instance. After creation, it will not yet be ready to use. You must perform\n     * setup by calling {@link #startSetup} and wait for setup to complete. This constructor does not\n     * block and is safe to call from a UI thread.\n     *\n     * @param ctx Your application or Activity context. Needed to bind to the in-app billing service.\n     * @param base64PublicKey Your application's public key, encoded in base64.\n     *     This is used for verification of purchase signatures. You can find your app's base64-encoded\n     *     public key in your application's page on Google Play Developer Console. Note that this\n     *     is NOT your \"developer public key\".\n     */\n    public IabHelper(Context ctx, String base64PublicKey) {\n        mContext = ctx.getApplicationContext();\n        mSignatureBase64 = base64PublicKey;\n        logDebug(\"IAB helper created.\");\n    }\n\n    /**\n     * Enables or disable debug logging through LogCat.\n     */\n    public void enableDebugLogging(boolean enable, String tag) {\n        checkNotDisposed();\n        mDebugLog = enable;\n        mDebugTag = tag;\n    }\n\n    public void enableDebugLogging(boolean enable) {\n        checkNotDisposed();\n        mDebugLog = enable;\n    }\n\n    /**\n     * Callback for setup process. This listener's {@link #onIabSetupFinished} method is called\n     * when the setup process is complete.\n     */\n    public interface OnIabSetupFinishedListener {\n        /**\n         * Called to notify that setup is complete.\n         *\n         * @param result The result of the setup process.\n         */\n        public void onIabSetupFinished(IabResult result);\n    }\n\n    /**\n     * Starts the setup process. This will start up the setup process asynchronously.\n     * You will be notified through the listener when the setup process is complete.\n     * This method is safe to call from a UI thread.\n     *\n     * @param listener The listener to notify when the setup process is complete.\n     */\n    public void startSetup(final OnIabSetupFinishedListener listener) {\n        // If already set up, can't do it again.\n        checkNotDisposed();\n        if (mSetupDone) throw new IllegalStateException(\"IAB helper is already set up.\");\n\n        // Connection to IAB service\n        logDebug(\"Starting in-app billing setup.\");\n        mServiceConn = new ServiceConnection() {\n            @Override\n            public void onServiceDisconnected(ComponentName name) {\n                logDebug(\"Billing service disconnected.\");\n                mService = null;\n            }\n\n            @Override\n            public void onServiceConnected(ComponentName name, IBinder service) {\n                if (mDisposed) return;\n                logDebug(\"Billing service connected.\");\n                mService = IInAppBillingService.Stub.asInterface(service);\n                String packageName = mContext.getPackageName();\n                try {\n                    logDebug(\"Checking for in-app billing 3 support.\");\n\n                    // check for in-app billing v3 support\n                    int response = mService.isBillingSupported(3, packageName, ITEM_TYPE_INAPP);\n                    if (response != BILLING_RESPONSE_RESULT_OK) {\n                        if (listener != null) listener.onIabSetupFinished(new IabResult(response,\n                                \"Error checking for billing v3 support.\"));\n\n                        // if in-app purchases aren't supported, neither are subscriptions.\n                        mSubscriptionsSupported = false;\n                        return;\n                    }\n                    logDebug(\"In-app billing version 3 supported for \" + packageName);\n\n                    // check for v3 subscriptions support\n                    response = mService.isBillingSupported(3, packageName, ITEM_TYPE_SUBS);\n                    if (response == BILLING_RESPONSE_RESULT_OK) {\n                        logDebug(\"Subscriptions AVAILABLE.\");\n                        mSubscriptionsSupported = true;\n                    }\n                    else {\n                        logDebug(\"Subscriptions NOT AVAILABLE. Response: \" + response);\n                    }\n\n                    mSetupDone = true;\n                }\n                catch (RemoteException e) {\n                    if (listener != null) {\n                        listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION,\n                                                    \"RemoteException while setting up in-app billing.\"));\n                    }\n                    e.printStackTrace();\n                    return;\n                }\n\n                if (listener != null) {\n                    listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, \"Setup successful.\"));\n                }\n            }\n        };\n\n        Intent serviceIntent = new Intent(\"com.android.vending.billing.InAppBillingService.BIND\");\n        serviceIntent.setPackage(\"com.android.vending\");\n        boolean successfullyBound = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);\n\n        if (!successfullyBound) {\n            // no service available to handle that Intent\n            if (listener != null) {\n                listener.onIabSetupFinished(\n                        new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,\n                                \"Billing service unavailable on device.\"));\n            }\n        }\n       /* if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {\n            // service available to handle that Intent\n            mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);\n        }\n        else {\n            // no service available to handle that Intent\n            if (listener != null) {\n                listener.onIabSetupFinished(\n                        new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,\n                        \"Billing service unavailable on device.\"));\n            }\n        }*/\n    }\n\n    /**\n     * Dispose of object, releasing resources. It's very important to call this\n     * method when you are done with this object. It will release any resources\n     * used by it such as service connections. Naturally, once the object is\n     * disposed of, it can't be used again.\n     */\n    public void dispose() {\n        logDebug(\"Disposing.\");\n        mSetupDone = false;\n        if (mServiceConn != null) {\n            logDebug(\"Unbinding from service.\");\n            if (mContext != null) mContext.unbindService(mServiceConn);\n        }\n        mDisposed = true;\n        mContext = null;\n        mServiceConn = null;\n        mService = null;\n        mPurchaseListener = null;\n    }\n\n    private void checkNotDisposed() {\n        if (mDisposed) throw new IllegalStateException(\"IabHelper was disposed of, so it cannot be used.\");\n    }\n\n    /** Returns whether subscriptions are supported. */\n    public boolean subscriptionsSupported() {\n        checkNotDisposed();\n        return mSubscriptionsSupported;\n    }\n\n\n    /**\n     * Callback that notifies when a purchase is finished.\n     */\n    public interface OnIabPurchaseFinishedListener {\n        /**\n         * Called to notify that an in-app purchase finished. If the purchase was successful,\n         * then the sku parameter specifies which item was purchased. If the purchase failed,\n         * the sku and extraData parameters may or may not be null, depending on how far the purchase\n         * process went.\n         *\n         * @param result The result of the purchase.\n         * @param info The purchase information (null if purchase failed)\n         */\n        public void onIabPurchaseFinished(IabResult result, Purchase info);\n    }\n\n    // The listener registered on launchPurchaseFlow, which we have to call back when\n    // the purchase finishes\n    OnIabPurchaseFinishedListener mPurchaseListener;\n\n    public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {\n        launchPurchaseFlow(act, sku, requestCode, listener, \"\");\n    }\n\n    public void launchPurchaseFlow(Activity act, String sku, int requestCode,\n            OnIabPurchaseFinishedListener listener, String extraData) {\n        launchPurchaseFlow(act, sku, ITEM_TYPE_INAPP, requestCode, listener, extraData);\n    }\n\n    public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode,\n            OnIabPurchaseFinishedListener listener) {\n        launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, \"\");\n    }\n\n    public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode,\n            OnIabPurchaseFinishedListener listener, String extraData) {\n        launchPurchaseFlow(act, sku, ITEM_TYPE_SUBS, requestCode, listener, extraData);\n    }\n\n    /**\n     * Initiate the UI flow for an in-app purchase. Call this method to initiate an in-app purchase,\n     * which will involve bringing up the Google Play screen. The calling activity will be paused while\n     * the user interacts with Google Play, and the result will be delivered via the activity's\n     * {@link Activity#onActivityResult} method, at which point you must call\n     * this object's {@link #handleActivityResult} method to continue the purchase flow. This method\n     * MUST be called from the UI thread of the Activity.\n     *\n     * @param act The calling activity.\n     * @param sku The sku of the item to purchase.\n     * @param itemType indicates if it's a product or a subscription (ITEM_TYPE_INAPP or ITEM_TYPE_SUBS)\n     * @param requestCode A request code (to differentiate from other responses --\n     *     as in {@link Activity#startActivityForResult}).\n     * @param listener The listener to notify when the purchase process finishes\n     * @param extraData Extra data (developer payload), which will be returned with the purchase data\n     *     when the purchase completes. This extra data will be permanently bound to that purchase\n     *     and will always be returned when the purchase is queried.\n     */\n    public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode,\n                        OnIabPurchaseFinishedListener listener, String extraData) {\n        checkNotDisposed();\n        checkSetupDone(\"launchPurchaseFlow\");\n        flagStartAsync(\"launchPurchaseFlow\");\n        IabResult result;\n\n        if (itemType.equals(ITEM_TYPE_SUBS) && !mSubscriptionsSupported) {\n            IabResult r = new IabResult(IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE,\n                    \"Subscriptions are not available.\");\n            flagEndAsync();\n            if (listener != null) listener.onIabPurchaseFinished(r, null);\n            return;\n        }\n\n        try {\n            logDebug(\"Constructing buy intent for \" + sku + \", item type: \" + itemType);\n            Bundle buyIntentBundle = mService.getBuyIntent(3, mContext.getPackageName(), sku, itemType, extraData);\n            int response = getResponseCodeFromBundle(buyIntentBundle);\n            if (response != BILLING_RESPONSE_RESULT_OK) {\n                logError(\"Unable to buy item, Error response: \" + getResponseDesc(response));\n                flagEndAsync();\n                result = new IabResult(response, \"Unable to buy item\");\n                if (listener != null) listener.onIabPurchaseFinished(result, null);\n                return;\n            }\n\n            PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);\n            logDebug(\"Launching buy intent for \" + sku + \". Request code: \" + requestCode);\n            mRequestCode = requestCode;\n            mPurchaseListener = listener;\n            mPurchasingItemType = itemType;\n            act.startIntentSenderForResult(pendingIntent.getIntentSender(),\n                                           requestCode, new Intent(),\n                                           Integer.valueOf(0), Integer.valueOf(0),\n                                           Integer.valueOf(0));\n        }\n        catch (SendIntentException e) {\n            logError(\"SendIntentException while launching purchase flow for sku \" + sku);\n            e.printStackTrace();\n            flagEndAsync();\n\n            result = new IabResult(IABHELPER_SEND_INTENT_FAILED, \"Failed to send intent.\");\n            if (listener != null) listener.onIabPurchaseFinished(result, null);\n        }\n        catch (RemoteException e) {\n            logError(\"RemoteException while launching purchase flow for sku \" + sku);\n            e.printStackTrace();\n            flagEndAsync();\n\n            result = new IabResult(IABHELPER_REMOTE_EXCEPTION, \"Remote exception while starting purchase flow\");\n            if (listener != null) listener.onIabPurchaseFinished(result, null);\n        }\n    }\n\n    /**\n     * Handles an activity result that's part of the purchase flow in in-app billing. If you\n     * are calling {@link #launchPurchaseFlow}, then you must call this method from your\n     * Activity's {@link Activity@onActivityResult} method. This method\n     * MUST be called from the UI thread of the Activity.\n     *\n     * @param requestCode The requestCode as you received it.\n     * @param resultCode The resultCode as you received it.\n     * @param data The data (Intent) as you received it.\n     * @return Returns true if the result was related to a purchase flow and was handled;\n     *     false if the result was not related to a purchase, in which case you should\n     *     handle it normally.\n     */\n    public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {\n        IabResult result;\n        if (requestCode != mRequestCode) return false;\n\n        checkNotDisposed();\n        checkSetupDone(\"handleActivityResult\");\n\n        // end of async purchase operation that started on launchPurchaseFlow\n        flagEndAsync();\n\n        if (data == null) {\n            logError(\"Null data in IAB activity result.\");\n            result = new IabResult(IABHELPER_BAD_RESPONSE, \"Null data in IAB result\");\n            if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);\n            return true;\n        }\n\n        int responseCode = getResponseCodeFromIntent(data);\n        String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);\n        String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);\n\n        if (resultCode == Activity.RESULT_OK && responseCode == BILLING_RESPONSE_RESULT_OK) {\n            logDebug(\"Successful resultcode from purchase activity.\");\n            logDebug(\"Purchase data: \" + purchaseData);\n            logDebug(\"Data signature: \" + dataSignature);\n            logDebug(\"Extras: \" + data.getExtras());\n            logDebug(\"Expected item type: \" + mPurchasingItemType);\n\n            if (purchaseData == null || dataSignature == null) {\n                logError(\"BUG: either purchaseData or dataSignature is null.\");\n                logDebug(\"Extras: \" + data.getExtras().toString());\n                result = new IabResult(IABHELPER_UNKNOWN_ERROR, \"IAB returned null purchaseData or dataSignature\");\n                if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);\n                return true;\n            }\n\n            Purchase purchase = null;\n            try {\n                purchase = new Purchase(mPurchasingItemType, purchaseData, dataSignature);\n                String sku = purchase.getSku();\n\n                // Verify signature\n                if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) {\n                    logError(\"Purchase signature verification FAILED for sku \" + sku);\n                    result = new IabResult(IABHELPER_VERIFICATION_FAILED, \"Signature verification failed for sku \" + sku);\n                    if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, purchase);\n                    return true;\n                }\n                logDebug(\"Purchase signature successfully verified.\");\n            }\n            catch (JSONException e) {\n                logError(\"Failed to parse purchase data.\");\n                e.printStackTrace();\n                result = new IabResult(IABHELPER_BAD_RESPONSE, \"Failed to parse purchase data.\");\n                if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);\n                return true;\n            }\n\n            if (mPurchaseListener != null) {\n                mPurchaseListener.onIabPurchaseFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, \"Success\"), purchase);\n            }\n        }\n        else if (resultCode == Activity.RESULT_OK) {\n            // result code was OK, but in-app billing response was not OK.\n            logDebug(\"Result code was OK but in-app billing response was not OK: \" + getResponseDesc(responseCode));\n            if (mPurchaseListener != null) {\n                result = new IabResult(responseCode, \"Problem purchashing item.\");\n                mPurchaseListener.onIabPurchaseFinished(result, null);\n            }\n        }\n        else if (resultCode == Activity.RESULT_CANCELED) {\n            logDebug(\"Purchase canceled - Response: \" + getResponseDesc(responseCode));\n            result = new IabResult(IABHELPER_USER_CANCELLED, \"User canceled.\");\n            if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);\n        }\n        else {\n            logError(\"Purchase failed. Result code: \" + Integer.toString(resultCode)\n                    + \". Response: \" + getResponseDesc(responseCode));\n            result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, \"Unknown purchase response.\");\n            if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);\n        }\n        return true;\n    }\n\n    public Inventory queryInventory(boolean querySkuDetails, List<String> moreSkus) throws IabException {\n        return queryInventory(querySkuDetails, moreSkus, null);\n    }\n\n    /**\n     * Queries the inventory. This will query all owned items from the server, as well as\n     * information on additional skus, if specified. This method may block or take long to execute.\n     * Do not call from a UI thread. For that, use the non-blocking version {@link #refreshInventoryAsync}.\n     *\n     * @param querySkuDetails if true, SKU details (price, description, etc) will be queried as well\n     *     as purchase information.\n     * @param moreItemSkus additional PRODUCT skus to query information on, regardless of ownership.\n     *     Ignored if null or if querySkuDetails is false.\n     * @param moreSubsSkus additional SUBSCRIPTIONS skus to query information on, regardless of ownership.\n     *     Ignored if null or if querySkuDetails is false.\n     * @throws IabException if a problem occurs while refreshing the inventory.\n     */\n    public Inventory queryInventory(boolean querySkuDetails, List<String> moreItemSkus,\n                                        List<String> moreSubsSkus) throws IabException {\n        checkNotDisposed();\n        checkSetupDone(\"queryInventory\");\n        try {\n            Inventory inv = new Inventory();\n            int r = queryPurchases(inv, ITEM_TYPE_INAPP);\n            if (r != BILLING_RESPONSE_RESULT_OK) {\n                throw new IabException(r, \"Error refreshing inventory (querying owned items).\");\n            }\n\n            if (querySkuDetails) {\n                r = querySkuDetails(ITEM_TYPE_INAPP, inv, moreItemSkus);\n                if (r != BILLING_RESPONSE_RESULT_OK) {\n                    throw new IabException(r, \"Error refreshing inventory (querying prices of items).\");\n                }\n            }\n\n            // if subscriptions are supported, then also query for subscriptions\n            if (mSubscriptionsSupported) {\n                r = queryPurchases(inv, ITEM_TYPE_SUBS);\n                if (r != BILLING_RESPONSE_RESULT_OK) {\n                    throw new IabException(r, \"Error refreshing inventory (querying owned subscriptions).\");\n                }\n\n                if (querySkuDetails) {\n                    r = querySkuDetails(ITEM_TYPE_SUBS, inv, moreItemSkus);\n                    if (r != BILLING_RESPONSE_RESULT_OK) {\n                        throw new IabException(r, \"Error refreshing inventory (querying prices of subscriptions).\");\n                    }\n                }\n            }\n\n            return inv;\n        }\n        catch (RemoteException e) {\n            throw new IabException(IABHELPER_REMOTE_EXCEPTION, \"Remote exception while refreshing inventory.\", e);\n        }\n        catch (JSONException e) {\n            throw new IabException(IABHELPER_BAD_RESPONSE, \"Error parsing JSON response while refreshing inventory.\", e);\n        }\n    }\n\n    /**\n     * Listener that notifies when an inventory query operation completes.\n     */\n    public interface QueryInventoryFinishedListener {\n        /**\n         * Called to notify that an inventory query operation completed.\n         *\n         * @param result The result of the operation.\n         * @param inv The inventory.\n         */\n        public void onQueryInventoryFinished(IabResult result, Inventory inv);\n    }\n\n\n    /**\n     * Asynchronous wrapper for inventory query. This will perform an inventory\n     * query as described in {@link #queryInventory}, but will do so asynchronously\n     * and call back the specified listener upon completion. This method is safe to\n     * call from a UI thread.\n     *\n     * @param querySkuDetails as in {@link #queryInventory}\n     * @param moreSkus as in {@link #queryInventory}\n     * @param listener The listener to notify when the refresh operation completes.\n     */\n    public void queryInventoryAsync(final boolean querySkuDetails,\n                               final List<String> moreSkus,\n                               final QueryInventoryFinishedListener listener) {\n        final Handler handler = new Handler();\n        checkNotDisposed();\n        checkSetupDone(\"queryInventory\");\n        flagStartAsync(\"refresh inventory\");\n        (new Thread(new Runnable() {\n            public void run() {\n                IabResult result = new IabResult(BILLING_RESPONSE_RESULT_OK, \"Inventory refresh successful.\");\n                Inventory inv = null;\n                try {\n                    inv = queryInventory(querySkuDetails, moreSkus);\n                }\n                catch (IabException ex) {\n                    result = ex.getResult();\n                }\n\n                flagEndAsync();\n\n                final IabResult result_f = result;\n                final Inventory inv_f = inv;\n                if (!mDisposed && listener != null) {\n                    handler.post(new Runnable() {\n                        public void run() {\n                            listener.onQueryInventoryFinished(result_f, inv_f);\n                        }\n                    });\n                }\n            }\n        })).start();\n    }\n\n    public void queryInventoryAsync(QueryInventoryFinishedListener listener) {\n        queryInventoryAsync(true, null, listener);\n    }\n\n    public void queryInventoryAsync(boolean querySkuDetails, QueryInventoryFinishedListener listener) {\n        queryInventoryAsync(querySkuDetails, null, listener);\n    }\n\n\n    /**\n     * Consumes a given in-app product. Consuming can only be done on an item\n     * that's owned, and as a result of consumption, the user will no longer own it.\n     * This method may block or take long to return. Do not call from the UI thread.\n     * For that, see {@link #consumeAsync}.\n     *\n     * @param itemInfo The PurchaseInfo that represents the item to consume.\n     * @throws IabException if there is a problem during consumption.\n     */\n    void consume(Purchase itemInfo) throws IabException {\n        checkNotDisposed();\n        checkSetupDone(\"consume\");\n\n        if (!itemInfo.mItemType.equals(ITEM_TYPE_INAPP)) {\n            throw new IabException(IABHELPER_INVALID_CONSUMPTION,\n                    \"Items of type '\" + itemInfo.mItemType + \"' can't be consumed.\");\n        }\n\n        try {\n            String token = itemInfo.getToken();\n            String sku = itemInfo.getSku();\n            if (token == null || token.equals(\"\")) {\n               logError(\"Can't consume \"+ sku + \". No token.\");\n               throw new IabException(IABHELPER_MISSING_TOKEN, \"PurchaseInfo is missing token for sku: \"\n                   + sku + \" \" + itemInfo);\n            }\n\n            logDebug(\"Consuming sku: \" + sku + \", token: \" + token);\n            int response = mService.consumePurchase(3, mContext.getPackageName(), token);\n            if (response == BILLING_RESPONSE_RESULT_OK) {\n               logDebug(\"Successfully consumed sku: \" + sku);\n            }\n            else {\n               logDebug(\"Error consuming consuming sku \" + sku + \". \" + getResponseDesc(response));\n               throw new IabException(response, \"Error consuming sku \" + sku);\n            }\n        }\n        catch (RemoteException e) {\n            throw new IabException(IABHELPER_REMOTE_EXCEPTION, \"Remote exception while consuming. PurchaseInfo: \" + itemInfo, e);\n        }\n    }\n\n    /**\n     * Callback that notifies when a consumption operation finishes.\n     */\n    public interface OnConsumeFinishedListener {\n        /**\n         * Called to notify that a consumption has finished.\n         *\n         * @param purchase The purchase that was (or was to be) consumed.\n         * @param result The result of the consumption operation.\n         */\n        public void onConsumeFinished(Purchase purchase, IabResult result);\n    }\n\n    /**\n     * Callback that notifies when a multi-item consumption operation finishes.\n     */\n    public interface OnConsumeMultiFinishedListener {\n        /**\n         * Called to notify that a consumption of multiple items has finished.\n         *\n         * @param purchases The purchases that were (or were to be) consumed.\n         * @param results The results of each consumption operation, corresponding to each\n         *     sku.\n         */\n        public void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results);\n    }\n\n    /**\n     * Asynchronous wrapper to item consumption. Works like {@link #consume}, but\n     * performs the consumption in the background and notifies completion through\n     * the provided listener. This method is safe to call from a UI thread.\n     *\n     * @param purchase The purchase to be consumed.\n     * @param listener The listener to notify when the consumption operation finishes.\n     */\n    public void consumeAsync(Purchase purchase, OnConsumeFinishedListener listener) {\n        checkNotDisposed();\n        checkSetupDone(\"consume\");\n        List<Purchase> purchases = new ArrayList<Purchase>();\n        purchases.add(purchase);\n        consumeAsyncInternal(purchases, listener, null);\n    }\n\n    /**\n     * Same as {@link consumeAsync}, but for multiple items at once.\n     * @param purchases The list of PurchaseInfo objects representing the purchases to consume.\n     * @param listener The listener to notify when the consumption operation finishes.\n     */\n    public void consumeAsync(List<Purchase> purchases, OnConsumeMultiFinishedListener listener) {\n        checkNotDisposed();\n        checkSetupDone(\"consume\");\n        consumeAsyncInternal(purchases, null, listener);\n    }\n\n    /**\n     * Returns a human-readable description for the given response code.\n     *\n     * @param code The response code\n     * @return A human-readable string explaining the result code.\n     *     It also includes the result code numerically.\n     */\n    public static String getResponseDesc(int code) {\n        String[] iab_msgs = (\"0:OK/1:User Canceled/2:Unknown/\" +\n                \"3:Billing Unavailable/4:Item unavailable/\" +\n                \"5:Developer Error/6:Error/7:Item Already Owned/\" +\n                \"8:Item not owned\").split(\"/\");\n        String[] iabhelper_msgs = (\"0:OK/-1001:Remote exception during initialization/\" +\n                                   \"-1002:Bad response received/\" +\n                                   \"-1003:Purchase signature verification failed/\" +\n                                   \"-1004:Send intent failed/\" +\n                                   \"-1005:User cancelled/\" +\n                                   \"-1006:Unknown purchase response/\" +\n                                   \"-1007:Missing token/\" +\n                                   \"-1008:Unknown error/\" +\n                                   \"-1009:Subscriptions not available/\" +\n                                   \"-1010:Invalid consumption attempt\").split(\"/\");\n\n        if (code <= IABHELPER_ERROR_BASE) {\n            int index = IABHELPER_ERROR_BASE - code;\n            if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index];\n            else return String.valueOf(code) + \":Unknown IAB Helper Error\";\n        }\n        else if (code < 0 || code >= iab_msgs.length)\n            return String.valueOf(code) + \":Unknown\";\n        else\n            return iab_msgs[code];\n    }\n\n\n    // Checks that setup was done; if not, throws an exception.\n    void checkSetupDone(String operation) {\n        if (!mSetupDone) {\n            logError(\"Illegal state for operation (\" + operation + \"): IAB helper is not set up.\");\n            throw new IllegalStateException(\"IAB helper is not set up. Can't perform operation: \" + operation);\n        }\n    }\n\n    // Workaround to bug where sometimes response codes come as Long instead of Integer\n    int getResponseCodeFromBundle(Bundle b) {\n        Object o = b.get(RESPONSE_CODE);\n        if (o == null) {\n            logDebug(\"Bundle with null response code, assuming OK (known issue)\");\n            return BILLING_RESPONSE_RESULT_OK;\n        }\n        else if (o instanceof Integer) return ((Integer)o).intValue();\n        else if (o instanceof Long) return (int)((Long)o).longValue();\n        else {\n            logError(\"Unexpected type for bundle response code.\");\n            logError(o.getClass().getName());\n            throw new RuntimeException(\"Unexpected type for bundle response code: \" + o.getClass().getName());\n        }\n    }\n\n    // Workaround to bug where sometimes response codes come as Long instead of Integer\n    int getResponseCodeFromIntent(Intent i) {\n        Object o = i.getExtras().get(RESPONSE_CODE);\n        if (o == null) {\n            logError(\"Intent with no response code, assuming OK (known issue)\");\n            return BILLING_RESPONSE_RESULT_OK;\n        }\n        else if (o instanceof Integer) return ((Integer)o).intValue();\n        else if (o instanceof Long) return (int)((Long)o).longValue();\n        else {\n            logError(\"Unexpected type for intent response code.\");\n            logError(o.getClass().getName());\n            throw new RuntimeException(\"Unexpected type for intent response code: \" + o.getClass().getName());\n        }\n    }\n\n    void flagStartAsync(String operation) {\n        if (mAsyncInProgress) throw new IllegalStateException(\"Can't start async operation (\" +\n                operation + \") because another async operation(\" + mAsyncOperation + \") is in progress.\");\n        mAsyncOperation = operation;\n        mAsyncInProgress = true;\n        logDebug(\"Starting async operation: \" + operation);\n    }\n\n    public void flagEndAsync() {\n        logDebug(\"Ending async operation: \" + mAsyncOperation);\n        mAsyncOperation = \"\";\n        mAsyncInProgress = false;\n    }\n\n\n    int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException {\n        // Query purchases\n\n        if (mService == null || mContext == null) {\n            logError(\"Our service and/or our context are null.  Exiting.\");\n            return IABHELPER_UNKNOWN_ERROR;\n        }\n\n        logDebug(\"Querying owned items, item type: \" + itemType);\n        logDebug(\"Package name: \" + mContext.getPackageName());\n        boolean verificationFailed = false;\n        String continueToken = null;\n\n        do {\n            logDebug(\"Calling getPurchases with continuation token: \" + continueToken);\n            Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(),\n                    itemType, continueToken);\n\n            int response = getResponseCodeFromBundle(ownedItems);\n            logDebug(\"Owned items response: \" + String.valueOf(response));\n            if (response != BILLING_RESPONSE_RESULT_OK) {\n                logDebug(\"getPurchases() failed: \" + getResponseDesc(response));\n                return response;\n            }\n            if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST)\n                    || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST)\n                    || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) {\n                logError(\"Bundle returned from getPurchases() doesn't contain required fields.\");\n                return IABHELPER_BAD_RESPONSE;\n            }\n\n            ArrayList<String> ownedSkus = ownedItems.getStringArrayList(\n                        RESPONSE_INAPP_ITEM_LIST);\n            ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(\n                        RESPONSE_INAPP_PURCHASE_DATA_LIST);\n            ArrayList<String> signatureList = ownedItems.getStringArrayList(\n                        RESPONSE_INAPP_SIGNATURE_LIST);\n\n            for (int i = 0; i < purchaseDataList.size(); ++i) {\n                String purchaseData = purchaseDataList.get(i);\n                String signature = signatureList.get(i);\n                String sku = ownedSkus.get(i);\n                if (Security.verifyPurchase(mSignatureBase64, purchaseData, signature)) {\n                    logDebug(\"Sku is owned: \" + sku);\n                    Purchase purchase = new Purchase(itemType, purchaseData, signature);\n\n                    if (TextUtils.isEmpty(purchase.getToken())) {\n                        logWarn(\"BUG: empty/null token!\");\n                        logDebug(\"Purchase data: \" + purchaseData);\n                    }\n\n                    // Record ownership and token\n                    inv.addPurchase(purchase);\n                }\n                else {\n                    logWarn(\"Purchase signature verification **FAILED**. Not adding item.\");\n                    logDebug(\"   Purchase data: \" + purchaseData);\n                    logDebug(\"   Signature: \" + signature);\n                    verificationFailed = true;\n                }\n            }\n\n            continueToken = ownedItems.getString(INAPP_CONTINUATION_TOKEN);\n            logDebug(\"Continuation token: \" + continueToken);\n        } while (!TextUtils.isEmpty(continueToken));\n\n        return verificationFailed ? IABHELPER_VERIFICATION_FAILED : BILLING_RESPONSE_RESULT_OK;\n    }\n\n    int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus)\n                                throws RemoteException, JSONException {\n        logDebug(\"Querying SKU details.\");\n        ArrayList<String> skuList = new ArrayList<String>();\n        skuList.addAll(inv.getAllOwnedSkus(itemType));\n        if (moreSkus != null) {\n            for (String sku : moreSkus) {\n                if (!skuList.contains(sku)) {\n                    skuList.add(sku);\n                }\n            }\n        }\n\n        if (skuList.size() == 0) {\n            logDebug(\"queryPrices: nothing to do because there are no SKUs.\");\n            return BILLING_RESPONSE_RESULT_OK;\n        }\n\n        Bundle querySkus = new Bundle();\n        querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skuList);\n        Bundle skuDetails = mService.getSkuDetails(3, mContext.getPackageName(),\n                itemType, querySkus);\n\n        if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {\n            int response = getResponseCodeFromBundle(skuDetails);\n            if (response != BILLING_RESPONSE_RESULT_OK) {\n                logDebug(\"getSkuDetails() failed: \" + getResponseDesc(response));\n                return response;\n            }\n            else {\n                logError(\"getSkuDetails() returned a bundle with neither an error nor a detail list.\");\n                return IABHELPER_BAD_RESPONSE;\n            }\n        }\n\n        ArrayList<String> responseList = skuDetails.getStringArrayList(\n                RESPONSE_GET_SKU_DETAILS_LIST);\n\n        for (String thisResponse : responseList) {\n            SkuDetails d = new SkuDetails(itemType, thisResponse);\n            logDebug(\"Got sku details: \" + d);\n            inv.addSkuDetails(d);\n        }\n        return BILLING_RESPONSE_RESULT_OK;\n    }\n\n\n    void consumeAsyncInternal(final List<Purchase> purchases,\n                              final OnConsumeFinishedListener singleListener,\n                              final OnConsumeMultiFinishedListener multiListener) {\n        final Handler handler = new Handler();\n        flagStartAsync(\"consume\");\n        (new Thread(new Runnable() {\n            public void run() {\n                final List<IabResult> results = new ArrayList<IabResult>();\n                for (Purchase purchase : purchases) {\n                    try {\n                        consume(purchase);\n                        results.add(new IabResult(BILLING_RESPONSE_RESULT_OK, \"Successful consume of sku \" + purchase.getSku()));\n                    }\n                    catch (IabException ex) {\n                        results.add(ex.getResult());\n                    }\n                }\n\n                flagEndAsync();\n                if (!mDisposed && singleListener != null) {\n                    handler.post(new Runnable() {\n                        public void run() {\n                            singleListener.onConsumeFinished(purchases.get(0), results.get(0));\n                        }\n                    });\n                }\n                if (!mDisposed && multiListener != null) {\n                    handler.post(new Runnable() {\n                        public void run() {\n                            multiListener.onConsumeMultiFinished(purchases, results);\n                        }\n                    });\n                }\n            }\n        })).start();\n    }\n\n    void logDebug(String msg) {\n        if (mDebugLog) Log.d(mDebugTag, msg);\n    }\n\n    void logError(String msg) {\n        Log.e(mDebugTag, \"In-app billing error: \" + msg);\n    }\n\n    void logWarn(String msg) {\n        Log.w(mDebugTag, \"In-app billing warning: \" + msg);\n    }\n\n    public boolean isAsyncInProgress(){\n        return mAsyncInProgress;\n    }\n    public boolean isSetupDone (){\n        return mSetupDone;\n    }\n    public boolean isDisposed (){\n        return mDisposed;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/IabResult.java",
    "content": "/* Copyright (c) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\n/**\n * Represents the result of an in-app billing operation.\n * A result is composed of a response code (an integer) and possibly a\n * message (String). You can get those by calling\n * {@link #getResponse} and {@link #getMessage()}, respectively. You\n * can also inquire whether a result is a success or a failure by\n * calling {@link #isSuccess()} and {@link #isFailure()}.\n */\npublic class IabResult {\n    int mResponse;\n    String mMessage;\n\n    public IabResult(int response, String message) {\n        mResponse = response;\n        if (message == null || message.trim().length() == 0) {\n            mMessage = IabHelper.getResponseDesc(response);\n        }\n        else {\n            mMessage = message + \" (response: \" + IabHelper.getResponseDesc(response) + \")\";\n        }\n    }\n    public int getResponse() { return mResponse; }\n    public String getMessage() { return mMessage; }\n    public boolean isSuccess() { return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK; }\n    public boolean isFailure() { return !isSuccess(); }\n    public String toString() { return \"IabResult: \" + getMessage(); }\n}\n\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/Inventory.java",
    "content": "/* Copyright (c) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Represents a block of information about in-app items.\n * An Inventory is returned by such methods as {@link IabHelper#queryInventory}.\n */\npublic class Inventory {\n    Map<String,SkuDetails> mSkuMap = new HashMap<String,SkuDetails>();\n    Map<String,Purchase> mPurchaseMap = new HashMap<String,Purchase>();\n\n    Inventory() { }\n\n    /** Returns the listing details for an in-app product. */\n    public SkuDetails getSkuDetails(String sku) {\n        return mSkuMap.get(sku);\n    }\n\n    /** Returns purchase information for a given product, or null if there is no purchase. */\n    public Purchase getPurchase(String sku) {\n        return mPurchaseMap.get(sku);\n    }\n\n    /** Returns whether or not there exists a purchase of the given product. */\n    public boolean hasPurchase(String sku) {\n        return mPurchaseMap.containsKey(sku);\n    }\n\n    /** Return whether or not details about the given product are available. */\n    public boolean hasDetails(String sku) {\n        return mSkuMap.containsKey(sku);\n    }\n\n    /**\n     * Erase a purchase (locally) from the inventory, given its product ID. This just\n     * modifies the Inventory object locally and has no effect on the server! This is\n     * useful when you have an existing Inventory object which you know to be up to date,\n     * and you have just consumed an item successfully, which means that erasing its\n     * purchase data from the Inventory you already have is quicker than querying for\n     * a new Inventory.\n     */\n    public void erasePurchase(String sku) {\n        if (mPurchaseMap.containsKey(sku)) mPurchaseMap.remove(sku);\n    }\n\n    /** Returns a list of all owned product IDs. */\n    List<String> getAllOwnedSkus() {\n        return new ArrayList<String>(mPurchaseMap.keySet());\n    }\n\n    /** Returns a list of all owned product IDs of a given type */\n    List<String> getAllOwnedSkus(String itemType) {\n        List<String> result = new ArrayList<String>();\n        for (Purchase p : mPurchaseMap.values()) {\n            if (p.getItemType().equals(itemType)) result.add(p.getSku());\n        }\n        return result;\n    }\n\n    /** Returns a list of all purchases. */\n    List<Purchase> getAllPurchases() {\n        return new ArrayList<Purchase>(mPurchaseMap.values());\n    }\n\n    void addSkuDetails(SkuDetails d) {\n        mSkuMap.put(d.getSku(), d);\n    }\n\n    void addPurchase(Purchase p) {\n        mPurchaseMap.put(p.getSku(), p);\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/Purchase.java",
    "content": "/* Copyright (c) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n/**\n * Represents an in-app billing purchase.\n */\npublic class Purchase {\n    String mItemType;  // ITEM_TYPE_INAPP or ITEM_TYPE_SUBS\n    String mOrderId;\n    String mPackageName;\n    String mSku;\n    long mPurchaseTime;\n    int mPurchaseState;\n    String mDeveloperPayload;\n    String mToken;\n    String mOriginalJson;\n    String mSignature;\n\n    public Purchase(String itemType, String jsonPurchaseInfo, String signature) throws JSONException {\n        mItemType = itemType;\n        mOriginalJson = jsonPurchaseInfo;\n        JSONObject o = new JSONObject(mOriginalJson);\n        mOrderId = o.optString(\"orderId\");\n        mPackageName = o.optString(\"packageName\");\n        mSku = o.optString(\"productId\");\n        mPurchaseTime = o.optLong(\"purchaseTime\");\n        mPurchaseState = o.optInt(\"purchaseState\");\n        mDeveloperPayload = o.optString(\"developerPayload\");\n        mToken = o.optString(\"token\", o.optString(\"purchaseToken\"));\n        mSignature = signature;\n    }\n\n    public String getItemType() { return mItemType; }\n    public String getOrderId() { return mOrderId; }\n    public String getPackageName() { return mPackageName; }\n    public String getSku() { return mSku; }\n    public long getPurchaseTime() { return mPurchaseTime; }\n    public int getPurchaseState() { return mPurchaseState; }\n    public String getDeveloperPayload() { return mDeveloperPayload; }\n    public String getToken() { return mToken; }\n    public String getOriginalJson() { return mOriginalJson; }\n    public String getSignature() { return mSignature; }\n\n    @Override\n    public String toString() { return \"PurchaseInfo(type:\" + mItemType + \"):\" + mOriginalJson; }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/Security.java",
    "content": "/* Copyright (c) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\n\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.vasilkoff.easyvpnfree.BuildConfig;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n\nimport java.security.InvalidKeyException;\nimport java.security.KeyFactory;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.PublicKey;\nimport java.security.Signature;\nimport java.security.SignatureException;\nimport java.security.spec.InvalidKeySpecException;\nimport java.security.spec.X509EncodedKeySpec;\n\n/**\n * Security-related methods. For a secure implementation, all of this code\n * should be implemented on a server that communicates with the\n * application on the device. For the sake of simplicity and clarity of this\n * example, this code is included here and is executed on the device. If you\n * must verify the purchases on the phone, you should obfuscate this code to\n * make it harder for an attacker to replace the code with stubs that treat all\n * purchases as verified.\n */\npublic class Security {\n    private static final String TAG = \"IABUtil/Security\";\n\n    private static final String KEY_FACTORY_ALGORITHM = \"RSA\";\n    private static final String SIGNATURE_ALGORITHM = \"SHA1withRSA\";\n\n    /**\n     * Verifies that the data was signed with the given signature, and returns\n     * the verified purchase. The data is in JSON format and signed\n     * with a private key. The data also contains the {@link PurchaseState}\n     * and product ID of the purchase.\n     * @param base64PublicKey the base64-encoded public key to use for verifying.\n     * @param signedData the signed JSON string (signed, not encrypted)\n     * @param signature the signature for the data, signed with the private key\n     */\n    public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {\n        if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) ||\n                TextUtils.isEmpty(signature)) {\n            Log.e(TAG, \"Purchase verification failed: missing data.\");\n            if (BuildConfig.DEBUG)\n                return true;\n\n           return false;\n        }\n\n        PublicKey key = Security.generatePublicKey(base64PublicKey);\n        return Security.verify(key, signedData, signature);\n    }\n\n    /**\n     * Generates a PublicKey instance from a string containing the\n     * Base64-encoded public key.\n     *\n     * @param encodedPublicKey Base64-encoded public key\n     * @throws IllegalArgumentException if encodedPublicKey is invalid\n     */\n    public static PublicKey generatePublicKey(String encodedPublicKey) {\n        try {\n            byte[] decodedKey = Base64.decode(encodedPublicKey);\n            KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);\n            return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));\n        } catch (NoSuchAlgorithmException e) {\n            throw new RuntimeException(e);\n        } catch (InvalidKeySpecException e) {\n            Log.e(TAG, \"Invalid key specification.\");\n            throw new IllegalArgumentException(e);\n        } catch (Base64DecoderException e) {\n            Log.e(TAG, \"Base64 decoding failed.\");\n            throw new IllegalArgumentException(e);\n        }\n    }\n\n    /**\n     * Verifies that the signature from the server matches the computed\n     * signature on the data.  Returns true if the data is correctly signed.\n     *\n     * @param publicKey public key associated with the developer account\n     * @param signedData signed data from server\n     * @param signature server signature\n     * @return true if the data and signature match\n     */\n    public static boolean verify(PublicKey publicKey, String signedData, String signature) {\n        Signature sig;\n        try {\n            sig = Signature.getInstance(SIGNATURE_ALGORITHM);\n            sig.initVerify(publicKey);\n            sig.update(signedData.getBytes());\n            if (!sig.verify(Base64.decode(signature))) {\n                Log.e(TAG, \"Signature verification failed.\");\n                return false;\n            }\n            return true;\n        } catch (NoSuchAlgorithmException e) {\n            Log.e(TAG, \"NoSuchAlgorithmException.\");\n        } catch (InvalidKeyException e) {\n            Log.e(TAG, \"Invalid key specification.\");\n        } catch (SignatureException e) {\n            Log.e(TAG, \"Signature exception.\");\n        } catch (Base64DecoderException e) {\n            Log.e(TAG, \"Base64 decoding failed.\");\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/iap/SkuDetails.java",
    "content": "/* Copyright (c) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.vasilkoff.easyvpnfree.util.iap;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\n/**\n * Represents an in-app product's listing details.\n */\npublic class SkuDetails {\n    String mItemType;\n    String mSku;\n    String mType;\n    String mPrice;\n    String mTitle;\n    String mDescription;\n    String mJson;\n\n    public SkuDetails(String jsonSkuDetails) throws JSONException {\n        this(IabHelper.ITEM_TYPE_INAPP, jsonSkuDetails);\n    }\n\n    public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException {\n        mItemType = itemType;\n        mJson = jsonSkuDetails;\n        JSONObject o = new JSONObject(mJson);\n        mSku = o.optString(\"productId\");\n        mType = o.optString(\"type\");\n        mPrice = o.optString(\"price\");\n        mTitle = o.optString(\"title\");\n        mDescription = o.optString(\"description\");\n    }\n\n    public String getSku() { return mSku; }\n    public String getType() { return mType; }\n    public String getPrice() { return mPrice; }\n    public String getTitle() { return mTitle; }\n    public String getDescription() { return mDescription; }\n\n    @Override\n    public String toString() {\n        return \"SkuDetails:\" + mJson;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/map/MapCreator.java",
    "content": "package com.vasilkoff.easyvpnfree.util.map;\n\nimport android.content.Context;\nimport android.support.v4.content.ContextCompat;\n\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.util.LoadData;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.mapsforge.core.graphics.Color;\nimport org.mapsforge.core.graphics.Paint;\nimport org.mapsforge.core.graphics.Style;\nimport org.mapsforge.core.model.LatLong;\nimport org.mapsforge.map.android.graphics.AndroidGraphicFactory;\nimport org.mapsforge.map.layer.Layers;\nimport org.mapsforge.map.layer.overlay.Polygon;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.List;\n\n/**\n * Created by Kusenko on 04.11.2016.\n */\n\npublic class MapCreator {\n\n    private Paint paintFill;\n    private Paint paintStroke;\n    private Layers layers;\n    private Context context;\n\n    public MapCreator(Context context, Layers layers) {\n        this.context = context;\n        this.layers = layers;\n\n        paintFill = AndroidGraphicFactory.INSTANCE.createPaint();\n        paintFill.setColor(ContextCompat.getColor(context,R.color.mapFill));\n        paintFill.setStyle(Style.FILL);\n\n        paintStroke = AndroidGraphicFactory.INSTANCE.createPaint();\n        paintStroke.setStrokeWidth(1);\n        paintStroke.setColor(ContextCompat.getColor(context,R.color.mapStroke));\n        paintStroke.setStyle(Style.STROKE);\n    }\n\n    public void parseGeoJson(String nameFile) {\n        String jsonString = null;\n\n        jsonString = LoadData.fromFile(nameFile, context);\n\n        if (jsonString != null)\n            parseData(jsonString);\n    }\n\n    private void parseData(String jsonString) {\n        try {\n            JSONObject dataJsonObj = new JSONObject(jsonString);\n            JSONArray features = dataJsonObj.getJSONArray(\"features\");\n            for (int i = 0; i < features.length(); i++) {\n                JSONObject feature = new JSONObject(features.get(i).toString());\n                JSONObject geometry = feature.getJSONObject(\"geometry\");\n                JSONArray coordinates = geometry.getJSONArray(\"coordinates\");\n\n                if (geometry.get(\"type\").equals(\"Polygon\")) {\n                    createPolygons(new JSONArray(coordinates.get(0).toString()));\n                } else {\n                    for (int j = 0; j < coordinates.length(); j++) {\n                        JSONArray coordinate = new JSONArray(coordinates.get(j).toString());\n                        createPolygons(new JSONArray(coordinate.get(0).toString()));\n                    }\n                }\n            }\n\n        } catch (JSONException e) {\n            e.printStackTrace();\n        }\n    }\n\n    private void createPolygons(JSONArray coordinates) {\n        Polygon polygon = new Polygon(paintFill, paintStroke,\n                AndroidGraphicFactory.INSTANCE);\n\n        List<LatLong> polygonList = polygon.getLatLongs();\n\n        for (int j = 0; j < coordinates.length(); j++) {\n            try {\n                JSONArray arrLatLong = new JSONArray(coordinates.get(j).toString());\n                polygonList.add(new LatLong(arrLatLong.getDouble(1), arrLatLong.getDouble(0)));\n            } catch (JSONException e) {\n                e.printStackTrace();\n            }\n        }\n\n        layers.add(polygon);\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/com/vasilkoff/easyvpnfree/util/map/MyMarker.java",
    "content": "package com.vasilkoff.easyvpnfree.util.map;\n\nimport org.mapsforge.core.graphics.Bitmap;\nimport org.mapsforge.core.model.LatLong;\nimport org.mapsforge.map.layer.overlay.Marker;\n\n/**\n * Created by Kusenko on 04.11.2016.\n */\n\npublic class MyMarker extends Marker {\n\n    private Object relationObject;\n    /**\n     * @param latLong          the initial geographical coordinates of this marker (may be null).\n     * @param bitmap           the initial {@code Bitmap} of this marker (may be null).\n     * @param horizontalOffset the horizontal marker offset.\n     * @param verticalOffset   the vertical marker offset.\n     */\n    public MyMarker(LatLong latLong, Bitmap bitmap, int horizontalOffset, int verticalOffset, Object relationObject) {\n        super(latLong, bitmap, horizontalOffset, verticalOffset);\n        this.relationObject = relationObject;\n    }\n\n    public Object getRelationObject() {\n        return relationObject;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/VpnProfile.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.SharedPreferences;\nimport android.content.pm.ApplicationInfo;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.os.Build;\nimport android.preference.PreferenceManager;\nimport android.security.KeyChain;\nimport android.security.KeyChainException;\nimport android.support.annotation.NonNull;\nimport android.text.TextUtils;\nimport android.util.Base64;\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport org.spongycastle.util.io.pem.PemObject;\nimport org.spongycastle.util.io.pem.PemWriter;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.Serializable;\nimport java.io.StringWriter;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.security.InvalidKeyException;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.PrivateKey;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateException;\nimport java.security.cert.X509Certificate;\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.Locale;\nimport java.util.UUID;\nimport java.util.Vector;\n\nimport javax.crypto.BadPaddingException;\nimport javax.crypto.Cipher;\nimport javax.crypto.IllegalBlockSizeException;\nimport javax.crypto.NoSuchPaddingException;\n\nimport de.blinkt.openvpn.core.Connection;\nimport de.blinkt.openvpn.core.NativeUtils;\nimport de.blinkt.openvpn.core.OpenVPNService;\nimport de.blinkt.openvpn.core.VPNLaunchHelper;\nimport de.blinkt.openvpn.core.VpnStatus;\nimport de.blinkt.openvpn.core.X509Utils;\n\npublic class VpnProfile implements Serializable, Cloneable {\n    // Note that this class cannot be moved to core where it belongs since\n    // the profile loading depends on it being here\n    // The Serializable documentation mentions that class name change are possible\n    // but the how is unclear\n    //\n    transient public static final long MAX_EMBED_FILE_SIZE = 2048 * 1024; // 2048kB\n    // Don't change this, not all parts of the program use this constant\n    public static final String EXTRA_PROFILEUUID = \"de.blinkt.openvpn.profileUUID\";\n    public static final String INLINE_TAG = \"[[INLINE]]\";\n    public static final String DISPLAYNAME_TAG = \"[[NAME]]\";\n\n    private static final long serialVersionUID = 7085688938959334563L;\n    public static final int MAXLOGLEVEL = 4;\n    public static final int CURRENT_PROFILE_VERSION = 6;\n    public static final int DEFAULT_MSSFIX_SIZE = 1280;\n    public static String DEFAULT_DNS1 = \"8.8.8.8\";\n    public static String DEFAULT_DNS2 = \"8.8.4.4\";\n\n    public transient String mTransientPW = null;\n    public transient String mTransientPCKS12PW = null;\n\n\n    public static final int TYPE_CERTIFICATES = 0;\n    public static final int TYPE_PKCS12 = 1;\n    public static final int TYPE_KEYSTORE = 2;\n    public static final int TYPE_USERPASS = 3;\n    public static final int TYPE_STATICKEYS = 4;\n    public static final int TYPE_USERPASS_CERTIFICATES = 5;\n    public static final int TYPE_USERPASS_PKCS12 = 6;\n    public static final int TYPE_USERPASS_KEYSTORE = 7;\n    public static final int X509_VERIFY_TLSREMOTE = 0;\n    public static final int X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING = 1;\n    public static final int X509_VERIFY_TLSREMOTE_DN = 2;\n    public static final int X509_VERIFY_TLSREMOTE_RDN = 3;\n    public static final int X509_VERIFY_TLSREMOTE_RDN_PREFIX = 4;\n    // variable named wrong and should haven beeen transient\n    // but needs to keep wrong name to guarante loading of old\n    // profiles\n    public transient boolean profileDeleted = false;\n    public int mAuthenticationType = TYPE_KEYSTORE;\n    public String mName;\n    public String mAlias;\n    public String mClientCertFilename;\n    public String mTLSAuthDirection = \"\";\n    public String mTLSAuthFilename;\n    public String mClientKeyFilename;\n    public String mCaFilename;\n    public boolean mUseLzo = true;\n    public String mPKCS12Filename;\n    public String mPKCS12Password;\n    public boolean mUseTLSAuth = false;\n\n    public String mDNS1 = DEFAULT_DNS1;\n    public String mDNS2 = DEFAULT_DNS2;\n    public String mIPv4Address;\n    public String mIPv6Address;\n    public boolean mOverrideDNS = false;\n    public String mSearchDomain = \"blinkt.de\";\n    public boolean mUseDefaultRoute = true;\n    public boolean mUsePull = true;\n    public String mCustomRoutes;\n    public boolean mCheckRemoteCN = true;\n    public boolean mExpectTLSCert = false;\n    public String mRemoteCN = \"\";\n    public String mPassword = \"\";\n    public String mUsername = \"\";\n    public boolean mRoutenopull = false;\n    public boolean mUseRandomHostname = false;\n    public boolean mUseFloat = false;\n    public boolean mUseCustomConfig = false;\n    public String mCustomConfigOptions = \"\";\n    public String mVerb = \"1\";  //ignored\n    public String mCipher = \"\";\n    public boolean mNobind = false;\n    public boolean mUseDefaultRoutev6 = true;\n    public String mCustomRoutesv6 = \"\";\n    public String mKeyPassword = \"\";\n    public boolean mPersistTun = false;\n    public String mConnectRetryMax = \"-1\";\n    public String mConnectRetry = \"2\";\n    public String mConnectRetryMaxTime = \"300\";\n    public boolean mUserEditable = true;\n    public String mAuth = \"\";\n    public int mX509AuthType = X509_VERIFY_TLSREMOTE_RDN;\n    public String mx509UsernameField = null;\n\n    private transient PrivateKey mPrivateKey;\n    // Public attributes, since I got mad with getter/setter\n    // set members to default values\n    private UUID mUuid;\n    public boolean mAllowLocalLAN;\n    private int mProfileVersion;\n    public String mExcludedRoutes;\n    public String mExcludedRoutesv6;\n    public int mMssFix = 0; // -1 is default,\n    public Connection[] mConnections = new Connection[0];\n    public boolean mRemoteRandom = false;\n    public HashSet<String> mAllowedAppsVpn = new HashSet<>();\n    public boolean mAllowedAppsVpnAreDisallowed = true;\n\n    public String mCrlFilename;\n    public String mProfileCreator;\n\n\n    public boolean mPushPeerInfo = false;\n    public static final boolean mIsOpenVPN22 = false;\n\n    /* Options no longer used in new profiles */\n    public String mServerName = \"openvpn.blinkt.de\";\n    public String mServerPort = \"1194\";\n    public boolean mUseUdp = true;\n\n    public VpnProfile(String name) {\n        mUuid = UUID.randomUUID();\n        mName = name;\n        mProfileVersion = CURRENT_PROFILE_VERSION;\n\n        mConnections = new Connection[1];\n        mConnections[0] = new Connection();\n    }\n\n    public static String openVpnEscape(String unescaped) {\n        if (unescaped == null)\n            return null;\n        String escapedString = unescaped.replace(\"\\\\\", \"\\\\\\\\\");\n        escapedString = escapedString.replace(\"\\\"\", \"\\\\\\\"\");\n        escapedString = escapedString.replace(\"\\n\", \"\\\\n\");\n\n        if (escapedString.equals(unescaped) && !escapedString.contains(\" \") &&\n                !escapedString.contains(\"#\") && !escapedString.contains(\";\")\n                && !escapedString.equals(\"\"))\n            return unescaped;\n        else\n            return '\"' + escapedString + '\"';\n    }\n\n    public void clearDefaults() {\n        mServerName = \"unknown\";\n        mUsePull = false;\n        mUseLzo = false;\n        mUseDefaultRoute = false;\n        mUseDefaultRoutev6 = false;\n        mExpectTLSCert = false;\n        mCheckRemoteCN = false;\n        mPersistTun = false;\n        mAllowLocalLAN = true;\n        mPushPeerInfo = false;\n        mMssFix = 0;\n    }\n\n    public UUID getUUID() {\n        return mUuid;\n\n    }\n\n    public String getName() {\n        if (mName == null)\n            return \"No profile name\";\n        return mName;\n    }\n\n    public void upgradeProfile() {\n        if (mProfileVersion < 2) {\n            /* default to the behaviour the OS used */\n            mAllowLocalLAN = Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT;\n        }\n\n        if (mProfileVersion < 4) {\n            moveOptionsToConnection();\n            mAllowedAppsVpnAreDisallowed = true;\n        }\n        if (mAllowedAppsVpn == null)\n            mAllowedAppsVpn = new HashSet<>();\n        if (mConnections == null)\n            mConnections = new Connection[0];\n\n        if (mProfileVersion < 6) {\n            if (TextUtils.isEmpty(mProfileCreator))\n                mUserEditable = true;\n        }\n\n\n        mProfileVersion = CURRENT_PROFILE_VERSION;\n\n    }\n\n    private void moveOptionsToConnection() {\n        mConnections = new Connection[1];\n        Connection conn = new Connection();\n\n        conn.mServerName = mServerName;\n        conn.mServerPort = mServerPort;\n        conn.mUseUdp = mUseUdp;\n        conn.mCustomConfiguration = \"\";\n\n        mConnections[0] = conn;\n\n    }\n\n    public String getConfigFile(Context context, boolean configForOvpn3) {\n\n        File cacheDir = context.getCacheDir();\n        String cfg = \"\";\n\n        // Enable management interface\n        cfg += \"# Enables connection to GUI\\n\";\n        cfg += \"management \";\n\n        cfg += cacheDir.getAbsolutePath() + \"/\" + \"mgmtsocket\";\n        cfg += \" unix\\n\";\n        cfg += \"management-client\\n\";\n        // Not needed, see updated man page in 2.3\n        //cfg += \"management-signal\\n\";\n        cfg += \"management-query-passwords\\n\";\n        cfg += \"management-hold\\n\\n\";\n\n        if (!configForOvpn3) {\n            cfg += String.format(\"setenv IV_GUI_VER %s \\n\", openVpnEscape(getVersionEnvString(context)));\n            String versionString = String.format(Locale.US, \"%d %s %s %s %s %s\", Build.VERSION.SDK_INT, Build.VERSION.RELEASE,\n                    NativeUtils.getNativeAPI(), Build.BRAND, Build.BOARD, Build.MODEL);\n            cfg += String.format(\"setenv IV_PLAT_VER %s\\n\", openVpnEscape(versionString));\n        }\n\n        cfg += \"machine-readable-output\\n\";\n\n        // Users are confused by warnings that are misleading...\n        cfg += \"ifconfig-nowarn\\n\";\n\n\n        boolean useTLSClient = (mAuthenticationType != TYPE_STATICKEYS);\n\n        if (useTLSClient && mUsePull)\n            cfg += \"client\\n\";\n        else if (mUsePull)\n            cfg += \"pull\\n\";\n        else if (useTLSClient)\n            cfg += \"tls-client\\n\";\n\n\n        //cfg += \"verb \" + mVerb + \"\\n\";\n        cfg += \"verb \" + MAXLOGLEVEL + \"\\n\";\n\n        if (mConnectRetryMax == null) {\n            mConnectRetryMax = \"-1\";\n        }\n\n        if (!mConnectRetryMax.equals(\"-1\"))\n            cfg += \"connect-retry-max \" + mConnectRetryMax + \"\\n\";\n\n        if (TextUtils.isEmpty(mConnectRetry))\n            mConnectRetry = \"2\";\n\n        if (TextUtils.isEmpty(mConnectRetryMaxTime))\n            mConnectRetryMaxTime=\"300\";\n\n\n        if (!mIsOpenVPN22)\n            cfg += \"connect-retry \" + mConnectRetry + \" \" + mConnectRetryMaxTime + \"\\n\";\n        else if (mIsOpenVPN22 && mUseUdp)\n            cfg += \"connect-retry \" + mConnectRetry + \"\\n\";\n\n\n        cfg += \"resolv-retry 60\\n\";\n\n\n        // We cannot use anything else than tun\n        cfg += \"dev tun\\n\";\n\n\n        boolean canUsePlainRemotes = true;\n\n        if (mConnections.length == 1) {\n            cfg += mConnections[0].getConnectionBlock();\n        } else {\n            for (Connection conn : mConnections) {\n                canUsePlainRemotes = canUsePlainRemotes && conn.isOnlyRemote();\n            }\n\n            if (mRemoteRandom)\n                cfg += \"remote-random\\n\";\n\n            if (canUsePlainRemotes) {\n                for (Connection conn : mConnections) {\n                    if (conn.mEnabled) {\n                        cfg += conn.getConnectionBlock();\n                    }\n                }\n            }\n        }\n\n\n        switch (mAuthenticationType) {\n            case VpnProfile.TYPE_USERPASS_CERTIFICATES:\n                cfg += \"auth-user-pass\\n\";\n            case VpnProfile.TYPE_CERTIFICATES:\n                // Ca\n                cfg += insertFileData(\"ca\", mCaFilename);\n\n                // Client Cert + Key\n                cfg += insertFileData(\"key\", mClientKeyFilename);\n                cfg += insertFileData(\"cert\", mClientCertFilename);\n\n                break;\n            case VpnProfile.TYPE_USERPASS_PKCS12:\n                cfg += \"auth-user-pass\\n\";\n            case VpnProfile.TYPE_PKCS12:\n                cfg += insertFileData(\"pkcs12\", mPKCS12Filename);\n                break;\n\n            case VpnProfile.TYPE_USERPASS_KEYSTORE:\n                cfg += \"auth-user-pass\\n\";\n            case VpnProfile.TYPE_KEYSTORE:\n                if (!configForOvpn3) {\n                    String[] ks = getKeyStoreCertificates(context);\n                    cfg += \"### From Keystore ####\\n\";\n                    if (ks != null) {\n                        cfg += \"<ca>\\n\" + ks[0] + \"\\n</ca>\\n\";\n                        if (ks[1] != null)\n                            cfg += \"<extra-certs>\\n\" + ks[1] + \"\\n</extra-certs>\\n\";\n                        cfg += \"<cert>\\n\" + ks[2] + \"\\n</cert>\\n\";\n                        cfg += \"management-external-key\\n\";\n                    } else {\n                        cfg += context.getString(R.string.keychain_access) + \"\\n\";\n                        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)\n                            if (!mAlias.matches(\"^[a-zA-Z0-9]$\"))\n                                cfg += context.getString(R.string.jelly_keystore_alphanumeric_bug) + \"\\n\";\n                    }\n                }\n                break;\n            case VpnProfile.TYPE_USERPASS:\n                cfg += \"auth-user-pass\\n\";\n                cfg += insertFileData(\"ca\", mCaFilename);\n        }\n\n        if (!TextUtils.isEmpty(mCrlFilename))\n            cfg += insertFileData(\"crl-verify\", mCrlFilename);\n\n        if (mUseLzo) {\n            cfg += \"comp-lzo\\n\";\n        }\n\n        if (mUseTLSAuth) {\n            if (mAuthenticationType == TYPE_STATICKEYS)\n                cfg += insertFileData(\"secret\", mTLSAuthFilename);\n            else\n                cfg += insertFileData(\"tls-auth\", mTLSAuthFilename);\n\n            if (!TextUtils.isEmpty(mTLSAuthDirection)) {\n                cfg += \"key-direction \";\n                cfg += mTLSAuthDirection;\n                cfg += \"\\n\";\n            }\n\n        }\n\n        if (!mUsePull) {\n            if (!TextUtils.isEmpty(mIPv4Address))\n                cfg += \"ifconfig \" + cidrToIPAndNetmask(mIPv4Address) + \"\\n\";\n\n            if (!TextUtils.isEmpty(mIPv6Address))\n                cfg += \"ifconfig-ipv6 \" + mIPv6Address + \"\\n\";\n        }\n\n        if (mUsePull && mRoutenopull)\n            cfg += \"route-nopull\\n\";\n\n        String routes = \"\";\n\n        if (mUseDefaultRoute)\n            routes += \"route 0.0.0.0 0.0.0.0 vpn_gateway\\n\";\n        else {\n            for (String route : getCustomRoutes(mCustomRoutes)) {\n                routes += \"route \" + route + \" vpn_gateway\\n\";\n            }\n\n            for (String route : getCustomRoutes(mExcludedRoutes)) {\n                routes += \"route \" + route + \" net_gateway\\n\";\n            }\n        }\n\n\n        if (mUseDefaultRoutev6)\n            cfg += \"route-ipv6 ::/0\\n\";\n        else\n            for (String route : getCustomRoutesv6(mCustomRoutesv6)) {\n                routes += \"route-ipv6 \" + route + \"\\n\";\n            }\n\n        cfg += routes;\n\n        if (mOverrideDNS || !mUsePull) {\n            if (!TextUtils.isEmpty(mDNS1))\n                cfg += \"dhcp-option DNS \" + mDNS1 + \"\\n\";\n            if (!TextUtils.isEmpty(mDNS2))\n                cfg += \"dhcp-option DNS \" + mDNS2 + \"\\n\";\n            if (!TextUtils.isEmpty(mSearchDomain))\n                cfg += \"dhcp-option DOMAIN \" + mSearchDomain + \"\\n\";\n\n        }\n\n        if (mMssFix != 0) {\n            if (mMssFix != 1450) {\n                cfg += String.format(Locale.US, \"mssfix %d\\n\", mMssFix);\n            } else\n                cfg += \"mssfix\\n\";\n        }\n\n        if (mNobind)\n            cfg += \"nobind\\n\";\n\n\n        // Authentication\n        if (mAuthenticationType != TYPE_STATICKEYS) {\n            if (mCheckRemoteCN) {\n                if (mRemoteCN == null || mRemoteCN.equals(\"\"))\n                    cfg += \"verify-x509-name \" + openVpnEscape(mConnections[0].mServerName) + \" name\\n\";\n                else\n                    switch (mX509AuthType) {\n\n                        // 2.2 style x509 checks\n                        case X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING:\n                            cfg += \"compat-names no-remapping\\n\";\n                        case X509_VERIFY_TLSREMOTE:\n                            cfg += \"tls-remote \" + openVpnEscape(mRemoteCN) + \"\\n\";\n                            break;\n\n                        case X509_VERIFY_TLSREMOTE_RDN:\n                            cfg += \"verify-x509-name \" + openVpnEscape(mRemoteCN) + \" name\\n\";\n                            break;\n\n                        case X509_VERIFY_TLSREMOTE_RDN_PREFIX:\n                            cfg += \"verify-x509-name \" + openVpnEscape(mRemoteCN) + \" name-prefix\\n\";\n                            break;\n\n                        case X509_VERIFY_TLSREMOTE_DN:\n                            cfg += \"verify-x509-name \" + openVpnEscape(mRemoteCN) + \"\\n\";\n                            break;\n                    }\n                if (!TextUtils.isEmpty(mx509UsernameField))\n                    cfg+= \"x509-username-field \" + openVpnEscape(mx509UsernameField) +\"\\n\";\n            }\n            if (mExpectTLSCert)\n                cfg += \"remote-cert-tls server\\n\";\n        }\n\n        if (!TextUtils.isEmpty(mCipher)) {\n            cfg += \"cipher \" + mCipher + \"\\n\";\n        }\n\n        if (!TextUtils.isEmpty(mAuth)) {\n            cfg += \"auth \" + mAuth + \"\\n\";\n        }\n\n        // Obscure Settings dialog\n        if (mUseRandomHostname)\n            cfg += \"#my favorite options :)\\nremote-random-hostname\\n\";\n\n        if (mUseFloat)\n            cfg += \"float\\n\";\n\n        if (mPersistTun) {\n            cfg += \"persist-tun\\n\";\n            cfg += \"# persist-tun also enables pre resolving to avoid DNS resolve problem\\n\";\n            cfg += \"preresolve\\n\";\n        }\n\n        if (mPushPeerInfo)\n            cfg += \"push-peer-info\\n\";\n\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);\n        boolean usesystemproxy = prefs.getBoolean(\"usesystemproxy\", true);\n        if (usesystemproxy && !mIsOpenVPN22) {\n            cfg += \"# Use system proxy setting\\n\";\n            cfg += \"management-query-proxy\\n\";\n        }\n\n\n        if (mUseCustomConfig) {\n            cfg += \"# Custom configuration options\\n\";\n            cfg += \"# You are on your on own here :)\\n\";\n            cfg += mCustomConfigOptions;\n            cfg += \"\\n\";\n\n        }\n\n        if (!canUsePlainRemotes) {\n            cfg += \"# Connection Options are at the end to allow global options (and global custom options) to influence connection blocks\\n\";\n            for (Connection conn : mConnections) {\n                if (conn.mEnabled) {\n                    cfg += \"<connection>\\n\";\n                    cfg += conn.getConnectionBlock();\n                    cfg += \"</connection>\\n\";\n                }\n            }\n        }\n\n\n        return cfg;\n    }\n\n    public String getVersionEnvString(Context c) {\n        String version = \"unknown\";\n        try {\n            PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);\n            version = packageinfo.versionName;\n        } catch (PackageManager.NameNotFoundException e) {\n            VpnStatus.logException(e);\n        }\n        return String.format(Locale.US, \"%s %s\", c.getPackageName(), version);\n\n    }\n\n    //! Put inline data inline and other data as normal escaped filename\n    public static String insertFileData(String cfgentry, String filedata) {\n        if (filedata == null) {\n            return String.format(\"%s %s\\n\", cfgentry, \"file missing in config profile\");\n        } else if (isEmbedded(filedata)) {\n            String dataWithOutHeader = getEmbeddedContent(filedata);\n            return String.format(Locale.ENGLISH, \"<%s>\\n%s\\n</%s>\\n\", cfgentry, dataWithOutHeader, cfgentry);\n        } else {\n            return String.format(Locale.ENGLISH, \"%s %s\\n\", cfgentry, openVpnEscape(filedata));\n        }\n    }\n\n    @NonNull\n    private Collection<String> getCustomRoutes(String routes) {\n        Vector<String> cidrRoutes = new Vector<>();\n        if (routes == null) {\n            // No routes set, return empty vector\n            return cidrRoutes;\n        }\n        for (String route : routes.split(\"[\\n \\t]\")) {\n            if (!route.equals(\"\")) {\n                String cidrroute = cidrToIPAndNetmask(route);\n                if (cidrroute == null)\n                    return cidrRoutes;\n\n                cidrRoutes.add(cidrroute);\n            }\n        }\n\n        return cidrRoutes;\n    }\n\n    private Collection<String> getCustomRoutesv6(String routes) {\n        Vector<String> cidrRoutes = new Vector<>();\n        if (routes == null) {\n            // No routes set, return empty vector\n            return cidrRoutes;\n        }\n        for (String route : routes.split(\"[\\n \\t]\")) {\n            if (!route.equals(\"\")) {\n                cidrRoutes.add(route);\n            }\n        }\n\n        return cidrRoutes;\n    }\n\n    private String cidrToIPAndNetmask(String route) {\n        String[] parts = route.split(\"/\");\n\n        // No /xx, assume /32 as netmask\n        if (parts.length == 1)\n            parts = (route + \"/32\").split(\"/\");\n\n        if (parts.length != 2)\n            return null;\n        int len;\n        try {\n            len = Integer.parseInt(parts[1]);\n        } catch (NumberFormatException ne) {\n            return null;\n        }\n        if (len < 0 || len > 32)\n            return null;\n\n\n        long nm = 0xffffffffL;\n        nm = (nm << (32 - len)) & 0xffffffffL;\n\n        String netmask = String.format(Locale.ENGLISH, \"%d.%d.%d.%d\", (nm & 0xff000000) >> 24, (nm & 0xff0000) >> 16, (nm & 0xff00) >> 8, nm & 0xff);\n        return parts[0] + \"  \" + netmask;\n    }\n\n\n    public Intent prepareStartService(Context context) {\n        Intent intent = getStartServiceIntent(context);\n\n        // TODO: Handle this?!\n//        if (mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) {\n//            if (getKeyStoreCertificates(context) == null)\n//                return null;\n//        }\n\n        return intent;\n    }\n\n    public void writeConfigFile(Context context) throws IOException {\n        FileWriter cfg = new FileWriter(VPNLaunchHelper.getConfigFilePath(context));\n        cfg.write(getConfigFile(context, false));\n        cfg.flush();\n        cfg.close();\n\n    }\n\n    public Intent getStartServiceIntent(Context context) {\n        String prefix = context.getPackageName();\n\n        Intent intent = new Intent(context, OpenVPNService.class);\n        intent.putExtra(prefix + \".profileUUID\", mUuid.toString());\n\n        return intent;\n    }\n\n    public String[] getKeyStoreCertificates(Context context) {\n        return getKeyStoreCertificates(context, 5);\n    }\n\n    public static String getDisplayName(String embeddedFile) {\n        int start = DISPLAYNAME_TAG.length();\n        int end = embeddedFile.indexOf(INLINE_TAG);\n        return embeddedFile.substring(start, end);\n    }\n\n    public static String getEmbeddedContent(String data) {\n        if (!data.contains(INLINE_TAG))\n            return data;\n\n        int start = data.indexOf(INLINE_TAG) + INLINE_TAG.length();\n        return data.substring(start);\n    }\n\n    public static boolean isEmbedded(String data) {\n        if (data == null)\n            return false;\n        if (data.startsWith(INLINE_TAG) || data.startsWith(DISPLAYNAME_TAG))\n            return true;\n        else\n            return false;\n    }\n\n    public void checkForRestart(final Context context) {\n        /* This method is called when OpenVPNService is restarted */\n\n        if ((mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE)\n                && mPrivateKey == null) {\n            new Thread(new Runnable() {\n                @Override\n                public void run() {\n                    getKeyStoreCertificates(context);\n\n                }\n            }).start();\n        }\n    }\n\n    @Override\n    protected VpnProfile clone() throws CloneNotSupportedException {\n        VpnProfile copy = (VpnProfile) super.clone();\n        copy.mUuid = UUID.randomUUID();\n        copy.mConnections = new Connection[mConnections.length];\n        int i = 0;\n        for (Connection conn : mConnections) {\n            copy.mConnections[i++] = conn.clone();\n        }\n        copy.mAllowedAppsVpn = (HashSet<String>) mAllowedAppsVpn.clone();\n        return copy;\n    }\n\n    public VpnProfile copy(String name) {\n        try {\n            VpnProfile copy = clone();\n            copy.mName = name;\n            return copy;\n\n        } catch (CloneNotSupportedException e) {\n            e.printStackTrace();\n            return null;\n        }\n    }\n\n\n    class NoCertReturnedException extends Exception {\n        public NoCertReturnedException(String msg) {\n            super(msg);\n        }\n    }\n\n    synchronized String[] getKeyStoreCertificates(Context context, int tries) {\n        // Force application context- KeyChain methods will block long enough that by the time they\n        // are finished and try to unbind, the original activity context might have been destroyed.\n        context = context.getApplicationContext();\n\n        try {\n            PrivateKey privateKey = KeyChain.getPrivateKey(context, mAlias);\n            mPrivateKey = privateKey;\n\n            String keystoreChain = null;\n\n\n            X509Certificate[] caChain = KeyChain.getCertificateChain(context, mAlias);\n            if (caChain == null)\n                throw new NoCertReturnedException(\"No certificate returned from Keystore\");\n\n            if (caChain.length <= 1 && TextUtils.isEmpty(mCaFilename)) {\n                VpnStatus.logMessage(VpnStatus.LogLevel.ERROR, \"\", context.getString(R.string.keychain_nocacert));\n            } else {\n                StringWriter ksStringWriter = new StringWriter();\n\n                PemWriter pw = new PemWriter(ksStringWriter);\n                for (int i = 1; i < caChain.length; i++) {\n                    X509Certificate cert = caChain[i];\n                    pw.writeObject(new PemObject(\"CERTIFICATE\", cert.getEncoded()));\n                }\n                pw.close();\n                keystoreChain = ksStringWriter.toString();\n            }\n\n\n            String caout = null;\n            if (!TextUtils.isEmpty(mCaFilename)) {\n                try {\n                    Certificate[] cacerts = X509Utils.getCertificatesFromFile(mCaFilename);\n                    StringWriter caoutWriter = new StringWriter();\n                    PemWriter pw = new PemWriter(caoutWriter);\n\n                    for (Certificate cert : cacerts)\n                        pw.writeObject(new PemObject(\"CERTIFICATE\", cert.getEncoded()));\n                    pw.close();\n                    caout = caoutWriter.toString();\n\n                } catch (Exception e) {\n                    VpnStatus.logError(\"Could not read CA certificate\" + e.getLocalizedMessage());\n                }\n            }\n\n\n            StringWriter certout = new StringWriter();\n\n\n            if (caChain.length >= 1) {\n                X509Certificate usercert = caChain[0];\n\n                PemWriter upw = new PemWriter(certout);\n                upw.writeObject(new PemObject(\"CERTIFICATE\", usercert.getEncoded()));\n                upw.close();\n\n            }\n            String user = certout.toString();\n\n\n            String ca, extra;\n            if (caout == null) {\n                ca = keystoreChain;\n                extra = null;\n            } else {\n                ca = caout;\n                extra = keystoreChain;\n            }\n\n            return new String[]{ca, extra, user};\n        } catch (InterruptedException | IOException | KeyChainException | NoCertReturnedException | IllegalArgumentException\n                | CertificateException e) {\n            e.printStackTrace();\n            VpnStatus.logError(R.string.keyChainAccessError, e.getLocalizedMessage());\n\n            VpnStatus.logError(R.string.keychain_access);\n            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {\n                if (!mAlias.matches(\"^[a-zA-Z0-9]$\")) {\n                    VpnStatus.logError(R.string.jelly_keystore_alphanumeric_bug);\n                }\n            }\n            return null;\n\n        } catch (AssertionError e) {\n            if (tries == 0)\n                return null;\n            VpnStatus.logError(String.format(\"Failure getting Keystore Keys (%s), retrying\", e.getLocalizedMessage()));\n            try {\n                Thread.sleep(3000);\n            } catch (InterruptedException e1) {\n                VpnStatus.logException(e1);\n            }\n            return getKeyStoreCertificates(context, tries - 1);\n        }\n\n    }\n\n    //! Return an error if something is wrong\n    public int checkProfile(Context context) {\n        if (mAuthenticationType == TYPE_KEYSTORE || mAuthenticationType == TYPE_USERPASS_KEYSTORE) {\n            if (mAlias == null)\n                return R.string.no_keystore_cert_selected;\n        }\n\n        if (!mUsePull || mAuthenticationType == TYPE_STATICKEYS) {\n            if (mIPv4Address == null || cidrToIPAndNetmask(mIPv4Address) == null)\n                return R.string.ipv4_format_error;\n        }\n        if (!mUseDefaultRoute) {\n            if (!TextUtils.isEmpty(mCustomRoutes) && getCustomRoutes(mCustomRoutes).size() == 0)\n                return R.string.custom_route_format_error;\n\n            if (!TextUtils.isEmpty(mExcludedRoutes) && getCustomRoutes(mExcludedRoutes).size() == 0)\n                return R.string.custom_route_format_error;\n\n        }\n\n        if (mUseTLSAuth && TextUtils.isEmpty(mTLSAuthFilename))\n            return R.string.missing_tlsauth;\n\n        if ((mAuthenticationType == TYPE_USERPASS_CERTIFICATES || mAuthenticationType == TYPE_CERTIFICATES)\n                && (TextUtils.isEmpty(mClientCertFilename) || TextUtils.isEmpty(mClientKeyFilename)))\n            return R.string.missing_certificates;\n\n        if ((mAuthenticationType == TYPE_CERTIFICATES || mAuthenticationType == TYPE_USERPASS_CERTIFICATES)\n                && TextUtils.isEmpty(mCaFilename))\n            return R.string.missing_ca_certificate;\n\n\n        boolean noRemoteEnabled = true;\n        for (Connection c : mConnections)\n            if (c.mEnabled)\n                noRemoteEnabled = false;\n\n        if (noRemoteEnabled)\n            return R.string.remote_no_server_selected;\n\n        // Everything okay\n        return R.string.no_error_found;\n\n    }\n\n    //! Openvpn asks for a \"Private Key\", this should be pkcs12 key\n    //\n    public String getPasswordPrivateKey() {\n        if (mTransientPCKS12PW != null) {\n            String pwcopy = mTransientPCKS12PW;\n            mTransientPCKS12PW = null;\n            return pwcopy;\n        }\n        switch (mAuthenticationType) {\n            case TYPE_PKCS12:\n            case TYPE_USERPASS_PKCS12:\n                return mPKCS12Password;\n\n            case TYPE_CERTIFICATES:\n            case TYPE_USERPASS_CERTIFICATES:\n                return mKeyPassword;\n\n            case TYPE_USERPASS:\n            case TYPE_STATICKEYS:\n            default:\n                return null;\n        }\n    }\n\n    public boolean isUserPWAuth() {\n        switch (mAuthenticationType) {\n            case TYPE_USERPASS:\n            case TYPE_USERPASS_CERTIFICATES:\n            case TYPE_USERPASS_KEYSTORE:\n            case TYPE_USERPASS_PKCS12:\n                return true;\n            default:\n                return false;\n\n        }\n    }\n\n    public boolean requireTLSKeyPassword() {\n        if (TextUtils.isEmpty(mClientKeyFilename))\n            return false;\n\n        String data = \"\";\n        if (isEmbedded(mClientKeyFilename))\n            data = mClientKeyFilename;\n        else {\n            char[] buf = new char[2048];\n            FileReader fr;\n            try {\n                fr = new FileReader(mClientKeyFilename);\n                int len = fr.read(buf);\n                while (len > 0) {\n                    data += new String(buf, 0, len);\n                    len = fr.read(buf);\n                }\n                fr.close();\n            } catch (FileNotFoundException e) {\n                return false;\n            } catch (IOException e) {\n                return false;\n            }\n\n        }\n\n        if (data.contains(\"Proc-Type: 4,ENCRYPTED\"))\n            return true;\n        else if (data.contains(\"-----BEGIN ENCRYPTED PRIVATE KEY-----\"))\n            return true;\n        else\n            return false;\n    }\n\n    public int needUserPWInput(boolean ignoreTransient) {\n        if ((mAuthenticationType == TYPE_PKCS12 || mAuthenticationType == TYPE_USERPASS_PKCS12) &&\n                (mPKCS12Password == null || mPKCS12Password.equals(\"\"))) {\n            if (ignoreTransient || mTransientPCKS12PW == null)\n                return R.string.pkcs12_file_encryption_key;\n        }\n\n        if (mAuthenticationType == TYPE_CERTIFICATES || mAuthenticationType == TYPE_USERPASS_CERTIFICATES) {\n            if (requireTLSKeyPassword() && TextUtils.isEmpty(mKeyPassword))\n                if (ignoreTransient || mTransientPCKS12PW == null) {\n                    return R.string.private_key_password;\n                }\n        }\n\n        if (isUserPWAuth() &&\n                (TextUtils.isEmpty(mUsername) ||\n                        (TextUtils.isEmpty(mPassword) && (mTransientPW == null || ignoreTransient)))) {\n            return R.string.password;\n        }\n        return 0;\n    }\n\n    public String getPasswordAuth() {\n        if (mTransientPW != null) {\n            String pwcopy = mTransientPW;\n            mTransientPW = null;\n            return pwcopy;\n        } else {\n            return mPassword;\n        }\n    }\n\n    // Used by the Array Adapter\n    @Override\n    public String toString() {\n        return mName;\n    }\n\n    public String getUUIDString() {\n        return mUuid.toString();\n    }\n\n    public PrivateKey getKeystoreKey() {\n        return mPrivateKey;\n    }\n\n    public String getSignedData(String b64data) {\n        PrivateKey privkey = getKeystoreKey();\n\n        byte[] data = Base64.decode(b64data, Base64.DEFAULT);\n\n        // The Jelly Bean *evil* Hack\n        // 4.2 implements the RSA/ECB/PKCS1PADDING in the OpenSSLprovider\n        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {\n            return processSignJellyBeans(privkey, data);\n        }\n\n\n        try {\n\n            /* ECB is perfectly fine in this special case, since we are using it for\n               the public/private part in the TLS exchange\n             */\n            @SuppressLint(\"GetInstance\")\n            Cipher rsaSigner = Cipher.getInstance(\"RSA/ECB/PKCS1PADDING\");\n\n            rsaSigner.init(Cipher.ENCRYPT_MODE, privkey);\n\n            byte[] signed_bytes = rsaSigner.doFinal(data);\n            return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);\n\n        } catch (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException\n                | BadPaddingException | NoSuchPaddingException e) {\n            VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage());\n            return null;\n        }\n    }\n\n    private String processSignJellyBeans(PrivateKey privkey, byte[] data) {\n        try {\n            Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod(\"getOpenSSLKey\");\n            getKey.setAccessible(true);\n\n            // Real object type is OpenSSLKey\n            Object opensslkey = getKey.invoke(privkey);\n\n            getKey.setAccessible(false);\n\n            Method getPkeyContext = opensslkey.getClass().getDeclaredMethod(\"getPkeyContext\");\n\n            // integer pointer to EVP_pkey\n            getPkeyContext.setAccessible(true);\n            int pkey = (Integer) getPkeyContext.invoke(opensslkey);\n            getPkeyContext.setAccessible(false);\n\n            // 112 with TLS 1.2 (172 back with 4.3), 36 with TLS 1.0\n            byte[] signed_bytes = NativeUtils.rsasign(data, pkey);\n            return Base64.encodeToString(signed_bytes, Base64.NO_WRAP);\n\n        } catch (NoSuchMethodException | InvalidKeyException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {\n            VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage());\n            return null;\n        }\n    }\n\n\n}\n\n\n\n\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport java.util.Locale;\n\nclass CIDRIP {\n    String mIp;\n    int len;\n\n\n    public CIDRIP(String ip, String mask) {\n        mIp = ip;\n        long netmask = getInt(mask);\n\n        // Add 33. bit to ensure the loop terminates\n        netmask += 1l << 32;\n\n        int lenZeros = 0;\n        while ((netmask & 0x1) == 0) {\n            lenZeros++;\n            netmask = netmask >> 1;\n        }\n        // Check if rest of netmask is only 1s\n        if (netmask != (0x1ffffffffl >> lenZeros)) {\n            // Asume no CIDR, set /32\n            len = 32;\n        } else {\n            len = 32 - lenZeros;\n        }\n\n    }\n\n    public CIDRIP(String address, int prefix_length) {\n        len = prefix_length;\n        mIp = address;\n    }\n\n    @Override\n    public String toString() {\n        return String.format(Locale.ENGLISH, \"%s/%d\", mIp, len);\n    }\n\n    public boolean normalise() {\n        long ip = getInt(mIp);\n\n        long newip = ip & (0xffffffffl << (32 - len));\n        if (newip != ip) {\n            mIp = String.format(\"%d.%d.%d.%d\", (newip & 0xff000000) >> 24, (newip & 0xff0000) >> 16, (newip & 0xff00) >> 8, newip & 0xff);\n            return true;\n        } else {\n            return false;\n        }\n\n    }\n\n    static long getInt(String ipaddr) {\n        String[] ipt = ipaddr.split(\"\\\\.\");\n        long ip = 0;\n\n        ip += Long.parseLong(ipt[0]) << 24;\n        ip += Integer.parseInt(ipt[1]) << 16;\n        ip += Integer.parseInt(ipt[2]) << 8;\n        ip += Integer.parseInt(ipt[3]);\n\n        return ip;\n    }\n\n    public long getInt() {\n        return getInt(mIp);\n    }\n\n}"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.text.TextUtils;\nimport android.util.Pair;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.io.StringReader;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Vector;\n\nimport de.blinkt.openvpn.VpnProfile;\n\n//! Openvpn Config FIle Parser, probably not 100% accurate but close enough\n\n// And remember, this is valid :)\n// --<foo>\n// bar\n// </foo>\npublic class ConfigParser {\n\n\n    public static final String CONVERTED_PROFILE = \"converted Profile\";\n    private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();\n    private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>();\n    private String auth_user_pass_file;\n\n    public void parseConfig(Reader reader) throws IOException, ConfigParseError {\n\n        HashMap<String, String> optionAliases = new HashMap<>();\n        optionAliases.put(\"server-poll-timeout\", \"timeout-connect\");\n\n        BufferedReader br = new BufferedReader(reader);\n\n        int lineno = 0;\n        try {\n            while (true) {\n                String line = br.readLine();\n                lineno++;\n                if (line == null)\n                    break;\n\n                if (lineno == 1) {\n                    if ((line.startsWith(\"PK\\003\\004\")\n                            || (line.startsWith(\"PK\\007\\008\")))) {\n                        throw new ConfigParseError(\"Input looks like a ZIP Archive. Import is only possible for OpenVPN config files (.ovpn/.conf)\");\n                    }\n                    if (line.startsWith(\"\\uFEFF\")) {\n                        line = line.substring(1);\n                    }\n                }\n\n                // Check for OpenVPN Access Server Meta information\n                if (line.startsWith(\"# OVPN_ACCESS_SERVER_\")) {\n                    Vector<String> metaarg = parsemeta(line);\n                    meta.put(metaarg.get(0), metaarg);\n                    continue;\n                }\n                Vector<String> args = parseline(line);\n\n                if (args.size() == 0)\n                    continue;\n\n\n                if (args.get(0).startsWith(\"--\"))\n                    args.set(0, args.get(0).substring(2));\n\n                checkinlinefile(args, br);\n\n                String optionname = args.get(0);\n                if (optionAliases.get(optionname)!=null)\n                    optionname = optionAliases.get(optionname);\n\n                if (!options.containsKey(optionname)) {\n                    options.put(optionname, new Vector<Vector<String>>());\n                }\n                options.get(optionname).add(args);\n            }\n        } catch (java.lang.OutOfMemoryError memoryError) {\n            throw new ConfigParseError(\"File too large to parse: \" + memoryError.getLocalizedMessage());\n        }\n    }\n\n    private Vector<String> parsemeta(String line) {\n        String meta = line.split(\"#\\\\sOVPN_ACCESS_SERVER_\", 2)[1];\n        String[] parts = meta.split(\"=\", 2);\n        Vector<String> rval = new Vector<String>();\n        Collections.addAll(rval, parts);\n        return rval;\n\n    }\n\n    private void checkinlinefile(Vector<String> args, BufferedReader br) throws IOException, ConfigParseError {\n        String arg0 = args.get(0).trim();\n        // CHeck for <foo>\n        if (arg0.startsWith(\"<\") && arg0.endsWith(\">\")) {\n            String argname = arg0.substring(1, arg0.length() - 1);\n            String inlinefile = VpnProfile.INLINE_TAG;\n\n            String endtag = String.format(\"</%s>\", argname);\n            do {\n                String line = br.readLine();\n                if (line == null) {\n                    throw new ConfigParseError(String.format(\"No endtag </%s> for starttag <%s> found\", argname, argname));\n                }\n                if (line.trim().equals(endtag))\n                    break;\n                else {\n                    inlinefile += line;\n                    inlinefile += \"\\n\";\n                }\n            } while (true);\n\n            args.clear();\n            args.add(argname);\n            args.add(inlinefile);\n        }\n\n    }\n\n    public String getAuthUserPassFile() {\n        return auth_user_pass_file;\n    }\n\n    enum linestate {\n        initial,\n        readin_single_quote, reading_quoted, reading_unquoted, done\n    }\n\n    private boolean space(char c) {\n        // I really hope nobody is using zero bytes inside his/her config file\n        // to sperate parameter but here we go:\n        return Character.isWhitespace(c) || c == '\\0';\n\n    }\n\n    public static class ConfigParseError extends Exception {\n        private static final long serialVersionUID = -60L;\n\n        public ConfigParseError(String msg) {\n            super(msg);\n        }\n    }\n\n\n    // adapted openvpn's parse function to java\n    private Vector<String> parseline(String line) throws ConfigParseError {\n        Vector<String> parameters = new Vector<String>();\n\n        if (line.length() == 0)\n            return parameters;\n\n\n        linestate state = linestate.initial;\n        boolean backslash = false;\n        char out = 0;\n\n        int pos = 0;\n        String currentarg = \"\";\n\n        do {\n            // Emulate the c parsing ...\n            char in;\n            if (pos < line.length())\n                in = line.charAt(pos);\n            else\n                in = '\\0';\n\n            if (!backslash && in == '\\\\' && state != linestate.readin_single_quote) {\n                backslash = true;\n            } else {\n                if (state == linestate.initial) {\n                    if (!space(in)) {\n                        if (in == ';' || in == '#') /* comment */\n                            break;\n                        if (!backslash && in == '\\\"')\n                            state = linestate.reading_quoted;\n                        else if (!backslash && in == '\\'')\n                            state = linestate.readin_single_quote;\n                        else {\n                            out = in;\n                            state = linestate.reading_unquoted;\n                        }\n                    }\n                } else if (state == linestate.reading_unquoted) {\n                    if (!backslash && space(in))\n                        state = linestate.done;\n                    else\n                        out = in;\n                } else if (state == linestate.reading_quoted) {\n                    if (!backslash && in == '\\\"')\n                        state = linestate.done;\n                    else\n                        out = in;\n                } else if (state == linestate.readin_single_quote) {\n                    if (in == '\\'')\n                        state = linestate.done;\n                    else\n                        out = in;\n                }\n\n                if (state == linestate.done) {\n                    /* ASSERT (parm_len > 0); */\n                    state = linestate.initial;\n                    parameters.add(currentarg);\n                    currentarg = \"\";\n                    out = 0;\n                }\n\n                if (backslash && out != 0) {\n                    if (!(out == '\\\\' || out == '\\\"' || space(out))) {\n                        throw new ConfigParseError(\"Options warning: Bad backslash ('\\\\') usage\");\n                    }\n                }\n                backslash = false;\n            }\n\n\t\t\t/* store parameter character */\n            if (out != 0) {\n                currentarg += out;\n            }\n        } while (pos++ < line.length());\n\n        return parameters;\n    }\n\n\n    final String[] unsupportedOptions = {\"config\",\n            \"tls-server\"\n\n    };\n\n    // Ignore all scripts\n    // in most cases these won't work and user who wish to execute scripts will\n    // figure out themselves\n    final String[] ignoreOptions = {\"tls-client\",\n            \"askpass\",\n            \"auth-nocache\",\n            \"up\",\n            \"down\",\n            \"route-up\",\n            \"ipchange\",\n            \"route-up\",\n            \"route-pre-down\",\n            \"auth-user-pass-verify\",\n            \"block-outside-dns\",\n            \"dhcp-release\",\n            \"dhcp-renew\",\n            \"dh\",\n            \"group\",\n            \"ip-win32\",\n            \"management-hold\",\n            \"management\",\n            \"management-client\",\n            \"management-query-remote\",\n            \"management-query-passwords\",\n            \"management-query-proxy\",\n            \"management-external-key\",\n            \"management-forget-disconnect\",\n            \"management-signal\",\n            \"management-log-cache\",\n            \"management-up-down\",\n            \"management-client-user\",\n            \"management-client-group\",\n            \"pause-exit\",\n            \"plugin\",\n            \"machine-readable-output\",\n            \"persist-key\",\n            \"push\",\n            \"register-dns\",\n            \"route-delay\",\n            \"route-gateway\",\n            \"route-metric\",\n            \"route-method\",\n            \"status\",\n            \"script-security\",\n            \"show-net-up\",\n            \"suppress-timestamps\",\n            \"tmp-dir\",\n            \"tun-ipv6\",\n            \"topology\",\n            \"user\",\n            \"win-sys\",\n    };\n\n    final String[][] ignoreOptionsWithArg =\n            {\n                    {\"setenv\", \"IV_GUI_VER\"},\n                    {\"setenv\", \"IV_OPENVPN_GUI_VERSION\"},\n                    {\"engine\", \"dynamic\"},\n                    {\"setenv\", \"CLIENT_CERT\"}\n            };\n\n    final String[] connectionOptions = {\n            \"local\",\n            \"remote\",\n            \"float\",\n            \"port\",\n            \"connect-retry\",\n            \"connect-timeout\",\n            \"connect-retry-max\",\n            \"link-mtu\",\n            \"tun-mtu\",\n            \"tun-mtu-extra\",\n            \"fragment\",\n            \"mtu-disc\",\n            \"local-port\",\n            \"remote-port\",\n            \"bind\",\n            \"nobind\",\n            \"proto\",\n            \"http-proxy\",\n            \"http-proxy-retry\",\n            \"http-proxy-timeout\",\n            \"http-proxy-option\",\n            \"socks-proxy\",\n            \"socks-proxy-retry\",\n            \"explicit-exit-notify\",\n            \"mssfix\"\n    };\n\n\n    // This method is far too long\n    @SuppressWarnings(\"ConstantConditions\")\n    public VpnProfile convertProfile() throws ConfigParseError, IOException {\n        boolean noauthtypeset = true;\n        VpnProfile np = new VpnProfile(CONVERTED_PROFILE);\n        // Pull, client, tls-client\n        np.clearDefaults();\n\n        if (options.containsKey(\"client\") || options.containsKey(\"pull\")) {\n            np.mUsePull = true;\n            options.remove(\"pull\");\n            options.remove(\"client\");\n        }\n\n        Vector<String> secret = getOption(\"secret\", 1, 2);\n        if (secret != null) {\n            np.mAuthenticationType = VpnProfile.TYPE_STATICKEYS;\n            noauthtypeset = false;\n            np.mUseTLSAuth = true;\n            np.mTLSAuthFilename = secret.get(1);\n            if (secret.size() == 3)\n                np.mTLSAuthDirection = secret.get(2);\n\n        }\n\n        Vector<Vector<String>> routes = getAllOption(\"route\", 1, 4);\n        if (routes != null) {\n            String routeopt = \"\";\n            String routeExcluded = \"\";\n            for (Vector<String> route : routes) {\n                String netmask = \"255.255.255.255\";\n                String gateway = \"vpn_gateway\";\n\n                if (route.size() >= 3)\n                    netmask = route.get(2);\n                if (route.size() >= 4)\n                    gateway = route.get(3);\n\n                String net = route.get(1);\n                try {\n                    CIDRIP cidr = new CIDRIP(net, netmask);\n                    if (gateway.equals(\"net_gateway\"))\n                        routeExcluded += cidr.toString() + \" \";\n                    else\n                        routeopt += cidr.toString() + \" \";\n                } catch (ArrayIndexOutOfBoundsException aioob) {\n                    throw new ConfigParseError(\"Could not parse netmask of route \" + netmask);\n                } catch (NumberFormatException ne) {\n\n\n                    throw new ConfigParseError(\"Could not parse netmask of route \" + netmask);\n                }\n\n            }\n            np.mCustomRoutes = routeopt;\n            np.mExcludedRoutes = routeExcluded;\n        }\n\n        Vector<Vector<String>> routesV6 = getAllOption(\"route-ipv6\", 1, 4);\n        if (routesV6 != null) {\n            String customIPv6Routes = \"\";\n            for (Vector<String> route : routesV6) {\n                customIPv6Routes += route.get(1) + \" \";\n            }\n\n            np.mCustomRoutesv6 = customIPv6Routes;\n        }\n\n        Vector<String> routeNoPull = getOption(\"route-nopull\", 1, 1);\n        if (routeNoPull!=null)\n            np.mRoutenopull=true;\n\n        // Also recognize tls-auth [inline] direction ...\n        Vector<Vector<String>> tlsauthoptions = getAllOption(\"tls-auth\", 1, 2);\n        if (tlsauthoptions != null) {\n            for (Vector<String> tlsauth : tlsauthoptions) {\n                if (tlsauth != null) {\n                    if (!tlsauth.get(1).equals(\"[inline]\")) {\n                        np.mTLSAuthFilename = tlsauth.get(1);\n                        np.mUseTLSAuth = true;\n                    }\n                    if (tlsauth.size() == 3)\n                        np.mTLSAuthDirection = tlsauth.get(2);\n                }\n            }\n        }\n\n        Vector<String> direction = getOption(\"key-direction\", 1, 1);\n        if (direction != null)\n            np.mTLSAuthDirection = direction.get(1);\n\n        Vector<Vector<String>> defgw = getAllOption(\"redirect-gateway\", 0, 5);\n        if (defgw != null) {\n            np.mUseDefaultRoute = true;\n            checkRedirectParameters(np, defgw);\n        }\n\n        Vector<Vector<String>> redirectPrivate = getAllOption(\"redirect-private\", 0, 5);\n        if (redirectPrivate != null) {\n            checkRedirectParameters(np, redirectPrivate);\n        }\n        Vector<String> dev = getOption(\"dev\", 1, 1);\n        Vector<String> devtype = getOption(\"dev-type\", 1, 1);\n\n        if ((devtype != null && devtype.get(1).equals(\"tun\")) ||\n                (dev != null && dev.get(1).startsWith(\"tun\")) ||\n                (devtype == null && dev == null)) {\n            //everything okay\n        } else {\n            throw new ConfigParseError(\"Sorry. Only tun mode is supported. See the FAQ for more detail\");\n        }\n\n        Vector<String> mssfix = getOption(\"mssfix\", 0, 1);\n\n        if (mssfix != null) {\n            if (mssfix.size() >= 2) {\n                try {\n                    np.mMssFix = Integer.parseInt(mssfix.get(1));\n                } catch (NumberFormatException e) {\n                    throw new ConfigParseError(\"Argument to --mssfix has to be an integer\");\n                }\n            } else {\n                np.mMssFix = 1450; // OpenVPN default size\n            }\n        }\n\n\n        Vector<String> mode = getOption(\"mode\", 1, 1);\n        if (mode != null) {\n            if (!mode.get(1).equals(\"p2p\"))\n                throw new ConfigParseError(\"Invalid mode for --mode specified, need p2p\");\n        }\n\n\n        Vector<Vector<String>> dhcpoptions = getAllOption(\"dhcp-option\", 2, 2);\n        if (dhcpoptions != null) {\n            for (Vector<String> dhcpoption : dhcpoptions) {\n                String type = dhcpoption.get(1);\n                String arg = dhcpoption.get(2);\n                if (type.equals(\"DOMAIN\")) {\n                    np.mSearchDomain = dhcpoption.get(2);\n                } else if (type.equals(\"DNS\")) {\n                    np.mOverrideDNS = true;\n                    if (np.mDNS1.equals(VpnProfile.DEFAULT_DNS1))\n                        np.mDNS1 = arg;\n                    else\n                        np.mDNS2 = arg;\n                }\n            }\n        }\n\n        Vector<String> ifconfig = getOption(\"ifconfig\", 2, 2);\n        if (ifconfig != null) {\n            try {\n                CIDRIP cidr = new CIDRIP(ifconfig.get(1), ifconfig.get(2));\n                np.mIPv4Address = cidr.toString();\n            } catch (NumberFormatException nfe) {\n                throw new ConfigParseError(\"Could not pase ifconfig IP address: \" + nfe.getLocalizedMessage());\n            }\n\n        }\n\n        if (getOption(\"remote-random-hostname\", 0, 0) != null)\n            np.mUseRandomHostname = true;\n\n        if (getOption(\"float\", 0, 0) != null)\n            np.mUseFloat = true;\n\n        if (getOption(\"comp-lzo\", 0, 1) != null)\n            np.mUseLzo = true;\n\n        Vector<String> cipher = getOption(\"cipher\", 1, 1);\n        if (cipher != null)\n            np.mCipher = cipher.get(1);\n\n        Vector<String> auth = getOption(\"auth\", 1, 1);\n        if (auth != null)\n            np.mAuth = auth.get(1);\n\n\n        Vector<String> ca = getOption(\"ca\", 1, 1);\n        if (ca != null) {\n            np.mCaFilename = ca.get(1);\n        }\n\n        Vector<String> cert = getOption(\"cert\", 1, 1);\n        if (cert != null) {\n            np.mClientCertFilename = cert.get(1);\n            np.mAuthenticationType = VpnProfile.TYPE_CERTIFICATES;\n            noauthtypeset = false;\n        }\n        Vector<String> key = getOption(\"key\", 1, 1);\n        if (key != null)\n            np.mClientKeyFilename = key.get(1);\n\n        Vector<String> pkcs12 = getOption(\"pkcs12\", 1, 1);\n        if (pkcs12 != null) {\n            np.mPKCS12Filename = pkcs12.get(1);\n            np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE;\n            noauthtypeset = false;\n        }\n\n        Vector<String> cryptoapicert = getOption(\"cryptoapicert\", 1, 1);\n        if (cryptoapicert != null) {\n            np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE;\n            noauthtypeset = false;\n        }\n\n        Vector<String> compatnames = getOption(\"compat-names\", 1, 2);\n        Vector<String> nonameremapping = getOption(\"no-name-remapping\", 1, 1);\n        Vector<String> tlsremote = getOption(\"tls-remote\", 1, 1);\n        if (tlsremote != null) {\n            np.mRemoteCN = tlsremote.get(1);\n            np.mCheckRemoteCN = true;\n            np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE;\n\n            if ((compatnames != null && compatnames.size() > 2) ||\n                    (nonameremapping != null))\n                np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING;\n        }\n\n        Vector<String> verifyx509name = getOption(\"verify-x509-name\", 1, 2);\n        if (verifyx509name != null) {\n            np.mRemoteCN = verifyx509name.get(1);\n            np.mCheckRemoteCN = true;\n            if (verifyx509name.size() > 2) {\n                if (verifyx509name.get(2).equals(\"name\"))\n                    np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_RDN;\n                else if (verifyx509name.get(2).equals(\"subject\"))\n                    np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_DN;\n                else if (verifyx509name.get(2).equals(\"name-prefix\"))\n                    np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_RDN_PREFIX;\n                else\n                    throw new ConfigParseError(\"Unknown parameter to verify-x509-name: \" + verifyx509name.get(2));\n            } else {\n                np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_DN;\n            }\n\n        }\n\n        Vector<String> x509usernamefield = getOption(\"x509-username-field\", 1,1);\n        if (x509usernamefield!=null) {\n            np.mx509UsernameField =  x509usernamefield.get(1);\n        }\n\n\n        Vector<String> verb = getOption(\"verb\", 1, 1);\n        if (verb != null) {\n            np.mVerb = verb.get(1);\n        }\n\n\n        if (getOption(\"nobind\", 0, 0) != null)\n            np.mNobind = true;\n\n        if (getOption(\"persist-tun\", 0, 0) != null)\n            np.mPersistTun = true;\n\n        if (getOption(\"push-peer-info\", 0, 0) != null)\n            np.mPushPeerInfo = true;\n\n        Vector<String> connectretry = getOption(\"connect-retry\", 1, 2);\n        if (connectretry != null) {\n            np.mConnectRetry = connectretry.get(1);\n            if (connectretry.size() > 2)\n                np.mConnectRetryMaxTime = connectretry.get(2);\n        }\n\n        Vector<String> connectretrymax = getOption(\"connect-retry-max\", 1, 1);\n        if (connectretrymax != null)\n            np.mConnectRetryMax = connectretrymax.get(1);\n\n        Vector<Vector<String>> remotetls = getAllOption(\"remote-cert-tls\", 1, 1);\n        if (remotetls != null)\n            if (remotetls.get(0).get(1).equals(\"server\"))\n                np.mExpectTLSCert = true;\n            else\n                options.put(\"remotetls\", remotetls);\n\n        Vector<String> authuser = getOption(\"auth-user-pass\", 0, 1);\n\n        if (authuser != null) {\n            if (noauthtypeset) {\n                np.mAuthenticationType = VpnProfile.TYPE_USERPASS;\n            } else if (np.mAuthenticationType == VpnProfile.TYPE_CERTIFICATES) {\n                np.mAuthenticationType = VpnProfile.TYPE_USERPASS_CERTIFICATES;\n            } else if (np.mAuthenticationType == VpnProfile.TYPE_KEYSTORE) {\n                np.mAuthenticationType = VpnProfile.TYPE_USERPASS_KEYSTORE;\n            }\n            if (authuser.size() > 1) {\n                if (!authuser.get(1).startsWith(VpnProfile.INLINE_TAG))\n                    auth_user_pass_file = authuser.get(1);\n                np.mUsername = null;\n                useEmbbedUserAuth(np, authuser.get(1));\n            }\n        }\n\n        Vector<String> crlfile = getOption(\"crl-verify\", 1, 2);\n        if (crlfile != null) {\n            // If the 'dir' parameter is present just add it as custom option ..\n            if (crlfile.size() == 3 && crlfile.get(2).equals(\"dir\"))\n                np.mCustomConfigOptions += TextUtils.join(\" \", crlfile) + \"\\n\";\n            else\n                // Save the filename for the config converter to add later\n                np.mCrlFilename = crlfile.get(1);\n\n        }\n\n\n        Pair<Connection, Connection[]> conns = parseConnectionOptions(null);\n        np.mConnections = conns.second;\n\n        Vector<Vector<String>> connectionBlocks = getAllOption(\"connection\", 1, 1);\n\n        if (np.mConnections.length > 0 && connectionBlocks != null) {\n            throw new ConfigParseError(\"Using a <connection> block and --remote is not allowed.\");\n        }\n\n        if (connectionBlocks != null) {\n            np.mConnections = new Connection[connectionBlocks.size()];\n\n            int connIndex = 0;\n            for (Vector<String> conn : connectionBlocks) {\n                Pair<Connection, Connection[]> connectionBlockConnection =\n                        parseConnection(conn.get(1), conns.first);\n\n                if (connectionBlockConnection.second.length != 1)\n                    throw new ConfigParseError(\"A <connection> block must have exactly one remote\");\n                np.mConnections[connIndex] = connectionBlockConnection.second[0];\n                connIndex++;\n            }\n        }\n        if (getOption(\"remote-random\", 0, 0) != null)\n            np.mRemoteRandom = true;\n\n        Vector<String> protoforce = getOption(\"proto-force\", 1, 1);\n        if (protoforce != null) {\n            boolean disableUDP;\n            String protoToDisable = protoforce.get(1);\n            if (protoToDisable.equals(\"udp\"))\n                disableUDP = true;\n            else if (protoToDisable.equals(\"tcp\"))\n                disableUDP = false;\n            else\n                throw new ConfigParseError(String.format(\"Unknown protocol %s in proto-force\", protoToDisable));\n\n            for (Connection conn : np.mConnections)\n                if (conn.mUseUdp == disableUDP)\n                    conn.mEnabled = false;\n        }\n\n        // Parse OpenVPN Access Server extra\n        Vector<String> friendlyname = meta.get(\"FRIENDLY_NAME\");\n        if (friendlyname != null && friendlyname.size() > 1)\n            np.mName = friendlyname.get(1);\n\n\n        Vector<String> ocusername = meta.get(\"USERNAME\");\n        if (ocusername != null && ocusername.size() > 1)\n            np.mUsername = ocusername.get(1);\n\n        checkIgnoreAndInvalidOptions(np);\n        fixup(np);\n\n        return np;\n    }\n\n    private Pair<Connection, Connection[]> parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError {\n        // Parse a connection Block as a new configuration file\n\n\n        ConfigParser connectionParser = new ConfigParser();\n        StringReader reader = new StringReader(connection.substring(VpnProfile.INLINE_TAG.length()));\n        connectionParser.parseConfig(reader);\n\n        Pair<Connection, Connection[]> conn = connectionParser.parseConnectionOptions(defaultValues);\n\n        return conn;\n    }\n\n    private Pair<Connection, Connection[]> parseConnectionOptions(Connection connDefault) throws ConfigParseError {\n        Connection conn;\n        if (connDefault != null)\n            try {\n                conn = connDefault.clone();\n            } catch (CloneNotSupportedException e) {\n                e.printStackTrace();\n                return null;\n            }\n        else\n            conn = new Connection();\n\n        Vector<String> port = getOption(\"port\", 1, 1);\n        if (port != null) {\n            conn.mServerPort = port.get(1);\n        }\n\n        Vector<String> rport = getOption(\"rport\", 1, 1);\n        if (rport != null) {\n            conn.mServerPort = rport.get(1);\n        }\n\n        Vector<String> proto = getOption(\"proto\", 1, 1);\n        if (proto != null) {\n            conn.mUseUdp = isUdpProto(proto.get(1));\n        }\n\n        Vector<String> connectTimeout = getOption(\"connect-timeout\", 1, 1);\n        if (connectTimeout != null) {\n            try {\n                conn.mConnectTimeout = Integer.parseInt(connectTimeout.get(1));\n            } catch (NumberFormatException nfe) {\n                throw new ConfigParseError(String.format(\"Argument to connect-timeout (%s) must to be an integer: %s\",\n                        connectTimeout.get(1), nfe.getLocalizedMessage()));\n\n            }\n        }\n\n                    // Parse remote config\n        Vector<Vector<String>> remotes = getAllOption(\"remote\", 1, 3);\n\n\n        // Assume that we need custom options if connectionDefault are set\n        if (connDefault != null) {\n            for (Vector<Vector<String>> option : options.values()) {\n\n                conn.mCustomConfiguration += getOptionStrings(option);\n\n            }\n            if (!TextUtils.isEmpty(conn.mCustomConfiguration))\n                conn.mUseCustomConfig = true;\n        }\n        // Make remotes empty to simplify code\n        if (remotes == null)\n            remotes = new Vector<Vector<String>>();\n\n        Connection[] connections = new Connection[remotes.size()];\n\n\n        int i = 0;\n        for (Vector<String> remote : remotes) {\n            try {\n                connections[i] = conn.clone();\n            } catch (CloneNotSupportedException e) {\n                e.printStackTrace();\n            }\n            switch (remote.size()) {\n                case 4:\n                    connections[i].mUseUdp = isUdpProto(remote.get(3));\n                case 3:\n                    connections[i].mServerPort = remote.get(2);\n                case 2:\n                    connections[i].mServerName = remote.get(1);\n            }\n            i++;\n        }\n        return Pair.create(conn, connections);\n\n    }\n\n    private void checkRedirectParameters(VpnProfile np, Vector<Vector<String>> defgw) {\n        for (Vector<String> redirect : defgw)\n            for (int i = 1; i < redirect.size(); i++) {\n                if (redirect.get(i).equals(\"block-local\"))\n                    np.mAllowLocalLAN = false;\n                else if (redirect.get(i).equals(\"unblock-local\"))\n                    np.mAllowLocalLAN = true;\n            }\n    }\n\n    private boolean isUdpProto(String proto) throws ConfigParseError {\n        boolean isudp;\n        if (proto.equals(\"udp\") || proto.equals(\"udp6\"))\n            isudp = true;\n        else if (proto.equals(\"tcp-client\") ||\n                proto.equals(\"tcp\") ||\n                proto.equals(\"tcp6\") ||\n                proto.endsWith(\"tcp6-client\"))\n            isudp = false;\n        else\n            throw new ConfigParseError(\"Unsupported option to --proto \" + proto);\n        return isudp;\n    }\n\n    static public void useEmbbedUserAuth(VpnProfile np, String inlinedata) {\n        String data = VpnProfile.getEmbeddedContent(inlinedata);\n        String[] parts = data.split(\"\\n\");\n        if (parts.length >= 2) {\n            np.mUsername = parts[0];\n            np.mPassword = parts[1];\n        }\n    }\n\n    private void checkIgnoreAndInvalidOptions(VpnProfile np) throws ConfigParseError {\n        for (String option : unsupportedOptions)\n            if (options.containsKey(option))\n                throw new ConfigParseError(String.format(\"Unsupported Option %s encountered in config file. Aborting\", option));\n\n        for (String option : ignoreOptions)\n            // removing an item which is not in the map is no error\n            options.remove(option);\n\n\n        if (options.size() > 0) {\n            np.mCustomConfigOptions = \"# These options found in the config file do not map to config settings:\\n\"\n                    + np.mCustomConfigOptions;\n\n            for (Vector<Vector<String>> option : options.values()) {\n\n                np.mCustomConfigOptions += getOptionStrings(option);\n\n            }\n            np.mUseCustomConfig = true;\n\n        }\n    }\n\n\n    boolean ignoreThisOption(Vector<String> option) {\n        for (String[] ignoreOption : ignoreOptionsWithArg) {\n\n            if (option.size() < ignoreOption.length)\n                continue;\n\n            boolean ignore = true;\n            for (int i = 0; i < ignoreOption.length; i++) {\n                if (!ignoreOption[i].equals(option.get(i)))\n                    ignore = false;\n            }\n            if (ignore)\n                return true;\n\n        }\n        return false;\n    }\n\n    //! Generate options for custom options\n    private String getOptionStrings(Vector<Vector<String>> option) {\n        String custom = \"\";\n        for (Vector<String> optionsline : option) {\n            if (!ignoreThisOption(optionsline)) {\n                // Check if option had been inlined and inline again\n                if (optionsline.size() == 2 && \"extra-certs\".equals(optionsline.get(0)) ) {\n                    custom += VpnProfile.insertFileData(optionsline.get(0), optionsline.get(1));\n\n\n                } else {\n                    for (String arg : optionsline)\n                        custom += VpnProfile.openVpnEscape(arg) + \" \";\n                    custom += \"\\n\";\n                }\n            }\n        }\n        return custom;\n    }\n\n\n    private void fixup(VpnProfile np) {\n        if (np.mRemoteCN.equals(np.mServerName)) {\n            np.mRemoteCN = \"\";\n        }\n    }\n\n    private Vector<String> getOption(String option, int minarg, int maxarg) throws ConfigParseError {\n        Vector<Vector<String>> alloptions = getAllOption(option, minarg, maxarg);\n        if (alloptions == null)\n            return null;\n        else\n            return alloptions.lastElement();\n    }\n\n\n    private Vector<Vector<String>> getAllOption(String option, int minarg, int maxarg) throws ConfigParseError {\n        Vector<Vector<String>> args = options.get(option);\n        if (args == null)\n            return null;\n\n        for (Vector<String> optionline : args)\n\n            if (optionline.size() < (minarg + 1) || optionline.size() > maxarg + 1) {\n                String err = String.format(Locale.getDefault(), \"Option %s has %d parameters, expected between %d and %d\",\n                        option, optionline.size() - 1, minarg, maxarg);\n                throw new ConfigParseError(err);\n            }\n        options.remove(option);\n        return args;\n    }\n\n}\n\n\n\n\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/Connection.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.text.TextUtils;\n\nimport java.io.Serializable;\n\npublic class Connection implements Serializable, Cloneable {\n    public String mServerName = \"openvpn.blinkt.de\";\n    public String mServerPort = \"1194\";\n    public boolean mUseUdp = true;\n    public String mCustomConfiguration = \"\";\n    public boolean mUseCustomConfig = false;\n    public boolean mEnabled = true;\n    public int mConnectTimeout = 0;\n    public static final int CONNECTION_DEFAULT_TIMEOUT = 120;\n\n    private static final long serialVersionUID = 92031902903829089L;\n\n\n    public String getConnectionBlock() {\n        String cfg = \"\";\n\n        // Server Address\n        cfg += \"remote \";\n        cfg += mServerName;\n        cfg += \" \";\n        cfg += mServerPort;\n        if (mUseUdp)\n            cfg += \" udp\\n\";\n        else\n            cfg += \" tcp-client\\n\";\n\n        if (mConnectTimeout != 0)\n            cfg += String.format(\" connect-timeout  %d\\n\", mConnectTimeout);\n\n\n        if (!TextUtils.isEmpty(mCustomConfiguration) && mUseCustomConfig) {\n            cfg += mCustomConfiguration;\n            cfg += \"\\n\";\n        }\n        return cfg;\n    }\n\n    @Override\n    public Connection clone() throws CloneNotSupportedException {\n        return (Connection) super.clone();\n    }\n\n    public boolean isOnlyRemote() {\n        return TextUtils.isEmpty(mCustomConfiguration) || !mUseCustomConfig;\n    }\n\n    public int getTimeout() {\n        if (mConnectTimeout <= 0)\n            return CONNECTION_DEFAULT_TIMEOUT;\n        else\n            return mConnectTimeout;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.SharedPreferences;\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\nimport android.net.NetworkInfo.State;\nimport android.os.Handler;\nimport android.preference.PreferenceManager;\n\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport de.blinkt.openvpn.core.VpnStatus.ByteCountListener;\n\nimport java.util.LinkedList;\nimport java.util.Objects;\n\nimport static de.blinkt.openvpn.core.OpenVPNManagement.pauseReason;\n\npublic class DeviceStateReceiver extends BroadcastReceiver implements ByteCountListener, OpenVPNManagement.PausedStateCallback {\n    private final Handler mDisconnectHandler;\n    private int lastNetwork = -1;\n    private OpenVPNManagement mManagement;\n\n    // Window time in s\n    private final int TRAFFIC_WINDOW = 60;\n    // Data traffic limit in bytes\n    private final long TRAFFIC_LIMIT = 64 * 1024;\n\n    // Time to wait after network disconnect to pause the VPN\n    private final int DISCONNECT_WAIT = 20;\n\n\n    connectState network = connectState.DISCONNECTED;\n    connectState screen = connectState.SHOULDBECONNECTED;\n    connectState userpause = connectState.SHOULDBECONNECTED;\n\n    private String lastStateMsg = null;\n    private java.lang.Runnable mDelayDisconnectRunnable = new Runnable() {\n        @Override\n        public void run() {\n            if (!(network == connectState.PENDINGDISCONNECT))\n                return;\n\n            network = connectState.DISCONNECTED;\n\n            // Set screen state to be disconnected if disconnect pending\n            if (screen == connectState.PENDINGDISCONNECT)\n                screen = connectState.DISCONNECTED;\n\n            mManagement.pause(getPauseReason());\n        }\n    };\n    private NetworkInfo lastConnectedNetwork;\n\n    @Override\n    public boolean shouldBeRunning() {\n        return shouldBeConnected();\n    }\n\n    enum connectState {\n        SHOULDBECONNECTED,\n        PENDINGDISCONNECT,\n        DISCONNECTED\n    }\n\n    static class Datapoint {\n        private Datapoint(long t, long d) {\n            timestamp = t;\n            data = d;\n        }\n\n        long timestamp;\n        long data;\n    }\n\n    LinkedList<Datapoint> trafficdata = new LinkedList<DeviceStateReceiver.Datapoint>();\n\n\n    @Override\n    public void updateByteCount(long in, long out, long diffIn, long diffOut) {\n        if (screen != connectState.PENDINGDISCONNECT)\n            return;\n\n        long total = diffIn + diffOut;\n        trafficdata.add(new Datapoint(System.currentTimeMillis(), total));\n\n        while (trafficdata.getFirst().timestamp <= (System.currentTimeMillis() - TRAFFIC_WINDOW * 1000)) {\n            trafficdata.removeFirst();\n        }\n\n        long windowtraffic = 0;\n        for (Datapoint dp : trafficdata)\n            windowtraffic += dp.data;\n\n        if (windowtraffic < TRAFFIC_LIMIT) {\n            screen = connectState.DISCONNECTED;\n            VpnStatus.logInfo(R.string.screenoff_pause,\n                    OpenVPNService.humanReadableByteCount(TRAFFIC_LIMIT, false), TRAFFIC_WINDOW);\n\n            mManagement.pause(getPauseReason());\n        }\n    }\n\n\n    public void userPause(boolean pause) {\n        if (pause) {\n            userpause = connectState.DISCONNECTED;\n            // Check if we should disconnect\n            mManagement.pause(getPauseReason());\n        } else {\n            boolean wereConnected = shouldBeConnected();\n            userpause = connectState.SHOULDBECONNECTED;\n            if (shouldBeConnected() && !wereConnected)\n                mManagement.resume();\n            else\n                // Update the reason why we currently paused\n                mManagement.pause(getPauseReason());\n        }\n    }\n\n    public DeviceStateReceiver(OpenVPNManagement magnagement) {\n        super();\n        mManagement = magnagement;\n        mManagement.setPauseCallback(this);\n        mDisconnectHandler = new Handler();\n    }\n\n\n    @Override\n    public void onReceive(Context context, Intent intent) {\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);\n\n\n        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {\n            networkStateChange(context);\n        } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {\n            boolean screenOffPause = prefs.getBoolean(\"screenoff\", false);\n\n            if (screenOffPause) {\n                if (ProfileManager.getLastConnectedVpn() != null && !ProfileManager.getLastConnectedVpn().mPersistTun)\n                    VpnStatus.logError(R.string.screen_nopersistenttun);\n\n                screen = connectState.PENDINGDISCONNECT;\n                fillTrafficData();\n                if (network == connectState.DISCONNECTED || userpause == connectState.DISCONNECTED)\n                    screen = connectState.DISCONNECTED;\n            }\n        } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {\n            // Network was disabled because screen off\n            boolean connected = shouldBeConnected();\n            screen = connectState.SHOULDBECONNECTED;\n\n            /* We should connect now, cancel any outstanding disconnect timer */\n            mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable);\n            /* should be connected has changed because the screen is on now, connect the VPN */\n            if (shouldBeConnected() != connected)\n                mManagement.resume();\n            else if (!shouldBeConnected())\n                /*Update the reason why we are still paused */\n                mManagement.pause(getPauseReason());\n\n        }\n    }\n\n\n    private void fillTrafficData() {\n        trafficdata.add(new Datapoint(System.currentTimeMillis(), TRAFFIC_LIMIT));\n    }\n    public static boolean equalsObj(Object a, Object b) {\n        return (a == null) ? (b == null) : a.equals(b);\n    }\n\n\n\n    public void networkStateChange(Context context) {\n        NetworkInfo networkInfo = getCurrentNetworkInfo(context);\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);\n        boolean sendusr1 = prefs.getBoolean(\"netchangereconnect\", true);\n\n\n        String netstatestring;\n        if (networkInfo == null) {\n            netstatestring = \"not connected\";\n        } else {\n            String subtype = networkInfo.getSubtypeName();\n            if (subtype == null)\n                subtype = \"\";\n            String extrainfo = networkInfo.getExtraInfo();\n            if (extrainfo == null)\n                extrainfo = \"\";\n\n\t\t\t/*\n            if(networkInfo.getType()==android.net.ConnectivityManager.TYPE_WIFI) {\n\t\t\t\tWifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);\n\t\t\t\tWifiInfo wifiinfo = wifiMgr.getConnectionInfo();\n\t\t\t\textrainfo+=wifiinfo.getBSSID();\n\n\t\t\t\tsubtype += wifiinfo.getNetworkId();\n\t\t\t}*/\n\n\n            netstatestring = String.format(\"%2$s %4$s to %1$s %3$s\", networkInfo.getTypeName(),\n                    networkInfo.getDetailedState(), extrainfo, subtype);\n        }\n\n        if (networkInfo != null && networkInfo.getState() == State.CONNECTED) {\n            int newnet = networkInfo.getType();\n\n            boolean pendingDisconnect = (network == connectState.PENDINGDISCONNECT);\n            network = connectState.SHOULDBECONNECTED;\n\n            boolean sameNetwork;\n            if (lastConnectedNetwork == null\n                    || lastConnectedNetwork.getType() != networkInfo.getType()\n                    || !equalsObj(lastConnectedNetwork.getExtraInfo(), networkInfo.getExtraInfo())\n                    )\n                sameNetwork = false;\n            else\n                sameNetwork = true;\n\n            /* Same network, connection still 'established' */\n            if (pendingDisconnect && sameNetwork) {\n                mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable);\n                // Reprotect the sockets just be sure\n                mManagement.networkChange(true);\n            } else {\n                /* Different network or connection not established anymore */\n\n                if (screen == connectState.PENDINGDISCONNECT)\n                    screen = connectState.DISCONNECTED;\n\n                if (shouldBeConnected()) {\n                    mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable);\n\n                    if (pendingDisconnect || !sameNetwork)\n                        mManagement.networkChange(sameNetwork);\n                    else\n                        mManagement.resume();\n                }\n\n                lastNetwork = newnet;\n                lastConnectedNetwork = networkInfo;\n            }\n        } else if (networkInfo == null) {\n            // Not connected, stop openvpn, set last connected network to no network\n            lastNetwork = -1;\n            if (sendusr1) {\n                network = connectState.PENDINGDISCONNECT;\n                mDisconnectHandler.postDelayed(mDelayDisconnectRunnable, DISCONNECT_WAIT * 1000);\n\n            }\n        }\n\n\n        if (!netstatestring.equals(lastStateMsg))\n            VpnStatus.logInfo(R.string.netstatus, netstatestring);\n        lastStateMsg = netstatestring;\n\n    }\n\n\n    public boolean isUserPaused() {\n        return userpause == connectState.DISCONNECTED;\n    }\n\n    private boolean shouldBeConnected() {\n        return (screen == connectState.SHOULDBECONNECTED && userpause == connectState.SHOULDBECONNECTED &&\n                network == connectState.SHOULDBECONNECTED);\n    }\n\n    private pauseReason getPauseReason() {\n        if (userpause == connectState.DISCONNECTED)\n            return pauseReason.userPause;\n\n        if (screen == connectState.DISCONNECTED)\n            return pauseReason.screenOff;\n\n        if (network == connectState.DISCONNECTED)\n            return pauseReason.noNetwork;\n\n        return pauseReason.userPause;\n    }\n\n    private NetworkInfo getCurrentNetworkInfo(Context context) {\n        ConnectivityManager conn = (ConnectivityManager)\n                context.getSystemService(Context.CONNECTIVITY_SERVICE);\n\n        return conn.getActiveNetworkInfo();\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\nimport android.app.Application;\n\n/*\nimport org.acra.ACRA;\nimport org.acra.ReportingInteractionMode;\nimport org.acra.annotation.ReportsCrashes;\n*/\n\n\n\nimport com.vasilkoff.easyvpnfree.BuildConfig;\n\nimport de.blinkt.openvpn.core.PRNGFixes;\n\n/*\n@ReportsCrashes(\n        formKey = \"\",\n        formUri = \"http://reports.blinkt.de/report-icsopenvpn\",\n        reportType = org.acra.sender.HttpSender.Type.JSON,\n        httpMethod = org.acra.sender.HttpSender.Method.PUT,\n        formUriBasicAuthLogin=\"report-icsopenvpn\",\n        formUriBasicAuthPassword=\"Tohd4neiF9Ai!!!!111eleven\",\n        mode = ReportingInteractionMode.TOAST,\n        resToastText = R.string.crash_toast_text\n)\n*/\npublic class ICSOpenVPNApplication extends Application {\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        PRNGFixes.apply();\n\n        if (BuildConfig.DEBUG) {\n            //ACRA.init(this);\n        }\n\n        VpnStatus.initLogCache(getApplicationContext().getCacheDir());\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java",
    "content": "/*\n * Copyright (c) 2012-2015 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.os.Message;\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport java.io.BufferedInputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.nio.BufferOverflowException;\nimport java.nio.ByteBuffer;\nimport java.util.Locale;\n\n\n\n/**\n * Created by arne on 23.01.16.\n */\nclass LogFileHandler extends Handler {\n    static final int TRIM_LOG_FILE = 100;\n    static final int FLUSH_TO_DISK = 101;\n    static final int LOG_INIT = 102;\n    public static final int LOG_MESSAGE = 103;\n    public static final int MAGIC_BYTE = 0x55;\n    protected OutputStream mLogFile;\n\n    public static final String LOGFILE_NAME = \"logcache.dat\";\n\n\n    public LogFileHandler(Looper looper) {\n        super(looper);\n    }\n\n\n    @Override\n    public void handleMessage(Message msg) {\n        try {\n            if (msg.what == LOG_INIT) {\n                if (mLogFile != null)\n                    throw new RuntimeException(\"mLogFile not null\");\n                readLogCache((File) msg.obj);\n                openLogFile((File) msg.obj);\n            } else if (msg.what == LOG_MESSAGE && msg.obj instanceof LogItem) {\n                // Ignore log messages if not yet initialized\n                if (mLogFile == null)\n                    return;\n                writeLogItemToDisk((LogItem) msg.obj);\n            } else if (msg.what == TRIM_LOG_FILE) {\n                trimLogFile();\n                for (LogItem li : VpnStatus.getlogbuffer())\n                    writeLogItemToDisk(li);\n            } else if (msg.what == FLUSH_TO_DISK) {\n                flushToDisk();\n            }\n\n        } catch (IOException | BufferOverflowException e) {\n            e.printStackTrace();\n            VpnStatus.logError(\"Error during log cache: \" + msg.what);\n            VpnStatus.logException(e);\n        }\n\n    }\n\n    private void flushToDisk() throws IOException {\n        mLogFile.flush();\n    }\n\n    private void trimLogFile() {\n        try {\n            mLogFile.flush();\n            ((FileOutputStream) mLogFile).getChannel().truncate(0);\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n\n    private void writeLogItemToDisk(LogItem li) throws IOException {\n\n        // We do not really care if the log cache breaks between Android upgrades,\n        // write binary format to disc\n\n        byte[] liBytes = li.getMarschaledBytes();\n\n        writeEscapedBytes(liBytes);\n    }\n\n    public void writeEscapedBytes(byte[] bytes) throws IOException {\n        int magic = 0;\n        for (byte b : bytes)\n            if (b == MAGIC_BYTE || b == MAGIC_BYTE + 1)\n                magic++;\n\n        byte eBytes[] = new byte[bytes.length + magic];\n\n        int i = 0;\n        for (byte b : bytes) {\n            if (b == MAGIC_BYTE || b == MAGIC_BYTE + 1) {\n                eBytes[i++] = MAGIC_BYTE + 1;\n                eBytes[i++] = (byte) (b - MAGIC_BYTE);\n            } else {\n                eBytes[i++] = b;\n            }\n        }\n\n        byte[] lenBytes = ByteBuffer.allocate(4).putInt(bytes.length).array();\n        synchronized (mLogFile) {\n            mLogFile.write(MAGIC_BYTE);\n            mLogFile.write(lenBytes);\n            mLogFile.write(eBytes);\n        }\n    }\n\n    private void openLogFile(File cacheDir) throws FileNotFoundException {\n        File logfile = new File(cacheDir, LOGFILE_NAME);\n        mLogFile = new FileOutputStream(logfile);\n    }\n\n    private void readLogCache(File cacheDir) {\n        try {\n            File logfile = new File(cacheDir, LOGFILE_NAME);\n\n\n            if (!logfile.exists() || !logfile.canRead())\n                return;\n\n            readCacheContents(new FileInputStream(logfile));\n\n        } catch (java.io.IOException | java.lang.RuntimeException e ) {\n            VpnStatus.logError(\"Reading cached logfile failed\");\n            VpnStatus.logException(e);\n            e.printStackTrace();\n            // ignore reading file error\n        }\n    }\n\n\n    protected void readCacheContents(InputStream in) throws IOException {\n\n\n        BufferedInputStream logFile = new BufferedInputStream(in);\n\n        byte[] buf = new byte[16384];\n        int read = logFile.read(buf, 0, 5);\n        int itemsRead = 0;\n\n\n        readloop:\n        while (read >= 5) {\n            int skipped = 0;\n            while (buf[skipped] != MAGIC_BYTE) {\n                skipped++;\n                if (!(logFile.read(buf, skipped + 4, 1) == 1) || skipped + 10 > buf.length) {\n                    VpnStatus.logDebug(String.format(Locale.US, \"Skipped %d bytes and no a magic byte found\", skipped));\n                    break readloop;\n                }\n            }\n            if (skipped > 0)\n                VpnStatus.logDebug(String.format(Locale.US, \"Skipped %d bytes before finding a magic byte\", skipped));\n\n            int len = ByteBuffer.wrap(buf, skipped+1, 4).asIntBuffer().get();\n\n            // Marshalled LogItem\n            int pos = 0;\n            byte buf2[] = new byte[buf.length];\n\n            while (pos < len) {\n                byte b = (byte) logFile.read();\n                if (b == MAGIC_BYTE) {\n                    VpnStatus.logDebug(String.format(Locale.US, \"Unexpected magic byte found at pos %d, abort current log item\", pos));\n                    read = logFile.read(buf, 1, 4) + 1;\n                    continue readloop;\n                } else if (b == MAGIC_BYTE + 1) {\n                    b = (byte) logFile.read();\n                    if (b == 0)\n                        b = MAGIC_BYTE;\n                    else if (b == 1)\n                        b = MAGIC_BYTE + 1;\n                    else {\n                        VpnStatus.logDebug(String.format(Locale.US, \"Escaped byte not 0 or 1: %d\", b));\n                        read = logFile.read(buf, 1, 4) + 1;\n                        continue readloop;\n                    }\n                }\n                buf2[pos++] = b;\n            }\n\n            restoreLogItem(buf2, len);\n\n            //Next item\n            read = logFile.read(buf, 0, 5);\n            itemsRead++;\n            if (itemsRead > 2 * VpnStatus.MAXLOGENTRIES) {\n                VpnStatus.logError(\"Too many logentries read from cache, aborting.\");\n                read = 0;\n            }\n\n        }\n        VpnStatus.logDebug(R.string.reread_log, itemsRead);\n\n\n    }\n\n    protected void restoreLogItem(byte[] buf, int len) throws UnsupportedEncodingException {\n\n        LogItem li = new LogItem(buf, len);\n        if (li.verify()) {\n            VpnStatus.newLogItem(li, true);\n        } else {\n            VpnStatus.logError(String.format(Locale.getDefault(),\n                    \"Could not read log item from file: %d: %s\",\n                     len, bytesToHex(buf, Math.max(len, 80))));\n        }\n    }\n\n    final protected static char[] hexArray = \"0123456789ABCDEF\".toCharArray();\n\n    public static String bytesToHex(byte[] bytes, int len) {\n        len = Math.min(bytes.length, len);\n        char[] hexChars = new char[len * 2];\n        for (int j = 0; j < len; j++) {\n            int v = bytes[j] & 0xFF;\n            hexChars[j * 2] = hexArray[v >>> 4];\n            hexChars[j * 2 + 1] = hexArray[v & 0x0F];\n        }\n        return new String(hexChars);\n    }\n\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/LogItem.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.content.pm.Signature;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.nio.BufferOverflowException;\nimport java.nio.ByteBuffer;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.X509Certificate;\nimport java.util.Arrays;\nimport java.util.FormatFlagsConversionMismatchException;\nimport java.util.Locale;\nimport java.util.UnknownFormatConversionException;\n\n\n\n/**\n * Created by arne on 24.04.16.\n */\npublic class LogItem implements Parcelable {\n    private Object[] mArgs = null;\n    private String mMessage = null;\n    private int mRessourceId;\n    // Default log priority\n    VpnStatus.LogLevel mLevel = VpnStatus.LogLevel.INFO;\n    private long logtime = System.currentTimeMillis();\n    private int mVerbosityLevel = -1;\n\n    private LogItem(int ressourceId, Object[] args) {\n        mRessourceId = ressourceId;\n        mArgs = args;\n    }\n\n    public LogItem(VpnStatus.LogLevel level, int verblevel, String message) {\n        mMessage = message;\n        mLevel = level;\n        mVerbosityLevel = verblevel;\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n        dest.writeArray(mArgs);\n        dest.writeString(mMessage);\n        dest.writeInt(mRessourceId);\n        dest.writeInt(mLevel.getInt());\n        dest.writeInt(mVerbosityLevel);\n\n        dest.writeLong(logtime);\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (!(obj instanceof LogItem))\n            return obj.equals(this);\n        LogItem other = (LogItem) obj;\n\n        return Arrays.equals(mArgs, other.mArgs) &&\n                ((other.mMessage == null && mMessage == other.mMessage) ||\n                        mMessage.equals(other.mMessage)) &&\n                mRessourceId == other.mRessourceId &&\n                ((mLevel == null && other.mLevel == mLevel) ||\n                        other.mLevel.equals(mLevel)) &&\n                mVerbosityLevel == other.mVerbosityLevel &&\n                logtime == other.logtime;\n\n\n    }\n\n    public byte[] getMarschaledBytes() throws UnsupportedEncodingException, BufferOverflowException {\n        ByteBuffer bb = ByteBuffer.allocate(16384);\n\n\n        bb.put((byte) 0x0);               //version\n        bb.putLong(logtime);              //8\n        bb.putInt(mVerbosityLevel);      //4\n        bb.putInt(mLevel.getInt());\n        bb.putInt(mRessourceId);\n        if (mMessage == null || mMessage.length() == 0) {\n            bb.putInt(0);\n        } else {\n            marschalString(mMessage, bb);\n        }\n        if (mArgs == null || mArgs.length == 0) {\n            bb.putInt(0);\n        } else {\n            bb.putInt(mArgs.length);\n            for (Object o : mArgs) {\n                if (o instanceof String) {\n                    bb.putChar('s');\n                    marschalString((String) o, bb);\n                } else if (o instanceof Integer) {\n                    bb.putChar('i');\n                    bb.putInt((Integer) o);\n                } else if (o instanceof Float) {\n                    bb.putChar('f');\n                    bb.putFloat((Float) o);\n                } else if (o instanceof Double) {\n                    bb.putChar('d');\n                    bb.putDouble((Double) o);\n                } else if (o instanceof Long) {\n                    bb.putChar('l');\n                    bb.putLong((Long) o);\n                } else if (o == null) {\n                    bb.putChar('0');\n                } else {\n                    VpnStatus.logDebug(\"Unknown object for LogItem marschaling \" + o);\n                    bb.putChar('s');\n                    marschalString(o.toString(), bb);\n                }\n\n            }\n        }\n\n        int pos = bb.position();\n        bb.rewind();\n        return Arrays.copyOf(bb.array(), pos);\n\n    }\n\n    public LogItem(byte[] in, int length) throws UnsupportedEncodingException {\n        ByteBuffer bb = ByteBuffer.wrap(in, 0, length);\n        bb.get(); // ignore version\n        logtime = bb.getLong();\n        mVerbosityLevel = bb.getInt();\n        mLevel = VpnStatus.LogLevel.getEnumByValue(bb.getInt());\n        mRessourceId = bb.getInt();\n        int len = bb.getInt();\n        if (len == 0) {\n            mMessage = null;\n        } else {\n            if (len > bb.remaining())\n                throw new IndexOutOfBoundsException(\"String length \" + len + \" is bigger than remaining bytes \" + bb.remaining());\n            byte[] utf8bytes = new byte[len];\n            bb.get(utf8bytes);\n            mMessage = new String(utf8bytes, \"UTF-8\");\n        }\n        int numArgs = bb.getInt();\n        if (numArgs > 30) {\n            throw new IndexOutOfBoundsException(\"Too many arguments for Logitem to unmarschal\");\n        }\n        if (numArgs == 0) {\n            mArgs = null;\n        } else {\n            mArgs = new Object[numArgs];\n            for (int i = 0; i < numArgs; i++) {\n                char type = bb.getChar();\n                switch (type) {\n                    case 's':\n                        mArgs[i] = unmarschalString(bb);\n                        break;\n                    case 'i':\n                        mArgs[i] = bb.getInt();\n                        break;\n                    case 'd':\n                        mArgs[i] = bb.getDouble();\n                        break;\n                    case 'f':\n                        mArgs[i] = bb.getFloat();\n                        break;\n                    case 'l':\n                        mArgs[i] = bb.getLong();\n                        break;\n                    case '0':\n                        mArgs[i] = null;\n                        break;\n                    default:\n                        throw new UnsupportedEncodingException(\"Unknown format type: \" + type);\n                }\n            }\n        }\n        if (bb.hasRemaining())\n            throw new UnsupportedEncodingException(bb.remaining() + \" bytes left after unmarshaling everything\");\n    }\n\n    private void marschalString(String str, ByteBuffer bb) throws UnsupportedEncodingException {\n        byte[] utf8bytes = str.getBytes(\"UTF-8\");\n        bb.putInt(utf8bytes.length);\n        bb.put(utf8bytes);\n    }\n\n    private String unmarschalString(ByteBuffer bb) throws UnsupportedEncodingException {\n        int len = bb.getInt();\n        byte[] utf8bytes = new byte[len];\n        bb.get(utf8bytes);\n        return new String(utf8bytes, \"UTF-8\");\n    }\n\n\n    public LogItem(Parcel in) {\n        mArgs = in.readArray(Object.class.getClassLoader());\n        mMessage = in.readString();\n        mRessourceId = in.readInt();\n        mLevel = VpnStatus.LogLevel.getEnumByValue(in.readInt());\n        mVerbosityLevel = in.readInt();\n        logtime = in.readLong();\n    }\n\n    public static final Creator<LogItem> CREATOR\n            = new Creator<LogItem>() {\n        public LogItem createFromParcel(Parcel in) {\n            return new LogItem(in);\n        }\n\n        public LogItem[] newArray(int size) {\n            return new LogItem[size];\n        }\n    };\n\n    public LogItem(VpnStatus.LogLevel loglevel, int ressourceId, Object... args) {\n        mRessourceId = ressourceId;\n        mArgs = args;\n        mLevel = loglevel;\n    }\n\n\n    public LogItem(VpnStatus.LogLevel loglevel, String msg) {\n        mLevel = loglevel;\n        mMessage = msg;\n    }\n\n\n    public LogItem(VpnStatus.LogLevel loglevel, int ressourceId) {\n        mRessourceId = ressourceId;\n        mLevel = loglevel;\n    }\n\n    public String getString(Context c) {\n        try {\n            if (mMessage != null) {\n                return mMessage;\n            } else {\n                if (c != null) {\n                    if (mRessourceId == R.string.mobile_info)\n                        return getMobileInfoString(c);\n                    if (mArgs == null)\n                        return c.getString(mRessourceId);\n                    else\n                        return c.getString(mRessourceId, mArgs);\n                } else {\n                    String str = String.format(Locale.ENGLISH, \"Log (no context) resid %d\", mRessourceId);\n                    if (mArgs != null)\n                        str += join(\"|\", mArgs);\n\n                    return str;\n                }\n            }\n        } catch (UnknownFormatConversionException e) {\n            if (c != null)\n                throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null));\n            else\n                throw e;\n        } catch (java.util.FormatFlagsConversionMismatchException e) {\n            if (c != null)\n                throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion());\n            else\n                throw e;\n        }\n\n    }\n\n\n    // TextUtils.join will cause not macked exeception in tests ....\n    public static String join(CharSequence delimiter, Object[] tokens) {\n        StringBuilder sb = new StringBuilder();\n        boolean firstTime = true;\n        for (Object token : tokens) {\n            if (firstTime) {\n                firstTime = false;\n            } else {\n                sb.append(delimiter);\n            }\n            sb.append(token);\n        }\n        return sb.toString();\n    }\n\n\n    public VpnStatus.LogLevel getLogLevel() {\n        return mLevel;\n    }\n\n\n    @Override\n    public String toString() {\n        return getString(null);\n    }\n\n    // The lint is wrong here\n    @SuppressLint(\"StringFormatMatches\")\n    private String getMobileInfoString(Context c) {\n        c.getPackageManager();\n        String apksign = \"error getting package signature\";\n\n        String version = \"error getting version\";\n        try {\n            @SuppressLint(\"PackageManagerGetSignatures\")\n            Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];\n            CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");\n            X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));\n            MessageDigest md = MessageDigest.getInstance(\"SHA-1\");\n            byte[] der = cert.getEncoded();\n            md.update(der);\n            byte[] digest = md.digest();\n\n            if (Arrays.equals(digest, VpnStatus.officalkey))\n                apksign = c.getString(R.string.official_build);\n            else if (Arrays.equals(digest, VpnStatus.officaldebugkey))\n                apksign = c.getString(R.string.debug_build);\n            else if (Arrays.equals(digest, VpnStatus.amazonkey))\n                apksign = \"amazon version\";\n            else if (Arrays.equals(digest, VpnStatus.fdroidkey))\n                apksign = \"F-Droid built and signed version\";\n            else\n                apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName());\n\n            PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);\n            version = packageinfo.versionName;\n\n        } catch (PackageManager.NameNotFoundException | CertificateException |\n                NoSuchAlgorithmException ignored) {\n        }\n\n        Object[] argsext = Arrays.copyOf(mArgs, mArgs.length);\n        argsext[argsext.length - 1] = apksign;\n        argsext[argsext.length - 2] = version;\n\n        return c.getString(R.string.mobile_info, argsext);\n\n    }\n\n    public long getLogtime() {\n        return logtime;\n    }\n\n\n    public int getVerbosityLevel() {\n        if (mVerbosityLevel == -1) {\n            // Hack:\n            // For message not from OpenVPN, report the status level as log level\n            return mLevel.getInt();\n        }\n        return mVerbosityLevel;\n    }\n\n    public boolean verify() {\n        if (mLevel == null)\n            return false;\n\n        if (mMessage == null && mRessourceId == 0)\n            return false;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/LollipopDeviceStateListener.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.annotation.TargetApi;\nimport android.net.ConnectivityManager;\nimport android.net.LinkProperties;\nimport android.net.Network;\nimport android.net.NetworkCapabilities;\nimport android.os.Build;\n\n/**\n * Created by arne on 26.11.14.\n */\n@TargetApi(Build.VERSION_CODES.LOLLIPOP)\npublic class LollipopDeviceStateListener extends ConnectivityManager.NetworkCallback {\n\n    private String mLastConnectedStatus;\n    private String mLastLinkProperties;\n    private String mLastNetworkCapabilities;\n\n    @Override\n    public void onAvailable(Network network) {\n        super.onAvailable(network);\n\n        if (!network.toString().equals(mLastConnectedStatus)) {\n            mLastConnectedStatus = network.toString();\n            VpnStatus.logDebug(\"Connected to \" + mLastConnectedStatus);\n        }\n    }\n\n    @Override\n    public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {\n        super.onLinkPropertiesChanged(network, linkProperties);\n\n        if (!linkProperties.toString().equals(mLastLinkProperties)) {\n            mLastLinkProperties = linkProperties.toString();\n            VpnStatus.logDebug(String.format(\"Linkproperties of %s: %s\", network, linkProperties));\n        }\n    }\n\n    @Override\n    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {\n        super.onCapabilitiesChanged(network, networkCapabilities);\n        if (!networkCapabilities.toString().equals(mLastNetworkCapabilities)) {\n            mLastNetworkCapabilities = networkCapabilities.toString();\n            VpnStatus.logDebug(String.format(\"Network capabilities of %s: %s\", network, networkCapabilities));\n        }\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.os.Build;\n\nimport java.security.InvalidKeyException;\n\npublic class NativeUtils {\n    public static native byte[] rsasign(byte[] input, int pkey) throws InvalidKeyException;\n\n    public static native String[] getIfconfig() throws IllegalArgumentException;\n\n    static native void jniclose(int fdint);\n\n    public static native String getNativeAPI();\n\n    static {\n        System.loadLibrary(\"opvpnutil\");\n        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)\n            System.loadLibrary(\"jbcrypto\");\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.os.Build;\nimport android.support.annotation.NonNull;\nimport android.text.TextUtils;\n\nimport com.vasilkoff.easyvpnfree.BuildConfig;\n\nimport junit.framework.Assert;\n\nimport java.math.BigInteger;\nimport java.net.Inet6Address;\nimport java.util.Collection;\nimport java.util.Locale;\nimport java.util.PriorityQueue;\nimport java.util.TreeSet;\nimport java.util.Vector;\n\n\n\npublic class NetworkSpace {\n\n    static class ipAddress implements Comparable<ipAddress> {\n        private BigInteger netAddress;\n        public int networkMask;\n        private boolean included;\n        private boolean isV4;\n        private BigInteger firstAddress;\n        private BigInteger lastAddress;\n\n\n        /**\n         * sorts the networks with following criteria:\n         * 1. compares first 1 of the network\n         * 2. smaller networks are returned as smaller\n         */\n        @Override\n        public int compareTo(@NonNull ipAddress another) {\n            int comp = getFirstAddress().compareTo(another.getFirstAddress());\n            if (comp != 0)\n                return comp;\n\n\n            if (networkMask > another.networkMask)\n                return -1;\n            else if (another.networkMask == networkMask)\n                return 0;\n            else\n                return 1;\n        }\n\n        /**\n         * Warning ignores the included integer\n         *\n         * @param o the object to compare this instance with.\n         */\n        @Override\n        public boolean equals(Object o) {\n            if (!(o instanceof ipAddress))\n                return super.equals(o);\n\n\n            ipAddress on = (ipAddress) o;\n            return (networkMask == on.networkMask) && on.getFirstAddress().equals(getFirstAddress());\n        }\n\n        public ipAddress(CIDRIP ip, boolean include) {\n            included = include;\n            netAddress = BigInteger.valueOf(ip.getInt());\n            networkMask = ip.len;\n            isV4 = true;\n        }\n\n        public ipAddress(Inet6Address address, int mask, boolean include) {\n            networkMask = mask;\n            included = include;\n\n            int s = 128;\n\n            netAddress = BigInteger.ZERO;\n            for (byte b : address.getAddress()) {\n                s -= 8;\n                netAddress = netAddress.add(BigInteger.valueOf((b & 0xFF)).shiftLeft(s));\n            }\n        }\n\n        public BigInteger getLastAddress() {\n            if (lastAddress == null)\n                lastAddress = getMaskedAddress(true);\n            return lastAddress;\n        }\n\n\n        public BigInteger getFirstAddress() {\n            if (firstAddress == null)\n                firstAddress = getMaskedAddress(false);\n            return firstAddress;\n        }\n\n\n        private BigInteger getMaskedAddress(boolean one) {\n            BigInteger numAddress = netAddress;\n\n            int numBits;\n            if (isV4) {\n                numBits = 32 - networkMask;\n            } else {\n                numBits = 128 - networkMask;\n            }\n\n            for (int i = 0; i < numBits; i++) {\n                if (one)\n                    numAddress = numAddress.setBit(i);\n                else\n                    numAddress = numAddress.clearBit(i);\n            }\n            return numAddress;\n        }\n\n\n        @Override\n        public String toString() {\n            //String in = included ? \"+\" : \"-\";\n            if (isV4)\n                return String.format(Locale.US, \"%s/%d\", getIPv4Address(), networkMask);\n            else\n                return String.format(Locale.US, \"%s/%d\", getIPv6Address(), networkMask);\n        }\n\n        ipAddress(BigInteger baseAddress, int mask, boolean included, boolean isV4) {\n            this.netAddress = baseAddress;\n            this.networkMask = mask;\n            this.included = included;\n            this.isV4 = isV4;\n        }\n\n\n        public ipAddress[] split() {\n            ipAddress firstHalf = new ipAddress(getFirstAddress(), networkMask + 1, included, isV4);\n            ipAddress secondHalf = new ipAddress(firstHalf.getLastAddress().add(BigInteger.ONE), networkMask + 1, included, isV4);\n            if (BuildConfig.DEBUG)\n                Assert.assertTrue(secondHalf.getLastAddress().equals(getLastAddress()));\n            return new ipAddress[]{firstHalf, secondHalf};\n        }\n\n        String getIPv4Address() {\n            if (BuildConfig.DEBUG) {\n                Assert.assertTrue(isV4);\n                Assert.assertTrue(netAddress.longValue() <= 0xffffffffl);\n                Assert.assertTrue(netAddress.longValue() >= 0);\n            }\n            long ip = netAddress.longValue();\n            return String.format(Locale.US, \"%d.%d.%d.%d\", (ip >> 24) % 256, (ip >> 16) % 256, (ip >> 8) % 256, ip % 256);\n        }\n\n        String getIPv6Address() {\n            if (BuildConfig.DEBUG) Assert.assertTrue(!isV4);\n            BigInteger r = netAddress;\n\n            String ipv6str = null;\n            boolean lastPart = true;\n\n            while (r.compareTo(BigInteger.ZERO) == 1) {\n\n                long part = r.mod(BigInteger.valueOf(0x10000)).longValue();\n                if (ipv6str != null || part != 0) {\n                    if (ipv6str == null && !lastPart)\n                            ipv6str = \":\";\n\n                    if (lastPart)\n                        ipv6str = String.format(Locale.US, \"%x\", part, ipv6str);\n                    else\n                        ipv6str = String.format(Locale.US, \"%x:%s\", part, ipv6str);\n                }\n\n                r = r.shiftRight(16);\n                lastPart = false;\n            }\n            if (ipv6str == null)\n                return \"::\";\n\n\n            return ipv6str;\n        }\n\n        public boolean containsNet(ipAddress network) {\n            // this.first >= net.first &&  this.last <= net.last\n            BigInteger ourFirst = getFirstAddress();\n            BigInteger ourLast = getLastAddress();\n            BigInteger netFirst = network.getFirstAddress();\n            BigInteger netLast = network.getLastAddress();\n\n            boolean a = ourFirst.compareTo(netFirst) != 1;\n            boolean b = ourLast.compareTo(netLast) != -1;\n            return a && b;\n\n        }\n    }\n\n\n    TreeSet<ipAddress> mIpAddresses = new TreeSet<ipAddress>();\n\n\n    public Collection<ipAddress> getNetworks(boolean included) {\n        Vector<ipAddress> ips = new Vector<ipAddress>();\n        for (ipAddress ip : mIpAddresses) {\n            if (ip.included == included)\n                ips.add(ip);\n        }\n        return ips;\n    }\n\n    public void clear() {\n        mIpAddresses.clear();\n    }\n\n\n    void addIP(CIDRIP cidrIp, boolean include) {\n\n        mIpAddresses.add(new ipAddress(cidrIp, include));\n    }\n\n    public void addIPSplit(CIDRIP cidrIp, boolean include) {\n        ipAddress newIP = new ipAddress(cidrIp, include);\n        ipAddress[] splitIps = newIP.split();\n        for (ipAddress split : splitIps)\n            mIpAddresses.add(split);\n    }\n\n    void addIPv6(Inet6Address address, int mask, boolean included) {\n        mIpAddresses.add(new ipAddress(address, mask, included));\n    }\n\n    TreeSet<ipAddress> generateIPList() {\n\n        PriorityQueue<ipAddress> networks = new PriorityQueue<ipAddress>(mIpAddresses);\n\n        TreeSet<ipAddress> ipsDone = new TreeSet<ipAddress>();\n\n        ipAddress currentNet = networks.poll();\n        if (currentNet == null)\n            return ipsDone;\n\n        while (currentNet != null) {\n            // Check if it and the next of it are compatible\n            ipAddress nextNet = networks.poll();\n\n            if (BuildConfig.DEBUG) Assert.assertNotNull(currentNet);\n            if (nextNet == null || currentNet.getLastAddress().compareTo(nextNet.getFirstAddress()) == -1) {\n                // Everything good, no overlapping nothing to do\n                ipsDone.add(currentNet);\n\n                currentNet = nextNet;\n            } else {\n                // This network is smaller or equal to the next but has the same base address\n                if (currentNet.getFirstAddress().equals(nextNet.getFirstAddress()) && currentNet.networkMask >= nextNet.networkMask) {\n                    if (currentNet.included == nextNet.included) {\n                        // Included in the next next and same type\n                        // Simply forget our current network\n                        currentNet = nextNet;\n                    } else {\n                        // our currentNet is included in next and types differ. Need to split the next network\n                        ipAddress[] newNets = nextNet.split();\n\n\n                        // TODO: The contains method of the Priority is stupid linear search\n\n                        // First add the second half to keep the order in networks\n                        if (!networks.contains(newNets[1]))\n                            networks.add(newNets[1]);\n\n                        if (newNets[0].getLastAddress().equals(currentNet.getLastAddress())) {\n                            if (BuildConfig.DEBUG)\n                                Assert.assertEquals(newNets[0].networkMask, currentNet.networkMask);\n                            // Don't add the lower half that would conflict with currentNet\n                        } else {\n                            if (!networks.contains(newNets[0]))\n                                networks.add(newNets[0]);\n                        }\n                        // Keep currentNet as is\n                    }\n                } else {\n                    if (BuildConfig.DEBUG) {\n                        Assert.assertTrue(currentNet.networkMask < nextNet.networkMask);\n                        Assert.assertTrue(nextNet.getFirstAddress().compareTo(currentNet.getFirstAddress()) == 1);\n                        Assert.assertTrue(currentNet.getLastAddress().compareTo(nextNet.getLastAddress()) != -1);\n                    }\n                    // This network is bigger than the next and last ip of current >= next\n\n                    //noinspection StatementWithEmptyBody\n                    if (currentNet.included == nextNet.included) {\n                        // Next network is in included in our network with the same type,\n                        // simply ignore the next and move on\n                    } else {\n                        // We need to split our network\n                        ipAddress[] newNets = currentNet.split();\n\n\n                        if (newNets[1].networkMask == nextNet.networkMask) {\n                            if (BuildConfig.DEBUG) {\n                                Assert.assertTrue(newNets[1].getFirstAddress().equals(nextNet.getFirstAddress()));\n                                Assert.assertTrue(newNets[1].getLastAddress().equals(currentNet.getLastAddress()));\n                                // split second equal the next network, do not add it\n                            }\n                            networks.add(nextNet);\n                        } else {\n                            // Add the smaller network first\n                            networks.add(newNets[1]);\n                            networks.add(nextNet);\n                        }\n                        currentNet = newNets[0];\n\n                    }\n                }\n            }\n\n        }\n\n        return ipsDone;\n    }\n\n    Collection<ipAddress> getPositiveIPList() {\n        TreeSet<ipAddress> ipsSorted = generateIPList();\n\n        Vector<ipAddress> ips = new Vector<ipAddress>();\n        for (ipAddress ia : ipsSorted) {\n            if (ia.included)\n                ips.add(ia);\n        }\n\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            // Include postive routes from the original set under < 4.4 since these might overrule the local\n            // network but only if no smaller negative route exists\n            for (ipAddress origIp : mIpAddresses) {\n                if (!origIp.included)\n                    continue;\n\n                // The netspace exists\n                if (ipsSorted.contains(origIp))\n                    continue;\n\n                boolean skipIp = false;\n                // If there is any smaller net that is excluded we may not add the positive route back\n\n                for (ipAddress calculatedIp : ipsSorted) {\n                    if (!calculatedIp.included && origIp.containsNet(calculatedIp)) {\n                        skipIp = true;\n                        break;\n                    }\n                }\n                if (skipIp)\n                    continue;\n\n                // It is safe to include the IP\n                ips.add(origIp);\n            }\n\n        }\n\n        return ips;\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\npublic interface OpenVPNManagement {\n    interface PausedStateCallback {\n        boolean shouldBeRunning();\n    }\n\n    enum pauseReason {\n        noNetwork,\n        userPause,\n        screenOff,\n    }\n\n    int mBytecountInterval = 2;\n\n    void reconnect();\n\n    void pause(pauseReason reason);\n\n    void resume();\n\n    /**\n     * @param replaceConnection True if the VPN is connected by a new connection.\n     * @return true if there was a process that has been send a stop signal\n     */\n    boolean stopVPN(boolean replaceConnection);\n\n    /*\n     * Rebind the interface\n     */\n    void networkChange(boolean sameNetwork);\n\n    void setPauseCallback(PausedStateCallback callback);\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.Manifest.permission;\nimport android.annotation.TargetApi;\nimport android.app.Notification;\nimport android.app.NotificationManager;\nimport android.app.PendingIntent;\nimport android.app.UiModeManager;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.content.SharedPreferences;\nimport android.content.pm.PackageManager;\nimport android.content.res.Configuration;\nimport android.net.ConnectivityManager;\nimport android.net.VpnService;\nimport android.os.Binder;\nimport android.os.Build;\nimport android.os.Handler;\nimport android.os.Handler.Callback;\nimport android.os.IBinder;\nimport android.os.Message;\nimport android.os.ParcelFileDescriptor;\nimport android.preference.PreferenceManager;\n\nimport android.system.OsConstants;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.widget.Toast;\n\nimport com.vasilkoff.easyvpnfree.BuildConfig;\n\n\nimport com.vasilkoff.easyvpnfree.R;\nimport com.vasilkoff.easyvpnfree.activity.ServerActivity;\nimport com.vasilkoff.easyvpnfree.util.TotalTraffic;\n\n\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.Inet6Address;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.util.Collection;\nimport java.util.Locale;\nimport java.util.Vector;\n\n\nimport de.blinkt.openvpn.VpnProfile;\nimport de.blinkt.openvpn.core.VpnStatus.ByteCountListener;\nimport de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;\nimport de.blinkt.openvpn.core.VpnStatus.StateListener;\n\nimport static de.blinkt.openvpn.core.NetworkSpace.ipAddress;\nimport static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTED;\nimport static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;\n\npublic class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener {\n    public static final String START_SERVICE = \"de.blinkt.openvpn.START_SERVICE\";\n    public static final String START_SERVICE_STICKY = \"de.blinkt.openvpn.START_SERVICE_STICKY\";\n    public static final String ALWAYS_SHOW_NOTIFICATION = \"de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE\";\n    public static final String DISCONNECT_VPN = \"de.blinkt.openvpn.DISCONNECT_VPN\";\n    private static final String PAUSE_VPN = \"de.blinkt.openvpn.PAUSE_VPN\";\n    private static final String RESUME_VPN = \"de.blinkt.openvpn.RESUME_VPN\";\n    private static final int OPENVPN_STATUS = 1;\n    private static boolean mNotificationAlwaysVisible = false;\n    private final Vector<String> mDnslist = new Vector<>();\n    private final NetworkSpace mRoutes = new NetworkSpace();\n    private final NetworkSpace mRoutesv6 = new NetworkSpace();\n    private final IBinder mBinder = new LocalBinder();\n    private Thread mProcessThread = null;\n    private VpnProfile mProfile;\n    private String mDomain = null;\n    private CIDRIP mLocalIP = null;\n    private int mMtu;\n    private String mLocalIPv6 = null;\n    private DeviceStateReceiver mDeviceStateReceiver;\n    private boolean mDisplayBytecount = false;\n    private boolean mStarting = false;\n    private long mConnecttime;\n    private boolean mOvpn3 = false;\n    private OpenVPNManagement mManagement;\n    private String mLastTunCfg;\n    private String mRemoteGW;\n    private final Object mProcessLock = new Object();\n    private Handler guiHandler;\n    private Toast mlastToast;\n    private Runnable mOpenVPNThread;\n\n    // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java\n    public static String humanReadableByteCount(long bytes, boolean mbit) {\n        if (mbit)\n            bytes = bytes * 8;\n        int unit = mbit ? 1000 : 1024;\n        if (bytes < unit)\n            return bytes + (mbit ? \" bit\" : \" B\");\n\n        int exp = (int) (Math.log(bytes) / Math.log(unit));\n        String pre = (mbit ? \"kMGTPE\" : \"KMGTPE\").charAt(exp - 1) + (mbit ? \"\" : \"\");\n        if (mbit)\n            return String.format(Locale.getDefault(), \"%.1f %sbit\", bytes / Math.pow(unit, exp), pre);\n        else\n            return String.format(Locale.getDefault(), \"%.1f %sB\", bytes / Math.pow(unit, exp), pre);\n    }\n\n    @Override\n    public IBinder onBind(Intent intent) {\n        String action = intent.getAction();\n        if (action != null && action.equals(START_SERVICE))\n            return mBinder;\n        else\n            return super.onBind(intent);\n    }\n\n    @Override\n    public void onRevoke() {\n        VpnStatus.logError(R.string.permission_revoked);\n        mManagement.stopVPN(false);\n        endVpnService();\n    }\n\n    // Similar to revoke but do not try to stop process\n    public void processDied() {\n        endVpnService();\n    }\n\n    private void endVpnService() {\n        synchronized (mProcessLock) {\n            mProcessThread = null;\n        }\n        VpnStatus.removeByteCountListener(this);\n        unregisterDeviceStateReceiver();\n        ProfileManager.setConntectedVpnProfileDisconnected(this);\n        mOpenVPNThread = null;\n        if (!mStarting) {\n            stopForeground(!mNotificationAlwaysVisible);\n\n            if (!mNotificationAlwaysVisible) {\n                stopSelf();\n                VpnStatus.removeStateListener(this);\n            }\n        }\n    }\n\n    private void showNotification(final String msg, String tickerText, boolean lowpriority, long when, ConnectionStatus status) {\n        String ns = Context.NOTIFICATION_SERVICE;\n        NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);\n\n\n        //int icon = getIconByConnectionStatus(status);\n        int icon = R.drawable.ic_app_notif;\n        android.app.Notification.Builder nbuilder = new Notification.Builder(this);\n\n        if (mProfile != null)\n            nbuilder.setContentTitle(getString(R.string.notification_title, mProfile.mName));\n        else\n            nbuilder.setContentTitle(getString(R.string.notifcation_title_notconnect));\n\n        nbuilder.setContentText(msg);\n        nbuilder.setOnlyAlertOnce(true);\n        nbuilder.setOngoing(true);\n        nbuilder.setContentIntent(getLogPendingIntent());\n        nbuilder.setSmallIcon(icon);\n\n\n        if (when != 0)\n            nbuilder.setWhen(when);\n\n\n        // Try to set the priority available since API 16 (Jellybean)\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)\n            jbNotificationExtras(lowpriority, nbuilder);\n\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)\n            lpNotificationExtras(nbuilder);\n\n        if (tickerText != null && !tickerText.equals(\"\"))\n            nbuilder.setTicker(tickerText);\n\n        @SuppressWarnings(\"deprecation\")\n        Notification notification = nbuilder.getNotification();\n\n\n        mNotificationManager.notify(OPENVPN_STATUS, notification);\n        startForeground(OPENVPN_STATUS, notification);\n\n        // Check if running on a TV\n        if (runningOnAndroidTV() && !lowpriority)\n            guiHandler.post(new Runnable() {\n\n                @Override\n                public void run() {\n\n                    if (mlastToast != null)\n                        mlastToast.cancel();\n                    String toastText = String.format(Locale.getDefault(), \"%s - %s\", mProfile.mName, msg);\n                    mlastToast = Toast.makeText(getBaseContext(), toastText, Toast.LENGTH_SHORT);\n                    mlastToast.show();\n                }\n            });\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    private void lpNotificationExtras(Notification.Builder nbuilder) {\n        nbuilder.setCategory(Notification.CATEGORY_SERVICE);\n        nbuilder.setLocalOnly(true);\n\n    }\n\n    private boolean runningOnAndroidTV() {\n        UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);\n        return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;\n    }\n\n    /*private int getIconByConnectionStatus(ConnectionStatus level) {\n        switch (level) {\n            case LEVEL_CONNECTED:\n                return R.drawable.ic_stat_vpn;\n            case LEVEL_AUTH_FAILED:\n            case LEVEL_NONETWORK:\n            case LEVEL_NOTCONNECTED:\n                return R.drawable.ic_stat_vpn_offline;\n            case LEVEL_CONNECTING_NO_SERVER_REPLY_YET:\n            case LEVEL_WAITING_FOR_USER_INPUT:\n                return R.drawable.ic_stat_vpn_outline;\n            case LEVEL_CONNECTING_SERVER_REPLIED:\n                return R.drawable.ic_stat_vpn_empty_halo;\n            case LEVEL_VPNPAUSED:\n                return android.R.drawable.ic_media_pause;\n            case UNKNOWN_LEVEL:\n            default:\n                return R.drawable.ic_stat_vpn;\n\n        }\n    }*/\n\n    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)\n    private void jbNotificationExtras(boolean lowpriority,\n                                      android.app.Notification.Builder nbuilder) {\n        try {\n            if (lowpriority) {\n                Method setpriority = nbuilder.getClass().getMethod(\"setPriority\", int.class);\n                // PRIORITY_MIN == -2\n                setpriority.invoke(nbuilder, -2);\n\n                Method setUsesChronometer = nbuilder.getClass().getMethod(\"setUsesChronometer\", boolean.class);\n                setUsesChronometer.invoke(nbuilder, true);\n\n            }\n\n            Intent disconnectVPN = new Intent(this, OpenVPNService.class);\n            disconnectVPN.setAction(DISCONNECT_VPN);\n            PendingIntent disconnectPendingIntent = PendingIntent.getService(\n                    this, 0, disconnectVPN, 0);\n\n            nbuilder.addAction(R.drawable.ic_menu_close_clear_cancel,\n                    getString(R.string.cancel_connection), disconnectPendingIntent);\n\n            Intent pauseVPN = new Intent(this, OpenVPNService.class);\n            if (mDeviceStateReceiver == null || !mDeviceStateReceiver.isUserPaused()) {\n                pauseVPN.setAction(PAUSE_VPN);\n                PendingIntent pauseVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0);\n                nbuilder.addAction(R.drawable.ic_menu_pause,\n                        getString(R.string.pauseVPN), pauseVPNPending);\n\n            } else {\n                pauseVPN.setAction(RESUME_VPN);\n                PendingIntent resumeVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0);\n                nbuilder.addAction(R.drawable.ic_menu_play,\n                        getString(R.string.resumevpn), resumeVPNPending);\n            }\n\n\n            //ignore exception\n        } catch (NoSuchMethodException | IllegalArgumentException |\n                InvocationTargetException | IllegalAccessException e) {\n            VpnStatus.logException(e);\n        }\n\n    }\n\n    PendingIntent getLogPendingIntent() {\n        // Let the configure Button show the Log\n        Intent intent = new Intent(getBaseContext(), ServerActivity.class);\n        //intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);\n        PendingIntent startLW = PendingIntent.getActivity(this, 0, intent, 0);\n        return startLW;\n    }\n\n\n    synchronized void registerDeviceStateReceiver(OpenVPNManagement magnagement) {\n        // Registers BroadcastReceiver to track network connection changes.\n        IntentFilter filter = new IntentFilter();\n        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);\n        filter.addAction(Intent.ACTION_SCREEN_OFF);\n        filter.addAction(Intent.ACTION_SCREEN_ON);\n        mDeviceStateReceiver = new DeviceStateReceiver(magnagement);\n        registerReceiver(mDeviceStateReceiver, filter);\n        VpnStatus.addByteCountListener(mDeviceStateReceiver);\n\n        /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)\n            addLollipopCMListener(); */\n    }\n\n    synchronized void unregisterDeviceStateReceiver() {\n        if (mDeviceStateReceiver != null)\n            try {\n                VpnStatus.removeByteCountListener(mDeviceStateReceiver);\n                this.unregisterReceiver(mDeviceStateReceiver);\n            } catch (IllegalArgumentException iae) {\n                // I don't know why  this happens:\n                // java.lang.IllegalArgumentException: Receiver not registered: de.blinkt.openvpn.NetworkSateReceiver@41a61a10\n                // Ignore for now ...\n                iae.printStackTrace();\n            }\n        mDeviceStateReceiver = null;\n\n        /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)\n            removeLollipopCMListener();*/\n\n    }\n\n    public void userPause(boolean shouldBePaused) {\n        if (mDeviceStateReceiver != null)\n            mDeviceStateReceiver.userPause(shouldBePaused);\n    }\n\n    @Override\n    public int onStartCommand(Intent intent, int flags, int startId) {\n\n        if (intent != null && intent.getBooleanExtra(ALWAYS_SHOW_NOTIFICATION, false))\n            mNotificationAlwaysVisible = true;\n\n        VpnStatus.addStateListener(this);\n        VpnStatus.addByteCountListener(this);\n\n        guiHandler = new Handler(getMainLooper());\n\n\n        if (intent != null && DISCONNECT_VPN.equals(intent.getAction())) {\n            if (mManagement != null)\n                mManagement.stopVPN(false);\n            return START_NOT_STICKY;\n        }\n\n        if (intent != null && PAUSE_VPN.equals(intent.getAction())) {\n            if (mDeviceStateReceiver != null)\n                mDeviceStateReceiver.userPause(true);\n            return START_NOT_STICKY;\n        }\n\n        if (intent != null && RESUME_VPN.equals(intent.getAction())) {\n            if (mDeviceStateReceiver != null)\n                mDeviceStateReceiver.userPause(false);\n            return START_NOT_STICKY;\n        }\n\n\n        if (intent != null && START_SERVICE.equals(intent.getAction()))\n            return START_NOT_STICKY;\n        if (intent != null && START_SERVICE_STICKY.equals(intent.getAction())) {\n            return START_REDELIVER_INTENT;\n        }\n\n        if (intent != null && intent.hasExtra(getPackageName() + \".profileUUID\")) {\n            String profileUUID = intent.getStringExtra(getPackageName() + \".profileUUID\");\n            mProfile = ProfileManager.get(this, profileUUID);\n        } else {\n            /* The intent is null when we are set as always-on or the service has been restarted. */\n            mProfile = ProfileManager.getLastConnectedProfile(this);\n            VpnStatus.logInfo(R.string.service_restarted);\n\n            /* Got no profile, just stop */\n            if (mProfile == null) {\n                Log.d(\"OpenVPN\", \"Got no last connected profile on null intent. Assuming always on.\");\n                mProfile = ProfileManager.getAlwaysOnVPN(this);\n\n                if (mProfile==null) {\n                    stopSelf(startId);\n                    return START_NOT_STICKY;\n                }\n            }\n            /* Do the asynchronous keychain certificate stuff */\n            mProfile.checkForRestart(this);\n\n            /* Recreate the intent */\n            intent = mProfile.getStartServiceIntent(this);\n        }\n\n        /* start the OpenVPN process itself in a background thread */\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                startOpenVPN();\n            }\n        }).start();\n\n\n        ProfileManager.setConnectedVpnProfile(this, mProfile);\n        /* TODO: At the moment we have no way to handle asynchronous PW input\n         * Fixing will also allow to handle challenge/response authentication */\n        if (mProfile.needUserPWInput(true) != 0)\n            return START_NOT_STICKY;\n\n        return START_STICKY;\n    }\n\n    private void startOpenVPN() {\n        VpnStatus.logInfo(R.string.building_configration);\n        VpnStatus.updateStateString(\"VPN_GENERATE_CONFIG\", \"\", R.string.building_configration, VpnStatus.ConnectionStatus.LEVEL_START);\n\n\n        try {\n            mProfile.writeConfigFile(this);\n        } catch (IOException e) {\n            VpnStatus.logException(\"Error writing config file\", e);\n            endVpnService();\n            return;\n        }\n\n        // Extract information from the intent.\n        String prefix = getPackageName();\n        String nativeLibraryDirectory = getApplicationInfo().nativeLibraryDir;\n\n        // Also writes OpenVPN binary\n        String[] argv = VPNLaunchHelper.buildOpenvpnArgv(this);\n\n\n        // Set a flag that we are starting a new VPN\n        mStarting = true;\n        // Stop the previous session by interrupting the thread.\n\n        stopOldOpenVPNProcess();\n        // An old running VPN should now be exited\n        mStarting = false;\n\n        // Start a new session by creating a new thread.\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);\n\n        mOvpn3 = prefs.getBoolean(\"ovpn3\", false);\n        if (!\"ovpn3\".equals(BuildConfig.FLAVOR))\n            mOvpn3 = false;\n\n        // Open the Management Interface\n        if (!mOvpn3) {\n            // start a Thread that handles incoming messages of the managment socket\n            OpenVpnManagementThread ovpnManagementThread = new OpenVpnManagementThread(mProfile, this);\n            if (ovpnManagementThread.openManagementInterface(this)) {\n\n                Thread mSocketManagerThread = new Thread(ovpnManagementThread, \"OpenVPNManagementThread\");\n                mSocketManagerThread.start();\n                mManagement = ovpnManagementThread;\n                VpnStatus.logInfo(\"started Socket Thread\");\n            } else {\n                endVpnService();\n                return;\n            }\n        }\n\n        Runnable processThread;\n        if (mOvpn3)\n\n        {\n\n            OpenVPNManagement mOpenVPN3 = instantiateOpenVPN3Core();\n            processThread = (Runnable) mOpenVPN3;\n            mManagement = mOpenVPN3;\n\n\n        } else {\n            processThread = new OpenVPNThread(this, argv, nativeLibraryDirectory);\n            mOpenVPNThread = processThread;\n        }\n\n        synchronized (mProcessLock)\n\n        {\n            mProcessThread = new Thread(processThread, \"OpenVPNProcessThread\");\n            mProcessThread.start();\n        }\n\n        new Handler(getMainLooper()).post(new Runnable() {\n                         @Override\n                         public void run() {\n                             if (mDeviceStateReceiver != null)\n                                 unregisterDeviceStateReceiver();\n\n                             registerDeviceStateReceiver(mManagement);\n                         }\n                     }\n\n                );\n    }\n\n    private void stopOldOpenVPNProcess() {\n        if (mManagement != null) {\n            if (mOpenVPNThread!=null)\n                ((OpenVPNThread) mOpenVPNThread).setReplaceConnection();\n            if (mManagement.stopVPN(true)) {\n                // an old was asked to exit, wait 1s\n                try {\n                    Thread.sleep(1000);\n                } catch (InterruptedException e) {\n                    //ignore\n                }\n            }\n        }\n\n        synchronized (mProcessLock) {\n            if (mProcessThread != null) {\n                mProcessThread.interrupt();\n                try {\n                    Thread.sleep(1000);\n                } catch (InterruptedException e) {\n                    //ignore\n                }\n            }\n        }\n    }\n\n    private OpenVPNManagement instantiateOpenVPN3Core() {\n        try {\n            Class cl = Class.forName(\"de.blinkt.openvpn.core.OpenVPNThreadv3\");\n            return (OpenVPNManagement) cl.getConstructor(OpenVPNService.class, VpnProfile.class).newInstance(this, mProfile);\n        } catch (IllegalArgumentException | InstantiationException | InvocationTargetException |\n                NoSuchMethodException | ClassNotFoundException | IllegalAccessException e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n\n    @Override\n    public void onDestroy() {\n        synchronized (mProcessLock) {\n            if (mProcessThread != null) {\n                mManagement.stopVPN(true);\n            }\n        }\n\n        if (mDeviceStateReceiver != null) {\n            this.unregisterReceiver(mDeviceStateReceiver);\n        }\n        // Just in case unregister for state\n        VpnStatus.removeStateListener(this);\n        VpnStatus.flushLog();\n\n    }\n\n    private String getTunConfigString() {\n        // The format of the string is not important, only that\n        // two identical configurations produce the same result\n        String cfg = \"TUNCFG UNQIUE STRING ips:\";\n\n        if (mLocalIP != null)\n            cfg += mLocalIP.toString();\n        if (mLocalIPv6 != null)\n            cfg += mLocalIPv6;\n\n\n        cfg += \"routes: \" + TextUtils.join(\"|\", mRoutes.getNetworks(true)) + TextUtils.join(\"|\", mRoutesv6.getNetworks(true));\n        cfg += \"excl. routes:\" + TextUtils.join(\"|\", mRoutes.getNetworks(false)) + TextUtils.join(\"|\", mRoutesv6.getNetworks(false));\n        cfg += \"dns: \" + TextUtils.join(\"|\", mDnslist);\n        cfg += \"domain: \" + mDomain;\n        cfg += \"mtu: \" + mMtu;\n        return cfg;\n    }\n\n    public ParcelFileDescriptor openTun() {\n\n        //Debug.startMethodTracing(getExternalFilesDir(null).toString() + \"/opentun.trace\", 40* 1024 * 1024);\n\n        Builder builder = new Builder();\n\n        VpnStatus.logInfo(R.string.last_openvpn_tun_config);\n\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) {\n            allowAllAFFamilies(builder);\n        }\n\n        if (mLocalIP == null && mLocalIPv6 == null) {\n            VpnStatus.logError(getString(R.string.opentun_no_ipaddr));\n            return null;\n        }\n\n        if (mLocalIP != null) {\n            addLocalNetworksToRoutes();\n            try {\n                builder.addAddress(mLocalIP.mIp, mLocalIP.len);\n            } catch (IllegalArgumentException iae) {\n                VpnStatus.logError(R.string.dns_add_error, mLocalIP, iae.getLocalizedMessage());\n                return null;\n            }\n        }\n\n        if (mLocalIPv6 != null) {\n            String[] ipv6parts = mLocalIPv6.split(\"/\");\n            try {\n                builder.addAddress(ipv6parts[0], Integer.parseInt(ipv6parts[1]));\n            } catch (IllegalArgumentException iae) {\n                VpnStatus.logError(R.string.ip_add_error, mLocalIPv6, iae.getLocalizedMessage());\n                return null;\n            }\n\n        }\n\n\n        for (String dns : mDnslist) {\n            try {\n                builder.addDnsServer(dns);\n            } catch (IllegalArgumentException iae) {\n                VpnStatus.logError(R.string.dns_add_error, dns, iae.getLocalizedMessage());\n            }\n        }\n\n        String release = Build.VERSION.RELEASE;\n        if ((Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith(\"4.4.3\")\n                && !release.startsWith(\"4.4.4\") && !release.startsWith(\"4.4.5\") && !release.startsWith(\"4.4.6\"))\n                && mMtu < 1280) {\n            VpnStatus.logInfo(String.format(Locale.US, \"Forcing MTU to 1280 instead of %d to workaround Android Bug #70916\", mMtu));\n            builder.setMtu(1280);\n        } else {\n            builder.setMtu(mMtu);\n        }\n\n        Collection<ipAddress> positiveIPv4Routes = mRoutes.getPositiveIPList();\n        Collection<ipAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList();\n\n        if (\"samsung\".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mDnslist.size() >= 1) {\n            // Check if the first DNS Server is in the VPN range\n            try {\n                ipAddress dnsServer = new ipAddress(new CIDRIP(mDnslist.get(0), 32), true);\n                boolean dnsIncluded = false;\n                for (ipAddress net : positiveIPv4Routes) {\n                    if (net.containsNet(dnsServer)) {\n                        dnsIncluded = true;\n                    }\n                }\n                if (!dnsIncluded) {\n                    String samsungwarning = String.format(\"Warning Samsung Android 5.0+ devices ignore DNS servers outside the VPN range. To enable DNS resolution a route to your DNS Server (%s) has been added.\", mDnslist.get(0));\n                    VpnStatus.logWarning(samsungwarning);\n                    positiveIPv4Routes.add(dnsServer);\n                }\n            } catch (Exception e) {\n                VpnStatus.logError(\"Error parsing DNS Server IP: \" + mDnslist.get(0));\n            }\n        }\n\n        ipAddress multicastRange = new ipAddress(new CIDRIP(\"224.0.0.0\", 3), true);\n\n        for (NetworkSpace.ipAddress route : positiveIPv4Routes) {\n            try {\n\n                if (multicastRange.containsNet(route))\n                    VpnStatus.logDebug(R.string.ignore_multicast_route, route.toString());\n                else\n                    builder.addRoute(route.getIPv4Address(), route.networkMask);\n            } catch (IllegalArgumentException ia) {\n                VpnStatus.logError(getString(R.string.route_rejected) + route + \" \" + ia.getLocalizedMessage());\n            }\n        }\n\n        for (NetworkSpace.ipAddress route6 : positiveIPv6Routes) {\n            try {\n                builder.addRoute(route6.getIPv6Address(), route6.networkMask);\n            } catch (IllegalArgumentException ia) {\n                VpnStatus.logError(getString(R.string.route_rejected) + route6 + \" \" + ia.getLocalizedMessage());\n            }\n        }\n\n\n        if (mDomain != null)\n            builder.addSearchDomain(mDomain);\n\n        VpnStatus.logInfo(R.string.local_ip_info, mLocalIP.mIp, mLocalIP.len, mLocalIPv6, mMtu);\n        VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(\", \", mDnslist), mDomain);\n        VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(\", \", mRoutes.getNetworks(true)), TextUtils.join(\", \", mRoutesv6.getNetworks(true)));\n        VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(\", \", mRoutes.getNetworks(false)), TextUtils.join(\", \", mRoutesv6.getNetworks(false)));\n        VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(\", \", positiveIPv4Routes), TextUtils.join(\", \", positiveIPv6Routes));\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            setAllowedVpnPackages(builder);\n        }\n\n\n        String session = mProfile.mName;\n        if (mLocalIP != null && mLocalIPv6 != null)\n            session = getString(R.string.session_ipv6string, session, mLocalIP, mLocalIPv6);\n        else if (mLocalIP != null)\n            session = getString(R.string.session_ipv4string, session, mLocalIP);\n\n        builder.setSession(session);\n\n        // No DNS Server, log a warning\n        if (mDnslist.size() == 0)\n            VpnStatus.logInfo(R.string.warn_no_dns);\n\n        mLastTunCfg = getTunConfigString();\n\n        // Reset information\n        mDnslist.clear();\n        mRoutes.clear();\n        mRoutesv6.clear();\n        mLocalIP = null;\n        mLocalIPv6 = null;\n        mDomain = null;\n\n        builder.setConfigureIntent(getLogPendingIntent());\n\n        try {\n            //Debug.stopMethodTracing();\n            ParcelFileDescriptor tun = builder.establish();\n            if (tun == null)\n                throw new NullPointerException(\"Android establish() method returned null (Really broken network configuration?)\");\n            return tun;\n        } catch (Exception e) {\n            VpnStatus.logError(R.string.tun_open_error);\n            VpnStatus.logError(getString(R.string.error) + e.getLocalizedMessage());\n            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {\n                VpnStatus.logError(R.string.tun_error_helpful);\n            }\n            return null;\n        }\n\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    private void allowAllAFFamilies(Builder builder) {\n        builder.allowFamily(OsConstants.AF_INET);\n        builder.allowFamily(OsConstants.AF_INET6);\n    }\n\n    private void addLocalNetworksToRoutes() {\n\n        // Add local network interfaces\n        String[] localRoutes = NativeUtils.getIfconfig();\n\n        // The format of mLocalRoutes is kind of broken because I don't really like JNI\n        for (int i = 0; i < localRoutes.length; i += 3) {\n            String intf = localRoutes[i];\n            String ipAddr = localRoutes[i + 1];\n            String netMask = localRoutes[i + 2];\n\n            if (intf == null || intf.equals(\"lo\") ||\n                    intf.startsWith(\"tun\") || intf.startsWith(\"rmnet\"))\n                continue;\n\n            if (ipAddr == null || netMask == null) {\n                VpnStatus.logError(\"Local routes are broken?! (Report to author) \" + TextUtils.join(\"|\", localRoutes));\n                continue;\n            }\n\n            if (ipAddr.equals(mLocalIP.mIp))\n                continue;\n\n            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT && !mProfile.mAllowLocalLAN) {\n                mRoutes.addIPSplit(new CIDRIP(ipAddr, netMask), true);\n\n            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mProfile.mAllowLocalLAN)\n                mRoutes.addIP(new CIDRIP(ipAddr, netMask), false);\n        }\n    }\n\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    private void setAllowedVpnPackages(Builder builder) {\n        boolean atLeastOneAllowedApp = false;\n        for (String pkg : mProfile.mAllowedAppsVpn) {\n            try {\n                if (mProfile.mAllowedAppsVpnAreDisallowed) {\n                    builder.addDisallowedApplication(pkg);\n                } else {\n                    builder.addAllowedApplication(pkg);\n                    atLeastOneAllowedApp = true;\n                }\n            } catch (PackageManager.NameNotFoundException e) {\n                mProfile.mAllowedAppsVpn.remove(pkg);\n                VpnStatus.logInfo(R.string.app_no_longer_exists, pkg);\n            }\n        }\n\n        if (!mProfile.mAllowedAppsVpnAreDisallowed && !atLeastOneAllowedApp) {\n            VpnStatus.logDebug(R.string.no_allowed_app, getPackageName());\n            try {\n                builder.addAllowedApplication(getPackageName());\n            } catch (PackageManager.NameNotFoundException e) {\n                VpnStatus.logError(\"This should not happen: \" + e.getLocalizedMessage());\n            }\n        }\n\n        if (mProfile.mAllowedAppsVpnAreDisallowed) {\n            VpnStatus.logDebug(R.string.disallowed_vpn_apps_info, TextUtils.join(\", \", mProfile.mAllowedAppsVpn));\n        } else {\n            VpnStatus.logDebug(R.string.allowed_vpn_apps_info, TextUtils.join(\", \", mProfile.mAllowedAppsVpn));\n        }\n    }\n\n    public void addDNS(String dns) {\n        mDnslist.add(dns);\n    }\n\n    public void setDomain(String domain) {\n        if (mDomain == null) {\n            mDomain = domain;\n        }\n    }\n\n    /**\n     * Route that is always included, used by the v3 core\n     */\n    public void addRoute(CIDRIP route) {\n        mRoutes.addIP(route, true);\n    }\n\n    public void addRoute(String dest, String mask, String gateway, String device) {\n        CIDRIP route = new CIDRIP(dest, mask);\n        boolean include = isAndroidTunDevice(device);\n\n        NetworkSpace.ipAddress gatewayIP = new NetworkSpace.ipAddress(new CIDRIP(gateway, 32), false);\n\n        if (mLocalIP == null) {\n            VpnStatus.logError(\"Local IP address unset and received. Neither pushed server config nor local config specifies an IP addresses. Opening tun device is most likely going to fail.\");\n            return;\n        }\n        NetworkSpace.ipAddress localNet = new NetworkSpace.ipAddress(mLocalIP, true);\n        if (localNet.containsNet(gatewayIP))\n            include = true;\n\n        if (gateway != null &&\n                (gateway.equals(\"255.255.255.255\") || gateway.equals(mRemoteGW)))\n            include = true;\n\n\n        if (route.len == 32 && !mask.equals(\"255.255.255.255\")) {\n            VpnStatus.logWarning(R.string.route_not_cidr, dest, mask);\n        }\n\n        if (route.normalise())\n            VpnStatus.logWarning(R.string.route_not_netip, dest, route.len, route.mIp);\n\n        mRoutes.addIP(route, include);\n    }\n\n    public void addRoutev6(String network, String device) {\n        String[] v6parts = network.split(\"/\");\n        boolean included = isAndroidTunDevice(device);\n\n        // Tun is opened after ROUTE6, no device name may be present\n\n        try {\n            Inet6Address ip = (Inet6Address) InetAddress.getAllByName(v6parts[0])[0];\n            int mask = Integer.parseInt(v6parts[1]);\n            mRoutesv6.addIPv6(ip, mask, included);\n\n        } catch (UnknownHostException e) {\n            VpnStatus.logException(e);\n        }\n\n\n    }\n\n    private boolean isAndroidTunDevice(String device) {\n        return device != null &&\n                (device.startsWith(\"tun\") || \"(null)\".equals(device) || \"vpnservice-tun\".equals(device));\n    }\n\n    public void setMtu(int mtu) {\n        mMtu = mtu;\n    }\n\n    public void setLocalIP(CIDRIP cdrip) {\n        mLocalIP = cdrip;\n    }\n\n    public void setLocalIP(String local, String netmask, int mtu, String mode) {\n        mLocalIP = new CIDRIP(local, netmask);\n        mMtu = mtu;\n        mRemoteGW = null;\n\n        long netMaskAsInt = CIDRIP.getInt(netmask);\n\n        if (mLocalIP.len == 32 && !netmask.equals(\"255.255.255.255\")) {\n            // get the netmask as IP\n\n            int masklen;\n            long mask;\n            if (\"net30\".equals(mode)) {\n                masklen = 30;\n                mask = 0xfffffffc;\n            } else {\n                masklen = 31;\n                mask = 0xfffffffe;\n            }\n\n            // Netmask is Ip address +/-1, assume net30/p2p with small net\n            if ((netMaskAsInt & mask) == (mLocalIP.getInt() & mask)) {\n                mLocalIP.len = masklen;\n            } else {\n                mLocalIP.len = 32;\n                if (!\"p2p\".equals(mode))\n                    VpnStatus.logWarning(R.string.ip_not_cidr, local, netmask, mode);\n            }\n        }\n        if ((\"p2p\".equals(mode) && mLocalIP.len < 32) || (\"net30\".equals(mode) && mLocalIP.len < 30)) {\n            VpnStatus.logWarning(R.string.ip_looks_like_subnet, local, netmask, mode);\n        }\n\n\n        /* Workaround for Lollipop, it  does not route traffic to the VPNs own network mask */\n        if (mLocalIP.len <= 31 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            CIDRIP interfaceRoute = new CIDRIP(mLocalIP.mIp, mLocalIP.len);\n            interfaceRoute.normalise();\n            addRoute(interfaceRoute);\n        }\n\n\n        // Configurations are sometimes really broken...\n        mRemoteGW = netmask;\n    }\n\n    public void setLocalIPv6(String ipv6addr) {\n        mLocalIPv6 = ipv6addr;\n    }\n\n    @Override\n    public void updateState(String state, String logmessage, int resid, ConnectionStatus level) {\n        // If the process is not running, ignore any state,\n        // Notification should be invisible in this state\n\n        doSendBroadcast(state, level);\n        if (mProcessThread == null && !mNotificationAlwaysVisible)\n            return;\n\n        boolean lowpriority = false;\n        // Display byte count only after being connected\n\n        {\n            if (level == LEVEL_WAITING_FOR_USER_INPUT) {\n                // The user is presented a dialog of some kind, no need to inform the user\n                // with a notifcation\n                return;\n            } else if (level == LEVEL_CONNECTED) {\n                mDisplayBytecount = true;\n                mConnecttime = System.currentTimeMillis();\n                if (!runningOnAndroidTV())\n                    lowpriority = true;\n            } else {\n                mDisplayBytecount = false;\n            }\n\n            // Other notifications are shown,\n            // This also mean we are no longer connected, ignore bytecount messages until next\n            // CONNECTED\n            // Does not work :(\n            String msg;\n            if (resid == R.string.state_waitconnectretry) {\n                msg = VpnStatus.getLastCleanLogMessage(this);\n            } else {\n                msg = getString(resid);\n            }\n\n\n            showNotification(VpnStatus.getLastCleanLogMessage(this),\n                    msg, lowpriority, 0, level);\n\n        }\n    }\n\n    private void doSendBroadcast(String state, ConnectionStatus level) {\n        Intent vpnstatus = new Intent();\n        vpnstatus.setAction(\"de.blinkt.openvpn.VPN_STATUS\");\n        vpnstatus.putExtra(\"status\", level.toString());\n        vpnstatus.putExtra(\"detailstatus\", state);\n        sendBroadcast(vpnstatus, permission.ACCESS_NETWORK_STATE);\n    }\n\n    @Override\n    public void updateByteCount(long in, long out, long diffIn, long diffOut) {\n        TotalTraffic.calcTraffic(this, in, out, diffIn, diffOut);\n        if (mDisplayBytecount) {\n            String netstat = String.format(getString(R.string.statusline_bytecount),\n                    humanReadableByteCount(in, false),\n                    humanReadableByteCount(diffIn / OpenVPNManagement.mBytecountInterval, true),\n                    humanReadableByteCount(out, false),\n                    humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true));\n\n            boolean lowpriority = !mNotificationAlwaysVisible;\n            showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED);\n        }\n\n\n    }\n\n    @Override\n    public boolean handleMessage(Message msg) {\n        Runnable r = msg.getCallback();\n        if (r != null) {\n            r.run();\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    public OpenVPNManagement getManagement() {\n        return mManagement;\n    }\n\n    public String getTunReopenStatus() {\n        String currentConfiguration = getTunConfigString();\n        if (currentConfiguration.equals(mLastTunCfg)) {\n            return \"NOACTION\";\n        } else {\n            String release = Build.VERSION.RELEASE;\n            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith(\"4.4.3\")\n                    && !release.startsWith(\"4.4.4\") && !release.startsWith(\"4.4.5\") && !release.startsWith(\"4.4.6\"))\n                // There will be probably no 4.4.4 or 4.4.5 version, so don't waste effort to do parsing here\n                return \"OPEN_AFTER_CLOSE\";\n            else\n                return \"OPEN_BEFORE_CLOSE\";\n        }\n    }\n\n    public class LocalBinder extends Binder {\n        public OpenVPNService getService() {\n            // Return this instance of LocalService so clients can call public methods\n            return OpenVPNService.this;\n        }\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.annotation.SuppressLint;\nimport android.util.Log;\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport java.io.BufferedReader;\nimport java.io.BufferedWriter;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.text.SimpleDateFormat;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.LinkedList;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n\nimport de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;\n\npublic class OpenVPNThread implements Runnable {\n    private static final String DUMP_PATH_STRING = \"Dump path: \";\n    @SuppressLint(\"SdCardPath\")\n    private static final String BROKEN_PIE_SUPPORT = \"/data/data/de.blinkt.openvpn/cache/pievpn\";\n    private final static String BROKEN_PIE_SUPPORT2 = \"syntax error\";\n    private static final String TAG = \"OpenVPN\";\n    public static final int M_FATAL = (1 << 4);\n    public static final int M_NONFATAL = (1 << 5);\n    public static final int M_WARN = (1 << 6);\n    public static final int M_DEBUG = (1 << 7);\n    private String[] mArgv;\n    private Process mProcess;\n    private String mNativeDir;\n    private OpenVPNService mService;\n    private String mDumpPath;\n    private boolean mBrokenPie = false;\n    private boolean mNoProcessExitStatus = false;\n\n    public OpenVPNThread(OpenVPNService service, String[] argv, String nativelibdir) {\n        mArgv = argv;\n        mNativeDir = nativelibdir;\n        mService = service;\n    }\n\n    public void stopProcess() {\n        mProcess.destroy();\n    }\n\n    void setReplaceConnection()\n    {\n        mNoProcessExitStatus=true;\n    }\n\n    @Override\n    public void run() {\n        try {\n            Log.i(TAG, \"Starting openvpn\");\n            startOpenVPNThreadArgs(mArgv);\n            Log.i(TAG, \"OpenVPN process exited\");\n        } catch (Exception e) {\n            VpnStatus.logException(\"Starting OpenVPN Thread\", e);\n            Log.e(TAG, \"OpenVPNThread Got \" + e.toString());\n        } finally {\n            int exitvalue = 0;\n            try {\n                if (mProcess != null)\n                    exitvalue = mProcess.waitFor();\n            } catch (IllegalThreadStateException ite) {\n                VpnStatus.logError(\"Illegal Thread state: \" + ite.getLocalizedMessage());\n            } catch (InterruptedException ie) {\n                VpnStatus.logError(\"InterruptedException: \" + ie.getLocalizedMessage());\n            }\n            if (exitvalue != 0) {\n                VpnStatus.logError(\"Process exited with exit value \" + exitvalue);\n                if (mBrokenPie) {\n                    /* This will probably fail since the NoPIE binary is probably not written */\n                    String[] noPieArgv = VPNLaunchHelper.replacePieWithNoPie(mArgv);\n\n                    // We are already noPIE, nothing to gain\n                    if (!noPieArgv.equals(mArgv)) {\n                        mArgv = noPieArgv;\n                        VpnStatus.logInfo(\"PIE Version could not be executed. Trying no PIE version\");\n                        run();\n                        return;\n                    }\n\n                }\n\n            }\n\n            if (!mNoProcessExitStatus)\n                VpnStatus.updateStateString(\"NOPROCESS\", \"No process running.\", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED);\n\n            if (mDumpPath != null) {\n                try {\n                    BufferedWriter logout = new BufferedWriter(new FileWriter(mDumpPath + \".log\"));\n                    SimpleDateFormat timeformat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\", Locale.GERMAN);\n                    for (LogItem li : VpnStatus.getlogbuffer()) {\n                        String time = timeformat.format(new Date(li.getLogtime()));\n                        logout.write(time + \" \" + li.getString(mService) + \"\\n\");\n                    }\n                    logout.close();\n                    VpnStatus.logError(R.string.minidump_generated);\n                } catch (IOException e) {\n                    VpnStatus.logError(\"Writing minidump log: \" + e.getLocalizedMessage());\n                }\n            }\n\n            mService.processDied();\n            Log.i(TAG, \"Exiting\");\n        }\n    }\n\n    private void startOpenVPNThreadArgs(String[] argv) {\n        LinkedList<String> argvlist = new LinkedList<String>();\n\n        Collections.addAll(argvlist, argv);\n\n        ProcessBuilder pb = new ProcessBuilder(argvlist);\n        // Hack O rama\n\n        String lbpath = genLibraryPath(argv, pb);\n\n        pb.environment().put(\"LD_LIBRARY_PATH\", lbpath);\n\n        pb.redirectErrorStream(true);\n        try {\n            mProcess = pb.start();\n            // Close the output, since we don't need it\n            mProcess.getOutputStream().close();\n            InputStream in = mProcess.getInputStream();\n            BufferedReader br = new BufferedReader(new InputStreamReader(in));\n\n            while (true) {\n                String logline = br.readLine();\n                if (logline == null)\n                    return;\n\n                if (logline.startsWith(DUMP_PATH_STRING))\n                    mDumpPath = logline.substring(DUMP_PATH_STRING.length());\n\n                if (logline.startsWith(BROKEN_PIE_SUPPORT) || logline.contains(BROKEN_PIE_SUPPORT2))\n                    mBrokenPie = true;\n\n\n                // 1380308330.240114 18000002 Send to HTTP proxy: 'X-Online-Host: bla.blabla.com'\n\n                Pattern p = Pattern.compile(\"(\\\\d+).(\\\\d+) ([0-9a-f])+ (.*)\");\n                Matcher m = p.matcher(logline);\n                if (m.matches()) {\n                    int flags = Integer.parseInt(m.group(3), 16);\n                    String msg = m.group(4);\n                    int logLevel = flags & 0x0F;\n\n                    VpnStatus.LogLevel logStatus = VpnStatus.LogLevel.INFO;\n\n                    if ((flags & M_FATAL) != 0)\n                        logStatus = VpnStatus.LogLevel.ERROR;\n                    else if ((flags & M_NONFATAL) != 0)\n                        logStatus = VpnStatus.LogLevel.WARNING;\n                    else if ((flags & M_WARN) != 0)\n                        logStatus = VpnStatus.LogLevel.WARNING;\n                    else if ((flags & M_DEBUG) != 0)\n                        logStatus = VpnStatus.LogLevel.VERBOSE;\n\n                    if (msg.startsWith(\"MANAGEMENT: CMD\"))\n                        logLevel = Math.max(4, logLevel);\n\n\n                    VpnStatus.logMessageOpenVPN(logStatus, logLevel, msg);\n                } else {\n                    VpnStatus.logInfo(\"P:\" + logline);\n                }\n            }\n\n\n        } catch (IOException e) {\n            VpnStatus.logException(\"Error reading from output of OpenVPN process\", e);\n            stopProcess();\n        }\n\n\n    }\n\n    private String genLibraryPath(String[] argv, ProcessBuilder pb) {\n        // Hack until I find a good way to get the real library path\n        String applibpath = argv[0].replaceFirst(\"/cache/.*$\", \"/lib\");\n\n        String lbpath = pb.environment().get(\"LD_LIBRARY_PATH\");\n        if (lbpath == null)\n            lbpath = applibpath;\n        else\n            lbpath = applibpath + \":\" + lbpath;\n\n        if (!applibpath.equals(mNativeDir)) {\n            lbpath = mNativeDir + \":\" + lbpath;\n        }\n        return lbpath;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.content.Context;\nimport android.net.LocalServerSocket;\nimport android.net.LocalSocket;\nimport android.net.LocalSocketAddress;\nimport android.os.Handler;\nimport android.os.ParcelFileDescriptor;\nimport android.support.annotation.NonNull;\nimport android.util.Log;\n\nimport com.vasilkoff.easyvpnfree.BuildConfig;\nimport com.vasilkoff.easyvpnfree.R;\n\nimport junit.framework.Assert;\n\nimport java.io.FileDescriptor;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.InetSocketAddress;\nimport java.net.SocketAddress;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.Locale;\nimport java.util.Vector;\n\n\nimport de.blinkt.openvpn.VpnProfile;\nimport de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;\n\npublic class OpenVpnManagementThread implements Runnable, OpenVPNManagement {\n\n    private static final String TAG = \"openvpn\";\n    private final Handler mResumeHandler;\n    private LocalSocket mSocket;\n    private VpnProfile mProfile;\n    private OpenVPNService mOpenVPNService;\n    private LinkedList<FileDescriptor> mFDList = new LinkedList<>();\n    private LocalServerSocket mServerSocket;\n    private boolean mWaitingForRelease = false;\n    private long mLastHoldRelease = 0;\n\n    private static final Vector<OpenVpnManagementThread> active = new Vector<>();\n    private LocalSocket mServerSocketLocal;\n\n    private pauseReason lastPauseReason = pauseReason.noNetwork;\n    private PausedStateCallback mPauseCallback;\n    private boolean mShuttingDown;\n\n    public OpenVpnManagementThread(VpnProfile profile, OpenVPNService openVpnService) {\n        mProfile = profile;\n        mOpenVPNService = openVpnService;\n        mResumeHandler = new Handler(openVpnService.getMainLooper());\n\n    }\n\n    private Runnable mResumeHoldRunnable = new Runnable() {\n        @Override\n        public void run() {\n            if (shouldBeRunning()) {\n                releaseHoldCmd();\n            }\n        }\n    };\n\n    public boolean openManagementInterface(@NonNull Context c) {\n        // Could take a while to open connection\n        int tries = 8;\n\n        String socketName = (c.getCacheDir().getAbsolutePath() + \"/\" + \"mgmtsocket\");\n        // The mServerSocketLocal is transferred to the LocalServerSocket, ignore warning\n\n        mServerSocketLocal = new LocalSocket();\n\n        while (tries > 0 && !mServerSocketLocal.isBound()) {\n            try {\n                mServerSocketLocal.bind(new LocalSocketAddress(socketName,\n                        LocalSocketAddress.Namespace.FILESYSTEM));\n            } catch (IOException e) {\n                // wait 300 ms before retrying\n                try {\n                    Thread.sleep(300);\n                } catch (InterruptedException ignored) {\n                }\n\n            }\n            tries--;\n        }\n\n        try {\n\n            mServerSocket = new LocalServerSocket(mServerSocketLocal.getFileDescriptor());\n            return true;\n        } catch (IOException e) {\n            VpnStatus.logException(e);\n        }\n        return false;\n\n\n    }\n\n    public void managmentCommand(String cmd) {\n        try {\n            if (mSocket != null && mSocket.getOutputStream() != null) {\n                mSocket.getOutputStream().write(cmd.getBytes());\n                mSocket.getOutputStream().flush();\n            }\n        } catch (IOException e) {\n            // Ignore socket stack traces\n        }\n    }\n\n\n    @Override\n    public void run() {\n        byte[] buffer = new byte[2048];\n        //\tmSocket.setSoTimeout(5); // Setting a timeout cannot be that bad\n\n        String pendingInput = \"\";\n        synchronized (active) {\n            active.add(this);\n        }\n\n        try {\n            // Wait for a client to connect\n            mSocket = mServerSocket.accept();\n            InputStream instream = mSocket.getInputStream();\n\n\n            // Close the management socket after client connected\n\n            mServerSocket.close();\n            // Closing one of the two sockets also closes the other\n            //mServerSocketLocal.close();\n\n            while (true) {\n\n                int numbytesread = instream.read(buffer);\n                if (numbytesread == -1)\n                    return;\n\n                FileDescriptor[] fds = null;\n                try {\n                    fds = mSocket.getAncillaryFileDescriptors();\n                } catch (IOException e) {\n                    VpnStatus.logException(\"Error reading fds from socket\", e);\n                }\n                if (fds != null) {\n                    Collections.addAll(mFDList, fds);\n                }\n\n                String input = new String(buffer, 0, numbytesread, \"UTF-8\");\n\n                pendingInput += input;\n\n                pendingInput = processInput(pendingInput);\n\n\n            }\n        } catch (IOException e) {\n            if (!e.getMessage().equals(\"socket closed\") && !e.getMessage().equals(\"Connection reset by peer\"))\n                VpnStatus.logException(e);\n        }\n        synchronized (active) {\n            active.remove(this);\n        }\n    }\n\n    //! Hack O Rama 2000!\n    private void protectFileDescriptor(FileDescriptor fd) {\n        try {\n            Method getInt = FileDescriptor.class.getDeclaredMethod(\"getInt$\");\n            int fdint = (Integer) getInt.invoke(fd);\n\n            // You can even get more evil by parsing toString() and extract the int from that :)\n\n            boolean result = mOpenVPNService.protect(fdint);\n            if (!result)\n                VpnStatus.logWarning(\"Could not protect VPN socket\");\n\n\n            //ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint);\n            //pfd.close();\n            NativeUtils.jniclose(fdint);\n            return;\n        } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException | NullPointerException e) {\n            VpnStatus.logException(\"Failed to retrieve fd from socket (\" + fd + \")\", e);\n        }\n\n        Log.d(\"Openvpn\", \"Failed to retrieve fd from socket: \" + fd);\n\n    }\n\n    private String processInput(String pendingInput) {\n\n\n        while (pendingInput.contains(\"\\n\")) {\n            String[] tokens = pendingInput.split(\"\\\\r?\\\\n\", 2);\n            processCommand(tokens[0]);\n            if (tokens.length == 1)\n                // No second part, newline was at the end\n                pendingInput = \"\";\n            else\n                pendingInput = tokens[1];\n        }\n        return pendingInput;\n    }\n\n\n    private void processCommand(String command) {\n        //Log.i(TAG, \"Line from managment\" + command);\n\n\n        if (command.startsWith(\">\") && command.contains(\":\")) {\n            String[] parts = command.split(\":\", 2);\n            String cmd = parts[0].substring(1);\n            String argument = parts[1];\n\n\n            switch (cmd) {\n                case \"INFO\":\n                /* Ignore greeting from management */\n                    return;\n                case \"PASSWORD\":\n                    processPWCommand(argument);\n                    break;\n                case \"HOLD\":\n                    handleHold(argument);\n                    break;\n                case \"NEED-OK\":\n                    processNeedCommand(argument);\n                    break;\n                case \"BYTECOUNT\":\n                    processByteCount(argument);\n                    break;\n                case \"STATE\":\n                    if (!mShuttingDown)\n                        processState(argument);\n                    break;\n                case \"PROXY\":\n                    processProxyCMD(argument);\n                    break;\n                case \"LOG\":\n                    processLogMessage(argument);\n                    break;\n                case \"RSA_SIGN\":\n                    processSignCommand(argument);\n                    break;\n                default:\n                    VpnStatus.logWarning(\"MGMT: Got unrecognized command\" + command);\n                    Log.i(TAG, \"Got unrecognized command\" + command);\n                    break;\n            }\n        } else if (command.startsWith(\"SUCCESS:\")) {\n            /* Ignore this kind of message too */\n            return;\n        } else if (command.startsWith(\"PROTECTFD: \")) {\n            FileDescriptor fdtoprotect = mFDList.pollFirst();\n            if (fdtoprotect != null)\n                protectFileDescriptor(fdtoprotect);\n        } else {\n            Log.i(TAG, \"Got unrecognized line from managment\" + command);\n            VpnStatus.logWarning(\"MGMT: Got unrecognized line from management:\" + command);\n        }\n    }\n\n    private void processLogMessage(String argument) {\n        String[] args = argument.split(\",\", 4);\n        // 0 unix time stamp\n        // 1 log level N,I,E etc.\n                /*\n                  (b) zero or more message flags in a single string:\n          I -- informational\n          F -- fatal error\n          N -- non-fatal error\n          W -- warning\n          D -- debug, and\n                 */\n        // 2 log message\n\n        Log.d(\"OpenVPN\", argument);\n\n        VpnStatus.LogLevel level;\n        switch (args[1]) {\n            case \"I\":\n                level = VpnStatus.LogLevel.INFO;\n                break;\n            case \"W\":\n                level = VpnStatus.LogLevel.WARNING;\n                break;\n            case \"D\":\n                level = VpnStatus.LogLevel.VERBOSE;\n                break;\n            case \"F\":\n                level = VpnStatus.LogLevel.ERROR;\n                break;\n            default:\n                level = VpnStatus.LogLevel.INFO;\n                break;\n        }\n\n        int ovpnlevel = Integer.parseInt(args[2]) & 0x0F;\n        String msg = args[3];\n\n        if (msg.startsWith(\"MANAGEMENT: CMD\"))\n            ovpnlevel = Math.max(4, ovpnlevel);\n\n        VpnStatus.logMessageOpenVPN(level, ovpnlevel, msg);\n    }\n\n    boolean shouldBeRunning() {\n        if (mPauseCallback == null)\n            return false;\n        else\n            return mPauseCallback.shouldBeRunning();\n    }\n\n    private void handleHold(String argument) {\n        int waittime = Integer.parseInt(argument.split(\":\")[1]);\n        if (shouldBeRunning()) {\n            if (waittime > 1)\n                VpnStatus.updateStateString(\"CONNECTRETRY\", String.valueOf(waittime),\n                        R.string.state_waitconnectretry, ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET);\n            mResumeHandler.postDelayed(mResumeHoldRunnable, waittime * 1000);\n            if (waittime > 5) {\n                VpnStatus.logInfo(R.string.state_waitconnectretry, String.valueOf(waittime));\n\n            }\n        } else {\n            mWaitingForRelease = true;\n\n            VpnStatus.updateStatePause(lastPauseReason);\n\n\n        }\n    }\n\n    private void releaseHoldCmd() {\n        mResumeHandler.removeCallbacks(mResumeHoldRunnable);\n        if ((System.currentTimeMillis() - mLastHoldRelease) < 5000) {\n            try {\n                Thread.sleep(3000);\n            } catch (InterruptedException ignored) {\n            }\n\n        }\n        mWaitingForRelease = false;\n        mLastHoldRelease = System.currentTimeMillis();\n        managmentCommand(\"hold release\\n\");\n        managmentCommand(\"bytecount \" + mBytecountInterval + \"\\n\");\n        managmentCommand(\"state on\\n\");\n        //managmentCommand(\"log on all\\n\");\n    }\n\n\n    public void releaseHold() {\n        if (mWaitingForRelease)\n            releaseHoldCmd();\n    }\n\n    private void processProxyCMD(String argument) {\n        String[] args = argument.split(\",\", 3);\n        SocketAddress proxyaddr = ProxyDetection.detectProxy(mProfile);\n\n\n        if (args.length >= 2) {\n            String proto = args[1];\n            if (proto.equals(\"UDP\")) {\n                proxyaddr = null;\n            }\n        }\n\n        if (proxyaddr instanceof InetSocketAddress) {\n            InetSocketAddress isa = (InetSocketAddress) proxyaddr;\n\n            VpnStatus.logInfo(R.string.using_proxy, isa.getHostName(), isa.getPort());\n\n            String proxycmd = String.format(Locale.ENGLISH, \"proxy HTTP %s %d\\n\", isa.getHostName(), isa.getPort());\n            managmentCommand(proxycmd);\n        } else {\n            managmentCommand(\"proxy NONE\\n\");\n        }\n\n    }\n\n    private void processState(String argument) {\n        String[] args = argument.split(\",\", 3);\n        String currentstate = args[1];\n\n        if (args[2].equals(\",,\"))\n            VpnStatus.updateStateString(currentstate, \"\");\n        else\n            VpnStatus.updateStateString(currentstate, args[2]);\n    }\n\n\n    private void processByteCount(String argument) {\n        //   >BYTECOUNT:{BYTES_IN},{BYTES_OUT}\n        int comma = argument.indexOf(',');\n        long in = Long.parseLong(argument.substring(0, comma));\n        long out = Long.parseLong(argument.substring(comma + 1));\n\n        VpnStatus.updateByteCount(in, out);\n\n    }\n\n\n    private void processNeedCommand(String argument) {\n        int p1 = argument.indexOf('\\'');\n        int p2 = argument.indexOf('\\'', p1 + 1);\n\n        String needed = argument.substring(p1 + 1, p2);\n        String extra = argument.split(\":\", 2)[1];\n\n        String status = \"ok\";\n\n\n        switch (needed) {\n            case \"PROTECTFD\":\n                FileDescriptor fdtoprotect = mFDList.pollFirst();\n                protectFileDescriptor(fdtoprotect);\n                break;\n            case \"DNSSERVER\":\n                mOpenVPNService.addDNS(extra);\n                break;\n            case \"DNSDOMAIN\":\n                mOpenVPNService.setDomain(extra);\n                break;\n            case \"ROUTE\": {\n                String[] routeparts = extra.split(\" \");\n\n            /*\n            buf_printf (&out, \"%s %s %s dev %s\", network, netmask, gateway, rgi->iface);\n            else\n            buf_printf (&out, \"%s %s %s\", network, netmask, gateway);\n            */\n\n                if (routeparts.length == 5) {\n                    if (BuildConfig.DEBUG) Assert.assertEquals(\"dev\", routeparts[3]);\n                    mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], routeparts[4]);\n                } else if (routeparts.length >= 3) {\n                    mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], null);\n                } else {\n                    VpnStatus.logError(\"Unrecognized ROUTE cmd:\" + Arrays.toString(routeparts) + \" | \" + argument);\n                }\n\n                break;\n            }\n            case \"ROUTE6\": {\n                String[] routeparts = extra.split(\" \");\n                mOpenVPNService.addRoutev6(routeparts[0], routeparts[1]);\n                break;\n            }\n            case \"IFCONFIG\":\n                String[] ifconfigparts = extra.split(\" \");\n                int mtu = Integer.parseInt(ifconfigparts[2]);\n                mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1], mtu, ifconfigparts[3]);\n                break;\n            case \"IFCONFIG6\":\n                mOpenVPNService.setLocalIPv6(extra);\n\n                break;\n            case \"PERSIST_TUN_ACTION\":\n                // check if tun cfg stayed the same\n                status = mOpenVPNService.getTunReopenStatus();\n                break;\n            case \"OPENTUN\":\n                if (sendTunFD(needed, extra))\n                    return;\n                else\n                    status = \"cancel\";\n                // This not nice or anything but setFileDescriptors accepts only FilDescriptor class :(\n\n                break;\n            default:\n                Log.e(TAG, \"Unknown needok command \" + argument);\n                return;\n        }\n\n        String cmd = String.format(\"needok '%s' %s\\n\", needed, status);\n        managmentCommand(cmd);\n    }\n\n    private boolean sendTunFD(String needed, String extra) {\n        if (!extra.equals(\"tun\")) {\n            // We only support tun\n            VpnStatus.logError(String.format(\"Device type %s requested, but only tun is possible with the Android API, sorry!\", extra));\n\n            return false;\n        }\n        ParcelFileDescriptor pfd = mOpenVPNService.openTun();\n        if (pfd == null)\n            return false;\n\n        Method setInt;\n        int fdint = pfd.getFd();\n        try {\n            setInt = FileDescriptor.class.getDeclaredMethod(\"setInt$\", int.class);\n            FileDescriptor fdtosend = new FileDescriptor();\n\n            setInt.invoke(fdtosend, fdint);\n\n            FileDescriptor[] fds = {fdtosend};\n            mSocket.setFileDescriptorsForSend(fds);\n\n            // Trigger a send so we can close the fd on our side of the channel\n            // The API documentation fails to mention that it will not reset the file descriptor to\n            // be send and will happily send the file descriptor on every write ...\n            String cmd = String.format(\"needok '%s' %s\\n\", needed, \"ok\");\n            managmentCommand(cmd);\n\n            // Set the FileDescriptor to null to stop this mad behavior\n            mSocket.setFileDescriptorsForSend(null);\n\n            pfd.close();\n\n            return true;\n        } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException |\n                IOException | IllegalAccessException exp) {\n            VpnStatus.logException(\"Could not send fd over socket\", exp);\n        }\n\n        return false;\n    }\n\n    private void processPWCommand(String argument) {\n        //argument has the form \tNeed 'Private Key' password\n        // or  \">PASSWORD:Verification Failed: '%s' ['%s']\"\n        String needed;\n\n\n        try {\n\n            int p1 = argument.indexOf('\\'');\n            int p2 = argument.indexOf('\\'', p1 + 1);\n            needed = argument.substring(p1 + 1, p2);\n            if (argument.startsWith(\"Verification Failed\")) {\n                proccessPWFailed(needed, argument.substring(p2 + 1));\n                return;\n            }\n        } catch (StringIndexOutOfBoundsException sioob) {\n            VpnStatus.logError(\"Could not parse management Password command: \" + argument);\n            return;\n        }\n\n        String pw = null;\n\n        if (needed.equals(\"Private Key\")) {\n            pw = mProfile.getPasswordPrivateKey();\n        } else if (needed.equals(\"Auth\")) {\n            String usercmd = String.format(\"username '%s' %s\\n\",\n                    needed, VpnProfile.openVpnEscape(mProfile.mUsername));\n            managmentCommand(usercmd);\n            pw = mProfile.getPasswordAuth();\n        }\n        if (pw != null) {\n            String cmd = String.format(\"password '%s' %s\\n\", needed, VpnProfile.openVpnEscape(pw));\n            managmentCommand(cmd);\n        } else {\n            VpnStatus.logError(String.format(\"Openvpn requires Authentication type '%s' but no password/key information available\", needed));\n        }\n\n    }\n\n\n    private void proccessPWFailed(String needed, String args) {\n        VpnStatus.updateStateString(\"AUTH_FAILED\", needed + args, R.string.state_auth_failed, ConnectionStatus.LEVEL_AUTH_FAILED);\n    }\n\n\n    private static boolean stopOpenVPN() {\n        synchronized (active) {\n            boolean sendCMD = false;\n            for (OpenVpnManagementThread mt : active) {\n                mt.managmentCommand(\"signal SIGINT\\n\");\n                sendCMD = true;\n                try {\n                    if (mt.mSocket != null)\n                        mt.mSocket.close();\n                } catch (IOException e) {\n                    // Ignore close error on already closed socket\n                }\n            }\n            return sendCMD;\n        }\n    }\n\n    @Override\n    public void networkChange(boolean samenetwork) {\n        if (mWaitingForRelease)\n            releaseHold();\n        else if (samenetwork)\n            managmentCommand(\"network-change samenetwork\\n\");\n        else\n            managmentCommand(\"network-change\\n\");\n    }\n\n    @Override\n    public void setPauseCallback(PausedStateCallback callback) {\n        mPauseCallback = callback;\n    }\n\n    public void signalusr1() {\n        mResumeHandler.removeCallbacks(mResumeHoldRunnable);\n        if (!mWaitingForRelease)\n            managmentCommand(\"signal SIGUSR1\\n\");\n        else\n            // If signalusr1 is called update the state string\n            // if there is another for stopping\n            VpnStatus.updateStatePause(lastPauseReason);\n    }\n\n    public void reconnect() {\n        signalusr1();\n        releaseHold();\n    }\n\n    private void processSignCommand(String b64data) {\n\n        String signed_string = mProfile.getSignedData(b64data);\n        if (signed_string == null) {\n            managmentCommand(\"rsa-sig\\n\");\n            managmentCommand(\"\\nEND\\n\");\n            stopOpenVPN();\n            return;\n        }\n        managmentCommand(\"rsa-sig\\n\");\n        managmentCommand(signed_string);\n        managmentCommand(\"\\nEND\\n\");\n    }\n\n    @Override\n    public void pause(pauseReason reason) {\n        lastPauseReason = reason;\n        signalusr1();\n    }\n\n    @Override\n    public void resume() {\n        releaseHold();\n        /* Reset the reason why we are disconnected */\n        lastPauseReason = pauseReason.noNetwork;\n    }\n\n    @Override\n    public boolean stopVPN(boolean replaceConnection) {\n        mShuttingDown = true;\n        return stopOpenVPN();\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;/*\n * This software is provided 'as-is', without any express or implied\n * warranty.  In no event will Google be held liable for any damages\n * arising from the use of this software.\n *\n * Permission is granted to anyone to use this software for any purpose,\n * including commercial applications, and to alter it and redistribute it\n * freely, as long as the origin is not misrepresented.\n */\n\nimport android.os.Build;\nimport android.os.Process;\nimport android.util.Log;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.DataInputStream;\nimport java.io.DataOutputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.Provider;\nimport java.security.SecureRandom;\nimport java.security.SecureRandomSpi;\nimport java.security.Security;\n\n/**\n * Fixes for the output of the default PRNG having low entropy.\n *\n * The fixes need to be applied via {@link #apply()} before any use of Java\n * Cryptography Architecture primitives. A good place to invoke them is in the\n * application's {@code onCreate}.\n */\npublic final class PRNGFixes {\n\n    private static final int VERSION_CODE_JELLY_BEAN = 16;\n    private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;\n    private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =\n            getBuildFingerprintAndDeviceSerial();\n\n    /** Hidden constructor to prevent instantiation. */\n    private PRNGFixes() {}\n\n    /**\n     * Applies all fixes.\n     *\n     * @throws SecurityException if a fix is needed but could not be applied.\n     */\n    public static void apply() {\n        applyOpenSSLFix();\n        installLinuxPRNGSecureRandom();\n    }\n\n    /**\n     * Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the\n     * fix is not needed.\n     *\n     * @throws SecurityException if the fix is needed but could not be applied.\n     */\n    private static void applyOpenSSLFix() throws SecurityException {\n        if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN)\n                || (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) {\n            // No need to apply the fix\n            return;\n        }\n\n        try {\n            // Mix in the device- and invocation-specific seed.\n            Class.forName(\"org.apache.harmony.xnet.provider.jsse.NativeCrypto\")\n                    .getMethod(\"RAND_seed\", byte[].class)\n                    .invoke(null, generateSeed());\n\n            // Mix output of Linux PRNG into OpenSSL's PRNG\n            int bytesRead = (Integer) Class.forName(\n                    \"org.apache.harmony.xnet.provider.jsse.NativeCrypto\")\n                    .getMethod(\"RAND_load_file\", String.class, long.class)\n                    .invoke(null, \"/dev/urandom\", 1024);\n            if (bytesRead != 1024) {\n                throw new IOException(\n                        \"Unexpected number of bytes read from Linux PRNG: \"\n                                + bytesRead);\n            }\n        } catch (Exception e) {\n            throw new SecurityException(\"Failed to seed OpenSSL PRNG\", e);\n        }\n    }\n\n    /**\n     * Installs a Linux PRNG-backed {@code SecureRandom} implementation as the\n     * default. Does nothing if the implementation is already the default or if\n     * there is not need to install the implementation.\n     *\n     * @throws SecurityException if the fix is needed but could not be applied.\n     */\n    private static void installLinuxPRNGSecureRandom()\n            throws SecurityException {\n        if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) {\n            // No need to apply the fix\n            return;\n        }\n\n        // Install a Linux PRNG-based SecureRandom implementation as the\n        // default, if not yet installed.\n        Provider[] secureRandomProviders =\n                Security.getProviders(\"SecureRandom.SHA1PRNG\");\n        if ((secureRandomProviders == null)\n                || (secureRandomProviders.length < 1)\n                || (!LinuxPRNGSecureRandomProvider.class.equals(\n                secureRandomProviders[0].getClass()))) {\n            Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1);\n        }\n\n        // Assert that new SecureRandom() and\n        // SecureRandom.getInstance(\"SHA1PRNG\") return a SecureRandom backed\n        // by the Linux PRNG-based SecureRandom implementation.\n        SecureRandom rng1 = new SecureRandom();\n        if (!LinuxPRNGSecureRandomProvider.class.equals(\n                rng1.getProvider().getClass())) {\n            throw new SecurityException(\n                    \"new SecureRandom() backed by wrong Provider: \"\n                            + rng1.getProvider().getClass());\n        }\n\n        SecureRandom rng2;\n        try {\n            rng2 = SecureRandom.getInstance(\"SHA1PRNG\");\n        } catch (NoSuchAlgorithmException e) {\n            throw new SecurityException(\"SHA1PRNG not available\", e);\n        }\n        if (!LinuxPRNGSecureRandomProvider.class.equals(\n                rng2.getProvider().getClass())) {\n            throw new SecurityException(\n                    \"SecureRandom.getInstance(\\\"SHA1PRNG\\\") backed by wrong\"\n                            + \" Provider: \" + rng2.getProvider().getClass());\n        }\n    }\n\n    /**\n     * {@code Provider} of {@code SecureRandom} engines which pass through\n     * all requests to the Linux PRNG.\n     */\n    private static class LinuxPRNGSecureRandomProvider extends Provider {\n\n        public LinuxPRNGSecureRandomProvider() {\n            super(\"LinuxPRNG\",\n                    1.0,\n                    \"A Linux-specific random number provider that uses\"\n                            + \" /dev/urandom\");\n            // Although /dev/urandom is not a SHA-1 PRNG, some apps\n            // explicitly request a SHA1PRNG SecureRandom and we thus need to\n            // prevent them from getting the default implementation whose output\n            // may have low entropy.\n            put(\"SecureRandom.SHA1PRNG\", LinuxPRNGSecureRandom.class.getName());\n            put(\"SecureRandom.SHA1PRNG ImplementedIn\", \"Software\");\n        }\n    }\n\n    /**\n     * {@link SecureRandomSpi} which passes all requests to the Linux PRNG\n     * ({@code /dev/urandom}).\n     */\n    public static class LinuxPRNGSecureRandom extends SecureRandomSpi {\n\n        /*\n         * IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed\n         * are passed through to the Linux PRNG (/dev/urandom). Instances of\n         * this class seed themselves by mixing in the current time, PID, UID,\n         * build fingerprint, and hardware serial number (where available) into\n         * Linux PRNG.\n         *\n         * Concurrency: Read requests to the underlying Linux PRNG are\n         * serialized (on sLock) to ensure that multiple threads do not get\n         * duplicated PRNG output.\n         */\n\n        private static final File URANDOM_FILE = new File(\"/dev/urandom\");\n\n        private static final Object sLock = new Object();\n\n        /**\n         * Input stream for reading from Linux PRNG or {@code null} if not yet\n         * opened.\n         *\n         * @GuardedBy(\"sLock\")\n         */\n        private static DataInputStream sUrandomIn;\n\n        /**\n         * Output stream for writing to Linux PRNG or {@code null} if not yet\n         * opened.\n         *\n         * @GuardedBy(\"sLock\")\n         */\n        private static OutputStream sUrandomOut;\n\n        /**\n         * Whether this engine instance has been seeded. This is needed because\n         * each instance needs to seed itself if the client does not explicitly\n         * seed it.\n         */\n        private boolean mSeeded;\n\n        @Override\n        protected void engineSetSeed(byte[] bytes) {\n            try {\n                OutputStream out;\n                synchronized (sLock) {\n                    out = getUrandomOutputStream();\n                }\n                out.write(bytes);\n                out.flush();\n            } catch (IOException e) {\n                // On a small fraction of devices /dev/urandom is not writable.\n                // Log and ignore.\n                Log.w(PRNGFixes.class.getSimpleName(),\n                        \"Failed to mix seed into \" + URANDOM_FILE);\n            } finally {\n                mSeeded = true;\n            }\n        }\n\n        @Override\n        protected void engineNextBytes(byte[] bytes) {\n            if (!mSeeded) {\n                // Mix in the device- and invocation-specific seed.\n                engineSetSeed(generateSeed());\n            }\n\n            try {\n                DataInputStream in;\n                synchronized (sLock) {\n                    in = getUrandomInputStream();\n                }\n                synchronized (in) {\n                    in.readFully(bytes);\n                }\n            } catch (IOException e) {\n                throw new SecurityException(\n                        \"Failed to read from \" + URANDOM_FILE, e);\n            }\n        }\n\n        @Override\n        protected byte[] engineGenerateSeed(int size) {\n            byte[] seed = new byte[size];\n            engineNextBytes(seed);\n            return seed;\n        }\n\n        private DataInputStream getUrandomInputStream() {\n            synchronized (sLock) {\n                if (sUrandomIn == null) {\n                    // NOTE: Consider inserting a BufferedInputStream between\n                    // DataInputStream and FileInputStream if you need higher\n                    // PRNG output performance and can live with future PRNG\n                    // output being pulled into this process prematurely.\n                    try {\n                        sUrandomIn = new DataInputStream(\n                                new FileInputStream(URANDOM_FILE));\n                    } catch (IOException e) {\n                        throw new SecurityException(\"Failed to open \"\n                                + URANDOM_FILE + \" for reading\", e);\n                    }\n                }\n                return sUrandomIn;\n            }\n        }\n\n        private OutputStream getUrandomOutputStream() throws IOException {\n            synchronized (sLock) {\n                if (sUrandomOut == null) {\n                    sUrandomOut = new FileOutputStream(URANDOM_FILE);\n                }\n                return sUrandomOut;\n            }\n        }\n    }\n\n    /**\n     * Generates a device- and invocation-specific seed to be mixed into the\n     * Linux PRNG.\n     */\n    private static byte[] generateSeed() {\n        try {\n            ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream();\n            DataOutputStream seedBufferOut =\n                    new DataOutputStream(seedBuffer);\n            seedBufferOut.writeLong(System.currentTimeMillis());\n            seedBufferOut.writeLong(System.nanoTime());\n            seedBufferOut.writeInt(Process.myPid());\n            seedBufferOut.writeInt(Process.myUid());\n            seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL);\n            seedBufferOut.close();\n            return seedBuffer.toByteArray();\n        } catch (IOException e) {\n            throw new SecurityException(\"Failed to generate seed\", e);\n        }\n    }\n\n    /**\n     * Gets the hardware serial number of this device.\n     *\n     * @return serial number or {@code null} if not available.\n     */\n    private static String getDeviceSerialNumber() {\n        // We're using the Reflection API because Build.SERIAL is only available\n        // since API Level 9 (Gingerbread, Android 2.3).\n        try {\n            return (String) Build.class.getField(\"SERIAL\").get(null);\n        } catch (Exception ignored) {\n            return null;\n        }\n    }\n\n    private static byte[] getBuildFingerprintAndDeviceSerial() {\n        StringBuilder result = new StringBuilder();\n        String fingerprint = Build.FINGERPRINT;\n        if (fingerprint != null) {\n            result.append(fingerprint);\n        }\n        String serial = getDeviceSerialNumber();\n        if (serial != null) {\n            result.append(serial);\n        }\n        try {\n            return result.toString().getBytes(\"UTF-8\");\n        } catch (UnsupportedEncodingException e) {\n            throw new RuntimeException(\"UTF-8 encoding not supported\");\n        }\n    }\n}"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport android.content.SharedPreferences.Editor;\nimport android.preference.PreferenceManager;\n\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport de.blinkt.openvpn.VpnProfile;\n\npublic class ProfileManager {\n    private static final String PREFS_NAME = \"VPNList\";\n\n    private static final String LAST_CONNECTED_PROFILE = \"lastConnectedProfile\";\n    private static ProfileManager instance;\n\n    private static VpnProfile mLastConnectedVpn = null;\n    private HashMap<String, VpnProfile> profiles = new HashMap<>();\n    private static VpnProfile tmpprofile = null;\n\n\n    private static VpnProfile get(String key) {\n        if (tmpprofile != null && tmpprofile.getUUIDString().equals(key))\n            return tmpprofile;\n\n        if (instance == null)\n            return null;\n        return instance.profiles.get(key);\n\n    }\n\n\n    private ProfileManager() {\n    }\n\n    private static void checkInstance(Context context) {\n        if (instance == null) {\n            instance = new ProfileManager();\n            instance.loadVPNList(context);\n        }\n    }\n\n    synchronized public static ProfileManager getInstance(Context context) {\n        checkInstance(context);\n        return instance;\n    }\n\n    public static void setConntectedVpnProfileDisconnected(Context c) {\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);\n        Editor prefsedit = prefs.edit();\n        prefsedit.putString(LAST_CONNECTED_PROFILE, null);\n        prefsedit.apply();\n\n    }\n\n    /**\n     * Sets the profile that is connected (to connect if the service restarts)\n     */\n    public static void setConnectedVpnProfile(Context c, VpnProfile connectedProfile) {\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);\n        Editor prefsedit = prefs.edit();\n\n        prefsedit.putString(LAST_CONNECTED_PROFILE, connectedProfile.getUUIDString());\n        prefsedit.apply();\n        mLastConnectedVpn = connectedProfile;\n\n    }\n\n    /**\n     * Returns the profile that was last connected (to connect if the service restarts)\n     */\n    public static VpnProfile getLastConnectedProfile(Context c) {\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);\n\n        String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null);\n        if (lastConnectedProfile != null)\n            return get(c, lastConnectedProfile);\n        else\n            return null;\n    }\n\n\n    public Collection<VpnProfile> getProfiles() {\n        return profiles.values();\n    }\n\n    public VpnProfile getProfileByName(String name) {\n        for (VpnProfile vpnp : profiles.values()) {\n            if (vpnp.getName().equals(name)) {\n                return vpnp;\n            }\n        }\n        return null;\n    }\n\n    public void saveProfileList(Context context) {\n        SharedPreferences sharedprefs = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);\n        Editor editor = sharedprefs.edit();\n        editor.putStringSet(\"vpnlist\", profiles.keySet());\n\n        // For reasing I do not understand at all\n        // Android saves my prefs file only one time\n        // if I remove the debug code below :(\n        int counter = sharedprefs.getInt(\"counter\", 0);\n        editor.putInt(\"counter\", counter + 1);\n        editor.apply();\n\n    }\n\n    public void addProfile(VpnProfile profile) {\n        profiles.put(profile.getUUID().toString(), profile);\n\n    }\n\n    public static void setTemporaryProfile(VpnProfile tmp) {\n        ProfileManager.tmpprofile = tmp;\n    }\n\n    public static boolean isTempProfile()\n    {\n        return mLastConnectedVpn == tmpprofile;\n    }\n\n\n    public void saveProfile(Context context, VpnProfile profile) {\n        ObjectOutputStream vpnfile;\n        try {\n            vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + \".vp\"), Activity.MODE_PRIVATE));\n\n            vpnfile.writeObject(profile);\n            vpnfile.flush();\n            vpnfile.close();\n        } catch (IOException e) {\n            VpnStatus.logException(\"saving VPN profile\", e);\n            throw new RuntimeException(e);\n        }\n    }\n\n\n    private void loadVPNList(Context context) {\n        profiles = new HashMap<>();\n        SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);\n        Set<String> vlist = listpref.getStringSet(\"vpnlist\", null);\n        if (vlist == null) {\n            vlist = new HashSet<>();\n        }\n\n        for (String vpnentry : vlist) {\n            try {\n                ObjectInputStream vpnfile = new ObjectInputStream(context.openFileInput(vpnentry + \".vp\"));\n                VpnProfile vp = ((VpnProfile) vpnfile.readObject());\n\n                // Sanity check\n                if (vp == null || vp.mName == null || vp.getUUID() == null)\n                    continue;\n\n                vp.upgradeProfile();\n                profiles.put(vp.getUUID().toString(), vp);\n\n            } catch (IOException | ClassNotFoundException e) {\n                VpnStatus.logException(\"Loading VPN List\", e);\n            }\n        }\n    }\n\n\n    public void removeProfile(Context context, VpnProfile profile) {\n        String vpnentry = profile.getUUID().toString();\n        profiles.remove(vpnentry);\n        saveProfileList(context);\n        context.deleteFile(vpnentry + \".vp\");\n        if (mLastConnectedVpn == profile)\n            mLastConnectedVpn = null;\n\n    }\n\n    public static VpnProfile get(Context context, String profileUUID) {\n        checkInstance(context);\n        return get(profileUUID);\n    }\n\n    public static VpnProfile getLastConnectedVpn() {\n        return mLastConnectedVpn;\n    }\n\n    public static VpnProfile getAlwaysOnVPN(Context context) {\n        checkInstance(context);\n        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);\n\n        String uuid = prefs.getString(\"alwaysOnVpn\", null);\n        return get(uuid);\n\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport java.net.InetSocketAddress;\nimport java.net.MalformedURLException;\nimport java.net.Proxy;\nimport java.net.ProxySelector;\nimport java.net.SocketAddress;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.util.List;\n\n\nimport de.blinkt.openvpn.VpnProfile;\n\npublic class ProxyDetection {\n\tstatic SocketAddress detectProxy(VpnProfile vp) {\n\t\t// Construct a new url with https as protocol\n\t\ttry {\n\t\t\tURL url = new URL(String.format(\"https://%s:%s\",vp.mServerName,vp.mServerPort));\n\t\t\tProxy proxy = getFirstProxy(url);\n\n\t\t\tif(proxy==null)\n\t\t\t\treturn null;\n\t\t\tSocketAddress addr = proxy.address();\n\t\t\tif (addr instanceof InetSocketAddress) {\n\t\t\t\treturn addr; \n\t\t\t}\n\t\t\t\n\t\t} catch (MalformedURLException e) {\n\t\t\tVpnStatus.logError(R.string.getproxy_error, e.getLocalizedMessage());\n\t\t} catch (URISyntaxException e) {\n\t\t\tVpnStatus.logError(R.string.getproxy_error, e.getLocalizedMessage());\n\t\t}\n\t\treturn null;\n\t}\n\n\tstatic Proxy getFirstProxy(URL url) throws URISyntaxException {\n\t\tSystem.setProperty(\"java.net.useSystemProxies\", \"true\");\n\n\t\tList<Proxy> proxylist = ProxySelector.getDefault().select(url.toURI());\n\n\n\t\tif (proxylist != null) {\n\t\t\tfor (Proxy proxy: proxylist) {\n\t\t\t\tSocketAddress addr = proxy.address();\n\n\t\t\t\tif (addr != null) {\n\t\t\t\t\treturn proxy;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\treturn null;\n\t}\n}"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Build;\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Arrays;\nimport java.util.Vector;\n\n\nimport de.blinkt.openvpn.VpnProfile;\n\npublic class VPNLaunchHelper {\n    private static final String MININONPIEVPN = \"nopie_openvpn\";\n    private static final String MINIPIEVPN = \"pie_openvpn\";\n    private static final String OVPNCONFIGFILE = \"android.conf\";\n\n\n\n    private static String writeMiniVPN(Context context) {\n        String[] abis;\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)\n            abis = getSupportedABIsLollipop();\n        else\n            //noinspection deprecation\n            abis = new String[]{Build.CPU_ABI, Build.CPU_ABI2};\n\n        String nativeAPI = NativeUtils.getNativeAPI();\n        if (!nativeAPI.equals(abis[0])) {\n            VpnStatus.logWarning(R.string.abi_mismatch, Arrays.toString(abis), nativeAPI);\n            abis = new String[] {nativeAPI};\n        }\n\n        for (String abi: abis) {\n\n            File vpnExecutable = new File(context.getCacheDir(), getMiniVPNExecutableName() + \".\" + abi);\n            if ((vpnExecutable.exists() && vpnExecutable.canExecute()) || writeMiniVPNBinary(context, abi, vpnExecutable)) {\n                return vpnExecutable.getPath();\n            }\n        }\n\n        return null;\n\t}\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    private static String[] getSupportedABIsLollipop() {\n        return Build.SUPPORTED_ABIS;\n    }\n\n    private static String getMiniVPNExecutableName()\n    {\n        if (Build.VERSION.SDK_INT  >= Build.VERSION_CODES.JELLY_BEAN)\n            return MINIPIEVPN;\n        else\n            return MININONPIEVPN;\n    }\n\n\n    public static String[] replacePieWithNoPie(String[] mArgv)\n    {\n        mArgv[0] = mArgv[0].replace(MINIPIEVPN, MININONPIEVPN);\n        return mArgv;\n    }\n\n\n    static String[] buildOpenvpnArgv(Context c) {\n        Vector<String> args = new Vector<>();\n\n        String binaryName = writeMiniVPN(c);\n        // Add fixed paramenters\n        //args.add(\"/data/data/de.blinkt.openvpn/lib/openvpn\");\n        if(binaryName==null) {\n            VpnStatus.logError(\"Error writing minivpn binary\");\n            return null;\n        }\n\n        args.add(binaryName);\n\n        args.add(\"--config\");\n        args.add(getConfigFilePath(c));\n\n        return args.toArray(new String[args.size()]);\n    }\n\n    private static boolean writeMiniVPNBinary(Context context, String abi, File mvpnout) {\n        try {\n            InputStream mvpn;\n\n            try {\n                mvpn = context.getAssets().open(getMiniVPNExecutableName() + \".\" + abi);\n            }\n            catch (IOException errabi) {\n                VpnStatus.logInfo(\"Failed getting assets for archicture \" + abi);\n                return false;\n            }\n\n\n            FileOutputStream fout = new FileOutputStream(mvpnout);\n\n            byte buf[]= new byte[4096];\n\n            int lenread = mvpn.read(buf);\n            while(lenread> 0) {\n                fout.write(buf, 0, lenread);\n                lenread = mvpn.read(buf);\n            }\n            fout.close();\n\n            if(!mvpnout.setExecutable(true)) {\n                VpnStatus.logError(\"Failed to make OpenVPN executable\");\n                return false;\n            }\n\n\n            return true;\n        } catch (IOException e) {\n            VpnStatus.logException(e);\n            return false;\n        }\n\n    }\n\t\n\n\tpublic static void startOpenVpn(VpnProfile startprofile, Context context) {\n\t\tIntent startVPN = startprofile.prepareStartService(context);\n\t\tif(startVPN!=null)\n\t\t\tcontext.startService(startVPN);\n\n\t}\n\n    public static String getConfigFilePath(Context context) {\n        return context.getCacheDir().getAbsolutePath() + \"/\" + OVPNCONFIGFILE;\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.content.Context;\nimport android.os.Build;\nimport android.os.HandlerThread;\nimport android.os.Message;\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport java.io.File;\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.util.LinkedList;\nimport java.util.Locale;\nimport java.util.Vector;\n\n\n\npublic class VpnStatus {\n\n\n    public static LinkedList<LogItem> logbuffer;\n\n    private static Vector<LogListener> logListener;\n    private static Vector<StateListener> stateListener;\n    private static Vector<ByteCountListener> byteCountListener;\n\n    private static String mLaststatemsg = \"\";\n\n    private static String mLaststate = \"NOPROCESS\";\n\n    private static int mLastStateresid = R.string.state_noprocess;\n\n    private static long mlastByteCount[] = {0, 0, 0, 0};\n    private static HandlerThread mHandlerThread;\n\n    public static void logException(LogLevel ll, String context, Exception e) {\n        StringWriter sw = new StringWriter();\n        e.printStackTrace(new PrintWriter(sw));\n        LogItem li;\n        if (context != null) {\n            li = new LogItem(ll, R.string.unhandled_exception_context, e.getMessage(), sw.toString(), context);\n        } else {\n            li = new LogItem(ll, R.string.unhandled_exception, e.getMessage(), sw.toString());\n        }\n        newLogItem(li);\n    }\n\n    public static void logException(Exception e) {\n        logException(LogLevel.ERROR, null, e);\n    }\n\n    public static void logException(String context, Exception e) {\n        logException(LogLevel.ERROR, context, e);\n    }\n\n    static final int MAXLOGENTRIES = 1000;\n\n    public static boolean isVPNActive() {\n        return mLastLevel != ConnectionStatus.LEVEL_AUTH_FAILED && !(mLastLevel == ConnectionStatus.LEVEL_NOTCONNECTED);\n    }\n\n    public static String getLastCleanLogMessage(Context c) {\n        String message = mLaststatemsg;\n        switch (mLastLevel) {\n            case LEVEL_CONNECTED:\n                String[] parts = mLaststatemsg.split(\",\");\n                /*\n                   (a) the integer unix date/time,\n                   (b) the state name,\n                   0 (c) optional descriptive string (used mostly on RECONNECTING\n                    and EXITING to show the reason for the disconnect),\n\n                    1 (d) optional TUN/TAP local IPv4 address\n                   2 (e) optional address of remote server,\n                   3 (f) optional port of remote server,\n                   4 (g) optional local address,\n                   5 (h) optional local port, and\n                   6 (i) optional TUN/TAP local IPv6 address.\n*/\n                // Return only the assigned IP addresses in the UI\n                if (parts.length >= 7)\n                    message = String.format(Locale.US, \"%s %s\", parts[1], parts[6]);\n                break;\n        }\n\n        while (message.endsWith(\",\"))\n            message = message.substring(0, message.length() - 1);\n\n        String status = mLaststate;\n        if (status.equals(\"NOPROCESS\"))\n            return message;\n\n        if (mLastStateresid == R.string.state_waitconnectretry) {\n            return c.getString(R.string.state_waitconnectretry, mLaststatemsg);\n        }\n\n        String prefix = c.getString(mLastStateresid);\n        if (mLastStateresid == R.string.unknown_state)\n            message = status + message;\n        if (message.length() > 0)\n            prefix += \": \";\n\n        return prefix + message;\n\n    }\n\n    public static void initLogCache(File cacheDir) {\n        mHandlerThread = new HandlerThread(\"LogFileWriter\", Thread.MIN_PRIORITY);\n        mHandlerThread.start();\n        mLogFileHandler = new LogFileHandler(mHandlerThread.getLooper());\n\n\n        Message m = mLogFileHandler.obtainMessage(LogFileHandler.LOG_INIT, cacheDir);\n        mLogFileHandler.sendMessage(m);\n\n    }\n\n    public static void flushLog() {\n        if (mLogFileHandler != null)\n            mLogFileHandler.sendEmptyMessage(LogFileHandler.FLUSH_TO_DISK);\n    }\n\n    public enum ConnectionStatus {\n        LEVEL_CONNECTED,\n        LEVEL_VPNPAUSED,\n        LEVEL_CONNECTING_SERVER_REPLIED,\n        LEVEL_CONNECTING_NO_SERVER_REPLY_YET,\n        LEVEL_NONETWORK,\n        LEVEL_NOTCONNECTED,\n        LEVEL_START,\n        LEVEL_AUTH_FAILED,\n        LEVEL_WAITING_FOR_USER_INPUT,\n        UNKNOWN_LEVEL\n    }\n\n    public enum LogLevel {\n        INFO(2),\n        ERROR(-2),\n        WARNING(1),\n        VERBOSE(3),\n        DEBUG(4);\n\n        protected int mValue;\n\n        LogLevel(int value) {\n            mValue = value;\n        }\n\n        public int getInt() {\n            return mValue;\n        }\n\n        public static LogLevel getEnumByValue(int value) {\n            switch (value) {\n                case 1:\n                    return INFO;\n                case 2:\n                    return ERROR;\n                case 3:\n                    return WARNING;\n                case 4:\n                    return DEBUG;\n                default:\n                    return null;\n            }\n        }\n    }\n\n    // keytool -printcert -jarfile de.blinkt.openvpn_85.apk\n    public static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109};\n    public static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43};\n    public static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57};\n    public static final byte[] fdroidkey = {-92, 111, -42, -46, 123, -96, -60, 79, -27, -31, 49, 103, 11, -54, -68, -27, 17, 2, 121, 104};\n\n\n    private static ConnectionStatus mLastLevel = ConnectionStatus.LEVEL_NOTCONNECTED;\n\n    private static LogFileHandler mLogFileHandler;\n\n    static {\n        logbuffer = new LinkedList<>();\n        logListener = new Vector<>();\n        stateListener = new Vector<>();\n        byteCountListener = new Vector<>();\n\n\n        logInformation();\n\n    }\n\n\n    public interface LogListener {\n        void newLog(LogItem logItem);\n    }\n\n    public interface StateListener {\n        void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level);\n    }\n\n    public interface ByteCountListener {\n        void updateByteCount(long in, long out, long diffIn, long diffOut);\n    }\n\n    public synchronized static void logMessage(LogLevel level, String prefix, String message) {\n        newLogItem(new LogItem(level, prefix + message));\n\n    }\n\n    public synchronized static void clearLog() {\n        logbuffer.clear();\n        logInformation();\n        if (mLogFileHandler != null)\n            mLogFileHandler.sendEmptyMessage(LogFileHandler.TRIM_LOG_FILE);\n    }\n\n    private static void logInformation() {\n      /*  String nativeAPI;\n        try {\n            nativeAPI = NativeUtils.getNativeAPI();\n        } catch (UnsatisfiedLinkError ignore) {\n            nativeAPI = \"error\";\n        }\n\n        logInfo(R.string.mobile_info, Build.MODEL, Build.BOARD, Build.BRAND, Build.VERSION.SDK_INT,\n                nativeAPI, Build.VERSION.RELEASE, Build.ID, Build.FINGERPRINT, \"\", \"\");*/\n    }\n\n    public synchronized static void addLogListener(LogListener ll) {\n        logListener.add(ll);\n    }\n\n    public synchronized static void removeLogListener(LogListener ll) {\n        logListener.remove(ll);\n    }\n\n    public synchronized static void addByteCountListener(ByteCountListener bcl) {\n        bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]);\n        byteCountListener.add(bcl);\n    }\n\n    public synchronized static void removeByteCountListener(ByteCountListener bcl) {\n        byteCountListener.remove(bcl);\n    }\n\n\n    public synchronized static void addStateListener(StateListener sl) {\n        if (!stateListener.contains(sl)) {\n            stateListener.add(sl);\n            if (mLaststate != null)\n                sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel);\n        }\n    }\n\n    private static int getLocalizedState(String state) {\n        switch (state) {\n            case \"CONNECTING\":\n                return R.string.state_connecting;\n            case \"WAIT\":\n                return R.string.state_wait;\n            case \"AUTH\":\n                return R.string.state_auth;\n            case \"GET_CONFIG\":\n                return R.string.state_get_config;\n            case \"ASSIGN_IP\":\n                return R.string.state_assign_ip;\n            case \"ADD_ROUTES\":\n                return R.string.state_add_routes;\n            case \"CONNECTED\":\n                return R.string.state_connected;\n            case \"DISCONNECTED\":\n                return R.string.state_disconnected;\n            case \"RECONNECTING\":\n                return R.string.state_reconnecting;\n            case \"EXITING\":\n                return R.string.state_exiting;\n            case \"RESOLVE\":\n                return R.string.state_resolve;\n            case \"TCP_CONNECT\":\n                return R.string.state_tcp_connect;\n            default:\n                return R.string.unknown_state;\n        }\n\n    }\n\n    public static void updateStatePause(OpenVPNManagement.pauseReason pauseReason) {\n        switch (pauseReason) {\n            case noNetwork:\n                VpnStatus.updateStateString(\"NONETWORK\", \"\", R.string.state_nonetwork, ConnectionStatus.LEVEL_NONETWORK);\n                break;\n            case screenOff:\n                VpnStatus.updateStateString(\"SCREENOFF\", \"\", R.string.state_screenoff, ConnectionStatus.LEVEL_VPNPAUSED);\n                break;\n            case userPause:\n                VpnStatus.updateStateString(\"USERPAUSE\", \"\", R.string.state_userpause, ConnectionStatus.LEVEL_VPNPAUSED);\n                break;\n        }\n\n    }\n\n    private static ConnectionStatus getLevel(String state) {\n        String[] noreplyet = {\"CONNECTING\", \"WAIT\", \"RECONNECTING\", \"RESOLVE\", \"TCP_CONNECT\"};\n        String[] reply = {\"AUTH\", \"GET_CONFIG\", \"ASSIGN_IP\", \"ADD_ROUTES\"};\n        String[] connected = {\"CONNECTED\"};\n        String[] notconnected = {\"DISCONNECTED\", \"EXITING\"};\n\n        for (String x : noreplyet)\n            if (state.equals(x))\n                return ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET;\n\n        for (String x : reply)\n            if (state.equals(x))\n                return ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED;\n\n        for (String x : connected)\n            if (state.equals(x))\n                return ConnectionStatus.LEVEL_CONNECTED;\n\n        for (String x : notconnected)\n            if (state.equals(x))\n                return ConnectionStatus.LEVEL_NOTCONNECTED;\n\n        return ConnectionStatus.UNKNOWN_LEVEL;\n\n    }\n\n\n    public synchronized static void removeStateListener(StateListener sl) {\n        stateListener.remove(sl);\n    }\n\n\n    synchronized public static LogItem[] getlogbuffer() {\n\n        // The stoned way of java to return an array from a vector\n        // brought to you by eclipse auto complete\n        return logbuffer.toArray(new LogItem[logbuffer.size()]);\n\n    }\n\n    public static void updateStateString(String state, String msg) {\n        int rid = getLocalizedState(state);\n        ConnectionStatus level = getLevel(state);\n        updateStateString(state, msg, rid, level);\n    }\n\n    public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) {\n        // Workound for OpenVPN doing AUTH and wait and being connected\n        // Simply ignore these state\n        if (mLastLevel == ConnectionStatus.LEVEL_CONNECTED &&\n                (state.equals(\"WAIT\") || state.equals(\"AUTH\"))) {\n            newLogItem(new LogItem((LogLevel.DEBUG), String.format(\"Ignoring OpenVPN Status in CONNECTED state (%s->%s): %s\", state, level.toString(), msg)));\n            return;\n        }\n\n        mLaststate = state;\n        mLaststatemsg = msg;\n        mLastStateresid = resid;\n        mLastLevel = level;\n\n\n        for (StateListener sl : stateListener) {\n            sl.updateState(state, msg, resid, level);\n        }\n        //newLogItem(new LogItem((LogLevel.DEBUG), String.format(\"New OpenVPN Status (%s->%s): %s\",state,level.toString(),msg)));\n    }\n\n    public static void logInfo(String message) {\n        newLogItem(new LogItem(LogLevel.INFO, message));\n    }\n\n    public static void logDebug(String message) {\n        newLogItem(new LogItem(LogLevel.DEBUG, message));\n    }\n\n    public static void logInfo(int resourceId, Object... args) {\n        newLogItem(new LogItem(LogLevel.INFO, resourceId, args));\n    }\n\n    public static void logDebug(int resourceId, Object... args) {\n        newLogItem(new LogItem(LogLevel.DEBUG, resourceId, args));\n    }\n\n    private static void newLogItem(LogItem logItem) {\n        newLogItem(logItem, false);\n    }\n\n\n    synchronized static void newLogItem(LogItem logItem, boolean cachedLine) {\n        if (cachedLine) {\n            logbuffer.addFirst(logItem);\n        } else {\n            logbuffer.addLast(logItem);\n            if (mLogFileHandler != null) {\n                Message m = mLogFileHandler.obtainMessage(LogFileHandler.LOG_MESSAGE, logItem);\n                mLogFileHandler.sendMessage(m);\n            }\n        }\n\n        if (logbuffer.size() > MAXLOGENTRIES + MAXLOGENTRIES / 2) {\n            while (logbuffer.size() > MAXLOGENTRIES)\n                logbuffer.removeFirst();\n            if (mLogFileHandler != null)\n                mLogFileHandler.sendMessage(mLogFileHandler.obtainMessage(LogFileHandler.TRIM_LOG_FILE));\n        }\n\n        //if (BuildConfig.DEBUG && !cachedLine && !BuildConfig.FLAVOR.equals(\"test\"))\n        //    Log.d(\"OpenVPN\", logItem.getString(null));\n\n\n        for (LogListener ll : logListener) {\n            ll.newLog(logItem);\n        }\n    }\n\n\n    public static void logError(String msg) {\n        newLogItem(new LogItem(LogLevel.ERROR, msg));\n\n    }\n\n    public static void logWarning(int resourceId, Object... args) {\n        newLogItem(new LogItem(LogLevel.WARNING, resourceId, args));\n    }\n\n    public static void logWarning(String msg) {\n        newLogItem(new LogItem(LogLevel.WARNING, msg));\n    }\n\n\n    public static void logError(int resourceId) {\n        newLogItem(new LogItem(LogLevel.ERROR, resourceId));\n    }\n\n    public static void logError(int resourceId, Object... args) {\n        newLogItem(new LogItem(LogLevel.ERROR, resourceId, args));\n    }\n\n    public static void logMessageOpenVPN(LogLevel level, int ovpnlevel, String message) {\n        newLogItem(new LogItem(level, ovpnlevel, message));\n\n    }\n\n\n    public static synchronized void updateByteCount(long in, long out) {\n        long lastIn = mlastByteCount[0];\n        long lastOut = mlastByteCount[1];\n        long diffIn = mlastByteCount[2] = Math.max(0, in - lastIn);\n        long diffOut = mlastByteCount[3] = Math.max(0, out - lastOut);\n\n\n        mlastByteCount = new long[]{in, out, diffIn, diffOut};\n        for (ByteCountListener bcl : byteCountListener) {\n            bcl.updateByteCount(in, out, diffIn, diffOut);\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage de.blinkt.openvpn.core;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.text.TextUtils;\n\n\nimport com.vasilkoff.easyvpnfree.R;\n\nimport de.blinkt.openvpn.VpnProfile;\nimport org.spongycastle.util.io.pem.PemObject;\nimport org.spongycastle.util.io.pem.PemReader;\n\n\nimport javax.security.auth.x500.X500Principal;\nimport java.io.*;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateExpiredException;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.CertificateNotYetValidException;\nimport java.security.cert.X509Certificate;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.Hashtable;\nimport java.util.Vector;\n\npublic class X509Utils {\n\tpublic static Certificate[] getCertificatesFromFile(String certfilename) throws FileNotFoundException, CertificateException {\n\t\tCertificateFactory certFact = CertificateFactory.getInstance(\"X.509\");\n\n        Vector<Certificate> certificates = new Vector<>();\n\t\tif(VpnProfile.isEmbedded(certfilename)) {\n            int subIndex = certfilename.indexOf(\"-----BEGIN CERTIFICATE-----\");\n            do {\n                // The java certifcate reader is ... kind of stupid\n                // It does NOT ignore chars before the --BEGIN ...\n\n                subIndex = Math.max(0, subIndex);\n                InputStream inStream = new ByteArrayInputStream(certfilename.substring(subIndex).getBytes());\n                certificates.add(certFact.generateCertificate(inStream));\n\n                subIndex = certfilename.indexOf(\"-----BEGIN CERTIFICATE-----\", subIndex+1);\n            } while (subIndex > 0);\n            return certificates.toArray(new Certificate[certificates.size()]);\n        } else {\n\t\t\tInputStream inStream = new FileInputStream(certfilename);\n            return new Certificate[] {certFact.generateCertificate(inStream)};\n        }\n\n\n\t}\n\n\tpublic static PemObject readPemObjectFromFile (String keyfilename) throws IOException {\n\n\t\tReader inStream;\n\n\t\tif(VpnProfile.isEmbedded(keyfilename))\n\t\t\tinStream = new StringReader(VpnProfile.getEmbeddedContent(keyfilename));\n\t\telse \n\t\t\tinStream = new FileReader(new File(keyfilename));\n\n\t\tPemReader pr = new PemReader(inStream);\n\t\tPemObject r = pr.readPemObject();\n\t\tpr.close();\n\t\treturn r;\n\t}\n\n\n\n\n\tpublic static String getCertificateFriendlyName (Context c, String filename) {\n\t\tif(!TextUtils.isEmpty(filename)) {\n\t\t\ttry {\n\t\t\t\tX509Certificate cert = (X509Certificate) getCertificatesFromFile(filename)[0];\n                String friendlycn = getCertificateFriendlyName(cert);\n                friendlycn = getCertificateValidityString(cert, c.getResources()) + friendlycn;\n                return friendlycn;\n\n\t\t\t} catch (Exception e) {\n\t\t\t\tVpnStatus.logError(\"Could not read certificate\" + e.getLocalizedMessage());\n\t\t\t}\n\t\t}\n\t\treturn c.getString(R.string.cannotparsecert);\n\t}\n\n    public static String getCertificateValidityString(X509Certificate cert, Resources res) {\n        try {\n            cert.checkValidity();\n        } catch (CertificateExpiredException ce) {\n            return \"EXPIRED: \";\n        } catch (CertificateNotYetValidException cny) {\n            return \"NOT YET VALID: \";\n        }\n\n        Date certNotAfter = cert.getNotAfter();\n        Date now = new Date();\n        long timeLeft = certNotAfter.getTime() - now.getTime(); // Time left in ms\n\n        // More than 72h left, display days\n        // More than 3 months display months\n        if (timeLeft > 90l* 24 * 3600 * 1000) {\n            long months = getMonthsDifference(now, certNotAfter);\n            return res.getString(R.string.months_left, months);\n        } else if (timeLeft > 72 * 3600 * 1000) {\n            long days = timeLeft / (24 * 3600 * 1000);\n            return res.getString(R.string.days_left, days);\n        } else {\n            long hours = timeLeft / (3600 * 1000);\n\n            return res.getString(R.string.hours_left, hours);\n        }\n    }\n\n    public static int getMonthsDifference(Date date1, Date date2) {\n        int m1 = date1.getYear() * 12 + date1.getMonth();\n        int m2 = date2.getYear() * 12 + date2.getMonth();\n        return m2 - m1 + 1;\n    }\n\n    public static String getCertificateFriendlyName(X509Certificate cert) {\n        X500Principal principal = cert.getSubjectX500Principal();\n        byte[] encodedSubject = principal.getEncoded();\n        String friendlyName=null;\n\n        /* Hack so we do not have to ship a whole Spongy/bouncycastle */\n        Exception exp=null;\n        try {\n            Class X509NameClass = Class.forName(\"com.android.org.bouncycastle.asn1.x509.X509Name\");\n            Method getInstance = X509NameClass.getMethod(\"getInstance\",Object.class);\n\n            Hashtable defaultSymbols = (Hashtable) X509NameClass.getField(\"DefaultSymbols\").get(X509NameClass);\n\n            if (!defaultSymbols.containsKey(\"1.2.840.113549.1.9.1\"))\n                defaultSymbols.put(\"1.2.840.113549.1.9.1\",\"eMail\");\n\n            Object subjectName = getInstance.invoke(X509NameClass, encodedSubject);\n\n            Method toString = X509NameClass.getMethod(\"toString\",boolean.class,Hashtable.class);\n\n            friendlyName= (String) toString.invoke(subjectName,true,defaultSymbols);\n                    \n        } catch (ClassNotFoundException e) {\n            exp =e ;\n        } catch (NoSuchMethodException e) {\n            exp =e;\n        } catch (InvocationTargetException e) {\n            exp =e;\n        } catch (IllegalAccessException e) {\n            exp =e;\n        } catch (NoSuchFieldException e) {\n            exp =e;\n        }\n        if (exp!=null)\n            VpnStatus.logException(\"Getting X509 Name from certificate\", exp);\n\n        /* Fallback if the reflection method did not work */\n        if(friendlyName==null)\n            friendlyName = principal.getName();\n\n\n        // Really evil hack to decode email address\n        // See: http://code.google.com/p/android/issues/detail?id=21531\n\n        String[] parts = friendlyName.split(\",\");\n        for (int i=0;i<parts.length;i++){\n            String part = parts[i];\n            if (part.startsWith(\"1.2.840.113549.1.9.1=#16\")) {\n                parts[i] = \"email=\" + ia5decode(part.replace(\"1.2.840.113549.1.9.1=#16\", \"\"));\n            }\n        }\n        friendlyName = TextUtils.join(\",\", parts);\n        return friendlyName;\n    }\n\n    public static boolean isPrintableChar(char c) {\n        Character.UnicodeBlock block = Character.UnicodeBlock.of( c );\n        return (!Character.isISOControl(c)) &&\n                block != null &&\n                block != Character.UnicodeBlock.SPECIALS;\n    }\n\n    private static String ia5decode(String ia5string) {\n        String d = \"\";\n        for (int i=1;i<ia5string.length();i=i+2) {\n            String hexstr = ia5string.substring(i-1,i+1);\n            char c = (char) Integer.parseInt(hexstr,16);\n            if (isPrintableChar(c)) {\n                d+=c;\n            } else if (i==1 && (c==0x12 || c==0x1b)) {\n                ;   // ignore\n            } else {\n                d += \"\\\\x\" + hexstr;\n            }\n        }\n        return d;\n    }\n\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/encoders/Base64.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.encoders;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\n\npublic class Base64\n{\n    private static final Encoder encoder = new Base64Encoder();\n    \n    /**\n     * encode the input data producing a base 64 encoded byte array.\n     *\n     * @return a byte array containing the base 64 encoded data.\n     */\n    public static byte[] encode(\n        byte[]    data)\n    {\n        int len = (data.length + 2) / 3 * 4;\n        ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);\n        \n        try\n        {\n            encoder.encode(data, 0, data.length, bOut);\n        }\n        catch (IOException e)\n        {\n            throw new RuntimeException(\"exception encoding base64 string: \" + e);\n        }\n        \n        return bOut.toByteArray();\n    }\n\n    /**\n     * Encode the byte data to base 64 writing it to the given output stream.\n     *\n     * @return the number of bytes produced.\n     */\n    public static int encode(\n        byte[]                data,\n        OutputStream    out)\n        throws IOException\n    {\n        return encoder.encode(data, 0, data.length, out);\n    }\n    \n    /**\n     * Encode the byte data to base 64 writing it to the given output stream.\n     *\n     * @return the number of bytes produced.\n     */\n    public static int encode(\n        byte[]                data,\n        int                    off,\n        int                    length,\n        OutputStream    out)\n        throws IOException\n    {\n        return encoder.encode(data, off, length, out);\n    }\n    \n    /**\n     * decode the base 64 encoded input data. It is assumed the input data is valid.\n     *\n     * @return a byte array representing the decoded data.\n     */\n    public static byte[] decode(\n        byte[]    data)\n    {\n        int len = data.length / 4 * 3;\n        ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);\n        \n        try\n        {\n            encoder.decode(data, 0, data.length, bOut);\n        }\n        catch (IOException e)\n        {\n            throw new RuntimeException(\"exception decoding base64 string: \" + e);\n        }\n        \n        return bOut.toByteArray();\n    }\n    \n    /**\n     * decode the base 64 encoded String data - whitespace will be ignored.\n     *\n     * @return a byte array representing the decoded data.\n     */\n    public static byte[] decode(\n        String    data)\n    {\n        int len = data.length() / 4 * 3;\n        ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);\n        \n        try\n        {\n            encoder.decode(data, bOut);\n        }\n        catch (IOException e)\n        {\n            throw new RuntimeException(\"exception decoding base64 string: \" + e);\n        }\n        \n        return bOut.toByteArray();\n    }\n    \n    /**\n     * decode the base 64 encoded String data writing it to the given output stream,\n     * whitespace characters will be ignored.\n     *\n     * @return the number of bytes produced.\n     */\n    public static int decode(\n        String                data,\n        OutputStream    out)\n        throws IOException\n    {\n        return encoder.decode(data, out);\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.encoders;\n\nimport java.io.IOException;\nimport java.io.OutputStream;\n\npublic class Base64Encoder\n    implements Encoder\n{\n    protected final byte[] encodingTable =\n        {\n            (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',\n            (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',\n            (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',\n            (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',\n            (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',\n            (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',\n            (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',\n            (byte)'v',\n            (byte)'w', (byte)'x', (byte)'y', (byte)'z',\n            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',\n            (byte)'7', (byte)'8', (byte)'9',\n            (byte)'+', (byte)'/'\n        };\n\n    protected byte    padding = (byte)'=';\n    \n    /*\n     * set up the decoding table.\n     */\n    protected final byte[] decodingTable = new byte[128];\n\n    protected void initialiseDecodingTable()\n    {\n        for (int i = 0; i < encodingTable.length; i++)\n        {\n            decodingTable[encodingTable[i]] = (byte)i;\n        }\n    }\n    \n    public Base64Encoder()\n    {\n        initialiseDecodingTable();\n    }\n    \n    /**\n     * encode the input data producing a base 64 output stream.\n     *\n     * @return the number of bytes produced.\n     */\n    public int encode(\n        byte[]                data,\n        int                    off,\n        int                    length,\n        OutputStream    out) \n        throws IOException\n    {\n        int modulus = length % 3;\n        int dataLength = (length - modulus);\n        int a1, a2, a3;\n        \n        for (int i = off; i < off + dataLength; i += 3)\n        {\n            a1 = data[i] & 0xff;\n            a2 = data[i + 1] & 0xff;\n            a3 = data[i + 2] & 0xff;\n\n            out.write(encodingTable[(a1 >>> 2) & 0x3f]);\n            out.write(encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]);\n            out.write(encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]);\n            out.write(encodingTable[a3 & 0x3f]);\n        }\n\n        /*\n         * process the tail end.\n         */\n        int    b1, b2, b3;\n        int    d1, d2;\n\n        switch (modulus)\n        {\n        case 0:        /* nothing left to do */\n            break;\n        case 1:\n            d1 = data[off + dataLength] & 0xff;\n            b1 = (d1 >>> 2) & 0x3f;\n            b2 = (d1 << 4) & 0x3f;\n\n            out.write(encodingTable[b1]);\n            out.write(encodingTable[b2]);\n            out.write(padding);\n            out.write(padding);\n            break;\n        case 2:\n            d1 = data[off + dataLength] & 0xff;\n            d2 = data[off + dataLength + 1] & 0xff;\n\n            b1 = (d1 >>> 2) & 0x3f;\n            b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;\n            b3 = (d2 << 2) & 0x3f;\n\n            out.write(encodingTable[b1]);\n            out.write(encodingTable[b2]);\n            out.write(encodingTable[b3]);\n            out.write(padding);\n            break;\n        }\n\n        return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);\n    }\n\n    private boolean ignore(\n        char    c)\n    {\n        return (c == '\\n' || c =='\\r' || c == '\\t' || c == ' ');\n    }\n    \n    /**\n     * decode the base 64 encoded byte data writing it to the given output stream,\n     * whitespace characters will be ignored.\n     *\n     * @return the number of bytes produced.\n     */\n    public int decode(\n        byte[]          data,\n        int             off,\n        int             length,\n        OutputStream    out)\n        throws IOException\n    {\n        byte    b1, b2, b3, b4;\n        int     outLen = 0;\n        \n        int     end = off + length;\n        \n        while (end > off)\n        {\n            if (!ignore((char)data[end - 1]))\n            {\n                break;\n            }\n            \n            end--;\n        }\n        \n        int  i = off;\n        int  finish = end - 4;\n        \n        i = nextI(data, i, finish);\n\n        while (i < finish)\n        {\n            b1 = decodingTable[data[i++]];\n            \n            i = nextI(data, i, finish);\n            \n            b2 = decodingTable[data[i++]];\n            \n            i = nextI(data, i, finish);\n            \n            b3 = decodingTable[data[i++]];\n            \n            i = nextI(data, i, finish);\n            \n            b4 = decodingTable[data[i++]];\n\n            out.write((b1 << 2) | (b2 >> 4));\n            out.write((b2 << 4) | (b3 >> 2));\n            out.write((b3 << 6) | b4);\n            \n            outLen += 3;\n            \n            i = nextI(data, i, finish);\n        }\n\n        outLen += decodeLastBlock(out, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);\n        \n        return outLen;\n    }\n\n    private int nextI(byte[] data, int i, int finish)\n    {\n        while ((i < finish) && ignore((char)data[i]))\n        {\n            i++;\n        }\n        return i;\n    }\n    \n    /**\n     * decode the base 64 encoded String data writing it to the given output stream,\n     * whitespace characters will be ignored.\n     *\n     * @return the number of bytes produced.\n     */\n    public int decode(\n        String          data,\n        OutputStream    out)\n        throws IOException\n    {\n        byte    b1, b2, b3, b4;\n        int     length = 0;\n        \n        int     end = data.length();\n        \n        while (end > 0)\n        {\n            if (!ignore(data.charAt(end - 1)))\n            {\n                break;\n            }\n            \n            end--;\n        }\n        \n        int  i = 0;\n        int  finish = end - 4;\n        \n        i = nextI(data, i, finish);\n        \n        while (i < finish)\n        {\n            b1 = decodingTable[data.charAt(i++)];\n            \n            i = nextI(data, i, finish);\n            \n            b2 = decodingTable[data.charAt(i++)];\n            \n            i = nextI(data, i, finish);\n            \n            b3 = decodingTable[data.charAt(i++)];\n            \n            i = nextI(data, i, finish);\n            \n            b4 = decodingTable[data.charAt(i++)];\n\n            out.write((b1 << 2) | (b2 >> 4));\n            out.write((b2 << 4) | (b3 >> 2));\n            out.write((b3 << 6) | b4);\n            \n            length += 3;\n            \n            i = nextI(data, i, finish);\n        }\n\n        length += decodeLastBlock(out, data.charAt(end - 4), data.charAt(end - 3), data.charAt(end - 2), data.charAt(end - 1));\n\n        return length;\n    }\n\n    private int decodeLastBlock(OutputStream out, char c1, char c2, char c3, char c4) \n        throws IOException\n    {\n        byte    b1, b2, b3, b4;\n        \n        if (c3 == padding)\n        {\n            b1 = decodingTable[c1];\n            b2 = decodingTable[c2];\n\n            out.write((b1 << 2) | (b2 >> 4));\n            \n            return 1;\n        }\n        else if (c4 == padding)\n        {\n            b1 = decodingTable[c1];\n            b2 = decodingTable[c2];\n            b3 = decodingTable[c3];\n\n            out.write((b1 << 2) | (b2 >> 4));\n            out.write((b2 << 4) | (b3 >> 2));\n            \n            return 2;\n        }\n        else\n        {\n            b1 = decodingTable[c1];\n            b2 = decodingTable[c2];\n            b3 = decodingTable[c3];\n            b4 = decodingTable[c4];\n\n            out.write((b1 << 2) | (b2 >> 4));\n            out.write((b2 << 4) | (b3 >> 2));\n            out.write((b3 << 6) | b4);\n            \n            return 3;\n        } \n    }\n\n    private int nextI(String data, int i, int finish)\n    {\n        while ((i < finish) && ignore(data.charAt(i)))\n        {\n            i++;\n        }\n        return i;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/encoders/Encoder.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.encoders;\n\nimport java.io.IOException;\nimport java.io.OutputStream;\n\n/**\n * Encode and decode byte arrays (typically from binary to 7-bit ASCII \n * encodings).\n */\npublic interface Encoder\n{\n    int encode(byte[] data, int off, int length, OutputStream out) throws IOException;\n    \n    int decode(byte[] data, int off, int length, OutputStream out) throws IOException;\n\n    int decode(String data, OutputStream out) throws IOException;\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.io.pem;\n\nimport java.io.IOException;\n\n@SuppressWarnings(\"serial\")\npublic class PemGenerationException\n    extends IOException\n{\n    private Throwable cause;\n\n    public PemGenerationException(String message, Throwable cause)\n    {\n        super(message);\n        this.cause = cause;\n    }\n\n    public PemGenerationException(String message)\n    {\n        super(message);\n    }\n\n    public Throwable getCause()\n    {\n        return cause;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/io/pem/PemHeader.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.io.pem;\n\npublic class PemHeader\n{\n    private String name;\n    private String value;\n\n    public PemHeader(String name, String value)\n    {\n        this.name = name;\n        this.value = value;\n    }\n\n    public String getName()\n    {\n        return name;\n    }\n\n    public String getValue()\n    {\n        return value;\n    }\n\n    public int hashCode()\n    {\n        return getHashCode(this.name) + 31 * getHashCode(this.value);    \n    }\n\n    public boolean equals(Object o)\n    {\n        if (!(o instanceof PemHeader))\n        {\n            return false;\n        }\n\n        PemHeader other = (PemHeader)o;\n\n        return other == this || (isEqual(this.name, other.name) && isEqual(this.value, other.value));\n    }\n\n    private int getHashCode(String s)\n    {\n        if (s == null)\n        {\n            return 1;\n        }\n\n        return s.hashCode();\n    }\n\n    private boolean isEqual(String s1, String s2)\n    {\n        if (s1 == s2)\n        {\n            return true;\n        }\n\n        if (s1 == null || s2 == null)\n        {\n            return false;\n        }\n\n        return s1.equals(s2);\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/io/pem/PemObject.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.io.pem;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n@SuppressWarnings(\"all\")\npublic class PemObject\n    implements PemObjectGenerator\n{\n\tprivate static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());\n\n    private String type;\n    private List   headers;\n    private byte[] content;\n\n    /**\n     * Generic constructor for object without headers.\n     *\n     * @param type pem object type.\n     * @param content the binary content of the object.\n     */\n    public PemObject(String type, byte[] content)\n    {\n        this(type, EMPTY_LIST, content);\n    }\n\n    /**\n     * Generic constructor for object with headers.\n     *\n     * @param type pem object type.\n     * @param headers a list of PemHeader objects.\n     * @param content the binary content of the object.\n     */\n    public PemObject(String type, List headers, byte[] content)\n    {\n        this.type = type;\n        this.headers = Collections.unmodifiableList(headers);\n        this.content = content;\n    }\n\n    public String getType()\n    {\n        return type;\n    }\n\n    public List getHeaders()\n    {\n        return headers;\n    }\n\n    public byte[] getContent()\n    {\n        return content;\n    }\n\n    public PemObject generate()\n        throws PemGenerationException\n    {\n        return this;\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.io.pem;\n\npublic interface PemObjectGenerator\n{\n    PemObject generate()\n        throws PemGenerationException;\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/io/pem/PemReader.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.io.pem;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.spongycastle.util.encoders.Base64;\n\npublic class PemReader\n    extends BufferedReader\n{\n    private static final String BEGIN = \"-----BEGIN \";\n    private static final String END = \"-----END \";\n\n    public PemReader(Reader reader)\n    {\n        super(reader);\n    }\n\n    public PemObject readPemObject()\n        throws IOException\n    {\n        String line = readLine();\n\n        while (line != null && !line.startsWith(BEGIN))\n        {\n            line = readLine();\n        }\n\n        if (line != null)\n        {\n            line = line.substring(BEGIN.length());\n            int index = line.indexOf('-');\n            String type = line.substring(0, index);\n\n            if (index > 0)\n            {\n                return loadObject(type);\n            }\n        }\n\n        return null;\n    }\n\n    private PemObject loadObject(String type)\n        throws IOException\n    {\n        String          line;\n        String          endMarker = END + type;\n        StringBuilder buf = new StringBuilder();\n        List            headers = new ArrayList();\n\n        while ((line = readLine()) != null)\n        {\n            if (line.indexOf(\":\") >= 0)\n            {\n                int index = line.indexOf(':');\n                String hdr = line.substring(0, index);\n                String value = line.substring(index + 1).trim();\n\n                headers.add(new PemHeader(hdr, value));\n\n                continue;\n            }\n\n            if (line.indexOf(endMarker) != -1)\n            {\n                break;\n            }\n            \n            buf.append(line.trim());\n        }\n\n        if (line == null)\n        {\n            throw new IOException(endMarker + \" not found\");\n        }\n\n        return new PemObject(type, headers, Base64.decode(buf.toString()));\n    }\n\n}\n"
  },
  {
    "path": "Android-code/app/src/main/java/org/spongycastle/util/io/pem/PemWriter.java",
    "content": "/*\n * Copyright (c) 2012-2016 Arne Schwabe\n * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n */\n\npackage org.spongycastle.util.io.pem;\n\nimport java.io.BufferedWriter;\nimport java.io.IOException;\nimport java.io.Writer;\nimport java.util.Iterator;\n\nimport org.spongycastle.util.encoders.Base64;\n\n/**\n * A generic PEM writer, based on RFC 1421\n */\n@SuppressWarnings(\"all\")\npublic class PemWriter\n    extends BufferedWriter\n{\n    private static final int LINE_LENGTH = 64;\n\n    private final int nlLength;\n    private char[]  buf = new char[LINE_LENGTH];\n\n    /**\n     * Base constructor.\n     *\n     * @param out output stream to use.\n     */\n    public PemWriter(Writer out)\n    {\n        super(out);\n\n        String nl = System.getProperty(\"line.separator\");\n        if (nl != null)\n        {\n            nlLength = nl.length();\n        }\n        else\n        {\n            nlLength = 2;\n        }\n    }\n\n    /**\n     * Return the number of bytes or characters required to contain the\n     * passed in object if it is PEM encoded.\n     *\n     * @param obj pem object to be output\n     * @return an estimate of the number of bytes\n     */\n    public int getOutputSize(PemObject obj)\n    {\n        // BEGIN and END boundaries.\n        int size = (2 * (obj.getType().length() + 10 + nlLength)) + 6 + 4;\n\n        if (!obj.getHeaders().isEmpty())\n        {\n            for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)\n            {\n                PemHeader hdr = (PemHeader)it.next();\n\n                size += hdr.getName().length() + \": \".length() + hdr.getValue().length() + nlLength;\n            }\n\n            size += nlLength;\n        }\n\n        // base64 encoding\n        int dataLen = ((obj.getContent().length + 2) / 3) * 4;\n        \n        size += dataLen + (((dataLen + LINE_LENGTH - 1) / LINE_LENGTH) * nlLength);\n\n        return size;\n    }\n    \n    public void writeObject(PemObjectGenerator objGen)\n        throws IOException\n    {\n        PemObject obj = objGen.generate();\n\n        writePreEncapsulationBoundary(obj.getType());\n\n        if (!obj.getHeaders().isEmpty())\n        {\n            for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)\n            {\n                PemHeader hdr = (PemHeader)it.next();\n\n                this.write(hdr.getName());\n                this.write(\": \");\n                this.write(hdr.getValue());\n                this.newLine();\n            }\n\n            this.newLine();\n        }\n        \n        writeEncoded(obj.getContent());\n        writePostEncapsulationBoundary(obj.getType());\n    }\n\n    private void writeEncoded(byte[] bytes)\n        throws IOException\n    {\n        bytes = Base64.encode(bytes);\n\n        for (int i = 0; i < bytes.length; i += buf.length)\n        {\n            int index = 0;\n\n            while (index != buf.length)\n            {\n                if ((i + index) >= bytes.length)\n                {\n                    break;\n                }\n                buf[index] = (char)bytes[i + index];\n                index++;\n            }\n            this.write(buf, 0, index);\n            this.newLine();\n        }\n    }\n\n    private void writePreEncapsulationBoundary(\n        String type)\n        throws IOException\n    {\n        this.write(\"-----BEGIN \" + type + \"-----\");\n        this.newLine();\n    }\n\n    private void writePostEncapsulationBoundary(\n        String type)\n        throws IOException\n    {\n        this.write(\"-----END \" + type + \"-----\");\n        this.newLine();\n    }\n}\n"
  },
  {
    "path": "Android-code/app/src/main/res/anim/scale.xml",
    "content": "<scale\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"200\"\n    android:fillAfter=\"true\"\n    android:fromXScale=\"0.8\"\n    android:fromYScale=\"0.8\"\n    android:pivotX=\"50%\"\n    android:pivotY=\"50%\"\n    android:toXScale=\"1.0\"\n    android:toYScale=\"1.0\" >\n</scale>"
  },
  {
    "path": "Android-code/app/src/main/res/drawable/button_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item>\n        <shape android:shape=\"rectangle\">\n            <solid android:color=\"@color/buttonBg\"/>\n            <corners android:radius=\"10dp\"/>\n        </shape>\n    </item>\n</selector>"
  },
  {
    "path": "Android-code/app/src/main/res/drawable/connected_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n<item>\n    <shape android:shape=\"rectangle\">\n        <solid android:color=\"#ff7e00\"/>\n        <corners android:radius=\"10dp\"/>\n    </shape>\n</item>\n</selector>"
  },
  {
    "path": "Android-code/app/src/main/res/drawable/info_servers_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item>\n        <shape android:shape=\"rectangle\" >\n            <solid android:color=\"#FFFFFF\" />\n            <stroke\n                android:width=\"2dp\"\n                android:color=\"#1c3f61\" />\n        </shape>\n    </item>\n</selector>"
  },
  {
    "path": "Android-code/app/src/main/res/drawable/server_info_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item\n        android:left=\"-3dp\"\n        android:right=\"-3dp\"\n        android:top=\"-3dp\">\n        <shape android:shape=\"rectangle\" >\n            <solid android:color=\"#FAFAFA\" />\n            <stroke\n                android:width=\"1dp\"\n                android:color=\"#d7d7d7\" />\n        </shape>\n    </item>\n</layer-list>"
  },
  {
    "path": "Android-code/app/src/main/res/drawable/side_nav_bar.xml",
    "content": "<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <gradient\n        android:angle=\"135\"\n        android:centerColor=\"#4CAF50\"\n        android:endColor=\"#2E7D32\"\n        android:startColor=\"#81C784\"\n        android:type=\"linear\" />\n</shape>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_about.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/activity_about\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:orientation=\"vertical\"\n    tools:context=\"com.vasilkoff.easyvpnfree.activity.AboutActivity\">\n    <TextView\n        android:id=\"@+id/appVersion\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/app_name\"\n        android:autoLink=\"web\"/>\n    <ScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n        <TextView\n            android:id=\"@+id/aboutApp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/aboutApp\"\n            android:autoLink=\"web\"/>\n    </ScrollView>\n</LinearLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_base.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v4.widget.DrawerLayout\n    android:id=\"@+id/activity_container\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n        <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            android:background=\"@color/toolbarBg\"\n            app:titleTextColor=\"@color/toolbarTitle\"\n            app:titleMarginStart=\"20dp\"\n            app:contentInsetStart=\"10dp\"\n            app:logo=\"@drawable/ic_app_small\"/>\n\n        <FrameLayout\n            android:id=\"@+id/activity_content\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\" />\n            <ListView\n                android:id=\"@android:id/list\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\" />\n    </LinearLayout>\n</android.support.v4.widget.DrawerLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_bookmark_server_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/activity_bookmark_server_list\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\"com.vasilkoff.easyvpnfree.activity.BookmarkServerListActivity\">\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:background=\"@color/serverNameBg\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\"\n        android:layout_marginBottom=\"10dp\"\n        android:id=\"@+id/bookmarkTitleLayout\">\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/bookmarks\"\n            android:layout_gravity=\"center\"\n            android:textStyle=\"bold\"\n            style=\"@style/serverName\"/>\n    </LinearLayout>\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/bookmarkRv\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@+id/bookmarkTitleLayout\"\n        android:layout_alignParentStart=\"true\" />\n\n</RelativeLayout>\n"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_home.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    android:id=\"@+id/homeContextRL\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"com.vasilkoff.easyvpnfree.activity.HomeActivity\">\n\n    <LinearLayout\n        android:id=\"@+id/map\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"horizontal\">\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:gravity=\"center\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_marginBottom=\"10dp\">\n\n        <Button\n            android:id=\"@+id/homeBtnRandomConnection\"\n            android:text=\"@string/random_connection\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            style=\"@style/buttons\"\n            android:minHeight=\"40dp\"\n            android:onClick=\"homeOnClick\"\n            android:padding=\"5dp\"\n            android:minWidth=\"180dp\"\n            android:layout_marginBottom=\"10dp\"/>\n\n        <Button\n            android:id=\"@+id/homeBtnChooseCountry\"\n            android:text=\"@string/home_btn_choose_country\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            style=\"@style/buttons\"\n            android:minHeight=\"40dp\"\n            android:minWidth=\"180dp\"\n            android:onClick=\"homeOnClick\"\n            android:padding=\"5dp\" />\n        <TextView\n            android:id=\"@+id/homeTotalServers\"\n            android:textColor=\"@color/totalServers\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:gravity=\"center\"/>\n\n    </LinearLayout>\n\n</RelativeLayout>\n\n"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_loader.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\"com.vasilkoff.easyvpnfree.activity.LoaderActivity\">\n\n    <LinearLayout\n        android:orientation=\"vertical\"\n        android:layout_gravity=\"center_vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentStart=\"true\"\n        android:id=\"@+id/linearLayout\">\n\n        <TextView\n            android:id=\"@+id/loaderPremiumText\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/loading_additional_servers\"\n            android:layout_gravity=\"center\"\n            android:textAllCaps=\"true\"\n            android:layout_marginBottom=\"20dp\"\n            android:visibility=\"gone\"/>\n\n        <com.daimajia.numberprogressbar.NumberProgressBar\n            android:id=\"@+id/number_progress_bar\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            />\n        <TextView\n            android:id=\"@+id/commentsText\"\n            android:layout_marginTop=\"@dimen/activity_vertical_margin\"\n            android:text=\"@string/loading_text\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\" />\n    </LinearLayout>\n\n</RelativeLayout>\n"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_preference.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <android.support.v7.widget.Toolbar\n        android:id=\"@+id/preferenceToolbar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"?attr/actionBarSize\"\n        android:background=\"@color/toolbarBg\"\n        app:navigationIcon=\"?attr/homeAsUpIndicator\"\n        app:titleTextColor=\"@color/toolbarTitle\"\n        app:logo=\"@drawable/ic_app_small\"/>\n\n    <FrameLayout\n        android:id=\"@+id/preferenceContent\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n        <ListView\n            android:id=\"@android:id/list\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\" />\n    </FrameLayout>\n\n</LinearLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_server.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/serverParentLayout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    tools:context=\"com.vasilkoff.easyvpnfree.activity.ServerActivity\">\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\"\n        android:background=\"@color/serverNameBg\"\n        android:layout_marginTop=\"15dp\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\">\n\n        <TextView\n            android:id=\"@+id/serverCountry\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textStyle=\"bold\"\n            style=\"@style/serverName\"/>\n\n        <TextView\n            android:id=\"@+id/serverCity\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            style=\"@style/serverName\"\n            android:paddingStart=\"5dp\"/>\n\n    </LinearLayout>\n        <ImageButton\n            android:id=\"@+id/serverBookmark\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"@drawable/ic_bookmark_grey\"\n            android:layout_alignParentEnd=\"true\"\n            android:layout_marginEnd=\"30dp\"\n            android:layout_marginTop=\"13dp\"\n            android:onClick=\"serverOnClick\"/>\n    </RelativeLayout>\n    <ScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:paddingBottom=\"@dimen/activity_vertical_margin\"\n            android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n            android:paddingRight=\"@dimen/activity_horizontal_margin\"\n            android:paddingTop=\"@dimen/activity_vertical_margin\">\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\"\n                android:background=\"@drawable/server_info_bg\"\n                android:padding=\"10dp\">\n                <LinearLayout\n                    android:orientation=\"horizontal\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\">\n                    <LinearLayout\n                        android:layout_width=\"0dp\"\n                        android:layout_weight=\"2\"\n                        android:layout_height=\"wrap_content\"\n                        android:orientation=\"vertical\">\n\n                        <ImageView\n                            android:id=\"@+id/serverFlag\"\n                            android:layout_width=\"wrap_content\"\n                            android:layout_height=\"wrap_content\"/>\n                        <Button\n                            android:id=\"@+id/serverConnect\"\n                            android:layout_width=\"wrap_content\"\n                            android:layout_height=\"wrap_content\"\n                            android:text=\"@string/server_btn_connect\"\n                            style=\"@style/buttons\"\n                            android:minHeight=\"35dp\"\n                            android:textAllCaps=\"false\"\n                            android:padding=\"5dp\"\n                            android:onClick=\"serverOnClick\"/>\n                    </LinearLayout>\n                    <LinearLayout\n                        android:layout_width=\"0dp\"\n                        android:layout_weight=\"3\"\n                        android:layout_height=\"wrap_content\"\n                        android:orientation=\"vertical\">\n                        <ImageView\n                            android:id=\"@+id/serverImageConnect\"\n                            android:layout_gravity=\"center\"\n                            android:layout_width=\"wrap_content\"\n                            android:layout_height=\"wrap_content\" />\n                        <TextView\n                            android:id=\"@+id/serverIP\"\n                            android:layout_width=\"wrap_content\"\n                            android:layout_height=\"wrap_content\"\n                            android:layout_gravity=\"center\"\n                            style=\"@style/serverDetails\"/>\n                        <LinearLayout\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            android:orientation=\"horizontal\">\n                            <TextView\n                                android:layout_width=\"0dp\"\n                                android:layout_weight=\"1\"\n                                android:gravity=\"end\"\n                                android:layout_height=\"wrap_content\"\n                                android:text=\"@string/server_txt_speed\"\n                                style=\"@style/serverDetails\"/>\n                            <TextView\n                                android:id=\"@+id/serverSpeed\"\n                                android:layout_width=\"0dp\"\n                                android:layout_weight=\"1\"\n                                android:layout_height=\"wrap_content\"\n                                style=\"@style/serverDetails\"/>\n                        </LinearLayout>\n                        <LinearLayout\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            android:orientation=\"horizontal\">\n                            <TextView\n                                android:layout_width=\"0dp\"\n                                android:layout_weight=\"1\"\n                                android:gravity=\"end\"\n                                android:layout_height=\"wrap_content\"\n                                android:text=\"@string/server_txt_sessions\"\n                                style=\"@style/serverDetails\"/>\n                            <TextView\n                                android:id=\"@+id/serverSessions\"\n                                android:layout_width=\"0dp\"\n                                android:layout_weight=\"1\"\n                                android:layout_height=\"wrap_content\"\n                                style=\"@style/serverDetails\"/>\n                        </LinearLayout>\n                        <LinearLayout\n                            android:layout_width=\"match_parent\"\n                            android:layout_height=\"wrap_content\"\n                            android:orientation=\"horizontal\">\n                            <TextView\n                                android:layout_width=\"0dp\"\n                                android:layout_weight=\"1\"\n                                android:gravity=\"end\"\n                                android:layout_height=\"wrap_content\"\n                                android:text=\"@string/server_txt_ping\"\n                                style=\"@style/serverDetails\"/>\n                            <TextView\n                                android:id=\"@+id/serverPing\"\n                                android:layout_width=\"0dp\"\n                                android:layout_weight=\"1\"\n                                android:layout_height=\"wrap_content\"\n                                style=\"@style/serverDetails\"/>\n                        </LinearLayout>\n\n                    </LinearLayout>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:orientation=\"horizontal\"\n                    android:paddingTop=\"10dp\"\n                    android:paddingBottom=\"10dp\">\n                        <android.support.v7.widget.AppCompatCheckBox\n                            android:id=\"@+id/serverBlockingCheck\"\n                            app:buttonTint=\"@color/buttonBg\"\n                            android:text=\"@string/blocking_ads\"\n                            android:textSize=\"16sp\"\n                            android:textStyle=\"bold\"\n                            android:visibility=\"gone\"\n                            android:textColor=\"@android:color/tab_indicator_text\"\n                            android:layout_marginEnd=\"10dp\"\n                            android:layout_gravity=\"center_vertical\"\n                            android:layout_width=\"wrap_content\"\n                            android:layout_height=\"wrap_content\"/>\n                        <Button\n                            android:id=\"@+id/serverUnblockCheck\"\n                            android:text=\"@string/unblock\"\n                            style=\"@style/buttons\"\n                            android:minHeight=\"25dp\"\n                            android:textAllCaps=\"false\"\n                            android:padding=\"5dp\"\n                            android:layout_marginTop=\"1dp\"\n                            android:layout_marginBottom=\"1dp\"\n                            android:layout_width=\"wrap_content\"\n                            android:layout_height=\"wrap_content\" />\n\n                </LinearLayout>\n\n            </LinearLayout>\n\n            <ProgressBar\n                android:id=\"@+id/serverConnectingProgress\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center\"\n                android:layout_marginBottom=\"10dp\"\n                android:layout_marginTop=\"10dp\"\n                android:visibility=\"gone\"/>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\"\n                android:paddingTop=\"5dp\"\n                android:paddingBottom=\"5dp\"\n                android:gravity=\"center\">\n                <Button\n                    android:id=\"@+id/serverBtnCheckIp\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/what_is_my_ip\"\n                    android:textAllCaps=\"false\"\n                    android:textSize=\"17sp\"\n                    android:textColor=\"@color/buttonBg\"\n                    android:background=\"@null\"\n                    android:onClick=\"serverOnClick\"/>\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\">\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:gravity=\"end\"\n                    android:textSize=\"16sp\"\n                    android:textAllCaps=\"true\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/server_txt_status\"/>\n                <TextView\n                    android:id=\"@+id/serverStatus\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\">\n                <TextView\n                    android:id=\"@+id/serverTrafficIn\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"/>\n                <TextView\n                    android:id=\"@+id/serverTrafficOut\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"/>\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/traffic_totally\"\n                    android:layout_marginTop=\"8dp\"/>\n                <TextView\n                    android:id=\"@+id/serverTrafficInTotally\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"/>\n                <TextView\n                    android:id=\"@+id/serverTrafficOutTotally\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"/>\n            </LinearLayout>\n        </LinearLayout>\n    </ScrollView>\n\n</LinearLayout>\n"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_servers_info.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/activity_servers_info\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\"com.vasilkoff.easyvpnfree.activity.ServersInfo\"\n    android:background=\"@drawable/info_servers_bg\">\n\n    <LinearLayout\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:layout_centerVertical=\"true\"\n        android:layout_centerHorizontal=\"true\">\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/you_have_servers\"\n            android:layout_gravity=\"center\"\n            style=\"@style/infoServersList\"/>\n        <TextView\n            android:id=\"@+id/infoBasic\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            style=\"@style/infoServersList\"/>\n        <TextView\n            android:id=\"@+id/infoAdditional\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            style=\"@style/infoServersList\"/>\n\n    </LinearLayout>\n\n</RelativeLayout>\n"
  },
  {
    "path": "Android-code/app/src/main/res/layout/activity_servers_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\"com.vasilkoff.easyvpnfree.activity.ServersListActivity\">\n\n    <ListView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:id=\"@+id/list\"\n        android:divider=\"@color/listDivider\"\n        android:dividerHeight=\"1dp\"/>\n</RelativeLayout>\n"
  },
  {
    "path": "Android-code/app/src/main/res/layout/bookmark_server_row.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <android.support.v7.widget.CardView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"2dp\"\n        android:layout_marginTop=\"2dp\">\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\">\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n                <TextView\n                    android:id=\"@+id/bookmarkCountry\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:textSize=\"17sp\"\n                    android:textStyle=\"bold\"/>\n\n                <TextView\n                    android:id=\"@+id/bookmarkCity\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    style=\"@style/serverList\"\n                    android:layout_marginLeft=\"5dp\"/>\n\n            </LinearLayout>\n\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_weight=\"1\"\n                    android:layout_height=\"wrap_content\"\n                    android:orientation=\"vertical\">\n                    <ImageView\n                        android:id=\"@+id/bookmarkFlag\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_gravity=\"center_horizontal\"/>\n\n                </LinearLayout>\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_weight=\"1\"\n                    android:layout_height=\"wrap_content\"\n                    android:orientation=\"vertical\"\n                    android:gravity=\"left\">\n                    <TextView\n                        android:id=\"@+id/bookmarkHostName\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        style=\"@style/serverList\"/>\n                    <TextView\n                        android:id=\"@+id/bookmarkIP\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        style=\"@style/serverList\"/>\n                    <ImageView\n                        android:id=\"@+id/bookmarkConnect\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"/>\n\n                </LinearLayout>\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_weight=\"1\"\n                    android:layout_height=\"wrap_content\"\n                    android:orientation=\"horizontal\">\n                    <Button\n                        android:id=\"@+id/bookmarkDelete\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/bookmark_delete\"\n                        android:minHeight=\"35dp\"\n                        android:textAllCaps=\"false\"\n                        style=\"@style/buttons\"/>\n\n                </LinearLayout>\n            </LinearLayout>\n        </LinearLayout>\n    </android.support.v7.widget.CardView>\n</LinearLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/layout_server_record_row.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\"\n    android:paddingLeft=\"5dp\"\n    android:paddingRight=\"5dp\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n        <TextView\n            android:id=\"@+id/textCountry\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textSize=\"17sp\"\n            android:textStyle=\"bold\"/>\n\n        <TextView\n            android:id=\"@+id/textCity\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            style=\"@style/serverList\"\n            android:layout_marginLeft=\"5dp\"/>\n\n    </LinearLayout>\n\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n        <LinearLayout\n            android:layout_width=\"0dp\"\n            android:layout_weight=\"1\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\">\n            <ImageView\n                android:id=\"@+id/imageFlag\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center_horizontal\"/>\n\n        </LinearLayout>\n        <LinearLayout\n            android:layout_width=\"0dp\"\n            android:layout_weight=\"2\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:gravity=\"left\">\n            <TextView\n                android:id=\"@+id/textHostName\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                style=\"@style/serverList\"/>\n            <TextView\n                android:id=\"@+id/textIP\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                style=\"@style/serverList\"/>\n            <ImageView\n                android:id=\"@+id/imageConnect\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"/>\n\n        </LinearLayout>\n    </LinearLayout>\n\n</LinearLayout>\n"
  },
  {
    "path": "Android-code/app/src/main/res/layout/pop_up_choose_country.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@color/popUpBg\">\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:background=\"@color/toolbarBg\"\n        android:textColor=\"@color/toolbarTitle\"\n        android:text=\"@string/home_pop_up_title_choose_country\"\n        android:layout_gravity=\"center\"\n        android:textSize=\"17sp\"\n        android:paddingTop=\"10dp\"\n        android:paddingBottom=\"10dp\"/>\n\n    <ListView\n        android:paddingBottom=\"@dimen/activity_vertical_margin\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:id=\"@+id/homeCountryList\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:divider=\"@color/listDivider\"\n        android:dividerHeight=\"1dp\"/>\n\n</LinearLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/pop_up_note.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@drawable/info_servers_bg\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentStart=\"true\"\n        android:gravity=\"center\"\n        android:padding=\"15dp\">\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/note_title\"\n            android:textColor=\"@color/buttonBg\"\n            android:textSize=\"18sp\"/>\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/note_text\"\n            android:textSize=\"16sp\"/>\n        <TextView\n            android:id=\"@+id/noteLink\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/note_link\"\n            android:textSize=\"16sp\"\n            android:textColor=\"@color/buttonBg\"/>\n    </LinearLayout>\n</RelativeLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/pop_up_rating.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@drawable/info_servers_bg\">\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentStart=\"true\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\">\n        <ImageView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:src=\"@drawable/recond_like\"\n            android:layout_gravity=\"center\"/>\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/rating_title\"\n            android:layout_gravity=\"center\"\n            android:gravity=\"center\"\n            android:padding=\"10dp\"\n            android:textSize=\"15sp\"\n            android:textColor=\"@color/buttonBg\"/>\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/rating_text\"\n            android:layout_gravity=\"center\"\n            android:gravity=\"center\"\n            android:padding=\"10dp\"\n            android:textSize=\"15sp\"\n            android:textColor=\"@color/buttonBg\"/>\n        <Button\n            android:id=\"@+id/ratingBtnSure\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/rating_sure\"\n            style=\"@style/buttonsPopUp\"/>\n        <Button\n            android:id=\"@+id/ratingBtnNot\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/rating_not\"\n            android:background=\"@null\"\n            android:textColor=\"@color/ratingNot\"\n            android:textAllCaps=\"false\"\n            android:layout_gravity=\"center\"/>\n    </LinearLayout>\n\n</RelativeLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/layout/pop_up_success_conected.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@drawable/info_servers_bg\">\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentStart=\"true\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\">\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/success_pop_up_title\"\n            android:layout_gravity=\"center\"\n            android:gravity=\"center\"\n            android:padding=\"10dp\"\n            android:textSize=\"15sp\"\n            android:textColor=\"@color/buttonBg\"/>\n        <Button\n            android:id=\"@+id/successPopUpBtnPlayMarket\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/open_playmarket\"\n            style=\"@style/buttonsPopUp\"/>\n        <Button\n            android:id=\"@+id/successPopUpBtnBrowser\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/open_browser\"\n            style=\"@style/buttonsPopUp\"/>\n        <Button\n            android:id=\"@+id/successPopUpBtnDesktop\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/show_my_desktop\"\n            style=\"@style/buttonsPopUp\"/>\n        <Button\n            android:id=\"@+id/successPopUpBtnClose\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/stay_to_try_something_else\"\n            style=\"@style/buttonsPopUp\"/>\n    </LinearLayout>\n\n</RelativeLayout>"
  },
  {
    "path": "Android-code/app/src/main/res/menu/menu_main.xml",
    "content": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:context=\"com.kusenko.myapplication.MainActivity\">\n    <item\n        android:id=\"@+id/actionShare\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/action_share\"\n        android:icon=\"@drawable/ic_share_white_24dp\"\n        app:showAsAction=\"always\"/>\n    <item\n        android:id=\"@+id/actionRefresh\"\n        android:orderInCategory=\"101\"\n        android:title=\"@string/action_refresh\"\n        android:icon=\"@drawable/ic_cached_white_36dp\"\n        app:showAsAction=\"always\"/>\n    <item\n        android:id=\"@+id/actionCurrentServer\"\n        android:orderInCategory=\"102\"\n        android:title=\"@string/action_current_connection\"\n        android:icon=\"@drawable/ic_vpn_key_white_24dp\"\n        app:showAsAction=\"ifRoom\"/>\n    <item\n        android:id=\"@+id/actionGetMoreServers\"\n        android:orderInCategory=\"103\"\n        android:title=\"@string/more_servers\"\n        app:showAsAction=\"never\"/>\n    <item\n        android:id=\"@+id/actionAbout\"\n        android:orderInCategory=\"104\"\n        android:title=\"@string/action_about\"\n        android:icon=\"@android:drawable/ic_menu_info_details\"\n        app:showAsAction=\"never\"/>\n    <item\n        android:id=\"@+id/action_settings\"\n        android:orderInCategory=\"105\"\n        android:title=\"@string/action_settings\"\n        app:showAsAction=\"never\" />\n    <item\n        android:id=\"@+id/action_bookmarks\"\n        android:orderInCategory=\"105\"\n        android:title=\"@string/bookmarks\"\n        app:showAsAction=\"never\" />\n\n</menu>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values/about.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"aboutApp\">\n        <b>Introduction</b>\n        \\nAndroid application which lets you easily to connect to a number of free VPN server around the world with just a single tap!\n        The list of servers the application connect is http://www.vpngate.net VPN Gate Academic Experiment Project is an online service as an academic research at Graduate School of University of Tsukuba, Japan. The purpose of this research is to expand the knowledge of \\\"Global Distributed Public VPN Relay Servers\\\".\n        \\n\\n<b>Why VPN Gate?</b>\n        \\nYou can take these advantages by using VPN Gate:\n        \\n * It is about 8531 Public VPN Relay Servers by volunteers around the world.\n        \\n * You can disguise your IP address to hide your identity while surfing the Internet.\n        \\n * You can protect yourself by utilizing its strong encryption while using public Wi-Fi.\n        \\nUnlike traditional VPN services, VPN Gate can get through most firewalls.\n        \\nVPN Gate is free of charge. Not a single registration is required.\n        \\n\\n<b>License</b>\n        \\n <i>Free Software!</i>\n        \\nhttps://www.gnu.org/licenses/gpl-3.0.en.html\n        \\nThis application uses the following components; see the source code for full details on the licenses.\n        \\n * OpenVPN for Android https://github.com/schwabe/ics-openvpn under GPLv2\n        \\n * NumberProgressBar https://github.com/daimajia/NumberProgressBar under MIT\n        \\n * Fast-Android-Networking https://github.com/amitshekhariitbhu/Fast-Android-Networking under Apache 2.0\n        \\n\\n<b>You can help</b>\n        \\nEven if you are not a programmer you can help by translating the Easy VPN Free client into your native language.\n    </string>\n</resources>"
  },
  {
    "path": "Android-code/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#1c3f61</color>\n    <color name=\"colorAccent\">#356690</color>\n\n    <color name=\"popUpBg\">#ffffff</color>\n    <color name=\"listDivider\">#356690</color>\n\n    <color name=\"mapFill\">#1c3f60</color>\n    <color name=\"mapStroke\">#7f7f7f</color>\n    <color name=\"mapBackground\">#71bad2</color>\n    <color name=\"mapNameCountry\">#ffffff</color>\n    <color name=\"mapLine\">#ffffff</color>\n\n    <color name=\"toolbarTitle\">#cbecfd</color>\n    <color name=\"toolbarBg\">#356690</color>\n\n    <color name=\"buttonText\">#cbecfd</color>\n    <color name=\"buttonBg\">#356690</color>\n\n    <color name=\"totalServers\">#ffffff</color>\n\n    <color name=\"infoServersList\">#1c3f61</color>\n\n    <color name=\"ratingNot\">#A7A7A7</color>\n\n    <color name=\"activeServer\">#cbecfd</color>\n    <color name=\"additionalServer\">#F1DD77</color>\n\n    <color name=\"serverNameBg\">#cbecfd</color>\n    <color name=\"serverName\">#356690</color>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"nav_header_vertical_spacing\">16dp</dimen>\n    <dimen name=\"nav_header_height\">160dp</dimen>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n    <dimen name=\"fab_margin\">16dp</dimen>\n    <dimen name=\"text_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values/props.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"base64EncodedPublicKey\">MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo6KAevJgZCEigAbUpgru1Phr8KX9tVR6nHITiFNJlJSazmifdT1GGjkozMC3Ff0syyA64CYx4YeNeChg5nLJeL3DKhs7tKkr2G4HhvMgP+MX/M9pOPiLe3VZ26YaqKI/BCOKXbNZ7UH1BXATiJdpANIP75HxpBXCQVbIvmwgbzp6hvTJFQMwYpQ+hyFL6URSRCiq2DOoirDPvClstXHvogSSW/5Kn7eYEiutE/YIn1G4NnT8XtCD3bCRdH5732ZSqiq+s52l0t+yDUdEeAbC6Aja/qSv/Wgfu8CsGrInuwmYlZQgtwOlhkR7quvgi9tCXyfDzanihI8LqZ88R93ytwIDAQAB</string>\n    <string name=\"url_check_ip\">http://ip-api.com/</string>\n    <string name=\"url_check_ip_batch\">http://ip-api.com/batch</string>\n\n</resources>"
  },
  {
    "path": "Android-code/app/src/main/res/values/reference.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <drawable name=\"ic_menu_close_clear_cancel\">@android:drawable/ic_menu_close_clear_cancel</drawable>\n    <drawable name=\"ic_menu_play\">@android:drawable/ic_media_play</drawable>\n    <drawable name=\"ic_menu_pause\">@android:drawable/ic_media_pause</drawable>\n</resources>"
  },
  {
    "path": "Android-code/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"action_settings\">Settings</string>\n    <string name=\"home_btn_choose_country\">Choose country</string>\n    <string name=\"home_pop_up_title_choose_country\">Choose country</string>\n    <string name=\"server_btn_connect\">Connect</string>\n    <string name=\"server_btn_disconnect\">Disconnect</string>\n    <string name=\"server_txt_ping\">Ping:</string>\n    <string name=\"server_txt_sessions\">Sessions:</string>\n    <string name=\"server_txt_speed\">Speed:</string>\n    <string name=\"server_txt_city\">City:</string>\n    <string name=\"server_error_loading_profile\">Error loading profile</string>\n    <string name=\"server_txt_status\">Status connection:</string>\n    <string name=\"server_not_connected\">Not connected</string>\n    <string name=\"server_list_more\">Details</string>\n    <string name=\"mbps\">Mbps</string>\n    <string name=\"ms\">ms</string>\n    <string name=\"loading_text\">Loading...</string>\n    <string name=\"downloading_csv_text\">Downloading servers list...</string>\n    <string name=\"parsing_csv_text\">Parsing servers list...</string>\n    <string name=\"csv_file_error\">Problem with a file reading...</string>\n    <string name=\"csv_file_error_parsing\">Problem with a file parsing...</string>\n    <string name=\"network_error\">Network error...</string>\n    <string name=\"successfully_loaded\">Successfully loaded</string>\n    <string name=\"action_about\">About</string>\n    <string name=\"action_refresh\">Refresh servers list</string>\n    <string name=\"action_share\">Share</string>\n    <string name=\"ok\">Ok</string>\n    <string name=\"network_error_message\">Internet is not available, reconnect network and try again.</string>\n    <string name=\"blocking_ads\">Turn on ads filtering</string>\n    <string name=\"more_servers\">Get more servers</string>\n    <string name=\"feature_not_available\">This feature temporarily is not available</string>\n    <string name=\"feature_not_available_without_perm\">Without account information this feature is not available</string>\n    <string name=\"unblock\">Ads filtering</string>\n    <string name=\"what_is_my_ip\">What is my IP?</string>\n    <string name=\"action_current_connection\">Current connection</string>\n    <string name=\"random_connection\">Quick connection</string>\n    <string name=\"total_servers\">%1$d servers available in the local database now</string>\n    <string name=\"loading_additional_servers\">The loading of additional servers</string>\n    <string name=\"current_servers_list\">Current servers list</string>\n    <string name=\"you_have_servers\"><b>You have servers:</b></string>\n    <string name=\"info_basic\">%1$d basic</string>\n    <string name=\"info_additional\">%1$d additional</string>\n    <string name=\"connect_on_start\">Connect on start</string>\n    <string name=\"connect_on_start_summary\">Connect when application is started</string>\n    <string name=\"choose_country_priority\">Choose country priority</string>\n    <string name=\"choose_country_priority_summary\">If not enabled then use random connection</string>\n    <string name=\"choose_country\">Choose country</string>\n    <string name=\"error_random_country\">Server with priority country %1$s is not available</string>\n    <string name=\"success_pop_up_title\"><b>You are successfuly connected!\n        \\n Let\\'s try it out?</b></string>\n    <string name=\"open_playmarket\">Open PlayMarket</string>\n    <string name=\"open_browser\">Open browser</string>\n    <string name=\"show_my_desktop\">Show my desktop</string>\n    <string name=\"stay_to_try_something_else\">Stay to try something else</string>\n    <string name=\"automatic_switching\">Automatic switching</string>\n    <string name=\"automatic_switching_category\">Automatic switching</string>\n    <string name=\"automatic_switching_set_seconds\">Set seconds</string>\n    <string name=\"automatic_switching_summary\">Automatic switching to the same country server after some seconds,\n        if this connecting impossible.\n    </string>\n    <string name=\"choose_country_priority_category\">Country priority</string>\n    <string name=\"connect_on_start_category\">Auto start on boot</string>\n    <string name=\"try_another_server_text\">Do you want try another server?</string>\n    <string name=\"try_another_server_ok\">Yes</string>\n    <string name=\"try_another_server_no\">No</string>\n    <string name=\"traffic_in\">Downloaded: %1$s</string>\n    <string name=\"traffic_out\">Uploaded: %1$s</string>\n    <string name=\"traffic_totally\"><b>Totally through the application</b></string>\n    <string name=\"rating_title\"><b>Thanks for using Easy VPN Free!</b></string>\n    <string name=\"rating_sure\">Sure</string>\n    <string name=\"rating_not\">Not really</string>\n    <string name=\"rating_text\">We are trying to make the app better!\n        \\nWould you like to show your support\n        \\nby rating us?\n    </string>\n    <string name=\"share_text\">\n        Easy VPN Free! Open source, Unlimited and 100% Free!\n        \\nMore than 22 countries to connect and unblock all blocked websites.\n        \\n\\nhttps://play.google.com/store/apps/details?id=com.vasilkoff.easyvpnfree\n    </string>\n    <string name=\"bookmarks\">Bookmarks</string>\n    <string name=\"bookmark_delete\">Delete</string>\n    <string name=\"note_title\"><b>Note</b></string>\n    <string name=\"note_text\">The list of the servers you will find\n        in this application are from VPN Gate and are\n        provided by <b>volunteers around the world</b>.\n    </string>\n    <string name=\"note_link\">\\nYou can provide your own computer as a VPN server to join this experiment.</string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n        <item name=\"colorControlNormal\">@color/toolbarTitle</item>\n    </style>\n\n    <style name=\"AppTheme.PopUp\">\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <item name=\"android:windowCloseOnTouchOutside\">true</item>\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"serverDetails\" >\n        <item name=\"android:textSize\">13sp</item>\n        <item name=\"android:layout_gravity\">center</item>\n    </style>\n\n    <style name=\"serverName\">\n        <item name=\"android:textSize\">17sp</item>\n        <item name=\"android:textColor\">@color/serverName</item>\n    </style>\n\n    <style name=\"serverList\" >\n        <item name=\"android:textSize\">14sp</item>\n    </style>\n\n    <style name=\"infoServersList\" >\n        <item name=\"android:textSize\">17sp</item>\n        <item name=\"android:textColor\">@color/infoServersList</item>\n    </style>\n\n    <style name=\"buttons\" >\n        <item name=\"android:background\">@drawable/button_bg</item>\n        <item name=\"android:textColor\">@color/buttonText</item>\n    </style>\n\n    <style name=\"buttonsPopUp\" >\n        <item name=\"android:background\">@drawable/button_bg</item>\n        <item name=\"android:textColor\">@color/buttonText</item>\n        <item name=\"android:layout_gravity\">center</item>\n        <item name=\"android:layout_marginTop\">8dp</item>\n        <item name=\"android:layout_marginBottom\">8dp</item>\n        <item name=\"android:textAllCaps\">false</item>\n        <item name=\"android:padding\">5dp</item>\n        <item name=\"android:minHeight\">35dp</item>\n        <item name=\"android:width\">250dp</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values/untranslatable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2012-2016 Arne Schwabe\n  ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n  -->\n\n<resources>\n\n    <string name=\"copyright_blinktgui\" translatable=\"false\">Copyright 2012–2016 Arne Schwabe &lt;arne@rfc2549.org></string>\n    <string name=\"copyright_logo\" translatable=\"false\">App Logo design by Helen Beierling &lt;helbeierling@t-online.de></string>\n\n    <string name=\"opevpn_copyright\" translatable=\"false\">Copyright © 2002–2010 OpenVPN Technologies, Inc. &lt;sales@openvpn.net>\\n\n\n\t  \"OpenVPN\" is a trademark of OpenVPN Technologies, Inc.\\n</string>\n    <string name=\"defaultserver\" translatable=\"false\">openvpn.uni-paderborn.de</string>\n    <string name=\"defaultport\" translatable=\"false\">1194</string>\n    <string name=\"copyright_file_dialog\" translatable=\"false\">File Dialog based on work by Alexander Ponomarev</string>\n    <string name=\"lzo_copyright\" translatable=\"false\">Copyright © 1996 – 2011 Markus Franz Xaver Johannes Oberhumer</string>\n    <string name=\"copyright_openssl\" translatable=\"false\">        This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit\\n\n        Copyright © 1998-2008 The OpenSSL Project. All rights reserved.\\n\\n\n        This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)\\n\n        Copyright © 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.</string>\n    <string name=\"openvpn\" translatable=\"false\">OpenVPN</string>\n    <string name=\"file_dialog\" translatable=\"false\">File Dialog</string>\n    <string name=\"lzo\" translatable=\"false\">LZO</string>\n    <string name=\"openssl\" translatable=\"false\">OpenSSL</string>\n    <string name=\"unknown_state\" translatable=\"false\">Unknown state</string>\n    <string name=\"permission_description\">Allows another app to control OpenVPN</string>\n    <string name=\"bouncy_castle\" translatable=\"false\">Bouncy Castle Crypto APIs</string>\n    <string name=\"copyright_bouncycastle\" translatable=\"false\">Copyright © 2000–2012 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)</string>\n\n    <string-array name=\"tls_directions_values\" translatable=\"false\">\n        <item>0</item>\n        <item>1</item>\n        <item></item>\n    </string-array>\n    <string-array name=\"crm_values\" translatable=\"false\">\n        <item>1</item>\n        <item>2</item>\n        <item>5</item>\n        <item>50</item>\n        <item>-1</item>\n    </string-array>\n    <string name=\"crash_toast_text\">OpenVPN for Android crashed, crash reported</string>\n    \n    <!-- These strings should not be visible to the user -->\n    <string name=\"state_user_vpn_permission\" translatable=\"false\">Waiting for user permission to use VPN API</string>\n    <string name=\"state_user_vpn_password\" translatable=\"false\">Waiting for user VPN password</string>\n    <string name=\"state_user_vpn_password_cancelled\" translatable=\"false\">VPN password input dialog cancelled</string>\n    <string name=\"state_user_vpn_permission_cancelled\" translatable=\"false\">VPN API permission dialog cancelled</string>\n\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values/vpn_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?> <!--\n  ~ Copyright (c) 2012-2016 Arne Schwabe\n  ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt\n  -->\n<resources>\n    <string name=\"address\">Server Address:</string>\n    <string name=\"port\">Server Port:</string>\n    <string name=\"location\">Location</string>\n    <string name=\"cant_read_folder\">Unable to read directory</string>\n    <string name=\"select\">Select</string>\n    <string name=\"cancel\">Cancel</string>\n    <string name=\"no_data\">No Data</string>\n    <string name=\"useLZO\">LZO Compression</string>\n    <string name=\"client_no_certificate\">No Certificate</string>\n    <string name=\"client_certificate_title\">Client Certificate</string>\n    <string name=\"client_key_title\">Client Certificate Key</string>\n    <string name=\"client_pkcs12_title\">PKCS12 File</string>\n    <string name=\"ca_title\">CA Certificate</string>\n    <string name=\"no_certificate\">You must select a certificate</string>\n    <string name=\"copyright_guicode\">Source code and issue tracker available at https://github.com/schwabe/ics-openvpn/</string>\n    <string name=\"copyright_others\">This program uses the following components; see the source code for full details on the licenses</string>\n    <string name=\"about\">About</string>\n    <string name=\"vpn_list_title\">Profiles</string>\n    <string name=\"vpn_type\">Type</string>\n    <string name=\"pkcs12pwquery\">PKCS12 Password</string>\n    <string name=\"file_select\">Select…</string>\n    <string name=\"file_nothing_selected\">You must select a file</string>\n    <string name=\"useTLSAuth\">Use TLS Authentication</string>\n    <string name=\"tls_direction\">TLS Direction</string>\n    <string name=\"ipv6_dialog_tile\">Enter IPv6 Address/Netmask in CIDR Format (e.g. 2000:dd::23/64)</string>\n    <string name=\"ipv4_dialog_title\">Enter IPv4 Address/Netmask in CIDR Format (e.g. 1.2.3.4/24)</string>\n    <string name=\"ipv4_address\">IPv4 Address</string>\n    <string name=\"ipv6_address\">IPv6 Address</string>\n    <string name=\"custom_option_warning\">Enter custom OpenVPN options. Use with caution. Also note that many of the tun related OpenVPN settings cannot be supported by design of the VPNSettings. If you think an important option is missing contact the author</string>\n    <string name=\"auth_username\">Username</string>\n    <string name=\"auth_pwquery\">Password</string>\n    <string name=\"static_keys_info\">For the static configuration the TLS Auth Keys will be used as static keys</string>\n    <string name=\"configure_the_vpn\">Configure the VPN</string>\n    <string name=\"menu_add_profile\">Add Profile</string>\n    <string name=\"add_profile_name_prompt\">Enter a name identifying the new Profile</string>\n    <string name=\"duplicate_profile_name\">Please enter a unique Profile Name</string>\n    <string name=\"profilename\">Profile Name</string>\n    <string name=\"no_keystore_cert_selected\">You must select a User certificate</string>\n    <string name=\"no_error_found\">No error found</string>\n    <string name=\"config_error_found\">Error in Configuration</string>\n    <string name=\"ipv4_format_error\">Error parsing the IPv4 address</string>\n    <string name=\"custom_route_format_error\">Error parsing the custom routes</string>\n    <string name=\"pw_query_hint\">(leave empty to query on demand)</string>\n    <string name=\"vpn_shortcut\">OpenVPN Shortcut</string>\n    <string name=\"vpn_launch_title\">Connect to VPN</string>\n    <string name=\"shortcut_profile_notfound\">Profile specified in shortcut not found</string>\n    <string name=\"random_host_prefix\">Random Host Prefix</string>\n    <string name=\"random_host_summary\">Adds 6 random chars in front of hostname</string>\n    <string name=\"custom_config_title\">Enable Custom Options</string>\n    <string name=\"custom_config_summary\">Specify custom options. Use with care!</string>\n    <string name=\"route_rejected\">Route rejected by Android</string>\n    <string name=\"cancel_connection\">Disconnect</string>\n    <string name=\"cancel_connection_long\">Disconnect VPN</string>\n    <string name=\"clear_log\">clear log</string>\n    <string name=\"title_cancel\">Cancel Confirmation</string>\n    <string name=\"cancel_connection_query\">Disconnect the connected VPN/cancel the connection attempt?</string>\n    <string name=\"remove_vpn\">Remove VPN</string>\n    <string name=\"check_remote_tlscert\">Checks whether the server uses a certificate with TLS Server extensions (--remote-cert-tls server)</string>\n    <string name=\"check_remote_tlscert_title\">Expect TLS server certificate</string>\n    <string name=\"remote_tlscn_check_summary\">Checks the Remote Server Certificate Subject DN</string>\n    <string name=\"remote_tlscn_check_title\">Certificate Hostname Check</string>\n    <string name=\"enter_tlscn_dialog\">Specify the check used to verify the remote certificate DN (e.g. C=DE, L=Paderborn, OU=Avian IP Carriers, CN=openvpn.blinkt.de)\\n\\nSpecify the complete DN or the RDN (openvpn.blinkt.de in the example) or an RDN prefix for verification.\\n\\nWhen using RDN prefix \\\"Server\\\" matches \\\"Server-1\\\" and \\\"Server-2\\\"\\n\\nLeaving the text field empty will check the RDN against the server hostname.\\n\\nFor more details see the OpenVPN 2.3.1+ manpage under —verify-x509-name</string>\n    <string name=\"enter_tlscn_title\">Remote certificate subject</string>\n    <string name=\"tls_key_auth\">Enables the TLS Key Authentication</string>\n    <string name=\"tls_auth_file\">TLS Auth File</string>\n    <string name=\"pull_on_summary\">Requests IP addresses, routes and timing options from the server.</string>\n    <string name=\"pull_off_summary\">No information is requested from the server. Settings need to be specified below.</string>\n    <string name=\"use_pull\">Pull Settings</string>\n    <string name=\"dns\">DNS</string>\n    <string name=\"override_dns\">Override DNS Settings by Server</string>\n    <string name=\"dns_override_summary\">Use your own DNS Servers</string>\n    <string name=\"searchdomain\">searchDomain</string>\n    <string name=\"dns1_summary\">DNS Server to be used.</string>\n    <string name=\"dns_server\">DNS Server</string>\n    <string name=\"secondary_dns_message\">Secondary DNS Server used if the normal DNS Server cannot be reached.</string>\n    <string name=\"backup_dns\">Backup DNS Server</string>\n    <string name=\"ignored_pushed_routes\">Ignore pushed routes</string>\n    <string name=\"ignore_routes_summary\">Ignore routed pushed by the server.</string>\n    <string name=\"default_route_summary\">Redirects all Traffic over the VPN</string>\n    <string name=\"use_default_title\">Use default Route</string>\n    <string name=\"custom_route_message\">Enter custom routes. Only enter destination in CIDR format. \\\"10.0.0.0/8 2002::/16\\\" would direct the networks 10.0.0.0/8 and 2002::/16 over the VPN.</string>\n    <string name=\"custom_route_message_excluded\">Routes that should NOT be routed over the VPN. Use the same syntax as for included routes.</string>\n    <string name=\"custom_routes_title\">Custom Routes</string>\n    <string name=\"custom_routes_title_excluded\">Excluded Networks</string>\n    <string name=\"log_verbosity_level\">Log verbosity level</string>\n    <string name=\"float_summary\">Allows authenticated packets from any IP</string>\n    <string name=\"float_title\">Allow floating server</string>\n    <string name=\"custom_options_title\">Custom Options</string>\n    <string name=\"edit_vpn\">Edit VPN Settings</string>\n    <string name=\"remove_vpn_query\">Remove the VPN Profile \\'%s\\'?</string>\n    <string name=\"tun_error_helpful\">On some custom ICS images the permission on /dev/tun might be wrong, or the tun module might be missing completely. For CM9 images try the fix ownership option under general settings</string>\n    <string name=\"tun_open_error\">Failed to open the tun interface</string>\n    <string name=\"error\">\"Error: \"</string>\n    <string name=\"clear\">Clear</string>\n    <string name=\"last_openvpn_tun_config\">Opening tun interface:</string>\n    <string name=\"local_ip_info\">Local IPv4: %1$s/%2$d IPv6: %3$s MTU: %4$d</string>\n    <string name=\"dns_server_info\">DNS Server: %1$s, Domain: %2$s</string>\n    <string name=\"routes_info_incl\">Routes: %1$s %2$s</string>\n    <string name=\"routes_info_excl\">Routes excluded: %1$s %2$s</string>\n    <string name=\"routes_debug\">VpnService routes installed: %1$s %2$s</string>\n    <string name=\"ip_not_cidr\">Got interface information %1$s and %2$s, assuming second address is peer address of remote. Using /32 netmask for local IP. Mode given by OpenVPN is \\\"%3$s\\\".</string>\n    <string name=\"route_not_cidr\">Cannot make sense of %1$s and %2$s as IP route with CIDR netmask, using /32 as netmask.</string>\n    <string name=\"route_not_netip\">Corrected route %1$s/%2$s to %3$s/%2$s</string>\n    <string name=\"keychain_access\">Cannot access the Android Keychain Certificates. This can be caused by a firmware upgrade or by restoring a backup of the app/app settings. Please edit the VPN and reselect the certificate under basic settings to recreate the permission to access the certificate.</string>\n    <string name=\"version_info\">%1$s %2$s</string>\n    <string name=\"send_logfile\">Send log file</string>\n    <string name=\"send\">Send</string>\n    <string name=\"ics_openvpn_log_file\">ICS OpenVPN log file</string>\n    <string name=\"copied_entry\">Copied log entry to clip board</string>\n    <string name=\"tap_mode\">Tap Mode</string>\n    <string name=\"faq_tap_mode\">Tap Mode is not possible with the non root VPN API. Therefore this application cannot provide tap support</string>\n    <string name=\"tap_faq2\">Again? Are you kidding? No, tap mode is really not supported and sending more mail asking if it will be supported will not help.</string>\n    <string name=\"tap_faq3\">A third time? Actually, one could write a a tap emulator based on tun that would add layer2 information on send and strip layer2 information on receive. But this tap emulator would also have to implement ARP and possibly a DHCP client. I am not aware of anybody doing any work in this direction. Contact me if you want to start coding on this.</string>\n    <string name=\"faq\">FAQ</string>\n    <string name=\"copying_log_entries\">Copying log entries</string>\n    <string name=\"faq_copying\">To copy a single log entry press and hold on the log entry. To copy/send the whole log use the Send Log option. Use the hardware menu button, if the button is not visible in the GUI.</string>\n    <string name=\"faq_shortcut\">Shortcut to start</string>\n    <string name=\"faq_howto_shortcut\">You can place a shortcut to start OpenVPN on your desktop. Depending on your homescreen program you will have to add either a shortcut or a widget.</string>\n    <string name=\"no_vpn_support_image\">Your image does not support the VPNService API, sorry :(</string>\n    <string name=\"encryption\">Encryption</string>\n    <string name=\"cipher_dialog_title\">Enter encryption method</string>\n    <string name=\"chipher_dialog_message\">Enter the encryption cipher algorithm used by OpenVPN. Leave empty to use default cipher.</string>\n    <string name=\"auth_dialog_message\">Enter the authentication digest used for OpenVPN. Leave empty to use default digest.</string>\n    <string name=\"settings_auth\">Authentication/Encryption</string>\n    <string name=\"file_explorer_tab\">File Explorer</string>\n    <string name=\"inline_file_tab\">Inline File</string>\n    <string name=\"error_importing_file\">Error importing File</string>\n    <string name=\"import_error_message\">Could not import File from filesystem</string>\n    <string name=\"inline_file_data\">[[Inline file data]]</string>\n    <string name=\"opentun_no_ipaddr\">Refusing to open tun device without IP information</string>\n    <string name=\"menu_import\">Import Profile from ovpn file</string>\n    <string name=\"menu_import_short\">Import</string>\n    <string name=\"import_content_resolve_error\">Could not read profile to import</string>\n    <string name=\"error_reading_config_file\">Error reading config file</string>\n    <string name=\"add_profile\">add Profile</string>\n    <string name=\"import_could_not_open\">Could not find file %1$s mentioned in the imported config file</string>\n    <string name=\"importing_config\">Importing config file from source %1$s</string>\n    <string name=\"import_warning_custom_options\">Your configuration had a few configuration options that are not mapped to UI configurations. These options were added as custom configuration options. The custom configuration is displayed below:</string>\n    <string name=\"import_done\">Done reading config file.</string>\n    <string name=\"nobind_summary\">Do not bind to local address and port</string>\n    <string name=\"no_bind\">No local binding</string>\n    <string name=\"import_configuration_file\">Import configuration file</string>\n    <string name=\"faq_security_title\">Security considerations</string>\n    <string name=\"faq_security\">\"As OpenVPN is security sensitive a few notes about security are sensible. All data on the sdcard is inherently insecure. Every app can read it (for example this program requires no special sd card rights). The data of this application can only be read by the application itself. By using the import option for cacert/cert/key in the file dialog the data is stored in the VPN profile. The VPN profiles are only accessible by this application. (Do not forget to delete the copies on the sd card afterwards). Even though accessible only by this application the data is still unencrypted. By rooting the telephone or other exploits it may be possible to retrieve the data. Saved passwords are stored in plain text as well. For pkcs12 files it is highly recommended that you import them into the android keystore.\"</string>\n    <string name=\"import_vpn\">Import</string>\n    <string name=\"broken_image_cert_title\">Error showing certificate selection</string>\n    <string name=\"broken_image_cert\">Got an exception trying to show the Android 4.0+ certificate selection dialog. This should never happen as this a standard feature of Android 4.0+. Maybe your Android ROM support for certificate storage is broken</string>\n    <string name=\"ipv4\">IPv4</string>\n    <string name=\"ipv6\">IPv6</string>\n    <string name=\"speed_waiting\">Waiting for state message…</string>\n    <string name=\"converted_profile\">imported profile</string>\n    <string name=\"converted_profile_i\">imported profile %d</string>\n    <string name=\"broken_images\">Broken Images</string>\n    <string name=\"broken_images_faq\">&lt;p&gt;Official HTC images are known to have a strange routing problem causing traffic not to flow through the tunnel (See also &lt;a href=\"https://github.com/schwabe/ics-openvpn/issues/18\"&gt;Issue 18&lt;/a&gt; in the bug tracker.)&lt;/p&gt;&lt;p&gt;Older official SONY images from Xperia Arc S and Xperia Ray have been reported to be missing the VPNService completely from the image. (See also &lt;a href=\"https://github.com/schwabe/ics-openvpn/issues/29\"&gt;Issue 29&lt;/a&gt; in the bug tracker.)&lt;/p&gt;&lt;p&gt;On custom build images the tun module might be missing or the rights of /dev/tun might be wrong. Some CM9 images need the \"Fix ownership\" option under \"Device specific hacks\" enabled.&lt;/p&gt;&lt;p&gt;Most importantly: If your device has a broken Android image, report it to your vendor. The more people who report an issue to the vendor, the more likely they are to fix it.&lt;/p&gt;</string>\n    <string name=\"pkcs12_file_encryption_key\">PKCS12 File Encryption Key</string>\n    <string name=\"private_key_password\">Private Key Password</string>\n    <string name=\"password\">Password</string>\n    <string name=\"file_icon\">file icon</string>\n    <string name=\"tls_authentication\">TLS Authentication</string>\n    <string name=\"generated_config\">Generated Config</string>\n    <string name=\"generalsettings\">Settings</string>\n    <string name=\"owner_fix_summary\">Tries to set the owner of /dev/tun to system. Some CM9 images need this to make the VPNService API work. Requires root.</string>\n    <string name=\"owner_fix\">Fix ownership of /dev/tun</string>\n    <string name=\"generated_config_summary\">Shows the generated OpenVPN Configuration File</string>\n    <string name=\"edit_profile_title\">Editing \\\"%s\\\"</string>\n    <string name=\"building_configration\">Building configuration…</string>\n    <string name=\"netchange_summary\">Turning this option on will force a reconnect if the network state is changed (e.g. WiFi to/from mobile)</string>\n    <string name=\"netchange\">Reconnect on network change</string>\n    <string name=\"netstatus\">Network Status: %s</string>\n    <string name=\"extracahint\">The CA cert is usually returned from the Android keystore. Specify a separate certificate if you get certificate verification errors.</string>\n    <string name=\"select_file\">Select</string>\n    <string name=\"keychain_nocacert\">No CA Certificate returned while reading from Android keystore. Authentication will probably fail.</string>\n    <string name=\"show_log_summary\">Shows the log window on connect. The log window can always be accessed from the notification status.</string>\n    <string name=\"show_log_window\">Show log window</string>\n    <string name=\"mobile_info\">%10$s %9$s running on %3$s %1$s (%2$s), Android %6$s (%7$s) API %4$d, ABI %5$s, (%8$s)</string>\n    <string name=\"error_rsa_sign\">Error signing with Android keystore key %1$s: %2$s</string>\n    <string name=\"faq_system_dialogs\">The VPN connection warning telling you that this app can intercept all traffic is imposed by the system to prevent abuse of the VPNService API.\\nThe VPN connection notification (The key symbol) is also imposed by the Android system to signal an ongoing VPN connection. On some images this notification plays a sound.\\nAndroid introduced these system dialogs for your own safety and made sure that they cannot be circumvented. (On some images this unfortunately includes a notification sound)</string>\n    <string name=\"faq_system_dialogs_title\">Connection warning and notification sound</string>\n    <string name=\"translationby\">English translation by Arne Schwabe&lt;arne@rfc2549.org&gt;</string>\n    <string name=\"ipdns\">IP and DNS</string>\n    <string name=\"basic\">Basic</string>\n    <string name=\"routing\">Routing</string>\n    <string name=\"obscure\">Obscure OpenVPN Settings. Normally not needed.</string>\n    <string name=\"advanced\">Advanced</string>\n    <string name=\"export_config_title\">ICS Openvpn Config</string>\n    <string name=\"warn_no_dns\">No DNS servers being used. Name resolution may not work. Consider setting custom DNS Servers. Please also note that Android will keep using your proxy settings specified for your mobile/Wi-Fi connection when no DNS servers are set.</string>\n    <string name=\"dns_add_error\">Could not add DNS Server \\\"%1$s\\\", rejected by the system: %2$s</string>\n    <string name=\"ip_add_error\">Could not configure IP Address \\\"%1$s\\\", rejected by the system: %2$s</string>\n    <string name=\"faq_howto\">&lt;p&gt;Get a working config (tested on your computer or download from your provider/organisation)&lt;/p&gt;&lt;p&gt;If it is a single file with no extra pem/pkcs12 files you can email the file yourself and open the attachment. If you have multiple files put them on your sd card.&lt;/p&gt;&lt;p&gt;Click on the email attachment/Use the folder icon in the vpn list to import the config file&lt;/p&gt;&lt;p&gt;If there are errors about missing files put the missing files on your sd card.&lt;/p&gt;&lt;p&gt;Click on the save symbol to add the imported VPN to your VPN list&lt;/p&gt;&lt;p&gt;Connect the VPN by clicking on the name of the VPN&lt;/p&gt;&lt;p&gt;If there are error or warnings in the log try to understand the warnings/error and try to fix them&lt;/p&gt; </string>\n    <string name=\"faq_howto_title\">Quick Start</string>\n    <string name=\"setting_loadtun_summary\">Try to load the tun.ko kernel module before trying to connect. Needs rooted devices.</string>\n    <string name=\"setting_loadtun\">Load tun module</string>\n    <string name=\"importpkcs12fromconfig\">Import PKCS12 from configuration into Android Keystore</string>\n    <string name=\"getproxy_error\">Error getting proxy settings: %s</string>\n    <string name=\"using_proxy\">Using proxy %1$s %2$d</string>\n    <string name=\"use_system_proxy\">Use system proxy</string>\n    <string name=\"use_system_proxy_summary\">Use the system wide configuration for HTTP/HTTPS proxies to connect.</string>\n    <string name=\"onbootrestartsummary\">OpenVPN will connect the specified VPN if it was active on system boot. Please read the connection warning FAQ before using this option on Android &lt; 5.0.</string>\n    <string name=\"onbootrestart\">Connect on boot</string>\n    <string name=\"ignore\">Ignore</string>\n    <string name=\"restart\">Restart</string>\n    <string name=\"restart_vpn_after_change\">Configuration changes are applied after restarting the VPN. (Re)start the VPN now?</string>\n    <string name=\"configuration_changed\">Configuration changed</string>\n    <string name=\"log_no_last_vpn\">Could not determine last connected profile for editing</string>\n    <string name=\"faq_duplicate_notification_title\">Duplicate notifications</string>\n    <string name=\"faq_duplicate_notification\">If Android is under system memory (RAM) pressure, apps and service which are not needed at the moment are removed from active memory. This terminates an ongoing VPN connection. To ensure that the connection/OpenVPN survives the service runs with higher priority. To run with higher priority the application must display a notification. The key notification icon is imposed by the system as described in the previous FAQ entry. It does not count as app notification for purpose of running with higher priority.</string>\n    <string name=\"no_vpn_profiles_defined\">No VPN profiles defined.</string>\n    <string name=\"add_new_vpn_hint\">Use the &lt;img src=\\\"ic_menu_add\\\"/&gt; icon to add a new VPN</string>\n    <string name=\"vpn_import_hint\">Use the &lt;img src=\\\"ic_menu_archive\\\"/&gt; icon to import an existing (.ovpn or .conf) profile from your sdcard.</string>\n    <string name=\"faq_hint\">Be sure to also check out the FAQ. There is a quick start guide.</string>\n    <string name=\"faq_routing_title\">Routing/Interface Configuration</string>\n    <string name=\"faq_routing\">The Routing and interface configuration is not done via traditional ifconfig/route commands but by using the VPNService API. This results in a different routing configuration than on other OSes. \\nThe configuration of the VPN tunnel consists of the IP address and the networks that should be routed over this interface. Especially, no peer partner address or gateway address is needed or required. Special routes to reach the VPN Server (for example added when using redirect-gateway) are not needed either. The application will consequently ignore these settings when importing a configuration. The app ensures with the VPNService API that the connection to the server is not routed through the VPN tunnel.\\nThe VPNService API does not allow specifying networks that should not be routed via the VPN. As a workaround the app tries to detect networks that should not be routed over tunnel (e.g. route x.x.x.x y.y.y.y net_gateway) and calculates a set of routes that excludes this routes to emulate the behaviour of other platforms. The log windows shows the configuration of the VPNService upon establishing a connection.\\nBehind the scenes: Android 4.4+ does use policy routing. Using route/ifconfig will not show the installed routes. Instead use ip rule, iptables -t mangle -L</string>\n    <string name=\"persisttun_summary\">Do not fallback to no VPN connection when OpenVPN is reconnecting.</string>\n    <string name=\"persistent_tun_title\">Persistent tun</string>\n    <string name=\"openvpn_log\">OpenVPN Log</string>\n    <string name=\"import_config\">Import OpenVPN configuration</string>\n    <string name=\"battery_consumption_title\">Battery consumption</string>\n    <string name=\"baterry_consumption\">In my personal tests the main reason for high battery consumption of OpenVPN are the keepalive packets. Most OpenVPN servers have a configuration directive like \\'keepalive 10 60\\' which causes the client and server to exchange keepalive packets every ten seconds. &lt;p&gt; While these packets are small and do not use much traffic, they keep the mobile radio network busy and increase the energy consumption. (See also &lt;a href=\"http://developer.android.com/training/efficient-downloads/efficient-network-access.html#RadioStateMachine\"&gt;The Radio State Machine | Android Developers&lt;/a&gt;) &lt;p&gt; This keepalive setting cannot be changed on the client. Only the system administrator of the OpenVPN can change the setting. &lt;p&gt; Unfortunately using a keepalive larger than 60 seconds with UDP can cause some NAT gateways to drop the connection due to an inactivity timeout. Using TCP with a long keep alive timeout works, but tunneling TCP over TCP performs extremely poorly on connections with high packet loss. (See &lt;a href=\"http://sites.inka.de/bigred/devel/tcp-tcp.html\"&gt;Why TCP Over TCP Is A Bad Idea&lt;/a&gt;)</string>\n    <string name=\"faq_tethering\">The Android Tethering feature (over WiFi, USB or Bluetooth) and the VPNService API (used by this program) do not work together. For more details see the &lt;a href=\\\"https://github.com/schwabe/ics-openvpn/issues/34\\\">issue #34&lt;/a></string>\n    <string name=\"vpn_tethering_title\">VPN and Tethering</string>\n    <string name=\"connection_retries\">Connection retries</string>\n    <string name=\"reconnection_settings\">Reconnection settings</string>\n    <string name=\"connectretrymessage\">Number of seconds to wait between connection attempts.</string>\n    <string name=\"connectretrywait\">Seconds between connections</string>\n    <string name=\"minidump_generated\">OpenVPN crashed unexpectedly. Please consider using the send Minidump option in the main menu</string>\n    <string name=\"send_minidump\">Send Minidump to developer</string>\n    <string name=\"send_minidump_summary\">Sends debugging information about last crash to developer</string>\n    <string name=\"notifcation_title\">OpenVPN - %s</string>\n    <string name=\"session_ipv4string\">%1$s - %2$s</string>\n    <string name=\"session_ipv6string\">%1$s - %3$s, %2$s</string>\n    <string name=\"state_connecting\">Connecting</string>\n    <string name=\"state_wait\">Waiting for server reply</string>\n    <string name=\"state_auth\">Authenticating</string>\n    <string name=\"state_get_config\">Getting client configuration</string>\n    <string name=\"state_assign_ip\">Assigning IP addresses</string>\n    <string name=\"state_add_routes\">Adding routes</string>\n    <string name=\"state_connected\">Connected</string>\n    <string name=\"state_disconnected\">Disconnect</string>\n    <string name=\"state_reconnecting\">Reconnecting</string>\n    <string name=\"state_exiting\">Exiting</string>\n    <string name=\"state_noprocess\">Not running</string>\n    <string name=\"state_resolve\">Resolving host names</string>\n    <string name=\"state_tcp_connect\">Connecting (TCP)</string>\n    <string name=\"state_auth_failed\">Authentication failed</string>\n    <string name=\"state_nonetwork\">Waiting for usable network</string>\n    <string name=\"statusline_bytecount\">↓%2$s/s %1$s - ↑%4$s/s %3$s</string>\n    <string name=\"notifcation_title_notconnect\">Not connected</string>\n    <string name=\"start_vpn_title\">Connecting to VPN %s</string>\n    <string name=\"start_vpn_ticker\">Connecting to VPN %s</string>\n    <string name=\"jelly_keystore_alphanumeric_bug\">Some versions of Android 4.1 have problems if the name of the keystore certificate contains non alphanumeric characters (like spaces, underscores or dashes). Try to reimport the certificate without special characters</string>\n    <string name=\"encryption_cipher\">Encryption cipher</string>\n    <string name=\"packet_auth\">Packet authentication</string>\n    <string name=\"auth_dialog_title\">Enter packet authentication method</string>\n    <string name=\"built_by\">built by %s</string>\n    <string name=\"debug_build\">debug build</string>\n    <string name=\"official_build\">official build</string>\n    <string name=\"make_selection_inline\">Copy into profile</string>\n    <string name=\"crashdump\">Crashdump</string>\n    <string name=\"add\">Add</string>\n    <string name=\"send_config\">Send config file</string>\n    <string name=\"complete_dn\">Complete DN</string>\n    <string name=\"remotetlsnote\">Your imported configuration used the old DEPRECATED tls-remote option which uses a different DN format.</string>\n    <string name=\"rdn\">RDN (common name)</string>\n    <string name=\"rdn_prefix\">RDN prefix</string>\n    <string name=\"tls_remote_deprecated\">tls-remote (DEPRECATED)</string>\n    <string name=\"help_translate\">You can help translating by visiting http://crowdin.net/project/ics-openvpn/invite</string>\n    <string name=\"prompt\">%1$s attempts to control %2$s</string>\n    <string name=\"remote_warning\">By proceeding, you are giving the application permission to completely control OpenVPN for Android and to intercept all network traffic.<b>Do NOT accept unless you trust the application.</b> Otherwise, you run the risk of having your data compromised by malicious software.\"</string>\n    <string name=\"remote_trust\">I trust this application.</string>\n    <string name=\"no_external_app_allowed\">No app allowed to use external API</string>\n    <string name=\"allowed_apps\">Allowed apps: %s</string>\n    <string name=\"clearappsdialog\">Clear list of allowed external apps?\\nCurrent list of allowed apps:\\n\\n%s</string>\n    <string name=\"screenoff_summary\">\"Pause VPN when screen is off and less than 64 kB transferred data in 60s. When the \\\"Persistent Tun\\\" option is enabled pausing the VPN will leave your device with NO network connectivity. Without the \\\"Persistent Tun\\\" option the device will have no VPN connection/protection.</string>\n    <string name=\"screenoff_title\">Pause VPN connection after screen off</string>\n    <string name=\"screenoff_pause\">Pausing connection in screen off state: less than %1$s in %2$ss</string>\n    <string name=\"screen_nopersistenttun\">Warning: Persistent tun not enabled for this VPN. Traffic will use the normal Internet connection when the screen is off.</string>\n    <string name=\"save_password\">Save Password</string>\n    <string name=\"pauseVPN\">Pause VPN</string>\n    <string name=\"resumevpn\">Resume VPN</string>\n    <string name=\"state_userpause\">VPN pause requested by user</string>\n    <string name=\"state_screenoff\">VPN paused - screen off</string>\n    <string name=\"device_specific\">Device specifics Hacks</string>\n    <string name=\"cannotparsecert\">Cannot display certificate information</string>\n    <string name=\"appbehaviour\">Application behaviour</string>\n    <string name=\"vpnbehaviour\">VPN behaviour</string>\n    <string name=\"allow_vpn_changes\">Allow changes to VPN Profiles</string>\n    <string name=\"hwkeychain\">Hardware Keystore:</string>\n    <string name=\"permission_icon_app\">Icon of app trying to use OpenVPN for Android</string>\n    <string name=\"faq_vpndialog43\">\"Starting with Android 4.3 the VPN confirmation is guarded against \\\"overlaying apps\\\". This results in the dialog not reacting to touch input. If you have an app that uses overlays it may cause this behaviour. If you find an offending app contact the author of the app. This problem affect all VPN applications on Android 4.3 and later. See also &lt;a href=\\\"https://github.com/schwabe/ics-openvpn/issues/185\\\">Issue 185&lt;a> for additional details\"</string>\n    <string name=\"faq_vpndialog43_title\">Vpn Confirmation Dialog</string>\n    <string name=\"donatePlayStore\">Alternatively you can send me a donation with the Play Store:</string>\n    <string name=\"thanks_for_donation\">Thanks for donating %s!</string>\n    <string name=\"logCleared\">Log cleared.</string>\n    <string name=\"show_password\">Show password</string>\n    <string name=\"keyChainAccessError\">KeyChain Access error: %s</string>\n    <string name=\"timestamp_short\">Short</string>\n    <string name=\"timestamp_iso\">ISO</string>\n    <string name=\"timestamps\">Timestamps</string>\n    <string name=\"timestamps_none\">None</string>\n    <string name=\"uploaded_data\">Upload</string>\n    <string name=\"downloaded_data\">Download</string>\n    <string name=\"vpn_status\">Vpn Status</string>\n    <string name=\"logview_options\">View options</string>\n    <string name=\"unhandled_exception\">Unhandled exception: %1$s\\n\\n%2$s</string>\n    <string name=\"unhandled_exception_context\">%3$s: %1$s\\n\\n%2$s</string>\n    <string name=\"faq_system_dialog_xposed\">If you have rooted your Android device you can install the &lt;a href=\\\"http://xposed.info/\\\"&gt;Xposed framework&lt;/a&gt; and a the &lt;a href=\\\"http://repo.xposed.info/module/de.blinkt.vpndialogxposed\\\"&gt;VPN Dialog confirm module&lt;/a&gt; at your own risk\"</string>\n    <string name=\"full_licenses\">Full licenses</string>\n    <string name=\"blocklocal_summary\">Networks directly connected to the local interfaces will not be routed over the VPN. Deselecting this option will redirect all traffic intented for local networks to the VPN.</string>\n    <string name=\"blocklocal_title\">Bypass VPN for local networks</string>\n    <string name=\"userpw_file\">Username/Password file</string>\n    <string name=\"imported_from_file\">[Imported from: %s]</string>\n    <string name=\"files_missing_hint\">Some files could not be found. Please select the files to import the profile:</string>\n    <string name=\"openvpn_is_no_free_vpn\">To use this app you need a VPN provider/VPN gateway supporting OpenVPN (often provided by your employer). Check out http://community.openvpn.net/ for more information on OpenVPN and how to setup your own OpenVPN server.</string>\n    <string name=\"import_log\">Import log:</string>\n    <string name=\"ip_looks_like_subnet\">Vpn topology \\\"%3$s\\\" specified but ifconfig %1$s %2$s looks more like an IP address with a network mask. Assuming \\\"subnet\\\" topology.</string>\n    <string name=\"mssfix_invalid_value\">The MSS override value has to be a integer between 0 and 9000</string>\n    <string name=\"mssfix_value_dialog\">Announce to TCP sessions running over the tunnel that they should limit their send packet sizes such that after OpenVPN has encapsulated them, the resulting UDP packet size that OpenVPN sends to its peer will not exceed this number of bytes. (default is 1450)</string>\n    <string name=\"mssfix_checkbox\">Override MSS value of TCP payload</string>\n    <string name=\"mssfix_dialogtitle\">Set MSS of TCP payload</string>\n    <string name=\"client_behaviour\">Client behaviour</string>\n    <string name=\"clear_external_apps\">Clear allowed external apps</string>\n    <string name=\"loading\">Loading…</string>\n    <string name=\"allowed_vpn_apps_info\">Allowed VPN apps: %1$s</string>\n    <string name=\"disallowed_vpn_apps_info\">Disallowed VPN apps: %1$s</string>\n    <string name=\"app_no_longer_exists\">Package %s is no longer installed, removing it from app allow/disallow list</string>\n    <string name=\"vpn_disallow_radio\">VPN is used for all apps but exclude selected</string>\n    <string name=\"vpn_allow_radio\">VPN is used for only for selected apps</string>\n    <string name=\"query_delete_remote\">Remove remote server entry?</string>\n    <string name=\"keep\">Keep</string>\n    <string name=\"delete\">Delete</string>\n    <string name=\"add_remote\">Add new remote</string>\n    <string name=\"remote_random\">Use connection entries in random order on connect</string>\n    <string name=\"remote_no_server_selected\">You need to define and enable at least one remote server.</string>\n    <string name=\"server_list\">Server List</string>\n    <string name=\"vpn_allowed_apps\">Allowed Apps</string>\n    <string name=\"advanced_settings\">Advanced Settings</string>\n    <string name=\"payload_options\">Payload options</string>\n    <string name=\"tls_settings\">TLS Settings</string>\n    <string name=\"no_remote_defined\">No remote defined</string>\n    <string name=\"duplicate_vpn\">Duplicate VPN profile</string>\n    <string name=\"duplicate_profile_title\">Duplicating profile: %s</string>\n    <string name=\"show_log\">Show log</string>\n    <string name=\"faq_android_clients\">Multiple OpenVPN clients for Android exist. The most common ones are OpenVPN for Android (this client), OpenVPN Connect and OpenVPN Settings.&lt;p&gt;The clients can be grouped into two groups: OpenVPN for Android and OpenVPN Connect use the official VPNService API (Android 4.0+) and require no root and OpenVPN Settings which uses root.&lt;p&gt;OpenVPN for Android is an open source client and developed by Arne Schwabe.  It is targeted at more advanced users and offers many settings and the ability to import profiles from files and to configure/change profiles inside the app. The client is based on the community version of OpenVPN. It is based on the OpenVPN 2.x source code. This client can be seen as the semi officially client of the community. &lt;p&gt;OpenVPN Connect is non open source client that is developed by OpenVPN Technologies, Inc. The client is indented to be general use client and more targeted at the average user and allows the import of OpenVPN profiles. This client is based on the OpenVPN C++ reimplementation of the OpenVPN protocol (This was required to allow OpenVPN Technologies, Inc to publish an iOS OpenVPN app). This client is the official client of the OpenVPN technologies &lt;p&gt; OpenVPN Settings is the oldest of the clients and also a UI for the open source OpenVPN. In contrast to OpenVPN  for Android it requires root and does not use the VPNService API. It does not depend on Android 4.0+</string>\n    <string name=\"faq_androids_clients_title\">Differences between the OpenVPN Android clients</string>\n    <string name=\"ignore_multicast_route\">Ignoring multicast route: %s</string>\n    <string name=\"ab_only_cidr\">Android supports only CIDR routes to the VPN. Since non-CIDR routes are almost never used, OpenVPN for Android will use a /32 for routes that are not CIDR and issue a warning.</string>\n    <string name=\"ab_tethering_44\">Tethering works while the VPN is active. The tethered connection will NOT use the VPN.</string>\n    <string name=\"ab_kitkat_mss\">Early KitKat version set the wrong MSS value on TCP connections (#61948). Try to enable the mssfix option to workaround this bug.</string>\n    <string name=\"ab_proxy\">Android will keep using your proxy settings specified for the mobile/Wi-Fi connection when no DNS servers are set. OpenVPN for Android will warn you about this in the log.<p>When a VPN sets a DNS server Android will not use a proxy. There is no API to set a proxy for a VPN connection.</p></string>\n    <string name=\"ab_lollipop_reinstall\">VPN apps may stop working when uninstalled and reinstalled again. For details see #80074</string>\n    <string name=\"ab_not_route_to_vpn\">The configured client IP and the IPs in its network mask are not routed to the VPN. OpenVPN works around this bug by explicitly adding a route that corrosponds to the client IP and its netmask</string>\n    <string name=\"ab_persist_tun\">Opening a tun device while another tun device is active, which is used for persist-tun support, crashes the VPNServices on the device. A reboot is required to make VPN work again. OpenVPN for Android tries to avoid reopening the tun device and if really needed first closes the current TUN before opening the new TUN device to avoid to crash. This may lead to a short window where packets are sent over the non-VPN connection. Even with this workaround the VPNServices sometimes crashes and requires a reboot of the device.</string>\n    <string name=\"ab_secondary_users\">VPN does not work at all for secondary users.</string>\n    <string name=\"ab_kitkat_reconnect\">\"Multiple users report that the mobile connection/mobile data connection is frequently dropped while using the VPN app. The behaviour seems to affect only some mobile provider/device combination and so far no cause/workaround for the bug could be identified. \"</string>\n    <string name=\"ab_vpn_reachability_44\">Only destination can be reached over the VPN that are reachable without VPN. IPv6 VPNs does not work at all.</string>\n    <string name=\"ab_only_cidr_title\">Non CIDR Routes</string>\n    <string name=\"ab_proxy_title\">Proxy behaviour for VPNs</string>\n    <string name=\"ab_lollipop_reinstall_title\">Reinstalling VPN apps</string>\n    <string name=\"version_upto\">%s and earlier</string>\n    <string name=\"copy_of_profile\">Copy of %s</string>\n    <string name=\"ab_not_route_to_vpn_title\">Route to the configured IP address</string>\n    <string name=\"ab_kitkat_mss_title\">Wrong MSS value for VPN connection</string>\n    <string name=\"ab_secondary_users_title\">Secondary tablet users</string>\n    <string name=\"custom_connection_options_warng\">Specify custom connection specific options. Use with care</string>\n    <string name=\"custom_connection_options\">Custom Options</string>\n    <string name=\"remove_connection_entry\">Remove connection entry</string>\n    <string name=\"ab_kitkat_reconnect_title\">Random disconnects from mobile network</string>\n    <string name=\"ab_vpn_reachability_44_title\">Remote networks not reachable</string>\n    <string name=\"ab_persist_tun_title\">Persist tun mode</string>\n    <string name=\"version_and_later\">%s and later</string>\n    <string name=\"tls_cipher_alert_title\">Connections fails with SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure</string>\n    <string name=\"tls_cipher_alert\">Newer OpenVPN for Android versions (0.6.29/March 2015) use a more secure default for the allowed cipher suites (tls-cipher \\\"DEFAULT:!EXP:!PSK:!SRP:!kRSA\\\"). Unfortunately, omitting the less secure cipher suites and export cipher suites, especially the omission of cipher suites that do not support Perfect Forward Secrecy (Diffie-Hellman) causes some problems. This usually caused by an well-intentioned but poorly executed attempt to strengthen TLS security by setting tls-cipher on the server or some embedded OSes with stripped down SSL (e.g. MikroTik).\\nTo solve this problem the problem, set the tls-cipher settings on the server to reasonable default like tls-cipher \\\"DEFAULT:!EXP:!PSK:!SRP:!kRSA\\\". To work around the problem on the client add the custom option tls-cipher DEFAULT on the Android client.</string>\n    <string name=\"message_no_user_edit\">This profile has been added from an external app (%s) and has been marked as not user editable.</string>\n    <string name=\"crl_file\">Certificate Revocation List</string>\n    <string name=\"service_restarted\">Restarting OpenVPN Service (App crashed probably crashed or killed for memory pressure)</string>\n    <string name=\"import_config_error\">Importing the config yielded an error, cannot save it</string>\n    <string name=\"Search\">Search</string>\n    <string name=\"lastdumpdate\">(Last dump is %1$d:%2$dh old (%3$s))</string>\n    <string name=\"clear_log_on_connect\">Clear log on new connection</string>\n    <string name=\"connect_timeout\">Connect Timeout</string>\n    <string name=\"no_allowed_app\">No allowed app added. Adding ourselves (%s) to have at least one app in the allowed app list to not allow all apps</string>\n    <string name=\"query_permissions_sdcard\">OpenVPN for Android can try to discover the missing file(s) on the sdcard automatically. Tap this message start the permission request.</string>\n    <string name=\"protocol\">Protocol</string>\n    <string name=\"enabled_connection_entry\">Enabled</string>\n    <string name=\"abi_mismatch\">Preferred native ABI precedence of this device (%1$s) and ABI reported by native libraries (%2$s) mismatch</string>\n    <string name=\"months_left\">%d months left</string>\n    <string name=\"days_left\">%d days left</string>\n    <string name=\"hours_left\">%d hours left</string>\n    <string name=\"permission_revoked\">VPN permission revoked by OS (e.g. other VPN program started), stopping VPN</string>\n    <string name=\"pushpeerinfo\">Push Peer info</string>\n    <string name=\"pushpeerinfosummary\">Send extra information to the server, e.g. SSL version and Android version</string>\n    <string name=\"pw_request_dialog_title\">Need %1$s</string>\n    <string name=\"pw_request_dialog_prompt\">Please enter the password for profile %1$s</string>\n    <string name=\"menu_use_inline_data\">Use inline data</string>\n    <string name=\"export_config_chooser_title\">Export configuration file</string>\n    <string name=\"missing_tlsauth\">tls-auth file is missing</string>\n    <string name=\"missing_certificates\">Missing user certificate or user certifcate key file</string>\n    <string name=\"missing_ca_certificate\">Missing CA certificate</string>\n    <string name=\"crl_title\">Certifcate Revoke List (optional)</string>\n    <string name=\"reread_log\">Reread (%d) log items from log cache file</string>\n    <string name=\"samsung_broken\">Even though Samsung phones are among the most selling Android phones, Samsung\\'s firmware are also among the most buggy Android firmwares. The bugs are not limited to the VPN operation on these devices but many of them can be workarounded. In the following some of these bugs are described.\\n\\nDNS does not work unless the DNS server in the VPN range.\\n\\nOn many Samsung 5.x devices the allowed/disallowed apps feature does not work.\\nOn Samsung 6.x VPN is reported not to work unless the VPN app is exempted from Powersave features.</string>\n    <string name=\"samsung_broken_title\">Samsung phones</string>\n    <string name=\"novpn_selected\">No VPN selected.</string>\n    <string name=\"alwaysonvpn\">VPN used on boot and for Always-On</string>\n    <string name=\"reconnect\">Reconnect</string>\n    <string name=\"qs_title\">Toggle VPN</string>\n    <string name=\"qs_connect\">Connect to %s</string>\n    <string name=\"qs_disconnect\">Disconnect %s</string>\n    <string name=\"connectretrymaxmessage\">Enter the maximum time between connection attempts. OpenVPN will slowly raise its waiting time after an unsuccessful connection attempt up to this value. Defaults to 300s.</string>\n    <string name=\"connectretrymaxtitle\">Maximum time between connection attempts</string>\n    <string name=\"state_waitconnectretry\">Waiting %s seconds between connection attempt</string>\n    <string name=\"nought_alwayson_warning\"><![CDATA[If you did not get a VPN confirmation dialog, you have \\\"Always on VPN\\\" enabled for another app. In that case only that app is allowed to connect to a VPN. Check under Settings-> Networks more .. -> VPNS]]></string>\n    <string name=\"management_socket_closed\">Connection to OpenVPN closed (%s)</string>\n</resources>"
  },
  {
    "path": "Android-code/app/src/main/res/values-ar/strings.xml",
    "content": "<resources>\n      <string name=\"home_btn_choose_country\"> اختر بلدك </string>\n      <string name=\"home_pop_up_title_choose_country\">  اختر بلدك </string>\n      <string name=\"server_btn_connect\"> اتصال</string>\n      <string name=\"server_btn_disconnect\"> قطع الاتصال </string>\n      <string name=\"server_txt_ping\"> الجدول: </string>\n      <string name=\"server_txt_sessions\"> الدورات: </string>\n      <string name=\"server_txt_speed\"> السرعة: </string>\n      <string name=\"server_error_loading_profile\">  فشل تحميل التشكيل الجانبي </string>\n      <string name=\"server_txt_status\">  حالة الاتصال: </string>\n      <string name=\"server_list_more\">  التفاصيل </string>\n      <string name=\"mbps\"> Mbps </string>\n      <string name=\"ms\"> ms </string>\n      <string name=\"loading_text\"> التحميل ... </string>\n      <string name=\"downloading_csv_text\"> تحميل قائمة خادم ...</string>\n      <string name=\"parsing_csv_text\"> التحليل اللغوي قائمة ملقمات ...  </string>\n      <string name=\"csv_file_error\">  المشكلة مع ملف القراءة ... </string>\n      <string name=\"csv_file_error_parsing\"> المشكلة مع تحليل ملف ...  </string>\n      <string name=\"network_error\"> خطأ الشبكة ... </string>\n      <string name=\"successfully_loaded\"> تحميل كاملة ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-be/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Абярыце краіну </string>\n    <string name=\"home_pop_up_title_choose_country\"> Абярыце краіну </string>\n    <string name=\"server_btn_connect\"> Падключыць </string>\n    <string name=\"server_btn_disconnect\"> раз\\'яднаць </string>\n    <string name=\"server_txt_ping\"> Пінг: </string>\n    <string name=\"server_txt_sessions\"> Сесіі: </string>\n    <string name=\"server_txt_speed\"> Хуткасць: </string>\n    <string name=\"server_error_loading_profile\"> Памылка загрузкі профілю </string>\n    <string name=\"server_txt_status\"> Стан злучэння: </string>\n    <string name=\"server_list_more\"> Больш падрабязна </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Загрузка ... </string>\n    <string name=\"downloading_csv_text\"> Загрузка спісу сервераў ... </string>\n    <string name=\"parsing_csv_text\"> парсінга спісу сервераў ... </string>\n    <string name=\"csv_file_error\"> Праблема з чытаннем файла ... </string>\n    <string name=\"csv_file_error_parsing\"> Праблема з парсінга файла ... </string>\n    <string name=\"network_error\"> Памылка сеткі ... </string>\n    <string name=\"successfully_loaded\"> Загрузка завершана ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-cs/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Vyberte zemi </string>\n    <string name=\"home_pop_up_title_choose_country\"> Vyberte zemi </string>\n    <string name=\"server_btn_connect\"> Připojit </string>\n    <string name=\"server_btn_disconnect\"> Odpojit </string>\n    <string name=\"server_txt_ping\"> Tabulka: </string>\n    <string name=\"server_txt_sessions\">  Sessions: </string>\n    <string name=\"server_txt_speed\"> Speed: </string>\n    <string name=\"server_error_loading_profile\"> Nepodařilo se načíst profil </string>\n    <string name=\"server_txt_status\"> Connection Status: </string>\n    <string name=\"server_list_more\"> Podrobnosti </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> MS </string>\n    <string name=\"loading_text\"> Loading ... </string>\n    <string name=\"downloading_csv_text\"> Seznam zatížení serverů ... </string>\n    <string name=\"parsing_csv_text\"> Rozebrat seznam serverů ... </string>\n    <string name=\"csv_file_error\"> Problém s při čtení souboru ... </string>\n    <string name=\"csv_file_error_parsing\"> Problém s analýze souboru ... </string>\n    <string name=\"network_error\"> Chyba sítě ... </string>\n    <string name=\"successfully_loaded\"> Ke stažení kompletní ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-de/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Wählen Sie Ihr Land </string>\n    <string name=\"home_pop_up_title_choose_country\"> Wählen Sie Ihr Land </string>\n    <string name=\"server_btn_connect\"> Verbinden </string>\n    <string name=\"server_btn_disconnect\"> Trennen </string>\n    <string name=\"server_txt_ping\"> Table: </string>\n    <string name=\"server_txt_sessions\"> Sessions: </string>\n    <string name=\"server_txt_speed\"> Geschwindigkeit: </string>\n    <string name=\"server_error_loading_profile\"> Profil konnte nicht geladen werden </string>\n    <string name=\"server_txt_status\"> Verbindungsstatus: </string>\n    <string name=\"server_list_more\"> Details </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Loading ... </string>\n    <string name=\"downloading_csv_text\"> Server-Liste laden ... </string>\n    <string name=\"parsing_csv_text\"> eine Liste der Server Parsen ... </string>\n    <string name=\"csv_file_error\"> Das Problem mit dem Lesen der Datei ... </string>\n    <string name=\"csv_file_error_parsing\"> Das Problem mit Parsen der Datei ... </string>\n    <string name=\"network_error\"> Netzwerkfehler ... </string>\n    <string name=\"successfully_loaded\"> Download komplett ... </string>\n\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-el/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Επιλέξτε τη χώρα  </string>\n    <string name=\"home_pop_up_title_choose_country\"> Επιλέξτε τη χώρα </string>\n    <string name=\"server_btn_connect\"> Σύνδεση </string>\n    <string name=\"server_btn_disconnect\"> Αποσύνδεση </string>\n    <string name=\"server_txt_ping\"> Πίνακας: </string>\n    <string name=\"server_txt_sessions\"> Συνεδρίες: </string>\n    <string name=\"server_txt_speed\"> Ταχύτητα: </string>\n    <string name=\"server_error_loading_profile\"> Απέτυχε η φόρτωση του προφίλ </string>\n    <string name=\"server_txt_status\"> Κατάσταση σύνδεσης: </string>\n    <string name=\"server_list_more\"> Λεπτομέρειες </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Φόρτωση ... </string>\n    <string name=\"downloading_csv_text\"> Load Λίστα διακομιστή ... </string>\n    <string name=\"parsing_csv_text\"> Parsing μια λίστα των διακομιστών ... </string>\n    <string name=\"csv_file_error\"> Το πρόβλημα με την ανάγνωση του αρχείου ... </string>\n    <string name=\"csv_file_error_parsing\"> Το πρόβλημα με την ανάλυση του αρχείου ... </string>\n    <string name=\"network_error\"> Σφάλμα δικτύου ... </string>\n    <string name=\"successfully_loaded\"> Λήψη πλήρη ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-es/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Seleccione su país </string>\n    <string name=\"home_pop_up_title_choose_country\"> Seleccione su país </string>\n    <string name=\"server_btn_connect\"> Conectar </string>\n    <string name=\"server_btn_disconnect\"> Desconectar </string>\n    <string name=\"server_txt_ping\"> Tabla: </string>\n    <string name=\"server_txt_sessions\">  Sesiones: </string>\n    <string name=\"server_txt_speed\"> Velocidad: </string>\n    <string name=\"server_error_loading_profile\"> No se ha podido cargar el perfil </string>\n    <string name=\"server_txt_status\"> Estado de la conexión: </string>\n    <string name=\"server_list_more\"> Detalles </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Cargando ... </string>\n    <string name=\"downloading_csv_text\"> Lista de servidores de carga ... </string>\n    <string name=\"parsing_csv_text\"> Analizar una lista de servidores ... </string>\n    <string name=\"csv_file_error\"> El problema con el archivo de lectura ... </string>\n    <string name=\"csv_file_error_parsing\"> El problema con el análisis del archivo ... </string>\n    <string name=\"network_error\"> Error de red ... </string>\n    <string name=\"successfully_loaded\"> Descarga completa ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-fa/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\">کشور خود را انتخاب کنید</string>\n    <string name=\"home_pop_up_title_choose_country\">کشور خود را انتخاب کنید</string>\n    <string name=\"server_btn_connect\">اتصال </string>\n    <string name=\"server_btn_disconnect\"> قطع ارتباط </string>\n    <string name=\"server_txt_ping\">جدول:</string>\n    <string name=\"server_txt_sessions\"> جلسات:</string>\n    <string name=\"server_txt_speed\">سرعت: </string>\n    <string name=\"server_error_loading_profile\">شکست خورده برای بارگذاری مشخصات</string>\n    <string name=\"server_txt_status\">وضعیت اتصال:</string>\n    <string name=\"server_list_more\">جزئیات</string>\n    <string name=\"mbps\">Mbps</string>\n    <string name=\"ms\">ms</string>\n    <string name=\"loading_text\">در حال بارگذاری ...</string>\n    <string name=\"downloading_csv_text\"> بارگذاری لیست سرور ...</string>\n    <string name=\"parsing_csv_text\">تجزیه لیستی از سرورهای ...</string>\n    <string name=\"csv_file_error\"> مشکل با فایل خواندن ... </string>\n    <string name=\"csv_file_error_parsing\">مشکل با تجزیه فایل ...</string>\n    <string name=\"network_error\">خطای شبکه ...</string>\n    <string name=\"successfully_loaded\"> دانلود کامل ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-fr/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Sélectionnez le pays </string>\n    <string name=\"home_pop_up_title_choose_country\"> Sélectionnez le pays </string>\n    <string name=\"server_btn_connect\"> Connectez-vous </string>\n    <string name=\"server_btn_disconnect\"> Déconnecter </string>\n    <string name=\"server_txt_ping\"> Tableau: </string>\n    <string name=\"server_txt_sessions\"> Sessions: </string>\n    <string name=\"server_txt_speed\"> Vitesse: </string>\n    <string name=\"server_error_loading_profile\"> Impossible de charger le profil </string>\n    <string name=\"server_txt_status\"> Connection Status: </string>\n    <string name=\"server_list_more\"> Détails </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Chargement en cours ... </string>\n    <string name=\"downloading_csv_text\"> Load Liste des serveurs ... </string>\n    <string name=\"parsing_csv_text\"> Parsing une liste de serveurs ... </string>\n    <string name=\"csv_file_error\"> Le problème avec le fichier de lecture ... </string>\n    <string name=\"csv_file_error_parsing\"> Le problème avec l\\'analyse du fichier ... </string>\n    <string name=\"network_error\"> Erreur réseau ... </string>\n    <string name=\"successfully_loaded\"> Télécharger complète ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-hu/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Válassza ki az országot </string>\n    <string name=\"home_pop_up_title_choose_country\"> Válassza ki az országot </string>\n    <string name=\"server_btn_connect\"> Csatlakozás </string>\n    <string name=\"server_btn_disconnect\"> Leválasztás </string>\n    <string name=\"server_txt_ping\"> Táblázat: </string>\n    <string name=\"server_txt_sessions\"> Sessions: </string>\n    <string name=\"server_txt_speed\"> Speed: </string>\n    <string name=\"server_error_loading_profile\"> Nem sikerült betölteni a profilt </string>\n    <string name=\"server_txt_status\"> Connection Status: </string>\n    <string name=\"server_list_more\"> Részletek </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Betöltés ... </string>\n    <string name=\"downloading_csv_text\"> Load Server List ... </string>\n    <string name=\"parsing_csv_text\"> Elemzés a kiszolgálók listáját ... </string>\n    <string name=\"csv_file_error\"> A probléma a fájl olvasása közben ... </string>\n    <string name=\"csv_file_error_parsing\"> A probléma elemzés a file ... </string>\n    <string name=\"network_error\"> Hálózati hiba ... </string>\n    <string name=\"successfully_loaded\"> Letöltés kész ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-id/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Pilih negara </string>\n    <string name=\"home_pop_up_title_choose_country\"> Pilih negara </string>\n    <string name=\"server_btn_connect\"> Connect </string>\n    <string name=\"server_btn_disconnect\"> Putus </string>\n    <string name=\"server_txt_ping\"> Table: </string>\n    <string name=\"server_txt_sessions\"> Sessions: </string>\n    <string name=\"server_txt_speed\"> Kecepatan: </string>\n    <string name=\"server_error_loading_profile\"> Gagal memuat profil </string>\n    <string name=\"server_txt_status\"> Status Connection: </string>\n    <string name=\"server_list_more\"> Detail </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Loading ... </string>\n    <string name=\"downloading_csv_text\"> Muat Daftar Server ... </string>\n    <string name=\"parsing_csv_text\"> Parsing daftar server ... </string>\n    <string name=\"csv_file_error\"> Masalah dengan membaca file ... </string>\n    <string name=\"csv_file_error_parsing\"> Masalah dengan parsing file ... </string>\n    <string name=\"network_error\"> error Jaringan ... </string>\n    <string name=\"successfully_loaded\"> Unduh lengkap ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-it/strings.xml",
    "content": "<resources>\n    <string name=\"home_pop_up_title_choose_country\"> Seleziona il tuo paese </string>\n    <string name=\"server_btn_connect\"> Connetti </string>\n    <string name=\"server_btn_disconnect\"> Disconnetti </string>\n    <string name=\"server_txt_ping\"> Tabella: </string>\n    <string name=\"server_txt_sessions\">  Sessions: </string>\n    <string name=\"server_txt_speed\"> Velocità: </string>\n    <string name=\"server_error_loading_profile\"> Impossibile caricare il profilo </string>\n    <string name=\"server_txt_status\"> Stato connessione: </string>\n    <string name=\"server_list_more\"> Dettagli </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\">  ms </string>\n    <string name=\"loading_text\"> Caricamento ... </string>\n    <string name=\"downloading_csv_text\"> Elenco server Carica ... </string>\n    <string name=\"parsing_csv_text\"> l\\'analisi di un elenco di server ... </string>\n    <string name=\"csv_file_error\"> Il problema con la lettura del file ... </string>\n    <string name=\"csv_file_error_parsing\"> Il problema con l\\'analisi del file ... </string>\n    <string name=\"network_error\"> Errore di rete ... </string>\n    <string name=\"successfully_loaded\"> Scarica completa ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-iw/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\">בחר את המדינה שלך</string>\n    <string name=\"home_pop_up_title_choose_country\"> בחר את המדינה שלך </string>\n    <string name=\"server_btn_connect\"> Connect </string>\n    <string name=\"server_btn_disconnect\"> נתק </string>\n    <string name=\"server_txt_ping\"> לוח: </string>\n    <string name=\"server_txt_sessions\"> הפעלות: </string>\n    <string name=\"server_txt_speed\"> מהירות: </string>\n    <string name=\"server_error_loading_profile\"> טעינת פרופיל נכשל </string>\n    <string name=\"server_txt_status\"> מצב חיבור: </string>\n    <string name=\"server_list_more\"> פרטים </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> טוען ... </string>\n    <string name=\"downloading_csv_text\"> רשימת שרתים טען ... </string>\n    <string name=\"parsing_csv_text\"> ניתוח רשימה של שרתים ... </string>\n    <string name=\"csv_file_error\"> הבעיה עם קובץ קריאה ... </string>\n    <string name=\"csv_file_error_parsing\"> הבעיה עם בקריאת קובץ ... </string>\n    <string name=\"network_error\"> שגיאת רשת ... </string>\n  \n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-ja/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> にあなたの国を選択</string>\n    <string name=\"home_pop_up_title_choose_country\"> にあなたの国を選択</string>\n    <string name=\"server_btn_connect\">接続</string>\n    <string name=\"server_btn_disconnect\">を切断</string>\n    <string name=\"server_txt_ping\">表：</string>\n    <string name=\"server_txt_sessions\">セッション：</string>\n    <string name=\"server_txt_speed\">スピード：</string>\n    <string name=\"server_error_loading_profile\">プロファイルをロードできませんでした</string>\n    <string name=\"server_txt_status\">接続ステータス：</string>\n    <string name=\"server_list_more\">詳細</string>\n    <string name=\"mbps\"> Mbps</string>\n    <string name=\"ms\">ミリ</string>\n    <string name=\"loading_text\">読み込んでいます... </string>\n    <string name=\"downloading_csv_text\">ロードサーバリスト... </string>\n    <string name=\"parsing_csv_text\">サーバーのリストを解析... </string>\n    <string name=\"csv_file_error\">読み取りファイルに問題... </string>\n    <string name=\"csv_file_error_parsing\">ファイルを解析すると、問題... </string>\n    <string name=\"network_error\">ネットワークエラー... </string>\n    <string name=\"successfully_loaded\">ダウンロードの完了... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-ka/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> აირჩიეთ თქვენი ქვეყანა </string>\n    <string name=\"home_pop_up_title_choose_country\"> აირჩიეთ თქვენი ქვეყანა </string>\n    <string name=\"server_btn_connect\"> Connect </string>\n    <string name=\"server_btn_disconnect\"> გათიშულია </string>\n    <string name=\"server_txt_ping\"> მაგიდა: </string>\n    <string name=\"server_txt_sessions\"> სესიები: </string>\n    <string name=\"server_txt_speed\"> Speed: </string>\n    <string name=\"server_error_loading_profile\"> ვერ მოხერხდა ნახვა </string>\n    <string name=\"server_txt_status\"> Connection სტატუსი: </string>\n    <string name=\"server_list_more\"> დეტალები </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Loading ... </string>\n    <string name=\"downloading_csv_text\"> Load Server List ... </string>\n    <string name=\"parsing_csv_text\"> დამუშავების სია სერვერები ... </string>\n    <string name=\"csv_file_error\"> პრობლემა მოსმენით ფაილი ... </string>\n    <string name=\"csv_file_error_parsing\"> პრობლემა parsing ფაილი ... </string>\n    <string name=\"network_error\"> ქსელის შეცდომა ... </string>\n    <string name=\"successfully_loaded\"> ჩამოტვირთვა სრული ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-ko/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> 국가를 선택 </string>\n    <string name=\"home_pop_up_title_choose_country\"> 국가를 선택 </string>\n    <string name=\"server_btn_connect\"> 연결 </string>\n    <string name=\"server_btn_disconnect\"> 연결 해제 </string>\n    <string name=\"server_txt_ping\"> 테이블 : </string>\n    <string name=\"server_txt_sessions\"> 세션 : </string>\n    <string name=\"server_txt_speed\"> 속도 : </string>\n    <string name=\"server_error_loading_profile\"> 프로파일을로드하지 못했습니다 </string>\n    <string name=\"server_txt_status\"> 연결 상태 : </string>\n    <string name=\"server_list_more\"> 자세한 사항 </string>\n    <string name=\"mbps\"> Mbps의 </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\">로드 ... </string>\n    <string name=\"downloading_csv_text\">로드 서버 목록 ... </string>\n    <string name=\"parsing_csv_text\"> 서버의 목록을 구문 분석 ... </string>\n    <string name=\"csv_file_error\"> 읽기 파일의 문제 ... </string>\n    <string name=\"csv_file_error_parsing\"> 파일을 구문 분석에 대한 문제 ... </string>\n    <string name=\"network_error\"> 네트워크 오류 ... </string>\n    <string name=\"successfully_loaded\"> 다운로드 완료 ... </string>\n\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-lt/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Pasirinkite savo šalį </string>\n    <string name=\"home_pop_up_title_choose_country\"> Pasirinkite savo šalį </string>\n    <string name=\"server_btn_connect\"> Jungti </string>\n    <string name=\"server_btn_disconnect\"> Baigti </string>\n    <string name=\"server_txt_ping\"> Lentelė: </string>\n    <string name=\"server_txt_sessions\"> posėdžiai </string>\n    <string name=\"server_txt_speed\"> Greitis: </string>\n    <string name=\"server_error_loading_profile\"> Nepavyko įkelti profilį </string>\n    <string name=\"server_txt_status\"> Ryšio Būsena: </string>\n    <string name=\"server_list_more\"> Detalės </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Kraunasi ... </string>\n    <string name=\"downloading_csv_text\"> Apkrovos serveriu ... </string>\n    <string name=\"parsing_csv_text\"> Analizuojant serverių sąrašą ... </string>\n    <string name=\"csv_file_error\"> Problema su skaitymo failo ... </string>\n    <string name=\"csv_file_error_parsing\"> Problema su apdorojant failą ... </string>\n    <string name=\"network_error\"> Tinklo klaida ... </string>\n    <string name=\"successfully_loaded\"> Atsisiųsti baigtas ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-lv/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Izvēlieties savu valsti </string>\n        <string name=\"home_pop_up_title_choose_country\"> Izvēlieties savu valsti </string>\n        <string name=\"server_btn_connect\"> Connect </string>\n        <string name=\"server_btn_disconnect\"> Atvienot </string>\n        <string name=\"server_txt_ping\"> tabula </string>\n        <string name=\"server_txt_sessions\"> Sessions: </string>\n        <string name=\"server_txt_speed\"> Speed: </string>\n        <string name=\"server_error_loading_profile\"> Neizdevās ielādēt anketu </string>\n        <string name=\"server_txt_status\"> Connection Status: </string>\n        <string name=\"server_list_more\"> Detaļas </string>\n        <string name=\"mbps\"> Mbps </string>\n        <string name=\"ms\"> ms </string>\n        <string name=\"loading_text\"> Loading ... </string>\n        <string name=\"downloading_csv_text\"> Load Server saraksts ... </string>\n        <string name=\"parsing_csv_text\"> analizējot sarakstu ar serveriem ... </string>\n        <string name=\"csv_file_error\"> Problēma ar lasīšanas failu ... </string>\n        <string name=\"csv_file_error_parsing\"> Problēma ar analizējot failu ... </string>\n        <string name=\"network_error\"> Tīkla kļūda ... </string>\n        <string name=\"successfully_loaded\"> Download pilnīgs ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-ro/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Selectați țara </string>\n        <string name=\"home_pop_up_title_choose_country\"> Selectați țara </string>\n        <string name=\"server_btn_connect\"> Connect </string>\n        <string name=\"server_btn_disconnect\"> Deconectare </string>\n        <string name=\"server_txt_ping\"> Tabel: </string>\n        <string name=\"server_txt_sessions\"> Sesiuni: </string>\n        <string name=\"server_txt_speed\"> Viteză: </string>\n        <string name=\"server_error_loading_profile\"> Eroare la încărcarea profilului </string>\n        <string name=\"server_txt_status\"> Connection Status: </string>\n        <string name=\"server_list_more\"> Detalii </string>\n        <string name=\"mbps\"> Mbps </string>\n        <string name=\"ms\"> ms </string>\n        <string name=\"loading_text\"> Loading ... </string>\n        <string name=\"downloading_csv_text\"> Load Server List ... </string>\n        <string name=\"parsing_csv_text\"> Analizare o listă de servere ... </string>\n        <string name=\"csv_file_error\"> Problema cu citirea fișierului ... </string>\n        <string name=\"csv_file_error_parsing\"> Problema cu analizarea fișierului ... </string>\n        <string name=\"network_error\"> Eroare de rețea ... </string>\n        <string name=\"successfully_loaded\"> Descărcare complet ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-ru/strings.xml",
    "content": "<resources>\n    <string name=\"action_settings\">Настройки</string>\n    <string name=\"action_about\">О приложении</string>\n    <string name=\"home_btn_choose_country\">Выберите страну</string>\n    <string name=\"home_pop_up_title_choose_country\">Выберите страну</string>\n    <string name=\"server_btn_connect\">Подключить</string>\n    <string name=\"server_btn_disconnect\">Разъединить</string>\n    <string name=\"server_txt_ping\">Пинг:</string>\n    <string name=\"server_txt_sessions\">Сессии:</string>\n    <string name=\"server_txt_speed\">Скорость:</string>\n    <string name=\"server_txt_city\">Город:</string>\n    <string name=\"server_error_loading_profile\">Ошибка загрузки профиля</string>\n    <string name=\"server_txt_status\">Состояние соединения:</string>\n    <string name=\"server_list_more\">Подробнее</string>\n    <string name=\"mbps\">Mbps</string>\n    <string name=\"ms\">ms</string>\n    <string name=\"loading_text\">Загрузка...</string>\n    <string name=\"downloading_csv_text\">Загрузка списка серверов...</string>\n    <string name=\"parsing_csv_text\">Парсинг списка серверов...</string>\n    <string name=\"csv_file_error\">Проблема с чтением файла...</string>\n    <string name=\"csv_file_error_parsing\">Проблема с парсингом файла...</string>\n    <string name=\"network_error\">Ошибка сети...</string>\n    <string name=\"successfully_loaded\">Загрузка завершена...</string>\n    <string name=\"network_error_message\">Интернет подключение отсутствует, подключитесь к сети и попробуйте снова.</string>\n    <string name=\"blocking_ads\">Блокировать рекламу</string>\n    <string name=\"more_servers\">Больше серверов</string>\n    <string name=\"feature_not_available\">Эта функция временно недоступна</string>\n    <string name=\"feature_not_available_without_perm\">Без информации об учетной записи эта функция недоступна</string>\n    <string name=\"unblock\">Купить блокировку рекламы</string>\n    <string name=\"what_is_my_ip\">Какой у меня IP?</string>\n    <string name=\"action_current_connection\">Текущее соединение</string>\n    <string name=\"random_connection\">Быстрое соединение</string>\n    <string name=\"total_servers\">На текщий момент, в локальной базе данных, доступно %1$d серверов</string>\n    <string name=\"loading_additional_servers\">Загрузка дополнительных серверов</string>\n    <string name=\"current_servers_list\">Список текущих серверов</string>\n    <string name=\"you_have_servers\"><b>Вам доступно серверов:</b></string>\n    <string name=\"info_basic\">%1$d базовых</string>\n    <string name=\"info_additional\">%1$d дополнительных</string>\n    <string name=\"connect_on_start\">Подключение на старте</string>\n    <string name=\"connect_on_start_summary\">Подключение при запуске приложения</string>\n    <string name=\"choose_country_priority\">Выберите приоритет страны</string>\n    <string name=\"choose_country_priority_summary\">Если не включена, то использовать соединение с любым сервером</string>\n    <string name=\"choose_country\">Выберите страну</string>\n    <string name=\"error_random_country\">Сервер с приоритетом страны %1$s не доступен</string>\n    <string name=\"success_pop_up_title\"><b>Вы успешно подключены! Что дальше?</b></string>\n    <string name=\"open_playmarket\">Открыть PlayMarket</string>\n    <string name=\"open_browser\">Открыть браузер</string>\n    <string name=\"show_my_desktop\">Показать рабочий стол</string>\n    <string name=\"stay_to_try_something_else\">Остаться в приложении</string>\n    <string name=\"try_another_server_text\">Вы хотите попробовать другой сервер?</string>\n    <string name=\"try_another_server_ok\">Да</string>\n    <string name=\"try_another_server_no\">Нет</string>\n    <string name=\"traffic_in\">Загружено: %1$s</string>\n    <string name=\"traffic_out\">Отправлено: %1$s</string>\n    <string name=\"traffic_totally\"><b>Всего через приложение</b></string>\n    <string name=\"rating_title\"><b>Благодарим Вас за использование Easy VPN Free!</b></string>\n    <string name=\"rating_sure\">Конечно</string>\n    <string name=\"rating_not\">На самом деле, нет</string>\n    <string name=\"rating_text\">Мы пытаемся сделать приложение лучше!\n        \\nВы хотите, чтобы показать свою поддержку,\n        \\nоценить нас?\n    </string>\n    <string name=\"share_text\">\n        Easy VPN Free! Открытый исходный код, без каких либо ограничений!\n        \\nБолее 22 стран для подключения и разблокировка всех заблокированных сайтов.\n        \\n\\nhttps://play.google.com/store/apps/details?id=com.vasilkoff.easyvpnfree\n    </string>\n    <string name=\"automatic_switching\">Автоматическое переключение</string>\n    <string name=\"automatic_switching_category\">Автоматическое переключение</string>\n    <string name=\"automatic_switching_set_seconds\">Установка секунд</string>\n    <string name=\"automatic_switching_summary\">Автоматическое переключение на сервер из той же страны через несколько секунд,\n        если текущее подключение невозможно\n    </string>\n    <string name=\"choose_country_priority_category\">Приоритет страны</string>\n    <string name=\"connect_on_start_category\">Подключение на старте</string>\n    <string name=\"bookmarks\">Закладки</string>\n    <string name=\"bookmark_delete\">Удалить</string>\n    <string name=\"note_title\"><b>Заметка</b></string>\n    <string name=\"note_text\">Cписок серверов, которые вы найдете в этом приложении\n        от VPNGate и обеспечиваются <b>добровольцами по всему миру</b>.\n    </string>\n    <string name=\"note_link\">\\nВы можете предоставить свой собственный компьютер в качестве сервера VPN,\n        чтобы присоединиться к этому эксперименту.</string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-sk/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Vyberte svoju krajinu </string>\n    <string name=\"home_pop_up_title_choose_country\"> Vyberte svoju krajinu </string>\n    <string name=\"server_btn_connect\"> Pripojiť </string>\n    <string name=\"server_btn_disconnect\"> Odpojiť </string>\n    <string name=\"server_txt_ping\"> Tabuľka: </string>\n    <string name=\"server_txt_sessions\">  Sessions: </string>\n    <string name=\"server_txt_speed\"> Speed: </string>\n    <string name=\"server_error_loading_profile\"> Nepodarilo sa načítať profil </string>\n    <string name=\"server_txt_status\"> Connection Status: </string>\n    <string name=\"server_list_more\"> Podrobnosti </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> MS </string>\n    <string name=\"loading_text\"> Loading ... </string>\n    <string name=\"downloading_csv_text\"> Zoznam zaťaženie serverov ... </string>\n    <string name=\"parsing_csv_text\"> Rozobrať zoznam serverov ... </string>\n    <string name=\"csv_file_error\"> Problém s pri čítaní súboru ... </string>\n    <string name=\"csv_file_error_parsing\"> Problém s analýze súboru ... </string>\n    <string name=\"network_error\"> Chyba siete ... </string>\n    <string name=\"successfully_loaded\"> Na stiahnutie kompletné ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-sl/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Izberite državo </string>\n    <string name=\"home_pop_up_title_choose_country\"> Izberite državo </string>\n    <string name=\"server_btn_connect\"> Poveži </string>\n    <string name=\"server_btn_disconnect\"> Prekini </string>\n    <string name=\"server_txt_ping\"> Tabela: </string>\n    <string name=\"server_txt_sessions\"> Sessions: </string>\n    <string name=\"server_txt_speed\"> Hitrost: </string>\n    <string name=\"server_error_loading_profile\"> Napaka pri nalaganju profila </string>\n    <string name=\"server_txt_status\"> Stanje povezave: </string>\n    <string name=\"server_list_more\"> Podrobnosti </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Nalaganje ... </string>\n    <string name=\"downloading_csv_text\"> Rokovanje Seznam Server ... </string>\n    <string name=\"parsing_csv_text\"> RazÄŤlenjevanje seznam strežnikov ... </string>\n    <string name=\"csv_file_error\"> Problem pri branje datoteke ... </string>\n    <string name=\"csv_file_error_parsing\"> Problem pri razčlenjevanju datoteke ... </string>\n    <string name=\"network_error\"> Napaka omrežja ... </string>\n    <string name=\"successfully_loaded\"> Download popoln ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-sr/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\">Изаберите своју земљу</string>\n    <string name=\"home_pop_up_title_choose_country\">Изаберите своју земљу</string>\n    <string name=\"server_btn_connect\">Повежи</string>\n    <string name=\"server_btn_disconnect\">Ацтион</string>\n    <string name=\"server_txt_ping\">Табела:</string>\n    <string name=\"server_txt_sessions\">Сессионс:</string>\n    <string name=\"server_txt_speed\">Брзина:</string>\n    <string name=\"server_error_loading_profile\">Фаилед то лоад профил</string>\n    <string name=\"server_txt_status\">Статус везе:</string>\n    <string name=\"server_list_more\">Детаљи</string>\n    <string name=\"mbps\">Мбит</string>\n    <string name=\"ms\">ms</string>\n    <string name=\"loading_text\">Учитавање...</string>\n    <string name=\"downloading_csv_text\">Tерета Сервер Лист...</string>\n    <string name=\"parsing_csv_text\">Рашчлањивање списак серверa...</string>\n    <string name=\"csv_file_error\">Проблем са читањем филе...</string>\n    <string name=\"csv_file_error_parsing\">Проблем са парсирања фајл...</string>\n    <string name=\"network_error\">Грешка мреже...</string>\n    <string name=\"successfully_loaded\">Преузмите комплетан...</string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-sv/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> Välj ditt land </string>\n    <string name=\"home_pop_up_title_choose_country\"> Välj ditt land </string>\n    <string name=\"server_btn_connect\"> Anslut </string>\n    <string name=\"server_btn_disconnect\"> Koppla </string>\n    <string name=\"server_txt_ping\"> Tabell: </string>\n    <string name=\"server_txt_sessions\"> Sessions: </string>\n    <string name=\"server_txt_speed\"> Hastighet: </string>\n    <string name=\"server_error_loading_profile\"> Det gick inte att läsa in profilen </string>\n    <string name=\"server_txt_status\"> Anslutningsstatus: </string>\n    <string name=\"server_list_more\"> Detaljer </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> Loading ... </string>\n    <string name=\"downloading_csv_text\"> Ladda serverlista ... </string>\n    <string name=\"parsing_csv_text\"> Analysera en lista över servrar ... </string>\n    <string name=\"csv_file_error\"> Problemet med läsning fil ... </string>\n    <string name=\"csv_file_error_parsing\"> Problemet med tolkning av fil ... </string>\n    <string name=\"network_error\"> Nätverks fel ... </string>\n    <string name=\"successfully_loaded\"> Hämta komplett ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-th/strings.xml",
    "content": "<resources>\n    <string name=\"home_btn_choose_country\"> เลือกประเทศของคุณ </string>\n    <string name=\"home_pop_up_title_choose_country\"> เลือกประเทศของคุณ </string>\n    <string name=\"server_btn_connect\"> เชื่อมต่อ </string>\n    <string name=\"server_btn_disconnect\"> ยกเลิกการเชื่อมต่อ </string>\n    <string name=\"server_txt_ping\"> ตาราง: </string>\n    <string name=\"server_txt_sessions\"> Sessions: </string>\n    <string name=\"server_txt_speed\"> ความเร็ว: </string>\n    <string name=\"server_error_loading_profile\"> ไม่สามารถโหลดรายละเอียด </string>\n    <string name=\"server_txt_status\"> สถานะการเชื่อมต่อ: </string>\n    <string name=\"server_list_more\"> รายละเอียด </string>\n    <string name=\"mbps\"> Mbps </string>\n    <string name=\"ms\"> ms </string>\n    <string name=\"loading_text\"> โหลด ... </string>\n    <string name=\"downloading_csv_text\"> รายชื่อเซิร์ฟเวอร์โหลด ... </string>\n    <string name=\"parsing_csv_text\"> แยกรายชื่อของเซิร์ฟเวอร์ ... </string>\n    <string name=\"csv_file_error\"> ปัญหากับการอ่านไฟล์ The ... </string>\n    <string name=\"csv_file_error_parsing\"> ปัญหาเกี่ยวกับการแยกไฟล์ที่ ... </string>\n    <string name=\"network_error\"> ข้อผิดพลาดเครือข่าย ... </string>\n    <string name=\"successfully_loaded\"> ดาวน์โหลดเสร็จสมบูรณ์ ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-tr/strings.xml",
    "content": "<resources>\n    <string name = \"home_btn_choose_country\"> Ülkenizi seçin </string>\n    <string name = \"home_pop_up_title_choose_country\"> Ülkenizi seçin </string>\n    <string name = \"server_btn_connect\"> Bağlan </string>\n    <string name = \"server_btn_disconnect\"> Bağlantıyı kes </string>\n    <string name = \"server_txt_ping\"> Tablo: </string>\n    <string name = \"server_txt_sessions\"> Oturumlar: </string>\n    <string name = \"server_txt_speed\"> Hız: </string>\n    <string name = \"server_error_loading_profile\"> profili yüklenemedi </string>\n    <string name = \"server_txt_status\"> Bağlantı Durumu: </string>\n    <string name = \"server_list_more\"> Detaylar </string>\n    <string name = \"mbps\"> Mbps </string>\n    <string name = \"ms\"> ms </string>\n    <string name = \"loading_text\"> Yükleniyor ... </string>\n    <string name = \"downloading_csv_text\"> Load Sunucu Listesi ... </string>\n    <string name = \"parsing_csv_text\"> sunucularının listesini ayrıştırılıyor ... </string>\n    <string name = \"csv_file_error\"> okuma dosyası ile sorun ... </string>\n    <string name = \"csv_file_error_parsing\"> dosyasını ayrıştırma sorun ... </string>\n    <string name = \"network_error\"> Ağ hatası ... </string>\n    <string name = \"successfully_loaded\"> İndirme tamamlandı ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-uk/strings.xml",
    "content": "<resources>\n    <string name=\"action_settings\">Налаштування</string>\n    <string name=\"action_about\">Про додаток</string>\n    <string name=\"home_btn_choose_country\">Виберіть країну</string>\n    <string name=\"home_pop_up_title_choose_country\">Виберіть країну</string>\n    <string name=\"server_btn_connect\">Підключити</string>\n    <string name=\"server_btn_disconnect\">Відключити</string>\n    <string name=\"server_txt_ping\">Пінг:</string>\n    <string name=\"server_txt_sessions\">Сесії:</string>\n    <string name=\"server_txt_speed\">Швидкість:</string>\n    <string name=\"server_txt_city\">Місто:</string>\n    <string name=\"server_error_loading_profile\">Помилка завантаження профілю</string>\n    <string name=\"server_txt_status\">Статус з\\'єднання:</string>\n    <string name=\"server_list_more\">Детальніше</string>\n    <string name=\"mbps\">Mbps</string>\n    <string name=\"ms\">ms</string>\n    <string name=\"loading_text\">Завантаження...</string>\n    <string name=\"downloading_csv_text\">Завантаження списка серверів...</string>\n    <string name=\"parsing_csv_text\">Парсинг списка серверів...</string>\n    <string name=\"csv_file_error\">Проблема з зчитуванням файла...</string>\n    <string name=\"csv_file_error_parsing\">Проблема з парсингом файла...</string>\n    <string name=\"network_error\">Помилка мережі...</string>\n    <string name=\"successfully_loaded\">Завантаження завершене...</string>\n    <string name=\"network_error_message\">Інтернет недоступний, підключіться до мережі та спробуйте ще раз.</string>\n    <string name=\"blocking_ads\">Фільтрування реклами</string>\n    <string name=\"more_servers\">Більше серверів</string>\n    <string name=\"feature_not_available\">Ця функція тимчасово недоступна</string>\n    <string name=\"feature_not_available_without_perm\">Без інформіції про обліковий запис ця функція недоступна</string>\n    <string name=\"unblock\">Придбати фільтрування реклами</string>\n    <string name=\"what_is_my_ip\">Який мій IP?</string>\n    <string name=\"action_current_connection\">Поточне з\\'єднання</string>\n    <string name=\"random_connection\">Швидке з\\'єднання</string>\n    <string name=\"total_servers\">На даний момент, в локальній базі даних, доступно %1$d серверів</string>\n    <string name=\"loading_additional_servers\">Завантаження додаткових серверів</string>\n    <string name=\"current_servers_list\">Поточний список серверів</string>\n    <string name=\"you_have_servers\"><b>Вам доступно серверів:</b></string>\n    <string name=\"info_basic\">%1$d базових</string>\n    <string name=\"info_additional\">%1$d додаткових</string>\n    <string name=\"connect_on_start\">Підключення на старті</string>\n    <string name=\"connect_on_start_summary\">Підключенння при запуску додатку</string>\n    <string name=\"choose_country_priority\">Виберіть пріоритет країни</string>\n    <string name=\"choose_country_priority_summary\">Якщо не включена, то використовувати випадкове з\\'єднання</string>\n    <string name=\"choose_country\">Виберіть країну</string>\n    <string name=\"error_random_country\">Сервер с пріоритетом країни %1$s не доступний</string>\n    <string name=\"success_pop_up_title\"><b>Ви успішно підключені! Давайте спробуємо це?</b></string>\n    <string name=\"open_playmarket\">Відкрить PlayMarket</string>\n    <string name=\"open_browser\">Відкрить браузер</string>\n    <string name=\"show_my_desktop\">Показати ваш рабочий стіл</string>\n    <string name=\"stay_to_try_something_else\">Спробувати щось інше</string>\n    <string name=\"try_another_server_text\">Ви хочете спробувати інший сервер?</string>\n    <string name=\"try_another_server_ok\">Так</string>\n    <string name=\"try_another_server_no\">Ні</string>\n    <string name=\"traffic_in\">Завантажено: %1$s</string>\n    <string name=\"traffic_out\">Відправлено: %1$s</string>\n    <string name=\"traffic_totally\"><b>Всього через додаток</b></string>\n    <string name=\"rating_title\"><b>Дякуємо Вам за використання Easy VPN Free!</b></string>\n    <string name=\"rating_sure\">Звичайно</string>\n    <string name=\"rating_not\">На справді, ні</string>\n    <string name=\"rating_text\">Ми намагаємося зробити додаток краще!\n        \\nВи хочете, щоб показати свою підтримку,\n        \\nоцінить нас?\n    </string>\n    <string name=\"share_text\">\n        Easy VPN Free! Відкритий вихідний код, без обмежень і 100% безкоштовний!\n        \\nБільше ніж 22 країни для піключення і розблокування всіх заблокований сайтів.\n        \\n\\nhttps://play.google.com/store/apps/details?id=com.vasilkoff.easyvpnfree\n    </string>\n    <string name=\"automatic_switching\">Автоматичне переключання</string>\n    <string name=\"automatic_switching_category\">Автоматичне переключання</string>\n    <string name=\"automatic_switching_set_seconds\">Установка секунд</string>\n    <string name=\"automatic_switching_summary\">Автоматичне переключення на сервер із тої ж країни через декілька секунд,\n        якщо поточне піключення неможливе\n    </string>\n    <string name=\"choose_country_priority_category\">Пріорітет країни</string>\n    <string name=\"connect_on_start_category\">Підключення на старті</string>\n    <string name=\"bookmarks\">Закладки</string>\n    <string name=\"bookmark_delete\">Видалити</string>\n    <string name=\"note_title\"><b>Примітка</b></string>\n    <string name=\"note_text\">Список серверів, які ви знайдете в цьому додатку,\n        від VPNGate і забезпечуються <b>добровольцями по всьому світу</b>.\n    </string>\n    <string name=\"note_link\">\\nВи можете надати свій власний комп\\'ютер в якості сервера VPN,\n        щоб приєднатися до цього експерименту</string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-v21/reference.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <drawable name=\"ic_menu_close_clear_cancel\">@drawable/ic_close_white_24dp</drawable>\n    <drawable name=\"ic_menu_play\">@drawable/ic_play_arrow_white_24dp</drawable>\n    <drawable name=\"ic_menu_pause\">@drawable/ic_pause_white_24dp</drawable>\n</resources>"
  },
  {
    "path": "Android-code/app/src/main/res/values-v21/styles.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-vi/strings.xml",
    "content": "<resources>\n    <string name = \"home_btn_choose_country\"> Chọn quốc gia của bạn </string>\n    <string name = \"home_pop_up_title_choose_country\"> Chọn quốc gia của bạn </string>\n    <string name = \"server_btn_connect\"> Kết nối </string>\n    <string name = \"server_btn_disconnect\"> Ngắt kết nối </string>\n    <string name = \"server_txt_ping\"> Bảng: </string>\n    <string name = \"server_txt_sessions\"> Sessions: </string>\n    <string name = \"server_txt_speed\"> Tốc độ: </string>\n    <string name = \"server_error_loading_profile\"> Không thể tải tiểu </string>\n    <string name = \"server_txt_status\"> Connection Status: </string>\n    <string name = \"server_list_more\"> Chi tiết </string>\n    <string name = \"mbps\"> Mbps </string>\n    <string name = \"ms\"> ms </string>\n    <string name = \"loading_text\"> Loading ... </string>\n    <string name = \"downloading_csv_text\"> Load Danh sách Server ... </string>\n    <string name = \"parsing_csv_text\"> Phân tích một danh sách các máy chủ ... </string>\n    <string name = \"csv_file_error\"> Vấn đề với tập đọc ... </string>\n    <string name = \"csv_file_error_parsing\"> Vấn đề với phân tích các tập tin ... </string>\n    <string name = \"network_error\"> Lỗi mạng ... </string>\n    <string name = \"successfully_loaded\"> Download hoàn chỉnh ... </string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/values-zh/strings.xml",
    "content": "<resources>\n      <string name=\"home_btn_choose_country\">选择您所在的国家</string>\n      <string name=\"home_pop_up_title_choose_country\">选择您所在的国家</string>\n      <string name=\"server_btn_connect\">连接</string>\n      <string name=\"server_btn_disconnect\">断开连接</string>\n      <string name=\"server_txt_ping\">表：</string>\n      <string name=\"server_txt_sessions\">会话：</string>\n      <string name=\"server_txt_speed\">速度：</string>\n      <string name=\"server_error_loading_profile\">无法加载个人资料</string>\n      <string name=\"server_txt_status\">连接状态：</string>\n      <string name=\"server_list_more\">详细信息</string>\n      <string name=\"mbps\"> Mbps</string>\n      <string name=\"ms\">毫秒</string>\n      <string name=\"loading_text\">加载...</string>\n      <string name=\"downloading_csv_text\">加载服务器列表...</string>\n      <string name=\"parsing_csv_text\">解析服务器的列表...</string>\n      <string name=\"csv_file_error\">伴读文件的问题...</string>\n      <string name=\"csv_file_error_parsing\">与解析文件的问题...</string>\n      <string name=\"network_error\">网络错误...</string>\n      <string name=\"successfully_loaded\">下载完成...</string>\n</resources>\n"
  },
  {
    "path": "Android-code/app/src/main/res/xml/preferences.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PreferenceScreen xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <PreferenceCategory\n        android:title=\"@string/automatic_switching_category\">\n        <CheckBoxPreference\n            android:title=\"@string/automatic_switching\"\n            android:defaultValue=\"true\"\n            android:summary=\"@string/automatic_switching_summary\"\n            android:key=\"automaticSwitching\"/>\n        <com.vasilkoff.easyvpnfree.util.NumberPickerPreference\n            android:dependency=\"automaticSwitching\"\n            android:key=\"automaticSwitchingSeconds\"\n            android:title=\"@string/automatic_switching_set_seconds\"\n            android:defaultValue=\"40\" />\n    </PreferenceCategory>\n    <PreferenceCategory\n        android:title=\"@string/connect_on_start_category\">\n        <CheckBoxPreference\n            android:title=\"@string/connect_on_start\"\n            android:defaultValue=\"false\"\n            android:summary=\"@string/connect_on_start_summary\"\n            android:key=\"connectOnStart\"/>\n    </PreferenceCategory>\n    <PreferenceCategory\n        android:key=\"countryPriorityCategory\"\n        android:title=\"@string/choose_country_priority_category\">\n        <CheckBoxPreference\n            android:title=\"@string/choose_country_priority\"\n            android:defaultValue=\"false\"\n            android:summary=\"@string/choose_country_priority_summary\"\n            android:key=\"countryPriority\"/>\n        <ListPreference\n            android:dependency=\"countryPriority\"\n            android:title=\"@string/choose_country\"\n            android:key=\"selectedCountry\"/>\n    </PreferenceCategory>\n</PreferenceScreen>"
  },
  {
    "path": "Android-code/app/src/pro/google-services.json",
    "content": "{\n  \"project_info\": {\n    \"project_number\": \"101174069905\",\n    \"project_id\": \"easy-vpn-155109\"\n  },\n  \"client\": [\n    {\n      \"client_info\": {\n        \"mobilesdk_app_id\": \"1:101174069905:android:21f96f0f8331f35b\",\n        \"android_client_info\": {\n          \"package_name\": \"com.vasilkoff.easyvpn\"\n        }\n      },\n      \"oauth_client\": [],\n      \"api_key\": [\n        {\n          \"current_key\": \"AIzaSyCMvXrN4gEs77cBnrMZdIsW-rq6mT-gkUc\"\n        }\n      ],\n      \"services\": {\n        \"analytics_service\": {\n          \"status\": 2,\n          \"analytics_property\": {\n            \"tracking_id\": \"UA-89641705-1\"\n          }\n        },\n        \"appinvite_service\": {\n          \"status\": 1,\n          \"other_platform_oauth_client\": []\n        },\n        \"ads_service\": {\n          \"status\": 1\n        }\n      }\n    }\n  ],\n  \"configuration_version\": \"1\"\n}"
  },
  {
    "path": "Android-code/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.2.3'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "Android-code/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Sep 29 11:04:28 EEST 2016\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.14.1-all.zip\n"
  },
  {
    "path": "Android-code/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true"
  },
  {
    "path": "Android-code/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "Android-code/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "Android-code/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "# Easy VPN Free\n----\n## Introduction\n\nAndroid application which lets you easily to connect to a number of free VPN server around the world with just a single tap!\n\nThe list of servers the application connect is http://www.vpngate.net/\n**VPN Gate Academic Experiment Project** is an online service as an academic research at Graduate School of University of Tsukuba, Japan. The purpose of this research is to expand the knowledge of \"Global Distributed Public VPN Relay Servers\".\n\n----\n###Demo\n\n![Easy VPN Free](https://github.com/MaxSmile/EasyVPN-Free/blob/master/easy-vpn-free.gif?raw=true)\n\n\n----\n## Installation\nThe app is available оn Goole's Play Market\n[![Easy VPN Free Play Market](https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png)](https://play.google.com/store/apps/details?id=com.vasilkoff.easyvpnfree)\n\n\n BUT If it is not available in your country (somehow...) you also can always find compiled binaries here https://github.com/MaxSmile/EasyVPN-Free/tree/master/binary all the versions\n\n----\n## Why VPN Gate?\n\nYou can take these advantages by using VPN Gate:\n* It is about 8531 Public VPN Relay Servers by volunteers around the world.\n* You can disguise your IP address to hide your identity while surfing the Internet.\n* You can protect yourself by utilizing its strong encryption while using public Wi-Fi.\nUnlike traditional VPN services, VPN Gate can get through most firewalls.\nVPN Gate is free of charge. Not a single registration is required.\n\n----\n## License\n**Free Software!**\n\nhttps://github.com/MaxSmile/EasyVPN-Free/blob/master/LICENSE\n\n[//]: # (https://www.gnu.org/licenses/gpl-3.0.en.html)\n\nThis application uses the following components; see the source code for full details on the licenses.\n\n* OpenVPN for Android https://github.com/schwabe/ics-openvpn under GPLv2\n* NumberProgressBar https://github.com/daimajia/NumberProgressBar under MIT\n* Fast-Android-Networking https://github.com/amitshekhariitbhu/Fast-Android-Networking under Apache 2.0\n\n----\n## You can help\n\nEven if you are not a programmer you can help by translating the Easy VPN Free client into your native language.\n\n----\n## In-App purchases\n\nThe app does not have any ads. And now more. I added ads filtering function.\nIt has 7 days trial and if you like it, you buy it. Should you support the project somehow, correct? :)\n"
  }
]