CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

INI.CPP (73204B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/INI.CPP 1     3/03/97 10:24a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : INI.CPP                                                      *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : September 10, 1993                                           *
     28  *                                                                                             *
     29  *                  Last Update : November 2, 1996 [JLB]                                       *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   INIClass::Clear -- Clears out a section (or all sections) of the INI data.                *
     34  *   INIClass::Entry_Count -- Fetches the number of entries in a specified section.            *
     35  *   INIClass::Find_Entry -- Find specified entry within section.                              *
     36  *   INIClass::Find_Section -- Find the specified section within the INI data.                 *
     37  *   INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified.          *
     38  *   INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name*
     39  *   INIClass::Get_Fixed -- Fetch a fixed point number from the section & entry.               *
     40  *   INIClass::Put_Fixed -- Store a fixed point number to the INI database.                    *
     41  *   INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified.   *
     42  *   INIClass::Get_Int -- Fetch an integer entry from the specified section.                   *
     43  *   INIClass::Get_PKey -- Fetch a key from the ini database.                                  *
     44  *   INIClass::Get_String -- Fetch the value of a particular entry in a specified section.     *
     45  *   INIClass::Get_TextBlock -- Fetch a block of normal text.                                  *
     46  *   INIClass::Get_UUBlock -- Fetch an encoded block from the section specified.               *
     47  *   INIClass::INISection::Find_Entry -- Finds a specified entry and returns pointer to it.    *
     48  *   INIClass::Load -- Load INI data from the file specified.                                  *
     49  *   INIClass::Load -- Load the INI data from the data stream (straw).                         *
     50  *   INIClass::Put_Bool -- Store a boolean value into the INI database.                        *
     51  *   INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format.        *
     52  *   INIClass::Put_Int -- Stores a signed integer into the INI data base.                      *
     53  *   INIClass::Put_PKey -- Stores the key to the INI database.                                 *
     54  *   INIClass::Put_String -- Output a string to the section and entry specified.               *
     55  *   INIClass::Put_TextBlock -- Stores a block of text into an INI section.                    *
     56  *   INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database.         *
     57  *   INIClass::Save -- Save the ini data to the file specified.                                *
     58  *   INIClass::Save -- Saves the INI data to a pipe stream.                                    *
     59  *   INIClass::Section_Count -- Counts the number of sections in the INI data.                 *
     60  *   INIClass::Strip_Comments -- Strips comments of the specified text line.                   *
     61  *   INIClass::~INIClass -- Destructor for INI handler.                                        *
     62  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     63 
     64 #include	<string.h>
     65 #include	<stdlib.h>
     66 #include	<stddef.h>
     67 #include	<stdio.h>
     68 #include	<ctype.h>
     69 #include	"ini.h"
     70 #include	"readline.h"
     71 #include	"xpipe.h"
     72 #include	"b64pipe.h"
     73 #include	"xstraw.h"
     74 #include	"b64straw.h"
     75 
     76 
     77 #ifdef FIXIT_FAST_LOAD
     78 #include	"cstraw.h"
     79 #endif
     80 
     81 
     82 
     83 // Disable the "temporary object used to initialize a non-constant reference" warning.
     84 //#pragma warning 665 9
     85 
     86 
     87 /***********************************************************************************************
     88  * INIClass::~INIClass -- Destructor for INI handler.                                          *
     89  *                                                                                             *
     90  *    This is the destructor for the INI class. It handles deleting all of the allocations     *
     91  *    it might have done.                                                                      *
     92  *                                                                                             *
     93  * INPUT:   none                                                                               *
     94  *                                                                                             *
     95  * OUTPUT:  none                                                                               *
     96  *                                                                                             *
     97  * WARNINGS:   none                                                                            *
     98  *                                                                                             *
     99  * HISTORY:                                                                                    *
    100  *   07/02/1996 JLB : Created.                                                                 *
    101  *=============================================================================================*/
    102 INIClass::~INIClass(void)
    103 {
    104 	Clear();
    105 }
    106 
    107 
    108 /***********************************************************************************************
    109  * INIClass::Clear -- Clears out a section (or all sections) of the INI data.                  *
    110  *                                                                                             *
    111  *    This routine is used to clear out the section specified. If no section is specified,     *
    112  *    then the entire INI data is cleared out. Optionally, this routine can be used to clear   *
    113  *    out just an individual entry in the specified section.                                   *
    114  *                                                                                             *
    115  * INPUT:   section  -- Pointer to the section to clear out [pass NULL to clear all].          *
    116  *                                                                                             *
    117  *          entry    -- Pointer to optional entry specifier. If this parameter is specified,   *
    118  *                      then only this specific entry (if found) will be cleared. Otherwise,   *
    119  *                      the entire section specified will be cleared.                          *
    120  *                                                                                             *
    121  * OUTPUT:  none                                                                               *
    122  *                                                                                             *
    123  * WARNINGS:   none                                                                            *
    124  *                                                                                             *
    125  * HISTORY:                                                                                    *
    126  *   07/02/1996 JLB : Created.                                                                 *
    127  *   08/21/1996 JLB : Optionally clears section too.                                           *
    128  *   11/02/1996 JLB : Updates the index list.                                                  *
    129  *=============================================================================================*/
    130 bool INIClass::Clear(char const * section, char const * entry)
    131 {
    132 	if (section == NULL) {
    133 		SectionList.Delete();
    134 		SectionIndex.Clear();
    135 	} else {
    136 		INISection * secptr = Find_Section(section);
    137 		if (secptr != NULL) {
    138 			if (entry != NULL) {
    139 				INIEntry * entptr = secptr->Find_Entry(entry);
    140 				if (entptr != NULL) {
    141 					/*
    142 					**	Remove the entry from the entry index list.
    143 					*/
    144 					secptr->EntryIndex.Remove_Index(entptr->Index_ID());
    145 
    146 					delete entptr;
    147 				}
    148 			} else {
    149 				/*
    150 				**	Remove this section index from the section index list.
    151 				*/
    152 				SectionIndex.Remove_Index(secptr->Index_ID());
    153 
    154 				delete secptr;
    155 			}
    156 		}
    157 	}
    158 	return(true);
    159 }
    160 
    161 
    162 /***********************************************************************************************
    163  * INIClass::Load -- Load INI data from the file specified.                                    *
    164  *                                                                                             *
    165  *    Use this routine to load the INI class with the data from the specified file.            *
    166  *                                                                                             *
    167  * INPUT:   file  -- Reference to the file that will be used to fill up this INI manager.      *
    168  *                                                                                             *
    169  * OUTPUT:  bool; Was the file loaded successfully?                                            *
    170  *                                                                                             *
    171  * WARNINGS:   This routine allocates memory.                                                  *
    172  *                                                                                             *
    173  * HISTORY:                                                                                    *
    174  *   07/02/1996 JLB : Created.                                                                 *
    175  *=============================================================================================*/
    176 bool INIClass::Load(FileClass & file)
    177 {
    178 	return(Load(FileStraw(file)));
    179 }
    180 
    181 
    182 /***********************************************************************************************
    183  * INIClass::Load -- Load the INI data from the data stream (straw).                           *
    184  *                                                                                             *
    185  *    This will fetch data from the straw and build an INI database from it.                   *
    186  *                                                                                             *
    187  * INPUT:   straw -- The straw that the data will be provided from.                            *
    188  *                                                                                             *
    189  * OUTPUT:  bool; Was the database loaded ok?                                                  *
    190  *                                                                                             *
    191  * WARNINGS:   none                                                                            *
    192  *                                                                                             *
    193  * HISTORY:                                                                                    *
    194  *   07/10/1996 JLB : Created.                                                                 *
    195  *=============================================================================================*/
    196 #ifdef FIXIT_FAST_LOAD
    197 bool INIClass::Load(Straw & ffile)
    198 #else
    199 bool INIClass::Load(Straw & file)
    200 #endif
    201 {
    202 	bool end_of_file = false;
    203 	char buffer[MAX_LINE_LENGTH];
    204 
    205 #ifdef FIXIT_FAST_LOAD
    206 	CacheStraw file;
    207 	file.Get_From(ffile);
    208 #endif
    209 
    210 	/*
    211 	**	Prescan until the first section is found.
    212 	*/
    213 	while (!end_of_file) {
    214 		Read_Line(file, buffer, sizeof(buffer), end_of_file);
    215 		if (end_of_file) return(false);
    216 		if (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;
    217 	}
    218 
    219 	/*
    220 	**	Process a section. The buffer is prefilled with the section name line.
    221 	*/
    222 	while (!end_of_file) {
    223 
    224 		buffer[0] = ' ';
    225 		char * ptr = strchr(buffer, ']');
    226 		if (ptr) *ptr = '\0';
    227 		strtrim(buffer);
    228 		INISection * secptr = new INISection(strdup(buffer));
    229 		if (secptr == NULL) {
    230 			Clear();
    231 			return(false);
    232 		}
    233 
    234 		/*
    235 		**	Read in the entries of this section.
    236 		*/
    237 		while (!end_of_file) {
    238 
    239 			/*
    240 			**	If this line is the start of another section, then bail out
    241 			**	of the entry loop and let the outer section loop take
    242 			**	care of it.
    243 			*/
    244 			int len = Read_Line(file, buffer, sizeof(buffer), end_of_file);
    245 			if (buffer[0] == '[' && strchr(buffer, ']') != NULL) break;
    246 
    247 			/*
    248 			**	Determine if this line is a comment or blank line. Throw it out if it is.
    249 			*/
    250 			Strip_Comments(buffer);
    251 			if (len == 0 || buffer[0] == ';' || buffer[0] == '=') continue;
    252 
    253 			/*
    254 			**	The line isn't an obvious comment. Make sure that there is the "=" character
    255 			**	at an appropriate spot.
    256 			*/
    257 			char * divider = strchr(buffer, '=');
    258 			if (!divider) continue;
    259 
    260 			/*
    261 			**	Split the line into entry and value sections. Be sure to catch the
    262 			**	"=foobar" and "foobar=" cases. These lines are ignored.
    263 			*/
    264 			*divider++ = '\0';
    265 			strtrim(buffer);
    266 			if (!strlen(buffer)) continue;
    267 
    268 			strtrim(divider);
    269 			if (!strlen(divider)) continue;
    270 
    271 			INIEntry * entryptr = new INIEntry(strdup(buffer), strdup(divider));
    272 			if (entryptr == NULL) {
    273 				delete secptr;
    274 				Clear();
    275 				return(false);
    276 			}
    277 
    278 			secptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);
    279 			secptr->EntryList.Add_Tail(entryptr);
    280 		}
    281 
    282 		/*
    283 		**	All the entries for this section have been parsed. If this section is blank, then
    284 		**	don't bother storing it.
    285 		*/
    286 		if (secptr->EntryList.Is_Empty()) {
    287 			delete secptr;
    288 		} else {
    289 			SectionIndex.Add_Index(secptr->Index_ID(), secptr);
    290 			SectionList.Add_Tail(secptr);
    291 		}
    292 	}
    293 	return(true);
    294 }
    295 
    296 
    297 /***********************************************************************************************
    298  * INIClass::Save -- Save the ini data to the file specified.                                  *
    299  *                                                                                             *
    300  *    Use this routine to save the ini data to the file specified. All existing data in the    *
    301  *    file, if it was present, is replaced.                                                    *
    302  *                                                                                             *
    303  * INPUT:   file  -- Reference to the file to write the INI data to.                           *
    304  *                                                                                             *
    305  * OUTPUT:  bool; Was the data written to the file?                                            *
    306  *                                                                                             *
    307  * WARNINGS:   none                                                                            *
    308  *                                                                                             *
    309  * HISTORY:                                                                                    *
    310  *   07/02/1996 JLB : Created.                                                                 *
    311  *=============================================================================================*/
    312 int INIClass::Save(FileClass & file) const
    313 {
    314 	return(Save(FilePipe(file)));
    315 }
    316 
    317 
    318 /***********************************************************************************************
    319  * INIClass::Save -- Saves the INI data to a pipe stream.                                      *
    320  *                                                                                             *
    321  *    This routine will output the data of the INI file to a pipe stream.                      *
    322  *                                                                                             *
    323  * INPUT:   pipe  -- Reference to the pipe stream to pump the INI image to.                    *
    324  *                                                                                             *
    325  * OUTPUT:  Returns with the number of bytes output to the pipe.                               *
    326  *                                                                                             *
    327  * WARNINGS:   none                                                                            *
    328  *                                                                                             *
    329  * HISTORY:                                                                                    *
    330  *   07/02/1996 JLB : Created.                                                                 *
    331  *=============================================================================================*/
    332 int INIClass::Save(Pipe & pipe) const
    333 {
    334 	int total = 0;
    335 
    336 	INISection * secptr = SectionList.First();
    337 	while (secptr && secptr->Is_Valid()) {
    338 
    339 		/*
    340 		**	Output the section identifier.
    341 		*/
    342 		total += pipe.Put("[", 1);
    343 		total += pipe.Put(secptr->Section, strlen(secptr->Section));
    344 		total += pipe.Put("]", 1);
    345 		total += pipe.Put("\r\n", strlen("\r\n"));
    346 
    347 		/*
    348 		**	Output all the entries and values in this section.
    349 		*/
    350 		INIEntry * entryptr = secptr->EntryList.First();
    351 		while (entryptr && entryptr->Is_Valid()) {
    352 			total += pipe.Put(entryptr->Entry, strlen(entryptr->Entry));
    353 			total += pipe.Put("=", 1);
    354 			total += pipe.Put(entryptr->Value, strlen(entryptr->Value));
    355 			total += pipe.Put("\r\n", strlen("\r\n"));
    356 
    357 			entryptr = entryptr->Next();
    358 		}
    359 
    360 		/*
    361 		**	After the last entry in this section, output an extra
    362 		**	blank line for readability purposes.
    363 		*/
    364 		total += pipe.Put("\r\n", strlen("\r\n"));
    365 
    366 		secptr = secptr->Next();
    367 	}
    368 	total += pipe.End();
    369 
    370 	return(total);
    371 }
    372 
    373 
    374 /***********************************************************************************************
    375  * INIClass::Find_Section -- Find the specified section within the INI data.                   *
    376  *                                                                                             *
    377  *    This routine will scan through the INI data looking for the section specified. If the    *
    378  *    section could be found, then a pointer to the section control data is returned.          *
    379  *                                                                                             *
    380  * INPUT:   section  -- The name of the section to search for. Don't enclose the name in       *
    381  *                      brackets. Case is NOT sensitive in the search.                         *
    382  *                                                                                             *
    383  * OUTPUT:  Returns with a pointer to the INI section control structure if the section was     *
    384  *          found. Otherwise, NULL is returned.                                                *
    385  *                                                                                             *
    386  * WARNINGS:   none                                                                            *
    387  *                                                                                             *
    388  * HISTORY:                                                                                    *
    389  *   07/02/1996 JLB : Created.                                                                 *
    390  *   11/02/1996 JLB : Uses index manager.                                                      *
    391  *=============================================================================================*/
    392 INIClass::INISection * INIClass::Find_Section(char const * section) const
    393 {
    394 	if (section != NULL) {
    395 
    396 		long crc = CRCEngine()(section, strlen(section));
    397 
    398 		if (SectionIndex.Is_Present(crc)) {
    399 			return(SectionIndex.Fetch_Index(crc));
    400 		}
    401 	}
    402 	return(NULL);
    403 }
    404 
    405 
    406 /***********************************************************************************************
    407  * INIClass::Section_Count -- Counts the number of sections in the INI data.                   *
    408  *                                                                                             *
    409  *    This routine will scan through all the sections in the INI data and return a count       *
    410  *    of the number it found.                                                                  *
    411  *                                                                                             *
    412  * INPUT:   none                                                                               *
    413  *                                                                                             *
    414  * OUTPUT:  Returns with the number of sections recorded in the INI data.                      *
    415  *                                                                                             *
    416  * WARNINGS:   none                                                                            *
    417  *                                                                                             *
    418  * HISTORY:                                                                                    *
    419  *   07/02/1996 JLB : Created.                                                                 *
    420  *   11/02/1996 JLB : Uses index manager.                                                      *
    421  *=============================================================================================*/
    422 int INIClass::Section_Count(void) const
    423 {
    424 	return(SectionIndex.Count());
    425 }
    426 
    427 
    428 /***********************************************************************************************
    429  * INIClass::Entry_Count -- Fetches the number of entries in a specified section.              *
    430  *                                                                                             *
    431  *    This routine will examine the section specified and return with the number of entries    *
    432  *    associated with it.                                                                      *
    433  *                                                                                             *
    434  * INPUT:   section  -- Pointer to the section that will be examined.                          *
    435  *                                                                                             *
    436  * OUTPUT:  Returns with the number entries in the specified section.                          *
    437  *                                                                                             *
    438  * WARNINGS:   none                                                                            *
    439  *                                                                                             *
    440  * HISTORY:                                                                                    *
    441  *   07/02/1996 JLB : Created.                                                                 *
    442  *   11/02/1996 JLB : Uses index manager.                                                      *
    443  *=============================================================================================*/
    444 int INIClass::Entry_Count(char const * section) const
    445 {
    446 	INISection * secptr = Find_Section(section);
    447 	if (secptr != NULL) {
    448 		return(secptr->EntryIndex.Count());
    449 	}
    450 	return(0);
    451 }
    452 
    453 
    454 /***********************************************************************************************
    455  * INIClass::Find_Entry -- Find specified entry within section.                                *
    456  *                                                                                             *
    457  *    This support routine will find the specified entry in the specified section. If found,   *
    458  *    a pointer to the entry control structure will be returned.                               *
    459  *                                                                                             *
    460  * INPUT:   section  -- Pointer to the section name to search under.                           *
    461  *                                                                                             *
    462  *          entry    -- Pointer to the entry name to search for.                               *
    463  *                                                                                             *
    464  * OUTPUT:  If the entry was found, then a pointer to the entry control structure will be      *
    465  *          returned. Otherwise, NULL will be returned.                                        *
    466  *                                                                                             *
    467  * WARNINGS:   none                                                                            *
    468  *                                                                                             *
    469  * HISTORY:                                                                                    *
    470  *   07/02/1996 JLB : Created.                                                                 *
    471  *=============================================================================================*/
    472 INIClass::INIEntry * INIClass::Find_Entry(char const * section, char const * entry) const
    473 {
    474 	INISection * secptr = Find_Section(section);
    475 	if (secptr != NULL) {
    476 		return(secptr->Find_Entry(entry));
    477 	}
    478 	return(NULL);
    479 }
    480 
    481 
    482 /***********************************************************************************************
    483  * INIClass::Get_Entry -- Get the entry identifier name given ordinal number and section name. *
    484  *                                                                                             *
    485  *    This will return the identifier name for the entry under the section specified. The      *
    486  *    ordinal number specified is used to determine which entry to retrieve. The entry         *
    487  *    identifier is the text that appears to the left of the "=" character.                    *
    488  *                                                                                             *
    489  * INPUT:   section  -- The section to use.                                                    *
    490  *                                                                                             *
    491  *          index    -- The ordinal number to use when fetching an entry name.                 *
    492  *                                                                                             *
    493  * OUTPUT:  Returns with a pointer to the entry name.                                          *
    494  *                                                                                             *
    495  * WARNINGS:   none                                                                            *
    496  *                                                                                             *
    497  * HISTORY:                                                                                    *
    498  *   07/02/1996 JLB : Created.                                                                 *
    499  *=============================================================================================*/
    500 char const * INIClass::Get_Entry(char const * section, int index) const
    501 {
    502 	INISection * secptr = Find_Section(section);
    503 
    504 	if (secptr != NULL && index < secptr->EntryIndex.Count()) {
    505 		INIEntry * entryptr = secptr->EntryList.First();
    506 
    507 		while (entryptr != NULL && entryptr->Is_Valid()) {
    508 			if (index == 0) return(entryptr->Entry);
    509 			index--;
    510 			entryptr = entryptr->Next();
    511 		}
    512 	}
    513 	return(NULL);
    514 }
    515 
    516 
    517 /***********************************************************************************************
    518  * INIClass::Put_UUBlock -- Store a binary encoded data block into the INI database.           *
    519  *                                                                                             *
    520  *    Use this routine to store an arbitrary length binary block of data into the INI database.*
    521  *    This routine will covert the data into displayable form and then break it into lines     *
    522  *    that are stored in sequence to the section. A section used to store data in this         *
    523  *    fashion can not be used for any other entries.                                           *
    524  *                                                                                             *
    525  * INPUT:   section  -- The section identifier to place the data into.                         *
    526  *                                                                                             *
    527  *          block    -- Pointer to the block of binary data to store.                          *
    528  *                                                                                             *
    529  *          len      -- The length of the binary data.                                         *
    530  *                                                                                             *
    531  * OUTPUT:  bool; Was the data stored to the database?                                         *
    532  *                                                                                             *
    533  * WARNINGS:   none                                                                            *
    534  *                                                                                             *
    535  * HISTORY:                                                                                    *
    536  *   07/03/1996 JLB : Created.                                                                 *
    537  *=============================================================================================*/
    538 bool INIClass::Put_UUBlock(char const * section, void const * block, int len)
    539 {
    540 	if (section == NULL || block == NULL || len < 1) return(false);
    541 
    542 	Clear(section);
    543 
    544 	BufferStraw straw(block, len);
    545 	Base64Straw bstraw(Base64Straw::ENCODE);
    546 	bstraw.Get_From(straw);
    547 
    548 	int counter = 1;
    549 
    550 	for (;;) {
    551 		char buffer[71];
    552 		char sbuffer[32];
    553 
    554 		int length = bstraw.Get(buffer, sizeof(buffer)-1);
    555 		buffer[length] = '\0';
    556 		if (length == 0) break;
    557 
    558 		sprintf(sbuffer, "%d", counter);
    559 		Put_String(section, sbuffer, buffer);
    560 		counter++;
    561 	}
    562 	return(true);
    563 }
    564 
    565 
    566 /***********************************************************************************************
    567  * INIClass::Get_UUBlock -- Fetch an encoded block from the section specified.                 *
    568  *                                                                                             *
    569  *    This routine will take all the entries in the specified section and decompose them into  *
    570  *    a binary block of data that will be stored into the buffer specified. By using this      *
    571  *    routine [and the Put_UUBLock counterpart], arbitrary blocks of binary data may be        *
    572  *    stored in the INI file. A section processed by this routine can contain no other         *
    573  *    entries than those put there by a previous call to Put_UUBlock.                          *
    574  *                                                                                             *
    575  * INPUT:   section  -- The section name to process.                                           *
    576  *                                                                                             *
    577  *          block    -- Pointer to the buffer that will hold the retrieved data.               *
    578  *                                                                                             *
    579  *          len      -- The length of the buffer. The retrieved data will not fill past this   *
    580  *                      limit.                                                                 *
    581  *                                                                                             *
    582  * OUTPUT:  Returns with the number of bytes decoded into the buffer specified.                *
    583  *                                                                                             *
    584  * WARNINGS:   If the number of bytes retrieved exactly matches the length of the buffer       *
    585  *             specified, then you might have a condition of buffer "overflow".                *
    586  *                                                                                             *
    587  * HISTORY:                                                                                    *
    588  *   07/02/1996 JLB : Created.                                                                 *
    589  *=============================================================================================*/
    590 int INIClass::Get_UUBlock(char const * section, void * block, int len) const
    591 {
    592 	if (section == NULL) return(0);
    593 
    594 	Base64Pipe b64pipe(Base64Pipe::DECODE);
    595 	BufferPipe bpipe(block, len);
    596 
    597 	b64pipe.Put_To(&bpipe);
    598 
    599 	int total = 0;
    600 	int counter = Entry_Count(section);
    601 	for (int index = 0; index < counter; index++) {
    602 		char buffer[128];
    603 
    604 		int length = Get_String(section, Get_Entry(section, index), "=", buffer, sizeof(buffer));
    605 		int outcount = b64pipe.Put(buffer, length);
    606 		total += outcount;
    607 	}
    608 	total += b64pipe.End();
    609 	return(total);
    610 }
    611 
    612 
    613 /***********************************************************************************************
    614  * INIClass::Put_TextBlock -- Stores a block of text into an INI section.                      *
    615  *                                                                                             *
    616  *    This routine will take an arbitrarily long block of text and store it into the INI       *
    617  *    database. The text is broken up into lines and each line is then stored as a numbered    *
    618  *    entry in the specified section. A section used to store text in this way can not be used *
    619  *    to hold any other entries. The text is presumed to contain space characters scattered    *
    620  *    throughout it and that one space between words and sentences is natural.                 *
    621  *                                                                                             *
    622  * INPUT:   section  -- The section to place the text block into.                              *
    623  *                                                                                             *
    624  *          text     -- Pointer to a null terminated text string that holds the block of       *
    625  *                      text. The length can be arbitrary.                                     *
    626  *                                                                                             *
    627  * OUTPUT:  bool; Was the text block placed into the database?                                 *
    628  *                                                                                             *
    629  * WARNINGS:   none                                                                            *
    630  *                                                                                             *
    631  * HISTORY:                                                                                    *
    632  *   07/03/1996 JLB : Created.                                                                 *
    633  *=============================================================================================*/
    634 bool INIClass::Put_TextBlock(char const * section, char const * text)
    635 {
    636 	if (section == NULL) return(false);
    637 
    638 	Clear(section);
    639 
    640 	int index = 1;
    641 	while (text != NULL && *text != NULL) {
    642 
    643 		char buffer[128];
    644 
    645 		strncpy(buffer, text, 75);
    646 		buffer[75] = '\0';
    647 
    648 		char b[32];
    649 		sprintf(b, "%d", index);
    650 
    651 		/*
    652 		**	Scan backward looking for a good break position.
    653 		*/
    654 		int count = strlen(buffer);
    655 		if (count > 0) {
    656 			if (count >= 75) {
    657 				while (count) {
    658 					char c = buffer[count];
    659 
    660 					if (isspace(c)) break;
    661 					count--;
    662 				}
    663 
    664 				if (count == 0) {
    665 					break;
    666 				} else {
    667 					buffer[count] = '\0';
    668 				}
    669 			}
    670 
    671 			strtrim(buffer);
    672 			Put_String(section, b, buffer);
    673 			index++;
    674 			text = ((char  *)text) + count;
    675 		} else {
    676 			break;
    677 		}
    678 	}
    679 	return(true);
    680 }
    681 
    682 
    683 /***********************************************************************************************
    684  * INIClass::Get_TextBlock -- Fetch a block of normal text.                                    *
    685  *                                                                                             *
    686  *    This will take all entries in the specified section and format them into a block of      *
    687  *    normalized text. That is, text with single spaces between each concatenated line. All    *
    688  *    entries in the specified section are processed by this routine. Use Put_TextBlock to     *
    689  *    build the entries in the section.                                                        *
    690  *                                                                                             *
    691  * INPUT:   section  -- The section name to process.                                           *
    692  *                                                                                             *
    693  *          buffer   -- Pointer to the buffer that will hold the complete text.                *
    694  *                                                                                             *
    695  *          len      -- The length of the buffer specified. The text will, at most, fill this  *
    696  *                      buffer with the last character being forced to null.                   *
    697  *                                                                                             *
    698  * OUTPUT:  Returns with the number of characters placed into the buffer. The trailing null    *
    699  *          is not counted.                                                                    *
    700  *                                                                                             *
    701  * WARNINGS:   none                                                                            *
    702  *                                                                                             *
    703  * HISTORY:                                                                                    *
    704  *   07/02/1996 JLB : Created.                                                                 *
    705  *=============================================================================================*/
    706 int INIClass::Get_TextBlock(char const * section, char * buffer, int len) const
    707 {
    708 	if (len <= 0) return(0);
    709 
    710 	buffer[0] = '\0';
    711 	if (len <= 1) return(0);
    712 
    713 	int elen = Entry_Count(section);
    714 	int total = 0;
    715 	for (int index = 0; index < elen; index++) {
    716 
    717 		/*
    718 		**	Add spacers between lines of fetched text.
    719 		*/
    720 		if (index > 0) {
    721 			*buffer++ = ' ';
    722 			len--;
    723 			total++;
    724 		}
    725 
    726 		Get_String(section, Get_Entry(section, index), "", buffer, len);
    727 
    728 		int partial = strlen(buffer);
    729 		total += partial;
    730 		buffer += partial;
    731 		len -= partial;
    732 		if (len <= 1) break;
    733 	}
    734 	return(total);
    735 }
    736 
    737 
    738 /***********************************************************************************************
    739  * INIClass::Put_Int -- Stores a signed integer into the INI data base.                        *
    740  *                                                                                             *
    741  *    Use this routine to store an integer value into the section and entry specified.         *
    742  *                                                                                             *
    743  * INPUT:   section  -- The identifier for the section that the entry will be placed in.       *
    744  *                                                                                             *
    745  *          entry    -- The entry identifier used for the integer number.                      *
    746  *                                                                                             *
    747  *          number   -- The integer number to store in the database.                           *
    748  *                                                                                             *
    749  *          format   -- The format to store the integer. The format is generally only a        *
    750  *                      cosmetic affect. The Get_Int operation will interpret the value the    *
    751  *                      same regardless of what format was used to store the integer.          *
    752  *                                                                                             *
    753  *                      0  : plain decimal digit                                               *
    754  *                      1  : hexadecimal digit (trailing "h")                                  *
    755  *                      2  : hexadecimal digit (leading "$")                                   *
    756  *                                                                                             *
    757  * OUTPUT:  bool; Was the number stored?                                                       *
    758  *                                                                                             *
    759  * WARNINGS:   none                                                                            *
    760  *                                                                                             *
    761  * HISTORY:                                                                                    *
    762  *   07/03/1996 JLB : Created.                                                                 *
    763  *   07/10/1996 JLB : Handles multiple integer formats.                                        *
    764  *=============================================================================================*/
    765 bool INIClass::Put_Int(char const * section, char const * entry, int number, int format)
    766 {
    767 	char buffer[MAX_LINE_LENGTH];
    768 
    769 	switch (format) {
    770 		default:
    771 		case 0:
    772 			sprintf(buffer, "%d", number);
    773 			break;
    774 
    775 		case 1:
    776 			sprintf(buffer, "%Xh", number);
    777 			break;
    778 
    779 		case 2:
    780 			sprintf(buffer, "$%X", number);
    781 			break;
    782 	}
    783 	return(Put_String(section, entry, buffer));
    784 }
    785 
    786 
    787 /***********************************************************************************************
    788  * INIClass::Get_Int -- Fetch an integer entry from the specified section.                     *
    789  *                                                                                             *
    790  *    This routine will fetch an integer value from the entry and section specified. If no     *
    791  *    entry could be found, then the default value will be returned instead.                   *
    792  *                                                                                             *
    793  * INPUT:   section  -- The section name to search under.                                      *
    794  *                                                                                             *
    795  *          entry    -- The entry name to search for.                                          *
    796  *                                                                                             *
    797  *          defvalue -- The default value to use if the specified entry could not be found.    *
    798  *                                                                                             *
    799  * OUTPUT:  Returns with the integer value specified in the INI database or else returns the   *
    800  *          default value.                                                                     *
    801  *                                                                                             *
    802  * WARNINGS:   none                                                                            *
    803  *                                                                                             *
    804  * HISTORY:                                                                                    *
    805  *   07/02/1996 JLB : Created.                                                                 *
    806  *   07/10/1996 JLB : Handles multiple integer formats.                                        *
    807  *=============================================================================================*/
    808 int INIClass::Get_Int(char const * section, char const * entry, int defvalue) const
    809 {
    810 	/*
    811 	**	Verify that the parameters are nominally correct.
    812 	*/
    813 	if (section == NULL || entry == NULL) return(defvalue);
    814 
    815 	INIEntry * entryptr = Find_Entry(section, entry);
    816 	if (entryptr && entryptr->Value != NULL) {
    817 
    818 		if (*entryptr->Value == '$') {
    819 			sscanf(entryptr->Value, "$%x", &defvalue);
    820 		} else {
    821 			if (tolower(entryptr->Value[strlen(entryptr->Value)-1]) == 'h') {
    822 				sscanf(entryptr->Value, "%xh", &defvalue);
    823 			} else {
    824 				defvalue = atoi(entryptr->Value);
    825 			}
    826 		}
    827 	}
    828 	return(defvalue);
    829 }
    830 
    831 
    832 /***********************************************************************************************
    833  * INIClass::Put_Hex -- Store an integer into the INI database, but use a hex format.          *
    834  *                                                                                             *
    835  *    This routine is similar to the Put_Int routine, but the number is stored as a hexadecimal*
    836  *    number.                                                                                  *
    837  *                                                                                             *
    838  * INPUT:   section  -- The identifier for the section that the entry will be placed in.       *
    839  *                                                                                             *
    840  *          entry    -- The entry identifier to tag to the integer number specified.           *
    841  *                                                                                             *
    842  *          number   -- The number to assign the the specified entry and placed in the         *
    843  *                      specified section.                                                     *
    844  *                                                                                             *
    845  * OUTPUT:  bool; Was the number placed into the INI database?                                 *
    846  *                                                                                             *
    847  * WARNINGS:   none                                                                            *
    848  *                                                                                             *
    849  * HISTORY:                                                                                    *
    850  *   07/03/1996 JLB : Created.                                                                 *
    851  *=============================================================================================*/
    852 bool INIClass::Put_Hex(char const * section, char const * entry, int number)
    853 {
    854 	char buffer[MAX_LINE_LENGTH];
    855 
    856 	sprintf(buffer, "%X", number);
    857 	return(Put_String(section, entry, buffer));
    858 }
    859 
    860 
    861 /***********************************************************************************************
    862  * INIClass::Get_Hex -- Fetches integer [hex format] from the section and entry specified.     *
    863  *                                                                                             *
    864  *    This routine will search under the section specified, looking for a matching entry. The  *
    865  *    value is interpreted as a hexadecimal number and then returned. If no entry could be     *
    866  *    found, then the default value is returned instead.                                       *
    867  *                                                                                             *
    868  * INPUT:   section  -- The section identifier to search under.                                *
    869  *                                                                                             *
    870  *          entry    -- The entry identifier to search for.                                    *
    871  *                                                                                             *
    872  *          defvalue -- The default value to use if the entry could not be located.            *
    873  *                                                                                             *
    874  * OUTPUT:  Returns with the integer value from the specified section and entry. If no entry   *
    875  *          could be found, then the default value will be returned instead.                   *
    876  *                                                                                             *
    877  * WARNINGS:   none                                                                            *
    878  *                                                                                             *
    879  * HISTORY:                                                                                    *
    880  *   07/02/1996 JLB : Created.                                                                 *
    881  *=============================================================================================*/
    882 int INIClass::Get_Hex(char const * section, char const * entry, int defvalue) const
    883 {
    884 	/*
    885 	**	Verify that the parameters are nominally correct.
    886 	*/
    887 	if (section == NULL || entry == NULL) return(defvalue);
    888 
    889 	INIEntry * entryptr = Find_Entry(section, entry);
    890 	if (entryptr && entryptr->Value != NULL) {
    891 		sscanf(entryptr->Value, "%x", &defvalue);
    892 	}
    893 	return(defvalue);
    894 }
    895 
    896 
    897 /***********************************************************************************************
    898  * INIClass::Put_String -- Output a string to the section and entry specified.                 *
    899  *                                                                                             *
    900  *    This routine will put an arbitrary string to the section and entry specified. Any        *
    901  *    previous matching entry will be replaced.                                                *
    902  *                                                                                             *
    903  * INPUT:   section  -- The section identifier to place the string under.                      *
    904  *                                                                                             *
    905  *          entry    -- The entry identifier to identify this string [placed under the section]*
    906  *                                                                                             *
    907  *          string   -- Pointer to the string to assign to this entry.                         *
    908  *                                                                                             *
    909  * OUTPUT:  bool; Was the entry assigned without error?                                        *
    910  *                                                                                             *
    911  * WARNINGS:   none                                                                            *
    912  *                                                                                             *
    913  * HISTORY:                                                                                    *
    914  *   07/02/1996 JLB : Created.                                                                 *
    915  *   11/02/1996 JLB : Uses index handler.                                                      *
    916  *=============================================================================================*/
    917 bool INIClass::Put_String(char const * section, char const * entry, char const * string)
    918 {
    919 	if (section == NULL || entry == NULL) return(false);
    920 
    921 	INISection * secptr = Find_Section(section);
    922 
    923 	if (secptr == NULL) {
    924 		secptr = new INISection(strdup(section));
    925 		if (secptr == NULL) return(false);
    926 		SectionList.Add_Tail(secptr);
    927 		SectionIndex.Add_Index(secptr->Index_ID(), secptr);
    928 	}
    929 
    930 	/*
    931 	**	Remove the old entry if found.
    932 	*/
    933 	INIEntry * entryptr = secptr->Find_Entry(entry);
    934 	if (entryptr != NULL) {
    935 		secptr->EntryIndex.Remove_Index(entryptr->Index_ID());
    936 		delete entryptr;
    937 	}
    938 
    939 	/*
    940 	**	Create and add the new entry.
    941 	*/
    942 	if (string != NULL && strlen(string) > 0) {
    943 		entryptr = new INIEntry(strdup(entry), strdup(string));
    944 
    945 		if (entryptr == NULL) {
    946 			return(false);
    947 		}
    948 		secptr->EntryList.Add_Tail(entryptr);
    949 		secptr->EntryIndex.Add_Index(entryptr->Index_ID(), entryptr);
    950 	}
    951 	return(true);
    952 }
    953 
    954 
    955 /***********************************************************************************************
    956  * INIClass::Get_String -- Fetch the value of a particular entry in a specified section.       *
    957  *                                                                                             *
    958  *    This will retrieve the entire text to the right of the "=" character. The text is        *
    959  *    found by finding a matching entry in the section specified. If no matching entry could   *
    960  *    be found, then the default value will be stored in the output string buffer.             *
    961  *                                                                                             *
    962  * INPUT:   section  -- Pointer to the section name to search under.                           *
    963  *                                                                                             *
    964  *          entry    -- The entry identifier to search for.                                    *
    965  *                                                                                             *
    966  *          defvalue -- If no entry could be found, then this text will be returned.           *
    967  *                                                                                             *
    968  *          buffer   -- Output buffer to store the retrieved string into.                      *
    969  *                                                                                             *
    970  *          size     -- The size of the output buffer. The maximum string length that could    *
    971  *                      be retrieved will be one less than this length. This is due to the     *
    972  *                      forced trailing zero added to the end of the string.                   *
    973  *                                                                                             *
    974  * OUTPUT:  Returns with the length of the string retrieved.                                   *
    975  *                                                                                             *
    976  * WARNINGS:   none                                                                            *
    977  *                                                                                             *
    978  * HISTORY:                                                                                    *
    979  *   07/02/1996 JLB : Created.                                                                 *
    980  *=============================================================================================*/
    981 int INIClass::Get_String(char const * section, char const * entry, char const * defvalue, char * buffer, int size) const
    982 {
    983 	/*
    984 	**	Verify that the parameters are nominally legal.
    985 	*/
    986 	if (section == NULL || entry == NULL) {
    987 		if (buffer != NULL && size > 0) {
    988 			buffer[0] = '\0';
    989 		}
    990 		return(0);
    991 	}
    992 
    993 	/*
    994 	**	Fetch the entry string if it is present. If not, then the normal default
    995 	**	value will be used as the entry value.
    996 	*/
    997 	INIEntry * entryptr = Find_Entry(section, entry);
    998 	if (entryptr) {
    999 		if (entryptr->Value) {
   1000 			defvalue = entryptr->Value;
   1001 		}
   1002 	}
   1003 
   1004 	/*
   1005 	**	Fill in the buffer with the entry value and return with the length of the string.
   1006 	*/
   1007 	if (buffer == NULL || !size) {
   1008 		return(0);
   1009 	} else if (defvalue == NULL) {
   1010 		buffer[0] = '\0';
   1011 		return(0);
   1012 	} else if (buffer == defvalue) {
   1013 		return(strlen(buffer));
   1014 	} else {
   1015 		strncpy(buffer, defvalue, size);
   1016 		buffer[size-1] = '\0';
   1017 		strtrim(buffer);
   1018 		return(strlen(buffer));
   1019 	}
   1020 }
   1021 
   1022 
   1023 /***********************************************************************************************
   1024  * INIClass::Put_Bool -- Store a boolean value into the INI database.                          *
   1025  *                                                                                             *
   1026  *    Use this routine to place a boolean value into the INI database. The boolean value will  *
   1027  *    be stored as "yes" or "no".                                                              *
   1028  *                                                                                             *
   1029  * INPUT:   section  -- The section to place the entry and boolean value into.                 *
   1030  *                                                                                             *
   1031  *          entry    -- The entry identifier to tag to the boolean value.                      *
   1032  *                                                                                             *
   1033  *          value    -- The boolean value to place into the database.                          *
   1034  *                                                                                             *
   1035  * OUTPUT:  bool; Was the boolean value placed into the database?                              *
   1036  *                                                                                             *
   1037  * WARNINGS:   none                                                                            *
   1038  *                                                                                             *
   1039  * HISTORY:                                                                                    *
   1040  *   07/03/1996 JLB : Created.                                                                 *
   1041  *=============================================================================================*/
   1042 bool INIClass::Put_Bool(char const * section, char const * entry, bool value)
   1043 {
   1044 	if (value) {
   1045 		return(Put_String(section, entry, "yes"));
   1046 	} else {
   1047 		return(Put_String(section, entry, "no"));
   1048 	}
   1049 }
   1050 
   1051 
   1052 /***********************************************************************************************
   1053  * INIClass::Get_Bool -- Fetch a boolean value for the section and entry specified.            *
   1054  *                                                                                             *
   1055  *    This routine will search under the section specified, looking for a matching entry. If   *
   1056  *    one is found, the value is interpreted as a boolean value and then returned. In the case *
   1057  *    of no matching entry, the default value will be returned instead. The boolean value      *
   1058  *    is interpreted using the standard boolean conventions. e.g., "Yes", "Y", "1", "True",    *
   1059  *    "T" are all consider to be a TRUE boolean value.                                         *
   1060  *                                                                                             *
   1061  * INPUT:   section  -- The section to search under.                                           *
   1062  *                                                                                             *
   1063  *          entry    -- The entry to search for.                                               *
   1064  *                                                                                             *
   1065  *          defvalue -- The default value to use if no matching entry could be located.        *
   1066  *                                                                                             *
   1067  * OUTPUT:  Returns with the boolean value of the specified section and entry. If no match     *
   1068  *          then the default boolean value is returned.                                        *
   1069  *                                                                                             *
   1070  * WARNINGS:   none                                                                            *
   1071  *                                                                                             *
   1072  * HISTORY:                                                                                    *
   1073  *   07/02/1996 JLB : Created.                                                                 *
   1074  *=============================================================================================*/
   1075 bool INIClass::Get_Bool(char const * section, char const * entry, bool defvalue) const
   1076 {
   1077 	/*
   1078 	**	Verify that the parameters are nominally correct.
   1079 	*/
   1080 	if (section == NULL || entry == NULL) return(defvalue);
   1081 
   1082 	INIEntry * entryptr = Find_Entry(section, entry);
   1083 	if (entryptr && entryptr->Value != NULL) {
   1084 		switch (toupper(*entryptr->Value)) {
   1085 			case 'Y':
   1086 			case 'T':
   1087 			case '1':
   1088 				return(true);
   1089 
   1090 			case 'N':
   1091 			case 'F':
   1092 			case '0':
   1093 				return(false);
   1094 		}
   1095 	}
   1096 	return(defvalue);
   1097 }
   1098 
   1099 
   1100 /***********************************************************************************************
   1101  * INIClass::INISection::Find_Entry -- Finds a specified entry and returns pointer to it.      *
   1102  *                                                                                             *
   1103  *    This routine scans the supplied entry for the section specified. This is used for        *
   1104  *    internal database maintenance.                                                           *
   1105  *                                                                                             *
   1106  * INPUT:   entry -- The entry to scan for.                                                    *
   1107  *                                                                                             *
   1108  * OUTPUT:  Returns with a pointer to the entry control structure if the entry was found.      *
   1109  *          Otherwise it returns NULL.                                                         *
   1110  *                                                                                             *
   1111  * WARNINGS:   none                                                                            *
   1112  *                                                                                             *
   1113  * HISTORY:                                                                                    *
   1114  *   07/03/1996 JLB : Created.                                                                 *
   1115  *   11/02/1996 JLB : Uses index handler.                                                      *
   1116  *=============================================================================================*/
   1117 INIClass::INIEntry * INIClass::INISection::Find_Entry(char const * entry) const
   1118 {
   1119 	if (entry != NULL) {
   1120 		int crc = CRCEngine()(entry, strlen(entry));
   1121 		if (EntryIndex.Is_Present(crc)) {
   1122 			return(EntryIndex.Fetch_Index(crc));
   1123 		}
   1124 	}
   1125 	return(NULL);
   1126 }
   1127 
   1128 
   1129 /***********************************************************************************************
   1130  * INIClass::Put_PKey -- Stores the key to the INI database.                                   *
   1131  *                                                                                             *
   1132  *    The key stored to the database will have both the exponent and modulus portions saved.   *
   1133  *    Since the fast key only requires the modulus, it is only necessary to save the slow      *
   1134  *    key to the database. However, storing the slow key stores the information necessary to   *
   1135  *    generate the fast and slow keys. Because public key encryption requires one key to be    *
   1136  *    completely secure, only store the fast key in situations where the INI database will     *
   1137  *    be made public.                                                                          *
   1138  *                                                                                             *
   1139  * INPUT:   key   -- The key to store the INI database.                                        *
   1140  *                                                                                             *
   1141  * OUTPUT:  bool; Was the key stored to the database?                                          *
   1142  *                                                                                             *
   1143  * WARNINGS:   Store the fast key for public INI database availability. Store the slow key if  *
   1144  *             the INI database is secure.                                                     *
   1145  *                                                                                             *
   1146  * HISTORY:                                                                                    *
   1147  *   07/08/1996 JLB : Created.                                                                 *
   1148  *=============================================================================================*/
   1149 bool INIClass::Put_PKey(PKey const & key)
   1150 {
   1151 	char buffer[512];
   1152 
   1153 	int len = key.Encode_Modulus(buffer);
   1154 	Put_UUBlock("PublicKey", buffer, len);
   1155 
   1156 	len = key.Encode_Exponent(buffer);
   1157 	Put_UUBlock("PrivateKey", buffer, len);
   1158 	return(true);
   1159 }
   1160 
   1161 
   1162 /***********************************************************************************************
   1163  * INIClass::Get_PKey -- Fetch a key from the ini database.                                    *
   1164  *                                                                                             *
   1165  *    This routine will fetch the key from the INI database. The key fetched is controlled by  *
   1166  *    the parameter. There are two choices of key -- the fast or slow key.                     *
   1167  *                                                                                             *
   1168  * INPUT:   fast  -- Should the fast key be retrieved? The fast key has the advantage of       *
   1169  *                   requiring only the modulus value.                                         *
   1170  *                                                                                             *
   1171  * OUTPUT:  Returns with the key retrieved.                                                    *
   1172  *                                                                                             *
   1173  * WARNINGS:   none                                                                            *
   1174  *                                                                                             *
   1175  * HISTORY:                                                                                    *
   1176  *   07/08/1996 JLB : Created.                                                                 *
   1177  *=============================================================================================*/
   1178 PKey INIClass::Get_PKey(bool fast) const
   1179 {
   1180 	PKey key;
   1181 	char buffer[512];
   1182 
   1183 	/*
   1184 	**	When retrieving the fast key, the exponent is a known constant. Don't parse the
   1185 	**	exponent from the database.
   1186 	*/
   1187 	if (fast) {
   1188 		BigInt exp = PKey::Fast_Exponent();
   1189 		exp.DEREncode((unsigned char *)buffer);
   1190 		key.Decode_Exponent(buffer);
   1191 	} else {
   1192 		Get_UUBlock("PrivateKey", buffer, sizeof(buffer));
   1193 		key.Decode_Exponent(buffer);
   1194 	}
   1195 
   1196 	Get_UUBlock("PublicKey", buffer, sizeof(buffer));
   1197 	key.Decode_Modulus(buffer);
   1198 
   1199 	return(key);
   1200 }
   1201 
   1202 
   1203 /***********************************************************************************************
   1204  * INIClass::Get_Fixed -- Fetch a fixed point number from the section & entry.                 *
   1205  *                                                                                             *
   1206  *    This routine will examine the section and entry specified and interpret the value        *
   1207  *    as if it were a fixed point number. The format of the fixed point number can be          *
   1208  *    percentage (e.g. 100%) or a floating point number (e.g., 1.7).                           *
   1209  *                                                                                             *
   1210  * INPUT:   section  -- Pointer to the section identifier to look under.                       *
   1211  *                                                                                             *
   1212  *          entry    -- Pointer to the entry identifier to examine.                            *
   1213  *                                                                                             *
   1214  *          defvalue -- If the section and entry could not be found, then this value will      *
   1215  *                      be returned.                                                           *
   1216  *                                                                                             *
   1217  * OUTPUT:  Returns with the fixed point number that occurs at the section and entry           *
   1218  *          specified. If it could not be found, then the default value is returned.           *
   1219  *                                                                                             *
   1220  * WARNINGS:   none                                                                            *
   1221  *                                                                                             *
   1222  * HISTORY:                                                                                    *
   1223  *   07/03/1996 JLB : Created.                                                                 *
   1224  *=============================================================================================*/
   1225 fixed INIClass::Get_Fixed(char const * section, char const * entry, fixed defvalue) const
   1226 {
   1227 	char buffer[128];
   1228 	fixed retval = defvalue;
   1229 
   1230 	if (Get_String(section, entry, "", buffer, sizeof(buffer))) {
   1231 		retval = fixed(buffer);
   1232 	}
   1233 	return(retval);
   1234 }
   1235 
   1236 
   1237 /***********************************************************************************************
   1238  * INIClass::Put_Fixed -- Store a fixed point number to the INI database.                      *
   1239  *                                                                                             *
   1240  *    Use this routine to output a fixed point number to the database. The entry will be       *
   1241  *    placed in the section and entry specified. If there was any existing entry, it will      *
   1242  *    be replaced.                                                                             *
   1243  *                                                                                             *
   1244  * INPUT:   section  -- Pointer to the section identifier.                                     *
   1245  *                                                                                             *
   1246  *          entry    -- Pointer to the entry identifier to use for this value.                 *
   1247  *                                                                                             *
   1248  *          value    -- The value to store in the database.                                    *
   1249  *                                                                                             *
   1250  * OUTPUT:  bool; Was the data stored?                                                         *
   1251  *                                                                                             *
   1252  * WARNINGS:   none                                                                            *
   1253  *                                                                                             *
   1254  * HISTORY:                                                                                    *
   1255  *   07/03/1996 JLB : Created.                                                                 *
   1256  *=============================================================================================*/
   1257 bool INIClass::Put_Fixed(char const * section, char const * entry, fixed value)
   1258 {
   1259 	return(Put_String(section, entry, value.As_ASCII()));
   1260 }
   1261 
   1262 
   1263 /***********************************************************************************************
   1264  * INIClass::Strip_Comments -- Strips comments of the specified text line.                     *
   1265  *                                                                                             *
   1266  *    This routine will scan the string (text line) supplied and if any comment portions are   *
   1267  *    found, they will be trimmed off. Leading and trailing blanks are also removed.           *
   1268  *                                                                                             *
   1269  * INPUT:   buffer   -- Pointer to the null terminate string to be processed.                  *
   1270  *                                                                                             *
   1271  * OUTPUT:  none                                                                               *
   1272  *                                                                                             *
   1273  * WARNINGS:   none                                                                            *
   1274  *                                                                                             *
   1275  * HISTORY:                                                                                    *
   1276  *   07/03/1996 JLB : Created.                                                                 *
   1277  *=============================================================================================*/
   1278 void INIClass::Strip_Comments(char * buffer)
   1279 {
   1280 	if (buffer != NULL) {
   1281 		char * comment = strchr(buffer, ';');
   1282 		if (comment) {
   1283 			*comment = '\0';
   1284 			strtrim(buffer);
   1285 		}
   1286 	}
   1287 }