Commit Diff


commit - bfea7cffba681b0c8b49194f37e4bc59f584b179
commit + 61acbd558cb8336f44c43ed9478023b247e26bb6
blob - 6389a88ec1ab83623efd4b625340b0837fbb7b2b
blob + c96d03f9df0062274eb70d38ab16e54190344639
--- msearchd/fcgi.c
+++ msearchd/fcgi.c
@@ -696,7 +696,56 @@ clt_putsan(struct client *clt, const char *s)
 			break;
 		case '>':
 			r = clt_puts(clt, ">");
+			break;
+		case '&':
+			r = clt_puts(clt, "&");
+			break;
+		case '"':
+			r = clt_puts(clt, """);
+			break;
+		case '\'':
+			r = clt_puts(clt, "'");
+			break;
+		default:
+			r = clt_putc(clt, *s);
+			break;
+		}
+
+		if (r == -1)
+			return (-1);
+	}
+
+	return (0);
+}
+
+int
+clt_putmatch(struct client *clt, const char *s)
+{
+	int	r, instrong = 0, intag = 0, lastnl = 0;
+
+	if (s == NULL)
+		return (0);
+
+	for (; *s; ++s) {
+		switch (*s) {
+		case '<':
+			if (!instrong && !strncmp(s, "<strong>", 8)) {
+				instrong = intag = 1;
+				r = clt_putc(clt, *s);
+			} else if (instrong && !strncmp(s, "</strong>", 9)) {
+				instrong = 0;
+				intag = 1;
+				r = clt_putc(clt, *s);
+			} else
+				r = clt_puts(clt, "&lt;");
 			break;
+		case '>':
+			if (intag) {
+				intag = 0;
+				r = clt_putc(clt, *s);
+			} else
+				r = clt_puts(clt, "&gt;");
+			break;
 		case '&':
 			r = clt_puts(clt, "&amp;");
 			break;
@@ -706,7 +755,14 @@ clt_putsan(struct client *clt, const char *s)
 		case '\'':
 			r = clt_puts(clt, "&apos;");
 			break;
+		case '\n':
+			if (lastnl)
+				break;
+			r = clt_puts(clt, "<br />");
+			lastnl = 1;
+			break;
 		default:
+			lastnl = 0;
 			r = clt_putc(clt, *s);
 			break;
 		}
@@ -715,6 +771,8 @@ clt_putsan(struct client *clt, const char *s)
 			return (-1);
 	}
 
+	if (instrong)		/* something went wrong... */
+		return clt_puts(clt, "</strong>");
 	return (0);
 }
 
blob - e0ac0be5e89e31a03ddc36507791c0320adef3f9
blob + 2efdad37df16fbfd2cedee23b3be99d95a3618d6
--- msearchd/msearchd.h
+++ msearchd/msearchd.h
@@ -99,6 +99,7 @@ void	fcgi_free(struct fcgi *);
 int	clt_putc(struct client *, char);
 int	clt_puts(struct client *, const char *);
 int	clt_putsan(struct client *, const char *);
+int	clt_putmatch(struct client *, const char *);
 int	clt_write_bufferevent(struct client *, struct bufferevent *);
 int	clt_flush(struct client *);
 int	clt_write(struct client *, const uint8_t *, size_t);
blob - 9a533b7f961b04d3bd636c5dd42247025b4701c7
blob + 843b633e7a02b2e18bb16c2bf1bc2718f79cc063
--- msearchd/server.c
+++ msearchd/server.c
@@ -75,7 +75,8 @@ server_open_db(struct env *env)
 		    sqlite3_errmsg(env->env_db));
 
 	loadstmt(env->env_db, &env->env_query,
-	    "select mid, \"from\", date, subj"
+	    "select mid, \"from\", date, subj,"
+	    "  snippet(email, 4, '<strong>', '</strong>', '...', 32)"
 	    " from email"
 	    " where email match ?"
 	    " order by rank, date"
@@ -299,7 +300,7 @@ server_handle(struct env *env, struct client *clt)
 	char		 dbuf[64];
 	char		 esc[QUERY_MAXLEN];
 	char		*query;
-	const char	*mid, *from, *subj;
+	const char	*mid, *from, *subj, *snip;
 	uint64_t	 date;
 	time_t		 d;
 	struct tm	*tm;
@@ -352,6 +353,7 @@ server_handle(struct env *env, struct client *clt)
 		from = sqlite3_column_text(env->env_query, 1);
 		date = sqlite3_column_int64(env->env_query, 2);
 		subj = sqlite3_column_text(env->env_query, 3);
+		snip = sqlite3_column_text(env->env_query, 4);
 
 		if ((sizeof(d) == 4) && date > UINT32_MAX) {
 			log_warnx("overflow of 32bit time value");
@@ -381,7 +383,9 @@ server_handle(struct env *env, struct client *clt)
 		    clt_putsan(clt, mid) == -1 ||
 		    clt_puts(clt, ".html'>") == -1 ||
 		    clt_putsan(clt, subj) == -1 ||
-		    clt_puts(clt, "</a></p></li>") == -1)
+		    clt_puts(clt, "</a></p><p class=excerpt>") == -1 ||
+		    clt_putmatch(clt, snip) == -1 ||
+		    clt_puts(clt, "</p></li>") == -1)
 			goto err;
 	}
 
blob - f649383462eabfc4dce6458a3d315078edca16e8
blob + 9ff7493422cd1e57103466a3ae1da48d428d8994
--- style.css
+++ style.css
@@ -92,6 +92,11 @@ hr {
     margin: 0;
 }
 
+.thread .excerpt {
+    margin-left: 10px;
+    margin-top: 5px;
+}
+
 .thread a {
     text-decoration: none;
 }