mirror of
https://codeberg.org/grunfink/snac2.git
synced 2024-11-24 14:05:05 +00:00
Added const everywhere.
This commit is contained in:
parent
b95fbe4e43
commit
4777fc86cb
20 changed files with 549 additions and 580 deletions
283
activitypub.c
283
activitypub.c
|
@ -67,7 +67,7 @@ int activitypub_request(snac *user, const char *url, xs_dict **data)
|
||||||
xs *response = NULL;
|
xs *response = NULL;
|
||||||
xs *payload = NULL;
|
xs *payload = NULL;
|
||||||
int p_size;
|
int p_size;
|
||||||
char *ctype;
|
const char *ctype;
|
||||||
|
|
||||||
*data = NULL;
|
*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) */
|
/* 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 the actor is a list of objects (like on Peertube videos), pick the Person */
|
||||||
if (xs_type(actor) == XSTYPE_LIST) {
|
if (xs_type(actor) == XSTYPE_LIST) {
|
||||||
xs_list *p = actor;
|
const xs_list *p = actor;
|
||||||
|
int c = 0;
|
||||||
xs_dict *v;
|
xs_dict *v;
|
||||||
actor = NULL;
|
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) {
|
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) {
|
if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Person") == 0) {
|
||||||
actor = xs_dict_get(v, "id");
|
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 */
|
/* unify the garbage fire that are the attachments */
|
||||||
{
|
{
|
||||||
xs_list *l = xs_list_new();
|
xs_list *l = xs_list_new();
|
||||||
xs_list *p;
|
const xs_list *p;
|
||||||
|
|
||||||
/* try first the attachments list */
|
/* try first the attachments list */
|
||||||
if (!xs_is_null(p = xs_dict_get(msg, "attachment"))) {
|
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) {
|
if (xs_type(attach) == XSTYPE_LIST) {
|
||||||
/* does the message have an image? */
|
/* 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 */
|
/* add it to the attachment list */
|
||||||
attach = xs_list_append(attach, v);
|
attach = xs_list_append(attach, d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now iterate the list */
|
/* now iterate the list */
|
||||||
p = attach;
|
int c = 0;
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_next(attach, &v, &c)) {
|
||||||
char *type = xs_dict_get(v, "mediaType");
|
const char *type = xs_dict_get(v, "mediaType");
|
||||||
if (xs_is_null(type))
|
if (xs_is_null(type))
|
||||||
type = xs_dict_get(v, "type");
|
type = xs_dict_get(v, "type");
|
||||||
|
|
||||||
if (xs_is_null(type))
|
if (xs_is_null(type))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char *href = xs_dict_get(v, "url");
|
const char *href = xs_dict_get(v, "url");
|
||||||
if (xs_is_null(href))
|
if (xs_is_null(href))
|
||||||
href = xs_dict_get(v, "href");
|
href = xs_dict_get(v, "href");
|
||||||
if (xs_is_null(href))
|
if (xs_is_null(href))
|
||||||
|
@ -233,7 +235,7 @@ xs_list *get_attachments(const xs_dict *msg)
|
||||||
type = mt;
|
type = mt;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *name = xs_dict_get(v, "name");
|
const char *name = xs_dict_get(v, "name");
|
||||||
if (xs_is_null(name))
|
if (xs_is_null(name))
|
||||||
name = xs_dict_get(msg, "name");
|
name = xs_dict_get(msg, "name");
|
||||||
if (xs_is_null(name))
|
if (xs_is_null(name))
|
||||||
|
@ -252,29 +254,31 @@ xs_list *get_attachments(const xs_dict *msg)
|
||||||
p = xs_dict_get(msg, "url");
|
p = xs_dict_get(msg, "url");
|
||||||
|
|
||||||
if (xs_type(p) == XSTYPE_LIST) {
|
if (xs_type(p) == XSTYPE_LIST) {
|
||||||
char *href = NULL;
|
const char *href = NULL;
|
||||||
char *type = NULL;
|
const char *type = NULL;
|
||||||
|
int c = 0;
|
||||||
xs_val *v;
|
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) {
|
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) {
|
if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "Link") == 0) {
|
||||||
mtype = xs_dict_get(v, "mediaType");
|
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 &&
|
if (xs_type(mtype) == XSTYPE_STRING &&
|
||||||
strcmp(mtype, "application/x-mpegURL") == 0 &&
|
strcmp(mtype, "application/x-mpegURL") == 0 &&
|
||||||
xs_type(tag) == XSTYPE_LIST) {
|
xs_type(tag) == XSTYPE_LIST) {
|
||||||
/* now iterate the tag list, looking for a video URL */
|
/* now iterate the tag list, looking for a video URL */
|
||||||
xs_dict *d;
|
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(d) == XSTYPE_DICT) {
|
||||||
if (xs_type(mtype = xs_dict_get(d, "mediaType")) == XSTYPE_STRING &&
|
if (xs_type(mtype = xs_dict_get(d, "mediaType")) == XSTYPE_STRING &&
|
||||||
xs_startswith(mtype, "video/")) {
|
xs_startswith(mtype, "video/")) {
|
||||||
char *h = xs_dict_get(d, "href");
|
const char *h = xs_dict_get(d, "href");
|
||||||
|
|
||||||
/* this is probably it */
|
/* this is probably it */
|
||||||
if (xs_type(h) == XSTYPE_STRING) {
|
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 */
|
/* ensures that an entry and its ancestors are in the timeline */
|
||||||
{
|
{
|
||||||
int status = 0;
|
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);
|
status = activitypub_request(snac, *id, &msg);
|
||||||
|
|
||||||
if (valid_status(status)) {
|
if (valid_status(status)) {
|
||||||
xs_dict *object = msg;
|
const xs_dict *object = msg;
|
||||||
const char *type = xs_dict_get(object, "type");
|
const char *type = xs_dict_get(object, "type");
|
||||||
|
|
||||||
/* get the id again from the object, as it may be different */
|
/* 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? */
|
/* 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 */
|
/* store */
|
||||||
timeline_add(snac, nid, object);
|
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;
|
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,
|
int send_to_inbox_raw(const char *keyid, const char *seckey,
|
||||||
const xs_str *inbox, const xs_dict *msg,
|
const xs_str *inbox, const xs_dict *msg,
|
||||||
xs_val **payload, int *p_size, int timeout)
|
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)
|
xs_val **payload, int *p_size, int timeout)
|
||||||
/* sends a message to an Inbox */
|
/* 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);
|
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 */
|
/* gets an actor's inbox */
|
||||||
{
|
{
|
||||||
xs *data = NULL;
|
xs *data = NULL;
|
||||||
char *v = NULL;
|
const char *v = NULL;
|
||||||
|
|
||||||
if (valid_status(actor_request(NULL, actor, &data))) {
|
if (valid_status(actor_request(NULL, actor, &data))) {
|
||||||
/* try first endpoints/sharedInbox */
|
/* 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)
|
xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public)
|
||||||
/* returns the list of recipients for a message */
|
/* returns the list of recipients for a message */
|
||||||
{
|
{
|
||||||
char *to = xs_dict_get(msg, "to");
|
const xs_val *to = xs_dict_get(msg, "to");
|
||||||
char *cc = xs_dict_get(msg, "cc");
|
const xs_val *cc = xs_dict_get(msg, "cc");
|
||||||
xs_set rcpts;
|
xs_set rcpts;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
xs_set_init(&rcpts);
|
xs_set_init(&rcpts);
|
||||||
|
|
||||||
char *lists[] = { to, cc, NULL };
|
const xs_list *lists[] = { to, cc, NULL };
|
||||||
for (n = 0; lists[n]; n++) {
|
for (n = 0; lists[n]; n++) {
|
||||||
char *l = lists[n];
|
xs_list *l = (xs_list *)lists[n];
|
||||||
char *v;
|
char *v;
|
||||||
xs *tl = NULL;
|
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 it's a Follow, it must be explicitly for us */
|
||||||
if (xs_match(type, "Follow")) {
|
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;
|
return !xs_is_null(object) && strcmp(snac->actor, object) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only accept Ping directed to us */
|
/* only accept Ping directed to us */
|
||||||
if (xs_match(type, "Ping")) {
|
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;
|
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))
|
if (pub_msg && following_check(snac, actor))
|
||||||
return 1;
|
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 *rcpts = recipient_list(snac, msg, 0);
|
||||||
xs_list *p = rcpts;
|
xs_list *p = rcpts;
|
||||||
xs_str *v;
|
xs_str *v;
|
||||||
|
@ -704,8 +637,9 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
|
||||||
xs *actor_obj = NULL;
|
xs *actor_obj = NULL;
|
||||||
|
|
||||||
if (valid_status(object_get(actor, &actor_obj))) {
|
if (valid_status(object_get(actor, &actor_obj))) {
|
||||||
if ((v = xs_dict_get(actor_obj, "followers")))
|
const xs_val *fw = xs_dict_get(actor_obj, "followers");
|
||||||
actor_followers = xs_dup(v);
|
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 */
|
/* 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))
|
if (pub_msg && !xs_is_null(atto) && following_check(snac, atto))
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
/* is this message a reply to another? */
|
/* 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)) {
|
if (!xs_is_null(irt)) {
|
||||||
xs *r_msg = NULL;
|
xs *r_msg = NULL;
|
||||||
|
|
||||||
|
@ -987,8 +921,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
|
||||||
|
|
||||||
/* telegram */
|
/* telegram */
|
||||||
|
|
||||||
char *bot = xs_dict_get(snac->config, "telegram_bot");
|
const char *bot = xs_dict_get(snac->config, "telegram_bot");
|
||||||
char *chat_id = xs_dict_get(snac->config, "telegram_chat_id");
|
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)
|
if (!xs_is_null(bot) && !xs_is_null(chat_id) && *bot && *chat_id)
|
||||||
enqueue_telegram(body, 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;
|
objid = actor;
|
||||||
|
|
||||||
/* ntfy */
|
/* ntfy */
|
||||||
char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
|
const char *ntfy_server = xs_dict_get(snac->config, "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_server) && *ntfy_server)
|
if (!xs_is_null(ntfy_server) && *ntfy_server)
|
||||||
enqueue_ntfy(body, ntfy_server, ntfy_token);
|
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 */
|
/* creates an empty OrderedCollection message */
|
||||||
{
|
{
|
||||||
xs_dict *msg = msg_base(snac, "OrderedCollection", id, NULL, NULL, NULL);
|
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) */
|
/* creates an Accept message (as a response to a Follow) */
|
||||||
{
|
{
|
||||||
xs_dict *msg = msg_base(snac, "Accept", "@dummy", snac->actor, NULL, object);
|
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 */
|
/* creates an Update message */
|
||||||
{
|
{
|
||||||
xs_dict *msg = msg_base(snac, "Update", "@object", snac->actor, "@now", object);
|
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) {
|
if (strcmp(type, "Note") == 0) {
|
||||||
msg = xs_dict_append(msg, "to", xs_dict_get(object, "to"));
|
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 */
|
/* creates a Like or Announce message */
|
||||||
{
|
{
|
||||||
xs *a_msg = NULL;
|
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 */
|
/* creates an Undo + admiration message */
|
||||||
{
|
{
|
||||||
xs *a_msg = NULL;
|
xs *a_msg = NULL;
|
||||||
|
@ -1210,7 +1144,7 @@ xs_dict *msg_actor(snac *snac)
|
||||||
xs *kid = NULL;
|
xs *kid = NULL;
|
||||||
xs *f_bio = NULL;
|
xs *f_bio = NULL;
|
||||||
xs_dict *msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL);
|
xs_dict *msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL);
|
||||||
char *p;
|
const char *p;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* change the @context (is this really necessary?) */
|
/* change the @context (is this really necessary?) */
|
||||||
|
@ -1268,7 +1202,7 @@ xs_dict *msg_actor(snac *snac)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add the metadata as attachments of PropertyValue */
|
/* 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) {
|
if (xs_type(metadata) == XSTYPE_DICT) {
|
||||||
xs *attach = xs_list_new();
|
xs *attach = xs_list_new();
|
||||||
xs_str *k;
|
xs_str *k;
|
||||||
|
@ -1314,7 +1248,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object)
|
||||||
/* creates a 'Create' message */
|
/* creates a 'Create' message */
|
||||||
{
|
{
|
||||||
xs_dict *msg = msg_base(snac, "Create", "@wrapper", snac->actor, NULL, object);
|
xs_dict *msg = msg_base(snac, "Create", "@wrapper", snac->actor, NULL, object);
|
||||||
xs_val *v;
|
const xs_val *v;
|
||||||
|
|
||||||
if ((v = get_atto(object)))
|
if ((v = get_atto(object)))
|
||||||
msg = xs_dict_append(msg, "attributedTo", v);
|
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 */
|
/* creates an 'Undo' message */
|
||||||
{
|
{
|
||||||
xs_dict *msg = msg_base(snac, "Undo", "@object", snac->actor, "@now", object);
|
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 */
|
/* creates a 'Delete' + 'Tombstone' for a local entry */
|
||||||
{
|
{
|
||||||
xs *tomb = xs_dict_new();
|
xs *tomb = xs_dict_new();
|
||||||
|
@ -1386,7 +1320,7 @@ xs_dict *msg_follow(snac *snac, const char *q)
|
||||||
|
|
||||||
if (valid_status(status)) {
|
if (valid_status(status)) {
|
||||||
/* check if the actor is an alias */
|
/* 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) {
|
if (r_actor && strcmp(actor, r_actor) != 0) {
|
||||||
snac_log(snac, xs_fmt("actor to follow is an alias %s -> %s", actor, r_actor));
|
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_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 */
|
/* creates a 'Note' message */
|
||||||
{
|
{
|
||||||
xs *ntid = tid(0);
|
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))) {
|
if (valid_status(object_get(in_reply_to, &p_msg))) {
|
||||||
/* add this author as recipient */
|
/* add this author as recipient */
|
||||||
char *a, *v;
|
const char *a, *v;
|
||||||
|
|
||||||
if ((a = get_atto(p_msg)) && xs_list_in(to, a) == -1)
|
if ((a = get_atto(p_msg)) && xs_list_in(to, a) == -1)
|
||||||
to = xs_list_append(to, a);
|
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;
|
xs *actor_o = NULL;
|
||||||
|
|
||||||
if (xs_list_len(l) > 3 && valid_status(object_get(a, &actor_o))) {
|
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) {
|
if (!xs_is_null(uname) && *uname) {
|
||||||
xs *handle = xs_fmt("@%s@%s", uname, xs_list_get(l, 2));
|
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 */
|
/* create the attachment list, if there are any */
|
||||||
if (!xs_is_null(attach)) {
|
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();
|
xs *d = xs_dict_new();
|
||||||
const char *url = xs_list_get(v, 0);
|
const char *url = xs_list_get(v, 0);
|
||||||
const char *alt = xs_list_get(v, 1);
|
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;
|
p = tag;
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_iter(&p, &v)) {
|
||||||
if (xs_type(v) == XSTYPE_DICT) {
|
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, "type")) && strcmp(t, "Mention") == 0) {
|
||||||
if (!xs_is_null(t = xs_dict_get(v, "href")))
|
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 *msg = NULL;
|
||||||
xs *rcnt = xs_dict_new();
|
xs *rcnt = xs_dict_new();
|
||||||
xs *lopts = xs_list_new();
|
xs *lopts = xs_list_new();
|
||||||
xs_list *opts;
|
const xs_list *opts;
|
||||||
xs_list *p;
|
xs_list *p;
|
||||||
xs_val *v;
|
xs_val *v;
|
||||||
|
|
||||||
|
@ -1657,8 +1592,8 @@ int update_question(snac *user, const char *id)
|
||||||
return -3;
|
return -3;
|
||||||
|
|
||||||
/* fill the initial count */
|
/* fill the initial count */
|
||||||
p = opts;
|
int c = 0;
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_next(opts, &v, &c)) {
|
||||||
const char *name = xs_dict_get(v, "name");
|
const char *name = xs_dict_get(v, "name");
|
||||||
if (name) {
|
if (name) {
|
||||||
lopts = xs_list_append(lopts, name);
|
lopts = xs_list_append(lopts, name);
|
||||||
|
@ -1764,13 +1699,13 @@ int update_question(snac *user, const char *id)
|
||||||
|
|
||||||
/** queues **/
|
/** 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 */
|
/* processes an ActivityPub message from the input queue */
|
||||||
/* return values: -1, fatal error; 0, transient error, retry;
|
/* return values: -1, fatal error; 0, transient error, retry;
|
||||||
1, processed and done; 2, propagate to users (only when no user is set) */
|
1, processed and done; 2, propagate to users (only when no user is set) */
|
||||||
{
|
{
|
||||||
char *actor = xs_dict_get(msg, "actor");
|
const char *actor = xs_dict_get(msg, "actor");
|
||||||
char *type = xs_dict_get(msg, "type");
|
const char *type = xs_dict_get(msg, "type");
|
||||||
xs *actor_o = NULL;
|
xs *actor_o = NULL;
|
||||||
int a_status;
|
int a_status;
|
||||||
int do_notify = 0;
|
int do_notify = 0;
|
||||||
|
@ -1790,7 +1725,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *object, *utype;
|
const char *object, *utype;
|
||||||
|
|
||||||
object = xs_dict_get(msg, "object");
|
object = xs_dict_get(msg, "object");
|
||||||
if (object != NULL && xs_type(object) == XSTYPE_DICT)
|
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 */
|
/* 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)
|
if (xs_type(obj_id) == XSTYPE_DICT)
|
||||||
obj_id = xs_dict_get(obj_id, "id");
|
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"));
|
int min_account_age = xs_number_get(xs_dict_get(srv_config, "min_account_age"));
|
||||||
|
|
||||||
if (min_account_age > 0) {
|
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)) {
|
if (!xs_is_null(actor_date)) {
|
||||||
time_t actor_t = xs_parse_iso_date(actor_date, 0);
|
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
|
else
|
||||||
if (strcmp(type, "Undo") == 0) { /** **/
|
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)
|
if (xs_type(object) != XSTYPE_DICT)
|
||||||
utype = "Follow";
|
utype = "Follow";
|
||||||
|
@ -1990,9 +1925,9 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xs_match(utype, "Note|Article")) { /** **/
|
if (xs_match(utype, "Note|Article")) { /** **/
|
||||||
char *id = xs_dict_get(object, "id");
|
const char *id = xs_dict_get(object, "id");
|
||||||
char *in_reply_to = xs_dict_get(object, "inReplyTo");
|
const char *in_reply_to = xs_dict_get(object, "inReplyTo");
|
||||||
char *atto = get_atto(object);
|
const char *atto = get_atto(object);
|
||||||
xs *wrk = NULL;
|
xs *wrk = NULL;
|
||||||
|
|
||||||
if (xs_is_null(id))
|
if (xs_is_null(id))
|
||||||
|
@ -2029,14 +1964,14 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (strcmp(utype, "Question") == 0) { /** **/
|
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))
|
if (timeline_add(snac, id, object))
|
||||||
snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id));
|
snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (strcmp(utype, "Video") == 0) { /** **/
|
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))
|
if (timeline_add(snac, id, object))
|
||||||
snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id));
|
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 */
|
/* invoke sendmail with email headers and body in msg */
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
@ -2244,14 +2179,14 @@ int send_email(char *msg)
|
||||||
void process_user_queue_item(snac *snac, xs_dict *q_item)
|
void process_user_queue_item(snac *snac, xs_dict *q_item)
|
||||||
/* processes an item from the user queue */
|
/* 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"));
|
int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
|
||||||
|
|
||||||
if ((type = xs_dict_get(q_item, "type")) == NULL)
|
if ((type = xs_dict_get(q_item, "type")) == NULL)
|
||||||
type = "output";
|
type = "output";
|
||||||
|
|
||||||
if (strcmp(type, "message") == 0) {
|
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 *rcpts = recipient_list(snac, msg, 1);
|
||||||
xs_set inboxes;
|
xs_set inboxes;
|
||||||
xs_list *p;
|
xs_list *p;
|
||||||
|
@ -2292,8 +2227,8 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
|
||||||
else
|
else
|
||||||
if (strcmp(type, "input") == 0) {
|
if (strcmp(type, "input") == 0) {
|
||||||
/* process the message */
|
/* process the message */
|
||||||
xs_dict *msg = xs_dict_get(q_item, "message");
|
const xs_dict *msg = xs_dict_get(q_item, "message");
|
||||||
xs_dict *req = xs_dict_get(q_item, "req");
|
const xs_dict *req = xs_dict_get(q_item, "req");
|
||||||
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
|
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
|
||||||
|
|
||||||
if (xs_is_null(msg))
|
if (xs_is_null(msg))
|
||||||
|
@ -2320,13 +2255,6 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
|
||||||
update_question(snac, id);
|
update_question(snac, id);
|
||||||
}
|
}
|
||||||
else
|
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) {
|
if (strcmp(type, "object_request") == 0) {
|
||||||
const char *id = xs_dict_get(q_item, "message");
|
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)
|
void process_queue_item(xs_dict *q_item)
|
||||||
/* processes an item from the global queue */
|
/* 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"));
|
int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
|
||||||
|
|
||||||
if (strcmp(type, "output") == 0) {
|
if (strcmp(type, "output") == 0) {
|
||||||
int status;
|
int status;
|
||||||
xs_str *inbox = xs_dict_get(q_item, "inbox");
|
const xs_str *inbox = xs_dict_get(q_item, "inbox");
|
||||||
xs_str *keyid = xs_dict_get(q_item, "keyid");
|
const xs_str *keyid = xs_dict_get(q_item, "keyid");
|
||||||
xs_str *seckey = xs_dict_get(q_item, "seckey");
|
const xs_str *seckey = xs_dict_get(q_item, "seckey");
|
||||||
xs_dict *msg = xs_dict_get(q_item, "message");
|
const xs_dict *msg = xs_dict_get(q_item, "message");
|
||||||
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
|
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
|
||||||
int p_status = xs_number_get(xs_dict_get(q_item, "p_status"));
|
int p_status = xs_number_get(xs_dict_get(q_item, "p_status"));
|
||||||
xs *payload = NULL;
|
xs *payload = NULL;
|
||||||
|
@ -2475,7 +2403,7 @@ void process_queue_item(xs_dict *q_item)
|
||||||
else
|
else
|
||||||
if (strcmp(type, "email") == 0) {
|
if (strcmp(type, "email") == 0) {
|
||||||
/* send this email */
|
/* 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"));
|
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
|
||||||
|
|
||||||
if (!send_email(msg))
|
if (!send_email(msg))
|
||||||
|
@ -2497,8 +2425,8 @@ void process_queue_item(xs_dict *q_item)
|
||||||
else
|
else
|
||||||
if (strcmp(type, "telegram") == 0) {
|
if (strcmp(type, "telegram") == 0) {
|
||||||
/* send this via telegram */
|
/* send this via telegram */
|
||||||
char *bot = xs_dict_get(q_item, "bot");
|
const char *bot = xs_dict_get(q_item, "bot");
|
||||||
char *msg = xs_dict_get(q_item, "message");
|
const char *msg = xs_dict_get(q_item, "message");
|
||||||
xs *chat_id = xs_dup(xs_dict_get(q_item, "chat_id"));
|
xs *chat_id = xs_dup(xs_dict_get(q_item, "chat_id"));
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
|
@ -2521,9 +2449,9 @@ void process_queue_item(xs_dict *q_item)
|
||||||
else
|
else
|
||||||
if (strcmp(type, "ntfy") == 0) {
|
if (strcmp(type, "ntfy") == 0) {
|
||||||
/* send this via ntfy */
|
/* send this via ntfy */
|
||||||
char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
|
const char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
|
||||||
char *msg = xs_dict_get(q_item, "message");
|
const char *msg = xs_dict_get(q_item, "message");
|
||||||
char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
|
const char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
xs *url = xs_fmt("%s", ntfy_server);
|
xs *url = xs_fmt("%s", ntfy_server);
|
||||||
|
@ -2552,8 +2480,8 @@ void process_queue_item(xs_dict *q_item)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (strcmp(type, "input") == 0) {
|
if (strcmp(type, "input") == 0) {
|
||||||
xs_dict *msg = xs_dict_get(q_item, "message");
|
const xs_dict *msg = xs_dict_get(q_item, "message");
|
||||||
xs_dict *req = xs_dict_get(q_item, "req");
|
const xs_dict *req = xs_dict_get(q_item, "req");
|
||||||
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
|
int retries = xs_number_get(xs_dict_get(q_item, "retries"));
|
||||||
|
|
||||||
/* do some instance-level checks */
|
/* do some instance-level checks */
|
||||||
|
@ -2572,7 +2500,7 @@ void process_queue_item(xs_dict *q_item)
|
||||||
else
|
else
|
||||||
if (r == 2) {
|
if (r == 2) {
|
||||||
/* redistribute the input message to all users */
|
/* 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);
|
xs *tmpfn = xs_fmt("%s/tmp/%s.json", srv_basedir, ntid);
|
||||||
FILE *f;
|
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)
|
char **body, int *b_size, char **ctype)
|
||||||
{
|
{
|
||||||
int status = 200;
|
int status = 200;
|
||||||
char *accept = xs_dict_get(req, "accept");
|
const char *accept = xs_dict_get(req, "accept");
|
||||||
snac snac;
|
snac snac;
|
||||||
xs *msg = NULL;
|
xs *msg = NULL;
|
||||||
|
|
||||||
|
@ -2659,7 +2587,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
xs *l = xs_split_n(q_path, "/", 2);
|
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);
|
uid = xs_list_get(l, 1);
|
||||||
if (!user_open(&snac, uid)) {
|
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);
|
msg = msg_actor(&snac);
|
||||||
*ctype = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
|
*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"));
|
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;
|
xs *i = NULL;
|
||||||
|
|
||||||
if (valid_status(object_get_by_md5(v, &i))) {
|
if (valid_status(object_get_by_md5(v, &i))) {
|
||||||
char *type = xs_dict_get(i, "type");
|
const char *type = xs_dict_get(i, "type");
|
||||||
char *id = xs_dict_get(i, "id");
|
const char *id = xs_dict_get(i, "id");
|
||||||
|
|
||||||
if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) {
|
if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) {
|
||||||
xs *c_msg = msg_create(&snac, i);
|
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;
|
(void)b_size;
|
||||||
|
|
||||||
int status = 202; /* accepted */
|
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;
|
snac snac;
|
||||||
char *v;
|
const char *v;
|
||||||
|
|
||||||
if (i_ctype == NULL) {
|
if (i_ctype == NULL) {
|
||||||
*body = xs_str_new("no content-type");
|
*body = xs_str_new("no content-type");
|
||||||
|
|
130
data.c
130
data.c
|
@ -29,7 +29,7 @@ pthread_mutex_t data_mutex = {0};
|
||||||
int snac_upgrade(xs_str **error);
|
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 */
|
/* opens a server */
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -58,10 +58,10 @@ int srv_open(char *basedir, int auto_upgrade)
|
||||||
if (srv_config == NULL)
|
if (srv_config == NULL)
|
||||||
error = xs_fmt("ERROR: cannot parse '%s'", cfg_file);
|
error = xs_fmt("ERROR: cannot parse '%s'", cfg_file);
|
||||||
else {
|
else {
|
||||||
char *host;
|
const char *host;
|
||||||
char *prefix;
|
const char *prefix;
|
||||||
char *dbglvl;
|
const char *dbglvl;
|
||||||
char *proto;
|
const char *proto;
|
||||||
|
|
||||||
host = xs_dict_get(srv_config, "host");
|
host = xs_dict_get(srv_config, "host");
|
||||||
prefix = xs_dict_get(srv_config, "prefix");
|
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);
|
fclose(f);
|
||||||
|
|
||||||
/* does this object has a parent? */
|
/* 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) {
|
if (!xs_is_null(in_reply_to) && *in_reply_to) {
|
||||||
/* update the children index of the parent */
|
/* 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 */
|
/* deletes a message from the timeline */
|
||||||
{
|
{
|
||||||
/* delete from the user's caches */
|
/* 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 */
|
/* returns the top level md5 entries from this index */
|
||||||
{
|
{
|
||||||
xs_set seen;
|
xs_set seen;
|
||||||
xs_list *p;
|
|
||||||
xs_str *v;
|
xs_str *v;
|
||||||
|
|
||||||
xs_set_init(&seen);
|
xs_set_init(&seen);
|
||||||
|
|
||||||
p = list;
|
int c = 0;
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_next(list, &v, &c)) {
|
||||||
char line[256] = "";
|
char line[256] = "";
|
||||||
|
|
||||||
strncpy(line, v, sizeof(line));
|
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,
|
/* object already exists; if it's of type Accept,
|
||||||
the actor is already being followed and confirmed,
|
the actor is already being followed and confirmed,
|
||||||
so do nothing */
|
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) {
|
if (!xs_is_null(type) && strcmp(type, "Accept") == 0) {
|
||||||
snac_debug(snac, 1, xs_fmt("following_add actor already confirmed %s", actor));
|
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 */
|
/* resolve to get the id */
|
||||||
if (valid_status(object_get_by_md5(v, &co))) {
|
if (valid_status(object_get_by_md5(v, &co))) {
|
||||||
if ((v = xs_dict_get(co, "id")) != NULL)
|
const char *id = xs_dict_get(co, "id");
|
||||||
hide(snac, v);
|
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 */
|
/* adds an actor */
|
||||||
{
|
{
|
||||||
return object_add_ow(actor, msg);
|
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)
|
void tag_index(const char *id, const xs_dict *obj)
|
||||||
/* update the tag indexes for this object */
|
/* 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) {
|
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);
|
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);
|
mkdirx(g_tag_dir);
|
||||||
|
|
||||||
xs_dict *v;
|
xs_dict *v;
|
||||||
while (xs_list_iter(&tags, &v)) {
|
int ct = 0;
|
||||||
char *type = xs_dict_get(v, "type");
|
while (xs_list_next(tags, &v, &ct)) {
|
||||||
char *name = xs_dict_get(v, "name");
|
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) {
|
if (!xs_is_null(type) && !xs_is_null(name) && strcmp(type, "Hashtag") == 0) {
|
||||||
while (*name == '#' || *name == '@')
|
while (*name == '#' || *name == '@')
|
||||||
|
@ -1706,7 +1707,7 @@ void tag_index(const char *id, const xs_dict *obj)
|
||||||
if (*name == '\0')
|
if (*name == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
name = xs_tolower_i(name);
|
name = xs_tolower_i((xs_str *)name);
|
||||||
|
|
||||||
xs *md5_tag = xs_md5_hex(name, strlen(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]);
|
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 */
|
/* returns the list of posts tagged with tag */
|
||||||
{
|
{
|
||||||
if (*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)
|
void list_distribute(snac *user, const char *who, const xs_dict *post)
|
||||||
/* distributes the post to all appropriate lists */
|
/* 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 who is not set, use the attributedTo in the message */
|
||||||
if (xs_is_null(who))
|
if (xs_is_null(who))
|
||||||
|
@ -2164,7 +2165,7 @@ void inbox_add(const char *inbox)
|
||||||
void inbox_add_by_actor(const xs_dict *actor)
|
void inbox_add_by_actor(const xs_dict *actor)
|
||||||
/* collects an actor's shared inbox, if it has one */
|
/* 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")) &&
|
if (!xs_is_null(v = xs_dict_get(actor, "endpoints")) &&
|
||||||
!xs_is_null(v = xs_dict_get(v, "sharedInbox"))) {
|
!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 *s = xs_replace(instance, "http:/" "/", "");
|
||||||
xs *s1 = xs_replace(s, "https:/" "/", "");
|
xs *s1 = xs_replace(s, "https:/" "/", "");
|
||||||
xs *l = xs_split(s1, "/");
|
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));
|
xs *md5 = xs_md5_hex(p, strlen(p));
|
||||||
|
|
||||||
return xs_fmt("%s/block/%s", srv_basedir, md5);
|
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);
|
xs *fn = xs_fmt("%s/%s", srv_basedir, file);
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int r = 0;
|
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 (xs_type(v) == XSTYPE_STRING && *v) {
|
||||||
if ((f = fopen(fn, "r")) != NULL) {
|
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))
|
if (id == NULL || is_hidden(user, id))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char *content = xs_dict_get(post, "content");
|
const char *content = xs_dict_get(post, "content");
|
||||||
|
|
||||||
if (xs_is_null(content))
|
if (xs_is_null(content))
|
||||||
continue;
|
continue;
|
||||||
|
@ -2639,7 +2640,7 @@ void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retri
|
||||||
/* enqueues an input message */
|
/* enqueues an input message */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("input", msg, retries);
|
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);
|
xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid);
|
||||||
|
|
||||||
qmsg = xs_dict_append(qmsg, "req", req);
|
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 */
|
/* enqueues an input message from the shared input */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("input", msg, retries);
|
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);
|
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
|
||||||
|
|
||||||
qmsg = xs_dict_append(qmsg, "req", req);
|
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,
|
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 */
|
/* enqueues an output message to an inbox */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("output", msg, retries);
|
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 *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
|
||||||
|
|
||||||
xs *ns = xs_number_new(p_status);
|
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 */
|
/* enqueues an output message to an inbox */
|
||||||
{
|
{
|
||||||
if (xs_startswith(inbox, snac->actor)) {
|
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;
|
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);
|
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 */
|
/* enqueues an output message for an actor */
|
||||||
{
|
{
|
||||||
xs *inbox = get_actor_inbox(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 */
|
/* enqueues an email message to be sent */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("email", msg, retries);
|
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);
|
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
|
||||||
|
|
||||||
qmsg = _enqueue_put(fn, qmsg);
|
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 */
|
/* enqueues a message to be sent via Telegram */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("telegram", msg, 0);
|
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);
|
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
|
||||||
|
|
||||||
qmsg = xs_dict_append(qmsg, "bot", bot);
|
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 */
|
/* enqueues a message to be sent via ntfy */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("ntfy", msg, 0);
|
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);
|
xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
|
||||||
|
|
||||||
qmsg = xs_dict_append(qmsg, "ntfy_server", ntfy_server);
|
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 */
|
/* enqueues an output message */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("message", msg, 0);
|
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);
|
xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid);
|
||||||
|
|
||||||
qmsg = _enqueue_put(fn, qmsg);
|
qmsg = _enqueue_put(fn, qmsg);
|
||||||
|
@ -2807,7 +2811,7 @@ void enqueue_verify_links(snac *user)
|
||||||
/* enqueues a link verification */
|
/* enqueues a link verification */
|
||||||
{
|
{
|
||||||
xs *qmsg = _new_qmsg("verify_links", "", 0);
|
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);
|
xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid);
|
||||||
|
|
||||||
qmsg = _enqueue_put(fn, qmsg);
|
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)
|
int was_question_voted(snac *user, const char *id)
|
||||||
/* returns true if the user voted in this poll */
|
/* 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;
|
xs *obj = NULL;
|
||||||
|
|
||||||
if (valid_status(object_get_by_md5(md5, &obj))) {
|
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 &&
|
if (atto && strcmp(atto, user->actor) == 0 &&
|
||||||
!xs_is_null(xs_dict_get(obj, "name"))) {
|
!xs_is_null(xs_dict_get(obj, "name"))) {
|
||||||
voted = 1;
|
voted = 1;
|
||||||
|
@ -3055,7 +3023,7 @@ void purge_server(void)
|
||||||
if (mtime_nl(v2, &n_link) < mt && n_link < 2) {
|
if (mtime_nl(v2, &n_link) < mt && n_link < 2) {
|
||||||
xs *s1 = xs_replace(v2, ".json", "");
|
xs *s1 = xs_replace(v2, ".json", "");
|
||||||
xs *l = xs_split(s1, "/");
|
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);
|
object_del_by_md5(md5);
|
||||||
cnt++;
|
cnt++;
|
||||||
|
@ -3147,7 +3115,7 @@ void purge_user(snac *snac)
|
||||||
/* do the purge for this user */
|
/* do the purge for this user */
|
||||||
{
|
{
|
||||||
int priv_days, pub_days, user_days = 0;
|
int priv_days, pub_days, user_days = 0;
|
||||||
char *v;
|
const char *v;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
priv_days = xs_number_get(xs_dict_get(srv_config, "timeline_purge_days"));
|
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) {
|
if (p_size && payload) {
|
||||||
xs *payload_fn = NULL;
|
xs *payload_fn = NULL;
|
||||||
xs *payload_fn_raw = 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) {
|
if (v && xs_str_in(v, "json") != -1) {
|
||||||
payload_fn = xs_fmt("%s/payload.json", dir);
|
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) {
|
if (b_size && body) {
|
||||||
xs *body_fn = NULL;
|
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) {
|
if (v && xs_str_in(v, "json") != -1) {
|
||||||
body_fn = xs_fmt("%s/body.json", dir);
|
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 */
|
/* archives a q_item in the error folder */
|
||||||
{
|
{
|
||||||
xs *ntid = tid(0);
|
xs *ntid = tid(0);
|
||||||
|
|
276
html.c
276
html.c
|
@ -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 */
|
/* replaces all the :shortnames: with the emojis in tag */
|
||||||
{
|
{
|
||||||
if (!xs_is_null(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 *style = xs_fmt("height: %dem; width: %dem; vertical-align: middle;", ems, ems);
|
||||||
|
|
||||||
xs_list *p = tag_list;
|
|
||||||
char *v;
|
char *v;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_next(tag_list, &v, &c)) {
|
||||||
char *t = xs_dict_get(v, "type");
|
const char *t = xs_dict_get(v, "type");
|
||||||
|
|
||||||
if (t && strcmp(t, "Emoji") == 0) {
|
if (t && strcmp(t, "Emoji") == 0) {
|
||||||
char *n = xs_dict_get(v, "name");
|
const char *n = xs_dict_get(v, "name");
|
||||||
char *i = xs_dict_get(v, "icon");
|
const char *i = xs_dict_get(v, "icon");
|
||||||
|
|
||||||
if (n && i) {
|
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 *img = xs_html_sctag("img",
|
||||||
xs_html_attr("loading", "lazy"),
|
xs_html_attr("loading", "lazy"),
|
||||||
xs_html_attr("src", u),
|
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)
|
xs_str *actor_name(xs_dict *actor)
|
||||||
/* gets the actor name */
|
/* 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, "name"))) || *v == '\0') {
|
||||||
if (xs_is_null(v = xs_dict_get(actor, "preferredUsername")) || *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_html *actor_icon = xs_html_tag("p", NULL);
|
||||||
|
|
||||||
xs *avatar = NULL;
|
xs *avatar = NULL;
|
||||||
char *v;
|
const char *v;
|
||||||
int fwing = 0;
|
int fwing = 0;
|
||||||
int fwer = 0;
|
int fwer = 0;
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
|
||||||
if (avatar == NULL)
|
if (avatar == NULL)
|
||||||
avatar = xs_fmt("data:image/png;base64, %s", default_avatar_base64());
|
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;
|
xs *href = NULL;
|
||||||
|
|
||||||
if (user) {
|
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') {
|
if (xs_is_null(username = xs_dict_get(actor, "preferredUsername")) || *username == '\0') {
|
||||||
/* This should never be reached */
|
/* 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 *actor = NULL;
|
||||||
xs_html *actor_icon = NULL;
|
xs_html *actor_icon = NULL;
|
||||||
|
|
||||||
if (actor_id && valid_status(actor_get_refresh(user, actor_id, &actor))) {
|
if (actor_id && valid_status(actor_get_refresh(user, actor_id, &actor))) {
|
||||||
char *date = NULL;
|
const char *date = NULL;
|
||||||
char *udate = NULL;
|
const char *udate = NULL;
|
||||||
char *url = NULL;
|
const char *url = NULL;
|
||||||
int priv = 0;
|
int priv = 0;
|
||||||
const char *type = xs_dict_get(msg, "type");
|
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,
|
xs_html *html_note(snac *user, const char *summary,
|
||||||
char *div_id, char *form_id,
|
const char *div_id, const char *form_id,
|
||||||
char *ta_plh, char *ta_content,
|
const char *ta_plh, const char *ta_content,
|
||||||
char *edit_id, char *actor_id,
|
const char *edit_id, const char *actor_id,
|
||||||
xs_val *cw_yn, char *cw_text,
|
const xs_val *cw_yn, const char *cw_text,
|
||||||
xs_val *mnt_only, char *redir,
|
const xs_val *mnt_only, const char *redir,
|
||||||
char *in_reply_to, int poll,
|
const char *in_reply_to, int poll,
|
||||||
char *att_file, char *att_alt_text)
|
const char *att_file, const char *att_alt_text)
|
||||||
{
|
{
|
||||||
xs *action = xs_fmt("%s/admin/note", user->actor);
|
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 */
|
/* add server CSS and favicon */
|
||||||
xs *f;
|
xs *f;
|
||||||
f = xs_fmt("%s/favicon.ico", srv_baseurl);
|
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;
|
char *v;
|
||||||
while (xs_list_iter(&p, &v)) {
|
int c = 0;
|
||||||
|
|
||||||
|
while (xs_list_next(p, &v, &c)) {
|
||||||
xs_html_add(head,
|
xs_html_add(head,
|
||||||
xs_html_sctag("link",
|
xs_html_sctag("link",
|
||||||
xs_html_attr("rel", "stylesheet"),
|
xs_html_attr("rel", "stylesheet"),
|
||||||
|
@ -498,8 +500,8 @@ xs_html *html_instance_head(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *host = xs_dict_get(srv_config, "host");
|
const char *host = xs_dict_get(srv_config, "host");
|
||||||
char *title = xs_dict_get(srv_config, "title");
|
const char *title = xs_dict_get(srv_config, "title");
|
||||||
|
|
||||||
xs_html_add(head,
|
xs_html_add(head,
|
||||||
xs_html_tag("title",
|
xs_html_tag("title",
|
||||||
|
@ -511,10 +513,10 @@ xs_html *html_instance_head(void)
|
||||||
|
|
||||||
static xs_html *html_instance_body(void)
|
static xs_html *html_instance_body(void)
|
||||||
{
|
{
|
||||||
char *host = xs_dict_get(srv_config, "host");
|
const char *host = xs_dict_get(srv_config, "host");
|
||||||
char *sdesc = xs_dict_get(srv_config, "short_description");
|
const char *sdesc = xs_dict_get(srv_config, "short_description");
|
||||||
char *email = xs_dict_get(srv_config, "admin_email");
|
const char *email = xs_dict_get(srv_config, "admin_email");
|
||||||
char *acct = xs_dict_get(srv_config, "admin_account");
|
const char *acct = xs_dict_get(srv_config, "admin_account");
|
||||||
|
|
||||||
xs *blurb = xs_replace(snac_blurb, "%host%", host);
|
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"));
|
xs_html_attr("class", "h-card snac-top-user"));
|
||||||
|
|
||||||
if (read_only) {
|
if (read_only) {
|
||||||
char *header = xs_dict_get(user->config, "header");
|
const char *header = xs_dict_get(user->config, "header");
|
||||||
if (header && *header) {
|
if (header && *header) {
|
||||||
xs_html_add(top_user,
|
xs_html_add(top_user,
|
||||||
xs_html_tag("div",
|
xs_html_tag("div",
|
||||||
|
@ -797,7 +799,7 @@ static xs_html *html_user_body(snac *user, int read_only)
|
||||||
xs_html_add(top_user,
|
xs_html_add(top_user,
|
||||||
top_user_bio);
|
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) {
|
if (xs_type(metadata) == XSTYPE_DICT) {
|
||||||
xs_str *k;
|
xs_str *k;
|
||||||
xs_str *v;
|
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:/")) {
|
if (xs_startswith(v, "https:/") || xs_startswith(v, "http:/")) {
|
||||||
/* is this link validated? */
|
/* is this link validated? */
|
||||||
xs *verified_link = NULL;
|
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) {
|
if (xs_type(val_time) == XSTYPE_NUMBER) {
|
||||||
time_t t = xs_number_get(val_time);
|
time_t t = xs_number_get(val_time);
|
||||||
|
@ -928,7 +930,7 @@ xs_html *html_top_controls(snac *snac)
|
||||||
|
|
||||||
/** user settings **/
|
/** 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) {
|
if (xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE) {
|
||||||
email = xs_dict_get(snac->config_o, "email");
|
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))
|
if (xs_is_null(cw))
|
||||||
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))
|
if (xs_is_null(telegram_bot))
|
||||||
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))
|
if (xs_is_null(telegram_chat_id))
|
||||||
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))
|
if (xs_is_null(ntfy_server))
|
||||||
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))
|
if (xs_is_null(ntfy_token))
|
||||||
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)
|
if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER)
|
||||||
purge_days = (char *)xs_number_str(purge_days);
|
purge_days = (char *)xs_number_str(purge_days);
|
||||||
else
|
else
|
||||||
purge_days = "0";
|
purge_days = "0";
|
||||||
|
|
||||||
xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown");
|
const xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown");
|
||||||
xs_val *bot = xs_dict_get(snac->config, "bot");
|
const xs_val *bot = xs_dict_get(snac->config, "bot");
|
||||||
xs_val *a_private = xs_dict_get(snac->config, "private");
|
const xs_val *a_private = xs_dict_get(snac->config, "private");
|
||||||
|
|
||||||
xs *metadata = xs_str_new(NULL);
|
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 *k;
|
||||||
xs_str *v;
|
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 */
|
/* returns a string with the mentions in msg */
|
||||||
{
|
{
|
||||||
xs_str *s = xs_str_new(NULL);
|
xs_str *s = xs_str_new(NULL);
|
||||||
char *list = xs_dict_get(msg, "tag");
|
const char *list = xs_dict_get(msg, "tag");
|
||||||
char *v;
|
char *v;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
while (xs_list_iter(&list, &v)) {
|
while (xs_list_next(list, &v, &c)) {
|
||||||
char *type = xs_dict_get(v, "type");
|
const char *type = xs_dict_get(v, "type");
|
||||||
char *href = xs_dict_get(v, "href");
|
const char *href = xs_dict_get(v, "href");
|
||||||
char *name = xs_dict_get(v, "name");
|
const char *name = xs_dict_get(v, "name");
|
||||||
|
|
||||||
if (type && strcmp(type, "Mention") == 0 &&
|
if (type && strcmp(type, "Mention") == 0 &&
|
||||||
href && strcmp(href, snac->actor) != 0 && name) {
|
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");
|
const char *id = xs_dict_get(msg, "id");
|
||||||
char *group = xs_dict_get(msg, "audience");
|
const char *group = xs_dict_get(msg, "audience");
|
||||||
|
|
||||||
xs *likes = object_likes(id);
|
xs *likes = object_likes(id);
|
||||||
xs *boosts = object_announces(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("delete", L("Delete"), L("Delete this post")),
|
||||||
html_button("hide", L("Hide"), L("Hide this post and its children")));
|
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 **/
|
if (!xs_is_null(prev_src) && strcmp(actor, snac->actor) == 0) { /** edit **/
|
||||||
/* post can be edited */
|
/* 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 *form_id = xs_fmt("%s_edit_form", md5);
|
||||||
xs *redir = xs_fmt("%s_entry", md5);
|
xs *redir = xs_fmt("%s_entry", md5);
|
||||||
|
|
||||||
char *att_file = "";
|
const char *att_file = "";
|
||||||
char *att_alt_text = "";
|
const char *att_alt_text = "";
|
||||||
xs_list *att_list = xs_dict_get(msg, "attachment");
|
const xs_list *att_list = xs_dict_get(msg, "attachment");
|
||||||
|
|
||||||
/* does it have an attachment? */
|
/* does it have an attachment? */
|
||||||
if (xs_type(att_list) == XSTYPE_LIST && xs_list_len(att_list)) {
|
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) {
|
if (xs_type(d) == XSTYPE_DICT) {
|
||||||
att_file = xs_dict_get_def(d, "url", "");
|
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,
|
xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
|
||||||
int level, char *md5, int hide_children)
|
int level, char *md5, int hide_children)
|
||||||
{
|
{
|
||||||
char *id = xs_dict_get(msg, "id");
|
const char *id = xs_dict_get(msg, "id");
|
||||||
char *type = xs_dict_get(msg, "type");
|
const char *type = xs_dict_get(msg, "type");
|
||||||
char *actor;
|
const char *actor;
|
||||||
char *v;
|
const char *v;
|
||||||
int has_title = 0;
|
int has_title = 0;
|
||||||
|
|
||||||
/* do not show non-public messages in the public timeline */
|
/* 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 (xs_list_len(boosts)) {
|
||||||
/* if somebody boosted this, show as origin */
|
/* 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;
|
xs *actor_r = NULL;
|
||||||
|
|
||||||
if (user && xs_list_in(boosts, user->md5) != -1) {
|
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)) {
|
if (!xs_is_null(name)) {
|
||||||
xs *href = NULL;
|
xs *href = NULL;
|
||||||
char *id = xs_dict_get(actor_r, "id");
|
const char *id = xs_dict_get(actor_r, "id");
|
||||||
int fwers = 0;
|
int fwers = 0;
|
||||||
int fwing = 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 (strcmp(type, "Note") == 0) {
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
/* is the parent not here? */
|
/* 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)) {
|
if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) {
|
||||||
xs_html_add(post_header,
|
xs_html_add(post_header,
|
||||||
|
@ -1603,7 +1607,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
|
||||||
v = "...";
|
v = "...";
|
||||||
|
|
||||||
/* only show it when not in the public timeline and the config setting is "open" */
|
/* 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)
|
if (xs_is_null(cw) || read_only)
|
||||||
cw = "";
|
cw = "";
|
||||||
|
|
||||||
|
@ -1632,7 +1636,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
|
||||||
|
|
||||||
{
|
{
|
||||||
/** build the content string **/
|
/** 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);
|
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);
|
c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2);
|
||||||
|
|
||||||
/* Peertube videos content is in markdown */
|
/* 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) {
|
if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "text/markdown") == 0) {
|
||||||
/* a full conversion could be better */
|
/* a full conversion could be better */
|
||||||
c = xs_replace_i(c, "\r", "");
|
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 **/
|
if (strcmp(type, "Question") == 0) { /** question content **/
|
||||||
xs_list *oo = xs_dict_get(msg, "oneOf");
|
const xs_list *oo = xs_dict_get(msg, "oneOf");
|
||||||
xs_list *ao = xs_dict_get(msg, "anyOf");
|
const xs_list *ao = xs_dict_get(msg, "anyOf");
|
||||||
xs_list *p;
|
const xs_list *p;
|
||||||
xs_dict *v;
|
xs_dict *v;
|
||||||
int closed = 0;
|
int closed = 0;
|
||||||
char *f_closed = NULL;
|
const char *f_closed = NULL;
|
||||||
|
|
||||||
xs_html *poll = xs_html_tag("div", 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 */
|
/* closed poll */
|
||||||
xs_html *poll_result = xs_html_tag("table",
|
xs_html *poll_result = xs_html_tag("table",
|
||||||
xs_html_attr("class", "snac-poll-result"));
|
xs_html_attr("class", "snac-poll-result"));
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_next(p, &v, &c)) {
|
||||||
char *name = xs_dict_get(v, "name");
|
const char *name = xs_dict_get(v, "name");
|
||||||
xs_dict *replies = xs_dict_get(v, "replies");
|
const xs_dict *replies = xs_dict_get(v, "replies");
|
||||||
|
|
||||||
if (name && replies) {
|
if (name && replies) {
|
||||||
char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems"));
|
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("name", "irt"),
|
||||||
xs_html_attr("value", id))));
|
xs_html_attr("value", id))));
|
||||||
|
|
||||||
while (xs_list_iter(&p, &v)) {
|
int c = 0;
|
||||||
char *name = xs_dict_get(v, "name");
|
while (xs_list_next(p, &v, &c)) {
|
||||||
xs_dict *replies = xs_dict_get(v, "replies");
|
const char *name = xs_dict_get(v, "name");
|
||||||
|
const xs_dict *replies = xs_dict_get(v, "replies");
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems"));
|
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 {
|
else {
|
||||||
/* show when the poll closes */
|
/* 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;
|
/* Pleroma does not have an endTime field;
|
||||||
it has a closed time in the future */
|
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,
|
xs_html_add(snac_content,
|
||||||
content_attachments);
|
content_attachments);
|
||||||
|
|
||||||
xs_list *p = attach;
|
int c = 0;
|
||||||
|
xs_dict *a;
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_next(attach, &a, &c)) {
|
||||||
char *type = xs_dict_get(v, "type");
|
const char *type = xs_dict_get(a, "type");
|
||||||
char *href = xs_dict_get(v, "href");
|
const char *href = xs_dict_get(a, "href");
|
||||||
char *name = xs_dict_get(v, "name");
|
const char *name = xs_dict_get(a, "name");
|
||||||
|
|
||||||
if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) {
|
if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) {
|
||||||
xs_html_add(content_attachments,
|
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)? */
|
/* 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)) {
|
if (strcmp(type, "Page") == 0 && !xs_is_null(audience)) {
|
||||||
xs_html *au_tag = xs_html_tag("p",
|
xs_html *au_tag = xs_html_tag("p",
|
||||||
xs_html_text("("),
|
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) {
|
if (xs_list_len(list) == 1) {
|
||||||
/* only one element? pick the description from the source */
|
/* 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;
|
xs *d = NULL;
|
||||||
object_get_by_md5(id, &d);
|
object_get_by_md5(id, &d);
|
||||||
if (d && (v = xs_dict_get(d, "sourceContent")) != NULL)
|
const char *sc = xs_dict_get(d, "sourceContent");
|
||||||
desc = xs_dup(v);
|
if (d && sc != NULL)
|
||||||
|
desc = xs_dup(sc);
|
||||||
|
|
||||||
alternate = xs_dup(xs_dict_get(d, "id"));
|
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? */
|
/* is this message a non-public reply? */
|
||||||
if (user != NULL && !is_msg_public(msg)) {
|
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? */
|
/* is it a reply to something not in the storage? */
|
||||||
if (!xs_is_null(irt) && !object_here(irt)) {
|
if (!xs_is_null(irt) && !object_here(irt)) {
|
||||||
/* is it for me? */
|
/* is it for me? */
|
||||||
xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST));
|
const 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 *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) {
|
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));
|
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)));
|
html_actor_icon(snac, actor, xs_dict_get(actor, "published"), NULL, NULL, 0, 1)));
|
||||||
|
|
||||||
/* content (user bio) */
|
/* content (user bio) */
|
||||||
char *c = xs_dict_get(actor, "summary");
|
const char *c = xs_dict_get(actor, "summary");
|
||||||
|
|
||||||
if (!xs_is_null(c)) {
|
if (!xs_is_null(c)) {
|
||||||
xs *sc = sanitize(c);
|
xs *sc = sanitize(c);
|
||||||
|
@ -2364,10 +2371,10 @@ xs_str *html_notifications(snac *user, int skip, int show)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
xs *obj = NULL;
|
xs *obj = NULL;
|
||||||
char *type = xs_dict_get(noti, "type");
|
const char *type = xs_dict_get(noti, "type");
|
||||||
char *utype = xs_dict_get(noti, "utype");
|
const char *utype = xs_dict_get(noti, "utype");
|
||||||
char *id = xs_dict_get(noti, "objid");
|
const char *id = xs_dict_get(noti, "objid");
|
||||||
char *date = xs_dict_get(noti, "date");
|
const char *date = xs_dict_get(noti, "date");
|
||||||
|
|
||||||
if (xs_is_null(id) || !valid_status(object_get(id, &obj)))
|
if (xs_is_null(id) || !valid_status(object_get(id, &obj)))
|
||||||
continue;
|
continue;
|
||||||
|
@ -2375,14 +2382,14 @@ xs_str *html_notifications(snac *user, int skip, int show)
|
||||||
if (is_hidden(user, id))
|
if (is_hidden(user, id))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char *actor_id = xs_dict_get(noti, "actor");
|
const char *actor_id = xs_dict_get(noti, "actor");
|
||||||
xs *actor = NULL;
|
xs *actor = NULL;
|
||||||
|
|
||||||
if (!valid_status(actor_get(actor_id, &actor)))
|
if (!valid_status(actor_get(actor_id, &actor)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
xs *a_name = actor_name(actor);
|
xs *a_name = actor_name(actor);
|
||||||
char *label = type;
|
const char *label = type;
|
||||||
|
|
||||||
if (strcmp(type, "Create") == 0)
|
if (strcmp(type, "Create") == 0)
|
||||||
label = L("Mention");
|
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,
|
int html_get_handler(const xs_dict *req, const char *q_path,
|
||||||
char **body, int *b_size, char **ctype, xs_str **etag)
|
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;
|
int status = 404;
|
||||||
snac snac;
|
snac snac;
|
||||||
xs *uid = NULL;
|
xs *uid = NULL;
|
||||||
char *p_path;
|
const char *p_path;
|
||||||
int cache = 1;
|
int cache = 1;
|
||||||
int save = 1;
|
int save = 1;
|
||||||
char *v;
|
const char *v;
|
||||||
|
|
||||||
xs *l = xs_split_n(q_path, "/", 2);
|
xs *l = xs_split_n(q_path, "/", 2);
|
||||||
v = xs_list_get(l, 1);
|
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 skip = 0;
|
||||||
int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries"));
|
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)
|
if ((v = xs_dict_get(q_vars, "skip")) != NULL)
|
||||||
skip = atoi(v), cache = 0, save = 0;
|
skip = atoi(v), cache = 0, save = 0;
|
||||||
if ((v = xs_dict_get(q_vars, "show")) != NULL)
|
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;
|
status = 401;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *q = xs_dict_get(q_vars, "q");
|
const char *q = xs_dict_get(q_vars, "q");
|
||||||
|
|
||||||
if (q && *q) {
|
if (q && *q) {
|
||||||
if (*q == '#') {
|
if (*q == '#') {
|
||||||
|
@ -2669,7 +2676,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
xs *l = xs_split(p_path, "/");
|
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)) {
|
if (md5 && *md5 && timeline_here(&snac, md5)) {
|
||||||
xs *list = xs_list_append(xs_list_new(), 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 {
|
else {
|
||||||
xs *l = xs_split(p_path, "/");
|
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 *list = list_timeline(&snac, lid, skip, show);
|
||||||
xs *next = list_timeline(&snac, lid, skip + show, 1);
|
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
|
else
|
||||||
if (xs_startswith(p_path, "s/")) { /** a static file **/
|
if (xs_startswith(p_path, "s/")) { /** a static file **/
|
||||||
xs *l = xs_split(p_path, "/");
|
xs *l = xs_split(p_path, "/");
|
||||||
char *id = xs_list_get(l, 1);
|
const char *id = xs_list_get(l, 1);
|
||||||
int sz;
|
int sz;
|
||||||
|
|
||||||
if (id && *id) {
|
if (id && *id) {
|
||||||
|
@ -2789,7 +2796,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
|
||||||
return 403;
|
return 403;
|
||||||
|
|
||||||
xs *l = xs_split(p_path, "/");
|
xs *l = xs_split(p_path, "/");
|
||||||
char *id = xs_list_get(l, 1);
|
const char *id = xs_list_get(l, 1);
|
||||||
|
|
||||||
if (id && *id) {
|
if (id && *id) {
|
||||||
if (xs_endswith(id, "timeline.html_")) {
|
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;
|
int status = 0;
|
||||||
snac snac;
|
snac snac;
|
||||||
char *uid, *p_path;
|
const char *uid;
|
||||||
xs_dict *p_vars;
|
const char *p_path;
|
||||||
|
const xs_dict *p_vars;
|
||||||
|
|
||||||
xs *l = xs_split_n(q_path, "/", 2);
|
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) { /** **/
|
if (p_path && strcmp(p_path, "admin/note") == 0) { /** **/
|
||||||
/* post note */
|
/* post note */
|
||||||
xs_str *content = xs_dict_get(p_vars, "content");
|
const xs_str *content = xs_dict_get(p_vars, "content");
|
||||||
xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to");
|
const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to");
|
||||||
xs_str *attach_url = xs_dict_get(p_vars, "attach_url");
|
const xs_str *attach_url = xs_dict_get(p_vars, "attach_url");
|
||||||
xs_list *attach_file = xs_dict_get(p_vars, "attach");
|
const xs_list *attach_file = xs_dict_get(p_vars, "attach");
|
||||||
xs_str *to = xs_dict_get(p_vars, "to");
|
const xs_str *to = xs_dict_get(p_vars, "to");
|
||||||
xs_str *sensitive = xs_dict_get(p_vars, "sensitive");
|
const xs_str *sensitive = xs_dict_get(p_vars, "sensitive");
|
||||||
xs_str *summary = xs_dict_get(p_vars, "summary");
|
const xs_str *summary = xs_dict_get(p_vars, "summary");
|
||||||
xs_str *edit_id = xs_dict_get(p_vars, "edit_id");
|
const 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 *alt_text = xs_dict_get(p_vars, "alt_text");
|
||||||
int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only"));
|
int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only"));
|
||||||
xs *attach_list = xs_list_new();
|
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? */
|
/* is attach_file set? */
|
||||||
if (!xs_is_null(attach_file) && xs_type(attach_file) == XSTYPE_LIST) {
|
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') {
|
if (*fn != '\0') {
|
||||||
char *ext = strrchr(fn, '.');
|
char *ext = strrchr(fn, '.');
|
||||||
|
@ -2978,7 +2986,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
for (n = 0; fields[n]; 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);
|
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
|
else
|
||||||
if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/
|
if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/
|
||||||
/* action on an entry */
|
/* action on an entry */
|
||||||
char *id = xs_dict_get(p_vars, "id");
|
const char *id = xs_dict_get(p_vars, "id");
|
||||||
char *actor = xs_dict_get(p_vars, "actor");
|
const char *actor = xs_dict_get(p_vars, "actor");
|
||||||
char *action = xs_dict_get(p_vars, "action");
|
const char *action = xs_dict_get(p_vars, "action");
|
||||||
char *group = xs_dict_get(p_vars, "group");
|
const char *group = xs_dict_get(p_vars, "group");
|
||||||
|
|
||||||
if (action == NULL)
|
if (action == NULL)
|
||||||
return 404;
|
return 404;
|
||||||
|
@ -3134,7 +3142,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (strcmp(action, L("Delete")) == 0) { /** **/
|
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) {
|
if (actor_form != NULL) {
|
||||||
/* delete follower */
|
/* delete follower */
|
||||||
if (valid_status(follower_del(&snac, actor)))
|
if (valid_status(follower_del(&snac, actor)))
|
||||||
|
@ -3178,8 +3186,8 @@ int html_post_handler(const xs_dict *req, const char *q_path,
|
||||||
else
|
else
|
||||||
if (p_path && strcmp(p_path, "admin/user-setup") == 0) { /** **/
|
if (p_path && strcmp(p_path, "admin/user-setup") == 0) { /** **/
|
||||||
/* change of user data */
|
/* change of user data */
|
||||||
char *v;
|
const char *v;
|
||||||
char *p1, *p2;
|
const char *p1, *p2;
|
||||||
|
|
||||||
if ((v = xs_dict_get(p_vars, "name")) != NULL)
|
if ((v = xs_dict_get(p_vars, "name")) != NULL)
|
||||||
snac.config = xs_dict_set(snac.config, "name", v);
|
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++) {
|
for (n = 0; uploads[n]; n++) {
|
||||||
xs *var_name = xs_fmt("%s_file", uploads[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) {
|
if (xs_type(uploaded_file) == XSTYPE_LIST) {
|
||||||
const char *fn = xs_list_get(uploaded_file, 0);
|
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
|
else
|
||||||
if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/
|
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 *opt = xs_dict_get(p_vars, "question");
|
||||||
const char *actor = xs_dict_get(p_vars, "actor");
|
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;
|
xs *poll = NULL;
|
||||||
|
|
||||||
if (valid_status(object_get(irt, &poll))) {
|
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))
|
if (xs_is_null(date))
|
||||||
date = xs_dict_get(poll, "closed");
|
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) {
|
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))
|
if (xs_is_null(redir))
|
||||||
redir = "top";
|
redir = "top";
|
||||||
|
@ -3411,8 +3419,8 @@ xs_str *timeline_to_rss(snac *user, const xs_list *timeline, char *title, char *
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *id = xs_dict_get(msg, "id");
|
const char *id = xs_dict_get(msg, "id");
|
||||||
char *content = xs_dict_get(msg, "content");
|
const char *content = xs_dict_get(msg, "content");
|
||||||
|
|
||||||
if (user && !xs_startswith(id, user->actor))
|
if (user && !xs_startswith(id, user->actor))
|
||||||
continue;
|
continue;
|
||||||
|
|
27
http.c
27
http.c
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
|
xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
|
||||||
const char *method, const char *url,
|
const char *method, const char *url,
|
||||||
xs_dict *headers,
|
const xs_dict *headers,
|
||||||
const char *body, int b_size,
|
const char *body, int b_size,
|
||||||
int *status, xs_str **payload, int *p_size,
|
int *status, xs_str **payload, int *p_size,
|
||||||
int timeout)
|
int timeout)
|
||||||
|
@ -24,8 +24,8 @@ xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
|
||||||
xs *s64 = NULL;
|
xs *s64 = NULL;
|
||||||
xs *signature = NULL;
|
xs *signature = NULL;
|
||||||
xs *hdrs = NULL;
|
xs *hdrs = NULL;
|
||||||
char *host;
|
const char *host;
|
||||||
char *target;
|
const char *target;
|
||||||
char *k, *v;
|
char *k, *v;
|
||||||
xs_dict *response;
|
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 *http_signed_request(snac *snac, const char *method, const char *url,
|
||||||
xs_dict *headers,
|
const xs_dict *headers,
|
||||||
const char *body, int b_size,
|
const char *body, int b_size,
|
||||||
int *status, xs_str **payload, int *p_size,
|
int *status, xs_str **payload, int *p_size,
|
||||||
int timeout)
|
int timeout)
|
||||||
/* does a signed HTTP request */
|
/* 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;
|
xs_dict *response;
|
||||||
|
|
||||||
response = http_signed_request_raw(snac->actor, seckey, method, url,
|
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 */
|
/* check the signature */
|
||||||
{
|
{
|
||||||
char *sig_hdr = xs_dict_get(req, "signature");
|
const char *sig_hdr = xs_dict_get(req, "signature");
|
||||||
xs *keyId = NULL;
|
xs *keyId = NULL;
|
||||||
xs *headers = NULL;
|
xs *headers = NULL;
|
||||||
xs *signature = NULL;
|
xs *signature = NULL;
|
||||||
xs *created = NULL;
|
xs *created = NULL;
|
||||||
xs *expires = NULL;
|
xs *expires = NULL;
|
||||||
char *pubkey;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
const char *pubkey;
|
||||||
|
const char *k;
|
||||||
|
|
||||||
if (xs_is_null(sig_hdr)) {
|
if (xs_is_null(sig_hdr)) {
|
||||||
*err = xs_fmt("missing 'signature' header");
|
*err = xs_fmt("missing 'signature' header");
|
||||||
|
@ -142,10 +143,10 @@ int check_signature(xs_dict *req, xs_str **err)
|
||||||
{
|
{
|
||||||
/* extract the values */
|
/* extract the values */
|
||||||
xs *l = xs_split(sig_hdr, ",");
|
xs *l = xs_split(sig_hdr, ",");
|
||||||
xs_list *p = l;
|
int c = 0;
|
||||||
xs_val *v;
|
xs_val *v;
|
||||||
|
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_next(l, &v, &c)) {
|
||||||
xs *kv = xs_split_n(v, "=", 1);
|
xs *kv = xs_split_n(v, "=", 1);
|
||||||
|
|
||||||
if (xs_list_len(kv) != 2)
|
if (xs_list_len(kv) != 2)
|
||||||
|
@ -192,8 +193,8 @@ int check_signature(xs_dict *req, xs_str **err)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p = xs_dict_get(actor, "publicKey")) == NULL ||
|
if ((k = xs_dict_get(actor, "publicKey")) == NULL ||
|
||||||
((pubkey = xs_dict_get(p, "publicKeyPem")) == NULL)) {
|
((pubkey = xs_dict_get(k, "publicKeyPem")) == NULL)) {
|
||||||
*err = xs_fmt("cannot get pubkey from %s", keyId);
|
*err = xs_fmt("cannot get pubkey from %s", keyId);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +209,7 @@ int check_signature(xs_dict *req, xs_str **err)
|
||||||
|
|
||||||
p = l;
|
p = l;
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_iter(&p, &v)) {
|
||||||
char *hc;
|
const char *hc;
|
||||||
xs *ss = NULL;
|
xs *ss = NULL;
|
||||||
|
|
||||||
if (*sig_str != '\0')
|
if (*sig_str != '\0')
|
||||||
|
|
16
httpd.c
16
httpd.c
|
@ -125,7 +125,7 @@ static xs_str *greeting_html(void)
|
||||||
|
|
||||||
/* does it have a %userlist% mark? */
|
/* does it have a %userlist% mark? */
|
||||||
if (xs_str_in(s, "%userlist%") != -1) {
|
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 = user_list();
|
||||||
xs_list *p = list;
|
xs_list *p = list;
|
||||||
xs_str *uid;
|
xs_str *uid;
|
||||||
|
@ -171,14 +171,14 @@ int server_get_handler(xs_dict *req, const char *q_path,
|
||||||
|
|
||||||
/* is it the server root? */
|
/* is it the server root? */
|
||||||
if (*q_path == '\0') {
|
if (*q_path == '\0') {
|
||||||
xs_dict *q_vars = xs_dict_get(req, "q_vars");
|
const xs_dict *q_vars = xs_dict_get(req, "q_vars");
|
||||||
char *t = NULL;
|
const char *t = NULL;
|
||||||
|
|
||||||
if (xs_type(q_vars) == XSTYPE_DICT && (t = xs_dict_get(q_vars, "t"))) {
|
if (xs_type(q_vars) == XSTYPE_DICT && (t = xs_dict_get(q_vars, "t"))) {
|
||||||
/** search by tag **/
|
/** search by tag **/
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries"));
|
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)
|
if ((v = xs_dict_get(q_vars, "skip")) != NULL)
|
||||||
skip = atoi(v);
|
skip = atoi(v);
|
||||||
|
@ -193,7 +193,7 @@ int server_get_handler(xs_dict *req, const char *q_path,
|
||||||
more = 1;
|
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) {
|
if (!xs_is_null(accept) && strcmp(accept, "application/rss+xml") == 0) {
|
||||||
xs *link = xs_fmt("%s/?t=%s", srv_baseurl, t);
|
xs *link = xs_fmt("%s/?t=%s", srv_baseurl, t);
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ void httpd_connection(FILE *f)
|
||||||
/* the connection processor */
|
/* the connection processor */
|
||||||
{
|
{
|
||||||
xs *req;
|
xs *req;
|
||||||
char *method;
|
const char *method;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
xs_str *body = NULL;
|
xs_str *body = NULL;
|
||||||
int b_size = 0;
|
int b_size = 0;
|
||||||
|
@ -278,7 +278,7 @@ void httpd_connection(FILE *f)
|
||||||
xs *payload = NULL;
|
xs *payload = NULL;
|
||||||
xs *etag = NULL;
|
xs *etag = NULL;
|
||||||
int p_size = 0;
|
int p_size = 0;
|
||||||
char *p;
|
const char *p;
|
||||||
int fcgi_id;
|
int fcgi_id;
|
||||||
|
|
||||||
if (p_state->use_fcgi)
|
if (p_state->use_fcgi)
|
||||||
|
@ -411,7 +411,7 @@ void httpd_connection(FILE *f)
|
||||||
headers = xs_dict_append(headers, "etag", etag);
|
headers = xs_dict_append(headers, "etag", etag);
|
||||||
|
|
||||||
/* if there are any additional headers, add them */
|
/* 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) {
|
if (xs_type(more_headers) == XSTYPE_DICT) {
|
||||||
char *k, *v;
|
char *k, *v;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
2
main.c
2
main.c
|
@ -315,7 +315,7 @@ int main(int argc, char *argv[])
|
||||||
xs *msg = msg_follow(&snac, url);
|
xs *msg = msg_follow(&snac, url);
|
||||||
|
|
||||||
if (msg != NULL) {
|
if (msg != NULL) {
|
||||||
char *actor = xs_dict_get(msg, "object");
|
const char *actor = xs_dict_get(msg, "object");
|
||||||
|
|
||||||
following_add(&snac, actor, msg);
|
following_add(&snac, actor, msg);
|
||||||
|
|
||||||
|
|
109
mastoapi.c
109
mastoapi.c
|
@ -175,7 +175,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int status = 404;
|
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);
|
xs *cmd = xs_replace_n(q_path, "/oauth", "", 1);
|
||||||
|
|
||||||
srv_debug(1, xs_fmt("oauth_get_handler %s", q_path));
|
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;
|
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;
|
xs *args = NULL;
|
||||||
|
|
||||||
if (i_ctype && xs_startswith(i_ctype, "application/json")) {
|
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);
|
acct = xs_dict_append(acct, "uri", id);
|
||||||
|
|
||||||
xs *avatar = NULL;
|
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) {
|
if (xs_type(av) == XSTYPE_DICT) {
|
||||||
char *url = xs_dict_get(av, "url");
|
const char *url = xs_dict_get(av, "url");
|
||||||
|
|
||||||
if (url != NULL)
|
if (url != NULL)
|
||||||
avatar = xs_dup(url);
|
avatar = xs_dup(url);
|
||||||
|
@ -584,7 +584,7 @@ xs_dict *mastoapi_account(const xs_dict *actor)
|
||||||
acct = xs_dict_append(acct, "avatar_static", avatar);
|
acct = xs_dict_append(acct, "avatar_static", avatar);
|
||||||
|
|
||||||
xs *header = NULL;
|
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)
|
if (xs_type(hd) == XSTYPE_DICT)
|
||||||
header = xs_dup(xs_dict_get(hd, "url"));
|
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);
|
acct = xs_dict_append(acct, "header_static", header);
|
||||||
|
|
||||||
/* emojis */
|
/* emojis */
|
||||||
xs_list *p;
|
const xs_list *p;
|
||||||
if (!xs_is_null(p = xs_dict_get(actor, "tag"))) {
|
if (!xs_is_null(p = xs_dict_get(actor, "tag"))) {
|
||||||
xs *eml = xs_list_new();
|
xs *eml = xs_list_new();
|
||||||
xs_dict *v;
|
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");
|
const char *type = xs_dict_get(v, "type");
|
||||||
|
|
||||||
if (!xs_is_null(type) && strcmp(type, "Emoji") == 0) {
|
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 */
|
/* dict of validated links */
|
||||||
xs_dict *val_links = NULL;
|
xs_dict *val_links = NULL;
|
||||||
xs_dict *metadata = xs_stock(XSTYPE_DICT);
|
const xs_dict *metadata = xs_stock(XSTYPE_DICT);
|
||||||
snac user = {0};
|
snac user = {0};
|
||||||
|
|
||||||
if (xs_startswith(id, srv_baseurl)) {
|
if (xs_startswith(id, srv_baseurl)) {
|
||||||
|
@ -654,19 +655,20 @@ xs_dict *mastoapi_account(const xs_dict *actor)
|
||||||
if (xs_is_null(val_links))
|
if (xs_is_null(val_links))
|
||||||
val_links = xs_stock(XSTYPE_DICT);
|
val_links = xs_stock(XSTYPE_DICT);
|
||||||
|
|
||||||
while (xs_list_iter(&p, &v)) {
|
int c = 0;
|
||||||
char *type = xs_dict_get(v, "type");
|
while (xs_list_next(p, &v, &c)) {
|
||||||
char *name = xs_dict_get(v, "name");
|
const char *type = xs_dict_get(v, "type");
|
||||||
char *value = xs_dict_get(v, "value");
|
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) &&
|
if (!xs_is_null(type) && !xs_is_null(name) &&
|
||||||
!xs_is_null(value) && strcmp(type, "PropertyValue") == 0) {
|
!xs_is_null(value) && strcmp(type, "PropertyValue") == 0) {
|
||||||
xs *val_date = NULL;
|
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:/" "/")) {
|
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) {
|
if (xs_type(verified_time) == XSTYPE_NUMBER) {
|
||||||
time_t t = xs_number_get(verified_time);
|
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 */
|
/* converts an ISO 8601 date to whatever format Mastodon uses */
|
||||||
{
|
{
|
||||||
xs_str *s = xs_crop_i(xs_dup(date), 0, 19);
|
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_dict *poll = xs_dict_new();
|
||||||
xs *mid = mastoapi_id(msg);
|
xs *mid = mastoapi_id(msg);
|
||||||
xs_list *opts = NULL;
|
const xs_list *opts = NULL;
|
||||||
xs_val *v;
|
xs_val *v;
|
||||||
int num_votes = 0;
|
int num_votes = 0;
|
||||||
xs *options = xs_list_new();
|
xs *options = xs_list_new();
|
||||||
|
|
||||||
poll = xs_dict_append(poll, "id", mid);
|
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)
|
if (date == NULL)
|
||||||
date = xs_dict_get(msg, "closed");
|
date = xs_dict_get(msg, "closed");
|
||||||
if (date == NULL)
|
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));
|
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 *title = xs_dict_get(v, "name");
|
||||||
const char *replies = xs_dict_get(v, "replies");
|
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 *idx = NULL;
|
||||||
xs *ixc = NULL;
|
xs *ixc = NULL;
|
||||||
char *tmp;
|
const char *tmp;
|
||||||
xs *mid = mastoapi_id(msg);
|
xs *mid = mastoapi_id(msg);
|
||||||
|
|
||||||
xs_dict *st = xs_dict_new();
|
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();
|
xs *matt = xs_list_new();
|
||||||
|
|
||||||
while (xs_list_iter(&p, &v)) {
|
while (xs_list_iter(&p, &v)) {
|
||||||
char *type = xs_dict_get(v, "type");
|
const char *type = xs_dict_get(v, "type");
|
||||||
char *href = xs_dict_get(v, "href");
|
const char *href = xs_dict_get(v, "href");
|
||||||
char *name = xs_dict_get(v, "name");
|
const char *name = xs_dict_get(v, "name");
|
||||||
|
|
||||||
if (xs_match(type, "image/*|video/*|Image|Video")) { /* */
|
if (xs_match(type, "image/*|video/*|Image|Video")) { /* */
|
||||||
xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt));
|
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 *ml = xs_list_new();
|
||||||
xs *htl = xs_list_new();
|
xs *htl = xs_list_new();
|
||||||
xs *eml = 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;
|
int n = 0;
|
||||||
|
|
||||||
xs *tag_list = NULL;
|
xs *tag_list = NULL;
|
||||||
|
@ -897,7 +900,8 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
|
||||||
tag = tag_list;
|
tag = tag_list;
|
||||||
xs_dict *v;
|
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");
|
const char *type = xs_dict_get(v, "type");
|
||||||
|
|
||||||
if (xs_is_null(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);
|
xs *irt_mid = mastoapi_id(irto);
|
||||||
st = xs_dict_set(st, "in_reply_to_id", irt_mid);
|
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))) {
|
if (!xs_is_null(at = get_atto(irto))) {
|
||||||
xs *at_md5 = xs_md5_hex(at, strlen(at));
|
xs *at_md5 = xs_md5_hex(at, strlen(at));
|
||||||
st = xs_dict_set(st, "in_reply_to_account_id", at_md5);
|
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 */
|
/* processes an authorization token, if there is one */
|
||||||
{
|
{
|
||||||
int logged_in = 0;
|
int logged_in = 0;
|
||||||
char *v;
|
const char *v;
|
||||||
|
|
||||||
/* if there is an authorization field, try to validate it */
|
/* if there is an authorization field, try to validate it */
|
||||||
if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) {
|
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;
|
return 0;
|
||||||
|
|
||||||
int status = 404;
|
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);
|
xs *cmd = xs_replace_n(q_path, "/api", "", 1);
|
||||||
|
|
||||||
snac snac1 = {0};
|
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);
|
acct = xs_dict_append(acct, "source", src);
|
||||||
|
|
||||||
xs *avatar = NULL;
|
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')
|
if (xs_is_null(av) || *av == '\0')
|
||||||
avatar = xs_fmt("%s/susie.png", srv_baseurl);
|
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);
|
acct = xs_dict_append(acct, "avatar_static", avatar);
|
||||||
|
|
||||||
xs *header = NULL;
|
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))
|
if (!xs_is_null(hd))
|
||||||
header = xs_dup(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", header);
|
||||||
acct = xs_dict_append(acct, "header_static", 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) {
|
if (xs_type(metadata) == XSTYPE_DICT) {
|
||||||
xs *fields = xs_list_new();
|
xs *fields = xs_list_new();
|
||||||
xs_str *k;
|
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)) {
|
while (xs_dict_next(metadata, &k, &v, &c)) {
|
||||||
xs *val_date = NULL;
|
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) {
|
if (xs_type(verified_time) == XSTYPE_NUMBER) {
|
||||||
time_t t = xs_number_get(verified_time);
|
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
|
else
|
||||||
if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/
|
if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/
|
||||||
/* lookup an account */
|
/* lookup an account */
|
||||||
char *acct = xs_dict_get(args, "acct");
|
const char *acct = xs_dict_get(args, "acct");
|
||||||
|
|
||||||
if (!xs_is_null(acct)) {
|
if (!xs_is_null(acct)) {
|
||||||
xs *s = xs_strip_chars_i(xs_dup(acct), "@");
|
xs *s = xs_strip_chars_i(xs_dup(acct), "@");
|
||||||
xs *l = xs_split_n(s, "@", 1);
|
xs *l = xs_split_n(s, "@", 1);
|
||||||
char *uid = xs_list_get(l, 0);
|
const char *uid = xs_list_get(l, 0);
|
||||||
char *host = xs_list_get(l, 1);
|
const char *host = xs_list_get(l, 1);
|
||||||
|
|
||||||
if (uid && (!host || strcmp(host, xs_dict_get(srv_config, "host")) == 0)) {
|
if (uid && (!host || strcmp(host, xs_dict_get(srv_config, "host")) == 0)) {
|
||||||
snac user;
|
snac user;
|
||||||
|
@ -1624,7 +1628,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
|
||||||
|
|
||||||
/* get the tag */
|
/* get the tag */
|
||||||
xs *l = xs_split(cmd, "/");
|
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 *timeline = tag_search(tag, 0, limit);
|
||||||
xs *out = xs_list_new();
|
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 */
|
/* get the list id */
|
||||||
if (logged_in) {
|
if (logged_in) {
|
||||||
xs *l = xs_split(cmd, "/");
|
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 *timeline = list_timeline(&snac1, list, 0, 2048);
|
||||||
xs *out = xs_list_new();
|
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 *out = xs_list_new();
|
||||||
xs_list *p = l;
|
xs_list *p = l;
|
||||||
xs_dict *v;
|
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)) {
|
while (xs_list_iter(&p, &v)) {
|
||||||
xs *noti = notify_get(&snac1, 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 (xs_startswith(cmd, "/v1/lists/")) { /** list information **/
|
||||||
if (logged_in) {
|
if (logged_in) {
|
||||||
xs *l = xs_split(cmd, "/");
|
xs *l = xs_split(cmd, "/");
|
||||||
char *p = xs_list_get(l, -1);
|
const char *p = xs_list_get(l, -1);
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
if (strcmp(p, "accounts") == 0) {
|
if (strcmp(p, "accounts") == 0) {
|
||||||
|
@ -1910,7 +1914,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
|
||||||
xs_list *v;
|
xs_list *v;
|
||||||
|
|
||||||
while (xs_list_next(lol, &v, &c)) {
|
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) {
|
if (id && strcmp(id, p) == 0) {
|
||||||
xs *d = xs_dict_new();
|
xs *d = xs_dict_new();
|
||||||
|
@ -2314,7 +2318,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
|
||||||
|
|
||||||
int status = 404;
|
int status = 404;
|
||||||
xs *args = NULL;
|
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 (i_ctype && xs_startswith(i_ctype, "application/json")) {
|
||||||
if (!xs_is_null(payload))
|
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);
|
mid = MID_TO_MD5(mid);
|
||||||
|
|
||||||
if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) {
|
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) {
|
if (op == NULL) {
|
||||||
/* no operation (?) */
|
/* 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) { /** **/
|
if (strcmp(cmd, "/v1/push/subscription") == 0) { /** **/
|
||||||
/* I don't know what I'm doing */
|
/* I don't know what I'm doing */
|
||||||
if (logged_in) {
|
if (logged_in) {
|
||||||
char *v;
|
const char *v;
|
||||||
|
|
||||||
xs *wpush = xs_dict_new();
|
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 *id = xs_dict_get(msg, "id");
|
||||||
const char *atto = get_atto(msg);
|
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)
|
if (opts == NULL)
|
||||||
opts = xs_dict_get(msg, "anyOf");
|
opts = xs_dict_get(msg, "anyOf");
|
||||||
|
|
||||||
|
@ -2773,7 +2777,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (strcmp(op, "votes") == 0) {
|
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))
|
if (xs_is_null(choices))
|
||||||
choices = xs_dict_get(args, "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) {
|
if (xs_type(choices) == XSTYPE_LIST) {
|
||||||
xs_str *v;
|
xs_str *v;
|
||||||
|
|
||||||
while (xs_list_iter(&choices, &v)) {
|
int c = 0;
|
||||||
|
while (xs_list_next(choices, &v, &c)) {
|
||||||
int io = atoi(v);
|
int io = atoi(v);
|
||||||
const xs_dict *o = xs_list_get(opts, io);
|
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 (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/
|
||||||
if (logged_in) {
|
if (logged_in) {
|
||||||
xs *l = xs_split(cmd, "/");
|
xs *l = xs_split(cmd, "/");
|
||||||
char *op = xs_list_get(l, -1);
|
const char *op = xs_list_get(l, -1);
|
||||||
char *id = xs_list_get(l, -2);
|
const char *id = xs_list_get(l, -2);
|
||||||
|
|
||||||
if (op && id && xs_is_hex(id)) {
|
if (op && id && xs_is_hex(id)) {
|
||||||
if (strcmp(op, "accounts") == 0) {
|
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;
|
int c = 0;
|
||||||
char *v;
|
char *v;
|
||||||
|
|
||||||
|
@ -2888,7 +2893,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
|
||||||
|
|
||||||
int status = 404;
|
int status = 404;
|
||||||
xs *args = NULL;
|
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 (i_ctype && xs_startswith(i_ctype, "application/json")) {
|
||||||
if (!xs_is_null(payload))
|
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 (xs_startswith(cmd, "/v1/lists/")) {
|
||||||
if (logged_in) {
|
if (logged_in) {
|
||||||
xs *l = xs_split(cmd, "/");
|
xs *l = xs_split(cmd, "/");
|
||||||
char *p = xs_list_get(l, -1);
|
const char *p = xs_list_get(l, -1);
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
if (strcmp(p, "accounts") == 0) {
|
if (strcmp(p, "accounts") == 0) {
|
||||||
/* delete account from list */
|
/* delete account from list */
|
||||||
p = xs_list_get(l, -2);
|
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;
|
int c = 0;
|
||||||
char *v;
|
char *v;
|
||||||
|
|
||||||
|
@ -2971,7 +2976,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
|
||||||
|
|
||||||
int status = 404;
|
int status = 404;
|
||||||
xs *args = NULL;
|
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 (i_ctype && xs_startswith(i_ctype, "application/json")) {
|
||||||
if (!xs_is_null(payload))
|
if (!xs_is_null(payload))
|
||||||
|
|
45
snac.h
45
snac.h
|
@ -69,7 +69,7 @@ void snac_log(snac *user, xs_str *str);
|
||||||
#define snac_debug(user, level, str) do { if (dbglevel >= (level)) \
|
#define snac_debug(user, level, str) do { if (dbglevel >= (level)) \
|
||||||
{ snac_log((user), (str)); } } while (0)
|
{ 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);
|
void srv_free(void);
|
||||||
|
|
||||||
int user_open(snac *snac, const char *uid);
|
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);
|
const char *body, int b_size);
|
||||||
void srv_archive_error(const char *prefix, const xs_str *err,
|
void srv_archive_error(const char *prefix, const xs_str *err,
|
||||||
const xs_dict *req, const xs_val *data);
|
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);
|
double mtime_nl(const char *fn, int *n_link);
|
||||||
#define mtime(fn) mtime_nl(fn, NULL)
|
#define mtime(fn) mtime_nl(fn, NULL)
|
||||||
|
@ -139,13 +139,13 @@ double timeline_mtime(snac *snac);
|
||||||
int timeline_touch(snac *snac);
|
int timeline_touch(snac *snac);
|
||||||
int timeline_here(snac *snac, const char *md5);
|
int timeline_here(snac *snac, const char *md5);
|
||||||
int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg);
|
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_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);
|
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_add(snac *snac, const char *id, const xs_dict *o_msg);
|
||||||
int timeline_admire(snac *snac, const char *id, const char *admirer, int like);
|
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 *local_list(snac *snac, int max);
|
||||||
xs_list *timeline_instance_list(int skip, int show);
|
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);
|
int is_hidden(snac *snac, const char *id);
|
||||||
|
|
||||||
void tag_index(const char *id, const xs_dict *obj);
|
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_val *list_maint(snac *user, const char *list, int op);
|
||||||
xs_list *list_timeline(snac *user, const char *list, int skip, int show);
|
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);
|
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);
|
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(const char *actor, xs_dict **data);
|
||||||
int actor_get_refresh(snac *user, 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_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_shared_input(const xs_dict *msg, const xs_dict *req, int retries);
|
||||||
void enqueue_output_raw(const char *keyid, const char *seckey,
|
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,
|
||||||
void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_status);
|
int retries, int p_status);
|
||||||
void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries);
|
void enqueue_output(snac *snac, const xs_dict *msg,
|
||||||
void enqueue_email(xs_str *msg, int retries);
|
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_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_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token);
|
||||||
void enqueue_message(snac *snac, const xs_dict *msg);
|
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_object_request(snac *user, const char *id, int forward_secs);
|
||||||
void enqueue_verify_links(snac *user);
|
void enqueue_verify_links(snac *user);
|
||||||
void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs);
|
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);
|
int was_question_voted(snac *user, const char *id);
|
||||||
|
|
||||||
xs_list *user_queue(snac *snac);
|
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,
|
xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
|
||||||
const char *method, const char *url,
|
const char *method, const char *url,
|
||||||
xs_dict *headers,
|
const xs_dict *headers,
|
||||||
const char *body, int b_size,
|
const char *body, int b_size,
|
||||||
int *status, xs_str **payload, int *p_size,
|
int *status, xs_str **payload, int *p_size,
|
||||||
int timeout);
|
int timeout);
|
||||||
xs_dict *http_signed_request(snac *snac, const char *method, const char *url,
|
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,
|
const char *body, int b_size,
|
||||||
int *status, xs_str **payload, int *p_size,
|
int *status, xs_str **payload, int *p_size,
|
||||||
int timeout);
|
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);
|
srv_state *srv_state_op(xs_str **fname, int op);
|
||||||
void httpd(void);
|
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);
|
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_list *get_attachments(const xs_dict *msg);
|
||||||
|
|
||||||
xs_dict *msg_admiration(snac *snac, char *object, char *type);
|
xs_dict *msg_admiration(snac *snac, const char *object, const char *type);
|
||||||
xs_dict *msg_repulsion(snac *user, char *id, 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_create(snac *snac, const xs_dict *object);
|
||||||
xs_dict *msg_follow(snac *snac, const char *actor);
|
xs_dict *msg_follow(snac *snac, const char *actor);
|
||||||
|
|
||||||
xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
|
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_undo(snac *snac, const xs_val *object);
|
||||||
xs_dict *msg_delete(snac *snac, char *id);
|
xs_dict *msg_delete(snac *snac, const char *id);
|
||||||
xs_dict *msg_actor(snac *snac);
|
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_ping(snac *user, const char *rcpt);
|
||||||
xs_dict *msg_pong(snac *user, const char *rcpt, const char *object);
|
xs_dict *msg_pong(snac *user, const char *rcpt, const char *object);
|
||||||
xs_dict *msg_question(snac *user, const char *content, xs_list *attach,
|
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 activitypub_request(snac *snac, const char *url, xs_dict **data);
|
||||||
int actor_request(snac *user, const char *actor, 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,
|
int send_to_inbox_raw(const char *keyid, const char *seckey,
|
||||||
const xs_str *inbox, const xs_dict *msg,
|
const xs_str *inbox, const xs_dict *msg,
|
||||||
xs_val **payload, int *p_size, int timeout);
|
xs_val **payload, int *p_size, int timeout);
|
||||||
|
|
38
upgrade.c
38
upgrade.c
|
@ -18,7 +18,7 @@ int snac_upgrade(xs_str **error)
|
||||||
double f = 0.0;
|
double f = 0.0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *layout = xs_dict_get(srv_config, "layout");
|
const char *layout = xs_dict_get(srv_config, "layout");
|
||||||
double nf;
|
double nf;
|
||||||
|
|
||||||
f = nf = xs_number_get(layout);
|
f = nf = xs_number_get(layout);
|
||||||
|
@ -57,7 +57,7 @@ int snac_upgrade(xs_str **error)
|
||||||
g = list;
|
g = list;
|
||||||
while (xs_list_iter(&g, &fn)) {
|
while (xs_list_iter(&g, &fn)) {
|
||||||
xs *l = xs_split(fn, "/");
|
xs *l = xs_split(fn, "/");
|
||||||
char *b = xs_list_get(l, -1);
|
const char *b = xs_list_get(l, -1);
|
||||||
xs *dir = xs_fmt("%s/object/%c%c", srv_basedir, b[0], b[1]);
|
xs *dir = xs_fmt("%s/object/%c%c", srv_basedir, b[0], b[1]);
|
||||||
xs *nfn = xs_fmt("%s/%s", dir, b);
|
xs *nfn = xs_fmt("%s/%s", dir, b);
|
||||||
|
|
||||||
|
@ -152,12 +152,12 @@ int snac_upgrade(xs_str **error)
|
||||||
xs *o = xs_json_loads(s);
|
xs *o = xs_json_loads(s);
|
||||||
fclose(f);
|
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) {
|
if (!xs_is_null(type) && strcmp(type, "Follow") == 0) {
|
||||||
unlink(v);
|
unlink(v);
|
||||||
|
|
||||||
char *actor = xs_dict_get(o, "actor");
|
const char *actor = xs_dict_get(o, "actor");
|
||||||
|
|
||||||
if (!xs_is_null(actor))
|
if (!xs_is_null(actor))
|
||||||
follower_add(&snac, actor);
|
follower_add(&snac, actor);
|
||||||
|
@ -198,22 +198,29 @@ int snac_upgrade(xs_str **error)
|
||||||
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
|
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
|
||||||
o = xs_dict_del(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 */
|
/* store object */
|
||||||
object_add_ow(id, o);
|
object_add_ow(id, o);
|
||||||
|
|
||||||
/* if it's from us, add to public */
|
/* if it's from us, add to public */
|
||||||
if (xs_startswith(id, snac.actor)) {
|
if (xs_startswith(id, snac.actor)) {
|
||||||
char *p, *v;
|
const xs_list *p;
|
||||||
|
char *v;
|
||||||
|
int c;
|
||||||
|
|
||||||
object_user_cache_add(&snac, id, "public");
|
object_user_cache_add(&snac, id, "public");
|
||||||
|
|
||||||
p = xs_dict_get(meta, "announced_by");
|
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);
|
object_admire(id, v, 0);
|
||||||
|
|
||||||
p = xs_dict_get(meta, "liked_by");
|
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);
|
object_admire(id, v, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,21 +264,28 @@ int snac_upgrade(xs_str **error)
|
||||||
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
|
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
|
||||||
o = xs_dict_del(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 */
|
/* store object */
|
||||||
object_add_ow(id, o);
|
object_add_ow(id, o);
|
||||||
|
|
||||||
{
|
{
|
||||||
char *p, *v;
|
const xs_list *p;
|
||||||
|
char *v;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
object_user_cache_add(&snac, id, "private");
|
object_user_cache_add(&snac, id, "private");
|
||||||
|
|
||||||
p = xs_dict_get(meta, "announced_by");
|
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);
|
object_admire(id, v, 0);
|
||||||
|
|
||||||
p = xs_dict_get(meta, "liked_by");
|
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);
|
object_admire(id, v, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
utils.c
2
utils.c
|
@ -418,7 +418,7 @@ int deluser(snac *user)
|
||||||
void verify_links(snac *user)
|
void verify_links(snac *user)
|
||||||
/* verifies a user's links */
|
/* 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;
|
char *k, *v;
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
|
||||||
|
|
23
webfinger.c
23
webfinger.c
|
@ -16,7 +16,7 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us
|
||||||
int p_size = 0;
|
int p_size = 0;
|
||||||
xs *headers = xs_dict_new();
|
xs *headers = xs_dict_new();
|
||||||
xs *l = NULL;
|
xs *l = NULL;
|
||||||
xs_str *host = NULL;
|
const char *host = NULL;
|
||||||
xs *resource = NULL;
|
xs *resource = NULL;
|
||||||
|
|
||||||
if (xs_startswith(qs, "https:/") || xs_startswith(qs, "http:/")) {
|
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 (obj) {
|
||||||
if (user != NULL) {
|
if (user != NULL) {
|
||||||
char *subject = xs_dict_get(obj, "subject");
|
const char *subject = xs_dict_get(obj, "subject");
|
||||||
|
|
||||||
if (subject)
|
if (subject)
|
||||||
*user = xs_replace_n(subject, "acct:", "", 1);
|
*user = xs_replace_n(subject, "acct:", "", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor != NULL) {
|
if (actor != NULL) {
|
||||||
char *list = xs_dict_get(obj, "links");
|
const xs_list *list = xs_dict_get(obj, "links");
|
||||||
|
int c = 0;
|
||||||
char *v;
|
char *v;
|
||||||
|
|
||||||
while (xs_list_iter(&list, &v)) {
|
while (xs_list_next(list, &v, &c)) {
|
||||||
if (xs_type(v) == XSTYPE_DICT) {
|
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 ||
|
if (type && (strcmp(type, "application/activity+json") == 0 ||
|
||||||
strcmp(type, "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") == 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)
|
if (strcmp(q_path, "/.well-known/webfinger") != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
char *q_vars = xs_dict_get(req, "q_vars");
|
const char *q_vars = xs_dict_get(req, "q_vars");
|
||||||
char *resource = xs_dict_get(q_vars, "resource");
|
const char *resource = xs_dict_get(q_vars, "resource");
|
||||||
|
|
||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
return 400;
|
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:/")) {
|
if (xs_startswith(resource, "https:/") || xs_startswith(resource, "http:/")) {
|
||||||
/* actor search: find a user with this actor */
|
/* actor search: find a user with this actor */
|
||||||
xs *l = xs_split(resource, "/");
|
xs *l = xs_split(resource, "/");
|
||||||
char *uid = xs_list_get(l, -1);
|
const char *uid = xs_list_get(l, -1);
|
||||||
|
|
||||||
if (uid)
|
if (uid)
|
||||||
found = user_open(&snac, 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);
|
l = xs_split_n(an, "@", 1);
|
||||||
|
|
||||||
if (xs_list_len(l) == 2) {
|
if (xs_list_len(l) == 2) {
|
||||||
char *uid = xs_list_get(l, 0);
|
const char *uid = xs_list_get(l, 0);
|
||||||
char *host = xs_list_get(l, 1);
|
const char *host = xs_list_get(l, 1);
|
||||||
|
|
||||||
if (strcmp(host, xs_dict_get(srv_config, "host")) == 0)
|
if (strcmp(host, xs_dict_get(srv_config, "host")) == 0)
|
||||||
found = user_open(&snac, uid);
|
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);
|
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) {
|
if (!xs_is_null(avatar) && *avatar) {
|
||||||
xs *d = xs_dict_new();
|
xs *d = xs_dict_new();
|
||||||
|
|
||||||
|
|
110
xs.h
110
xs.h
|
@ -21,8 +21,8 @@ typedef enum {
|
||||||
XSTYPE_FALSE = 0x15, /* Boolean */
|
XSTYPE_FALSE = 0x15, /* Boolean */
|
||||||
XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */
|
XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */
|
||||||
XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */
|
XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */
|
||||||
XSTYPE_DICT = 0x1c, /* Sequence of DITEMs up to EOM (with size) */
|
XSTYPE_DICT = 0x1c, /* Sequence of KEYVALs up to EOM (with size) */
|
||||||
XSTYPE_DITEM = 0x1e, /* Element of a dict (STRING key + any type) */
|
XSTYPE_KEYVAL = 0x1e, /* key + value (STRING key + any type) */
|
||||||
XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */
|
XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */
|
||||||
XSTYPE_DATA = 0x10 /* A block of anonymous data */
|
XSTYPE_DATA = 0x10 /* A block of anonymous data */
|
||||||
} xstype;
|
} xstype;
|
||||||
|
@ -32,6 +32,7 @@ typedef enum {
|
||||||
typedef char xs_val;
|
typedef char xs_val;
|
||||||
typedef char xs_str;
|
typedef char xs_str;
|
||||||
typedef char xs_list;
|
typedef char xs_list;
|
||||||
|
typedef char xs_keyval;
|
||||||
typedef char xs_dict;
|
typedef char xs_dict;
|
||||||
typedef char xs_number;
|
typedef char xs_number;
|
||||||
typedef char xs_data;
|
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_iter(xs_list **list, xs_val **value);
|
||||||
int xs_list_next(const xs_list *list, xs_val **value, int *ctxt);
|
int xs_list_next(const xs_list *list, xs_val **value, int *ctxt);
|
||||||
int xs_list_len(const xs_list *list);
|
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_del(xs_list *list, int num);
|
||||||
xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data);
|
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);
|
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)
|
#define xs_split(str, sep) xs_split_n(str, sep, XS_ALL)
|
||||||
xs_list *xs_list_cat(xs_list *l1, const xs_list *l2);
|
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_new(void);
|
||||||
xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value);
|
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);
|
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);
|
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)
|
#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_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_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_val *xs_val_new(xstype t);
|
||||||
xs_number *xs_number_new(double f);
|
xs_number *xs_number_new(double f);
|
||||||
|
@ -244,7 +251,7 @@ xstype xs_type(const xs_val *data)
|
||||||
case XSTYPE_LIST:
|
case XSTYPE_LIST:
|
||||||
case XSTYPE_LITEM:
|
case XSTYPE_LITEM:
|
||||||
case XSTYPE_DICT:
|
case XSTYPE_DICT:
|
||||||
case XSTYPE_DITEM:
|
case XSTYPE_KEYVAL:
|
||||||
case XSTYPE_NUMBER:
|
case XSTYPE_NUMBER:
|
||||||
case XSTYPE_EOM:
|
case XSTYPE_EOM:
|
||||||
case XSTYPE_DATA:
|
case XSTYPE_DATA:
|
||||||
|
@ -262,7 +269,7 @@ xstype xs_type(const xs_val *data)
|
||||||
void _xs_put_size(xs_val *ptr, int i)
|
void _xs_put_size(xs_val *ptr, int i)
|
||||||
/* must match _XS_TYPE_SIZE */
|
/* 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;
|
break;
|
||||||
|
|
||||||
case XSTYPE_DITEM:
|
case XSTYPE_KEYVAL:
|
||||||
/* calculate the size of the key and the value */
|
/* calculate the size of the key and the value */
|
||||||
p = data + 1;
|
p = data + 1;
|
||||||
p += xs_size(p);
|
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 ||
|
if (xs_type(data) == XSTYPE_LIST ||
|
||||||
xs_type(data) == XSTYPE_DICT ||
|
xs_type(data) == XSTYPE_DICT ||
|
||||||
xs_type(data) == XSTYPE_DATA)
|
xs_type(data) == XSTYPE_DATA)
|
||||||
_xs_put_size(data + 1, sz);
|
_xs_put_size(data, sz);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -405,7 +412,7 @@ xs_val *xs_collapse(xs_val *data, int offset, int size)
|
||||||
if (xs_type(data) == XSTYPE_LIST ||
|
if (xs_type(data) == XSTYPE_LIST ||
|
||||||
xs_type(data) == XSTYPE_DICT ||
|
xs_type(data) == XSTYPE_DICT ||
|
||||||
xs_type(data) == XSTYPE_DATA)
|
xs_type(data) == XSTYPE_DATA)
|
||||||
_xs_put_size(data + 1, sz);
|
_xs_put_size(data, sz);
|
||||||
|
|
||||||
return xs_realloc(data, _xs_blk_size(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;
|
int sz = 1 + _XS_TYPE_SIZE + 1;
|
||||||
xs_list *l = xs_realloc(NULL, sz);
|
xs_list *l = xs_realloc(NULL, sz);
|
||||||
memset(l, '\0', sz);
|
memset(l, XSTYPE_EOM, sz);
|
||||||
|
|
||||||
l[0] = XSTYPE_LIST;
|
l[0] = XSTYPE_LIST;
|
||||||
_xs_put_size(&l[1], sz);
|
_xs_put_size(l, sz);
|
||||||
|
|
||||||
return l;
|
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 */
|
/* returns the element #num */
|
||||||
{
|
{
|
||||||
XS_ASSERT_TYPE(list, XSTYPE_LIST);
|
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_ASSERT_TYPE(list, XSTYPE_LIST);
|
||||||
|
|
||||||
xs_val *v;
|
const xs_val *v;
|
||||||
|
|
||||||
if ((v = xs_list_get(list, num)) != NULL)
|
if ((v = xs_list_get(list, num)) != NULL)
|
||||||
list = xs_collapse(list, v - 1 - list, xs_size(v - 1));
|
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_ASSERT_TYPE(list, XSTYPE_LIST);
|
||||||
|
|
||||||
xs_val *v;
|
const xs_val *v;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if ((v = xs_list_get(list, num)) != NULL)
|
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 **/
|
/** dicts **/
|
||||||
|
|
||||||
xs_dict *xs_dict_new(void)
|
xs_dict *xs_dict_new(void)
|
||||||
|
@ -1006,34 +1047,27 @@ xs_dict *xs_dict_new(void)
|
||||||
{
|
{
|
||||||
int sz = 1 + _XS_TYPE_SIZE + 1;
|
int sz = 1 + _XS_TYPE_SIZE + 1;
|
||||||
xs_dict *d = xs_realloc(NULL, sz);
|
xs_dict *d = xs_realloc(NULL, sz);
|
||||||
memset(d, '\0', sz);
|
memset(d, XSTYPE_EOM, sz);
|
||||||
|
|
||||||
d[0] = XSTYPE_DICT;
|
d[0] = XSTYPE_DICT;
|
||||||
_xs_put_size(&d[1], sz);
|
_xs_put_size(d, sz);
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key,
|
xs_dict *_xs_dict_write_keyval(xs_dict *dict, int offset, const xs_str *key, const xs_val *value)
|
||||||
const xs_val *data, int dsz)
|
/* adds a new keyval to the dict */
|
||||||
/* inserts a memory block into the dict */
|
|
||||||
{
|
{
|
||||||
XS_ASSERT_TYPE(dict, XSTYPE_DICT);
|
XS_ASSERT_TYPE(dict, XSTYPE_DICT);
|
||||||
XS_ASSERT_TYPE(key, XSTYPE_STRING);
|
XS_ASSERT_TYPE(key, XSTYPE_STRING);
|
||||||
|
|
||||||
if (data == NULL) {
|
if (value == NULL)
|
||||||
data = xs_stock(XSTYPE_NULL);
|
value = xs_stock(XSTYPE_NULL);
|
||||||
dsz = xs_size(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ksz = xs_size(key);
|
dict = xs_expand(dict, offset, xs_keyval_size(key, value));
|
||||||
|
|
||||||
dict = xs_expand(dict, offset, 1 + ksz + dsz);
|
xs_keyval_make(&dict[offset], key, value);
|
||||||
|
|
||||||
dict[offset] = XSTYPE_DITEM;
|
|
||||||
memcpy(&dict[offset + 1], key, ksz);
|
|
||||||
memcpy(&dict[offset + 1 + ksz], data, dsz);
|
|
||||||
|
|
||||||
return dict;
|
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)
|
xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value)
|
||||||
/* appends a memory block to the dict */
|
/* 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)
|
xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value)
|
||||||
/* prepends a memory block to the dict */
|
/* 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;
|
p += *ctxt;
|
||||||
|
|
||||||
/* an element? */
|
/* an element? */
|
||||||
if (xs_type(p) == XSTYPE_DITEM) {
|
if (xs_type(p) == XSTYPE_KEYVAL) {
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
*key = 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 */
|
/* returns the value directed by key, or the default value */
|
||||||
{
|
{
|
||||||
XS_ASSERT_TYPE(dict, XSTYPE_DICT);
|
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 **/
|
/** other values **/
|
||||||
|
|
||||||
xs_val *xs_val_new(xstype t)
|
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 = xs_realloc(NULL, _xs_blk_size(total_size));
|
||||||
v[0] = XSTYPE_DATA;
|
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);
|
memcpy(&v[1 + _XS_TYPE_SIZE], data, size);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ static size_t _header_callback(char *buffer, size_t size,
|
||||||
if (xs_str_in(l, ": ") != -1) {
|
if (xs_str_in(l, ": ") != -1) {
|
||||||
xs *knv = xs_split_n(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));
|
headers = xs_dict_set(headers, xs_list_get(knv, 0), xs_list_get(knv, 1));
|
||||||
}
|
}
|
||||||
|
|
34
xs_html.h
34
xs_html.h
|
@ -6,26 +6,26 @@
|
||||||
|
|
||||||
typedef struct xs_html xs_html;
|
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_attr(const char *key, const char *value);
|
||||||
xs_html *xs_html_text(char *content);
|
xs_html *xs_html_text(const char *content);
|
||||||
xs_html *xs_html_raw(char *content);
|
xs_html *xs_html_raw(const char *content);
|
||||||
|
|
||||||
xs_html *_xs_html_add(xs_html *tag, xs_html *var[]);
|
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 })
|
#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 })
|
#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 })
|
#define xs_html_sctag(tag, ...) _xs_html_sctag(tag, (xs_html *[]) { __VA_ARGS__, NULL })
|
||||||
|
|
||||||
xs_html *_xs_html_container(xs_html *var[]);
|
xs_html *_xs_html_container(xs_html *var[]);
|
||||||
#define xs_html_container(...) _xs_html_container((xs_html *[]) { __VA_ARGS__, NULL })
|
#define xs_html_container(...) _xs_html_container((xs_html *[]) { __VA_ARGS__, NULL })
|
||||||
|
|
||||||
void xs_html_render_f(xs_html *h, FILE *f);
|
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)
|
#define xs_html_render(tag) xs_html_render_s(tag, NULL)
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,16 +47,16 @@ struct xs_html {
|
||||||
xs_html *next;
|
xs_html *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
xs_str *xs_html_encode(char *str)
|
xs_str *xs_html_encode(const char *str)
|
||||||
/* encodes str using HTML entities */
|
/* encodes str using HTML entities */
|
||||||
{
|
{
|
||||||
xs_str *s = xs_str_new(NULL);
|
xs_str *s = xs_str_new(NULL);
|
||||||
int o = 0;
|
int o = 0;
|
||||||
char *e = str + strlen(str);
|
const char *e = str + strlen(str);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *ec = "<>\"'&"; /* characters to escape */
|
char *ec = "<>\"'&"; /* characters to escape */
|
||||||
char *q = e;
|
const char *q = e;
|
||||||
int z;
|
int z;
|
||||||
|
|
||||||
/* find the nearest happening of a char */
|
/* 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))
|
#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 */
|
/* creates an HTML block with an attribute */
|
||||||
{
|
{
|
||||||
xs_html *a = XS_HTML_NEW();
|
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 */
|
/* creates an HTML block of text, escaping it previously */
|
||||||
{
|
{
|
||||||
xs_html *a = XS_HTML_NEW();
|
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) */
|
/* creates an HTML block without escaping (for pre-formatted HTML, comments, etc) */
|
||||||
{
|
{
|
||||||
xs_html *a = XS_HTML_NEW();
|
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 */
|
/* creates a tag with a variable list of attributes and subtags */
|
||||||
{
|
{
|
||||||
xs_html *a = XS_HTML_NEW();
|
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);
|
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);
|
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 */
|
/* renders to a string */
|
||||||
{
|
{
|
||||||
xs_str *s = NULL;
|
xs_str *s = NULL;
|
||||||
|
|
|
@ -16,7 +16,7 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
|
||||||
xs *q_vars = NULL;
|
xs *q_vars = NULL;
|
||||||
xs *p_vars = NULL;
|
xs *p_vars = NULL;
|
||||||
xs *l1, *l2;
|
xs *l1, *l2;
|
||||||
char *v;
|
const char *v;
|
||||||
|
|
||||||
xs_socket_timeout(fileno(f), 2.0, 0.0);
|
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);
|
p = xs_split_n(l, ": ", 1);
|
||||||
|
|
||||||
if (xs_list_len(p) == 2)
|
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);
|
xs_socket_timeout(fileno(f), 5.0, 0.0);
|
||||||
|
|
|
@ -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 */
|
/* dumps partial data as JSON */
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
int ct = 0;
|
||||||
xs_val *v;
|
xs_val *v;
|
||||||
xs_val *data = (xs_val *)s_data;
|
|
||||||
|
|
||||||
switch (xs_type(data)) {
|
switch (xs_type(data)) {
|
||||||
case XSTYPE_NULL:
|
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:
|
case XSTYPE_LIST:
|
||||||
fputc('[', f);
|
fputc('[', f);
|
||||||
|
|
||||||
while (xs_list_iter(&data, &v)) {
|
while (xs_list_next(data, &v, &ct)) {
|
||||||
if (c != 0)
|
if (c != 0)
|
||||||
fputc(',', f);
|
fputc(',', f);
|
||||||
|
|
||||||
|
@ -117,9 +117,8 @@ static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
|
||||||
fputc('{', f);
|
fputc('{', f);
|
||||||
|
|
||||||
xs_str *k;
|
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)
|
if (c != 0)
|
||||||
fputc(',', f);
|
fputc(',', f);
|
||||||
|
|
||||||
|
|
2
xs_set.h
2
xs_set.h
|
@ -104,7 +104,7 @@ int xs_set_add(xs_set *s, const xs_val *data)
|
||||||
|
|
||||||
/* if it's new, add the data */
|
/* if it's new, add the data */
|
||||||
if (ret)
|
if (ret)
|
||||||
s->list = xs_list_append_m(s->list, data, xs_size(data));
|
s->list = xs_list_append(s->list, data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
int _xs_utf8_enc(char buf[4], unsigned int cpoint);
|
int _xs_utf8_enc(char buf[4], unsigned int cpoint);
|
||||||
int xs_is_utf8_cont_byte(char c);
|
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_unicode_width(unsigned int cpoint);
|
||||||
int xs_is_surrogate(unsigned int cpoint);
|
int xs_is_surrogate(unsigned int cpoint);
|
||||||
unsigned int xs_surrogate_dec(unsigned int p1, unsigned int p2);
|
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 */
|
/* decodes an utf-8 char inside str and updates the pointer */
|
||||||
{
|
{
|
||||||
char *p = *str;
|
const char *p = *str;
|
||||||
unsigned int cpoint = 0;
|
unsigned int cpoint = 0;
|
||||||
unsigned char c = *p++;
|
unsigned char c = *p++;
|
||||||
int cb = 0;
|
int cb = 0;
|
||||||
|
|
4
xs_url.h
4
xs_url.h
|
@ -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) {
|
while ((p = xs_memmem(payload + offset, p_size - offset, boundary, bsz)) != NULL) {
|
||||||
xs *s1 = NULL;
|
xs *s1 = NULL;
|
||||||
xs *l1 = NULL;
|
xs *l1 = NULL;
|
||||||
char *vn = NULL;
|
const char *vn = NULL;
|
||||||
char *fn = NULL;
|
const char *fn = NULL;
|
||||||
char *q;
|
char *q;
|
||||||
int po, ps;
|
int po, ps;
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
/* 6e75e8736f7f1b6ea6c6774d4bd922b3ad56b771 2024-05-15T11:42:19+02:00 */
|
/* 34850dcdec50b669a2c0bbe9f16f6d9c4b16eafd 2024-05-21T14:06:02+02:00 */
|
||||||
|
|
Loading…
Reference in a new issue