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);
}