Added const everywhere.

This commit is contained in:
default 2024-05-21 14:12:15 +02:00
parent b95fbe4e43
commit 4777fc86cb
20 changed files with 549 additions and 580 deletions

View file

@ -67,7 +67,7 @@ int activitypub_request(snac *user, const char *url, xs_dict **data)
xs *response = NULL;
xs *payload = NULL;
int p_size;
char *ctype;
const char *ctype;
*data = NULL;
@ -154,20 +154,21 @@ int actor_request(snac *user, const char *actor, xs_dict **data)
}
char *get_atto(const xs_dict *msg)
const char *get_atto(const xs_dict *msg)
/* gets the attributedTo field (an actor) */
{
char *actor = xs_dict_get(msg, "attributedTo");
const xs_val *actor = xs_dict_get(msg, "attributedTo");
/* if the actor is a list of objects (like on Peertube videos), pick the Person */
if (xs_type(actor) == XSTYPE_LIST) {
xs_list *p = actor;
const xs_list *p = actor;
int c = 0;
xs_dict *v;
actor = NULL;
while (actor == NULL && xs_list_iter(&p, &v)) {
while (actor == NULL && xs_list_next(p, &v, &c)) {
if (xs_type(v) == XSTYPE_DICT) {
char *type = xs_dict_get(v, "type");
const char *type = xs_dict_get(v, "type");
if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Person") == 0) {
actor = xs_dict_get(v, "id");
@ -186,7 +187,7 @@ xs_list *get_attachments(const xs_dict *msg)
/* unify the garbage fire that are the attachments */
{
xs_list *l = xs_list_new();
xs_list *p;
const xs_list *p;
/* try first the attachments list */
if (!xs_is_null(p = xs_dict_get(msg, "attachment"))) {
@ -203,23 +204,24 @@ xs_list *get_attachments(const xs_dict *msg)
if (xs_type(attach) == XSTYPE_LIST) {
/* does the message have an image? */
if (xs_type(v = xs_dict_get(msg, "image")) == XSTYPE_DICT) {
const xs_dict *d = xs_dict_get(msg, "image");
if (xs_type(d) == XSTYPE_DICT) {
/* add it to the attachment list */
attach = xs_list_append(attach, v);
attach = xs_list_append(attach, d);
}
}
/* now iterate the list */
p = attach;
while (xs_list_iter(&p, &v)) {
char *type = xs_dict_get(v, "mediaType");
int c = 0;
while (xs_list_next(attach, &v, &c)) {
const char *type = xs_dict_get(v, "mediaType");
if (xs_is_null(type))
type = xs_dict_get(v, "type");
if (xs_is_null(type))
continue;
char *href = xs_dict_get(v, "url");
const char *href = xs_dict_get(v, "url");
if (xs_is_null(href))
href = xs_dict_get(v, "href");
if (xs_is_null(href))
@ -233,7 +235,7 @@ xs_list *get_attachments(const xs_dict *msg)
type = mt;
}
char *name = xs_dict_get(v, "name");
const char *name = xs_dict_get(v, "name");
if (xs_is_null(name))
name = xs_dict_get(msg, "name");
if (xs_is_null(name))
@ -252,29 +254,31 @@ xs_list *get_attachments(const xs_dict *msg)
p = xs_dict_get(msg, "url");
if (xs_type(p) == XSTYPE_LIST) {
char *href = NULL;
char *type = NULL;
const char *href = NULL;
const char *type = NULL;
int c = 0;
xs_val *v;
while (href == NULL && xs_list_iter(&p, &v)) {
while (href == NULL && xs_list_next(p, &v, &c)) {
if (xs_type(v) == XSTYPE_DICT) {
char *mtype = xs_dict_get(v, "type");
const char *mtype = xs_dict_get(v, "type");
if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "Link") == 0) {
mtype = xs_dict_get(v, "mediaType");
xs_list *tag = xs_dict_get(v, "tag");
const xs_list *tag = xs_dict_get(v, "tag");
if (xs_type(mtype) == XSTYPE_STRING &&
strcmp(mtype, "application/x-mpegURL") == 0 &&
xs_type(tag) == XSTYPE_LIST) {
/* now iterate the tag list, looking for a video URL */
xs_dict *d;
int c = 0;
while (href == NULL && xs_list_iter(&tag, &d)) {
while (href == NULL && xs_list_next(tag, &d, &c)) {
if (xs_type(d) == XSTYPE_DICT) {
if (xs_type(mtype = xs_dict_get(d, "mediaType")) == XSTYPE_STRING &&
xs_startswith(mtype, "video/")) {
char *h = xs_dict_get(d, "href");
const char *h = xs_dict_get(d, "href");
/* this is probably it */
if (xs_type(h) == XSTYPE_STRING) {
@ -303,7 +307,7 @@ xs_list *get_attachments(const xs_dict *msg)
}
int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
int timeline_request(snac *snac, const char **id, xs_str **wrk, int level)
/* ensures that an entry and its ancestors are in the timeline */
{
int status = 0;
@ -323,7 +327,7 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
status = activitypub_request(snac, *id, &msg);
if (valid_status(status)) {
xs_dict *object = msg;
const xs_dict *object = msg;
const char *type = xs_dict_get(object, "type");
/* get the id again from the object, as it may be different */
@ -369,7 +373,7 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
}
/* does it have an ancestor? */
char *in_reply_to = xs_dict_get(object, "inReplyTo");
const char *in_reply_to = xs_dict_get(object, "inReplyTo");
/* store */
timeline_add(snac, nid, object);
@ -381,83 +385,12 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
}
}
}
enqueue_request_replies(snac, *id);
}
return status;
}
void timeline_request_replies(snac *user, const char *id)
/* requests all replies of a message */
/* FIXME: experimental -- needs more testing */
{
/* FIXME: TEMPORARILY DISABLED */
/* Reason: I've found that many of the posts in the 'replies' Collection
do not have an inReplyTo field (why??? aren't they 'replies'???).
For this reason, these requested objects are not stored as children
of the original post and they are shown as out-of-context, top level posts.
This process is disabled until I find an elegant way of providing a parent
for these 'stray' children. */
return;
xs *msg = NULL;
if (!valid_status(object_get(id, &msg)))
return;
/* does it have a replies collection? */
const xs_dict *replies = xs_dict_get(msg, "replies");
if (!xs_is_null(replies)) {
const char *type = xs_dict_get(replies, "type");
const char *first = xs_dict_get(replies, "first");
if (!xs_is_null(type) && !xs_is_null(first) && strcmp(type, "Collection") == 0) {
const char *next = xs_dict_get(first, "next");
if (!xs_is_null(next)) {
xs *rpls = NULL;
int status = activitypub_request(user, next, &rpls);
/* request the Collection of replies */
if (valid_status(status)) {
xs_list *items = xs_dict_get(rpls, "items");
if (xs_type(items) == XSTYPE_LIST) {
xs_val *v;
/* request them all */
while (xs_list_iter(&items, &v)) {
if (xs_type(v) == XSTYPE_DICT) {
/* not an id, but the object itself (!) */
const char *c_id = xs_dict_get(v, "id");
if (!xs_is_null(id)) {
snac_debug(user, 0, xs_fmt("embedded reply %s", c_id));
object_add(c_id, v);
/* get its own children */
timeline_request_replies(user, v);
}
}
else {
snac_debug(user, 0, xs_fmt("request reply %s", v));
timeline_request(user, &v, NULL, 0);
}
}
}
}
else
snac_debug(user, 0, xs_fmt("replies request error %s %d", next, status));
}
}
}
}
int send_to_inbox_raw(const char *keyid, const char *seckey,
const xs_str *inbox, const xs_dict *msg,
xs_val **payload, int *p_size, int timeout)
@ -480,7 +413,7 @@ int send_to_inbox(snac *snac, const xs_str *inbox, const xs_dict *msg,
xs_val **payload, int *p_size, int timeout)
/* sends a message to an Inbox */
{
char *seckey = xs_dict_get(snac->key, "secret");
const char *seckey = xs_dict_get(snac->key, "secret");
return send_to_inbox_raw(snac->actor, seckey, inbox, msg, payload, p_size, timeout);
}
@ -490,7 +423,7 @@ xs_str *get_actor_inbox(const char *actor)
/* gets an actor's inbox */
{
xs *data = NULL;
char *v = NULL;
const char *v = NULL;
if (valid_status(actor_request(NULL, actor, &data))) {
/* try first endpoints/sharedInbox */
@ -539,16 +472,16 @@ void post_message(snac *snac, const char *actor, const xs_dict *msg)
xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public)
/* returns the list of recipients for a message */
{
char *to = xs_dict_get(msg, "to");
char *cc = xs_dict_get(msg, "cc");
const xs_val *to = xs_dict_get(msg, "to");
const xs_val *cc = xs_dict_get(msg, "cc");
xs_set rcpts;
int n;
xs_set_init(&rcpts);
char *lists[] = { to, cc, NULL };
const xs_list *lists[] = { to, cc, NULL };
for (n = 0; lists[n]; n++) {
char *l = lists[n];
xs_list *l = (xs_list *)lists[n];
char *v;
xs *tl = NULL;
@ -671,13 +604,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
/* if it's a Follow, it must be explicitly for us */
if (xs_match(type, "Follow")) {
char *object = xs_dict_get(c_msg, "object");
const char *object = xs_dict_get(c_msg, "object");
return !xs_is_null(object) && strcmp(snac->actor, object) == 0;
}
/* only accept Ping directed to us */
if (xs_match(type, "Ping")) {
char *dest = xs_dict_get(c_msg, "to");
const char *dest = xs_dict_get(c_msg, "to");
return !xs_is_null(dest) && strcmp(snac->actor, dest) == 0;
}
@ -692,7 +625,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
if (pub_msg && following_check(snac, actor))
return 1;
xs_dict *msg = xs_dict_get(c_msg, "object");
const xs_dict *msg = xs_dict_get(c_msg, "object");
xs *rcpts = recipient_list(snac, msg, 0);
xs_list *p = rcpts;
xs_str *v;
@ -704,8 +637,9 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
xs *actor_obj = NULL;
if (valid_status(object_get(actor, &actor_obj))) {
if ((v = xs_dict_get(actor_obj, "followers")))
actor_followers = xs_dup(v);
const xs_val *fw = xs_dict_get(actor_obj, "followers");
if (fw)
actor_followers = xs_dup(fw);
}
}
@ -728,13 +662,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
}
/* accept if it's by someone we follow */
char *atto = get_atto(msg);
const char *atto = get_atto(msg);
if (pub_msg && !xs_is_null(atto) && following_check(snac, atto))
return 3;
/* is this message a reply to another? */
char *irt = xs_dict_get(msg, "inReplyTo");
const char *irt = xs_dict_get(msg, "inReplyTo");
if (!xs_is_null(irt)) {
xs *r_msg = NULL;
@ -987,8 +921,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
/* telegram */
char *bot = xs_dict_get(snac->config, "telegram_bot");
char *chat_id = xs_dict_get(snac->config, "telegram_chat_id");
const char *bot = xs_dict_get(snac->config, "telegram_bot");
const char *chat_id = xs_dict_get(snac->config, "telegram_chat_id");
if (!xs_is_null(bot) && !xs_is_null(chat_id) && *bot && *chat_id)
enqueue_telegram(body, bot, chat_id);
@ -1001,8 +935,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
objid = actor;
/* ntfy */
char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
const char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
const char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
if (!xs_is_null(ntfy_server) && *ntfy_server)
enqueue_ntfy(body, ntfy_server, ntfy_token);
@ -1088,7 +1022,7 @@ xs_dict *msg_base(snac *snac, const char *type, const char *id,
}
xs_dict *msg_collection(snac *snac, char *id)
xs_dict *msg_collection(snac *snac, const char *id)
/* creates an empty OrderedCollection message */
{
xs_dict *msg = msg_base(snac, "OrderedCollection", id, NULL, NULL, NULL);
@ -1102,7 +1036,7 @@ xs_dict *msg_collection(snac *snac, char *id)
}
xs_dict *msg_accept(snac *snac, char *object, char *to)
xs_dict *msg_accept(snac *snac, const xs_val *object, const char *to)
/* creates an Accept message (as a response to a Follow) */
{
xs_dict *msg = msg_base(snac, "Accept", "@dummy", snac->actor, NULL, object);
@ -1113,12 +1047,12 @@ xs_dict *msg_accept(snac *snac, char *object, char *to)
}
xs_dict *msg_update(snac *snac, xs_dict *object)
xs_dict *msg_update(snac *snac, const xs_dict *object)
/* creates an Update message */
{
xs_dict *msg = msg_base(snac, "Update", "@object", snac->actor, "@now", object);
char *type = xs_dict_get(object, "type");
const char *type = xs_dict_get(object, "type");
if (strcmp(type, "Note") == 0) {
msg = xs_dict_append(msg, "to", xs_dict_get(object, "to"));
@ -1141,7 +1075,7 @@ xs_dict *msg_update(snac *snac, xs_dict *object)
}
xs_dict *msg_admiration(snac *snac, char *object, char *type)
xs_dict *msg_admiration(snac *snac, const char *object, const char *type)
/* creates a Like or Announce message */
{
xs *a_msg = NULL;
@ -1172,7 +1106,7 @@ xs_dict *msg_admiration(snac *snac, char *object, char *type)
}
xs_dict *msg_repulsion(snac *user, char *id, char *type)
xs_dict *msg_repulsion(snac *user, const char *id, const char *type)
/* creates an Undo + admiration message */
{
xs *a_msg = NULL;
@ -1210,7 +1144,7 @@ xs_dict *msg_actor(snac *snac)
xs *kid = NULL;
xs *f_bio = NULL;
xs_dict *msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL);
char *p;
const char *p;
int n;
/* change the @context (is this really necessary?) */
@ -1268,7 +1202,7 @@ xs_dict *msg_actor(snac *snac)
}
/* add the metadata as attachments of PropertyValue */
xs_dict *metadata = xs_dict_get(snac->config, "metadata");
const xs_dict *metadata = xs_dict_get(snac->config, "metadata");
if (xs_type(metadata) == XSTYPE_DICT) {
xs *attach = xs_list_new();
xs_str *k;
@ -1314,7 +1248,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object)
/* creates a 'Create' message */
{
xs_dict *msg = msg_base(snac, "Create", "@wrapper", snac->actor, NULL, object);
xs_val *v;
const xs_val *v;
if ((v = get_atto(object)))
msg = xs_dict_append(msg, "attributedTo", v);
@ -1331,7 +1265,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object)
}
xs_dict *msg_undo(snac *snac, char *object)
xs_dict *msg_undo(snac *snac, const xs_val *object)
/* creates an 'Undo' message */
{
xs_dict *msg = msg_base(snac, "Undo", "@object", snac->actor, "@now", object);
@ -1344,7 +1278,7 @@ xs_dict *msg_undo(snac *snac, char *object)
}
xs_dict *msg_delete(snac *snac, char *id)
xs_dict *msg_delete(snac *snac, const char *id)
/* creates a 'Delete' + 'Tombstone' for a local entry */
{
xs *tomb = xs_dict_new();
@ -1386,7 +1320,7 @@ xs_dict *msg_follow(snac *snac, const char *q)
if (valid_status(status)) {
/* check if the actor is an alias */
char *r_actor = xs_dict_get(actor_o, "id");
const char *r_actor = xs_dict_get(actor_o, "id");
if (r_actor && strcmp(actor, r_actor) != 0) {
snac_log(snac, xs_fmt("actor to follow is an alias %s -> %s", actor, r_actor));
@ -1402,7 +1336,7 @@ xs_dict *msg_follow(snac *snac, const char *q)
xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
xs_str *in_reply_to, xs_list *attach, int priv)
const xs_str *in_reply_to, const xs_list *attach, int priv)
/* creates a 'Note' message */
{
xs *ntid = tid(0);
@ -1442,7 +1376,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
if (valid_status(object_get(in_reply_to, &p_msg))) {
/* add this author as recipient */
char *a, *v;
const char *a, *v;
if ((a = get_atto(p_msg)) && xs_list_in(to, a) == -1)
to = xs_list_append(to, a);
@ -1453,7 +1387,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
xs *actor_o = NULL;
if (xs_list_len(l) > 3 && valid_status(object_get(a, &actor_o))) {
char *uname = xs_dict_get(actor_o, "preferredUsername");
const char *uname = xs_dict_get(actor_o, "preferredUsername");
if (!xs_is_null(uname) && *uname) {
xs *handle = xs_fmt("@%s@%s", uname, xs_list_get(l, 2));
@ -1492,7 +1426,8 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
/* create the attachment list, if there are any */
if (!xs_is_null(attach)) {
while (xs_list_iter(&attach, &v)) {
int c = 0;
while (xs_list_next(attach, &v, &c)) {
xs *d = xs_dict_new();
const char *url = xs_list_get(v, 0);
const char *alt = xs_list_get(v, 1);
@ -1515,7 +1450,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
p = tag;
while (xs_list_iter(&p, &v)) {
if (xs_type(v) == XSTYPE_DICT) {
char *t;
const char *t;
if (!xs_is_null(t = xs_dict_get(v, "type")) && strcmp(t, "Mention") == 0) {
if (!xs_is_null(t = xs_dict_get(v, "href")))
@ -1639,7 +1574,7 @@ int update_question(snac *user, const char *id)
xs *msg = NULL;
xs *rcnt = xs_dict_new();
xs *lopts = xs_list_new();
xs_list *opts;
const xs_list *opts;
xs_list *p;
xs_val *v;
@ -1657,8 +1592,8 @@ int update_question(snac *user, const char *id)
return -3;
/* fill the initial count */
p = opts;
while (xs_list_iter(&p, &v)) {
int c = 0;
while (xs_list_next(opts, &v, &c)) {
const char *name = xs_dict_get(v, "name");
if (name) {
lopts = xs_list_append(lopts, name);
@ -1764,13 +1699,13 @@ int update_question(snac *user, const char *id)
/** queues **/
int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
/* processes an ActivityPub message from the input queue */
/* return values: -1, fatal error; 0, transient error, retry;
1, processed and done; 2, propagate to users (only when no user is set) */
{
char *actor = xs_dict_get(msg, "actor");
char *type = xs_dict_get(msg, "type");
const char *actor = xs_dict_get(msg, "actor");
const char *type = xs_dict_get(msg, "type");
xs *actor_o = NULL;
int a_status;
int do_notify = 0;
@ -1790,7 +1725,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
return -1;
}
char *object, *utype;
const char *object, *utype;
object = xs_dict_get(msg, "object");
if (object != NULL && xs_type(object) == XSTYPE_DICT)
@ -1813,7 +1748,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
}
/* also discard if the object to be deleted is not here */
char *obj_id = object;
const char *obj_id = object;
if (xs_type(obj_id) == XSTYPE_DICT)
obj_id = xs_dict_get(obj_id, "id");
@ -1885,7 +1820,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
int min_account_age = xs_number_get(xs_dict_get(srv_config, "min_account_age"));
if (min_account_age > 0) {
char *actor_date = xs_dict_get(actor_o, "published");
const char *actor_date = xs_dict_get(actor_o, "published");
if (!xs_is_null(actor_date)) {
time_t actor_t = xs_parse_iso_date(actor_date, 0);
@ -1945,7 +1880,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
}
else
if (strcmp(type, "Undo") == 0) { /** **/
char *id = xs_dict_get(object, "object");
const char *id = xs_dict_get(object, "object");
if (xs_type(object) != XSTYPE_DICT)
utype = "Follow";
@ -1990,9 +1925,9 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
}
if (xs_match(utype, "Note|Article")) { /** **/
char *id = xs_dict_get(object, "id");
char *in_reply_to = xs_dict_get(object, "inReplyTo");
char *atto = get_atto(object);
const char *id = xs_dict_get(object, "id");
const char *in_reply_to = xs_dict_get(object, "inReplyTo");
const char *atto = get_atto(object);
xs *wrk = NULL;
if (xs_is_null(id))
@ -2029,14 +1964,14 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
}
else
if (strcmp(utype, "Question") == 0) { /** **/
char *id = xs_dict_get(object, "id");
const char *id = xs_dict_get(object, "id");
if (timeline_add(snac, id, object))
snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id));
}
else
if (strcmp(utype, "Video") == 0) { /** **/
char *id = xs_dict_get(object, "id");
const char *id = xs_dict_get(object, "id");
if (timeline_add(snac, id, object))
snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id));
@ -2212,7 +2147,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
}
int send_email(char *msg)
int send_email(const char *msg)
/* invoke sendmail with email headers and body in msg */
{
FILE *f;
@ -2244,14 +2179,14 @@ int send_email(char *msg)
void process_user_queue_item(snac *snac, xs_dict *q_item)
/* processes an item from the user queue */
{
char *type;
const char *type;
int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
if ((type = xs_dict_get(q_item, "type")) == NULL)
type = "output";
if (strcmp(type, "message") == 0) {
xs_dict *msg = xs_dict_get(q_item, "message");
const xs_dict *msg = xs_dict_get(q_item, "message");
xs *rcpts = recipient_list(snac, msg, 1);
xs_set inboxes;
xs_list *p;
@ -2292,8 +2227,8 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
else
if (strcmp(type, "input") == 0) {
/* process the message */
xs_dict *msg = xs_dict_get(q_item, "message");
xs_dict *req = xs_dict_get(q_item, "req");
const xs_dict *msg = xs_dict_get(q_item, "message");
const xs_dict *req = xs_dict_get(q_item, "req");
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
if (xs_is_null(msg))
@ -2320,13 +2255,6 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
update_question(snac, id);
}
else
if (strcmp(type, "request_replies") == 0) {
const char *id = xs_dict_get(q_item, "message");
if (!xs_is_null(id))
timeline_request_replies(snac, id);
}
else
if (strcmp(type, "object_request") == 0) {
const char *id = xs_dict_get(q_item, "message");
@ -2395,15 +2323,15 @@ int process_user_queue(snac *snac)
void process_queue_item(xs_dict *q_item)
/* processes an item from the global queue */
{
char *type = xs_dict_get(q_item, "type");
const char *type = xs_dict_get(q_item, "type");
int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
if (strcmp(type, "output") == 0) {
int status;
xs_str *inbox = xs_dict_get(q_item, "inbox");
xs_str *keyid = xs_dict_get(q_item, "keyid");
xs_str *seckey = xs_dict_get(q_item, "seckey");
xs_dict *msg = xs_dict_get(q_item, "message");
const xs_str *inbox = xs_dict_get(q_item, "inbox");
const xs_str *keyid = xs_dict_get(q_item, "keyid");
const xs_str *seckey = xs_dict_get(q_item, "seckey");
const xs_dict *msg = xs_dict_get(q_item, "message");
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
int p_status = xs_number_get(xs_dict_get(q_item, "p_status"));
xs *payload = NULL;
@ -2475,7 +2403,7 @@ void process_queue_item(xs_dict *q_item)
else
if (strcmp(type, "email") == 0) {
/* send this email */
xs_str *msg = xs_dict_get(q_item, "message");
const xs_str *msg = xs_dict_get(q_item, "message");
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
if (!send_email(msg))
@ -2497,8 +2425,8 @@ void process_queue_item(xs_dict *q_item)
else
if (strcmp(type, "telegram") == 0) {
/* send this via telegram */
char *bot = xs_dict_get(q_item, "bot");
char *msg = xs_dict_get(q_item, "message");
const char *bot = xs_dict_get(q_item, "bot");
const char *msg = xs_dict_get(q_item, "message");
xs *chat_id = xs_dup(xs_dict_get(q_item, "chat_id"));
int status = 0;
@ -2521,9 +2449,9 @@ void process_queue_item(xs_dict *q_item)
else
if (strcmp(type, "ntfy") == 0) {
/* send this via ntfy */
char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
char *msg = xs_dict_get(q_item, "message");
char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
const char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
const char *msg = xs_dict_get(q_item, "message");
const char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
int status = 0;
xs *url = xs_fmt("%s", ntfy_server);
@ -2552,8 +2480,8 @@ void process_queue_item(xs_dict *q_item)
}
else
if (strcmp(type, "input") == 0) {
xs_dict *msg = xs_dict_get(q_item, "message");
xs_dict *req = xs_dict_get(q_item, "req");
const xs_dict *msg = xs_dict_get(q_item, "message");
const xs_dict *req = xs_dict_get(q_item, "req");
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
/* do some instance-level checks */
@ -2572,7 +2500,7 @@ void process_queue_item(xs_dict *q_item)
else
if (r == 2) {
/* redistribute the input message to all users */
char *ntid = xs_dict_get(q_item, "ntid");
const char *ntid = xs_dict_get(q_item, "ntid");
xs *tmpfn = xs_fmt("%s/tmp/%s.json", srv_basedir, ntid);
FILE *f;
@ -2647,7 +2575,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
char **body, int *b_size, char **ctype)
{
int status = 200;
char *accept = xs_dict_get(req, "accept");
const char *accept = xs_dict_get(req, "accept");
snac snac;
xs *msg = NULL;
@ -2659,7 +2587,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
return 0;
xs *l = xs_split_n(q_path, "/", 2);
char *uid, *p_path;
const char *uid;
const char *p_path;
uid = xs_list_get(l, 1);
if (!user_open(&snac, uid)) {
@ -2677,7 +2606,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
msg = msg_actor(&snac);
*ctype = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
char *ua = xs_dict_get(req, "user-agent");
const char *ua = xs_dict_get(req, "user-agent");
snac_debug(&snac, 0, xs_fmt("serving actor [%s]", ua ? ua : "No UA"));
}
@ -2694,8 +2623,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
xs *i = NULL;
if (valid_status(object_get_by_md5(v, &i))) {
char *type = xs_dict_get(i, "type");
char *id = xs_dict_get(i, "id");
const char *type = xs_dict_get(i, "type");
const char *id = xs_dict_get(i, "id");
if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) {
xs *c_msg = msg_create(&snac, i);
@ -2748,9 +2677,9 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
(void)b_size;
int status = 202; /* accepted */
char *i_ctype = xs_dict_get(req, "content-type");
const char *i_ctype = xs_dict_get(req, "content-type");
snac snac;
char *v;
const char *v;
if (i_ctype == NULL) {
*body = xs_str_new("no content-type");

130
data.c
View file

@ -29,7 +29,7 @@ pthread_mutex_t data_mutex = {0};
int snac_upgrade(xs_str **error);
int srv_open(char *basedir, int auto_upgrade)
int srv_open(const char *basedir, int auto_upgrade)
/* opens a server */
{
int ret = 0;
@ -58,10 +58,10 @@ int srv_open(char *basedir, int auto_upgrade)
if (srv_config == NULL)
error = xs_fmt("ERROR: cannot parse '%s'", cfg_file);
else {
char *host;
char *prefix;
char *dbglvl;
char *proto;
const char *host;
const char *prefix;
const char *dbglvl;
const char *proto;
host = xs_dict_get(srv_config, "host");
prefix = xs_dict_get(srv_config, "prefix");
@ -710,7 +710,7 @@ int _object_add(const char *id, const xs_dict *obj, int ow)
fclose(f);
/* does this object has a parent? */
char *in_reply_to = xs_dict_get(obj, "inReplyTo");
const char *in_reply_to = xs_dict_get(obj, "inReplyTo");
if (!xs_is_null(in_reply_to) && *in_reply_to) {
/* update the children index of the parent */
@ -1124,7 +1124,7 @@ int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg)
}
int timeline_del(snac *snac, char *id)
int timeline_del(snac *snac, const char *id)
/* deletes a message from the timeline */
{
/* delete from the user's caches */
@ -1192,17 +1192,16 @@ int timeline_admire(snac *snac, const char *id, const char *admirer, int like)
}
xs_list *timeline_top_level(snac *snac, xs_list *list)
xs_list *timeline_top_level(snac *snac, const xs_list *list)
/* returns the top level md5 entries from this index */
{
xs_set seen;
xs_list *p;
xs_str *v;
xs_set_init(&seen);
p = list;
while (xs_list_iter(&p, &v)) {
int c = 0;
while (xs_list_next(list, &v, &c)) {
char line[256] = "";
strncpy(line, v, sizeof(line));
@ -1290,7 +1289,7 @@ int following_add(snac *snac, const char *actor, const xs_dict *msg)
/* object already exists; if it's of type Accept,
the actor is already being followed and confirmed,
so do nothing */
char *type = xs_dict_get(p_object, "type");
const char *type = xs_dict_get(p_object, "type");
if (!xs_is_null(type) && strcmp(type, "Accept") == 0) {
snac_debug(snac, 1, xs_fmt("following_add actor already confirmed %s", actor));
@ -1546,8 +1545,9 @@ void hide(snac *snac, const char *id)
/* resolve to get the id */
if (valid_status(object_get_by_md5(v, &co))) {
if ((v = xs_dict_get(co, "id")) != NULL)
hide(snac, v);
const char *id = xs_dict_get(co, "id");
if (id != NULL)
hide(snac, id);
}
}
}
@ -1563,7 +1563,7 @@ int is_hidden(snac *snac, const char *id)
}
int actor_add(const char *actor, xs_dict *msg)
int actor_add(const char *actor, const xs_dict *msg)
/* adds an actor */
{
return object_add_ow(actor, msg);
@ -1687,7 +1687,7 @@ int limited(snac *user, const char *id, int cmd)
void tag_index(const char *id, const xs_dict *obj)
/* update the tag indexes for this object */
{
xs_list *tags = xs_dict_get(obj, "tag");
const xs_list *tags = xs_dict_get(obj, "tag");
if (is_msg_public(obj) && xs_type(tags) == XSTYPE_LIST && xs_list_len(tags) > 0) {
xs *g_tag_dir = xs_fmt("%s/tag", srv_basedir);
@ -1695,9 +1695,10 @@ void tag_index(const char *id, const xs_dict *obj)
mkdirx(g_tag_dir);
xs_dict *v;
while (xs_list_iter(&tags, &v)) {
char *type = xs_dict_get(v, "type");
char *name = xs_dict_get(v, "name");
int ct = 0;
while (xs_list_next(tags, &v, &ct)) {
const char *type = xs_dict_get(v, "type");
const char *name = xs_dict_get(v, "name");
if (!xs_is_null(type) && !xs_is_null(name) && strcmp(type, "Hashtag") == 0) {
while (*name == '#' || *name == '@')
@ -1706,7 +1707,7 @@ void tag_index(const char *id, const xs_dict *obj)
if (*name == '\0')
continue;
name = xs_tolower_i(name);
name = xs_tolower_i((xs_str *)name);
xs *md5_tag = xs_md5_hex(name, strlen(name));
xs *tag_dir = xs_fmt("%s/%c%c", g_tag_dir, md5_tag[0], md5_tag[1]);
@ -1729,7 +1730,7 @@ void tag_index(const char *id, const xs_dict *obj)
}
xs_list *tag_search(char *tag, int skip, int show)
xs_list *tag_search(const char *tag, int skip, int show)
/* returns the list of posts tagged with tag */
{
if (*tag == '#')
@ -1912,7 +1913,7 @@ xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op
void list_distribute(snac *user, const char *who, const xs_dict *post)
/* distributes the post to all appropriate lists */
{
char *id = xs_dict_get(post, "id");
const char *id = xs_dict_get(post, "id");
/* if who is not set, use the attributedTo in the message */
if (xs_is_null(who))
@ -2164,7 +2165,7 @@ void inbox_add(const char *inbox)
void inbox_add_by_actor(const xs_dict *actor)
/* collects an actor's shared inbox, if it has one */
{
char *v;
const char *v;
if (!xs_is_null(v = xs_dict_get(actor, "endpoints")) &&
!xs_is_null(v = xs_dict_get(v, "sharedInbox"))) {
@ -2210,7 +2211,7 @@ xs_str *_instance_block_fn(const char *instance)
xs *s = xs_replace(instance, "http:/" "/", "");
xs *s1 = xs_replace(s, "https:/" "/", "");
xs *l = xs_split(s1, "/");
char *p = xs_list_get(l, 0);
const char *p = xs_list_get(l, 0);
xs *md5 = xs_md5_hex(p, strlen(p));
return xs_fmt("%s/block/%s", srv_basedir, md5);
@ -2279,7 +2280,7 @@ int content_match(const char *file, const xs_dict *msg)
xs *fn = xs_fmt("%s/%s", srv_basedir, file);
FILE *f;
int r = 0;
char *v = xs_dict_get(msg, "content");
const char *v = xs_dict_get(msg, "content");
if (xs_type(v) == XSTYPE_STRING && *v) {
if ((f = fopen(fn, "r")) != NULL) {
@ -2386,7 +2387,7 @@ xs_list *content_search(snac *user, const char *regex,
if (id == NULL || is_hidden(user, id))
continue;
char *content = xs_dict_get(post, "content");
const char *content = xs_dict_get(post, "content");
if (xs_is_null(content))
continue;
@ -2639,7 +2640,7 @@ void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retri
/* enqueues an input message */
{
xs *qmsg = _new_qmsg("input", msg, retries);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid);
qmsg = xs_dict_append(qmsg, "req", req);
@ -2654,7 +2655,7 @@ void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries)
/* enqueues an input message from the shared input */
{
xs *qmsg = _new_qmsg("input", msg, retries);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
qmsg = xs_dict_append(qmsg, "req", req);
@ -2666,11 +2667,12 @@ void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries)
void enqueue_output_raw(const char *keyid, const char *seckey,
xs_dict *msg, xs_str *inbox, int retries, int p_status)
const xs_dict *msg, const xs_str *inbox,
int retries, int p_status)
/* enqueues an output message to an inbox */
{
xs *qmsg = _new_qmsg("output", msg, retries);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
xs *ns = xs_number_new(p_status);
@ -2690,7 +2692,8 @@ void enqueue_output_raw(const char *keyid, const char *seckey,
}
void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_status)
void enqueue_output(snac *snac, const xs_dict *msg,
const xs_str *inbox, int retries, int p_status)
/* enqueues an output message to an inbox */
{
if (xs_startswith(inbox, snac->actor)) {
@ -2698,13 +2701,14 @@ void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_
return;
}
char *seckey = xs_dict_get(snac->key, "secret");
const char *seckey = xs_dict_get(snac->key, "secret");
enqueue_output_raw(snac->actor, seckey, msg, inbox, retries, p_status);
}
void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries)
void enqueue_output_by_actor(snac *snac, const xs_dict *msg,
const xs_str *actor, int retries)
/* enqueues an output message for an actor */
{
xs *inbox = get_actor_inbox(actor);
@ -2716,11 +2720,11 @@ void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int
}
void enqueue_email(xs_str *msg, int retries)
void enqueue_email(const xs_str *msg, int retries)
/* enqueues an email message to be sent */
{
xs *qmsg = _new_qmsg("email", msg, retries);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
qmsg = _enqueue_put(fn, qmsg);
@ -2733,7 +2737,7 @@ void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id)
/* enqueues a message to be sent via Telegram */
{
xs *qmsg = _new_qmsg("telegram", msg, 0);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
qmsg = xs_dict_append(qmsg, "bot", bot);
@ -2748,7 +2752,7 @@ void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_t
/* enqueues a message to be sent via ntfy */
{
xs *qmsg = _new_qmsg("ntfy", msg, 0);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
qmsg = xs_dict_append(qmsg, "ntfy_server", ntfy_server);
@ -2764,7 +2768,7 @@ void enqueue_message(snac *snac, const xs_dict *msg)
/* enqueues an output message */
{
xs *qmsg = _new_qmsg("message", msg, 0);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid);
qmsg = _enqueue_put(fn, qmsg);
@ -2807,7 +2811,7 @@ void enqueue_verify_links(snac *user)
/* enqueues a link verification */
{
xs *qmsg = _new_qmsg("verify_links", "", 0);
char *ntid = xs_dict_get(qmsg, "ntid");
const char *ntid = xs_dict_get(qmsg, "ntid");
xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid);
qmsg = _enqueue_put(fn, qmsg);
@ -2832,42 +2836,6 @@ void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs)
}
void enqueue_request_replies(snac *user, const char *id)
/* enqueues a request for the replies of a message */
{
/* test first if this precise request is already in the queue */
xs *queue = user_queue(user);
xs_list *p = queue;
xs_str *v;
while (xs_list_iter(&p, &v)) {
xs *q_item = queue_get(v);
if (q_item != NULL) {
const char *type = xs_dict_get(q_item, "type");
const char *msg = xs_dict_get(q_item, "message");
if (type && msg && strcmp(type, "request_replies") == 0 && strcmp(msg, id) == 0) {
/* don't requeue */
snac_debug(user, 1, xs_fmt("enqueue_request_replies already here %s", id));
return;
}
}
}
/* not there; enqueue the request with a small delay */
xs *qmsg = _new_qmsg("request_replies", id, 0);
xs *ntid = tid(10);
xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid);
qmsg = xs_dict_set(qmsg, "ntid", ntid);
qmsg = _enqueue_put(fn, qmsg);
snac_debug(user, 2, xs_fmt("enqueue_request_replies %s", id));
}
int was_question_voted(snac *user, const char *id)
/* returns true if the user voted in this poll */
{
@ -2881,7 +2849,7 @@ int was_question_voted(snac *user, const char *id)
xs *obj = NULL;
if (valid_status(object_get_by_md5(md5, &obj))) {
char *atto = get_atto(obj);
const char *atto = get_atto(obj);
if (atto && strcmp(atto, user->actor) == 0 &&
!xs_is_null(xs_dict_get(obj, "name"))) {
voted = 1;
@ -3055,7 +3023,7 @@ void purge_server(void)
if (mtime_nl(v2, &n_link) < mt && n_link < 2) {
xs *s1 = xs_replace(v2, ".json", "");
xs *l = xs_split(s1, "/");
char *md5 = xs_list_get(l, -1);
const char *md5 = xs_list_get(l, -1);
object_del_by_md5(md5);
cnt++;
@ -3147,7 +3115,7 @@ void purge_user(snac *snac)
/* do the purge for this user */
{
int priv_days, pub_days, user_days = 0;
char *v;
const char *v;
int n;
priv_days = xs_number_get(xs_dict_get(srv_config, "timeline_purge_days"));
@ -3256,7 +3224,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req,
if (p_size && payload) {
xs *payload_fn = NULL;
xs *payload_fn_raw = NULL;
char *v = xs_dict_get(req, "content-type");
const char *v = xs_dict_get(req, "content-type");
if (v && xs_str_in(v, "json") != -1) {
payload_fn = xs_fmt("%s/payload.json", dir);
@ -3287,7 +3255,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req,
if (b_size && body) {
xs *body_fn = NULL;
char *v = xs_dict_get(headers, "content-type");
const char *v = xs_dict_get(headers, "content-type");
if (v && xs_str_in(v, "json") != -1) {
body_fn = xs_fmt("%s/body.json", dir);
@ -3356,7 +3324,7 @@ void srv_archive_error(const char *prefix, const xs_str *err,
}
void srv_archive_qitem(char *prefix, xs_dict *q_item)
void srv_archive_qitem(const char *prefix, xs_dict *q_item)
/* archives a q_item in the error folder */
{
xs *ntid = tid(0);

278
html.c
View file

@ -41,7 +41,7 @@ int login(snac *snac, const xs_dict *headers)
}
xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems)
xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems)
/* replaces all the :shortnames: with the emojis in tag */
{
if (!xs_is_null(tag)) {
@ -57,18 +57,18 @@ xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems)
xs *style = xs_fmt("height: %dem; width: %dem; vertical-align: middle;", ems, ems);
xs_list *p = tag_list;
char *v;
int c = 0;
while (xs_list_iter(&p, &v)) {
char *t = xs_dict_get(v, "type");
while (xs_list_next(tag_list, &v, &c)) {
const char *t = xs_dict_get(v, "type");
if (t && strcmp(t, "Emoji") == 0) {
char *n = xs_dict_get(v, "name");
char *i = xs_dict_get(v, "icon");
const char *n = xs_dict_get(v, "name");
const char *i = xs_dict_get(v, "icon");
if (n && i) {
char *u = xs_dict_get(i, "url");
const char *u = xs_dict_get(i, "url");
xs_html *img = xs_html_sctag("img",
xs_html_attr("loading", "lazy"),
xs_html_attr("src", u),
@ -88,7 +88,7 @@ xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems)
xs_str *actor_name(xs_dict *actor)
/* gets the actor name */
{
char *v;
const char *v;
if (xs_is_null((v = xs_dict_get(actor, "name"))) || *v == '\0') {
if (xs_is_null(v = xs_dict_get(actor, "preferredUsername")) || *v == '\0') {
@ -106,7 +106,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
xs_html *actor_icon = xs_html_tag("p", NULL);
xs *avatar = NULL;
char *v;
const char *v;
int fwing = 0;
int fwer = 0;
@ -125,7 +125,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
if (avatar == NULL)
avatar = xs_fmt("data:image/png;base64, %s", default_avatar_base64());
char *actor_id = xs_dict_get(actor, "id");
const char *actor_id = xs_dict_get(actor, "id");
xs *href = NULL;
if (user) {
@ -216,7 +216,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
}
{
char *username, *id;
const char *username, *id;
if (xs_is_null(username = xs_dict_get(actor, "preferredUsername")) || *username == '\0') {
/* This should never be reached */
@ -244,15 +244,15 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
}
xs_html *html_msg_icon(snac *user, char *actor_id, const xs_dict *msg)
xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg)
{
xs *actor = NULL;
xs_html *actor_icon = NULL;
if (actor_id && valid_status(actor_get_refresh(user, actor_id, &actor))) {
char *date = NULL;
char *udate = NULL;
char *url = NULL;
const char *date = NULL;
const char *udate = NULL;
const char *url = NULL;
int priv = 0;
const char *type = xs_dict_get(msg, "type");
@ -271,14 +271,14 @@ xs_html *html_msg_icon(snac *user, char *actor_id, const xs_dict *msg)
}
xs_html *html_note(snac *user, char *summary,
char *div_id, char *form_id,
char *ta_plh, char *ta_content,
char *edit_id, char *actor_id,
xs_val *cw_yn, char *cw_text,
xs_val *mnt_only, char *redir,
char *in_reply_to, int poll,
char *att_file, char *att_alt_text)
xs_html *html_note(snac *user, const char *summary,
const char *div_id, const char *form_id,
const char *ta_plh, const char *ta_content,
const char *edit_id, const char *actor_id,
const xs_val *cw_yn, const char *cw_text,
const xs_val *mnt_only, const char *redir,
const char *in_reply_to, int poll,
const char *att_file, const char *att_alt_text)
{
xs *action = xs_fmt("%s/admin/note", user->actor);
@ -460,9 +460,11 @@ static xs_html *html_base_head(void)
/* add server CSS and favicon */
xs *f;
f = xs_fmt("%s/favicon.ico", srv_baseurl);
xs_list *p = xs_dict_get(srv_config, "cssurls");
const xs_list *p = xs_dict_get(srv_config, "cssurls");
char *v;
while (xs_list_iter(&p, &v)) {
int c = 0;
while (xs_list_next(p, &v, &c)) {
xs_html_add(head,
xs_html_sctag("link",
xs_html_attr("rel", "stylesheet"),
@ -498,8 +500,8 @@ xs_html *html_instance_head(void)
}
}
char *host = xs_dict_get(srv_config, "host");
char *title = xs_dict_get(srv_config, "title");
const char *host = xs_dict_get(srv_config, "host");
const char *title = xs_dict_get(srv_config, "title");
xs_html_add(head,
xs_html_tag("title",
@ -511,10 +513,10 @@ xs_html *html_instance_head(void)
static xs_html *html_instance_body(void)
{
char *host = xs_dict_get(srv_config, "host");
char *sdesc = xs_dict_get(srv_config, "short_description");
char *email = xs_dict_get(srv_config, "admin_email");
char *acct = xs_dict_get(srv_config, "admin_account");
const char *host = xs_dict_get(srv_config, "host");
const char *sdesc = xs_dict_get(srv_config, "short_description");
const char *email = xs_dict_get(srv_config, "admin_email");
const char *acct = xs_dict_get(srv_config, "admin_account");
xs *blurb = xs_replace(snac_blurb, "%host%", host);
@ -760,7 +762,7 @@ static xs_html *html_user_body(snac *user, int read_only)
xs_html_attr("class", "h-card snac-top-user"));
if (read_only) {
char *header = xs_dict_get(user->config, "header");
const char *header = xs_dict_get(user->config, "header");
if (header && *header) {
xs_html_add(top_user,
xs_html_tag("div",
@ -797,7 +799,7 @@ static xs_html *html_user_body(snac *user, int read_only)
xs_html_add(top_user,
top_user_bio);
xs_dict *metadata = xs_dict_get(user->config, "metadata");
const xs_dict *metadata = xs_dict_get(user->config, "metadata");
if (xs_type(metadata) == XSTYPE_DICT) {
xs_str *k;
xs_str *v;
@ -816,7 +818,7 @@ static xs_html *html_user_body(snac *user, int read_only)
if (xs_startswith(v, "https:/") || xs_startswith(v, "http:/")) {
/* is this link validated? */
xs *verified_link = NULL;
xs_number *val_time = xs_dict_get(val_links, v);
const xs_number *val_time = xs_dict_get(val_links, v);
if (xs_type(val_time) == XSTYPE_NUMBER) {
time_t t = xs_number_get(val_time);
@ -928,7 +930,7 @@ xs_html *html_top_controls(snac *snac)
/** user settings **/
char *email = "[disabled by admin]";
const char *email = "[disabled by admin]";
if (xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE) {
email = xs_dict_get(snac->config_o, "email");
@ -940,38 +942,38 @@ xs_html *html_top_controls(snac *snac)
}
}
char *cw = xs_dict_get(snac->config, "cw");
const char *cw = xs_dict_get(snac->config, "cw");
if (xs_is_null(cw))
cw = "";
char *telegram_bot = xs_dict_get(snac->config, "telegram_bot");
const char *telegram_bot = xs_dict_get(snac->config, "telegram_bot");
if (xs_is_null(telegram_bot))
telegram_bot = "";
char *telegram_chat_id = xs_dict_get(snac->config, "telegram_chat_id");
const char *telegram_chat_id = xs_dict_get(snac->config, "telegram_chat_id");
if (xs_is_null(telegram_chat_id))
telegram_chat_id = "";
char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
const char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
if (xs_is_null(ntfy_server))
ntfy_server = "";
char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
const char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
if (xs_is_null(ntfy_token))
ntfy_token = "";
char *purge_days = xs_dict_get(snac->config, "purge_days");
const char *purge_days = xs_dict_get(snac->config, "purge_days");
if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER)
purge_days = (char *)xs_number_str(purge_days);
else
purge_days = "0";
xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown");
xs_val *bot = xs_dict_get(snac->config, "bot");
xs_val *a_private = xs_dict_get(snac->config, "private");
const xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown");
const xs_val *bot = xs_dict_get(snac->config, "bot");
const xs_val *a_private = xs_dict_get(snac->config, "private");
xs *metadata = xs_str_new(NULL);
xs_dict *md = xs_dict_get(snac->config, "metadata");
const xs_dict *md = xs_dict_get(snac->config, "metadata");
xs_str *k;
xs_str *v;
@ -1158,13 +1160,14 @@ xs_str *build_mentions(snac *snac, const xs_dict *msg)
/* returns a string with the mentions in msg */
{
xs_str *s = xs_str_new(NULL);
char *list = xs_dict_get(msg, "tag");
const char *list = xs_dict_get(msg, "tag");
char *v;
int c = 0;
while (xs_list_iter(&list, &v)) {
char *type = xs_dict_get(v, "type");
char *href = xs_dict_get(v, "href");
char *name = xs_dict_get(v, "name");
while (xs_list_next(list, &v, &c)) {
const char *type = xs_dict_get(v, "type");
const char *href = xs_dict_get(v, "href");
const char *name = xs_dict_get(v, "name");
if (type && strcmp(type, "Mention") == 0 &&
href && strcmp(href, snac->actor) != 0 && name) {
@ -1208,10 +1211,11 @@ xs_str *build_mentions(snac *snac, const xs_dict *msg)
}
xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const char *md5)
xs_html *html_entry_controls(snac *snac, const char *actor,
const xs_dict *msg, const char *md5)
{
char *id = xs_dict_get(msg, "id");
char *group = xs_dict_get(msg, "audience");
const char *id = xs_dict_get(msg, "id");
const char *group = xs_dict_get(msg, "audience");
xs *likes = object_likes(id);
xs *boosts = object_announces(id);
@ -1310,7 +1314,7 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const
html_button("delete", L("Delete"), L("Delete this post")),
html_button("hide", L("Hide"), L("Hide this post and its children")));
char *prev_src = xs_dict_get(msg, "sourceContent");
const char *prev_src = xs_dict_get(msg, "sourceContent");
if (!xs_is_null(prev_src) && strcmp(actor, snac->actor) == 0) { /** edit **/
/* post can be edited */
@ -1318,13 +1322,13 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const
xs *form_id = xs_fmt("%s_edit_form", md5);
xs *redir = xs_fmt("%s_entry", md5);
char *att_file = "";
char *att_alt_text = "";
xs_list *att_list = xs_dict_get(msg, "attachment");
const char *att_file = "";
const char *att_alt_text = "";
const xs_list *att_list = xs_dict_get(msg, "attachment");
/* does it have an attachment? */
if (xs_type(att_list) == XSTYPE_LIST && xs_list_len(att_list)) {
xs_dict *d = xs_list_get(att_list, 0);
const xs_dict *d = xs_list_get(att_list, 0);
if (xs_type(d) == XSTYPE_DICT) {
att_file = xs_dict_get_def(d, "url", "");
@ -1370,10 +1374,10 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const
xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
int level, char *md5, int hide_children)
{
char *id = xs_dict_get(msg, "id");
char *type = xs_dict_get(msg, "type");
char *actor;
char *v;
const char *id = xs_dict_get(msg, "id");
const char *type = xs_dict_get(msg, "type");
const char *actor;
const char *v;
int has_title = 0;
/* do not show non-public messages in the public timeline */
@ -1509,7 +1513,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
if (xs_list_len(boosts)) {
/* if somebody boosted this, show as origin */
char *p = xs_list_get(boosts, -1);
const char *p = xs_list_get(boosts, -1);
xs *actor_r = NULL;
if (user && xs_list_in(boosts, user->md5) != -1) {
@ -1529,7 +1533,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
if (!xs_is_null(name)) {
xs *href = NULL;
char *id = xs_dict_get(actor_r, "id");
const char *id = xs_dict_get(actor_r, "id");
int fwers = 0;
int fwing = 0;
@ -1558,7 +1562,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
if (strcmp(type, "Note") == 0) {
if (level == 0) {
/* is the parent not here? */
char *parent = xs_dict_get(msg, "inReplyTo");
const char *parent = xs_dict_get(msg, "inReplyTo");
if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) {
xs_html_add(post_header,
@ -1603,7 +1607,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
v = "...";
/* only show it when not in the public timeline and the config setting is "open" */
char *cw = xs_dict_get(user->config, "cw");
const char *cw = xs_dict_get(user->config, "cw");
if (xs_is_null(cw) || read_only)
cw = "";
@ -1632,7 +1636,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
{
/** build the content string **/
char *content = xs_dict_get(msg, "content");
const char *content = xs_dict_get(msg, "content");
xs *c = sanitize(xs_is_null(content) ? "" : content);
@ -1650,7 +1654,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2);
/* Peertube videos content is in markdown */
char *mtype = xs_dict_get(msg, "mediaType");
const char *mtype = xs_dict_get(msg, "mediaType");
if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "text/markdown") == 0) {
/* a full conversion could be better */
c = xs_replace_i(c, "\r", "");
@ -1663,12 +1667,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
}
if (strcmp(type, "Question") == 0) { /** question content **/
xs_list *oo = xs_dict_get(msg, "oneOf");
xs_list *ao = xs_dict_get(msg, "anyOf");
xs_list *p;
const xs_list *oo = xs_dict_get(msg, "oneOf");
const xs_list *ao = xs_dict_get(msg, "anyOf");
const xs_list *p;
xs_dict *v;
int closed = 0;
char *f_closed = NULL;
const char *f_closed = NULL;
xs_html *poll = xs_html_tag("div", NULL);
@ -1697,10 +1701,11 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
/* closed poll */
xs_html *poll_result = xs_html_tag("table",
xs_html_attr("class", "snac-poll-result"));
int c = 0;
while (xs_list_iter(&p, &v)) {
char *name = xs_dict_get(v, "name");
xs_dict *replies = xs_dict_get(v, "replies");
while (xs_list_next(p, &v, &c)) {
const char *name = xs_dict_get(v, "name");
const xs_dict *replies = xs_dict_get(v, "replies");
if (name && replies) {
char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems"));
@ -1737,9 +1742,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
xs_html_attr("name", "irt"),
xs_html_attr("value", id))));
while (xs_list_iter(&p, &v)) {
char *name = xs_dict_get(v, "name");
xs_dict *replies = xs_dict_get(v, "replies");
int c = 0;
while (xs_list_next(p, &v, &c)) {
const char *name = xs_dict_get(v, "name");
const xs_dict *replies = xs_dict_get(v, "replies");
if (name) {
char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems"));
@ -1777,7 +1783,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
}
else {
/* show when the poll closes */
char *end_time = xs_dict_get(msg, "endTime");
const char *end_time = xs_dict_get(msg, "endTime");
/* Pleroma does not have an endTime field;
it has a closed time in the future */
@ -1820,12 +1826,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
xs_html_add(snac_content,
content_attachments);
xs_list *p = attach;
while (xs_list_iter(&p, &v)) {
char *type = xs_dict_get(v, "type");
char *href = xs_dict_get(v, "href");
char *name = xs_dict_get(v, "name");
int c = 0;
xs_dict *a;
while (xs_list_next(attach, &a, &c)) {
const char *type = xs_dict_get(a, "type");
const char *href = xs_dict_get(a, "href");
const char *name = xs_dict_get(a, "name");
if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) {
xs_html_add(content_attachments,
@ -1889,7 +1895,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
}
/* has this message an audience (i.e., comes from a channel or community)? */
char *audience = xs_dict_get(msg, "audience");
const char *audience = xs_dict_get(msg, "audience");
if (strcmp(type, "Page") == 0 && !xs_is_null(audience)) {
xs_html *au_tag = xs_html_tag("p",
xs_html_text("("),
@ -2023,11 +2029,12 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
if (xs_list_len(list) == 1) {
/* only one element? pick the description from the source */
char *id = xs_list_get(list, 0);
const char *id = xs_list_get(list, 0);
xs *d = NULL;
object_get_by_md5(id, &d);
if (d && (v = xs_dict_get(d, "sourceContent")) != NULL)
desc = xs_dup(v);
const char *sc = xs_dict_get(d, "sourceContent");
if (d && sc != NULL)
desc = xs_dup(sc);
alternate = xs_dup(xs_dict_get(d, "id"));
}
@ -2087,13 +2094,13 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
/* is this message a non-public reply? */
if (user != NULL && !is_msg_public(msg)) {
char *irt = xs_dict_get(msg, "inReplyTo");
const char *irt = xs_dict_get(msg, "inReplyTo");
/* is it a reply to something not in the storage? */
if (!xs_is_null(irt) && !object_here(irt)) {
/* is it for me? */
xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST));
xs_list *cc = xs_dict_get_def(msg, "cc", xs_stock(XSTYPE_LIST));
const xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST));
const xs_list *cc = xs_dict_get_def(msg, "cc", xs_stock(XSTYPE_LIST));
if (xs_list_in(to, user->actor) == -1 && xs_list_in(cc, user->actor) == -1) {
snac_debug(user, 1, xs_fmt("skipping non-public reply to an unknown post %s", v));
@ -2212,7 +2219,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t)
html_actor_icon(snac, actor, xs_dict_get(actor, "published"), NULL, NULL, 0, 1)));
/* content (user bio) */
char *c = xs_dict_get(actor, "summary");
const char *c = xs_dict_get(actor, "summary");
if (!xs_is_null(c)) {
xs *sc = sanitize(c);
@ -2364,10 +2371,10 @@ xs_str *html_notifications(snac *user, int skip, int show)
continue;
xs *obj = NULL;
char *type = xs_dict_get(noti, "type");
char *utype = xs_dict_get(noti, "utype");
char *id = xs_dict_get(noti, "objid");
char *date = xs_dict_get(noti, "date");
const char *type = xs_dict_get(noti, "type");
const char *utype = xs_dict_get(noti, "utype");
const char *id = xs_dict_get(noti, "objid");
const char *date = xs_dict_get(noti, "date");
if (xs_is_null(id) || !valid_status(object_get(id, &obj)))
continue;
@ -2375,14 +2382,14 @@ xs_str *html_notifications(snac *user, int skip, int show)
if (is_hidden(user, id))
continue;
char *actor_id = xs_dict_get(noti, "actor");
const char *actor_id = xs_dict_get(noti, "actor");
xs *actor = NULL;
if (!valid_status(actor_get(actor_id, &actor)))
continue;
xs *a_name = actor_name(actor);
char *label = type;
const char *label = type;
if (strcmp(type, "Create") == 0)
label = L("Mention");
@ -2494,14 +2501,14 @@ xs_str *html_notifications(snac *user, int skip, int show)
int html_get_handler(const xs_dict *req, const char *q_path,
char **body, int *b_size, char **ctype, xs_str **etag)
{
char *accept = xs_dict_get(req, "accept");
const char *accept = xs_dict_get(req, "accept");
int status = 404;
snac snac;
xs *uid = NULL;
char *p_path;
const char *p_path;
int cache = 1;
int save = 1;
char *v;
const char *v;
xs *l = xs_split_n(q_path, "/", 2);
v = xs_list_get(l, 1);
@ -2540,7 +2547,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
int skip = 0;
int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries"));
xs_dict *q_vars = xs_dict_get(req, "q_vars");
const xs_dict *q_vars = xs_dict_get(req, "q_vars");
if ((v = xs_dict_get(q_vars, "skip")) != NULL)
skip = atoi(v), cache = 0, save = 0;
if ((v = xs_dict_get(q_vars, "show")) != NULL)
@ -2585,7 +2592,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
status = 401;
}
else {
char *q = xs_dict_get(q_vars, "q");
const char *q = xs_dict_get(q_vars, "q");
if (q && *q) {
if (*q == '#') {
@ -2669,7 +2676,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
}
else {
xs *l = xs_split(p_path, "/");
char *md5 = xs_list_get(l, -1);
const char *md5 = xs_list_get(l, -1);
if (md5 && *md5 && timeline_here(&snac, md5)) {
xs *list = xs_list_append(xs_list_new(), md5);
@ -2728,7 +2735,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
}
else {
xs *l = xs_split(p_path, "/");
char *lid = xs_list_get(l, -1);
const char *lid = xs_list_get(l, -1);
xs *list = list_timeline(&snac, lid, skip, show);
xs *next = list_timeline(&snac, lid, skip + show, 1);
@ -2767,7 +2774,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
else
if (xs_startswith(p_path, "s/")) { /** a static file **/
xs *l = xs_split(p_path, "/");
char *id = xs_list_get(l, 1);
const char *id = xs_list_get(l, 1);
int sz;
if (id && *id) {
@ -2788,8 +2795,8 @@ int html_get_handler(const xs_dict *req, const char *q_path,
if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE)
return 403;
xs *l = xs_split(p_path, "/");
char *id = xs_list_get(l, 1);
xs *l = xs_split(p_path, "/");
const char *id = xs_list_get(l, 1);
if (id && *id) {
if (xs_endswith(id, "timeline.html_")) {
@ -2845,8 +2852,9 @@ int html_post_handler(const xs_dict *req, const char *q_path,
int status = 0;
snac snac;
char *uid, *p_path;
xs_dict *p_vars;
const char *uid;
const char *p_path;
const xs_dict *p_vars;
xs *l = xs_split_n(q_path, "/", 2);
@ -2874,15 +2882,15 @@ int html_post_handler(const xs_dict *req, const char *q_path,
if (p_path && strcmp(p_path, "admin/note") == 0) { /** **/
/* post note */
xs_str *content = xs_dict_get(p_vars, "content");
xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to");
xs_str *attach_url = xs_dict_get(p_vars, "attach_url");
xs_list *attach_file = xs_dict_get(p_vars, "attach");
xs_str *to = xs_dict_get(p_vars, "to");
xs_str *sensitive = xs_dict_get(p_vars, "sensitive");
xs_str *summary = xs_dict_get(p_vars, "summary");
xs_str *edit_id = xs_dict_get(p_vars, "edit_id");
xs_str *alt_text = xs_dict_get(p_vars, "alt_text");
const xs_str *content = xs_dict_get(p_vars, "content");
const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to");
const xs_str *attach_url = xs_dict_get(p_vars, "attach_url");
const xs_list *attach_file = xs_dict_get(p_vars, "attach");
const xs_str *to = xs_dict_get(p_vars, "to");
const xs_str *sensitive = xs_dict_get(p_vars, "sensitive");
const xs_str *summary = xs_dict_get(p_vars, "summary");
const xs_str *edit_id = xs_dict_get(p_vars, "edit_id");
const xs_str *alt_text = xs_dict_get(p_vars, "alt_text");
int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only"));
xs *attach_list = xs_list_new();
@ -2902,7 +2910,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
/* is attach_file set? */
if (!xs_is_null(attach_file) && xs_type(attach_file) == XSTYPE_LIST) {
char *fn = xs_list_get(attach_file, 0);
const char *fn = xs_list_get(attach_file, 0);
if (*fn != '\0') {
char *ext = strrchr(fn, '.');
@ -2978,7 +2986,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
int n;
for (n = 0; fields[n]; n++) {
char *v = xs_dict_get(p_msg, fields[n]);
const char *v = xs_dict_get(p_msg, fields[n]);
msg = xs_dict_set(msg, fields[n], v);
}
@ -3007,10 +3015,10 @@ int html_post_handler(const xs_dict *req, const char *q_path,
else
if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/
/* action on an entry */
char *id = xs_dict_get(p_vars, "id");
char *actor = xs_dict_get(p_vars, "actor");
char *action = xs_dict_get(p_vars, "action");
char *group = xs_dict_get(p_vars, "group");
const char *id = xs_dict_get(p_vars, "id");
const char *actor = xs_dict_get(p_vars, "actor");
const char *action = xs_dict_get(p_vars, "action");
const char *group = xs_dict_get(p_vars, "group");
if (action == NULL)
return 404;
@ -3134,7 +3142,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
}
else
if (strcmp(action, L("Delete")) == 0) { /** **/
char *actor_form = xs_dict_get(p_vars, "actor-form");
const char *actor_form = xs_dict_get(p_vars, "actor-form");
if (actor_form != NULL) {
/* delete follower */
if (valid_status(follower_del(&snac, actor)))
@ -3178,8 +3186,8 @@ int html_post_handler(const xs_dict *req, const char *q_path,
else
if (p_path && strcmp(p_path, "admin/user-setup") == 0) { /** **/
/* change of user data */
char *v;
char *p1, *p2;
const char *v;
const char *p1, *p2;
if ((v = xs_dict_get(p_vars, "name")) != NULL)
snac.config = xs_dict_set(snac.config, "name", v);
@ -3245,7 +3253,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
for (n = 0; uploads[n]; n++) {
xs *var_name = xs_fmt("%s_file", uploads[n]);
xs_list *uploaded_file = xs_dict_get(p_vars, var_name);
const xs_list *uploaded_file = xs_dict_get(p_vars, var_name);
if (xs_type(uploaded_file) == XSTYPE_LIST) {
const char *fn = xs_list_get(uploaded_file, 0);
@ -3310,7 +3318,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
}
else
if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/
char *irt = xs_dict_get(p_vars, "irt");
const char *irt = xs_dict_get(p_vars, "irt");
const char *opt = xs_dict_get(p_vars, "question");
const char *actor = xs_dict_get(p_vars, "actor");
@ -3345,7 +3353,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
xs *poll = NULL;
if (valid_status(object_get(irt, &poll))) {
char *date = xs_dict_get(poll, "endTime");
const char *date = xs_dict_get(poll, "endTime");
if (xs_is_null(date))
date = xs_dict_get(poll, "closed");
@ -3363,7 +3371,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
}
if (status == 303) {
char *redir = xs_dict_get(p_vars, "redir");
const char *redir = xs_dict_get(p_vars, "redir");
if (xs_is_null(redir))
redir = "top";
@ -3411,8 +3419,8 @@ xs_str *timeline_to_rss(snac *user, const xs_list *timeline, char *title, char *
continue;
}
char *id = xs_dict_get(msg, "id");
char *content = xs_dict_get(msg, "content");
const char *id = xs_dict_get(msg, "id");
const char *content = xs_dict_get(msg, "content");
if (user && !xs_startswith(id, user->actor))
continue;

27
http.c
View file

@ -12,7 +12,7 @@
xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
const char *method, const char *url,
xs_dict *headers,
const xs_dict *headers,
const char *body, int b_size,
int *status, xs_str **payload, int *p_size,
int timeout)
@ -24,8 +24,8 @@ xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
xs *s64 = NULL;
xs *signature = NULL;
xs *hdrs = NULL;
char *host;
char *target;
const char *host;
const char *target;
char *k, *v;
xs_dict *response;
@ -106,13 +106,13 @@ xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
xs_dict *http_signed_request(snac *snac, const char *method, const char *url,
xs_dict *headers,
const xs_dict *headers,
const char *body, int b_size,
int *status, xs_str **payload, int *p_size,
int timeout)
/* does a signed HTTP request */
{
char *seckey = xs_dict_get(snac->key, "secret");
const char *seckey = xs_dict_get(snac->key, "secret");
xs_dict *response;
response = http_signed_request_raw(snac->actor, seckey, method, url,
@ -122,17 +122,18 @@ xs_dict *http_signed_request(snac *snac, const char *method, const char *url,
}
int check_signature(xs_dict *req, xs_str **err)
int check_signature(const xs_dict *req, xs_str **err)
/* check the signature */
{
char *sig_hdr = xs_dict_get(req, "signature");
const char *sig_hdr = xs_dict_get(req, "signature");
xs *keyId = NULL;
xs *headers = NULL;
xs *signature = NULL;
xs *created = NULL;
xs *expires = NULL;
char *pubkey;
char *p;
const char *pubkey;
const char *k;
if (xs_is_null(sig_hdr)) {
*err = xs_fmt("missing 'signature' header");
@ -142,10 +143,10 @@ int check_signature(xs_dict *req, xs_str **err)
{
/* extract the values */
xs *l = xs_split(sig_hdr, ",");
xs_list *p = l;
int c = 0;
xs_val *v;
while (xs_list_iter(&p, &v)) {
while (xs_list_next(l, &v, &c)) {
xs *kv = xs_split_n(v, "=", 1);
if (xs_list_len(kv) != 2)
@ -192,8 +193,8 @@ int check_signature(xs_dict *req, xs_str **err)
return 0;
}
if ((p = xs_dict_get(actor, "publicKey")) == NULL ||
((pubkey = xs_dict_get(p, "publicKeyPem")) == NULL)) {
if ((k = xs_dict_get(actor, "publicKey")) == NULL ||
((pubkey = xs_dict_get(k, "publicKeyPem")) == NULL)) {
*err = xs_fmt("cannot get pubkey from %s", keyId);
return 0;
}
@ -208,7 +209,7 @@ int check_signature(xs_dict *req, xs_str **err)
p = l;
while (xs_list_iter(&p, &v)) {
char *hc;
const char *hc;
xs *ss = NULL;
if (*sig_str != '\0')

16
httpd.c
View file

@ -125,7 +125,7 @@ static xs_str *greeting_html(void)
/* does it have a %userlist% mark? */
if (xs_str_in(s, "%userlist%") != -1) {
char *host = xs_dict_get(srv_config, "host");
const char *host = xs_dict_get(srv_config, "host");
xs *list = user_list();
xs_list *p = list;
xs_str *uid;
@ -171,14 +171,14 @@ int server_get_handler(xs_dict *req, const char *q_path,
/* is it the server root? */
if (*q_path == '\0') {
xs_dict *q_vars = xs_dict_get(req, "q_vars");
char *t = NULL;
const xs_dict *q_vars = xs_dict_get(req, "q_vars");
const char *t = NULL;
if (xs_type(q_vars) == XSTYPE_DICT && (t = xs_dict_get(q_vars, "t"))) {
/** search by tag **/
int skip = 0;
int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries"));
char *v;
const char *v;
if ((v = xs_dict_get(q_vars, "skip")) != NULL)
skip = atoi(v);
@ -193,7 +193,7 @@ int server_get_handler(xs_dict *req, const char *q_path,
more = 1;
}
char *accept = xs_dict_get(req, "accept");
const char *accept = xs_dict_get(req, "accept");
if (!xs_is_null(accept) && strcmp(accept, "application/rss+xml") == 0) {
xs *link = xs_fmt("%s/?t=%s", srv_baseurl, t);
@ -268,7 +268,7 @@ void httpd_connection(FILE *f)
/* the connection processor */
{
xs *req;
char *method;
const char *method;
int status = 0;
xs_str *body = NULL;
int b_size = 0;
@ -278,7 +278,7 @@ void httpd_connection(FILE *f)
xs *payload = NULL;
xs *etag = NULL;
int p_size = 0;
char *p;
const char *p;
int fcgi_id;
if (p_state->use_fcgi)
@ -411,7 +411,7 @@ void httpd_connection(FILE *f)
headers = xs_dict_append(headers, "etag", etag);
/* if there are any additional headers, add them */
xs_dict *more_headers = xs_dict_get(srv_config, "http_headers");
const xs_dict *more_headers = xs_dict_get(srv_config, "http_headers");
if (xs_type(more_headers) == XSTYPE_DICT) {
char *k, *v;
int c = 0;

2
main.c
View file

@ -315,7 +315,7 @@ int main(int argc, char *argv[])
xs *msg = msg_follow(&snac, url);
if (msg != NULL) {
char *actor = xs_dict_get(msg, "object");
const char *actor = xs_dict_get(msg, "object");
following_add(&snac, actor, msg);

View file

@ -175,7 +175,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path,
return 0;
int status = 404;
xs_dict *msg = xs_dict_get(req, "q_vars");
const xs_dict *msg = xs_dict_get(req, "q_vars");
xs *cmd = xs_replace_n(q_path, "/oauth", "", 1);
srv_debug(1, xs_fmt("oauth_get_handler %s", q_path));
@ -239,7 +239,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
int status = 404;
char *i_ctype = xs_dict_get(req, "content-type");
const char *i_ctype = xs_dict_get(req, "content-type");
xs *args = NULL;
if (i_ctype && xs_startswith(i_ctype, "application/json")) {
@ -568,10 +568,10 @@ xs_dict *mastoapi_account(const xs_dict *actor)
acct = xs_dict_append(acct, "uri", id);
xs *avatar = NULL;
xs_dict *av = xs_dict_get(actor, "icon");
const xs_dict *av = xs_dict_get(actor, "icon");
if (xs_type(av) == XSTYPE_DICT) {
char *url = xs_dict_get(av, "url");
const char *url = xs_dict_get(av, "url");
if (url != NULL)
avatar = xs_dup(url);
@ -584,7 +584,7 @@ xs_dict *mastoapi_account(const xs_dict *actor)
acct = xs_dict_append(acct, "avatar_static", avatar);
xs *header = NULL;
xs_dict *hd = xs_dict_get(actor, "image");
const xs_dict *hd = xs_dict_get(actor, "image");
if (xs_type(hd) == XSTYPE_DICT)
header = xs_dup(xs_dict_get(hd, "url"));
@ -596,12 +596,13 @@ xs_dict *mastoapi_account(const xs_dict *actor)
acct = xs_dict_append(acct, "header_static", header);
/* emojis */
xs_list *p;
const xs_list *p;
if (!xs_is_null(p = xs_dict_get(actor, "tag"))) {
xs *eml = xs_list_new();
xs_dict *v;
int c = 0;
while (xs_list_iter(&p, &v)) {
while (xs_list_next(p, &v, &c)) {
const char *type = xs_dict_get(v, "type");
if (!xs_is_null(type) && strcmp(type, "Emoji") == 0) {
@ -640,7 +641,7 @@ xs_dict *mastoapi_account(const xs_dict *actor)
/* dict of validated links */
xs_dict *val_links = NULL;
xs_dict *metadata = xs_stock(XSTYPE_DICT);
const xs_dict *metadata = xs_stock(XSTYPE_DICT);
snac user = {0};
if (xs_startswith(id, srv_baseurl)) {
@ -654,19 +655,20 @@ xs_dict *mastoapi_account(const xs_dict *actor)
if (xs_is_null(val_links))
val_links = xs_stock(XSTYPE_DICT);
while (xs_list_iter(&p, &v)) {
char *type = xs_dict_get(v, "type");
char *name = xs_dict_get(v, "name");
char *value = xs_dict_get(v, "value");
int c = 0;
while (xs_list_next(p, &v, &c)) {
const char *type = xs_dict_get(v, "type");
const char *name = xs_dict_get(v, "name");
const char *value = xs_dict_get(v, "value");
if (!xs_is_null(type) && !xs_is_null(name) &&
!xs_is_null(value) && strcmp(type, "PropertyValue") == 0) {
xs *val_date = NULL;
char *url = xs_dict_get(metadata, name);
const char *url = xs_dict_get(metadata, name);
if (!xs_is_null(url) && xs_startswith(url, "https:/" "/")) {
xs_number *verified_time = xs_dict_get(val_links, url);
const xs_number *verified_time = xs_dict_get(val_links, url);
if (xs_type(verified_time) == XSTYPE_NUMBER) {
time_t t = xs_number_get(verified_time);
@ -695,7 +697,7 @@ xs_dict *mastoapi_account(const xs_dict *actor)
}
xs_str *mastoapi_date(char *date)
xs_str *mastoapi_date(const char *date)
/* converts an ISO 8601 date to whatever format Mastodon uses */
{
xs_str *s = xs_crop_i(xs_dup(date), 0, 19);
@ -710,13 +712,13 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg)
{
xs_dict *poll = xs_dict_new();
xs *mid = mastoapi_id(msg);
xs_list *opts = NULL;
const xs_list *opts = NULL;
xs_val *v;
int num_votes = 0;
xs *options = xs_list_new();
poll = xs_dict_append(poll, "id", mid);
char *date = xs_dict_get(msg, "endTime");
const char *date = xs_dict_get(msg, "endTime");
if (date == NULL)
date = xs_dict_get(msg, "closed");
if (date == NULL)
@ -741,7 +743,8 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg)
poll = xs_dict_append(poll, "multiple", xs_stock(XSTYPE_TRUE));
}
while (xs_list_iter(&opts, &v)) {
int c = 0;
while (xs_list_next(opts, &v, &c)) {
const char *title = xs_dict_get(v, "name");
const char *replies = xs_dict_get(v, "replies");
@ -794,7 +797,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
xs *idx = NULL;
xs *ixc = NULL;
char *tmp;
const char *tmp;
xs *mid = mastoapi_id(msg);
xs_dict *st = xs_dict_new();
@ -851,9 +854,9 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
xs *matt = xs_list_new();
while (xs_list_iter(&p, &v)) {
char *type = xs_dict_get(v, "type");
char *href = xs_dict_get(v, "href");
char *name = xs_dict_get(v, "name");
const char *type = xs_dict_get(v, "type");
const char *href = xs_dict_get(v, "href");
const char *name = xs_dict_get(v, "name");
if (xs_match(type, "image/*|video/*|Image|Video")) { /* */
xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt));
@ -879,7 +882,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
xs *ml = xs_list_new();
xs *htl = xs_list_new();
xs *eml = xs_list_new();
xs_list *tag = xs_dict_get(msg, "tag");
const xs_list *tag = xs_dict_get(msg, "tag");
int n = 0;
xs *tag_list = NULL;
@ -897,7 +900,8 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
tag = tag_list;
xs_dict *v;
while (xs_list_iter(&tag, &v)) {
int c = 0;
while (xs_list_next(tag, &v, &c)) {
const char *type = xs_dict_get(v, "type");
if (xs_is_null(type))
@ -1006,7 +1010,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
xs *irt_mid = mastoapi_id(irto);
st = xs_dict_set(st, "in_reply_to_id", irt_mid);
char *at = NULL;
const char *at = NULL;
if (!xs_is_null(at = get_atto(irto))) {
xs *at_md5 = xs_md5_hex(at, strlen(at));
st = xs_dict_set(st, "in_reply_to_account_id", at_md5);
@ -1118,7 +1122,7 @@ int process_auth_token(snac *snac, const xs_dict *req)
/* processes an authorization token, if there is one */
{
int logged_in = 0;
char *v;
const char *v;
/* if there is an authorization field, try to validate it */
if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) {
@ -1156,7 +1160,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
return 0;
int status = 404;
xs_dict *args = xs_dict_get(req, "q_vars");
const xs_dict *args = xs_dict_get(req, "q_vars");
xs *cmd = xs_replace_n(q_path, "/api", "", 1);
snac snac1 = {0};
@ -1182,7 +1186,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
acct = xs_dict_append(acct, "source", src);
xs *avatar = NULL;
char *av = xs_dict_get(snac1.config, "avatar");
const char *av = xs_dict_get(snac1.config, "avatar");
if (xs_is_null(av) || *av == '\0')
avatar = xs_fmt("%s/susie.png", srv_baseurl);
@ -1193,7 +1197,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
acct = xs_dict_append(acct, "avatar_static", avatar);
xs *header = NULL;
char *hd = xs_dict_get(snac1.config, "header");
const char *hd = xs_dict_get(snac1.config, "header");
if (!xs_is_null(hd))
header = xs_dup(hd);
@ -1203,7 +1207,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
acct = xs_dict_append(acct, "header", header);
acct = xs_dict_append(acct, "header_static", header);
xs_dict *metadata = xs_dict_get(snac1.config, "metadata");
const xs_dict *metadata = xs_dict_get(snac1.config, "metadata");
if (xs_type(metadata) == XSTYPE_DICT) {
xs *fields = xs_list_new();
xs_str *k;
@ -1217,7 +1221,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
while (xs_dict_next(metadata, &k, &v, &c)) {
xs *val_date = NULL;
xs_number *verified_time = xs_dict_get(val_links, v);
const xs_number *verified_time = xs_dict_get(val_links, v);
if (xs_type(verified_time) == XSTYPE_NUMBER) {
time_t t = xs_number_get(verified_time);
@ -1283,13 +1287,13 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
else
if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/
/* lookup an account */
char *acct = xs_dict_get(args, "acct");
const char *acct = xs_dict_get(args, "acct");
if (!xs_is_null(acct)) {
xs *s = xs_strip_chars_i(xs_dup(acct), "@");
xs *l = xs_split_n(s, "@", 1);
char *uid = xs_list_get(l, 0);
char *host = xs_list_get(l, 1);
const char *uid = xs_list_get(l, 0);
const char *host = xs_list_get(l, 1);
if (uid && (!host || strcmp(host, xs_dict_get(srv_config, "host")) == 0)) {
snac user;
@ -1624,7 +1628,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
/* get the tag */
xs *l = xs_split(cmd, "/");
char *tag = xs_list_get(l, -1);
const char *tag = xs_list_get(l, -1);
xs *timeline = tag_search(tag, 0, limit);
xs *out = xs_list_new();
@ -1664,7 +1668,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
/* get the list id */
if (logged_in) {
xs *l = xs_split(cmd, "/");
char *list = xs_list_get(l, -1);
const char *list = xs_list_get(l, -1);
xs *timeline = list_timeline(&snac1, list, 0, 2048);
xs *out = xs_list_new();
@ -1744,7 +1748,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
xs *out = xs_list_new();
xs_list *p = l;
xs_dict *v;
xs_list *excl = xs_dict_get(args, "exclude_types[]");
const xs_list *excl = xs_dict_get(args, "exclude_types[]");
while (xs_list_iter(&p, &v)) {
xs *noti = notify_get(&snac1, v);
@ -1876,7 +1880,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
if (xs_startswith(cmd, "/v1/lists/")) { /** list information **/
if (logged_in) {
xs *l = xs_split(cmd, "/");
char *p = xs_list_get(l, -1);
const char *p = xs_list_get(l, -1);
if (p) {
if (strcmp(p, "accounts") == 0) {
@ -1910,7 +1914,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
xs_list *v;
while (xs_list_next(lol, &v, &c)) {
char *id = xs_list_get(v, 0);
const char *id = xs_list_get(v, 0);
if (id && strcmp(id, p) == 0) {
xs *d = xs_dict_new();
@ -2314,7 +2318,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
int status = 404;
xs *args = NULL;
char *i_ctype = xs_dict_get(req, "content-type");
const char *i_ctype = xs_dict_get(req, "content-type");
if (i_ctype && xs_startswith(i_ctype, "application/json")) {
if (!xs_is_null(payload))
@ -2487,7 +2491,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
mid = MID_TO_MD5(mid);
if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) {
char *id = xs_dict_get(msg, "id");
const char *id = xs_dict_get(msg, "id");
if (op == NULL) {
/* no operation (?) */
@ -2593,7 +2597,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
if (strcmp(cmd, "/v1/push/subscription") == 0) { /** **/
/* I don't know what I'm doing */
if (logged_in) {
char *v;
const char *v;
xs *wpush = xs_dict_new();
@ -2765,7 +2769,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
const char *id = xs_dict_get(msg, "id");
const char *atto = get_atto(msg);
xs_list *opts = xs_dict_get(msg, "oneOf");
const xs_list *opts = xs_dict_get(msg, "oneOf");
if (opts == NULL)
opts = xs_dict_get(msg, "anyOf");
@ -2773,7 +2777,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
}
else
if (strcmp(op, "votes") == 0) {
xs_list *choices = xs_dict_get(args, "choices[]");
const xs_list *choices = xs_dict_get(args, "choices[]");
if (xs_is_null(choices))
choices = xs_dict_get(args, "choices");
@ -2781,7 +2785,8 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
if (xs_type(choices) == XSTYPE_LIST) {
xs_str *v;
while (xs_list_iter(&choices, &v)) {
int c = 0;
while (xs_list_next(choices, &v, &c)) {
int io = atoi(v);
const xs_dict *o = xs_list_get(opts, io);
@ -2843,12 +2848,12 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
if (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/
if (logged_in) {
xs *l = xs_split(cmd, "/");
char *op = xs_list_get(l, -1);
char *id = xs_list_get(l, -2);
const char *op = xs_list_get(l, -1);
const char *id = xs_list_get(l, -2);
if (op && id && xs_is_hex(id)) {
if (strcmp(op, "accounts") == 0) {
xs_list *accts = xs_dict_get(args, "account_ids[]");
const xs_list *accts = xs_dict_get(args, "account_ids[]");
int c = 0;
char *v;
@ -2888,7 +2893,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
int status = 404;
xs *args = NULL;
char *i_ctype = xs_dict_get(req, "content-type");
const char *i_ctype = xs_dict_get(req, "content-type");
if (i_ctype && xs_startswith(i_ctype, "application/json")) {
if (!xs_is_null(payload))
@ -2921,13 +2926,13 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
if (xs_startswith(cmd, "/v1/lists/")) {
if (logged_in) {
xs *l = xs_split(cmd, "/");
char *p = xs_list_get(l, -1);
const char *p = xs_list_get(l, -1);
if (p) {
if (strcmp(p, "accounts") == 0) {
/* delete account from list */
p = xs_list_get(l, -2);
xs_list *accts = xs_dict_get(args, "account_ids[]");
const xs_list *accts = xs_dict_get(args, "account_ids[]");
int c = 0;
char *v;
@ -2971,7 +2976,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
int status = 404;
xs *args = NULL;
char *i_ctype = xs_dict_get(req, "content-type");
const char *i_ctype = xs_dict_get(req, "content-type");
if (i_ctype && xs_startswith(i_ctype, "application/json")) {
if (!xs_is_null(payload))

45
snac.h
View file

@ -69,7 +69,7 @@ void snac_log(snac *user, xs_str *str);
#define snac_debug(user, level, str) do { if (dbglevel >= (level)) \
{ snac_log((user), (str)); } } while (0)
int srv_open(char *basedir, int auto_upgrade);
int srv_open(const char *basedir, int auto_upgrade);
void srv_free(void);
int user_open(snac *snac, const char *uid);
@ -88,7 +88,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req,
const char *body, int b_size);
void srv_archive_error(const char *prefix, const xs_str *err,
const xs_dict *req, const xs_val *data);
void srv_archive_qitem(char *prefix, xs_dict *q_item);
void srv_archive_qitem(const char *prefix, xs_dict *q_item);
double mtime_nl(const char *fn, int *n_link);
#define mtime(fn) mtime_nl(fn, NULL)
@ -139,13 +139,13 @@ double timeline_mtime(snac *snac);
int timeline_touch(snac *snac);
int timeline_here(snac *snac, const char *md5);
int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg);
int timeline_del(snac *snac, char *id);
int timeline_del(snac *snac, const char *id);
xs_list *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show);
xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show);
int timeline_add(snac *snac, const char *id, const xs_dict *o_msg);
int timeline_admire(snac *snac, const char *id, const char *admirer, int like);
xs_list *timeline_top_level(snac *snac, xs_list *list);
xs_list *timeline_top_level(snac *snac, const xs_list *list);
xs_list *local_list(snac *snac, int max);
xs_list *timeline_instance_list(int skip, int show);
@ -174,14 +174,14 @@ void hide(snac *snac, const char *id);
int is_hidden(snac *snac, const char *id);
void tag_index(const char *id, const xs_dict *obj);
xs_list *tag_search(char *tag, int skip, int show);
xs_list *tag_search(const char *tag, int skip, int show);
xs_val *list_maint(snac *user, const char *list, int op);
xs_list *list_timeline(snac *user, const char *list, int skip, int show);
xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op);
void list_distribute(snac *user, const char *who, const xs_dict *post);
int actor_add(const char *actor, xs_dict *msg);
int actor_add(const char *actor, const xs_dict *msg);
int actor_get(const char *actor, xs_dict **data);
int actor_get_refresh(snac *user, const char *actor, xs_dict **data);
@ -223,10 +223,13 @@ xs_list *content_search(snac *user, const char *regex,
void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retries);
void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries);
void enqueue_output_raw(const char *keyid, const char *seckey,
xs_dict *msg, xs_str *inbox, int retries, int p_status);
void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_status);
void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries);
void enqueue_email(xs_str *msg, int retries);
const xs_dict *msg, const xs_str *inbox,
int retries, int p_status);
void enqueue_output(snac *snac, const xs_dict *msg,
const xs_str *inbox, int retries, int p_status);
void enqueue_output_by_actor(snac *snac, const xs_dict *msg,
const xs_str *actor, int retries);
void enqueue_email(const xs_str *msg, int retries);
void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id);
void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token);
void enqueue_message(snac *snac, const xs_dict *msg);
@ -234,7 +237,6 @@ void enqueue_close_question(snac *user, const char *id, int end_secs);
void enqueue_object_request(snac *user, const char *id, int forward_secs);
void enqueue_verify_links(snac *user);
void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs);
void enqueue_request_replies(snac *user, const char *id);
int was_question_voted(snac *user, const char *id);
xs_list *user_queue(snac *snac);
@ -247,16 +249,16 @@ void purge_all(void);
xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
const char *method, const char *url,
xs_dict *headers,
const xs_dict *headers,
const char *body, int b_size,
int *status, xs_str **payload, int *p_size,
int timeout);
xs_dict *http_signed_request(snac *snac, const char *method, const char *url,
xs_dict *headers,
const xs_dict *headers,
const char *body, int b_size,
int *status, xs_str **payload, int *p_size,
int timeout);
int check_signature(xs_dict *req, xs_str **err);
int check_signature(const xs_dict *req, xs_str **err);
srv_state *srv_state_op(xs_str **fname, int op);
void httpd(void);
@ -270,21 +272,21 @@ const char *default_avatar_base64(void);
xs_str *process_tags(snac *snac, const char *content, xs_list **tag);
char *get_atto(const xs_dict *msg);
const char *get_atto(const xs_dict *msg);
xs_list *get_attachments(const xs_dict *msg);
xs_dict *msg_admiration(snac *snac, char *object, char *type);
xs_dict *msg_repulsion(snac *user, char *id, char *type);
xs_dict *msg_admiration(snac *snac, const char *object, const char *type);
xs_dict *msg_repulsion(snac *user, const char *id, const char *type);
xs_dict *msg_create(snac *snac, const xs_dict *object);
xs_dict *msg_follow(snac *snac, const char *actor);
xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
xs_str *in_reply_to, xs_list *attach, int priv);
const xs_str *in_reply_to, const xs_list *attach, int priv);
xs_dict *msg_undo(snac *snac, char *object);
xs_dict *msg_delete(snac *snac, char *id);
xs_dict *msg_undo(snac *snac, const xs_val *object);
xs_dict *msg_delete(snac *snac, const char *id);
xs_dict *msg_actor(snac *snac);
xs_dict *msg_update(snac *snac, xs_dict *object);
xs_dict *msg_update(snac *snac, const xs_dict *object);
xs_dict *msg_ping(snac *user, const char *rcpt);
xs_dict *msg_pong(snac *user, const char *rcpt, const char *object);
xs_dict *msg_question(snac *user, const char *content, xs_list *attach,
@ -292,7 +294,6 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach,
int activitypub_request(snac *snac, const char *url, xs_dict **data);
int actor_request(snac *user, const char *actor, xs_dict **data);
void timeline_request_replies(snac *user, const char *id);
int send_to_inbox_raw(const char *keyid, const char *seckey,
const xs_str *inbox, const xs_dict *msg,
xs_val **payload, int *p_size, int timeout);

View file

@ -18,7 +18,7 @@ int snac_upgrade(xs_str **error)
double f = 0.0;
for (;;) {
char *layout = xs_dict_get(srv_config, "layout");
const char *layout = xs_dict_get(srv_config, "layout");
double nf;
f = nf = xs_number_get(layout);
@ -56,8 +56,8 @@ int snac_upgrade(xs_str **error)
g = list;
while (xs_list_iter(&g, &fn)) {
xs *l = xs_split(fn, "/");
char *b = xs_list_get(l, -1);
xs *l = xs_split(fn, "/");
const char *b = xs_list_get(l, -1);
xs *dir = xs_fmt("%s/object/%c%c", srv_basedir, b[0], b[1]);
xs *nfn = xs_fmt("%s/%s", dir, b);
@ -152,12 +152,12 @@ int snac_upgrade(xs_str **error)
xs *o = xs_json_loads(s);
fclose(f);
char *type = xs_dict_get(o, "type");
const char *type = xs_dict_get(o, "type");
if (!xs_is_null(type) && strcmp(type, "Follow") == 0) {
unlink(v);
char *actor = xs_dict_get(o, "actor");
const char *actor = xs_dict_get(o, "actor");
if (!xs_is_null(actor))
follower_add(&snac, actor);
@ -198,22 +198,29 @@ int snac_upgrade(xs_str **error)
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
o = xs_dict_del(o, "_snac");
char *id = xs_dict_get(o, "id");
const char *id = xs_dict_get(o, "id");
/* store object */
object_add_ow(id, o);
/* if it's from us, add to public */
if (xs_startswith(id, snac.actor)) {
char *p, *v;
const xs_list *p;
char *v;
int c;
object_user_cache_add(&snac, id, "public");
p = xs_dict_get(meta, "announced_by");
while (xs_list_iter(&p, &v))
c = 0;
while (xs_list_next(p, &v, &c))
object_admire(id, v, 0);
p = xs_dict_get(meta, "liked_by");
while (xs_list_iter(&p, &v))
c = 0;
while (xs_list_next(p, &v, &c))
object_admire(id, v, 1);
}
@ -257,21 +264,28 @@ int snac_upgrade(xs_str **error)
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
o = xs_dict_del(o, "_snac");
char *id = xs_dict_get(o, "id");
const char *id = xs_dict_get(o, "id");
/* store object */
object_add_ow(id, o);
{
char *p, *v;
const xs_list *p;
char *v;
int c = 0;
object_user_cache_add(&snac, id, "private");
p = xs_dict_get(meta, "announced_by");
while (xs_list_iter(&p, &v))
c = 0;
while (xs_list_next(p, &v, &c))
object_admire(id, v, 0);
p = xs_dict_get(meta, "liked_by");
while (xs_list_iter(&p, &v))
c = 0;
while (xs_list_next(p, &v, &c))
object_admire(id, v, 1);
}

View file

@ -418,7 +418,7 @@ int deluser(snac *user)
void verify_links(snac *user)
/* verifies a user's links */
{
xs_dict *p = xs_dict_get(user->config, "metadata");
const xs_dict *p = xs_dict_get(user->config, "metadata");
char *k, *v;
int changed = 0;

View file

@ -16,7 +16,7 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us
int p_size = 0;
xs *headers = xs_dict_new();
xs *l = NULL;
xs_str *host = NULL;
const char *host = NULL;
xs *resource = NULL;
if (xs_startswith(qs, "https:/") || xs_startswith(qs, "http:/")) {
@ -87,19 +87,20 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us
if (obj) {
if (user != NULL) {
char *subject = xs_dict_get(obj, "subject");
const char *subject = xs_dict_get(obj, "subject");
if (subject)
*user = xs_replace_n(subject, "acct:", "", 1);
}
if (actor != NULL) {
char *list = xs_dict_get(obj, "links");
const xs_list *list = xs_dict_get(obj, "links");
int c = 0;
char *v;
while (xs_list_iter(&list, &v)) {
while (xs_list_next(list, &v, &c)) {
if (xs_type(v) == XSTYPE_DICT) {
char *type = xs_dict_get(v, "type");
const char *type = xs_dict_get(v, "type");
if (type && (strcmp(type, "application/activity+json") == 0 ||
strcmp(type, "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") == 0)) {
@ -133,8 +134,8 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
if (strcmp(q_path, "/.well-known/webfinger") != 0)
return 0;
char *q_vars = xs_dict_get(req, "q_vars");
char *resource = xs_dict_get(q_vars, "resource");
const char *q_vars = xs_dict_get(req, "q_vars");
const char *resource = xs_dict_get(q_vars, "resource");
if (resource == NULL)
return 400;
@ -145,7 +146,7 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
if (xs_startswith(resource, "https:/") || xs_startswith(resource, "http:/")) {
/* actor search: find a user with this actor */
xs *l = xs_split(resource, "/");
char *uid = xs_list_get(l, -1);
const char *uid = xs_list_get(l, -1);
if (uid)
found = user_open(&snac, uid);
@ -163,8 +164,8 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
l = xs_split_n(an, "@", 1);
if (xs_list_len(l) == 2) {
char *uid = xs_list_get(l, 0);
char *host = xs_list_get(l, 1);
const char *uid = xs_list_get(l, 0);
const char *host = xs_list_get(l, 1);
if (strcmp(host, xs_dict_get(srv_config, "host")) == 0)
found = user_open(&snac, uid);
@ -194,7 +195,7 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
links = xs_list_append(links, prof);
char *avatar = xs_dict_get(snac.config, "avatar");
const char *avatar = xs_dict_get(snac.config, "avatar");
if (!xs_is_null(avatar) && *avatar) {
xs *d = xs_dict_new();

110
xs.h
View file

@ -21,8 +21,8 @@ typedef enum {
XSTYPE_FALSE = 0x15, /* Boolean */
XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */
XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */
XSTYPE_DICT = 0x1c, /* Sequence of DITEMs up to EOM (with size) */
XSTYPE_DITEM = 0x1e, /* Element of a dict (STRING key + any type) */
XSTYPE_DICT = 0x1c, /* Sequence of KEYVALs up to EOM (with size) */
XSTYPE_KEYVAL = 0x1e, /* key + value (STRING key + any type) */
XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */
XSTYPE_DATA = 0x10 /* A block of anonymous data */
} xstype;
@ -32,6 +32,7 @@ typedef enum {
typedef char xs_val;
typedef char xs_str;
typedef char xs_list;
typedef char xs_keyval;
typedef char xs_dict;
typedef char xs_number;
typedef char xs_data;
@ -96,7 +97,7 @@ xs_list *_xs_list_append(xs_list *list, const xs_val *vals[]);
int xs_list_iter(xs_list **list, xs_val **value);
int xs_list_next(const xs_list *list, xs_val **value, int *ctxt);
int xs_list_len(const xs_list *list);
xs_val *xs_list_get(const xs_list *list, int num);
const xs_val *xs_list_get(const xs_list *list, int num);
xs_list *xs_list_del(xs_list *list, int num);
xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data);
xs_list *xs_list_set(xs_list *list, int num, const xs_val *data);
@ -109,14 +110,20 @@ xs_list *xs_split_n(const char *str, const char *sep, int times);
#define xs_split(str, sep) xs_split_n(str, sep, XS_ALL)
xs_list *xs_list_cat(xs_list *l1, const xs_list *l2);
int xs_keyval_size(const xs_str *key, const xs_val *value);
xs_str *xs_keyval_key(const xs_keyval *keyval);
xs_val *xs_keyval_value(const xs_keyval *keyval);
xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value);
xs_dict *xs_dict_new(void);
xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value);
xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value);
int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt);
xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def);
const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def);
#define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL)
xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key);
xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data);
xs_dict *xs_dict_gc(xs_dict *dict);
xs_val *xs_val_new(xstype t);
xs_number *xs_number_new(double f);
@ -244,7 +251,7 @@ xstype xs_type(const xs_val *data)
case XSTYPE_LIST:
case XSTYPE_LITEM:
case XSTYPE_DICT:
case XSTYPE_DITEM:
case XSTYPE_KEYVAL:
case XSTYPE_NUMBER:
case XSTYPE_EOM:
case XSTYPE_DATA:
@ -262,7 +269,7 @@ xstype xs_type(const xs_val *data)
void _xs_put_size(xs_val *ptr, int i)
/* must match _XS_TYPE_SIZE */
{
memcpy(ptr, &i, sizeof(i));
memcpy(ptr + 1, &i, sizeof(i));
}
@ -296,7 +303,7 @@ int xs_size(const xs_val *data)
break;
case XSTYPE_DITEM:
case XSTYPE_KEYVAL:
/* calculate the size of the key and the value */
p = data + 1;
p += xs_size(p);
@ -380,7 +387,7 @@ xs_val *xs_expand(xs_val *data, int offset, int size)
if (xs_type(data) == XSTYPE_LIST ||
xs_type(data) == XSTYPE_DICT ||
xs_type(data) == XSTYPE_DATA)
_xs_put_size(data + 1, sz);
_xs_put_size(data, sz);
return data;
}
@ -405,7 +412,7 @@ xs_val *xs_collapse(xs_val *data, int offset, int size)
if (xs_type(data) == XSTYPE_LIST ||
xs_type(data) == XSTYPE_DICT ||
xs_type(data) == XSTYPE_DATA)
_xs_put_size(data + 1, sz);
_xs_put_size(data, sz);
return xs_realloc(data, _xs_blk_size(sz));
}
@ -666,10 +673,10 @@ xs_list *xs_list_new(void)
{
int sz = 1 + _XS_TYPE_SIZE + 1;
xs_list *l = xs_realloc(NULL, sz);
memset(l, '\0', sz);
memset(l, XSTYPE_EOM, sz);
l[0] = XSTYPE_LIST;
_xs_put_size(&l[1], sz);
_xs_put_size(l, sz);
return l;
}
@ -802,7 +809,7 @@ int xs_list_len(const xs_list *list)
}
xs_val *xs_list_get(const xs_list *list, int num)
const xs_val *xs_list_get(const xs_list *list, int num)
/* returns the element #num */
{
XS_ASSERT_TYPE(list, XSTYPE_LIST);
@ -830,7 +837,7 @@ xs_list *xs_list_del(xs_list *list, int num)
{
XS_ASSERT_TYPE(list, XSTYPE_LIST);
xs_val *v;
const xs_val *v;
if ((v = xs_list_get(list, num)) != NULL)
list = xs_collapse(list, v - 1 - list, xs_size(v - 1));
@ -844,7 +851,7 @@ xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data)
{
XS_ASSERT_TYPE(list, XSTYPE_LIST);
xs_val *v;
const xs_val *v;
int offset;
if ((v = xs_list_get(list, num)) != NULL)
@ -999,6 +1006,40 @@ xs_list *xs_list_cat(xs_list *l1, const xs_list *l2)
}
/** keyvals **/
int xs_keyval_size(const xs_str *key, const xs_val *value)
/* returns the needed size for a keyval */
{
return 1 + xs_size(key) + xs_size(value);
}
xs_str *xs_keyval_key(const xs_keyval *keyval)
/* returns a pointer to the key of the keyval */
{
return (xs_str *)&keyval[1];
}
xs_val *xs_keyval_value(const xs_keyval *keyval)
/* returns a pointer to the value of the keyval */
{
return (xs_val *)&keyval[1 + xs_size(xs_keyval_key(keyval))];
}
xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value)
/* builds a keyval into mem (should have enough size) */
{
keyval[0] = XSTYPE_KEYVAL;
memcpy(xs_keyval_key(keyval), key, xs_size(key));
memcpy(xs_keyval_value(keyval), value, xs_size(value));
return keyval;
}
/** dicts **/
xs_dict *xs_dict_new(void)
@ -1006,34 +1047,27 @@ xs_dict *xs_dict_new(void)
{
int sz = 1 + _XS_TYPE_SIZE + 1;
xs_dict *d = xs_realloc(NULL, sz);
memset(d, '\0', sz);
memset(d, XSTYPE_EOM, sz);
d[0] = XSTYPE_DICT;
_xs_put_size(&d[1], sz);
_xs_put_size(d, sz);
return d;
}
xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key,
const xs_val *data, int dsz)
/* inserts a memory block into the dict */
xs_dict *_xs_dict_write_keyval(xs_dict *dict, int offset, const xs_str *key, const xs_val *value)
/* adds a new keyval to the dict */
{
XS_ASSERT_TYPE(dict, XSTYPE_DICT);
XS_ASSERT_TYPE(key, XSTYPE_STRING);
if (data == NULL) {
data = xs_stock(XSTYPE_NULL);
dsz = xs_size(data);
}
if (value == NULL)
value = xs_stock(XSTYPE_NULL);
int ksz = xs_size(key);
dict = xs_expand(dict, offset, xs_keyval_size(key, value));
dict = xs_expand(dict, offset, 1 + ksz + dsz);
dict[offset] = XSTYPE_DITEM;
memcpy(&dict[offset + 1], key, ksz);
memcpy(&dict[offset + 1 + ksz], data, dsz);
xs_keyval_make(&dict[offset], key, value);
return dict;
}
@ -1042,14 +1076,14 @@ xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key,
xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value)
/* appends a memory block to the dict */
{
return _xs_dict_write_ditem(dict, xs_size(dict) - 1, key, value, xs_size(value));
return _xs_dict_write_keyval(dict, xs_size(dict) - 1, key, value);
}
xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value)
/* prepends a memory block to the dict */
{
return _xs_dict_write_ditem(dict, 1 + _XS_TYPE_SIZE, key, value, xs_size(value));
return _xs_dict_write_keyval(dict, 1 + _XS_TYPE_SIZE, key, value);
}
@ -1070,7 +1104,7 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt)
p += *ctxt;
/* an element? */
if (xs_type(p) == XSTYPE_DITEM) {
if (xs_type(p) == XSTYPE_KEYVAL) {
p++;
*key = p;
@ -1091,7 +1125,7 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt)
}
xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def)
const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def)
/* returns the value directed by key, or the default value */
{
XS_ASSERT_TYPE(dict, XSTYPE_DICT);
@ -1150,6 +1184,14 @@ xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data)
}
xs_dict *xs_dict_gc(xs_dict *dict)
/* collects garbage (leaked values) inside a dict */
{
/* this kind of dicts does not get garbage */
return dict;
}
/** other values **/
xs_val *xs_val_new(xstype t)
@ -1235,7 +1277,7 @@ xs_data *xs_data_new(const void *data, int size)
v = xs_realloc(NULL, _xs_blk_size(total_size));
v[0] = XSTYPE_DATA;
_xs_put_size(v + 1, total_size);
_xs_put_size(v, total_size);
memcpy(&v[1 + _XS_TYPE_SIZE], data, size);

View file

@ -28,7 +28,7 @@ static size_t _header_callback(char *buffer, size_t size,
if (xs_str_in(l, ": ") != -1) {
xs *knv = xs_split_n(l, ": ", 1);
xs_tolower_i(xs_list_get(knv, 0));
xs_tolower_i((xs_str *)xs_list_get(knv, 0));
headers = xs_dict_set(headers, xs_list_get(knv, 0), xs_list_get(knv, 1));
}

View file

@ -6,26 +6,26 @@
typedef struct xs_html xs_html;
xs_str *xs_html_encode(char *str);
xs_str *xs_html_encode(const char *str);
xs_html *xs_html_attr(char *key, char *value);
xs_html *xs_html_text(char *content);
xs_html *xs_html_raw(char *content);
xs_html *xs_html_attr(const char *key, const char *value);
xs_html *xs_html_text(const char *content);
xs_html *xs_html_raw(const char *content);
xs_html *_xs_html_add(xs_html *tag, xs_html *var[]);
#define xs_html_add(tag, ...) _xs_html_add(tag, (xs_html *[]) { __VA_ARGS__, NULL })
xs_html *_xs_html_tag(char *tag, xs_html *var[]);
xs_html *_xs_html_tag(const char *tag, xs_html *var[]);
#define xs_html_tag(tag, ...) _xs_html_tag(tag, (xs_html *[]) { __VA_ARGS__, NULL })
xs_html *_xs_html_sctag(char *tag, xs_html *var[]);
xs_html *_xs_html_sctag(const char *tag, xs_html *var[]);
#define xs_html_sctag(tag, ...) _xs_html_sctag(tag, (xs_html *[]) { __VA_ARGS__, NULL })
xs_html *_xs_html_container(xs_html *var[]);
#define xs_html_container(...) _xs_html_container((xs_html *[]) { __VA_ARGS__, NULL })
void xs_html_render_f(xs_html *h, FILE *f);
xs_str *xs_html_render_s(xs_html *tag, char *prefix);
xs_str *xs_html_render_s(xs_html *tag, const char *prefix);
#define xs_html_render(tag) xs_html_render_s(tag, NULL)
@ -47,16 +47,16 @@ struct xs_html {
xs_html *next;
};
xs_str *xs_html_encode(char *str)
xs_str *xs_html_encode(const char *str)
/* encodes str using HTML entities */
{
xs_str *s = xs_str_new(NULL);
int o = 0;
char *e = str + strlen(str);
const char *e = str + strlen(str);
for (;;) {
char *ec = "<>\"'&"; /* characters to escape */
char *q = e;
const char *q = e;
int z;
/* find the nearest happening of a char */
@ -90,7 +90,7 @@ xs_str *xs_html_encode(char *str)
#define XS_HTML_NEW() memset(xs_realloc(NULL, sizeof(xs_html)), '\0', sizeof(xs_html))
xs_html *xs_html_attr(char *key, char *value)
xs_html *xs_html_attr(const char *key, const char *value)
/* creates an HTML block with an attribute */
{
xs_html *a = XS_HTML_NEW();
@ -108,7 +108,7 @@ xs_html *xs_html_attr(char *key, char *value)
}
xs_html *xs_html_text(char *content)
xs_html *xs_html_text(const char *content)
/* creates an HTML block of text, escaping it previously */
{
xs_html *a = XS_HTML_NEW();
@ -120,7 +120,7 @@ xs_html *xs_html_text(char *content)
}
xs_html *xs_html_raw(char *content)
xs_html *xs_html_raw(const char *content)
/* creates an HTML block without escaping (for pre-formatted HTML, comments, etc) */
{
xs_html *a = XS_HTML_NEW();
@ -152,7 +152,7 @@ xs_html *_xs_html_add(xs_html *tag, xs_html *var[])
}
static xs_html *_xs_html_tag_t(xs_html_type type, char *tag, xs_html *var[])
static xs_html *_xs_html_tag_t(xs_html_type type, const char *tag, xs_html *var[])
/* creates a tag with a variable list of attributes and subtags */
{
xs_html *a = XS_HTML_NEW();
@ -169,13 +169,13 @@ static xs_html *_xs_html_tag_t(xs_html_type type, char *tag, xs_html *var[])
}
xs_html *_xs_html_tag(char *tag, xs_html *var[])
xs_html *_xs_html_tag(const char *tag, xs_html *var[])
{
return _xs_html_tag_t(XS_HTML_TAG, tag, var);
}
xs_html *_xs_html_sctag(char *tag, xs_html *var[])
xs_html *_xs_html_sctag(const char *tag, xs_html *var[])
{
return _xs_html_tag_t(XS_HTML_SCTAG, tag, var);
}
@ -239,7 +239,7 @@ void xs_html_render_f(xs_html *h, FILE *f)
}
xs_str *xs_html_render_s(xs_html *tag, char *prefix)
xs_str *xs_html_render_s(xs_html *tag, const char *prefix)
/* renders to a string */
{
xs_str *s = NULL;

View file

@ -16,7 +16,7 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
xs *q_vars = NULL;
xs *p_vars = NULL;
xs *l1, *l2;
char *v;
const char *v;
xs_socket_timeout(fileno(f), 2.0, 0.0);
@ -60,7 +60,8 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
p = xs_split_n(l, ": ", 1);
if (xs_list_len(p) == 2)
req = xs_dict_append(req, xs_tolower_i(xs_list_get(p, 0)), xs_list_get(p, 1));
req = xs_dict_append(req, xs_tolower_i(
(xs_str *)xs_list_get(p, 0)), xs_list_get(p, 1));
}
xs_socket_timeout(fileno(f), 5.0, 0.0);

View file

@ -71,12 +71,12 @@ static void _xs_json_indent(int level, int indent, FILE *f)
}
static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
static void _xs_json_dump(const xs_val *data, int level, int indent, FILE *f)
/* dumps partial data as JSON */
{
int c = 0;
int ct = 0;
xs_val *v;
xs_val *data = (xs_val *)s_data;
switch (xs_type(data)) {
case XSTYPE_NULL:
@ -98,7 +98,7 @@ static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
case XSTYPE_LIST:
fputc('[', f);
while (xs_list_iter(&data, &v)) {
while (xs_list_next(data, &v, &ct)) {
if (c != 0)
fputc(',', f);
@ -117,9 +117,8 @@ static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
fputc('{', f);
xs_str *k;
int ct = 0;
while (xs_dict_next(s_data, &k, &v, &ct)) {
while (xs_dict_next(data, &k, &v, &ct)) {
if (c != 0)
fputc(',', f);

View file

@ -104,7 +104,7 @@ int xs_set_add(xs_set *s, const xs_val *data)
/* if it's new, add the data */
if (ret)
s->list = xs_list_append_m(s->list, data, xs_size(data));
s->list = xs_list_append(s->list, data);
return ret;
}

View file

@ -6,7 +6,7 @@
int _xs_utf8_enc(char buf[4], unsigned int cpoint);
int xs_is_utf8_cont_byte(char c);
unsigned int xs_utf8_dec(char **str);
unsigned int xs_utf8_dec(const char **str);
int xs_unicode_width(unsigned int cpoint);
int xs_is_surrogate(unsigned int cpoint);
unsigned int xs_surrogate_dec(unsigned int p1, unsigned int p2);
@ -66,10 +66,10 @@ int xs_is_utf8_cont_byte(char c)
}
unsigned int xs_utf8_dec(char **str)
unsigned int xs_utf8_dec(const char **str)
/* decodes an utf-8 char inside str and updates the pointer */
{
char *p = *str;
const char *p = *str;
unsigned int cpoint = 0;
unsigned char c = *p++;
int cb = 0;

View file

@ -119,8 +119,8 @@ xs_dict *xs_multipart_form_data(const char *payload, int p_size, const char *hea
while ((p = xs_memmem(payload + offset, p_size - offset, boundary, bsz)) != NULL) {
xs *s1 = NULL;
xs *l1 = NULL;
char *vn = NULL;
char *fn = NULL;
const char *vn = NULL;
const char *fn = NULL;
char *q;
int po, ps;

View file

@ -1 +1 @@
/* 6e75e8736f7f1b6ea6c6774d4bd922b3ad56b771 2024-05-15T11:42:19+02:00 */
/* 34850dcdec50b669a2c0bbe9f16f6d9c4b16eafd 2024-05-21T14:06:02+02:00 */