1 /*:ts=8*/
2 /*****************************************************************************
3  * FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail
4  *
5  *
6  * MSGID history functions and dupe checking
7  *
8  *****************************************************************************
9  * Copyright (C) 1990-2001
10  *  _____ _____
11  * |     |___  |   Martin Junius             FIDO:      2:2452/110
12  * | | | |   | |   Radiumstr. 18             Internet:  mj@fido.de
13  * |_|_|_|@home|   D-51069 Koeln, Germany
14  *
15  * This file is part of FIDOGATE.
16  *
17  * FIDOGATE is free software; you can redistribute it and/or modify it
18  * under the terms of the GNU General Public License as published by the
19  * Free Software Foundation; either version 2, or (at your option) any
20  * later version.
21  *
22  * FIDOGATE is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with FIDOGATE; see the file COPYING.  If not, write to the Free
29  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30  *****************************************************************************/
31 
32 #include "fidogate.h"
33 #include "dbz.h"
34 
35 /*
36  * History file
37  */
38 static FILE *hi_file = NULL;
39 short int hi_init(char *);
40 
41 /*
42  * Get base name
43  */
44 #if defined(DBC_HISTORY) && defined(FIDO_STYLE_MSGID)
hi_init_dbc()45 short int hi_init_dbc()
46 {
47     char db_name[MAXPATH];
48 
49     BUF_EXPAND(db_name, cf_p_dbc_history());
50 
51     if (hi_init(db_name) == ERROR) {
52         return ERROR;
53     }
54     return OK;
55 }
56 #endif                          /* DBC_HISTORY && FIDO_STYLE_MSGID */
57 
58 #ifdef TIC_HISTORY
hi_init_tic_history(void)59 void hi_init_tic_history(void)
60 {
61     char db_name[MAXPATH];
62 
63     BUF_EXPAND(db_name, cf_p_tic_history());
64 
65     if (hi_init(db_name) == ERROR) {
66         return;
67     }
68     return;
69 }
70 #endif                          /* TIC_HISTORY */
71 
hi_init_history(void)72 void hi_init_history(void)
73 {
74     char db_name[MAXPATH];
75 
76     BUF_EXPAND(db_name, cf_p_history());
77 
78     hi_init(db_name);
79 }
80 
81 /*
82  * Initialize MSGID history
83  */
hi_init(char * his_file)84 short int hi_init(char *his_file)
85 {
86     FILE *fp;
87 
88     /* Test for history.dir, history.pag */
89     BUF_EXPAND(buffer, his_file);
90     BUF_APPEND(buffer, ".dir");
91     if (check_access(buffer, CHECK_FILE) != TRUE) {
92         /* Doesn't exist, create */
93         if ((fp = fopen(buffer, W_MODE)) == NULL) {
94             fglog("$ERROR: creating MSGID history %s failed", buffer);
95             return ERROR;
96         } else
97             debug(9, "creating MSGID history %s", buffer);
98     }
99     BUF_EXPAND(buffer, his_file);
100     BUF_APPEND(buffer, ".pag");
101     if (check_access(buffer, CHECK_FILE) != TRUE) {
102         /* Doesn't exist, create */
103         if ((fp = fopen(buffer, W_MODE)) == NULL) {
104             fglog("$ERROR: creating MSGID history %s failed", buffer);
105             return ERROR;
106         } else
107             fglog("creating MSGID history %s", buffer);
108     }
109     /* Open the history text file */
110     BUF_EXPAND(buffer, his_file);
111     if ((hi_file = fopen(buffer, A_MODE)) == NULL) {
112         fglog("$ERROR: open MSGID history %s failed", buffer);
113         if (check_access(buffer, CHECK_FILE) == ERROR) {
114             fglog("$ERROR: Premission denied %s", buffer);
115             return ERROR;
116         }
117     }
118     /* Open the DBZ file */
119     dbzincore(1);
120     /**dbzwritethrough(1);**/
121     if (dbminit(buffer) == -1) {
122         fglog("$ERROR: dbminit %s failed", buffer);
123         return ERROR;
124     }
125     return OK;
126 }
127 
128 /*
129  * Close MSGID history
130  */
hi_close(void)131 void hi_close(void)
132 {
133 
134     if (hi_file) {
135         if (fclose(hi_file) == ERROR)
136             fglog("$ERROR: close MSGID history failed");
137         if (dbzsync())
138             fglog("$ERROR: dbzsync MSGID history failed");
139         if (dbmclose() < 0)
140             fglog("$ERROR: dbmclose MSGID history failed");
141 
142         hi_file = NULL;
143     }
144 }
145 
146 /*
147  * Write record to DBC MSGID history
148  */
149 #if defined(DBC_HISTORY) && defined(FIDO_STYLE_MSGID)
hi_write_dbc(char * rfc_msgid,char * fido_msgid,short int dont_flush)150 short int hi_write_dbc(char *rfc_msgid, char *fido_msgid, short int dont_flush)
151 {
152     long offset;
153     int ret;
154     datum key, val;
155     TIMEINFO ti;
156 
157     GetTimeInfo(&ti);
158     if (hi_file) {
159         /* Get offset in history text file */
160         if ((offset = ftell(hi_file)) == ERROR) {
161             fglog("$ERROR: ftell DBC MSGID history failed");
162             return ERROR;
163         }
164     } else {
165         fglog("$ERROR: can't open MSGID history file");
166         return ERROR;
167     }
168 
169     /* Write MSGID line to history text file */
170     if (strchr(fido_msgid, ' '))
171         fido_msgid = strrchr(fido_msgid, ' ') + 1;
172     debug(7, "dbc history: offset=%ld: %s %s %ld", offset, fido_msgid,
173           rfc_msgid, (long)ti.time);
174     ret =
175         fprintf(hi_file, "%s\t%s\t%ld\n", fido_msgid, rfc_msgid, (long)ti.time);
176     if (ret == ERROR || (!dont_flush && fflush(hi_file) == ERROR)) {
177         fglog("$ERROR: write to DBC MSGID history failed");
178         return ERROR;
179     }
180 
181     /* Write database record */
182     key.dptr = fido_msgid;      /* Key */
183     key.dsize = strlen(fido_msgid) + 1;
184     val.dptr = (char *)&offset; /* Value */
185     val.dsize = sizeof offset;
186     if (dbzstore(key, val) < 0) {
187         fglog("ERROR: dbzstore of record for DBC MSGID history failed");
188         return ERROR;
189     }
190 
191        /**FIXME: dbzsync() every n msgids */
192 
193     return OK;
194 }
195 #endif                          /* DBC_HISTORY && FIDO_STYLE_MSGID */
196 
197 /*
198  * Write record to MSGID history
199  */
hi_write_t(time_t t,time_t msgdate,char * msgid)200 short int hi_write_t(time_t t, time_t msgdate, char *msgid)
201 {
202     long offset;
203     int ret;
204     datum key, val;
205 
206     if (hi_file) {
207         /* Get offset in history text file */
208         if ((offset = ftell(hi_file)) == ERROR) {
209             fglog("$ERROR: ftell MSGID history failed");
210             return ERROR;
211         }
212     } else {
213         fglog("$ERROR: can't open MSGID history file");
214         return ERROR;
215     }
216 
217     /* Write MSGID line to history text file */
218     debug(7, "history: offset=%ld: %s %ld", offset, msgid, (long)t);
219     ret = fprintf(hi_file, "%s\t%ld\n", msgid, (long)t);
220     if (ret == ERROR || fflush(hi_file) == ERROR) {
221         fglog("$ERROR: write to MSGID history failed");
222         return ERROR;
223     }
224 
225     /* Write database record */
226     key.dptr = msgid;           /* Key */
227     key.dsize = strlen(msgid) + 1;
228     val.dptr = (char *)&offset; /* Value */
229     val.dsize = sizeof offset;
230     if (dbzstore(key, val) < 0) {
231         fglog("ERROR: dbzstore of record for MSGID history failed");
232         return ERROR;
233     }
234 
235        /**FIXME: dbzsync() every n msgids */
236 
237     return OK;
238 }
239 
hi_write(time_t msgdate,char * msgid)240 short int hi_write(time_t msgdate, char *msgid)
241     /* msgdate currently not used */
242 {
243     TIMEINFO ti;
244 
245     GetTimeInfo(&ti);
246 
247     return hi_write_t(ti.time, msgdate, msgid);
248 }
249 
250 /*
251  * Write record to DB
252  */
hi_write_avail(char * area,char * desc)253 short int hi_write_avail(char *area, char *desc)
254 {
255     long offset;
256     int ret;
257     datum key, val;
258 
259     if (hi_file) {
260         /* Get offset in history text file */
261         if ((offset = ftell(hi_file)) == ERROR) {
262             fglog("$ERROR: ftell MSGID history failed");
263             return ERROR;
264         }
265     } else {
266         fglog("$ERROR: can't open MSGID history file");
267         return ERROR;
268     }
269 
270     /* Write MSGID line to history text file */
271     debug(7, "history: offset=%ld: %s %s", offset, area, desc);
272     ret = fprintf(hi_file, "%s\t%s\n", area, desc);
273     if (ret == ERROR || fflush(hi_file) == ERROR) {
274         fglog("$ERROR: write to MSGID history failed");
275         return ERROR;
276     }
277 
278     /* Write database record */
279     key.dptr = area;            /* Key */
280     key.dsize = strlen(area) + 1;
281     val.dptr = (char *)&offset; /* Value */
282     val.dsize = sizeof offset;
283     if (dbzstore(key, val) < 0) {
284         fglog("ERROR: dbzstore of record for MSGID history failed");
285         return ERROR;
286     }
287 
288        /**FIXME: dbzsync() every n msgids */
289 
290     return OK;
291 }
292 
293 /*
294  * Test if MSGID is already in database
295  */
hi_test(char * key_string)296 short int hi_test(char *key_string)
297 {
298     datum key, val;
299 
300     key.dptr = key_string;      /* Key */
301     key.dsize = strlen(key_string) + 1;
302     val = dbzfetch(key);
303 #ifdef DEBUG
304     debug(1, "hi_test() key = %s, returned %s", key_string, val.dptr);
305 #endif
306     return val.dptr != NULL;
307 }
308 
309 /*
310  * Test if DB key is already in database
311  */
hi_fetch(char * key_string,int flag)312 char *hi_fetch(char *key_string, int flag)
313 {
314     datum key, val;
315     static char out[MAXPATH];
316 
317     if (flag == 0)
318         key_string = strchr(key_string, ' ') + 1;
319     debug(7, "search key %s", key_string);
320     key.dptr = key_string;      /* Key */
321     key.dsize = strlen(key_string) + 1;
322     val = dbcfetch(key);
323     if (val.dptr) {
324         BUF_COPY(out, xstrtok(val.dptr, " \t"));
325         debug(7, "found: %s", out);
326         return out;
327     } else {
328         debug(7, "not found");
329         return NULL;
330     }
331 }
332