Back to index

lightning-sunbird  0.9+nobinonly
pplib.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /****************************************************/
00039 /*                                                  */
00040 /* Private profile library                          */
00041 /*                                                  */
00042 /* Attempt to write a cross-platform library for    */
00043 /* dealing with Windows style .INI profiles.        */
00044 /*                                                  */
00045 /* For API see pplib.h                              */
00046 /*                                                  */
00047 /* 11.26.97 - av started                            */
00048 /*                                                  */
00049 /* Current limitations:                             */
00050 /*   - profile must NOT contain space chars         */
00051 /*   - colon indicating comments must be in the     */
00052 /*     first position                               */
00053 /*                                                  */
00054 /****************************************************/
00055 
00056 #include "xp.h"
00057 
00058 static BOOL isCurrentLineCommentedOut(char * pBuf, char * pPosition)
00059 {
00060   for(;;)
00061   {
00062     if((*pPosition == ';') && ((pPosition - 1 < pBuf) || (*(pPosition - 1) == '\n') || (*(pPosition - 1) == '\r')))
00063       return TRUE;
00064     pPosition--;
00065     if(pPosition < pBuf)
00066       return FALSE;
00067     if((*pPosition == '\n') || (*pPosition == '\r'))
00068       return FALSE;
00069   }
00070 }
00071 
00072 /*******************************************************************/
00073 /*                                                                 */
00074 /* Note: For a section header to be found, the [ must be the first */
00075 /* character on the line.  This prevents the [Options] string in   */
00076 /* the comments of the Sample.pts script from being found as the   */
00077 /* top of the Options section.          -pollmann                  */
00078 /*                                                                 */
00079 /*******************************************************************/
00080 static char * goToSectionBody(char * pBuf, char * szSection)
00081 {
00082   if((pBuf == NULL) || (szSection == NULL))
00083     return NULL;
00084   char szSectionString[256];
00085   strcpy(szSectionString, "\n");   /* Line feed before [ */
00086   strcat(szSectionString, "[");
00087   strcat(szSectionString, szSection);
00088   strcat(szSectionString, "]");
00089   char * p = strstr(pBuf, szSectionString);
00090   if(p == NULL) {
00091     szSectionString[0] = '\r';     /* Carriage return before [ */
00092     char * p = strstr(pBuf, szSectionString);
00093     if(p == NULL)
00094       return NULL;
00095   }
00096   p += strlen(szSectionString) + 1; // 1 is for new line character
00097   return p;
00098 }
00099 
00100 static int getSectionLength(char * pBuf, char * szSection)
00101 {
00102   int iRet = 0;
00103 
00104   char * pSectionStart = goToSectionBody(pBuf, szSection);
00105 
00106   if(pSectionStart == NULL)
00107     return 0;
00108 
00109   char * pNextSection = strstr(pSectionStart, "[");
00110 
00111   if(pNextSection != NULL)
00112     iRet = (int)(pNextSection - pSectionStart);
00113   else
00114     iRet = (int)(pBuf + strlen(pBuf) - pSectionStart);
00115 
00116   return iRet;
00117 }
00118 
00119 static char * goToKeyBody(char * pSectionStart, int iSectionLength, char * szKey)
00120 {
00121   if((pSectionStart == NULL) || (szKey == NULL))
00122     return NULL;
00123   if((int)strlen(szKey) >= iSectionLength)
00124     return NULL;
00125   char szKeyString[256];
00126   strcpy(szKeyString, szKey);
00127   strcat(szKeyString, "=");
00128   char chBackup = pSectionStart[iSectionLength];
00129   pSectionStart[iSectionLength] = '\0';
00130   char * p = strstr(pSectionStart, szKeyString);
00131   if(p == NULL)
00132   {
00133     pSectionStart[iSectionLength] = chBackup;
00134     return NULL;
00135   }
00136   p = strstr(p, "=");
00137   if(p == NULL)
00138   {
00139     pSectionStart[iSectionLength] = chBackup;
00140     return NULL;
00141   }
00142   p++;
00143   pSectionStart[iSectionLength] = chBackup;
00144   if(isCurrentLineCommentedOut(pSectionStart, p))
00145     return NULL;
00146   else
00147     return p;
00148 }
00149 
00150 static int getKeyLength(char * pSectionStart, int iSectionLength, char * szKey)
00151 {
00152   int iRet = 0;
00153 
00154   char * pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
00155 
00156   if(pKeyStart == NULL)
00157     return 0;
00158 
00159   char * pFirstCarriageReturn = strchr(pKeyStart, '\r');
00160   char * pFirstNewLine = strchr(pKeyStart, '\n');
00161 
00162   if((pFirstCarriageReturn == NULL) && (pFirstNewLine == NULL))
00163     return iSectionLength;
00164 
00165   char * p = NULL;
00166 
00167   if((pFirstCarriageReturn != NULL) && (pFirstNewLine != NULL))
00168     p = (pFirstCarriageReturn < pFirstNewLine) ? pFirstCarriageReturn : pFirstNewLine;
00169   else
00170     p = (pFirstCarriageReturn != NULL) ? pFirstCarriageReturn : pFirstNewLine;
00171 
00172   p--;
00173 
00174   // cut off ending spaces and tabs
00175   while((*p == ' ') || (*p == '\t'))
00176     p--;
00177 
00178   p++;
00179 
00180   iRet = (int)(p - pKeyStart);
00181 
00182   return iRet;
00183 }
00184 
00185 static char * readFileToNewAllocatedZeroTerminatedBuffer(XP_HFILE hFile)
00186 {
00187   if(hFile == NULL)
00188     return NULL;
00189 
00190   int iSize;
00191   
00192 #ifdef XP_MAC
00193   iSize = 32000;  /* HACK for the MAC */
00194 #else  
00195   #if defined(XP_UNIX) || defined(XP_OS2)
00196     struct stat buf;
00197     fstat(fileno(hFile), &buf);
00198     iSize = buf.st_size;
00199   #else
00200     iSize = (int)_filelength(/*_fileno*/(hFile));
00201   #endif
00202 #endif
00203 
00204   if(iSize <= 0)
00205     return NULL;
00206 
00207   char * pBuf = new char[iSize + 1];
00208   if(pBuf == NULL)
00209     return NULL;
00210 
00211   fseek((FILE *)hFile, 0L, SEEK_SET);
00212   fread((void *)pBuf, iSize, 1, (FILE *)hFile);
00213 
00214   // cut off strange stuff at the end and reallocate
00215   char * p = pBuf + iSize - 1;
00216   for(;;)
00217   {
00218     BOOL bNormalChar = ((int)*p > 0) && (isprint(*p) != 0);
00219     if(bNormalChar || (*p == '\n') || (*p == '\r') || (p < pBuf))
00220       break;
00221     p--;
00222   }
00223   p++;
00224   *p = '\0';
00225 
00226   iSize = strlen(pBuf);
00227   char * pBufFinal = new char[iSize + 1];
00228   memcpy((void *)pBufFinal, (void *)pBuf, iSize);
00229   pBufFinal[iSize] = '\0';
00230   delete [] pBuf;
00231   return pBufFinal;
00232 }
00233 
00234 DWORD PP_GetString(char * szSection, char * szKey, char * szDefault, char * szString, DWORD dwSize,  XP_HFILE hFile)
00235 {
00236   char * pBuf = NULL;
00237   char * pSectionStart = NULL;
00238   int iSectionLength = 0;
00239   int iSize = 0;
00240 
00241   pBuf = readFileToNewAllocatedZeroTerminatedBuffer(hFile);
00242 
00243   if(pBuf == NULL)
00244     goto ReturnDefault;
00245 
00246   iSize = strlen(pBuf);
00247 
00248   //
00249   // first consider two special cases: szSection = NULL and szKey = NULL
00250   //
00251   if(szSection == NULL) // find all sections and return
00252   {
00253     char * pNextSection = NULL;
00254     char * pSource = pBuf;
00255     char * pDest = szString;
00256     int iBytes = 0;
00257 
00258     for(;;)
00259     {
00260       pSource = strstr(pSource, "[");
00261       if(pSource == NULL)
00262         break;
00263 
00264       pNextSection = pSource + 1;
00265       char * pEnd = strstr(pSource, "]");
00266       int iLength = pEnd - pNextSection;
00267 
00268       if(!isCurrentLineCommentedOut(pBuf, pSource))
00269       {
00270         if(iBytes + iLength + 2 < (int)dwSize)
00271           memcpy((void *)pDest, (void *)pNextSection, iLength);
00272         else
00273           break;
00274 
00275         pDest += iLength;
00276         *pDest = '\0';
00277         pDest++;
00278         iBytes += iLength + 1;  // for '\0'
00279         if(iBytes >= iSize)
00280           break;
00281       }
00282       pSource += iLength + 2; // for "[" and "]"
00283     }
00284 
00285     *pDest = '\0';
00286     iBytes++; // for this '\0'
00287     delete [] pBuf;
00288     return (DWORD)iBytes;
00289   }
00290 
00291   pSectionStart = goToSectionBody(pBuf, szSection);
00292 
00293   if(pSectionStart == NULL)
00294     goto ReturnDefault;
00295 
00296   iSectionLength = getSectionLength(pBuf, szSection);
00297 
00298   if(iSectionLength == 0)
00299     goto ReturnDefault;
00300 
00301   if(szKey == NULL) // find all keys and return
00302   {
00303     int iBytes = 0;
00304     char * pSource = pSectionStart - 1; // point to previous new line char
00305     char * pDest = szString;
00306 
00307     for(;;)
00308     {
00309       char * pEqualSign = strstr(pSource, "=");
00310 
00311       if(pEqualSign > pSectionStart + iSectionLength)
00312         break;
00313 
00314       *pEqualSign = '\0';
00315 
00316       char * pLastCarriageReturn = strrchr(pSource, '\r');
00317       char * pLastNewLine = strrchr(pSource, '\n');
00318 
00319       if((pLastCarriageReturn == NULL) && (pLastNewLine == NULL))
00320       {
00321         pSource = pEqualSign + 1;
00322         continue;
00323       }
00324 
00325       char * pKey = (pLastCarriageReturn > pLastNewLine) ? pLastCarriageReturn : pLastNewLine;
00326       pKey++;
00327       int iLength = strlen(pKey);
00328 
00329       if(!isCurrentLineCommentedOut(pBuf, pKey))
00330       {
00331         if(iBytes + iLength + 2 < (int)dwSize)
00332           memcpy((void *)pDest, (void *)pKey, iLength);
00333         else
00334           break;
00335 
00336         pDest += iLength;
00337         *pDest = '\0';
00338         pDest++;
00339         iBytes += iLength + 1; // for '\0'
00340         if(iBytes >= iSize)
00341           break;
00342       }
00343       pSource = pEqualSign + 1;
00344     }
00345 
00346     *pDest = '\0';
00347     iBytes++; // for this '\0'
00348     delete [] pBuf;
00349     return (DWORD)iBytes;
00350   }
00351 
00352   //
00353   // Now the real thing
00354   //
00355   {
00356     char * pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
00357     if(pKeyStart == NULL)
00358       goto ReturnDefault;
00359     int iKeyLength = getKeyLength(pSectionStart, iSectionLength, szKey);
00360     int iLength = (iKeyLength < (int)dwSize - 1) ? iKeyLength : (int)dwSize - 1;
00361     memcpy((void *)szString, (void *)pKeyStart, iLength);
00362     szString[iLength] = '\0';
00363     delete [] pBuf;
00364     return (DWORD)iLength;
00365   }
00366 
00367 ReturnDefault:
00368 
00369   if(pBuf != NULL)
00370     delete [] pBuf;
00371   if((szDefault != NULL) && (szString != NULL))
00372     strcpy(szString, szDefault);
00373   return (DWORD)strlen(szString);
00374 }
00375 
00376 static BOOL replaceBytesInReallocatedBufferAfter(
00377                  char ** ppBuf,       // address of buffer pointer
00378                  char * szString,     // string to make a replacement with
00379                  int iPosition,       // byte after which to insert the string
00380                  int iBytesToReplace) // number of bytes to replace
00381 {
00382   if(ppBuf == NULL)
00383     return FALSE;
00384   char * pBuf = *ppBuf;
00385   if(pBuf == NULL)
00386     return FALSE;
00387   
00388   int iNewLength = strlen(pBuf) - iBytesToReplace + strlen(szString);
00389   char * pBufNew = new char[iNewLength + 1]; // 1 - for zero termination
00390   if(pBufNew == NULL)
00391     return FALSE;
00392   if(iPosition > 0)
00393     memcpy((void *)pBufNew, (void *)pBuf, iPosition);
00394   char * p = pBufNew + iPosition;
00395   memcpy((void *)p, (void *)szString, strlen(szString));
00396   p += strlen(szString);
00397   memcpy((void *)p, (void *)(pBuf + iPosition + iBytesToReplace), strlen(pBuf) - iPosition - iBytesToReplace);
00398   p += strlen(pBuf) - iPosition - iBytesToReplace;
00399   *p = '\0';
00400   delete [] pBuf;
00401   *ppBuf = pBufNew;
00402   return TRUE;
00403 }
00404 
00405 BOOL PP_WriteString(char * szSection, char * szKey, char * szString, XP_HFILE hFile)
00406 {
00407   if((szSection == NULL) || (szKey == NULL) || (szString == NULL) || (hFile == NULL))
00408     return FALSE;
00409 
00410   char * pBuf = readFileToNewAllocatedZeroTerminatedBuffer(hFile);
00411 
00412   if(pBuf == NULL)
00413     return FALSE;
00414 
00415 #if !(defined XP_MAC || defined XP_UNIX || defined XP_OS2)
00416   long lOldSize = (long)strlen(pBuf);
00417 #endif
00418 
00419   char * pSectionStart = goToSectionBody(pBuf, szSection);
00420 
00421   // add section if not present
00422   if(pSectionStart == NULL)
00423   {
00424     char szNewSection[256];
00425     strcpy(szNewSection, "[");
00426     strcat(szNewSection, szSection);
00427     strcat(szNewSection, "]");
00428     strcat(szNewSection, "\n");
00429     strcat(szNewSection, "\n");
00430     if(!replaceBytesInReallocatedBufferAfter(&pBuf, szNewSection, 0, 0))
00431     {
00432       if(pBuf != NULL)
00433         delete [] pBuf;
00434       return FALSE;
00435     }
00436     pSectionStart = goToSectionBody(pBuf, szSection);
00437   }
00438 
00439   if(pSectionStart == NULL)
00440     return FALSE;
00441 
00442   int iSectionLength = getSectionLength(pBuf, szSection);
00443   char * pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
00444 
00445   // add key if not present
00446   if(pKeyStart == NULL)
00447   {
00448     char szNewKey[256];
00449     strcpy(szNewKey, szKey);
00450     strcat(szNewKey, "=");
00451     strcat(szNewKey, "\n");
00452     int iPos = pSectionStart - pBuf;
00453     if(!replaceBytesInReallocatedBufferAfter(&pBuf, szNewKey, iPos, 0))
00454     {
00455       if(pBuf != NULL)
00456         delete [] pBuf;
00457       return FALSE;
00458     }
00459     pSectionStart = goToSectionBody(pBuf, szSection);
00460     iSectionLength = getSectionLength(pBuf, szSection);
00461     pKeyStart = goToKeyBody(pSectionStart, iSectionLength, szKey);
00462   }
00463 
00464   if(pKeyStart == NULL)
00465     return FALSE;
00466 
00467   int iKeyLength = getKeyLength(pSectionStart, iSectionLength, szKey);
00468   int iPos = pKeyStart - pBuf;
00469   if(!replaceBytesInReallocatedBufferAfter(&pBuf, szString, iPos, iKeyLength))
00470   {
00471     if(pBuf != NULL)
00472       delete [] pBuf;
00473     return FALSE;
00474   }
00475   
00476 #if (defined XP_MAC || defined XP_UNIX || defined XP_OS2)
00477        rewind(hFile);
00478 #else
00479   // change file size
00480   long lNewSize = (long)strlen(pBuf);
00481   long lSizeChange = lNewSize - lOldSize;
00482   if(lSizeChange != 0L)
00483   {
00484     long lOldFileSize = (long)_filelength(/*_fileno*/(hFile));
00485     long lNewFileSize = lOldFileSize + lSizeChange;
00486     _chsize(/*_fileno*/(hFile), lNewFileSize);
00487   }
00488 
00489   fseek((FILE *)hFile, 0L, SEEK_SET);
00490 #endif
00491 
00492   fwrite(pBuf, strlen(pBuf), 1, (FILE *)hFile);
00493 
00494   delete [] pBuf;
00495 
00496   return TRUE;
00497 }