PR-13708279.diff   [plain text]


--- server/request.c	2016-04-01 05:36:42.000000000 -0700
+++ server/request.c	2016-07-26 15:22:47.000000000 -0700
@@ -105,6 +105,11 @@
 static int auth_internal_per_conf_hooks = 0;
 static int auth_internal_per_conf_providers = 0;
 
+#ifndef DARWIN
+#define files_strcmp(s1, s2, case_sensative, r) strcmp((s1, (s2))
+#else
+static int files_strcmp(const char *s1, const char *s2, int case_sensative, request_rec *r);
+#endif
 
 static int decl_die(int status, const char *phase, request_rec *r)
 {
@@ -1581,6 +1586,72 @@
     return OK;
 }
 
+
+#ifdef DARWIN
+#include <CoreFoundation/CoreFoundation.h>
+
+#define release_if_non_nil(cfptr) do { if ((cfptr)) { CFRelease(cfptr); (cfptr) = NULL; } } while(0);
+
+static int  files_strcmp(const char *s1, const char *s2, int case_sensitive, request_rec *r) {
+    int retval = 1;             // default to not matching
+    
+    if (strcmp(s1, s2) == 0) {
+        retval = 0;
+    } 
+    else {
+        if (case_sensitive) {
+            return retval;
+        }
+        
+        CFMutableStringRef str1 = CFStringCreateMutable(kCFAllocatorDefault, 0);
+        CFMutableStringRef str2 = CFStringCreateMutable(kCFAllocatorDefault, 0);
+        
+        if ((!str1) || (!str2)) {
+            release_if_non_nil(str1);
+            release_if_non_nil(str2);
+            return retval;
+        }
+        
+        CFStringAppendCString(str1, s1, kCFStringEncodingUTF8);
+        CFStringAppendCString(str2, s2, kCFStringEncodingUTF8);
+
+        // allocate the test buffers
+        CFIndex str1_fsr_len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str1), kCFStringEncodingUTF8);
+        CFIndex str2_fsr_len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str2), kCFStringEncodingUTF8);
+        char *str1_fsr = apr_pcalloc(r->pool, str1_fsr_len);
+        char *str2_fsr = apr_pcalloc(r->pool, str2_fsr_len);
+        
+        if ((!str1_fsr) || (!str2_fsr)) {
+            goto cleanup;
+        }
+        
+        CFLocaleRef locale = CFLocaleCopyCurrent();
+        CFStringLowercase(str1, locale);
+        CFStringLowercase(str2, locale);
+        CFRelease(locale);
+        
+        if (!CFStringGetFileSystemRepresentation(str1, str1_fsr, str1_fsr_len)) {
+            goto cleanup;
+        }
+        
+        if (!CFStringGetFileSystemRepresentation(str2, str2_fsr, str2_fsr_len)) {
+            goto cleanup;
+        }
+        
+        if (strcmp(str1_fsr, str2_fsr) == 0) {
+            retval = 0;
+        } 
+    cleanup:        
+        release_if_non_nil(str1);
+        release_if_non_nil(str2);
+
+    }
+    
+    return retval;
+}
+
+#endif
+
 AP_DECLARE(int) ap_file_walk(request_rec *r)
 {
     ap_conf_vector_t *now_merged = NULL;
@@ -1590,6 +1663,7 @@
     walk_cache_t *cache;
     const char *test_file;
     int cached;
+    int case_sensitive;
 
     if (dconf->sec_file) {
         sec_ent = (ap_conf_vector_t **)dconf->sec_file->elts;
@@ -1626,13 +1700,22 @@
         test_file = apr_pstrdup(r->pool, ++test_file);
     }
 
+#ifdef DARWIN
+    case_sensitive = pathconf(r->filename, _PC_CASE_SENSITIVE);
+    if (case_sensitive == -1) {
+	case_sensitive = 1;	// nonexistant paths are case sensative
+    }
+#else
+    case_sensitive = 0;
+#endif
+
     /* If we have an cache->cached file name that matches test_file,
      * and the directory's list of file sections hasn't changed, we
      * can skip rewalking the file_walk entries.
      */
     if (cached
         && (cache->dir_conf_tested == sec_ent)
-        && (strcmp(test_file, cache->cached) == 0)) {
+        && (files_strcmp(test_file, cache->cached, case_sensitive, r) == 0)) {
         /* Well this looks really familiar!  If our end-result (per_dir_result)
          * didn't change, we have absolutely nothing to do :)
          * Otherwise (as is the case with most dir_merged requests)
@@ -1701,7 +1784,7 @@
             else {
                 if ((entry_core->d_is_fnmatch
                        ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
-                       : strcmp(entry_core->d, cache->cached))) {
+                       : files_strcmp(entry_core->d, cache->cached, case_sensitive, r))) {
                     continue;
                 }
             }