diff options
Diffstat (limited to 'data.c')
| -rw-r--r-- | data.c | 130 |
1 files changed, 121 insertions, 9 deletions
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "xs_glob.h" | 9 | #include "xs_glob.h" |
| 10 | #include "xs_set.h" | 10 | #include "xs_set.h" |
| 11 | #include "xs_time.h" | 11 | #include "xs_time.h" |
| 12 | #include "xs_regex.h" | ||
| 12 | 13 | ||
| 13 | #include "snac.h" | 14 | #include "snac.h" |
| 14 | 15 | ||
| @@ -116,21 +117,33 @@ int srv_open(char *basedir, int auto_upgrade) | |||
| 116 | srv_debug(1, xs_dup("OpenBSD security disabled by admin")); | 117 | srv_debug(1, xs_dup("OpenBSD security disabled by admin")); |
| 117 | } | 118 | } |
| 118 | else { | 119 | else { |
| 120 | int smail = xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE; | ||
| 121 | |||
| 119 | srv_debug(1, xs_fmt("Calling unveil()")); | 122 | srv_debug(1, xs_fmt("Calling unveil()")); |
| 120 | unveil(basedir, "rwc"); | 123 | unveil(basedir, "rwc"); |
| 121 | unveil("/tmp", "rwc"); | 124 | unveil("/tmp", "rwc"); |
| 122 | unveil("/usr/sbin/sendmail", "x"); | ||
| 123 | unveil("/etc/resolv.conf", "r"); | 125 | unveil("/etc/resolv.conf", "r"); |
| 124 | unveil("/etc/hosts", "r"); | 126 | unveil("/etc/hosts", "r"); |
| 125 | unveil("/etc/ssl/openssl.cnf", "r"); | 127 | unveil("/etc/ssl/openssl.cnf", "r"); |
| 126 | unveil("/etc/ssl/cert.pem", "r"); | 128 | unveil("/etc/ssl/cert.pem", "r"); |
| 127 | unveil("/usr/share/zoneinfo", "r"); | 129 | unveil("/usr/share/zoneinfo", "r"); |
| 130 | |||
| 131 | if (smail) | ||
| 132 | unveil("/usr/sbin/sendmail", "x"); | ||
| 133 | |||
| 128 | unveil(NULL, NULL); | 134 | unveil(NULL, NULL); |
| 129 | srv_debug(1, xs_fmt("Calling pledge()")); | 135 | srv_debug(1, xs_fmt("Calling pledge()")); |
| 130 | pledge("stdio rpath wpath cpath flock inet proc exec dns fattr", NULL); | 136 | |
| 137 | if (smail) | ||
| 138 | pledge("stdio rpath wpath cpath flock inet proc exec dns fattr", NULL); | ||
| 139 | else | ||
| 140 | pledge("stdio rpath wpath cpath flock inet proc dns fattr", NULL); | ||
| 131 | } | 141 | } |
| 132 | #endif /* __OpenBSD__ */ | 142 | #endif /* __OpenBSD__ */ |
| 133 | 143 | ||
| 144 | /* read (and drop) emojis.json, possibly creating it */ | ||
| 145 | xs_free(emojis()); | ||
| 146 | |||
| 134 | return ret; | 147 | return ret; |
| 135 | } | 148 | } |
| 136 | 149 | ||
| @@ -393,7 +406,7 @@ int index_del_md5(const char *fn, const char *md5) | |||
| 393 | fclose(f); | 406 | fclose(f); |
| 394 | } | 407 | } |
| 395 | else | 408 | else |
| 396 | status = 500; | 409 | status = 410; |
| 397 | 410 | ||
| 398 | pthread_mutex_unlock(&data_mutex); | 411 | pthread_mutex_unlock(&data_mutex); |
| 399 | 412 | ||
| @@ -796,6 +809,30 @@ double object_ctime(const char *id) | |||
| 796 | } | 809 | } |
| 797 | 810 | ||
| 798 | 811 | ||
| 812 | double object_mtime_by_md5(const char *md5) | ||
| 813 | { | ||
| 814 | xs *fn = _object_fn_by_md5(md5, "object_mtime_by_md5"); | ||
| 815 | return mtime(fn); | ||
| 816 | } | ||
| 817 | |||
| 818 | |||
| 819 | double object_mtime(const char *id) | ||
| 820 | { | ||
| 821 | xs *md5 = xs_md5_hex(id, strlen(id)); | ||
| 822 | return object_mtime_by_md5(md5); | ||
| 823 | } | ||
| 824 | |||
| 825 | |||
| 826 | void object_touch(const char *id) | ||
| 827 | { | ||
| 828 | xs *md5 = xs_md5_hex(id, strlen(id)); | ||
| 829 | xs *fn = _object_fn_by_md5(md5, "object_touch"); | ||
| 830 | |||
| 831 | if (mtime(fn)) | ||
| 832 | utimes(fn, NULL); | ||
| 833 | } | ||
| 834 | |||
| 835 | |||
| 799 | xs_str *_object_index_fn(const char *id, const char *idxsfx) | 836 | xs_str *_object_index_fn(const char *id, const char *idxsfx) |
| 800 | /* returns the filename of an object's index */ | 837 | /* returns the filename of an object's index */ |
| 801 | { | 838 | { |
| @@ -880,6 +917,9 @@ int object_unadmire(const char *id, const char *actor, int like) | |||
| 880 | 917 | ||
| 881 | status = index_del(fn, actor); | 918 | status = index_del(fn, actor); |
| 882 | 919 | ||
| 920 | if (valid_status(status)) | ||
| 921 | index_gc(fn); | ||
| 922 | |||
| 883 | srv_debug(0, | 923 | srv_debug(0, |
| 884 | xs_fmt("object_unadmire (%s) %s %s %d", like ? "Like" : "Announce", actor, fn, status)); | 924 | xs_fmt("object_unadmire (%s) %s %s %d", like ? "Like" : "Announce", actor, fn, status)); |
| 885 | 925 | ||
| @@ -1551,7 +1591,6 @@ int actor_get(const char *actor, xs_dict **data) | |||
| 1551 | else | 1591 | else |
| 1552 | d = xs_free(d); | 1592 | d = xs_free(d); |
| 1553 | 1593 | ||
| 1554 | #ifdef STALE_ACTORS | ||
| 1555 | xs *fn = _object_fn(actor); | 1594 | xs *fn = _object_fn(actor); |
| 1556 | double max_time; | 1595 | double max_time; |
| 1557 | 1596 | ||
| @@ -1560,13 +1599,20 @@ int actor_get(const char *actor, xs_dict **data) | |||
| 1560 | 1599 | ||
| 1561 | if (mtime(fn) + max_time < (double) time(NULL)) { | 1600 | if (mtime(fn) + max_time < (double) time(NULL)) { |
| 1562 | /* actor data exists but also stinks */ | 1601 | /* actor data exists but also stinks */ |
| 1563 | |||
| 1564 | /* touch the file */ | ||
| 1565 | utimes(fn, NULL); | ||
| 1566 | |||
| 1567 | status = 205; /* "205: Reset Content" "110: Response Is Stale" */ | 1602 | status = 205; /* "205: Reset Content" "110: Response Is Stale" */ |
| 1568 | } | 1603 | } |
| 1569 | #endif /* STALE_ACTORS */ | 1604 | |
| 1605 | return status; | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | |||
| 1609 | int actor_get_refresh(snac *user, const char *actor, xs_dict **data) | ||
| 1610 | /* gets an actor and requests a refresh if it's stale */ | ||
| 1611 | { | ||
| 1612 | int status = actor_get(actor, data); | ||
| 1613 | |||
| 1614 | if (status == 205 && user && !xs_startswith(actor, srv_baseurl)) | ||
| 1615 | enqueue_actor_refresh(user, actor); | ||
| 1570 | 1616 | ||
| 1571 | return status; | 1617 | return status; |
| 1572 | } | 1618 | } |
| @@ -2007,6 +2053,47 @@ int instance_unblock(const char *instance) | |||
| 2007 | } | 2053 | } |
| 2008 | 2054 | ||
| 2009 | 2055 | ||
| 2056 | /** content filtering **/ | ||
| 2057 | |||
| 2058 | int content_check(const char *file, const xs_dict *msg) | ||
| 2059 | /* checks if a message's content matches any of the regexes in file */ | ||
| 2060 | /* file format: one regex per line */ | ||
| 2061 | { | ||
| 2062 | xs *fn = xs_fmt("%s/%s", srv_basedir, file); | ||
| 2063 | FILE *f; | ||
| 2064 | int r = 0; | ||
| 2065 | char *v = xs_dict_get(msg, "content"); | ||
| 2066 | |||
| 2067 | if (xs_type(v) == XSTYPE_STRING && *v) { | ||
| 2068 | if ((f = fopen(fn, "r")) != NULL) { | ||
| 2069 | srv_debug(1, xs_fmt("content_check: loading regexes from %s", fn)); | ||
| 2070 | |||
| 2071 | /* massage content (strip HTML tags, etc.) */ | ||
| 2072 | xs *c = xs_regex_replace(v, "<[^>]+>", " "); | ||
| 2073 | c = xs_regex_replace_i(c, " {2,}", " "); | ||
| 2074 | c = xs_tolower_i(c); | ||
| 2075 | |||
| 2076 | while (!r && !feof(f)) { | ||
| 2077 | xs *rx = xs_strip_i(xs_readline(f)); | ||
| 2078 | |||
| 2079 | if (*rx) { | ||
| 2080 | xs *l = xs_regex_select_n(c, rx, 1); | ||
| 2081 | |||
| 2082 | if (xs_list_len(l)) { | ||
| 2083 | srv_debug(1, xs_fmt("content_check: match for '%s'", rx)); | ||
| 2084 | r = 1; | ||
| 2085 | } | ||
| 2086 | } | ||
| 2087 | } | ||
| 2088 | |||
| 2089 | fclose(f); | ||
| 2090 | } | ||
| 2091 | } | ||
| 2092 | |||
| 2093 | return r; | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | |||
| 2010 | /** notifications **/ | 2097 | /** notifications **/ |
| 2011 | 2098 | ||
| 2012 | xs_str *notify_check_time(snac *snac, int reset) | 2099 | xs_str *notify_check_time(snac *snac, int reset) |
| @@ -2388,6 +2475,21 @@ void enqueue_verify_links(snac *user) | |||
| 2388 | } | 2475 | } |
| 2389 | 2476 | ||
| 2390 | 2477 | ||
| 2478 | void enqueue_actor_refresh(snac *user, const char *actor) | ||
| 2479 | /* enqueues an actor refresh */ | ||
| 2480 | { | ||
| 2481 | xs *qmsg = _new_qmsg("actor_refresh", "", 0); | ||
| 2482 | char *ntid = xs_dict_get(qmsg, "ntid"); | ||
| 2483 | xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid); | ||
| 2484 | |||
| 2485 | qmsg = xs_dict_append(qmsg, "actor", actor); | ||
| 2486 | |||
| 2487 | qmsg = _enqueue_put(fn, qmsg); | ||
| 2488 | |||
| 2489 | snac_debug(user, 1, xs_fmt("enqueue_actor_refresh %s", actor)); | ||
| 2490 | } | ||
| 2491 | |||
| 2492 | |||
| 2391 | void enqueue_request_replies(snac *user, const char *id) | 2493 | void enqueue_request_replies(snac *user, const char *id) |
| 2392 | /* enqueues a request for the replies of a message */ | 2494 | /* enqueues a request for the replies of a message */ |
| 2393 | { | 2495 | { |
| @@ -2645,6 +2747,16 @@ void purge_server(void) | |||
| 2645 | } | 2747 | } |
| 2646 | } | 2748 | } |
| 2647 | } | 2749 | } |
| 2750 | |||
| 2751 | /* delete index backups */ | ||
| 2752 | xs *specb = xs_fmt("%s/" "*.bak", v); | ||
| 2753 | xs *bakfs = xs_glob(specb, 0, 0); | ||
| 2754 | |||
| 2755 | p2 = bakfs; | ||
| 2756 | while (xs_list_iter(&p2, &v2)) { | ||
| 2757 | unlink(v2); | ||
| 2758 | srv_debug(1, xs_fmt("purged %s", v2)); | ||
| 2759 | } | ||
| 2648 | } | 2760 | } |
| 2649 | } | 2761 | } |
| 2650 | 2762 | ||