From ec27db46cef1c4643087fa2eeaad2ca72228bc06 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sat, 1 Jan 2011 04:06:19 -0600 Subject: [PATCH] Add RSS CGI, also quite a lot of refactoring --- Makefile | 22 +++++++--- cgi/canned_responses.c | 33 +++++++++++++++ cgi/canned_responses.h | 10 +++++ cgi/cgi_blerg.c | 34 +++------------ cgi/rss.c | 93 ++++++++++++++++++++++++++++++++++++++++++ common/app.c | 29 ------------- common/app.h | 1 - common/escapery.c | 35 ++++++++++++++++ common/escapery.h | 7 ++++ common/json.c | 34 +++++++++++++++ common/json.h | 6 +++ 11 files changed, 240 insertions(+), 64 deletions(-) create mode 100644 cgi/canned_responses.c create mode 100644 cgi/canned_responses.h create mode 100644 cgi/rss.c create mode 100644 common/escapery.c create mode 100644 common/escapery.h create mode 100644 common/json.c create mode 100644 common/json.h diff --git a/Makefile b/Makefile index 2e49315..640be85 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,22 @@ 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) @@ -27,5 +30,14 @@ http_blerg: $(http_blerg_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 $@ diff --git a/cgi/canned_responses.c b/cgi/canned_responses.c new file mode 100644 index 0000000..2f430b1 --- /dev/null +++ b/cgi/canned_responses.c @@ -0,0 +1,33 @@ +#include +#include +#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)); +} diff --git a/cgi/canned_responses.h b/cgi/canned_responses.h new file mode 100644 index 0000000..84fd56a --- /dev/null +++ b/cgi/canned_responses.h @@ -0,0 +1,10 @@ +#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 */ diff --git a/cgi/cgi_blerg.c b/cgi/cgi_blerg.c index d0dcdba..2d48d82 100644 --- a/cgi/cgi_blerg.c +++ b/cgi/cgi_blerg.c @@ -6,40 +6,12 @@ #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; @@ -118,6 +90,10 @@ int main(int argc, char *argv[]) { 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) { diff --git a/cgi/rss.c b/cgi/rss.c new file mode 100644 index 0000000..bd8a1d1 --- /dev/null +++ b/cgi/rss.c @@ -0,0 +1,93 @@ +#include +#include +#include +#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, + "\n" + "\n" + "\n" + "%s's blërg\n" + "%s\n" + "%s\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, + "\n" + "%s\n" + "\n", + tmp + ); + free(tmp); + free(data); + i++; + } + blerg_close(b); + + fprintf(f, + "\n" + "\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"); + +} diff --git a/common/app.c b/common/app.c index 9bc4e40..9d3e6cf 100644 --- a/common/app.c +++ b/common/app.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "app.h" int parse_url_info(const char *url, struct url_info *info) { @@ -48,31 +47,3 @@ uint64_t *make_sequential_list(uint64_t from, uint64_t to) { 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); -} - diff --git a/common/app.h b/common/app.h index 93dc8b4..e37b47a 100644 --- a/common/app.h +++ b/common/app.h @@ -26,6 +26,5 @@ struct url_info { 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 */ diff --git a/common/escapery.c b/common/escapery.c new file mode 100644 index 0000000..27456bf --- /dev/null +++ b/common/escapery.c @@ -0,0 +1,35 @@ +#include +#include +#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; +} diff --git a/common/escapery.h b/common/escapery.h new file mode 100644 index 0000000..ae74226 --- /dev/null +++ b/common/escapery.h @@ -0,0 +1,7 @@ +#ifndef _ESCAPERY_H +#define _ESCAPERY_H + +char *xml_escape(const char *str); +char *xml_escape_data(const char *str, int len); + +#endif /* _ESCAPERY_H */ diff --git a/common/json.c b/common/json.c new file mode 100644 index 0000000..6b793ab --- /dev/null +++ b/common/json.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#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); +} + diff --git a/common/json.h b/common/json.h new file mode 100644 index 0000000..61e396d --- /dev/null +++ b/common/json.h @@ -0,0 +1,6 @@ +#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 */ -- 2.34.1