/* this is libspopc.h file.
 * this is part of the libspopc library sources
 * copyright © 2002 Benoit Rouits <brouits@free.fr>
 * released under the terms of GNU LGPL
 * (GNU Lesser General Public Licence).
 * libspopc offers simple API for a pop3 client (MTA).
 * See RFC 1725 for pop3 specifications.
 * more information on http://brouits.free.fr/libspopc/
 */
#ifndef _LIBSPOPC_H
#define _LIBSPOPC_H
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

/***************************************
 * low-level methods for a pop3 client *
 ***************************************/
/**************
 * connecting *
 **************/

int pop3_prepare(const char* servername, const int port, struct sockaddr_in* connection, struct hostent* server);
/* prepares the pop session and returns a socket descriptor */

char* pop3_connect(int sock, struct sockaddr_in* connection);
/* connects to the server through the sock and returns server's welcome */

void pop3_disconnect(int sock);
/* close socket  */


/****************
 * pop3 queries *
 ****************/

char* pop3_user(int sock, char* name);
/* performs "USER" pop query and returns server's <64 bytes response */

char* pop3_pass(int sock, char* pw);
/* performs "PASS" pop query and return server's <63 bytes response */

char* pop3_quit(int sock);
/* performs "QUIT" pop query and returns server's <64 bytes response */

char* pop3_stat(int sock);
/* performs "STAT" pop query and returns server's <64 bytes response */

char* recv_rest(int sock, char* buf, int cs, int bs);
/* recv rest of data through sock, given a cs bytes filled buffer of total size bs */
/* end of data is assumed when data has a "\n.\n" or "\n.\0" string */

char* pop3_list(int sock, int id);
/* performs a "LIST" pop query and returns server's (long) response */

char* pop3_retr(int sock, int id);
/* performs a "RETR" pop query and returns server's (long) response */

char* pop3_dele(int sock, int id);
/* performs a "DELE" pop query and returns server's <64 bytes response */

char* pop3_noop(int sock);
/* performs a "NOOP" pop query and returns server's <64 bytes response */

char* pop3_rset(int sock);
/* performs a "RSET" pop query and returns server's <64 bytes response */

char* pop3_top(int sock, int id, int lines);
/* performs a "TOP" pop query and returns server's (long) response */

char* pop3_uidl(int sock, int id);
/* performs a "UIDL" pop query and returns server's (long) response */

char* pop3_apop(int sock, char* name, char* digest);
/* performs a "APOP" secure pop query and returns server's <64 bytes response */

/*********************
 * parsing utilities *
 *********************/
#define DOTLINE(s) (((s)[0]=='\r'||(s)[0]=='\n')&&((s)[1]=='.')&&((s)[2]=='\r'||(s)[2]=='\n'||(s)[2]=='\0')) /* be careful, it's different to ESR's pop3.c ;-) */
#define DOTBEGIN(s) (((s)[0]=='\r'||(s)[0]=='\n')&&((s)[1]=='.'))

int dotline(char* buf, int bs);
/* returns 1 if buf contains a "\n.\n" or "\n.\0" substring */

int pop3_error(char* string);
/* returns 1 if pop server error reply (i.e : -ERR ...) */

/**********************************
 * formatting methods, post query *
 **********************************/
char* nextline(char* string);
/* returns a pointer to the next line of given string */

char* retr2msg(char* data);
/* retruns formatted mail from a pop RETR X query */
/* should only be called on data returned by pop3_retr() */

int* list2array(char* poplist);
/* returns an int array of sizes of messages from a LIST pop query */
/* array[0] holds id of the array's element */
/* should only be called on data received by a pop3_list() request */

int listi2size(char* resp);
/* grep the given size (in bytes) in resp after a pop3_list(sock,ID) request */

int stat2last(char* resp);
/* returns the number of stored messages on pop server */

int stat2bytes(char* resp);
/* returns the sumsize in bytes of all stored messages on server */
/* should only be called just after a pop3_stat() request */

char** uidl2array(char* resp);
/* returns an array of unique strings for each message id */
/* array[0] gives array's last id */
/* should only be called just after a pop3_uidl() request */

char* uidli2sig(char* resp);
/* array[0] holds id of the array's element */
/* should only be called on data received by a pop3_list() request */

int listi2size(char* resp);
/* grep the given size (in bytes) in resp after a pop3_list(sock,ID) request */

int stat2last(char* resp);
/* returns the number of stored messages on pop server */

int stat2bytes(char* resp);
/* returns the sumsize in bytes of all stored messages on server */
/* should only be called just after a pop3_stat() request */

char** uidl2array(char* resp);
/* returns an array of unique strings for each message id */
/* array[0] gives array's last id */
/* should only be called just after a pop3_uidl() request */

char* uidli2sig(char* resp);
/* greps signature from server resp */
/* should only be called after a pop3_uidl(sock,ID) */


/***************************************************
 * high-level objects and methods for a SIMPLE MTA *
 ***************************************************/

typedef enum{AUTHORIZATION,TRANSACTION,UPDATE}popstate;
/* pop server states definition from RFC 1725*/

typedef struct{
        int sock;/* socket descriptor */
        struct sockaddr_in* connection;
        struct hostent* server;
        popstate state;/* pop server state */
        int* list;/* pop messages size list */
        char** uidl;/* pop messages signature list */
        int bytes;/* total stored (in bytes) on pop server */
        int last;/* last message id */
        int del;/* 0|1 flag to ask deletion of retrieved messages */
}popsession;

#define popbytes(s) ((s)->bytes)
/* gives the total stored data size (in bytes) on the pop server */
/* arg is type 'popsession*'; return is type 'int' */

#define popnum(s) ((s)->last)
/* gives the number of messages stored on the pop server before any operation */
/* arg is type 'popsession*'; return is type 'int' */

#define popsetdel(s) ((s)->del=1)
/* asks the session to delete any retrieved messages on the server */
/* arg is type 'popsession*' */

#define popsetundel(s) ((s)->del=0)
/* asks the session to not delete any retrieved message on the server */
/* arg 's' is type 'popsession*' */

#define popmsgsize(s,i) ((s)->list[(i)])
/* gives the size of message 'i' for session 's' */
/* args are type 'session*'(s) and 'int'(i) */
/* i must not be 0 */

#define popmsguid(s,i) ((s)->uidl[(i)])
/* gives the 'char*' uid (unique signature) of 'int' message id */

char* popbegin(char* servername,char* user,char* pass, popsession** sp);
/* prepares, connect and get lists of messages stored on pop server */
/* you must give a valid servername, user and pass */
/* returns an error message if a problem occurs, else NULL */

char* popgethead(popsession* session, int id);
/* returns the header of a message (id from 1 to popnum()) or NULL if bad id */

char* popgetmsg(popsession* session, int id);
/* returns a message (id from 1 to popnum()) or NULL if bad id */

void popend(popsession* session);
/* quit and destroys pop session */
#endif