1 |
/* Conversion routines for PTlink >= 2.13.x databases. |
2 |
* |
3 |
* IRC Services is copyright (c) 1996-2009 Andrew Church. |
4 |
* E-mail: <achurch@achurch.org> |
5 |
* Parts written by Andrew Kempe and others. |
6 |
* This program is free but copyrighted software; see the file GPL.txt for |
7 |
* details. |
8 |
*/ |
9 |
|
10 |
#include "convert-db.h" |
11 |
|
12 |
#if NICKMAX < 32 |
13 |
# error NICKMAX too small (must be >=32) |
14 |
#elif CHANMAX < 64 |
15 |
# error CHANMAX too small (must be >=64) |
16 |
#elif PASSMAX < 32 |
17 |
# error PASSMAX too small (must be >=32) |
18 |
#endif |
19 |
|
20 |
/*************************************************************************/ |
21 |
|
22 |
static void ptlink_load_nick(const char *dir) |
23 |
{ |
24 |
char filename[PATH_MAX+1]; |
25 |
dbFILE *f; |
26 |
int i, j, c, delete; |
27 |
int16 tmp16, ver; |
28 |
int32 tmp32, total, count; |
29 |
NickInfo *ni; |
30 |
NickGroupInfo *ngi; |
31 |
char *s; |
32 |
signed char ch; |
33 |
|
34 |
snprintf(filename, sizeof(filename), "%s/nick.db", dir); |
35 |
if (!(f = open_db(filename, "r", 0))) |
36 |
return; |
37 |
SAFE(read_int8(&ch, f)); |
38 |
SAFE(read_int16(&ver, f)); |
39 |
if (ch != -1 || ver < 6 || ver > 11) { |
40 |
fprintf(stderr, "Wrong version number on %s\n", filename); |
41 |
exit(1); |
42 |
} |
43 |
|
44 |
SAFE(read_int32(&total, f)); |
45 |
count = 0; |
46 |
#if CLEAN_COMPILE |
47 |
c = 0; |
48 |
#endif |
49 |
for (i = 0; i < 256; i++) { |
50 |
while (ver >= 10 || (c = getc_db(f)) == 1) { |
51 |
char nickbuf[32], passbuf[32], authbuf[16]; |
52 |
if (ver >= 9) { |
53 |
int res = read_int32(&tmp32, f); /* SUID (broken) / SNID */ |
54 |
if (res < 0) { |
55 |
if (ver >= 10) /* v10: no more int8 markers */ |
56 |
break; |
57 |
else |
58 |
SAFE(res); |
59 |
} |
60 |
} |
61 |
SAFE(read_buffer(nickbuf, f)); |
62 |
/* The source (v2.26-eol.1) claims that duplicate nicknames can |
63 |
* get stored in the database for unknown reasons, so watch for |
64 |
* and delete them as needed */ |
65 |
delete = (get_nickinfo(nickbuf) != NULL); |
66 |
ni = makenick(nickbuf, &ngi); |
67 |
/* Use the SNID (file version 11) as a nickname group ID only |
68 |
* if it's nonzero and unique. Never use the SUID (versions 9 |
69 |
* and 10) as the source code claims that it's broken. */ |
70 |
if (ver >= 11 && tmp32 && !get_nickgroupinfo(tmp32)) |
71 |
ni->nickgroup = ngi->id = (uint32)tmp32; |
72 |
SAFE(read_buffer(passbuf, f)); |
73 |
init_password(&ngi->pass); |
74 |
memcpy(ngi->pass.password, passbuf, sizeof(passbuf)); |
75 |
if (ver >= 7) |
76 |
SAFE(read_buffer(authbuf, f)); |
77 |
SAFE(read_string(&ngi->url, f)); |
78 |
if (ver >= 7) |
79 |
SAFE(read_string(&s, f)); /* temporary, unauthed E-mail */ |
80 |
else |
81 |
s = NULL; |
82 |
SAFE(read_string(&ngi->email, f)); |
83 |
if (s) { |
84 |
ngi->last_email = ngi->email; |
85 |
ngi->email = s; |
86 |
} |
87 |
SAFE(read_string(&s, f)); /* icq_number */ |
88 |
SAFE(read_string(&s, f)); /* location */ |
89 |
SAFE(read_string(&ni->last_usermask, f)); |
90 |
if (!ni->last_usermask) |
91 |
ni->last_usermask = (char *)"@"; |
92 |
SAFE(read_string(&ni->last_realname, f)); |
93 |
if (!ni->last_realname) |
94 |
ni->last_realname = (char *)""; |
95 |
SAFE(read_string(&ni->last_quit, f)); |
96 |
SAFE(read_int32(&tmp32, f)); |
97 |
ni->time_registered = tmp32; |
98 |
SAFE(read_int32(&tmp32, f)); /* last_identify */ |
99 |
SAFE(read_int32(&tmp32, f)); |
100 |
ni->last_seen = tmp32; |
101 |
if (ver >= 7) |
102 |
SAFE(read_int32(&tmp32, f)); /* last_email_request */ |
103 |
SAFE(read_int32(&tmp32, f)); /* birth_date */ |
104 |
SAFE(read_int16(&tmp16, f)); /* status */ |
105 |
if (tmp16 & 0x0002) { |
106 |
ni->status |= NS_VERBOTEN; |
107 |
del_nickgroupinfo(ngi); |
108 |
ni->nickgroup = 0; |
109 |
} |
110 |
if (tmp16 & 0x0004) |
111 |
ni->status |= NS_NOEXPIRE; |
112 |
SAFE(read_int16(&tmp16, f)); /* crypt_method */ |
113 |
switch (tmp16) { |
114 |
case 0: break; |
115 |
case 2: ngi->pass.cipher = sstrdup("unix-crypt"); break; |
116 |
case 3: ngi->pass.cipher = sstrdup("md5"); break; |
117 |
case 1: |
118 |
fprintf(stderr, "%s: `%s' password encrypted with" |
119 |
" unsupported method JP2, resetting password" |
120 |
" to nickname", filename, nickbuf); |
121 |
/* fall through */ |
122 |
default: |
123 |
if (tmp16 != 1) { |
124 |
fprintf(stderr, "%s: `%s' password encrypted with" |
125 |
" unsupported method %d, resetting password" |
126 |
" to nickname", filename, nickbuf, tmp16); |
127 |
} |
128 |
strbcpy(ngi->pass.password, nickbuf); |
129 |
break; |
130 |
} |
131 |
SAFE(read_int32(&tmp32, f)); /* news_mask */ |
132 |
SAFE(read_int16(&tmp16, f)); /* news_status */ |
133 |
SAFE(read_string(&ni->last_realmask, f)); /* link */ |
134 |
SAFE(read_int16(&tmp16, f)); /* linkcount */ |
135 |
if (ni->last_realmask) { |
136 |
ni->nickgroup = 0; |
137 |
SAFE(read_int16(&tmp16, f)); /* channelcount */ |
138 |
} else { |
139 |
SAFE(read_int32(&tmp32, f)); /* flags */ |
140 |
if (tmp32 & 0x00000001) |
141 |
ngi->flags |= NF_KILLPROTECT; |
142 |
if (tmp32 & 0x00004002) |
143 |
ngi->flags |= 0x80000000; /* suspended */ |
144 |
if (tmp32 & 0x00000008) |
145 |
ngi->flags |= NF_MEMO_HARDMAX; |
146 |
if (tmp32 & 0x00000010) |
147 |
ngi->flags |= NF_MEMO_SIGNON; |
148 |
if (tmp32 & 0x00000020) |
149 |
ngi->flags |= NF_MEMO_RECEIVE; |
150 |
if (tmp32 & 0x00000040) |
151 |
ngi->flags |= NF_PRIVATE; |
152 |
if (tmp32 & 0x00000080) |
153 |
ngi->flags |= NF_HIDE_EMAIL; |
154 |
if (tmp32 & 0x00000100) |
155 |
ngi->flags |= NF_HIDE_MASK; |
156 |
if (tmp32 & 0x00000200) |
157 |
ngi->flags |= NF_HIDE_QUIT; |
158 |
if (tmp32 & 0x00000400) |
159 |
ngi->flags |= NF_KILL_QUICK; |
160 |
if (tmp32 & 0x00000800) |
161 |
ngi->flags |= NF_KILL_IMMED; |
162 |
SAFE(read_int32(&tmp32, f)); /* online */ |
163 |
if (ngi->flags & 0x80000000) { |
164 |
ngi->flags &= ~0x80000000; |
165 |
SAFE(read_int32(&tmp32, f)); /* expires */ |
166 |
strbcpy(ngi->suspend_who, "<unknown>"); |
167 |
ngi->suspend_reason = |
168 |
(char *)"Unknown (imported from PTlink IRC Services)"; |
169 |
ngi->suspend_time = time(NULL); |
170 |
ngi->suspend_expires = tmp32; |
171 |
ngi->flags |= NF_SUSPENDED; |
172 |
} |
173 |
SAFE(read_int16(&ngi->ajoin_count, f)); |
174 |
ngi->ajoin = scalloc(sizeof(char *), ngi->ajoin_count); |
175 |
for (j = 0; j < ngi->ajoin_count; j++) |
176 |
SAFE(read_string(&ngi->ajoin[j], f)); |
177 |
SAFE(read_int16(&ngi->memos.memos_count, f)); |
178 |
SAFE(read_int16(&ngi->memos.memomax, f)); |
179 |
if (ngi->memos.memos_count) { |
180 |
Memo *memos; |
181 |
memos = scalloc(sizeof(*memos), ngi->memos.memos_count); |
182 |
ngi->memos.memos = memos; |
183 |
for (j = 0; j < ngi->memos.memos_count; j++, memos++) { |
184 |
SAFE(read_uint32(&memos->number, f)); |
185 |
SAFE(read_int16(&tmp16, f)); |
186 |
if (tmp16 & 1) |
187 |
memos->flags |= MF_UNREAD; |
188 |
SAFE(read_int32(&tmp32, f)); |
189 |
memos->time = tmp32; |
190 |
SAFE(read_buffer(nickbuf, f)); |
191 |
strbcpy(memos->sender, nickbuf); |
192 |
SAFE(read_string(&memos->text, f)); |
193 |
} |
194 |
} |
195 |
SAFE(read_int16(&tmp16, f)); /* notes.count */ |
196 |
j = tmp16; |
197 |
SAFE(read_int16(&tmp16, f)); /* notes.max */ |
198 |
while (j--) /* notes.note[] */ |
199 |
SAFE(read_string(&s, f)); |
200 |
SAFE(read_int16(&tmp16, f)); /* channelcount */ |
201 |
SAFE(read_int16(&tmp16, f)); /* channelmax */ |
202 |
SAFE(read_int16(&tmp16, f)); |
203 |
switch (tmp16) { |
204 |
case 0: ngi->language = LANG_EN_US; break; |
205 |
case 1: ngi->language = LANG_PT; break; |
206 |
case 2: ngi->language = LANG_TR; break; |
207 |
case 3: ngi->language = LANG_DE; break; |
208 |
case 4: ngi->language = LANG_IT; break; |
209 |
} |
210 |
} |
211 |
if (delete) { |
212 |
del_nickgroupinfo(ngi); |
213 |
del_nickinfo(ni); |
214 |
} |
215 |
count++; |
216 |
} /* while (getc_db(f) == 1) */ |
217 |
if (ver < 10 && c != 0) { |
218 |
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename); |
219 |
exit(1); |
220 |
} |
221 |
} /* for (i) */ |
222 |
close_db(f); |
223 |
if (count != total) { |
224 |
fprintf(stderr, "%s: warning: expected %d nicks, got %d\n", |
225 |
filename, total, count); |
226 |
fprintf(stderr, " This means that your data files may be corrupt." |
227 |
" It may also be the\n" |
228 |
" result of a bug in some versions of PTlink Services.\n"); |
229 |
} |
230 |
|
231 |
/* Resolve links */ |
232 |
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) { |
233 |
NickInfo *ni2; |
234 |
const char *last_nick; |
235 |
if (ni->last_realmask) { |
236 |
ni2 = ni; |
237 |
/* Find root nick (this will actually stop at the first nick |
238 |
* in the path to the root that isn't marked as linked, but |
239 |
* that's okay because such a nick will already have its |
240 |
* nickgroup ID set correctly) */ |
241 |
do { |
242 |
last_nick = ni2->last_realmask; |
243 |
ni2 = get_nickinfo(last_nick); |
244 |
} while (ni2 && ni2 != ni && ni2->last_realmask); |
245 |
ni->last_realmask = NULL; |
246 |
/* Set nickgroup, or delete nick if an error occurred */ |
247 |
if (ni2 == ni) { |
248 |
fprintf(stderr, |
249 |
"Warning: dropping nick %s with circular link\n", |
250 |
ni->nick); |
251 |
del_nickinfo(ni); |
252 |
} else if (!ni2) { |
253 |
fprintf(stderr, "Warning: dropping nick %s linked to" |
254 |
" nonexistent nick %s\n", ni->nick, last_nick); |
255 |
del_nickinfo(ni); |
256 |
} else { |
257 |
ngi = get_nickgroupinfo(ni->nickgroup); |
258 |
if (ngi) |
259 |
del_nickgroupinfo(ngi); |
260 |
ni->nickgroup = ni2->nickgroup; |
261 |
ngi = get_nickgroupinfo(ni->nickgroup); |
262 |
if (ngi) { |
263 |
ARRAY_EXTEND(ngi->nicks); |
264 |
strbcpy(ngi->nicks[ngi->nicks_count-1], ni->nick); |
265 |
} else if (ni->nickgroup != 0) { |
266 |
fprintf(stderr, "Warning: Nick group %d for nick %s not" |
267 |
" found -- program bug? Output may be corrupt.", |
268 |
ni->nickgroup, ni->nick); |
269 |
} |
270 |
} |
271 |
} |
272 |
} |
273 |
} |
274 |
|
275 |
/*************************************************************************/ |
276 |
|
277 |
static struct { |
278 |
int32 flag; |
279 |
char mode; |
280 |
} ptlink_cmodes[] = { |
281 |
{ 0x00000001, 'i' }, |
282 |
{ 0x00000002, 'm' }, |
283 |
{ 0x00000004, 'n' }, |
284 |
{ 0x00000008, 'p' }, |
285 |
{ 0x00000010, 's' }, |
286 |
{ 0x00000020, 't' }, |
287 |
{ 0x00000040, 'k' }, |
288 |
{ 0x00000080, 'l' }, |
289 |
{ 0x00000200, 'R' }, |
290 |
{ 0x00000400, 'c' }, |
291 |
{ 0x00001000, 'O' }, |
292 |
{ 0x00002000, 'A' }, |
293 |
{ 0x00008000, 0 }, /* Like Unreal 'f': no dup lines within 10 secs */ |
294 |
{ 0, 0 } |
295 |
}; |
296 |
|
297 |
static void ptlink_load_chan(const char *dir) |
298 |
{ |
299 |
char filename[PATH_MAX+1]; |
300 |
dbFILE *f; |
301 |
int i, j, c, C_MAX; |
302 |
ChannelInfo *ci; |
303 |
NickInfo *ni; |
304 |
signed char ch; |
305 |
int16 tmp16, ver; |
306 |
int32 tmp32, total, count, mlock_on, mlock_off; |
307 |
char *on, *off; |
308 |
MemoInfo tmpmi; |
309 |
|
310 |
snprintf(filename, sizeof(filename), "%s/chan.db", dir); |
311 |
if (!(f = open_db(filename, "r", 0))) |
312 |
return; |
313 |
SAFE(read_int8(&ch, f)); |
314 |
SAFE(read_int16(&ver, f)); |
315 |
if (ch != -1 || ver < 7 || ver > 10) { |
316 |
fprintf(stderr, "Wrong version number on %s\n", filename); |
317 |
exit(1); |
318 |
} |
319 |
|
320 |
if (ver >= 9) |
321 |
SAFE(read_int32(&total, f)); |
322 |
count = 0; |
323 |
|
324 |
C_MAX = (ver<9 ? 256 : 65535); |
325 |
for (i = 0; i < C_MAX; i++) { |
326 |
char *s; |
327 |
|
328 |
while ((c = getc_db(f)) == 1) { |
329 |
char namebuf[64], passbuf[32], nickbuf[32]; |
330 |
if (ver >= 10) |
331 |
SAFE(read_int32(&tmp32, f)); /* SCID */ |
332 |
SAFE(read_buffer(namebuf, f)); |
333 |
ci = makechan(namebuf); |
334 |
SAFE(read_string(&s, f)); |
335 |
if (s) { |
336 |
ni = get_nickinfo(s); |
337 |
if (!ni) { |
338 |
fprintf(stderr, |
339 |
"Warning: Founder %s for channel %s not found\n", |
340 |
s, ci->name); |
341 |
} else if (!ni->nickgroup) { |
342 |
fprintf(stderr, "Warning: Founder %s for channel %s is a" |
343 |
" forbidden nick\n", s, ci->name); |
344 |
} else { |
345 |
ci->founder = ni->nickgroup; |
346 |
} |
347 |
} |
348 |
SAFE(read_string(&s, f)); |
349 |
if (s) { |
350 |
ni = get_nickinfo(s); |
351 |
if (!ni) { |
352 |
fprintf(stderr, "Warning: Successor %s for channel %s" |
353 |
" not found\n", s, ci->name); |
354 |
} else if (!ni->nickgroup) { |
355 |
fprintf(stderr, "Warning: Successor %s for channel %s" |
356 |
" is a forbidden nick\n", s, ci->name); |
357 |
} else if (ni->nickgroup == ci->founder) { |
358 |
fprintf(stderr, "Warning: Successor %s for channel %s" |
359 |
" is the same as the founder, clearing\n", |
360 |
s, ci->name); |
361 |
} else { |
362 |
ci->successor = ni->nickgroup; |
363 |
} |
364 |
} |
365 |
SAFE(read_int16(&tmp16, f)); /* maxusers */ |
366 |
SAFE(read_int32(&tmp32, f)); /* maxtime */ |
367 |
SAFE(read_buffer(passbuf, f)); |
368 |
init_password(&ci->founderpass); |
369 |
memcpy(ci->founderpass.password, passbuf, sizeof(passbuf)); |
370 |
SAFE(read_string(&ci->desc, f)); |
371 |
if (!ci->desc) |
372 |
ci->desc = (char *)""; |
373 |
SAFE(read_string(&ci->url, f)); |
374 |
SAFE(read_string(&ci->email, f)); |
375 |
SAFE(read_int32(&tmp32, f)); |
376 |
ci->time_registered = tmp32; |
377 |
SAFE(read_int32(&tmp32, f)); |
378 |
ci->last_used = tmp32; |
379 |
SAFE(read_string(&ci->last_topic, f)); |
380 |
SAFE(read_buffer(nickbuf, f)); |
381 |
strbcpy(ci->last_topic_setter, nickbuf); |
382 |
SAFE(read_int32(&tmp32, f)); |
383 |
ci->last_topic_time = tmp32; |
384 |
SAFE(read_int32(&tmp32, f)); /* flags */ |
385 |
if (tmp32 & 0x00000001) |
386 |
ci->flags |= CF_KEEPTOPIC; |
387 |
if (tmp32 & 0x00000002) |
388 |
ci->flags |= CF_SECUREOPS; |
389 |
if (tmp32 & 0x00000004) |
390 |
ci->flags |= CF_PRIVATE; |
391 |
if (tmp32 & 0x00000008) |
392 |
ci->flags |= CF_TOPICLOCK; |
393 |
if (tmp32 & 0x00000010) |
394 |
ci->flags |= CF_RESTRICTED; |
395 |
if (tmp32 & 0x00000020) |
396 |
ci->flags |= CF_LEAVEOPS; |
397 |
if (tmp32 & 0x00000080) |
398 |
ci->flags |= CF_VERBOTEN; |
399 |
if (tmp32 & 0x00000200) |
400 |
ci->flags |= CF_NOEXPIRE; |
401 |
if (tmp32 & 0x00000800) |
402 |
ci->flags |= CF_OPNOTICE; |
403 |
SAFE(read_int16(&tmp16, f)); /* crypt_method */ |
404 |
switch (tmp16) { |
405 |
case 0: break; |
406 |
case 2: ci->founderpass.cipher = sstrdup("unix-crypt"); break; |
407 |
case 3: ci->founderpass.cipher = sstrdup("md5"); break; |
408 |
case 1: |
409 |
fprintf(stderr, "%s: `%s' password encrypted with" |
410 |
" unsupported method JP2, resetting password" |
411 |
" to channel name", filename, namebuf); |
412 |
/* fall through */ |
413 |
default: |
414 |
if (tmp16 != 1) { |
415 |
fprintf(stderr, "%s: `%s' password encrypted with" |
416 |
" unsupported method %d, resetting password" |
417 |
" to channel name", filename, namebuf, tmp16); |
418 |
} |
419 |
strbcpy(ci->founderpass.password, namebuf); |
420 |
break; |
421 |
} |
422 |
if (tmp32 & 0x1000) |
423 |
SAFE(read_int32(&tmp32, f)); /* drop_time */ |
424 |
|
425 |
SAFE(read_int16(&tmp16, f)); /* levels[] */ |
426 |
for (j = tmp16; j > 0; j--) |
427 |
SAFE(read_int16(&tmp16, f)); |
428 |
|
429 |
SAFE(read_int16(&ci->access_count, f)); |
430 |
if (ci->access_count) { |
431 |
ci->access = scalloc(ci->access_count, sizeof(ChanAccess)); |
432 |
for (j = 0; j < ci->access_count; j++) { |
433 |
SAFE(read_int16(&tmp16, f)); /* in_use */ |
434 |
if (tmp16) { |
435 |
SAFE(read_int16(&ci->access[j].level, f)); |
436 |
SAFE(read_string(&s, f)); |
437 |
ci->access[j].level = |
438 |
convert_acclev(ci->access[j].level); |
439 |
if (s) { |
440 |
ni = get_nickinfo(s); |
441 |
if (ni) |
442 |
ci->access[j].nickgroup = ni->nickgroup; |
443 |
} |
444 |
SAFE(read_string(&s, f)); /* who */ |
445 |
} |
446 |
} |
447 |
} |
448 |
|
449 |
SAFE(read_int16(&ci->akick_count, f)); |
450 |
if (ci->akick_count) { |
451 |
ci->akick = scalloc(ci->akick_count, sizeof(AutoKick)); |
452 |
for (j = 0; j < ci->akick_count; j++) { |
453 |
SAFE(read_int16(&tmp16, f)); /* in_use */ |
454 |
if (tmp16) { |
455 |
SAFE(read_string(&ci->akick[j].mask, f)); |
456 |
SAFE(read_string(&ci->akick[j].reason, f)); |
457 |
SAFE(read_string(&s, f)); /* who */ |
458 |
strbcpy(ci->akick[j].who, s); |
459 |
ci->akick[j].set = time(NULL); |
460 |
SAFE(read_int32(&tmp32, f)); /* last_kick */ |
461 |
ci->akick[j].lastused = tmp32; |
462 |
} |
463 |
} |
464 |
} |
465 |
|
466 |
if (ver < 8) { |
467 |
SAFE(read_int16(&tmp16, f)); |
468 |
mlock_on = (int32)tmp16 & 0xFFFF; |
469 |
SAFE(read_int16(&tmp16, f)); |
470 |
mlock_off = (int32)tmp16 & 0xFFFF; |
471 |
} else { |
472 |
SAFE(read_int32(&mlock_on, f)); |
473 |
SAFE(read_int32(&mlock_off, f)); |
474 |
} |
475 |
ci->mlock.on = on = scalloc(64, 1); |
476 |
ci->mlock.off = off = scalloc(64, 1); |
477 |
for (j = 0; ptlink_cmodes[j].flag != 0; j++) { |
478 |
if (mlock_on & ptlink_cmodes[j].flag) |
479 |
*on++ = ptlink_cmodes[j].mode; |
480 |
if (mlock_off & ptlink_cmodes[j].flag) |
481 |
*off++ = ptlink_cmodes[j].mode; |
482 |
} |
483 |
*on = 0; |
484 |
*off = 0; |
485 |
SAFE(read_int32(&ci->mlock.limit, f)); |
486 |
SAFE(read_string(&ci->mlock.key, f)); |
487 |
|
488 |
SAFE(read_int16(&tmpmi.memos_count, f)); |
489 |
SAFE(read_int16(&tmp16, f)); /* memomax */ |
490 |
if (tmpmi.memos_count) { |
491 |
Memo *memos; |
492 |
memos = scalloc(sizeof(Memo), tmpmi.memos_count); |
493 |
tmpmi.memos = memos; |
494 |
for (j = 0; j < tmpmi.memos_count; j++, memos++) { |
495 |
SAFE(read_uint32(&memos->number, f)); |
496 |
SAFE(read_int16(&tmp16, f)); |
497 |
if (tmp16 & 1) |
498 |
memos->flags |= MF_UNREAD; |
499 |
SAFE(read_int32(&tmp32, f)); |
500 |
memos->time = tmp32; |
501 |
SAFE(read_buffer(nickbuf, f)); |
502 |
strbcpy(memos->sender, nickbuf); |
503 |
SAFE(read_string(&memos->text, f)); |
504 |
} |
505 |
} |
506 |
|
507 |
SAFE(read_string(&ci->entry_message, f)); |
508 |
|
509 |
if (!(ci->flags & CF_VERBOTEN) && !ci->founder) { |
510 |
fprintf(stderr, "Ignoring channel %s (missing founder)\n", |
511 |
ci->name); |
512 |
del_channelinfo(ci); |
513 |
} |
514 |
|
515 |
count++; |
516 |
|
517 |
} /* while (getc_db(f) == 1) */ |
518 |
|
519 |
if (c != 0) { |
520 |
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename); |
521 |
exit(1); |
522 |
} |
523 |
} /* for (i) */ |
524 |
close_db(f); |
525 |
|
526 |
if (ver >= 9 && count != total) { |
527 |
fprintf(stderr, "%s: warning: expected %d channels, got %d\n", |
528 |
filename, total, count); |
529 |
fprintf(stderr, " This means that your data files may be corrupt." |
530 |
" It may also be the\n" |
531 |
" result of a bug in some versions of PTlink Services.\n"); |
532 |
} |
533 |
} |
534 |
|
535 |
/*************************************************************************/ |
536 |
|
537 |
static void ptlink_load_oper(const char *dir) |
538 |
{ |
539 |
char filename[PATH_MAX+1]; |
540 |
dbFILE *f; |
541 |
int16 i, n, tmp16; |
542 |
int32 tmp32; |
543 |
char *s; |
544 |
signed char ch; |
545 |
|
546 |
snprintf(filename, sizeof(filename), "%s/oper.db", dir); |
547 |
if (!(f = open_db(filename, "r", 0))) |
548 |
return; |
549 |
SAFE(read_int8(&ch, f)); |
550 |
SAFE(read_int16(&tmp16, f)); |
551 |
if (ch != -1 || tmp16 < 1 || tmp16 > 2) { |
552 |
fprintf(stderr, "Wrong version number on %s\n", filename); |
553 |
exit(1); |
554 |
} |
555 |
SAFE(read_int16(&n, f)); |
556 |
for (i = 0; i < n; i++) { |
557 |
SAFE(read_string(&s, f)); |
558 |
set_os_priv(s, NP_SERVADMIN); |
559 |
} |
560 |
SAFE(read_int16(&n, f)); |
561 |
for (i = 0; i < n; i++) { |
562 |
SAFE(read_string(&s, f)); |
563 |
set_os_priv(s, NP_SERVOPER); |
564 |
} |
565 |
SAFE(read_int32(&maxusercnt, f)); |
566 |
SAFE(read_int32(&tmp32, f)); |
567 |
maxusertime = tmp32; |
568 |
close_db(f); |
569 |
} |
570 |
|
571 |
/*************************************************************************/ |
572 |
|
573 |
static void ptlink_load_akill(const char *dir) |
574 |
{ |
575 |
char filename[PATH_MAX+1]; |
576 |
dbFILE *f; |
577 |
int16 tmp16, i, n; |
578 |
int32 tmp32; |
579 |
signed char ch; |
580 |
MaskData *md; |
581 |
|
582 |
snprintf(filename, sizeof(filename), "%s/akill.db", dir); |
583 |
if (!(f = open_db(filename, "r", 0))) |
584 |
return; |
585 |
SAFE(read_int8(&ch, f)); |
586 |
SAFE(read_int16(&tmp16, f)); |
587 |
if (ch != -1 || tmp16 != 1) { |
588 |
fprintf(stderr, "Wrong version number on %s\n", filename); |
589 |
exit(1); |
590 |
} |
591 |
SAFE(read_int16(&n, f)); |
592 |
md = scalloc(sizeof(*md), n); |
593 |
for (i = 0; i < n; i++) { |
594 |
char nickbuf[32]; |
595 |
SAFE(read_string(&md[i].mask, f)); |
596 |
SAFE(read_string(&md[i].reason, f)); |
597 |
SAFE(read_buffer(nickbuf, f)); |
598 |
strbcpy(md[i].who, nickbuf); |
599 |
SAFE(read_int32(&tmp32, f)); |
600 |
md[i].time = tmp32; |
601 |
SAFE(read_int32(&tmp32, f)); |
602 |
md[i].expires = tmp32; |
603 |
if (md[i].mask) |
604 |
add_maskdata(MD_AKILL, &md[i]); |
605 |
} |
606 |
close_db(f); |
607 |
} |
608 |
|
609 |
/*************************************************************************/ |
610 |
|
611 |
static void ptlink_load_sqline(const char *dir) |
612 |
{ |
613 |
char filename[PATH_MAX+1]; |
614 |
dbFILE *f; |
615 |
int16 tmp16, i, n; |
616 |
int32 tmp32; |
617 |
signed char ch; |
618 |
MaskData *md; |
619 |
|
620 |
snprintf(filename, sizeof(filename), "%s/sqline.db", dir); |
621 |
if (!(f = open_db(filename, "r", 0))) |
622 |
return; |
623 |
SAFE(read_int8(&ch, f)); |
624 |
SAFE(read_int16(&tmp16, f)); |
625 |
if (ch != -1 || tmp16 != 1) { |
626 |
fprintf(stderr, "Wrong version number on %s\n", filename); |
627 |
exit(1); |
628 |
} |
629 |
SAFE(read_int16(&n, f)); |
630 |
md = scalloc(sizeof(*md), n); |
631 |
for (i = 0; i < n; i++) { |
632 |
char nickbuf[32]; |
633 |
SAFE(read_string(&md[i].mask, f)); |
634 |
SAFE(read_string(&md[i].reason, f)); |
635 |
SAFE(read_buffer(nickbuf, f)); |
636 |
strbcpy(md[i].who, nickbuf); |
637 |
SAFE(read_int32(&tmp32, f)); |
638 |
md[i].time = tmp32; |
639 |
SAFE(read_int32(&tmp32, f)); |
640 |
md[i].expires = tmp32; |
641 |
if (md[i].mask) |
642 |
add_maskdata(MD_SQLINE, &md[i]); |
643 |
} |
644 |
close_db(f); |
645 |
} |
646 |
|
647 |
/*************************************************************************/ |
648 |
|
649 |
static void ptlink_load_sxline(const char *dir) |
650 |
{ |
651 |
char filename[PATH_MAX+1]; |
652 |
dbFILE *f; |
653 |
int16 tmp16, i, n; |
654 |
int32 tmp32; |
655 |
signed char ch; |
656 |
MaskData *md; |
657 |
|
658 |
snprintf(filename, sizeof(filename), "%s/sxline.db", dir); |
659 |
if (!(f = open_db(filename, "r", 0))) |
660 |
return; |
661 |
SAFE(read_int8(&ch, f)); |
662 |
SAFE(read_int16(&tmp16, f)); |
663 |
if (ch != -1 || tmp16 != 1) { |
664 |
fprintf(stderr, "Wrong version number on %s\n", filename); |
665 |
exit(1); |
666 |
} |
667 |
SAFE(read_int16(&n, f)); |
668 |
md = scalloc(sizeof(*md), n); |
669 |
for (i = 0; i < n; i++) { |
670 |
char nickbuf[32]; |
671 |
SAFE(read_string(&md[i].mask, f)); |
672 |
SAFE(read_string(&md[i].reason, f)); |
673 |
SAFE(read_buffer(nickbuf, f)); |
674 |
strbcpy(md[i].who, nickbuf); |
675 |
SAFE(read_int32(&tmp32, f)); |
676 |
md[i].time = tmp32; |
677 |
SAFE(read_int32(&tmp32, f)); |
678 |
md[i].expires = tmp32; |
679 |
if (md[i].mask) |
680 |
add_maskdata(MD_SGLINE, &md[i]); |
681 |
} |
682 |
close_db(f); |
683 |
} |
684 |
|
685 |
/*************************************************************************/ |
686 |
|
687 |
static void ptlink_load_news(const char *dir) |
688 |
{ |
689 |
char filename[PATH_MAX+1]; |
690 |
dbFILE *f; |
691 |
int16 tmp16, i, n; |
692 |
int32 tmp32; |
693 |
signed char ch; |
694 |
NewsItem *news; |
695 |
|
696 |
snprintf(filename, sizeof(filename), "%s/news.db", dir); |
697 |
if (!(f = open_db(filename, "r", 0))) |
698 |
return; |
699 |
SAFE(read_int8(&ch, f)); |
700 |
SAFE(read_int16(&tmp16, f)); |
701 |
if (ch != -1 || tmp16 != 1) { |
702 |
fprintf(stderr, "Wrong version number on %s\n", filename); |
703 |
exit(1); |
704 |
} |
705 |
SAFE(read_int16(&n, f)); |
706 |
news = scalloc(sizeof(*news), n); |
707 |
for (i = 0; i < n; i++) { |
708 |
char nickbuf[32]; |
709 |
SAFE(read_int16(&news[i].type, f)); |
710 |
SAFE(read_int32(&news[i].num, f)); |
711 |
SAFE(read_string(&news[i].text, f)); |
712 |
SAFE(read_buffer(nickbuf, f)); |
713 |
strbcpy(news[i].who, nickbuf); |
714 |
SAFE(read_int32(&tmp32, f)); |
715 |
news[i].time = tmp32; |
716 |
add_news(&news[i]); |
717 |
} |
718 |
close_db(f); |
719 |
} |
720 |
|
721 |
/*************************************************************************/ |
722 |
/*************************************************************************/ |
723 |
|
724 |
static const char *check_ptlink(const char *dir) |
725 |
{ |
726 |
char buf[PATH_MAX+1]; |
727 |
|
728 |
snprintf(buf, sizeof(buf), "%s/vline.db", dir); |
729 |
if (access(buf, R_OK) == 0) |
730 |
return "PTlink"; |
731 |
return NULL; |
732 |
} |
733 |
|
734 |
static void load_ptlink(const char *dir, int verbose, int ac, char **av) |
735 |
{ |
736 |
if (ac > 1) { |
737 |
fprintf(stderr, "Unrecognized option %s\n", av[1]); |
738 |
usage(av[0]); |
739 |
} |
740 |
if (verbose) |
741 |
fprintf(stderr, "Loading nick.db...\n"); |
742 |
ptlink_load_nick(dir); |
743 |
if (verbose) |
744 |
fprintf(stderr, "Loading chan.db...\n"); |
745 |
ptlink_load_chan(dir); |
746 |
if (verbose) |
747 |
fprintf(stderr, "Loading oper.db...\n"); |
748 |
ptlink_load_oper(dir); |
749 |
if (verbose) |
750 |
fprintf(stderr, "Loading akill.db...\n"); |
751 |
ptlink_load_akill(dir); |
752 |
if (verbose) |
753 |
fprintf(stderr, "Loading sqline.db...\n"); |
754 |
ptlink_load_sqline(dir); |
755 |
if (verbose) |
756 |
fprintf(stderr, "Loading sxline.db...\n"); |
757 |
ptlink_load_sxline(dir); |
758 |
if (verbose) |
759 |
fprintf(stderr, "Loading news.db...\n"); |
760 |
ptlink_load_news(dir); |
761 |
} |
762 |
|
763 |
/*************************************************************************/ |
764 |
/*************************************************************************/ |
765 |
|
766 |
DBTypeInfo dbtype_ptlink = { |
767 |
"ptlink", |
768 |
check_ptlink, |
769 |
load_ptlink |
770 |
}; |
771 |
|
772 |
/*************************************************************************/ |
773 |
|
774 |
/* |
775 |
* Local variables: |
776 |
* c-file-style: "stroustrup" |
777 |
* c-file-offsets: ((case-label . *) (statement-case-intro . *)) |
778 |
* indent-tabs-mode: nil |
779 |
* End: |
780 |
* |
781 |
* vim: expandtab shiftwidth=4: |
782 |
*/ |