diff options
Diffstat (limited to 'html.c')
| -rw-r--r-- | html.c | 217 |
1 files changed, 195 insertions, 22 deletions
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "xs_curl.h" | 14 | #include "xs_curl.h" |
| 15 | #include "xs_unicode.h" | 15 | #include "xs_unicode.h" |
| 16 | #include "xs_url.h" | 16 | #include "xs_url.h" |
| 17 | #include "xs_random.h" | ||
| 17 | 18 | ||
| 18 | #include "snac.h" | 19 | #include "snac.h" |
| 19 | 20 | ||
| @@ -72,6 +73,9 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p | |||
| 72 | const xs_dict *v; | 73 | const xs_dict *v; |
| 73 | int c = 0; | 74 | int c = 0; |
| 74 | 75 | ||
| 76 | xs_set rep_emoji; | ||
| 77 | xs_set_init(&rep_emoji); | ||
| 78 | |||
| 75 | while (xs_list_next(tag_list, &v, &c)) { | 79 | while (xs_list_next(tag_list, &v, &c)) { |
| 76 | const char *t = xs_dict_get(v, "type"); | 80 | const char *t = xs_dict_get(v, "type"); |
| 77 | 81 | ||
| @@ -79,6 +83,10 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p | |||
| 79 | const char *n = xs_dict_get(v, "name"); | 83 | const char *n = xs_dict_get(v, "name"); |
| 80 | const xs_dict *i = xs_dict_get(v, "icon"); | 84 | const xs_dict *i = xs_dict_get(v, "icon"); |
| 81 | 85 | ||
| 86 | /* avoid repeated emojis (Misskey seems to return this) */ | ||
| 87 | if (xs_set_add(&rep_emoji, n) == 0) | ||
| 88 | continue; | ||
| 89 | |||
| 82 | if (xs_is_string(n) && xs_is_dict(i)) { | 90 | if (xs_is_string(n) && xs_is_dict(i)) { |
| 83 | const char *u = xs_dict_get(i, "url"); | 91 | const char *u = xs_dict_get(i, "url"); |
| 84 | const char *mt = xs_dict_get(i, "mediaType"); | 92 | const char *mt = xs_dict_get(i, "mediaType"); |
| @@ -93,6 +101,8 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p | |||
| 93 | xs_html_attr("loading", "lazy"), | 101 | xs_html_attr("loading", "lazy"), |
| 94 | xs_html_attr("src", url), | 102 | xs_html_attr("src", url), |
| 95 | xs_html_attr("alt", n), | 103 | xs_html_attr("alt", n), |
| 104 | xs_html_attr("title", n), | ||
| 105 | xs_html_attr("class", "snac-emoji"), | ||
| 96 | xs_html_attr("style", style)); | 106 | xs_html_attr("style", style)); |
| 97 | 107 | ||
| 98 | xs *s1 = xs_html_render(img); | 108 | xs *s1 = xs_html_render(img); |
| @@ -104,6 +114,8 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p | |||
| 104 | } | 114 | } |
| 105 | } | 115 | } |
| 106 | } | 116 | } |
| 117 | |||
| 118 | xs_set_free(&rep_emoji); | ||
| 107 | } | 119 | } |
| 108 | 120 | ||
| 109 | return s; | 121 | return s; |
| @@ -339,7 +351,7 @@ xs_html *html_note(snac *user, const char *summary, | |||
| 339 | const xs_val *mnt_only, const char *redir, | 351 | const xs_val *mnt_only, const char *redir, |
| 340 | const char *in_reply_to, int poll, | 352 | const char *in_reply_to, int poll, |
| 341 | const xs_list *att_files, const xs_list *att_alt_texts, | 353 | const xs_list *att_files, const xs_list *att_alt_texts, |
| 342 | int is_draft) | 354 | int is_draft, const char *published) |
| 343 | /* Yes, this is a FUCKTON of arguments and I'm a bit embarrased */ | 355 | /* Yes, this is a FUCKTON of arguments and I'm a bit embarrased */ |
| 344 | { | 356 | { |
| 345 | xs *action = xs_fmt("%s/admin/note", user->actor); | 357 | xs *action = xs_fmt("%s/admin/note", user->actor); |
| @@ -429,6 +441,42 @@ xs_html *html_note(snac *user, const char *summary, | |||
| 429 | xs_html_attr("name", "is_draft"), | 441 | xs_html_attr("name", "is_draft"), |
| 430 | xs_html_attr(is_draft ? "checked" : "", NULL)))); | 442 | xs_html_attr(is_draft ? "checked" : "", NULL)))); |
| 431 | 443 | ||
| 444 | /* post date and time */ | ||
| 445 | xs *post_date = NULL; | ||
| 446 | xs *post_time = NULL; | ||
| 447 | |||
| 448 | if (xs_is_string(published)) { | ||
| 449 | time_t t = xs_parse_iso_date(published, 0); | ||
| 450 | |||
| 451 | if (t > 0) { | ||
| 452 | post_date = xs_str_time(t, "%Y-%m-%d", 1); | ||
| 453 | post_time = xs_str_time(t, "%H:%M:%S", 1); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | if (edit_id == NULL || is_draft || is_scheduled(user, edit_id)) { | ||
| 458 | xs *pdat = xs_fmt(L("Post date and time (timezone: %s):"), user->tz); | ||
| 459 | |||
| 460 | xs_html_add(form, | ||
| 461 | xs_html_tag("p", | ||
| 462 | xs_html_tag("details", | ||
| 463 | xs_html_tag("summary", | ||
| 464 | xs_html_text(L("Scheduled post..."))), | ||
| 465 | xs_html_tag("p", | ||
| 466 | xs_html_text(pdat), | ||
| 467 | xs_html_sctag("br", NULL), | ||
| 468 | xs_html_sctag("input", | ||
| 469 | xs_html_attr("type", "date"), | ||
| 470 | xs_html_attr("value", post_date ? post_date : ""), | ||
| 471 | xs_html_attr("name", "post_date")), | ||
| 472 | xs_html_text(" "), | ||
| 473 | xs_html_sctag("input", | ||
| 474 | xs_html_attr("type", "time"), | ||
| 475 | xs_html_attr("value", post_time ? post_time : ""), | ||
| 476 | xs_html_attr("step", "1"), | ||
| 477 | xs_html_attr("name", "post_time")))))); | ||
| 478 | } | ||
| 479 | |||
| 432 | if (edit_id) | 480 | if (edit_id) |
| 433 | xs_html_add(form, | 481 | xs_html_add(form, |
| 434 | xs_html_sctag("input", | 482 | xs_html_sctag("input", |
| @@ -1116,7 +1164,7 @@ xs_html *html_top_controls(snac *user) | |||
| 1116 | NULL, NULL, | 1164 | NULL, NULL, |
| 1117 | xs_stock(XSTYPE_FALSE), "", | 1165 | xs_stock(XSTYPE_FALSE), "", |
| 1118 | xs_stock(XSTYPE_FALSE), NULL, | 1166 | xs_stock(XSTYPE_FALSE), NULL, |
| 1119 | NULL, 1, NULL, NULL, 0), | 1167 | NULL, 1, NULL, NULL, 0, NULL), |
| 1120 | 1168 | ||
| 1121 | /** operations **/ | 1169 | /** operations **/ |
| 1122 | xs_html_tag("details", | 1170 | xs_html_tag("details", |
| @@ -1270,6 +1318,27 @@ xs_html *html_top_controls(snac *user) | |||
| 1270 | xs_html_attr("value", lang))); | 1318 | xs_html_attr("value", lang))); |
| 1271 | } | 1319 | } |
| 1272 | 1320 | ||
| 1321 | /* timezone */ | ||
| 1322 | xs_html *tz_select = xs_html_tag("select", | ||
| 1323 | xs_html_attr("name", "tz")); | ||
| 1324 | |||
| 1325 | xs *tzs = xs_tz_list(); | ||
| 1326 | const char *tz; | ||
| 1327 | |||
| 1328 | xs_list_foreach(tzs, tz) { | ||
| 1329 | if (strcmp(tz, user->tz) == 0) | ||
| 1330 | xs_html_add(tz_select, | ||
| 1331 | xs_html_tag("option", | ||
| 1332 | xs_html_text(tz), | ||
| 1333 | xs_html_attr("value", tz), | ||
| 1334 | xs_html_attr("selected", "selected"))); | ||
| 1335 | else | ||
| 1336 | xs_html_add(tz_select, | ||
| 1337 | xs_html_tag("option", | ||
| 1338 | xs_html_text(tz), | ||
| 1339 | xs_html_attr("value", tz))); | ||
| 1340 | } | ||
| 1341 | |||
| 1273 | xs *user_setup_action = xs_fmt("%s/admin/user-setup", user->actor); | 1342 | xs *user_setup_action = xs_fmt("%s/admin/user-setup", user->actor); |
| 1274 | 1343 | ||
| 1275 | xs_html_add(top_controls, | 1344 | xs_html_add(top_controls, |
| @@ -1466,6 +1535,11 @@ xs_html *html_top_controls(snac *user) | |||
| 1466 | lang_select), | 1535 | lang_select), |
| 1467 | 1536 | ||
| 1468 | xs_html_tag("p", | 1537 | xs_html_tag("p", |
| 1538 | xs_html_text(L("Time zone:")), | ||
| 1539 | xs_html_sctag("br", NULL), | ||
| 1540 | tz_select), | ||
| 1541 | |||
| 1542 | xs_html_tag("p", | ||
| 1469 | xs_html_text(L("New password:")), | 1543 | xs_html_text(L("New password:")), |
| 1470 | xs_html_sctag("br", NULL), | 1544 | xs_html_sctag("br", NULL), |
| 1471 | xs_html_sctag("input", | 1545 | xs_html_sctag("input", |
| @@ -1774,7 +1848,8 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1774 | id, NULL, | 1848 | id, NULL, |
| 1775 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 1849 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1776 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 1850 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, |
| 1777 | NULL, 0, att_files, att_alt_texts, is_draft(user, id))), | 1851 | NULL, 0, att_files, att_alt_texts, is_draft(user, id), |
| 1852 | xs_dict_get(msg, "published"))), | ||
| 1778 | xs_html_tag("p", NULL)); | 1853 | xs_html_tag("p", NULL)); |
| 1779 | } | 1854 | } |
| 1780 | 1855 | ||
| @@ -1793,7 +1868,7 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1793 | NULL, NULL, | 1868 | NULL, NULL, |
| 1794 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 1869 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1795 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 1870 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, |
| 1796 | id, 0, NULL, NULL, 0)), | 1871 | id, 0, NULL, NULL, 0, NULL)), |
| 1797 | xs_html_tag("p", NULL)); | 1872 | xs_html_tag("p", NULL)); |
| 1798 | } | 1873 | } |
| 1799 | 1874 | ||
| @@ -2396,13 +2471,19 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 2396 | name = NULL; | 2471 | name = NULL; |
| 2397 | } | 2472 | } |
| 2398 | else { | 2473 | else { |
| 2474 | xs *d_href = xs_dup(o_href); | ||
| 2475 | if (strlen(d_href) > 64) { | ||
| 2476 | d_href[64] = '\0'; | ||
| 2477 | d_href = xs_str_cat(d_href, "..."); | ||
| 2478 | } | ||
| 2479 | |||
| 2399 | xs_html_add(content_attachments, | 2480 | xs_html_add(content_attachments, |
| 2400 | xs_html_tag("p", | 2481 | xs_html_tag("p", |
| 2401 | xs_html_tag("a", | 2482 | xs_html_tag("a", |
| 2402 | xs_html_attr("href", o_href), | 2483 | xs_html_attr("href", o_href), |
| 2403 | xs_html_text(L("Attachment")), | 2484 | xs_html_text(L("Attachment")), |
| 2404 | xs_html_text(": "), | 2485 | xs_html_text(": "), |
| 2405 | xs_html_text(o_href)))); | 2486 | xs_html_text(d_href)))); |
| 2406 | 2487 | ||
| 2407 | /* do not generate an Alt... */ | 2488 | /* do not generate an Alt... */ |
| 2408 | name = NULL; | 2489 | name = NULL; |
| @@ -2689,6 +2770,11 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 2689 | } | 2770 | } |
| 2690 | } | 2771 | } |
| 2691 | 2772 | ||
| 2773 | /* add an invisible hr, to help differentiate between posts in text browsers */ | ||
| 2774 | xs_html_add(entry_top, | ||
| 2775 | xs_html_sctag("hr", | ||
| 2776 | xs_html_attr("hidden", NULL))); | ||
| 2777 | |||
| 2692 | return entry_top; | 2778 | return entry_top; |
| 2693 | } | 2779 | } |
| 2694 | 2780 | ||
| @@ -2830,6 +2916,18 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 2830 | xs_html_text(L("drafts"))))); | 2916 | xs_html_text(L("drafts"))))); |
| 2831 | } | 2917 | } |
| 2832 | 2918 | ||
| 2919 | { | ||
| 2920 | /* show the list of scheduled posts */ | ||
| 2921 | xs *url = xs_fmt("%s/sched", user->actor); | ||
| 2922 | xs_html_add(lol, | ||
| 2923 | xs_html_tag("li", | ||
| 2924 | xs_html_tag("a", | ||
| 2925 | xs_html_attr("href", url), | ||
| 2926 | xs_html_attr("class", "snac-list-link"), | ||
| 2927 | xs_html_attr("title", L("Scheduled posts")), | ||
| 2928 | xs_html_text(L("scheduled posts"))))); | ||
| 2929 | } | ||
| 2930 | |||
| 2833 | /* the list of followed hashtags */ | 2931 | /* the list of followed hashtags */ |
| 2834 | const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags"); | 2932 | const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags"); |
| 2835 | 2933 | ||
| @@ -3130,7 +3228,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c | |||
| 3130 | NULL, actor_id, | 3228 | NULL, actor_id, |
| 3131 | xs_stock(XSTYPE_FALSE), "", | 3229 | xs_stock(XSTYPE_FALSE), "", |
| 3132 | xs_stock(XSTYPE_FALSE), NULL, | 3230 | xs_stock(XSTYPE_FALSE), NULL, |
| 3133 | NULL, 0, NULL, NULL, 0), | 3231 | NULL, 0, NULL, NULL, 0, NULL), |
| 3134 | xs_html_tag("p", NULL)); | 3232 | xs_html_tag("p", NULL)); |
| 3135 | 3233 | ||
| 3136 | xs_html_add(snac_post, snac_controls); | 3234 | xs_html_add(snac_post, snac_controls); |
| @@ -3879,6 +3977,21 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 3879 | } | 3977 | } |
| 3880 | } | 3978 | } |
| 3881 | else | 3979 | else |
| 3980 | if (strcmp(p_path, "sched") == 0) { /** list of scheduled posts **/ | ||
| 3981 | if (!login(&snac, req)) { | ||
| 3982 | *body = xs_dup(uid); | ||
| 3983 | status = HTTP_STATUS_UNAUTHORIZED; | ||
| 3984 | } | ||
| 3985 | else { | ||
| 3986 | xs *list = scheduled_list(&snac); | ||
| 3987 | |||
| 3988 | *body = html_timeline(&snac, list, 0, skip, show, | ||
| 3989 | 0, L("Scheduled posts"), "", 0, error); | ||
| 3990 | *b_size = strlen(*body); | ||
| 3991 | status = HTTP_STATUS_OK; | ||
| 3992 | } | ||
| 3993 | } | ||
| 3994 | else | ||
| 3882 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ | 3995 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ |
| 3883 | if (!login(&snac, req)) { | 3996 | if (!login(&snac, req)) { |
| 3884 | *body = xs_dup(uid); | 3997 | *body = xs_dup(uid); |
| @@ -4175,12 +4288,14 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4175 | snac_debug(&snac, 1, xs_fmt("web action '%s' received", p_path)); | 4288 | snac_debug(&snac, 1, xs_fmt("web action '%s' received", p_path)); |
| 4176 | 4289 | ||
| 4177 | /* post note */ | 4290 | /* post note */ |
| 4178 | const xs_str *content = xs_dict_get(p_vars, "content"); | 4291 | const char *content = xs_dict_get(p_vars, "content"); |
| 4179 | const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); | 4292 | const char *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); |
| 4180 | const xs_str *to = xs_dict_get(p_vars, "to"); | 4293 | const char *to = xs_dict_get(p_vars, "to"); |
| 4181 | const xs_str *sensitive = xs_dict_get(p_vars, "sensitive"); | 4294 | const char *sensitive = xs_dict_get(p_vars, "sensitive"); |
| 4182 | const xs_str *summary = xs_dict_get(p_vars, "summary"); | 4295 | const char *summary = xs_dict_get(p_vars, "summary"); |
| 4183 | const xs_str *edit_id = xs_dict_get(p_vars, "edit_id"); | 4296 | const char *edit_id = xs_dict_get(p_vars, "edit_id"); |
| 4297 | const char *post_date = xs_dict_get_def(p_vars, "post_date", ""); | ||
| 4298 | const char *post_time = xs_dict_get_def(p_vars, "post_time", ""); | ||
| 4184 | int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); | 4299 | int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); |
| 4185 | int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); | 4300 | int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); |
| 4186 | xs *attach_list = xs_list_new(); | 4301 | xs *attach_list = xs_list_new(); |
| @@ -4210,9 +4325,12 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4210 | const char *fn = xs_list_get(attach_file, 0); | 4325 | const char *fn = xs_list_get(attach_file, 0); |
| 4211 | 4326 | ||
| 4212 | if (xs_is_string(fn) && *fn != '\0') { | 4327 | if (xs_is_string(fn) && *fn != '\0') { |
| 4213 | char *ext = strrchr(fn, '.'); | 4328 | char rnd[32]; |
| 4214 | xs *hash = xs_md5_hex(fn, strlen(fn)); | 4329 | xs_rnd_buf(rnd, sizeof(rnd)); |
| 4215 | xs *id = xs_fmt("%s%s", hash, ext); | 4330 | |
| 4331 | const char *ext = strrchr(fn, '.'); | ||
| 4332 | xs *hash = xs_md5_hex(rnd, strlen(rnd)); | ||
| 4333 | xs *id = xs_fmt("post-%s%s", hash, ext ? ext : ""); | ||
| 4216 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); | 4334 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); |
| 4217 | int fo = xs_number_get(xs_list_get(attach_file, 1)); | 4335 | int fo = xs_number_get(xs_list_get(attach_file, 1)); |
| 4218 | int fs = xs_number_get(xs_list_get(attach_file, 2)); | 4336 | int fs = xs_number_get(xs_list_get(attach_file, 2)); |
| @@ -4268,6 +4386,31 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4268 | msg = xs_dict_set(msg, "summary", xs_is_null(summary) ? "..." : summary); | 4386 | msg = xs_dict_set(msg, "summary", xs_is_null(summary) ? "..." : summary); |
| 4269 | } | 4387 | } |
| 4270 | 4388 | ||
| 4389 | if (xs_is_string(post_date) && *post_date) { | ||
| 4390 | xs *post_pubdate = xs_fmt("%sT%s", post_date, | ||
| 4391 | xs_is_string(post_time) && *post_time ? post_time : "00:00:00"); | ||
| 4392 | |||
| 4393 | time_t t = xs_parse_iso_date(post_pubdate, 0); | ||
| 4394 | |||
| 4395 | if (t != 0) { | ||
| 4396 | t -= xs_tz_offset(snac.tz); | ||
| 4397 | |||
| 4398 | xs *iso_date = xs_str_iso_date(t); | ||
| 4399 | msg = xs_dict_set(msg, "published", iso_date); | ||
| 4400 | |||
| 4401 | snac_debug(&snac, 1, xs_fmt("Published date: [%s]", iso_date)); | ||
| 4402 | } | ||
| 4403 | else | ||
| 4404 | snac_log(&snac, xs_fmt("Invalid post date: [%s]", post_pubdate)); | ||
| 4405 | } | ||
| 4406 | |||
| 4407 | /* is the published date from the future? */ | ||
| 4408 | int future_post = 0; | ||
| 4409 | xs *right_now = xs_str_utctime(0, ISO_DATE_SPEC); | ||
| 4410 | |||
| 4411 | if (strcmp(xs_dict_get(msg, "published"), right_now) > 0) | ||
| 4412 | future_post = 1; | ||
| 4413 | |||
| 4271 | if (xs_is_null(edit_id)) { | 4414 | if (xs_is_null(edit_id)) { |
| 4272 | /* new message */ | 4415 | /* new message */ |
| 4273 | const char *id = xs_dict_get(msg, "id"); | 4416 | const char *id = xs_dict_get(msg, "id"); |
| @@ -4275,6 +4418,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4275 | if (store_as_draft) { | 4418 | if (store_as_draft) { |
| 4276 | draft_add(&snac, id, msg); | 4419 | draft_add(&snac, id, msg); |
| 4277 | } | 4420 | } |
| 4421 | else | ||
| 4422 | if (future_post) { | ||
| 4423 | schedule_add(&snac, id, msg); | ||
| 4424 | } | ||
| 4278 | else { | 4425 | else { |
| 4279 | c_msg = msg_create(&snac, msg); | 4426 | c_msg = msg_create(&snac, msg); |
| 4280 | timeline_add(&snac, id, msg); | 4427 | timeline_add(&snac, id, msg); |
| @@ -4286,7 +4433,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4286 | 4433 | ||
| 4287 | if (valid_status(object_get(edit_id, &p_msg))) { | 4434 | if (valid_status(object_get(edit_id, &p_msg))) { |
| 4288 | /* copy relevant fields from previous version */ | 4435 | /* copy relevant fields from previous version */ |
| 4289 | char *fields[] = { "id", "context", "url", "published", | 4436 | char *fields[] = { "id", "context", "url", |
| 4290 | "to", "inReplyTo", NULL }; | 4437 | "to", "inReplyTo", NULL }; |
| 4291 | int n; | 4438 | int n; |
| 4292 | 4439 | ||
| @@ -4302,18 +4449,34 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4302 | if (is_draft(&snac, edit_id)) { | 4449 | if (is_draft(&snac, edit_id)) { |
| 4303 | /* message was previously a draft; it's a create activity */ | 4450 | /* message was previously a draft; it's a create activity */ |
| 4304 | 4451 | ||
| 4305 | /* set the published field to now */ | 4452 | /* if the date is from the past, overwrite it with right_now */ |
| 4306 | xs *published = xs_str_utctime(0, ISO_DATE_SPEC); | 4453 | if (strcmp(xs_dict_get(msg, "published"), right_now) < 0) { |
| 4307 | msg = xs_dict_set(msg, "published", published); | 4454 | snac_debug(&snac, 1, xs_fmt("setting draft ancient date to %s", right_now)); |
| 4455 | msg = xs_dict_set(msg, "published", right_now); | ||
| 4456 | } | ||
| 4308 | 4457 | ||
| 4309 | /* overwrite object */ | 4458 | /* overwrite object */ |
| 4310 | object_add_ow(edit_id, msg); | 4459 | object_add_ow(edit_id, msg); |
| 4311 | 4460 | ||
| 4312 | c_msg = msg_create(&snac, msg); | 4461 | if (future_post) { |
| 4313 | timeline_add(&snac, edit_id, msg); | 4462 | schedule_add(&snac, edit_id, msg); |
| 4463 | } | ||
| 4464 | else { | ||
| 4465 | c_msg = msg_create(&snac, msg); | ||
| 4466 | timeline_add(&snac, edit_id, msg); | ||
| 4467 | } | ||
| 4468 | |||
| 4314 | draft_del(&snac, edit_id); | 4469 | draft_del(&snac, edit_id); |
| 4315 | } | 4470 | } |
| 4471 | else | ||
| 4472 | if (is_scheduled(&snac, edit_id)) { | ||
| 4473 | /* editing an scheduled post; just update it */ | ||
| 4474 | schedule_add(&snac, edit_id, msg); | ||
| 4475 | } | ||
| 4316 | else { | 4476 | else { |
| 4477 | /* ignore the (possibly changed) published date */ | ||
| 4478 | msg = xs_dict_set(msg, "published", xs_dict_get(p_msg, "published")); | ||
| 4479 | |||
| 4317 | /* set the updated field */ | 4480 | /* set the updated field */ |
| 4318 | xs *updated = xs_str_utctime(0, ISO_DATE_SPEC); | 4481 | xs *updated = xs_str_utctime(0, ISO_DATE_SPEC); |
| 4319 | msg = xs_dict_set(msg, "updated", updated); | 4482 | msg = xs_dict_set(msg, "updated", updated); |
| @@ -4398,6 +4561,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4398 | if (is_draft(&snac, id)) | 4561 | if (is_draft(&snac, id)) |
| 4399 | draft_del(&snac, id); | 4562 | draft_del(&snac, id); |
| 4400 | else | 4563 | else |
| 4564 | if (is_scheduled(&snac, id)) | ||
| 4565 | schedule_del(&snac, id); | ||
| 4566 | else | ||
| 4401 | hide(&snac, id); | 4567 | hide(&snac, id); |
| 4402 | } | 4568 | } |
| 4403 | else | 4569 | else |
| @@ -4493,6 +4659,8 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4493 | 4659 | ||
| 4494 | draft_del(&snac, id); | 4660 | draft_del(&snac, id); |
| 4495 | 4661 | ||
| 4662 | schedule_del(&snac, id); | ||
| 4663 | |||
| 4496 | snac_log(&snac, xs_fmt("deleted entry %s", id)); | 4664 | snac_log(&snac, xs_fmt("deleted entry %s", id)); |
| 4497 | } | 4665 | } |
| 4498 | } | 4666 | } |
| @@ -4613,6 +4781,8 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4613 | snac.config = xs_dict_set(snac.config, "show_contact_metrics", xs_stock(XSTYPE_FALSE)); | 4781 | snac.config = xs_dict_set(snac.config, "show_contact_metrics", xs_stock(XSTYPE_FALSE)); |
| 4614 | if ((v = xs_dict_get(p_vars, "web_ui_lang")) != NULL) | 4782 | if ((v = xs_dict_get(p_vars, "web_ui_lang")) != NULL) |
| 4615 | snac.config = xs_dict_set(snac.config, "lang", v); | 4783 | snac.config = xs_dict_set(snac.config, "lang", v); |
| 4784 | if ((v = xs_dict_get(p_vars, "tz")) != NULL) | ||
| 4785 | snac.config = xs_dict_set(snac.config, "tz", v); | ||
| 4616 | 4786 | ||
| 4617 | snac.config = xs_dict_set(snac.config, "latitude", xs_dict_get_def(p_vars, "latitude", "")); | 4787 | snac.config = xs_dict_set(snac.config, "latitude", xs_dict_get_def(p_vars, "latitude", "")); |
| 4618 | snac.config = xs_dict_set(snac.config, "longitude", xs_dict_get_def(p_vars, "longitude", "")); | 4788 | snac.config = xs_dict_set(snac.config, "longitude", xs_dict_get_def(p_vars, "longitude", "")); |
| @@ -4636,7 +4806,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4636 | if (xs_startswith(mimetype, "image/")) { | 4806 | if (xs_startswith(mimetype, "image/")) { |
| 4637 | const char *ext = strrchr(fn, '.'); | 4807 | const char *ext = strrchr(fn, '.'); |
| 4638 | xs *hash = xs_md5_hex(fn, strlen(fn)); | 4808 | xs *hash = xs_md5_hex(fn, strlen(fn)); |
| 4639 | xs *id = xs_fmt("%s%s", hash, ext); | 4809 | xs *id = xs_fmt("%s-%s%s", uploads[n], hash, ext ? ext : ""); |
| 4640 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); | 4810 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); |
| 4641 | int fo = xs_number_get(xs_list_get(uploaded_file, 1)); | 4811 | int fo = xs_number_get(xs_list_get(uploaded_file, 1)); |
| 4642 | int fs = xs_number_get(xs_list_get(uploaded_file, 2)); | 4812 | int fs = xs_number_get(xs_list_get(uploaded_file, 2)); |
| @@ -4705,6 +4875,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4705 | /* set the option */ | 4875 | /* set the option */ |
| 4706 | msg = xs_dict_append(msg, "name", v); | 4876 | msg = xs_dict_append(msg, "name", v); |
| 4707 | 4877 | ||
| 4878 | /* delete the content */ | ||
| 4879 | msg = xs_dict_del(msg, "content"); | ||
| 4880 | |||
| 4708 | xs *c_msg = msg_create(&snac, msg); | 4881 | xs *c_msg = msg_create(&snac, msg); |
| 4709 | 4882 | ||
| 4710 | enqueue_message(&snac, c_msg); | 4883 | enqueue_message(&snac, c_msg); |