Hi,

I would like to send a couple of patches for quark. I made more
changes to quark for my own purposes, but I thought the below changes
might be useful for the suckless quark aswell :) . Feel free to apply
any patch (or none) you want.

Attachments:

Fixes:
======

0001-http-status-moved-permanently-is-code-301.patch:
    change the HTTP status code of "moved permanently" from 302 (moved
temporary) to 301.

0002-remove-unused-code.patch:
    removed some unused code.

Features:
=========

0003-implement-http-not-modified.patch:

    On each request quark sends the "last-modified" header with the
modification time of the requested file. The clients browser might
store this field and use it on the next request(s). Quark will check
the "if-modified-since" field with the modified date sent by the
client, depending on this send all the data or the "304 not modified"
http status.

    CAVEAT: it is assumed the exact field will be send by the client,
no date/time conversion is done for simplicity sake, as far as that's
possible with http ;)

The patches are also available at:
http://www.codemadness.nl/downloads/patches/quark/

Kind regards,
Hiltjo
From b6365cb19fef52e6d2ecc0dfe4d39c69c4c6099b Mon Sep 17 00:00:00 2001
From: Hiltjo Posthuma <[email protected]>
Date: Sat, 15 Feb 2014 14:31:14 +0100
Subject: [PATCH 1/3] http status moved permanently is code 301

Signed-off-by: Hiltjo Posthuma <[email protected]>
---
 quark.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/quark.c b/quark.c
index 234f6e2..152476a 100644
--- a/quark.c
+++ b/quark.c
@@ -53,7 +53,7 @@ typedef struct {
 } RequestHandler;
 
 static const char HttpOk[]           = "200 OK";
-static const char HttpMoved[]        = "302 Moved Permanently";
+static const char HttpMoved[]        = "301 Moved Permanently";
 static const char HttpUnauthorized[] = "401 Unauthorized";
 static const char HttpNotFound[]     = "404 Not Found";
 static const char texthtml[]         = "text/html";
-- 
1.8.5.3

From 3ebbf1c0dd5dfaee56e6fae28cefb7756180ff22 Mon Sep 17 00:00:00 2001
From: Hiltjo Posthuma <[email protected]>
Date: Sat, 15 Feb 2014 15:09:55 +0100
Subject: [PATCH 2/3] remove unused code

Signed-off-by: Hiltjo Posthuma <[email protected]>
---
 quark.c | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/quark.c b/quark.c
index 152476a..565e091 100644
--- a/quark.c
+++ b/quark.c
@@ -31,27 +31,11 @@ typedef struct {
 	const char *mimetype;
 } MimeType;
 
-typedef struct _Param Param;
-struct _Param {
-	const char *key;
-	const char *value;
-	Param *next;
-};
-
 typedef struct {
 	int type;
 	int fd;
-	const char *hostname;
-	const char *resource;
-	Param *params;
 } Request;
 
-typedef struct {
-	const char *hostname;
-	const char *resource;
-	void (*handle)(const Request *r);
-} RequestHandler;
-
 static const char HttpOk[]           = "200 OK";
 static const char HttpMoved[]        = "301 Moved Permanently";
 static const char HttpUnauthorized[] = "401 Unauthorized";
-- 
1.8.5.3

From aca12949c1ca39a107abdd02ca76b4a5937ca643 Mon Sep 17 00:00:00 2001
From: Hiltjo Posthuma <[email protected]>
Date: Sat, 15 Feb 2014 15:36:52 +0100
Subject: [PATCH 3/3] implement http not modified

On each request send "last-modified" header with the modification time of
each file. the client will store this field and send it on the next
request(s). On the server check the "if-modified-since" field with the
modified date sent by the client, depending on this send all the data or
the "304 not modified" http status.

CAVEAT: it is assumed the exact field will be send by the client, no date/time
conversion is done for simplicity sake, as far as that's possible with http ;)

Signed-off-by: Hiltjo Posthuma <[email protected]>
---
 quark.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 57 insertions(+), 18 deletions(-)

diff --git a/quark.c b/quark.c
index 565e091..33f5b10 100644
--- a/quark.c
+++ b/quark.c
@@ -38,6 +38,7 @@ typedef struct {
 
 static const char HttpOk[]           = "200 OK";
 static const char HttpMoved[]        = "301 Moved Permanently";
+static const char HttpNotModified[]  = "304 Not Modified";
 static const char HttpUnauthorized[] = "401 Unauthorized";
 static const char HttpNotFound[]     = "404 Not Found";
 static const char texthtml[]         = "text/html";
@@ -67,6 +68,7 @@ static char host[NI_MAXHOST];
 static char reqbuf[MAXBUFLEN+1];
 static char resbuf[MAXBUFLEN+1];
 static char reqhost[256];
+static char reqmod[256];
 static int fd;
 static Request req;
 
@@ -184,6 +186,18 @@ responsecontenttype(const char *mimetype) {
 	return writetext(resbuf);
 }
 
+int
+responsemodified(char *mod) {
+    if(snprintf(resbuf, MAXBUFLEN,
+        "Last-Modified: %s\r\n",
+        mod) >= MAXBUFLEN)
+    {
+        logerrmsg("snprintf failed, buffer sizeof exceeded");
+        return -1;
+    }
+    return writetext(resbuf);
+}
+
 void
 responsefiledata(int fd, off_t size) {
 	char buf[BUFSIZ];
@@ -200,10 +214,13 @@ void
 responsefile(void) {
 	const char *mimetype = "unknown";
 	char *p;
-	int i, ffd;
+	char mod[25];
+	int i, ffd, r;
 	struct stat st;
+	time_t t;
 
-	if(stat(reqbuf, &st) == -1 || (ffd = open(reqbuf, O_RDONLY)) == -1) {
+	r = stat(reqbuf, &st);
+	if(r == -1 || (ffd = open(reqbuf, O_RDONLY)) == -1) {
 		logerrmsg("%s requests unknown path %s\n", host, reqbuf);
 		if(responsehdr(HttpNotFound) != -1
 		&& responsecontenttype(texthtml) != -1)
@@ -214,22 +231,33 @@ responsefile(void) {
 			writetext("\r\n<html><body>404 Not Found</body></html>\r\n");
 	}
 	else {
-		if((p = strrchr(reqbuf, '.'))) {
-			p++;
-			for(i = 0; i < LENGTH(servermimes); i++)
-				if(!strcmp(servermimes[i].extension, p)) {
-					mimetype = servermimes[i].mimetype;
-					break;
-				}
+		t = st.st_mtim.tv_sec;
+		memcpy(mod, asctime(gmtime(&t)), 24);
+		mod[24] = 0;
+		if(!strcmp(reqmod, mod)) {
+			if(responsehdr(HttpNotModified) != -1)
+				;
+			else
+				return;
+		} else {
+			if((p = strrchr(reqbuf, '.'))) {
+				p++;
+				for(i = 0; i < LENGTH(servermimes); i++)
+					if(!strcmp(servermimes[i].extension, p)) {
+						mimetype = servermimes[i].mimetype;
+						break;
+					}
+			}
+			if(responsehdr(HttpOk) != -1
+			&& responsemodified(mod) != -1
+			&& responsecontentlen(st.st_size) != -1
+			&& responsecontenttype(mimetype) != -1)
+				;
+			else
+				return;
+			if(req.type == GET && writetext("\r\n") != -1)
+				responsefiledata(ffd, st.st_size);
 		}
-		if(responsehdr(HttpOk) != -1
-		&& responsecontentlen(st.st_size) != -1
-		&& responsecontenttype(mimetype) != -1)
-			;
-		else
-			return;
-		if(req.type == GET && writetext("\r\n") != -1)
-			responsefiledata(ffd, st.st_size);
 		close(ffd);
 	}
 }
@@ -388,12 +416,23 @@ request(void) {
 		for(p = res; *p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n'; p++);
 		if(!*p)
 			goto invalid_request;
-		*p = 0;
 		if(p - res > sizeof reqhost)
 			goto invalid_request;
 		memcpy(reqhost, res, p - res);
 		reqhost[p - res] = 0;
 	}
+	if((res = strstr(reqbuf, "If-Modified-Since:"))) {
+		for(res = res + 19; *res && (*res == ' ' || *res == '\t'); res++);
+		if(!*res)
+			goto invalid_request;
+		for(p = res; *p && *p != '\r' && *p != '\n'; p++);
+		if(!*p)
+			goto invalid_request;
+		if(p - res > sizeof reqmod)
+			goto invalid_request;
+		memcpy(reqmod, res, p - res);
+		reqmod[p - res] = 0;
+	}
 	for(p = reqbuf; *p && *p != '\r' && *p != '\n'; p++);
 	if(*p == '\r' || *p == '\n') {
 		*p = 0;
-- 
1.8.5.3

Reply via email to