📄 cryptlibconverter.py
字号:
private static void processStatus(int status) { if (status < crypt.OK) throw new CryptException(status); } private static void checkIndices(byte[] array, int sequenceOffset, int sequenceLength) { if (array == null) { if (sequenceOffset == 0) return; else throw new IndexOutOfRangeException(); } int arrayLength = array.Length; if (sequenceOffset < 0 || sequenceOffset >= arrayLength || sequenceOffset + sequenceLength > arrayLength) throw new IndexOutOfRangeException(); } private static void getPointer(byte[] buffer, int bufferOffset, ref GCHandle bufferHandle, ref IntPtr bufferPtr) { if (buffer == null) return; bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferOffset); } private static void releasePointer(GCHandle bufferHandle) { if (bufferHandle.IsAllocated) bufferHandle.Free(); }}""" sFuncs = None sInts = Nones = open(inFile).read()inFileTabSize = 4#Global variables#These accumulate information about the types in the input file#----------------------------------------------------------------nameSpace = {} #Accumulate enum'd values here and use them to eval() the RHS of new onesenumTypes = [] #Accumulate typedef'd enum types hereintTypes = [] #Accumulate typedef'd int types herestructTypes = []#Accumulate typedef'd struct types hererawTypes = ["char", "int", "void"]functionNames = [] #Accumulate function names hererawParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of original c code)newParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of new java/python code)newReturnStructsDict = {} #Accumulate function name -> ParamStruct of return parameter (of new java/python code)newDiscardedStructsDict = {} #Accumulate function name -> ParamStruct of discarded parameterlengthIndicesDict = {} #Accumulate function name -> indices in newParamStructs of lengths (used for python)offsetIndicesDict= {} #Accumulate function name -> indices in newParamStructs of offsets (used for python)errors = {} #Dictionary mapping return values to exception objectsprint "Parsing input file and generating %s files..." % language#Removing enclosing include guard#---------------------------------s = re.search(r"#ifndef _CRYPTLIB_DEFINED\n(.*)\n#endif", s, re.DOTALL).group(1)#Ignore anything before "#define C_INOUT..."#--------------------------------------------s = s[re.search(r"#define C_INOUT.*?\n", s, re.DOTALL).end() : ]#Remove all conditionals#------------------------while 1: endifMatch = re.search(r"#endif.*?\n", s, re.DOTALL) if endifMatch == None: break ifdefIndex = s.rfind("#if", 0, endifMatch.start()) s = s[ : ifdefIndex] + s[endifMatch.end() : ]#Replace typedef enums#----------------------typedefEnumPattern = re.compile(r"typedef[ \t]+enum[ \t]+{([^}]*)}\s*(\w*);", re.DOTALL) # typedef enum { %1 } %2;#Find the next typedef enumtypedefEnumMatch = typedefEnumPattern.search(s)while typedefEnumMatch: #Extract its contents and type name enumContents, typedefName = typedefEnumMatch.groups() enumTypes.append(typedefName) #Parse its contents enumTuples = parseEnumContents(enumContents, nameSpace, "typedef") #Determine the length to pad names to namePad = str( max( [len(e[0]) for e in enumTuples] ) ) valuePad = str( max( [len(e[1]) for e in enumTuples] ) ) #Construct its output equivalent from language-specific string templates newTypedefEnum = typedefEnumTemplate % vars() for enumTuple in enumTuples: name, value, comment = enumTuple if not comment: paddedTemplate = typedefEnumElementTemplate.replace("NPAD", namePad).replace("VPAD", valuePad) newEnum = paddedTemplate % vars() else: paddedTemplate = typedefEnumElementTemplateComment.replace("NPAD", namePad).replace("VPAD", valuePad) newEnum = paddedTemplate % vars() if newTypedefEnum: newTypedefEnum += "\n" #Don't always add this or we'll get extraneous newlines in python newTypedefEnum += newEnum #print "Output Equivalent of Typedef Enum====\n", newTypedefEnum #raw_input() if sInts: sInts += newTypedefEnum + "\n" #Substitute the output equivalent for the input s = s[ : typedefEnumMatch.start()] + newTypedefEnum + s[typedefEnumMatch.end() : ] #Get next typedef typedefEnumMatch = typedefEnumPattern.search(s, typedefEnumMatch.start() + len(newTypedefEnum))#print "ENUMTYPES:\n",enumTypes#Replace simple enums#---------------------#This works on the theory that we've already replaced all typedef enums with#something that doesn't use the word "enum", so any remaining occurrences of#enum will belong to simple enums.simpleEnumPattern = re.compile(r"enum[ \t]+{([^}]*)};", re.DOTALL) # enum { %1 };#Find the next simple enumsimpleEnumMatch = simpleEnumPattern.search(s)while simpleEnumMatch: #Extract its contents enumContents = simpleEnumMatch.group(1) #Parse its contents enumTuples = parseEnumContents(enumContents, nameSpace, "simple") #Determine the length to pad names to namePad = str( max( [len(e[0]) for e in enumTuples] ) ) valuePad = str( max( [len(e[1]) for e in enumTuples] ) ) #Construct its output equivalent from language-specific string templates newSimpleEnum = "" for enumTuple in enumTuples: name, value, comment = enumTuple if not comment: paddedTemplate = simpleEnumElementTemplate.replace("NPAD", namePad).replace("VPAD", valuePad) newEnum = paddedTemplate % vars() else: paddedTemplate = simpleEnumElementTemplateComment.replace("NPAD", namePad).replace("VPAD", valuePad) newEnum = paddedTemplate % vars() if newSimpleEnum: newSimpleEnum += "\n" #Don't always add this or we'll get extraneous newlines in python newSimpleEnum += newEnum #print "Output Equivalent of Simple Enum====\n", newSimpleEnum #raw_input() if sInts: sInts += newSimpleEnum + "\n" #Substitute the output equivalent for the input s = s[ : simpleEnumMatch.start()] + newSimpleEnum + s[simpleEnumMatch.end() : ] #Get next typedef simpleEnumMatch = simpleEnumPattern.search(s, simpleEnumMatch.start() + len(newSimpleEnum))#Replace #define'd constants#----------------------------definePattern = re.compile(r"#define[ \t]+(\w+)[ \t]+([-\w]+)[ \t]*(/\*.*\*/*)?") # #define %1 %2 [/*%3*/]exceptionString = exceptionPrefix#Find the next #definedefineMatch = definePattern.search(s)while defineMatch: #Parse its contents name, value, comment = defineMatch.groups() if not name.startswith("CRYPT_"): raise "name doesn't start with CRYPT_"+name name = name.replace("CRYPT_", "") #Construct its output equivalent from language-specific string templates if not comment: paddedTemplate = defineTemplate.replace("NPAD", defineNPad).replace("VPAD", defineVPad) newDefine = paddedTemplate % vars() else: comment = comment[2:-2].strip() paddedTemplate = defineTemplateComment.replace("NPAD", defineNPad).replace("VPAD", defineVPad) newDefine = paddedTemplate % vars() #print "define: " + newDefine #raw_input() if sInts: sInts += newDefine + "\n" #Substitute the output equivalent for the input s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ] #Append to exception string if error if name.startswith("ERROR_") or name.startswith("ENVELOPE_RESOURCE"): exceptionString += exceptionTemplate % vars() #Get next #define defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))exceptionString += exceptionPostfix#Comment out #define'd macros#-----------------------------definePattern = re.compile(r"#define[ \t]+[^(]+\([^\)]*\)([^\n]*\\\n)*[^\n]*")defineMatch = definePattern.search(s)while defineMatch: #print "defined macros:", defineMatch.group() #raw_input() define = defineMatch.group() newDefine = commentPrefix + "CRYPTLIBCONVERTER - NOT SUPPORTED:\n" + define newDefine = newDefine.replace("\n", "\n"+commentPrefix) s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ] defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))#Comment out typedef integer types#----------------------------------typedefIntPattern = re.compile(r"typedef[ \t]+int[ \t]+([^ \t]*)[ \t]*;[ \t]*\n")typedefIntMatch = typedefIntPattern.search(s)while typedefIntMatch: typedefInt = typedefIntMatch.group() typedefIntName = typedefIntMatch.group(1) intTypes.append(typedefIntName) #print "typedef int:", typedefInt #raw_input() newTypedefInt = commentPrefix + "CRYPTLIBCONVERTER - NOT NEEDED: " + typedefInt s = s[ : typedefIntMatch.start()] + newTypedefInt + s[typedefIntMatch.end() : ] typedefIntMatch = typedefIntPattern.search(s, typedefIntMatch.start() + len(newTypedefInt))#print "INTTYPES:\n",intTypes#Comment out typedef structs#----------------------------typedefStructPattern = re.compile(r"typedef[ \t]+struct[ \t]\{[^}]*}[ \t]*([^;]+);")typedefStructMatch = typedefStructPattern.search(s)while typedefStructMatch: typedefStruct = typedefStructMatch.group() typedefStructName = typedefStructMatch.group(1) structTypes.append(typedefStructName) #print "typedef struct:", typedefStructName #raw_input() newTypedefStruct = commentPrefix + "CRYPTLIBCONVERTER - NOT SUPPORTED:\n" + typedefStruct newTypedefStruct = newTypedefStruct.replace("\n", "\n"+commentPrefix) s = s[ : typedefStructMatch.start()] + newTypedefStruct + s[typedefStructMatch.end() : ] typedefStructMatch = typedefStructPattern.search(s, typedefStructMatch.start() + len(newTypedefStruct))#print "STRUCTTYPES:\n",structTypes#raw_input()#Translate functions#--------------------functionPattern = re.compile(r"C_RET[ \t]+([^ \t]+)[ \t]*\(([^\)]*)\);", re.DOTALL)functionMatch = functionPattern.search(s)while functionMatch: function = functionMatch.group() functionName, functionParams = functionMatch.groups() if not functionName.startswith("crypt"): raise "name doesn't start with crypt"+functionName functionName = functionName[len("crypt") : ] functionNames.append(functionName) #print "function:", functionName, functionParams #raw_input() #Parse its parameters paramStructs = parseFunctionParams(functionParams) #Add raw list of ParamStructs to dictionary #This will be used later, when generating the .c glue code rawParamStructsDict[functionName] = paramStructs # Since java and python don't have pass-by-reference, what we do is migrate the # output int parameter in certain functions into the return value. If the function # creates or returns values such as integers or a (void*, int*) pair, we record # the indexes of the parameters to migrate. We do this in functions like: # cryptCreate*() # return handle of new object # cryptGetAttribute() # return integer value of attribute # cryptGetAttributeString() # convert (void*, int*) to python string or java byte array # cryptExportKey() # convert (void*, int*) " # cryptCreateSignature() # convert (void*, int*) # cryptKeysetOpen() # return handle # cryptGetPublicKey() # return handle # cryptGetPrivateKey() # return handle # cryptGetCertExtension() # convert (void*, int) but DISCARD criticalFlag (the int* before)! # cryptImportCert() # return handle # cryptExportCert() # convert (void*, int) # cryptCAGetItem() # return handle # cryptCACertManagement() # return handle # cryptPushData() # return integer (# of bytes copied) # cryptPopData() # convert (void*, int*) even though they're not adjacent discardIntIndex = -1 returnIntIndex = -1 returnVoidPtrIndex = -1 discardInLengthIndex1 = -1 # To discard input lengths, since python don't need these discardInLengthIndex2 = -1 #Scan through looking for a void pointer preceded by "keyIDtype" #Convert it into a char* index = 1 for p in paramStructs[1:]: p2 = paramStructs[index-1] if p.isPtr and p.type=="void" and p2.type=="CRYPT_KEYID_TYPE": p.type = "char" index += 1 #Scan through looking for output int pointers (or structs)?! #If there's two, we will migrate the second occurrence to the return value #and discard the first so as to handle cryptGetCertExtension() index = 0 for p in paramStructs: if p.isOut and p.isPtr and (p.category=="intType" or p.type=="int" or p.category=="structType"): if returnIntIndex != -1: if discardIntIndex != -1: raise "Found two returned ints to discard?!" discardIntIndex = returnIntIndex returnIntIndex = index index += 1 #Record the migrated return value's ParamStruct if returnIntIndex != -1: newReturnStructsDict[functionName] = paramStructs[returnIntIndex] #Return the discarded value's ParamStruct if discardIntIndex != -1: newDiscardedStructsDict[functionName] = paramStructs[discardIntIndex] #Copy the parsed parameters and remove those we're going to migrate or discard newParamStructs = [paramStructs[count] for count in range(len(paramStructs)) if count not in (discardIntIndex, returnIntIndex)] #Indices of input offsets and lengths offsetIndices = [] lengthIndices = [] #Scan through looking for void pointer, add an int offset index = 0 while 1: if index >= len(newParamStructs): break p = newParamStructs[index] if p.isPtr and p.type=="void": newp = ParamStruct() newp.type = "int" newp.isPtr = 0 newp.isOut = 0 newp.category = "rawType" newp.name = p.name+"Offset" newParamStructs = newParamStructs[:index+1] + [newp] + newParamStructs[index+1:] offsetIndices.append(index+1) if not p.isOut and len(newParamStructs)> index+2 and newParamStructs[index+2].type == "int": lengthIndices.append(index+2) index += 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -