Source code

Revision control

Copy as Markdown

Other Tools

/* 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);
}
}