#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>

#include <fstream.h>

#include <tools.h>
#include <logf.h>
#include <dboxpath.h>
#include <getpeer.h>
#include <sfolderrfc.h>
#include <deliverrfc.h>
#include <lock.h>
#include "pop.h"
#include "passwd.h"

char peer[TEXTLEN];

dboxpopt::dboxpopt()
 {
  transfer=FALSE;
  protocol="unknown";
  timeout_minutes=10;
 }

bool dboxpopt::getcommand()
 {
  char *tptr;
  char line[1000];

  alarm(timeout_minutes*60);
  fflush(stdout);
  if(fgets(line, 900, stdin)==NULL) return TRUE; 
  alarm(0);

  tptr=strchr(line, '\r'); if(tptr!=NULL) *tptr=0;
  tptr=strchr(line, '\n'); if(tptr!=NULL) *tptr=0;

  commandline=line;
 
  return FALSE;
 }

bool dboxpopt::login(const std::string &password)
 {
  up.setfilename();

  if(check_unix_passwd(up.name, password.c_str(), uid, protocol.c_str()))
   {
    logf.printf("login", "invalid login: \"%s\"", up.name);
    return TRUE;
   }

  logf.printf("login", "successfull login of %s", up.name);

  std::string path;
  getboxuserdir(path, config.boxdir, up.name);
  path+=".";
  if(access(path.c_str(), 00)!=0)
   {
    up.setfilename();
    makepath(up.getpath());
    if(!up.lock())
     {
      up.write();
      up.unlock();
     }
    getboxusermaildir(path, config.boxdir, up.name, "");
    makepath(path.c_str());

    std::string foldername="0@";
    foldername+=up.name;
    fp.setname(foldername);
    fp.setfilename();
    makepath(fp.getpath());
    if(!fp.lock())
     {
      fp.write();
      fp.unlock();
     }
   }

  transfer=TRUE;

  return FALSE;
 }

void getpeer()
 {
  std::string peer_string;

  getpeer(peer_string);

  strmaxcpy(peer, peer_string.c_str(), TEXTLEN-1);
 }

static void append(const std::string &message,
                   userpt &up,
                   const std::string &from)
 {
  rfcmessaget rfcm;
  dword nr;

  rfcm.data=message.c_str();
  rfcm.endoffile=rfcm.data+message.size();
  rfcm.endofmail=rfcm.endoffile;

  if(rfcm.parse() || rfcm.headerlen==0)
   {
   }
  else 
   {
    std::string subject;
    rfcm.findsingleheader(subject, "Subject");
    if(subject!="DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA")
     {
      std::string to;
      rfcm.findsingleheader(to, "X-POP3-Rcpt");

      deliver_mail(rfcm, up, to, from);
     }
   }
 }

void dboxpopt::movemail()
 {
  std::string mailbox_file, tmp_file;
  char pid[TEXTLEN];

  snprintf(pid, TEXTLEN, "%d", getpid());

  mailbox_file=GLOBALMAILDIR;
  mailbox_file+=up.name;

  if(filelength(mailbox_file.c_str())==0) return;

  if(lock("dkimap", "movemail", config.boxname, "movemail"))
    return; 

  getdboxtempdir(tmp_file, config.dboxdir);
  tmp_file+="movemail.";
  tmp_file+=pid;
  unlink(tmp_file.c_str());

  pid_t child_pid=fork();

  switch(child_pid)
   {
   case -1:
    logf.printf("movemail", "fork() failed");
    break;

   case 0:
    //setreuid(uid, -1); // fall back to users uid
    execl(MOVEMAIL,
          "movemail",
          mailbox_file.c_str(),
          tmp_file.c_str(), NULL);  
    logf.printf("movemail", "failed to execl %s", MOVEMAIL);
    exit(1);

   default:
    int status;
    waitpid(child_pid, &status, 0);
   }

  std::ifstream in(tmp_file.c_str(), std::ios::in|std::ios::binary);
  if(in)
   {
    char line[10000], ch;
    std::string message, from;

    while(!(in.eof() || in.fail()))
     {
      if(in.get(line, 9000))
       {
        in.get(ch); // \n lesen
        if(strncmp(line, "From ", 5)==0)
         {
          if(!message.empty())
           {
            append(message, up, from);
            message="";
            from="";
           }

          const char *tptr=line+5;
          while(*tptr!=0 && *tptr!=' ' && *tptr!='\t' &&
                *tptr!='\r' && *tptr!='\n') from+=*(tptr++);
         }        
        else
         {
          message+=line;
          if(strchr(line, '\r')==NULL) message+='\r';
          message+='\n';
         }
       }
     }

    if(!message.empty()) append(message, up, from);
   }
  else
   {
    cout << "ERROR: movemail failed 1\n";
   }

  unlink(tmp_file.c_str());

  unlock("dkimap", "movemail", config.boxname);
 }


syntax highlighted by Code2HTML, v. 0.9.1