outbox.c (2794B)
1 2 #include "http.h" 3 #include "env.h" 4 #include "io.h" 5 6 #include <sys/mman.h> 7 8 /* 9 { 10 "@context": [ 11 "https://www.w3.org/ns/activitystreams", 12 "https://gleasonator.com/schemas/litepub-0.1.jsonld", 13 { 14 "@language": "und" 15 } 16 ], 17 "first": "https://gleasonator.com/users/alex/outbox?page=true", 18 "id": "https://gleasonator.com/users/alex/outbox", 19 "type": "OrderedCollection" 20 } 21 */ 22 23 int handle_outbox_request(struct http_req *req) 24 { 25 const char *hostname = get_hostname(); 26 27 http_write_header(req, "200 OK"); 28 29 fprintf(req->client.socket_file, 30 "{\"@context\": [\"https://www.w3.org/ns/activitystreams\"]," 31 " \"first\": \"https://%s/outbox?page=true\"," 32 " \"id\": \"https://%s/outbox\"," 33 " \"type\": \"OrderedCollection\"" 34 " }\r\n", hostname, hostname); 35 36 return 1; 37 } 38 39 static inline int is_space(char c) 40 { 41 return c == 0x20 || (c >= 0x09 && c <= 0x0d); 42 } 43 44 static inline int is_linebreak(char c) 45 { 46 return c == '\n' || c == '\r'; 47 } 48 49 static void consume_space_back(const char *start, const char **cursor) 50 { 51 const char *p = *cursor; 52 if (p <= start) return; 53 while (!is_space(*p--) && p > start); 54 *cursor = p; 55 } 56 57 static void consume_until_linebreak(const char *start, const char **cursor) 58 { 59 const char *p = *cursor; 60 if (p <= start) return; 61 while (!is_linebreak(*p) && --p > start); 62 *cursor = p == start? start : p+1; 63 } 64 65 /* 66 static void tail_data(const char *data, size_t len, FILE *out, int lines) 67 { 68 const char *p = data + len; 69 const char *line_end; 70 71 line_end = p; 72 73 while (lines-- > 0 && p >= data) { 74 line_end = p; 75 consume_space_back(data, &p); 76 consume_until_linebreak(data, &p); 77 78 fwrite(p, line_end - p, 1, out); 79 p--; 80 } 81 } 82 */ 83 84 static void tail_data_array(const char *data, size_t len, FILE *out, int lines) 85 { 86 const char *p = data + len; 87 const char *line_end; 88 int first = 1; 89 90 line_end = p; 91 92 while (lines-- > 0 && p >= data) { 93 line_end = p; 94 consume_space_back(data, &p); 95 consume_until_linebreak(data, &p); 96 97 if (!first) 98 putc(',', out); 99 first = 0; 100 101 fwrite(p, line_end - p, 1, out); 102 p--; 103 } 104 } 105 106 int handle_outbox_page_request(struct http_req *req, const char *outbox) 107 { 108 unsigned char *data; 109 const char *hostname; 110 size_t len; 111 112 hostname = get_hostname(); 113 114 http_write_header(req, "200 OK"); 115 116 fprintf(req->client.socket_file, 117 "{\"@context\": [\"https://www.w3.org/ns/activitystreams\"]," 118 " \"id\": \"https://%s/outbox?page=true\"," 119 " \"partOf\": \"https://%s/outbox\"," 120 " \"type\": \"OrderedCollectionPage\"," 121 " \"orderedItems\": [" 122 , hostname, hostname); 123 124 // technically a 404 but whatevs 125 if (map_file(outbox, &data, &len)) { 126 if (len > 0) { 127 tail_data_array((const char*)data, len, 128 req->client.socket_file, 20); 129 } 130 131 munmap(data, len); 132 } 133 134 fprintf(req->client.socket_file, "]}\r\n"); 135 136 return 1; 137 }