~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to plugin_pop3.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:24:15 UTC
  • mto: This revision was merged to the branch mainline in revision 750.
  • Revision ID: siretart@tauware.de-20110427172415-6n4aptmvmz0eztvm
Tags: upstream-0.11.0~svn1143
ImportĀ upstreamĀ versionĀ 0.11.0~svn1143

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: plugin_pop3.c 728 2007-01-14 11:14:38Z michael $
 
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_pop3.c $
 
3
 *
 
4
 * Plugin to check POP3 mail accounts
 
5
 *
 
6
 * Copyright (C) 2004 Javi Garcia Dominguez (aka Stolz) <javi@gsmlandia.com>
 
7
 * Based on code from  pop3check (C) 1999 http://sourceforge.net/projects/pop3check
 
8
 *     Simon Liddington <squidly@users.sourceforge.net> is the pop3check current maintainer.
 
9
 *     The pop3check original author is Steven Radack <steve@lconn.net>.
 
10
 *
 
11
 * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 
12
 *
 
13
 * This file is a pluging for LCD4Linux.
 
14
 *
 
15
 * LCD4Linux is free software; you can redistribute it and/or modify
 
16
 * it under the terms of the GNU General Public License as published by
 
17
 * the Free Software Foundation; either version 2, or (at your option)
 
18
 * any later version.
 
19
 *
 
20
 * LCD4Linux is distributed in the hope that it will be useful,
 
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
23
 * GNU General Public License for more details.
 
24
 *
 
25
 * You should have received a copy of the GNU General Public License
 
26
 * along with this program; if not, write to the Free Software
 
27
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
28
 *
 
29
 */
 
30
 
 
31
 
 
32
#include "config.h"
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <ctype.h>
 
36
#include "debug.h"
 
37
#include "plugin.h"
 
38
#include "cfg.h"
 
39
 
 
40
/*added */
 
41
#include <sys/socket.h>
 
42
#include <sys/types.h>
 
43
/*#include <netinet/in.h> */
 
44
#include <netdb.h>
 
45
#include <unistd.h>
 
46
/*#include <pwd.h> */
 
47
#include <stdio.h>
 
48
 
 
49
#ifdef WITH_DMALLOC
 
50
#include <dmalloc.h>
 
51
#endif
 
52
 
 
53
/*POP 3 */
 
54
#define POPERR           "-ERR"
 
55
#define LOCKEDERR        "-ERR account is locked by another session or for maintenance, try again."
 
56
#define BUFSIZE          8192
 
57
#define POP3PORT         110
 
58
#define MAX_NUM_ACCOUNTS 3
 
59
 
 
60
 
 
61
struct check {
 
62
    int id;
 
63
    char *username;
 
64
    char *password;
 
65
    char *server;
 
66
    int port;
 
67
    int messages;
 
68
    struct check *next;
 
69
};
 
70
 
 
71
 
 
72
/************************ PROTOTYPES  ********************************/
 
73
/* list */
 
74
static struct check *check_node_alloc(void);
 
75
static void check_node_add(struct check **head, struct check *new_check);
 
76
static void check_destroy(struct check **head);
 
77
 
 
78
/* pop3 */
 
79
static void pop3_check_messages(struct check *hi, int verbose);
 
80
static void pop3_recv_crlf_terminated(int sockfd, char *buf, int size);
 
81
 
 
82
/* socket  */
 
83
static int tcp_connect(struct check *hi);
 
84
 
 
85
 
 
86
/************************ GLOBAL ***********************************/
 
87
static char Section[] = "Plugin:POP3";
 
88
static struct check *head = NULL;
 
89
/********************************************************************/
 
90
 
 
91
 
 
92
/************************ LIST  ***********************************/
 
93
 
 
94
static struct check *check_node_alloc(void)
 
95
{
 
96
    struct check *new_check;
 
97
    new_check = (struct check *) calloc(1, sizeof(struct check));
 
98
    if (new_check == NULL) {
 
99
        error("[POP3] out of memory\n");
 
100
    }
 
101
    return new_check;
 
102
}
 
103
 
 
104
static void check_node_add(struct check **head, struct check *new_check)
 
105
{
 
106
    new_check->next = *head;
 
107
    *head = new_check;
 
108
}
 
109
 
 
110
static void check_destroy(struct check **head)
 
111
{
 
112
    struct check *iter;
 
113
    while (*head) {
 
114
        iter = (*head)->next;
 
115
        free((*head)->username);
 
116
        free((*head)->password);
 
117
        free((*head)->server);
 
118
        free(*head);
 
119
        *head = iter;
 
120
    }
 
121
    *head = NULL;
 
122
}
 
123
 
 
124
/************************ POP3  ********************************/
 
125
static void pop3_check_messages(struct check *hi, int verbose)
 
126
{
 
127
    char buf[BUFSIZE];
 
128
    int sockfd;
 
129
 
 
130
    if ((sockfd = tcp_connect(hi)) < 0) {
 
131
        hi->messages = -1;
 
132
        return;
 
133
    }
 
134
 
 
135
    pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf));        /* server greeting */
 
136
    if (verbose)
 
137
        info("[POP3] %s -> %s\n", hi->server, buf);
 
138
 
 
139
    snprintf(buf, sizeof(buf), "USER %s\r\n", hi->username);
 
140
    write(sockfd, buf, strlen(buf));
 
141
    buf[strlen(buf) - 1] = '\0';
 
142
    if (verbose)
 
143
        info("[POP3] %s <- %s\n", hi->server, buf);
 
144
    pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf));        /* response from USER command */
 
145
    if (verbose)
 
146
        info("[POP3] %s -> %s\n", hi->server, buf);
 
147
 
 
148
    snprintf(buf, sizeof(buf), "PASS %s\r\n", hi->password);
 
149
    write(sockfd, buf, strlen(buf));
 
150
    if (verbose)
 
151
        info("[POP3] %s <- PASS ???\n", hi->server);
 
152
    pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf));        /* response from PASS command */
 
153
    if (verbose)
 
154
        info("[POP3] %s -> %s\n", hi->server, buf);
 
155
 
 
156
    if (strncmp(buf, LOCKEDERR, strlen(LOCKEDERR)) == 0) {
 
157
        hi->messages = -2;
 
158
        close(sockfd);
 
159
        return;
 
160
    }
 
161
    if (strncmp(buf, POPERR, strlen(POPERR)) == 0) {
 
162
        error("[POP3] error logging into %s\n", hi->server);
 
163
        error("[POP3] server responded: %s\n", buf);
 
164
        hi->messages = -1;
 
165
        close(sockfd);
 
166
        return;
 
167
    }
 
168
 
 
169
    snprintf(buf, sizeof(buf), "STAT\r\n");
 
170
    write(sockfd, buf, strlen(buf));
 
171
    if (verbose)
 
172
        info("[POP3] %s <- STAT\n", hi->server);
 
173
    pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf));        /* response from PASS command */
 
174
    if (verbose)
 
175
        info("[POP3] %s -> %s\n", hi->server, buf);
 
176
 
 
177
    strtok(buf, " ");
 
178
    hi->messages = atoi(strtok(NULL, " "));
 
179
 
 
180
    snprintf(buf, sizeof(buf), "QUIT\r\n");
 
181
    write(sockfd, buf, strlen(buf));
 
182
    if (verbose)
 
183
        info("[POP3] %s <- QUIT\n", hi->server);
 
184
    pop3_recv_crlf_terminated(sockfd, buf, sizeof(buf));        /* response from QUIT command */
 
185
    if (verbose)
 
186
        info("[POP3] %s -> %s\n", hi->server, buf);
 
187
 
 
188
    close(sockfd);
 
189
}
 
190
 
 
191
static void pop3_recv_crlf_terminated(int sockfd, char *buf, int size)
 
192
{
 
193
    /* receive one line server responses terminated with CRLF */
 
194
    char *pos;
 
195
    int bytes = 0;
 
196
    memset(buf, 0, size);
 
197
    while ((pos = strstr(buf, "\r\n")) == NULL)
 
198
        bytes += read(sockfd, buf + bytes, size - bytes);
 
199
    *pos = '\0';
 
200
}
 
201
 
 
202
/************************ SOCKET  ********************************/
 
203
static int tcp_connect(struct check *hi)
 
204
{
 
205
    struct sockaddr_in addr;
 
206
    struct hostent *he = gethostbyname(hi->server);
 
207
    int sockfd;
 
208
 
 
209
    if (hi == NULL)
 
210
        return -1;
 
211
 
 
212
    if (!he) {
 
213
        error("[POP3] Failed to lookup %s\n", hi->server);
 
214
        return (-1);
 
215
    }
 
216
 
 
217
    memset((char *) &addr, 0, sizeof(struct sockaddr_in));
 
218
    addr.sin_family = AF_INET;
 
219
    memcpy(&(addr.sin_addr.s_addr), he->h_addr, he->h_length);
 
220
    addr.sin_port = htons(hi->port);
 
221
 
 
222
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 
223
        perror("socket()");
 
224
        return (-1);
 
225
    }
 
226
 
 
227
    if (connect(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr)) < 0) {
 
228
        perror("connect()");
 
229
        close(sockfd);
 
230
        return (-1);
 
231
    }
 
232
 
 
233
    return (sockfd);
 
234
}
 
235
 
 
236
 
 
237
static int getConfig(void)
 
238
{
 
239
    struct check *node = NULL;
 
240
    int i, n = 0;
 
241
    char *user = (char *) calloc(1, sizeof("user") + sizeof(int));
 
242
    char *password = (char *) calloc(1, sizeof("password") + sizeof(int));
 
243
    char *server = (char *) calloc(1, sizeof("server") + sizeof(int));
 
244
    char *port = (char *) calloc(1, sizeof("port") + sizeof(int));
 
245
 
 
246
    for (i = 1; i <= MAX_NUM_ACCOUNTS; i++) {
 
247
        char *x;
 
248
        sprintf(user, "user%d", i);
 
249
        sprintf(password, "password%d", i);
 
250
        sprintf(server, "server%d", i);
 
251
        sprintf(port, "port%d", i);
 
252
 
 
253
        x = cfg_get(Section, server, "");
 
254
        if (*x == '\0') {
 
255
            info("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, server, cfg_source(), i);
 
256
            free(x);
 
257
        } else {
 
258
            node = check_node_alloc();
 
259
            node->id = i;
 
260
            node->server = x;
 
261
            node->messages = 0;
 
262
            node->next = NULL;
 
263
 
 
264
            x = cfg_get(Section, user, "");
 
265
            if (*x == '\0') {
 
266
                info("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, user, cfg_source(), i);
 
267
                free(x);
 
268
            } else {
 
269
                node->username = x;
 
270
                x = cfg_get(Section, password, "");
 
271
                if (*x == '\0') {
 
272
                    info("[POP3] No '%s.%s' entry from %s, disabling POP3 account #%d", Section, password, cfg_source(),
 
273
                         i);
 
274
                    free(x);
 
275
                } else {
 
276
                    node->password = x;
 
277
                    if (cfg_number(Section, port, POP3PORT, 1, 65536, &node->port) < 1) {
 
278
                        info("[POP3] No '%s.%s' entry from %s, %d will be used for account #%d", Section, port,
 
279
                             cfg_source(), POP3PORT, i);
 
280
                    }
 
281
                    check_node_add(&head, node);
 
282
                    n++;
 
283
                }
 
284
            }
 
285
        }
 
286
    }
 
287
    return (n);
 
288
}
 
289
 
 
290
 
 
291
static int configure_pop3(void)
 
292
{
 
293
    static int configured = 0;
 
294
    int n;
 
295
 
 
296
    if (configured != 0)
 
297
        return configured;
 
298
 
 
299
    n = getConfig();
 
300
    /* by now, head should point to a list of all our accounts */
 
301
    if (head) {
 
302
        info("[POP3] %d POP3 accounts have been succesfully defined", n);
 
303
        configured = 1;
 
304
    } else {
 
305
        configured = -1;
 
306
    }
 
307
    return configured;
 
308
}
 
309
 
 
310
 
 
311
static void my_POP3check(RESULT * result, RESULT * check)
 
312
{
 
313
    double param = R2N(check);
 
314
    struct check *node = NULL;
 
315
    double value;
 
316
 
 
317
    if (configure_pop3() < 0) {
 
318
        value = -1;
 
319
        SetResult(&result, R_NUMBER, &value);
 
320
        return;
 
321
    }
 
322
 
 
323
    for (node = head; node; node = node->next) {
 
324
        if (node->id == param)
 
325
            break;
 
326
    }
 
327
    if (node == NULL) {         /*Inexistent account */
 
328
        value = -1;
 
329
    } else {
 
330
        pop3_check_messages(node, 0);
 
331
        value = (double) node->messages;
 
332
    }
 
333
    SetResult(&result, R_NUMBER, &value);
 
334
}
 
335
 
 
336
 
 
337
int plugin_init_pop3(void)
 
338
{
 
339
    AddFunction("POP3check", 1, my_POP3check);
 
340
    return 0;
 
341
}
 
342
 
 
343
void plugin_exit_pop3(void)
 
344
{
 
345
    check_destroy(&head);
 
346
}