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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "install-ds.h"
     6 #include <prmem.h>
     7 #include <plstr.h>
     8 #include <prprf.h>
     9 #include <string.h>
    11 #define PORT_Strcasecmp PL_strcasecmp
    13 #define MODULE_FILE_STRING "ModuleFile"
    14 #define MODULE_NAME_STRING "ModuleName"
    15 #define MECH_FLAGS_STRING "DefaultMechanismFlags"
    16 #define CIPHER_FLAGS_STRING "DefaultCipherFlags"
    17 #define FILES_STRING "Files"
    18 #define FORWARD_COMPATIBLE_STRING "ForwardCompatible"
    19 #define PLATFORMS_STRING "Platforms"
    20 #define RELATIVE_DIR_STRING "RelativePath"
    21 #define ABSOLUTE_DIR_STRING "AbsolutePath"
    22 #define FILE_PERMISSIONS_STRING "FilePermissions"
    23 #define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform"
    24 #define EXECUTABLE_STRING "Executable"
    26 #define DEFAULT_PERMISSIONS 0777
    28 #define PLATFORM_SEPARATOR_CHAR ':'
    30 /* Error codes */
    31 enum {
    32 	BOGUS_RELATIVE_DIR=0,
    33 	BOGUS_ABSOLUTE_DIR,
    34 	BOGUS_FILE_PERMISSIONS,
    35 	NO_RELATIVE_DIR,
    36 	NO_ABSOLUTE_DIR,
    37 	EMPTY_PLATFORM_STRING,
    38 	BOGUS_PLATFORM_STRING,
    39 	REPEAT_MODULE_FILE,
    40 	REPEAT_MODULE_NAME,
    41 	BOGUS_MODULE_FILE,
    42 	BOGUS_MODULE_NAME,
    43 	REPEAT_MECH,
    44 	BOGUS_MECH_FLAGS,
    45 	REPEAT_CIPHER,
    46 	BOGUS_CIPHER_FLAGS,
    47 	REPEAT_FILES,
    48 	REPEAT_EQUIV,
    49 	BOGUS_EQUIV,
    50 	EQUIV_TOO_MUCH_INFO,
    51 	NO_FILES,
    52 	NO_MODULE_FILE,
    53 	NO_MODULE_NAME,
    54 	NO_PLATFORMS,
    55 	EQUIV_LOOP,
    56 	UNKNOWN_MODULE_FILE
    57 };
    59 /* Indexed by the above error codes */
    60 static const char *errString[] = {
    61 	"%s: Invalid relative directory",
    62 	"%s: Invalid absolute directory",
    63 	"%s: Invalid file permissions",
    64 	"%s: No relative directory specified",
    65 	"%s: No absolute directory specified",
    66 	"Empty string given for platform name",
    67 	"%s: invalid platform string",
    68 	"More than one ModuleFile entry given for platform %s",
    69 	"More than one ModuleName entry given for platform %s",
    70 	"Invalid ModuleFile specification for platform %s",
    71 	"Invalid ModuleName specification for platform %s",
    72 	"More than one DefaultMechanismFlags entry given for platform %s",
    73 	"Invalid DefaultMechanismFlags specification for platform %s",
    74 	"More than one DefaultCipherFlags entry given for platform %s",
    75 	"Invalid DefaultCipherFlags entry given for platform %s",
    76 	"More than one Files entry given for platform %s",
    77 	"More than one EquivalentPlatform entry given for platform %s",
    78 	"Invalid EquivalentPlatform specification for platform %s",
    79 	"Module %s uses an EquivalentPlatform but also specifies its own"
    80 		" information",
    81 	"No Files specification in module %s",
    82 	"No ModuleFile specification in module %s",
    83 	"No ModuleName specification in module %s",
    84 	"No Platforms specification in installer script",
    85 	"Platform %s has an equivalency loop",
    86 	"Module file \"%s\" in platform \"%s\" does not exist"
    87 };
    89 static char* PR_Strdup(const char* str);
    91 #define PAD(x)  {int i; for(i=0;i<x;i++) printf(" ");}
    92 #define PADINC 4
    94 Pk11Install_File*
    95 Pk11Install_File_new()
    96 {
    97 	Pk11Install_File* new_this;
    98 	new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File));
    99 	Pk11Install_File_init(new_this);
   100 	return new_this;
   101 }
   103 void
   104 Pk11Install_File_init(Pk11Install_File* _this)
   105 {
   106 	_this->jarPath=NULL;
   107 	_this->relativePath=NULL;
   108 	_this->absolutePath=NULL;
   109 	_this->executable=PR_FALSE;
   110 	_this->permissions=0;
   111 }
   113 /*
   114 //////////////////////////////////////////////////////////////////////////
   115 // Method:	~Pk11Install_File
   116 // Class:	Pk11Install_File
   117 // Notes:	Destructor.
   118 */
   119 void
   120 Pk11Install_File_delete(Pk11Install_File* _this)
   121 {
   122 	Pk11Install_File_Cleanup(_this);
   123 }
   125 /*
   126 //////////////////////////////////////////////////////////////////////////
   127 // Method:	Cleanup
   128 // Class:	Pk11Install_File
   129 */
   130 void
   131 Pk11Install_File_Cleanup(Pk11Install_File* _this)
   132 {
   133 	if(_this->jarPath) {
   134 		PR_Free(_this->jarPath);
   135 		_this->jarPath = NULL;
   136 	}
   137 	if(_this->relativePath) {
   138 		PR_Free(_this->relativePath);
   139 		_this->relativePath = NULL;
   140 	}
   141 	if(_this->absolutePath) {
   142 		PR_Free(_this->absolutePath);
   143 		_this->absolutePath = NULL;
   144 	}
   146 	_this->permissions = 0;
   147 	_this->executable = PR_FALSE;
   148 }
   150 /*
   151 //////////////////////////////////////////////////////////////////////////
   152 // Method:	Generate
   153 // Class:	Pk11Install_File
   154 // Notes:	Creates a file data structure from a syntax tree.
   155 // Returns:	NULL for success, otherwise an error message.
   156 */
   157 char*
   158 Pk11Install_File_Generate(Pk11Install_File* _this,
   159                           const Pk11Install_Pair *pair)
   160 {
   161 	Pk11Install_ListIter *iter;
   162 	Pk11Install_Value *val;
   163 	Pk11Install_Pair *subpair;
   164 	Pk11Install_ListIter *subiter;
   165 	Pk11Install_Value *subval;
   166 	char* errStr;
   167 	char *endp;
   168 	PRBool gotPerms;
   170 	iter=NULL;
   171 	subiter=NULL;
   172 	errStr=NULL;
   173 	gotPerms=PR_FALSE;
   175 	/* Clear out old values */
   176 	Pk11Install_File_Cleanup(_this);
   178 	_this->jarPath = PR_Strdup(pair->key);
   180 	/* Go through all the pairs under this file heading */
   181 	iter = Pk11Install_ListIter_new(pair->list);
   182 	for( ; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
   183 		if(val->type == PAIR_VALUE) {
   184 			subpair = val->pair;
   186 			/* Relative directory */
   187 			if(!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) {
   188 				subiter = Pk11Install_ListIter_new(subpair->list);
   189 				subval = subiter->current;
   190 				if(!subval || (subval->type != STRING_VALUE)){
   191 					errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR], 
   192                                     _this->jarPath);
   193 					goto loser;
   194 				}
   195 				_this->relativePath = PR_Strdup(subval->string);
   196 				Pk11Install_ListIter_delete(subiter);
   197 				subiter = NULL;
   199 				/* Absolute directory */
   200 			} else if( !PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) {
   201 				subiter = Pk11Install_ListIter_new(subpair->list);
   202 				subval = subiter->current;
   203 				if(!subval || (subval->type != STRING_VALUE)){
   204 					errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR], 
   205                                     _this->jarPath);
   206 					goto loser;
   207 				}
   208 				_this->absolutePath = PR_Strdup(subval->string);
   209 				Pk11Install_ListIter_delete(subiter);
   210 				subiter = NULL;
   212 			/* file permissions */
   213 			} else if( !PORT_Strcasecmp(subpair->key,
   214                                      FILE_PERMISSIONS_STRING)) {
   215 				subiter = Pk11Install_ListIter_new(subpair->list);
   216 				subval = subiter->current;
   217 				if(!subval || (subval->type != STRING_VALUE) ||
   218 				   !subval->string || !subval->string[0]){
   219 					errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
   220                                     _this->jarPath);
   221 					goto loser;
   222 				}
   223 				_this->permissions = (int) strtol(subval->string, &endp, 8);
   224 				if(*endp != '\0') {
   225 					errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
   226                                     _this->jarPath);
   227 					goto loser;
   228 				}
   229 				gotPerms = PR_TRUE;
   230 				Pk11Install_ListIter_delete(subiter);
   231 				subiter = NULL;
   232 			}
   233 		} else {
   234 			if(!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) {
   235 				_this->executable = PR_TRUE;
   236 			}
   237 		}
   238 	}
   240 	/* Default permission value */
   241 	if(!gotPerms) {
   242 		_this->permissions = DEFAULT_PERMISSIONS;
   243 	}
   245 	/* Make sure we got all the information */
   246 	if(!_this->relativePath && !_this->absolutePath) {
   247 		errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
   248 		goto loser;
   249 	}
   250 #if 0
   251 	if(!_this->relativePath ) {
   252 		errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath);
   253 		goto loser;
   254 	}
   255 	if(!_this->absolutePath) {
   256 		errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
   257 		goto loser;
   258 	}
   259 #endif
   261 loser:
   262 	if(iter) {
   263 		Pk11Install_ListIter_delete(iter);
   264 		PR_Free(iter);
   265 	}
   266 	if(subiter) {
   267 		Pk11Install_ListIter_delete(subiter);
   268 		PR_Free(subiter);
   269 	}
   270 	return errStr;
   271 }
   273 /*
   274 //////////////////////////////////////////////////////////////////////////
   275 // Method:	Print
   276 // Class:	Pk11Install_File
   277 */
   278 void
   279 Pk11Install_File_Print(Pk11Install_File* _this, int pad)
   280 {
   281 	PAD(pad); printf("jarPath: %s\n", 
   282                     _this->jarPath ? _this->jarPath : "<NULL>");
   283 	PAD(pad); printf("relativePath: %s\n",
   284 				_this->relativePath ? _this->relativePath: "<NULL>");
   285 	PAD(pad); printf("absolutePath: %s\n",
   286 				_this->absolutePath ? _this->absolutePath: "<NULL>");
   287 	PAD(pad); printf("permissions: %o\n", _this->permissions);
   288 }
   290 Pk11Install_PlatformName*
   291 Pk11Install_PlatformName_new()
   292 {
   293 	Pk11Install_PlatformName* new_this;
   294 	new_this = (Pk11Install_PlatformName*)
   295                PR_Malloc(sizeof(Pk11Install_PlatformName));
   296 	Pk11Install_PlatformName_init(new_this);
   297 	return new_this;
   298 }
   300 void
   301 Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this)
   302 {
   303 	_this->OS = NULL;
   304 	_this->verString = NULL;
   305 	_this->numDigits = 0;
   306 	_this->arch = NULL;
   307 }
   309 /*
   310 //////////////////////////////////////////////////////////////////////////
   311 // Method:	~Pk11Install_PlatformName
   312 // Class:	Pk11Install_PlatformName
   313 */
   314 void
   315 Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this)
   316 {
   317 	Pk11Install_PlatformName_Cleanup(_this);
   318 }
   320 /*
   321 //////////////////////////////////////////////////////////////////////////
   322 // Method:	Cleanup
   323 // Class:	Pk11Install_PlatformName
   324 */
   325 void
   326 Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this)
   327 {
   328 	if(_this->OS) {
   329 		PR_Free(_this->OS);
   330 		_this->OS = NULL;
   331 	}
   332 	if(_this->verString) {
   333 		int i;
   334 		for (i=0; i<_this->numDigits; i++) {
   335 			PR_Free(_this->verString[i]);
   336 		}
   337 		PR_Free(_this->verString);
   338 		_this->verString = NULL;
   339 	}
   340 	if(_this->arch) {
   341 		PR_Free(_this->arch);
   342 		_this->arch = NULL;
   343 	}
   344 	_this->numDigits = 0;
   345 }
   347 /*
   348 //////////////////////////////////////////////////////////////////////////
   349 // Method:	Generate
   350 // Class:	Pk11Install_PlatformName
   351 // Notes:	Extracts the information from a platform string.
   352 */
   353 char*
   354 Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
   355                                   const char *str)
   356 {
   357 	char *errStr;
   358 	char *copy;
   359 	char *end, *start; /* start and end of a section (OS, version, arch)*/
   360 	char *pend, *pstart; /* start and end of one portion of version*/
   361 	char *endp; /* used by strtol*/
   362 	int periods, i;
   364 	errStr=NULL;
   365 	copy=NULL;
   367 	if(!str) {
   368 		errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]);
   369 		goto loser;
   370 	}
   371 	copy = PR_Strdup(str);
   373 	/*
   374 	// Get the OS
   375 	*/
   376 	end = strchr(copy, PLATFORM_SEPARATOR_CHAR);
   377 	if(!end || end==copy) {
   378 		errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   379 		goto loser;
   380 	}
   381 	*end = '\0';
   383 	_this->OS = PR_Strdup(copy);
   385 	/*
   386 	// Get the digits of the version of form: x.x.x (arbitrary number of digits)
   387 	*/
   389 	start = end+1;
   390 	end = strchr(start, PLATFORM_SEPARATOR_CHAR);
   391 	if(!end) {
   392 		errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   393 		goto loser;
   394 	}
   395 	*end = '\0';
   397 	if(end!=start) { 
   398 		/* Find out how many periods*/
   399 		periods = 0;
   400 		pstart = start;
   401 		while( (pend=strchr(pstart, '.')) ) {
   402 			periods++;
   403 			pstart = pend+1;
   404 		}
   405 		_this->numDigits= 1+ periods;
   406 		_this->verString = (char**)PR_Malloc(sizeof(char*)*_this->numDigits);
   408 		pstart = start;
   409 		i = 0;
   410 		/* Get the digits before each period*/
   411 		while( (pend=strchr(pstart, '.')) ) {
   412 			if(pend == pstart) {
   413 				errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   414 				goto loser;
   415 			}
   416 			*pend = '\0';
   417 			_this->verString[i] = PR_Strdup(pstart);
   418 			endp = pend;
   419 		if(endp==pstart || (*endp != '\0')) {
   420 				errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   421 				goto loser;
   422 			}
   423 			pstart = pend+1;
   424 			i++;
   425 		}
   426 		/* Last digit comes after the last period*/
   427 		if(*pstart == '\0') {
   428 			errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   429 			goto loser;
   430 		}
   431 		_this->verString[i] = PR_Strdup(pstart);
   432 		/*
   433 		if(endp==pstart || (*endp != '\0')) {
   434 			errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   435 			goto loser;
   436 		}
   437 		*/
   438 	} else {
   439 		_this->verString = NULL;
   440 		_this->numDigits = 0;
   441 	}
   443 	/*
   444 	// Get the architecture
   445 	*/
   446 	start = end+1;
   447 	if( strchr(start, PLATFORM_SEPARATOR_CHAR) ) {
   448 		errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
   449 		goto loser;
   450 	}
   451 	_this->arch = PR_Strdup(start);
   453 	if(copy) {
   454 		PR_Free(copy);
   455 	}
   456 	return NULL;
   457 loser:
   458 	if(_this->OS) {
   459 		PR_Free(_this->OS);
   460 		_this->OS = NULL;
   461 	}
   462 	if(_this->verString) {
   463 		for (i=0; i<_this->numDigits; i++) {
   464 			PR_Free(_this->verString[i]);
   465 		}
   466 		PR_Free(_this->verString);
   467 		_this->verString = NULL;
   468 	}
   469 	_this->numDigits = 0;
   470 	if(_this->arch) {
   471 		PR_Free(_this->arch);
   472 		_this->arch = NULL;
   473 	}
   475 	return errStr;
   476 }
   478 /*
   479 //////////////////////////////////////////////////////////////////////////
   480 // Method:	operator ==
   481 // Class:	Pk11Install_PlatformName
   482 // Returns:	PR_TRUE if the platform have the same OS, arch, and version
   483 */
   484 PRBool
   485 Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
   486                                Pk11Install_PlatformName* cmp) 
   487 {
   488 	int i;
   490 	if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
   491 		return PR_FALSE;
   492 	}
   494 	if(	PORT_Strcasecmp(_this->OS, cmp->OS) ||
   495 		PORT_Strcasecmp(_this->arch, cmp->arch) ||
   496 		_this->numDigits != cmp->numDigits ) {
   497 			return PR_FALSE;
   498 	}
   500 	for(i=0; i < _this->numDigits; i++) {
   501 		if(PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) {
   502 			return PR_FALSE;
   503 		}
   504 	}
   505 	return PR_TRUE;
   506 }
   508 /*
   509 //////////////////////////////////////////////////////////////////////////
   510 // Method:	operator <=
   511 // Class:	Pk11Install_PlatformName
   512 // Returns:	PR_TRUE if the platform have the same OS and arch and a lower
   513 //			or equal release.
   514 */
   515 PRBool
   516 Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
   517                               Pk11Install_PlatformName* cmp)
   518 {
   519 	return (Pk11Install_PlatformName_equal(_this,cmp) ||
   520           Pk11Install_PlatformName_lt(_this,cmp)) ? PR_TRUE : PR_FALSE;
   521 }
   523 /*
   524 //////////////////////////////////////////////////////////////////////////
   525 // Method:	operator <
   526 // Class:	Pk11Install_PlatformName
   527 // Returns:	PR_TRUE if the platform have the same OS and arch and a greater
   528 //			release.
   529 */
   530 PRBool
   531 Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
   532                             Pk11Install_PlatformName* cmp)
   533 {
   534 	int i, scmp;
   536 	if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
   537 		return PR_FALSE;
   538 	}
   540 	if( PORT_Strcasecmp(_this->OS, cmp->OS) ) {
   541 		return PR_FALSE;
   542 	}
   543 	if( PORT_Strcasecmp(_this->arch, cmp->arch) ) {
   544 		return PR_FALSE;
   545 	}
   547 	for(i=0; (i < _this->numDigits) && (i < cmp->numDigits); i++) {
   548 		scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]);
   549 		if (scmp > 0) {
   550 			return PR_FALSE;
   551 		} else if (scmp < 0) {
   552 			return PR_TRUE;
   553 		}
   554 	}
   555 	/* All the digits they have in common are the same. */
   556 	if(_this->numDigits < cmp->numDigits) {
   557 		return  PR_TRUE;
   558 	} 
   560 	return PR_FALSE;
   561 }
   563 /*
   564 //////////////////////////////////////////////////////////////////////////
   565 // Method:	GetString
   566 // Class:	Pk11Install_PlatformName
   567 // Returns:	String composed of OS, release, and architecture separated
   568 //			by the separator char.  Memory is allocated by this function
   569 //			but is the responsibility of the caller to de-allocate.
   570 */
   571 char*
   572 Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this) 
   573 {
   574 	char *ret;
   575 	char *ver;
   576 	char *OS_;
   577 	char *arch_;
   579 	OS_=NULL;
   580 	arch_=NULL;
   582 	OS_ = _this->OS ? _this->OS : "";
   583 	arch_ = _this->arch ? _this->arch : "";
   585 	ver = Pk11Install_PlatformName_GetVerString(_this);
   586 	ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver,
   587 					PLATFORM_SEPARATOR_CHAR, arch_);
   589 	PR_Free(ver);
   591 	return ret;
   592 }
   594 /*
   595 //////////////////////////////////////////////////////////////////////////
   596 // Method:	GetVerString
   597 // Class:	Pk11Install_PlatformName
   598 // Returns:	The version string for this platform, in the form x.x.x with an
   599 //			arbitrary number of digits.  Memory allocated by function,
   600 //			must be de-allocated by caller.
   601 */
   602 char*
   603 Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this) 
   604 {
   605 	char *tmp;
   606 	char *ret;
   607 	int i;
   608 	char buf[80];
   610 	tmp = (char*)PR_Malloc(80*_this->numDigits+1);
   611 	tmp[0] = '\0';
   613 	for(i=0; i < _this->numDigits-1; i++) {
   614 		sprintf(buf, "%s.", _this->verString[i]);
   615 		strcat(tmp, buf);
   616 	}
   617 	if(i < _this->numDigits) {
   618 		sprintf(buf, "%s", _this->verString[i]);
   619 		strcat(tmp, buf);
   620 	}
   622 	ret = PR_Strdup(tmp);
   623 	free(tmp);
   625 	return ret;
   626 }
   628 /*
   629 //////////////////////////////////////////////////////////////////////////
   630 // Method:	Print
   631 // Class:	Pk11Install_PlatformName
   632 */
   633 void
   634 Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad)
   635 {
   636 	PAD(pad); printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>");
   637 	PAD(pad); printf("Digits: ");
   638 	if(_this->numDigits == 0) {
   639 		printf("None\n");
   640 	} else {
   641 		printf("%s\n", Pk11Install_PlatformName_GetVerString(_this));
   642 	}
   643 	PAD(pad); printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>");
   644 }
   646 Pk11Install_Platform*
   647 Pk11Install_Platform_new()
   648 {
   649 	Pk11Install_Platform* new_this;
   650 	new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform));
   651 	Pk11Install_Platform_init(new_this);
   652 	return new_this;
   653 }
   655 void
   656 Pk11Install_Platform_init(Pk11Install_Platform* _this)
   657 {
   658 	Pk11Install_PlatformName_init(&_this->name);
   659 	Pk11Install_PlatformName_init(&_this->equivName);
   660 	_this->equiv = NULL;
   661 	_this->usesEquiv = PR_FALSE;
   662 	_this->moduleFile = NULL;
   663 	_this->moduleName = NULL;
   664 	_this->modFile = -1;
   665 	_this->mechFlags = 0;
   666 	_this->cipherFlags = 0;
   667 	_this->files = NULL;
   668 	_this->numFiles = 0;
   669 }
   671 /*
   672 //////////////////////////////////////////////////////////////////////////
   673 // Method:	~Pk11Install_Platform
   674 // Class:	Pk11Install_Platform
   675 */
   676 void
   677 Pk11Install_Platform_delete(Pk11Install_Platform* _this)
   678 {
   679 	Pk11Install_Platform_Cleanup(_this);
   680 }
   682 /*
   683 //////////////////////////////////////////////////////////////////////////
   684 // Method:	Cleanup
   685 // Class:	Pk11Install_Platform
   686 */
   687 void
   688 Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this)
   689 {
   690 	int i;
   691 	if(_this->moduleFile) {
   692 		PR_Free(_this->moduleFile);
   693 		_this->moduleFile = NULL;
   694 	}
   695 	if(_this->moduleName) {
   696 		PR_Free(_this->moduleName);
   697 		_this->moduleName = NULL;
   698 	}
   699 	if(_this->files) {
   700 		for (i=0;i<_this->numFiles;i++) {
   701 			Pk11Install_File_delete(&_this->files[i]);
   702 		}
   703 		PR_Free(_this->files);
   704 		_this->files = NULL;
   705 	}
   706 	_this->equiv = NULL;
   707 	_this->usesEquiv = PR_FALSE;
   708 	_this->modFile = -1;
   709 	_this->numFiles = 0;
   710 	_this->mechFlags = _this->cipherFlags = 0;
   711 }
   713 /*
   714 //////////////////////////////////////////////////////////////////////////
   715 // Method:	Generate
   716 // Class:	Pk11Install_Platform
   717 // Notes:	Creates a platform data structure from a syntax tree.
   718 // Returns:	NULL for success, otherwise an error message.
   719 */
   720 char*
   721 Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
   722                               const Pk11Install_Pair *pair)
   723 {
   724 	char* errStr;
   725 	char* endptr;
   726 	char* tmp;
   727 	int i;
   728 	Pk11Install_ListIter *iter;
   729 	Pk11Install_Value *val;
   730 	Pk11Install_Value *subval;
   731 	Pk11Install_Pair *subpair;
   732 	Pk11Install_ListIter *subiter;
   733 	PRBool gotModuleFile, gotModuleName, gotMech, 
   734           gotCipher, gotFiles, gotEquiv;
   736 	errStr=NULL;
   737 	iter=subiter=NULL;
   738 	val=subval=NULL;
   739 	subpair=NULL;
   740 	gotModuleFile=gotModuleName=gotMech=gotCipher=gotFiles=gotEquiv=PR_FALSE;
   741 	Pk11Install_Platform_Cleanup(_this);
   743 	errStr = Pk11Install_PlatformName_Generate(&_this->name,pair->key);
   744 	if(errStr) {
   745 		tmp = PR_smprintf("%s: %s", pair->key, errStr);
   746 		PR_smprintf_free(errStr);
   747 		errStr = tmp;
   748 		goto loser;
   749 	}
   751 	iter = Pk11Install_ListIter_new(pair->list);
   752 	for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
   753 		if(val->type==PAIR_VALUE) {
   754 			subpair = val->pair;
   756 			if( !PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) {
   757 				if(gotModuleFile) {
   758 					errStr = PR_smprintf(errString[REPEAT_MODULE_FILE],
   759                                     Pk11Install_PlatformName_GetString(&_this->name));
   760 					goto loser;
   761 				}
   762 				subiter = Pk11Install_ListIter_new(subpair->list);
   763 				subval = subiter->current;
   764 				if(!subval || (subval->type != STRING_VALUE)) {
   765 					errStr = PR_smprintf(errString[BOGUS_MODULE_FILE],
   766                                     Pk11Install_PlatformName_GetString(&_this->name));
   767 					goto loser;
   768 				}
   769 				_this->moduleFile = PR_Strdup(subval->string);
   770 				Pk11Install_ListIter_delete(subiter);
   771 				PR_Free(subiter);
   772 				subiter = NULL;
   773 				gotModuleFile = PR_TRUE;
   774 			} else if(!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)){
   775 				if(gotModuleName) {
   776 					errStr = PR_smprintf(errString[REPEAT_MODULE_NAME],
   777                                     Pk11Install_PlatformName_GetString(&_this->name));
   778 					goto loser;
   779 				}
   780 				subiter = Pk11Install_ListIter_new(subpair->list);
   781 				subval = subiter->current;
   782 				if(!subval || (subval->type != STRING_VALUE)) {
   783 					errStr = PR_smprintf(errString[BOGUS_MODULE_NAME],
   784                                     Pk11Install_PlatformName_GetString(&_this->name));
   785 					goto loser;
   786 				}
   787 				_this->moduleName = PR_Strdup(subval->string);
   788 				Pk11Install_ListIter_delete(subiter);
   789 				PR_Free(subiter);
   790 				subiter = NULL;
   791 				gotModuleName = PR_TRUE;
   792 			} else if(!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) {
   793 				endptr=NULL;
   795 				if(gotMech) {
   796 					errStr = PR_smprintf(errString[REPEAT_MECH],
   797                                     Pk11Install_PlatformName_GetString(&_this->name));
   798 					goto loser;
   799 				}
   800 				subiter = Pk11Install_ListIter_new(subpair->list);
   801 				subval = subiter->current;
   802 				if(!subval || (subval->type != STRING_VALUE)) {
   803 					errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
   804                                     Pk11Install_PlatformName_GetString(&_this->name));
   805 					goto loser;
   806 				}
   807 				_this->mechFlags = strtol(subval->string, &endptr, 0);
   808 				if(*endptr!='\0' || (endptr==subval->string) ) {
   809 					errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
   810                                     Pk11Install_PlatformName_GetString(&_this->name));
   811 					goto loser;
   812 				}
   813 				Pk11Install_ListIter_delete(subiter);
   814 				PR_Free(subiter);
   815 				subiter=NULL;
   816 				gotMech = PR_TRUE;
   817 			} else if(!PORT_Strcasecmp(subpair->key,CIPHER_FLAGS_STRING)) {
   818 				endptr=NULL;
   820 				if(gotCipher) {
   821 					errStr = PR_smprintf(errString[REPEAT_CIPHER],
   822                                     Pk11Install_PlatformName_GetString(&_this->name));
   823 					goto loser;
   824 				}
   825 				subiter = Pk11Install_ListIter_new(subpair->list);
   826 				subval = subiter->current;
   827 				if(!subval || (subval->type != STRING_VALUE)) {
   828 					errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
   829                                     Pk11Install_PlatformName_GetString(&_this->name));
   830 					goto loser;
   831 				}
   832 				_this->cipherFlags = strtol(subval->string, &endptr, 0);
   833 				if(*endptr!='\0' || (endptr==subval->string) ) {
   834 					errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
   835                                     Pk11Install_PlatformName_GetString(&_this->name));
   836 					goto loser;
   837 				}
   838 				Pk11Install_ListIter_delete(subiter);
   839 				PR_Free(subiter);
   840 				subiter=NULL;
   841 				gotCipher = PR_TRUE;
   842 			} else if(!PORT_Strcasecmp(subpair->key, FILES_STRING)) {
   843 				if(gotFiles) {
   844 					errStr = PR_smprintf(errString[REPEAT_FILES],
   845                                     Pk11Install_PlatformName_GetString(&_this->name));
   846 					goto loser;
   847 				}
   848 				subiter = Pk11Install_ListIter_new(subpair->list);
   849 				_this->numFiles = subpair->list->numPairs;
   850 				_this->files = (Pk11Install_File*)
   851                             PR_Malloc(sizeof(Pk11Install_File)*_this->numFiles);
   852 				for(i=0; i < _this->numFiles; i++, 
   853                                    Pk11Install_ListIter_nextItem(subiter)) {
   854 					Pk11Install_File_init(&_this->files[i]);
   855 					val = subiter->current;
   856 					if(val && (val->type==PAIR_VALUE)) {
   857 						errStr = Pk11Install_File_Generate(&_this->files[i],val->pair);
   858 						if(errStr) {
   859 							tmp = PR_smprintf("%s: %s", 
   860                                        Pk11Install_PlatformName_GetString(&_this->name),errStr);
   861 							PR_smprintf_free(errStr);
   862 							errStr = tmp;
   863 							goto loser;
   864 						}
   865 					}
   866 				}
   867 				gotFiles = PR_TRUE;
   868 			} else if(!PORT_Strcasecmp(subpair->key,
   869                                     EQUIVALENT_PLATFORM_STRING)) {
   870 				if(gotEquiv) {
   871 					errStr = PR_smprintf(errString[REPEAT_EQUIV],
   872                                     Pk11Install_PlatformName_GetString(&_this->name));
   873 					goto loser;
   874 				}
   875 				subiter = Pk11Install_ListIter_new(subpair->list);
   876 				subval = subiter->current;
   877 				if(!subval || (subval->type != STRING_VALUE) ) {
   878 					errStr = PR_smprintf(errString[BOGUS_EQUIV],
   879                                Pk11Install_PlatformName_GetString(&_this->name));
   880 					goto loser;
   881 				}
   882 				errStr = Pk11Install_PlatformName_Generate(&_this->equivName,
   883                                                        subval->string);
   884 				if(errStr) {
   885 					tmp = PR_smprintf("%s: %s", 
   886                             Pk11Install_PlatformName_GetString(&_this->name), errStr);
   887 					tmp = PR_smprintf("%s: %s", 
   888                             Pk11Install_PlatformName_GetString(&_this->name), errStr);
   889 					PR_smprintf_free(errStr);
   890 					errStr = tmp;
   891 					goto loser;
   892 				}
   893 				_this->usesEquiv = PR_TRUE;
   894 			}
   895 		}
   896 	}
   898 	/* Make sure we either have an EquivalentPlatform or all the other info */
   899 	if(_this->usesEquiv &&
   900 		(gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) {
   901 		errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO], 
   902                            Pk11Install_PlatformName_GetString(&_this->name));
   903 		goto loser;
   904 	}
   905 	if(!gotFiles && !_this->usesEquiv) {
   906 		errStr = PR_smprintf(errString[NO_FILES], 
   907                            Pk11Install_PlatformName_GetString(&_this->name));
   908 		goto loser;
   909 	}
   910 	if(!gotModuleFile && !_this->usesEquiv) {
   911 		errStr= PR_smprintf(errString[NO_MODULE_FILE], 
   912                           Pk11Install_PlatformName_GetString(&_this->name));
   913 		goto loser;
   914 	}
   915 	if(!gotModuleName && !_this->usesEquiv) {
   916 		errStr = PR_smprintf(errString[NO_MODULE_NAME], 
   917                           Pk11Install_PlatformName_GetString(&_this->name));
   918 		goto loser;
   919 	}
   921 	/* Point the modFile pointer to the correct file */
   922 	if(gotModuleFile) {
   923 		for(i=0; i < _this->numFiles; i++) {
   924 			if(!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath) ) {
   925 				_this->modFile = i;
   926 				break;
   927 			}
   928 		}
   929 		if(_this->modFile==-1) {
   930 			errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE], 
   931                               _this->moduleFile,
   932                               Pk11Install_PlatformName_GetString(&_this->name));
   933 			goto loser;
   934 		}
   935 	}
   937 loser:
   938 	if(iter) {
   939 		PR_Free(iter);
   940 	}
   941 	if(subiter) {
   942 		PR_Free(subiter);
   943 	}
   944 	return errStr;
   945 }
   947 /*
   948 //////////////////////////////////////////////////////////////////////////
   949 // Method:		Print
   950 // Class:		Pk11Install_Platform
   951 */
   952 void
   953 Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
   954 {
   955 	int i;
   957 	PAD(pad); printf("Name:\n"); 
   958 	Pk11Install_PlatformName_Print(&_this->name,pad+PADINC);
   959 	PAD(pad); printf("equivName:\n"); 
   960 	Pk11Install_PlatformName_Print(&_this->equivName,pad+PADINC);
   961 	PAD(pad);
   962 	if(_this->usesEquiv) {
   963 		printf("Uses equiv, which points to:\n");
   964 		Pk11Install_Platform_Print(_this->equiv,pad+PADINC);
   965 	} else {
   966 		printf("Doesn't use equiv\n");
   967 	}
   968 	PAD(pad); 
   969 	printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile 
   970                                                  : "<NULL>");
   971 	PAD(pad); printf("mechFlags: %lx\n", _this->mechFlags);
   972 	PAD(pad); printf("cipherFlags: %lx\n", _this->cipherFlags);
   973 	PAD(pad); printf("Files:\n");
   974 	for(i=0; i < _this->numFiles; i++) {
   975 		Pk11Install_File_Print(&_this->files[i],pad+PADINC);
   976 		PAD(pad); printf("--------------------\n");
   977 	}
   978 }
   980 /*
   981 //////////////////////////////////////////////////////////////////////////
   982 // Method:		Pk11Install_Info
   983 // Class:		Pk11Install_Info
   984 */
   985 Pk11Install_Info*
   986 Pk11Install_Info_new()
   987 {
   988 	Pk11Install_Info* new_this;
   989 	new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info));
   990 	Pk11Install_Info_init(new_this);
   991 	return new_this;
   992 }
   994 void
   995 Pk11Install_Info_init(Pk11Install_Info* _this)
   996 {
   997 	_this->platforms = NULL;
   998 	_this->numPlatforms = 0;
   999 	_this->forwardCompatible = NULL;
  1000 	_this->numForwardCompatible = 0;
  1003 /*
  1004 //////////////////////////////////////////////////////////////////////////
  1005 // Method:		~Pk11Install_Info
  1006 // Class:		Pk11Install_Info
  1007 */
  1008 void
  1009 Pk11Install_Info_delete(Pk11Install_Info* _this)
  1011 	Pk11Install_Info_Cleanup(_this);
  1014 /*
  1015 //////////////////////////////////////////////////////////////////////////
  1016 // Method:		Cleanup
  1017 // Class:		Pk11Install_Info
  1018 */
  1019 void
  1020 Pk11Install_Info_Cleanup(Pk11Install_Info* _this)
  1022 	int i;
  1023 	if(_this->platforms) {
  1024 		for (i=0;i<_this->numPlatforms;i++) {
  1025 			Pk11Install_Platform_delete(&_this->platforms[i]);
  1027 		PR_Free(&_this->platforms);
  1028 		_this->platforms = NULL;
  1029 		_this->numPlatforms = 0;
  1032 	if(_this->forwardCompatible) {
  1033 		for (i=0;i<_this->numForwardCompatible;i++) {
  1034 			Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]);
  1036 		PR_Free(&_this->forwardCompatible);
  1037 		_this->numForwardCompatible = 0;
  1041 /*
  1042 //////////////////////////////////////////////////////////////////////////
  1043 // Method:		Generate
  1044 // Class:		Pk11Install_Info
  1045 // Takes:		Pk11Install_ValueList *list, the top-level list
  1046 //				resulting from parsing an installer file.
  1047 // Returns:		char*, NULL if successful, otherwise an error string.
  1048 //				Caller is responsible for freeing memory.
  1049 */
  1050 char*
  1051 Pk11Install_Info_Generate(Pk11Install_Info* _this,
  1052                           const Pk11Install_ValueList *list)
  1054 	char *errStr;
  1055 	Pk11Install_ListIter *iter;
  1056 	Pk11Install_Value *val;
  1057 	Pk11Install_Pair *pair;
  1058 	Pk11Install_ListIter *subiter;
  1059 	Pk11Install_Value *subval;
  1060 	Pk11Install_Platform *first, *second;
  1061 	int i, j;
  1063 	errStr=NULL;
  1064 	iter=subiter=NULL;
  1065 	Pk11Install_Info_Cleanup(_this);
  1067 	iter = Pk11Install_ListIter_new(list);
  1068 	for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
  1069 		if(val->type == PAIR_VALUE) {
  1070 			pair = val->pair;
  1072 			if(!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) {
  1073 				subiter = Pk11Install_ListIter_new(pair->list);
  1074 				_this->numForwardCompatible = pair->list->numStrings;
  1075 				_this->forwardCompatible = (Pk11Install_PlatformName*)
  1076                                         PR_Malloc(sizeof(Pk11Install_PlatformName)*
  1077                                                _this->numForwardCompatible);
  1078 				for(i=0; i < _this->numForwardCompatible; i++, 
  1079                        Pk11Install_ListIter_nextItem(subiter)) {
  1080 					subval = subiter->current;
  1081 					if(subval->type == STRING_VALUE) {
  1082 						errStr = Pk11Install_PlatformName_Generate(
  1083                               &_this->forwardCompatible[i], subval->string);
  1084 						if(errStr) {
  1085 							goto loser;
  1089 				Pk11Install_ListIter_delete(subiter);
  1090 				PR_Free(subiter);
  1091 				subiter = NULL;
  1092 			} else if(!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) {
  1093 				subiter = Pk11Install_ListIter_new(pair->list);
  1094 				_this->numPlatforms = pair->list->numPairs;
  1095 				_this->platforms = (Pk11Install_Platform*)
  1096                             PR_Malloc(sizeof(Pk11Install_Platform)*
  1097                             _this->numPlatforms);
  1098 				for(i=0; i < _this->numPlatforms; i++, 
  1099                        Pk11Install_ListIter_nextItem(subiter)) {
  1100 					 Pk11Install_Platform_init(&_this->platforms[i]);
  1101 					subval = subiter->current;
  1102 					if(subval->type == PAIR_VALUE) {
  1103 						errStr = Pk11Install_Platform_Generate(&_this->platforms[i],subval->pair);
  1104 						if(errStr) {
  1105 							goto loser;
  1109 				Pk11Install_ListIter_delete(subiter);
  1110 				PR_Free(subiter);
  1111 				subiter = NULL;
  1116 	if(_this->numPlatforms == 0) {
  1117 		errStr = PR_smprintf(errString[NO_PLATFORMS]);
  1118 		goto loser;
  1121 /*
  1122 	//
  1123 	// Now process equivalent platforms
  1124 	//
  1126 	// First the naive pass
  1127 */
  1128 	for(i=0; i < _this->numPlatforms; i++) {
  1129 		if(_this->platforms[i].usesEquiv) {
  1130 			_this->platforms[i].equiv = NULL;
  1131 			for(j=0; j < _this->numPlatforms; j++) {
  1132 				if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName,
  1133                                            &_this->platforms[j].name)) {
  1134 					if(i==j) {
  1135 						errStr = PR_smprintf(errString[EQUIV_LOOP],
  1136                               Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1137 						goto loser;
  1139 					_this->platforms[i].equiv = &_this->platforms[j];
  1140 					break;
  1143 			if(_this->platforms[i].equiv == NULL) {
  1144 				errStr = PR_smprintf(errString[BOGUS_EQUIV],
  1145                        Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1146 				goto loser;
  1151 /*
  1152 	// Now the intelligent pass, which will also detect loops.
  1153 	// We will send two pointers through the linked list of equivalent
  1154 	// platforms. Both start with the current node.  "first" traverses
  1155 	// two nodes for each iteration.  "second" lags behind, only traversing
  1156 	// one node per iteration.  Eventually one of two things will happen:
  1157 	// first will hit the end of the list (a platform that doesn't use
  1158 	// an equivalency), or first will equal second if there is a loop.
  1159 */
  1160 	for(i=0; i < _this->numPlatforms; i++) {
  1161 		if(_this->platforms[i].usesEquiv) {
  1162 			second = _this->platforms[i].equiv;
  1163 			if(!second->usesEquiv) {
  1164 				/* The first link is the terminal node */
  1165 				continue;
  1167 			first = second->equiv;
  1168 			while(first->usesEquiv) {
  1169 				if(first == second) {
  1170 					errStr = PR_smprintf(errString[EQUIV_LOOP],
  1171                          Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1172 					goto loser;
  1174 				first = first->equiv;
  1175 				if(!first->usesEquiv) {
  1176 					break;
  1178 				if(first == second) {
  1179 					errStr = PR_smprintf(errString[EQUIV_LOOP],
  1180                        Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
  1181 					goto loser;
  1183 				second = second->equiv;
  1184 				first = first->equiv;
  1186 			_this->platforms[i].equiv = first;
  1190 loser:
  1191 	if(iter) {
  1192 		Pk11Install_ListIter_delete(iter);
  1193 		PR_Free(iter);
  1194 		iter = NULL;
  1196 	if(subiter) {
  1197 		Pk11Install_ListIter_delete(subiter);
  1198 		PR_Free(subiter);
  1199 		subiter = NULL;
  1201 	return errStr;
  1204 /*
  1205 //////////////////////////////////////////////////////////////////////////
  1206 // Method:		GetBestPlatform
  1207 // Class:		Pk11Install_Info
  1208 // Takes:		char *myPlatform, the platform we are currently running
  1209 //				on.
  1210 */
  1211 Pk11Install_Platform*
  1212 Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char *myPlatform)
  1214 	Pk11Install_PlatformName plat;
  1215 	char *errStr;
  1216 	int i, j;
  1218 	errStr=NULL;
  1220 	Pk11Install_PlatformName_init(&plat);
  1221 	if( (errStr=Pk11Install_PlatformName_Generate(&plat, myPlatform)) ) {
  1222 		PR_smprintf_free(errStr);
  1223 		return NULL;
  1226 	/* First try real platforms */
  1227 	for(i=0; i < _this->numPlatforms; i++) {
  1228 		if(Pk11Install_PlatformName_equal(&_this->platforms[i].name,&plat)) {
  1229 			if(_this->platforms[i].equiv) {
  1230 				return _this->platforms[i].equiv;
  1232 			else {
  1233 				return &_this->platforms[i];
  1238 	/* Now try forward compatible platforms */
  1239 	for(i=0; i < _this->numForwardCompatible; i++) {
  1240 		if(Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i],&plat)) {
  1241 			break;
  1244 	if(i == _this->numForwardCompatible) {
  1245 		return NULL;
  1248 	/* Got a forward compatible name, find the actual platform. */
  1249 	for(j=0; j < _this->numPlatforms; j++) {
  1250 		if(Pk11Install_PlatformName_equal(&_this->platforms[j].name,
  1251          &_this->forwardCompatible[i])) {
  1252 			if(_this->platforms[j].equiv) {
  1253 				return _this->platforms[j].equiv;
  1254 			} else {
  1255 				return &_this->platforms[j];
  1260 	return NULL;
  1263 /*
  1264 //////////////////////////////////////////////////////////////////////////
  1265 // Method:		Print
  1266 // Class:		Pk11Install_Info
  1267 */
  1268 void
  1269 Pk11Install_Info_Print(Pk11Install_Info* _this, int pad)
  1271 	int i;
  1273 	PAD(pad); printf("Forward Compatible:\n");
  1274 	for(i = 0; i < _this->numForwardCompatible; i++) {
  1275 		Pk11Install_PlatformName_Print(&_this->forwardCompatible[i],pad+PADINC);
  1276 		PAD(pad); printf("-------------------\n");
  1278 	PAD(pad); printf("Platforms:\n");
  1279 	for( i = 0; i < _this->numPlatforms; i++) {
  1280 		Pk11Install_Platform_Print(&_this->platforms[i],pad+PADINC);
  1281 		PAD(pad); printf("-------------------\n");
  1285 /*
  1286 //////////////////////////////////////////////////////////////////////////
  1287 */
  1288 static char*
  1289 PR_Strdup(const char* str)
  1291 	char *tmp;
  1292 	tmp = (char*) PR_Malloc((unsigned int)(strlen(str)+1));
  1293 	strcpy(tmp, str);
  1294 	return tmp;
  1297 /* The global value list, the top of the tree */
  1298 Pk11Install_ValueList* Pk11Install_valueList=NULL;
  1300 /****************************************************************************/
  1301 void
  1302 Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
  1303                               Pk11Install_Value *item)
  1305 	_this->numItems++;
  1306 	if (item->type == STRING_VALUE) {
  1307 		_this->numStrings++;
  1308 	} else {
  1309 		_this->numPairs++;
  1311 	item->next = _this->head;
  1312 	_this->head = item;
  1315 /****************************************************************************/
  1316 Pk11Install_ListIter*
  1317 Pk11Install_ListIter_new_default()
  1319 	Pk11Install_ListIter* new_this;
  1320 	new_this = (Pk11Install_ListIter*)
  1321                     PR_Malloc(sizeof(Pk11Install_ListIter));
  1322 	Pk11Install_ListIter_init(new_this);
  1323 	return new_this;
  1326 /****************************************************************************/
  1327 void
  1328 Pk11Install_ListIter_init(Pk11Install_ListIter* _this)
  1330 	_this->list = NULL;
  1331 	_this->current = NULL;
  1334 /****************************************************************************/
  1335 Pk11Install_ListIter*
  1336 Pk11Install_ListIter_new(const Pk11Install_ValueList *_list)
  1338 	Pk11Install_ListIter* new_this;
  1339 	new_this = (Pk11Install_ListIter*)
  1340                     PR_Malloc(sizeof(Pk11Install_ListIter));
  1341 	new_this->list = _list;
  1342 	new_this->current = _list->head;
  1343 	return new_this;
  1346 /****************************************************************************/
  1347 void
  1348 Pk11Install_ListIter_delete(Pk11Install_ListIter* _this)
  1350 	_this->list=NULL;
  1351 	_this->current=NULL;
  1354 /****************************************************************************/
  1355 void
  1356 Pk11Install_ListIter_reset(Pk11Install_ListIter* _this)
  1358 	if(_this->list) {
  1359 		_this->current = _this->list->head;
  1363 /*************************************************************************/
  1364 Pk11Install_Value*
  1365 Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this)
  1367 	if(_this->current) {
  1368 		_this->current = _this->current->next;
  1371 	return _this->current;
  1374 /****************************************************************************/
  1375 Pk11Install_ValueList*
  1376 Pk11Install_ValueList_new()
  1378 	Pk11Install_ValueList* new_this;
  1379 	new_this = (Pk11Install_ValueList*)
  1380                     PR_Malloc(sizeof(Pk11Install_ValueList));
  1381 	new_this->numItems = 0;
  1382 	new_this->numPairs = 0;
  1383 	new_this->numStrings = 0;
  1384 	new_this->head = NULL;
  1385 	return new_this;
  1388 /****************************************************************************/
  1389 void
  1390 Pk11Install_ValueList_delete(Pk11Install_ValueList* _this)
  1393 	Pk11Install_Value *tmp;
  1394 	Pk11Install_Value *list;
  1395 	list = _this->head;
  1397 	while(list != NULL) {
  1398 		tmp = list;
  1399 		list = list->next;
  1400 		PR_Free(tmp);
  1402 	PR_Free(_this);
  1405 /****************************************************************************/
  1406 Pk11Install_Value*
  1407 Pk11Install_Value_new_default()
  1409 	Pk11Install_Value* new_this;
  1410 	new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value));
  1411 	new_this->type = STRING_VALUE;
  1412 	new_this->string = NULL;
  1413 	new_this->pair = NULL;
  1414 	new_this->next = NULL;
  1415 	return new_this;
  1418 /****************************************************************************/
  1419 Pk11Install_Value*
  1420 Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr)
  1422 	Pk11Install_Value* new_this;
  1423 	new_this = Pk11Install_Value_new_default();
  1424 	new_this->type = _type;
  1425 	if(_type == STRING_VALUE) {
  1426 		new_this->pair = NULL;
  1427 		new_this->string = ptr.string;
  1428 	} else {
  1429 		new_this->string = NULL;
  1430 		new_this->pair = ptr.pair;
  1432 	return new_this;
  1435 /****************************************************************************/
  1436 void
  1437 Pk11Install_Value_delete(Pk11Install_Value* _this)
  1439 	if(_this->type == STRING_VALUE) {
  1440 		PR_Free(_this->string);
  1441 	} else {
  1442 		PR_Free(_this->pair);
  1446 /****************************************************************************/
  1447 Pk11Install_Pair*
  1448 Pk11Install_Pair_new_default()
  1450 	return Pk11Install_Pair_new(NULL,NULL);
  1453 /****************************************************************************/
  1454 Pk11Install_Pair*
  1455 Pk11Install_Pair_new(char *_key, Pk11Install_ValueList *_list)
  1457 	Pk11Install_Pair* new_this;
  1458 	new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair));
  1459 	new_this->key = _key;
  1460 	new_this->list = _list;
  1461 	return new_this;
  1464 /****************************************************************************/
  1465 void
  1466 Pk11Install_Pair_delete(Pk11Install_Pair* _this)
  1468 	PR_Free(_this->key);
  1469 	Pk11Install_ValueList_delete(_this->list);
  1470 	PR_Free(_this->list);
  1473 /*************************************************************************/
  1474 void
  1475 Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad)
  1477 	while (_this) {
  1478 		/*PAD(pad); printf("**Pair\n");
  1479 		PAD(pad); printf("***Key====\n");*/
  1480 		PAD(pad); printf("%s {\n", _this->key);
  1481 		/*PAD(pad); printf("====\n");*/
  1482 		/*PAD(pad); printf("***ValueList\n");*/
  1483 		Pk11Install_ValueList_Print(_this->list,pad+PADINC);
  1484 		PAD(pad); printf("}\n");
  1488 /*************************************************************************/
  1489 void
  1490 Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad)
  1492 	Pk11Install_Value *v;
  1494 	/*PAD(pad);printf("**Value List**\n");*/
  1495 	for(v = _this->head; v != NULL; v=v->next) {
  1496 		Pk11Install_Value_Print(v,pad);
  1500 /*************************************************************************/
  1501 void
  1502 Pk11Install_Value_Print(Pk11Install_Value* _this, int pad)
  1504 	/*PAD(pad); printf("**Value, type=%s\n",
  1505 		type==STRING_VALUE ? "string" : "pair");*/
  1506 	if(_this->type==STRING_VALUE) {
  1507 		/*PAD(pad+PADINC); printf("====\n");*/
  1508 		PAD(pad); printf("%s\n", _this->string);
  1509 		/*PAD(pad+PADINC); printf("====\n");*/
  1510 	} else {
  1511 		Pk11Install_Pair_Print(_this->pair,pad+PADINC);

mercurial