ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/backend/flatfile.C
Revision: 1.2
Committed: Sat Jul 21 01:29:08 2007 UTC (19 years, 3 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +2 -2 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * Copyright © 2005-2006 Atheme Development Group
3 pippijn 1.2 * Rights to this code are as documented in doc/pod/license.pod.
4 pippijn 1.1 *
5     * This file contains the implementation of the Atheme 0.1
6     * flatfile database format, with metadata extensions.
7     *
8 pippijn 1.2 * $Id: flatfile.C,v 1.1 2007-07-19 08:24:52 pippijn Exp $
9 pippijn 1.1 */
10    
11     #include "atheme.h"
12     #include <account/chanacs.h>
13     #include <account/kline.h>
14     #include <account/metadata.h>
15     #include <account/mychan.h>
16     #include <account/mymemo.h>
17     #include <account/mynick.h>
18     #include <account/myuser.h>
19     #include <account/svsignore.h>
20    
21     static char const rcsid[] = "$Id";
22    
23     struct be_flatfile_listeners : callback::has_listeners
24     {
25     };
26    
27     be_flatfile_listeners listeners;
28    
29     DECLARE_MODULE_V1 ("backend/flatfile", true, _modinit, NULL, rcsid, "The Ermyth Team <http://ermyth.schmorp.de>");
30    
31     /* database versions */
32     #define DB_SHRIKE 1
33     #define DB_ATHEME 2
34    
35     /* flatfile state */
36     unsigned int muout = 0, mcout = 0, caout = 0, kout = 0;
37    
38     static int
39     flatfile_db_save_myusers_cb (dictionary_elem_t *delem, void *privdata)
40     {
41     FILE *f = (FILE *) privdata;
42     metadata_map::iterator mdit, mdit_end;
43     myuser_t::memo_vector::iterator mzit, mzit_end;
44     myuser_t::mzignore_vector::iterator miit, miit_end;
45     myuser_t *mu = (myuser_t *) delem->node.data;
46     node_t *tn;
47    
48     /* MU <name> <pass> <email> <registered> [lastlogin] [failnum*] [lastfail*]
49     * [lastfailon*] [flags]
50     *
51     * * failnum, lastfail, and lastfailon are deprecated (moved to metadata)
52     */
53     fprintf (f, "MU %s %s %s %ld", mu->name, mu->pass, mu->email, (long) mu->registered);
54     fprintf (f, " %ld", (long) mu->lastlogin);
55     fprintf (f, " 0 0 0");
56     if (!mu->logins.empty ())
57     fprintf (f, " %d\n", mu->flags & ~MU_NOBURSTLOGIN);
58     else
59     fprintf (f, " %d\n", mu->flags);
60    
61     muout++;
62    
63     for (mdit = mu->mdmap.begin (), mdit_end = mu->mdmap.end (); mdit != mdit_end; ++mdit)
64     {
65     metadata *md = mdit->second;
66     fprintf (f, "MD U %s %s %s\n", mu->name, md->key, md->value);
67     }
68    
69     for (mzit = mu->memos.begin (), mzit_end = mu->memos.end (); mzit != mzit_end; ++mzit)
70     {
71     mymemo_t *mz = *mzit;
72     fprintf (f, "ME %s %s %lu %lu %s\n", mu->name, mz->sender, (unsigned long) mz->sent, (unsigned long) mz->status, mz->text);
73     }
74    
75     for (miit = mu->memo_ignores.begin (), miit_end = mu->memo_ignores.end (); miit != miit_end; ++miit)
76     fprintf (f, "MI %s %s\n", mu->name, *miit);
77    
78     LIST_FOREACH (tn, mu->access_list.head)
79     {
80     fprintf (f, "AC %s %s\n", mu->name, (char *) tn->data);
81     }
82    
83     LIST_FOREACH (tn, mu->nicks.head)
84     {
85     mynick_t *mn = static_cast<mynick_t *> (tn->data);
86    
87     fprintf (f, "MN %s %s %ld %ld\n", mu->name, mn->nick, (long) mn->registered, (long) mn->lastseen);
88     }
89    
90     return 0;
91     }
92    
93     /* write db */
94     static void
95     flatfile_db_save (void *arg)
96     {
97     myuser_t *mu;
98     mychan_t *mc;
99     chanacs_t *ca;
100     kline_t *k;
101     svsignore_t *svsignore;
102     soper_t *soper;
103     node_t *n, *tn;
104     FILE *f;
105     int errno1, was_errored = 0;
106     dictionary_iteration_state_t state;
107     svsignore_vector::iterator siit, siit_end;
108     kline_vector::iterator klit, klit_end;
109     metadata_map::iterator mdit, mdit_end;
110    
111     errno = 0;
112    
113     /* reset state */
114     muout = 0, mcout = 0, caout = 0, kout = 0;
115    
116     /* write to a temporary file first */
117     if (!(f = fopen (DATADIR "/" PACKAGE_NAME ".db.new", "w")))
118     {
119     errno1 = errno;
120     slog (LG_ERROR, "db_save(): cannot create " PACKAGE_NAME ".db.new: %s", strerror (errno1));
121     wallops (_("\2DATABASE ERROR\2: db_save(): cannot create " PACKAGE_NAME ".db.new: %s"), strerror (errno1));
122     snoop (_("\2DATABASE ERROR\2: db_save(): cannot create " PACKAGE_NAME ".db.new: %s"), strerror (errno1));
123     return;
124     }
125    
126     /* write the database version */
127     fprintf (f, "DBV 6\n");
128     fprintf (f, "CF %s\n", bitmask_to_flags (ca_all, chanacs_flags));
129    
130     slog (LG_DEBUG, "db_save(): saving myusers");
131    
132     dictionary_foreach (mulist, flatfile_db_save_myusers_cb, f);
133    
134     slog (LG_DEBUG, "db_save(): saving mychans");
135    
136     DICTIONARY_FOREACH (mc, mychan_t, &state, mclist)
137     {
138     /* MC <name> <pass> <founder> <registered> [used] [flags]
139     * [mlock_on] [mlock_off] [mlock_limit] [mlock_key]
140     * PASS is now ignored -- replaced with a "0" to avoid having to special-case this version
141     */
142     fprintf (f, "MC %s %s %s %ld %ld", mc->name, "0", mc->founder->name, (long) mc->registered, (long) mc->used);
143     fprintf (f, " %d", mc->flags);
144     fprintf (f, " %d", mc->mlock_on);
145     fprintf (f, " %d", mc->mlock_off);
146     fprintf (f, " %d", mc->mlock_limit);
147    
148     if (mc->mlock_key)
149     fprintf (f, " %s\n", mc->mlock_key);
150     else
151     fprintf (f, "\n");
152    
153     mcout++;
154    
155     LIST_FOREACH (tn, mc->chanacs.head)
156     {
157     ca = (chanacs_t *) tn->data;
158    
159     fprintf (f, "CA %s %s %s %ld\n", ca->mychan->name, ca->myuser ? ca->myuser->name : ca->host, bitmask_to_flags (ca->level, chanacs_flags), ca->ts);
160    
161     for (mdit = ca->mdmap.begin (), mdit_end = ca->mdmap.end (); mdit != mdit_end; ++mdit)
162     {
163     metadata *md = mdit->second;
164    
165     fprintf (f, "MD A %s:%s %s %s\n", ca->mychan->name, (ca->myuser) ? ca->myuser->name : ca->host, md->key, md->value);
166     }
167    
168     caout++;
169     }
170    
171     for (mdit = mc->mdmap.begin (), mdit_end = mc->mdmap.end (); mdit != mdit_end; ++mdit)
172     {
173     metadata *md = mdit->second;
174    
175     fprintf (f, "MD C %s %s %s\n", mc->name, md->key, md->value);
176     }
177     }
178    
179     /* subscriptions -- we have to walk the myuser table again
180     because otherwise we could encounter unknowns on restart. */
181     slog (LG_DEBUG, "db_save(): saving subscriptions");
182    
183     DICTIONARY_FOREACH (mu, myuser_t, &state, mulist)
184     {
185     metadata_subscription_t *subscriptor;
186    
187     LIST_FOREACH (n, mu->subscriptions.head)
188     {
189     node_t *i;
190     string str (64);
191     subscriptor = (metadata_subscription_t *) n->data;
192    
193     LIST_FOREACH (i, subscriptor->taglist.head)
194     {
195     str.append (static_cast<char *> (i->data), strlen (static_cast<char *> (i->data)));
196    
197     if (i->next)
198     str.append (',');
199     }
200    
201     fprintf (f, "SU %s %s %s\n", mu->name, subscriptor->mu->name, str.c_str ());
202     }
203     }
204    
205     /* Services ignores */
206     slog (LG_DEBUG, "db_save(): saving svsignores");
207    
208     for (siit = svs_ignore_list.begin (), siit_end = svs_ignore_list.end (); siit != siit_end; ++siit)
209     {
210     svsignore = *siit;
211    
212     /* SI <mask> <settime> <setby> <reason> */
213     fprintf (f, "SI %s %ld %s %s\n", svsignore->mask, (long) svsignore->settime, svsignore->setby, svsignore->reason);
214     }
215    
216     /* Services operators */
217     slog (LG_DEBUG, "db_save(): saving sopers");
218    
219     LIST_FOREACH (n, soperlist.head)
220     {
221     soper = static_cast<soper_t *> (n->data);
222    
223     if (soper->flags & SOPER_CONF || soper->myuser == NULL)
224     continue;
225    
226     /* SO <account> <operclass> <flags> */
227     fprintf (f, "SO %s %s %d\n", soper->myuser->name, soper->classname, soper->flags);
228     }
229    
230     slog (LG_DEBUG, "db_save(): saving klines");
231    
232     for (klit = klnlist.begin (), klit_end = klnlist.end (); klit != klit_end; ++klit)
233     {
234     k = *klit;
235    
236     /* KL <user> <host> <duration> <settime> <setby> <reason> */
237     fprintf (f, "KL %s %s %ld %ld %s %s\n", k->user, k->host, k->duration, (long) k->settime, k->setby, k->reason);
238    
239     kout++;
240     }
241    
242     /* DE <muout> <mcout> <caout> <kout> */
243     fprintf (f, "DE %d %d %d %d\n", muout, mcout, caout, kout);
244    
245     was_errored = ferror (f);
246     was_errored |= fclose (f);
247     if (was_errored)
248     {
249     errno1 = errno;
250     slog (LG_ERROR, "db_save(): cannot write to " PACKAGE_NAME ".db.new: %s", strerror (errno1));
251     wallops (_("\2DATABASE ERROR\2: db_save(): cannot write to " PACKAGE_NAME ".db.new: %s"), strerror (errno1));
252     snoop (_("\2DATABASE ERROR\2: db_save(): cannot write to " PACKAGE_NAME ".db.new: %s"), strerror (errno1));
253     return;
254     }
255    
256     /* now, replace the old database with the new one, using an atomic rename */
257     unlink (DATADIR "/" PACKAGE_NAME ".db");
258    
259     if ((rename (DATADIR "/" PACKAGE_NAME ".db.new", DATADIR "/" PACKAGE_NAME ".db")) < 0)
260     {
261     errno1 = errno;
262     slog (LG_ERROR, "db_save(): cannot rename " PACKAGE_NAME ".db.new to " PACKAGE_NAME ".db: %s", strerror (errno1));
263     wallops (_("\2DATABASE ERROR\2: db_save(): cannot rename " PACKAGE_NAME ".db.new to " PACKAGE_NAME ".db: %s"), strerror (errno1));
264     snoop (_("\2DATABASE ERROR\2: db_save(): cannot rename " PACKAGE_NAME ".db.new to " PACKAGE_NAME ".db: %s"), strerror (errno1));
265     return;
266     }
267     }
268    
269     /* loads db */
270     static void
271     flatfile_db_load (void)
272     {
273     myuser_t *mu;
274     mychan_t *mc;
275     kline_t *k;
276     svsignore_t *svsignore;
277     unsigned int i = 0, linecnt = 0, muin = 0, mcin = 0, cain = 0, kin = 0;
278     FILE *f;
279     char *item, *s, dBuf[BUFSIZE];
280     unsigned int their_ca_all = ca_all;
281    
282     f = fopen (DATADIR "/" PACKAGE_NAME ".db", "r");
283     if (f == NULL)
284     {
285     if (errno == ENOENT)
286     {
287     slog (LG_ERROR, "db_load(): %s does not exist, creating it", DATADIR "/" PACKAGE_NAME ".db");
288     return;
289     }
290     else
291     {
292     slog (LG_ERROR, "db_load(): can't open %s for reading: %s", DATADIR "/" PACKAGE_NAME ".db", strerror (errno));
293     slog (LG_ERROR, "db_load(): exiting to avoid data loss");
294     exit (1);
295     }
296     }
297    
298     slog (LG_DEBUG, "db_load(): ----------------------- loading ------------------------");
299    
300     /* start reading it, one line at a time */
301     while (fgets (dBuf, BUFSIZE, f))
302     {
303     linecnt++;
304    
305     /* check for unimportant lines */
306     item = strtok (dBuf, " ");
307     strip (item);
308    
309     if (*item == '#' || *item == '\n' || *item == '\t' || *item == ' ' || *item == '\0' || *item == '\r' || !*item)
310     continue;
311    
312     /* database version */
313     if (!strcmp ("DBV", item))
314     {
315     i = atoi (strtok (NULL, " "));
316     if (i > 6)
317     {
318     slog (LG_INFO, "db_load(): database version is %d; I only understand "
319     "6 (Ermyth 2.3), "
320     "5 (Atheme 2.0, 2.1), "
321     "4 (Atheme 0.2), "
322     "3 (Atheme 0.2 without CA_ACLVIEW), "
323     "2 (Atheme 0.1) or "
324     "1 (Shrike)", i);
325     exit (EXIT_FAILURE);
326     }
327     }
328    
329     /* enabled chanacs flags */
330     if (!strcmp ("CF", item))
331     {
332     s = strtok (NULL, " ");
333     if (s == NULL)
334     slog (LG_INFO, "db_load(): missing param to CF");
335     else
336     {
337     their_ca_all = flags_to_bitmask (s, chanacs_flags, 0);
338     if (their_ca_all & ~ca_all)
339     {
340     slog (LG_ERROR, "db_load(): losing flags %s from file", bitmask_to_flags (their_ca_all & ~ca_all, chanacs_flags));
341     }
342     if (~their_ca_all & ca_all)
343     {
344     slog (LG_ERROR, "db_load(): making up flags %s not present in file", bitmask_to_flags (~their_ca_all & ca_all, chanacs_flags));
345     }
346     }
347     }
348    
349     /* myusers */
350     if (!strcmp ("MU", item))
351     {
352     char *muname, *mupass, *muemail;
353    
354     if ((s = strtok (NULL, " ")))
355     {
356     /* We need to know the flags before we myuser_add,
357     * so we need a few temporary places to put stuff.
358     */
359     unsigned int registered, lastlogin;
360     char *failnum, *lastfailaddr, *lastfailtime;
361    
362     if ((mu = myuser_find (s)))
363     continue;
364    
365     muin++;
366    
367     muname = s;
368     mupass = strtok (NULL, " ");
369     muemail = strtok (NULL, " ");
370    
371     registered = atoi (strtok (NULL, " "));
372     lastlogin = atoi (strtok (NULL, " "));
373     failnum = strtok (NULL, " ");
374     lastfailaddr = strtok (NULL, " ");
375     lastfailtime = strtok (NULL, " ");
376    
377     mu = myuser_add (muname, mupass, muemail, atol (strtok (NULL, " ")));
378    
379     mu->registered = registered;
380     mu->lastlogin = lastlogin;
381    
382     if (strcmp (failnum, "0"))
383     mu->add_metadata ("private:loginfail:failnum", failnum);
384     if (strcmp (lastfailaddr, "0"))
385     mu->add_metadata ("private:loginfail:lastfailaddr", lastfailaddr);
386     if (strcmp (lastfailtime, "0"))
387     mu->add_metadata ("private:loginfail:lastfailtime", lastfailtime);
388    
389     /* Verification keys were moved to metadata,
390     * but we'll still accept them from legacy
391     * databases. Note that we only transfer over
392     * initial registration keys -- I don't think
393     * we saved mu->temp, so we can't transition
394     * e-mail change keys anyway. --alambert
395     */
396     if ((s = strtok (NULL, " ")))
397     {
398     strip (s);
399     mu->add_metadata ("private:verify:register:key", s);
400     mu->add_metadata ("private:verify:register:timestamp", "0");
401     }
402     }
403     }
404    
405     if (!strcmp ("ME", item))
406     {
407     char *sender, *text;
408     time_t mtime;
409     unsigned int status;
410     mymemo_t *mz;
411    
412     mu = myuser_find (strtok (NULL, " "));
413     sender = strtok (NULL, " ");
414     mtime = atoi (strtok (NULL, " "));
415     status = atoi (strtok (NULL, " "));
416     text = strtok (NULL, "\n");
417    
418     if (!mu)
419     {
420     slog (LG_DEBUG, "db_load(): memo for unknown account");
421     continue;
422     }
423    
424     if (!sender || !mtime || !text)
425     continue;
426    
427     mz = static_cast<mymemo_t *> (smalloc (sizeof (mymemo_t)));
428    
429     strlcpy (mz->sender, sender, NICKLEN);
430     strlcpy (mz->text, text, MEMOLEN);
431     mz->sent = mtime;
432     mz->status = status;
433    
434     if (!(mz->status & MEMO_READ))
435     mu->memoct_new++;
436    
437     mu->memos.insert (mz);
438     }
439    
440     if (!strcmp ("MI", item))
441     {
442     char *user, *target;
443    
444     user = strtok (NULL, " ");
445     target = strtok (NULL, "\n");
446    
447     mu = myuser_find (user);
448    
449     if (!mu)
450     {
451     slog (LG_DEBUG, "db_load(): invalid ignore (MI %s %s)", user, target);
452     continue;
453     }
454    
455     mu->memo_ignores.insert (sstrdup (target));
456     }
457    
458     /* myuser access list */
459     if (!strcmp ("AC", item))
460     {
461     char *user, *mask;
462    
463     user = strtok (NULL, " ");
464     mask = strtok (NULL, "\n");
465    
466     mu = myuser_find (user);
467    
468     if (mu == NULL)
469     {
470     slog (LG_DEBUG, "db_load(): invalid access entry<%s> for unknown user<%s>", mask, user);
471     continue;
472     }
473    
474     myuser_access_add (mu, mask);
475     }
476    
477     /* registered nick */
478     if (!strcmp ("MN", item))
479     {
480     char *user, *nick, *treg, *tseen;
481     mynick_t *mn;
482    
483     user = strtok (NULL, " ");
484     nick = strtok (NULL, " ");
485     treg = strtok (NULL, " ");
486     tseen = strtok (NULL, " ");
487    
488     mu = myuser_find (user);
489     if (mu == NULL || nick == NULL || tseen == NULL)
490     {
491     slog (LG_DEBUG, "db_load(): invalid registered nick<%s> for user<%s>", nick, user);
492     continue;
493     }
494    
495     mn = mynick_add (mu, nick);
496     mn->registered = atoi (treg);
497     mn->lastseen = atoi (tseen);
498     }
499    
500     /* subscriptions */
501     if (!strcmp ("SU", item))
502     {
503     char *user, *sub_user, *tags, *tag;
504     myuser_t *subscriptor;
505     metadata_subscription_t *md;
506    
507     user = strtok (NULL, " ");
508     sub_user = strtok (NULL, " ");
509     tags = strtok (NULL, "\n");
510     if (!user || !sub_user || !tags)
511     {
512     slog (LG_INFO, "db_load(): invalid subscription (line %d)", linecnt);
513     continue;
514     }
515    
516     strip (tags);
517    
518     mu = myuser_find (user);
519     subscriptor = myuser_find (sub_user);
520     if (!mu || !subscriptor)
521     {
522     slog (LG_INFO, "db_load(): invalid subscription <%s,%s> (line %d)", user, sub_user, linecnt);
523     continue;
524     }
525    
526     md = static_cast<metadata_subscription_t *> (smalloc (sizeof (metadata_subscription_t)));
527     md->mu = subscriptor;
528    
529     tag = strtok (tags, ",");
530     do
531     {
532     node_add (sstrdup (tag), node_create (), &md->taglist);
533     }
534     while ((tag = strtok (NULL, ",")) != NULL);
535    
536     node_add (md, node_create (), &mu->subscriptions);
537     }
538    
539     /* services oper */
540     if (!strcmp ("SO", item))
541     {
542     char *user, *classname, *flagstr;
543    
544     user = strtok (NULL, " ");
545     classname = strtok (NULL, " ");
546     flagstr = strtok (NULL, "\n");
547    
548     mu = myuser_find (user);
549    
550     if (!mu || !classname || !flagstr)
551     {
552     slog (LG_DEBUG, "db_load(): invalid services oper (SO %s %s %s)", user, classname, flagstr);
553     continue;
554     }
555     soper_add (mu->name, classname, atoi (flagstr) & ~SOPER_CONF);
556     }
557    
558     /* mychans */
559     if (!strcmp ("MC", item))
560     {
561     char *mcname, *mcpass;
562    
563     if ((s = strtok (NULL, " ")))
564     {
565     if ((mc = mychan_find (s)))
566     continue;
567    
568     mcin++;
569    
570     mcname = s;
571     /* unused */
572     mcpass = strtok (NULL, " ");
573    
574     mc = mychan_add (mcname);
575    
576     mc->founder = myuser_find (strtok (NULL, " "));
577    
578     if (!mc->founder)
579     {
580     slog (LG_DEBUG, "db_load(): channel %s has no founder, dropping.", mc->name);
581     mc->refcnt_dec ();
582     continue;
583     }
584    
585     mc->registered = atoi (strtok (NULL, " "));
586     mc->used = atoi (strtok (NULL, " "));
587     mc->flags = atoi (strtok (NULL, " "));
588    
589     mc->mlock_on = atoi (strtok (NULL, " "));
590     mc->mlock_off = atoi (strtok (NULL, " "));
591     mc->mlock_limit = atoi (strtok (NULL, " "));
592    
593     if ((s = strtok (NULL, " ")))
594     {
595     strip (s);
596     if (*s != '\0' && *s != ':' && !strchr (s, ','))
597     mc->mlock_key = sstrdup (s);
598     }
599    
600     if (i < 5 && config_options.join_chans)
601     mc->flags |= MC_GUARD;
602     }
603     }
604    
605     /* Metadata entry */
606     if (!strcmp ("MD", item))
607     {
608     char *type = strtok (NULL, " ");
609     char *name = strtok (NULL, " ");
610     char *property = strtok (NULL, " ");
611     char *value = strtok (NULL, "");
612    
613     if (!type || !name || !property || !value)
614     continue;
615    
616     strip (value);
617    
618     if (*type == 'U')
619     {
620     mu = myuser_find (name);
621     if (mu != NULL)
622     mu->add_metadata (property, value);
623     }
624     else if (*type == 'C')
625     {
626     mc = mychan_find (name);
627     if (mc != NULL)
628     mc->add_metadata (property, value);
629     }
630     else if (*type == 'A')
631     {
632     chanacs_t *ca;
633     char *mask;
634    
635     mask = strrchr (name, ':');
636     if (mask != NULL)
637     {
638     *mask++ = '\0';
639     ca = chanacs_find_by_mask (mychan_find (name), mask, CA_NONE);
640     if (ca != NULL)
641     ca->add_metadata (property, value);
642     }
643     }
644     }
645    
646     /* Channel URLs */
647     if (!strcmp ("UR", item))
648     {
649     char *chan, *url;
650    
651     chan = strtok (NULL, " ");
652     url = strtok (NULL, " ");
653    
654     strip (url);
655    
656     if (chan && url)
657     {
658     mc = mychan_find (chan);
659    
660     if (mc)
661     mc->add_metadata ("url", url);
662     }
663     }
664    
665     /* Channel entry messages */
666     if (!strcmp ("EM", item))
667     {
668     char *chan, *message;
669    
670     chan = strtok (NULL, " ");
671     message = strtok (NULL, "");
672    
673     strip (message);
674    
675     if (chan && message)
676     {
677     mc = mychan_find (chan);
678    
679     if (mc)
680     mc->add_metadata ("private:entrymsg", message);
681     }
682     }
683    
684     /* chanacs */
685     if (!strcmp ("CA", item))
686     {
687     chanacs_t *ca;
688     char *cachan, *causer;
689    
690     cachan = strtok (NULL, " ");
691     causer = strtok (NULL, " ");
692    
693     if (cachan && causer)
694     {
695     mc = mychan_find (cachan);
696     mu = myuser_find (causer);
697    
698     if (mc == NULL || (mu == NULL && !validhostmask (causer)))
699     {
700     slog (LG_ERROR, "db_load(): invalid chanacs (line %d)", linecnt);
701     continue;
702     }
703    
704     cain++;
705    
706     if (i >= DB_ATHEME)
707     {
708     unsigned int fl = flags_to_bitmask (strtok (NULL, " "), chanacs_flags, 0x0);
709     const char *tsstr;
710     time_t ts = 0;
711    
712     /* Compatibility with oldworld databases. --nenolod */
713     /* arbitrary cutoff to avoid touching newer +voOt entries -- jilles */
714     if (fl == OLD_CA_AOP && i < 4)
715     fl = CA_AOP_DEF;
716    
717     /*
718     * If the database revision is version 6 or newer, CA entries are
719     * timestamped... otherwise we use 0 as the last modified TS
720     * --nenolod/jilles
721     */
722     tsstr = strtok (NULL, " ");
723     if (tsstr != NULL)
724     ts = atoi (tsstr);
725    
726     /* previous to CA_ACLVIEW, everyone could view
727     * access lists. If they aren't AKICKed, upgrade
728     * them. This keeps us from breaking old XOPs.
729     */
730     if (i < 4)
731     if (!(fl & CA_AKICK))
732     fl |= CA_ACLVIEW;
733    
734     /* Grant +h if they have +o,
735     * the file does not have +h enabled
736     * and we currently have +h enabled.
737     * This preserves AOP, SOP and +*.
738     */
739     if (fl & CA_OP && !(their_ca_all & CA_HALFOP) && ca_all & CA_HALFOP)
740     fl |= CA_HALFOP;
741    
742     if ((!mu) && (validhostmask (causer)))
743     ca = chanacs_add_host (mc, causer, fl, ts);
744     else
745     ca = chanacs_add (mc, mu, fl, ts);
746     }
747     else if (i == DB_SHRIKE) /* DB_SHRIKE */
748     {
749     unsigned int fl = atol (strtok (NULL, " "));
750     unsigned int fl2 = 0x0;
751     time_t ts = NOW;
752    
753     switch (fl)
754     {
755     case SHRIKE_CA_VOP:
756     fl2 = chansvs.ca_vop;
757     case SHRIKE_CA_AOP:
758     fl2 = chansvs.ca_aop;
759     case SHRIKE_CA_SOP:
760     fl2 = chansvs.ca_sop;
761     case SHRIKE_CA_SUCCESSOR:
762     fl2 = CA_SUCCESSOR_0;
763     case SHRIKE_CA_FOUNDER:
764     fl2 = CA_FOUNDER_0;
765     }
766    
767     if ((!mu) && (validhostmask (causer)))
768     ca = chanacs_add_host (mc, causer, fl2, ts);
769     else
770     ca = chanacs_add (mc, mu, fl2, ts);
771     }
772     }
773     }
774    
775    
776     /* Services ignores */
777     if (!strcmp ("SI", item))
778     {
779     char *mask, *setby, *reason, *tmp;
780     time_t settime;
781    
782     mask = strtok (NULL, " ");
783     tmp = strtok (NULL, " ");
784     settime = atol (tmp);
785     setby = strtok (NULL, " ");
786     reason = strtok (NULL, "");
787    
788     strip (reason);
789    
790     svsignore = svsignore_add (mask, reason);
791     svsignore->settime = settime;
792     svsignore->setby = sstrdup (setby);
793    
794     }
795    
796     /* klines */
797     if (!strcmp ("KL", item))
798     {
799     char *user, *host, *reason, *setby, *tmp;
800     time_t settime;
801     long duration;
802    
803     user = strtok (NULL, " ");
804     host = strtok (NULL, " ");
805     tmp = strtok (NULL, " ");
806     duration = atol (tmp);
807     tmp = strtok (NULL, " ");
808     settime = atol (tmp);
809     setby = strtok (NULL, " ");
810     reason = strtok (NULL, "");
811    
812     strip (reason);
813    
814     k = kline_add (user, host, reason, duration);
815     k->settime = settime;
816     /* XXX this is not nice, oh well -- jilles */
817     k->expires = k->settime + k->duration;
818     k->setby = sstrdup (setby);
819    
820     kin++;
821     }
822    
823     /* end */
824     if (!strcmp ("DE", item))
825     {
826     i = atoi (strtok (NULL, " "));
827     if (i != muin)
828     slog (LG_ERROR, "db_load(): got %d myusers; expected %d", muin, i);
829    
830     i = atoi (strtok (NULL, " "));
831     if (i != mcin)
832     slog (LG_ERROR, "db_load(): got %d mychans; expected %d", mcin, i);
833    
834     i = atoi (strtok (NULL, " "));
835     if (i != cain)
836     slog (LG_ERROR, "db_load(): got %d chanacs; expected %d", cain, i);
837    
838     if ((s = strtok (NULL, " ")))
839     if ((i = atoi (s)) != kin)
840     slog (LG_ERROR, "db_load(): got %d klines; expected %d", kin, i);
841     }
842     }
843    
844     fclose (f);
845    
846     slog (LG_DEBUG, "db_load(): ------------------------- done -------------------------");
847     }
848    
849     void
850     _modinit (module_t *m)
851     {
852     m->mflags = MODTYPE_CORE;
853    
854     db_load = &flatfile_db_load;
855     db_save = &flatfile_db_save;
856    
857     backend_loaded = true;
858     }