From 35808e31f83f4f46869feb740b793aa5f3817e2e Mon Sep 17 00:00:00 2001
From: pancake <pancake@nopcode.org>
Date: Thu, 3 Jan 2013 01:43:23 +0100
Subject: [PATCH] Add io.zeromap to toggle old buggy mode doublemapping file to
 0

Add http.maxsize to define the maximum file size to be uploaded
Add http.upget config var (not yet implemented)
---
 libr/core/config.c        | 26 ++++++++++++---
 libr/core/rtr.c           | 66 ++++++++++++++++++++++++---------------
 libr/include/r_io.h       |  1 +
 libr/include/r_socket.h   |  2 +-
 libr/io/io.c              | 13 ++++++--
 libr/io/section.c         |  3 +-
 libr/socket/http_server.c |  4 +--
 shlr/www/new/index.html   |  4 +--
 shlr/www/upload.html      |  8 +++++
 9 files changed, 87 insertions(+), 40 deletions(-)
 create mode 100644 shlr/www/upload.html

diff --git a/libr/core/config.c b/libr/core/config.c
index 6ba357c200..caab4e072e 100644
--- a/libr/core/config.c
+++ b/libr/core/config.c
@@ -43,6 +43,14 @@ static int config_iomaxblk_callback(void *user, void *data) {
 	core->blocksize_max = node->i_value;
 	return R_TRUE;
 }
+
+static int config_iozeromap_callback(void *user, void *data) {
+	RCore *core = (RCore *) user;
+	RConfigNode *node = (RConfigNode *) data;
+	core->io->zeromap = node->i_value;
+	return R_TRUE;
+}
+
 static int config_ioffio_callback(void *user, void *data) {
 	RCore *core = (RCore *) user;
 	RConfigNode *node = (RConfigNode *) data;
@@ -641,10 +649,6 @@ R_API int r_core_config_init(RCore *core) {
 	r_config_desc (cfg, "cmd.vprompt", "Visual prompt commands");
 	r_config_set (cfg, "cmd.bp", "");
 	r_config_desc (cfg, "cmd.bp", "Command to executed every breakpoint hitted");
-	r_config_set (cfg, "http.sandbox", "false");
-	r_config_set_i (cfg, "http.timeout", 3);
-	r_config_set (cfg, "http.public", "false");
-	r_config_desc (cfg, "http.public", "set to true to listen on 0.0.0.0");
 #if __WINDOWS__
 	r_config_set (cfg, "http.browser", "start");
 #else
@@ -658,12 +662,22 @@ R_API int r_core_config_init(RCore *core) {
 	else r_config_set (cfg, "http.browser", "firefox");
 #endif
 	r_config_desc (cfg, "http.browser", "command to open http urls");
+	r_config_set (cfg, "http.sandbox", "false");
+	r_config_set_i (cfg, "http.timeout", 3);
+	r_config_desc (cfg, "http.timeout", "disconnect clients after N seconds if no data sent");
+	r_config_set (cfg, "http.public", "false");
+	r_config_desc (cfg, "http.public", "set to true to listen on 0.0.0.0");
 	r_config_set (cfg, "http.port", "9090");
 	r_config_desc (cfg, "http.root", "port to listen for http connections");
 	r_config_set (cfg, "http.root", WWWROOT);
 	r_config_desc (cfg, "http.root", "http root directory");
+
 	r_config_set (cfg, "http.upload", "false");
-	r_config_desc (cfg, "http.upload", "enable file uploads");
+	r_config_desc (cfg, "http.upload", "enable file POST uploads in /up/<filename>");
+	r_config_set_i (cfg, "http.maxsize", 0);
+	r_config_desc (cfg, "http.maxsize", "define maximum file size to upload");
+	r_config_set (cfg, "http.upget", "false");
+	r_config_desc (cfg, "http.upget", "/up/ can be GET, not only POST");
 	tmpdir = r_file_tmpdir ();
 	r_config_set (cfg, "http.uproot", tmpdir);
 	free (tmpdir);
@@ -716,6 +730,8 @@ R_API int r_core_config_init(RCore *core) {
 	r_config_desc (cfg, "search.align", "Only catch aligned search hits");
 
 	sprintf (buf, "%d", R_CORE_BLOCKSIZE_MAX);
+	r_config_set_cb (cfg, "io.zeromap", buf, &config_iozeromap_callback);
+	r_config_desc (cfg, "io.zeromap", "double map the last opened file to address zero");
 	r_config_set_cb (cfg, "io.maxblk", buf, &config_iomaxblk_callback);
 	r_config_desc (cfg, "io.maxblk", "set max block size (soft limit)");
 
diff --git a/libr/core/rtr.c b/libr/core/rtr.c
index 05db2231aa..fe2e07868c 100644
--- a/libr/core/rtr.c
+++ b/libr/core/rtr.c
@@ -86,13 +86,24 @@ R_API int r_core_rtr_http(RCore *core, int launch) {
 			continue;
 		}
 		if (!strcmp (rs->method, "GET")) {
+			if (!memcmp (rs->path, "/up/", 5)) {
+				if (r_config_get_i (core->config, "http.upget")) {
+// TODO: implement upget
+					r_socket_http_response (rs, 200,
+						"TODO\n", 0, NULL);
+				} else {
+					r_socket_http_response (rs, 403,
+						"Permission denied\n", 0, NULL);
+				}
+			} else
 			if (!memcmp (rs->path, "/cmd/", 5)) {
 				char *out, *cmd = rs->path+5;
 				r_str_uri_decode (cmd);
 				out = r_core_cmd_str_pipe (core, cmd);
 				if (out) {
 					char *res = r_str_uri_encode (out);
-					r_socket_http_response (rs, 200, out, 0, "Content-Type: text/plain\n");
+					r_socket_http_response (rs, 200, out, 0,
+						"Content-Type: text/plain\n");
 					free (out);
 					free (res);
 				} else r_socket_http_response (rs, 200, "", 0, NULL);
@@ -101,12 +112,15 @@ R_API int r_core_rtr_http(RCore *core, int launch) {
 				char path[1024];
 				// fix crosspath
 				if (rs->path [strlen (rs->path)-1] == '/') {
-					rs->path = r_str_concat (rs->path, "index.html");
+					rs->path = r_str_concat (rs->path,
+						"index.html");
 				} else {
 					snprintf (path, sizeof (path), "%s/%s", root, rs->path);
 					if (r_file_is_directory (path)) {
-						snprintf (path, sizeof (path), "Location: %s/\n", rs->path);
-						r_socket_http_response (rs, 302, NULL, 0, path);
+						snprintf (path, sizeof (path),
+							"Location: %s/\n", rs->path);
+						r_socket_http_response (rs, 302,
+							NULL, 0, path);
 						r_socket_http_close (rs);
 						continue;
 					}
@@ -130,33 +144,32 @@ R_API int r_core_rtr_http(RCore *core, int launch) {
 			}
 		} else 
 		if (!strcmp (rs->method, "POST")) {
-			const ut8 *ret;
+			ut8 *ret;
 			int retlen;
 			char buf[128];
 			if (r_config_get_i (core->config, "http.upload")) {
-			ret = r_socket_http_handle_upload (
-				rs->data, rs->data_length, &retlen);
-			if (ret) {
-				char *filename = r_file_root (
-					r_config_get (core->config, "http.uproot"),
-					rs->path + 4);
-				eprintf ("UPLOADED '%s'\n", filename);
-				r_file_dump (filename, ret, retlen);
-				free (filename);
-				free (ret);
-			} else {
-				r_str_uri_decode ((char *)rs->data);
-			}
-			snprintf (buf, sizeof (buf),
-				"<html><body><h2>uploaded %d bytes. Thanks</h2>\n", retlen);
-				r_socket_http_response (rs, 200, buf, 0, NULL);
+				ret = r_socket_http_handle_upload (
+					rs->data, rs->data_length, &retlen);
+				if (ret) {
+					ut64 size = r_config_get_i (core->config, "http.maxsize");
+					if (size && retlen > size) {
+						r_socket_http_response (rs, 403, "403 File too big\n", 0, NULL);
+					} else {
+						char *filename = r_file_root (
+							r_config_get (core->config, "http.uproot"),
+							rs->path + 4);
+						eprintf ("UPLOADED '%s'\n", filename);
+						r_file_dump (filename, ret, retlen);
+						free (filename);
+						snprintf (buf, sizeof (buf),
+							"<html><body><h2>uploaded %d bytes. Thanks</h2>\n", retlen);
+							r_socket_http_response (rs, 200, buf, 0, NULL);
+					}
+					free (ret);
+				}
 			} else {
 				r_socket_http_response (rs, 403, "403 Forbidden\n", 0, NULL);
 			}
-#if 0
-			strcat (buf, (char*)rs->data);
-			strcat (buf, ret);
-#endif
 		} else {
 			r_socket_http_response (rs, 404, "Invalid protocol", 0, NULL);
 		}
@@ -378,7 +391,8 @@ R_API void r_core_rtr_session(RCore *core, const char *input) {
 
 	if (input[0] >= '0' && input[0] <= '9') {
 		fd = r_num_math (core->num, input);
-		for (rtr_n = 0; rtr_host[rtr_n].fd->fd != fd && rtr_n < RTR_MAX_HOSTS; rtr_n++);
+		for (rtr_n = 0; rtr_host[rtr_n].fd->fd != fd \
+			&& rtr_n < RTR_MAX_HOSTS; rtr_n++);
 	}
 
 	for (;;) {
diff --git a/libr/include/r_io.h b/libr/include/r_io.h
index b39bd30d38..abb211e24f 100644
--- a/libr/include/r_io.h
+++ b/libr/include/r_io.h
@@ -124,6 +124,7 @@ typedef struct r_io_t {
 	RList *maps; /*<RIOMap>*/
 	RList *desc;
 	RList *cache;
+	int zeromap;
 	//XXX: Need by rap
 	void *user;
 	int (*core_cmd_cb)(void *user, const char *str);
diff --git a/libr/include/r_socket.h b/libr/include/r_socket.h
index 86f171ce38..9674f43df8 100644
--- a/libr/include/r_socket.h
+++ b/libr/include/r_socket.h
@@ -83,6 +83,6 @@ typedef struct r_socket_http_request {
 R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, int timeout);
 R_API void r_socket_http_response (RSocketHTTPRequest *rs, int code, const char *out, int x, const char *headers);
 R_API void r_socket_http_close (RSocketHTTPRequest *rs);
-R_API char *r_socket_http_handle_upload(const ut8 *str, int len, int *olen);
+R_API ut8 *r_socket_http_handle_upload(const ut8 *str, int len, int *olen);
 #endif
 #endif
diff --git a/libr/io/io.c b/libr/io/io.c
index fc34c4aa10..a01d80f452 100644
--- a/libr/io/io.c
+++ b/libr/io/io.c
@@ -10,6 +10,7 @@
 R_API RIO *r_io_new() {
 	RIO *io = R_NEW (RIO);
 	if (!io) return NULL;
+	io->zeromap = R_FALSE; // if true, then 0 is mapped with contents of file
 	io->fd = NULL;
 	io->write_mask_fd = -1;
 	io->redirect = NULL;
@@ -123,7 +124,7 @@ R_API RIODesc *r_io_open(RIO *io, const char *file, int flags, int mode) {
 		} else fd = r_sandbox_open (uri, O_BINARY);
 #else
 		fd = r_sandbox_open (uri, (flags&R_IO_WRITE)?
-			O_RDWR:O_RDONLY, mode);
+			O_RDWR: O_RDONLY, mode);
 #endif
 	}
 	if (fd >= 0) {
@@ -178,7 +179,7 @@ R_API int r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
 	int ret, l, olen = len;
 	int w = 0;
 
-	r_io_seek (io, addr, R_IO_SEEK_SET);
+	//r_io_seek (io, addr, R_IO_SEEK_SET);
 	// XXX: this is buggy!
 	memset (buf, 0xff, len);
 	while (len>0) {
@@ -193,6 +194,14 @@ R_API int r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
 			memset (buf+w, 0xff, l);
 			return -1;
 		}
+		if (!io->zeromap)
+			if (!r_io_map_get (io, addr+w)) {
+				if (r_io_section_getv (io, addr+w)) {
+					memset (buf+w, 0xff, l);
+					return -1;
+				}
+			}
+		// XXX is this necessary?
 		ms = r_io_map_select (io, addr+w);
 		ret = r_io_read_internal (io, buf+w, l);
 		if (ret<1) {
diff --git a/libr/io/section.c b/libr/io/section.c
index 541edf66ea..a7f67c39ec 100644
--- a/libr/io/section.c
+++ b/libr/io/section.c
@@ -160,9 +160,8 @@ R_API RIOSection *r_io_section_getv(RIO *io, ut64 vaddr) {
 	RListIter *iter;
 	RIOSection *s;
 	r_list_foreach (io->sections, iter, s) {
-		if (vaddr >= s->vaddr && vaddr < s->vaddr + s->vsize) {
+		if (vaddr >= s->vaddr && vaddr < s->vaddr + s->vsize)
 			return s;
-		}
 	}
 	return NULL;
 }
diff --git a/libr/socket/http_server.c b/libr/socket/http_server.c
index 88bc4da9c6..f02a85c07c 100644
--- a/libr/socket/http_server.c
+++ b/libr/socket/http_server.c
@@ -73,7 +73,7 @@ R_API void r_socket_http_response (RSocketHTTPRequest *rs, int code, const char
 	if (out && len>0) r_socket_write (rs->s, (void*)out, len);
 }
 
-R_API char *r_socket_http_handle_upload(const ut8 *str, int len, int *retlen) {
+R_API ut8 *r_socket_http_handle_upload(const ut8 *str, int len, int *retlen) {
 	if (retlen)
 		*retlen = 0;
 	if (!strncmp ((const char *)str, "------------------------------", 10)) {
@@ -98,7 +98,7 @@ R_API char *r_socket_http_handle_upload(const ut8 *str, int len, int *retlen) {
 			ret[datalen] = 0;
 			if (retlen)
 				*retlen = datalen;
-			return ret;
+			return (ut8*)ret;
 		}
 	}
 	return NULL;
diff --git a/shlr/www/new/index.html b/shlr/www/new/index.html
index a1a7323a90..7633c3429a 100644
--- a/shlr/www/new/index.html
+++ b/shlr/www/new/index.html
@@ -53,8 +53,8 @@ Lungo.init ({
 </script>
 <!-- windows -->
 
-  <div id="exampleB" style="position:fixed!important;top:200px;left:10;width:250px;height:350px;background-color:#e0e0e0;border: 1px solid black;z-index:99">
-    <div id="exampleBHandle" style="height:20px;left:0px;top:0px;cursor:move;width:248px;background-color:#20a0e0;font-weight:bold;color:white;border:1px solid black">&nbsp;Registers</div>
+  <div id="exampleB" style="position:fixed!important;top:200px;left:10;width:250px;height:350px;background-color:#e0e0e0;border: 1px solid black;z-index:999">
+    <div id="exampleBHandle" style="height:20px;left:0px;top:0px;cursor:move;width:248px;background-color:#20a0e0;font-weight:bold;color:white;z-index:1000;border:1px solid black">&nbsp;Registers</div>
 <div style="margin:5px">
 <br /><br />
 <pre>
diff --git a/shlr/www/upload.html b/shlr/www/upload.html
new file mode 100644
index 0000000000..714267ef48
--- /dev/null
+++ b/shlr/www/upload.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<form action="/up/test.bin" enctype="multipart/form-data" method="post">
+<input type="file" name="file" />
+<input type="submit" value="Upload" />
+</form>
+</body>
+</html>