Index: modules/mod_ls.c =================================================================== RCS file: /cvsroot/proftp/proftpd/modules/mod_ls.c,v retrieving revision 1.192 diff -u -r1.192 mod_ls.c --- modules/mod_ls.c 1 Feb 2012 22:03:50 -0000 1.192 +++ modules/mod_ls.c 1 Feb 2012 23:13:14 -0000 @@ -54,8 +54,10 @@ #endif #define LS_SENDLINE_FL_FLUSH 0x0001 -static unsigned long list_flags = 0; #define LS_FL_NO_ERROR_IF_ABSENT 0x0001 +#define LS_FL_LIST_ONLY 0x0002 +#define LS_FL_NLST_ONLY 0x0004 +static unsigned long list_flags = 0; static unsigned char list_strict_opts = FALSE; static char *list_options = NULL; @@ -2273,15 +2275,28 @@ config_rec *c = NULL; tmp = get_param_ptr(TOPLEVEL_CONF, "ShowSymlinks", FALSE); - if (tmp != NULL) + if (tmp != NULL) { list_show_symlinks = *tmp; + } list_strict_opts = FALSE; - list_nfiles.max = list_ndirs.max = list_ndepth.max = 0; c = find_config(CURRENT_CONF, CONF_PARAM, "ListOptions", FALSE); - if (c != NULL) { + while (c != NULL) { + pr_signals_handle(); + + list_flags = *((unsigned long *) c->argv[5]); + + /* Make sure that this ListOptions can be applied to the LIST command. + * If not, keep looking for other applicable ListOptions. + */ + if (list_flags & LS_FL_NLST_ONLY) { + pr_log_debug(DEBUG10, "%s: skipping NLSTOnly ListOptions", cmd->argv[0]); + c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE); + continue; + } + list_options = c->argv[0]; list_strict_opts = *((unsigned char *) c->argv[1]); @@ -2299,7 +2314,7 @@ list_nfiles.max = *((unsigned int *) c->argv[3]); list_ndirs.max = *((unsigned int *) c->argv[4]); - list_flags = *((unsigned long *) c->argv[5]); + break; } fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE); @@ -2440,7 +2455,26 @@ list_ndepth.max = list_nfiles.max = list_ndirs.max = 0; c = find_config(CURRENT_CONF, CONF_PARAM, "ListOptions", FALSE); - if (c != NULL) { + while (c != NULL) { + pr_signals_handle(); + + list_flags = *((unsigned long *) c->argv[5]); + + /* Make sure that this ListOptions can be applied to the STAT command. + * If not, keep looking for other applicable ListOptions. + */ + if (list_flags & LS_FL_LIST_ONLY) { + pr_log_debug(DEBUG10, "%s: skipping LISTOnly ListOptions", cmd->argv[0]); + c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE); + continue; + } + + if (list_flags & LS_FL_NLST_ONLY) { + pr_log_debug(DEBUG10, "%s: skipping NLSTOnly ListOptions", cmd->argv[0]); + c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE); + continue; + } + list_options = c->argv[0]; list_strict_opts = *((unsigned char *) c->argv[1]); @@ -2458,7 +2492,7 @@ list_nfiles.max = *((unsigned int *) c->argv[3]); list_ndirs.max = *((unsigned int *) c->argv[4]); - list_flags = *((unsigned long *) c->argv[5]); + break; } fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE); @@ -2535,7 +2569,20 @@ pr_fs_decode_path(cmd->tmp_pool, cmd->arg); c = find_config(CURRENT_CONF, CONF_PARAM, "ListOptions", FALSE); - if (c != NULL) { + while (c != NULL) { + pr_signals_handle(); + + list_flags = *((unsigned long *) c->argv[5]); + + /* Make sure that this ListOptions can be applied to the NLST command. + * If not, keep looking for other applicable ListOptions. + */ + if (list_flags & LS_FL_LIST_ONLY) { + pr_log_debug(DEBUG10, "%s: skipping LISTOnly ListOptions", cmd->argv[0]); + c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE); + continue; + } + list_options = c->argv[0]; list_strict_opts = *((unsigned char *) c->argv[1]); @@ -2554,6 +2601,8 @@ list_ndirs.max = *((unsigned int *) c->argv[4]); list_flags = *((unsigned long *) c->argv[5]); + + break; } /* Clear the listing option flags. */ @@ -3019,7 +3068,6 @@ /* The default flags */ c->argv[5] = pcalloc(c->pool, sizeof(unsigned long)); - *((unsigned int *) c->argv[5]) = 0; /* Check for, and handle, optional arguments. */ if (cmd->argc-1 >= 2) { @@ -3060,6 +3108,12 @@ *((unsigned int *) c->argv[4]) = maxdirs; + } else if (strcasecmp(cmd->argv[i], "LISTOnly") == 0) { + flags |= LS_FL_LIST_ONLY; + + } else if (strcasecmp(cmd->argv[i], "NLSTOnly") == 0) { + flags |= LS_FL_NLST_ONLY; + } else if (strcasecmp(cmd->argv[i], "NoErrorIfAbsent") == 0) { flags |= LS_FL_NO_ERROR_IF_ABSENT; @@ -3071,7 +3125,6 @@ } *((unsigned long *) c->argv[5]) = flags; - return PR_HANDLED(cmd); }