mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-17 16:44:27 -04:00
[core] add INI file/portable support
* Application will start in portable mode if its name contains a 'p' eg. "rufus_portable.exe" or "prufus.exe" * Closes #264 * Also fix a couple smaller issues
This commit is contained in:
parent
7b0a5abab1
commit
17872dc1de
13 changed files with 369 additions and 79 deletions
181
src/parser.c
181
src/parser.c
|
@ -37,6 +37,7 @@
|
|||
|
||||
static const char space[] = " \t";
|
||||
static const wchar_t wspace[] = L" \t";
|
||||
static const char* conversion_error = "Could not convert '%s' to UTF-16";
|
||||
|
||||
const struct {char c; int flag;} attr_parse[] = {
|
||||
{ 'r', LOC_RIGHT_TO_LEFT },
|
||||
|
@ -215,7 +216,7 @@ FILE* open_loc_file(const char* filename)
|
|||
}
|
||||
wfilename = utf8_to_wchar(filename);
|
||||
if (wfilename == NULL) {
|
||||
uprintf("localization: could not convert '%s' filename to UTF-16\n", filename);
|
||||
uprintf(conversion_error, filename);
|
||||
goto out;
|
||||
}
|
||||
fd = _wfopen(wfilename, L"rb");
|
||||
|
@ -638,12 +639,12 @@ char* get_token_data_file(const char* token, const char* filename)
|
|||
|
||||
wfilename = utf8_to_wchar(filename);
|
||||
if (wfilename == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", filename);
|
||||
uprintf(conversion_error, filename);
|
||||
goto out;
|
||||
}
|
||||
wtoken = utf8_to_wchar(token);
|
||||
if (wfilename == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", token);
|
||||
uprintf(conversion_error, token);
|
||||
goto out;
|
||||
}
|
||||
fd = _wfopen(wfilename, L"r, ccs=UNICODE");
|
||||
|
@ -667,6 +668,159 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* replace or add 'data' for token 'token' in config file 'filename'
|
||||
*/
|
||||
char* set_token_data_file(const char* token, const char* data, const char* filename)
|
||||
{
|
||||
const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" };
|
||||
wchar_t *wtoken = NULL, *wfilename = NULL, *wtmpname = NULL, *wdata = NULL, bom = 0;
|
||||
wchar_t buf[1024];
|
||||
FILE *fd_in = NULL, *fd_out = NULL;
|
||||
size_t i, size;
|
||||
int mode = 0;
|
||||
char *ret = NULL, tmp[2];
|
||||
|
||||
if ((filename == NULL) || (token == NULL) || (data == NULL))
|
||||
return NULL;
|
||||
if ((filename[0] == 0) || (token[0] == 0) || (data[0] == 0))
|
||||
return NULL;
|
||||
|
||||
wfilename = utf8_to_wchar(filename);
|
||||
if (wfilename == NULL) {
|
||||
uprintf(conversion_error, filename);
|
||||
goto out;
|
||||
}
|
||||
wtoken = utf8_to_wchar(token);
|
||||
if (wfilename == NULL) {
|
||||
uprintf(conversion_error, token);
|
||||
goto out;
|
||||
}
|
||||
wdata = utf8_to_wchar(data);
|
||||
if (wdata == NULL) {
|
||||
uprintf(conversion_error, data);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd_in = _wfopen(wfilename, L"r, ccs=UNICODE");
|
||||
if (fd_in == NULL) {
|
||||
uprintf("Could not open file '%s'\n", filename);
|
||||
goto out;
|
||||
}
|
||||
// Check the input file's BOM and create an output file with the same
|
||||
if (fread(&bom, sizeof(bom), 1, fd_in) == 1) {
|
||||
switch(bom) {
|
||||
case 0xFEFF:
|
||||
mode = 2; // UTF-16 (LE)
|
||||
break;
|
||||
case 0xBBEF: // Yeah, the UTF-8 BOM is really 0xEF,0xBB,0xBF, but
|
||||
mode = 1; // find me a non UTF-8 file that actually begins with "ï»"
|
||||
break;
|
||||
default:
|
||||
mode = 0; // ANSI
|
||||
break;
|
||||
}
|
||||
fseek(fd_in, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
wtmpname = (wchar_t*)calloc(wcslen(wfilename)+2, sizeof(wchar_t));
|
||||
if (wtmpname == NULL) {
|
||||
uprintf("Could not allocate space for temporary output name\n");
|
||||
goto out;
|
||||
}
|
||||
wcscpy(wtmpname, wfilename);
|
||||
wtmpname[wcslen(wtmpname)] = '~';
|
||||
|
||||
fd_out = _wfopen(wtmpname, outmode[mode]);
|
||||
if (fd_out == NULL) {
|
||||
uprintf("Could not open temporary output file '%s~'\n", filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Process individual lines. NUL is always appended.
|
||||
while (fgetws(buf, ARRAYSIZE(buf), fd_in) != NULL) {
|
||||
|
||||
i = 0;
|
||||
|
||||
// Skip leading spaces
|
||||
i += wcsspn(&buf[i], wspace);
|
||||
|
||||
// Ignore comments or section headers
|
||||
if ((buf[i] == ';') || (buf[i] == '[')) {
|
||||
fputws(buf, fd_out);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Our token should begin a line
|
||||
if (_wcsnicmp(&buf[i], wtoken, wcslen(wtoken)) != 0) {
|
||||
fputws(buf, fd_out);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Token was found, move past token
|
||||
i += wcslen(wtoken);
|
||||
|
||||
// Skip spaces
|
||||
i += wcsspn(&buf[i], wspace);
|
||||
|
||||
// Check for an equal sign
|
||||
if (buf[i] != L'=') {
|
||||
fputws(buf, fd_out);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
|
||||
// Skip spaces after equal sign
|
||||
i += wcsspn(&buf[i], wspace);
|
||||
|
||||
// Output the token
|
||||
buf[i] = 0;
|
||||
fputws(buf, fd_out);
|
||||
|
||||
// Now output the new data
|
||||
fwprintf(fd_out, L"%s\n", wdata);
|
||||
ret = (char*)data;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
// Didn't find an existing token => append it
|
||||
fwprintf(fd_out, L"%s = %s\n", wtoken, wdata);
|
||||
ret = (char*)data;
|
||||
}
|
||||
|
||||
out:
|
||||
if (fd_in != NULL) fclose(fd_in);
|
||||
if (fd_out != NULL) fclose(fd_out);
|
||||
|
||||
// If an insertion occurred, delete existing file and use the new one
|
||||
if (ret != NULL) {
|
||||
// We're in Windows text mode => Remove CRs if requested
|
||||
fd_in = _wfopen(wtmpname, L"rb");
|
||||
fd_out = _wfopen(wfilename, L"wb");
|
||||
// Don't check fds
|
||||
if ((fd_in != NULL) && (fd_out != NULL)) {
|
||||
size = (mode==2)?2:1;
|
||||
while(fread(tmp, size, 1, fd_in) == 1)
|
||||
fwrite(tmp, size, 1, fd_out);
|
||||
fclose(fd_in);
|
||||
fclose(fd_out);
|
||||
} else {
|
||||
uprintf("Could not write '%s' - original file has been left unmodified\n", filename);
|
||||
ret = NULL;
|
||||
if (fd_in != NULL) fclose(fd_in);
|
||||
if (fd_out != NULL) fclose(fd_out);
|
||||
}
|
||||
}
|
||||
if (wtmpname != NULL)
|
||||
_wunlink(wtmpname);
|
||||
safe_free(wfilename);
|
||||
safe_free(wtmpname);
|
||||
safe_free(wtoken);
|
||||
safe_free(wdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a buffer (ANSI or UTF-8) and return the data for the 'n'th occurrence of 'token'
|
||||
* The returned string is UTF-8 and MUST be freed by the caller
|
||||
|
@ -806,17 +960,17 @@ char* insert_section_data(const char* filename, const char* section, const char*
|
|||
|
||||
wfilename = utf8_to_wchar(filename);
|
||||
if (wfilename == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", filename);
|
||||
uprintf(conversion_error, filename);
|
||||
goto out;
|
||||
}
|
||||
wsection = utf8_to_wchar(section);
|
||||
if (wfilename == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", section);
|
||||
uprintf(conversion_error, section);
|
||||
goto out;
|
||||
}
|
||||
wdata = utf8_to_wchar(data);
|
||||
if (wdata == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", data);
|
||||
uprintf(conversion_error, data);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -842,9 +996,8 @@ char* insert_section_data(const char* filename, const char* section, const char*
|
|||
break;
|
||||
}
|
||||
fseek(fd_in, 0, SEEK_SET);
|
||||
duprintf("'%s' was detected as %s\n", filename,
|
||||
(mode==0)?"ANSI/UTF8 (no BOM)":((mode==1)?"UTF8 (with BOM)":"UTF16 (with BOM"));
|
||||
|
||||
// duprintf("'%s' was detected as %s\n", filename,
|
||||
// (mode==0)?"ANSI/UTF8 (no BOM)":((mode==1)?"UTF8 (with BOM)":"UTF16 (with BOM"));
|
||||
|
||||
wtmpname = (wchar_t*)calloc(wcslen(wfilename)+2, sizeof(wchar_t));
|
||||
if (wtmpname == NULL) {
|
||||
|
@ -941,22 +1094,22 @@ char* replace_in_token_data(const char* filename, const char* token, const char*
|
|||
|
||||
wfilename = utf8_to_wchar(filename);
|
||||
if (wfilename == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", filename);
|
||||
uprintf(conversion_error, filename);
|
||||
goto out;
|
||||
}
|
||||
wtoken = utf8_to_wchar(token);
|
||||
if (wfilename == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", token);
|
||||
uprintf(conversion_error, token);
|
||||
goto out;
|
||||
}
|
||||
wsrc = utf8_to_wchar(src);
|
||||
if (wsrc == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", src);
|
||||
uprintf(conversion_error, src);
|
||||
goto out;
|
||||
}
|
||||
wrep = utf8_to_wchar(rep);
|
||||
if (wsrc == NULL) {
|
||||
uprintf("Could not convert '%s' to UTF-16\n", rep);
|
||||
uprintf(conversion_error, rep);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1015,7 +1168,7 @@ char* replace_in_token_data(const char* filename, const char* token, const char*
|
|||
}
|
||||
|
||||
// Token was found, move past token
|
||||
i += strlen(token);
|
||||
i += wcslen(wtoken);
|
||||
|
||||
// Skip spaces
|
||||
i += wcsspn(&buf[i], wspace);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue