📄 cryptlibconverter.py
字号:
#Add processed list of ParamStructs to dictionary #This will be used later, when generating the .c glue code newParamStructsDict[functionName] = newParamStructs lengthIndicesDict[functionName] = lengthIndices offsetIndicesDict[functionName] = offsetIndices #Used for Python if wholeFunctionDeclaration: newFunction = wholeFunctionDeclaration % functionName if sFuncs: sFuncs += newFunction + "\n" else: assert(0) sModFuncs += (moduleFunctionEntry % (functionName, functionName)) + "\n" else: #Java #Construct new function declaration from language-specific templates newFunction = functionDeclaration if returnIntIndex != -1: if newReturnStructsDict.get(functionName).category == "structType": newFunction += newReturnStructsDict.get(functionName).type + " " else: newFunction += returnIntDeclaration else: newFunction += returnVoidDeclaration newFunction += functionName + paramsPrefix if len(newParamStructs): newFunction += "\n" + paramWhiteSpace if offsetIndices or lengthIndices: newFunctionWrapper = newFunction newFunctionWrapperArgs = "" else: newFunctionWrapper = None #At this point I'm just getting lazy. Basically, we automatically generate #String wrappers for function that take void* input parameters. Encrypt and #Decrypt take void* in/out parameters. We should be smart enough to detect #these and not generate wrappers for them, but instead, since we don't otherwise #differentiate between C_IN and C_INOUT, we just hardcodedly exclude these #from having String wrappers if offsetIndices and lengthIndices and functionName not in ("Encrypt", "Decrypt"): newFunctionStringWrapper = newFunction newFunctionStringWrapperArgs = "" else: newFunctionStringWrapper = None newFunctionStringWrapperArgs = "" index = 0 for p in newParamStructs: if p.category == "rawType" and p.type == "void" and p.isPtr: template = paramVoidPtrTemplate previousBufferName = p.name elif p.category == "rawType" and p.type == "char" and p.isPtr: template = paramCharPtrTemplate elif p.category == "rawType" and p.type == "int" and not p.isPtr: template = paramIntTemplate elif p.category == "intType" and not p.isPtr: template = paramIntTypeTemplate elif p.category == "enumType" and not p.isPtr: template = paramEnumTypeTemplate #elif p.category == "structType" else: raise "Unrecognized parameter type! " + str(p) #Strip out commas from the last param template, kind of a hack.. if index == len(newParamStructs)-1: template = template[:].replace(",", "") #Update the main function with this new param newFunction += template % vars(p) newFunction += paramWhiteSpace #Update the wrapper function with this new param #If this is not a special param... if addFunctionWrappers and newFunctionWrapper and \ index not in offsetIndices and index not in lengthIndices: #Determine if this is the last param in the wrapper function anyMoreParams = [e for e in range(index+1, len(newParamStructs)) if e not in offsetIndices and e not in lengthIndices] #Update the wrapper function's param list if not anyMoreParams: template = template[:].replace(",", "") newFunctionWrapper += template % vars(p) newFunctionWrapper += paramWhiteSpace #Update the wrapper function's args that it uses to call the main function newFunctionWrapperArgs += p.name newFunctionWrapperArgs += ", " #Do the same things for the string wrapper if newFunctionStringWrapper: newFunctionStringWrapper += template % vars(p) newFunctionStringWrapper += paramWhiteSpace if p.type=="void" and p.isPtr and not p.isOut: newFunctionStringWrapperArgs += wrapperStringTemplate % {"1":p.name}; else: newFunctionStringWrapperArgs += p.name newFunctionStringWrapperArgs += ", " else: #If this is a special param (an offset or length)... if index in offsetIndices: newFunctionWrapperArgs += "0, " newFunctionStringWrapperArgs += "0, " elif index in lengthIndices: newFunctionWrapperArgs += wrapperLengthTemplate % {"1":previousBufferName} newFunctionStringWrapperArgs += wrapperStringLengthTemplate % {"1":previousBufferName} index += 1 #Add final postfix of ); to the main and wrapper param lists newFunction += paramsPostfix if newFunctionWrapper: newFunctionWrapper += paramsPostfix if newFunctionStringWrapper: newFunctionStringWrapper += paramsPostfix #If this function takes a void* parameter, and we want to convert this #into two different versions, duplicate and modify the version here if addFunctionAlternate: if newFunction.find(paramVoidPtrAlternate[0]) != -1: newFunction += "\n" + newFunction.replace(*paramVoidPtrAlternate) #If we've prepared a wrapper function to eliminate need for offset[, length]: if addFunctionWrappers and newFunctionWrapper: newFunctionWrapper = newFunctionWrapper.replace("native ", "") newFunctionWrapper = newFunctionWrapper[:-1] + " { return %s(%s); }" % (functionName, newFunctionWrapperArgs[:-2]) if returnIntIndex == -1: newFunctionWrapper = newFunctionWrapper.replace("return ", "") #Duplicate and modify the wrapper function if addFunctionAlternate: newFunctionWrapper2 = newFunctionWrapper.replace(*paramVoidPtrAlternate) newFunctionWrapper2 = newFunctionWrapper2.replace("capacity()", "length") newFunctionWrapper += "\n" + newFunctionWrapper2 newFunction += "\n" + newFunctionWrapper if addFunctionWrappers and newFunctionStringWrapper: newFunctionStringWrapper = newFunctionStringWrapper.replace("native ", "") newFunctionStringWrapper = newFunctionStringWrapper[:-1] + " { return %s(%s); }" % (functionName, newFunctionStringWrapperArgs[:-2]) newFunctionStringWrapper = newFunctionStringWrapper.replace(*wrapperStringReplace) if returnIntIndex == -1: newFunctionStringWrapper = newFunctionStringWrapper.replace("return ", "") newFunction += "\n" + newFunctionStringWrapper #Add a special-case string accessor for GetAttributeString() to Java and .NET if functionName == "GetAttributeString" and language == "java": newFunction += """public static String GetAttributeString( int cryptHandle, // CRYPT_HANDLE int attributeType // CRYPT_ATTRIBUTE_TYPE ) throws CryptException { int length = GetAttributeString(cryptHandle, attributeType, (byte[])null); byte[] bytes = new byte[length]; length = GetAttributeString(cryptHandle, attributeType, bytes); return new String(bytes, 0, length); }""" elif functionName == "GetAttributeString" and language == "net": newFunction += """public static String GetAttributeString( int cryptHandle, // CRYPT_HANDLE int attributeType // CRYPT_ATTRIBUTE_TYPE ) { int length = GetAttributeString(cryptHandle, attributeType, null); byte[] bytes = new byte[length]; length = GetAttributeString(cryptHandle, attributeType, bytes); return new UTF8Encoding().GetString(bytes, 0, length); }""" #Add special-case functions for cryptAddRandom(), since it allows NULL as a #first parameter, and a pollType constant in place of the length elif functionName == "AddRandom": if language == "java": newFunction += """public static native void AddRandom( int pollType ) throws CryptException;""" elif language == "net": newFunction += """public static void AddRandom( int pollType );""" # Add an extra linebreak between functions # This isn't in cryptlib.h, but it makes the converted files more readable if s[functionMatch.end()+1] != "\n": newFunction += "\n" s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ] functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))#Translate comments#-------------------if language != "java" and language != "net": while 1: match = re.search(r"/\*(.*?)\*/", s, re.DOTALL) if match == None: break #print match.group() #raw_input() commentStrings = (commentPrefix + match.group(1) + " ").split("\n") newComment = commentStrings[0] for commentString in commentStrings[1:]: if commentString.startswith("\t"): newComment += "\n" + commentPrefix + (" " * (inFileTabSize-2)) + commentString[1:] elif commentString.startswith(" "): newComment += "\n" + commentPrefix + commentString[1:] else: newComment += "\n" + commentPrefix + commentString #print "building up:\n", newComment #raw_input() idx = commentString.find("\n") s = s[ : match.start()] + newComment + s[match.end() : ]#Indent each line by one tab#---------------------------s = s.replace("\n", "\n\t")#Write out file(s)#Then generate the .h/.c files necessary for language integration#At this point it's easier to just hardcode constants and have#separate python and java codepaths#---------------if language=="java": #Add enclosing class syntax #--------------------------- s = classPrefix + s + classPostfix os.chdir(outDir) if not os.path.exists("cryptlib"): os.mkdir("./cryptlib") os.chdir("./cryptlib") print "Writing java files..." f = open("crypt.java", "w") f.write(s) f.close() f = open("CryptException.java", "w") f.write(exceptionString) f.close() f = open("CRYPT_QUERY_INFO.java", "w") f.write(cryptQueryInfoString) f.close() f = open("CRYPT_OBJECT_INFO.java", "w") f.write(cryptObjectInfoString) f.close() print "Compiling java files..." print os.popen4("javac -classpath .. crypt.java")[1].read() #Compile java file print os.popen4("javac -classpath .. CryptException.java")[1].read() #Compile java file print os.popen4("javac -classpath .. CRYPT_QUERY_INFO.java")[1].read() #Compile java file print os.popen4("javac -classpath .. CRYPT_OBJECT_INFO.java")[1].read() #Compile java file os.chdir("..") print "Generating jar file..." print os.popen4("jar cf cryptlib.jar cryptlib/crypt.class cryptlib/CryptException.class cryptlib/CRYPT_QUERY_INFO.class cryptlib/CRYPT_OBJECT_INFO.class cryptlib")[1].read() print "Generating JNI header file..." print os.popen4("javah -classpath . -o cryptlib_jni.h -jni cryptlib.crypt")[1].read() #Generate C header s = open("cryptlib_jni.h").read() os.remove("cryptlib_jni.h") print "Generating JNI source file..." #Now we take cryptlib_jni.h and derive the .c file from it #Strip off headers and footers #startIndex = s.find("/*\n * Class") #endIndex = s.find("#ifdef", startIndex) #s = s[startIndex : endIndex] startIndex = s.find("#undef") endIndex = s.find("/*\n * Class", startIndex) sold = s s = s[startIndex : endIndex] startIndex = endIndex endIndex = sold.find("#ifdef", startIndex) s2 = sold[startIndex : endIndex] #Add includes and helper functions #Note that we assume "cryptlib.h" is one directory behind us s = r"""#include "../crypt.h"#ifdef USE_JAVA#include <jni.h>#include <stdio.h> //printf#include <stdlib.h> //malloc, free%s/* Helper Functions */int processStatus(JNIEnv *env, jint status){ jclass exClass; jmethodID exConstructor; jthrowable obj; if (status >= cryptlib_crypt_OK) return 1; exClass = (*env)->FindClass(env, "cryptlib/CryptException"); if (exClass == 0) { printf("java_jni.c:processStatus - no class?!\n"); return 0; } exConstructor = (*env)->GetMethodID(env, exClass, "<init>", "(I)V"); if (exConstructor == 0) { printf("java_jni.c:processStatus - no constructor?!\n"); return 0; } obj = (*env)->NewObject(env, exClass, exConstructor, status); if (obj == 0) { printf("java_jni.c:processStatus - no object?!\n"); return 0; } if ((*env)->Throw(env, obj) < 0) { printf("java_jni.c:processStatus - failed to throw?!\n"); return 0; } return 0;}jobject processStatusReturnCryptQueryInfo(JNIEnv *env, int status, CRYPT_QUERY_INFO returnValue){ jclass exClass; jmethodID exConstructor; jstring algoName; jobject obj; if (status < cryptlib_crypt_OK) return NULL; exClass = (*env)->FindClass(env, "cryptlib/CRYPT_QUERY_INFO"); if (exClass == 0) { printf("java_jni.c:processStatusReturnCryptQueryInfo - no class?!\n"); return NULL; } exConstructor = (*env)->GetMethodID(env, exClass, "<init>", "(Ljava/lang/String;IIII)V"); if (exConstructor == 0) { printf("java_jni.c:processStatusReturnCryptQueryInfo - no constructor?!\n"); return NULL; } algoName = (*env)->NewStringUTF(env, returnValue.algoName); obj = (*env)->NewObject(env, exClass, exConstructor, algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize); if (obj == 0) { printf("java_jni.c:processStatusReturnCryptQueryInfo - no object?!\n"); return NULL; } return obj;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -