Advertisement
FlyFar

folder.c

May 15th, 2024
620
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 19.42 KB | Cybersecurity | 0 0
  1. /*
  2.  *  pop3d       - IP/TCP/POP3 server for UNIX 4.3BSD
  3.  *            Post Office Protocol - Version 3 (RFC1225)
  4.  *
  5.  *      (C) Copyright 1991 Regents of the University of California
  6.  *
  7.  *      Permission to use, copy, modify, and distribute this program
  8.  *      for any purpose and without fee is hereby granted, provided
  9.  *      that this copyright and permission notice appear on all copies
  10.  *      and supporting documentation, the name of University of California
  11.  *      not be used in advertising or publicity pertaining to distribution
  12.  *      of the program without specific prior permission, and notice be
  13.  *      given in supporting documentation that copying and distribution is
  14.  *      by permission of the University of California.
  15.  *      The University of California makes no representations about
  16.  *      the suitability of this software for any purpose.  It is provided
  17.  *      "as is" without express or implied warranty.
  18.  *
  19.  *  Katie Stevens
  20.  *  dkstevens@ucdavis.edu
  21.  *  Information Technology -- Campus Access Point
  22.  *  University of California, Davis
  23.  *
  24.  **************************************
  25.  *
  26.  *  folder.c
  27.  *
  28.  *  REVISIONS:
  29.  *      02-27-90 [ks]   original implementation
  30.  *  1.000   03-04-90 [ks]
  31.  *  1.001   06-24-90 [ks]   allow TRANS state if 0 msgs in folder
  32.  *              implement optional TOP command
  33.  *  1.002   07-22-91 [ks]   reset index counter after folder rewind
  34.  *              in fld_release (Thanks to John Briggs,
  35.  *              vaxs09@vitro.com, Vitro Corporation,
  36.  *              Silver Spring, MD for finding this bug!)
  37.  *  1.004   11-13-91 [ks]   leave original mailbox intact during POP
  38.  *              session (Thanks to Dave Cooley,
  39.  *              dwcooley@colby.edu for suggesting this)
  40.  *  1.005   01-04-96 [dts]  change mktemp to mkstemp to avoid security
  41.  *              hole with mktemp (timing attack).
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <string.h>
  46. #include <errno.h>
  47. #include <stdlib.h>
  48. #include <syslog.h>
  49. #include <sys/types.h>
  50. #include <sys/stat.h>
  51. #include <sys/file.h>
  52. #include "pop3.h"
  53.  
  54. #ifdef QMAIL
  55. # include <pwd.h>
  56. #endif
  57.  
  58. #ifdef LINUX
  59. # include <unistd.h>
  60. #endif
  61.  
  62. #ifdef VIRTUAL
  63. extern int virtual_mode;
  64. extern char *virt_spooldir;
  65. extern char *virt_workdir;
  66. #endif
  67.  
  68. /* In main.c */
  69. extern char *svr_hostname;
  70. extern char svr_buf[];
  71. extern char cli_user[];
  72.  
  73. /* In util.c */
  74. extern char flash_buf[];
  75.  
  76. extern FILE *logfp;
  77. extern int mypid;
  78. extern int debug;
  79.  
  80. /* Constants used when closing a folder after POP session */
  81. #define REMOVE_MBOX 1
  82. #define SAVE_NEW    2
  83. #define SAVE_ALL    3
  84.  
  85. static char *svr_nomsg = "-ERR no messages in mailbox\r\n";
  86. static char *cli_mbox = NULL;       /* Filename of mailbox folder */
  87.  
  88. #define FNAME_SIZ 128
  89. static char fld_fname[FNAME_SIZ];   /* Filename for working folder */
  90. static FILE *fld_fp = NULL;     /* Stream pointer for mailbox */
  91. static struct fld_item *fld_msg;    /* Struct for mailbox stats */
  92. static int fld_max = -1;        /* Actual # msgs in mailbox */
  93. static int fld_highest = -1;        /* Max msg accessed by client */
  94. static long fld_orig_size;      /* [1.004] size of mbox when loaded */
  95. static time_t fld_orig_mod_time;    /* [1.004] timestamp on mbox file */
  96.  
  97. #define isfromsp_start(buf) (strncmp(buf,"From ",5) == 0)
  98.  
  99. static int fld_select();
  100. static void retr_fromsp();
  101. static int msg_fromsp();
  102.  
  103. /**************************************************************************/
  104.  
  105. static void
  106. delete_folder()
  107. {
  108.     unlink(fld_fname);
  109. }
  110.  
  111. /**************************************************************************/
  112.  
  113. /* Open a FromSpace delimited mailbox */
  114. int
  115. fld_fromsp(fname)
  116. char *fname;
  117. {
  118.     int cnt;
  119.     static char buffer[256];    /* DTS 14Sep99 - try to speed up */
  120.  
  121.     /* Release previously opened mailbox */
  122.     if (fld_fp != NULL)
  123.         fld_release();
  124.     /* Construct filename for new mailbox */
  125.     /* DTS 14Sep99 - added "if" to try to speed up (malloc slow?) */
  126.     if ( strlen(fname) <= 255 ) {
  127.         cli_mbox = buffer;
  128.     } else {
  129.         cli_mbox = malloc(strlen(fname)+1);
  130.         if (cli_mbox == NULL)
  131.             fail(FAIL_OUT_OF_MEMORY);
  132.     }
  133. /*  cli_mbox = malloc(strlen(fname)+1);
  134.  *  if (cli_mbox == NULL)
  135.  *      fail(FAIL_OUT_OF_MEMORY);
  136.  */
  137.     strcpy(cli_mbox,fname);
  138.     /* Open mailbox */
  139.     /* DTS 10Oct96 [ 1.005d ] added logic for "-2" return value */
  140.     if ((cnt = fld_select(cli_mbox)) < 0) {
  141.         if( cnt == -2 )
  142.             sprintf(svr_buf,"-ERR being read already %s (stuck lock file in %s?)\r\n",
  143.                 cli_mbox,DEF_POP3_DIR);
  144.         else
  145. #ifdef QMAIL
  146.             sprintf(svr_buf,
  147. "-ERR cannot open mailbox %s or work file (disk space full?)\r\n",
  148.                 cli_mbox);
  149. #else
  150.             sprintf(svr_buf,
  151. "-ERR cannot open mailbox %s or work file (disk space for %s?)\r\n",
  152.                 cli_mbox,DEF_POP3_DIR);
  153. #endif
  154.         free(cli_mbox);
  155.         cli_mbox = NULL;
  156.         return(SVR_FOLD_STATE);
  157.     } else {
  158.         sprintf(svr_buf,"+OK %d messages ready for %s in %s\r\n",
  159.             cnt,cli_user,cli_mbox);
  160.         return(SVR_TRANS_STATE);
  161.     }
  162. }
  163.  
  164. /**************************************************************************/
  165.  
  166. /* Mark a message for deletion */
  167. void
  168. fld_delete(msgnum)
  169. int msgnum;
  170. {
  171.     if (fld_fp == NULL) {
  172.         strcpy(svr_buf, svr_nomsg);
  173.         return;
  174.     }
  175.  
  176.     if ((msgnum < 1)||(msgnum > fld_max)) {
  177.         sprintf(svr_buf,"-ERR invalid message; number out of range\r\n");
  178.     } else {
  179.         fld_msg[msgnum-1].status |= MSG_DELETED;
  180.         sprintf(svr_buf,"+OK message %d marked for deletion\r\n",
  181.             msgnum);
  182.         if ((msgnum-1) > fld_highest)
  183.             fld_highest =(msgnum-1);
  184.     }
  185. }
  186.  
  187. /* Report the highest access number for this mailbox */
  188. void
  189. fld_last()
  190. {
  191.     sprintf(svr_buf,"+OK %d\r\n",(fld_highest+1));
  192. }
  193.  
  194. /* Give information about messages in mailbox folder */
  195. void
  196. fld_list(msgnum)
  197. int msgnum;
  198. {
  199.     int i;
  200.  
  201.     if (fld_fp == NULL) {
  202.         strcpy(svr_buf, svr_nomsg);
  203.         return;
  204.     }
  205.  
  206.     if (msgnum == -1) {
  207.         sprintf(svr_buf,"+OK %d messages; msg# and size (in octets) for undeleted messages:\r\n",fld_max);
  208.         svr_data_out(svr_buf);
  209.         for (i=0; i<fld_max; ++i) {
  210.             if ((fld_msg[i].status & MSG_DELETED) == 0) {
  211.                 sprintf(svr_buf,"%d %ld\r\n",
  212.                     (i+1),fld_msg[i].bcount);
  213.                 svr_data_out(svr_buf);
  214.             }
  215.         }
  216.         sprintf(svr_buf,".\r\n");
  217.     } else {
  218.         if ((msgnum < 1)||(msgnum > fld_max))
  219.             sprintf(svr_buf,"-ERR invalid message; number out of range\r\n");
  220.         else if (fld_msg[msgnum-1].status & MSG_DELETED)
  221.             sprintf(svr_buf,"-ERR message %d has been marked for deletion\r\n",
  222.                 msgnum);
  223.         else
  224.             sprintf(svr_buf,"+OK %d %ld\r\n",
  225.                 msgnum,fld_msg[msgnum-1].bcount);
  226.     }
  227. }
  228.  
  229. /* Give id listing of messages in mailbox folder */
  230. void
  231. fld_uidl(msgnum)
  232. int msgnum;
  233. {
  234.     static int uidl_ready = 0;
  235.     int i;
  236.  
  237.     if (fld_fp == NULL) {
  238.         strcpy(svr_buf, svr_nomsg);
  239.         return;
  240.     }
  241.  
  242.     if (!uidl_ready) {
  243.         for (i=0; i<fld_max; ++i) {
  244.             do_md5_file(fld_fp, fld_msg[i].fmsg_entry, fld_msg[i].count, svr_buf);
  245.             if( fld_msg[i].id ) free(fld_msg[i].id);
  246.             fld_msg[i].id = strdup(svr_buf);
  247.         }
  248.         uidl_ready = 1;
  249.     }
  250.  
  251.     if (msgnum == -1) {
  252.         sprintf(svr_buf,"+OK %d messages; msg# and id for undeleted messages:\r\n",fld_max);
  253.         svr_data_out(svr_buf);
  254.         for (i=0; i<fld_max; ++i) {
  255.             if ((fld_msg[i].status & MSG_DELETED) == 0) {
  256.                 sprintf(svr_buf,"%d %s\r\n",
  257.                     (i+1),fld_msg[i].id);
  258.                 svr_data_out(svr_buf);
  259.             }
  260.         }
  261.         sprintf(svr_buf,".\r\n");
  262.     } else {
  263.         if ((msgnum < 1)||(msgnum > fld_max))
  264.             sprintf(svr_buf,"-ERR invalid message; number out of range\r\n");
  265.         else if (fld_msg[msgnum-1].status & MSG_DELETED)
  266.             sprintf(svr_buf,"-ERR message %d has been marked for deletion\r\n",
  267.                 msgnum);
  268.         else {
  269.             sprintf(svr_buf,"+OK %d %s\r\n",
  270.                 msgnum,fld_msg[msgnum-1].id);
  271.         }
  272.     }
  273. }
  274.  
  275. /* Reset deleted messages and highest access number */
  276. void
  277. fld_reset()
  278. {
  279.     int i;
  280.  
  281.     if (fld_fp == NULL) {
  282.         strcpy(svr_buf, svr_nomsg);
  283.         return;
  284.     }
  285.     /* Reset messages marked for deletion */
  286.     for (i=0; i<fld_max; ++i) {
  287.         fld_msg[i].status &= ~MSG_DELETED;
  288.     }
  289.     /* Reset highest access number for this mailbox */
  290.     fld_highest = -1;
  291.     sprintf(svr_buf,"+OK %d messages ready for %s in %s\r\n",
  292.         fld_max,cli_user,cli_mbox);
  293. }
  294.  
  295. /* Retrieve a message from mailbox */
  296. void
  297. fld_retr(msgnum,linecnt)
  298. int msgnum;
  299. int linecnt;
  300. {
  301.     if (fld_fp == NULL) {
  302.         strcpy(svr_buf, svr_nomsg);
  303.         return;
  304.     }
  305.  
  306.     if ((msgnum < 1)||(msgnum > fld_max)) {
  307.         sprintf(svr_buf,"-ERR invalid message; number out of range\r\n");
  308.     } else if (fld_msg[msgnum-1].status & MSG_DELETED) {
  309.         sprintf(svr_buf,"-ERR message %d has been marked for deletion\r\n",
  310.             msgnum);
  311.     } else {
  312.         sprintf(svr_buf,"+OK message %d (%ld octets):\r\n",
  313.             msgnum,fld_msg[msgnum-1].bcount);
  314.         svr_data_out(svr_buf);
  315.         retr_fromsp(--msgnum,linecnt);
  316.         sprintf(svr_buf,".\r\n");
  317.         if ((linecnt != -1)&&(msgnum > fld_highest))
  318.             fld_highest = msgnum;
  319.     }
  320. }
  321.  
  322. /* Give message count and total size (in octets) of a mailbox folder */
  323. void
  324. fld_stat()
  325. {
  326.     int i;
  327.     long total_cnt = 0L;
  328.  
  329.     if (fld_fp == NULL) {
  330.         strcpy(svr_buf, "+OK 0 0\r\n");
  331.         return;
  332.     }
  333.     for (i=0; i<fld_max; ++i) {
  334.         total_cnt += fld_msg[i].bcount;
  335.     }
  336.     sprintf(svr_buf,"+OK %d %ld\r\n",fld_max,total_cnt);
  337. }
  338.  
  339. /**************************************************************************/
  340.  
  341. /* Attempt to load a mailbox folder */
  342. static int
  343. fld_select(mbox)
  344. char *mbox;
  345. {
  346.     int fd;         /* [1.005] DTS for mkstemp */
  347. #ifdef QMAIL
  348.     struct passwd *pwd;
  349. #endif
  350.     struct stat stat_buf;
  351.     FILE *mboxfp;
  352.     int lock;
  353.  
  354.     /* Reset folder variables */
  355.     fld_fp = NULL;
  356.     fld_highest = -1;
  357.  
  358.     /* Make sure mailbox is present and non-zero size */
  359.     /* DTS 06Oct98 - added syslog below, rec'd by:  led@cyberdiner.com  */
  360.     if (stat(mbox,&stat_buf) == -1) {
  361.         if (errno == EACCES)
  362.             syslog(SYSLOGPRI,
  363.                 "Permission denied on mailbox for %s",mbox);
  364.         return 0;
  365.     }
  366.  
  367.     if (stat_buf.st_size == 0L)
  368.         return 0;
  369.  
  370.     /* Save current mailbox size and last-modified-timestamp */
  371.     fld_orig_size = stat_buf.st_size;   /* [1.004] */
  372.     fld_orig_mod_time = stat_buf.st_mtime;  /* [1.004] */
  373.  
  374.     /* [1.005d] DTS 20Oct96 re-wrote to use named temp file
  375.      *  (checking for prior existance for security reasons).
  376.      */
  377. #ifdef VIRTUAL
  378.     if(virtual_mode)
  379.         snprintf(fld_fname,FNAME_SIZ,"%s",virt_workdir);
  380.     else {
  381. #  ifdef QMAIL
  382.         pwd=getpwnam(cli_user);
  383.         snprintf(fld_fname,FNAME_SIZ,"%s/.pop-",pwd->pw_dir);
  384. #  else
  385.         strncpy(fld_fname, DEF_POP3_DIR, FNAME_SIZ-1);
  386. #  endif
  387.     }
  388.  
  389. #else
  390. #  ifdef QMAIL
  391.     pwd=getpwnam(cli_user);
  392.     snprintf(fld_fname,FNAME_SIZ,"%s/.pop-",pwd->pw_dir);
  393. #  else
  394.     strncpy(fld_fname, DEF_POP3_DIR, FNAME_SIZ-1);
  395. #  endif
  396. #endif
  397.     strncat(fld_fname, (const char *) basename(mbox),
  398.             FNAME_SIZ-strlen(fld_fname)-1);
  399.     if ((fd=open(fld_fname, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0)
  400.         return -2;
  401.  
  402.     atexit(delete_folder);
  403.  
  404.     /* [1.005] DTS Convert from fd to fp to be compat. with existing code */
  405.     if ((fld_fp = fdopen(fd,"w")) == NULL) {
  406.         close(fd);
  407.         unlink(fld_fname);
  408.         return -1;
  409.     }
  410.    
  411.     /* Secure mailbox for POP3 session; copy to temporary file */
  412.     if ((mboxfp = fopen(mbox, "r")) == NULL) {
  413.         fclose(fld_fp);
  414.         unlink(fld_fname);
  415.         return -1;
  416.     }
  417.     if ((lock = dup(fileno(mboxfp))) == -1) {
  418.         fclose(fld_fp);
  419.         fclose(mboxfp);
  420.         unlink(fld_fname);
  421.         return -1;
  422.     }
  423.     if (flock(lock, LOCK_EX) == -1) {
  424.         fclose(fld_fp);
  425.         fclose(mboxfp);
  426.         close(lock);
  427.         unlink(fld_fname);
  428.         return -1;
  429.     }
  430.  
  431.     /* Load messages from folder */
  432.     fld_max = msg_fromsp(mboxfp, fld_fp);
  433.     if (fclose(mboxfp) == EOF)
  434.         fld_max = -1;
  435.     if (fclose(fld_fp) == EOF)
  436.         fld_max = -1;
  437.  
  438.     /* Unlock mailbox */
  439.     flock(lock, LOCK_UN);
  440.     close(lock);
  441.  
  442.     /* Prepare to use temporary file for POP3 session */
  443.     if (fld_max > 0) {
  444.         if ((fld_fp = fopen(fld_fname,"r")) == NULL) {
  445.             unlink(fld_fname);
  446.             fld_max = -1;
  447.         }
  448.     } else {
  449.         /* Either zero messages or error */
  450.         unlink(fld_fname);
  451.         fld_fp = NULL;
  452.     }
  453.     return(fld_max);
  454. }
  455.  
  456. /* Close a mailbox folder; remove messages marked for deletion */
  457. void
  458. fld_release()
  459. {
  460.     char temp_fname[FNAME_SIZ];
  461.     int fd;         /* [1.005] DTS for mkstemp */
  462.     FILE *mboxfp;
  463.     FILE *tempfp;
  464.     int lock;
  465.     int i = 0;
  466.     int savemsg = 1;
  467.     int zap_orig_mbox;
  468.     struct stat stat_buf;
  469.  
  470.     /* If no messages in folder, just free memory for filename */
  471.     if (fld_fp == NULL) {
  472.         if (cli_mbox != NULL) {
  473.             free(cli_mbox);
  474.             cli_mbox = NULL;
  475.         }
  476.         return;
  477.     }
  478.  
  479.     /* [1.004] Check size and timestamp on the original mailbox file */
  480.     if (stat(cli_mbox, &stat_buf) == -1) {
  481.         /* Another user agent removed it while we were working */
  482.         zap_orig_mbox = REMOVE_MBOX;
  483.     } else {
  484.         if ((stat_buf.st_mtime == fld_orig_mod_time) &&
  485.             (stat_buf.st_size  == fld_orig_size)) {
  486.             /* Nothing added to mailbox while we were working */
  487.             zap_orig_mbox = REMOVE_MBOX;
  488.         } else {
  489.             if (stat_buf.st_size > fld_orig_size) {
  490.                 /* More messages were added to end of mbox */
  491.                 zap_orig_mbox = SAVE_NEW;
  492.    
  493.                 /* If no messages were deleted, just remove */
  494.                 /* the working mailbox file.                */
  495.                 for (i=0; i<fld_max; ++i) {
  496.                     if ((fld_msg[i].status & MSG_DELETED) != 0)
  497.                         break;
  498.                 }
  499.                 if (i == fld_max)
  500.                     goto cleanup;
  501.             } else {
  502.                 /* Another user agent made changes while
  503.                  * we were working; save it all to be safe
  504.                  */
  505.                 zap_orig_mbox = SAVE_ALL;
  506.             }
  507.         }
  508.     }
  509.  
  510.     /* Save changes made to original mailbox folder during
  511.      * this POP3 session
  512.      */
  513.     if (zap_orig_mbox == REMOVE_MBOX) {
  514.         /* No changes to save */
  515.         if ((mboxfp = fopen(cli_mbox, "w")) == NULL)
  516.             fail(FAIL_FILE_ERROR);
  517.     } else { /* SAVE_NEW or SAVE_ALL */
  518.         /* Save parts of this mailbox */
  519.         if ((mboxfp = fopen(cli_mbox, "r")) == NULL)
  520.             fail(FAIL_FILE_ERROR);
  521.     }
  522.     /* Lock original mailbox folder */
  523.     if ((lock = dup(fileno(mboxfp))) == -1)
  524.         fail(FAIL_FILE_ERROR);
  525.     if (flock(lock, LOCK_EX) == -1)
  526.         fail(FAIL_FILE_ERROR);
  527.  
  528.     /* Adjust position in original mailbox file */
  529.     if (zap_orig_mbox == SAVE_NEW) {
  530.         /* Save only the messages added while we were working */
  531.         if (fseek(mboxfp, fld_orig_size, 0) == -1)
  532.             fail(FAIL_FILE_ERROR);
  533.     }
  534.  
  535.     /* Transfer messages we want to save */
  536.     if (zap_orig_mbox == REMOVE_MBOX) {
  537.         /* Nothing to save, close file we just openned for write */
  538.         if (fclose(mboxfp) == EOF)
  539.             fail(FAIL_FILE_ERROR);
  540.         temp_fname[0] = '\0';
  541.     } else {         /* SAVE_NEW or SAVE_ALL */
  542.         /* Copy from the original mailbox to a temp file */
  543.         /* [1.005d] DTS 20Oct96 re-wrote to use named temp file
  544.          *  (checking for prior existance for security reasons).
  545.          */
  546.         strncpy(temp_fname, fld_fname, FNAME_SIZ-1);
  547.         strncat(temp_fname, ".tmp", FNAME_SIZ-strlen(temp_fname)-1);
  548.         if ((fd=open(temp_fname, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0)
  549.             fail(FAIL_DUP_READ);
  550.  
  551.         if ((tempfp = fdopen(fd,"w")) == NULL)
  552.             fail(FAIL_FILE_ERROR);
  553.  
  554.         while (fgetl(svr_buf,SVR_BUFSIZ,mboxfp) != NULL) {
  555.             fputs(svr_buf,tempfp);
  556.             if (ferror(tempfp))
  557.                 fail(FAIL_FILE_ERROR);
  558.         }
  559.         if (ferror(mboxfp))
  560.             fail(FAIL_FILE_ERROR);
  561.         if (fclose(mboxfp) == EOF)
  562.             fail(FAIL_FILE_ERROR);
  563.         if (fclose(tempfp) == EOF)
  564.             fail(FAIL_FILE_ERROR);
  565.     }
  566.    
  567.     /* Transfer contents of working folder to original */
  568.     /* mailbox folder; dont copy deleted messages.     */
  569.     if ((mboxfp = fopen(cli_mbox,"w")) == NULL)
  570.         fail(FAIL_FILE_ERROR);
  571.  
  572.     /* If all messages were deleted, we don't need to look */
  573.     /* through the working mailbox file.                   */
  574.     for (i=0; i<fld_max; ++i) {
  575.         if ((fld_msg[i].status & MSG_DELETED) == 0)
  576.             break;
  577.     }
  578.     if (i == fld_max)
  579.         goto addnew;
  580.  
  581.     /* Transfer undeleted messages from the working mailbox */
  582.     rewind(fld_fp);
  583.     i = 0;              /* [1.002] reset index counter */
  584.     while (fgetl(svr_buf,SVR_BUFSIZ,fld_fp) != NULL) {
  585.         if (isfromsp_start(svr_buf)) {
  586.             /* FromSPACE delimited mailbox */
  587.             /* Transfer next msg, unless deleted */
  588.             savemsg = !(fld_msg[i++].status & MSG_DELETED);
  589.         }
  590.         if (savemsg) {
  591.             fputs(svr_buf,mboxfp);
  592.             if (ferror(mboxfp))
  593.                 fail(FAIL_FILE_ERROR);
  594.         }
  595.     }
  596.     if (ferror(fld_fp))
  597.         fail(FAIL_FILE_ERROR);
  598.  
  599.     if (temp_fname[0] == '\0') {
  600.         /* Nothing more to add, close the original mailbox file */
  601.         if (fclose(mboxfp) == EOF)
  602.             fail(FAIL_FILE_ERROR);
  603.     }
  604.  
  605. addnew:
  606.     if (temp_fname[0] != '\0') {
  607.         /* There were changes to the original mailbox file
  608.          * while we were working. Save the messages that
  609.          * changed in the original mailbox file.
  610.          */
  611.         /* Transfer contents of temp file (messages added */
  612.         /* to original mailbox during this POP3 session)  */
  613.         /* back to mailbox folder                         */
  614.         if ((tempfp = fopen(temp_fname,"r")) == NULL)
  615.             fail(FAIL_FILE_ERROR);
  616.         while (fgets(svr_buf,SVR_BUFSIZ,tempfp) != NULL) {
  617.             fputs(svr_buf,mboxfp);
  618.             if (ferror(mboxfp))
  619.                 fail(FAIL_FILE_ERROR);
  620.         }
  621.         if (ferror(tempfp))
  622.             fail(FAIL_FILE_ERROR);
  623.         if (fclose(tempfp) == EOF)
  624.             fail(FAIL_FILE_ERROR);
  625.         unlink(temp_fname);
  626.         if (fclose(mboxfp) == EOF)
  627.             fail(FAIL_FILE_ERROR);
  628.     }
  629.  
  630.     /* Unlock original mailbox folder */
  631.     flock(lock, LOCK_UN);
  632.     close(lock);
  633.  
  634.  
  635. cleanup:
  636.     /* Close and remove working copy of mailbox folder */
  637.     fclose(fld_fp);
  638.     fld_fp = NULL;
  639.     unlink(fld_fname);
  640.     for (i=0; i<fld_max; ++i) {
  641.         if (fld_msg[i].pop_hdr != NULL)
  642.             free(fld_msg[i].pop_hdr);
  643.     }
  644.     free( (char *)fld_msg );
  645.     free(cli_mbox);
  646.     cli_mbox = NULL;
  647. }
  648.  
  649. /********************************************/
  650.  
  651. /* Send a FromSP delimited message to the POP3 client */
  652. static void
  653. retr_fromsp(msgnum,linecnt)
  654. int msgnum;
  655. int linecnt;
  656. {
  657.     char *cp, *tp;
  658.     int msgbody = 0;
  659.  
  660.     /* Locate start of message in mailbox file */
  661.     if (fseek(fld_fp, fld_msg[msgnum].fmsg_entry, 0) == -1)
  662.         return;
  663.  
  664.     /* Setup for byte-stuff on lines that start with '.' */
  665.     cp = svr_buf;
  666.     *cp = DOT_CHAR;
  667.     ++cp;
  668.     /* Display message for the client */
  669.     if (fld_msg[msgnum].pop_hdr != NULL)
  670.         svr_data_out(fld_msg[msgnum].pop_hdr);
  671.     while (fgetl(cp,SVR_BUFSIZ,fld_fp) != NULL) {
  672.         if (isfromsp_start(cp))
  673.             break;
  674.         /* Use CR-LF line terminator */
  675.         tp = strchr(cp,LF_CHAR);
  676.         if (tp != NULL)
  677.             strcpy(tp,"\r\n");
  678.         /* Byte-stuff lines that start with '.' */
  679.         if (*cp == DOT_CHAR)
  680.             svr_data_out(svr_buf);
  681.         else
  682.             svr_data_out(cp);
  683.         if ((msgbody)&&(--linecnt == 0)) {
  684.             break;
  685.         } else {
  686.             if (*cp == CR_CHAR) {
  687.                 msgbody = 1;
  688.                 if (linecnt == 0)
  689.                     break;
  690.             }
  691.         }
  692.     }
  693. }
  694.  
  695. /**************************************************************************/
  696.  
  697. /* Load messages from a mailbox delimited by FromSPACE */
  698. static int
  699. msg_fromsp(infp, outfp)
  700. FILE *infp;
  701. FILE *outfp;
  702. {
  703.     int i = 0;
  704.     register struct fld_item *mp;
  705.  
  706.     /* Get an array for storing info about messages in folder */
  707.     get_e_array(fld_msg, FLD_ENTRY_BLOCK);
  708.     if (fld_msg == NULL)
  709.         fail(FAIL_OUT_OF_MEMORY);
  710.     mp = &fld_msg[0];
  711.     /* Load messages from mailbox folder to temporary folder */
  712.     while (fgetl(svr_buf,SVR_BUFSIZ,infp) != NULL) {
  713.         fputs(svr_buf, outfp);
  714.         if (ferror(outfp))
  715.             return -1;
  716.         if (isfromsp_start(svr_buf)) {
  717.             /* Make sure there is room in array for this entry */
  718.             chk_e_size(fld_msg, FLD_ENTRY_BLOCK, i);
  719.             if (fld_msg == NULL)
  720.                 fail(FAIL_OUT_OF_MEMORY);
  721.             /* Reset stats for this message */
  722.             mp = &fld_msg[i];
  723.             mp->fmsg_entry = ftell(outfp);
  724.             mp->status = 0;
  725.             sprintf(flash_buf,"%s %s@%s\r\n",POP3_RCPT_HDR,
  726.                     cli_user,svr_hostname);
  727.             mp->pop_hdr = malloc(strlen(flash_buf)+1);
  728.             if (mp->pop_hdr == NULL)
  729.                 fail(FAIL_OUT_OF_MEMORY);
  730.             strcpy(mp->pop_hdr,flash_buf);
  731.             mp->bcount = strlen(mp->pop_hdr);
  732.             mp->count = 0;
  733.                         /* patch: wlad, 06/14/98,  UIDL crash on line 224, free(id) */
  734.             mp->id = (char *)NULL;
  735.             /* patch: end */
  736.  
  737.             ++i;
  738.         } else {
  739.             int len = strlen(svr_buf);
  740.             mp->bcount += len + 1L;
  741.             mp->count += len;
  742.         }
  743.     }
  744.     if (ferror(infp))
  745.         return -1;
  746.     if (i == 0)
  747.         free((char *)fld_msg);
  748.     return(i);
  749. }
  750.  
  751. /************************************************/
  752.  
  753.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement