1#!/usr/local/bin/bash 2# 3# Simple shell script to update IP2Location database files 4# 5# For updating non-sample files, credentials are or token is required: 6# provided by file $HOME/.ip2location 7# credential-based authentication: 8# login=EMAIL 9# password=PASSWORD 10# token-based authentication: 11# token=TOKEN 12# 13# Project : ipv6calc/IP2Location 14# File : IP2Location-update.sh 15# Version : $Id: 51d432e406fc84c7f196a92c9037e730e1172131 $ 16# Copyright : 2012-2021 by Peter Bieringer <pb (at) bieringer.de> 17# License : GNU GPL version 2 18 19# 20150416: remove softlink support, no longer needed 20# 20210528: add support for 'token' 21 22IP2LOCATION_CONFIG=${IP2LOCATION_CONFIG:-"$HOME/.ip2location"} 23 24IP2LOCATION_DAT_DIR_DEFAULT="@IP2LOCATION_DB@" 25[ -z "$IP2LOCATION_DAT_DIR" -a -n "$IPV6CALC_DB_IP2LOCATION_DIR" ] && IP2LOCATION_DAT_DIR="$IPV6CALC_DB_IP2LOCATION_DIR" 26[ -z "$IP2LOCATION_DAT_DIR" ] && IP2LOCATION_DAT_DIR="$IP2LOCATION_DAT_DIR_DEFAULT" 27 28IP2LOCATION_DAT_URL_BASE="https://www.ip2location.com/download?login=@LOGIN@&password=@PASSWORD@&token=@TOKEN@" 29IP2LOCATION_DAT_URL_BASE_SAMPLE="https://www.ip2location.com/downloads" 30IP2LOCATION_DAT_URL_BASE_LITE_FREE="https://download.ip2location.com/lite" 31 32# Format: Proto:DB-Number 33 34# free downloads 35IP2LOCATION_DAT_FILES_LITE_FREE=${IP2LOCATION_DAT_FILES_LITE_FREE:-"IPv4:1 IPv6:1"} 36 37# (free) subscription is required for LITE DB-Number > 1 38IP2LOCATION_DAT_FILES_LITE=${IP2LOCATION_DAT_FILES_LITE:-"IPv4:11 IPv6:11"} 39 40# list of normal (purchased subscription required) 41IP2LOCATION_DAT_FILES="${IP2LOCATION_DAT_FILES}" 42 43# list of recommended SAMPLE 44IP2LOCATION_DAT_FILES_SAMPLE=${IP2LOCATION_DAT_FILES_SAMPLE:-"IPv4:20 IPv6:20 IPv4:24 IPv6:24"} 45 46 47help() { 48 cat <<END 49Usage: $(basename "$0") [-D <dir>] [-n] [-s] [-t] [-v] 50 -D <dir> database destination directory (optional) 51 -n no action (dry-run) 52 -s skip already successfully downloaded files 53 -t enforce use of 'token' instead of using 'login' & 'password' 54 -v verbose 55 56 database directory: $IP2LOCATION_DAT_DIR (default: $IP2LOCATION_DAT_DIR_DEFAULT) 57 58 it honors externally defined environment value: 59 prio 1: IP2LOCATION_DAT_DIR 60 prio 2: IPV6CALC_DB_IP2LOCATION_DIR 61 62 this script will download data from ip2location.com 63 into given/set database directory 64 65 Sample databases: 66 IP2LOCATION_DAT_FILES_SAMPLE=$IP2LOCATION_DAT_FILES_SAMPLE 67 68 Lite (free) databases: 69 IP2LOCATION_DAT_FILES_LITE_FREE=$IP2LOCATION_DAT_FILES_LITE_FREE 70 71 With authentication (requires login/password or token in $IP2LOCATION_CONFIG) and a valid subscription 72 IP2LOCATION_DAT_FILES_LITE=$IP2LOCATION_DAT_FILES_LITE 73 IP2LOCATION_DAT_FILES=$IP2LOCATION_DAT_FILES 74 75 Credentials or token must be defined in \$HOME/.ip2location by 76 login=IP2LOCATION-LOGIN ${login:+found: ${login:0:2}...} 77 password=IP2LOCATION-PASSWORD ${password:+found: ${password:0:2}...} 78 token=IP2LOCATION-TOKEN ${token:+found: ${token:0:2}...} 79 80 In addition settings from above can be overwritten by setting related variables 81END 82} 83 84# source credentials (must provide login= and password= or token=) 85authenticated=false 86has_token=false 87has_credentials=false 88verbose=false 89 90if [ -f "$IP2LOCATION_CONFIG" ]; then 91 source "$IP2LOCATION_CONFIG" || exit 1 92 93 if [ -n "${token}" ]; then 94 has_token=true 95 authenticated=true 96 echo "INFO : found token in: $IP2LOCATION_CONFIG (for authenticated downloads)" 97 fi 98 99 if [ -n "${login}" -a -n "${password}" ]; then 100 has_credentials=true 101 authenticated=true 102 echo "INFO : found credentials in: $IP2LOCATION_CONFIG (for authenticated downloads)" 103 fi 104 105 if ! $authenticated; then 106 echo "NOTICE: missing credentials/token in: $IP2LOCATION_CONFIG (skip authenticated downloads)" 107 fi 108fi 109 110# option parsing 111while getopts "vfsntD:h\?" opt; do 112 case $opt in 113 D) 114 IP2LOCATION_DAT_DIR=$OPTARG 115 ;; 116 n) 117 NO_ACTION=1 118 ;; 119 s) 120 SKIP_OK=1 121 ;; 122 t) 123 has_credentials=false 124 ;; 125 v) 126 verbose=true 127 ;; 128 *) 129 help 130 exit 1 131 ;; 132 esac 133done 134 135 136# directory check 137if [ ! -d "$IP2LOCATION_DAT_DIR" ]; then 138 echo "ERROR : missing directory: $IP2LOCATION_DAT_DIR (check option -D or set IP2LOCATION_DAT_DIR)" 139 exit 1 140fi 141 142if [ ! -w "$IP2LOCATION_DAT_DIR" ]; then 143 echo "ERROR : missing write permissions on directory: $IP2LOCATION_DAT_DIR" 144 exit 1 145fi 146 147# required binary check 148if ! which unzip >/dev/null 2>&1; then 149 echo "ERROR : missing binary: unzip" 150 exit 1 151fi 152 153if ! $authenticated; then 154 echo "NOTICE: IP2Location credentials/token not found, clear IP2LOCATION_DAT_FILES" 155 IP2LOCATION_DAT_FILES="" 156 157 echo "NOTICE: IP2Location credentials/token not found, clear IP2LOCATION_DAT_FILES_LITE" 158 IP2LOCATION_DAT_FILES_LITE="" 159fi 160 161if $has_credentials; then 162 # replace placeholders 163 IP2LOCATION_DAT_URL_BASE=${IP2LOCATION_DAT_URL_BASE//@LOGIN@/$login} 164 IP2LOCATION_DAT_URL_BASE=${IP2LOCATION_DAT_URL_BASE//@PASSWORD@/$password} 165 # clear token parameter 166 IP2LOCATION_DAT_URL_BASE=${IP2LOCATION_DAT_URL_BASE//@TOKEN@/} 167fi 168 169if $has_token; then 170 # replace placeholders 171 IP2LOCATION_DAT_URL_BASE=${IP2LOCATION_DAT_URL_BASE//@TOKEN@/$token} 172 # clear credential parameters 173 IP2LOCATION_DAT_URL_BASE=${IP2LOCATION_DAT_URL_BASE//@LOGIN@/} 174 IP2LOCATION_DAT_URL_BASE=${IP2LOCATION_DAT_URL_BASE//@PASSWORD@/} 175fi 176 177# Download and unpack non-sample files 178for list in IP2LOCATION_DAT_FILES_LITE IP2LOCATION_DAT_FILES IP2LOCATION_DAT_FILES_LITE_FREE IP2LOCATION_DAT_FILES_SAMPLE; do 179 if [ -z "${!list}" ]; then 180 echo "NOTICE: empty list, skip: $list" 181 continue 182 fi 183 184 $verbose && echo "INFO : download list $list: ${!list}" 185 186 url_base="$IP2LOCATION_DAT_URL_BASE" 187 188 case $list in 189 *_LITE|*_LITE_FREE) 190 code_suffix="LITEBIN" 191 file_prefix="IP2LOCATION-LITE" 192 193 case $list in 194 *_LITE_FREE) 195 url_base="$IP2LOCATION_DAT_URL_BASE_LITE_FREE" 196 ;; 197 esac 198 ;; 199 *_SAMPLE) 200 url_base="$IP2LOCATION_DAT_URL_BASE_SAMPLE" 201 ;; 202 *) 203 code_suffix="BIN" 204 file_prefix="IP2LOCATION" 205 ;; 206 esac 207 208 file_dest="$IP2LOCATION_DAT_DIR/$file" 209 210 if [ "${!list}" = "skip" ]; then 211 echo "NOTICE: skip list (by keyword 'skip'): $list" 212 continue 213 fi 214 215 for item in ${!list}; do 216 proto=${item/:*} 217 number=${item/*:} 218 219 case $list in 220 *_SAMPLE) 221 case $proto in 222 IPv4) 223 protoitem="" 224 ;; 225 IPv6) 226 protoitem="6" 227 ;; 228 *) 229 echo "ERROR : unsupported 'proto' in item: $item" 230 exit 1 231 ;; 232 esac 233 234 file="sample${protoitem}.bin.db${number}.zip" 235 ;; 236 *) 237 case $proto in 238 IPv4) 239 code="DB${number}${code_suffix}" 240 file="${file_prefix}-DB${number}.BIN.ZIP" 241 ;; 242 IPv6) 243 code="DB${number}${code_suffix}IPV6" 244 file="${file_prefix}-DB${number}.IPV6.BIN.ZIP" 245 ;; 246 *) 247 echo "ERROR : unsupported 'proto' in item: $item" 248 exit 1 249 ;; 250 esac 251 252 ;; 253 esac 254 255 case $list in 256 *_SAMPLE|*_LITE_FREE) 257 url="$url_base/$file" 258 ;; 259 *) 260 url="$url_base&productcode=$code" 261 ;; 262 esac 263 264 file_dest="$IP2LOCATION_DAT_DIR/$file" 265 266 if [ "$NO_ACTION" = "1" ]; then 267 if $has_credentials; then 268 echo "NOTICE: download skipped by option: ${url/password=*&/password=**PASS**&} ($file_dest)" 269 continue 270 fi 271 if $has_token; then 272 echo "NOTICE: download skipped by option: ${url/token=*&/token=**TOK**&} ($file_dest)" 273 continue 274 fi 275 fi 276 277 if [ "$SKIP_OK" = "1" ]; then 278 if file "$file_dest" | grep -q "Zip archive data"; then 279 echo "NOTICE: download skipped by option because file already existing and is a ZIP file: $code ($file_dest)" 280 281 file_unzip=$(unzip -l "$file_dest" '*.BIN' | grep "\.BIN$" | awk '{ print $NF }' | head -1) 282 283 if [ -n "$file_unzip" ]; then 284 if [ ! -f "$IP2LOCATION_DAT_DIR/$file_unzip" ]; then 285 unzip -o -d "$IP2LOCATION_DAT_DIR" "$file_dest" '*.BIN' 286 if [ $? -ne 0 ]; then 287 echo "ERROR : unzip of file not successful: $file_dest" 288 continue 289 else 290 echo "INFO : unzip of file successful: $file_dest" 291 fi 292 else 293 echo "INFO : skip unzip because unzipped file already existing: $code ($file_dest)" 294 fi 295 fi 296 continue 297 fi 298 fi 299 300 if $has_credentials; then 301 $verbose && echo "INFO : try to download URL: ${url/password=*&/password=**PASS**&} ($file_dest)" 302 fi 303 if $has_token; then 304 $verbose && echo "INFO : try to download URL: ${url/token=*&/token=**TOK**&} ($file_dest)" 305 fi 306 307 wget -q -O "$file_dest" "$url" 308 result=$? 309 310 if [ $result -ne 0 ]; then 311 echo "ERROR : download of file not successful: $file_dest ($!)" 312 continue 313 fi 314 $verbose && echo "INFO : download of file successful: $file_dest" 315 316 if [ ! -s "$file_dest" ]; then 317 echo "ERROR : downloaded file has ZERO size: $file_dest" 318 continue 319 fi 320 321 if ! file "$file_dest" | grep -q "Zip archive data"; then 322 if file "$file_dest" | grep -q "ASCII text"; then 323 echo "ERROR : downloaded file is not a ZIP archive: $file_dest ($(head -1 "$file_dest"))" 324 else 325 echo "ERROR : downloaded file is not a ZIP archive: $file_dest" 326 fi 327 continue 328 fi 329 330 unzip -o -d "$IP2LOCATION_DAT_DIR" "$file_dest" '*.BIN' 331 if [ $? -ne 0 ]; then 332 echo "ERROR : unzip of file not successful: $file_dest" 333 continue 334 fi 335 $verbose && echo "INFO : unzip of file successful: $file_dest (remove downloaded file now)" 336 rm -f "$file_dest" 337 338 echo "NOTICE: download/unzip successful: $item" 339 done 340done 341 342# Adjust permissions 343if [ "$NO_ACTION" != "1" ]; then 344 chmod 644 $IP2LOCATION_DAT_DIR/*.BIN 345fi 346