char *bsEscape(char *bs) { char *copy = bsNew(bs); char *res = bsNew(""); char *c = copy; char *p = copy; while (*c != '\0') { if (*c == '<') { *c = '\0'; bsLCat(&res, p); bsLCat(&res, "<"); p = c + 1; } else if (*c == '>') { *c = '\0'; bsLCat(&res, p); bsLCat(&res, ">"); p = c + 1; } c++; } bsLCat(&res, p); bsDel(copy); return res; }
Account *accountNew(int id, int createdAt, char *name, char *email, char *username) { Account *account = malloc(sizeof(Account)); account->id = id; account->createdAt = createdAt; account->name = bsNew(name); account->email = bsNew(email); account->username = bsNew(username); return account; }
// TODO: Make this less shitty. static inline char *urldecode(char *segment) { char *cc = segment; char *bs = bsNew(""); char cb[3] = "\0\0\0"; char c[2] = "\0\0"; while (*cc != '\0') { if (*cc == '+') *cc = ' '; if (*cc == '%') { *cc = '\0'; bsLCat(&bs, segment); cb[0] = *(cc + 1); cb[1] = *(cc + 2); c[0] = (char)strtol(cb, NULL, 16); cc += 2; segment = cc + 1; bsLCat(&bs, c); } cc++; } bsLCat(&bs, segment); return bs; }
static inline ListCell *parseQS(char *path) { ListCell *qs = NULL; char *copy = bsNew(path); char *segment, *key, *value; bool s = true; for (;;) { if (s) {segment = strtok(copy, "="); s = false;} else {segment = strtok(NULL, "=");} if (segment == NULL) break; if (*(segment + strlen(segment) + 1) == '&') continue; key = segment; segment = strtok(NULL, "&\0"); if (segment == NULL) break; key = urldecode(key); value = urldecode(segment); qs = listCons(kvNew(key, value), sizeof(KV), qs); bsDel(key); bsDel(value); } bsDel(copy); return qs; }
static inline ListCell *parseCookies(char *header) { ListCell *cookies = NULL; char *copy = bsNew(header); char *segment, *key; bool s = true; for (;;) { if (s) {segment = strtok(copy, "="); s = false;} else {segment = strtok(NULL, "=");} if (segment == NULL) break; if (*segment == ' ') segment += 1; key = segment; segment = strtok(NULL, ";\0"); if (segment == NULL) break; cookies = listCons(kvNew(key, segment), sizeof(KV), cookies); } bsDel(copy); return cookies; }
Post *postNew(int id, int createdAt, int authorId, char *body) { Post *post = malloc(sizeof(Post)); post->id = id; post->createdAt = createdAt; post->authorId = authorId; post->body = bsNew(body); return post; }
Session *sessionNew(int id, int createdAt, int accountId, char *sessionId) { Session *session = malloc(sizeof(Session)); session->id = id; session->createdAt = createdAt; session->accountId = accountId; session->sessionId = bsNew(sessionId); return session; }
Request *requestNew(char *buff) { Request *request = malloc(sizeof(Request)); char *segment, *bs; request->method = UNKNOWN_METHOD; request->path = NULL; request->uri = NULL; request->queryString = NULL; request->postBody = NULL; request->headers = NULL; request->cookies = NULL; request->account = NULL; // METHOD TOK(buff, " \t"); if (strcmp(segment, "OPTIONS") == 0) request->method = OPTIONS; else if (strcmp(segment, "GET") == 0) request->method = GET; else if (strcmp(segment, "HEAD") == 0) request->method = HEAD; else if (strcmp(segment, "POST") == 0) request->method = POST; else if (strcmp(segment, "PUT") == 0) request->method = PUT; else if (strcmp(segment, "DELETE") == 0) request->method = DELETE; else if (strcmp(segment, "TRACE") == 0) request->method = TRACE; else if (strcmp(segment, "CONNECT") == 0) request->method = CONNECT; else goto fail; // PATH TOK(NULL, " \t"); request->path = bsNew(segment); request->uri = bsNew(segment); if (strchr(request->path, '#') != NULL) goto fail; // VERSION TOK(NULL, "\n"); if (strncmp(segment, "HTTP/1.0", 8) != 0 && strncmp(segment, "HTTP/1.1", 8) != 0) goto fail; // HEADERS request->headers = parseHeaders(segment); // BODY bs = kvFindList(request->headers, "Content-Type"); if (bs != NULL && strncmp(bs, "application/x-www-form-urlencoded", 33) == 0) { segment = strtok(NULL, "\0"); if (segment == NULL) goto fail; request->postBody = parseQS(segment); } // QUERYSTRING segment = strchr(request->path, '?'); if (segment != NULL) { request->uri = bsNewLen(request->path, segment - request->path); request->queryString = parseQS(segment + 1); if (request->queryString == NULL) goto fail; } // COOKIES segment = kvFindList(request->headers, "Cookie"); if (segment != NULL) { request->cookies = parseCookies(segment); if (request->cookies == NULL) goto fail; } return request; fail: requestDel(request); return NULL; }