diff options
Diffstat (limited to 'security/nss/cmd/modutil/install-ds.c')
-rw-r--r-- | security/nss/cmd/modutil/install-ds.c | 1522 |
1 files changed, 1522 insertions, 0 deletions
diff --git a/security/nss/cmd/modutil/install-ds.c b/security/nss/cmd/modutil/install-ds.c new file mode 100644 index 0000000000..d4ea73eda6 --- /dev/null +++ b/security/nss/cmd/modutil/install-ds.c @@ -0,0 +1,1522 @@ +/* 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 <prmem.h> +#include <plstr.h> +#include <prprf.h> +#include <string.h> + +#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 pad_i; \ + for (pad_i = 0; pad_i < (x); pad_i++) \ + printf(" "); \ + } +#define PADINC 4 + +Pk11Install_File* +Pk11Install_File_new() +{ + Pk11Install_File* new_this; + new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File)); + Pk11Install_File_init(new_this); + return new_this; +} + +void +Pk11Install_File_init(Pk11Install_File* _this) +{ + _this->jarPath = 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); + + /* 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); + + /* 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); + } + } 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); + } + if (subiter) { + Pk11Install_ListIter_delete(&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 : "<NULL>"); + PAD(pad); + printf("relativePath: %s\n", + _this->relativePath ? _this->relativePath : "<NULL>"); + PAD(pad); + printf("absolutePath: %s\n", + _this->absolutePath ? _this->absolutePath : "<NULL>"); + 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++) { + snprintf(buf, sizeof(buf), "%s.", _this->verString[i]); + strcat(tmp, buf); + } + if (i < _this->numDigits) { + snprintf(buf, sizeof(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) +{ + char* str = NULL; + PAD(pad); + printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>"); + PAD(pad); + printf("Digits: "); + if (_this->numDigits == 0) { + printf("None\n"); + } else { + str = Pk11Install_PlatformName_GetVerString(_this); + printf("%s\n", str); + PR_Free(str); + } + PAD(pad); + printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>"); +} + +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); + 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); + 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); + 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); + 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); + 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 : "<NULL>"); + 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); + } 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); + } + } + } + + 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); + } + if (subiter) { + Pk11Install_ListIter_delete(&subiter); + } + 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; + PR_Free(*_this); + *_this = 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); +} + +/*************************************************************************/ +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); + } +} |