Back to index

lightning-sunbird  0.9+nobinonly
install-ds.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "install-ds.h"
00038 #include <prmem.h>
00039 #include <plstr.h>
00040 #include <prprf.h>
00041 #include <string.h>
00042 
00043 #define PORT_Strcasecmp PL_strcasecmp
00044 
00045 #define MODULE_FILE_STRING "ModuleFile"
00046 #define MODULE_NAME_STRING "ModuleName"
00047 #define MECH_FLAGS_STRING "DefaultMechanismFlags"
00048 #define CIPHER_FLAGS_STRING "DefaultCipherFlags"
00049 #define FILES_STRING "Files"
00050 #define FORWARD_COMPATIBLE_STRING "ForwardCompatible"
00051 #define PLATFORMS_STRING "Platforms"
00052 #define RELATIVE_DIR_STRING "RelativePath"
00053 #define ABSOLUTE_DIR_STRING "AbsolutePath"
00054 #define FILE_PERMISSIONS_STRING "FilePermissions"
00055 #define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform"
00056 #define EXECUTABLE_STRING "Executable"
00057 
00058 #define DEFAULT_PERMISSIONS 0777
00059 
00060 #define PLATFORM_SEPARATOR_CHAR ':'
00061 
00062 /* Error codes */
00063 enum {
00064        BOGUS_RELATIVE_DIR=0,
00065        BOGUS_ABSOLUTE_DIR,
00066        BOGUS_FILE_PERMISSIONS,
00067        NO_RELATIVE_DIR,
00068        NO_ABSOLUTE_DIR,
00069        EMPTY_PLATFORM_STRING,
00070        BOGUS_PLATFORM_STRING,
00071        REPEAT_MODULE_FILE,
00072        REPEAT_MODULE_NAME,
00073        BOGUS_MODULE_FILE,
00074        BOGUS_MODULE_NAME,
00075        REPEAT_MECH,
00076        BOGUS_MECH_FLAGS,
00077        REPEAT_CIPHER,
00078        BOGUS_CIPHER_FLAGS,
00079        REPEAT_FILES,
00080        REPEAT_EQUIV,
00081        BOGUS_EQUIV,
00082        EQUIV_TOO_MUCH_INFO,
00083        NO_FILES,
00084        NO_MODULE_FILE,
00085        NO_MODULE_NAME,
00086        NO_PLATFORMS,
00087        EQUIV_LOOP,
00088        UNKNOWN_MODULE_FILE
00089 };
00090 
00091 /* Indexed by the above error codes */
00092 static const char *errString[] = {
00093        "%s: Invalid relative directory",
00094        "%s: Invalid absolute directory",
00095        "%s: Invalid file permissions",
00096        "%s: No relative directory specified",
00097        "%s: No absolute directory specified",
00098        "Empty string given for platform name",
00099        "%s: invalid platform string",
00100        "More than one ModuleFile entry given for platform %s",
00101        "More than one ModuleName entry given for platform %s",
00102        "Invalid ModuleFile specification for platform %s",
00103        "Invalid ModuleName specification for platform %s",
00104        "More than one DefaultMechanismFlags entry given for platform %s",
00105        "Invalid DefaultMechanismFlags specification for platform %s",
00106        "More than one DefaultCipherFlags entry given for platform %s",
00107        "Invalid DefaultCipherFlags entry given for platform %s",
00108        "More than one Files entry given for platform %s",
00109        "More than one EquivalentPlatform entry given for platform %s",
00110        "Invalid EquivalentPlatform specification for platform %s",
00111        "Module %s uses an EquivalentPlatform but also specifies its own"
00112               " information",
00113        "No Files specification in module %s",
00114        "No ModuleFile specification in module %s",
00115        "No ModuleName specification in module %s",
00116        "No Platforms specification in installer script",
00117        "Platform %s has an equivalency loop",
00118        "Module file \"%s\" in platform \"%s\" does not exist"
00119 };
00120 
00121 static char* PR_Strdup(const char* str);
00122 
00123 #define PAD(x)  {int i; for(i=0;i<x;i++) printf(" ");}
00124 #define PADINC 4
00125 
00126 Pk11Install_File*
00127 Pk11Install_File_new()
00128 {
00129        Pk11Install_File* new_this;
00130        new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File));
00131        Pk11Install_File_init(new_this);
00132        return new_this;
00133 }
00134 
00135 void
00136 Pk11Install_File_init(Pk11Install_File* _this)
00137 {
00138        _this->jarPath=NULL;
00139        _this->relativePath=NULL;
00140        _this->absolutePath=NULL;
00141        _this->executable=PR_FALSE;
00142        _this->permissions=0;
00143 }
00144 
00145 /*
00147 // Method:    ~Pk11Install_File
00148 // Class:     Pk11Install_File
00149 // Notes:     Destructor.
00150 */
00151 void
00152 Pk11Install_File_delete(Pk11Install_File* _this)
00153 {
00154        Pk11Install_File_Cleanup(_this);
00155 }
00156 
00157 /*
00159 // Method:    Cleanup
00160 // Class:     Pk11Install_File
00161 */
00162 void
00163 Pk11Install_File_Cleanup(Pk11Install_File* _this)
00164 {
00165        if(_this->jarPath) {
00166               PR_Free(_this->jarPath);
00167               _this->jarPath = NULL;
00168        }
00169        if(_this->relativePath) {
00170               PR_Free(_this->relativePath);
00171               _this->relativePath = NULL;
00172        }
00173        if(_this->absolutePath) {
00174               PR_Free(_this->absolutePath);
00175               _this->absolutePath = NULL;
00176        }
00177 
00178        _this->permissions = 0;
00179        _this->executable = PR_FALSE;
00180 }
00181 
00182 /*
00184 // Method:    Generate
00185 // Class:     Pk11Install_File
00186 // Notes:     Creates a file data structure from a syntax tree.
00187 // Returns:   NULL for success, otherwise an error message.
00188 */
00189 char*
00190 Pk11Install_File_Generate(Pk11Install_File* _this,
00191                           const Pk11Install_Pair *pair)
00192 {
00193        Pk11Install_ListIter *iter;
00194        Pk11Install_Value *val;
00195        Pk11Install_Pair *subpair;
00196        Pk11Install_ListIter *subiter;
00197        Pk11Install_Value *subval;
00198        char* errStr;
00199        char *endp;
00200        PRBool gotPerms;
00201 
00202        iter=NULL;
00203        subiter=NULL;
00204        errStr=NULL;
00205        gotPerms=PR_FALSE;
00206 
00207        /* Clear out old values */
00208        Pk11Install_File_Cleanup(_this);
00209 
00210        _this->jarPath = PR_Strdup(pair->key);
00211 
00212        /* Go through all the pairs under this file heading */
00213        iter = Pk11Install_ListIter_new(pair->list);
00214        for( ; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
00215               if(val->type == PAIR_VALUE) {
00216                      subpair = val->pair;
00217 
00218                      /* Relative directory */
00219                      if(!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) {
00220                             subiter = Pk11Install_ListIter_new(subpair->list);
00221                             subval = subiter->current;
00222                             if(!subval || (subval->type != STRING_VALUE)){
00223                                    errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR], 
00224                                     _this->jarPath);
00225                                    goto loser;
00226                             }
00227                             _this->relativePath = PR_Strdup(subval->string);
00228                             Pk11Install_ListIter_delete(subiter);
00229                             subiter = NULL;
00230 
00231                             /* Absolute directory */
00232                      } else if( !PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) {
00233                             subiter = Pk11Install_ListIter_new(subpair->list);
00234                             subval = subiter->current;
00235                             if(!subval || (subval->type != STRING_VALUE)){
00236                                    errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR], 
00237                                     _this->jarPath);
00238                                    goto loser;
00239                             }
00240                             _this->absolutePath = PR_Strdup(subval->string);
00241                             Pk11Install_ListIter_delete(subiter);
00242                             subiter = NULL;
00243 
00244                      /* file permissions */
00245                      } else if( !PORT_Strcasecmp(subpair->key,
00246                                      FILE_PERMISSIONS_STRING)) {
00247                             subiter = Pk11Install_ListIter_new(subpair->list);
00248                             subval = subiter->current;
00249                             if(!subval || (subval->type != STRING_VALUE)){
00250                                    errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
00251                                     _this->jarPath);
00252                                    goto loser;
00253                             }
00254                             _this->permissions = (int) strtol(subval->string, &endp, 8);
00255                             if(*endp != '\0' || subval->string == "\0") {
00256                                    errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
00257                                     _this->jarPath);
00258                                    goto loser;
00259                             }
00260                             gotPerms = PR_TRUE;
00261                             Pk11Install_ListIter_delete(subiter);
00262                             subiter = NULL;
00263                      }
00264               } else {
00265                      if(!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) {
00266                             _this->executable = PR_TRUE;
00267                      }
00268               }
00269        }
00270 
00271        /* Default permission value */
00272        if(!gotPerms) {
00273               _this->permissions = DEFAULT_PERMISSIONS;
00274        }
00275 
00276        /* Make sure we got all the information */
00277        if(!_this->relativePath && !_this->absolutePath) {
00278               errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
00279               goto loser;
00280        }
00281 #if 0
00282        if(!_this->relativePath ) {
00283               errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath);
00284               goto loser;
00285        }
00286        if(!_this->absolutePath) {
00287               errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
00288               goto loser;
00289        }
00290 #endif
00291 
00292 loser:
00293        if(iter) {
00294               Pk11Install_ListIter_delete(iter);
00295               PR_Free(iter);
00296        }
00297        if(subiter) {
00298               Pk11Install_ListIter_delete(subiter);
00299               PR_Free(subiter);
00300        }
00301        return errStr;
00302 }
00303 
00304 /*
00306 // Method:    Print
00307 // Class:     Pk11Install_File
00308 */
00309 void
00310 Pk11Install_File_Print(Pk11Install_File* _this, int pad)
00311 {
00312        PAD(pad); printf("jarPath: %s\n", 
00313                     _this->jarPath ? _this->jarPath : "<NULL>");
00314        PAD(pad); printf("relativePath: %s\n",
00315                             _this->relativePath ? _this->relativePath: "<NULL>");
00316        PAD(pad); printf("absolutePath: %s\n",
00317                             _this->absolutePath ? _this->absolutePath: "<NULL>");
00318        PAD(pad); printf("permissions: %o\n", _this->permissions);
00319 }
00320 
00321 Pk11Install_PlatformName*
00322 Pk11Install_PlatformName_new()
00323 {
00324        Pk11Install_PlatformName* new_this;
00325        new_this = (Pk11Install_PlatformName*)
00326                PR_Malloc(sizeof(Pk11Install_PlatformName));
00327        Pk11Install_PlatformName_init(new_this);
00328        return new_this;
00329 }
00330 
00331 void
00332 Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this)
00333 {
00334        _this->OS = NULL;
00335        _this->verString = NULL;
00336        _this->numDigits = 0;
00337        _this->arch = NULL;
00338 }
00339 
00340 /*
00342 // Method:    ~Pk11Install_PlatformName
00343 // Class:     Pk11Install_PlatformName
00344 */
00345 void
00346 Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this)
00347 {
00348        Pk11Install_PlatformName_Cleanup(_this);
00349 }
00350 
00351 /*
00353 // Method:    Cleanup
00354 // Class:     Pk11Install_PlatformName
00355 */
00356 void
00357 Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this)
00358 {
00359        if(_this->OS) {
00360               PR_Free(_this->OS);
00361               _this->OS = NULL;
00362        }
00363        if(_this->verString) {
00364               int i;
00365               for (i=0; i<_this->numDigits; i++) {
00366                      PR_Free(_this->verString[i]);
00367               }
00368               PR_Free(_this->verString);
00369               _this->verString = NULL;
00370        }
00371        if(_this->arch) {
00372               PR_Free(_this->arch);
00373               _this->arch = NULL;
00374        }
00375        _this->numDigits = 0;
00376 }
00377 
00378 /*
00380 // Method:    Generate
00381 // Class:     Pk11Install_PlatformName
00382 // Notes:     Extracts the information from a platform string.
00383 */
00384 char*
00385 Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
00386                                   const char *str)
00387 {
00388        char *errStr;
00389        char *copy;
00390        char *end, *start; /* start and end of a section (OS, version, arch)*/
00391        char *pend, *pstart; /* start and end of one portion of version*/
00392        char *endp; /* used by strtol*/
00393        int periods, i;
00394 
00395        errStr=NULL;
00396        copy=NULL;
00397 
00398        if(!str) {
00399               errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]);
00400               goto loser;
00401        }
00402        copy = PR_Strdup(str);
00403 
00404        /*
00405        // Get the OS
00406        */
00407        end = strchr(copy, PLATFORM_SEPARATOR_CHAR);
00408        if(!end || end==copy) {
00409               errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
00410               goto loser;
00411        }
00412        *end = '\0';
00413 
00414        _this->OS = PR_Strdup(copy);
00415 
00416        /*
00417        // Get the digits of the version of form: x.x.x (arbitrary number of digits)
00418        */
00419 
00420        start = end+1;
00421        end = strchr(start, PLATFORM_SEPARATOR_CHAR);
00422        if(!end) {
00423               errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
00424               goto loser;
00425        }
00426        *end = '\0';
00427 
00428        if(end!=start) { 
00429               /* Find out how many periods*/
00430               periods = 0;
00431               pstart = start;
00432               while( (pend=strchr(pstart, '.')) ) {
00433                      periods++;
00434                      pstart = pend+1;
00435               }
00436               _this->numDigits= 1+ periods;
00437               _this->verString = (char**)PR_Malloc(sizeof(char*)*_this->numDigits);
00438 
00439               pstart = start;
00440               i = 0;
00441               /* Get the digits before each period*/
00442               while( (pend=strchr(pstart, '.')) ) {
00443                      if(pend == pstart) {
00444                             errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
00445                             goto loser;
00446                      }
00447                      *pend = '\0';
00448                      _this->verString[i] = PR_Strdup(pstart);
00449                      endp = pend;
00450               if(endp==pstart || (*endp != '\0')) {
00451                             errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
00452                             goto loser;
00453                      }
00454                      pstart = pend+1;
00455                      i++;
00456               }
00457               /* Last digit comes after the last period*/
00458               if(*pstart == '\0') {
00459                      errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
00460                      goto loser;
00461               }
00462               _this->verString[i] = PR_Strdup(pstart);
00463               /*
00464               if(endp==pstart || (*endp != '\0')) {
00465                      errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
00466                      goto loser;
00467               }
00468               */
00469        } else {
00470               _this->verString = NULL;
00471               _this->numDigits = 0;
00472        }
00473 
00474        /*
00475        // Get the architecture
00476        */
00477        start = end+1;
00478        if( strchr(start, PLATFORM_SEPARATOR_CHAR) ) {
00479               errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
00480               goto loser;
00481        }
00482        _this->arch = PR_Strdup(start);
00483 
00484        if(copy) {
00485               PR_Free(copy);
00486        }
00487        return NULL;
00488 loser:
00489        if(_this->OS) {
00490               PR_Free(_this->OS);
00491               _this->OS = NULL;
00492        }
00493        if(_this->verString) {
00494               for (i=0; i<_this->numDigits; i++) {
00495                      PR_Free(_this->verString[i]);
00496               }
00497               PR_Free(_this->verString);
00498               _this->verString = NULL;
00499        }
00500        _this->numDigits = 0;
00501        if(_this->arch) {
00502               PR_Free(_this->arch);
00503               _this->arch = NULL;
00504        }
00505 
00506        return errStr;
00507 }
00508 
00509 /*
00511 // Method:    operator ==
00512 // Class:     Pk11Install_PlatformName
00513 // Returns:   PR_TRUE if the platform have the same OS, arch, and version
00514 */
00515 PRBool
00516 Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
00517                                Pk11Install_PlatformName* cmp) 
00518 {
00519        int i;
00520 
00521        if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
00522               return PR_FALSE;
00523        }
00524 
00525        if(    PORT_Strcasecmp(_this->OS, cmp->OS) ||
00526               PORT_Strcasecmp(_this->arch, cmp->arch) ||
00527               _this->numDigits != cmp->numDigits ) {
00528                      return PR_FALSE;
00529        }
00530 
00531        for(i=0; i < _this->numDigits; i++) {
00532               if(PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) {
00533                      return PR_FALSE;
00534               }
00535        }
00536        return PR_TRUE;
00537 }
00538 
00539 /*
00541 // Method:    operator <=
00542 // Class:     Pk11Install_PlatformName
00543 // Returns:   PR_TRUE if the platform have the same OS and arch and a lower
00544 //                   or equal release.
00545 */
00546 PRBool
00547 Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
00548                               Pk11Install_PlatformName* cmp)
00549 {
00550        return (Pk11Install_PlatformName_equal(_this,cmp) ||
00551           Pk11Install_PlatformName_lt(_this,cmp)) ? PR_TRUE : PR_FALSE;
00552 }
00553 
00554 /*
00556 // Method:    operator <
00557 // Class:     Pk11Install_PlatformName
00558 // Returns:   PR_TRUE if the platform have the same OS and arch and a greater
00559 //                   release.
00560 */
00561 PRBool
00562 Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
00563                             Pk11Install_PlatformName* cmp)
00564 {
00565        int i, scmp;
00566 
00567        if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
00568               return PR_FALSE;
00569        }
00570 
00571        if( PORT_Strcasecmp(_this->OS, cmp->OS) ) {
00572               return PR_FALSE;
00573        }
00574        if( PORT_Strcasecmp(_this->arch, cmp->arch) ) {
00575               return PR_FALSE;
00576        }
00577 
00578        for(i=0; (i < _this->numDigits) && (i < cmp->numDigits); i++) {
00579               scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]);
00580               if (scmp > 0) {
00581                      return PR_FALSE;
00582               } else if (scmp < 0) {
00583                      return PR_TRUE;
00584               }
00585        }
00586        /* All the digits they have in common are the same. */
00587        if(_this->numDigits < cmp->numDigits) {
00588               return  PR_TRUE;
00589        } 
00590 
00591        return PR_FALSE;
00592 }
00593 
00594 /*
00596 // Method:    GetString
00597 // Class:     Pk11Install_PlatformName
00598 // Returns:   String composed of OS, release, and architecture separated
00599 //                   by the separator char.  Memory is allocated by this function
00600 //                   but is the responsibility of the caller to de-allocate.
00601 */
00602 char*
00603 Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this) 
00604 {
00605        char *ret;
00606        char *ver;
00607        char *OS_;
00608        char *arch_;
00609 
00610        OS_=NULL;
00611        arch_=NULL;
00612 
00613        OS_ = _this->OS ? _this->OS : "";
00614        arch_ = _this->arch ? _this->arch : "";
00615 
00616        ver = Pk11Install_PlatformName_GetVerString(_this);
00617        ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver,
00618                                    PLATFORM_SEPARATOR_CHAR, arch_);
00619 
00620        PR_Free(ver);
00621 
00622        return ret;
00623 }
00624 
00625 /*
00627 // Method:    GetVerString
00628 // Class:     Pk11Install_PlatformName
00629 // Returns:   The version string for this platform, in the form x.x.x with an
00630 //                   arbitrary number of digits.  Memory allocated by function,
00631 //                   must be de-allocated by caller.
00632 */
00633 char*
00634 Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this) 
00635 {
00636        char *tmp;
00637        char *ret;
00638        int i;
00639        char buf[80];
00640 
00641        tmp = (char*)PR_Malloc(80*_this->numDigits+1);
00642        tmp[0] = '\0';
00643 
00644        for(i=0; i < _this->numDigits-1; i++) {
00645               sprintf(buf, "%s.", _this->verString[i]);
00646               strcat(tmp, buf);
00647        }
00648        if(i < _this->numDigits) {
00649               sprintf(buf, "%s", _this->verString[i]);
00650               strcat(tmp, buf);
00651        }
00652 
00653        ret = PR_Strdup(tmp);
00654        free(tmp);
00655 
00656        return ret;
00657 }
00658 
00659 /*
00661 // Method:    Print
00662 // Class:     Pk11Install_PlatformName
00663 */
00664 void
00665 Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad)
00666 {
00667        PAD(pad); printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>");
00668        PAD(pad); printf("Digits: ");
00669        if(_this->numDigits == 0) {
00670               printf("None\n");
00671        } else {
00672               printf("%s\n", Pk11Install_PlatformName_GetVerString(_this));
00673        }
00674        PAD(pad); printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>");
00675 }
00676 
00677 Pk11Install_Platform*
00678 Pk11Install_Platform_new()
00679 {
00680        Pk11Install_Platform* new_this;
00681        new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform));
00682        Pk11Install_Platform_init(new_this);
00683        return new_this;
00684 }
00685 
00686 void
00687 Pk11Install_Platform_init(Pk11Install_Platform* _this)
00688 {
00689        Pk11Install_PlatformName_init(&_this->name);
00690        Pk11Install_PlatformName_init(&_this->equivName);
00691        _this->equiv = NULL;
00692        _this->usesEquiv = PR_FALSE;
00693        _this->moduleFile = NULL;
00694        _this->moduleName = NULL;
00695        _this->modFile = -1;
00696        _this->mechFlags = 0;
00697        _this->cipherFlags = 0;
00698        _this->files = NULL;
00699        _this->numFiles = 0;
00700 }
00701 
00702 /*
00704 // Method:    ~Pk11Install_Platform
00705 // Class:     Pk11Install_Platform
00706 */
00707 void
00708 Pk11Install_Platform_delete(Pk11Install_Platform* _this)
00709 {
00710        Pk11Install_Platform_Cleanup(_this);
00711 }
00712 
00713 /*
00715 // Method:    Cleanup
00716 // Class:     Pk11Install_Platform
00717 */
00718 void
00719 Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this)
00720 {
00721        int i;
00722        if(_this->moduleFile) {
00723               PR_Free(_this->moduleFile);
00724               _this->moduleFile = NULL;
00725        }
00726        if(_this->moduleName) {
00727               PR_Free(_this->moduleName);
00728               _this->moduleName = NULL;
00729        }
00730        if(_this->files) {
00731               for (i=0;i<_this->numFiles;i++) {
00732                      Pk11Install_File_delete(&_this->files[i]);
00733               }
00734               PR_Free(_this->files);
00735               _this->files = NULL;
00736        }
00737        _this->equiv = NULL;
00738        _this->usesEquiv = PR_FALSE;
00739        _this->modFile = -1;
00740        _this->numFiles = 0;
00741        _this->mechFlags = _this->cipherFlags = 0;
00742 }
00743 
00744 /*
00746 // Method:    Generate
00747 // Class:     Pk11Install_Platform
00748 // Notes:     Creates a platform data structure from a syntax tree.
00749 // Returns:   NULL for success, otherwise an error message.
00750 */
00751 char*
00752 Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
00753                               const Pk11Install_Pair *pair)
00754 {
00755        char* errStr;
00756        char* endptr;
00757        char* tmp;
00758        int i;
00759        Pk11Install_ListIter *iter;
00760        Pk11Install_Value *val;
00761        Pk11Install_Value *subval;
00762        Pk11Install_Pair *subpair;
00763        Pk11Install_ListIter *subiter;
00764        PRBool gotModuleFile, gotModuleName, gotMech, 
00765           gotCipher, gotFiles, gotEquiv;
00766 
00767        errStr=NULL;
00768        iter=subiter=NULL;
00769        val=subval=NULL;
00770        subpair=NULL;
00771        gotModuleFile=gotModuleName=gotMech=gotCipher=gotFiles=gotEquiv=PR_FALSE;
00772        Pk11Install_Platform_Cleanup(_this);
00773 
00774        errStr = Pk11Install_PlatformName_Generate(&_this->name,pair->key);
00775        if(errStr) {
00776               tmp = PR_smprintf("%s: %s", pair->key, errStr);
00777               PR_smprintf_free(errStr);
00778               errStr = tmp;
00779               goto loser;
00780        }
00781 
00782        iter = Pk11Install_ListIter_new(pair->list);
00783        for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
00784               if(val->type==PAIR_VALUE) {
00785                      subpair = val->pair;
00786 
00787                      if( !PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) {
00788                             if(gotModuleFile) {
00789                                    errStr = PR_smprintf(errString[REPEAT_MODULE_FILE],
00790                                     Pk11Install_PlatformName_GetString(&_this->name));
00791                                    goto loser;
00792                             }
00793                             subiter = Pk11Install_ListIter_new(subpair->list);
00794                             subval = subiter->current;
00795                             if(!subval || (subval->type != STRING_VALUE)) {
00796                                    errStr = PR_smprintf(errString[BOGUS_MODULE_FILE],
00797                                     Pk11Install_PlatformName_GetString(&_this->name));
00798                                    goto loser;
00799                             }
00800                             _this->moduleFile = PR_Strdup(subval->string);
00801                             Pk11Install_ListIter_delete(subiter);
00802                             PR_Free(subiter);
00803                             subiter = NULL;
00804                             gotModuleFile = PR_TRUE;
00805                      } else if(!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)){
00806                             if(gotModuleName) {
00807                                    errStr = PR_smprintf(errString[REPEAT_MODULE_NAME],
00808                                     Pk11Install_PlatformName_GetString(&_this->name));
00809                                    goto loser;
00810                             }
00811                             subiter = Pk11Install_ListIter_new(subpair->list);
00812                             subval = subiter->current;
00813                             if(!subval || (subval->type != STRING_VALUE)) {
00814                                    errStr = PR_smprintf(errString[BOGUS_MODULE_NAME],
00815                                     Pk11Install_PlatformName_GetString(&_this->name));
00816                                    goto loser;
00817                             }
00818                             _this->moduleName = PR_Strdup(subval->string);
00819                             Pk11Install_ListIter_delete(subiter);
00820                             PR_Free(subiter);
00821                             subiter = NULL;
00822                             gotModuleName = PR_TRUE;
00823                      } else if(!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) {
00824                             endptr=NULL;
00825 
00826                             if(gotMech) {
00827                                    errStr = PR_smprintf(errString[REPEAT_MECH],
00828                                     Pk11Install_PlatformName_GetString(&_this->name));
00829                                    goto loser;
00830                             }
00831                             subiter = Pk11Install_ListIter_new(subpair->list);
00832                             subval = subiter->current;
00833                             if(!subval || (subval->type != STRING_VALUE)) {
00834                                    errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
00835                                     Pk11Install_PlatformName_GetString(&_this->name));
00836                                    goto loser;
00837                             }
00838                             _this->mechFlags = strtol(subval->string, &endptr, 0);
00839                             if(*endptr!='\0' || (endptr==subval->string) ) {
00840                                    errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
00841                                     Pk11Install_PlatformName_GetString(&_this->name));
00842                                    goto loser;
00843                             }
00844                             Pk11Install_ListIter_delete(subiter);
00845                             PR_Free(subiter);
00846                             subiter=NULL;
00847                             gotMech = PR_TRUE;
00848                      } else if(!PORT_Strcasecmp(subpair->key,CIPHER_FLAGS_STRING)) {
00849                             endptr=NULL;
00850 
00851                             if(gotCipher) {
00852                                    errStr = PR_smprintf(errString[REPEAT_CIPHER],
00853                                     Pk11Install_PlatformName_GetString(&_this->name));
00854                                    goto loser;
00855                             }
00856                             subiter = Pk11Install_ListIter_new(subpair->list);
00857                             subval = subiter->current;
00858                             if(!subval || (subval->type != STRING_VALUE)) {
00859                                    errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
00860                                     Pk11Install_PlatformName_GetString(&_this->name));
00861                                    goto loser;
00862                             }
00863                             _this->cipherFlags = strtol(subval->string, &endptr, 0);
00864                             if(*endptr!='\0' || (endptr==subval->string) ) {
00865                                    errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
00866                                     Pk11Install_PlatformName_GetString(&_this->name));
00867                                    goto loser;
00868                             }
00869                             Pk11Install_ListIter_delete(subiter);
00870                             PR_Free(subiter);
00871                             subiter=NULL;
00872                             gotCipher = PR_TRUE;
00873                      } else if(!PORT_Strcasecmp(subpair->key, FILES_STRING)) {
00874                             if(gotFiles) {
00875                                    errStr = PR_smprintf(errString[REPEAT_FILES],
00876                                     Pk11Install_PlatformName_GetString(&_this->name));
00877                                    goto loser;
00878                             }
00879                             subiter = Pk11Install_ListIter_new(subpair->list);
00880                             _this->numFiles = subpair->list->numPairs;
00881                             _this->files = (Pk11Install_File*)
00882                             PR_Malloc(sizeof(Pk11Install_File)*_this->numFiles);
00883                             for(i=0; i < _this->numFiles; i++, 
00884                                    Pk11Install_ListIter_nextItem(subiter)) {
00885                                    Pk11Install_File_init(&_this->files[i]);
00886                                    val = subiter->current;
00887                                    if(val && (val->type==PAIR_VALUE)) {
00888                                           errStr = Pk11Install_File_Generate(&_this->files[i],val->pair);
00889                                           if(errStr) {
00890                                                  tmp = PR_smprintf("%s: %s", 
00891                                        Pk11Install_PlatformName_GetString(&_this->name),errStr);
00892                                                  PR_smprintf_free(errStr);
00893                                                  errStr = tmp;
00894                                                  goto loser;
00895                                           }
00896                                    }
00897                             }
00898                             gotFiles = PR_TRUE;
00899                      } else if(!PORT_Strcasecmp(subpair->key,
00900                                     EQUIVALENT_PLATFORM_STRING)) {
00901                             if(gotEquiv) {
00902                                    errStr = PR_smprintf(errString[REPEAT_EQUIV],
00903                                     Pk11Install_PlatformName_GetString(&_this->name));
00904                                    goto loser;
00905                             }
00906                             subiter = Pk11Install_ListIter_new(subpair->list);
00907                             subval = subiter->current;
00908                             if(!subval || (subval->type != STRING_VALUE) ) {
00909                                    errStr = PR_smprintf(errString[BOGUS_EQUIV],
00910                                Pk11Install_PlatformName_GetString(&_this->name));
00911                                    goto loser;
00912                             }
00913                             errStr = Pk11Install_PlatformName_Generate(&_this->equivName,
00914                                                        subval->string);
00915                             if(errStr) {
00916                                    tmp = PR_smprintf("%s: %s", 
00917                             Pk11Install_PlatformName_GetString(&_this->name), errStr);
00918                                    tmp = PR_smprintf("%s: %s", 
00919                             Pk11Install_PlatformName_GetString(&_this->name), errStr);
00920                                    PR_smprintf_free(errStr);
00921                                    errStr = tmp;
00922                                    goto loser;
00923                             }
00924                             _this->usesEquiv = PR_TRUE;
00925                      }
00926               }
00927        }
00928 
00929        /* Make sure we either have an EquivalentPlatform or all the other info */
00930        if(_this->usesEquiv &&
00931               (gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) {
00932               errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO], 
00933                            Pk11Install_PlatformName_GetString(&_this->name));
00934               goto loser;
00935        }
00936        if(!gotFiles && !_this->usesEquiv) {
00937               errStr = PR_smprintf(errString[NO_FILES], 
00938                            Pk11Install_PlatformName_GetString(&_this->name));
00939               goto loser;
00940        }
00941        if(!gotModuleFile && !_this->usesEquiv) {
00942               errStr= PR_smprintf(errString[NO_MODULE_FILE], 
00943                           Pk11Install_PlatformName_GetString(&_this->name));
00944               goto loser;
00945        }
00946        if(!gotModuleName && !_this->usesEquiv) {
00947               errStr = PR_smprintf(errString[NO_MODULE_NAME], 
00948                           Pk11Install_PlatformName_GetString(&_this->name));
00949               goto loser;
00950        }
00951 
00952        /* Point the modFile pointer to the correct file */
00953        if(gotModuleFile) {
00954               for(i=0; i < _this->numFiles; i++) {
00955                      if(!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath) ) {
00956                             _this->modFile = i;
00957                             break;
00958                      }
00959               }
00960               if(_this->modFile==-1) {
00961                      errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE], 
00962                               _this->moduleFile,
00963                               Pk11Install_PlatformName_GetString(&_this->name));
00964                      goto loser;
00965               }
00966        }
00967        
00968 loser:
00969        if(iter) {
00970               PR_Free(iter);
00971        }
00972        if(subiter) {
00973               PR_Free(subiter);
00974        }
00975        return errStr;
00976 }
00977 
00978 /*
00980 // Method:           Print
00981 // Class:            Pk11Install_Platform
00982 */
00983 void
00984 Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
00985 {
00986        int i;
00987 
00988        PAD(pad); printf("Name:\n"); 
00989        Pk11Install_PlatformName_Print(&_this->name,pad+PADINC);
00990        PAD(pad); printf("equivName:\n"); 
00991        Pk11Install_PlatformName_Print(&_this->equivName,pad+PADINC);
00992        PAD(pad);
00993        if(_this->usesEquiv) {
00994               printf("Uses equiv, which points to:\n");
00995               Pk11Install_Platform_Print(_this->equiv,pad+PADINC);
00996        } else {
00997               printf("Doesn't use equiv\n");
00998        }
00999        PAD(pad); 
01000        printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile 
01001                                                  : "<NULL>");
01002        PAD(pad); printf("mechFlags: %lx\n", _this->mechFlags);
01003        PAD(pad); printf("cipherFlags: %lx\n", _this->cipherFlags);
01004        PAD(pad); printf("Files:\n");
01005        for(i=0; i < _this->numFiles; i++) {
01006               Pk11Install_File_Print(&_this->files[i],pad+PADINC);
01007               PAD(pad); printf("--------------------\n");
01008        }
01009 }
01010 
01011 /*
01013 // Method:           Pk11Install_Info
01014 // Class:            Pk11Install_Info
01015 */
01016 Pk11Install_Info*
01017 Pk11Install_Info_new()
01018 {
01019        Pk11Install_Info* new_this;
01020        new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info));
01021        Pk11Install_Info_init(new_this);
01022        return new_this;
01023 }
01024 
01025 void
01026 Pk11Install_Info_init(Pk11Install_Info* _this)
01027 {
01028        _this->platforms = NULL;
01029        _this->numPlatforms = 0;
01030        _this->forwardCompatible = NULL;
01031        _this->numForwardCompatible = 0;
01032 }
01033 
01034 /*
01036 // Method:           ~Pk11Install_Info
01037 // Class:            Pk11Install_Info
01038 */
01039 void
01040 Pk11Install_Info_delete(Pk11Install_Info* _this)
01041 {
01042        Pk11Install_Info_Cleanup(_this);
01043 }
01044 
01045 /*
01047 // Method:           Cleanup
01048 // Class:            Pk11Install_Info
01049 */
01050 void
01051 Pk11Install_Info_Cleanup(Pk11Install_Info* _this)
01052 {
01053        int i;
01054        if(_this->platforms) {
01055               for (i=0;i<_this->numPlatforms;i++) {
01056                      Pk11Install_Platform_delete(&_this->platforms[i]);
01057               }
01058               PR_Free(&_this->platforms);
01059               _this->platforms = NULL;
01060               _this->numPlatforms = 0;
01061        }
01062 
01063        if(_this->forwardCompatible) {
01064               for (i=0;i<_this->numForwardCompatible;i++) {
01065                      Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]);
01066               }
01067               PR_Free(&_this->forwardCompatible);
01068               _this->numForwardCompatible = 0;
01069        }
01070 }
01071 
01072 /*
01074 // Method:           Generate
01075 // Class:            Pk11Install_Info
01076 // Takes:            Pk11Install_ValueList *list, the top-level list
01077 //                          resulting from parsing an installer file.
01078 // Returns:          char*, NULL if successful, otherwise an error string.
01079 //                          Caller is responsible for freeing memory.
01080 */
01081 char*
01082 Pk11Install_Info_Generate(Pk11Install_Info* _this,
01083                           const Pk11Install_ValueList *list)
01084 {
01085        char *errStr;
01086        Pk11Install_ListIter *iter;
01087        Pk11Install_Value *val;
01088        Pk11Install_Pair *pair;
01089        Pk11Install_ListIter *subiter;
01090        Pk11Install_Value *subval;
01091        Pk11Install_Platform *first, *second;
01092        int i, j;
01093 
01094        errStr=NULL;
01095        iter=subiter=NULL;
01096        Pk11Install_Info_Cleanup(_this);
01097 
01098        iter = Pk11Install_ListIter_new(list);
01099        for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
01100               if(val->type == PAIR_VALUE) {
01101                      pair = val->pair;
01102 
01103                      if(!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) {
01104                             subiter = Pk11Install_ListIter_new(pair->list);
01105                             _this->numForwardCompatible = pair->list->numStrings;
01106                             _this->forwardCompatible = (Pk11Install_PlatformName*)
01107                                         PR_Malloc(sizeof(Pk11Install_PlatformName)*
01108                                                _this->numForwardCompatible);
01109                             for(i=0; i < _this->numForwardCompatible; i++, 
01110                        Pk11Install_ListIter_nextItem(subiter)) {
01111                                    subval = subiter->current;
01112                                    if(subval->type == STRING_VALUE) {
01113                                           errStr = Pk11Install_PlatformName_Generate(
01114                               &_this->forwardCompatible[i], subval->string);
01115                                           if(errStr) {
01116                                                  goto loser;
01117                                           }
01118                                    }
01119                             }
01120                             Pk11Install_ListIter_delete(subiter);
01121                             PR_Free(subiter);
01122                             subiter = NULL;
01123                      } else if(!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) {
01124                             subiter = Pk11Install_ListIter_new(pair->list);
01125                             _this->numPlatforms = pair->list->numPairs;
01126                             _this->platforms = (Pk11Install_Platform*)
01127                             PR_Malloc(sizeof(Pk11Install_Platform)*
01128                             _this->numPlatforms);
01129                             for(i=0; i < _this->numPlatforms; i++, 
01130                        Pk11Install_ListIter_nextItem(subiter)) {
01131                                     Pk11Install_Platform_init(&_this->platforms[i]);
01132                                    subval = subiter->current;
01133                                    if(subval->type == PAIR_VALUE) {
01134                                           errStr = Pk11Install_Platform_Generate(&_this->platforms[i],subval->pair);
01135                                           if(errStr) {
01136                                                  goto loser;
01137                                           }
01138                                    }
01139                             }
01140                             Pk11Install_ListIter_delete(subiter);
01141                             PR_Free(subiter);
01142                             subiter = NULL;
01143                      }
01144               }
01145        }
01146 
01147        if(_this->numPlatforms == 0) {
01148               errStr = PR_smprintf(errString[NO_PLATFORMS]);
01149               goto loser;
01150        }
01151 
01152 /*
01153        //
01154        // Now process equivalent platforms
01155        //
01156 
01157        // First the naive pass
01158 */
01159        for(i=0; i < _this->numPlatforms; i++) {
01160               if(_this->platforms[i].usesEquiv) {
01161                      _this->platforms[i].equiv = NULL;
01162                      for(j=0; j < _this->numPlatforms; j++) {
01163                             if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName,
01164                                            &_this->platforms[j].name)) {
01165                                    if(i==j) {
01166                                           errStr = PR_smprintf(errString[EQUIV_LOOP],
01167                               Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
01168                                           goto loser;
01169                                    }
01170                                    _this->platforms[i].equiv = &_this->platforms[j];
01171                                    break;
01172                             }
01173                      }
01174                      if(_this->platforms[i].equiv == NULL) {
01175                             errStr = PR_smprintf(errString[BOGUS_EQUIV],
01176                        Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
01177                             goto loser;
01178                      }
01179               }
01180        }
01181 
01182 /*
01183        // Now the intelligent pass, which will also detect loops.
01184        // We will send two pointers through the linked list of equivalent
01185        // platforms. Both start with the current node.  "first" traverses
01186        // two nodes for each iteration.  "second" lags behind, only traversing
01187        // one node per iteration.  Eventually one of two things will happen:
01188        // first will hit the end of the list (a platform that doesn't use
01189        // an equivalency), or first will equal second if there is a loop.
01190 */
01191        for(i=0; i < _this->numPlatforms; i++) {
01192               if(_this->platforms[i].usesEquiv) {
01193                      second = _this->platforms[i].equiv;
01194                      if(!second->usesEquiv) {
01195                             /* The first link is the terminal node */
01196                             continue;
01197                      }
01198                      first = second->equiv;
01199                      while(first->usesEquiv) {
01200                             if(first == second) {
01201                                    errStr = PR_smprintf(errString[EQUIV_LOOP],
01202                          Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
01203                                    goto loser;
01204                             }
01205                             first = first->equiv;
01206                             if(!first->usesEquiv) {
01207                                    break;
01208                             }
01209                             if(first == second) {
01210                                    errStr = PR_smprintf(errString[EQUIV_LOOP],
01211                        Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
01212                                    goto loser;
01213                             }
01214                             second = second->equiv;
01215                             first = first->equiv;
01216                      }
01217                      _this->platforms[i].equiv = first;
01218               }
01219        }
01220 
01221 loser:
01222        if(iter) {
01223               Pk11Install_ListIter_delete(iter);
01224               PR_Free(iter);
01225               iter = NULL;
01226        }
01227        if(subiter) {
01228               Pk11Install_ListIter_delete(subiter);
01229               PR_Free(subiter);
01230               subiter = NULL;
01231        }
01232        return errStr;
01233 }
01234 
01235 /*
01237 // Method:           GetBestPlatform
01238 // Class:            Pk11Install_Info
01239 // Takes:            char *myPlatform, the platform we are currently running
01240 //                          on.
01241 */
01242 Pk11Install_Platform*
01243 Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char *myPlatform)
01244 {
01245        Pk11Install_PlatformName plat;
01246        char *errStr;
01247        int i, j;
01248 
01249        errStr=NULL;
01250 
01251        Pk11Install_PlatformName_init(&plat);
01252        if( (errStr=Pk11Install_PlatformName_Generate(&plat, myPlatform)) ) {
01253               PR_smprintf_free(errStr);
01254               return NULL;
01255        }
01256 
01257        /* First try real platforms */
01258        for(i=0; i < _this->numPlatforms; i++) {
01259               if(Pk11Install_PlatformName_equal(&_this->platforms[i].name,&plat)) {
01260                      if(_this->platforms[i].equiv) {
01261                             return _this->platforms[i].equiv;
01262                      }
01263                      else {
01264                             return &_this->platforms[i];
01265                      }
01266               }
01267        }
01268 
01269        /* Now try forward compatible platforms */
01270        for(i=0; i < _this->numForwardCompatible; i++) {
01271               if(Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i],&plat)) {
01272                      break;
01273               }
01274        }
01275        if(i == _this->numForwardCompatible) {
01276               return NULL;
01277        }
01278 
01279        /* Got a forward compatible name, find the actual platform. */
01280        for(j=0; j < _this->numPlatforms; j++) {
01281               if(Pk11Install_PlatformName_equal(&_this->platforms[j].name,
01282          &_this->forwardCompatible[i])) {
01283                      if(_this->platforms[j].equiv) {
01284                             return _this->platforms[j].equiv;
01285                      } else {
01286                             return &_this->platforms[j];
01287                      }
01288               }
01289        }
01290 
01291        return NULL;
01292 }
01293 
01294 /*
01296 // Method:           Print
01297 // Class:            Pk11Install_Info
01298 */
01299 void
01300 Pk11Install_Info_Print(Pk11Install_Info* _this, int pad)
01301 {
01302        int i;
01303 
01304        PAD(pad); printf("Forward Compatible:\n");
01305        for(i = 0; i < _this->numForwardCompatible; i++) {
01306               Pk11Install_PlatformName_Print(&_this->forwardCompatible[i],pad+PADINC);
01307               PAD(pad); printf("-------------------\n");
01308        }
01309        PAD(pad); printf("Platforms:\n");
01310        for( i = 0; i < _this->numPlatforms; i++) {
01311               Pk11Install_Platform_Print(&_this->platforms[i],pad+PADINC);
01312               PAD(pad); printf("-------------------\n");
01313        }
01314 }
01315 
01316 /*
01318 */
01319 static char*
01320 PR_Strdup(const char* str)
01321 {
01322        char *tmp;
01323        tmp = (char*) PR_Malloc((unsigned int)(strlen(str)+1));
01324        strcpy(tmp, str);
01325        return tmp;
01326 }
01327 
01328 /* The global value list, the top of the tree */
01329 Pk11Install_ValueList* Pk11Install_valueList=NULL;
01330 
01331 /****************************************************************************/
01332 void
01333 Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
01334                               Pk11Install_Value *item)
01335 {
01336        _this->numItems++;
01337        if (item->type == STRING_VALUE) {
01338               _this->numStrings++;
01339        } else {
01340               _this->numPairs++;
01341        }
01342        item->next = _this->head;
01343        _this->head = item;
01344 }
01345 
01346 /****************************************************************************/
01347 Pk11Install_ListIter*
01348 Pk11Install_ListIter_new_default()
01349 {
01350        Pk11Install_ListIter* new_this;
01351        new_this = (Pk11Install_ListIter*)
01352                     PR_Malloc(sizeof(Pk11Install_ListIter));
01353        Pk11Install_ListIter_init(new_this);
01354        return new_this;
01355 }
01356 
01357 /****************************************************************************/
01358 void
01359 Pk11Install_ListIter_init(Pk11Install_ListIter* _this)
01360 {
01361        _this->list = NULL;
01362        _this->current = NULL;
01363 }
01364 
01365 /****************************************************************************/
01366 Pk11Install_ListIter*
01367 Pk11Install_ListIter_new(const Pk11Install_ValueList *_list)
01368 {
01369        Pk11Install_ListIter* new_this;
01370        new_this = (Pk11Install_ListIter*)
01371                     PR_Malloc(sizeof(Pk11Install_ListIter));
01372        new_this->list = _list;
01373        new_this->current = _list->head;
01374        return new_this;
01375 }
01376 
01377 /****************************************************************************/
01378 void
01379 Pk11Install_ListIter_delete(Pk11Install_ListIter* _this)
01380 {
01381        _this->list=NULL;
01382        _this->current=NULL;
01383 }
01384 
01385 /****************************************************************************/
01386 void
01387 Pk11Install_ListIter_reset(Pk11Install_ListIter* _this)
01388 {
01389        if(_this->list) {
01390               _this->current = _this->list->head;
01391        }
01392 }
01393 
01394 /*************************************************************************/
01395 Pk11Install_Value*
01396 Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this)
01397 {
01398        if(_this->current) {
01399               _this->current = _this->current->next;
01400        }
01401 
01402        return _this->current;
01403 }
01404 
01405 /****************************************************************************/
01406 Pk11Install_ValueList*
01407 Pk11Install_ValueList_new()
01408 {
01409        Pk11Install_ValueList* new_this;
01410        new_this = (Pk11Install_ValueList*)
01411                     PR_Malloc(sizeof(Pk11Install_ValueList));
01412        new_this->numItems = 0;
01413        new_this->numPairs = 0;
01414        new_this->numStrings = 0;
01415        new_this->head = NULL;
01416        return new_this;
01417 }
01418 
01419 /****************************************************************************/
01420 void
01421 Pk11Install_ValueList_delete(Pk11Install_ValueList* _this)
01422 {
01423 
01424        Pk11Install_Value *tmp;
01425        Pk11Install_Value *list;
01426        list = _this->head;
01427        
01428        while(list != NULL) {
01429               tmp = list;
01430               list = list->next;
01431               PR_Free(tmp);
01432        }
01433        PR_Free(_this);
01434 }
01435 
01436 /****************************************************************************/
01437 Pk11Install_Value*
01438 Pk11Install_Value_new_default()
01439 {
01440        Pk11Install_Value* new_this;
01441        new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value));
01442        new_this->type = STRING_VALUE;
01443        new_this->string = NULL;
01444        new_this->pair = NULL;
01445        new_this->next = NULL;
01446        return new_this;
01447 }
01448 
01449 /****************************************************************************/
01450 Pk11Install_Value*
01451 Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr)
01452 {
01453        Pk11Install_Value* new_this;
01454        new_this = Pk11Install_Value_new_default();
01455        new_this->type = _type;
01456        if(_type == STRING_VALUE) {
01457               new_this->pair = NULL;
01458               new_this->string = ptr.string;
01459        } else {
01460               new_this->string = NULL;
01461               new_this->pair = ptr.pair;
01462        }
01463        return new_this;
01464 }
01465 
01466 /****************************************************************************/
01467 void
01468 Pk11Install_Value_delete(Pk11Install_Value* _this)
01469 {
01470        if(_this->type == STRING_VALUE) {
01471               PR_Free(_this->string);
01472        } else {
01473               PR_Free(_this->pair);
01474        }
01475 }
01476 
01477 /****************************************************************************/
01478 Pk11Install_Pair*
01479 Pk11Install_Pair_new_default()
01480 {
01481        return Pk11Install_Pair_new(NULL,NULL);
01482 }
01483 
01484 /****************************************************************************/
01485 Pk11Install_Pair*
01486 Pk11Install_Pair_new(char *_key, Pk11Install_ValueList *_list)
01487 {
01488        Pk11Install_Pair* new_this;
01489        new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair));
01490        new_this->key = _key;
01491        new_this->list = _list;
01492        return new_this;
01493 }
01494 
01495 /****************************************************************************/
01496 void
01497 Pk11Install_Pair_delete(Pk11Install_Pair* _this)
01498 {
01499        PR_Free(_this->key);
01500        Pk11Install_ValueList_delete(_this->list);
01501        PR_Free(_this->list);
01502 }
01503 
01504 /*************************************************************************/
01505 void
01506 Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad)
01507 {
01508        while (_this) {
01509               /*PAD(pad); printf("**Pair\n");
01510               PAD(pad); printf("***Key====\n");*/
01511               PAD(pad); printf("%s {\n", _this->key);
01512               /*PAD(pad); printf("====\n");*/
01513               /*PAD(pad); printf("***ValueList\n");*/
01514               Pk11Install_ValueList_Print(_this->list,pad+PADINC);
01515               PAD(pad); printf("}\n");
01516        }
01517 }
01518 
01519 /*************************************************************************/
01520 void
01521 Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad)
01522 {
01523        Pk11Install_Value *v;
01524 
01525        /*PAD(pad);printf("**Value List**\n");*/
01526        for(v = _this->head; v != NULL; v=v->next) {
01527               Pk11Install_Value_Print(v,pad);
01528        }
01529 }
01530 
01531 /*************************************************************************/
01532 void
01533 Pk11Install_Value_Print(Pk11Install_Value* _this, int pad)
01534 {
01535        /*PAD(pad); printf("**Value, type=%s\n",
01536               type==STRING_VALUE ? "string" : "pair");*/
01537        if(_this->type==STRING_VALUE) {
01538               /*PAD(pad+PADINC); printf("====\n");*/
01539               PAD(pad); printf("%s\n", _this->string);
01540               /*PAD(pad+PADINC); printf("====\n");*/
01541        } else {
01542               Pk11Install_Pair_Print(_this->pair,pad+PADINC);
01543        }
01544 }