From 0eab236580f77d3d9e76829047e07f2ef656ed26 Mon Sep 17 00:00:00 2001
From: Chris Allegretta <chrisa@asty.org>
Date: Mon, 3 Feb 2003 03:39:05 +0000
Subject: [PATCH] files.c:do_browser()  - Even more checks and operating dir
 fixes (David Benbennick)

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1415 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
---
 ChangeLog |  1 +
 files.c   | 91 +++++++++++++++++++++++++------------------------------
 2 files changed, 43 insertions(+), 49 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 82d1cd34..0d27b9d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -47,6 +47,7 @@ CVS Code -
 	  (David Benbennick).
 	- Fix goto directory operating dir check and tilde expansion
 	  (David Benbennick).
+	- Even more checks and operating dir fixes (David Benbennick).
   open_file()
 	- Fix FD leak with file load error (David Benbennick).
   add_open_file()
diff --git a/files.c b/files.c
index 0fab49aa..d7a8cd6b 100644
--- a/files.c
+++ b/files.c
@@ -2514,7 +2514,6 @@ char *do_browser(const char *inpath)
 
     /* Loop invariant: Microsoft sucks. */
     do {
-	DIR *test_dir;
 	char *new_path;
 	    /* Used by the Go To Directory prompt. */
 
@@ -2621,67 +2620,61 @@ char *do_browser(const char *inpath)
 	    /* You can't cd up from / */
 	    if (!strcmp(filelist[selected], "/..") && !strcmp(path, "/")) {
 		statusbar(_("Can't move up a directory"));
+		beep();
 		break;
 	    }
 
 #ifndef DISABLE_OPERATINGDIR
-	    /* Note: The case of the user's being completely outside the
-	       operating directory is handled elsewhere, before this
-	       point */
-	    if (operating_dir != NULL) {
-		if (check_operating_dir(filelist[selected], 0)) {
-		    statusbar(_("Can't visit parent in restricted mode"));
-		    beep();
-		    break;
-		}
+	    /*
+	     *  Note: the selected file can be outside the operating
+	     *  directory if it is .. or if it is a symlink to a directory
+	     *  outside the opdir. */
+	    if (check_operating_dir(filelist[selected], FALSE)) {
+		statusbar(_("Can't go outside of %s in restricted mode"), operating_dir);
+		beep();
+		break;
 	    }
 #endif
 
-	    path = mallocstrcpy(path, filelist[selected]);
+	    if (stat(filelist[selected], &st) == -1) {
+		statusbar(_("Can't open \"%s\": %s"), filelist[selected], strerror(errno));
+		beep();
+		break;
+	    }
 
-	    /* SPK for '.' path, get the current path via getcwd */
-	    if (!strcmp(path, "./..")) {
-		free(path);
-#ifdef PATH_MAX
-		path = getcwd(NULL, PATH_MAX + 1);
-#else
-		path = getcwd(NULL, 0);
-#endif
-		striponedir(path);		    
-		align(&path);
-		free_charptrarray(filelist, numents);
-		free(foo);
-		return do_browser(path);
+	    if (!S_ISDIR(st.st_mode)) {
+		retval = mallocstrcpy(retval, filelist[selected]);
+		abort = 1;
+		break;
 	    }
 
-	    st = filestat(path);
-	    if (S_ISDIR(st.st_mode)) {
-		if ((test_dir = opendir(path)) == NULL) {
-		    /* We can't open this dir for some reason.  Complain */
-		    statusbar(_("Can't open \"%s\": %s"), path, strerror(errno));
-		    striponedir(path);
-		    align(&path);
-		    break;
-		} 
-		closedir(test_dir);
-
-		if (!strcmp("..", tail(path))) {
-		    /* They want to go up a level, so strip off .. and the
-		       current dir */
-		    striponedir(path);
-		    striponedir(path);
-		    align(&path);
+	    new_path = mallocstrcpy(NULL, filelist[selected]);
+
+	    if (strcmp("..", tail(new_path)) == 0) {
+		/* They want to go up a level, so strip off .. and the
+		   current dir */
+		striponedir(new_path);
+		/* SPK for '.' path, get the current path via getcwd */
+		if (strcmp(new_path, ".") == 0) {
+		    free(new_path);
+		    new_path = getcwd(NULL, PATH_MAX + 1);
 		}
+		striponedir(new_path);
+	    }
 
-		/* Start over again with the new path value */
-		free_charptrarray(filelist, numents);
-		free(foo);
-		return do_browser(path);
-	    } else {
-		retval = mallocstrcpy(retval, path);
-		abort = 1;
+	    if (!readable_dir(new_path)) {
+		/* We can't open this dir for some reason.  Complain */
+		statusbar(_("Can't open \"%s\": %s"), new_path, strerror(errno));
+		free(new_path);
+		break;
 	    }
-	    break;
+
+	    free_charptrarray(filelist, numents);
+	    free(foo);
+	    free(path);
+	    path = new_path;
+	    return do_browser(path);
+
 	/* Goto a specific directory */
 	case 'g':	/* Pico compatibility */
 	case 'G':
-- 
GitLab