1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /****************************************************/
40 /* Private profile library */
42 /* Attempt to write a cross-platform library for */
43 /* dealing with Windows style .INI profiles. */
45 /* For API see pplib.h */
47 /* 11.26.97 - av started */
49 /* Current limitations: */
50 /* - profile must NOT contain space chars */
51 /* - colon indicating comments must be in the */
54 /****************************************************/
58 static BOOL
isCurrentLineCommentedOut(char * pBuf
, char * pPosition
)
62 if((*pPosition
== ';') && ((pPosition
- 1 < pBuf
) || (*(pPosition
- 1) == '\n') || (*(pPosition
- 1) == '\r')))
67 if((*pPosition
== '\n') || (*pPosition
== '\r'))
72 /*******************************************************************/
74 /* Note: For a section header to be found, the [ must be the first */
75 /* character on the line. This prevents the [Options] string in */
76 /* the comments of the Sample.pts script from being found as the */
77 /* top of the Options section. -pollmann */
79 /*******************************************************************/
80 static char * goToSectionBody(char * pBuf
, char * szSection
)
82 if((pBuf
== NULL
) || (szSection
== NULL
))
84 char szSectionString
[256];
85 strcpy(szSectionString
, "\n"); /* Line feed before [ */
86 strcat(szSectionString
, "[");
87 strcat(szSectionString
, szSection
);
88 strcat(szSectionString
, "]");
89 char * p
= strstr(pBuf
, szSectionString
);
91 szSectionString
[0] = '\r'; /* Carriage return before [ */
92 char * p
= strstr(pBuf
, szSectionString
);
96 p
+= strlen(szSectionString
) + 1; // 1 is for new line character
100 static int getSectionLength(char * pBuf
, char * szSection
)
104 char * pSectionStart
= goToSectionBody(pBuf
, szSection
);
106 if(pSectionStart
== NULL
)
109 char * pNextSection
= strstr(pSectionStart
, "[");
111 if(pNextSection
!= NULL
)
112 iRet
= (int)(pNextSection
- pSectionStart
);
114 iRet
= (int)(pBuf
+ strlen(pBuf
) - pSectionStart
);
119 static char * goToKeyBody(char * pSectionStart
, int iSectionLength
, char * szKey
)
121 if((pSectionStart
== NULL
) || (szKey
== NULL
))
123 if((int)strlen(szKey
) >= iSectionLength
)
125 char szKeyString
[256];
126 strcpy(szKeyString
, szKey
);
127 strcat(szKeyString
, "=");
128 char chBackup
= pSectionStart
[iSectionLength
];
129 pSectionStart
[iSectionLength
] = '\0';
130 char * p
= strstr(pSectionStart
, szKeyString
);
133 pSectionStart
[iSectionLength
] = chBackup
;
139 pSectionStart
[iSectionLength
] = chBackup
;
143 pSectionStart
[iSectionLength
] = chBackup
;
144 if(isCurrentLineCommentedOut(pSectionStart
, p
))
150 static int getKeyLength(char * pSectionStart
, int iSectionLength
, char * szKey
)
154 char * pKeyStart
= goToKeyBody(pSectionStart
, iSectionLength
, szKey
);
156 if(pKeyStart
== NULL
)
159 char * pFirstCarriageReturn
= strchr(pKeyStart
, '\r');
160 char * pFirstNewLine
= strchr(pKeyStart
, '\n');
162 if((pFirstCarriageReturn
== NULL
) && (pFirstNewLine
== NULL
))
163 return iSectionLength
;
167 if((pFirstCarriageReturn
!= NULL
) && (pFirstNewLine
!= NULL
))
168 p
= (pFirstCarriageReturn
< pFirstNewLine
) ? pFirstCarriageReturn
: pFirstNewLine
;
170 p
= (pFirstCarriageReturn
!= NULL
) ? pFirstCarriageReturn
: pFirstNewLine
;
174 // cut off ending spaces and tabs
175 while((*p
== ' ') || (*p
== '\t'))
180 iRet
= (int)(p
- pKeyStart
);
185 static char * readFileToNewAllocatedZeroTerminatedBuffer(XP_HFILE hFile
)
193 iSize
= 32000; /* HACK for the MAC */
195 #if defined(XP_UNIX) || defined(XP_OS2)
197 fstat(fileno(hFile
), &buf
);
200 iSize
= (int)_filelength(/*_fileno*/(hFile
));
207 char * pBuf
= new char[iSize
+ 1];
211 fseek((FILE *)hFile
, 0L, SEEK_SET
);
212 fread((void *)pBuf
, iSize
, 1, (FILE *)hFile
);
214 // cut off strange stuff at the end and reallocate
215 char * p
= pBuf
+ iSize
- 1;
218 BOOL bNormalChar
= ((int)*p
> 0) && (isprint(*p
) != 0);
219 if(bNormalChar
|| (*p
== '\n') || (*p
== '\r') || (p
< pBuf
))
226 iSize
= strlen(pBuf
);
227 char * pBufFinal
= new char[iSize
+ 1];
228 memcpy((void *)pBufFinal
, (void *)pBuf
, iSize
);
229 pBufFinal
[iSize
] = '\0';
234 DWORD
PP_GetString(char * szSection
, char * szKey
, char * szDefault
, char * szString
, DWORD dwSize
, XP_HFILE hFile
)
237 char * pSectionStart
= NULL
;
238 int iSectionLength
= 0;
241 pBuf
= readFileToNewAllocatedZeroTerminatedBuffer(hFile
);
246 iSize
= strlen(pBuf
);
249 // first consider two special cases: szSection = NULL and szKey = NULL
251 if(szSection
== NULL
) // find all sections and return
253 char * pNextSection
= NULL
;
254 char * pSource
= pBuf
;
255 char * pDest
= szString
;
260 pSource
= strstr(pSource
, "[");
264 pNextSection
= pSource
+ 1;
265 char * pEnd
= strstr(pSource
, "]");
266 int iLength
= pEnd
- pNextSection
;
268 if(!isCurrentLineCommentedOut(pBuf
, pSource
))
270 if(iBytes
+ iLength
+ 2 < (int)dwSize
)
271 memcpy((void *)pDest
, (void *)pNextSection
, iLength
);
278 iBytes
+= iLength
+ 1; // for '\0'
282 pSource
+= iLength
+ 2; // for "[" and "]"
286 iBytes
++; // for this '\0'
288 return (DWORD
)iBytes
;
291 pSectionStart
= goToSectionBody(pBuf
, szSection
);
293 if(pSectionStart
== NULL
)
296 iSectionLength
= getSectionLength(pBuf
, szSection
);
298 if(iSectionLength
== 0)
301 if(szKey
== NULL
) // find all keys and return
304 char * pSource
= pSectionStart
- 1; // point to previous new line char
305 char * pDest
= szString
;
309 char * pEqualSign
= strstr(pSource
, "=");
311 if(pEqualSign
> pSectionStart
+ iSectionLength
)
316 char * pLastCarriageReturn
= strrchr(pSource
, '\r');
317 char * pLastNewLine
= strrchr(pSource
, '\n');
319 if((pLastCarriageReturn
== NULL
) && (pLastNewLine
== NULL
))
321 pSource
= pEqualSign
+ 1;
325 char * pKey
= (pLastCarriageReturn
> pLastNewLine
) ? pLastCarriageReturn
: pLastNewLine
;
327 int iLength
= strlen(pKey
);
329 if(!isCurrentLineCommentedOut(pBuf
, pKey
))
331 if(iBytes
+ iLength
+ 2 < (int)dwSize
)
332 memcpy((void *)pDest
, (void *)pKey
, iLength
);
339 iBytes
+= iLength
+ 1; // for '\0'
343 pSource
= pEqualSign
+ 1;
347 iBytes
++; // for this '\0'
349 return (DWORD
)iBytes
;
353 // Now the real thing
356 char * pKeyStart
= goToKeyBody(pSectionStart
, iSectionLength
, szKey
);
357 if(pKeyStart
== NULL
)
359 int iKeyLength
= getKeyLength(pSectionStart
, iSectionLength
, szKey
);
360 int iLength
= (iKeyLength
< (int)dwSize
- 1) ? iKeyLength
: (int)dwSize
- 1;
361 memcpy((void *)szString
, (void *)pKeyStart
, iLength
);
362 szString
[iLength
] = '\0';
364 return (DWORD
)iLength
;
371 if((szDefault
!= NULL
) && (szString
!= NULL
))
372 strcpy(szString
, szDefault
);
373 return (DWORD
)strlen(szString
);
376 static BOOL
replaceBytesInReallocatedBufferAfter(
377 char ** ppBuf
, // address of buffer pointer
378 char * szString
, // string to make a replacement with
379 int iPosition
, // byte after which to insert the string
380 int iBytesToReplace
) // number of bytes to replace
384 char * pBuf
= *ppBuf
;
388 int iNewLength
= strlen(pBuf
) - iBytesToReplace
+ strlen(szString
);
389 char * pBufNew
= new char[iNewLength
+ 1]; // 1 - for zero termination
393 memcpy((void *)pBufNew
, (void *)pBuf
, iPosition
);
394 char * p
= pBufNew
+ iPosition
;
395 memcpy((void *)p
, (void *)szString
, strlen(szString
));
396 p
+= strlen(szString
);
397 memcpy((void *)p
, (void *)(pBuf
+ iPosition
+ iBytesToReplace
), strlen(pBuf
) - iPosition
- iBytesToReplace
);
398 p
+= strlen(pBuf
) - iPosition
- iBytesToReplace
;
405 BOOL
PP_WriteString(char * szSection
, char * szKey
, char * szString
, XP_HFILE hFile
)
407 if((szSection
== NULL
) || (szKey
== NULL
) || (szString
== NULL
) || (hFile
== NULL
))
410 char * pBuf
= readFileToNewAllocatedZeroTerminatedBuffer(hFile
);
415 #if !(defined XP_MAC || defined XP_UNIX || defined XP_OS2)
416 long lOldSize
= (long)strlen(pBuf
);
419 char * pSectionStart
= goToSectionBody(pBuf
, szSection
);
421 // add section if not present
422 if(pSectionStart
== NULL
)
424 char szNewSection
[256];
425 strcpy(szNewSection
, "[");
426 strcat(szNewSection
, szSection
);
427 strcat(szNewSection
, "]");
428 strcat(szNewSection
, "\n");
429 strcat(szNewSection
, "\n");
430 if(!replaceBytesInReallocatedBufferAfter(&pBuf
, szNewSection
, 0, 0))
436 pSectionStart
= goToSectionBody(pBuf
, szSection
);
439 if(pSectionStart
== NULL
)
442 int iSectionLength
= getSectionLength(pBuf
, szSection
);
443 char * pKeyStart
= goToKeyBody(pSectionStart
, iSectionLength
, szKey
);
445 // add key if not present
446 if(pKeyStart
== NULL
)
449 strcpy(szNewKey
, szKey
);
450 strcat(szNewKey
, "=");
451 strcat(szNewKey
, "\n");
452 int iPos
= pSectionStart
- pBuf
;
453 if(!replaceBytesInReallocatedBufferAfter(&pBuf
, szNewKey
, iPos
, 0))
459 pSectionStart
= goToSectionBody(pBuf
, szSection
);
460 iSectionLength
= getSectionLength(pBuf
, szSection
);
461 pKeyStart
= goToKeyBody(pSectionStart
, iSectionLength
, szKey
);
464 if(pKeyStart
== NULL
)
467 int iKeyLength
= getKeyLength(pSectionStart
, iSectionLength
, szKey
);
468 int iPos
= pKeyStart
- pBuf
;
469 if(!replaceBytesInReallocatedBufferAfter(&pBuf
, szString
, iPos
, iKeyLength
))
476 #if (defined XP_MAC || defined XP_UNIX || defined XP_OS2)
480 long lNewSize
= (long)strlen(pBuf
);
481 long lSizeChange
= lNewSize
- lOldSize
;
482 if(lSizeChange
!= 0L)
484 long lOldFileSize
= (long)_filelength(/*_fileno*/(hFile
));
485 long lNewFileSize
= lOldFileSize
+ lSizeChange
;
486 _chsize(/*_fileno*/(hFile
), lNewFileSize
);
489 fseek((FILE *)hFile
, 0L, SEEK_SET
);
492 fwrite(pBuf
, strlen(pBuf
), 1, (FILE *)hFile
);