mds/net-ftp/atftp/files/atftpd-filecase.diff
2009-03-19 18:09:00 +00:00

142 lines
4.4 KiB
Diff

* 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