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