From 72c539d35e1853980de1d74e65acc9a22caa63f6 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Wed, 22 Nov 2023 00:07:30 -0500 Subject: [Bug_Fix] shortcut to directory in .link files caused crash since the plugin browser is now closed when running plugins rb->set_current_file() had no valid browser context and used 'random' memory instead also adds a way to discard levels so we can load the desired directory instead of returning to the previous https://forums.rockbox.org/index.php/topic,54694.0.html Change-Id: I624246e56d42972bf6a1ce566a209b745de6f30b --- apps/filetree.c | 9 +++++ apps/open_plugin.c | 2 +- apps/plugins/shortcuts/shortcuts_view.c | 58 ++++++++++++++++++++++++++++----- apps/tree.c | 22 +++++++++++-- apps/tree.h | 5 ++- 5 files changed, 83 insertions(+), 13 deletions(-) diff --git a/apps/filetree.c b/apps/filetree.c index 42f13f39e7..eb429c83e3 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -287,12 +287,18 @@ static int compare(const void* p1, const void* p2) /* load and sort directory into the tree's cache. returns NULL on failure. */ int ft_load(struct tree_context* c, const char* tempdir) { + if (c->out_of_tree > 0) /* something else is loaded */ + return 0; + int files_in_dir = 0; int name_buffer_used = 0; struct dirent *entry; bool (*callback_show_item)(char *, int, struct tree_context *) = NULL; DIR *dir; + if (!c->is_browsing) + c->browse = NULL; + if (tempdir) dir = opendir(tempdir); else @@ -760,6 +766,7 @@ int ft_enter(struct tree_context* c) } } } + return rc; } @@ -802,5 +809,7 @@ int ft_exit(struct tree_context* c) if (exit_func) rc = 3; + c->out_of_tree = 0; + return rc; } diff --git a/apps/open_plugin.c b/apps/open_plugin.c index 1256db79f8..afe59b38e3 100644 --- a/apps/open_plugin.c +++ b/apps/open_plugin.c @@ -353,7 +353,7 @@ static bool callback_show_item(char *name, int attr, struct tree_context *tc) { if (strstr(tc->currdir, PLUGIN_DIR) != NULL) return true; - tc->browse = NULL; /* exit immediately */ + tc->is_browsing = false; /* exit immediately */ } else if(attr & FILE_ATTR_ROCK) { diff --git a/apps/plugins/shortcuts/shortcuts_view.c b/apps/plugins/shortcuts/shortcuts_view.c index 2a7970bebe..187ed740a1 100644 --- a/apps/plugins/shortcuts/shortcuts_view.c +++ b/apps/plugins/shortcuts/shortcuts_view.c @@ -32,7 +32,7 @@ enum sc_list_action_type SCLA_USB, }; - +static size_t root_len; static char *link_filename; static bool user_file; @@ -175,6 +175,42 @@ bool goto_entry(char *file_or_dir) } #endif +static bool callback_show_item(char *name, int attr, struct tree_context *tc) +{ + (void)name; + if(attr & ATTR_DIRECTORY) + { + if ((tc->browse->flags & BROWSE_SELECTED) == 0 && + rb->strlen(tc->currdir) < root_len) + { + tc->is_browsing = false; /* exit immediately */ + } + } + + return true; +} + +bool open_browse(char *path, char *buf, size_t bufsz) +{ + struct browse_context browse = { + .dirfilter = rb->global_settings->dirfilter, + .flags = BROWSE_DIRFILTER| BROWSE_SELECTONLY | BROWSE_NO_CONTEXT_MENU, + .title = path, + .icon = Icon_Plugin, + .root = path, + .buf = buf, + .bufsize = bufsz, + .callback_show_item = callback_show_item, + }; + root_len = 0; + char *name = rb->strrchr(path, '/'); + if (name) + root_len = name - path; + rb->rockbox_browse(&browse); + + return (browse.flags & BROWSE_SELECTED); +} + int goto_entry(char *file_or_dir) { DEBUGF("Trying to go to '%s'...\n", file_or_dir); @@ -202,14 +238,18 @@ int goto_entry(char *file_or_dir) } else { - /* Set the browsers dirfilter to the global setting - * This is required in case the plugin was launched - * from the plugins browser, in which case the - * dirfilter is set to only display .rock files */ - rb->set_dirfilter(rb->global_settings->dirfilter); - - /* Change directory to the entry selected by the user */ - rb->set_current_file(file_or_dir); + if (!is_dir) + { + rb->set_current_file(file_or_dir); + return LOOP_EXIT; + } + char tmp_buf[MAX_PATH]; + if (open_browse(file_or_dir, tmp_buf, sizeof(tmp_buf))) + { + DEBUGF("Trying to load '%s'...\n", tmp_buf); + rb->set_current_file(tmp_buf); + return LOOP_EXIT; + } } return PLUGIN_OK; } diff --git a/apps/tree.c b/apps/tree.c index 8fa5f168fd..ba4da816d1 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -608,6 +608,13 @@ void set_current_file(const char *path) { tc.selected_item = tree_get_file_position(lastfile); } + + if (!tc.is_browsing && tc.out_of_tree == 0) + { + /* the browser is closed */ + /* don't allow the previous items to overwrite what we just loaded */ + tc.out_of_tree = tc.selected_item + 1; + } } @@ -652,7 +659,7 @@ static int dirbrowse(void) return GO_TO_PREVIOUS; /* No files found for rockbox_browse() */ } - while(tc.browse) { + while(tc.browse && tc.is_browsing) { bool restore = false; if (tc.dirlevel < 0) tc.dirlevel = 0; /* shouldnt be needed.. this code needs work! */ @@ -973,10 +980,18 @@ static struct tree_context backups[NUM_TC_BACKUP]; static int backup_count = -1; int rockbox_browse(struct browse_context *browse) { + tc.is_browsing = (browse != NULL); static char current[MAX_PATH]; int ret_val = 0; int dirfilter = browse->dirfilter; + if (tc.out_of_tree > 0) + { + tc.selected_item = tc.out_of_tree - 1; + tc.out_of_tree = 0; + return ft_enter(&tc); + } + if (backup_count >= NUM_TC_BACKUP) return GO_TO_PREVIOUS; if (backup_count >= 0) @@ -1031,6 +1046,9 @@ int rockbox_browse(struct browse_context *browse) backup_count--; if (backup_count >= 0) tc = backups[backup_count]; + + tc.is_browsing = false; + return ret_val; } @@ -1198,7 +1216,7 @@ static int ft_play_filename(char *dir, char *file, int attr) /* These two functions are called by the USB and shutdown handlers */ void tree_flush(void) { - tc.browse = NULL; /* clear browse to prevent reentry to a possibly missing file */ + tc.is_browsing = false;/* clear browse to prevent reentry to a possibly missing file */ #ifdef HAVE_TAGCACHE tagcache_shutdown(); #endif diff --git a/apps/tree.h b/apps/tree.h index d454c0f7ee..d13c75d434 100644 --- a/apps/tree.h +++ b/apps/tree.h @@ -90,9 +90,12 @@ struct tree_context { int currtable; /* db use */ int currextra; /* db use */ #endif + int sort_dir; /* directory sort order */ + int out_of_tree; /* shortcut from elsewhere */ struct tree_cache cache; bool dirfull; - int sort_dir; /* directory sort order */ + bool is_browsing; /* valid browse context? */ + struct browse_context *browse; }; -- cgit v1.2.3