ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/backend/flatfile.C
Revision: 1.7
Committed: Thu Aug 30 19:56:20 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.6: +68 -65 lines
Log Message:
- put faultcodes into their own namespace
- removed old files
- limited header garbage in atheme.h
- macros to inline bools for connection_t::is_*
- put some connection_t functions into the connection_t class

File Contents

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