aboutsummaryrefslogtreecommitdiff
path: root/html.c
diff options
context:
space:
mode:
Diffstat (limited to 'html.c')
-rw-r--r--html.c393
1 files changed, 282 insertions, 111 deletions
diff --git a/html.c b/html.c
index 3fd1e4b..e742e94 100644
--- a/html.c
+++ b/html.c
@@ -13,6 +13,7 @@
#include "xs_html.h"
#include "xs_curl.h"
#include "xs_unicode.h"
+#include "xs_url.h"
#include "snac.h"
@@ -115,7 +116,8 @@ xs_str *actor_name(xs_dict *actor, const char *proxy)
xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
const char *udate, const char *url, int priv,
- int in_people, const char *proxy, const char *lang)
+ int in_people, const char *proxy, const char *lang,
+ const char *md5)
{
xs_html *actor_icon = xs_html_tag("p", NULL);
@@ -224,12 +226,31 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
if (xs_is_string(lang))
date_title = xs_str_cat(date_title, " (", lang, ")");
+ xs_html *date_text = xs_html_text(date_label);
+
+ if (user && md5) {
+ xs *lpost_url = xs_fmt("%s/admin/p/%s#%s_entry",
+ user->actor, md5, md5);
+ date_text = xs_html_tag("a",
+ xs_html_attr("href", lpost_url),
+ xs_html_attr("class", "snac-pubdate"),
+ date_text);
+ }
+ else if (user && url) {
+ xs *lpost_url = xs_fmt("%s/admin?q=%s",
+ user->actor, xs_url_enc(url));
+ date_text = xs_html_tag("a",
+ xs_html_attr("href", lpost_url),
+ xs_html_attr("class", "snac-pubdate"),
+ date_text);
+ }
+
xs_html_add(actor_icon,
xs_html_text(" "),
xs_html_tag("time",
xs_html_attr("class", "dt-published snac-pubdate"),
xs_html_attr("title", date_title),
- xs_html_text(date_label)));
+ date_text));
}
{
@@ -261,7 +282,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
}
-xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, const char *proxy)
+xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, const char *proxy, const char *md5)
{
xs *actor = NULL;
xs_html *actor_icon = NULL;
@@ -292,7 +313,7 @@ xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, con
else
lang = NULL;
- actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy, lang);
+ actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy, lang, md5);
}
return actor_icon;
@@ -306,7 +327,7 @@ xs_html *html_note(snac *user, const char *summary,
const xs_val *cw_yn, const char *cw_text,
const xs_val *mnt_only, const char *redir,
const char *in_reply_to, int poll,
- const char *att_file, const char *att_alt_text,
+ const xs_list *att_files, const xs_list *att_alt_texts,
int is_draft)
/* Yes, this is a FUCKTON of arguments and I'm a bit embarrased */
{
@@ -411,30 +432,71 @@ xs_html *html_note(snac *user, const char *summary,
xs_html_tag("p", NULL),
att = xs_html_tag("details",
xs_html_tag("summary",
- xs_html_text(L("Attachment..."))),
+ xs_html_text(L("Attachments..."))),
xs_html_tag("p", NULL)));
- if (att_file && *att_file)
+ int max_attachments = xs_number_get(xs_dict_get_def(srv_config, "max_attachments", "4"));
+ int att_n = 0;
+
+ /* fields for the currently existing attachments */
+ if (xs_is_list(att_files) && xs_is_list(att_alt_texts)) {
+ while (att_n < max_attachments) {
+ const char *att_file = xs_list_get(att_files, att_n);
+ const char *att_alt_text = xs_list_get(att_alt_texts, att_n);
+
+ if (!xs_is_string(att_file) || !xs_is_string(att_alt_text))
+ break;
+
+ xs *att_lbl = xs_fmt("attach_url_%d", att_n);
+ xs *alt_lbl = xs_fmt("alt_text_%d", att_n);
+
+ if (att_n)
+ xs_html_add(att,
+ xs_html_sctag("br", NULL));
+
+ xs_html_add(att,
+ xs_html_text(L("File:")),
+ xs_html_sctag("input",
+ xs_html_attr("type", "text"),
+ xs_html_attr("name", att_lbl),
+ xs_html_attr("title", L("Clear this field to delete the attachment")),
+ xs_html_attr("value", att_file)));
+
+ xs_html_add(att,
+ xs_html_text(" "),
+ xs_html_sctag("input",
+ xs_html_attr("type", "text"),
+ xs_html_attr("name", alt_lbl),
+ xs_html_attr("value", att_alt_text),
+ xs_html_attr("placeholder", L("Attachment description"))));
+
+ att_n++;
+ }
+ }
+
+ /* the rest of possible attachments */
+ while (att_n < max_attachments) {
+ xs *att_lbl = xs_fmt("attach_%d", att_n);
+ xs *alt_lbl = xs_fmt("alt_text_%d", att_n);
+
+ if (att_n)
+ xs_html_add(att,
+ xs_html_sctag("br", NULL));
+
xs_html_add(att,
- xs_html_text(L("File:")),
xs_html_sctag("input",
- xs_html_attr("type", "text"),
- xs_html_attr("name", "attach_url"),
- xs_html_attr("title", L("Clear this field to delete the attachment")),
- xs_html_attr("value", att_file)));
- else
+ xs_html_attr("type", "file"),
+ xs_html_attr("name", att_lbl)));
+
xs_html_add(att,
+ xs_html_text(" "),
xs_html_sctag("input",
- xs_html_attr("type", "file"),
- xs_html_attr("name", "attach")));
+ xs_html_attr("type", "text"),
+ xs_html_attr("name", alt_lbl),
+ xs_html_attr("placeholder", L("Attachment description"))));
- xs_html_add(att,
- xs_html_text(" "),
- xs_html_sctag("input",
- xs_html_attr("type", "text"),
- xs_html_attr("name", "alt_text"),
- xs_html_attr("value", att_alt_text),
- xs_html_attr("placeholder", L("Attachment description"))));
+ att_n++;
+ }
/* add poll controls */
if (poll) {
@@ -553,10 +615,11 @@ xs_html *html_instance_head(void)
static xs_html *html_instance_body(void)
{
- const char *host = xs_dict_get(srv_config, "host");
- const char *sdesc = xs_dict_get(srv_config, "short_description");
- const char *email = xs_dict_get(srv_config, "admin_email");
- const char *acct = xs_dict_get(srv_config, "admin_account");
+ const char *host = xs_dict_get(srv_config, "host");
+ const char *sdesc = xs_dict_get(srv_config, "short_description");
+ const char *sdescraw = xs_dict_get(srv_config, "short_description_raw");
+ const char *email = xs_dict_get(srv_config, "admin_email");
+ const char *acct = xs_dict_get(srv_config, "admin_account");
xs *blurb = xs_replace(snac_blurb, "%host%", host);
@@ -569,12 +632,21 @@ static xs_html *html_instance_body(void)
dl = xs_html_tag("dl", NULL)));
if (sdesc && *sdesc) {
- xs_html_add(dl,
- xs_html_tag("di",
- xs_html_tag("dt",
- xs_html_text(L("Site description"))),
- xs_html_tag("dd",
- xs_html_text(sdesc))));
+ if (!xs_is_null(sdescraw) && xs_type(sdescraw) == XSTYPE_TRUE) {
+ xs_html_add(dl,
+ xs_html_tag("di",
+ xs_html_tag("dt",
+ xs_html_text(L("Site description"))),
+ xs_html_tag("dd",
+ xs_html_raw(sdesc))));
+ } else {
+ xs_html_add(dl,
+ xs_html_tag("di",
+ xs_html_tag("dt",
+ xs_html_text(L("Site description"))),
+ xs_html_tag("dd",
+ xs_html_text(sdesc))));
+ }
}
if (email && *email) {
xs *mailto = xs_fmt("mailto:%s", email);
@@ -1028,7 +1100,7 @@ xs_html *html_top_controls(snac *snac)
NULL, NULL,
xs_stock(XSTYPE_FALSE), "",
xs_stock(XSTYPE_FALSE), NULL,
- NULL, 1, "", "", 0),
+ NULL, 1, NULL, NULL, 0),
/** operations **/
xs_html_tag("details",
@@ -1600,17 +1672,22 @@ xs_html *html_entry_controls(snac *snac, const char *actor,
xs *form_id = xs_fmt("%s_edit_form", md5);
xs *redir = xs_fmt("%s_entry", md5);
- const char *att_file = "";
- const char *att_alt_text = "";
+ xs *att_files = xs_list_new();
+ xs *att_alt_texts = xs_list_new();
+
const xs_list *att_list = xs_dict_get(msg, "attachment");
- /* does it have an attachment? */
- if (xs_type(att_list) == XSTYPE_LIST && xs_list_len(att_list)) {
- const xs_dict *d = xs_list_get(att_list, 0);
+ if (xs_is_list(att_list)) {
+ const xs_dict *d;
+
+ xs_list_foreach(att_list, d) {
+ const char *att_file = xs_dict_get(d, "url");
+ const char *att_alt_text = xs_dict_get(d, "name");
- if (xs_type(d) == XSTYPE_DICT) {
- att_file = xs_dict_get_def(d, "url", "");
- att_alt_text = xs_dict_get_def(d, "name", "");
+ if (xs_is_string(att_file) && xs_is_string(att_alt_text)) {
+ att_files = xs_list_append(att_files, att_file);
+ att_alt_texts = xs_list_append(att_alt_texts, att_alt_text);
+ }
}
}
@@ -1622,7 +1699,7 @@ xs_html *html_entry_controls(snac *snac, const char *actor,
id, NULL,
xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"),
xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir,
- NULL, 0, att_file, att_alt_text, is_draft(snac, id))),
+ NULL, 0, att_files, att_alt_texts, is_draft(snac, id))),
xs_html_tag("p", NULL));
}
@@ -1641,7 +1718,7 @@ xs_html *html_entry_controls(snac *snac, const char *actor,
NULL, NULL,
xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"),
xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir,
- id, 0, "", "", 0)),
+ id, 0, NULL, NULL, 0)),
xs_html_tag("p", NULL));
}
@@ -1696,7 +1773,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
xs_html_tag("div",
xs_html_attr("class", "snac-origin"),
xs_html_text(L("follows you"))),
- html_msg_icon(read_only ? NULL : user, xs_dict_get(msg, "actor"), msg, proxy)));
+ html_msg_icon(read_only ? NULL : user, xs_dict_get(msg, "actor"), msg, proxy, NULL)));
}
else
if (!xs_match(type, POSTLIKE_OBJECT_TYPE)) {
@@ -1877,7 +1954,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
}
xs_html_add(post_header,
- html_msg_icon(read_only ? NULL : user, actor, msg, proxy));
+ html_msg_icon(read_only ? NULL : user, actor, msg, proxy, md5));
/** post content **/
@@ -2022,16 +2099,17 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
const char *name = xs_dict_get(v, "name");
const xs_dict *replies = xs_dict_get(v, "replies");
- if (name && replies) {
- char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems"));
+ if (xs_is_string(name) && xs_is_dict(replies)) {
+ const char *ti = xs_number_str(xs_dict_get(replies, "totalItems"));
- xs_html_add(poll_result,
- xs_html_tag("tr",
- xs_html_tag("td",
- xs_html_text(name),
- xs_html_text(":")),
- xs_html_tag("td",
- xs_html_text(ti))));
+ if (xs_is_string(ti))
+ xs_html_add(poll_result,
+ xs_html_tag("tr",
+ xs_html_tag("td",
+ xs_html_text(name),
+ xs_html_text(":")),
+ xs_html_tag("td",
+ xs_html_text(ti))));
}
}
@@ -2629,6 +2707,29 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
xs_html_attr("title", L("Post drafts")),
xs_html_text("drafts"))));
}
+
+ /* the list of followed hashtags */
+ const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags");
+
+ if (xs_is_list(followed_hashtags) && xs_list_len(followed_hashtags)) {
+ xs_html *loht = xs_html_tag("ul",
+ xs_html_attr("class", "snac-list-of-lists"));
+ xs_html_add(body, loht);
+
+ const char *ht;
+
+ xs_list_foreach(followed_hashtags, ht) {
+ xs *url = xs_fmt("%s/admin?q=%s", user->actor, ht);
+ url = xs_replace_i(url, "#", "%23");
+
+ xs_html_add(loht,
+ xs_html_tag("li",
+ xs_html_tag("a",
+ xs_html_attr("href", url),
+ xs_html_attr("class", "snac-list-link"),
+ xs_html_text(ht))));
+ }
+ }
}
xs_html_add(body,
@@ -2648,10 +2749,32 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
xs_html_add(body,
posts);
+ int mark_shown = 0;
+
while (xs_list_iter(&p, &v)) {
xs *msg = NULL;
int status;
+ /* "already seen" mark? */
+ if (strcmp(v, MD5_ALREADY_SEEN_MARK) == 0) {
+ if (skip == 0 && !mark_shown) {
+ xs *s = xs_fmt("%s/admin", user->actor);
+
+ xs_html_add(posts,
+ xs_html_tag("div",
+ xs_html_attr("class", "snac-no-more-unseen-posts"),
+ xs_html_text(L("No more unseen posts")),
+ xs_html_text(" - "),
+ xs_html_tag("a",
+ xs_html_attr("href", s),
+ xs_html_text(L("Back to top")))));
+ }
+
+ mark_shown = 1;
+
+ continue;
+ }
+
if (utl && user && !is_pinned_by_md5(user, v))
status = timeline_get_by_md5(user, v, &msg);
else
@@ -2788,7 +2911,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t, cons
xs_html_tag("div",
xs_html_attr("class", "snac-post-header"),
html_actor_icon(snac, actor, xs_dict_get(actor, "published"),
- NULL, NULL, 0, 1, proxy, NULL)));
+ NULL, NULL, 0, 1, proxy, NULL, NULL)));
/* content (user bio) */
const char *c = xs_dict_get(actor, "summary");
@@ -2885,7 +3008,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t, cons
NULL, actor_id,
xs_stock(XSTYPE_FALSE), "",
xs_stock(XSTYPE_FALSE), NULL,
- NULL, 0, "", "", 0),
+ NULL, 0, NULL, NULL, 0),
xs_html_tag("p", NULL));
xs_html_add(snac_post, snac_controls);
@@ -2970,6 +3093,9 @@ xs_str *html_notifications(snac *user, int skip, int show)
xs_set rep;
xs_set_init(&rep);
+ /* dict to store previous notification labels */
+ xs *admiration_labels = xs_dict_new();
+
const xs_str *v;
xs_list_foreach(n_list, v) {
@@ -2983,6 +3109,7 @@ xs_str *html_notifications(snac *user, int skip, int show)
const char *utype = xs_dict_get(noti, "utype");
const char *id = xs_dict_get(noti, "objid");
const char *date = xs_dict_get(noti, "date");
+ const char *id2 = xs_dict_get_path(noti, "msg.id");
xs *wrk = NULL;
if (xs_is_null(id))
@@ -2991,12 +3118,15 @@ xs_str *html_notifications(snac *user, int skip, int show)
if (is_hidden(user, id))
continue;
+ if (xs_is_string(id2) && xs_set_add(&rep, id2) != 1)
+ continue;
+
object_get(id, &obj);
const char *msg_id = NULL;
- if (xs_is_dict(obj) && (msg_id = xs_dict_get(obj, "id")) && xs_set_add(&rep, msg_id) != 1)
- continue;
+ if (xs_is_dict(obj))
+ msg_id = xs_dict_get(obj, "id");
const char *actor_id = xs_dict_get(noti, "actor");
xs *actor = NULL;
@@ -3030,9 +3160,7 @@ xs_str *html_notifications(snac *user, int skip, int show)
xs *s_date = xs_crop_i(xs_dup(date), 0, 10);
- xs_html *entry = xs_html_tag("div",
- xs_html_attr("class", "snac-post-with-desc"),
- xs_html_tag("p",
+ xs_html *this_html_label = xs_html_container(
xs_html_tag("b",
xs_html_text(label),
xs_html_text(" by "),
@@ -3043,13 +3171,45 @@ xs_str *html_notifications(snac *user, int skip, int show)
xs_html_tag("time",
xs_html_attr("class", "dt-published snac-pubdate"),
xs_html_attr("title", date),
- xs_html_text(s_date))));
+ xs_html_text(s_date)));
+
+ xs_html *html_label = NULL;
+
+ if (xs_is_string(msg_id)) {
+ const xs_val *prev_label = xs_dict_get(admiration_labels, msg_id);
+
+ if (xs_type(prev_label) == XSTYPE_DATA) {
+ /* there is a previous list of admiration labels! */
+ xs_data_get(&html_label, prev_label);
+
+ xs_html_add(html_label,
+ xs_html_sctag("br", NULL),
+ this_html_label);
+
+ continue;
+ }
+ }
+
+ xs_html *entry = NULL;
+
+ html_label = xs_html_tag("p",
+ this_html_label);
+
+ /* store in the admiration labels dict */
+ xs *pl = xs_data_new(&html_label, sizeof(html_label));
+
+ if (xs_is_string(msg_id))
+ admiration_labels = xs_dict_set(admiration_labels, msg_id, pl);
+
+ entry = xs_html_tag("div",
+ xs_html_attr("class", "snac-post-with-desc"),
+ html_label);
if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0 || strcmp(type, "Block") == 0) {
xs_html_add(entry,
xs_html_tag("div",
xs_html_attr("class", "snac-post"),
- html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy, NULL)));
+ html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy, NULL, NULL)));
}
else
if (strcmp(type, "Move") == 0) {
@@ -3063,18 +3223,23 @@ xs_str *html_notifications(snac *user, int skip, int show)
xs_html_add(entry,
xs_html_tag("div",
xs_html_attr("class", "snac-post"),
- html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy, NULL)));
+ html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy, NULL, NULL)));
}
}
}
else
if (obj != NULL) {
xs *md5 = xs_md5_hex(id, strlen(id));
+ xs *ctxt = xs_fmt("%s/admin/p/%s#%s_entry", user->actor, md5, md5);
xs_html *h = html_entry(user, obj, 0, 0, md5, 1);
if (h != NULL) {
xs_html_add(entry,
+ xs_html_tag("p",
+ xs_html_tag("a",
+ xs_html_attr("href", ctxt),
+ xs_html_text(L("Context")))),
h);
}
}
@@ -3111,8 +3276,6 @@ xs_str *html_notifications(snac *user, int skip, int show)
}
}
- xs_set_free(&rep);
-
if (noti_new == NULL && noti_seen == NULL)
xs_html_add(body,
xs_html_tag("h2",
@@ -3132,6 +3295,8 @@ xs_str *html_notifications(snac *user, int skip, int show)
xs_html_text(L("More...")))));
}
+ xs_set_free(&rep);
+
xs_html_add(body,
html_footer());
@@ -3232,7 +3397,8 @@ int html_get_handler(const xs_dict *req, const char *q_path,
cache = 0;
int skip = 0;
- int def_show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries"));
+ int def_show = xs_number_get(xs_dict_get_def(srv_config, "def_timeline_entries",
+ xs_dict_get_def(srv_config, "max_timeline_entries", "50")));
int show = def_show;
if ((v = xs_dict_get(q_vars, "skip")) != NULL)
@@ -3277,21 +3443,17 @@ int html_get_handler(const xs_dict *req, const char *q_path,
}
else {
xs *list = NULL;
- xs *next = NULL;
+ int more = 0;
- if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines"))) {
- list = timeline_simple_list(&snac, "public", skip, show);
- next = timeline_simple_list(&snac, "public", skip + show, 1);
- }
- else {
- list = timeline_list(&snac, "public", skip, show);
- next = timeline_list(&snac, "public", skip + show, 1);
- }
+ if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines")))
+ list = timeline_simple_list(&snac, "public", skip, show, &more);
+ else
+ list = timeline_list(&snac, "public", skip, show, &more);
xs *pins = pinned_list(&snac);
pins = xs_list_cat(pins, list);
- *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1, error);
+ *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error);
*b_size = strlen(*body);
status = HTTP_STATUS_OK;
@@ -3440,6 +3602,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
}
}
else {
+ /** the private timeline **/
double t = history_mtime(&snac, "timeline.html_");
/* if enabled by admin, return a cached page if its timestamp is:
@@ -3453,19 +3616,22 @@ int html_get_handler(const xs_dict *req, const char *q_path,
xs_dict_get(req, "if-none-match"), etag);
}
else {
+ int more = 0;
+
snac_debug(&snac, 1, xs_fmt("building timeline"));
- xs *list = timeline_list(&snac, "private", skip, show);
- xs *next = timeline_list(&snac, "private", skip + show, 1);
+ xs *list = timeline_list(&snac, "private", skip, show, &more);
*body = html_timeline(&snac, list, 0, skip, show,
- xs_list_len(next), NULL, "/admin", 1, error);
+ more, NULL, "/admin", 1, error);
*b_size = strlen(*body);
status = HTTP_STATUS_OK;
if (save)
history_add(&snac, "timeline.html_", *body, *b_size, etag);
+
+ timeline_add_mark(&snac);
}
}
}
@@ -3481,7 +3647,8 @@ int html_get_handler(const xs_dict *req, const char *q_path,
const char *md5 = xs_list_get(l, -1);
if (md5 && *md5 && timeline_here(&snac, md5)) {
- xs *list = xs_list_append(xs_list_new(), md5);
+ xs *list0 = xs_list_append(xs_list_new(), md5);
+ xs *list = timeline_top_level(&snac, list0);
*body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1, error);
*b_size = strlen(*body);
@@ -3665,7 +3832,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
int cnt = xs_number_get(xs_dict_get_def(srv_config, "max_public_entries", "20"));
- xs *elems = timeline_simple_list(&snac, "public", 0, cnt);
+ xs *elems = timeline_simple_list(&snac, "public", 0, cnt, NULL);
xs *bio = xs_dup(xs_dict_get(snac.config, "bio"));
xs *rss_title = xs_fmt("%s (@%s@%s)",
@@ -3869,52 +4036,56 @@ int html_post_handler(const xs_dict *req, const char *q_path,
/* post note */
const xs_str *content = xs_dict_get(p_vars, "content");
const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to");
- const xs_str *attach_url = xs_dict_get(p_vars, "attach_url");
- const xs_list *attach_file = xs_dict_get(p_vars, "attach");
const xs_str *to = xs_dict_get(p_vars, "to");
const xs_str *sensitive = xs_dict_get(p_vars, "sensitive");
const xs_str *summary = xs_dict_get(p_vars, "summary");
const xs_str *edit_id = xs_dict_get(p_vars, "edit_id");
- const xs_str *alt_text = xs_dict_get(p_vars, "alt_text");
int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only"));
int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft"));
xs *attach_list = xs_list_new();
- /* default alt text */
- if (xs_is_null(alt_text))
- alt_text = "";
+ /* iterate the attachments */
+ int max_attachments = xs_number_get(xs_dict_get_def(srv_config, "max_attachments", "4"));
- /* is attach_url set? */
- if (!xs_is_null(attach_url) && *attach_url != '\0') {
- xs *l = xs_list_new();
+ for (int att_n = 0; att_n < max_attachments; att_n++) {
+ xs *url_lbl = xs_fmt("attach_url_%d", att_n);
+ xs *att_lbl = xs_fmt("attach_%d", att_n);
+ xs *alt_lbl = xs_fmt("alt_text_%d", att_n);
- l = xs_list_append(l, attach_url);
- l = xs_list_append(l, alt_text);
+ const char *attach_url = xs_dict_get(p_vars, url_lbl);
+ const xs_list *attach_file = xs_dict_get(p_vars, att_lbl);
+ const char *alt_text = xs_dict_get_def(p_vars, alt_lbl, "");
- attach_list = xs_list_append(attach_list, l);
- }
+ if (xs_is_string(attach_url) && *attach_url != '\0') {
+ xs *l = xs_list_new();
- /* is attach_file set? */
- if (!xs_is_null(attach_file) && xs_type(attach_file) == XSTYPE_LIST) {
- const char *fn = xs_list_get(attach_file, 0);
+ l = xs_list_append(l, attach_url);
+ l = xs_list_append(l, alt_text);
- if (*fn != '\0') {
- char *ext = strrchr(fn, '.');
- xs *hash = xs_md5_hex(fn, strlen(fn));
- xs *id = xs_fmt("%s%s", hash, ext);
- xs *url = xs_fmt("%s/s/%s", snac.actor, id);
- int fo = xs_number_get(xs_list_get(attach_file, 1));
- int fs = xs_number_get(xs_list_get(attach_file, 2));
+ attach_list = xs_list_append(attach_list, l);
+ }
+ else
+ if (xs_is_list(attach_file)) {
+ const char *fn = xs_list_get(attach_file, 0);
- /* store */
- static_put(&snac, id, payload + fo, fs);
+ if (xs_is_string(fn) && *fn != '\0') {
+ char *ext = strrchr(fn, '.');
+ xs *hash = xs_md5_hex(fn, strlen(fn));
+ xs *id = xs_fmt("%s%s", hash, ext);
+ xs *url = xs_fmt("%s/s/%s", snac.actor, id);
+ int fo = xs_number_get(xs_list_get(attach_file, 1));
+ int fs = xs_number_get(xs_list_get(attach_file, 2));
- xs *l = xs_list_new();
+ /* store */
+ static_put(&snac, id, payload + fo, fs);
- l = xs_list_append(l, url);
- l = xs_list_append(l, alt_text);
+ xs *l = xs_list_new();
- attach_list = xs_list_append(attach_list, l);
+ l = xs_list_append(l, url);
+ l = xs_list_append(l, alt_text);
+
+ attach_list = xs_list_append(attach_list, l);
+ }
}
}