#ifndef WIN32
#include <unistd.h>
#endif

#include <fstream>

#include <tools.h>
#include <logf.h>
#include <folder.h>
#include <folderindex.h>
#include <stringtools.h>
#include <dboxpath.h>
#include <mtoolrfc.h>
#include <sfolderrfc.h>
#include <parsefrom.h>
#include <rfc1522.h>

static bool checkfolderdir(const char *directory)
 {
  char tempstr[DIRLEN];

  snprintf(tempstr, DIRLEN, "%s.", directory);
  if(access(tempstr, 00)==0) return FALSE;

  return TRUE;
 }

bool spool_in_folder(rfcmessaget &m, const std::string &folder,
                     bool forceextern, const std::string &envelope_to,
                     const std::string &envelope_from)
 {
  dword nr;
  folderpt fp(folder.c_str());

  if(fp.lock("spool_in_folder"))
   {
    logf.printf("spool_in_folder",
      "fatal: folder %s is locked", fp.name);
    return TRUE;
   }

  bool result=spool_in_folder(m, fp, forceextern, envelope_to,
                              envelope_from, nr);

  fp.unlock();

  return result;
 }

extern "C" time_t parsedate(char *line, int *tz);

time_t parsedate(const std::string &header)
 {
  int tz;

  return parsedate((char *)header.c_str(), &tz);
 }

bool spool_in_folder(rfcmessaget &m, folderpt &fp,
                     bool forceextern, const std::string &envelope_to,
                     const std::string &envelope_from,
                     dword &nr)
 {
  folderindext fi;
  char envelope_to_header[TEXTLEN*2];
  char envelope_from_header[TEXTLEN*2];

  if(envelope_to!="")
    snprintf(envelope_to_header, TEXTLEN*2, 
      "X-POP3-Rcpt:\t%s\r\n"
      "Envelope-To:\t%s\r\n",
      envelope_to.c_str(), envelope_to.c_str());
  else
    envelope_to_header[0]=0;

  if(envelope_from!="")
    snprintf(envelope_from_header, TEXTLEN*2, "X-POP3-From:\t%s\r\n", 
      envelope_from.c_str());
  else
    envelope_from_header[0]=0;

  fp.setfilename();

  if(checkfolderdir(fp.getpath()))
   {
    logf.printf("spool_in_folder",
      "fatal: failed to access folder \"%s\"", fp.getpath());
    return TRUE;
   }

  fp.read();

   {
    char header_filename[DIRLEN];

    snprintf(header_filename, DIRLEN, "%sheader", fp.getpath());

    std::ofstream outfile(header_filename, ios::out|ios::app|ios::binary);
    if(!outfile)
     {
      logf.printf("spool_in_folder",
        "fatal: failed to open \"%s\"", header_filename);
      return TRUE;
     }

    fi.clear();

    std::string header; 

    m.findsingleheader(header, "Subject");
    header=decode_rfc1522(header);
    iso2ibm(header);
    strmaxcpy(fi.bet, header.c_str(), TEXTLEN-1);

     {
      std::string mailto, name;
      m.findsingleheader(header, "From");
      parse_from(header, mailto, name);
      std::string parsed_from=mailto;
      if(name!="") parsed_from+=" ("+decode_rfc1522(name)+")";
      strmaxcpy(fi.abs, parsed_from.c_str(), TEXTLEN-1);
     }

    m.findsingleheader(header, "Message-ID"); // TODO: mehr parsen
    strmaxcpy(fi.mid, header.c_str(), TEXTLEN-1);

    m.findsingleheader(header, "Date"); // TODO: mehr parsen
    fi.eda=parsedate(header);

    time(&fi.received);
    fi.len=m.len;
    fi.headerlen=m.headerlen+strlen(envelope_from_header)+
                 strlen(envelope_to_header);
    fi.flags.bodyextern=(forceextern || fi.len>EXTERNLEN);
    fi.flags.binary=FALSE;
    fi.flags.rfc=TRUE;
    fi.headeroffs=filelength(header_filename);
    fi.id=atol(fp|"nextid");
    if(fi.id==0) fi.id=1;

    outfile << envelope_to_header << envelope_from_header;

    if(fi.flags.bodyextern)
     {
      if(m.copyheader(outfile))
       {
        logf.printf("spool_in_folder",
          "fatal: failed to store header in \"%s\"", header_filename);
        return TRUE;
       }

      std::string externalfilename, hint;
      m.findsingleheader(hint, "Subject");
      makeexternfilename(externalfilename, hint, fp.getpath());

      std::ofstream outfile2(externalfilename.c_str(), ios::out|ios::binary);
      if(!outfile2)
       {
        logf.printf("spool_in_folder",
          "fatal: failed to open \"%s\"",
          externalfilename.c_str());
        return TRUE;
       }

      strmaxcpy(fi.file, strrchr(externalfilename.c_str(), 
        DIRCHAR[0])+1, TEXTLEN-1);

      m.copybody(outfile2);
     }
    else
     {
      if(m.copy(outfile))
       {
        logf.printf("spool_in_folder",
          "fatal: failed to store message in \"%s\"", header_filename);
        return TRUE;
       }
     }
   }

   {
    char index_filename[DIRLEN];

    snprintf(index_filename, DIRLEN, "%sindex", fp.getpath());

    std::ofstream indexfile(index_filename, ios::out|ios::app);

    if(!indexfile)
     {
      logf.printf("spool_in_folder",
        "fatal: failed to open \"%s\"", index_filename);
      return TRUE;
     }

    nr=indexfile.tellp()/sizeof fi;

    if(!indexfile.write((char *)&fi, sizeof fi))
     {
      logf.printf("spool_in_folder",
        "fatal: failed to store index in \"%s\"", index_filename);
     }
   }

  fp.set("nextid", fi.id+1);
  fp.write();

  return FALSE;
 }


syntax highlighted by Code2HTML, v. 0.9.1