Add RSS CGI, also quite a lot of refactoring
CFLAGS ?= -g
-INCLUDES = -I. -Ifcgi -Idatabase -Icommon -Icgi-util-2.2.1 -Ilibmicrohttpd-0.9.3/src/include -Iyajl/build/yajl-1.0.11/include
+INCLUDES = -I. -Idatabase -Icommon -Iyajl/build/yajl-1.0.11/include
+HTTP_INCLUDES = -Ihttp -Ilibmicrohttpd-0.9.3/src/include
+CGI_INCLUDES = -Icgi -Icgi-util-2.2.1
LDFLAGS ?=
HTTP_LIBDIRS = -Llibmicrohttpd-0.9.3/src/daemon/.libs -Lyajl/build/yajl-1.0.11/lib
CGI_LIBDIRS = -Lcgi-util-2.2.1 -Lyajl/build/yajl-1.0.11/lib
-targets = blerg.a blergtool http_blerg cgi_blerg
+targets = blerg.a blergtool http_blerg cgi_blerg rss
blerg_a_objects = database/database.o database/tags.o database/util.o
blergtool_objects = tools/blergtool.o blerg.a
-http_blerg_objects = http/http_blerg.o http/canned_responses.o common/app.o common/auth.o blerg.a
-cgi_blerg_objects = cgi/cgi_blerg.o common/app.o common/auth.o blerg.a
+rss_objects = cgi/rss.o cgi/canned_responses.o common/app.o common/escapery.o blerg.a
+http_blerg_objects = http/http_blerg.o http/canned_responses.o common/app.o common/json.o common/auth.o blerg.a
+cgi_blerg_objects = cgi/cgi_blerg.o cgi/canned_responses.o common/app.o common/json.o common/auth.o blerg.a
all: $(targets)
clean:
- rm -f $(targets) $(blerg_a_objects) $(blergtool_objects) $(http_blerg_objects)
+ rm -f $(targets) $(blerg_a_objects) $(blergtool_objects) $(http_blerg_objects) $(cgi_blerg_objects) $(rss_objects)
blerg.a: $(blerg_a_objects)
ar rcu $@ $(blerg_a_objects)
cgi_blerg: $(cgi_blerg_objects)
gcc $(CGI_LIBDIRS) $(LDFLAGS) $(cgi_blerg_objects) -lcgi-util -lyajl_s -o $@
+rss: $(rss_objects)
+ gcc $(CGI_LIBDIRS) $(LDFLAGS) $(rss_objects) -lcgi-util -o $@
+
+http/%.o: http/%.c
+ gcc $(INCLUDES) $(HTTP_INCLUDES) $(CFLAGS) -c $< -o $@
+
+cgi/%.o: cgi/%.c
+ gcc $(INCLUDES) $(CGI_INCLUDES) $(CFLAGS) -c $< -o $@
+
%.o: %.c
gcc $(INCLUDES) $(CFLAGS) -c $< -o $@
+#include <stdio.h>
+#include <string.h>
+#include "canned_responses.h"
+#include "app.h"
+
+void respond_simple_data(unsigned const char *data, int len) {
+ printf("Content-length: %d\r\n\r\n", len);
+ fwrite(data, len, 1, stdout);
+}
+
+void respond_404() {
+ printf("Status: 404 Not Found\r\n");
+ printf("Content-type: text/html\r\n");
+ printf("Content-length: %d\r\n\r\n", strlen(CONTENT_404));
+
+ printf(CONTENT_404);
+}
+
+void respond_405() {
+ printf("Status: 405 Method Not Allowed\r\n");
+ printf("Content-type: text/html\r\n");
+ printf("Content-length: %d\r\n\r\n", strlen(CONTENT_405));
+
+ printf(CONTENT_405);
+}
+
+void respond_JSON_Failure() {
+ respond_simple_data(JSON_FAILURE, strlen(JSON_FAILURE));
+}
+
+void respond_JSON_Success() {
+ respond_simple_data(JSON_SUCCESS, strlen(JSON_SUCCESS));
+}
+#ifndef _CANNED_RESPONSES
+#define _CANNED_RESPONSES
+
+void respond_simple_data(unsigned const char *data, int len);
+void respond_404();
+void respond_405();
+void respond_JSON_Failure();
+void respond_JSON_Success();
+
+#endif /* _CANNED_RESPONSES */
#include "database.h"
#include "tags.h"
#include "auth.h"
+#include "canned_responses.h"
#include "app.h"
#include "config.h"
yajl_gen_config yajl_c = { 0, 0 };
-void respond_simple_data(unsigned const char *data, int len) {
- printf("Content-length: %d\r\n\r\n", len);
- fwrite(data, len, 1, stdout);
-}
-
-void respond_404() {
- printf("Status: 404 Not Found\r\n");
- printf("Content-type: text/html\r\n");
- printf("Content-length: %d\r\n\r\n", strlen(CONTENT_404));
-
- printf(CONTENT_404);
-}
-
-void respond_405() {
- printf("Status: 405 Method Not Allowed\r\n");
- printf("Content-type: text/html\r\n");
- printf("Content-length: %d\r\n\r\n", strlen(CONTENT_405));
-
- printf(CONTENT_405);
-}
-
-void respond_JSON_Failure() {
- respond_simple_data(JSON_FAILURE, strlen(JSON_FAILURE));
-}
-
-void respond_JSON_Success() {
- respond_simple_data(JSON_SUCCESS, strlen(JSON_SUCCESS));
-}
-
void respond_for_range(struct blerg *b, uint64_t from, uint64_t to) {
const unsigned char *ybuf;
unsigned int len;
exit(0);
}
request_method = getenv("REQUEST_METHOD");
+ if (request_method == NULL) {
+ fprintf(stderr, "Request method is null!?\n");
+ exit(0);
+ }
if (strncmp(path, "/get", 4) == 0 && strlen(path) > 4) {
if (strncmp(request_method, "GET", 4) != 0) {
+#include <stdio.h>
+#include <stdlib.h>
+#include <cgi-util.h>
+#include "database.h"
+#include "escapery.h"
+#include "canned_responses.h"
+#include "app.h"
+
+int fprint_rss(FILE *f, const char *username) {
+ struct blerg *b = blerg_open(username);
+ uint64_t record_count = blerg_get_record_count(b);
+ uint64_t i = (record_count > 50 ? record_count - 50 : 0);
+ char *data;
+ char *tmp;
+ int len;
+
+ fprintf(f,
+ "<?xml version=\"1.0\" charset=\"utf8\">\n"
+ "<rss version=\"2.0\">\n"
+ "<channel>\n"
+ "<title>%s's blërg</title>\n"
+ "<link>%s</link>\n"
+ "<description>%s</description>\n",
+ "blërg",
+ "http://blerg.dominionfawesome.com/",
+ "Textual vomit"
+ );
+
+ while (i < record_count) {
+ blerg_fetch(b, i, &data, &len);
+ tmp = xml_escape_data(data, len);
+ fprintf(f,
+ "<item>\n"
+ "<description>%s</description>\n"
+ "</item>\n",
+ tmp
+ );
+ free(tmp);
+ free(data);
+ i++;
+ }
+ blerg_close(b);
+
+ fprintf(f,
+ "</channel>\n"
+ "</rss>\n"
+ );
+}
+
+int main (int argc, char *argv) {
+ char *path;
+ char *request_method;
+ int ret;
+ struct url_info info;
+
+ request_method = getenv("REQUEST_METHOD");
+ if (request_method == NULL) {
+ fprintf(stderr, "Request method is null!?\n");
+ exit(0);
+ }
+
+ if (strncmp(request_method, "GET", 4) != 0) {
+ respond_405();
+ exit(0);
+ }
+
+ path = getenv("PATH_INFO");
+ if (path == NULL) {
+ respond_404();
+ exit(0);
+ }
+
+ if (path[0] != '/') {
+ respond_404();
+ exit(0);
+ }
+
+ ret = parse_url_info(path + 1, &info);
+ if ((ret & URL_INFO_AUTHOR) == 0) {
+ respond_404();
+ exit(0);
+ }
+
+ if (!blerg_exists(info.author)) {
+ respond_404();
+ exit(0);
+ }
+
+ printf("Content-type: application/rss+xml\r\n\r\n");
+
+ fprint_rss(stdout, "chip");
+
+}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <yajl/yajl_gen.h>
#include "app.h"
int parse_url_info(const char *url, struct url_info *info) {
return list;
}
-
-void json_generate_one_record(yajl_gen g, const char *author, struct blerg *b, uint64_t record) {
- char *data;
- char number[21];
- int len;
-
- if (!blerg_fetch(b, record, &data, &len)) {
- fprintf(stderr, "Could not fetch record\n");
- return;
- }
-
- yajl_gen_map_open(g);
- if (author != NULL) {
- yajl_gen_string(g, "author", 6);
- yajl_gen_string(g, author, strlen(author));
- }
- yajl_gen_string(g, "record", 6);
- snprintf(number, 21, "%llu", record);
- yajl_gen_string(g, number, strlen(number));
- yajl_gen_string(g, "timestamp", 9);
- yajl_gen_integer(g, blerg_get_timestamp(b, record));
- yajl_gen_string(g, "data", 4);
- yajl_gen_string(g, data, len);
- yajl_gen_map_close(g);
-
- free(data);
-}
-
int parse_url_info(const char *url, struct url_info *info);
uint64_t *make_sequential_list(uint64_t from, uint64_t to);
-void json_generate_one_record(yajl_gen g, const char *author, struct blerg *b, uint64_t record);
#endif /* _APP_H */
+#include <string.h>
+#include <stdlib.h>
+#include "escapery.h"
+
+char *xml_escape(const char *str) {
+ return xml_escape_data(str, strlen(str));
+}
+
+char *xml_escape_data(const char *str, int len) {
+ char *r = malloc(len * 5 + 1); /* Up to 5x the space if they're all &'s */
+ int i, j;
+
+ for (i = 0, j = 0; i < len; i++) {
+ switch(str[i]) {
+ case '<':
+ memcpy(r + j, "<", 4);
+ j += 4;
+ break;
+ case '>':
+ memcpy(r + j, ">", 4);
+ j += 4;
+ break;
+ case '&':
+ memcpy(r + j, "&", 5);
+ j += 5;
+ break;
+ default:
+ r[j] = str[i];
+ j += 1;
+ }
+ }
+ r[j] = 0;
+
+ return r;
+}
+#ifndef _ESCAPERY_H
+#define _ESCAPERY_H
+
+char *xml_escape(const char *str);
+char *xml_escape_data(const char *str, int len);
+
+#endif /* _ESCAPERY_H */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <yajl/yajl_gen.h>
+#include "database.h"
+#include "json.h"
+
+void json_generate_one_record(yajl_gen g, const char *author, struct blerg *b, uint64_t record) {
+ char *data;
+ char number[21];
+ int len;
+
+ if (!blerg_fetch(b, record, &data, &len)) {
+ fprintf(stderr, "Could not fetch record\n");
+ return;
+ }
+
+ yajl_gen_map_open(g);
+ if (author != NULL) {
+ yajl_gen_string(g, "author", 6);
+ yajl_gen_string(g, author, strlen(author));
+ }
+ yajl_gen_string(g, "record", 6);
+ snprintf(number, 21, "%llu", record);
+ yajl_gen_string(g, number, strlen(number));
+ yajl_gen_string(g, "timestamp", 9);
+ yajl_gen_integer(g, blerg_get_timestamp(b, record));
+ yajl_gen_string(g, "data", 4);
+ yajl_gen_string(g, data, len);
+ yajl_gen_map_close(g);
+
+ free(data);
+}
+
+#ifndef _JSON_H
+#define _JSON_H
+
+void json_generate_one_record(yajl_gen g, const char *author, struct blerg *b, uint64_t record);
+
+#endif /* _JSON_H */