@ -270,15 +270,20 @@ class Format(object):
@rtype : C { str }
@rtype : C { str }
"""
"""
# Initialize the htmlParsed variable to None
htmlParsed = None
htmlParsed = None
# If the knowledge base htmlFp list is empty or the heuristic test is not positive, do nothing
if len ( kb . htmlFp ) == 0 or kb . heuristicTest != HEURISTIC_TEST . POSITIVE :
if len ( kb . htmlFp ) == 0 or kb . heuristicTest != HEURISTIC_TEST . POSITIVE :
pass
pass
# If the knowledge base htmlFp list has only one element, set htmlParsed to that element
elif len ( kb . htmlFp ) == 1 :
elif len ( kb . htmlFp ) == 1 :
htmlParsed = kb . htmlFp [ 0 ]
htmlParsed = kb . htmlFp [ 0 ]
# If the knowledge base htmlFp list has more than one element, set htmlParsed to a string of all elements joined by " or "
elif len ( kb . htmlFp ) > 1 :
elif len ( kb . htmlFp ) > 1 :
htmlParsed = " or " . join ( kb . htmlFp )
htmlParsed = " or " . join ( kb . htmlFp )
# Return the htmlParsed variable
return htmlParsed
return htmlParsed
@staticmethod
@staticmethod
@ -385,34 +390,42 @@ class Backend(object):
@staticmethod
@staticmethod
def setVersion ( version ) :
def setVersion ( version ) :
# 如果version是字符串类型, 则将kb.dbmsVersion设置为version
if isinstance ( version , six . string_types ) :
if isinstance ( version , six . string_types ) :
kb . dbmsVersion = [ version ]
kb . dbmsVersion = [ version ]
# 返回kb.dbmsVersion
return kb . dbmsVersion
return kb . dbmsVersion
@staticmethod
@staticmethod
def setVersionList ( versionsList ) :
def setVersionList ( versionsList ) :
# 如果versionsList是列表类型, 则将kb.dbmsVersion设置为versionsList
if isinstance ( versionsList , list ) :
if isinstance ( versionsList , list ) :
kb . dbmsVersion = versionsList
kb . dbmsVersion = versionsList
# 如果versionsList是字符串类型, 则调用Backend.setVersion方法
elif isinstance ( versionsList , six . string_types ) :
elif isinstance ( versionsList , six . string_types ) :
Backend . setVersion ( versionsList )
Backend . setVersion ( versionsList )
# 否则,记录错误信息
else :
else :
logger . error ( " invalid format of versionsList " )
logger . error ( " invalid format of versionsList " )
@staticmethod
@staticmethod
def forceDbms ( dbms , sticky = False ) :
def forceDbms ( dbms , sticky = False ) :
# 如果kb.stickyDBMS为False, 则将kb.forcedDbms设置为aliasToDbmsEnum(dbms), 并将kb.stickyDBMS设置为sticky
if not kb . stickyDBMS :
if not kb . stickyDBMS :
kb . forcedDbms = aliasToDbmsEnum ( dbms )
kb . forcedDbms = aliasToDbmsEnum ( dbms )
kb . stickyDBMS = sticky
kb . stickyDBMS = sticky
@staticmethod
@staticmethod
def flushForcedDbms ( force = False ) :
def flushForcedDbms ( force = False ) :
# 如果kb.stickyDBMS为False或者force为True, 则将kb.forcedDbms设置为None, 并将kb.stickyDBMS设置为False
if not kb . stickyDBMS or force :
if not kb . stickyDBMS or force :
kb . forcedDbms = None
kb . forcedDbms = None
kb . stickyDBMS = False
kb . stickyDBMS = False
@staticmethod
@staticmethod
def setOs ( os ) :
def setOs ( os ) :
# 如果os为None, 则返回None
if os is None :
if os is None :
return None
return None
@ -510,26 +523,36 @@ class Backend(object):
dbms = None
dbms = None
# 如果kb为空, 则不执行任何操作
if not kb :
if not kb :
pass
pass
# 如果kb中没有testMode, 并且dbmsHandler存在, 并且dbmsHandler._dbms存在, 则将dbms赋值为dbmsHandler._dbms
elif not kb . get ( " testMode " ) and conf . get ( " dbmsHandler " ) and getattr ( conf . dbmsHandler , " _dbms " , None ) :
elif not kb . get ( " testMode " ) and conf . get ( " dbmsHandler " ) and getattr ( conf . dbmsHandler , " _dbms " , None ) :
dbms = conf . dbmsHandler . _dbms
dbms = conf . dbmsHandler . _dbms
# 如果Backend.getForcedDbms()不为空, 则将dbms赋值为Backend.getForcedDbms()
elif Backend . getForcedDbms ( ) is not None :
elif Backend . getForcedDbms ( ) is not None :
dbms = Backend . getForcedDbms ( )
dbms = Backend . getForcedDbms ( )
# 如果Backend.getDbms()不为空, 则将dbms赋值为Backend.getDbms()
elif Backend . getDbms ( ) is not None :
elif Backend . getDbms ( ) is not None :
dbms = Backend . getDbms ( )
dbms = Backend . getDbms ( )
# 如果kb中有injection, 并且kb.injection.dbms存在, 则将dbms赋值为kb.injection.dbms
elif kb . get ( " injection " ) and kb . injection . dbms :
elif kb . get ( " injection " ) and kb . injection . dbms :
dbms = unArrayizeValue ( kb . injection . dbms )
dbms = unArrayizeValue ( kb . injection . dbms )
# 如果Backend.getErrorParsedDBMSes()存在, 则将dbms赋值为Backend.getErrorParsedDBMSes()
elif Backend . getErrorParsedDBMSes ( ) :
elif Backend . getErrorParsedDBMSes ( ) :
dbms = unArrayizeValue ( Backend . getErrorParsedDBMSes ( ) )
dbms = unArrayizeValue ( Backend . getErrorParsedDBMSes ( ) )
# 如果conf中有dbms, 则将dbms赋值为conf.get("dbms")
elif conf . get ( " dbms " ) :
elif conf . get ( " dbms " ) :
dbms = conf . get ( " dbms " )
dbms = conf . get ( " dbms " )
# 将dbms转换为dbmsEnum类型并返回
return aliasToDbmsEnum ( dbms )
return aliasToDbmsEnum ( dbms )
@staticmethod
@staticmethod
def getVersion ( ) :
def getVersion ( ) :
# 如果kb.dbmsVersion不是字符串类型, 则将kb.dbmsVersion展开并过滤掉None值, 否则将kb.dbmsVersion赋值给versions
versions = filterNone ( flattenValue ( kb . dbmsVersion ) ) if not isinstance ( kb . dbmsVersion , six . string_types ) else [ kb . dbmsVersion ]
versions = filterNone ( flattenValue ( kb . dbmsVersion ) ) if not isinstance ( kb . dbmsVersion , six . string_types ) else [ kb . dbmsVersion ]
# 如果versions不为空, 则返回versions的第一个元素, 否则返回None
if not isNoneValue ( versions ) :
if not isNoneValue ( versions ) :
return versions [ 0 ]
return versions [ 0 ]
else :
else :
@ -537,7 +560,9 @@ class Backend(object):
@staticmethod
@staticmethod
def getVersionList ( ) :
def getVersionList ( ) :
# 如果kb.dbmsVersion不是字符串类型, 则将kb.dbmsVersion展开并过滤掉None值, 否则将kb.dbmsVersion赋值给versions
versions = filterNone ( flattenValue ( kb . dbmsVersion ) ) if not isinstance ( kb . dbmsVersion , six . string_types ) else [ kb . dbmsVersion ]
versions = filterNone ( flattenValue ( kb . dbmsVersion ) ) if not isinstance ( kb . dbmsVersion , six . string_types ) else [ kb . dbmsVersion ]
# 如果versions不为空, 则返回versions, 否则返回None
if not isNoneValue ( versions ) :
if not isNoneValue ( versions ) :
return versions
return versions
else :
else :
@ -618,35 +643,48 @@ def paramToDict(place, parameters=None):
testableParameters = OrderedDict ( )
testableParameters = OrderedDict ( )
# 如果place在conf.parameters中, 并且parameters为空, 则将parameters设置为conf.parameters[place]
if place in conf . parameters and not parameters :
if place in conf . parameters and not parameters :
parameters = conf . parameters [ place ]
parameters = conf . parameters [ place ]
# 将parameters中的&替换为PARAMETER_AMP_MARKER, ;替换为PARAMETER_SEMICOLON_MARKER
parameters = re . sub ( r " &( \ w { 1,4}); " , r " %s \ g<1> %s " % ( PARAMETER_AMP_MARKER , PARAMETER_SEMICOLON_MARKER ) , parameters )
parameters = re . sub ( r " &( \ w { 1,4}); " , r " %s \ g<1> %s " % ( PARAMETER_AMP_MARKER , PARAMETER_SEMICOLON_MARKER ) , parameters )
# 根据place的值, 将parameters按照不同的分隔符进行分割
if place == PLACE . COOKIE :
if place == PLACE . COOKIE :
splitParams = parameters . split ( conf . cookieDel or DEFAULT_COOKIE_DELIMITER )
splitParams = parameters . split ( conf . cookieDel or DEFAULT_COOKIE_DELIMITER )
else :
else :
splitParams = parameters . split ( conf . paramDel or DEFAULT_GET_POST_DELIMITER )
splitParams = parameters . split ( conf . paramDel or DEFAULT_GET_POST_DELIMITER )
# 遍历分割后的参数
for element in splitParams :
for element in splitParams :
# 将PARAMETER_AMP_MARKER和PARAMETER_SEMICOLON_MARKER替换为&和;
element = re . sub ( r " %s (.+?) %s " % ( PARAMETER_AMP_MARKER , PARAMETER_SEMICOLON_MARKER ) , r " & \ g<1>; " , element )
element = re . sub ( r " %s (.+?) %s " % ( PARAMETER_AMP_MARKER , PARAMETER_SEMICOLON_MARKER ) , r " & \ g<1>; " , element )
# 将参数按照=进行分割
parts = element . split ( " = " )
parts = element . split ( " = " )
# 如果分割后的参数长度大于等于2
if len ( parts ) > = 2 :
if len ( parts ) > = 2 :
# 对参数进行url解码
parameter = urldecode ( parts [ 0 ] . replace ( " " , " " ) )
parameter = urldecode ( parts [ 0 ] . replace ( " " , " " ) )
# 如果参数为空,则跳过
if not parameter :
if not parameter :
continue
continue
# 如果conf.paramDel为\n, 则去掉参数的最后一个字符
if conf . paramDel and conf . paramDel == ' \n ' :
if conf . paramDel and conf . paramDel == ' \n ' :
parts [ - 1 ] = parts [ - 1 ] . rstrip ( )
parts [ - 1 ] = parts [ - 1 ] . rstrip ( )
# 判断参数是否在conf.testParameter中, 或者参数是否在conf.testParameter中, 或者参数是否在PLACE.COOKIE中
condition = not conf . testParameter
condition = not conf . testParameter
condition | = conf . testParameter is not None and parameter in conf . testParameter
condition | = conf . testParameter is not None and parameter in conf . testParameter
condition | = place == PLACE . COOKIE and len ( intersect ( ( PLACE . COOKIE , ) , conf . testParameter , True ) ) > 0
condition | = place == PLACE . COOKIE and len ( intersect ( ( PLACE . COOKIE , ) , conf . testParameter , True ) ) > 0
# 如果满足条件, 则将参数和值添加到testableParameters中
if condition :
if condition :
value = " = " . join ( parts [ 1 : ] )
value = " = " . join ( parts [ 1 : ] )
# 如果参数在conf.base64Parameter中, 则进行base64解码
if parameter in ( conf . base64Parameter or [ ] ) :
if parameter in ( conf . base64Parameter or [ ] ) :
try :
try :
kb . base64Originals [ parameter ] = oldValue = value
kb . base64Originals [ parameter ] = oldValue = value
@ -660,8 +698,10 @@ def paramToDict(place, parameters=None):
testableParameters [ parameter ] = value
testableParameters [ parameter ] = value
# 如果没有设置conf.multipleTargets, 并且参数不是conf.csrfToken, 则进行警告
if not conf . multipleTargets and not ( conf . csrfToken and re . search ( conf . csrfToken , parameter , re . I ) ) :
if not conf . multipleTargets and not ( conf . csrfToken and re . search ( conf . csrfToken , parameter , re . I ) ) :
_ = urldecode ( testableParameters [ parameter ] , convall = True )
_ = urldecode ( testableParameters [ parameter ] , convall = True )
# 如果参数值以'结尾,并且'的数量为1, 或者参数值以9开头, 或者参数值以-开头, 或者参数值匹配DUMMY_USER_INJECTION, 并且参数不是GOOGLE_ANALYTICS_COOKIE_PREFIX, 则进行警告
if ( _ . endswith ( " ' " ) and _ . count ( " ' " ) == 1 or re . search ( r ' \ A9 { 3,} ' , _ ) or re . search ( r ' \ A- \ d+ \ Z ' , _ ) or re . search ( DUMMY_USER_INJECTION , _ ) ) and not parameter . upper ( ) . startswith ( GOOGLE_ANALYTICS_COOKIE_PREFIX ) :
if ( _ . endswith ( " ' " ) and _ . count ( " ' " ) == 1 or re . search ( r ' \ A9 { 3,} ' , _ ) or re . search ( r ' \ A- \ d+ \ Z ' , _ ) or re . search ( DUMMY_USER_INJECTION , _ ) ) and not parameter . upper ( ) . startswith ( GOOGLE_ANALYTICS_COOKIE_PREFIX ) :
warnMsg = " it appears that you have provided tainted parameter values "
warnMsg = " it appears that you have provided tainted parameter values "
warnMsg + = " ( ' %s ' ) with most likely leftover " % element
warnMsg + = " ( ' %s ' ) with most likely leftover " % element
@ -672,14 +712,17 @@ def paramToDict(place, parameters=None):
message = " are you really sure that you want to continue (sqlmap could have problems)? [y/N] "
message = " are you really sure that you want to continue (sqlmap could have problems)? [y/N] "
# 如果用户输入的不是y, 则抛出SqlmapSilentQuitException异常
if not readInput ( message , default = ' N ' , boolean = True ) :
if not readInput ( message , default = ' N ' , boolean = True ) :
raise SqlmapSilentQuitException
raise SqlmapSilentQuitException
# 如果参数值为空,则进行警告
elif not _ :
elif not _ :
warnMsg = " provided value for parameter ' %s ' is empty. " % parameter
warnMsg = " provided value for parameter ' %s ' is empty. " % parameter
warnMsg + = " Please, always use only valid parameter values "
warnMsg + = " Please, always use only valid parameter values "
warnMsg + = " so sqlmap could be able to run properly "
warnMsg + = " so sqlmap could be able to run properly "
logger . warning ( warnMsg )
logger . warning ( warnMsg )
# 如果place是PLACE.POST或PLACE.GET, 则进行警告
if place in ( PLACE . POST , PLACE . GET ) :
if place in ( PLACE . POST , PLACE . GET ) :
for regex in ( r " \ A((?:<[^>]+>)+ \ w+)((?:<[^>]+>)+) \ Z " , r " \ A([^ \ w]+.* \ w+)([^ \ w]+) \ Z " ) :
for regex in ( r " \ A((?:<[^>]+>)+ \ w+)((?:<[^>]+>)+) \ Z " , r " \ A([^ \ w]+.* \ w+)([^ \ w]+) \ Z " ) :
match = re . search ( regex , testableParameters [ parameter ] )
match = re . search ( regex , testableParameters [ parameter ] )
@ -687,15 +730,19 @@ def paramToDict(place, parameters=None):
try :
try :
candidates = OrderedDict ( )
candidates = OrderedDict ( )
# 遍历参数值
def walk ( head , current = None ) :
def walk ( head , current = None ) :
if current is None :
if current is None :
current = head
current = head
# 如果current是列表, 则遍历列表
if isListLike ( current ) :
if isListLike ( current ) :
for _ in current :
for _ in current :
walk ( head , _ )
walk ( head , _ )
# 如果current是字典, 则遍历字典
elif isinstance ( current , dict ) :
elif isinstance ( current , dict ) :
for key in current . keys ( ) :
for key in current . keys ( ) :
value = current [ key ]
value = current [ key ]
# 如果value是bool、int、float、six.string_types, 或者value是None、[],则进行替换
if isinstance ( value , ( bool , int , float , six . string_types ) ) or value in ( None , [ ] ) :
if isinstance ( value , ( bool , int , float , six . string_types ) ) or value in ( None , [ ] ) :
original = current [ key ]
original = current [ key ]
if isinstance ( value , bool ) :
if isinstance ( value , bool ) :
@ -708,6 +755,7 @@ def paramToDict(place, parameters=None):
current [ key ] = " %s %s " % ( value , BOUNDED_INJECTION_MARKER )
current [ key ] = " %s %s " % ( value , BOUNDED_INJECTION_MARKER )
candidates [ " %s ( %s ) " % ( parameter , key ) ] = re . sub ( r " \ b( %s \ s*= \ s*) %s " % ( re . escape ( parameter ) , re . escape ( testableParameters [ parameter ] ) ) , r " \ g<1> %s " % json . dumps ( deserialized , separators = ( ' , ' , ' : ' ) if " , " not in testableParameters [ parameter ] else None ) , parameters )
candidates [ " %s ( %s ) " % ( parameter , key ) ] = re . sub ( r " \ b( %s \ s*= \ s*) %s " % ( re . escape ( parameter ) , re . escape ( testableParameters [ parameter ] ) ) , r " \ g<1> %s " % json . dumps ( deserialized , separators = ( ' , ' , ' : ' ) if " , " not in testableParameters [ parameter ] else None ) , parameters )
current [ key ] = original
current [ key ] = original
# 如果value是列表、元组、集合、字典, 则进行递归
elif isinstance ( value , ( list , tuple , set , dict ) ) :
elif isinstance ( value , ( list , tuple , set , dict ) ) :
if value :
if value :
walk ( head , value )
walk ( head , value )
@ -736,32 +784,42 @@ def paramToDict(place, parameters=None):
except Exception :
except Exception :
pass
pass
# 使用正则表达式替换testableParameters[parameter]中的匹配项
_ = re . sub ( regex , r " \ g<1> %s \ g< %d > " % ( kb . customInjectionMark , len ( match . groups ( ) ) ) , testableParameters [ parameter ] )
_ = re . sub ( regex , r " \ g<1> %s \ g< %d > " % ( kb . customInjectionMark , len ( match . groups ( ) ) ) , testableParameters [ parameter ] )
# 构造提示信息
message = " it appears that provided value for %s parameter ' %s ' " % ( " %s " % place if place != parameter else " " , parameter )
message = " it appears that provided value for %s parameter ' %s ' " % ( " %s " % place if place != parameter else " " , parameter )
message + = " has boundaries. Do you want to inject inside? ( ' %s ' ) [y/N] " % getUnicode ( _ )
message + = " has boundaries. Do you want to inject inside? ( ' %s ' ) [y/N] " % getUnicode ( _ )
# 读取用户输入, 如果用户选择注入, 则替换testableParameters[parameter]中的匹配项
if readInput ( message , default = ' N ' , boolean = True ) :
if readInput ( message , default = ' N ' , boolean = True ) :
testableParameters [ parameter ] = re . sub ( r " \ b( %s \ s*= \ s*) %s " % ( re . escape ( parameter ) , re . escape ( testableParameters [ parameter ] ) ) , ( r " \ g<1> %s " % re . sub ( regex , r " \ g<1> %s \ g<2> " % BOUNDED_INJECTION_MARKER , testableParameters [ parameter ] . replace ( " \\ " , r " \\ " ) ) ) , parameters )
testableParameters [ parameter ] = re . sub ( r " \ b( %s \ s*= \ s*) %s " % ( re . escape ( parameter ) , re . escape ( testableParameters [ parameter ] ) ) , ( r " \ g<1> %s " % re . sub ( regex , r " \ g<1> %s \ g<2> " % BOUNDED_INJECTION_MARKER , testableParameters [ parameter ] . replace ( " \\ " , r " \\ " ) ) ) , parameters )
break
break
# 如果配置了测试参数
if conf . testParameter :
if conf . testParameter :
# 如果没有可测试的参数
if not testableParameters :
if not testableParameters :
paramStr = " , " . join ( test for test in conf . testParameter )
paramStr = " , " . join ( test for test in conf . testParameter )
# 如果测试参数数量大于1
if len ( conf . testParameter ) > 1 :
if len ( conf . testParameter ) > 1 :
warnMsg = " provided parameters ' %s ' " % paramStr
warnMsg = " provided parameters ' %s ' " % paramStr
warnMsg + = " are not inside the %s " % place
warnMsg + = " are not inside the %s " % place
logger . warning ( warnMsg )
logger . warning ( warnMsg )
else :
else :
# 如果测试参数数量为1
parameter = conf . testParameter [ 0 ]
parameter = conf . testParameter [ 0 ]
# 如果测试参数不在USER_AGENT_ALIASES、REFERER_ALIASES、HOST_ALIASES中
if not intersect ( USER_AGENT_ALIASES + REFERER_ALIASES + HOST_ALIASES , parameter , True ) :
if not intersect ( USER_AGENT_ALIASES + REFERER_ALIASES + HOST_ALIASES , parameter , True ) :
debugMsg = " provided parameter ' %s ' " % paramStr
debugMsg = " provided parameter ' %s ' " % paramStr
debugMsg + = " is not inside the %s " % place
debugMsg + = " is not inside the %s " % place
logger . debug ( debugMsg )
logger . debug ( debugMsg )
# 如果测试参数数量不等于可测试参数数量
elif len ( conf . testParameter ) != len ( testableParameters ) :
elif len ( conf . testParameter ) != len ( testableParameters ) :
for parameter in conf . testParameter :
for parameter in conf . testParameter :
# 如果测试参数不在可测试参数中
if parameter not in testableParameters :
if parameter not in testableParameters :
debugMsg = " provided parameter ' %s ' " % parameter
debugMsg = " provided parameter ' %s ' " % parameter
debugMsg + = " is not inside the %s " % place
debugMsg + = " is not inside the %s " % place
@ -817,13 +875,16 @@ def getManualDirectories():
directories = normalizePath ( directories )
directories = normalizePath ( directories )
# 如果配置文件中有webRoot, 则使用webRoot作为web服务器文档根目录
if conf . webRoot :
if conf . webRoot :
directories = [ conf . webRoot ]
directories = [ conf . webRoot ]
infoMsg = " using ' %s ' as web server document root " % conf . webRoot
infoMsg = " using ' %s ' as web server document root " % conf . webRoot
logger . info ( infoMsg )
logger . info ( infoMsg )
# 如果directories有值, 则使用directories作为web服务器文档根目录
elif directories :
elif directories :
infoMsg = " retrieved the web server document root: ' %s ' " % directories
infoMsg = " retrieved the web server document root: ' %s ' " % directories
logger . info ( infoMsg )
logger . info ( infoMsg )
# 如果以上两种情况都不满足, 则提示无法自动获取web服务器文档根目录
else :
else :
warnMsg = " unable to automatically retrieve the web server "
warnMsg = " unable to automatically retrieve the web server "
warnMsg + = " document root "
warnMsg + = " document root "
@ -831,6 +892,7 @@ def getManualDirectories():
directories = [ ]
directories = [ ]
# 提示用户选择可写目录
message = " what do you want to use for writable directory? \n "
message = " what do you want to use for writable directory? \n "
message + = " [1] common location(s) ( ' %s ' ) (default) \n " % " , " . join ( root for root in defaultDocRoot )
message + = " [1] common location(s) ( ' %s ' ) (default) \n " % " , " . join ( root for root in defaultDocRoot )
message + = " [2] custom location(s) \n "
message + = " [2] custom location(s) \n "
@ -1639,48 +1701,64 @@ def parseTargetDirect():
break
break
# 如果kb.smokeMode为True, 则直接返回
if kb . smokeMode :
if kb . smokeMode :
return
return
# 如果details为空, 则抛出SqlmapSyntaxException异常
if not details :
if not details :
errMsg = " invalid target details, valid syntax is for instance "
errMsg = " invalid target details, valid syntax is for instance "
errMsg + = " ' mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME ' "
errMsg + = " ' mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME ' "
errMsg + = " or ' access://DATABASE_FILEPATH ' "
errMsg + = " or ' access://DATABASE_FILEPATH ' "
raise SqlmapSyntaxException ( errMsg )
raise SqlmapSyntaxException ( errMsg )
# 遍历DBMS_DICT字典
for dbmsName , data in DBMS_DICT . items ( ) :
for dbmsName , data in DBMS_DICT . items ( ) :
# 如果dbmsName等于conf.dbms或者conf.dbms.lower()在data[0]中,则执行以下操作
if dbmsName == conf . dbms or conf . dbms . lower ( ) in data [ 0 ] :
if dbmsName == conf . dbms or conf . dbms . lower ( ) in data [ 0 ] :
try :
try :
# 将conf.dbms设置为dbmsName
conf . dbms = dbmsName
conf . dbms = dbmsName
# 如果dbmsName在(DBMS.ACCESS, DBMS.SQLITE, DBMS.FIREBIRD)中,则执行以下操作
if dbmsName in ( DBMS . ACCESS , DBMS . SQLITE , DBMS . FIREBIRD ) :
if dbmsName in ( DBMS . ACCESS , DBMS . SQLITE , DBMS . FIREBIRD ) :
# 如果remote为True, 则抛出警告信息
if remote :
if remote :
warnMsg = " direct connection over the network for "
warnMsg = " direct connection over the network for "
warnMsg + = " %s DBMS is not supported " % dbmsName
warnMsg + = " %s DBMS is not supported " % dbmsName
logger . warning ( warnMsg )
logger . warning ( warnMsg )
# 将conf.hostname设置为localhost, conf.port设置为0
conf . hostname = " localhost "
conf . hostname = " localhost "
conf . port = 0
conf . port = 0
# 如果remote为False, 则抛出SqlmapSyntaxException异常
elif not remote :
elif not remote :
errMsg = " missing remote connection details (e.g. "
errMsg = " missing remote connection details (e.g. "
errMsg + = " ' mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME ' "
errMsg + = " ' mysql://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME ' "
errMsg + = " or ' access://DATABASE_FILEPATH ' ) "
errMsg + = " or ' access://DATABASE_FILEPATH ' ) "
raise SqlmapSyntaxException ( errMsg )
raise SqlmapSyntaxException ( errMsg )
# 如果dbmsName在(DBMS.MSSQL, DBMS.SYBASE)中,则执行以下操作
if dbmsName in ( DBMS . MSSQL , DBMS . SYBASE ) :
if dbmsName in ( DBMS . MSSQL , DBMS . SYBASE ) :
# 导入_mssql模块
__import__ ( " _mssql " )
__import__ ( " _mssql " )
# 导入pymssql模块
pymssql = __import__ ( " pymssql " )
pymssql = __import__ ( " pymssql " )
# 如果pymssql没有__version__属性或者pymssql.__version__小于1.0.2, 则抛出SqlmapMissingDependence异常
if not hasattr ( pymssql , " __version__ " ) or pymssql . __version__ < " 1.0.2 " :
if not hasattr ( pymssql , " __version__ " ) or pymssql . __version__ < " 1.0.2 " :
errMsg = " ' %s ' third-party library must be " % data [ 1 ]
errMsg = " ' %s ' third-party library must be " % data [ 1 ]
errMsg + = " version >= 1.0.2 to work properly. "
errMsg + = " version >= 1.0.2 to work properly. "
errMsg + = " Download from ' %s ' " % data [ 2 ]
errMsg + = " Download from ' %s ' " % data [ 2 ]
raise SqlmapMissingDependence ( errMsg )
raise SqlmapMissingDependence ( errMsg )
# 如果dbmsName等于DBMS.MYSQL, 则导入pymysql模块
elif dbmsName == DBMS . MYSQL :
elif dbmsName == DBMS . MYSQL :
__import__ ( " pymysql " )
__import__ ( " pymysql " )
# 如果dbmsName等于DBMS.PGSQL, 则导入psycopg2模块
elif dbmsName == DBMS . PGSQL :
elif dbmsName == DBMS . PGSQL :
__import__ ( " psycopg2 " )
__import__ ( " psycopg2 " )
# 如果dbmsName等于DBMS.ORACLE, 则导入cx_Oracle模块
elif dbmsName == DBMS . ORACLE :
elif dbmsName == DBMS . ORACLE :
__import__ ( " cx_Oracle " )
__import__ ( " cx_Oracle " )
@ -2437,21 +2515,29 @@ def getSQLSnippet(dbms, sfile, **variables):
filename = os . path . join ( paths . SQLMAP_PROCS_PATH , DBMS_DIRECTORY_DICT [ dbms ] , sfile if sfile . endswith ( ' .sql ' ) else " %s .sql " % sfile )
filename = os . path . join ( paths . SQLMAP_PROCS_PATH , DBMS_DIRECTORY_DICT [ dbms ] , sfile if sfile . endswith ( ' .sql ' ) else " %s .sql " % sfile )
checkFile ( filename )
checkFile ( filename )
# 读取缓存文件内容
retVal = readCachedFileContent ( filename )
retVal = readCachedFileContent ( filename )
# 删除注释
retVal = re . sub ( r " #.+ " , " " , retVal )
retVal = re . sub ( r " #.+ " , " " , retVal )
# 将分号替换为"; "
retVal = re . sub ( r " ; \ s+ " , " ; " , retVal ) . strip ( " \r \n " )
retVal = re . sub ( r " ; \ s+ " , " ; " , retVal ) . strip ( " \r \n " )
# 替换变量
for _ in variables :
for _ in variables :
retVal = re . sub ( r " %% %s %% " % _ , variables [ _ ] . replace ( ' \\ ' , r ' \\ ' ) , retVal )
retVal = re . sub ( r " %% %s %% " % _ , variables [ _ ] . replace ( ' \\ ' , r ' \\ ' ) , retVal )
# 替换随机字符串
for _ in re . findall ( r " % RANDSTR \ d+ % " , retVal , re . I ) :
for _ in re . findall ( r " % RANDSTR \ d+ % " , retVal , re . I ) :
retVal = retVal . replace ( _ , randomStr ( ) )
retVal = retVal . replace ( _ , randomStr ( ) )
# 替换随机整数
for _ in re . findall ( r " % RANDINT \ d+ % " , retVal , re . I ) :
for _ in re . findall ( r " % RANDINT \ d+ % " , retVal , re . I ) :
retVal = retVal . replace ( _ , randomInt ( ) )
retVal = retVal . replace ( _ , randomInt ( ) )
# 查找未解析的变量
variables = re . findall ( r " (?<! \ bLIKE ' ) % ( \ w+) % " , retVal , re . I )
variables = re . findall ( r " (?<! \ bLIKE ' ) % ( \ w+) % " , retVal , re . I )
# 如果有未解析的变量,则提示用户输入替换值
if variables :
if variables :
errMsg = " unresolved variable %s ' %s ' in SQL file ' %s ' " % ( " s " if len ( variables ) > 1 else " " , " , " . join ( variables ) , sfile )
errMsg = " unresolved variable %s ' %s ' in SQL file ' %s ' " % ( " s " if len ( variables ) > 1 else " " , " , " . join ( variables ) , sfile )
logger . error ( errMsg )
logger . error ( errMsg )
@ -2474,6 +2560,7 @@ def readCachedFileContent(filename, mode="rb"):
True
True
"""
"""
# 如果文件不在缓存中,则读取文件内容并缓存
if filename not in kb . cache . content :
if filename not in kb . cache . content :
with kb . locks . cache :
with kb . locks . cache :
if filename not in kb . cache . content :
if filename not in kb . cache . content :
@ -3935,6 +4022,7 @@ def fetchRandomAgent():
True
True
"""
"""
# 如果kb.userAgents为空, 则从文件中加载HTTP User-Agent header值
if not kb . userAgents :
if not kb . userAgents :
debugMsg = " loading random HTTP User-Agent header(s) from "
debugMsg = " loading random HTTP User-Agent header(s) from "
debugMsg + = " file ' %s ' " % paths . USER_AGENTS
debugMsg + = " file ' %s ' " % paths . USER_AGENTS
@ -3947,6 +4035,7 @@ def fetchRandomAgent():
errMsg + = " file ' %s ' " % paths . USER_AGENTS
errMsg + = " file ' %s ' " % paths . USER_AGENTS
raise SqlmapSystemException ( errMsg )
raise SqlmapSystemException ( errMsg )
# 从kb.userAgents中随机选择一个User-Agent header值并返回
return random . sample ( kb . userAgents , 1 ) [ 0 ]
return random . sample ( kb . userAgents , 1 ) [ 0 ]
def createGithubIssue ( errMsg , excMsg ) :
def createGithubIssue ( errMsg , excMsg ) :
@ -3954,6 +4043,7 @@ def createGithubIssue(errMsg, excMsg):
Automatically create a Github issue with unhandled exception information
Automatically create a Github issue with unhandled exception information
"""
"""
# 从文件中获取已创建的Github issue列表
try :
try :
issues = getFileItems ( paths . GITHUB_HISTORY , unique = True )
issues = getFileItems ( paths . GITHUB_HISTORY , unique = True )
except :
except :
@ -3961,6 +4051,7 @@ def createGithubIssue(errMsg, excMsg):
finally :
finally :
issues = set ( issues )
issues = set ( issues )
# 对异常信息进行处理,去除不必要的字符
_ = re . sub ( r " ' [^ ' ]+ ' " , " ' ' " , excMsg )
_ = re . sub ( r " ' [^ ' ]+ ' " , " ' ' " , excMsg )
_ = re . sub ( r " \ s+line \ d+ " , " " , _ )
_ = re . sub ( r " \ s+line \ d+ " , " " , _ )
_ = re . sub ( r ' File " .+?/( \ w+ \ .py) ' , r " \ g<1> " , _ )
_ = re . sub ( r ' File " .+?/( \ w+ \ .py) ' , r " \ g<1> " , _ )
@ -3968,11 +4059,14 @@ def createGithubIssue(errMsg, excMsg):
_ = re . sub ( r " (Unicode[^:]*Error:).+ " , r " \ g<1> " , _ )
_ = re . sub ( r " (Unicode[^:]*Error:).+ " , r " \ g<1> " , _ )
_ = re . sub ( r " = _ " , " = " , _ )
_ = re . sub ( r " = _ " , " = " , _ )
# 计算异常信息的MD5值, 并取前8位作为key
key = hashlib . md5 ( getBytes ( _ ) ) . hexdigest ( ) [ : 8 ]
key = hashlib . md5 ( getBytes ( _ ) ) . hexdigest ( ) [ : 8 ]
# 如果key已经在已创建的Github issue列表中, 则返回
if key in issues :
if key in issues :
return
return
# 提示用户是否要自动创建一个新的Github issue
msg = " \n do you want to automatically create a new (anonymized) issue "
msg = " \n do you want to automatically create a new (anonymized) issue "
msg + = " with the unhandled exception information at "
msg + = " with the unhandled exception information at "
msg + = " the official Github repository? [y/N] "
msg + = " the official Github repository? [y/N] "
@ -3981,10 +4075,12 @@ def createGithubIssue(errMsg, excMsg):
except :
except :
choice = None
choice = None
# 如果用户选择创建新的Github issue, 则进行后续操作
if choice :
if choice :
_excMsg = None
_excMsg = None
errMsg = errMsg [ errMsg . find ( " \n " ) : ]
errMsg = errMsg [ errMsg . find ( " \n " ) : ]
# 构造请求, 查询是否已存在相同的Github issue
req = _urllib . request . Request ( url = " https://api.github.com/search/issues?q= %s " % _urllib . parse . quote ( " repo:sqlmapproject/sqlmap Unhandled exception (# %s ) " % key ) , headers = { HTTP_HEADER . USER_AGENT : fetchRandomAgent ( ) } )
req = _urllib . request . Request ( url = " https://api.github.com/search/issues?q= %s " % _urllib . parse . quote ( " repo:sqlmapproject/sqlmap Unhandled exception (# %s ) " % key ) , headers = { HTTP_HEADER . USER_AGENT : fetchRandomAgent ( ) } )
try :
try :
@ -4071,9 +4167,11 @@ def listToStrValue(value):
' 1, 2, 3 '
' 1, 2, 3 '
"""
"""
# 如果value是set、tuple或types.GeneratorType类型, 将其转换为list
if isinstance ( value , ( set , tuple , types . GeneratorType ) ) :
if isinstance ( value , ( set , tuple , types . GeneratorType ) ) :
value = list ( value )
value = list ( value )
# 如果value是list类型, 将其转换为字符串, 并去掉首尾的方括号
if isinstance ( value , list ) :
if isinstance ( value , list ) :
retVal = value . __str__ ( ) . lstrip ( ' [ ' ) . rstrip ( ' ] ' )
retVal = value . __str__ ( ) . lstrip ( ' [ ' ) . rstrip ( ' ] ' )
else :
else :
@ -4146,62 +4244,97 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
value = value . replace ( 2 * REFLECTED_REPLACEMENT_REGEX , REFLECTED_REPLACEMENT_REGEX )
value = value . replace ( 2 * REFLECTED_REPLACEMENT_REGEX , REFLECTED_REPLACEMENT_REGEX )
return value
return value
# 将payload中的PAYLOAD_DELIMITER替换为空字符串, 并使用urldecode解码, 然后使用getUnicode转换为Unicode编码
payload = getUnicode ( urldecode ( payload . replace ( PAYLOAD_DELIMITER , " " ) , convall = True ) )
payload = getUnicode ( urldecode ( payload . replace ( PAYLOAD_DELIMITER , " " ) , convall = True ) )
# 使用filterStringValue函数过滤payload中的字符串, 并使用encodeStringEscape函数进行编码, 然后使用_函数进行转换
regex = _ ( filterStringValue ( payload , r " [A-Za-z0-9] " , encodeStringEscape ( REFLECTED_REPLACEMENT_REGEX ) ) )
regex = _ ( filterStringValue ( payload , r " [A-Za-z0-9] " , encodeStringEscape ( REFLECTED_REPLACEMENT_REGEX ) ) )
# 如果regex不等于payload
if regex != payload :
if regex != payload :
# 使用filterNone函数过滤regex中的空字符串, 并使用REFLECTED_REPLACEMENT_REGEX进行分割, 然后使用all函数检查分割后的字符串是否都在content中
if all ( part . lower ( ) in content . lower ( ) for part in filterNone ( regex . split ( REFLECTED_REPLACEMENT_REGEX ) ) [ 1 : ] ) : # fast optimization check
if all ( part . lower ( ) in content . lower ( ) for part in filterNone ( regex . split ( REFLECTED_REPLACEMENT_REGEX ) ) [ 1 : ] ) : # fast optimization check
# 使用REFLECTED_REPLACEMENT_REGEX进行分割
parts = regex . split ( REFLECTED_REPLACEMENT_REGEX )
parts = regex . split ( REFLECTED_REPLACEMENT_REGEX )
# Note: naive approach
# Note: naive approach
# 将content中的payload替换为REFLECTED_VALUE_MARKER
retVal = content . replace ( payload , REFLECTED_VALUE_MARKER )
retVal = content . replace ( payload , REFLECTED_VALUE_MARKER )
# 将content中的payload的开头替换为REFLECTED_VALUE_MARKER
retVal = retVal . replace ( re . sub ( r " \ A \ w+ " , " " , payload ) , REFLECTED_VALUE_MARKER )
retVal = retVal . replace ( re . sub ( r " \ A \ w+ " , " " , payload ) , REFLECTED_VALUE_MARKER )
# 如果分割后的字符串长度大于REFLECTED_MAX_REGEX_PARTS
if len ( parts ) > REFLECTED_MAX_REGEX_PARTS : # preventing CPU hogs
if len ( parts ) > REFLECTED_MAX_REGEX_PARTS : # preventing CPU hogs
# 使用REFLECTED_REPLACEMENT_REGEX进行分割, 并使用join函数进行连接
regex = _ ( " %s %s %s " % ( REFLECTED_REPLACEMENT_REGEX . join ( parts [ : REFLECTED_MAX_REGEX_PARTS / / 2 ] ) , REFLECTED_REPLACEMENT_REGEX , REFLECTED_REPLACEMENT_REGEX . join ( parts [ - REFLECTED_MAX_REGEX_PARTS / / 2 : ] ) ) )
regex = _ ( " %s %s %s " % ( REFLECTED_REPLACEMENT_REGEX . join ( parts [ : REFLECTED_MAX_REGEX_PARTS / / 2 ] ) , REFLECTED_REPLACEMENT_REGEX , REFLECTED_REPLACEMENT_REGEX . join ( parts [ - REFLECTED_MAX_REGEX_PARTS / / 2 : ] ) ) )
# 使用filterNone函数过滤regex中的空字符串, 并使用REFLECTED_REPLACEMENT_REGEX进行分割
parts = filterNone ( regex . split ( REFLECTED_REPLACEMENT_REGEX ) )
parts = filterNone ( regex . split ( REFLECTED_REPLACEMENT_REGEX ) )
# 如果regex以REFLECTED_REPLACEMENT_REGEX开头
if regex . startswith ( REFLECTED_REPLACEMENT_REGEX ) :
if regex . startswith ( REFLECTED_REPLACEMENT_REGEX ) :
# 使用REFLECTED_BORDER_REGEX和regex[len(REFLECTED_REPLACEMENT_REGEX):]进行连接
regex = r " %s %s " % ( REFLECTED_BORDER_REGEX , regex [ len ( REFLECTED_REPLACEMENT_REGEX ) : ] )
regex = r " %s %s " % ( REFLECTED_BORDER_REGEX , regex [ len ( REFLECTED_REPLACEMENT_REGEX ) : ] )
else :
else :
# 使用\b和regex进行连接
regex = r " \ b %s " % regex
regex = r " \ b %s " % regex
# 如果regex以REFLECTED_REPLACEMENT_REGEX结尾
if regex . endswith ( REFLECTED_REPLACEMENT_REGEX ) :
if regex . endswith ( REFLECTED_REPLACEMENT_REGEX ) :
# 使用regex[:-len(REFLECTED_REPLACEMENT_REGEX)]和REFLECTED_BORDER_REGEX进行连接
regex = r " %s %s " % ( regex [ : - len ( REFLECTED_REPLACEMENT_REGEX ) ] , REFLECTED_BORDER_REGEX )
regex = r " %s %s " % ( regex [ : - len ( REFLECTED_REPLACEMENT_REGEX ) ] , REFLECTED_BORDER_REGEX )
else :
else :
# 使用regex和\b进行连接
regex = r " %s \ b " % regex
regex = r " %s \ b " % regex
# 创建一个列表, 用于存储retVal
_retVal = [ retVal ]
_retVal = [ retVal ]
# 定义一个函数, 用于替换retVal中的regex
def _thread ( regex ) :
def _thread ( regex ) :
try :
try :
# 使用re.sub函数替换retVal中的regex, 并使用REFLECTED_VALUE_MARKER进行替换
_retVal [ 0 ] = re . sub ( r " (?i) %s " % regex , REFLECTED_VALUE_MARKER , _retVal [ 0 ] )
_retVal [ 0 ] = re . sub ( r " (?i) %s " % regex , REFLECTED_VALUE_MARKER , _retVal [ 0 ] )
# 如果分割后的字符串长度大于2
if len ( parts ) > 2 :
if len ( parts ) > 2 :
# 使用REFLECTED_REPLACEMENT_REGEX进行分割, 并使用join函数进行连接
regex = REFLECTED_REPLACEMENT_REGEX . join ( parts [ 1 : ] )
regex = REFLECTED_REPLACEMENT_REGEX . join ( parts [ 1 : ] )
# 使用re.sub函数替换retVal中的regex, 并使用REFLECTED_VALUE_MARKER进行替换
_retVal [ 0 ] = re . sub ( r " (?i) \ b %s \ b " % regex , REFLECTED_VALUE_MARKER , _retVal [ 0 ] )
_retVal [ 0 ] = re . sub ( r " (?i) \ b %s \ b " % regex , REFLECTED_VALUE_MARKER , _retVal [ 0 ] )
except KeyboardInterrupt :
except KeyboardInterrupt :
raise
raise
except :
except :
pass
pass
# 创建一个线程, 用于执行_thread函数
thread = threading . Thread ( target = _thread , args = ( regex , ) )
thread = threading . Thread ( target = _thread , args = ( regex , ) )
# 设置线程为守护线程
thread . daemon = True
thread . daemon = True
# 启动线程
thread . start ( )
thread . start ( )
# 等待线程执行完毕, 超时时间为REFLECTED_REPLACEMENT_TIMEOUT
thread . join ( REFLECTED_REPLACEMENT_TIMEOUT )
thread . join ( REFLECTED_REPLACEMENT_TIMEOUT )
# 如果线程还在运行
if thread . is_alive ( ) :
if thread . is_alive ( ) :
# 将kb.reflectiveMechanism设置为False
kb . reflectiveMechanism = False
kb . reflectiveMechanism = False
# 将retVal设置为content
retVal = content
retVal = content
# 如果不抑制警告
if not suppressWarning :
if not suppressWarning :
# 打印debugMsg
debugMsg = " turning off reflection removal mechanism (because of timeouts) "
debugMsg = " turning off reflection removal mechanism (because of timeouts) "
logger . debug ( debugMsg )
logger . debug ( debugMsg )
else :
else :
# 将retVal设置为_retVal[0]
retVal = _retVal [ 0 ]
retVal = _retVal [ 0 ]
# 如果retVal不等于content
if retVal != content :
if retVal != content :
# 将kb.reflectiveCounters[REFLECTIVE_COUNTER.HIT]加1
kb . reflectiveCounters [ REFLECTIVE_COUNTER . HIT ] + = 1
kb . reflectiveCounters [ REFLECTIVE_COUNTER . HIT ] + = 1
# 如果不抑制警告
if not suppressWarning :
if not suppressWarning :
warnMsg = " reflective value(s) found and filtering out "
warnMsg = " reflective value(s) found and filtering out "
singleTimeWarnMessage ( warnMsg )
singleTimeWarnMessage ( warnMsg )
@ -4367,6 +4500,7 @@ def isNullValue(value):
False
False
"""
"""
# 判断value是否具有upper()方法, 并且value的大写等于NULL
return hasattr ( value , " upper " ) and value . upper ( ) == NULL
return hasattr ( value , " upper " ) and value . upper ( ) == NULL
def expandMnemonics ( mnemonics , parser , args ) :
def expandMnemonics ( mnemonics , parser , args ) :
@ -4374,19 +4508,23 @@ def expandMnemonics(mnemonics, parser, args):
Expands mnemonic options
Expands mnemonic options
"""
"""
# 定义一个MnemonicNode类, 用于存储选项
class MnemonicNode ( object ) :
class MnemonicNode ( object ) :
def __init__ ( self ) :
def __init__ ( self ) :
self . next = { }
self . next = { }
self . current = [ ]
self . current = [ ]
# 初始化头节点和指针
head = MnemonicNode ( )
head = MnemonicNode ( )
pointer = None
pointer = None
# 遍历parser中的option_groups
for group in parser . option_groups :
for group in parser . option_groups :
for option in group . option_list :
for option in group . option_list :
for opt in option . _long_opts + option . _short_opts :
for opt in option . _long_opts + option . _short_opts :
pointer = head
pointer = head
# 遍历opt中的每个字符
for char in opt :
for char in opt :
if char == " - " :
if char == " - " :
continue
continue
@ -4396,12 +4534,14 @@ def expandMnemonics(mnemonics, parser, args):
pointer = pointer . next [ char ]
pointer = pointer . next [ char ]
pointer . current . append ( option )
pointer . current . append ( option )
# 遍历mnemonics中的每个选项
for mnemonic in ( mnemonics or " " ) . split ( ' , ' ) :
for mnemonic in ( mnemonics or " " ) . split ( ' , ' ) :
found = None
found = None
name = mnemonic . split ( ' = ' ) [ 0 ] . replace ( ' - ' , " " ) . strip ( )
name = mnemonic . split ( ' = ' ) [ 0 ] . replace ( ' - ' , " " ) . strip ( )
value = mnemonic . split ( ' = ' ) [ 1 ] if len ( mnemonic . split ( ' = ' ) ) > 1 else None
value = mnemonic . split ( ' = ' ) [ 1 ] if len ( mnemonic . split ( ' = ' ) ) > 1 else None
pointer = head
pointer = head
# 遍历name中的每个字符
for char in name :
for char in name :
if char in pointer . next :
if char in pointer . next :
pointer = pointer . next [ char ]
pointer = pointer . next [ char ]
@ -4409,10 +4549,12 @@ def expandMnemonics(mnemonics, parser, args):
pointer = None
pointer = None
break
break
# 如果pointer为None或head, 则抛出异常
if pointer in ( None , head ) :
if pointer in ( None , head ) :
errMsg = " mnemonic ' %s ' can ' t be resolved to any parameter name " % name
errMsg = " mnemonic ' %s ' can ' t be resolved to any parameter name " % name
raise SqlmapSyntaxException ( errMsg )
raise SqlmapSyntaxException ( errMsg )
# 如果pointer.current的长度大于1, 则说明有多个选项, 需要进行解析
elif len ( pointer . current ) > 1 :
elif len ( pointer . current ) > 1 :
options = { }
options = { }
@ -4422,26 +4564,32 @@ def expandMnemonics(mnemonics, parser, args):
if opt . startswith ( name ) :
if opt . startswith ( name ) :
options [ opt ] = option
options [ opt ] = option
# 如果options为空, 则说明没有找到对应的选项, 进行警告
if not options :
if not options :
warnMsg = " mnemonic ' %s ' can ' t be resolved " % name
warnMsg = " mnemonic ' %s ' can ' t be resolved " % name
logger . warning ( warnMsg )
logger . warning ( warnMsg )
# 如果name在options中, 则说明找到了对应的选项, 进行调试
elif name in options :
elif name in options :
found = name
found = name
debugMsg = " mnemonic ' %s ' resolved to %s ). " % ( name , found )
debugMsg = " mnemonic ' %s ' resolved to %s ). " % ( name , found )
logger . debug ( debugMsg )
logger . debug ( debugMsg )
# 否则,说明有多个选项,进行警告,并选择最短的选项
else :
else :
found = sorted ( options . keys ( ) , key = len ) [ 0 ]
found = sorted ( options . keys ( ) , key = len ) [ 0 ]
warnMsg = " detected ambiguity (mnemonic ' %s ' can be resolved to any of: %s ). " % ( name , " , " . join ( " ' %s ' " % key for key in options ) )
warnMsg = " detected ambiguity (mnemonic ' %s ' can be resolved to any of: %s ). " % ( name , " , " . join ( " ' %s ' " % key for key in options ) )
warnMsg + = " Resolved to shortest of those ( ' %s ' ) " % found
warnMsg + = " Resolved to shortest of those ( ' %s ' ) " % found
logger . warning ( warnMsg )
logger . warning ( warnMsg )
# 如果找到了对应的选项,则进行赋值
if found :
if found :
found = options [ found ]
found = options [ found ]
# 如果pointer.current的长度等于1, 则说明只有一个选项, 进行调试
else :
else :
found = pointer . current [ 0 ]
found = pointer . current [ 0 ]
debugMsg = " mnemonic ' %s ' resolved to %s ). " % ( name , found )
debugMsg = " mnemonic ' %s ' resolved to %s ). " % ( name , found )
logger . debug ( debugMsg )
logger . debug ( debugMsg )
# 如果找到了对应的选项,则进行赋值
if found :
if found :
try :
try :
value = found . convert_value ( found , value )
value = found . convert_value ( found , value )
@ -4468,13 +4616,18 @@ def safeCSValue(value):
' foobar '
' foobar '
"""
"""
# 初始化返回值
retVal = value
retVal = value
# 如果value不为空, 并且是字符串类型
if retVal and isinstance ( retVal , six . string_types ) :
if retVal and isinstance ( retVal , six . string_types ) :
# 如果value的第一个字符和最后一个字符不是双引号, 并且value中包含csv分隔符、双引号或换行符
if not ( retVal [ 0 ] == retVal [ - 1 ] == ' " ' ) :
if not ( retVal [ 0 ] == retVal [ - 1 ] == ' " ' ) :
if any ( _ in retVal for _ in ( conf . get ( " csvDel " , defaults . csvDel ) , ' " ' , ' \n ' ) ) :
if any ( _ in retVal for _ in ( conf . get ( " csvDel " , defaults . csvDel ) , ' " ' , ' \n ' ) ) :
# 将value中的双引号替换为两个双引号, 并在value的两端加上双引号
retVal = ' " %s " ' % retVal . replace ( ' " ' , ' " " ' )
retVal = ' " %s " ' % retVal . replace ( ' " ' , ' " " ' )
# 返回处理后的value
return retVal
return retVal
def filterPairValues ( values ) :
def filterPairValues ( values ) :
@ -4485,11 +4638,15 @@ def filterPairValues(values):
[ [ 1 , 2 ] , [ 4 , 5 ] ]
[ [ 1 , 2 ] , [ 4 , 5 ] ]
"""
"""
# 初始化返回值
retVal = [ ]
retVal = [ ]
# 如果values不为空, 并且是可迭代的
if not isNoneValue ( values ) and hasattr ( values , ' __iter__ ' ) :
if not isNoneValue ( values ) and hasattr ( values , ' __iter__ ' ) :
# 遍历values中的每个value
retVal = [ value for value in values if isinstance ( value , ( tuple , list , set ) ) and len ( value ) == 2 ]
retVal = [ value for value in values if isinstance ( value , ( tuple , list , set ) ) and len ( value ) == 2 ]
# 返回处理后的values
return retVal
return retVal
def randomizeParameterValue ( value ) :
def randomizeParameterValue ( value ) :
@ -5517,6 +5674,7 @@ def unsafeVariableNaming(value):
True
True
"""
"""
# 如果value以EVALCODE_ENCODED_PREFIX开头, 则解码value
if value . startswith ( EVALCODE_ENCODED_PREFIX ) :
if value . startswith ( EVALCODE_ENCODED_PREFIX ) :
value = decodeHex ( value [ len ( EVALCODE_ENCODED_PREFIX ) : ] , binary = False )
value = decodeHex ( value [ len ( EVALCODE_ENCODED_PREFIX ) : ] , binary = False )
@ -5532,6 +5690,7 @@ def firstNotNone(*args):
retVal = None
retVal = None
# 遍历args, 找到第一个不为None的值
for _ in args :
for _ in args :
if _ is not None :
if _ is not None :
retVal = _
retVal = _
@ -5549,6 +5708,7 @@ def removePostHintPrefix(value):
' id '
' id '
"""
"""
# 使用正则表达式去除value中的POST提示前缀
return re . sub ( r " \ A( %s ) " % ' | ' . join ( re . escape ( __ ) for __ in getPublicTypeMembers ( POST_HINT , onlyValues = True ) ) , " " , value )
return re . sub ( r " \ A( %s ) " % ' | ' . join ( re . escape ( __ ) for __ in getPublicTypeMembers ( POST_HINT , onlyValues = True ) ) , " " , value )
def chunkSplitPostData ( data ) :
def chunkSplitPostData ( data ) :