mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-05-12 11:43:16 -04:00
[bugfix] open_plugin_import fails to import full path WIP
settings_load_config() only reads up to 128 characters while openplugin entries could be upwards of 600 instead use the open_plugins plugin to restore entries add import from .cfg file add save to .cfg file better dupe checking Change-Id: Iec2506aad14a3eb89dcc558b0fbc1f014aad98b5
This commit is contained in:
parent
6cf705886d
commit
6928581bf9
5 changed files with 614 additions and 90 deletions
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
static const uint32_t open_plugin_csum = OPEN_PLUGIN_CHECKSUM;
|
static const uint32_t open_plugin_csum = OPEN_PLUGIN_CHECKSUM;
|
||||||
|
|
||||||
static const int op_entry_sz = sizeof(struct open_plugin_entry_t);
|
#define OP_ENTRY_SZ (sizeof(struct open_plugin_entry_t))
|
||||||
|
|
||||||
static const char* strip_rockbox_root(const char *path)
|
static const char* strip_rockbox_root(const char *path)
|
||||||
{
|
{
|
||||||
|
|
@ -49,7 +49,7 @@ static inline void op_clear_entry(struct open_plugin_entry_t *entry)
|
||||||
{
|
{
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return;
|
return;
|
||||||
memset(entry, 0, op_entry_sz);
|
memset(entry, 0, OP_ENTRY_SZ);
|
||||||
entry->lang_id = OPEN_PLUGIN_LANG_INVALID;
|
entry->lang_id = OPEN_PLUGIN_LANG_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ static int op_find_entry(int fd, struct open_plugin_entry_t *entry,
|
||||||
{
|
{
|
||||||
logf("OP find_entry *Searching* hash: %x lang_id: %d", hash, lang_id);
|
logf("OP find_entry *Searching* hash: %x lang_id: %d", hash, lang_id);
|
||||||
|
|
||||||
while (read(fd, entry, op_entry_sz) == op_entry_sz)
|
while (read(fd, entry, OP_ENTRY_SZ) == OP_ENTRY_SZ)
|
||||||
{
|
{
|
||||||
if (entry->lang_id == lang_id || entry->hash == hash ||
|
if (entry->lang_id == lang_id || entry->hash == hash ||
|
||||||
(lang_id == OPEN_PLUGIN_LANG_IGNOREALL))/* return first entry found */
|
(lang_id == OPEN_PLUGIN_LANG_IGNOREALL))/* return first entry found */
|
||||||
|
|
@ -167,9 +167,9 @@ static int op_update_dat(struct open_plugin_entry_t *entry, bool clear)
|
||||||
lseek(fd, 0-hlc_sz, SEEK_CUR);/* back to the start of record */
|
lseek(fd, 0-hlc_sz, SEEK_CUR);/* back to the start of record */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lseek(fd, op_entry_sz - hlc_sz, SEEK_CUR); /* finish record */
|
lseek(fd, OP_ENTRY_SZ - hlc_sz, SEEK_CUR); /* finish record */
|
||||||
}
|
}
|
||||||
write(fd, entry, op_entry_sz);
|
write(fd, entry, OP_ENTRY_SZ);
|
||||||
close(fd);
|
close(fd);
|
||||||
#else /* Everyone else make a temp file */
|
#else /* Everyone else make a temp file */
|
||||||
logf("OP update *Copying entries* %s", OPEN_PLUGIN_DAT ".tmp");
|
logf("OP update *Copying entries* %s", OPEN_PLUGIN_DAT ".tmp");
|
||||||
|
|
@ -177,18 +177,18 @@ static int op_update_dat(struct open_plugin_entry_t *entry, bool clear)
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return OPEN_PLUGIN_NOT_FOUND;
|
return OPEN_PLUGIN_NOT_FOUND;
|
||||||
write(fd, entry, op_entry_sz);
|
write(fd, entry, OP_ENTRY_SZ);
|
||||||
|
|
||||||
int fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY);
|
int fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY);
|
||||||
if (fd1 >= 0)
|
if (fd1 >= 0)
|
||||||
{
|
{
|
||||||
/* copy non-duplicate entries back from original */
|
/* copy non-duplicate entries back from original */
|
||||||
while (read(fd1, entry, op_entry_sz) == op_entry_sz)
|
while (read(fd1, entry, OP_ENTRY_SZ) == OP_ENTRY_SZ)
|
||||||
{
|
{
|
||||||
if (entry->hash != hash && entry->lang_id != lang_id &&
|
if (entry->hash != hash && entry->lang_id != lang_id &&
|
||||||
op_entry_checksum(entry) > 0)
|
op_entry_checksum(entry) > 0)
|
||||||
{
|
{
|
||||||
write(fd, entry, op_entry_sz);
|
write(fd, entry, OP_ENTRY_SZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(fd1);
|
close(fd1);
|
||||||
|
|
@ -529,41 +529,13 @@ static bool op_entry_read(int fd, int selected_item, off_t data_sz, struct open_
|
||||||
{
|
{
|
||||||
op_clear_entry(op_entry);
|
op_clear_entry(op_entry);
|
||||||
return ((selected_item >= 0) && (fd >= 0) &&
|
return ((selected_item >= 0) && (fd >= 0) &&
|
||||||
(lseek(fd, selected_item * op_entry_sz, SEEK_SET) >= 0) &&
|
(lseek(fd, selected_item * OP_ENTRY_SZ, SEEK_SET) >= 0) &&
|
||||||
(read(fd, op_entry, data_sz) == data_sz) && op_entry_checksum(op_entry) > 0);
|
(read(fd, op_entry, data_sz) == data_sz) && op_entry_checksum(op_entry) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_plugin_import(char *strdat)
|
void open_plugin_import(const char *cfg_file)
|
||||||
{
|
{
|
||||||
/* Note: Destroys strdat */
|
plugin_load(VIEWERS_DIR"/open_plugins.rock", cfg_file);
|
||||||
char *vect[5];
|
|
||||||
/* expected openplugin strdat: "englishid", "name", "path", "param" */
|
|
||||||
|
|
||||||
if (split_string(strdat, ',', vect, 5) == 4)
|
|
||||||
{
|
|
||||||
/* Space for 5 values so we will fail if excess arguments or too few */
|
|
||||||
for(int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
vect[i] = skip_whitespace(vect[i]);
|
|
||||||
int eos = ((int)strlen(vect[i]))-2;
|
|
||||||
/* Failure if string is not quoted */
|
|
||||||
if (vect[i][0] != '"' || eos < 0 || vect[i][eos + 1] != '"')
|
|
||||||
{
|
|
||||||
logf("%s[%d] error: quoted string expected\n", __func__, i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vect[i]++; /* skip first " */
|
|
||||||
vect[i][eos] = '\0'; /* skip other " */
|
|
||||||
}
|
|
||||||
char *key = vect[1];
|
|
||||||
int lang_id = lang_english_to_id(vect[0]);
|
|
||||||
if (lang_id >= 0)
|
|
||||||
key = ID2P(lang_id);
|
|
||||||
/* if key exists it will be overwritten */
|
|
||||||
open_plugin_add_path(key, vect[2], vect[3]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logf("%s error: importing entries", __func__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_plugin_export(int cfg_fd)
|
void open_plugin_export(int cfg_fd)
|
||||||
|
|
@ -584,7 +556,7 @@ void open_plugin_export(int cfg_fd)
|
||||||
logf("%s error: opening %s", __func__, OPEN_PLUGIN_DAT);
|
logf("%s error: opening %s", __func__, OPEN_PLUGIN_DAT);
|
||||||
return; /* OPEN_PLUGIN_NOT_FOUND */
|
return; /* OPEN_PLUGIN_NOT_FOUND */
|
||||||
}
|
}
|
||||||
while (op_entry_read(fd, index++, op_entry_sz, op_entry))
|
while (op_entry_read(fd, index++, OP_ENTRY_SZ, op_entry))
|
||||||
{
|
{
|
||||||
/* don't save the LANG_OPEN_PLUGIN entry -- it is for internal use */
|
/* don't save the LANG_OPEN_PLUGIN entry -- it is for internal use */
|
||||||
if (op_entry->lang_id == LANG_OPEN_PLUGIN)
|
if (op_entry->lang_id == LANG_OPEN_PLUGIN)
|
||||||
|
|
@ -596,8 +568,16 @@ void open_plugin_export(int cfg_fd)
|
||||||
else
|
else
|
||||||
lang_name = "[USER]"; /* needs to be an invalid lang string */
|
lang_name = "[USER]"; /* needs to be an invalid lang string */
|
||||||
|
|
||||||
fdprintf(cfg_fd,"%s: \"%s\", \"%s\", \"%s\", \"%s\"\n",
|
bool dblquote = strchr(op_entry->name, '"') != NULL ||
|
||||||
"openplugin", lang_name, op_entry->name, op_entry->path, op_entry->param);
|
strchr(op_entry->param, '"') != NULL;
|
||||||
|
const char* fmtstr = "%s: \"%s\", \"%s\", \"%s\", \"%s\"\n";
|
||||||
|
|
||||||
|
if (dblquote) /* if using double quotes export with single quotes */
|
||||||
|
{
|
||||||
|
fmtstr = "%s: '%s', '%s', '%s', '%s'\n";
|
||||||
|
}
|
||||||
|
fdprintf(cfg_fd, fmtstr, OPEN_PLUGIN_CFGNAME,
|
||||||
|
lang_name, op_entry->name, op_entry->path, op_entry->param);
|
||||||
|
|
||||||
logf("openplugin[%d]: \"%s\", \"%s\", \"%s\", \"%s\"\n lang id: %d hash: %x, csum: %x\n",
|
logf("openplugin[%d]: \"%s\", \"%s\", \"%s\", \"%s\"\n lang id: %d hash: %x, csum: %x\n",
|
||||||
index, lang_name, op_entry->name, op_entry->path, op_entry->param,
|
index, lang_name, op_entry->name, op_entry->path, op_entry->param,
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#define OPEN_RBPLUGIN_DAT PLUGIN_DIR "/rb_plugins.dat"
|
#define OPEN_RBPLUGIN_DAT PLUGIN_DIR "/rb_plugins.dat"
|
||||||
#define OPEN_PLUGIN_BUFSZ MAX_PATH
|
#define OPEN_PLUGIN_BUFSZ MAX_PATH
|
||||||
#define OPEN_PLUGIN_NAMESZ 32
|
#define OPEN_PLUGIN_NAMESZ 32
|
||||||
|
#define OPEN_PLUGIN_CFGNAME "openplugin"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OPEN_PLUGIN_LANG_INVALID = (-1),
|
OPEN_PLUGIN_LANG_INVALID = (-1),
|
||||||
|
|
@ -84,7 +85,7 @@ int open_plugin_load_entry(const char *key);
|
||||||
void open_plugin_browse(const char *key);
|
void open_plugin_browse(const char *key);
|
||||||
int open_plugin_run(const char *key);
|
int open_plugin_run(const char *key);
|
||||||
void open_plugin_cache_flush(void); /* flush to disk */
|
void open_plugin_cache_flush(void); /* flush to disk */
|
||||||
void open_plugin_import(char *strdat);
|
void open_plugin_import(const char *cfg_file);
|
||||||
void open_plugin_export(int cfg_fd);
|
void open_plugin_export(int cfg_fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -892,7 +892,8 @@ int plugin_load(const char* plugin, const void* parameter)
|
||||||
!strcmp("playing_time.rock", sepch + 1) ||
|
!strcmp("playing_time.rock", sepch + 1) ||
|
||||||
!strcmp("main_menu_config.rock", sepch + 1) ||
|
!strcmp("main_menu_config.rock", sepch + 1) ||
|
||||||
!strcmp("text_viewer.rock", sepch + 1) ||
|
!strcmp("text_viewer.rock", sepch + 1) ||
|
||||||
!strcmp("disktidy.rock", sepch + 1));
|
!strcmp("disktidy.rock", sepch + 1) ||
|
||||||
|
!strcmp("open_plugins.rock", sepch + 1));
|
||||||
|
|
||||||
if (current_plugin_handle)
|
if (current_plugin_handle)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,14 @@
|
||||||
* with the parameters previously supplied
|
* with the parameters previously supplied
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(SIMULATOR)
|
||||||
|
#define logf(...) rb->debugf(__VA_ARGS__); rb->debugf("\n")
|
||||||
|
#elif defined(ROCKBOX_HAS_LOGF)
|
||||||
|
#define logf rb->logf
|
||||||
|
#else
|
||||||
|
#define logf(...) do { } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "lang_enum.h"
|
#include "lang_enum.h"
|
||||||
#include "../open_plugin.h"
|
#include "../open_plugin.h"
|
||||||
|
|
@ -46,16 +54,77 @@
|
||||||
#define MENU_ID_MAIN "0"
|
#define MENU_ID_MAIN "0"
|
||||||
#define MENU_ID_EDIT "1"
|
#define MENU_ID_EDIT "1"
|
||||||
|
|
||||||
static int fd_dat;
|
#define MAX_ENTRIES 128
|
||||||
|
|
||||||
|
static int fd_dat = -1;
|
||||||
static struct gui_synclist lists;
|
static struct gui_synclist lists;
|
||||||
struct open_plugin_entry_t op_entry;
|
static struct open_plugin_entry_t op_entry;
|
||||||
static const uint32_t open_plugin_csum = OPEN_PLUGIN_CHECKSUM;
|
static const uint32_t open_plugin_csum = OPEN_PLUGIN_CHECKSUM;
|
||||||
static const off_t op_entry_sz = sizeof(struct open_plugin_entry_t);
|
static const off_t op_entry_sz = sizeof(struct open_plugin_entry_t);
|
||||||
|
|
||||||
/* we only need the names for the first menu so don't bother reading paths yet */
|
/* we only need the names for the first menu so don't bother reading paths yet */
|
||||||
const off_t op_name_sz = OPEN_PLUGIN_NAMESZ + (op_entry.name - (char*)&op_entry);
|
const off_t op_name_sz = OPEN_PLUGIN_NAMESZ + (op_entry.name - (char*)&op_entry);
|
||||||
|
/*static char op_names[MAX_ENTRIES][OPEN_PLUGIN_NAMESZ + 1] = {0};*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations*/
|
||||||
static uint32_t op_entry_add_path(const char *key, const char *plugin, const char *parameter, bool use_key);
|
static uint32_t op_entry_add_path(const char *key, const char *plugin, const char *parameter, bool use_key);
|
||||||
|
static int import_from_config(const char* cfgfile);
|
||||||
|
static int export_to_config(const char* cfgfile);
|
||||||
|
|
||||||
|
static bool hash_exists(uint32_t hash, bool remove)
|
||||||
|
{
|
||||||
|
/* keeps track of hash entries
|
||||||
|
* supply hash = 0, remove = true to erase all entries
|
||||||
|
* supply hash = 0, remove = false; returns true if empty entries are available
|
||||||
|
* supply a hash, remove = false; returns false if the hash does not exist & adds hash to the db
|
||||||
|
* supply a hash, remove = true; returns true and removes the hash from the db
|
||||||
|
* returns false if hash is unique
|
||||||
|
*/
|
||||||
|
static uint32_t seen_hashes[MAX_ENTRIES] = {0};
|
||||||
|
int i;
|
||||||
|
if (hash == 0)
|
||||||
|
{
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
logf("removing all hashes");
|
||||||
|
for(i = 0; i < MAX_ENTRIES; i++)
|
||||||
|
seen_hashes[i] = 0;
|
||||||
|
}
|
||||||
|
return seen_hashes[MAX_ENTRIES - 1] == 0; /* true if empty entries exist */
|
||||||
|
}
|
||||||
|
for(i = 0; i < MAX_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
uint32_t current_hash = seen_hashes[i];
|
||||||
|
if (current_hash == 0 && !remove)
|
||||||
|
{
|
||||||
|
logf("(%d) added new hash: %x", i, hash);
|
||||||
|
seen_hashes[i] = hash;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (current_hash == hash)
|
||||||
|
{
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
logf("(%d) remove hash: %x", i, hash);
|
||||||
|
for (int j = i + 1; j < MAX_ENTRIES; j++, i++)
|
||||||
|
{
|
||||||
|
/* move everything above down 1*/
|
||||||
|
uint32_t next_hash = seen_hashes[j];
|
||||||
|
seen_hashes[i] = next_hash;
|
||||||
|
if (next_hash == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i + 1 == MAX_ENTRIES) /* handle last entry */
|
||||||
|
{
|
||||||
|
seen_hashes[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; /* hash is unique */
|
||||||
|
}
|
||||||
|
|
||||||
static bool _yesno_pop(const char* text)
|
static bool _yesno_pop(const char* text)
|
||||||
{
|
{
|
||||||
|
|
@ -87,6 +156,7 @@ static size_t pathbasename(const char *name, const char **nameptr)
|
||||||
*nameptr = q;
|
*nameptr = q;
|
||||||
return r - q;
|
return r - q;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int op_entry_checksum(void)
|
static int op_entry_checksum(void)
|
||||||
{
|
{
|
||||||
if (op_entry.checksum != open_plugin_csum +
|
if (op_entry.checksum != open_plugin_csum +
|
||||||
|
|
@ -134,7 +204,36 @@ static int op_entry_read_opx(const char *path)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void op_entry_export(int selection)
|
static void op_entry_config_export(void)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int len;
|
||||||
|
char buf[MAX_PATH + 1];
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
rb->snprintf(buf, sizeof(buf), "%s/%s%d%s", ROCKBOX_DIR, "open_plugins", i, ".cfg");
|
||||||
|
} while (i < 100 && rb->file_exists(buf));
|
||||||
|
|
||||||
|
if( rb->kbd_input(buf, MAX_PATH, NULL ) == 0 )
|
||||||
|
{
|
||||||
|
len = rb->strlen(buf);
|
||||||
|
if(len > 4 && buf[len] != PATH_SEPCH &&
|
||||||
|
rb->strcasecmp(&((buf)[len-4]), ".cfg") != 0)
|
||||||
|
{
|
||||||
|
rb->strcat(buf, ".cfg");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (export_to_config(buf) > 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb->splashf( 2*HZ, "Save Failed (%s)", buf );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void op_entry_export_opx(int selection)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
@ -257,19 +356,43 @@ static void op_entry_set_param(void)
|
||||||
rb->strlcpy(op_entry.param, tmp_buf, OPEN_PLUGIN_BUFSZ);
|
rb->strlcpy(op_entry.param, tmp_buf, OPEN_PLUGIN_BUFSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int op_et_exclude_invalid(struct open_plugin_entry_t *op_entry, int item, void *data)
|
||||||
|
{
|
||||||
|
(void)item;
|
||||||
|
(void)data;
|
||||||
|
if (op_entry->hash == 0 || op_entry->name[0] == '\0')
|
||||||
|
{
|
||||||
|
logf("Exclude entry %d - Bad hash", item);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (op_entry->checksum != open_plugin_csum +
|
||||||
|
(op_entry->lang_id <= OPEN_PLUGIN_LANG_INVALID ? 0 : LANG_LAST_INDEX_IN_ARRAY))
|
||||||
|
{
|
||||||
|
logf("Exclude entry %d - Bad csum", item);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!rb->file_exists(op_entry->path))
|
||||||
|
{
|
||||||
|
logf("Exclude entry %d - Bad path '%s'", item, op_entry->path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
logf("%s Include entry %d %s - hash %x", __func__, item,
|
||||||
|
(op_entry->lang_id >= 0 ? "[Builtin]" : "[User]"), op_entry->hash);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int op_et_exclude_hash(struct open_plugin_entry_t *op_entry, int item, void *data)
|
static int op_et_exclude_hash(struct open_plugin_entry_t *op_entry, int item, void *data)
|
||||||
{
|
{
|
||||||
(void)item;
|
(void)item;
|
||||||
|
|
||||||
if (op_entry->hash == 0 || op_entry->name[0] == '\0')
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
uint32_t *hash = data;
|
uint32_t *hash = data;
|
||||||
|
|
||||||
if (op_entry->hash != *hash)
|
if (op_entry->hash != *hash)
|
||||||
return 1;
|
return op_et_exclude_invalid(op_entry, item, data);
|
||||||
}
|
}
|
||||||
|
logf("Exclude entry %d - hash %x", item, op_entry->hash);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,11 +402,12 @@ static int op_et_exclude_builtin(struct open_plugin_entry_t *op_entry, int item,
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
if (op_entry->lang_id >= 0)
|
if (op_entry->lang_id >= 0)
|
||||||
|
{
|
||||||
|
logf("Exclude entry %d - Builtin", item);
|
||||||
return 0;
|
return 0;
|
||||||
else if(op_entry->hash == 0 || op_entry->name[0] == '\0')
|
}
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
return op_et_exclude_invalid(op_entry, item, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int op_et_exclude_user(struct open_plugin_entry_t *op_entry, int item, void *data)
|
static int op_et_exclude_user(struct open_plugin_entry_t *op_entry, int item, void *data)
|
||||||
|
|
@ -292,11 +416,11 @@ static int op_et_exclude_user(struct open_plugin_entry_t *op_entry, int item, vo
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
if (op_entry->lang_id < 0)
|
if (op_entry->lang_id < 0)
|
||||||
|
{
|
||||||
|
logf("Exclude entry %d - User", item);
|
||||||
return 0;
|
return 0;
|
||||||
else if (op_entry->hash == 0 || op_entry->name[0] == '\0')
|
}
|
||||||
return 0;
|
return op_et_exclude_invalid(op_entry, item, data);
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int op_entry_transfer(int fd, int fd_tmp,
|
static int op_entry_transfer(int fd, int fd_tmp,
|
||||||
|
|
@ -304,21 +428,82 @@ static int op_entry_transfer(int fd, int fd_tmp,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
int entries = -1;
|
int entries = -1;
|
||||||
|
int skipped = 0;
|
||||||
if (fd_tmp >= 0 && fd >= 0 && rb->lseek(fd, 0, SEEK_SET) == 0)
|
if (fd_tmp >= 0 && fd >= 0 && rb->lseek(fd, 0, SEEK_SET) == 0)
|
||||||
{
|
{
|
||||||
entries = 0;
|
entries = 0;
|
||||||
while (rb->read(fd, &op_entry, op_entry_sz) == op_entry_sz)
|
while (rb->read(fd, &op_entry, op_entry_sz) == op_entry_sz)
|
||||||
{
|
{
|
||||||
if (compfn && compfn(&op_entry, entries, data) > 0 && op_entry_checksum() > 0)
|
if (compfn && compfn(&op_entry, entries + skipped, data) > 0 && op_entry_checksum() > 0)
|
||||||
{
|
{
|
||||||
rb->write(fd_tmp, &op_entry, op_entry_sz);
|
rb->write(fd_tmp, &op_entry, op_entry_sz);
|
||||||
entries++;
|
entries++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
skipped++;
|
||||||
}
|
}
|
||||||
|
logf("%s %d entries %d skipped", __func__, entries, skipped);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logf("%s Error: fd %d, fd_tmp %d, seekfd: %d", __func__,
|
||||||
|
fd, fd_tmp, (int) rb->lseek(fd, 0, SEEK_SET));
|
||||||
}
|
}
|
||||||
return entries + 1;
|
return entries + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int op_entry_exists(int fd)
|
||||||
|
{
|
||||||
|
logf("%s? %s - %s", __func__, op_entry.name, op_entry.path);
|
||||||
|
/* returns index of the entry that already exists if not found returns -1 */
|
||||||
|
static struct open_plugin_entry_t op_entry_rd;
|
||||||
|
int entries = 0;
|
||||||
|
if (fd >= 0 && rb->lseek(fd, 0, SEEK_SET) == 0)
|
||||||
|
{
|
||||||
|
while (rb->read(fd, &op_entry_rd, op_entry_sz) == op_entry_sz)
|
||||||
|
{
|
||||||
|
logf("rd: %s - %s", op_entry_rd.name, op_entry_rd.path);
|
||||||
|
if (rb->memcmp(&op_entry_rd, &op_entry, op_entry_sz) == 0)
|
||||||
|
{
|
||||||
|
logf("%s entry exists @ %d", op_entry_rd.name, entries);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
entries++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logf("%s is unique in %d entries", op_entry.name, entries);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool browse_configs(void)
|
||||||
|
{
|
||||||
|
int entries = 0;
|
||||||
|
char tmp_buf[MAX_PATH+1];
|
||||||
|
|
||||||
|
struct browse_context browse = {
|
||||||
|
.dirfilter = SHOW_CFG,
|
||||||
|
.flags = BROWSE_SELECTONLY | BROWSE_DIRFILTER,
|
||||||
|
.title = rb->str(LANG_CUSTOM_CFG),
|
||||||
|
.icon = Icon_Plugin,
|
||||||
|
.root = ROCKBOX_DIR,
|
||||||
|
.buf = tmp_buf,
|
||||||
|
.bufsize = sizeof(tmp_buf),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
|
||||||
|
{
|
||||||
|
logf("import from %s\n", tmp_buf);
|
||||||
|
if(rb->filetype_get_attr(tmp_buf) == FILE_ATTR_CFG)
|
||||||
|
{
|
||||||
|
entries = import_from_config(tmp_buf);
|
||||||
|
rb->splashf(HZ *2, "Imported %d entries", entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (entries > 0);
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t op_entry_add_path(const char *key, const char *plugin, const char *parameter, bool use_key)
|
static uint32_t op_entry_add_path(const char *key, const char *plugin, const char *parameter, bool use_key)
|
||||||
{
|
{
|
||||||
char buf[MAX_PATH];
|
char buf[MAX_PATH];
|
||||||
|
|
@ -358,8 +543,6 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha
|
||||||
if (op_entry.name[0] == '\0' || op_entry.lang_id >= 0)
|
if (op_entry.name[0] == '\0' || op_entry.lang_id >= 0)
|
||||||
rb->strlcpy(op_entry.name, pos, OPEN_PLUGIN_NAMESZ);
|
rb->strlcpy(op_entry.name, pos, OPEN_PLUGIN_NAMESZ);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ((!parameter || parameter[0] == '\0') && fattr != FILE_ATTR_ROCK && fattr != FILE_ATTR_OPX)
|
if ((!parameter || parameter[0] == '\0') && fattr != FILE_ATTR_ROCK && fattr != FILE_ATTR_OPX)
|
||||||
{
|
{
|
||||||
rb->strlcpy(op_entry.param, plugin, OPEN_PLUGIN_BUFSZ);
|
rb->strlcpy(op_entry.param, plugin, OPEN_PLUGIN_BUFSZ);
|
||||||
|
|
@ -396,16 +579,28 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha
|
||||||
}
|
}
|
||||||
else if (parameter != op_entry.param)
|
else if (parameter != op_entry.param)
|
||||||
rb->strlcpy(op_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
|
rb->strlcpy(op_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
|
||||||
|
}
|
||||||
|
|
||||||
/* hash on the parameter path if it is a file */
|
op_entry_set_checksum();
|
||||||
if (op_entry.lang_id <0 && (key == op_entry.path || key == NULL) &&
|
|
||||||
rb->file_exists(op_entry.param))
|
if (!use_key)
|
||||||
|
{
|
||||||
|
if (op_entry.lang_id <0)
|
||||||
{
|
{
|
||||||
open_plugin_get_hash(op_entry.param, &newhash);
|
open_plugin_get_hash(op_entry.name, &hash);
|
||||||
op_entry.hash = newhash;
|
op_entry.hash = hash;
|
||||||
|
}
|
||||||
|
if (hash_exists(op_entry.hash, false) &&
|
||||||
|
_yesno_pop(ID2P(LANG_REALLY_OVERWRITE)) == false)
|
||||||
|
{
|
||||||
|
logf("%s error: duplicate key exists: '%s' lang id: %d hash: %x",
|
||||||
|
__func__, key, op_entry.lang_id, op_entry.hash);
|
||||||
|
rb->close(fd_tmp);
|
||||||
|
rb->remove(OPEN_PLUGIN_DAT ".tmp");
|
||||||
|
return op_entry.hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
op_entry_set_checksum();
|
|
||||||
rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */
|
rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */
|
||||||
}
|
}
|
||||||
else if(op_entry_read_opx(plugin) == op_entry_sz)
|
else if(op_entry_read_opx(plugin) == op_entry_sz)
|
||||||
|
|
@ -414,13 +609,23 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha
|
||||||
if (fd_tmp < 0)
|
if (fd_tmp < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (op_entry.lang_id <0 && rb->file_exists(op_entry.param))
|
if (op_entry.lang_id <0)
|
||||||
open_plugin_get_hash(op_entry.param, &hash);
|
{
|
||||||
else
|
open_plugin_get_hash(op_entry.name, &hash);
|
||||||
open_plugin_get_hash(op_entry.path, &hash);
|
}
|
||||||
|
|
||||||
op_entry.hash = hash;
|
op_entry.hash = hash;
|
||||||
op_entry_set_checksum();
|
op_entry_set_checksum();
|
||||||
|
|
||||||
|
if (hash_exists(op_entry.hash, false))
|
||||||
|
{
|
||||||
|
logf("%s error: duplicate key exists: '%s' lang id: %d hash: %x",
|
||||||
|
__func__, key, op_entry.lang_id, op_entry.hash);
|
||||||
|
rb->close(fd_tmp);
|
||||||
|
rb->remove(OPEN_PLUGIN_DAT ".tmp");
|
||||||
|
return op_entry.hash;
|
||||||
|
}
|
||||||
|
|
||||||
rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */
|
rb->write(fd_tmp, &op_entry, op_entry_sz); /* add new entry first */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -431,6 +636,7 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*logf("OP add key: '%s' lang id: %d hash: %x", op_entry.name, op_entry.lang_id, op_entry.hash);*/
|
||||||
if (op_entry_transfer(fd_dat, fd_tmp, op_et_exclude_hash, &hash) > 0)
|
if (op_entry_transfer(fd_dat, fd_tmp, op_et_exclude_hash, &hash) > 0)
|
||||||
{
|
{
|
||||||
rb->close(fd_tmp);
|
rb->close(fd_tmp);
|
||||||
|
|
@ -451,6 +657,7 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha
|
||||||
|
|
||||||
void op_entry_browse_add(int selection)
|
void op_entry_browse_add(int selection)
|
||||||
{
|
{
|
||||||
|
logf("%s", __func__);
|
||||||
char* key;
|
char* key;
|
||||||
op_entry_read(fd_dat, selection, op_entry_sz);
|
op_entry_read(fd_dat, selection, op_entry_sz);
|
||||||
if (op_entry_set_path() > 0)
|
if (op_entry_set_path() > 0)
|
||||||
|
|
@ -466,7 +673,6 @@ void op_entry_browse_add(int selection)
|
||||||
|
|
||||||
static void op_entry_remove(int selection)
|
static void op_entry_remove(int selection)
|
||||||
{
|
{
|
||||||
|
|
||||||
int entries = rb->lseek(fd_dat, 0, SEEK_END) / op_entry_sz;
|
int entries = rb->lseek(fd_dat, 0, SEEK_END) / op_entry_sz;
|
||||||
int32_t hash = 0;
|
int32_t hash = 0;
|
||||||
int lang_id = -1;
|
int lang_id = -1;
|
||||||
|
|
@ -486,6 +692,7 @@ static void op_entry_remove(int selection)
|
||||||
rb->global_settings->start_in_screen = GO_TO_ROOT + 2; /* default */
|
rb->global_settings->start_in_screen = GO_TO_ROOT + 2; /* default */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hash_exists(op_entry.hash, true);
|
||||||
rb->memset(&op_entry, 0, op_entry_sz);
|
rb->memset(&op_entry, 0, op_entry_sz);
|
||||||
op_entry.lang_id = lang_id;
|
op_entry.lang_id = lang_id;
|
||||||
op_entry.hash = hash;
|
op_entry.hash = hash;
|
||||||
|
|
@ -685,9 +892,9 @@ static int context_menu_cb(int action,
|
||||||
/*Run, Edit, Remove, Export, Blank, Import, Add, Back*/
|
/*Run, Edit, Remove, Export, Blank, Import, Add, Back*/
|
||||||
switch(selection)
|
switch(selection)
|
||||||
{
|
{
|
||||||
case 0:case 1:case 2:case 3:case 5:
|
case 0:case 1:case 2:case 3:case 4:case 5:case 7:
|
||||||
return ACTION_STD_OK;
|
return ACTION_STD_OK;
|
||||||
case 4: /*blank*/
|
case 6: /*blank*/
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ACTION_STD_CANCEL;
|
return ACTION_STD_CANCEL;
|
||||||
|
|
@ -709,6 +916,9 @@ static void edit_menu(int selection)
|
||||||
if (!op_entry_read(fd_dat, selection, op_entry_sz))
|
if (!op_entry_read(fd_dat, selection, op_entry_sz))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (op_entry.hash != 0) /* remove old hash */
|
||||||
|
hash_exists(op_entry.hash, true);
|
||||||
|
|
||||||
uint32_t crc = rb->crc_32(&op_entry, op_entry_sz, 0xffffffff);
|
uint32_t crc = rb->crc_32(&op_entry, op_entry_sz, 0xffffffff);
|
||||||
|
|
||||||
synclist_set(MENU_ID_EDIT, 2, 8, 2);
|
synclist_set(MENU_ID_EDIT, 2, 8, 2);
|
||||||
|
|
@ -762,6 +972,8 @@ static void edit_menu(int selection)
|
||||||
op_entry_add_path(NULL, op_entry.path, param, false);
|
op_entry_add_path(NULL, op_entry.path, param, false);
|
||||||
fd_dat = rb->open(OPEN_PLUGIN_DAT, O_RDWR, 0666);
|
fd_dat = rb->open(OPEN_PLUGIN_DAT, O_RDWR, 0666);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
hash_exists(op_entry.hash, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int context_menu(int selection)
|
static int context_menu(int selection)
|
||||||
|
|
@ -771,9 +983,11 @@ static int context_menu(int selection)
|
||||||
{
|
{
|
||||||
MENUITEM_STRINGLIST(menu, op_entry.name, context_menu_cb,
|
MENUITEM_STRINGLIST(menu, op_entry.name, context_menu_cb,
|
||||||
ID2P(LANG_RUN), ID2P(LANG_EDIT), ID2P(LANG_REMOVE), ID2P(LANG_EXPORT),
|
ID2P(LANG_RUN), ID2P(LANG_EDIT), ID2P(LANG_REMOVE), ID2P(LANG_EXPORT),
|
||||||
ID2P(VOICE_BLANK), ID2P(LANG_ADD), ID2P(LANG_BACK));
|
ID2P(LANG_SAVE_SETTINGS), ID2P(LANG_CUSTOM_CFG), ID2P(VOICE_BLANK),
|
||||||
|
ID2P(LANG_ADD), ID2P(LANG_BACK));
|
||||||
|
|
||||||
selected_item = rb->do_menu(&menu, 0, NULL, false);
|
selected_item = rb->do_menu(&menu, 0, NULL, false);
|
||||||
|
logf("%s %d", __func__, selected_item);
|
||||||
switch (selected_item)
|
switch (selected_item)
|
||||||
{
|
{
|
||||||
case 0: /*run*/
|
case 0: /*run*/
|
||||||
|
|
@ -785,11 +999,20 @@ static int context_menu(int selection)
|
||||||
op_entry_remove(selection);
|
op_entry_remove(selection);
|
||||||
break;
|
break;
|
||||||
case 3: /*export*/
|
case 3: /*export*/
|
||||||
op_entry_export(selection);
|
op_entry_export_opx(selection);
|
||||||
break;
|
break;
|
||||||
case 4: /*blank*/
|
case 4: /* export to cfg */
|
||||||
|
op_entry_config_export();
|
||||||
|
case 5: /*import from cfg*/
|
||||||
|
if (browse_configs())
|
||||||
|
{
|
||||||
|
rb->plugin_open(rb->plugin_get_current_filename(), "\0");
|
||||||
|
return OP_PLUGIN_RESTART;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5: /*add*/
|
case 6: /*blank*/
|
||||||
|
break;
|
||||||
|
case 7: /*add*/
|
||||||
op_entry_browse_add(-1);
|
op_entry_browse_add(-1);
|
||||||
rb->plugin_open(rb->plugin_get_current_filename(), "\0");
|
rb->plugin_open(rb->plugin_get_current_filename(), "\0");
|
||||||
return OP_PLUGIN_RESTART;
|
return OP_PLUGIN_RESTART;
|
||||||
|
|
@ -802,6 +1025,296 @@ static int context_menu(int selection)
|
||||||
return PLUGIN_ERROR;
|
return PLUGIN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read up to buffer_size chars from a quoted string
|
||||||
|
* within fd into buffer and return number of bytes read.
|
||||||
|
* A string starts with a quote character (single or double quote)
|
||||||
|
* and ends with a matching closing quote. Neither opening or closing quotes
|
||||||
|
* are stored in buffer. Too small buf or no opening and closing quote is an error.
|
||||||
|
* If an error occurs, -1 is returned (and buffer is cleared).
|
||||||
|
* If buffer too small file will still be advanced to the closing quote/LF/EOF
|
||||||
|
*/
|
||||||
|
static int read_quoted_string(int fd, char* buffer, int buffer_size)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
char ch;
|
||||||
|
char quote = '\0';
|
||||||
|
/*logf("%s fd: %d bufsz: %d", __func__, fd, buffer_size);*/
|
||||||
|
while (rb->read(fd, &ch, 1) == 1)
|
||||||
|
{
|
||||||
|
if (ch == '\n') /*LF marks end of line*/
|
||||||
|
{
|
||||||
|
rb->lseek(fd, -1, SEEK_CUR);/*back up cursor to LF so calling fn sees it*/
|
||||||
|
break; /* fail */
|
||||||
|
}
|
||||||
|
if (quote == '\0' &&
|
||||||
|
(ch == '\'' || ch == '"')) /*handle single or double quotes*/
|
||||||
|
{
|
||||||
|
quote = ch;
|
||||||
|
}
|
||||||
|
else if (quote != '\0')
|
||||||
|
{
|
||||||
|
if (ch == quote)
|
||||||
|
{
|
||||||
|
if (pos < buffer_size)
|
||||||
|
{
|
||||||
|
buffer[pos] = '\0'; /*end quote*/
|
||||||
|
return pos + 1;
|
||||||
|
}
|
||||||
|
break; /*fail*/
|
||||||
|
}
|
||||||
|
if (pos < buffer_size)
|
||||||
|
{
|
||||||
|
buffer[pos] = ch; /*inside quote*/
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fail*/
|
||||||
|
/*logf("Error %s", __func__);*/
|
||||||
|
buffer[0] = '\0';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lang_english_to_id(const char *english)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char *ptr;
|
||||||
|
size_t ptrlen, len = rb->strlen(english);
|
||||||
|
for (i = 0; i < LANG_LAST_INDEX_IN_ARRAY; i++) {
|
||||||
|
ptr = rb->language_strings[i];
|
||||||
|
ptrlen = rb->strlen((char *)ptr);
|
||||||
|
if ((ptrlen == len) && rb->memcmp(ptr, english, ptrlen) == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_entry_config_import(int cfg_fd, int fd_tmp)
|
||||||
|
{
|
||||||
|
/* NOTE: assumes cfg_fd is valid */
|
||||||
|
/*"key", "name", "path", "param"*/
|
||||||
|
/*"Start Screen", "logo.rock", "/.rockbox/rocks/demos/logo.rock", ""*/
|
||||||
|
/*"[USER]", "text_viewer.rock", "/.rockbox/rocks/viewers/text_viewer.rock", "/text.txt"*/
|
||||||
|
rb->memset(&op_entry, 0, op_entry_sz);
|
||||||
|
|
||||||
|
static char errmsg[MAX_PATH];
|
||||||
|
static char keybuf[MAX_PATH];
|
||||||
|
int32_t lang_id;
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
|
if (read_quoted_string(cfg_fd, keybuf, sizeof(keybuf)) < 0)
|
||||||
|
{
|
||||||
|
logf("%s error: importing key entry @ %d", __func__, 0);
|
||||||
|
rb->snprintf(errmsg, sizeof(errmsg), "importing key entry @ %d", 1);
|
||||||
|
rb->splashf(HZ*2, ID2P(LANG_ERROR_FORMATSTR), errmsg);
|
||||||
|
return false; /* fail */
|
||||||
|
}
|
||||||
|
|
||||||
|
lang_id = lang_english_to_id(keybuf);
|
||||||
|
if (lang_id < 0)
|
||||||
|
{
|
||||||
|
int rd = read_quoted_string(cfg_fd, keybuf, sizeof(keybuf)); /* grab name field */
|
||||||
|
if(rd < 0)
|
||||||
|
{
|
||||||
|
logf("%s error: importing key entry @ %d", __func__, 1);
|
||||||
|
rb->snprintf(errmsg, sizeof(errmsg), "importing key entry @ %d", 1);
|
||||||
|
rb->splashf(HZ*2, ID2P(LANG_ERROR_FORMATSTR), errmsg);
|
||||||
|
return false; /* fail */
|
||||||
|
}
|
||||||
|
rb->lseek(cfg_fd, -(rd+2), SEEK_CUR); /* restore position to read name again */
|
||||||
|
}
|
||||||
|
|
||||||
|
int i, bufsz;
|
||||||
|
char *field[3] = {op_entry.name, op_entry.path, op_entry.param};
|
||||||
|
for (i = 0, bufsz = OPEN_PLUGIN_NAMESZ; i < (int)ARRAYLEN(field); i++)
|
||||||
|
{
|
||||||
|
if (read_quoted_string(cfg_fd, field[i], bufsz) < 0)
|
||||||
|
{
|
||||||
|
logf("%s error: importing entry @ %d", __func__, i);
|
||||||
|
logf("OP import key: '%s' name: '%s' '%s' '%s'", keybuf,
|
||||||
|
op_entry.name, op_entry.path, op_entry.param);
|
||||||
|
rb->memset(&op_entry, 0, op_entry_sz);
|
||||||
|
rb->snprintf(errmsg, sizeof(errmsg), "importing entry %s @ %d", keybuf, i);
|
||||||
|
rb->splashf(HZ*2, ID2P(LANG_ERROR_FORMATSTR), errmsg);
|
||||||
|
return false; /* fail */
|
||||||
|
}
|
||||||
|
bufsz = OPEN_PLUGIN_BUFSZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rb->file_exists(op_entry.path))
|
||||||
|
{
|
||||||
|
logf("%s error: '%s' '%s' does not exist", __func__, keybuf, op_entry.path);
|
||||||
|
rb->splashf(HZ*2, ID2P(LANG_PLUGIN_CANT_OPEN), op_entry.path);
|
||||||
|
return false; /* fail */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lang_id <0)
|
||||||
|
{
|
||||||
|
open_plugin_get_hash(op_entry.name, &hash);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
open_plugin_get_hash(keybuf, &hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
op_entry.hash = hash;
|
||||||
|
op_entry.lang_id = lang_id;
|
||||||
|
|
||||||
|
/*logf("OP import key: '%s' name: '%s' '%s' '%s'", keybuf,
|
||||||
|
op_entry.name, op_entry.path, op_entry.param);*/
|
||||||
|
|
||||||
|
op_entry_set_checksum();
|
||||||
|
|
||||||
|
if (fd_tmp >= 0 && fd_dat >= 0)
|
||||||
|
{
|
||||||
|
if (hash_exists(op_entry.hash, false))
|
||||||
|
{
|
||||||
|
logf("%s error: duplicate key exists: '%s' lang id: %d hash: %x",
|
||||||
|
__func__, keybuf, lang_id, hash);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logf("writing to tmp: %s - %s", op_entry.name, op_entry.path);
|
||||||
|
|
||||||
|
if (rb->write(fd_tmp, &op_entry, op_entry_sz) != op_entry_sz)/* add new entry */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logf("%s error: bad fd dat: %d tmp: %d", __func__, fd_dat, fd_tmp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int import_from_config(const char* cfgfile)
|
||||||
|
{
|
||||||
|
logf("%s() %s\r\n", __func__, cfgfile);
|
||||||
|
int fd;
|
||||||
|
char ch;
|
||||||
|
int entries = 0;
|
||||||
|
static char line[sizeof("openplugin:")];
|
||||||
|
|
||||||
|
fd = rb->open_utf8(cfgfile, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int fd_tmp = rb->open(OPEN_PLUGIN_DAT ".tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd_tmp < 0)
|
||||||
|
{
|
||||||
|
logf("%s error: can not open '%s'", __func__, OPEN_PLUGIN_DAT ".tmp");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((rb->read(fd, line, sizeof line) - 1) == sizeof(line) - 1)
|
||||||
|
{
|
||||||
|
if (rb->strncasecmp(line, "openplugin:", sizeof("openplugin:") -1) == 0)
|
||||||
|
{
|
||||||
|
if (op_entry_config_import(fd, fd_tmp))
|
||||||
|
entries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rb->read(fd, &ch, 1) == 1) /* continue reading till EOL */
|
||||||
|
{
|
||||||
|
if (ch == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} /* while(...) */
|
||||||
|
|
||||||
|
rb->close(fd);
|
||||||
|
#if 1
|
||||||
|
if (entries > 0 && op_entry_transfer(fd_dat, fd_tmp, &op_et_exclude_user, NULL) > 0 &&
|
||||||
|
op_entry_transfer(fd_dat, fd_tmp, &op_et_exclude_builtin, NULL) > 0)
|
||||||
|
#else
|
||||||
|
if (entries > 0 && op_entry_transfer(fd_dat, fd_tmp, op_et_exclude_invalid, 0) >= 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
logf("%s imported %d entries", __func__, entries);
|
||||||
|
rb->close(fd_tmp);
|
||||||
|
rb->close(fd_dat);
|
||||||
|
fd_dat = -1;
|
||||||
|
rb->remove(OPEN_PLUGIN_DAT);
|
||||||
|
rb->rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logf("%s error: can not transfer entries", __func__);
|
||||||
|
if (entries > 0)
|
||||||
|
{
|
||||||
|
logf("%s error: can not transfer entries to '%s'", __func__, OPEN_PLUGIN_DAT ".tmp");
|
||||||
|
entries = -1;
|
||||||
|
}
|
||||||
|
rb->close(fd_tmp);
|
||||||
|
rb->remove(OPEN_PLUGIN_DAT ".tmp");
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int export_to_config(const char* cfgfile)
|
||||||
|
{
|
||||||
|
logf("%s() %s\r\n", __func__, cfgfile);
|
||||||
|
int cfg_fd;
|
||||||
|
char *lang_name;
|
||||||
|
int fd;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
cfg_fd = rb->open_utf8(cfgfile, O_WRONLY | O_CREAT | O_TRUNC);
|
||||||
|
if (cfg_fd < 0)
|
||||||
|
return index;
|
||||||
|
|
||||||
|
fd = rb->open_utf8(OPEN_PLUGIN_DAT, O_RDONLY);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
logf("%s error: opening %s", __func__, OPEN_PLUGIN_DAT);
|
||||||
|
rb->close(cfg_fd);
|
||||||
|
rb->remove(cfgfile);
|
||||||
|
return index; /* OPEN_PLUGIN_NOT_FOUND */
|
||||||
|
}
|
||||||
|
while (op_entry_read(fd, index, op_entry_sz))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
/* don't save the LANG_OPEN_PLUGIN entry -- it is for internal use */
|
||||||
|
if (op_entry.lang_id == LANG_OPEN_PLUGIN)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (op_entry.lang_id >=0)
|
||||||
|
lang_name = rb->str(op_entry.lang_id);
|
||||||
|
else
|
||||||
|
lang_name = "[USER]"; /* needs to be an invalid lang string */
|
||||||
|
bool dblquote = rb->strchr(op_entry.name, '"') != NULL ||
|
||||||
|
rb->strchr(op_entry.param, '"') != NULL;
|
||||||
|
|
||||||
|
const char* fmtstr = "%s: \"%s\", \"%s\", \"%s\", \"%s\"\n";
|
||||||
|
|
||||||
|
if (dblquote) /* if using double quotes export with single quotes */
|
||||||
|
{
|
||||||
|
fmtstr = "%s: '%s', '%s', '%s', '%s'\n";
|
||||||
|
}
|
||||||
|
rb->fdprintf(cfg_fd,fmtstr, OPEN_PLUGIN_CFGNAME,
|
||||||
|
lang_name, op_entry.name, op_entry.path, op_entry.param);
|
||||||
|
|
||||||
|
logf("openplugin[%d]: \"%s\", \"%s\", \"%s\", \"%s\"\n lang id: %d hash: %x, csum: %x\n",
|
||||||
|
index, lang_name, op_entry.name, op_entry.path, op_entry.param,
|
||||||
|
op_entry.lang_id, op_entry.hash, op_entry.checksum);
|
||||||
|
}
|
||||||
|
rb->close(fd);
|
||||||
|
rb->close(cfg_fd);
|
||||||
|
logf("%s exported %d entries", __func__, index);
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
/* Nothing to export */
|
||||||
|
rb->remove(cfgfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
enum plugin_status plugin_start(const void* parameter)
|
enum plugin_status plugin_start(const void* parameter)
|
||||||
{
|
{
|
||||||
int ret = PLUGIN_OK;
|
int ret = PLUGIN_OK;
|
||||||
|
|
@ -817,11 +1330,20 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
const int creat_flags = O_RDWR | O_CREAT;
|
const int creat_flags = O_RDWR | O_CREAT;
|
||||||
|
|
||||||
reopen_datfile:
|
reopen_datfile:
|
||||||
|
|
||||||
fd_dat = rb->open(OPEN_PLUGIN_DAT, creat_flags, 0666);
|
fd_dat = rb->open(OPEN_PLUGIN_DAT, creat_flags, 0666);
|
||||||
|
|
||||||
|
hash_exists(0, true);
|
||||||
|
while (rb->read(fd_dat, &op_entry, op_entry_sz) == op_entry_sz)
|
||||||
|
{
|
||||||
|
hash_exists(op_entry.hash, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fd_dat)
|
if (!fd_dat)
|
||||||
exit = true;
|
exit = true;
|
||||||
|
|
||||||
items = rb->lseek(fd_dat, 0, SEEK_END) / op_entry_sz;
|
items = rb->lseek(fd_dat, 0, SEEK_END) / op_entry_sz;
|
||||||
|
|
||||||
if (parameter)
|
if (parameter)
|
||||||
{
|
{
|
||||||
path = (char*)parameter;
|
path = (char*)parameter;
|
||||||
|
|
@ -833,13 +1355,18 @@ reopen_datfile:
|
||||||
parameter = NULL;
|
parameter = NULL;
|
||||||
op_entry_browse_add(-1);
|
op_entry_browse_add(-1);
|
||||||
rb->close(fd_dat);
|
rb->close(fd_dat);
|
||||||
|
fd_dat = -1;
|
||||||
goto reopen_datfile;
|
goto reopen_datfile;
|
||||||
}
|
}
|
||||||
}
|
if(rb->filetype_get_attr(path) == FILE_ATTR_CFG)
|
||||||
|
{
|
||||||
|
int ret = import_from_config(path);
|
||||||
|
rb->close(fd_dat);
|
||||||
|
if (ret >= 0)
|
||||||
|
return PLUGIN_OK;
|
||||||
|
return PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (parameter)
|
|
||||||
{
|
|
||||||
path = (char*)parameter;
|
|
||||||
res = op_entry_read_opx(path);
|
res = op_entry_read_opx(path);
|
||||||
if (res >= 0)
|
if (res >= 0)
|
||||||
{
|
{
|
||||||
|
|
@ -910,6 +1437,7 @@ reopen_datfile:
|
||||||
if (op_entry_add_path(rb->str(LANG_ADD), cur_filename, "-add", true))
|
if (op_entry_add_path(rb->str(LANG_ADD), cur_filename, "-add", true))
|
||||||
{
|
{
|
||||||
rb->close(fd_dat);
|
rb->close(fd_dat);
|
||||||
|
fd_dat = -1;
|
||||||
parameter = NULL;
|
parameter = NULL;
|
||||||
goto reopen_datfile;
|
goto reopen_datfile;
|
||||||
}
|
}
|
||||||
|
|
@ -917,8 +1445,6 @@ reopen_datfile:
|
||||||
return PLUGIN_ERROR;
|
return PLUGIN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!exit)
|
if (!exit)
|
||||||
{
|
{
|
||||||
synclist_set(MENU_ID_MAIN, selection, items, 1);
|
synclist_set(MENU_ID_MAIN, selection, items, 1);
|
||||||
|
|
@ -947,7 +1473,7 @@ reopen_datfile:
|
||||||
rb->gui_synclist_draw(&lists);
|
rb->gui_synclist_draw(&lists);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Inentional fallthrough */
|
/* fallthrough */
|
||||||
case ACTION_STD_OK:
|
case ACTION_STD_OK:
|
||||||
if (op_entry_read(fd_dat, selection, op_entry_sz))
|
if (op_entry_read(fd_dat, selection, op_entry_sz))
|
||||||
{
|
{
|
||||||
|
|
@ -962,6 +1488,14 @@ reopen_datfile:
|
||||||
exit = true;
|
exit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
if (rb->default_event_handler(action) == SYS_USB_CONNECTED)
|
||||||
|
{
|
||||||
|
op_entry_remove_empty();
|
||||||
|
rb->close(fd_dat);
|
||||||
|
return PLUGIN_USB_CONNECTED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
op_entry_remove_empty();
|
op_entry_remove_empty();
|
||||||
|
|
|
||||||
|
|
@ -405,7 +405,7 @@ bool settings_load_config(const char* file, bool apply)
|
||||||
int fd;
|
int fd;
|
||||||
char line[128];
|
char line[128];
|
||||||
bool theme_changed = false;
|
bool theme_changed = false;
|
||||||
|
bool import_open_plugins = false;
|
||||||
fd = open_utf8(file, O_RDONLY);
|
fd = open_utf8(file, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -418,17 +418,25 @@ bool settings_load_config(const char* file, bool apply)
|
||||||
|
|
||||||
if (!string_to_cfg(name, value, &theme_changed))
|
if (!string_to_cfg(name, value, &theme_changed))
|
||||||
{
|
{
|
||||||
#ifndef __PCTOOL__
|
|
||||||
/* if we are here then name was not a valid setting */
|
/* if we are here then name was not a valid setting */
|
||||||
if (!strcmp(name, "openplugin"))
|
if (strcmp(name, OPEN_PLUGIN_CFGNAME) == 0)
|
||||||
{
|
{
|
||||||
open_plugin_import(value);
|
import_open_plugins = true;
|
||||||
|
char ch;
|
||||||
|
while (read(fd, &ch, 1) == 1 && ch != '\n'){};
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} /* while(...) */
|
} /* while(...) */
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
#ifndef __PCTOOL__
|
||||||
|
if (import_open_plugins)
|
||||||
|
open_plugin_import(file);
|
||||||
|
#else
|
||||||
|
(void) import_open_plugins;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (apply)
|
if (apply)
|
||||||
{
|
{
|
||||||
settings_save();
|
settings_save();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue