From 42d10a2a24f550a66776eb1d9c55ff8be63a3ed0 Mon Sep 17 00:00:00 2001
From: Adrian Perez de Castro <aperez@igalia.com>
Date: Sun, 16 Aug 2015 13:01:18 +0300
Subject: [PATCH] Add option to hide symbolic links from generated listings

This adds a new "fancyindex_hide_symlinks" configuration flag, which will
filter out symbolic links from the generated file listings when enabled.

Feature suggested by Peter Wemm (https://github.com/DarkHelmet433)

Fixes issue #27
---
 CHANGELOG.md                 |  4 ++++
 README.rst                   |  8 ++++++++
 ngx_http_fancyindex_module.c | 26 ++++++++++++++++++++------
 3 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc1c8d0..f5188c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 All notable changes to this project will be documented in this file.
 
 ## Unreleased
+### Added
+- New feature: Allow filtering out symbolic links using the
+  `fancyindex_hide_symlinks` configuration directive. (Idea and prototype
+  patch by Thomas Wemm.)
 ### Changed
 - Listings in top-level directories will not generate a "Parent Directory"
   link as first element of the listing. (Patch by Thomas P.)
diff --git a/README.rst b/README.rst
index b33de59..9671e02 100644
--- a/README.rst
+++ b/README.rst
@@ -180,6 +180,14 @@ fancyindex_ignore
   listings. If Nginx was built with PCRE support strings are interpreted as
   regular expressions.
 
+fancyindex_hide_symlinks
+~~~~~~~~~~~~~~~~~~~~~~~~
+:Syntax: *fancyindex_hide_symlinks* [*on* | *off*]
+:Default: fancyindex_hide_symlinks off
+:Context: http, server, location
+:Description:
+  When enabled, generated listings will not contain symbolic links.
+
 fancyindex_localtime
 ~~~~~~~~~~~~~~~~~~~~
 :Syntax: *fancyindex_localtime* [*on* | *off*]
diff --git a/ngx_http_fancyindex_module.c b/ngx_http_fancyindex_module.c
index 03eefd1..3527cd0 100644
--- a/ngx_http_fancyindex_module.c
+++ b/ngx_http_fancyindex_module.c
@@ -44,6 +44,7 @@ typedef struct {
     ngx_flag_t localtime;    /**< File mtime dates are sent in local time. */
     ngx_flag_t exact_size;   /**< Sizes are sent always in bytes. */
     ngx_uint_t name_length;  /**< Maximum length of file names in bytes. */
+    ngx_flag_t hide_symlinks;/**< Hide symbolic links in listings. */
 
     ngx_str_t  header;       /**< File name for header, or empty if none. */
     ngx_str_t  footer;       /**< File name for footer, or empty if none. */
@@ -223,6 +224,14 @@ static ngx_command_t  ngx_http_fancyindex_commands[] = {
       0,
       NULL },
 
+    { ngx_string("fancyindex_hide_symlinks"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      offsetof(ngx_http_fancyindex_loc_conf_t, hide_symlinks),
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
     ngx_null_command
 };
 
@@ -497,6 +506,9 @@ make_content_buf(
         if (ngx_de_name(&dir)[0] == '.')
             continue;
 
+        if (alcf->hide_symlinks && ngx_de_is_link (&dir))
+            continue;
+
 #if NGX_PCRE
         {
             ngx_str_t str = { len, ngx_de_name(&dir) };
@@ -1185,12 +1197,13 @@ ngx_http_fancyindex_create_loc_conf(ngx_conf_t *cf)
      *    conf->footer.len   = 0
      *    conf->footer.data  = NULL
      */
-    conf->enable       = NGX_CONF_UNSET;
-    conf->default_sort = NGX_CONF_UNSET_UINT;
-    conf->localtime    = NGX_CONF_UNSET;
-    conf->name_length  = NGX_CONF_UNSET_UINT;
-    conf->exact_size   = NGX_CONF_UNSET;
-    conf->ignore       = NGX_CONF_UNSET_PTR;
+    conf->enable        = NGX_CONF_UNSET;
+    conf->default_sort  = NGX_CONF_UNSET_UINT;
+    conf->localtime     = NGX_CONF_UNSET;
+    conf->name_length   = NGX_CONF_UNSET_UINT;
+    conf->exact_size    = NGX_CONF_UNSET;
+    conf->ignore        = NGX_CONF_UNSET_PTR;
+    conf->hide_symlinks = NGX_CONF_UNSET;
 
     return conf;
 }
@@ -1212,6 +1225,7 @@ ngx_http_fancyindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
     ngx_conf_merge_str_value(conf->footer, prev->footer, "");
 
     ngx_conf_merge_ptr_value(conf->ignore, prev->ignore, NULL);
+    ngx_conf_merge_value(conf->hide_symlinks, prev->hide_symlinks, 0);
 
     return NGX_CONF_OK;
 }