ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/backend/flatfile.C
Revision: 1.5
Committed: Tue Aug 28 22:18:30 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.4: +14 -14 lines
Log Message:
added type traits

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