[go: up one dir, main page]

File: xover.c

package info (click to toggle)
suck 3.10.1-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 728 kB
  • ctags: 727
  • sloc: ansic: 8,357; sh: 585; makefile: 212; java: 144; perl: 24
file content (367 lines) | stat: -rw-r--r-- 10,486 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
#include <config.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif

#include "suck.h"
#include "suck_config.h"
#include "both.h"
#include "xover.h"
#include "phrases.h"
#include "killfile.h"
#include "suckutils.h"

/*func prototypes */
int do_one_line(PMaster, char *, char *, PGroup);
int chk_a_group(PMaster, POneKill, POverview, char **);
int match_group(char *, char *, int);

/* these MUST match xover_reasons[] ! EXCEPT FOR THE last entry which MUST BE REASON_NONE */
enum { REASON_HIBYTES, REASON_LOWBYTES, REASON_HILINES, REASON_LOWLINES, REASON_HEADER, REASON_NOKEEP, REASON_NONE};

/*----------------------------------------------------------------------*/
int do_group_xover(PMaster master, char *grpname, long startnr) {

	int done, len, nr, retval = RETVAL_OK;
	char *resp, cmd[MAXLINLEN];
	PKillStruct xoverkill;
	PGroup grpkill = NULL;

	sprintf(cmd, "xover %ld-\r\n", startnr);
	retval = send_command(master, cmd, &resp, 0);
	if(retval == RETVAL_OK) {
		number(resp, &nr);
		switch(nr) {
		  default:
		  case 412:
		  case 502:
			  /* abort on these errors */
			  error_log(ERRLOG_REPORT, xover_phrases[0], resp, NULL);
			  retval = RETVAL_ERROR;
			  break;
		  case 420:
			  /* no articles available, no prob */
			  break;
		  case 224:
			  /* first, check to see if there is a group kill file for this group */
			  /* we do this here, so we only do it once per group, since we don't */
			  /* have all the crossposted groups to deal with */
			  xoverkill = master->xoverp;
			  if(xoverkill->totgrps > 0) {
				  for(nr = 0; xoverkill != NULL && nr < xoverkill->totgrps; nr++) {
					  if(match_group(xoverkill->grps[nr].group, grpname, master->debug) == TRUE) {
/* have to set up to use wildcards in group name */
						  grpkill = &(xoverkill->grps[nr]);
						  if(master->debug == TRUE) {
							  do_debug("Using Group Xover killfile\n");
						  }
					  }
				  }
			  }
			  
			  /* okay, do it */
			  done = FALSE;
			  while((done == FALSE) && (retval == RETVAL_OK)) {
				  len = sgetline(master->sockfd, &resp);
				  /* have we got the last one? */
				  if((len == 2) && (strcmp(resp, ".\n") == 0)) {
					  done = TRUE;
				  }
				  else if(len < 0) {
					  retval =RETVAL_ERROR;
				  }
				  else {
					  retval = do_one_line(master, grpname, resp, grpkill);
				  }
			  }
			  break;
		}
	}
	return retval;
}
/*-----------------------------------------------------------------------------------*/
int do_one_line(PMaster master, char *group, char *linein, PGroup grpkill) {

	/* take in one line of xover, then run it thru the kill routines */
	
	int len, msgidlen = 0, retval = RETVAL_OK, match = REASON_NONE;
	char *msgid = NULL, *ptr, *reason = NULL, tmp = '\0';
	long msgnr;
	POverview overv;
	
	PKillStruct masterk = master->xoverp; /* our master killstruct */
	overv = masterk->xoverview;
	ptr  = get_long(linein, &msgnr);  /* get our message number */
	
	/* first go thru and match up the header with the fields in the line, and fill */
	/* in the pointers in the xoverview with pointers to start of field */
	while( *ptr != '\0' && overv != NULL) {
		/* we are just past a tab */
		len = 0;
		overv->field = ptr;
		while(*ptr != '\t' && *ptr != '\0') {
			len++;
			ptr++;
		}
		overv->fieldlen = len;
		
		/* save Messag-ID location for later passing to subroutines */
		if(strcasecmp("Message-ID:", overv->header) == 0) {
			msgid = overv->field;
			msgidlen = overv->fieldlen;
		}
		overv = overv->next;
		if(*ptr == '\t') {
			ptr++; /* advance past tab */
		}
	}
	while(overv != NULL) {
		/* in case we got a short xoverview */
		overv->field = NULL;
		overv->fieldlen = 0;
		overv = overv->next;
	}
	if(msgid == NULL) {
		error_log(ERRLOG_REPORT, xover_phrases[13], linein, NULL);
	}
	else {
		/* we have to check against master killfile and group kill file */
		match = chk_a_group( master, &(masterk->master), masterk->xoverview, &reason);
		if((grpkill != NULL) && (match == REASON_NONE || masterk->grp_override == TRUE)) {
			/* we have to check against group */
		
			match = chk_a_group( master, &(grpkill->match), masterk->xoverview, &reason);
			if(grpkill->delkeep == DELKEEP_KEEP) {
				/* we keep only those that match */
				if(match == REASON_NONE) {
				/* we didn't match, so DON'T keep */
					match = REASON_NOKEEP;
				}
				else {
				/* so we keep it */
					match = REASON_NONE;
				}
			}
		}

		/* now we need to null terminate the msgid, for allocing or printing */

		if(msgid != NULL) {
			tmp = msgid[msgidlen];
			msgid[msgidlen] = '\0';
		}
	
		if(match == REASON_NONE) {
			/* we keep it */
			retval= allocnode(master, msgid, MANDATORY_OPTIONAL, group, msgnr);
		}
		else if(masterk->logyn != KILL_LOG_NONE) {
			/* only open this once */
			if(masterk->logfp == NULL) {
				if((masterk->logfp = fopen(full_path(FP_GET, FP_TMPDIR, master->kill_log_name), "a")) == NULL) {
					MyPerror(xover_phrases[11]);
				}
			}
			
			if(masterk->logfp != NULL) {
				/* Log it */
				if(match == REASON_HEADER) {
					print_phrases(masterk->logfp, xover_phrases[9], group, reason, msgid, NULL);
				}
				else {
					print_phrases(masterk->logfp, xover_phrases[9], group, xover_reasons[match], msgid, NULL);
				}
				
				if(masterk->logyn == KILL_LOG_LONG) {
				/* print the xover as well */
				/* first restore the message-id end of string, so entire line prints */
					if(msgid != NULL) {
						msgid[msgidlen] = tmp;
					}
					print_phrases(masterk->logfp, xover_phrases[10],linein, NULL);
				}
			}
		}
	}
	
	return retval;
}
/*----------------------------------------------------------------------------------------*/
void get_xoverview(PMaster master) {
	/* get in the xoverview.fmt list, so we can parse what xover returns later */
	/* we'll put em in a linked list */
	
	int done, retval, len;
	char *resp;
	POverview tmp, tmp2, curptr;
	PKillStruct killp;
	
	retval = RETVAL_OK;
	killp = master->xoverp;
	curptr = NULL;  /* where we are currently at in the linked list */
	
	if(send_command(master, "list overview.fmt\r\n", &resp, 215) == RETVAL_OK) {
		done = FALSE;
		/* now get em in, until we hit .\n which signifies end of response */
		while(done != TRUE) {
			sgetline(master->sockfd, &resp);
			if(strcmp(resp, ".\n") == 0) {
				done = TRUE;
			}
			else if(retval == RETVAL_OK) {
				/* now save em if we haven't run out of memory */
				len = strlen(resp);
				/* now get rid of everything back to : */
				while(resp[len-1] != ':') {
					resp[len--] = '\0';
				}
				if((tmp = malloc(sizeof(POverview))) == NULL) {
					error_log(ERRLOG_REPORT, xover_phrases[12], NULL);
					retval = RETVAL_ERROR;
				}
				else if((tmp->header = calloc(sizeof(char), len+1)) == NULL) {
					error_log(ERRLOG_REPORT, xover_phrases[12], NULL);
					retval = RETVAL_ERROR;
				}
				else {
					/* initialize the structure */
					strncpy(tmp->header, resp, len); /* don't copy the nl */
					tmp->header[len] = '\0';
					tmp->next = NULL;
					tmp->field = NULL;
					tmp->fieldlen = 0;
					
					if(curptr == NULL) {
						/* at head of list */
						curptr = tmp;
						killp->xoverview = tmp;
					}
					else {
						/* add to linked list */
						curptr->next = tmp;
						curptr = tmp;
					}
				}
			}
		}
	}
	if(retval != RETVAL_OK) {
		/* free up whatever alloced */
		tmp = killp->xoverview;
		while (tmp != NULL) {
			tmp2 = tmp;
			if(tmp->header != NULL) {
				free(tmp->header);
			}
			free(tmp);
			tmp = tmp2;
		}
		killp->xoverview = NULL;
	}
	if((tmp = killp->xoverview) != NULL) {
		do_debug("--Xoverview.fmt list\n");
		while(tmp != NULL) {
			if(tmp->header != NULL) {
				do_debug("item = %s\n", tmp->header);
			}
			tmp = tmp->next;
		}
		do_debug("--End Xoverview.fmt list\n");
	}
}
/*-------------------------------------------------------------------------------------*/
int chk_a_group(PMaster master, POneKill grp, POverview overv, char **reason) {
	/* return REASON_  if xover matches group */
	/* linein should be at tab after the Message Number */
 
	int match = REASON_NONE;
	unsigned long bytes;
	int lines;
	char tchar;
	static char reasonstr[MAXLINLEN];
	
	pmy_regex ptr;
	POverview tmp;
	*reason = reasonstr;
	
	if(grp->bodybig > 0 || grp->bodysmall > 0) {
		tmp = overv;
		while(tmp != NULL && match == REASON_NONE) {
			if(strcasecmp(tmp->header, "Bytes:") == 0) {
				sscanf(tmp->field, "%lu", &bytes); /* convert ascii to long */
				if((grp->bodybig > 0) && (bytes > grp->bodybig)) {
					match = REASON_HIBYTES;
				}
				else if((grp->bodysmall > 0) && (bytes < grp->bodysmall)) {
					match = REASON_LOWBYTES;
				}
			}
			tmp = tmp->next;
		}
	}
	
	if(match == REASON_NONE && (grp->hilines > 0 || grp->lowlines > 0)) {
		tmp = overv;
		while(tmp != NULL && match == REASON_NONE) {
			if(strcasecmp(tmp->header, "Lines:") == 0) {
				sscanf(tmp->field, "%d", &lines);
				if((grp->hilines > 0) && (lines > grp->hilines)) {
					match = REASON_HILINES;
				}
				else if((grp->lowlines > 0) && (lines < grp->lowlines)) {
					match = REASON_LOWLINES;
				}
			}
			tmp = tmp->next;
		}
	}
	if(match == REASON_NONE) {
		ptr = grp->list;
		while (match == REASON_NONE && ptr != NULL) {
			tmp = overv;
			while( tmp != NULL && match == REASON_NONE) {
				if(strcasecmp(tmp->header, ptr->header) == 0) {
                                        /* we need to null terminate the field and restore it later */
					tchar = tmp->field[tmp->fieldlen];
					tmp->field[tmp->fieldlen] = '\0';
					if(regex_block(tmp->field, ptr, master->debug) == TRUE) {
						match = REASON_HEADER;
						sprintf(reasonstr, "%s-%s%s", xover_reasons[REASON_HEADER], tmp->header, tmp->field);
					}
					tmp->field[tmp->fieldlen] = tchar;
				}
				tmp = tmp->next;
			}
			ptr = ptr->next;
		}
	}
	
	return match;
}
/*---------------------------------------------------------------------------*/
int match_group(char *match_grp, char *group, int debug) {
	/* does match match group?  match may contain wildcards */
	int match = FALSE;
	if(match_grp != NULL && group != NULL) {
		if(debug == TRUE) {
			do_debug("Xover - matching %s against %s\n", match_grp, group);
		}
		
		while( *group == *match_grp && *group != '\0') {
			group++;
			match_grp++;
		}
		if(*match_grp == '\0' || *match_grp == '*') {
                        /* wildcard match or end of string, they match so far, so they match */
			match = TRUE;
		}
		if(debug == TRUE) {
			do_debug("match = %s\n", true_str(match));
		}
		
	}
	return match;
}