1#!/usr/bin/env python 2 3""" 4Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/) 5See the file 'LICENSE' for copying permission 6""" 7 8import glob 9import os 10import re 11import shutil 12import subprocess 13import time 14import zipfile 15 16from lib.core.common import dataToStdout 17from lib.core.common import getLatestRevision 18from lib.core.common import getSafeExString 19from lib.core.common import openFile 20from lib.core.common import pollProcess 21from lib.core.common import readInput 22from lib.core.convert import getText 23from lib.core.data import conf 24from lib.core.data import logger 25from lib.core.data import paths 26from lib.core.revision import getRevisionNumber 27from lib.core.settings import GIT_REPOSITORY 28from lib.core.settings import IS_WIN 29from lib.core.settings import VERSION 30from lib.core.settings import ZIPBALL_PAGE 31from thirdparty.six.moves import urllib as _urllib 32 33def update(): 34 if not conf.updateAll: 35 return 36 37 success = False 38 39 if not os.path.exists(os.path.join(paths.SQLMAP_ROOT_PATH, ".git")): 40 warnMsg = "not a git repository. It is recommended to clone the 'sqlmapproject/sqlmap' repository " 41 warnMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY 42 logger.warn(warnMsg) 43 44 if VERSION == getLatestRevision(): 45 logger.info("already at the latest revision '%s'" % getRevisionNumber()) 46 return 47 48 message = "do you want to try to fetch the latest 'zipball' from repository and extract it (experimental) ? [y/N]" 49 if readInput(message, default='N', boolean=True): 50 directory = os.path.abspath(paths.SQLMAP_ROOT_PATH) 51 52 try: 53 open(os.path.join(directory, "sqlmap.py"), "w+b") 54 except Exception as ex: 55 errMsg = "unable to update content of directory '%s' ('%s')" % (directory, getSafeExString(ex)) 56 logger.error(errMsg) 57 else: 58 attrs = os.stat(os.path.join(directory, "sqlmap.py")).st_mode 59 for wildcard in ('*', ".*"): 60 for _ in glob.glob(os.path.join(directory, wildcard)): 61 try: 62 if os.path.isdir(_): 63 shutil.rmtree(_) 64 else: 65 os.remove(_) 66 except: 67 pass 68 69 if glob.glob(os.path.join(directory, '*')): 70 errMsg = "unable to clear the content of directory '%s'" % directory 71 logger.error(errMsg) 72 else: 73 try: 74 archive = _urllib.request.urlretrieve(ZIPBALL_PAGE)[0] 75 76 with zipfile.ZipFile(archive) as f: 77 for info in f.infolist(): 78 info.filename = re.sub(r"\Asqlmap[^/]+", "", info.filename) 79 if info.filename: 80 f.extract(info, directory) 81 82 filepath = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "core", "settings.py") 83 if os.path.isfile(filepath): 84 with openFile(filepath, "rb") as f: 85 version = re.search(r"(?m)^VERSION\s*=\s*['\"]([^'\"]+)", f.read()).group(1) 86 logger.info("updated to the latest version '%s#dev'" % version) 87 success = True 88 except Exception as ex: 89 logger.error("update could not be completed ('%s')" % getSafeExString(ex)) 90 else: 91 if not success: 92 logger.error("update could not be completed") 93 else: 94 try: 95 os.chmod(os.path.join(directory, "sqlmap.py"), attrs) 96 except OSError: 97 logger.warning("could not set the file attributes of '%s'" % os.path.join(directory, "sqlmap.py")) 98 else: 99 infoMsg = "updating sqlmap to the latest development revision from the " 100 infoMsg += "GitHub repository" 101 logger.info(infoMsg) 102 103 debugMsg = "sqlmap will try to update itself using 'git' command" 104 logger.debug(debugMsg) 105 106 dataToStdout("\r[%s] [INFO] update in progress" % time.strftime("%X")) 107 108 output = "" 109 try: 110 process = subprocess.Popen("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=paths.SQLMAP_ROOT_PATH) 111 pollProcess(process, True) 112 output, _ = process.communicate() 113 success = not process.returncode 114 except Exception as ex: 115 success = False 116 output = getSafeExString(ex) 117 finally: 118 output = getText(output) 119 120 if success: 121 logger.info("%s the latest revision '%s'" % ("already at" if "Already" in output else "updated to", getRevisionNumber())) 122 else: 123 if "Not a git repository" in output: 124 errMsg = "not a valid git repository. Please checkout the 'sqlmapproject/sqlmap' repository " 125 errMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY 126 logger.error(errMsg) 127 else: 128 logger.error("update could not be completed ('%s')" % re.sub(r"\W+", " ", output).strip()) 129 130 if not success: 131 if IS_WIN: 132 infoMsg = "for Windows platform it's recommended " 133 infoMsg += "to use a GitHub for Windows client for updating " 134 infoMsg += "purposes (http://windows.github.com/) or just " 135 infoMsg += "download the latest snapshot from " 136 infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads" 137 else: 138 infoMsg = "for Linux platform it's recommended " 139 infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt-get install git')" 140 141 logger.info(infoMsg) 142