| /* 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++) { |
| sprintf(buf, "%s.", _this->verString[i]); |
| strcat(tmp, buf); |
| } |
| if (i < _this->numDigits) { |
| sprintf(buf, "%s", _this->verString[i]); |
| strcat(tmp, buf); |
| } |
| |
| ret = PR_Strdup(tmp); |
| free(tmp); |
| |
| return ret; |
| } |
| |
| /* |
| ////////////////////////////////////////////////////////////////////////// |
| // Method: Print |
| // Class: Pk11Install_PlatformName |
| */ |
| void |
| Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad) |
| { |
| 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); |
| } |
| } |