forked from mirrors/treebird
Pretty path parsing
Introduces a new path parser that uses the : token to represent a variable. It isn't fully featured but is just capable enough to work for ratFE FossilOrigin-Name: f7646dd5278f3c509d96307e45dc216522f81d9b93eb6b17125dc1b1892b1eee
This commit is contained in:
parent
1a31ca43ba
commit
8dbeb095f1
12 changed files with 132 additions and 81 deletions
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@ CC ?= cc
|
|||
GIT ?= git
|
||||
MASTODONT_DIR = mastodont-c/
|
||||
MASTODONT = $(MASTODONT_DIR)libmastodont.a
|
||||
CFLAGS = -Wall -I $(MASTODONT_DIR)include/
|
||||
CFLAGS += -Wall -I $(MASTODONT_DIR)include/
|
||||
LDFLAGS = -L$(MASTODONT_DIR) -lcurl -lmastodont -lcjson
|
||||
SRC = $(wildcard src/*.c)
|
||||
OBJ = $(patsubst %.c,%.o,$(SRC))
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "../config.h"
|
||||
#include "account.h"
|
||||
#include "easprintf.h"
|
||||
#include "uri.h"
|
||||
|
||||
// Files
|
||||
#include "../static/index.chtml"
|
||||
|
@ -51,25 +50,23 @@ char* construct_account_page(struct mstdnt_account* acct, size_t* res_size)
|
|||
return result;
|
||||
}
|
||||
|
||||
void content_account(mastodont_t* api)
|
||||
void content_account(mastodont_t* api, char** data, size_t size)
|
||||
{
|
||||
int cleanup = 0;
|
||||
char* account_page;
|
||||
struct mstdnt_account acct;
|
||||
struct mstdnt_storage storage;
|
||||
char uri[MSTDNT_URISIZE];
|
||||
|
||||
if (parse_uri(uri, MSTDNT_URISIZE, getenv("PATH_INFO")+2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mastodont_account(api, MSTDNT_LOOKUP_ACCT, uri,
|
||||
if (mastodont_account(api, MSTDNT_LOOKUP_ACCT, data[0],
|
||||
&acct, &storage, NULL))
|
||||
account_page = "An error occured";
|
||||
account_page = "Couldn't load account info";
|
||||
else
|
||||
{
|
||||
cleanup = 1;
|
||||
account_page = construct_account_page(&acct, NULL);
|
||||
|
||||
if (!account_page)
|
||||
account_page = "Malloc error";
|
||||
if (!account_page)
|
||||
account_page = "Malloc error";
|
||||
}
|
||||
|
||||
struct base_page b = {
|
||||
.locale = L10N_EN_US,
|
||||
|
@ -82,5 +79,5 @@ void content_account(mastodont_t* api)
|
|||
|
||||
/* Cleanup */
|
||||
mastodont_storage_cleanup(&storage);
|
||||
free(account_page);
|
||||
if (cleanup) free(account_page);
|
||||
}
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
|
||||
#ifndef ACCOUNT_H
|
||||
#define ACCOUNT_H
|
||||
#include <stddef.h>
|
||||
#include <mastodont.h>
|
||||
|
||||
char* construct_account_page(struct mstdnt_account* acct, size_t* res_size);
|
||||
void content_account(mastodont_t* api);
|
||||
void content_account(mastodont_t* api, char** data, size_t data_size);
|
||||
|
||||
#endif // ACCOUNT_H
|
||||
|
|
21
src/index.c
21
src/index.c
|
@ -28,16 +28,23 @@
|
|||
|
||||
void content_index(mastodont_t* api)
|
||||
{
|
||||
int cleanup = 0;
|
||||
size_t status_count, statuses_html_count;
|
||||
struct mstdnt_status* statuses;
|
||||
struct mstdnt_storage storage;
|
||||
char* status_format;
|
||||
mastodont_timeline_public(api, NULL, &storage, &statuses, &status_count);
|
||||
|
||||
/* Construct statuses into HTML */
|
||||
status_format = construct_statuses(statuses, status_count, &statuses_html_count);
|
||||
if (status_format == NULL)
|
||||
status_format = "Error in malloc!";
|
||||
if (mastodont_timeline_public(api, NULL, &storage, &statuses, &status_count))
|
||||
{
|
||||
status_format = "An error occured loading the timeline";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Construct statuses into HTML */
|
||||
status_format = construct_statuses(statuses, status_count, &statuses_html_count);
|
||||
if (status_format == NULL)
|
||||
status_format = "Error in malloc!";
|
||||
cleanup = 1;
|
||||
}
|
||||
|
||||
struct base_page b = {
|
||||
.locale = L10N_EN_US,
|
||||
|
@ -50,5 +57,5 @@ void content_index(mastodont_t* api)
|
|||
|
||||
/* Cleanup */
|
||||
mastodont_storage_cleanup(&storage);
|
||||
free(status_format);
|
||||
if (cleanup) free(status_format);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "index.h"
|
||||
#include "page_config.h"
|
||||
#include "path.h"
|
||||
#include "account.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
@ -41,7 +42,8 @@ int main(void)
|
|||
* Path handling *
|
||||
******************/
|
||||
struct path_info paths[] = {
|
||||
{ "/config", content_config }
|
||||
{ "/config", content_config },
|
||||
{ "/@:", content_account },
|
||||
};
|
||||
|
||||
handle_paths(&api, paths, sizeof(paths)/sizeof(paths[0]));
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "base_page.h"
|
||||
#include "../config.h"
|
||||
#include "page_config.h"
|
||||
#include "query.h"
|
||||
|
@ -28,17 +29,13 @@
|
|||
#include "../static/index.chtml"
|
||||
#include "../static/config.chtml"
|
||||
|
||||
void content_config(mastodont_t* api)
|
||||
void content_config(mastodont_t* api, char** data, size_t size)
|
||||
{
|
||||
(void)api; // No need to use this
|
||||
char* request_method = getenv("REQUEST_METHOD");
|
||||
char* post_query, * p_query_read;
|
||||
struct http_query_info info;
|
||||
|
||||
// Output
|
||||
printf("Content-Length: %ld\r\n\r\n",
|
||||
data_index_html_size + data_config_html_size);
|
||||
|
||||
|
||||
// Handle POST
|
||||
if (request_method && (strcmp("POST", request_method) == 0))
|
||||
|
@ -71,5 +68,13 @@ void content_config(mastodont_t* api)
|
|||
free(post_query);
|
||||
}
|
||||
|
||||
struct base_page b = {
|
||||
.locale = L10N_EN_US,
|
||||
.content = data_config_html,
|
||||
.sidebar_right = NULL
|
||||
};
|
||||
|
||||
render_base_page(&b);
|
||||
|
||||
printf(data_index_html, config_canonical_name, data_config_html);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
|
||||
#ifndef PAGE_CONFIG_H
|
||||
#define PAGE_CONFIG_H
|
||||
#include <stddef.h>
|
||||
#include <mastodont.h>
|
||||
|
||||
void content_config(mastodont_t* api);
|
||||
void content_config(mastodont_t* api, char** data, size_t data_size);
|
||||
|
||||
#endif // PAGE_CONFIG_H
|
||||
|
|
95
src/path.c
95
src/path.c
|
@ -22,6 +22,91 @@
|
|||
#include "index.h"
|
||||
#include "account.h"
|
||||
|
||||
enum path_state
|
||||
{
|
||||
PARSE_NEUTRAL,
|
||||
PARSE_READ,
|
||||
};
|
||||
|
||||
void parse_path(mastodont_t* api, struct path_info* path_info)
|
||||
{
|
||||
int fail = 0, fin = 0;
|
||||
enum path_state state = PARSE_NEUTRAL;
|
||||
char* p = path_info->path + 1;
|
||||
char* p2 = getenv("PATH_INFO") + 1;
|
||||
|
||||
// Stored into data
|
||||
int str_size = 0;
|
||||
char* tmp = NULL;
|
||||
char** data = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
for (int i = 0, j = 0;;)
|
||||
{
|
||||
switch (p[j])
|
||||
{
|
||||
case '\0':
|
||||
fin = 1;
|
||||
// fall
|
||||
case '/':
|
||||
if (state == PARSE_READ)
|
||||
{
|
||||
state = PARSE_NEUTRAL;
|
||||
|
||||
// Set value and move on
|
||||
data = realloc(data, ++size * sizeof(tmp));
|
||||
data[size-1] = tmp;
|
||||
tmp = NULL;
|
||||
str_size = 0;
|
||||
}
|
||||
|
||||
if (fin) goto breakpt;
|
||||
break;
|
||||
case ':':
|
||||
state = PARSE_READ;
|
||||
// fall
|
||||
default:
|
||||
if (state == PARSE_NEUTRAL)
|
||||
{
|
||||
if (p[j] == p2[i])
|
||||
break;
|
||||
else {
|
||||
fail = 1;
|
||||
goto breakpt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Don't realloc, we already have a space for our final character
|
||||
if (p2[i] == '\0')
|
||||
{
|
||||
tmp[str_size] = '\0';
|
||||
++j;
|
||||
}
|
||||
tmp = realloc(tmp, ++str_size + 1);
|
||||
tmp[str_size-1] = p2[i];
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == PARSE_NEUTRAL) ++j; // Used for p
|
||||
++i; // Used for p2
|
||||
}
|
||||
breakpt:
|
||||
if (fail)
|
||||
return;
|
||||
|
||||
path_info->callback(api, data, size);
|
||||
|
||||
// Cleanup
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
free(data[i]);
|
||||
}
|
||||
if (data) free(data);
|
||||
}
|
||||
|
||||
void handle_paths(mastodont_t* api, struct path_info* paths, size_t paths_len)
|
||||
{
|
||||
char* path = getenv("PATH_INFO");
|
||||
|
@ -30,16 +115,10 @@ void handle_paths(mastodont_t* api, struct path_info* paths, size_t paths_len)
|
|||
{
|
||||
content_index(api);
|
||||
}
|
||||
else if (path[1] == '@')
|
||||
{ // Account path
|
||||
content_account(api);
|
||||
}
|
||||
else
|
||||
{ // Generic path
|
||||
else { // Generic path
|
||||
for (size_t i = 0; i < paths_len; ++i)
|
||||
{
|
||||
if (strcmp(path, paths[i].path) == 0)
|
||||
paths[i].callback(api);
|
||||
parse_path(api, paths + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,10 @@
|
|||
struct path_info
|
||||
{
|
||||
char* path;
|
||||
void (*callback)(mastodont_t*);
|
||||
void (*callback)(mastodont_t*, char**, size_t);
|
||||
};
|
||||
|
||||
void handle_paths(mastodont_t* api, struct path_info* paths, size_t paths_len);
|
||||
void parse_path(mastodont_t* api, struct path_info* path_info);
|
||||
|
||||
#endif // PATH_H
|
||||
|
|
17
src/uri.c
17
src/uri.c
|
@ -1,17 +0,0 @@
|
|||
#include <string.h>
|
||||
#include "uri.h"
|
||||
|
||||
int parse_uri(char* dest, size_t dest_max_n, char* src)
|
||||
{
|
||||
strncpy(dest, src, dest_max_n);
|
||||
char* delim = strchr(dest, '/');
|
||||
int xp = delim != NULL; /* Expression */
|
||||
if (xp || dest[strlen(dest)] == '\0')
|
||||
{
|
||||
/* Incase the second expression didn't match, check xp again */
|
||||
if (xp) *delim = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
25
src/uri.h
25
src/uri.h
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* RatFE - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef URI_H
|
||||
#define URI_H
|
||||
#include <stddef.h>
|
||||
|
||||
int parse_uri(char* dest, size_t dest_max_n, char* src);
|
||||
|
||||
#endif // URI_H
|
|
@ -1,5 +1,5 @@
|
|||
<div id="config-page">
|
||||
<form action="/config" method="post">
|
||||
<form action="config" method="post">
|
||||
<h1>General</h1>
|
||||
<h3>JavaScript</h3>
|
||||
<ul>
|
||||
|
|
Loading…
Reference in a new issue