
/* CGI program to read email from a pop server (port 110). */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>

extern int errno;  /* Error codes are returned here. */

struct hostent *hostent;
struct sockaddr_in sockaddr;
int sock,status,hostaddr,pop3_port=110,socket_option=0;
time_t current_time,hold_time;
char buffer[4096];
fd_set socket_read_status;
struct timeval socket_time_structure;

#define TIMEOUT_SECONDS 30

char pop3_server[128],pop3_account[32],pop3_password[32];
char temp_string[128],form_data_string[255];
int message_number,temp_int,temp_string_pointer;
char message_number_string[8],byte_count_string[8];
int byte_count,byte_count_string_pointer,message_bytes_read,extra_bytes_read;


/*----------------------------- Subroutines ----------------------------------*/

#include "web_based_email.h"

int list_messages_and_sizes(void)
{
/* Get the results of the LIST command for display. */
printf("<HR>List of messages and their sizes (in bytes):\n");
printf("<PRE>\n");
strcpy(buffer,"LIST");
strcat(buffer,"\r\n");
write(sock,buffer,strlen(buffer));
strcpy(temp_string,"");
while (strcmp(temp_string,"."))
  {
  if (get_message_from_socket())
    {
    printf("Error getting LIST response from POP3 server.\n");
    printf("</PRE>\n");
    shutdown(sock,2);
    close(sock);
    return(1);
    }
  if ((strcmp(temp_string,".")) && (strcmp(temp_string,"+OK")))
    printf("%s\n",temp_string);
  }
printf("</PRE>\n");
return(0);
}


/*----------------------------- Main Program ---------------------------------*/
int main(void)
{
printf("Content-type: text/html\n");  /* We have to return this line first. */
printf("\n");

printf("<HTML>\n");
printf("<HEAD>\n");
printf("<H2>POP3 Session Results</H2>\n");
printf("</HEAD>\n");
printf("<BODY>\n");

gets(form_data_string);  /* Get form data. */
temp_int = 0;
while (form_data_string[temp_int])
  {
  if (form_data_string[temp_int] == '+')
    form_data_string[temp_int] = ' ';
  temp_int++;
  }

/* Figure out POP3 information and load variables. */
find_field_in_form_data_string("pop3_server");
strcpy(pop3_server,temp_string);
find_field_in_form_data_string("pop3_account");
strcpy(pop3_account,temp_string);
find_field_in_form_data_string("pop3_password");
strcpy(pop3_password,temp_string);

/* Now get connected. */
strcpy(temp_string,pop3_server);
hostent = gethostbyname(temp_string);  /* Do DNS lookup. */
if (hostent == NULL)
  {
  printf("Couldn't resolve POP3 server address; quitting.\n");
  goto exit_program;
  }

sock = socket(AF_INET,SOCK_STREAM,0);  /* Allocate a socket. */
if (sock < 0)
  {
  printf("Unable to allocate a socket; quitting.\n");
  goto exit_program;
  }

/* Initialize sockaddr fields. */
memset(&sockaddr,0,sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
memcpy((char *)&(sockaddr.sin_addr.s_addr),(char *)hostent->h_addr_list[0],
 (size_t)hostent->h_length);
sockaddr.sin_port = htons(pop3_port);

/* Connect to remote port now. */
if (connect(sock,(struct sockaddr *)&sockaddr,sizeof(sockaddr)) < 0)
  {
  printf("Unable to connect to your POP3 server; quitting.\n");
  close(sock);
  goto exit_program;
  }
fcntl(sock,F_SETFL,O_NONBLOCK);  /* Set socket to non-blocking. */

/*-------------------------------------*/
/* Now we're ready to talk with the pop3 server, with text messages. */

/* Get welcome message from server. */
if (get_message_from_socket())
  {
  printf("Didn't get welcome message from POP3 server; quitting.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"+OK",3))  /* Not ok? */
  {
  printf("Bad welcome message from server: %s\n",temp_string);
  goto shut_down_and_close;
  }

strcpy(buffer,"USER ");
strcat(buffer,pop3_account);
strcat(buffer,"\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting USER response from POP3 server.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"+OK",3))  /* Not ok? */
  {
  printf("Bad name response from server: %s\n",temp_string);
  goto shut_down_and_close;
  }

strcpy(buffer,"PASS ");
strcat(buffer,pop3_password);
strcat(buffer,"\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting PASS response from POP3 server.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"+OK",3))  /* Didn't get +OK? */
  {
  printf("Bad password response from server; quitting.\n");
  goto shut_down_and_close;
  }
printf("<P>\n");
printf("Login message: %s\n",temp_string);

if (list_messages_and_sizes())
  goto shut_down_and_close;


/*--------------------*/

message_number = 0;
while (1)
  {
  message_number++;
  sprintf(message_number_string,"%d",message_number);
  strcpy(buffer,"LIST ");  /* Find out how many bytes the message has. */
  strcat(buffer,message_number_string);
  strcat(buffer,"\r\n");
  write(sock,buffer,strlen(buffer));
  if (get_message_from_socket())
    {
    printf("Timeout getting LIST response; quitting.\n");
    goto shut_down_and_close;
    }
  if (strncmp(temp_string,"+OK",3))  /* No such message? */
    break;

  temp_string_pointer = 4;  /* Point to 1st digit of message number in result string. */
  while (temp_string[temp_string_pointer++] != ' ')  /* Skip to start of byte count. */
    {
    }
  byte_count_string_pointer = 0;
  while (1)
    {
    if (temp_string[temp_string_pointer] == 10)
      break;
    if (temp_string[temp_string_pointer] == 13)
      break;
    if (temp_string[temp_string_pointer] == 0)
      break;
    byte_count_string[byte_count_string_pointer++] = temp_string[temp_string_pointer++];
    }
  byte_count_string[byte_count_string_pointer] = 0;  /* Terminate. */
  byte_count = atoi(byte_count_string);

  printf("<HR>\n");
  printf("<H4>Message %d (%d bytes):</H4>\n",message_number,byte_count);
  
  strcpy(buffer,"RETR ");  /* Ask the mail server for the message. */
  strcat(buffer,message_number_string);
  strcat(buffer,"\r\n");
  write(sock,buffer,strlen(buffer));
  if (get_message_from_socket())  /* Get response. */
    {
    printf("Timeout after RETR %d command; quitting.\n",message_number);
    goto shut_down_and_close;
    }
  if (strncmp(temp_string,"+OK",3))  /* Problem, or invalid message? */
    {
    printf("Unable to RETR after a successful LIST %d.\n",message_number);
    goto shut_down_and_close;
    }
  printf("<PRE>\n");
  printf("\n");

  message_bytes_read = 0;
  hold_time = time((time_t *) 0);
  while (message_bytes_read < byte_count)  /* Read and print email message. */
    {
    current_time = time((time_t *) 0);
    if (current_time - hold_time > TIMEOUT_SECONDS)
      {
      printf("POP3 timeout while printing message; quitting.\n");
      break;
      }
    if (read(sock,buffer,1) != 1)  /* Try to read just one character. */
      {
      sleep(1);
      continue;
      }
    hold_time = time((time_t *) 0);  /* Reset timer in case message is long. */
    message_bytes_read++;
    if (isprint(buffer[0]) || (buffer[0]==10) || (buffer[0]==13))  /* Avoid messing up the screen. */
      printf("%c",buffer[0]);  /* Print the character we received. */
    }
  fflush(stdout);

  extra_bytes_read = 0;
  hold_time = time((time_t *) 0);  /* Trash anything else for 5 seconds. */
  while (1)
    {
    current_time = time((time_t *) 0);
    if (current_time - hold_time > 5)
      break;
    if (read(sock,buffer,1) != 1)
      {
      sleep(1);
      continue;
      }
    if (++extra_bytes_read == 3)
      break;
    }

  printf("</PRE>\n");  /* Go back for another message. */
  }

if (list_messages_and_sizes())
  goto shut_down_and_close;


/*--------------------*/

/* Now log out from the pop3 server. */
strcpy(buffer,"QUIT\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting QUIT response from pop3 server.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"+OK",3))
  printf("POP3 QUIT response was: %s\n",temp_string);

if (message_number == 1)  /* No messages on file? */
  {
  printf("<HR>\n");
  printf("<H4>There were no messages waiting.</H4>\n");
  goto shut_down_and_close;
  }

/* Produce the form here for message deletion. */
printf("<HR>Enter message numbers to delete, separated by spaces.<BR>\n");
printf("<FORM METHOD=POST ACTION=\"pop3_delete_email\">\n");
printf("<INPUT TYPE=HIDDEN NAME=\"pop3_server\"   VALUE=\"%s\">\n",pop3_server);
printf("<INPUT TYPE=HIDDEN NAME=\"pop3_account\"  VALUE=\"%s\">\n",pop3_account);
printf("<INPUT TYPE=HIDDEN NAME=\"pop3_password\" VALUE=\"%s\">\n",pop3_password);
printf("<INPUT TYPE=TEXT   NAME=\"numbers_list\"  SIZE=\"32\">\n");
printf("<INPUT TYPE=SUBMIT VALUE=\"Delete these messages\">\n");
printf("</FORM>\n");


/*-------------------------------------*/
shut_down_and_close:
shutdown(sock,2);
close(sock);

exit_program:
printf("<HR>\n");
printf("Please send any comments on this web-based email system to\n");
printf("<A HREF=""mailto:alton@alton-moore.net"">Alton Moore</A>.\n");
printf("</BODY>\n");
printf("</HTML>\n");

return(0);
}

