0782894dd27ad81323fb370582b2dba16bb8e61e
[citadel.git] / citadel / modules / pop3client / serv_pop3client.c
1 /*
2  * Aggregate remote POP3 accounts
3  */
4
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <stdio.h>
8
9 #if TIME_WITH_SYS_TIME
10 # include <sys/time.h>
11 # include <time.h>
12 #else
13 # if HAVE_SYS_TIME_H
14 #  include <sys/time.h>
15 # else
16 #  include <time.h>
17 # endif
18 #endif
19
20 #include <ctype.h>
21 #include <string.h>
22 #include <errno.h>
23 #include "citadel.h"
24 #include "server.h"
25 #include "citserver.h"
26 #include "support.h"
27 #include "config.h"
28 #include "tools.h"
29 #include "room_ops.h"
30 #include "ctdl_module.h"
31 #include "clientsocket.h"
32
33 struct pop3aggr {
34         struct pop3aggr *next;
35         char roomname[ROOMNAMELEN];
36         char pop3host[128];
37         char pop3user[128];
38         char pop3pass[128];
39 };
40
41 struct pop3aggr *palist = NULL;
42
43 #ifdef POP3_AGGREGATION
44
45
46 void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3pass)
47 {
48         int sock;
49         char buf[SIZ];
50
51         lprintf(CTDL_DEBUG, "POP3: %s %s %s %s\n", roomname, pop3host, pop3user, pop3pass);
52         lprintf(CTDL_NOTICE, "Connecting to <%s>\n", pop3host);
53         sock = sock_connect(pop3host, "110", "tcp");
54         if (sock < 0) {
55                 lprintf(CTDL_ERR, "Could not connect: %s\n", strerror(errno));
56                 return;
57         }
58         
59         lprintf(CTDL_DEBUG, "Connected!\n");
60
61         /* Read the server greeting */
62         if (sock_gets(sock, buf) < 0) goto bail;
63         lprintf(CTDL_DEBUG, ">%s\n", buf);
64         if (strncasecmp(buf, "+OK", 3)) goto bail;
65
66         /* Identify ourselves */
67         snprintf(buf, sizeof buf, "USER %s", pop3user);
68         lprintf(CTDL_DEBUG, "<%s\n", buf);
69         if (sock_puts(sock, buf) <0) goto bail;
70         if (sock_gets(sock, buf) < 0) goto bail;
71         lprintf(CTDL_DEBUG, ">%s\n", buf);
72         if (strncasecmp(buf, "+OK", 3)) goto bail;
73
74         /* Password */
75         snprintf(buf, sizeof buf, "PASS %s", pop3pass);
76         lprintf(CTDL_DEBUG, "<%s\n", buf);
77         if (sock_puts(sock, buf) <0) goto bail;
78         if (sock_gets(sock, buf) < 0) goto bail;
79         lprintf(CTDL_DEBUG, ">%s\n", buf);
80         if (strncasecmp(buf, "+OK", 3)) goto bail;
81
82         sock_puts(sock, "QUIT");
83 bail:   sock_close(sock);
84 }
85
86
87 /*
88  * Scan a room's netconfig to determine whether it requires POP3 aggregation
89  */
90 void pop3client_scan_room(struct ctdlroom *qrbuf, void *data)
91 {
92         char filename[PATH_MAX];
93         char buf[1024];
94         char instr[32];
95         FILE *fp;
96         struct pop3aggr *pptr;
97
98         assoc_file_name(filename, sizeof filename, qrbuf, ctdl_netcfg_dir);
99
100         /* Only do net processing for rooms that have netconfigs */
101         fp = fopen(filename, "r");
102         if (fp == NULL) {
103                 return;
104         }
105
106         while (fgets(buf, sizeof buf, fp) != NULL) {
107                 buf[strlen(buf)-1] = 0;
108
109                 extract_token(instr, buf, 0, '|', sizeof instr);
110                 if (!strcasecmp(instr, "pop3client")) {
111                         pptr = (struct pop3aggr *) malloc(sizeof(struct pop3aggr));
112                         if (pptr != NULL) {
113                                 safestrncpy(pptr->roomname, qrbuf->QRname, sizeof pptr->roomname);
114                                 extract_token(pptr->pop3host, buf, 1, '|', sizeof pptr->pop3host);
115                                 extract_token(pptr->pop3user, buf, 2, '|', sizeof pptr->pop3user);
116                                 extract_token(pptr->pop3pass, buf, 3, '|', sizeof pptr->pop3pass);
117                                 pptr->next = palist;
118                                 palist = pptr;
119                         }
120                 }
121
122         }
123
124         fclose(fp);
125
126 }
127
128
129 void pop3client_scan(void) {
130         static time_t last_run = 0L;
131         static int doing_pop3client = 0;
132         struct pop3aggr *pptr;
133
134         /*
135          * Run POP3 aggregation no more frequently than once every n seconds
136          */
137         if ( (time(NULL) - last_run) < config.c_net_freq ) {
138                 return;
139         }
140
141         /*
142          * This is a simple concurrency check to make sure only one pop3client run
143          * is done at a time.  We could do this with a mutex, but since we
144          * don't really require extremely fine granularity here, we'll do it
145          * with a static variable instead.
146          */
147         if (doing_pop3client) return;
148         doing_pop3client = 1;
149
150         lprintf(CTDL_DEBUG, "pop3client started\n");
151         ForEachRoom(pop3client_scan_room, NULL);
152
153         while (palist != NULL) {
154                 pop3_do_fetching(palist->roomname, palist->pop3host, palist->pop3user, palist->pop3pass);
155                 pptr = palist;
156                 palist = palist->next;
157                 free(pptr);
158         }
159
160         lprintf(CTDL_DEBUG, "pop3client ended\n");
161         last_run = time(NULL);
162         doing_pop3client = 0;
163 }
164
165 #endif
166
167 CTDL_MODULE_INIT(pop3client)
168 {
169 #ifdef POP3_AGGREGATION
170         CtdlRegisterSessionHook(pop3client_scan, EVT_TIMER);
171 #endif
172
173         /* return our Subversion id for the Log */
174         return "$Id:  $";
175 }