📄 pop3.c
字号:
/* * libsms pop3 * * Authors: Michael Jochum <e9725005@stud3.tuwien.ac.at> * * TODO: * * Fixes: Michael Jochum : Rewrite for new socket functions * and new interface * * For license terms, see the file COPYING in the project directory. */#include <config.h>#include <gnome.h>#include <stdio.h>#include <string.h>#include <glib.h>#include "sock.h"#include "mail.h"#include "misc.h"#include "pop3.h"static GSmsPop3Error pop3_get_ok(const GSmsSocket * s, gchar * par){ gchar buf[POP3_BUFSIZE + 1]; if (gsms_socket_read_line(s, buf, sizeof(buf)) < 0) return GSMS_POP3_ERROR_NET; if (strncmp(buf, "+OK", 3) == 0) { if (buf[3] == ' ' && par != NULL) strcpy(par, buf + 4); } else if (strncmp(buf, "-ERR", 4) == 0) return GSMS_POP3_ERR; else return GSMS_POP3_ERROR_PROTO; return GSMS_POP3_OK;}static GSmsMail *find_uidl(GList * mails, const gchar * uid){ GList *mailent; GSmsMail *mail; mailent = g_list_first(mails); while (mailent != NULL) { mail = mailent->data; if (strcmp(mail->uid, uid) == 0) return mail; mailent = g_list_next(mailent); } return NULL;}static GList *pop3_expire(GList * mails){ GList *mailent; GList *mailexp; GSmsMail *mail; mailent = g_list_first(mails); while (mailent != NULL) { mail = mailent->data; mailent = g_list_next(mailexp = mailent); if (!mail->on_server) { mails = g_list_remove_link(mails, mailexp); mail_destructor(mail); } } return mails;}static gint pop3_get_uidl(const GSmsSocket * s, GList ** mails){ gint ok; gchar buf[POP3_BUFSIZE]; gchar uid[POP3_BUFSIZE]; gint num; GList *mailent; GSmsMail *mail; /* set on_server=FALSE for all GSmsMails */ mailent = g_list_first(*mails); while (mailent != NULL) { mail = mailent->data; mail->on_server = FALSE; mailent = g_list_next(mailent); } gsms_socket_write_str(s, "UIDL\n"); /* TODO: Error check */ ok = pop3_get_ok(s, NULL); if (ok == GSMS_POP3_OK) { while ((ok = gsms_socket_read_line(s, buf, sizeof(buf))) > 0) { if (buf[0] == '.') break; if (sscanf(buf, "%d %s", &num, uid) == 2) { if ((mail = find_uidl(*mails, uid)) == NULL) { mail = g_new0(GSmsMail, 1); mail->uid = g_strdup(uid); mail->new = TRUE; *mails = g_list_append(*mails, mail); } mail->on_server = TRUE; mail->msg_num = num; } } ok = ok > 0 ? GSMS_POP3_OK : GSMS_POP3_ERROR_NET; } else if (ok == GSMS_POP3_ERR) { /* implement alternativ method */ g_log(NULL, G_LOG_LEVEL_CRITICAL, _("Error: Your POP3 server does not implement the UIDL command!")); } /* remove mesages from the list which are no longer on the server */ *mails = pop3_expire(*mails); /* TODO: get headers for new mails */ return ok;}static GSmsPop3Error pop3_get_header(const GSmsSocket * s, GSmsMail * mail){ gint length; GString *head; gchar buf[POP3_BUFSIZE]; GSmsPop3Error ok; gsms_socket_printf(s, "TOP %d 0\n", mail->msg_num); if ((ok = pop3_get_ok(s, NULL)) != GSMS_POP3_OK) { /* if the command is not supported (ok == POP3_ERR) we could write a slow method wich would download the whole email => verrrrry slow => so we return an error code for now */ return ok; } head = g_string_sized_new(POP3_BUFSIZE); while ((length = gsms_socket_read_line(s, buf, sizeof(buf))) > 0) { if (buf[0] == '.') break; head = g_string_append(head, buf); } if (length <= 0) { g_string_free(head, TRUE); return GSMS_POP3_ERROR_NET; } mail->head = g_strdup(head->str); g_string_free(head, TRUE); mail->from = mail_get_field(mail->head, "From:"); mail->to = mail_get_field(mail->head, "To:"); mail->subject = mail_get_field(mail->head, "Subject:"); return GSMS_POP3_OK;}static GSmsPop3Error pop3_get_all_new_headers(const GSmsSocket * s, GList * mails){ GList *mailent; GSmsMail *mail; GSmsPop3Error res; mailent = g_list_first(mails); while (mailent != NULL) { mail = mailent->data; mailent = g_list_next(mailent); if (mail->new == TRUE) { if ((res = pop3_get_header(s, mail)) < 0) return res; } } return GSMS_POP3_OK;}/********* public functions **********/GSmsPop3 *gsms_pop3_init(GSmsSocket * s){ GSmsPop3 *pd; g_return_val_if_fail(s != NULL, NULL); if (pop3_get_ok(s, NULL) != GSMS_POP3_OK) return NULL; pd = g_new(GSmsPop3, 1); pd->state = GSMS_POP3_AUTHORIZATION; pd->s = s; pd->mails = NULL; return pd;}GSmsPop3Error gsms_pop3_auth(GSmsPop3 * pd, const gchar * uname, const gchar * passwd){ GSmsPop3Error res; g_return_val_if_fail(pd != NULL, GSMS_POP3_ERROR); g_return_val_if_fail(uname != NULL, GSMS_POP3_ERROR); g_return_val_if_fail(passwd != NULL, GSMS_POP3_ERROR); if (pd->state != GSMS_POP3_AUTHORIZATION) return GSMS_POP3_ERROR_STATE; if (gsms_socket_printf(pd->s, "USER %s\n", uname) < 0) return GSMS_POP3_ERROR_NET; if ((res = pop3_get_ok(pd->s, NULL)) != GSMS_POP3_OK) return res; gsms_socket_printf(pd->s, "PASS %s\n", passwd); res = pop3_get_ok(pd->s, NULL); if (res == GSMS_POP3_OK) pd->state = GSMS_POP3_TRANSACTION; return res;}GSmsPop3Error gsms_pop3_mail_getnew(GSmsPop3 * pd){ GSmsPop3Error res; g_return_val_if_fail(pd != NULL, GSMS_POP3_ERROR); if ((res = pop3_get_uidl(pd->s, &pd->mails)) != GSMS_POP3_OK) return res; res = pop3_get_all_new_headers(pd->s, pd->mails); return res;}GList *gsms_pop3_get_mailbox(GSmsPop3 * pd){ return pd->mails;}void gsms_pop3_set_mailbox(GSmsPop3 * pd, GList * mb){ pd->mails = mb; return;}GSmsPop3Error gsms_pop3_load_headers(GSmsPop3 * pd, FILE * f){ GSmsMail *mail; gchar buf[POP3_BUFSIZE]; GString *head; gboolean done = FALSE; gchar *p; g_return_val_if_fail(pd != NULL, GSMS_POP3_ERROR); g_return_val_if_fail(f != NULL, GSMS_POP3_ERROR); /* TODO: free_mailbox(pd->mails); */ pd->mails = NULL; /* read file header */ if (fgets(buf, sizeof(buf), f) == NULL) { return GSMS_POP3_ERROR; } if (strncmp(buf, "# GSMS POP3 Headers; Version 1", 29) != 0) return GSMS_POP3_ERROR; /* read mails */ if (fgets(buf, sizeof(buf), f) == NULL) { return GSMS_POP3_ERROR; } if (buf[0] != '.') return GSMS_POP3_ERROR; while (!done) { if (buf[1] != ' ') return GSMS_POP3_ERROR; mail = g_new0(GSmsMail, 1); gsms_str_strip_crlf(buf); mail->uid = g_strdup(buf + 2); head = g_string_sized_new(POP3_BUFSIZE); while ((p = fgets(buf, sizeof(buf), f)) != NULL) { if (buf[0] == '.') break; head = g_string_append(head, buf); } if (p == NULL && !feof(f)) { g_free(mail); g_string_free(head, TRUE); return GSMS_POP3_ERROR; } if (buf[0] != '.') done = TRUE; mail->head = g_strdup(head->str); g_string_free(head, TRUE); mail->from = mail_get_field(mail->head, "From:"); mail->to = mail_get_field(mail->head, "To:"); mail->subject = mail_get_field(mail->head, "Subject:"); pd->mails = g_list_append(pd->mails, mail); } return GSMS_POP3_OK;}GSmsPop3Error gsms_pop3_save_headers(GSmsPop3 * pd, FILE * f){ GList *mailent; GSmsMail *mail; g_return_val_if_fail(pd != NULL, GSMS_POP3_ERROR); g_return_val_if_fail(f != NULL, GSMS_POP3_ERROR); fprintf(f, "# GSMS POP3 Headers; Version 1\n"); mailent = g_list_first(pd->mails); while (mailent != NULL) { mail = mailent->data; mailent = g_list_next(mailent); if (mail->uid != NULL) { if (fprintf(f, ". %s\n", mail->uid) <= 0) return GSMS_POP3_ERROR; if (fprintf(f, "%s", mail->head) <= 0) return GSMS_POP3_ERROR; } } return GSMS_POP3_OK;}GSmsPop3Error gsms_pop3_mail_delete(GSmsPop3 * pd, GSmsMail * m){ GSmsPop3Error res; gchar buf[POP3_BUFSIZE]; gchar uid[POP3_BUFSIZE]; gint num; g_return_val_if_fail(m != NULL, GSMS_POP3_ERROR); if (pd->state != GSMS_POP3_TRANSACTION) return GSMS_POP3_ERROR_STATE; /* security check: */ /* check if the mail on the server has the same uid */ if (gsms_socket_printf(pd->s, "UIDL %d\n", m->msg_num) < 0) return GSMS_POP3_ERROR_NET; if ((res = pop3_get_ok(pd->s, buf)) != GSMS_POP3_OK) return res; if (sscanf(buf, "%d %s", &num, uid) != 2) return GSMS_POP3_ERROR_PROTO; if (num != m->msg_num) return GSMS_POP3_ERROR_PROTO; if (strcmp(uid, m->uid) != 0) return GSMS_POP3_ERROR; if ((res = gsms_socket_printf(pd->s, "DELE %d\n", num)) < 0) return res; if ((res = pop3_get_ok(pd->s, buf)) != GSMS_POP3_OK) return res; m->on_server = FALSE; pd->mails = pop3_expire(pd->mails); return GSMS_POP3_OK;}GSmsPop3Error gsms_pop3_mail_get_body(GSmsPop3 * pd, GSmsMail * m){ GSmsPop3Error res; gchar buf[POP3_BUFSIZE]; GString *body; gint length; g_return_val_if_fail(m != NULL, GSMS_POP3_ERROR); if (pd->state != GSMS_POP3_TRANSACTION) return GSMS_POP3_ERROR_STATE; if (gsms_socket_printf(pd->s, "RETR %d\n", m->msg_num) < 0) return GSMS_POP3_ERROR_NET; if ((res = pop3_get_ok(pd->s, NULL)) != GSMS_POP3_OK) return res; body = g_string_sized_new(POP3_BUFSIZE); while ((length = gsms_socket_read_line(pd->s, buf, sizeof(buf))) > 0) { if (buf[0] == '.' && buf[1] == '.') { body = g_string_append(body, buf + 1); continue; } else { break; } body = g_string_append(body, buf); } if (length <= 0) { g_string_free(body, TRUE); return -1; /* TODO ERROR CODE */ } m->body = g_strdup(body->str); g_string_free(body, TRUE); return GSMS_POP3_OK;}/* ATTN: You have to free your Mail list !!! */GSmsPop3Error gsms_pop3_close(GSmsPop3 * pd){ GSmsPop3Error res; if (gsms_socket_write_str(pd->s, "QUIT\n") < 0) return GSMS_POP3_ERROR_NET; if ((res = pop3_get_ok(pd->s, NULL)) != GSMS_POP3_OK) return res; g_free(pd); return GSMS_POP3_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -