security/nss/cmd/modutil/install-ds.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/modutil/install-ds.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1513 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "install-ds.h"
     1.9 +#include <prmem.h>
    1.10 +#include <plstr.h>
    1.11 +#include <prprf.h>
    1.12 +#include <string.h>
    1.13 +
    1.14 +#define PORT_Strcasecmp PL_strcasecmp
    1.15 +
    1.16 +#define MODULE_FILE_STRING "ModuleFile"
    1.17 +#define MODULE_NAME_STRING "ModuleName"
    1.18 +#define MECH_FLAGS_STRING "DefaultMechanismFlags"
    1.19 +#define CIPHER_FLAGS_STRING "DefaultCipherFlags"
    1.20 +#define FILES_STRING "Files"
    1.21 +#define FORWARD_COMPATIBLE_STRING "ForwardCompatible"
    1.22 +#define PLATFORMS_STRING "Platforms"
    1.23 +#define RELATIVE_DIR_STRING "RelativePath"
    1.24 +#define ABSOLUTE_DIR_STRING "AbsolutePath"
    1.25 +#define FILE_PERMISSIONS_STRING "FilePermissions"
    1.26 +#define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform"
    1.27 +#define EXECUTABLE_STRING "Executable"
    1.28 +
    1.29 +#define DEFAULT_PERMISSIONS 0777
    1.30 +
    1.31 +#define PLATFORM_SEPARATOR_CHAR ':'
    1.32 +
    1.33 +/* Error codes */
    1.34 +enum {
    1.35 +	BOGUS_RELATIVE_DIR=0,
    1.36 +	BOGUS_ABSOLUTE_DIR,
    1.37 +	BOGUS_FILE_PERMISSIONS,
    1.38 +	NO_RELATIVE_DIR,
    1.39 +	NO_ABSOLUTE_DIR,
    1.40 +	EMPTY_PLATFORM_STRING,
    1.41 +	BOGUS_PLATFORM_STRING,
    1.42 +	REPEAT_MODULE_FILE,
    1.43 +	REPEAT_MODULE_NAME,
    1.44 +	BOGUS_MODULE_FILE,
    1.45 +	BOGUS_MODULE_NAME,
    1.46 +	REPEAT_MECH,
    1.47 +	BOGUS_MECH_FLAGS,
    1.48 +	REPEAT_CIPHER,
    1.49 +	BOGUS_CIPHER_FLAGS,
    1.50 +	REPEAT_FILES,
    1.51 +	REPEAT_EQUIV,
    1.52 +	BOGUS_EQUIV,
    1.53 +	EQUIV_TOO_MUCH_INFO,
    1.54 +	NO_FILES,
    1.55 +	NO_MODULE_FILE,
    1.56 +	NO_MODULE_NAME,
    1.57 +	NO_PLATFORMS,
    1.58 +	EQUIV_LOOP,
    1.59 +	UNKNOWN_MODULE_FILE
    1.60 +};
    1.61 +
    1.62 +/* Indexed by the above error codes */
    1.63 +static const char *errString[] = {
    1.64 +	"%s: Invalid relative directory",
    1.65 +	"%s: Invalid absolute directory",
    1.66 +	"%s: Invalid file permissions",
    1.67 +	"%s: No relative directory specified",
    1.68 +	"%s: No absolute directory specified",
    1.69 +	"Empty string given for platform name",
    1.70 +	"%s: invalid platform string",
    1.71 +	"More than one ModuleFile entry given for platform %s",
    1.72 +	"More than one ModuleName entry given for platform %s",
    1.73 +	"Invalid ModuleFile specification for platform %s",
    1.74 +	"Invalid ModuleName specification for platform %s",
    1.75 +	"More than one DefaultMechanismFlags entry given for platform %s",
    1.76 +	"Invalid DefaultMechanismFlags specification for platform %s",
    1.77 +	"More than one DefaultCipherFlags entry given for platform %s",
    1.78 +	"Invalid DefaultCipherFlags entry given for platform %s",
    1.79 +	"More than one Files entry given for platform %s",
    1.80 +	"More than one EquivalentPlatform entry given for platform %s",
    1.81 +	"Invalid EquivalentPlatform specification for platform %s",
    1.82 +	"Module %s uses an EquivalentPlatform but also specifies its own"
    1.83 +		" information",
    1.84 +	"No Files specification in module %s",
    1.85 +	"No ModuleFile specification in module %s",
    1.86 +	"No ModuleName specification in module %s",
    1.87 +	"No Platforms specification in installer script",
    1.88 +	"Platform %s has an equivalency loop",
    1.89 +	"Module file \"%s\" in platform \"%s\" does not exist"
    1.90 +};
    1.91 +
    1.92 +static char* PR_Strdup(const char* str);
    1.93 +
    1.94 +#define PAD(x)  {int i; for(i=0;i<x;i++) printf(" ");}
    1.95 +#define PADINC 4
    1.96 +
    1.97 +Pk11Install_File*
    1.98 +Pk11Install_File_new()
    1.99 +{
   1.100 +	Pk11Install_File* new_this;
   1.101 +	new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File));
   1.102 +	Pk11Install_File_init(new_this);
   1.103 +	return new_this;
   1.104 +}
   1.105 +
   1.106 +void
   1.107 +Pk11Install_File_init(Pk11Install_File* _this)
   1.108 +{
   1.109 +	_this->jarPath=NULL;
   1.110 +	_this->relativePath=NULL;
   1.111 +	_this->absolutePath=NULL;
   1.112 +	_this->executable=PR_FALSE;
   1.113 +	_this->permissions=0;
   1.114 +}
   1.115 +
   1.116 +/*
   1.117 +//////////////////////////////////////////////////////////////////////////
   1.118 +// Method:	~Pk11Install_File
   1.119 +// Class:	Pk11Install_File
   1.120 +// Notes:	Destructor.
   1.121 +*/
   1.122 +void
   1.123 +Pk11Install_File_delete(Pk11Install_File* _this)
   1.124 +{
   1.125 +	Pk11Install_File_Cleanup(_this);
   1.126 +}
   1.127 +
   1.128 +/*
   1.129 +//////////////////////////////////////////////////////////////////////////
   1.130 +// Method:	Cleanup
   1.131 +// Class:	Pk11Install_File
   1.132 +*/
   1.133 +void
   1.134 +Pk11Install_File_Cleanup(Pk11Install_File* _this)
   1.135 +{
   1.136 +	if(_this->jarPath) {
   1.137 +		PR_Free(_this->jarPath);
   1.138 +		_this->jarPath = NULL;
   1.139 +	}
   1.140 +	if(_this->relativePath) {
   1.141 +		PR_Free(_this->relativePath);
   1.142 +		_this->relativePath = NULL;
   1.143 +	}
   1.144 +	if(_this->absolutePath) {
   1.145 +		PR_Free(_this->absolutePath);
   1.146 +		_this->absolutePath = NULL;
   1.147 +	}
   1.148 +
   1.149 +	_this->permissions = 0;
   1.150 +	_this->executable = PR_FALSE;
   1.151 +}
   1.152 +
   1.153 +/*
   1.154 +//////////////////////////////////////////////////////////////////////////
   1.155 +// Method:	Generate
   1.156 +// Class:	Pk11Install_File
   1.157 +// Notes:	Creates a file data structure from a syntax tree.
   1.158 +// Returns:	NULL for success, otherwise an error message.
   1.159 +*/
   1.160 +char*
   1.161 +Pk11Install_File_Generate(Pk11Install_File* _this,
   1.162 +                          const Pk11Install_Pair *pair)
   1.163 +{
   1.164 +	Pk11Install_ListIter *iter;
   1.165 +	Pk11Install_Value *val;
   1.166 +	Pk11Install_Pair *subpair;
   1.167 +	Pk11Install_ListIter *subiter;
   1.168 +	Pk11Install_Value *subval;
   1.169 +	char* errStr;
   1.170 +	char *endp;
   1.171 +	PRBool gotPerms;
   1.172 +
   1.173 +	iter=NULL;
   1.174 +	subiter=NULL;
   1.175 +	errStr=NULL;
   1.176 +	gotPerms=PR_FALSE;
   1.177 +
   1.178 +	/* Clear out old values */
   1.179 +	Pk11Install_File_Cleanup(_this);
   1.180 +
   1.181 +	_this->jarPath = PR_Strdup(pair->key);
   1.182 +
   1.183 +	/* Go through all the pairs under this file heading */
   1.184 +	iter = Pk11Install_ListIter_new(pair->list);
   1.185 +	for( ; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
   1.186 +		if(val->type == PAIR_VALUE) {
   1.187 +			subpair = val->pair;
   1.188 +
   1.189 +			/* Relative directory */
   1.190 +			if(!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) {
   1.191 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.192 +				subval = subiter->current;
   1.193 +				if(!subval || (subval->type != STRING_VALUE)){
   1.194 +					errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR], 
   1.195 +                                    _this->jarPath);
   1.196 +					goto loser;
   1.197 +				}
   1.198 +				_this->relativePath = PR_Strdup(subval->string);
   1.199 +				Pk11Install_ListIter_delete(subiter);
   1.200 +				subiter = NULL;
   1.201 +
   1.202 +				/* Absolute directory */
   1.203 +			} else if( !PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) {
   1.204 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.205 +				subval = subiter->current;
   1.206 +				if(!subval || (subval->type != STRING_VALUE)){
   1.207 +					errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR], 
   1.208 +                                    _this->jarPath);
   1.209 +					goto loser;
   1.210 +				}
   1.211 +				_this->absolutePath = PR_Strdup(subval->string);
   1.212 +				Pk11Install_ListIter_delete(subiter);
   1.213 +				subiter = NULL;
   1.214 +
   1.215 +			/* file permissions */
   1.216 +			} else if( !PORT_Strcasecmp(subpair->key,
   1.217 +                                     FILE_PERMISSIONS_STRING)) {
   1.218 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.219 +				subval = subiter->current;
   1.220 +				if(!subval || (subval->type != STRING_VALUE) ||
   1.221 +				   !subval->string || !subval->string[0]){
   1.222 +					errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
   1.223 +                                    _this->jarPath);
   1.224 +					goto loser;
   1.225 +				}
   1.226 +				_this->permissions = (int) strtol(subval->string, &endp, 8);
   1.227 +				if(*endp != '\0') {
   1.228 +					errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
   1.229 +                                    _this->jarPath);
   1.230 +					goto loser;
   1.231 +				}
   1.232 +				gotPerms = PR_TRUE;
   1.233 +				Pk11Install_ListIter_delete(subiter);
   1.234 +				subiter = NULL;
   1.235 +			}
   1.236 +		} else {
   1.237 +			if(!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) {
   1.238 +				_this->executable = PR_TRUE;
   1.239 +			}
   1.240 +		}
   1.241 +	}
   1.242 +
   1.243 +	/* Default permission value */
   1.244 +	if(!gotPerms) {
   1.245 +		_this->permissions = DEFAULT_PERMISSIONS;
   1.246 +	}
   1.247 +
   1.248 +	/* Make sure we got all the information */
   1.249 +	if(!_this->relativePath && !_this->absolutePath) {
   1.250 +		errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
   1.251 +		goto loser;
   1.252 +	}
   1.253 +#if 0
   1.254 +	if(!_this->relativePath ) {
   1.255 +		errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath);
   1.256 +		goto loser;
   1.257 +	}
   1.258 +	if(!_this->absolutePath) {
   1.259 +		errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
   1.260 +		goto loser;
   1.261 +	}
   1.262 +#endif
   1.263 +
   1.264 +loser:
   1.265 +	if(iter) {
   1.266 +		Pk11Install_ListIter_delete(iter);
   1.267 +		PR_Free(iter);
   1.268 +	}
   1.269 +	if(subiter) {
   1.270 +		Pk11Install_ListIter_delete(subiter);
   1.271 +		PR_Free(subiter);
   1.272 +	}
   1.273 +	return errStr;
   1.274 +}
   1.275 +
   1.276 +/*
   1.277 +//////////////////////////////////////////////////////////////////////////
   1.278 +// Method:	Print
   1.279 +// Class:	Pk11Install_File
   1.280 +*/
   1.281 +void
   1.282 +Pk11Install_File_Print(Pk11Install_File* _this, int pad)
   1.283 +{
   1.284 +	PAD(pad); printf("jarPath: %s\n", 
   1.285 +                    _this->jarPath ? _this->jarPath : "<NULL>");
   1.286 +	PAD(pad); printf("relativePath: %s\n",
   1.287 +				_this->relativePath ? _this->relativePath: "<NULL>");
   1.288 +	PAD(pad); printf("absolutePath: %s\n",
   1.289 +				_this->absolutePath ? _this->absolutePath: "<NULL>");
   1.290 +	PAD(pad); printf("permissions: %o\n", _this->permissions);
   1.291 +}
   1.292 +
   1.293 +Pk11Install_PlatformName*
   1.294 +Pk11Install_PlatformName_new()
   1.295 +{
   1.296 +	Pk11Install_PlatformName* new_this;
   1.297 +	new_this = (Pk11Install_PlatformName*)
   1.298 +               PR_Malloc(sizeof(Pk11Install_PlatformName));
   1.299 +	Pk11Install_PlatformName_init(new_this);
   1.300 +	return new_this;
   1.301 +}
   1.302 +
   1.303 +void
   1.304 +Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this)
   1.305 +{
   1.306 +	_this->OS = NULL;
   1.307 +	_this->verString = NULL;
   1.308 +	_this->numDigits = 0;
   1.309 +	_this->arch = NULL;
   1.310 +}
   1.311 +
   1.312 +/*
   1.313 +//////////////////////////////////////////////////////////////////////////
   1.314 +// Method:	~Pk11Install_PlatformName
   1.315 +// Class:	Pk11Install_PlatformName
   1.316 +*/
   1.317 +void
   1.318 +Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this)
   1.319 +{
   1.320 +	Pk11Install_PlatformName_Cleanup(_this);
   1.321 +}
   1.322 +
   1.323 +/*
   1.324 +//////////////////////////////////////////////////////////////////////////
   1.325 +// Method:	Cleanup
   1.326 +// Class:	Pk11Install_PlatformName
   1.327 +*/
   1.328 +void
   1.329 +Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this)
   1.330 +{
   1.331 +	if(_this->OS) {
   1.332 +		PR_Free(_this->OS);
   1.333 +		_this->OS = NULL;
   1.334 +	}
   1.335 +	if(_this->verString) {
   1.336 +		int i;
   1.337 +		for (i=0; i<_this->numDigits; i++) {
   1.338 +			PR_Free(_this->verString[i]);
   1.339 +		}
   1.340 +		PR_Free(_this->verString);
   1.341 +		_this->verString = NULL;
   1.342 +	}
   1.343 +	if(_this->arch) {
   1.344 +		PR_Free(_this->arch);
   1.345 +		_this->arch = NULL;
   1.346 +	}
   1.347 +	_this->numDigits = 0;
   1.348 +}
   1.349 +
   1.350 +/*
   1.351 +//////////////////////////////////////////////////////////////////////////
   1.352 +// Method:	Generate
   1.353 +// Class:	Pk11Install_PlatformName
   1.354 +// Notes:	Extracts the information from a platform string.
   1.355 +*/
   1.356 +char*
   1.357 +Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
   1.358 +                                  const char *str)
   1.359 +{
   1.360 +	char *errStr;
   1.361 +	char *copy;
   1.362 +	char *end, *start; /* start and end of a section (OS, version, arch)*/
   1.363 +	char *pend, *pstart; /* start and end of one portion of version*/
   1.364 +	char *endp; /* used by strtol*/
   1.365 +	int periods, i;
   1.366 +
   1.367 +	errStr=NULL;
   1.368 +	copy=NULL;
   1.369 +
   1.370 +	if(!str) {
   1.371 +		errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]);
   1.372 +		goto loser;
   1.373 +	}
   1.374 +	copy = PR_Strdup(str);
   1.375 +
   1.376 +	/*
   1.377 +	// Get the OS
   1.378 +	*/
   1.379 +	end = strchr(copy, PLATFORM_SEPARATOR_CHAR);
   1.380 +	if(!end || end==copy) {
   1.381 +		errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   1.382 +		goto loser;
   1.383 +	}
   1.384 +	*end = '\0';
   1.385 +
   1.386 +	_this->OS = PR_Strdup(copy);
   1.387 +
   1.388 +	/*
   1.389 +	// Get the digits of the version of form: x.x.x (arbitrary number of digits)
   1.390 +	*/
   1.391 +
   1.392 +	start = end+1;
   1.393 +	end = strchr(start, PLATFORM_SEPARATOR_CHAR);
   1.394 +	if(!end) {
   1.395 +		errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   1.396 +		goto loser;
   1.397 +	}
   1.398 +	*end = '\0';
   1.399 +
   1.400 +	if(end!=start) { 
   1.401 +		/* Find out how many periods*/
   1.402 +		periods = 0;
   1.403 +		pstart = start;
   1.404 +		while( (pend=strchr(pstart, '.')) ) {
   1.405 +			periods++;
   1.406 +			pstart = pend+1;
   1.407 +		}
   1.408 +		_this->numDigits= 1+ periods;
   1.409 +		_this->verString = (char**)PR_Malloc(sizeof(char*)*_this->numDigits);
   1.410 +
   1.411 +		pstart = start;
   1.412 +		i = 0;
   1.413 +		/* Get the digits before each period*/
   1.414 +		while( (pend=strchr(pstart, '.')) ) {
   1.415 +			if(pend == pstart) {
   1.416 +				errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   1.417 +				goto loser;
   1.418 +			}
   1.419 +			*pend = '\0';
   1.420 +			_this->verString[i] = PR_Strdup(pstart);
   1.421 +			endp = pend;
   1.422 +		if(endp==pstart || (*endp != '\0')) {
   1.423 +				errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   1.424 +				goto loser;
   1.425 +			}
   1.426 +			pstart = pend+1;
   1.427 +			i++;
   1.428 +		}
   1.429 +		/* Last digit comes after the last period*/
   1.430 +		if(*pstart == '\0') {
   1.431 +			errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   1.432 +			goto loser;
   1.433 +		}
   1.434 +		_this->verString[i] = PR_Strdup(pstart);
   1.435 +		/*
   1.436 +		if(endp==pstart || (*endp != '\0')) {
   1.437 +			errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   1.438 +			goto loser;
   1.439 +		}
   1.440 +		*/
   1.441 +	} else {
   1.442 +		_this->verString = NULL;
   1.443 +		_this->numDigits = 0;
   1.444 +	}
   1.445 +
   1.446 +	/*
   1.447 +	// Get the architecture
   1.448 +	*/
   1.449 +	start = end+1;
   1.450 +	if( strchr(start, PLATFORM_SEPARATOR_CHAR) ) {
   1.451 +		errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   1.452 +		goto loser;
   1.453 +	}
   1.454 +	_this->arch = PR_Strdup(start);
   1.455 +
   1.456 +	if(copy) {
   1.457 +		PR_Free(copy);
   1.458 +	}
   1.459 +	return NULL;
   1.460 +loser:
   1.461 +	if(_this->OS) {
   1.462 +		PR_Free(_this->OS);
   1.463 +		_this->OS = NULL;
   1.464 +	}
   1.465 +	if(_this->verString) {
   1.466 +		for (i=0; i<_this->numDigits; i++) {
   1.467 +			PR_Free(_this->verString[i]);
   1.468 +		}
   1.469 +		PR_Free(_this->verString);
   1.470 +		_this->verString = NULL;
   1.471 +	}
   1.472 +	_this->numDigits = 0;
   1.473 +	if(_this->arch) {
   1.474 +		PR_Free(_this->arch);
   1.475 +		_this->arch = NULL;
   1.476 +	}
   1.477 +
   1.478 +	return errStr;
   1.479 +}
   1.480 +
   1.481 +/*
   1.482 +//////////////////////////////////////////////////////////////////////////
   1.483 +// Method:	operator ==
   1.484 +// Class:	Pk11Install_PlatformName
   1.485 +// Returns:	PR_TRUE if the platform have the same OS, arch, and version
   1.486 +*/
   1.487 +PRBool
   1.488 +Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
   1.489 +                               Pk11Install_PlatformName* cmp) 
   1.490 +{
   1.491 +	int i;
   1.492 +
   1.493 +	if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
   1.494 +		return PR_FALSE;
   1.495 +	}
   1.496 +
   1.497 +	if(	PORT_Strcasecmp(_this->OS, cmp->OS) ||
   1.498 +		PORT_Strcasecmp(_this->arch, cmp->arch) ||
   1.499 +		_this->numDigits != cmp->numDigits ) {
   1.500 +			return PR_FALSE;
   1.501 +	}
   1.502 +
   1.503 +	for(i=0; i < _this->numDigits; i++) {
   1.504 +		if(PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) {
   1.505 +			return PR_FALSE;
   1.506 +		}
   1.507 +	}
   1.508 +	return PR_TRUE;
   1.509 +}
   1.510 +
   1.511 +/*
   1.512 +//////////////////////////////////////////////////////////////////////////
   1.513 +// Method:	operator <=
   1.514 +// Class:	Pk11Install_PlatformName
   1.515 +// Returns:	PR_TRUE if the platform have the same OS and arch and a lower
   1.516 +//			or equal release.
   1.517 +*/
   1.518 +PRBool
   1.519 +Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
   1.520 +                              Pk11Install_PlatformName* cmp)
   1.521 +{
   1.522 +	return (Pk11Install_PlatformName_equal(_this,cmp) ||
   1.523 +          Pk11Install_PlatformName_lt(_this,cmp)) ? PR_TRUE : PR_FALSE;
   1.524 +}
   1.525 +
   1.526 +/*
   1.527 +//////////////////////////////////////////////////////////////////////////
   1.528 +// Method:	operator <
   1.529 +// Class:	Pk11Install_PlatformName
   1.530 +// Returns:	PR_TRUE if the platform have the same OS and arch and a greater
   1.531 +//			release.
   1.532 +*/
   1.533 +PRBool
   1.534 +Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
   1.535 +                            Pk11Install_PlatformName* cmp)
   1.536 +{
   1.537 +	int i, scmp;
   1.538 +
   1.539 +	if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
   1.540 +		return PR_FALSE;
   1.541 +	}
   1.542 +
   1.543 +	if( PORT_Strcasecmp(_this->OS, cmp->OS) ) {
   1.544 +		return PR_FALSE;
   1.545 +	}
   1.546 +	if( PORT_Strcasecmp(_this->arch, cmp->arch) ) {
   1.547 +		return PR_FALSE;
   1.548 +	}
   1.549 +
   1.550 +	for(i=0; (i < _this->numDigits) && (i < cmp->numDigits); i++) {
   1.551 +		scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]);
   1.552 +		if (scmp > 0) {
   1.553 +			return PR_FALSE;
   1.554 +		} else if (scmp < 0) {
   1.555 +			return PR_TRUE;
   1.556 +		}
   1.557 +	}
   1.558 +	/* All the digits they have in common are the same. */
   1.559 +	if(_this->numDigits < cmp->numDigits) {
   1.560 +		return  PR_TRUE;
   1.561 +	} 
   1.562 +
   1.563 +	return PR_FALSE;
   1.564 +}
   1.565 +
   1.566 +/*
   1.567 +//////////////////////////////////////////////////////////////////////////
   1.568 +// Method:	GetString
   1.569 +// Class:	Pk11Install_PlatformName
   1.570 +// Returns:	String composed of OS, release, and architecture separated
   1.571 +//			by the separator char.  Memory is allocated by this function
   1.572 +//			but is the responsibility of the caller to de-allocate.
   1.573 +*/
   1.574 +char*
   1.575 +Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this) 
   1.576 +{
   1.577 +	char *ret;
   1.578 +	char *ver;
   1.579 +	char *OS_;
   1.580 +	char *arch_;
   1.581 +
   1.582 +	OS_=NULL;
   1.583 +	arch_=NULL;
   1.584 +
   1.585 +	OS_ = _this->OS ? _this->OS : "";
   1.586 +	arch_ = _this->arch ? _this->arch : "";
   1.587 +
   1.588 +	ver = Pk11Install_PlatformName_GetVerString(_this);
   1.589 +	ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver,
   1.590 +					PLATFORM_SEPARATOR_CHAR, arch_);
   1.591 +
   1.592 +	PR_Free(ver);
   1.593 +
   1.594 +	return ret;
   1.595 +}
   1.596 +
   1.597 +/*
   1.598 +//////////////////////////////////////////////////////////////////////////
   1.599 +// Method:	GetVerString
   1.600 +// Class:	Pk11Install_PlatformName
   1.601 +// Returns:	The version string for this platform, in the form x.x.x with an
   1.602 +//			arbitrary number of digits.  Memory allocated by function,
   1.603 +//			must be de-allocated by caller.
   1.604 +*/
   1.605 +char*
   1.606 +Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this) 
   1.607 +{
   1.608 +	char *tmp;
   1.609 +	char *ret;
   1.610 +	int i;
   1.611 +	char buf[80];
   1.612 +
   1.613 +	tmp = (char*)PR_Malloc(80*_this->numDigits+1);
   1.614 +	tmp[0] = '\0';
   1.615 +
   1.616 +	for(i=0; i < _this->numDigits-1; i++) {
   1.617 +		sprintf(buf, "%s.", _this->verString[i]);
   1.618 +		strcat(tmp, buf);
   1.619 +	}
   1.620 +	if(i < _this->numDigits) {
   1.621 +		sprintf(buf, "%s", _this->verString[i]);
   1.622 +		strcat(tmp, buf);
   1.623 +	}
   1.624 +
   1.625 +	ret = PR_Strdup(tmp);
   1.626 +	free(tmp);
   1.627 +
   1.628 +	return ret;
   1.629 +}
   1.630 +
   1.631 +/*
   1.632 +//////////////////////////////////////////////////////////////////////////
   1.633 +// Method:	Print
   1.634 +// Class:	Pk11Install_PlatformName
   1.635 +*/
   1.636 +void
   1.637 +Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad)
   1.638 +{
   1.639 +	PAD(pad); printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>");
   1.640 +	PAD(pad); printf("Digits: ");
   1.641 +	if(_this->numDigits == 0) {
   1.642 +		printf("None\n");
   1.643 +	} else {
   1.644 +		printf("%s\n", Pk11Install_PlatformName_GetVerString(_this));
   1.645 +	}
   1.646 +	PAD(pad); printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>");
   1.647 +}
   1.648 +
   1.649 +Pk11Install_Platform*
   1.650 +Pk11Install_Platform_new()
   1.651 +{
   1.652 +	Pk11Install_Platform* new_this;
   1.653 +	new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform));
   1.654 +	Pk11Install_Platform_init(new_this);
   1.655 +	return new_this;
   1.656 +}
   1.657 +
   1.658 +void
   1.659 +Pk11Install_Platform_init(Pk11Install_Platform* _this)
   1.660 +{
   1.661 +	Pk11Install_PlatformName_init(&_this->name);
   1.662 +	Pk11Install_PlatformName_init(&_this->equivName);
   1.663 +	_this->equiv = NULL;
   1.664 +	_this->usesEquiv = PR_FALSE;
   1.665 +	_this->moduleFile = NULL;
   1.666 +	_this->moduleName = NULL;
   1.667 +	_this->modFile = -1;
   1.668 +	_this->mechFlags = 0;
   1.669 +	_this->cipherFlags = 0;
   1.670 +	_this->files = NULL;
   1.671 +	_this->numFiles = 0;
   1.672 +}
   1.673 +
   1.674 +/*
   1.675 +//////////////////////////////////////////////////////////////////////////
   1.676 +// Method:	~Pk11Install_Platform
   1.677 +// Class:	Pk11Install_Platform
   1.678 +*/
   1.679 +void
   1.680 +Pk11Install_Platform_delete(Pk11Install_Platform* _this)
   1.681 +{
   1.682 +	Pk11Install_Platform_Cleanup(_this);
   1.683 +}
   1.684 +
   1.685 +/*
   1.686 +//////////////////////////////////////////////////////////////////////////
   1.687 +// Method:	Cleanup
   1.688 +// Class:	Pk11Install_Platform
   1.689 +*/
   1.690 +void
   1.691 +Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this)
   1.692 +{
   1.693 +	int i;
   1.694 +	if(_this->moduleFile) {
   1.695 +		PR_Free(_this->moduleFile);
   1.696 +		_this->moduleFile = NULL;
   1.697 +	}
   1.698 +	if(_this->moduleName) {
   1.699 +		PR_Free(_this->moduleName);
   1.700 +		_this->moduleName = NULL;
   1.701 +	}
   1.702 +	if(_this->files) {
   1.703 +		for (i=0;i<_this->numFiles;i++) {
   1.704 +			Pk11Install_File_delete(&_this->files[i]);
   1.705 +		}
   1.706 +		PR_Free(_this->files);
   1.707 +		_this->files = NULL;
   1.708 +	}
   1.709 +	_this->equiv = NULL;
   1.710 +	_this->usesEquiv = PR_FALSE;
   1.711 +	_this->modFile = -1;
   1.712 +	_this->numFiles = 0;
   1.713 +	_this->mechFlags = _this->cipherFlags = 0;
   1.714 +}
   1.715 +
   1.716 +/*
   1.717 +//////////////////////////////////////////////////////////////////////////
   1.718 +// Method:	Generate
   1.719 +// Class:	Pk11Install_Platform
   1.720 +// Notes:	Creates a platform data structure from a syntax tree.
   1.721 +// Returns:	NULL for success, otherwise an error message.
   1.722 +*/
   1.723 +char*
   1.724 +Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
   1.725 +                              const Pk11Install_Pair *pair)
   1.726 +{
   1.727 +	char* errStr;
   1.728 +	char* endptr;
   1.729 +	char* tmp;
   1.730 +	int i;
   1.731 +	Pk11Install_ListIter *iter;
   1.732 +	Pk11Install_Value *val;
   1.733 +	Pk11Install_Value *subval;
   1.734 +	Pk11Install_Pair *subpair;
   1.735 +	Pk11Install_ListIter *subiter;
   1.736 +	PRBool gotModuleFile, gotModuleName, gotMech, 
   1.737 +          gotCipher, gotFiles, gotEquiv;
   1.738 +
   1.739 +	errStr=NULL;
   1.740 +	iter=subiter=NULL;
   1.741 +	val=subval=NULL;
   1.742 +	subpair=NULL;
   1.743 +	gotModuleFile=gotModuleName=gotMech=gotCipher=gotFiles=gotEquiv=PR_FALSE;
   1.744 +	Pk11Install_Platform_Cleanup(_this);
   1.745 +
   1.746 +	errStr = Pk11Install_PlatformName_Generate(&_this->name,pair->key);
   1.747 +	if(errStr) {
   1.748 +		tmp = PR_smprintf("%s: %s", pair->key, errStr);
   1.749 +		PR_smprintf_free(errStr);
   1.750 +		errStr = tmp;
   1.751 +		goto loser;
   1.752 +	}
   1.753 +
   1.754 +	iter = Pk11Install_ListIter_new(pair->list);
   1.755 +	for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
   1.756 +		if(val->type==PAIR_VALUE) {
   1.757 +			subpair = val->pair;
   1.758 +
   1.759 +			if( !PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) {
   1.760 +				if(gotModuleFile) {
   1.761 +					errStr = PR_smprintf(errString[REPEAT_MODULE_FILE],
   1.762 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.763 +					goto loser;
   1.764 +				}
   1.765 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.766 +				subval = subiter->current;
   1.767 +				if(!subval || (subval->type != STRING_VALUE)) {
   1.768 +					errStr = PR_smprintf(errString[BOGUS_MODULE_FILE],
   1.769 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.770 +					goto loser;
   1.771 +				}
   1.772 +				_this->moduleFile = PR_Strdup(subval->string);
   1.773 +				Pk11Install_ListIter_delete(subiter);
   1.774 +				PR_Free(subiter);
   1.775 +				subiter = NULL;
   1.776 +				gotModuleFile = PR_TRUE;
   1.777 +			} else if(!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)){
   1.778 +				if(gotModuleName) {
   1.779 +					errStr = PR_smprintf(errString[REPEAT_MODULE_NAME],
   1.780 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.781 +					goto loser;
   1.782 +				}
   1.783 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.784 +				subval = subiter->current;
   1.785 +				if(!subval || (subval->type != STRING_VALUE)) {
   1.786 +					errStr = PR_smprintf(errString[BOGUS_MODULE_NAME],
   1.787 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.788 +					goto loser;
   1.789 +				}
   1.790 +				_this->moduleName = PR_Strdup(subval->string);
   1.791 +				Pk11Install_ListIter_delete(subiter);
   1.792 +				PR_Free(subiter);
   1.793 +				subiter = NULL;
   1.794 +				gotModuleName = PR_TRUE;
   1.795 +			} else if(!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) {
   1.796 +				endptr=NULL;
   1.797 +
   1.798 +				if(gotMech) {
   1.799 +					errStr = PR_smprintf(errString[REPEAT_MECH],
   1.800 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.801 +					goto loser;
   1.802 +				}
   1.803 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.804 +				subval = subiter->current;
   1.805 +				if(!subval || (subval->type != STRING_VALUE)) {
   1.806 +					errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
   1.807 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.808 +					goto loser;
   1.809 +				}
   1.810 +				_this->mechFlags = strtol(subval->string, &endptr, 0);
   1.811 +				if(*endptr!='\0' || (endptr==subval->string) ) {
   1.812 +					errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
   1.813 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.814 +					goto loser;
   1.815 +				}
   1.816 +				Pk11Install_ListIter_delete(subiter);
   1.817 +				PR_Free(subiter);
   1.818 +				subiter=NULL;
   1.819 +				gotMech = PR_TRUE;
   1.820 +			} else if(!PORT_Strcasecmp(subpair->key,CIPHER_FLAGS_STRING)) {
   1.821 +				endptr=NULL;
   1.822 +
   1.823 +				if(gotCipher) {
   1.824 +					errStr = PR_smprintf(errString[REPEAT_CIPHER],
   1.825 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.826 +					goto loser;
   1.827 +				}
   1.828 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.829 +				subval = subiter->current;
   1.830 +				if(!subval || (subval->type != STRING_VALUE)) {
   1.831 +					errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
   1.832 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.833 +					goto loser;
   1.834 +				}
   1.835 +				_this->cipherFlags = strtol(subval->string, &endptr, 0);
   1.836 +				if(*endptr!='\0' || (endptr==subval->string) ) {
   1.837 +					errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
   1.838 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.839 +					goto loser;
   1.840 +				}
   1.841 +				Pk11Install_ListIter_delete(subiter);
   1.842 +				PR_Free(subiter);
   1.843 +				subiter=NULL;
   1.844 +				gotCipher = PR_TRUE;
   1.845 +			} else if(!PORT_Strcasecmp(subpair->key, FILES_STRING)) {
   1.846 +				if(gotFiles) {
   1.847 +					errStr = PR_smprintf(errString[REPEAT_FILES],
   1.848 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.849 +					goto loser;
   1.850 +				}
   1.851 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.852 +				_this->numFiles = subpair->list->numPairs;
   1.853 +				_this->files = (Pk11Install_File*)
   1.854 +                            PR_Malloc(sizeof(Pk11Install_File)*_this->numFiles);
   1.855 +				for(i=0; i < _this->numFiles; i++, 
   1.856 +                                   Pk11Install_ListIter_nextItem(subiter)) {
   1.857 +					Pk11Install_File_init(&_this->files[i]);
   1.858 +					val = subiter->current;
   1.859 +					if(val && (val->type==PAIR_VALUE)) {
   1.860 +						errStr = Pk11Install_File_Generate(&_this->files[i],val->pair);
   1.861 +						if(errStr) {
   1.862 +							tmp = PR_smprintf("%s: %s", 
   1.863 +                                       Pk11Install_PlatformName_GetString(&_this->name),errStr);
   1.864 +							PR_smprintf_free(errStr);
   1.865 +							errStr = tmp;
   1.866 +							goto loser;
   1.867 +						}
   1.868 +					}
   1.869 +				}
   1.870 +				gotFiles = PR_TRUE;
   1.871 +			} else if(!PORT_Strcasecmp(subpair->key,
   1.872 +                                    EQUIVALENT_PLATFORM_STRING)) {
   1.873 +				if(gotEquiv) {
   1.874 +					errStr = PR_smprintf(errString[REPEAT_EQUIV],
   1.875 +                                    Pk11Install_PlatformName_GetString(&_this->name));
   1.876 +					goto loser;
   1.877 +				}
   1.878 +				subiter = Pk11Install_ListIter_new(subpair->list);
   1.879 +				subval = subiter->current;
   1.880 +				if(!subval || (subval->type != STRING_VALUE) ) {
   1.881 +					errStr = PR_smprintf(errString[BOGUS_EQUIV],
   1.882 +                               Pk11Install_PlatformName_GetString(&_this->name));
   1.883 +					goto loser;
   1.884 +				}
   1.885 +				errStr = Pk11Install_PlatformName_Generate(&_this->equivName,
   1.886 +                                                       subval->string);
   1.887 +				if(errStr) {
   1.888 +					tmp = PR_smprintf("%s: %s", 
   1.889 +                            Pk11Install_PlatformName_GetString(&_this->name), errStr);
   1.890 +					tmp = PR_smprintf("%s: %s", 
   1.891 +                            Pk11Install_PlatformName_GetString(&_this->name), errStr);
   1.892 +					PR_smprintf_free(errStr);
   1.893 +					errStr = tmp;
   1.894 +					goto loser;
   1.895 +				}
   1.896 +				_this->usesEquiv = PR_TRUE;
   1.897 +			}
   1.898 +		}
   1.899 +	}
   1.900 +
   1.901 +	/* Make sure we either have an EquivalentPlatform or all the other info */
   1.902 +	if(_this->usesEquiv &&
   1.903 +		(gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) {
   1.904 +		errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO], 
   1.905 +                           Pk11Install_PlatformName_GetString(&_this->name));
   1.906 +		goto loser;
   1.907 +	}
   1.908 +	if(!gotFiles && !_this->usesEquiv) {
   1.909 +		errStr = PR_smprintf(errString[NO_FILES], 
   1.910 +                           Pk11Install_PlatformName_GetString(&_this->name));
   1.911 +		goto loser;
   1.912 +	}
   1.913 +	if(!gotModuleFile && !_this->usesEquiv) {
   1.914 +		errStr= PR_smprintf(errString[NO_MODULE_FILE], 
   1.915 +                          Pk11Install_PlatformName_GetString(&_this->name));
   1.916 +		goto loser;
   1.917 +	}
   1.918 +	if(!gotModuleName && !_this->usesEquiv) {
   1.919 +		errStr = PR_smprintf(errString[NO_MODULE_NAME], 
   1.920 +                          Pk11Install_PlatformName_GetString(&_this->name));
   1.921 +		goto loser;
   1.922 +	}
   1.923 +
   1.924 +	/* Point the modFile pointer to the correct file */
   1.925 +	if(gotModuleFile) {
   1.926 +		for(i=0; i < _this->numFiles; i++) {
   1.927 +			if(!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath) ) {
   1.928 +				_this->modFile = i;
   1.929 +				break;
   1.930 +			}
   1.931 +		}
   1.932 +		if(_this->modFile==-1) {
   1.933 +			errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE], 
   1.934 +                              _this->moduleFile,
   1.935 +                              Pk11Install_PlatformName_GetString(&_this->name));
   1.936 +			goto loser;
   1.937 +		}
   1.938 +	}
   1.939 +	
   1.940 +loser:
   1.941 +	if(iter) {
   1.942 +		PR_Free(iter);
   1.943 +	}
   1.944 +	if(subiter) {
   1.945 +		PR_Free(subiter);
   1.946 +	}
   1.947 +	return errStr;
   1.948 +}
   1.949 +
   1.950 +/*
   1.951 +//////////////////////////////////////////////////////////////////////////
   1.952 +// Method:		Print
   1.953 +// Class:		Pk11Install_Platform
   1.954 +*/
   1.955 +void
   1.956 +Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
   1.957 +{
   1.958 +	int i;
   1.959 +
   1.960 +	PAD(pad); printf("Name:\n"); 
   1.961 +	Pk11Install_PlatformName_Print(&_this->name,pad+PADINC);
   1.962 +	PAD(pad); printf("equivName:\n"); 
   1.963 +	Pk11Install_PlatformName_Print(&_this->equivName,pad+PADINC);
   1.964 +	PAD(pad);
   1.965 +	if(_this->usesEquiv) {
   1.966 +		printf("Uses equiv, which points to:\n");
   1.967 +		Pk11Install_Platform_Print(_this->equiv,pad+PADINC);
   1.968 +	} else {
   1.969 +		printf("Doesn't use equiv\n");
   1.970 +	}
   1.971 +	PAD(pad); 
   1.972 +	printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile 
   1.973 +                                                 : "<NULL>");
   1.974 +	PAD(pad); printf("mechFlags: %lx\n", _this->mechFlags);
   1.975 +	PAD(pad); printf("cipherFlags: %lx\n", _this->cipherFlags);
   1.976 +	PAD(pad); printf("Files:\n");
   1.977 +	for(i=0; i < _this->numFiles; i++) {
   1.978 +		Pk11Install_File_Print(&_this->files[i],pad+PADINC);
   1.979 +		PAD(pad); printf("--------------------\n");
   1.980 +	}
   1.981 +}
   1.982 +
   1.983 +/*
   1.984 +//////////////////////////////////////////////////////////////////////////
   1.985 +// Method:		Pk11Install_Info
   1.986 +// Class:		Pk11Install_Info
   1.987 +*/
   1.988 +Pk11Install_Info*
   1.989 +Pk11Install_Info_new()
   1.990 +{
   1.991 +	Pk11Install_Info* new_this;
   1.992 +	new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info));
   1.993 +	Pk11Install_Info_init(new_this);
   1.994 +	return new_this;
   1.995 +}
   1.996 +
   1.997 +void
   1.998 +Pk11Install_Info_init(Pk11Install_Info* _this)
   1.999 +{
  1.1000 +	_this->platforms = NULL;
  1.1001 +	_this->numPlatforms = 0;
  1.1002 +	_this->forwardCompatible = NULL;
  1.1003 +	_this->numForwardCompatible = 0;
  1.1004 +}
  1.1005 +
  1.1006 +/*
  1.1007 +//////////////////////////////////////////////////////////////////////////
  1.1008 +// Method:		~Pk11Install_Info
  1.1009 +// Class:		Pk11Install_Info
  1.1010 +*/
  1.1011 +void
  1.1012 +Pk11Install_Info_delete(Pk11Install_Info* _this)
  1.1013 +{
  1.1014 +	Pk11Install_Info_Cleanup(_this);
  1.1015 +}
  1.1016 +
  1.1017 +/*
  1.1018 +//////////////////////////////////////////////////////////////////////////
  1.1019 +// Method:		Cleanup
  1.1020 +// Class:		Pk11Install_Info
  1.1021 +*/
  1.1022 +void
  1.1023 +Pk11Install_Info_Cleanup(Pk11Install_Info* _this)
  1.1024 +{
  1.1025 +	int i;
  1.1026 +	if(_this->platforms) {
  1.1027 +		for (i=0;i<_this->numPlatforms;i++) {
  1.1028 +			Pk11Install_Platform_delete(&_this->platforms[i]);
  1.1029 +		}
  1.1030 +		PR_Free(&_this->platforms);
  1.1031 +		_this->platforms = NULL;
  1.1032 +		_this->numPlatforms = 0;
  1.1033 +	}
  1.1034 +
  1.1035 +	if(_this->forwardCompatible) {
  1.1036 +		for (i=0;i<_this->numForwardCompatible;i++) {
  1.1037 +			Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]);
  1.1038 +		}
  1.1039 +		PR_Free(&_this->forwardCompatible);
  1.1040 +		_this->numForwardCompatible = 0;
  1.1041 +	}
  1.1042 +}
  1.1043 +
  1.1044 +/*
  1.1045 +//////////////////////////////////////////////////////////////////////////
  1.1046 +// Method:		Generate
  1.1047 +// Class:		Pk11Install_Info
  1.1048 +// Takes:		Pk11Install_ValueList *list, the top-level list
  1.1049 +//				resulting from parsing an installer file.
  1.1050 +// Returns:		char*, NULL if successful, otherwise an error string.
  1.1051 +//				Caller is responsible for freeing memory.
  1.1052 +*/
  1.1053 +char*
  1.1054 +Pk11Install_Info_Generate(Pk11Install_Info* _this,
  1.1055 +                          const Pk11Install_ValueList *list)
  1.1056 +{
  1.1057 +	char *errStr;
  1.1058 +	Pk11Install_ListIter *iter;
  1.1059 +	Pk11Install_Value *val;
  1.1060 +	Pk11Install_Pair *pair;
  1.1061 +	Pk11Install_ListIter *subiter;
  1.1062 +	Pk11Install_Value *subval;
  1.1063 +	Pk11Install_Platform *first, *second;
  1.1064 +	int i, j;
  1.1065 +
  1.1066 +	errStr=NULL;
  1.1067 +	iter=subiter=NULL;
  1.1068 +	Pk11Install_Info_Cleanup(_this);
  1.1069 +
  1.1070 +	iter = Pk11Install_ListIter_new(list);
  1.1071 +	for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
  1.1072 +		if(val->type == PAIR_VALUE) {
  1.1073 +			pair = val->pair;
  1.1074 +
  1.1075 +			if(!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) {
  1.1076 +				subiter = Pk11Install_ListIter_new(pair->list);
  1.1077 +				_this->numForwardCompatible = pair->list->numStrings;
  1.1078 +				_this->forwardCompatible = (Pk11Install_PlatformName*)
  1.1079 +                                        PR_Malloc(sizeof(Pk11Install_PlatformName)*
  1.1080 +                                               _this->numForwardCompatible);
  1.1081 +				for(i=0; i < _this->numForwardCompatible; i++, 
  1.1082 +                       Pk11Install_ListIter_nextItem(subiter)) {
  1.1083 +					subval = subiter->current;
  1.1084 +					if(subval->type == STRING_VALUE) {
  1.1085 +						errStr = Pk11Install_PlatformName_Generate(
  1.1086 +                              &_this->forwardCompatible[i], subval->string);
  1.1087 +						if(errStr) {
  1.1088 +							goto loser;
  1.1089 +						}
  1.1090 +					}
  1.1091 +				}
  1.1092 +				Pk11Install_ListIter_delete(subiter);
  1.1093 +				PR_Free(subiter);
  1.1094 +				subiter = NULL;
  1.1095 +			} else if(!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) {
  1.1096 +				subiter = Pk11Install_ListIter_new(pair->list);
  1.1097 +				_this->numPlatforms = pair->list->numPairs;
  1.1098 +				_this->platforms = (Pk11Install_Platform*)
  1.1099 +                            PR_Malloc(sizeof(Pk11Install_Platform)*
  1.1100 +                            _this->numPlatforms);
  1.1101 +				for(i=0; i < _this->numPlatforms; i++, 
  1.1102 +                       Pk11Install_ListIter_nextItem(subiter)) {
  1.1103 +					 Pk11Install_Platform_init(&_this->platforms[i]);
  1.1104 +					subval = subiter->current;
  1.1105 +					if(subval->type == PAIR_VALUE) {
  1.1106 +						errStr = Pk11Install_Platform_Generate(&_this->platforms[i],subval->pair);
  1.1107 +						if(errStr) {
  1.1108 +							goto loser;
  1.1109 +						}
  1.1110 +					}
  1.1111 +				}
  1.1112 +				Pk11Install_ListIter_delete(subiter);
  1.1113 +				PR_Free(subiter);
  1.1114 +				subiter = NULL;
  1.1115 +			}
  1.1116 +		}
  1.1117 +	}
  1.1118 +
  1.1119 +	if(_this->numPlatforms == 0) {
  1.1120 +		errStr = PR_smprintf(errString[NO_PLATFORMS]);
  1.1121 +		goto loser;
  1.1122 +	}
  1.1123 +
  1.1124 +/*
  1.1125 +	//
  1.1126 +	// Now process equivalent platforms
  1.1127 +	//
  1.1128 +
  1.1129 +	// First the naive pass
  1.1130 +*/
  1.1131 +	for(i=0; i < _this->numPlatforms; i++) {
  1.1132 +		if(_this->platforms[i].usesEquiv) {
  1.1133 +			_this->platforms[i].equiv = NULL;
  1.1134 +			for(j=0; j < _this->numPlatforms; j++) {
  1.1135 +				if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName,
  1.1136 +                                           &_this->platforms[j].name)) {
  1.1137 +					if(i==j) {
  1.1138 +						errStr = PR_smprintf(errString[EQUIV_LOOP],
  1.1139 +                              Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1.1140 +						goto loser;
  1.1141 +					}
  1.1142 +					_this->platforms[i].equiv = &_this->platforms[j];
  1.1143 +					break;
  1.1144 +				}
  1.1145 +			}
  1.1146 +			if(_this->platforms[i].equiv == NULL) {
  1.1147 +				errStr = PR_smprintf(errString[BOGUS_EQUIV],
  1.1148 +                       Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1.1149 +				goto loser;
  1.1150 +			}
  1.1151 +		}
  1.1152 +	}
  1.1153 +
  1.1154 +/*
  1.1155 +	// Now the intelligent pass, which will also detect loops.
  1.1156 +	// We will send two pointers through the linked list of equivalent
  1.1157 +	// platforms. Both start with the current node.  "first" traverses
  1.1158 +	// two nodes for each iteration.  "second" lags behind, only traversing
  1.1159 +	// one node per iteration.  Eventually one of two things will happen:
  1.1160 +	// first will hit the end of the list (a platform that doesn't use
  1.1161 +	// an equivalency), or first will equal second if there is a loop.
  1.1162 +*/
  1.1163 +	for(i=0; i < _this->numPlatforms; i++) {
  1.1164 +		if(_this->platforms[i].usesEquiv) {
  1.1165 +			second = _this->platforms[i].equiv;
  1.1166 +			if(!second->usesEquiv) {
  1.1167 +				/* The first link is the terminal node */
  1.1168 +				continue;
  1.1169 +			}
  1.1170 +			first = second->equiv;
  1.1171 +			while(first->usesEquiv) {
  1.1172 +				if(first == second) {
  1.1173 +					errStr = PR_smprintf(errString[EQUIV_LOOP],
  1.1174 +                         Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1.1175 +					goto loser;
  1.1176 +				}
  1.1177 +				first = first->equiv;
  1.1178 +				if(!first->usesEquiv) {
  1.1179 +					break;
  1.1180 +				}
  1.1181 +				if(first == second) {
  1.1182 +					errStr = PR_smprintf(errString[EQUIV_LOOP],
  1.1183 +                       Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1.1184 +					goto loser;
  1.1185 +				}
  1.1186 +				second = second->equiv;
  1.1187 +				first = first->equiv;
  1.1188 +			}
  1.1189 +			_this->platforms[i].equiv = first;
  1.1190 +		}
  1.1191 +	}
  1.1192 +
  1.1193 +loser:
  1.1194 +	if(iter) {
  1.1195 +		Pk11Install_ListIter_delete(iter);
  1.1196 +		PR_Free(iter);
  1.1197 +		iter = NULL;
  1.1198 +	}
  1.1199 +	if(subiter) {
  1.1200 +		Pk11Install_ListIter_delete(subiter);
  1.1201 +		PR_Free(subiter);
  1.1202 +		subiter = NULL;
  1.1203 +	}
  1.1204 +	return errStr;
  1.1205 +}
  1.1206 +
  1.1207 +/*
  1.1208 +//////////////////////////////////////////////////////////////////////////
  1.1209 +// Method:		GetBestPlatform
  1.1210 +// Class:		Pk11Install_Info
  1.1211 +// Takes:		char *myPlatform, the platform we are currently running
  1.1212 +//				on.
  1.1213 +*/
  1.1214 +Pk11Install_Platform*
  1.1215 +Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char *myPlatform)
  1.1216 +{
  1.1217 +	Pk11Install_PlatformName plat;
  1.1218 +	char *errStr;
  1.1219 +	int i, j;
  1.1220 +
  1.1221 +	errStr=NULL;
  1.1222 +
  1.1223 +	Pk11Install_PlatformName_init(&plat);
  1.1224 +	if( (errStr=Pk11Install_PlatformName_Generate(&plat, myPlatform)) ) {
  1.1225 +		PR_smprintf_free(errStr);
  1.1226 +		return NULL;
  1.1227 +	}
  1.1228 +
  1.1229 +	/* First try real platforms */
  1.1230 +	for(i=0; i < _this->numPlatforms; i++) {
  1.1231 +		if(Pk11Install_PlatformName_equal(&_this->platforms[i].name,&plat)) {
  1.1232 +			if(_this->platforms[i].equiv) {
  1.1233 +				return _this->platforms[i].equiv;
  1.1234 +			}
  1.1235 +			else {
  1.1236 +				return &_this->platforms[i];
  1.1237 +			}
  1.1238 +		}
  1.1239 +	}
  1.1240 +
  1.1241 +	/* Now try forward compatible platforms */
  1.1242 +	for(i=0; i < _this->numForwardCompatible; i++) {
  1.1243 +		if(Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i],&plat)) {
  1.1244 +			break;
  1.1245 +		}
  1.1246 +	}
  1.1247 +	if(i == _this->numForwardCompatible) {
  1.1248 +		return NULL;
  1.1249 +	}
  1.1250 +
  1.1251 +	/* Got a forward compatible name, find the actual platform. */
  1.1252 +	for(j=0; j < _this->numPlatforms; j++) {
  1.1253 +		if(Pk11Install_PlatformName_equal(&_this->platforms[j].name,
  1.1254 +         &_this->forwardCompatible[i])) {
  1.1255 +			if(_this->platforms[j].equiv) {
  1.1256 +				return _this->platforms[j].equiv;
  1.1257 +			} else {
  1.1258 +				return &_this->platforms[j];
  1.1259 +			}
  1.1260 +		}
  1.1261 +	}
  1.1262 +
  1.1263 +	return NULL;
  1.1264 +}
  1.1265 +
  1.1266 +/*
  1.1267 +//////////////////////////////////////////////////////////////////////////
  1.1268 +// Method:		Print
  1.1269 +// Class:		Pk11Install_Info
  1.1270 +*/
  1.1271 +void
  1.1272 +Pk11Install_Info_Print(Pk11Install_Info* _this, int pad)
  1.1273 +{
  1.1274 +	int i;
  1.1275 +
  1.1276 +	PAD(pad); printf("Forward Compatible:\n");
  1.1277 +	for(i = 0; i < _this->numForwardCompatible; i++) {
  1.1278 +		Pk11Install_PlatformName_Print(&_this->forwardCompatible[i],pad+PADINC);
  1.1279 +		PAD(pad); printf("-------------------\n");
  1.1280 +	}
  1.1281 +	PAD(pad); printf("Platforms:\n");
  1.1282 +	for( i = 0; i < _this->numPlatforms; i++) {
  1.1283 +		Pk11Install_Platform_Print(&_this->platforms[i],pad+PADINC);
  1.1284 +		PAD(pad); printf("-------------------\n");
  1.1285 +	}
  1.1286 +}
  1.1287 +
  1.1288 +/*
  1.1289 +//////////////////////////////////////////////////////////////////////////
  1.1290 +*/
  1.1291 +static char*
  1.1292 +PR_Strdup(const char* str)
  1.1293 +{
  1.1294 +	char *tmp;
  1.1295 +	tmp = (char*) PR_Malloc((unsigned int)(strlen(str)+1));
  1.1296 +	strcpy(tmp, str);
  1.1297 +	return tmp;
  1.1298 +}
  1.1299 +
  1.1300 +/* The global value list, the top of the tree */
  1.1301 +Pk11Install_ValueList* Pk11Install_valueList=NULL;
  1.1302 +
  1.1303 +/****************************************************************************/
  1.1304 +void
  1.1305 +Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
  1.1306 +                              Pk11Install_Value *item)
  1.1307 +{
  1.1308 +	_this->numItems++;
  1.1309 +	if (item->type == STRING_VALUE) {
  1.1310 +		_this->numStrings++;
  1.1311 +	} else {
  1.1312 +		_this->numPairs++;
  1.1313 +	}
  1.1314 +	item->next = _this->head;
  1.1315 +	_this->head = item;
  1.1316 +}
  1.1317 +
  1.1318 +/****************************************************************************/
  1.1319 +Pk11Install_ListIter*
  1.1320 +Pk11Install_ListIter_new_default()
  1.1321 +{
  1.1322 +	Pk11Install_ListIter* new_this;
  1.1323 +	new_this = (Pk11Install_ListIter*)
  1.1324 +                    PR_Malloc(sizeof(Pk11Install_ListIter));
  1.1325 +	Pk11Install_ListIter_init(new_this);
  1.1326 +	return new_this;
  1.1327 +}
  1.1328 +
  1.1329 +/****************************************************************************/
  1.1330 +void
  1.1331 +Pk11Install_ListIter_init(Pk11Install_ListIter* _this)
  1.1332 +{
  1.1333 +	_this->list = NULL;
  1.1334 +	_this->current = NULL;
  1.1335 +}
  1.1336 +
  1.1337 +/****************************************************************************/
  1.1338 +Pk11Install_ListIter*
  1.1339 +Pk11Install_ListIter_new(const Pk11Install_ValueList *_list)
  1.1340 +{
  1.1341 +	Pk11Install_ListIter* new_this;
  1.1342 +	new_this = (Pk11Install_ListIter*)
  1.1343 +                    PR_Malloc(sizeof(Pk11Install_ListIter));
  1.1344 +	new_this->list = _list;
  1.1345 +	new_this->current = _list->head;
  1.1346 +	return new_this;
  1.1347 +}
  1.1348 +
  1.1349 +/****************************************************************************/
  1.1350 +void
  1.1351 +Pk11Install_ListIter_delete(Pk11Install_ListIter* _this)
  1.1352 +{
  1.1353 +	_this->list=NULL;
  1.1354 +	_this->current=NULL;
  1.1355 +}
  1.1356 +
  1.1357 +/****************************************************************************/
  1.1358 +void
  1.1359 +Pk11Install_ListIter_reset(Pk11Install_ListIter* _this)
  1.1360 +{
  1.1361 +	if(_this->list) {
  1.1362 +		_this->current = _this->list->head;
  1.1363 +	}
  1.1364 +}
  1.1365 +
  1.1366 +/*************************************************************************/
  1.1367 +Pk11Install_Value*
  1.1368 +Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this)
  1.1369 +{
  1.1370 +	if(_this->current) {
  1.1371 +		_this->current = _this->current->next;
  1.1372 +	}
  1.1373 +
  1.1374 +	return _this->current;
  1.1375 +}
  1.1376 +
  1.1377 +/****************************************************************************/
  1.1378 +Pk11Install_ValueList*
  1.1379 +Pk11Install_ValueList_new()
  1.1380 +{
  1.1381 +	Pk11Install_ValueList* new_this;
  1.1382 +	new_this = (Pk11Install_ValueList*)
  1.1383 +                    PR_Malloc(sizeof(Pk11Install_ValueList));
  1.1384 +	new_this->numItems = 0;
  1.1385 +	new_this->numPairs = 0;
  1.1386 +	new_this->numStrings = 0;
  1.1387 +	new_this->head = NULL;
  1.1388 +	return new_this;
  1.1389 +}
  1.1390 +
  1.1391 +/****************************************************************************/
  1.1392 +void
  1.1393 +Pk11Install_ValueList_delete(Pk11Install_ValueList* _this)
  1.1394 +{
  1.1395 +
  1.1396 +	Pk11Install_Value *tmp;
  1.1397 +	Pk11Install_Value *list;
  1.1398 +	list = _this->head;
  1.1399 +	
  1.1400 +	while(list != NULL) {
  1.1401 +		tmp = list;
  1.1402 +		list = list->next;
  1.1403 +		PR_Free(tmp);
  1.1404 +	}
  1.1405 +	PR_Free(_this);
  1.1406 +}
  1.1407 +
  1.1408 +/****************************************************************************/
  1.1409 +Pk11Install_Value*
  1.1410 +Pk11Install_Value_new_default()
  1.1411 +{
  1.1412 +	Pk11Install_Value* new_this;
  1.1413 +	new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value));
  1.1414 +	new_this->type = STRING_VALUE;
  1.1415 +	new_this->string = NULL;
  1.1416 +	new_this->pair = NULL;
  1.1417 +	new_this->next = NULL;
  1.1418 +	return new_this;
  1.1419 +}
  1.1420 +
  1.1421 +/****************************************************************************/
  1.1422 +Pk11Install_Value*
  1.1423 +Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr)
  1.1424 +{
  1.1425 +	Pk11Install_Value* new_this;
  1.1426 +	new_this = Pk11Install_Value_new_default();
  1.1427 +	new_this->type = _type;
  1.1428 +	if(_type == STRING_VALUE) {
  1.1429 +		new_this->pair = NULL;
  1.1430 +		new_this->string = ptr.string;
  1.1431 +	} else {
  1.1432 +		new_this->string = NULL;
  1.1433 +		new_this->pair = ptr.pair;
  1.1434 +	}
  1.1435 +	return new_this;
  1.1436 +}
  1.1437 +
  1.1438 +/****************************************************************************/
  1.1439 +void
  1.1440 +Pk11Install_Value_delete(Pk11Install_Value* _this)
  1.1441 +{
  1.1442 +	if(_this->type == STRING_VALUE) {
  1.1443 +		PR_Free(_this->string);
  1.1444 +	} else {
  1.1445 +		PR_Free(_this->pair);
  1.1446 +	}
  1.1447 +}
  1.1448 +
  1.1449 +/****************************************************************************/
  1.1450 +Pk11Install_Pair*
  1.1451 +Pk11Install_Pair_new_default()
  1.1452 +{
  1.1453 +	return Pk11Install_Pair_new(NULL,NULL);
  1.1454 +}
  1.1455 +
  1.1456 +/****************************************************************************/
  1.1457 +Pk11Install_Pair*
  1.1458 +Pk11Install_Pair_new(char *_key, Pk11Install_ValueList *_list)
  1.1459 +{
  1.1460 +	Pk11Install_Pair* new_this;
  1.1461 +	new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair));
  1.1462 +	new_this->key = _key;
  1.1463 +	new_this->list = _list;
  1.1464 +	return new_this;
  1.1465 +}
  1.1466 +
  1.1467 +/****************************************************************************/
  1.1468 +void
  1.1469 +Pk11Install_Pair_delete(Pk11Install_Pair* _this)
  1.1470 +{
  1.1471 +	PR_Free(_this->key);
  1.1472 +	Pk11Install_ValueList_delete(_this->list);
  1.1473 +	PR_Free(_this->list);
  1.1474 +}
  1.1475 +
  1.1476 +/*************************************************************************/
  1.1477 +void
  1.1478 +Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad)
  1.1479 +{
  1.1480 +	while (_this) {
  1.1481 +		/*PAD(pad); printf("**Pair\n");
  1.1482 +		PAD(pad); printf("***Key====\n");*/
  1.1483 +		PAD(pad); printf("%s {\n", _this->key);
  1.1484 +		/*PAD(pad); printf("====\n");*/
  1.1485 +		/*PAD(pad); printf("***ValueList\n");*/
  1.1486 +		Pk11Install_ValueList_Print(_this->list,pad+PADINC);
  1.1487 +		PAD(pad); printf("}\n");
  1.1488 +	}
  1.1489 +}
  1.1490 +
  1.1491 +/*************************************************************************/
  1.1492 +void
  1.1493 +Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad)
  1.1494 +{
  1.1495 +	Pk11Install_Value *v;
  1.1496 +
  1.1497 +	/*PAD(pad);printf("**Value List**\n");*/
  1.1498 +	for(v = _this->head; v != NULL; v=v->next) {
  1.1499 +		Pk11Install_Value_Print(v,pad);
  1.1500 +	}
  1.1501 +}
  1.1502 +
  1.1503 +/*************************************************************************/
  1.1504 +void
  1.1505 +Pk11Install_Value_Print(Pk11Install_Value* _this, int pad)
  1.1506 +{
  1.1507 +	/*PAD(pad); printf("**Value, type=%s\n",
  1.1508 +		type==STRING_VALUE ? "string" : "pair");*/
  1.1509 +	if(_this->type==STRING_VALUE) {
  1.1510 +		/*PAD(pad+PADINC); printf("====\n");*/
  1.1511 +		PAD(pad); printf("%s\n", _this->string);
  1.1512 +		/*PAD(pad+PADINC); printf("====\n");*/
  1.1513 +	} else {
  1.1514 +		Pk11Install_Pair_Print(_this->pair,pad+PADINC);
  1.1515 +	}
  1.1516 +}

mercurial