diff options
Diffstat (limited to 'html.c')
| -rw-r--r-- | html.c | 173 |
1 files changed, 152 insertions, 21 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,36 @@ 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_html_add(form, | ||
| 459 | xs_html_tag("p", | ||
| 460 | xs_html_text(L("Post date and time (empty, right now; in the future, schedule for later):")), | ||
| 461 | xs_html_sctag("br", NULL), | ||
| 462 | xs_html_sctag("input", | ||
| 463 | xs_html_attr("type", "date"), | ||
| 464 | xs_html_attr("value", post_date ? post_date : ""), | ||
| 465 | xs_html_attr("name", "post_date")), | ||
| 466 | xs_html_text(" "), | ||
| 467 | xs_html_sctag("input", | ||
| 468 | xs_html_attr("type", "time"), | ||
| 469 | xs_html_attr("value", post_time ? post_time : ""), | ||
| 470 | xs_html_attr("step", "1"), | ||
| 471 | xs_html_attr("name", "post_time")))); | ||
| 472 | } | ||
| 473 | |||
| 432 | if (edit_id) | 474 | if (edit_id) |
| 433 | xs_html_add(form, | 475 | xs_html_add(form, |
| 434 | xs_html_sctag("input", | 476 | xs_html_sctag("input", |
| @@ -1116,7 +1158,7 @@ xs_html *html_top_controls(snac *user) | |||
| 1116 | NULL, NULL, | 1158 | NULL, NULL, |
| 1117 | xs_stock(XSTYPE_FALSE), "", | 1159 | xs_stock(XSTYPE_FALSE), "", |
| 1118 | xs_stock(XSTYPE_FALSE), NULL, | 1160 | xs_stock(XSTYPE_FALSE), NULL, |
| 1119 | NULL, 1, NULL, NULL, 0), | 1161 | NULL, 1, NULL, NULL, 0, NULL), |
| 1120 | 1162 | ||
| 1121 | /** operations **/ | 1163 | /** operations **/ |
| 1122 | xs_html_tag("details", | 1164 | xs_html_tag("details", |
| @@ -1774,7 +1816,8 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1774 | id, NULL, | 1816 | id, NULL, |
| 1775 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 1817 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1776 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 1818 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, |
| 1777 | NULL, 0, att_files, att_alt_texts, is_draft(user, id))), | 1819 | NULL, 0, att_files, att_alt_texts, is_draft(user, id), |
| 1820 | xs_dict_get(msg, "published"))), | ||
| 1778 | xs_html_tag("p", NULL)); | 1821 | xs_html_tag("p", NULL)); |
| 1779 | } | 1822 | } |
| 1780 | 1823 | ||
| @@ -1793,7 +1836,7 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1793 | NULL, NULL, | 1836 | NULL, NULL, |
| 1794 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 1837 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1795 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 1838 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, |
| 1796 | id, 0, NULL, NULL, 0)), | 1839 | id, 0, NULL, NULL, 0, NULL)), |
| 1797 | xs_html_tag("p", NULL)); | 1840 | xs_html_tag("p", NULL)); |
| 1798 | } | 1841 | } |
| 1799 | 1842 | ||
| @@ -2689,6 +2732,11 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 2689 | } | 2732 | } |
| 2690 | } | 2733 | } |
| 2691 | 2734 | ||
| 2735 | /* add an invisible hr, to help differentiate between posts in text browsers */ | ||
| 2736 | xs_html_add(entry_top, | ||
| 2737 | xs_html_sctag("hr", | ||
| 2738 | xs_html_attr("hidden", NULL))); | ||
| 2739 | |||
| 2692 | return entry_top; | 2740 | return entry_top; |
| 2693 | } | 2741 | } |
| 2694 | 2742 | ||
| @@ -2830,6 +2878,18 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 2830 | xs_html_text(L("drafts"))))); | 2878 | xs_html_text(L("drafts"))))); |
| 2831 | } | 2879 | } |
| 2832 | 2880 | ||
| 2881 | { | ||
| 2882 | /* show the list of scheduled posts */ | ||
| 2883 | xs *url = xs_fmt("%s/sched", user->actor); | ||
| 2884 | xs_html_add(lol, | ||
| 2885 | xs_html_tag("li", | ||
| 2886 | xs_html_tag("a", | ||
| 2887 | xs_html_attr("href", url), | ||
| 2888 | xs_html_attr("class", "snac-list-link"), | ||
| 2889 | xs_html_attr("title", L("Scheduled posts")), | ||
| 2890 | xs_html_text(L("scheduled posts"))))); | ||
| 2891 | } | ||
| 2892 | |||
| 2833 | /* the list of followed hashtags */ | 2893 | /* the list of followed hashtags */ |
| 2834 | const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags"); | 2894 | const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags"); |
| 2835 | 2895 | ||
| @@ -3130,7 +3190,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c | |||
| 3130 | NULL, actor_id, | 3190 | NULL, actor_id, |
| 3131 | xs_stock(XSTYPE_FALSE), "", | 3191 | xs_stock(XSTYPE_FALSE), "", |
| 3132 | xs_stock(XSTYPE_FALSE), NULL, | 3192 | xs_stock(XSTYPE_FALSE), NULL, |
| 3133 | NULL, 0, NULL, NULL, 0), | 3193 | NULL, 0, NULL, NULL, 0, NULL), |
| 3134 | xs_html_tag("p", NULL)); | 3194 | xs_html_tag("p", NULL)); |
| 3135 | 3195 | ||
| 3136 | xs_html_add(snac_post, snac_controls); | 3196 | xs_html_add(snac_post, snac_controls); |
| @@ -3879,6 +3939,21 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 3879 | } | 3939 | } |
| 3880 | } | 3940 | } |
| 3881 | else | 3941 | else |
| 3942 | if (strcmp(p_path, "sched") == 0) { /** list of scheduled posts **/ | ||
| 3943 | if (!login(&snac, req)) { | ||
| 3944 | *body = xs_dup(uid); | ||
| 3945 | status = HTTP_STATUS_UNAUTHORIZED; | ||
| 3946 | } | ||
| 3947 | else { | ||
| 3948 | xs *list = scheduled_list(&snac); | ||
| 3949 | |||
| 3950 | *body = html_timeline(&snac, list, 0, skip, show, | ||
| 3951 | 0, L("Scheduled posts"), "", 0, error); | ||
| 3952 | *b_size = strlen(*body); | ||
| 3953 | status = HTTP_STATUS_OK; | ||
| 3954 | } | ||
| 3955 | } | ||
| 3956 | else | ||
| 3882 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ | 3957 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ |
| 3883 | if (!login(&snac, req)) { | 3958 | if (!login(&snac, req)) { |
| 3884 | *body = xs_dup(uid); | 3959 | *body = xs_dup(uid); |
| @@ -4175,12 +4250,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)); | 4250 | snac_debug(&snac, 1, xs_fmt("web action '%s' received", p_path)); |
| 4176 | 4251 | ||
| 4177 | /* post note */ | 4252 | /* post note */ |
| 4178 | const xs_str *content = xs_dict_get(p_vars, "content"); | 4253 | const char *content = xs_dict_get(p_vars, "content"); |
| 4179 | const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); | 4254 | const char *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); |
| 4180 | const xs_str *to = xs_dict_get(p_vars, "to"); | 4255 | const char *to = xs_dict_get(p_vars, "to"); |
| 4181 | const xs_str *sensitive = xs_dict_get(p_vars, "sensitive"); | 4256 | const char *sensitive = xs_dict_get(p_vars, "sensitive"); |
| 4182 | const xs_str *summary = xs_dict_get(p_vars, "summary"); | 4257 | const char *summary = xs_dict_get(p_vars, "summary"); |
| 4183 | const xs_str *edit_id = xs_dict_get(p_vars, "edit_id"); | 4258 | const char *edit_id = xs_dict_get(p_vars, "edit_id"); |
| 4259 | const char *post_date = xs_dict_get_def(p_vars, "post_date", ""); | ||
| 4260 | 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")); | 4261 | 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")); | 4262 | int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); |
| 4186 | xs *attach_list = xs_list_new(); | 4263 | xs *attach_list = xs_list_new(); |
| @@ -4210,9 +4287,12 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4210 | const char *fn = xs_list_get(attach_file, 0); | 4287 | const char *fn = xs_list_get(attach_file, 0); |
| 4211 | 4288 | ||
| 4212 | if (xs_is_string(fn) && *fn != '\0') { | 4289 | if (xs_is_string(fn) && *fn != '\0') { |
| 4213 | char *ext = strrchr(fn, '.'); | 4290 | char rnd[32]; |
| 4214 | xs *hash = xs_md5_hex(fn, strlen(fn)); | 4291 | xs_rnd_buf(rnd, sizeof(rnd)); |
| 4215 | xs *id = xs_fmt("%s%s", hash, ext); | 4292 | |
| 4293 | const char *ext = strrchr(fn, '.'); | ||
| 4294 | xs *hash = xs_md5_hex(rnd, strlen(rnd)); | ||
| 4295 | xs *id = xs_fmt("post-%s%s", hash, ext ? ext : ""); | ||
| 4216 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); | 4296 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); |
| 4217 | int fo = xs_number_get(xs_list_get(attach_file, 1)); | 4297 | int fo = xs_number_get(xs_list_get(attach_file, 1)); |
| 4218 | int fs = xs_number_get(xs_list_get(attach_file, 2)); | 4298 | int fs = xs_number_get(xs_list_get(attach_file, 2)); |
| @@ -4268,6 +4348,29 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4268 | msg = xs_dict_set(msg, "summary", xs_is_null(summary) ? "..." : summary); | 4348 | msg = xs_dict_set(msg, "summary", xs_is_null(summary) ? "..." : summary); |
| 4269 | } | 4349 | } |
| 4270 | 4350 | ||
| 4351 | if (xs_is_string(post_date) && *post_date) { | ||
| 4352 | xs *local_pubdate = xs_fmt("%sT%s", post_date, | ||
| 4353 | xs_is_string(post_time) && *post_time ? post_time : "00:00:00"); | ||
| 4354 | |||
| 4355 | time_t t = xs_parse_iso_date(local_pubdate, 1); | ||
| 4356 | |||
| 4357 | if (t != 0) { | ||
| 4358 | xs *iso_date = xs_str_iso_date(t); | ||
| 4359 | msg = xs_dict_set(msg, "published", iso_date); | ||
| 4360 | |||
| 4361 | snac_debug(&snac, 1, xs_fmt("Published date: [%s]", iso_date)); | ||
| 4362 | } | ||
| 4363 | else | ||
| 4364 | snac_log(&snac, xs_fmt("Invalid post date: [%s]", local_pubdate)); | ||
| 4365 | } | ||
| 4366 | |||
| 4367 | /* is the published date from the future? */ | ||
| 4368 | int future_post = 0; | ||
| 4369 | xs *right_now = xs_str_utctime(0, ISO_DATE_SPEC); | ||
| 4370 | |||
| 4371 | if (strcmp(xs_dict_get(msg, "published"), right_now) > 0) | ||
| 4372 | future_post = 1; | ||
| 4373 | |||
| 4271 | if (xs_is_null(edit_id)) { | 4374 | if (xs_is_null(edit_id)) { |
| 4272 | /* new message */ | 4375 | /* new message */ |
| 4273 | const char *id = xs_dict_get(msg, "id"); | 4376 | const char *id = xs_dict_get(msg, "id"); |
| @@ -4275,6 +4378,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4275 | if (store_as_draft) { | 4378 | if (store_as_draft) { |
| 4276 | draft_add(&snac, id, msg); | 4379 | draft_add(&snac, id, msg); |
| 4277 | } | 4380 | } |
| 4381 | else | ||
| 4382 | if (future_post) { | ||
| 4383 | schedule_add(&snac, id, msg); | ||
| 4384 | } | ||
| 4278 | else { | 4385 | else { |
| 4279 | c_msg = msg_create(&snac, msg); | 4386 | c_msg = msg_create(&snac, msg); |
| 4280 | timeline_add(&snac, id, msg); | 4387 | timeline_add(&snac, id, msg); |
| @@ -4286,7 +4393,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4286 | 4393 | ||
| 4287 | if (valid_status(object_get(edit_id, &p_msg))) { | 4394 | if (valid_status(object_get(edit_id, &p_msg))) { |
| 4288 | /* copy relevant fields from previous version */ | 4395 | /* copy relevant fields from previous version */ |
| 4289 | char *fields[] = { "id", "context", "url", "published", | 4396 | char *fields[] = { "id", "context", "url", |
| 4290 | "to", "inReplyTo", NULL }; | 4397 | "to", "inReplyTo", NULL }; |
| 4291 | int n; | 4398 | int n; |
| 4292 | 4399 | ||
| @@ -4302,18 +4409,34 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4302 | if (is_draft(&snac, edit_id)) { | 4409 | if (is_draft(&snac, edit_id)) { |
| 4303 | /* message was previously a draft; it's a create activity */ | 4410 | /* message was previously a draft; it's a create activity */ |
| 4304 | 4411 | ||
| 4305 | /* set the published field to now */ | 4412 | /* if the date is from the past, overwrite it with right_now */ |
| 4306 | xs *published = xs_str_utctime(0, ISO_DATE_SPEC); | 4413 | if (strcmp(xs_dict_get(msg, "published"), right_now) < 0) { |
| 4307 | msg = xs_dict_set(msg, "published", published); | 4414 | snac_debug(&snac, 1, xs_fmt("setting draft ancient date to %s", right_now)); |
| 4415 | msg = xs_dict_set(msg, "published", right_now); | ||
| 4416 | } | ||
| 4308 | 4417 | ||
| 4309 | /* overwrite object */ | 4418 | /* overwrite object */ |
| 4310 | object_add_ow(edit_id, msg); | 4419 | object_add_ow(edit_id, msg); |
| 4311 | 4420 | ||
| 4312 | c_msg = msg_create(&snac, msg); | 4421 | if (future_post) { |
| 4313 | timeline_add(&snac, edit_id, msg); | 4422 | schedule_add(&snac, edit_id, msg); |
| 4423 | } | ||
| 4424 | else { | ||
| 4425 | c_msg = msg_create(&snac, msg); | ||
| 4426 | timeline_add(&snac, edit_id, msg); | ||
| 4427 | } | ||
| 4428 | |||
| 4314 | draft_del(&snac, edit_id); | 4429 | draft_del(&snac, edit_id); |
| 4315 | } | 4430 | } |
| 4431 | else | ||
| 4432 | if (is_scheduled(&snac, edit_id)) { | ||
| 4433 | /* editing an scheduled post; just update it */ | ||
| 4434 | schedule_add(&snac, edit_id, msg); | ||
| 4435 | } | ||
| 4316 | else { | 4436 | else { |
| 4437 | /* ignore the (possibly changed) published date */ | ||
| 4438 | msg = xs_dict_set(msg, "published", xs_dict_get(p_msg, "published")); | ||
| 4439 | |||
| 4317 | /* set the updated field */ | 4440 | /* set the updated field */ |
| 4318 | xs *updated = xs_str_utctime(0, ISO_DATE_SPEC); | 4441 | xs *updated = xs_str_utctime(0, ISO_DATE_SPEC); |
| 4319 | msg = xs_dict_set(msg, "updated", updated); | 4442 | msg = xs_dict_set(msg, "updated", updated); |
| @@ -4398,6 +4521,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4398 | if (is_draft(&snac, id)) | 4521 | if (is_draft(&snac, id)) |
| 4399 | draft_del(&snac, id); | 4522 | draft_del(&snac, id); |
| 4400 | else | 4523 | else |
| 4524 | if (is_scheduled(&snac, id)) | ||
| 4525 | schedule_del(&snac, id); | ||
| 4526 | else | ||
| 4401 | hide(&snac, id); | 4527 | hide(&snac, id); |
| 4402 | } | 4528 | } |
| 4403 | else | 4529 | else |
| @@ -4493,6 +4619,8 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4493 | 4619 | ||
| 4494 | draft_del(&snac, id); | 4620 | draft_del(&snac, id); |
| 4495 | 4621 | ||
| 4622 | schedule_del(&snac, id); | ||
| 4623 | |||
| 4496 | snac_log(&snac, xs_fmt("deleted entry %s", id)); | 4624 | snac_log(&snac, xs_fmt("deleted entry %s", id)); |
| 4497 | } | 4625 | } |
| 4498 | } | 4626 | } |
| @@ -4636,7 +4764,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4636 | if (xs_startswith(mimetype, "image/")) { | 4764 | if (xs_startswith(mimetype, "image/")) { |
| 4637 | const char *ext = strrchr(fn, '.'); | 4765 | const char *ext = strrchr(fn, '.'); |
| 4638 | xs *hash = xs_md5_hex(fn, strlen(fn)); | 4766 | xs *hash = xs_md5_hex(fn, strlen(fn)); |
| 4639 | xs *id = xs_fmt("%s%s", hash, ext); | 4767 | xs *id = xs_fmt("%s-%s%s", uploads[n], hash, ext ? ext : ""); |
| 4640 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); | 4768 | xs *url = xs_fmt("%s/s/%s", snac.actor, id); |
| 4641 | int fo = xs_number_get(xs_list_get(uploaded_file, 1)); | 4769 | int fo = xs_number_get(xs_list_get(uploaded_file, 1)); |
| 4642 | int fs = xs_number_get(xs_list_get(uploaded_file, 2)); | 4770 | int fs = xs_number_get(xs_list_get(uploaded_file, 2)); |
| @@ -4705,6 +4833,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4705 | /* set the option */ | 4833 | /* set the option */ |
| 4706 | msg = xs_dict_append(msg, "name", v); | 4834 | msg = xs_dict_append(msg, "name", v); |
| 4707 | 4835 | ||
| 4836 | /* delete the content */ | ||
| 4837 | msg = xs_dict_del(msg, "content"); | ||
| 4838 | |||
| 4708 | xs *c_msg = msg_create(&snac, msg); | 4839 | xs *c_msg = msg_create(&snac, msg); |
| 4709 | 4840 | ||
| 4710 | enqueue_message(&snac, c_msg); | 4841 | enqueue_message(&snac, c_msg); |