/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "install-ds.h" #include #include #include #include #define PORT_Strcasecmp PL_strcasecmp #define MODULE_FILE_STRING "ModuleFile" #define MODULE_NAME_STRING "ModuleName" #define MECH_FLAGS_STRING "DefaultMechanismFlags" #define CIPHER_FLAGS_STRING "DefaultCipherFlags" #define FILES_STRING "Files" #define FORWARD_COMPATIBLE_STRING "ForwardCompatible" #define PLATFORMS_STRING "Platforms" #define RELATIVE_DIR_STRING "RelativePath" #define ABSOLUTE_DIR_STRING "AbsolutePath" #define FILE_PERMISSIONS_STRING "FilePermissions" #define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform" #define EXECUTABLE_STRING "Executable" #define DEFAULT_PERMISSIONS 0777 #define PLATFORM_SEPARATOR_CHAR ':' /* Error codes */ enum { BOGUS_RELATIVE_DIR=0, BOGUS_ABSOLUTE_DIR, BOGUS_FILE_PERMISSIONS, NO_RELATIVE_DIR, NO_ABSOLUTE_DIR, EMPTY_PLATFORM_STRING, BOGUS_PLATFORM_STRING, REPEAT_MODULE_FILE, REPEAT_MODULE_NAME, BOGUS_MODULE_FILE, BOGUS_MODULE_NAME, REPEAT_MECH, BOGUS_MECH_FLAGS, REPEAT_CIPHER, BOGUS_CIPHER_FLAGS, REPEAT_FILES, REPEAT_EQUIV, BOGUS_EQUIV, EQUIV_TOO_MUCH_INFO, NO_FILES, NO_MODULE_FILE, NO_MODULE_NAME, NO_PLATFORMS, EQUIV_LOOP, UNKNOWN_MODULE_FILE }; /* Indexed by the above error codes */ static const char *errString[] = { "%s: Invalid relative directory", "%s: Invalid absolute directory", "%s: Invalid file permissions", "%s: No relative directory specified", "%s: No absolute directory specified", "Empty string given for platform name", "%s: invalid platform string", "More than one ModuleFile entry given for platform %s", "More than one ModuleName entry given for platform %s", "Invalid ModuleFile specification for platform %s", "Invalid ModuleName specification for platform %s", "More than one DefaultMechanismFlags entry given for platform %s", "Invalid DefaultMechanismFlags specification for platform %s", "More than one DefaultCipherFlags entry given for platform %s", "Invalid DefaultCipherFlags entry given for platform %s", "More than one Files entry given for platform %s", "More than one EquivalentPlatform entry given for platform %s", "Invalid EquivalentPlatform specification for platform %s", "Module %s uses an EquivalentPlatform but also specifies its own" " information", "No Files specification in module %s", "No ModuleFile specification in module %s", "No ModuleName specification in module %s", "No Platforms specification in installer script", "Platform %s has an equivalency loop", "Module file \"%s\" in platform \"%s\" does not exist" }; static char* PR_Strdup(const char* str); #define PAD(x) {int i; for(i=0;ijarPath=NULL; _this->relativePath=NULL; _this->absolutePath=NULL; _this->executable=PR_FALSE; _this->permissions=0; } /* ////////////////////////////////////////////////////////////////////////// // Method: ~Pk11Install_File // Class: Pk11Install_File // Notes: Destructor. */ void Pk11Install_File_delete(Pk11Install_File* _this) { Pk11Install_File_Cleanup(_this); } /* ////////////////////////////////////////////////////////////////////////// // Method: Cleanup // Class: Pk11Install_File */ void Pk11Install_File_Cleanup(Pk11Install_File* _this) { if(_this->jarPath) { PR_Free(_this->jarPath); _this->jarPath = NULL; } if(_this->relativePath) { PR_Free(_this->relativePath); _this->relativePath = NULL; } if(_this->absolutePath) { PR_Free(_this->absolutePath); _this->absolutePath = NULL; } _this->permissions = 0; _this->executable = PR_FALSE; } /* ////////////////////////////////////////////////////////////////////////// // Method: Generate // Class: Pk11Install_File // Notes: Creates a file data structure from a syntax tree. // Returns: NULL for success, otherwise an error message. */ char* Pk11Install_File_Generate(Pk11Install_File* _this, const Pk11Install_Pair *pair) { Pk11Install_ListIter *iter; Pk11Install_Value *val; Pk11Install_Pair *subpair; Pk11Install_ListIter *subiter; Pk11Install_Value *subval; char* errStr; char *endp; PRBool gotPerms; iter=NULL; subiter=NULL; errStr=NULL; gotPerms=PR_FALSE; /* Clear out old values */ Pk11Install_File_Cleanup(_this); _this->jarPath = PR_Strdup(pair->key); /* Go through all the pairs under this file heading */ iter = Pk11Install_ListIter_new(pair->list); for( ; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) { if(val->type == PAIR_VALUE) { subpair = val->pair; /* Relative directory */ if(!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) { subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE)){ errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR], _this->jarPath); goto loser; } _this->relativePath = PR_Strdup(subval->string); Pk11Install_ListIter_delete(subiter); subiter = NULL; /* Absolute directory */ } else if( !PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) { subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE)){ errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR], _this->jarPath); goto loser; } _this->absolutePath = PR_Strdup(subval->string); Pk11Install_ListIter_delete(subiter); subiter = NULL; /* file permissions */ } else if( !PORT_Strcasecmp(subpair->key, FILE_PERMISSIONS_STRING)) { subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE) || !subval->string || !subval->string[0]){ errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS], _this->jarPath); goto loser; } _this->permissions = (int) strtol(subval->string, &endp, 8); if(*endp != '\0') { errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS], _this->jarPath); goto loser; } gotPerms = PR_TRUE; Pk11Install_ListIter_delete(subiter); subiter = NULL; } } else { if(!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) { _this->executable = PR_TRUE; } } } /* Default permission value */ if(!gotPerms) { _this->permissions = DEFAULT_PERMISSIONS; } /* Make sure we got all the information */ if(!_this->relativePath && !_this->absolutePath) { errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath); goto loser; } #if 0 if(!_this->relativePath ) { errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath); goto loser; } if(!_this->absolutePath) { errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath); goto loser; } #endif loser: if(iter) { Pk11Install_ListIter_delete(iter); PR_Free(iter); } if(subiter) { Pk11Install_ListIter_delete(subiter); PR_Free(subiter); } return errStr; } /* ////////////////////////////////////////////////////////////////////////// // Method: Print // Class: Pk11Install_File */ void Pk11Install_File_Print(Pk11Install_File* _this, int pad) { PAD(pad); printf("jarPath: %s\n", _this->jarPath ? _this->jarPath : ""); PAD(pad); printf("relativePath: %s\n", _this->relativePath ? _this->relativePath: ""); PAD(pad); printf("absolutePath: %s\n", _this->absolutePath ? _this->absolutePath: ""); PAD(pad); printf("permissions: %o\n", _this->permissions); } Pk11Install_PlatformName* Pk11Install_PlatformName_new() { Pk11Install_PlatformName* new_this; new_this = (Pk11Install_PlatformName*) PR_Malloc(sizeof(Pk11Install_PlatformName)); Pk11Install_PlatformName_init(new_this); return new_this; } void Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this) { _this->OS = NULL; _this->verString = NULL; _this->numDigits = 0; _this->arch = NULL; } /* ////////////////////////////////////////////////////////////////////////// // Method: ~Pk11Install_PlatformName // Class: Pk11Install_PlatformName */ void Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this) { Pk11Install_PlatformName_Cleanup(_this); } /* ////////////////////////////////////////////////////////////////////////// // Method: Cleanup // Class: Pk11Install_PlatformName */ void Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this) { if(_this->OS) { PR_Free(_this->OS); _this->OS = NULL; } if(_this->verString) { int i; for (i=0; i<_this->numDigits; i++) { PR_Free(_this->verString[i]); } PR_Free(_this->verString); _this->verString = NULL; } if(_this->arch) { PR_Free(_this->arch); _this->arch = NULL; } _this->numDigits = 0; } /* ////////////////////////////////////////////////////////////////////////// // Method: Generate // Class: Pk11Install_PlatformName // Notes: Extracts the information from a platform string. */ char* Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this, const char *str) { char *errStr; char *copy; char *end, *start; /* start and end of a section (OS, version, arch)*/ char *pend, *pstart; /* start and end of one portion of version*/ char *endp; /* used by strtol*/ int periods, i; errStr=NULL; copy=NULL; if(!str) { errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]); goto loser; } copy = PR_Strdup(str); /* // Get the OS */ end = strchr(copy, PLATFORM_SEPARATOR_CHAR); if(!end || end==copy) { errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); goto loser; } *end = '\0'; _this->OS = PR_Strdup(copy); /* // Get the digits of the version of form: x.x.x (arbitrary number of digits) */ start = end+1; end = strchr(start, PLATFORM_SEPARATOR_CHAR); if(!end) { errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); goto loser; } *end = '\0'; if(end!=start) { /* Find out how many periods*/ periods = 0; pstart = start; while( (pend=strchr(pstart, '.')) ) { periods++; pstart = pend+1; } _this->numDigits= 1+ periods; _this->verString = (char**)PR_Malloc(sizeof(char*)*_this->numDigits); pstart = start; i = 0; /* Get the digits before each period*/ while( (pend=strchr(pstart, '.')) ) { if(pend == pstart) { errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); goto loser; } *pend = '\0'; _this->verString[i] = PR_Strdup(pstart); endp = pend; if(endp==pstart || (*endp != '\0')) { errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); goto loser; } pstart = pend+1; i++; } /* Last digit comes after the last period*/ if(*pstart == '\0') { errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); goto loser; } _this->verString[i] = PR_Strdup(pstart); /* if(endp==pstart || (*endp != '\0')) { errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); goto loser; } */ } else { _this->verString = NULL; _this->numDigits = 0; } /* // Get the architecture */ start = end+1; if( strchr(start, PLATFORM_SEPARATOR_CHAR) ) { errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str); goto loser; } _this->arch = PR_Strdup(start); if(copy) { PR_Free(copy); } return NULL; loser: if(_this->OS) { PR_Free(_this->OS); _this->OS = NULL; } if(_this->verString) { for (i=0; i<_this->numDigits; i++) { PR_Free(_this->verString[i]); } PR_Free(_this->verString); _this->verString = NULL; } _this->numDigits = 0; if(_this->arch) { PR_Free(_this->arch); _this->arch = NULL; } if(copy) { PR_Free(copy); } return errStr; } /* ////////////////////////////////////////////////////////////////////////// // Method: operator == // Class: Pk11Install_PlatformName // Returns: PR_TRUE if the platform have the same OS, arch, and version */ PRBool Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this, Pk11Install_PlatformName* cmp) { int i; if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) { return PR_FALSE; } if( PORT_Strcasecmp(_this->OS, cmp->OS) || PORT_Strcasecmp(_this->arch, cmp->arch) || _this->numDigits != cmp->numDigits ) { return PR_FALSE; } for(i=0; i < _this->numDigits; i++) { if(PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) { return PR_FALSE; } } return PR_TRUE; } /* ////////////////////////////////////////////////////////////////////////// // Method: operator <= // Class: Pk11Install_PlatformName // Returns: PR_TRUE if the platform have the same OS and arch and a lower // or equal release. */ PRBool Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this, Pk11Install_PlatformName* cmp) { return (Pk11Install_PlatformName_equal(_this,cmp) || Pk11Install_PlatformName_lt(_this,cmp)) ? PR_TRUE : PR_FALSE; } /* ////////////////////////////////////////////////////////////////////////// // Method: operator < // Class: Pk11Install_PlatformName // Returns: PR_TRUE if the platform have the same OS and arch and a greater // release. */ PRBool Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this, Pk11Install_PlatformName* cmp) { int i, scmp; if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) { return PR_FALSE; } if( PORT_Strcasecmp(_this->OS, cmp->OS) ) { return PR_FALSE; } if( PORT_Strcasecmp(_this->arch, cmp->arch) ) { return PR_FALSE; } for(i=0; (i < _this->numDigits) && (i < cmp->numDigits); i++) { scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]); if (scmp > 0) { return PR_FALSE; } else if (scmp < 0) { return PR_TRUE; } } /* All the digits they have in common are the same. */ if(_this->numDigits < cmp->numDigits) { return PR_TRUE; } return PR_FALSE; } /* ////////////////////////////////////////////////////////////////////////// // Method: GetString // Class: Pk11Install_PlatformName // Returns: String composed of OS, release, and architecture separated // by the separator char. Memory is allocated by this function // but is the responsibility of the caller to de-allocate. */ char* Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this) { char *ret; char *ver; char *OS_; char *arch_; OS_=NULL; arch_=NULL; OS_ = _this->OS ? _this->OS : ""; arch_ = _this->arch ? _this->arch : ""; ver = Pk11Install_PlatformName_GetVerString(_this); ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver, PLATFORM_SEPARATOR_CHAR, arch_); PR_Free(ver); return ret; } /* ////////////////////////////////////////////////////////////////////////// // Method: GetVerString // Class: Pk11Install_PlatformName // Returns: The version string for this platform, in the form x.x.x with an // arbitrary number of digits. Memory allocated by function, // must be de-allocated by caller. */ char* Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this) { char *tmp; char *ret; int i; char buf[80]; tmp = (char*)PR_Malloc(80*_this->numDigits+1); tmp[0] = '\0'; for(i=0; i < _this->numDigits-1; i++) { sprintf(buf, "%s.", _this->verString[i]); strcat(tmp, buf); } if(i < _this->numDigits) { sprintf(buf, "%s", _this->verString[i]); strcat(tmp, buf); } ret = PR_Strdup(tmp); free(tmp); return ret; } /* ////////////////////////////////////////////////////////////////////////// // Method: Print // Class: Pk11Install_PlatformName */ void Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad) { PAD(pad); printf("OS: %s\n", _this->OS ? _this->OS : ""); PAD(pad); printf("Digits: "); if(_this->numDigits == 0) { printf("None\n"); } else { printf("%s\n", Pk11Install_PlatformName_GetVerString(_this)); } PAD(pad); printf("arch: %s\n", _this->arch ? _this->arch : ""); } Pk11Install_Platform* Pk11Install_Platform_new() { Pk11Install_Platform* new_this; new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform)); Pk11Install_Platform_init(new_this); return new_this; } void Pk11Install_Platform_init(Pk11Install_Platform* _this) { Pk11Install_PlatformName_init(&_this->name); Pk11Install_PlatformName_init(&_this->equivName); _this->equiv = NULL; _this->usesEquiv = PR_FALSE; _this->moduleFile = NULL; _this->moduleName = NULL; _this->modFile = -1; _this->mechFlags = 0; _this->cipherFlags = 0; _this->files = NULL; _this->numFiles = 0; } /* ////////////////////////////////////////////////////////////////////////// // Method: ~Pk11Install_Platform // Class: Pk11Install_Platform */ void Pk11Install_Platform_delete(Pk11Install_Platform* _this) { Pk11Install_Platform_Cleanup(_this); } /* ////////////////////////////////////////////////////////////////////////// // Method: Cleanup // Class: Pk11Install_Platform */ void Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this) { int i; if(_this->moduleFile) { PR_Free(_this->moduleFile); _this->moduleFile = NULL; } if(_this->moduleName) { PR_Free(_this->moduleName); _this->moduleName = NULL; } if(_this->files) { for (i=0;i<_this->numFiles;i++) { Pk11Install_File_delete(&_this->files[i]); } PR_Free(_this->files); _this->files = NULL; } _this->equiv = NULL; _this->usesEquiv = PR_FALSE; _this->modFile = -1; _this->numFiles = 0; _this->mechFlags = _this->cipherFlags = 0; } /* ////////////////////////////////////////////////////////////////////////// // Method: Generate // Class: Pk11Install_Platform // Notes: Creates a platform data structure from a syntax tree. // Returns: NULL for success, otherwise an error message. */ char* Pk11Install_Platform_Generate(Pk11Install_Platform* _this, const Pk11Install_Pair *pair) { char* errStr; char* endptr; char* tmp; int i; Pk11Install_ListIter *iter; Pk11Install_Value *val; Pk11Install_Value *subval; Pk11Install_Pair *subpair; Pk11Install_ListIter *subiter; PRBool gotModuleFile, gotModuleName, gotMech, gotCipher, gotFiles, gotEquiv; errStr=NULL; iter=subiter=NULL; val=subval=NULL; subpair=NULL; gotModuleFile=gotModuleName=gotMech=gotCipher=gotFiles=gotEquiv=PR_FALSE; Pk11Install_Platform_Cleanup(_this); errStr = Pk11Install_PlatformName_Generate(&_this->name,pair->key); if(errStr) { tmp = PR_smprintf("%s: %s", pair->key, errStr); PR_smprintf_free(errStr); errStr = tmp; goto loser; } iter = Pk11Install_ListIter_new(pair->list); for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) { if(val->type==PAIR_VALUE) { subpair = val->pair; if( !PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) { if(gotModuleFile) { errStr = PR_smprintf(errString[REPEAT_MODULE_FILE], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE)) { errStr = PR_smprintf(errString[BOGUS_MODULE_FILE], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } _this->moduleFile = PR_Strdup(subval->string); Pk11Install_ListIter_delete(subiter); PR_Free(subiter); subiter = NULL; gotModuleFile = PR_TRUE; } else if(!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)){ if(gotModuleName) { errStr = PR_smprintf(errString[REPEAT_MODULE_NAME], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE)) { errStr = PR_smprintf(errString[BOGUS_MODULE_NAME], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } _this->moduleName = PR_Strdup(subval->string); Pk11Install_ListIter_delete(subiter); PR_Free(subiter); subiter = NULL; gotModuleName = PR_TRUE; } else if(!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) { endptr=NULL; if(gotMech) { errStr = PR_smprintf(errString[REPEAT_MECH], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE)) { errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } _this->mechFlags = strtol(subval->string, &endptr, 0); if(*endptr!='\0' || (endptr==subval->string) ) { errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } Pk11Install_ListIter_delete(subiter); PR_Free(subiter); subiter=NULL; gotMech = PR_TRUE; } else if(!PORT_Strcasecmp(subpair->key,CIPHER_FLAGS_STRING)) { endptr=NULL; if(gotCipher) { errStr = PR_smprintf(errString[REPEAT_CIPHER], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE)) { errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } _this->cipherFlags = strtol(subval->string, &endptr, 0); if(*endptr!='\0' || (endptr==subval->string) ) { errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } Pk11Install_ListIter_delete(subiter); PR_Free(subiter); subiter=NULL; gotCipher = PR_TRUE; } else if(!PORT_Strcasecmp(subpair->key, FILES_STRING)) { if(gotFiles) { errStr = PR_smprintf(errString[REPEAT_FILES], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } subiter = Pk11Install_ListIter_new(subpair->list); _this->numFiles = subpair->list->numPairs; _this->files = (Pk11Install_File*) PR_Malloc(sizeof(Pk11Install_File)*_this->numFiles); for(i=0; i < _this->numFiles; i++, Pk11Install_ListIter_nextItem(subiter)) { Pk11Install_File_init(&_this->files[i]); val = subiter->current; if(val && (val->type==PAIR_VALUE)) { errStr = Pk11Install_File_Generate(&_this->files[i],val->pair); if(errStr) { tmp = PR_smprintf("%s: %s", Pk11Install_PlatformName_GetString(&_this->name),errStr); PR_smprintf_free(errStr); errStr = tmp; goto loser; } } } gotFiles = PR_TRUE; } else if(!PORT_Strcasecmp(subpair->key, EQUIVALENT_PLATFORM_STRING)) { if(gotEquiv) { errStr = PR_smprintf(errString[REPEAT_EQUIV], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } subiter = Pk11Install_ListIter_new(subpair->list); subval = subiter->current; if(!subval || (subval->type != STRING_VALUE) ) { errStr = PR_smprintf(errString[BOGUS_EQUIV], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } errStr = Pk11Install_PlatformName_Generate(&_this->equivName, subval->string); if(errStr) { tmp = PR_smprintf("%s: %s", Pk11Install_PlatformName_GetString(&_this->name), errStr); tmp = PR_smprintf("%s: %s", Pk11Install_PlatformName_GetString(&_this->name), errStr); PR_smprintf_free(errStr); errStr = tmp; goto loser; } _this->usesEquiv = PR_TRUE; } } } /* Make sure we either have an EquivalentPlatform or all the other info */ if(_this->usesEquiv && (gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) { errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } if(!gotFiles && !_this->usesEquiv) { errStr = PR_smprintf(errString[NO_FILES], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } if(!gotModuleFile && !_this->usesEquiv) { errStr= PR_smprintf(errString[NO_MODULE_FILE], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } if(!gotModuleName && !_this->usesEquiv) { errStr = PR_smprintf(errString[NO_MODULE_NAME], Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } /* Point the modFile pointer to the correct file */ if(gotModuleFile) { for(i=0; i < _this->numFiles; i++) { if(!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath) ) { _this->modFile = i; break; } } if(_this->modFile==-1) { errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE], _this->moduleFile, Pk11Install_PlatformName_GetString(&_this->name)); goto loser; } } loser: if(iter) { PR_Free(iter); } if(subiter) { PR_Free(subiter); } return errStr; } /* ////////////////////////////////////////////////////////////////////////// // Method: Print // Class: Pk11Install_Platform */ void Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad) { int i; PAD(pad); printf("Name:\n"); Pk11Install_PlatformName_Print(&_this->name,pad+PADINC); PAD(pad); printf("equivName:\n"); Pk11Install_PlatformName_Print(&_this->equivName,pad+PADINC); PAD(pad); if(_this->usesEquiv) { printf("Uses equiv, which points to:\n"); Pk11Install_Platform_Print(_this->equiv,pad+PADINC); } else { printf("Doesn't use equiv\n"); } PAD(pad); printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile : ""); PAD(pad); printf("mechFlags: %lx\n", _this->mechFlags); PAD(pad); printf("cipherFlags: %lx\n", _this->cipherFlags); PAD(pad); printf("Files:\n"); for(i=0; i < _this->numFiles; i++) { Pk11Install_File_Print(&_this->files[i],pad+PADINC); PAD(pad); printf("--------------------\n"); } } /* ////////////////////////////////////////////////////////////////////////// // Method: Pk11Install_Info // Class: Pk11Install_Info */ Pk11Install_Info* Pk11Install_Info_new() { Pk11Install_Info* new_this; new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info)); Pk11Install_Info_init(new_this); return new_this; } void Pk11Install_Info_init(Pk11Install_Info* _this) { _this->platforms = NULL; _this->numPlatforms = 0; _this->forwardCompatible = NULL; _this->numForwardCompatible = 0; } /* ////////////////////////////////////////////////////////////////////////// // Method: ~Pk11Install_Info // Class: Pk11Install_Info */ void Pk11Install_Info_delete(Pk11Install_Info* _this) { Pk11Install_Info_Cleanup(_this); } /* ////////////////////////////////////////////////////////////////////////// // Method: Cleanup // Class: Pk11Install_Info */ void Pk11Install_Info_Cleanup(Pk11Install_Info* _this) { int i; if(_this->platforms) { for (i=0;i<_this->numPlatforms;i++) { Pk11Install_Platform_delete(&_this->platforms[i]); } PR_Free(&_this->platforms); _this->platforms = NULL; _this->numPlatforms = 0; } if(_this->forwardCompatible) { for (i=0;i<_this->numForwardCompatible;i++) { Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]); } PR_Free(&_this->forwardCompatible); _this->numForwardCompatible = 0; } } /* ////////////////////////////////////////////////////////////////////////// // Method: Generate // Class: Pk11Install_Info // Takes: Pk11Install_ValueList *list, the top-level list // resulting from parsing an installer file. // Returns: char*, NULL if successful, otherwise an error string. // Caller is responsible for freeing memory. */ char* Pk11Install_Info_Generate(Pk11Install_Info* _this, const Pk11Install_ValueList *list) { char *errStr; Pk11Install_ListIter *iter; Pk11Install_Value *val; Pk11Install_Pair *pair; Pk11Install_ListIter *subiter; Pk11Install_Value *subval; Pk11Install_Platform *first, *second; int i, j; errStr=NULL; iter=subiter=NULL; Pk11Install_Info_Cleanup(_this); iter = Pk11Install_ListIter_new(list); for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) { if(val->type == PAIR_VALUE) { pair = val->pair; if(!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) { subiter = Pk11Install_ListIter_new(pair->list); _this->numForwardCompatible = pair->list->numStrings; _this->forwardCompatible = (Pk11Install_PlatformName*) PR_Malloc(sizeof(Pk11Install_PlatformName)* _this->numForwardCompatible); for(i=0; i < _this->numForwardCompatible; i++, Pk11Install_ListIter_nextItem(subiter)) { subval = subiter->current; if(subval->type == STRING_VALUE) { errStr = Pk11Install_PlatformName_Generate( &_this->forwardCompatible[i], subval->string); if(errStr) { goto loser; } } } Pk11Install_ListIter_delete(subiter); PR_Free(subiter); subiter = NULL; } else if(!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) { subiter = Pk11Install_ListIter_new(pair->list); _this->numPlatforms = pair->list->numPairs; _this->platforms = (Pk11Install_Platform*) PR_Malloc(sizeof(Pk11Install_Platform)* _this->numPlatforms); for(i=0; i < _this->numPlatforms; i++, Pk11Install_ListIter_nextItem(subiter)) { Pk11Install_Platform_init(&_this->platforms[i]); subval = subiter->current; if(subval->type == PAIR_VALUE) { errStr = Pk11Install_Platform_Generate(&_this->platforms[i],subval->pair); if(errStr) { goto loser; } } } Pk11Install_ListIter_delete(subiter); PR_Free(subiter); subiter = NULL; } } } if(_this->numPlatforms == 0) { errStr = PR_smprintf(errString[NO_PLATFORMS]); goto loser; } /* // // Now process equivalent platforms // // First the naive pass */ for(i=0; i < _this->numPlatforms; i++) { if(_this->platforms[i].usesEquiv) { _this->platforms[i].equiv = NULL; for(j=0; j < _this->numPlatforms; j++) { if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName, &_this->platforms[j].name)) { if(i==j) { errStr = PR_smprintf(errString[EQUIV_LOOP], Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); goto loser; } _this->platforms[i].equiv = &_this->platforms[j]; break; } } if(_this->platforms[i].equiv == NULL) { errStr = PR_smprintf(errString[BOGUS_EQUIV], Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); goto loser; } } } /* // Now the intelligent pass, which will also detect loops. // We will send two pointers through the linked list of equivalent // platforms. Both start with the current node. "first" traverses // two nodes for each iteration. "second" lags behind, only traversing // one node per iteration. Eventually one of two things will happen: // first will hit the end of the list (a platform that doesn't use // an equivalency), or first will equal second if there is a loop. */ for(i=0; i < _this->numPlatforms; i++) { if(_this->platforms[i].usesEquiv) { second = _this->platforms[i].equiv; if(!second->usesEquiv) { /* The first link is the terminal node */ continue; } first = second->equiv; while(first->usesEquiv) { if(first == second) { errStr = PR_smprintf(errString[EQUIV_LOOP], Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); goto loser; } first = first->equiv; if(!first->usesEquiv) { break; } if(first == second) { errStr = PR_smprintf(errString[EQUIV_LOOP], Pk11Install_PlatformName_GetString(&_this->platforms[i].name)); goto loser; } second = second->equiv; first = first->equiv; } _this->platforms[i].equiv = first; } } loser: if(iter) { Pk11Install_ListIter_delete(iter); PR_Free(iter); iter = NULL; } if(subiter) { Pk11Install_ListIter_delete(subiter); PR_Free(subiter); subiter = NULL; } return errStr; } /* ////////////////////////////////////////////////////////////////////////// // Method: GetBestPlatform // Class: Pk11Install_Info // Takes: char *myPlatform, the platform we are currently running // on. */ Pk11Install_Platform* Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char *myPlatform) { Pk11Install_PlatformName plat; char *errStr; int i, j; errStr=NULL; Pk11Install_PlatformName_init(&plat); if( (errStr=Pk11Install_PlatformName_Generate(&plat, myPlatform)) ) { PR_smprintf_free(errStr); return NULL; } /* First try real platforms */ for(i=0; i < _this->numPlatforms; i++) { if(Pk11Install_PlatformName_equal(&_this->platforms[i].name,&plat)) { if(_this->platforms[i].equiv) { return _this->platforms[i].equiv; } else { return &_this->platforms[i]; } } } /* Now try forward compatible platforms */ for(i=0; i < _this->numForwardCompatible; i++) { if(Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i],&plat)) { break; } } if(i == _this->numForwardCompatible) { return NULL; } /* Got a forward compatible name, find the actual platform. */ for(j=0; j < _this->numPlatforms; j++) { if(Pk11Install_PlatformName_equal(&_this->platforms[j].name, &_this->forwardCompatible[i])) { if(_this->platforms[j].equiv) { return _this->platforms[j].equiv; } else { return &_this->platforms[j]; } } } return NULL; } /* ////////////////////////////////////////////////////////////////////////// // Method: Print // Class: Pk11Install_Info */ void Pk11Install_Info_Print(Pk11Install_Info* _this, int pad) { int i; PAD(pad); printf("Forward Compatible:\n"); for(i = 0; i < _this->numForwardCompatible; i++) { Pk11Install_PlatformName_Print(&_this->forwardCompatible[i],pad+PADINC); PAD(pad); printf("-------------------\n"); } PAD(pad); printf("Platforms:\n"); for( i = 0; i < _this->numPlatforms; i++) { Pk11Install_Platform_Print(&_this->platforms[i],pad+PADINC); PAD(pad); printf("-------------------\n"); } } /* ////////////////////////////////////////////////////////////////////////// */ static char* PR_Strdup(const char* str) { char *tmp; tmp = (char*) PR_Malloc((unsigned int)(strlen(str)+1)); strcpy(tmp, str); return tmp; } /* The global value list, the top of the tree */ Pk11Install_ValueList* Pk11Install_valueList=NULL; /****************************************************************************/ void Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this, Pk11Install_Value *item) { _this->numItems++; if (item->type == STRING_VALUE) { _this->numStrings++; } else { _this->numPairs++; } item->next = _this->head; _this->head = item; } /****************************************************************************/ Pk11Install_ListIter* Pk11Install_ListIter_new_default() { Pk11Install_ListIter* new_this; new_this = (Pk11Install_ListIter*) PR_Malloc(sizeof(Pk11Install_ListIter)); Pk11Install_ListIter_init(new_this); return new_this; } /****************************************************************************/ void Pk11Install_ListIter_init(Pk11Install_ListIter* _this) { _this->list = NULL; _this->current = NULL; } /****************************************************************************/ Pk11Install_ListIter* Pk11Install_ListIter_new(const Pk11Install_ValueList *_list) { Pk11Install_ListIter* new_this; new_this = (Pk11Install_ListIter*) PR_Malloc(sizeof(Pk11Install_ListIter)); new_this->list = _list; new_this->current = _list->head; return new_this; } /****************************************************************************/ void Pk11Install_ListIter_delete(Pk11Install_ListIter* _this) { _this->list=NULL; _this->current=NULL; } /****************************************************************************/ void Pk11Install_ListIter_reset(Pk11Install_ListIter* _this) { if(_this->list) { _this->current = _this->list->head; } } /*************************************************************************/ Pk11Install_Value* Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this) { if(_this->current) { _this->current = _this->current->next; } return _this->current; } /****************************************************************************/ Pk11Install_ValueList* Pk11Install_ValueList_new() { Pk11Install_ValueList* new_this; new_this = (Pk11Install_ValueList*) PR_Malloc(sizeof(Pk11Install_ValueList)); new_this->numItems = 0; new_this->numPairs = 0; new_this->numStrings = 0; new_this->head = NULL; return new_this; } /****************************************************************************/ void Pk11Install_ValueList_delete(Pk11Install_ValueList* _this) { Pk11Install_Value *tmp; Pk11Install_Value *list; list = _this->head; while(list != NULL) { tmp = list; list = list->next; PR_Free(tmp); } PR_Free(_this); } /****************************************************************************/ Pk11Install_Value* Pk11Install_Value_new_default() { Pk11Install_Value* new_this; new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value)); new_this->type = STRING_VALUE; new_this->string = NULL; new_this->pair = NULL; new_this->next = NULL; return new_this; } /****************************************************************************/ Pk11Install_Value* Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr) { Pk11Install_Value* new_this; new_this = Pk11Install_Value_new_default(); new_this->type = _type; if(_type == STRING_VALUE) { new_this->pair = NULL; new_this->string = ptr.string; } else { new_this->string = NULL; new_this->pair = ptr.pair; } return new_this; } /****************************************************************************/ void Pk11Install_Value_delete(Pk11Install_Value* _this) { if(_this->type == STRING_VALUE) { PR_Free(_this->string); } else { PR_Free(_this->pair); } } /****************************************************************************/ Pk11Install_Pair* Pk11Install_Pair_new_default() { return Pk11Install_Pair_new(NULL,NULL); } /****************************************************************************/ Pk11Install_Pair* Pk11Install_Pair_new(char *_key, Pk11Install_ValueList *_list) { Pk11Install_Pair* new_this; new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair)); new_this->key = _key; new_this->list = _list; return new_this; } /****************************************************************************/ void Pk11Install_Pair_delete(Pk11Install_Pair* _this) { PR_Free(_this->key); Pk11Install_ValueList_delete(_this->list); PR_Free(_this->list); } /*************************************************************************/ void Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad) { while (_this) { /*PAD(pad); printf("**Pair\n"); PAD(pad); printf("***Key====\n");*/ PAD(pad); printf("%s {\n", _this->key); /*PAD(pad); printf("====\n");*/ /*PAD(pad); printf("***ValueList\n");*/ Pk11Install_ValueList_Print(_this->list,pad+PADINC); PAD(pad); printf("}\n"); } } /*************************************************************************/ void Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad) { Pk11Install_Value *v; /*PAD(pad);printf("**Value List**\n");*/ for(v = _this->head; v != NULL; v=v->next) { Pk11Install_Value_Print(v,pad); } } /*************************************************************************/ void Pk11Install_Value_Print(Pk11Install_Value* _this, int pad) { /*PAD(pad); printf("**Value, type=%s\n", type==STRING_VALUE ? "string" : "pair");*/ if(_this->type==STRING_VALUE) { /*PAD(pad+PADINC); printf("====\n");*/ PAD(pad); printf("%s\n", _this->string); /*PAD(pad+PADINC); printf("====\n");*/ } else { Pk11Install_Pair_Print(_this->pair,pad+PADINC); } }