1 /* groupserv - group services.
2 * Copyright (c) 2010 Atheme Development Group
3 */
4
5 #include "groupserv_main.h"
6
7 #define GDBV_VERSION 4
8
9 static unsigned int loading_gdbv = -1;
10 static unsigned int their_ga_all;
11
write_groupdb(database_handle_t * db)12 static void write_groupdb(database_handle_t *db)
13 {
14 myentity_t *mt;
15 myentity_iteration_state_t state;
16 mowgli_patricia_iteration_state_t state2;
17 metadata_t *md;
18
19 db_start_row(db, "GDBV");
20 db_write_uint(db, GDBV_VERSION);
21 db_commit_row(db);
22
23 db_start_row(db, "GFA");
24 db_write_word(db, gflags_tostr(ga_flags, GA_ALL));
25 db_commit_row(db);
26
27 MYENTITY_FOREACH_T(mt, &state, ENT_GROUP)
28 {
29 mowgli_node_t *n;
30
31 continue_if_fail(mt != NULL);
32 mygroup_t *mg = group(mt);
33 continue_if_fail(mg != NULL);
34
35 char *mgflags = gflags_tostr(mg_flags, mg->flags);
36
37 db_start_row(db, "GRP");
38 db_write_word(db, entity(mg)->id);
39 db_write_word(db, entity(mg)->name);
40 db_write_time(db, mg->regtime);
41 db_write_word(db, mgflags);
42 db_commit_row(db);
43
44 MOWGLI_ITER_FOREACH(n, mg->acs.head)
45 {
46 groupacs_t *ga = n->data;
47 char *flags = gflags_tostr(ga_flags, ga->flags);
48
49 db_start_row(db, "GACL");
50 db_start_row(db, entity(mg)->name);
51 db_start_row(db, ga->mt->name);
52 db_start_row(db, flags);
53 db_commit_row(db);
54 }
55
56 if (object(mg)->metadata)
57 {
58 MOWGLI_PATRICIA_FOREACH(md, &state2, object(mg)->metadata)
59 {
60 db_start_row(db, "MDG");
61 db_write_word(db, entity(mg)->name);
62 db_write_word(db, md->name);
63 db_write_str(db, md->value);
64 db_commit_row(db);
65 }
66 }
67 }
68 }
69
db_h_gdbv(database_handle_t * db,const char * type)70 static void db_h_gdbv(database_handle_t *db, const char *type)
71 {
72 loading_gdbv = db_sread_uint(db);
73 slog(LG_INFO, "groupserv: opensex data schema version is %d.", loading_gdbv);
74
75 their_ga_all = GA_ALL_OLD;
76 }
77
db_h_gfa(database_handle_t * db,const char * type)78 static void db_h_gfa(database_handle_t *db, const char *type)
79 {
80 const char *flags = db_sread_word(db);
81
82 gflags_fromstr(ga_flags, flags, &their_ga_all);
83 if (their_ga_all & ~GA_ALL)
84 {
85 slog(LG_ERROR, "db-h-gfa: losing flags %s from file", gflags_tostr(ga_flags, their_ga_all & ~GA_ALL));
86 }
87 if (~their_ga_all & GA_ALL)
88 {
89 slog(LG_ERROR, "db-h-gfa: making up flags %s not present in file", gflags_tostr(ga_flags, ~their_ga_all & GA_ALL));
90 }
91 }
92
db_h_grp(database_handle_t * db,const char * type)93 static void db_h_grp(database_handle_t *db, const char *type)
94 {
95 mygroup_t *mg;
96 const char *uid = NULL;
97 const char *name;
98 time_t regtime;
99 const char *flagset;
100
101 if (loading_gdbv >= 4)
102 uid = db_sread_word(db);
103
104 name = db_sread_word(db);
105
106 if (mygroup_find(name))
107 {
108 slog(LG_INFO, "db-h-grp: line %d: skipping duplicate group %s", db->line, name);
109 return;
110 }
111 if (uid && myentity_find_uid(uid))
112 {
113 slog(LG_INFO, "db-h-grp: line %d: skipping group %s with duplicate UID %s", db->line, name, uid);
114 return;
115 }
116
117 regtime = db_sread_time(db);
118
119 mg = mygroup_add_id(uid, name);
120 mg->regtime = regtime;
121
122 if (loading_gdbv >= 3)
123 {
124 flagset = db_sread_word(db);
125
126 if (!gflags_fromstr(mg_flags, flagset, &mg->flags))
127 slog(LG_INFO, "db-h-grp: line %d: confused by flags: %s", db->line, flagset);
128 }
129 }
130
db_h_gacl(database_handle_t * db,const char * type)131 static void db_h_gacl(database_handle_t *db, const char *type)
132 {
133 mygroup_t *mg;
134 myentity_t *mt;
135 unsigned int flags = GA_ALL; /* GDBV 1 entires had full access */
136
137 const char *name = db_sread_word(db);
138 const char *entity = db_sread_word(db);
139 const char *flagset;
140
141 mg = mygroup_find(name);
142 mt = myentity_find(entity);
143
144 if (mg == NULL)
145 {
146 slog(LG_INFO, "db-h-gacl: line %d: groupacs for nonexistent group %s", db->line, name);
147 return;
148 }
149
150 if (mt == NULL)
151 {
152 slog(LG_INFO, "db-h-gacl: line %d: groupacs for nonexistent entity %s", db->line, entity);
153 return;
154 }
155
156 if (loading_gdbv >= 2)
157 {
158 flagset = db_sread_word(db);
159
160 if (!gflags_fromstr(ga_flags, flagset, &flags))
161 slog(LG_INFO, "db-h-gacl: line %d: confused by flags: %s", db->line, flagset);
162
163 /* ACL view permission was added, so make up the permission (#279), but only if the database
164 * is from atheme 7.1 or earlier. --kaniini
165 */
166 if (!(their_ga_all & GA_ACLVIEW) && ((flags & GA_ALL_OLD) == their_ga_all))
167 flags |= GA_ACLVIEW;
168 }
169
170 groupacs_add(mg, mt, flags);
171 }
172
db_h_mdg(database_handle_t * db,const char * type)173 static void db_h_mdg(database_handle_t *db, const char *type)
174 {
175 const char *name = db_sread_word(db);
176 const char *prop = db_sread_word(db);
177 const char *value = db_sread_str(db);
178 void *obj = NULL;
179
180 obj = mygroup_find(name);
181
182 if (obj == NULL)
183 {
184 slog(LG_INFO, "db-h-mdg: attempting to add %s property to non-existant object %s",
185 prop, name);
186 return;
187 }
188
189 metadata_add(obj, prop, value);
190 }
191
gs_db_init(void)192 void gs_db_init(void)
193 {
194 hook_add_db_write_pre_ca(write_groupdb);
195
196 db_register_type_handler("GDBV", db_h_gdbv);
197 db_register_type_handler("GRP", db_h_grp);
198 db_register_type_handler("GACL", db_h_gacl);
199 db_register_type_handler("MDG", db_h_mdg);
200 db_register_type_handler("GFA", db_h_gfa);
201 }
202
gs_db_deinit(void)203 void gs_db_deinit(void)
204 {
205 hook_del_db_write_pre_ca(write_groupdb);
206
207 db_unregister_type_handler("GDBV");
208 db_unregister_type_handler("GRP");
209 db_unregister_type_handler("GACL");
210 db_unregister_type_handler("MDG");
211 db_unregister_type_handler("GFA");
212 }
213