Index: uKadecot/trunk/uip/apps/webserver/http-strings
===================================================================
--- uKadecot/trunk/uip/apps/webserver/http-strings	(revision 154)
+++ uKadecot/trunk/uip/apps/webserver/http-strings	(revision 155)
@@ -8,5 +8,5 @@
 http_content_type "content-type: "
 http_texthtml "text/html"
-http_location "location: "
+http_location "Location: "
 http_host "host: "
 http_crnl "\r\n"
@@ -21,4 +21,5 @@
 http_header_101 "HTTP/1.1 101 Switching Protocols\r\n"
 http_header_200 "HTTP/1.1 200 OK\r\nServer: uIP/1.0 http://www.toppers.jp/\r\nConnection: close\r\n"
+http_header_301 "HTTP/1.1 301 Moved Permanently\r\nServer: uIP/1.0 http://www.toppers.jp/\r\nConnection: close\r\n"
 http_header_404 "HTTP/1.1 404 Not found\r\nServer: uIP/1.0 http://www.toppers.jp/\r\nConnection: close\r\n"
 http_content_encoding_gzip "Content-Encoding: gzip\r\n"
Index: uKadecot/trunk/uip/apps/webserver/http-strings.c
===================================================================
--- uKadecot/trunk/uip/apps/webserver/http-strings.c	(revision 154)
+++ uKadecot/trunk/uip/apps/webserver/http-strings.c	(revision 155)
@@ -27,6 +27,6 @@
 {0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, };
 const char http_location[11] = 
-/* "location: " */
-{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, };
+/* "Location: " */
+{0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, };
 const char http_host[7] = 
 /* "host: " */
@@ -65,4 +65,7 @@
 /* "HTTP/1.1 200 OK\r\nServer: uIP/1.0 http://www.toppers.jp/\r\nConnection: close\r\n" */
 {0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x6a, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, };
+const char http_header_301[92] = 
+/* "HTTP/1.1 301 Moved Permanently\r\nServer: uIP/1.0 http://www.toppers.jp/\r\nConnection: close\r\n" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x20, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x6a, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, };
 const char http_header_404[84] = 
 /* "HTTP/1.1 404 Not found\r\nServer: uIP/1.0 http://www.toppers.jp/\r\nConnection: close\r\n" */
Index: uKadecot/trunk/uip/apps/webserver/http-strings.h
===================================================================
--- uKadecot/trunk/uip/apps/webserver/http-strings.h	(revision 154)
+++ uKadecot/trunk/uip/apps/webserver/http-strings.h	(revision 155)
@@ -21,4 +21,5 @@
 extern const char http_header_101[35];
 extern const char http_header_200[77];
+extern const char http_header_301[92];
 extern const char http_header_404[84];
 extern const char http_content_encoding_gzip[25];
Index: uKadecot/trunk/uip/apps/webserver/httpd-fs.c
===================================================================
--- uKadecot/trunk/uip/apps/webserver/httpd-fs.c	(revision 154)
+++ uKadecot/trunk/uip/apps/webserver/httpd-fs.c	(revision 155)
@@ -40,4 +40,11 @@
 #include "mmc_rspi.h"
 #include <string.h>
+#include "http-strings.h"
+
+#ifndef _MSC_VER
+#ifndef strcat_s
+#define strcat_s(dst, dsz, src) strcat(dst, src)
+#endif
+#endif
 
 //#define FILE_DUMP
@@ -114,8 +121,10 @@
 /*-----------------------------------------------------------------------------------*/
 int
-httpd_fs_open(int drv, const char *name, struct httpd_fs_file *file)
+httpd_fs_open(int drv, char *name, int len, struct httpd_fs_file *file)
 {
 	FRESULT res;
-	FATFS *fs = (FATFS *)file->fs;
+	FATFS *fs = (FATFS *)&file->fs;
+	FILINFO fno;
+	DIR dir;
 
 	file->pos = 0;
@@ -123,4 +132,5 @@
 	file->drv = drv;
 	file->name = name;
+	file->redirect = 0;
 	memset(fs, 0, sizeof(FATFS));
 
@@ -143,7 +153,28 @@
 	}
 
-	if((res = pf_open(fs, name)) != FR_OK){
-		printf("pf_open(%d:%s) => %d\n", drv, name, res);
-		return 0;
+	if ((res = pf_open(fs, name)) != FR_OK) {
+		dir.fs = fs;
+		if ((res = pf_opendir(&dir, name)) != FR_OK) {
+			printf("pf_opendir(%d:%s) => %d\n", drv, name, res);
+			return 0;
+		}
+
+		if ((res = pf_readdir(&dir, &fno)) != FR_OK) {
+			printf("pf_readdir(%d:%s) => %d\n", drv, name, res);
+			return 0;
+		}
+
+		if (len != 0/*fno.fattrib & AM_DIR*/) {
+			strcat_s(name, len, http_index_html);
+			res = pf_open(fs, name);
+			file->redirect = res == FR_OK;
+		}
+		else
+			res = FR_NO_FILE;
+
+		if (res != FR_OK) {
+			printf("pf_open(%d:%s) => %d %x\n", drv, name, res, fno.fattrib);
+			return 0;
+		}
 	}
 
@@ -160,5 +191,5 @@
 	FRESULT ret;
 	UINT rlen;
-	FATFS *fs = (FATFS *)file->fs;
+	FATFS *fs = (FATFS *)&file->fs;
 
 	if((ret = pf_lseek(fs, file->pos)) != FR_OK){
Index: uKadecot/trunk/uip/apps/webserver/httpd-fs.h
===================================================================
--- uKadecot/trunk/uip/apps/webserver/httpd-fs.h	(revision 154)
+++ uKadecot/trunk/uip/apps/webserver/httpd-fs.h	(revision 155)
@@ -43,10 +43,11 @@
   int drv;
   const char *name;
-  void *fs;
+  int redirect;
+  char fs[64 + 512/*sizeof(FATFS)*/];
 };
 
 /* file must be allocated by caller and will be filled in
    by the function. */
-int httpd_fs_open(int drv, const char *name, struct httpd_fs_file *file);
+int httpd_fs_open(int drv, char *name, int len, struct httpd_fs_file *file);
 int httpd_fs_read(struct httpd_fs_file *file, void *dst, int len);
 
Index: uKadecot/trunk/uip/apps/webserver/httpd.c
===================================================================
--- uKadecot/trunk/uip/apps/webserver/httpd.c	(revision 154)
+++ uKadecot/trunk/uip/apps/webserver/httpd.c	(revision 155)
@@ -203,4 +203,17 @@
   }
 
+  if (s->file.redirect) {
+    len = strlen(http_location);
+    memcpy(pos, http_location, len); pos += len;
+    if (s->drv == 1) {
+      len = 2;
+      memcpy(pos, "/~", len); pos += len;
+    }
+    len = strlen(s->filename);
+    memcpy(pos, s->filename, len); pos += len;
+    len = 2;
+    memcpy(pos, "\r\n", len); pos += len;
+  }
+
   ptr = strrchr(s->message.request_url, ISO_period);
   if (ptr == NULL) {
@@ -248,10 +261,8 @@
   PT_BEGIN(&s->outputpt);
 
-  s->file.fs = ((char *)&s[1]) - 64 - 512;
-
-  if (!httpd_fs_open(s->drv, s->filename, &s->file)) {
+  if (!httpd_fs_open(s->drv, s->filename, sizeof(s->filename), &s->file)) {
     s->drv = 0;
-    httpd_fs_open(s->drv, http_404_html, &s->file);
-    strcpy_s(s->message.request_url, sizeof(s->message.request_url), http_404_html);
+    strcpy_s(s->filename, sizeof(s->filename), http_404_html);
+    httpd_fs_open(s->drv, s->filename, sizeof(s->filename), &s->file);
     PT_WAIT_THREAD(&s->outputpt,
       send_headers(s,
@@ -261,5 +272,5 @@
     PT_WAIT_THREAD(&s->outputpt,
       send_headers(s,
-      http_header_200));
+      s->file.redirect ? http_header_301 : http_header_200));
     PT_WAIT_THREAD(&s->outputpt, send_file(s));
   }
@@ -381,4 +392,6 @@
   size_t done;
   const char *data;
+  char *ptr;
+
   PSOCK_BEGIN(&s->sin);
 
@@ -407,16 +420,20 @@
   /* ""か"/"なら"index.html"に変更 */
   if ((s->message.request_url[0] == '\0') || ((s->message.request_url[0] == '/') && (s->message.request_url[1] == '\0'))) {
-    strncpy_s(s->message.request_url, sizeof(s->message.request_url), http_index_html, sizeof(s->message.request_url));
-    s->filename = s->message.request_url;
+    s->drv = 0;
+    strcpy_s(s->filename, sizeof(s->filename), http_index_html);
   }
   /* "/~/"ならSDカードから読み込み */
   else if ((s->message.request_url[0] == '/') && (s->message.request_url[1] == '~') && (s->message.request_url[2] == '/')) {
     s->drv = 1;
-    s->filename = &s->message.request_url[2];
+    strcpy_s(s->filename, sizeof(s->filename), &s->message.request_url[2]);
   }
   else {
     s->drv = 0;
-    s->filename = s->message.request_url;
-  }
+    strcpy_s(s->filename, sizeof(s->filename), s->message.request_url);
+  }
+
+  ptr = strrchr(s->filename, '?');
+  if (ptr != NULL)
+    ptr[0] = '\0';
 
   /*  httpd_log_file(uip_conn->ripaddr, s->message.request_url);*/
@@ -426,4 +443,5 @@
     s->state = STATE_WS_OUTPUT;
 
+    s->close_req = 0;
     websocket_init(&s->websocket, uip_getid((struct uip_conn *)((intptr_t)s - offsetof(struct uip_conn, appstate))));
     for (;;) {
Index: uKadecot/trunk/uip/apps/webserver/httpd.h
===================================================================
--- uKadecot/trunk/uip/apps/webserver/httpd.h	(revision 154)
+++ uKadecot/trunk/uip/apps/webserver/httpd.h	(revision 155)
@@ -47,15 +47,25 @@
   char inputbuf[50];
   char state;
-  int drv;
-  char *filename;
-  int len;
-  struct httpd_fs_file file;
-  int parse_pos;
-  int parse_len;
-  struct http_parser parser;
-  struct http_parser_url handle;
-  struct message message;
-  struct websocket websocket;
-  int close_req;
+  union{
+    struct{
+      int parse_pos;
+      int parse_len;
+      struct http_parser parser;
+      struct http_parser_url handle;
+      struct message message;
+    };
+    struct{
+      char _dummy1[340];
+      int drv;
+      char filename[256];
+      int len;
+      struct httpd_fs_file file;
+    };
+    struct{
+      char _dummy2[340];
+      struct websocket websocket;
+      int close_req;
+    };
+  };
 };
 #define get_context(p) (struct httpd_state *)((intptr_t)p - (intptr_t)&((struct httpd_state *)0)->parser)
