chiark / gitweb /
update debian version
[inn-innduct.git] / nnrpd / group.c
1 /*  $Id: group.c 7538 2006-08-26 05:44:06Z eagle $
2 **
3 **  Newsgroups and the active file.
4 */
5
6 #include "config.h"
7 #include "clibrary.h"
8
9 #include "inn/innconf.h"
10 #include "nnrpd.h"
11 #include "ov.h"
12
13 /*
14 **  Change to or list the specified newsgroup.  If invalid, stay in the old
15 **  group.
16 */
17 void CMDgroup(int ac, char *av[])
18 {
19     static char         NOSUCHGROUP[] = NNTP_NOSUCHGROUP;
20     ARTNUM              i;
21     char                *grplist[2];
22     char                *group;
23     void                *handle;
24     TOKEN               token;
25     int                 count;
26     bool                boolval;
27     bool                hookpresent = false;
28
29 #ifdef DO_PYTHON
30     hookpresent = PY_use_dynamic;
31 #endif /* DO_PYTHON */
32
33     if (!hookpresent && !PERMcanread) {
34         if (PERMspecified)
35             Reply("%d Permission denied\r\n", NNTP_ACCESS_VAL);
36         else
37             Reply("%d Authentication required\r\n", NNTP_AUTH_NEEDED_VAL);
38         return;
39     }
40
41     /* Parse arguments. */
42     if (ac == 1) {
43         if (GRPcur == NULL) {
44             Printf("%d No group specified\r\n", NNTP_XGTITLE_BAD);
45             return;
46         } else {
47             group = xstrdup(GRPcur);
48         }
49     } else {
50         group = xstrdup(av[1]);
51     }
52     
53     if (!OVgroupstats(group, &ARTlow, &ARThigh, &count, NULL)) {
54         Reply("%s %s\r\n", NOSUCHGROUP, group);
55         free(group);
56         return;
57     }
58
59 #ifdef DO_PYTHON
60     if (PY_use_dynamic) {
61         char    *reply;
62
63         /* Authorize user using Python module method dynamic*/
64         if (PY_dynamic(PERMuser, group, false, &reply) < 0) {
65             syslog(L_NOTICE, "PY_dynamic(): authorization skipped due to no Python dynamic method defined.");
66         } else {
67             if (reply != NULL) {
68                 syslog(L_TRACE, "PY_dynamic() returned a refuse string for user %s at %s who wants to read %s: %s", PERMuser, ClientHost, group, reply);
69                 Reply("%d %s\r\n", NNTP_ACCESS_VAL, reply);
70                 free(group);
71                 free(reply);
72                 return;
73             }
74         }
75     }
76 #endif /* DO_PYTHON */
77
78     if (!hookpresent) {
79         if (PERMspecified) {
80             grplist[0] = group;
81             grplist[1] = NULL;
82             if (!PERMmatch(PERMreadlist, grplist)) {
83                 Reply("%d Permission denied\r\n", NNTP_ACCESS_VAL);
84                 free(group);
85                 return;
86             }
87         } else {
88             Reply("%d Authentication required\r\n", NNTP_AUTH_NEEDED_VAL);
89             free(group);
90             return;
91         }
92     }
93
94     /* Close out any existing article, report group stats. */
95     ARTclose();
96     GRPreport();
97
98     /* Doing a "group" command? */
99     if (strcasecmp(av[0], "group") == 0) {
100         if (count == 0)
101             Reply("%d 0 0 0 %s\r\n", NNTP_GROUPOK_VAL, group);
102         else {
103             /* if we're an NFS reader, check the last nfsreaderdelay
104              * articles in the group to see if they arrived in the
105              * last nfsreaderdelay (default 60) seconds. If they did,
106              * don't report them as we don't want them to appear too
107              * soon */
108             if (innconf->nfsreader) {
109                 ARTNUM low, prev;
110                 time_t now, arrived;
111
112                 time(&now);
113                 if (ARTlow + innconf->nfsreaderdelay > ARThigh)
114                     low = ARTlow;
115                 else
116                     low = ARThigh - innconf->nfsreaderdelay;
117                 handle = OVopensearch(group, low, ARThigh);
118                 if (!handle) {
119                     Reply("%d group disappeared\r\n", NNTP_TEMPERR_VAL);
120                     free(group);
121                     return;
122                 }
123                 prev = low;
124                 while (OVsearch(handle, &i, NULL, NULL, NULL, &arrived)) {
125                     if (arrived + innconf->nfsreaderdelay > now) {
126                         ARThigh = prev;
127                         break;
128                     }
129                     prev = i;
130                 }
131                 OVclosesearch(handle);
132             }
133             Reply("%d %d %lu %lu %s\r\n", NNTP_GROUPOK_VAL, count,
134                   (unsigned long) ARTlow, (unsigned long) ARThigh, group);
135         }
136         GRPcount++;
137         ARTnumber = ARTlow;
138         if (GRPcur) {
139             if (strcmp(GRPcur, group) != 0) {
140                 OVctl(OVCACHEFREE, &boolval);
141                 free(GRPcur);
142                 GRPcur = xstrdup(group);
143             }
144         } else
145             GRPcur = xstrdup(group);
146     } else {
147         /* Must be doing a "listgroup" command.  We used to just return
148            something bland here ("Article list follows"), but reference NNTP
149            returns the same data as GROUP does and since we have it all
150            available it shouldn't hurt to return the same thing. */
151         if (count == 0) {
152             Reply("%d 0 0 0 %s\r\n", NNTP_GROUPOK_VAL, group);
153             Printf(".\r\n");
154         } else if ((handle = OVopensearch(group, ARTlow, ARThigh)) != NULL) {
155             Reply("%d %d %lu %lu %s\r\n", NNTP_GROUPOK_VAL, count,
156                   (unsigned long) ARTlow, (unsigned long) ARThigh, group);
157             while (OVsearch(handle, &i, NULL, NULL, &token, NULL)) {
158                 if (PERMaccessconf->nnrpdcheckart && !ARTinstorebytoken(token))
159                     continue;
160                 Printf("%lu\r\n", (unsigned long) i);
161             }
162             OVclosesearch(handle);
163             Printf(".\r\n");
164             GRPcount++;
165             ARTnumber = ARTlow;
166             if (GRPcur) {
167                 if (strcmp(GRPcur, group) != 0) {
168                     OVctl(OVCACHEFREE, &boolval);
169                     free(GRPcur);
170                     GRPcur = xstrdup(group);
171                 }
172             } else
173                 GRPcur = xstrdup(group);
174         } else {
175             Reply("%s %s\r\n", NOSUCHGROUP, group);
176         }
177     }
178     free(group);
179 }
180
181
182 /*
183 **  Report on the number of articles read in the group, and clear the count.
184 */
185 void
186 GRPreport()
187 {
188     char                buff[SPOOLNAMEBUFF];
189     char                repbuff[1024];
190
191     if (GRPcur) {
192         strlcpy(buff, GRPcur, sizeof(buff));
193         syslog(L_NOTICE, "%s group %s %lu", ClientHost, buff,
194                (unsigned long) GRParticles);
195         GRParticles = 0;
196         repbuff[0]='\0';
197     }
198 }
199
200
201 /*
202 **  Used by ANU-News clients.
203 */
204 void
205 CMDxgtitle(ac, av)
206     int                 ac;
207     char                *av[];
208 {
209     QIOSTATE    *qp;
210     char        *line;
211     char        *p;
212     char        *q;
213     char                *grplist[2];
214     char                save;
215
216     /* Parse the arguments. */
217     if (ac == 1) {
218         if (GRPcount == 0) {
219             Printf("%d No group specified\r\n", NNTP_XGTITLE_BAD);
220             return;
221         }
222         p = GRPcur;
223     }
224     else
225         p = av[1];
226
227     if (!PERMspecified) {
228         Printf("%d list follows\r\n", NNTP_XGTITLE_OK);
229         Printf(".\r\n");
230         return;
231     }
232
233     /* Open the file, get ready to scan. */
234     if ((qp = QIOopen(NEWSGROUPS)) == NULL) {
235         syslog(L_ERROR, "%s cant open %s %m", ClientHost, NEWSGROUPS);
236         Printf("%d Can't open %s\r\n", NNTP_XGTITLE_BAD, NEWSGROUPS);
237         return;
238     }
239     Printf("%d list follows\r\n", NNTP_XGTITLE_OK);
240
241     /* Print all lines with matching newsgroup name. */
242     while ((line = QIOread(qp)) != NULL) {
243         for (q = line; *q && !ISWHITE(*q); q++)
244             continue;
245         save = *q;
246         *q = '\0';
247         if (uwildmat(line, p)) {
248             if (PERMspecified) {
249                 grplist[0] = line;
250                 grplist[1] = NULL;
251                 if (!PERMmatch(PERMreadlist, grplist))
252                     continue;
253             }
254             *q = save;
255             Printf("%s\r\n", line);
256         }
257     }
258
259     /* Done. */
260     QIOclose(qp);
261     Printf(".\r\n");
262 }