Back to index

lightning-sunbird  0.9+nobinonly
Parser.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Samir Gehani <sgehani@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "MacInstallWizard.h"
00041 
00042 
00043 /*-----------------------------------------------------------*
00044  *   INI Parser
00045  *-----------------------------------------------------------*/
00046 
00047 void
00048 ParseConfig(void)
00049 {      
00050        OSErr  err;
00051        char   *cfgText;
00052 
00053        gControls->cfg = (Config*) NewPtrClear(sizeof(Config));               
00054 
00055        if(!gControls->cfg)
00056        {
00057         ErrorHandler(eMem, nil);
00058               return;
00059        }
00060        
00061        if (!ReadINIFile(sConfigFName, &cfgText))
00062        {
00063         ErrorHandler(eCfgRead, nil);
00064            return;
00065        }
00066        
00067        ERR_CHECK(PopulateGeneralKeys(cfgText));
00068        ERR_CHECK(PopulateLicWinKeys(cfgText));
00069        ERR_CHECK(PopulateWelcWinKeys(cfgText));
00070        ERR_CHECK(PopulateCompWinKeys(cfgText));
00071        ERR_CHECK(PopulateSetupTypeWinKeys(cfgText));
00072        ERR_CHECK(PopulateTermWinKeys(cfgText));
00073        ERR_CHECK(PopulateIDIKeys(cfgText));
00074        ERR_CHECK(PopulateMiscKeys(cfgText));
00075        
00076        ERR_CHECK(MapDependees());
00077     
00078     if (cfgText)
00079            DisposePtr(cfgText);
00080 }
00081 
00082 void
00083 ParseInstall(void)
00084 {      
00085     OSErr                          err;
00086     char      *instText;
00087 
00088     gStrings = (InstINIRes*) NewPtrClear(sizeof(InstINIRes));                
00089 
00090     if(!gStrings)
00091     {
00092         ErrorHandler(eMem, nil);
00093        return;
00094     }
00095     
00096     if (!ReadINIFile(sInstallFName, &instText))
00097     {
00098         ErrorHandler(eInstRead, nil);
00099         return;
00100     }
00101     
00102     ERR_CHECK(PopulateInstallKeys(instText));
00103     
00104     ERR_CHECK(ReadSystemErrors(instText));
00105     
00106     if (instText)
00107         DisposePtr(instText);
00108 }
00109 
00110 Boolean
00111 ReadINIFile(int sINIFName, char **text)
00112 {
00113     Boolean                        bSuccess = false, isDir = false;
00114        OSErr                       err;
00115        FSSpec                             cfgFile;
00116        long                        cwdDirID, dirID, dataSize;
00117        short                       vRefNum, fileRefNum;
00118        Str255                             fname, pModulesDir;
00119        
00120        *text = nil;
00121        
00122        ERR_CHECK_RET(GetCWD(&cwdDirID, &vRefNum), false);
00123        
00124        /* get the "Installer Modules" relative subdir */
00125        GetIndString(pModulesDir, rStringList, sInstModules);
00126        GetDirectoryID(vRefNum, cwdDirID, pModulesDir, &dirID, &isDir);
00127        if (!isDir)          /* bail if we can't find the "Installer Modules" dir */
00128               return false;
00129               
00130     /* open config.ini or install.ini file */
00131     GetIndString(fname, rStringList, sINIFName);
00132        if ((err = FSMakeFSSpec(vRefNum, dirID, fname, &cfgFile)) != noErr )
00133               return false;
00134        if ((err = FSpOpenDF( &cfgFile, fsRdPerm, &fileRefNum)) != noErr)
00135               return false;
00136               
00137        /* read in entire text */
00138        if ( (err = GetEOF(fileRefNum, &dataSize)) != noErr)
00139               bSuccess = false;
00140        if (dataSize > 0)
00141        {
00142               *text = (char*) NewPtrClear(dataSize + 1);              // ensure null termination
00143               if (!(*text))
00144               {
00145             ErrorHandler(eMem, nil);
00146                      return false;
00147               }
00148                      
00149         if ((err = FSRead(fileRefNum, &dataSize, *text)) == noErr)
00150                      bSuccess = true;
00151        }
00152        
00153        /* close file */
00154        if (!bSuccess || ((err = FSClose(fileRefNum))!=noErr))   
00155               return false;
00156 
00157        return bSuccess;
00158 }      
00159 
00160 #pragma mark -
00161 
00162  OSErr
00163 PopulateInstallKeys(char *instText)
00164 {
00165     OSErr err = noErr;
00166     Handle tmp;
00167     int i;
00168     
00169     tmp = NewHandleClear(kValueMaxLen);
00170     if (!tmp)
00171     {
00172         ErrorHandler(eMem, nil);
00173               return eParseFailed;
00174     }
00175 
00176     for( i = 1; i < instKeysNum + 1; i++ )
00177     {
00178         FillKeyValueUsingSLID(rInstList, sInstGeneral, i, tmp, instText);
00179         my_c2pstrcpy(*tmp, gStrings->iKey[i]);
00180     }
00181 
00182     for( i = 1; i < instMenuNum + 1; i++ )
00183     {
00184         FillKeyValueUsingSLID(rInstMenuList, sMenuGeneral, i, tmp, instText);
00185         my_c2pstrcpy(*tmp, gStrings->iMenu[i]);
00186     }
00187     
00188     for( i = 1; i < instErrsNum + 1; i++ )
00189     {
00190         FillKeyValueUsingSLID(rErrorList, eErrorMessage, i, tmp, instText);
00191         my_c2pstrcpy(*tmp, gStrings->iErr[i]);
00192     }
00193 
00194     DisposeHandle(tmp);
00195     return err;
00196 }
00197 
00198 #define kSystemErrors "System Errors"
00199 
00200 OSErr
00201 ReadSystemErrors(const char *cfg)
00202 {
00203   char  *sectionName, *section, *key, *cfgPtr[1], *sectionPtr[1];
00204   char      *value, *outValue;
00205   extern short gErrTableSize;
00206   unsigned char *pStr255;
00207   extern ErrTableEnt *gErrTable;  
00208   OSErr ret = noErr;  
00209 
00210   *cfgPtr = (char*) cfg;
00211     
00212   value = (char*) calloc(kValueMaxLen, sizeof( char ) );
00213   outValue = (char*) calloc(kValueMaxLen, sizeof( char ) );
00214   sectionName =     (char *) calloc( kSNameMaxLen, sizeof( char ) );
00215   section =         (char *) calloc( kSectionMaxLen, sizeof( char ) ); 
00216   key =             (char *) calloc( kKeyMaxLen, sizeof( char ) );
00217   if (!sectionName || !section || !key || !value || !outValue)
00218   {
00219     ErrorHandler(eMem, nil);
00220     ret = eParseFailed;
00221   } 
00222   else {
00223     
00224     /* find next section   [cfgPtr moved past next section per iteration] */
00225     
00226     while(GetNextSection(cfgPtr, sectionName, section))
00227     { 
00228       if (strncmp(sectionName, kSystemErrors, strlen(kSystemErrors)) == 0)    
00229       {
00230         *sectionPtr = section;
00231             
00232       /* find next key   [sectionPtr moved past next key per iteration] */
00233         while(GetNextKeyVal(sectionPtr, key, outValue))
00234         {             
00235           gErrTable = (ErrTableEnt *) realloc( gErrTable, (gErrTableSize + 1) * sizeof( ErrTableEnt ) );
00236           if ( gErrTable != NULL ) {
00237             gErrTable[gErrTableSize].num = atoi(key);
00238             pStr255 = CToPascal(outValue);
00239             if ( pStr255 ) {
00240               BlockMoveData(&pStr255[0], &gErrTable[gErrTableSize++].msg[0], pStr255[0] + 1);
00241               DisposePtr((char *) pStr255);
00242             }
00243           }                      
00244         }
00245       }
00246     }
00247   }
00248   
00249   if(key) 
00250     free(key);
00251   if(sectionName) 
00252     free(sectionName);
00253   if(section) 
00254     free(section);
00255   if(value) 
00256     free(value);
00257   if(outValue) 
00258     free(outValue);
00259     
00260   return ret; 
00261 }
00262 
00263 OSErr
00264 PopulateGeneralKeys(char *cfgText)
00265 {
00266     short rv;
00267     int i;
00268     char cSection[255], cKeyRoot[255], cKey[255];
00269     Str255 pSection, pKeyRoot;
00270     
00271     /* General section: subdir */
00272     gControls->cfg->targetSubfolder = NewHandleClear(kValueMaxLen);
00273     if (!gControls->cfg->targetSubfolder)
00274     {
00275         ErrorHandler(eMem, nil);
00276         return eParseFailed;
00277     }
00278     
00279     /* don't check retval siunce we don't care if we don't find this: it's optional */
00280     FillKeyValueUsingResID(sGeneral, sSubfolder, gControls->cfg->targetSubfolder, cfgText);
00281     
00282     /* General section: global URL */
00283     GetIndString(pSection, rParseKeys, sGeneral);
00284     GetIndString(pKeyRoot, rParseKeys, sURL);
00285     CopyPascalStrToC(pKeyRoot, cKeyRoot);
00286     CopyPascalStrToC(pSection, cSection);
00287     gControls->cfg->numGlobalURLs = 0;
00288     for (i = 0; i < kMaxGlobalURLs; ++i)
00289     {
00290         gControls->cfg->globalURL[i] = NewHandleClear(kValueMaxLen);
00291         if (!gControls->cfg->globalURL[i])
00292         {
00293             ErrorHandler(eMem, nil);
00294             return eParseFailed;
00295         }
00296 
00297         /* not compulsory */
00298         sprintf(cKey, "%s%d", cKeyRoot, i);  // URL0, URL1, ... URL4
00299         rv  = FillKeyValueUsingName(cSection, cKey, gControls->cfg->globalURL[i], cfgText);
00300         if (rv == false)
00301             break;
00302         gControls->cfg->numGlobalURLs++;
00303     }
00304     
00305     return noErr;
00306 }
00307 
00308 OSErr
00309 PopulateLicWinKeys(char *cfgText)
00310 {
00311        OSErr err = noErr;
00312        
00313        /* LicenseWin: license file name */
00314        gControls->cfg->licFileName = NewHandleClear(kValueMaxLen);
00315        if (!gControls->cfg->licFileName)
00316        {
00317         ErrorHandler(eMem, nil);
00318               return eParseFailed;
00319        }
00320        
00321        if (!FillKeyValueUsingResID(sLicDlg, sLicFile, gControls->cfg->licFileName, cfgText))
00322               err = eParseFailed;
00323        
00324        return err;
00325 }
00326 
00327 OSErr
00328 PopulateWelcWinKeys(char *cfgText)
00329 {
00330        OSErr err = noErr;
00331        
00332        /* WelcomeWin: message strings */
00333        gControls->cfg->welcMsg[0] = NewHandleClear(kValueMaxLen);
00334        if (!gControls->cfg->welcMsg[0])
00335        {
00336         ErrorHandler(eMem, nil);
00337               return eParseFailed;
00338        }
00339               
00340        if (!FillKeyValueUsingResID(sWelcDlg, sMsg0, gControls->cfg->welcMsg[0], cfgText))
00341        {
00342         ErrorHandler(eParseFailed, nil);
00343               return eParseFailed;
00344        }
00345               
00346        gControls->cfg->welcMsg[1] = NewHandleClear(kValueMaxLen);
00347        if (!gControls->cfg->welcMsg[1])
00348        {
00349         ErrorHandler(eParseFailed, nil);
00350               return eParseFailed;
00351        }      
00352 
00353     FillKeyValueUsingResID(sWelcDlg, sMsg1, gControls->cfg->welcMsg[1], cfgText);
00354               
00355        gControls->cfg->welcMsg[2] = NewHandleClear(kValueMaxLen);
00356        if (!gControls->cfg->welcMsg[2])
00357        {
00358         ErrorHandler(eParseFailed, nil);
00359               return eParseFailed;
00360        }
00361 
00362        FillKeyValueUsingResID(sWelcDlg, sMsg2, gControls->cfg->welcMsg[2], cfgText);
00363        /*
00364        ** NOTE:
00365        ** We don't care if the second and third messages are not filled since by
00366        ** definition we require only one message string to be specified in the INI
00367        ** file. Msgs 2 and 3 are optional.
00368        */
00369        
00370        /* get readme file name and app to launch it with */
00371        gControls->cfg->readmeFile = NewHandleClear(kValueMaxLen);
00372        if (!gControls->cfg->readmeFile)
00373        {
00374         ErrorHandler(eMem, nil);
00375               return eParseFailed;
00376        }
00377        if (FillKeyValueUsingResID(sWelcDlg, sReadmeFilename, gControls->cfg->readmeFile, cfgText))
00378               gControls->cfg->bReadme = true;
00379        else
00380               gControls->cfg->bReadme = false;
00381        
00382        if (gControls->cfg->bReadme)
00383        {
00384               gControls->cfg->readmeApp = NewHandleClear(kValueMaxLen);
00385               if (!gControls->cfg->readmeApp)
00386               {
00387             ErrorHandler(eMem, nil);
00388                      return eParseFailed;
00389               }
00390               
00391               if (!FillKeyValueUsingResID(sWelcDlg, sReadmeApp, gControls->cfg->readmeApp, cfgText))
00392               {
00393             ErrorHandler(eMem, nil);
00394                      return eParseFailed;
00395               }
00396        }
00397               
00398        return err;
00399 }
00400 
00401 OSErr
00402 PopulateCompWinKeys(char *cfgText)
00403 {
00404        OSErr         err = noErr;
00405        int                  i, j, hunVal, tenVal, unitVal;
00406        Ptr                  currSNameBuf, currSName, currKeyBuf, currKey, idxCh;
00407        Str255        pSName, pkey, pidx;
00408        char          eof[1];
00409        char          *currDepNum;
00410        long          randomPercent;
00411        Boolean              bRandomSet;
00412        
00413        eof[0] = 0;
00414        
00415        /* ComponentsWin: components and their descriptions, and other properties */
00416        gControls->cfg->selCompMsg = NewHandleClear(kValueMaxLen);
00417        FillKeyValueUsingResID(sCompDlg, sMsg0, gControls->cfg->selCompMsg, cfgText);
00418        
00419        /* AdditionsWin: additional components */
00420        gControls->cfg->selAddMsg = NewHandleClear(kValueMaxLen);
00421        FillKeyValueUsingResID(sAddDlg, sMsg0, gControls->cfg->selAddMsg, cfgText);
00422        gControls->cfg->bAdditionsExist = false;
00423        
00424        gControls->cfg->numComps = 0;
00425        for (i=0; i<kMaxComponents; i++)
00426        {
00427               GetIndString(pSName, rParseKeys, sComponent);           
00428               currSNameBuf = PascalToC(pSName);
00429               currSName = NewPtrClear(kSNameMaxLen);
00430               strncpy(currSName, currSNameBuf, strlen(currSNameBuf));
00431               
00432               if(i>99) // concat 100's digit 
00433               {
00434                      hunVal = i/100;
00435                      GetIndString(pidx, rIndices, hunVal+1);
00436                      idxCh = PascalToC(pidx);
00437                      strncat(currSName, idxCh, 1);
00438                      DisposePtr(idxCh);
00439               }
00440               else
00441                      hunVal = 0;
00442               
00443               if(i>9)       // concat 10's digit 
00444               {
00445                      tenVal = (i - (hunVal*100))/10;
00446                      GetIndString(pidx, rIndices, tenVal+1);
00447                      idxCh = PascalToC(pidx);
00448                      strncat(currSName, idxCh, 1);
00449                      DisposePtr(idxCh);
00450               }
00451               else
00452                      tenVal = 0;
00453        
00454               unitVal = i - (hunVal*100) - (tenVal*10);
00455               GetIndString(pidx, rIndices, unitVal+1);
00456               idxCh = PascalToC(pidx);
00457               strncat(currSName, idxCh, 1);
00458               DisposePtr(idxCh);
00459               strncat(currSName, eof, 1);
00460               
00461               /* short description */
00462               GetIndString(pkey, rParseKeys, sDescShort);
00463               currKey = PascalToC(pkey);
00464               gControls->cfg->comp[i].shortDesc = NewHandleClear(kValueMaxLen);
00465               if (!FillKeyValueUsingName(currSName, currKey, gControls->cfg->comp[i].shortDesc, cfgText))
00466               {
00467                   DisposePtr(currSName);
00468                   DisposePtr(currSNameBuf);
00469                      DisposePtr(currKey);
00470                      break; // no more Components
00471               }
00472               DisposePtr(currKey);
00473               
00474               /* long description */
00475               GetIndString(pkey, rParseKeys, sDescLong);
00476               currKey = PascalToC(pkey);
00477               gControls->cfg->comp[i].longDesc = NewHandleClear(kValueMaxLen);
00478               FillKeyValueUsingName(currSName, currKey, gControls->cfg->comp[i].longDesc, cfgText);
00479               DisposePtr(currKey);
00480               
00481               /* archive */
00482               GetIndString(pkey, rParseKeys, sArchive);
00483               currKey = PascalToC(pkey);
00484               gControls->cfg->comp[i].archive = NewHandleClear(kArchiveMaxLen);
00485               FillKeyValueUsingName(currSName, currKey, gControls->cfg->comp[i].archive, cfgText);
00486               DisposePtr(currKey);
00487               
00488               /* install size */
00489               GetIndString(pkey, rParseKeys, sInstSize);
00490               currKey = PascalToC(pkey);
00491               Handle sizeH = NewHandleClear(4); // long is four bytes
00492               FillKeyValueUsingName(currSName, currKey, sizeH, cfgText);
00493               HLock(sizeH);
00494               gControls->cfg->comp[i].size = atol(*sizeH);
00495               HUnlock(sizeH);
00496               DisposeHandle(sizeH);
00497               DisposePtr(currKey);
00498               
00499               // set the dirty flag to indicate the CRC has not passed
00500               
00501               gControls->cfg->comp[i].dirty = true;
00502               
00503               /* random install percentage */
00504               GetIndString(pkey, rParseKeys, sRandomInstall);
00505               currKey = PascalToC(pkey);
00506               Handle randomH = NewHandleClear(4);
00507               if (FillKeyValueUsingName(currSName, currKey, randomH, cfgText))
00508               {
00509                      bRandomSet = true;
00510                      HLock(randomH);
00511                      randomPercent = atol(*randomH);
00512                      HUnlock(randomH);
00513                      
00514                      if (randomPercent != 0) /* idiot proof for those giving 0 as the rand percent */
00515                      {
00516                             if (RandomSelect(randomPercent))
00517                             {
00518                                    gControls->cfg->comp[i].selected = true;
00519                                    gControls->cfg->comp[i].refcnt = 1;
00520                             }
00521                             else
00522                             {
00523                                    gControls->cfg->comp[i].selected = false;
00524                                    gControls->cfg->comp[i].refcnt = 0;
00525                             }
00526                      }
00527                      else
00528                             bRandomSet = false;
00529               }
00530               else
00531                      bRandomSet = false;
00532               if (randomH)
00533                      DisposeHandle(randomH);
00534               if (currKey)
00535                      DisposePtr(currKey);
00536               
00537               /* attributes (SELECTED|INVISIBLE|LAUNCHAPP|ADDITIONAL|DOWNLOAD_ONLY) */
00538               GetIndString(pkey, rParseKeys, sAttributes);
00539               currKey = PascalToC(pkey);
00540               Handle attrValH = NewHandleClear(255);
00541               if (FillKeyValueUsingName(currSName, currKey, attrValH, cfgText))
00542               {
00543                      HLock(attrValH);
00544               
00545                      char *attrType = NULL;
00546                      GetIndString(pkey, rParseKeys, sSELECTED);
00547                      attrType = PascalToC(pkey);
00548                      if (!bRandomSet) /* when random key specified then selected attr is overriden */
00549                      {
00550                             if (NULL != strstr(*attrValH, attrType))
00551                             {
00552                                    gControls->cfg->comp[i].selected = true;
00553                                    gControls->cfg->comp[i].refcnt = 1;
00554                             }
00555                             else
00556                             {
00557                                    gControls->cfg->comp[i].selected = false;
00558                                    gControls->cfg->comp[i].refcnt = 0;
00559                             }
00560                      }
00561                      if (attrType)
00562                             DisposePtr(attrType);
00563               
00564                      GetIndString(pkey, rParseKeys, sINVISIBLE);
00565                      attrType = PascalToC(pkey);
00566                      if (NULL != strstr(*attrValH, attrType))
00567                             gControls->cfg->comp[i].invisible = true;
00568                      else
00569                             gControls->cfg->comp[i].invisible = false;
00570                      if (attrType)
00571                             DisposePtr(attrType);
00572                             
00573                      GetIndString(pkey, rParseKeys, sLAUNCHAPP);
00574                      attrType = PascalToC(pkey);
00575                      if (NULL != strstr(*attrValH, attrType))
00576                             gControls->cfg->comp[i].launchapp = true;
00577                      else
00578                             gControls->cfg->comp[i].launchapp = false;
00579                      if (attrType)
00580                             DisposePtr(attrType);
00581                      
00582                      GetIndString(pkey, rParseKeys, sADDITIONAL);
00583                      attrType = PascalToC(pkey);
00584                      if (NULL != strstr(*attrValH, attrType))
00585                      {
00586                             gControls->cfg->comp[i].additional = true;
00587                             gControls->cfg->bAdditionsExist = true; /* doesn't matter if set multiple times */
00588                      }
00589                      else
00590                             gControls->cfg->comp[i].additional = false;
00591                      if (attrType)
00592                             DisposePtr(attrType);       
00593                      
00594                      GetIndString(pkey, rParseKeys, sDOWNLOAD_ONLY);
00595                      attrType = PascalToC(pkey);
00596                      if (NULL != strstr(*attrValH, attrType))
00597                             gControls->cfg->comp[i].download_only = true;
00598                      else
00599                             gControls->cfg->comp[i].download_only = false;
00600                      if (attrType)
00601                             DisposePtr(attrType);       
00602                             
00603                      HUnlock(attrValH);
00604               }
00605               if (attrValH)
00606                      DisposeHandle(attrValH);
00607                      
00608               /* initialize to not highlighted */
00609               gControls->cfg->comp[i].highlighted = false;
00610               
00611               /* dependees for other components */
00612               gControls->cfg->comp[i].numDeps = 0;
00613               GetIndString(pkey, rParseKeys, sDependee);
00614               currKeyBuf = PascalToC(pkey);
00615               for (j=0; j<kMaxComponents; j++)
00616               {
00617                      // currKey = "Dependee<j>"
00618                      currDepNum = ltoa(j);
00619                      currKey = NewPtrClear(strlen(currKeyBuf) + strlen(currDepNum) + 1);
00620                      strcpy(currKey, currKeyBuf);
00621                      strcat(currKey, currDepNum);
00622 
00623                      gControls->cfg->comp[i].depName[j] = NewHandleClear(kValueMaxLen);
00624                      if (!FillKeyValueUsingName(currSName, currKey, gControls->cfg->comp[i].depName[j], cfgText))
00625                      {
00626                             if (currKey)
00627                                    DisposePtr(currKey);
00628                             if (currDepNum)
00629                                    free(currDepNum);
00630                             break;
00631                      }
00632                      
00633                      gControls->cfg->comp[i].numDeps++;
00634                      if (currKey)
00635                             DisposePtr(currKey);
00636                      if (currDepNum)
00637                             free(currDepNum);
00638               }
00639               if (currKeyBuf)
00640                      DisposePtr(currKeyBuf);
00641        }
00642        gControls->cfg->numComps = i;
00643        
00644        return err;
00645 }
00646 
00647 OSErr
00648 PopulateSetupTypeWinKeys(char *cfgText)
00649 {
00650        OSErr         err = noErr;
00651        int                  i, j, hunVal, tenVal, unitVal, compNum, cNumIdx;
00652        Ptr                  currSNameBuf, currSName, currKeyBuf, currKey, idxCh, currCompName, compIdx;
00653        Str255        pSName, pkey, pidx;
00654        char          eof[1];
00655        Handle        currVal;
00656        
00657        eof[0] = 0;
00658        
00659        /* SetupTypeWin: types and their descriptions */
00660        gControls->cfg->numSetupTypes = 0;
00661        for (i=0;i<kMaxSetupTypes;i++)   /* init stComp[][] lists */
00662        {
00663               for(j=0; j<gControls->cfg->numComps; j++)
00664               {
00665                      gControls->cfg->st[i].comp[j] = kNotInSetupType;
00666               }
00667        }
00668        for (i=0; i<kMaxSetupTypes; i++)
00669        {
00670               GetIndString(pSName, rParseKeys, sSetupType);           
00671               currSNameBuf = PascalToC(pSName);
00672               currSName = NewPtrClear(kKeyMaxLen);
00673               strncpy(currSName, currSNameBuf, strlen(currSNameBuf));
00674 
00675               unitVal = i;
00676               GetIndString(pidx, rIndices, unitVal+1);
00677               idxCh = PascalToC(pidx);
00678               strncat(currSName, idxCh, 1);
00679               DisposePtr(idxCh);
00680               strncat(currSName, eof, 1);
00681               
00682               /* short description */
00683               GetIndString(pkey, rParseKeys, sDescShort);
00684               currKey = PascalToC(pkey);
00685               gControls->cfg->st[i].shortDesc = NewHandleClear(kValueMaxLen);
00686               if (!FillKeyValueUsingName(currSName, currKey, gControls->cfg->st[i].shortDesc, cfgText))
00687               {
00688                      DisposePtr(currKey);
00689                      DisposePtr(currSName);
00690                      DisposePtr(currSNameBuf);
00691                      break; // no more SetupTypes 
00692               }
00693               DisposePtr(currKey);
00694 
00695               /* long description */
00696               GetIndString(pkey, rParseKeys, sDescLong);
00697               currKey = PascalToC(pkey);
00698               gControls->cfg->st[i].longDesc = NewHandleClear(kValueMaxLen);
00699               FillKeyValueUsingName(currSName, currKey, gControls->cfg->st[i].longDesc, cfgText);
00700               DisposePtr(currKey);
00701               
00702               /* now search for all components in this SetupType and fill its stComp[][] array */
00703               gControls->cfg->st[i].numComps = 0;
00704               for (j=0; j<gControls->cfg->numComps; j++)
00705               {
00706                      GetIndString(pkey, rParseKeys, sC);
00707                      currKeyBuf = PascalToC(pkey);
00708                      currKey = NewPtrClear(kKeyMaxLen);
00709                      strncpy(currKey, currKeyBuf, strlen(currKeyBuf));
00710                      
00711                      if(j>99) // concat 100's digit 
00712                      {
00713                             hunVal = j/100;
00714                             GetIndString(pidx, rIndices, hunVal+1);
00715                             idxCh = PascalToC(pidx);
00716                             strncat(currKey, idxCh, 1);
00717                             DisposePtr(idxCh);
00718                      }
00719                      else
00720                             hunVal = 0;
00721               
00722                      if(j>9)       // concat 10's digit 
00723                      {
00724                             tenVal = (j - (hunVal*100))/10;
00725                             GetIndString(pidx, rIndices, tenVal+1);
00726                             idxCh = PascalToC(pidx);
00727                             strncat(currKey, idxCh, 1);
00728                             DisposePtr(idxCh);
00729                      }
00730                      else
00731                             tenVal = 0;
00732        
00733                      unitVal = j - (hunVal*100) - (tenVal*10);
00734                      GetIndString(pidx, rIndices, unitVal+1);
00735                      idxCh = PascalToC(pidx);
00736                      strncat(currKey, idxCh, 1);
00737                      DisposePtr(idxCh);
00738                      strncat(currKey, eof, 1);
00739                      
00740                      currVal = NewHandleClear(kValueMaxLen);
00741                      if (FillKeyValueUsingName(currSName, currKey, currVal, cfgText))
00742                      {
00743                             /* Parse the value to get the component index */
00744                             GetIndString(pSName, rParseKeys, sComponent);           
00745                             currSNameBuf = PascalToC(pSName);
00746                             currCompName = NewPtrClear(kKeyMaxLen);
00747                             strncpy(currCompName, currSNameBuf, strlen(currSNameBuf));
00748                             
00749                             HLock(currVal);
00750                             cNumIdx = strspn(currCompName, *currVal);
00751                             compIdx = *currVal+cNumIdx;
00752                             compNum = atoi(compIdx);
00753                             gControls->cfg->st[i].comp[compNum] = kInSetupType;
00754                             gControls->cfg->st[i].numComps++;
00755                             HUnlock(currVal);
00756                      }
00757               }
00758                      
00759               DisposePtr(currKey);
00760               DisposePtr(currKeyBuf);
00761               DisposePtr(currSName);
00762               DisposePtr(currSNameBuf);
00763        }
00764        gControls->cfg->numSetupTypes = i;
00765        
00766        return err;
00767 }
00768        
00769 OSErr
00770 PopulateTermWinKeys(char *cfgText)
00771 {
00772        OSErr  err = noErr;
00773        short  i;
00774        Str255        pSection, pIdRoot, pDomainRoot, pDescRoot, pSubpath;
00775        char   *cSection = NULL, *cId = NULL, *cDomain = NULL, 
00776                *cDesc = NULL, *cSubpath = NULL, *cIndex = NULL;
00777        Boolean bMoreSites = true;
00778        
00779        /* TerminalWin: start install msg */
00780        gControls->cfg->startMsg = NewHandleClear(kValueMaxLen);
00781        FillKeyValueUsingResID(sTermDlg, sMsg0, gControls->cfg->startMsg, cfgText);
00782        
00783        /* site selector keys */
00784        gControls->cfg->numSites = 0;
00785        GetIndString(pSection, rParseKeys, sSiteSelector);
00786        GetIndString(pIdRoot, rParseKeys, sIdentifier);
00787        GetIndString(pDomainRoot, rParseKeys, sDomain);
00788        GetIndString(pDescRoot, rParseKeys, sDescription);
00789        cSection = PascalToC(pSection);
00790        cId = NewPtrClear(pIdRoot[0] + 4);
00791        cDesc = NewPtrClear(pDescRoot[0] + 4);
00792        cDomain = NewPtrClear(pDomainRoot[0] + 4);
00793        if (!cSection || !cDesc || !cDomain)
00794               return eParseFailed;
00795        for (i = 0; i < kMaxSites; i++)
00796        {      
00797               cIndex = ltoa(i);
00798               if (!cIndex) 
00799                      break;
00800               
00801               memset(cId, 0, pIdRoot[0] + 4);
00802               strncpy(cId, (char*)&pIdRoot[1], pIdRoot[0]);
00803               strcat(cId, cIndex);
00804               
00805               memset(cDesc, 0, pDescRoot[0] + 4);
00806               strncpy(cDesc, (char*)&pDescRoot[1], pDescRoot[0]);
00807               strcat(cDesc, cIndex);
00808               
00809               memset(cDomain, 0 , pDomainRoot[0] + 4);
00810               strncpy(cDomain, (char*)&pDomainRoot[1], pDomainRoot[0]);
00811               strcat(cDomain, cIndex);
00812               
00813               gControls->cfg->site[i].id = NewHandleClear(kValueMaxLen);
00814               if (!FillKeyValueUsingName(cSection, cId, gControls->cfg->site[i].id, cfgText))
00815                   bMoreSites = false;
00816               if (bMoreSites)
00817               {
00818                      gControls->cfg->site[i].desc = NewHandleClear(kValueMaxLen);
00819                   if (!FillKeyValueUsingName(cSection, cDesc, gControls->cfg->site[i].desc, cfgText))
00820                          bMoreSites = false;
00821                      gControls->cfg->site[i].domain = NewHandleClear(kValueMaxLen);
00822                      if (!FillKeyValueUsingName(cSection, cDomain, gControls->cfg->site[i].domain, cfgText))
00823                             bMoreSites = false;
00824                      else
00825                             gControls->cfg->numSites++;
00826               }
00827 
00828               if (cIndex)
00829                      free(cIndex);
00830               cIndex = NULL;
00831               
00832               if (!bMoreSites)
00833                      break;
00834        }
00835        
00836        if (cSection)
00837               DisposePtr((Ptr) cSection);
00838        if (cId)
00839            DisposePtr((Ptr) cId);
00840        if (cDesc)
00841               DisposePtr((Ptr) cDesc);
00842        if (cDomain)
00843               DisposePtr((Ptr) cDomain);
00844               
00845        /* redirect for remote site selector section */
00846        GetIndString(pSection, rParseKeys, sRedirect);
00847        GetIndString(pSubpath, rParseKeys, sSubpath);
00848        cSection = PascalToC(pSection);
00849        cDesc = PascalToC(pDescRoot);
00850        cSubpath = PascalToC(pSubpath);
00851        if (!cSubpath || !cSection || !cDesc)
00852               return eMem;
00853               
00854        gControls->cfg->redirect.desc = NewHandleClear(kValueMaxLen);
00855        if (FillKeyValueUsingResID(sRedirect, sDescription, gControls->cfg->redirect.desc, cfgText))
00856        {                    
00857               gControls->cfg->redirect.subpath = NewHandleClear(kValueMaxLen);
00858               FillKeyValueUsingName(cSection, cSubpath, gControls->cfg->redirect.subpath, cfgText);
00859        }
00860        
00861        /* save bits msg */
00862        gControls->cfg->saveBitsMsg = NewHandleClear(kValueMaxLen);
00863        FillKeyValueUsingResID(sTermDlg, sMsg1, gControls->cfg->saveBitsMsg, cfgText);
00864        
00865        if (cSection)
00866               DisposePtr((Ptr)cSection);
00867        if (cDesc)
00868               DisposePtr((Ptr)cDesc);
00869        if (cSubpath)
00870               DisposePtr((Ptr)cSubpath);
00871               
00872        return err;
00873 }
00874 
00875 OSErr
00876 PopulateIDIKeys(char *cfgText)
00877 {
00878        OSErr err = noErr;
00879               
00880        /* "Tunneled" IDI Keys */
00881        gControls->cfg->coreFile = NewHandleClear(kValueMaxLen);
00882        FillKeyValueUsingSLID(rIDIKeys, sSDNSInstall, sCoreFile, gControls->cfg->coreFile, cfgText);
00883        
00884        gControls->cfg->coreDir = NewHandleClear(kValueMaxLen);
00885        FillKeyValueUsingSLID(rIDIKeys, sSDNSInstall, sCoreDir, gControls->cfg->coreDir, cfgText);
00886        
00887        gControls->cfg->noAds = NewHandleClear(kValueMaxLen);
00888        FillKeyValueUsingSLID(rIDIKeys, sSDNSInstall, sNoAds, gControls->cfg->noAds, cfgText);
00889        
00890        gControls->cfg->silent = NewHandleClear(kValueMaxLen);
00891        FillKeyValueUsingSLID(rIDIKeys, sSDNSInstall, sSilent, gControls->cfg->silent, cfgText);
00892        
00893        gControls->cfg->execution = NewHandleClear(kValueMaxLen);
00894        FillKeyValueUsingSLID(rIDIKeys, sSDNSInstall, sExecution, gControls->cfg->execution, cfgText);
00895        
00896        gControls->cfg->confirmInstall = NewHandleClear(kValueMaxLen);
00897        FillKeyValueUsingSLID(rIDIKeys, sSDNSInstall, sConfirmInstall, gControls->cfg->confirmInstall, cfgText);
00898        
00899        return err;
00900 }
00901 
00902 OSErr
00903 PopulateMiscKeys(char *cfgText)
00904 {
00905        OSErr err = noErr;
00906        int i;
00907        Str255 psection;
00908        Ptr           csection;
00909        char   *section, *idx;
00910        
00911        /* RunAppX section */
00912        gControls->cfg->numRunApps = 0;
00913        GetIndString(psection, rParseKeys, sRunApp);
00914        csection = PascalToC(psection);
00915 
00916        for (i = 0; i < kMaxRunApps; i++)
00917        {
00918               section = (char*) malloc((strlen(csection) * sizeof(char)) + 3); /* added 3 for idx nums and null termination */
00919               if (!section)
00920                      return eParseFailed;
00921               memset( section, 0, ((strlen(csection) * sizeof(char)) + 3) );
00922               idx = ltoa(i);
00923               strcpy(section, csection);
00924               strcat(section, idx);
00925               strcat(section, "\0");
00926               gControls->cfg->apps[i].targetApp = NewHandleClear(kValueMaxLen);
00927               if (!FillKeyValueSecNameKeyID(rParseKeys, section, sTargetApp, gControls->cfg->apps[i].targetApp, cfgText))
00928               {
00929                      if (section)
00930                             free (section);
00931                      if (idx)
00932                             free(idx);
00933                      break;
00934               }
00935               gControls->cfg->apps[i].targetDoc = NewHandleClear(kValueMaxLen);
00936               if (!FillKeyValueSecNameKeyID(rParseKeys, section, sTargetDoc, gControls->cfg->apps[i].targetDoc, cfgText))
00937                      gControls->cfg->apps[i].targetDoc = NULL; // no optional doc supplied
00938                      
00939               gControls->cfg->numRunApps++;
00940               if (section)
00941                      free (section);
00942               if (idx)
00943                      free (idx);
00944        }
00945        if (csection)
00946               DisposePtr(csection);
00947        
00948        /* LegacyCheckX section */
00949        gControls->cfg->numLegacyChecks = 0;
00950        GetIndString(psection, rParseKeys, sLegacyCheck);
00951        csection = PascalToC(psection);
00952        
00953        for (i = 0; i < kMaxLegacyChecks; i++)
00954        {
00955               section = (char *) malloc((strlen(csection) * sizeof(char)) + 3); /* added 3 for idx nums and null termination */
00956               if (!section)
00957                      return eParseFailed;
00958               memset( section, 0, ((strlen(csection) * sizeof(char)) + 3) );
00959               idx = ltoa(i);
00960               strcpy(section, csection);
00961               strcat(section, idx);
00962               strcat(section, "\0");
00963               
00964               gControls->cfg->checks[i].filename = NewHandleClear(kValueMaxLen);
00965               if (!FillKeyValueSecNameKeyID(rParseKeys, section, sFilename, gControls->cfg->checks[i].filename, cfgText))
00966               {
00967                      if (section)
00968                             free (section);
00969                      if (idx)
00970                             free (idx);
00971                      break;
00972               }
00973               
00974               gControls->cfg->checks[i].subfolder = NewHandleClear(kValueMaxLen);
00975               FillKeyValueSecNameKeyID(rParseKeys, section, sSubfolder, gControls->cfg->checks[i].subfolder, cfgText);
00976               
00977               /* if no version, we'll detect if the file is there and throw up the warning dlg */
00978               gControls->cfg->checks[i].version = NewHandleClear(kValueMaxLen);
00979               FillKeyValueSecNameKeyID(rParseKeys, section, sVersion, gControls->cfg->checks[i].version, cfgText);
00980               
00981               gControls->cfg->checks[i].message = NewHandleClear(kValueMaxLen);
00982               if (!FillKeyValueSecNameKeyID(rParseKeys, section, sMessage, gControls->cfg->checks[i].message, cfgText))
00983               {
00984                      if (section)
00985                             free (section);
00986                      if (idx)
00987                             free (idx);
00988                      break;
00989               }
00990               gControls->cfg->numLegacyChecks++;
00991               if (section)
00992                      free (section);
00993               if (idx)
00994                      free (idx);
00995        }
00996        if (csection)
00997               DisposePtr(csection);
00998        
00999        return err;
01000 }
01001 
01002 #pragma mark - 
01003 
01004 OSErr
01005 MapDependees()
01006 {
01007        OSErr  err = noErr;
01008        int    i, j, compIdx;
01009        
01010        for (i=0; i<gControls->cfg->numComps; i++)
01011        {
01012               // init all deps to off
01013               for (j=0; j<kMaxComponents; j++)
01014               {
01015                      gControls->cfg->comp[i].dep[j] = kDependeeOff;
01016               }
01017               
01018               // loop through turning on deps
01019               for(j=0; j<gControls->cfg->comp[i].numDeps; j++)
01020               {
01021                      compIdx = GetComponentIndex(gControls->cfg->comp[i].depName[j]);
01022                      if (compIdx != kInvalidCompIdx)
01023                      {
01024                             gControls->cfg->comp[i].dep[compIdx] = kDependeeOn;
01025                             
01026                             // we deal with making it selected and mucking with the ref count
01027                             // in the components win code (see ComponentsWin.c:{SetOptInfo(), ResolveDependees()}
01028                      }
01029               }
01030        }
01031        
01032        return err;
01033 }
01034 
01035 Boolean
01036 RandomSelect(long percent)
01037 {
01038        Boolean bSelect = false;
01039        int arbitrary = 0;
01040        
01041        srand(time(NULL));
01042        arbitrary = rand();
01043        arbitrary %= 100;
01044        
01045        if (arbitrary <= percent)
01046               bSelect = true;
01047               
01048        return bSelect;
01049 }
01050 
01051 short
01052 GetComponentIndex(Handle compName)
01053 {
01054        int i;
01055        short compIdx = kInvalidCompIdx;
01056        
01057        HLock(compName);
01058        for (i=0; i<gControls->cfg->numComps; i++)
01059        {
01060               HLock(gControls->cfg->comp[i].shortDesc);
01061               if (0==strcmp(*gControls->cfg->comp[i].shortDesc, *compName))
01062               {
01063                      compIdx = i;                
01064                      HUnlock(gControls->cfg->comp[i].shortDesc);
01065                      break;
01066               }
01067               HUnlock(gControls->cfg->comp[i].shortDesc);
01068        }
01069        HUnlock(compName);
01070        
01071        return compIdx;
01072 }
01073 
01074 #pragma mark -
01075        
01076 Boolean
01077 FillKeyValueUsingResID(short dlgID, short keyID, Handle dest, char *cfgText)
01078 {
01079        /* Fill key-value pair using resIDs for the dlg/section name, and the key */
01080        
01081        return FillKeyValueUsingSLID(rParseKeys, dlgID, keyID, dest, cfgText);
01082 }
01083 
01084 Boolean
01085 FillKeyValueForIDIKey(short keyID, Handle dest, char *cfgText)
01086 {
01087        /* Fill key-value pair in IDI stringlist */
01088        
01089        return FillKeyValueUsingSLID(rIDIKeys, sSDNSInstall, keyID, dest, cfgText);
01090 }
01091 
01092 Boolean
01093 FillKeyValueUsingSLID(short stringListID, short dlgID, short keyID, Handle dest, char *cfgText)
01094 {
01095        /* Fill key-value pair using stringlist ID */
01096 
01097        unsigned char pkey[kKeyMaxLen], psectionName[kSNameMaxLen];
01098        char                 *key, *sectionName;
01099        Boolean                     bFound = false;
01100        
01101        GetIndString(pkey, stringListID, keyID);         
01102        key = PascalToC(pkey);
01103        
01104        GetIndString(psectionName, stringListID, dlgID);
01105        sectionName = PascalToC(psectionName);
01106        
01107        if (FillKeyValueUsingName(sectionName, key, dest, cfgText))
01108               bFound = true;
01109 
01110        if(sectionName)
01111         DisposePtr(sectionName);
01112        if(key)
01113         DisposePtr(key);
01114        return bFound;
01115 }
01116 
01117 Boolean
01118 FillKeyValueSecNameKeyID(short strListID, char *sectionName, short keyID, Handle dest, char *cfgText)
01119 {
01120        /* Fill key-value pair using section name str and key res id */
01121        
01122        unsigned char pkey[kKeyMaxLen];
01123        char                 *key;
01124        Boolean              bFound = false;
01125        
01126        GetIndString(pkey, strListID, keyID);
01127        key = PascalToC(pkey);
01128        
01129        if (FillKeyValueUsingName(sectionName, key, dest, cfgText))
01130               bFound = true;
01131        
01132        if (key)
01133               DisposePtr(key);
01134               
01135        return bFound;
01136 }
01137 
01138 Boolean
01139 FillKeyValueUsingName(char *sectionName, char *keyName, Handle dest, char *cfgText)
01140 {
01141        /* Fill key-value pair using the pascal string section name and key name */
01142        
01143        char          *value;
01144        Boolean              bFound = false;
01145        
01146        value = (char*) NewPtrClear(kValueMaxLen);
01147        if (!value)
01148        {
01149         ErrorHandler(eMem, nil);
01150               return false;
01151        }
01152                      
01153        if (FindKeyValue(cfgText, sectionName, keyName, value))
01154        {
01155               long   len = strlen(value);        
01156               OSErr  err;
01157               
01158               SetHandleSize(dest, len + 1);
01159               err = MemError();
01160               if (err != noErr)
01161               {
01162             ErrorHandler(err, nil);
01163                      return false;
01164               }
01165               
01166               HLock(dest);
01167               strcpy(*dest, value);
01168               HUnlock(dest);
01169               bFound = true;
01170        }
01171        if (value)
01172            DisposePtr(value);
01173        return bFound;
01174 }
01175 
01176 #pragma mark -
01177 
01178 Boolean
01179 FindKeyValue(const char *cfg, const char *inSectionName, const char *inKey, char *outValue)
01180 {
01181        char   *sectionName, *section, *key, *cfgPtr[1], *sectionPtr[1];
01182 
01183        *cfgPtr = (char*) cfg;
01184        
01185        sectionName =        (char *) NewPtrClear( kSNameMaxLen );
01186        section =            (char *) NewPtrClear( kSectionMaxLen ); 
01187        key =                (char *) NewPtrClear( kKeyMaxLen );
01188        if (!sectionName || !section || !key)
01189        {
01190         ErrorHandler(eMem, nil);
01191               return false;
01192        }      
01193     
01194        /* find next section   [cfgPtr moved past next section per iteration] */
01195     while(GetNextSection(cfgPtr, sectionName, section))
01196        { 
01197         if (strncmp(sectionName, inSectionName, strlen(inSectionName)) == 0) 
01198               {
01199                      *sectionPtr = section;
01200                      
01201                      /* find next key   [sectionPtr moved past next key per iteration] */
01202             while(GetNextKeyVal(sectionPtr, key, outValue))
01203                      {
01204                             if (*key && strncmp(key, inKey, strlen(inKey)) == 0)
01205                             {
01206                                    if(key) 
01207                         DisposePtr(key);
01208                                    if(sectionName) 
01209                         DisposePtr(sectionName);
01210                                    if(section) 
01211                         DisposePtr(section);
01212                                    return true;
01213                             }
01214                      }
01215               }
01216        }
01217     if(key) 
01218         DisposePtr(key);
01219     if(sectionName) 
01220         DisposePtr(sectionName);
01221     if(section) 
01222         DisposePtr(section);
01223        
01224        return false; 
01225 }
01226 
01227 
01228 Boolean
01229 GetNextSection(char **ioTxt, char *outSectionName, char *outSection)
01230 {
01231        Boolean exists = false;
01232        char *txt, *snbuf, *sbuf;
01233        long cnt;
01234        
01235        txt = *ioTxt;
01236        
01237        while (*txt != START_SECTION)
01238        {
01239               if (*txt == ';') /* comment encountered */
01240               {
01241                      while ((*txt != MAC_EOL) && (*txt != WIN_EOL)) /* ignore rest of line */
01242                             txt++;
01243               }
01244               
01245               if (*txt == MY_EOF)
01246                      return false;
01247               else
01248                      txt++;
01249        }
01250        
01251        if (*txt == START_SECTION) /* section name start */
01252        {
01253               txt++; 
01254               snbuf = outSectionName;
01255               cnt = 0;
01256               while (*txt != END_SECTION) /* section name end */
01257               {
01258                      if ((*txt==MAC_EOL) || (*txt==WIN_EOL)) /* incomplete section name so die */
01259                      {      
01260                             return false;
01261                      }
01262                      
01263                      if( kSNameMaxLen-1 >= cnt++) /* prevent falling of end of outSectionName buffer */
01264                      {
01265                             *snbuf = *txt;
01266                             snbuf++; txt++;
01267                      }
01268                      else
01269                             txt++;
01270               }
01271               *snbuf = MY_EOF;  /* close string */
01272               txt++; /* skip over section name end char ']' */
01273        }
01274               
01275        /* adminstration before section contents encountered */
01276        while( (*txt == MAC_EOL) || (*txt == WIN_EOL) || (*txt == ' ') || (*txt == '\t'))
01277        {
01278               txt++;
01279        }
01280        
01281        sbuf = outSection;
01282        cnt = 0;
01283 find_contents:
01284        while (*txt != START_SECTION && *txt != MY_EOF) /* next section encountered */
01285        {
01286               if( kSectionMaxLen-1 >= cnt++)     /* prevent from falling of end of outSection buffer */                       
01287               {
01288                      *sbuf = *txt;
01289                      sbuf++; txt++;
01290               }
01291               else
01292                      txt++;
01293        }
01294            
01295     /* handle case where '[' is in key or value (i.e., for i18n)*/
01296     if (*txt != MY_EOF)
01297     {
01298         if (*txt == START_SECTION && 
01299             !(txt == *ioTxt || *(txt-1) == MAC_EOL || *(txt-1) == WIN_EOL))
01300         {
01301               if( kSectionMaxLen-1 >= cnt++)     /* prevent from falling of end of outSection buffer */                       
01302               {
01303                      *sbuf = *txt;
01304                      sbuf++; txt++;
01305               }
01306               else
01307                      txt++;
01308             goto find_contents;
01309         }
01310     } 
01311     
01312        *sbuf = MY_EOF;      /* close string */
01313        *ioTxt = txt;        /* move txt ptr to next section */
01314        exists = true;
01315        
01316        return exists;
01317 }
01318 
01319 Boolean
01320 GetNextKeyVal(char **inSection, char *outKey, char *outVal)
01321 {
01322        Boolean exists = false;
01323        char *key, *sbuf, *val;
01324        long cnt;
01325        
01326        sbuf = *inSection;
01327        
01328        /* clear out extra carriage returns above next key */
01329        while( (*sbuf == MAC_EOL) || (*sbuf == WIN_EOL) || (*sbuf == ' ') || (*sbuf == '\t')) 
01330                      sbuf++;
01331 
01332        if (*sbuf == MY_EOF) /* no more keys */
01333               return false;
01334        
01335        if (*sbuf == ';') /* comment encountered */
01336        {
01337               while ((*sbuf != MAC_EOL) && (*sbuf != WIN_EOL)) /*ignore rest of line */
01338                      sbuf++;
01339               sbuf++;
01340        }
01341        
01342        key = outKey;
01343        cnt = 0;
01344        while((*sbuf != MAC_EOL) && (*sbuf != WIN_EOL))
01345        {
01346               if (*sbuf == KV_DELIM)
01347               {
01348                      if (key != nil) /* key not empty */
01349                             exists = true;
01350                      break;
01351               }
01352               
01353               if ( kKeyMaxLen-1 >= cnt++) /* prevent from falling of end of outKey buffer */
01354               {
01355                      *key = *sbuf;
01356                      key++; sbuf++;
01357               }
01358               else
01359                      sbuf++;
01360        }
01361 
01362        *key = MY_EOF; /* close string */
01363        sbuf++;
01364        
01365        if (exists) /* key found so now get value */
01366        {
01367               val = outVal;
01368               cnt = 0;
01369               while((*sbuf != MAC_EOL) && (*sbuf != WIN_EOL))
01370               {
01371                      if ( kValueMaxLen-1 >= cnt++) /* prevent from falling of end of outValue buffer */
01372                      {
01373                             *val = *sbuf;
01374                             val++; sbuf++;
01375                      }
01376                      else
01377                             sbuf++;
01378               }
01379        }
01380        *val = MY_EOF; /* close string */
01381        sbuf++;
01382        
01383        *inSection = sbuf; /* capture current position in section for future GetNextKeyValue() */
01384 
01385        if (*outKey == NULL)
01386               exists = false;
01387               
01388        return exists;
01389 }
01390 
01391 #pragma mark -
01392 
01393 /*
01394  * Makes a copy of the C string, converts the copy to a Pascal string,
01395  * and returns the Pascal string copy
01396  */
01397 unsigned char *CToPascal(char *str)
01398 {
01399        long len;
01400        char* cpy;
01401 
01402        len = strlen(str);
01403        cpy = (char*)NewPtrClear(len+1);
01404        if (!cpy)
01405               return 0;
01406     strncpy(&cpy[1], str, len);
01407     if (len > 255) 
01408         cpy[0] = 255;
01409     else
01410         cpy[0] = len;
01411        return((unsigned char *)cpy);
01412 }
01413 
01414 char *PascalToC(unsigned char *str)
01415 {
01416        register unsigned char *p,*q,*end;
01417        unsigned char * cpy; 
01418        
01419        cpy = (unsigned char*)NewPtrClear( ((long)*str+1) ); 
01420        if (!cpy)
01421               return 0;
01422        strncpy((char*)cpy, (char*) str, (long)*str+1);
01423        end = cpy + *cpy;
01424        q = (p=cpy) + 1;
01425        while (p < end) *p++ = *q++;
01426        *p = '\0';
01427        return((char *)cpy);
01428 }
01429 
01430 void CopyPascalStrToC(ConstStr255Param srcPString, char* dest)
01431 {
01432     BlockMoveData(&srcPString[1], dest, srcPString[0]);
01433     dest[srcPString[0]] = '\0';
01434 }
01435 
01436 /* Get strings from install.ini */
01437 Boolean GetResourcedString(Str255 skey, int nList, int nIndex)
01438 {
01439        if( nList == rInstList && nIndex < instKeysNum + 1 )
01440        {
01441               pstrcpy(skey, gStrings->iKey[nIndex]);
01442               return true;
01443        }
01444        else if( nList == rErrorList && nIndex < instErrsNum + 1 )
01445        {
01446               pstrcpy(skey, gStrings->iErr[nIndex]);
01447               return true;
01448        }
01449        else if( nList == rInstMenuList && nIndex < instMenuNum + 1 )
01450        {
01451               pstrcpy(skey, gStrings->iMenu[nIndex]);
01452               return true;
01453        }
01454        else
01455               return false;
01456 }