ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/modules/backend/flatfile.C
Revision: 1.11
Committed: Sat Sep 22 14:27:26 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.10: +14 -16 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

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