commit c3b5057
default
·
2024-02-15 18:24:10 +0000 UTC
parent b75e44a
New function verify_links().
M
main.c
+5,
-0
1@@ -247,6 +247,11 @@ int main(int argc, char *argv[])
2 return 0;
3 }
4
5+ if (strcmp(cmd, "verify_links") == 0) { /** **/
6+ verify_links(&snac);
7+ return 0;
8+ }
9+
10 if (strcmp(cmd, "timeline") == 0) { /** **/
11 #if 0
12 xs *list = local_list(&snac, XS_ALL);
M
snac.h
+2,
-0
1@@ -330,3 +330,5 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
2 const char *payload, int p_size,
3 char **body, int *b_size, char **ctype);
4 void mastoapi_purge(void);
5+
6+void verify_links(snac *user);
M
utils.c
+106,
-0
1@@ -8,6 +8,8 @@
2 #include "xs_openssl.h"
3 #include "xs_random.h"
4 #include "xs_glob.h"
5+#include "xs_curl.h"
6+#include "xs_regex.h"
7
8 #include "snac.h"
9
10@@ -407,3 +409,107 @@ int deluser(snac *user)
11
12 return ret;
13 }
14+
15+
16+void verify_links(snac *user)
17+/* verifies a user's links */
18+{
19+ xs_dict *p = xs_dict_get(user->config, "metadata");
20+ char *k, *v;
21+ int changed = 0;
22+
23+ while (p && xs_dict_iter(&p, &k, &v)) {
24+ /* not an https link? skip */
25+ if (!xs_startswith(v, "https:/" "/"))
26+ continue;
27+
28+ int status;
29+ xs *req = NULL;
30+ xs *payload = NULL;
31+ int p_size = 0;
32+
33+ req = xs_http_request("GET", v, NULL, NULL, 0, &status,
34+ &payload, &p_size, 0);
35+
36+ if (!valid_status(status))
37+ continue;
38+
39+ /* extract the links */
40+ xs *ls = xs_regex_select(payload, "< *(a|link) +[^>]+>");
41+
42+ xs_list *lp = ls;
43+ char *ll;
44+
45+ while (xs_list_iter(&lp, &ll)) {
46+ /* extract href and rel */
47+ xs *r = xs_regex_select(ll, "(href|rel) *= *(\"[^\"]*\"|'[^']*')");
48+
49+ /* must have both attributes */
50+ if (xs_list_len(r) != 2)
51+ continue;
52+
53+ xs *href = NULL;
54+ int is_rel_me = 0;
55+ xs_list *pr = r;
56+ char *ar;
57+
58+ while (xs_list_iter(&pr, &ar)) {
59+ xs *nq = xs_dup(ar);
60+
61+ nq = xs_replace_i(nq, "\"", "");
62+ nq = xs_replace_i(nq, "'", "");
63+
64+ xs *r2 = xs_split_n(nq, "=", 1);
65+ if (xs_list_len(r2) != 2)
66+ continue;
67+
68+ xs *ak = xs_strip_i(xs_dup(xs_list_get(r2, 0)));
69+ xs *av = xs_strip_i(xs_dup(xs_list_get(r2, 1)));
70+
71+ if (strcmp(ak, "href") == 0)
72+ href = xs_dup(av);
73+ else
74+ if (strcmp(ak, "rel") == 0) {
75+ /* split the value by spaces */
76+ xs *vbs = xs_split(av, " ");
77+
78+ /* is any of it "me"? */
79+ if (xs_list_in(vbs, "me") != -1)
80+ is_rel_me = 1;
81+ }
82+ }
83+
84+ /* after all this acrobatics, do we have an href and a rel="me"? */
85+ if (href != NULL && is_rel_me) {
86+ /* is it the same as the actor? */
87+ if (strcmp(href, user->actor) == 0) {
88+ /* got it! */
89+ xs *verified_at = xs_str_utctime(0, ISO_DATE_SPEC);
90+
91+ user->links = xs_dict_set(user->links, v, verified_at);
92+
93+ changed++;
94+
95+ snac_log(user, xs_fmt("verify_links: %s at %s", v, verified_at));
96+ }
97+ }
98+ }
99+ }
100+
101+ if (changed) {
102+ FILE *f;
103+
104+ /* update the links.json file */
105+ xs *fn = xs_fmt("%s/links.json", user->basedir);
106+ xs *bfn = xs_fmt("%s.bak", fn);
107+
108+ rename(fn, bfn);
109+
110+ if ((f = fopen(fn, "w")) != NULL) {
111+ xs_json_dump(user->links, 4, f);
112+ fclose(f);
113+ }
114+ else
115+ rename(bfn, fn);
116+ }
117+}