* Case insensitive lookup patch for atftpd
*
* Copyright (c) 2006-2007 Gianluigi Tiesi <sherpya@netfarm.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this software; if not, write to the
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

diff -Nur atftp-0.7.dfsg.orig/tftpd.c atftp-0.7.dfsg/tftpd.c
--- atftp-0.7.dfsg.orig/tftpd.c	2007-12-09 06:06:20.000000000 +0100
+++ atftp-0.7.dfsg/tftpd.c	2007-12-09 06:08:51.229707272 +0100
@@ -667,6 +667,15 @@
           switch (retval)
           {
           case GET_RRQ:
+                if (data->tftp_options[OPT_FILENAME].value[0] == '\\')
+                    if (!tftpd_lookup_file(directory, data->tftp_options[OPT_FILENAME].value))
+                    {
+                        /* Short circuit */
+                        tftp_send_error(data->sockfd, &data->client_info->client,
+                                        ENOTFOUND, data->data_buffer, data->data_buffer_size);
+                        stats_err_locked();
+                        break;
+                    }
                logger(LOG_NOTICE, "Serving %s to %s:%d",
                       data->tftp_options[OPT_FILENAME].value,
                       inet_ntoa(data->client_info->client.sin_addr),
diff -Nur atftp-0.7.dfsg.orig/tftpd.h atftp-0.7.dfsg/tftpd.h
--- atftp-0.7.dfsg.orig/tftpd.h	2004-02-27 03:05:26.000000000 +0100
+++ atftp-0.7.dfsg/tftpd.h	2007-12-09 06:06:35.319368784 +0100
@@ -77,6 +77,7 @@
 /*
  * Functions defined in tftpd_file.c
  */
+int tftpd_lookup_file(const char *directory, char *filename);
 int tftpd_rules_check(char *filename);
 int tftpd_receive_file(struct thread_data *data);
 int tftpd_send_file(struct thread_data *data);
diff -Nur atftp-0.7.dfsg.orig/tftpd_file.c atftp-0.7.dfsg/tftpd_file.c
--- atftp-0.7.dfsg.orig/tftpd_file.c	2004-02-18 03:21:47.000000000 +0100
+++ atftp-0.7.dfsg/tftpd_file.c	2007-12-09 06:09:23.683773504 +0100
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <dirent.h>
 #include <sys/stat.h>
 #include "tftpd.h"
 #include "tftp_io.h"
@@ -60,6 +61,81 @@
 extern tftpd_pcre_self_t *pcre_top;
 #endif
 
+/*
+ *  Case insensitive file lookup, for windows clients
+ */
+
+int tftpd_lookup_entry(const char *comp, char *dest)
+{
+    DIR *dirp;
+    struct dirent *dptr;
+    dirp = opendir(dest);
+    if (!dirp) return 0;
+    while ((dptr = readdir(dirp)))
+    {
+          if (!strcasecmp(dptr->d_name, comp))
+          {
+                 strcat(dest, "/");
+                 strcat(dest, dptr->d_name);
+                 closedir(dirp);
+                 return 1;
+          }
+    }
+    closedir(dirp);
+    return 0;
+}
+
+int tftpd_lookup_file(const char *directory, char *filename)
+{
+    int found = 0;
+    int len = 0;
+    char dest[MAXLEN];
+    char comp[MAXLEN];
+    char *check = filename;
+    char *seek = NULL;
+
+    dest[0] = 0;
+    strcat(dest, directory);
+    len = strlen(dest);
+    if (dest[len-1] == '/')
+        dest[len-1] = 0;
+    check++;
+    while (*check)
+    {
+         seek = strchr(check, '\\');
+         if (!seek)
+         {
+                if ((*check) && (tftpd_lookup_entry(check, dest)))
+                      found = 1;
+                break;
+         }
+         len = seek - check;
+         memcpy(comp, check, len);
+         comp[len]=0;
+         if (!tftpd_lookup_entry(comp, dest))
+                break;
+         check += len + 1;
+    }
+    
+    if (found)
+    {
+         filename[0] = 0;
+         strcat(filename, dest + strlen(directory));
+    }
+    else
+    {
+         seek = filename;
+         while (*seek)
+         {
+             if (*seek == '\\') *seek = '/';
+             seek++;
+         }
+         filename++;
+    }
+
+    logger(LOG_DEBUG, "Filecase lookup file: %s (found %s)", filename, (found ? "yes" : "no"));
+    return found;
+}
 
 /*
  * Rules for filenames. This is common to both tftpd_recieve_file