home *** CD-ROM | disk | FTP | other *** search
/ YPA: Your Privacy Assured / YPA.ISO / other_goodies / utilities / amipop116.lha / AmiPOP116 / source / pop_dopop.c < prev    next >
C/C++ Source or Header  |  1995-01-11  |  11KB  |  621 lines

  1. #include "pop.h"
  2.  
  3. /* Stuff for "From " Header */
  4. /* Courtesy Michael B. Smith */
  5.  
  6.  
  7. struct mytm    {
  8.                 int year;
  9.                 int month;
  10.                 int day;
  11.                 int dow;
  12.                 int hour;
  13.                 int min;
  14.                 int sec;
  15.             };
  16.  
  17. /* DaysInMonth */
  18. static const int    dim [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  19. static const char    *months [] = {    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  20.                                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  21. static const char    *days [] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  22.  
  23. static void DateStampToMyTm (struct DateStamp *date, struct mytm *da)
  24. {
  25.     int days, years, leap  = 0, month = 0;
  26.  
  27.     days = date->ds_Days + 731;        /*  1976    */
  28.     years = days / (365*3+366);        /*  #quad yrs    */
  29.     days -= years * (365*3+366);
  30.     years = 1976 + 4 * years;
  31.  
  32.     if (days <= 365)
  33.     {
  34.         leap = 1;
  35.     }
  36.     else
  37.     {
  38.         days -= 366;
  39.         ++years;
  40.         years += days / 365;
  41.         days %= 365;
  42.     }
  43.  
  44.     month = 0;
  45.     while (1)
  46.     {
  47.         if (month == 1)
  48.         {
  49.             if (days < (28 + leap)) break;
  50.             days -= 28 + leap;
  51.         }
  52.         else
  53.         {
  54.             if (days < dim [month]) break;
  55.             days -= dim [month];
  56.         }
  57.         ++month;
  58.     }
  59.  
  60.     da->hour   = date->ds_Minute / 60;
  61.     da->min    = date->ds_Minute % 60;
  62.     da->sec    = date->ds_Tick / 50;
  63.  
  64.     da->day    = days + 1;
  65.     da->month  = month + 1;
  66.     da->dow    = date->ds_Days % 7;    /*  0 = sunday   */
  67.     da->year   = years;
  68.  
  69.     return;
  70. }
  71.  
  72. char * datestr (char *buf)
  73. {
  74.     /*
  75.     **  datestr
  76.     **
  77.     **    Build ARPA date-time as specified in RFC-822:
  78.     **
  79.     **        Wed, 13 Oct 93 18:52:04 EST
  80.     **        123456789012345678901234567890
  81.     **
  82.     **    buf must be 24 characters, plus space for TimeZone and NUL.
  83.     **
  84.     **    As TimeZone may be "(+23:30)" or similar, 33 chars should
  85.     **    do it.
  86.     */
  87.     struct mytm da;
  88.     struct DateStamp ds;
  89.  
  90.     DateStampToMyTm (DateStamp (&ds), &da);
  91.  
  92.     DoFmt (buf, "%s, %ld %s %ld %02ld:%02ld:%02ld",
  93.                 days [da.dow], da.day,
  94.                 months [da.month - 1], da.year % 100,
  95.                 da.hour, da.min, da.sec);
  96.  
  97.     return buf;
  98. }
  99.  
  100. char * time_stamp (char *buf)
  101. {
  102.     /*
  103.     **  time_stamp
  104.     **
  105.     **    Put a time/date stamp into buf (for logging)
  106.     **
  107.     **    13 Nov 93 13:14:45
  108.     */
  109.     struct DateStamp ds;
  110.     struct mytm da;
  111.  
  112.     DateStampToMyTm (DateStamp (&ds), &da);
  113.  
  114.     DoFmt (buf, "%ld %s %ld %02ld:%02ld:%02ld",
  115.                 da.day,
  116.                 months [da.month - 1], da.year % 100,
  117.                 da.hour, da.min, da.sec);
  118.  
  119.     return buf;
  120. }
  121.  
  122. /*  End stuff for "From " header */
  123.  
  124.  
  125. #define ASYNCBUFSIZE 8192
  126.  
  127. BOOL needfrom ( char * , struct AsyncFile *);
  128.  
  129. /* Variables global to this file */
  130.  
  131. struct Library *SockBase ;
  132. int havemail;
  133.  
  134. /* Functions */
  135.  
  136. int dopop(void)
  137. {
  138.     int s;
  139.     int count=1;
  140.     int okay=1;
  141.     struct hostent *hp;
  142.     struct sockaddr_in sa;
  143.  
  144.     DoFmt(title,"Connecting to %s",pophost);
  145.     settitle(title);
  146.  
  147.     if((SockBase = OpenLibrary( SOCKLIBNAME, SOCKLIBVERSION )) == NULL)
  148.     {
  149.         doreq("Error opening "SOCKLIBNAME"\n",bum);
  150.         return(1);
  151.     }
  152. #ifdef AMITCP
  153.     SetErrnoPtr(&errno, sizeof errno);
  154. #else
  155.     setup_sockets( MAXSOCKS, &errno );
  156. #endif
  157.  
  158.     if((hp=gethostbyname(pophost))==NULL)
  159.     {
  160. #ifndef AMITCP
  161.         cleanup_sockets();
  162. #endif
  163.         CloseLibrary( SockBase ) ;
  164.         doreq("Connection Refused.",bum);
  165.         return(1);
  166.     }
  167.  
  168.     bzero(&sa, sizeof(sa));
  169.     bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
  170.     sa.sin_family = hp->h_addrtype;
  171.     sa.sin_port = htons((u_short)port);
  172.     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)
  173.     {
  174. #ifndef AMITCP
  175.         cleanup_sockets();
  176. #endif
  177.         CloseLibrary( SockBase ) ;
  178.         doreq("Something bad\nhas happened.",bum);
  179.         return(1);
  180.     }
  181.  
  182.     if (connect(s,(struct sockaddr *) &sa,sizeof(sa))< 0)
  183.     {
  184.         doreq("No POP3 daemon\nrunning on this\nmachine or port.",bum);
  185.         s_close(s);
  186. #ifndef AMITCP
  187.         cleanup_sockets();
  188. #endif
  189.         CloseLibrary( SockBase ) ;
  190.         return(1);
  191.     }
  192.  
  193. /* Put actual code here */
  194.  
  195. /* We need to loop on this recv, because the initial greeting may not fit in one BUFSIZE.
  196.    We loop until we get a "\n" */
  197.  
  198.     settitle("Got Connection");
  199.  
  200.     recv(s,buf,BUFSIZE-1,0);
  201.     while (!(strstr(buf,"\n")))
  202.     {
  203.         recv(s,buf,BUFSIZE-1,0);
  204.     }
  205.  
  206.  
  207.     if (senduser(s))
  208.     {
  209. #ifndef AMITCP
  210.         cleanup_sockets();
  211. #endif
  212.         CloseLibrary( SockBase ) ;
  213.         return(1);
  214.     }
  215.  
  216.     havemail=sendstat(s);
  217.  
  218.     while ((okay) && ((havemail > count) || (havemail == count)))
  219.     {
  220.         DoFmt(title,"Retrieving %lu of %lu",count,havemail);
  221.         settitle(title);
  222.  
  223.         okay=retrieve(s,count);
  224.  
  225.         if (delmail && okay)
  226.         {
  227.             DoFmt(title,"Deleting %lu",count);
  228.             settitle(title);
  229.  
  230.             okay=delmessage(s,count);
  231.         }
  232.         ++count;
  233.     }
  234.  
  235.     if(sendquit(s))
  236.     {
  237. #ifndef AMITCP
  238.         cleanup_sockets();
  239. #endif
  240.         CloseLibrary( SockBase ) ;
  241.         return(1);
  242.     }
  243.  
  244.     if (Project0Wnd)
  245.     {
  246.         SetWindowTitles(Project0Wnd,Project0Wdt, (UBYTE *) ~0);
  247.     }
  248.  
  249.     if (havemail && notify) /* removed sendstat() after Nofify */
  250.     {
  251.         doreq("You have new mail.","Cool");
  252.     }
  253.  
  254. /* End actual code */
  255.  
  256.     s_close(s);
  257. #ifndef AMITCP
  258.     cleanup_sockets();
  259. #endif
  260.     CloseLibrary( SockBase ) ;
  261.     return(0);
  262. }
  263.  
  264. int senduser(int s)
  265. {
  266.     int t;
  267.  
  268.     settitle("Sending Username");
  269.  
  270.     DoFmt(buf,"USER %s\r\n",username);
  271.  
  272.     if ( !trans(s,buf) ) return(1);
  273.  
  274.     t=sscanf(buf,"%s",temp);
  275.     if ( valcheck(t,temp) ) return(1);
  276.  
  277. /* Password */
  278.  
  279.     if (password[1])
  280.     {
  281.         settitle("Sending Password");
  282.  
  283.         DoFmt(buf,"PASS %s\r\n",password);
  284.  
  285.         if ( !trans(s,buf) ) return(1);
  286.  
  287.         t=sscanf(buf,"%s",temp);
  288.  
  289.         if ( valcheck(t,temp) ) return(1);
  290.     }
  291.  
  292.     return(0);
  293. }
  294.  
  295. int sendquit(int s)
  296. {
  297.     int t;
  298.  
  299.     settitle("Sending QUIT");
  300.  
  301.     DoFmt(buf,"QUIT\r\n");
  302.  
  303.     if ( !trans(s,buf) ) return(1);
  304.  
  305.     t=sscanf(buf,"%s",temp);
  306.  
  307.     if ( valcheck(t,temp) ) return(1);
  308.  
  309.     settitle("Quit Acknowledged");
  310.  
  311.     return(0);
  312. }
  313.  
  314. int sendstat( int s )
  315. {
  316.     int t;
  317.     int count=0;
  318.  
  319.     DoFmt(buf,"STAT\r\n");
  320.  
  321.     if ( !trans(s,buf) ) return(0);
  322.  
  323.     t=sscanf(buf,"%s %lu",temp,&count);
  324.  
  325.     if ( valcheck(t,temp) ) return(0);
  326.  
  327.     return(count);
  328. }
  329.  
  330. /* function retrieve does the work of retrieving a message, removing
  331.    the byte stuffing and writing it to the mailfile.
  332.    Rewritten by David Duggan, Sandia National Labs */
  333.  
  334. int retrieve(int s, int count)
  335. {
  336.     int foo;            /* temp integer for numb bytes read */
  337.     int state;            /* flag saying what state we are in */
  338.     int x1;            /* index for tmpbuf */
  339.  
  340.     char *tmpbuf;        /* ptr to place to put unstuffed msg */
  341.     char *buf3;            /* ptr to front of mail message */
  342.     char *buf4;            /* ptr to char being examined in mail message */
  343.  
  344.     struct AsyncFile *ofp;
  345.  
  346.     if ( ! (tmpbuf = AllocVec(BUFSIZE,MEMF_CLEAR)))
  347.     {
  348.         doreq("Not enough memory for buffer.",bum);
  349.         return(0);
  350.     }
  351.  
  352.     if (( count == 1 ) && ( !appfile ))
  353.     {
  354.         ofp = OpenAsync(mailbox, MODE_WRITE,ASYNCBUFSIZE);
  355.     }
  356.     else
  357.     {
  358.         ofp = OpenAsync(mailbox, MODE_APPEND,ASYNCBUFSIZE);
  359.     }
  360.  
  361.     if ( ofp == NULL )
  362.     {
  363.         doreq("Unable to lock Mailbox.\nCheck path and filename.",bum);
  364.         FreeVec(tmpbuf);
  365.         return(0);
  366.     }
  367.  
  368.     DoFmt(buf,"RETR %lu\r\n",count);
  369.  
  370.     if ( !trans(s,buf) )    /* send data, get answer */
  371.     {
  372.         CloseAsync(ofp);
  373.         FreeVec(tmpbuf);
  374.         return(0);
  375.     }
  376.  
  377.     if ( valcheck(1,buf) )    /* check for good response */
  378.     {
  379.         CloseAsync(ofp);
  380.         FreeVec(tmpbuf);
  381.         return(0);
  382.     }
  383.  
  384.     /* Here we have a good first line for this multi-line response.
  385.        Now we should process the rest of the buffer */
  386.  
  387.     buf3 = strstr(buf,"\r\n");
  388.     if (buf3 != NULL) buf3 += 2;/* move ptr past first line */
  389.     needfrom(buf3,ofp);    /* add "from" if needed */
  390.     buf4 = buf3 = strip(buf3); /* remove CRs */
  391.  
  392.     state = 0;        /* start clean every time */
  393.     while ( state < 3 )
  394.     {
  395.         x1 = 0;            /* reset index */
  396.         while ( *buf4 )        /* until we hit the end of buffer */
  397.         {
  398.             switch (state)
  399.             {
  400.                 case 0:
  401.                     if ( *buf4 == '\n' )
  402.                     {
  403.                         state++;    /* go to next state */
  404.                     }
  405.                     tmpbuf[x1++] = *buf4;/* move character */
  406.                     break;
  407.  
  408.                 case 1:
  409.                     if ( *buf4 == '.' )
  410.                     {
  411.                         state++;    /* next state, deleting period */
  412.                     }
  413.                     else
  414.                     {    /* reset state if not "\n"  */
  415.                         if (*buf4 != '\n')
  416.                         {
  417.                             state = 0;
  418.                         }
  419.                         tmpbuf[x1++] = *buf4;/* move character */
  420.                     }
  421.                     break;
  422.  
  423.                 case 2:
  424.                     if ( *buf4 == '\n' )
  425.                     {
  426.                         state++;    /* go to final state */
  427.                     }
  428.                     else
  429.                     {
  430.                         state = 0;    /* reset the state */
  431.                     }
  432.                     tmpbuf[x1++] = *buf4;
  433.                     break;
  434.             } /* switch */
  435.             buf4++;        /* move to next byte */
  436.         }
  437.  
  438.         tmpbuf[x1] = '\0';        /* terminate it */
  439.  
  440.         if ( state < 3 )    /* we need more in the buffer */
  441.         {
  442.             if ( WriteAsync(ofp,tmpbuf,strlen(tmpbuf) ) == -1)
  443.             {
  444.                 doreq("Error writing to mailbox.",bum);
  445.                 CloseAsync(ofp);
  446.                 FreeVec(tmpbuf);
  447.                 return(0);    /* return error */
  448.             }
  449.  
  450.             /* get next buffer full */
  451.             foo = recv(s,buf,(BUFSIZE - 1),0);
  452.  
  453.             if ( foo > 0 )
  454.             {
  455.                 buf[foo] = '\0'; /* terminate it for grins */
  456.                 buf4 = buf3 = strip(buf);/* remove CRs */
  457.             }
  458.             else
  459.             { /* should never happen! */
  460.                 doreq("Internal Error.",bum);
  461.                 state = 4;/* should never happen */
  462.             }
  463.         }    /* if (state < 3) */
  464.     }    /* while (state < 3) */
  465.  
  466.     /* write out last buffer, leaving off last ".\n" */
  467.     if ( WriteAsync(ofp,tmpbuf,strlen(tmpbuf)) == -1 )
  468.     {
  469.         doreq("Error writing to Mailbox.",bum);
  470.         CloseAsync(ofp);
  471.         FreeVec(tmpbuf);
  472.         return(0);    /* return error */
  473.     }
  474.  
  475.     CloseAsync(ofp);
  476.     FreeVec(tmpbuf);
  477.     return(1);
  478.  
  479. } /* end of retrieve */
  480.  
  481. int delmessage( int s, int count )
  482. {
  483.     DoFmt(buf,"DELE %lu\r\n",count);
  484.     trans(s,buf);
  485.  
  486.     if ( valcheck(1,buf) ) return(0);
  487.  
  488.     return(1);
  489. }
  490.  
  491. int valcheck(int t, char *localtemp)
  492. {
  493.     if (t == 0)
  494.     {
  495.         doreq("Got a bogus return string.",bum);
  496.         return(1);
  497.     }
  498.  
  499.     if ( !strstr(localtemp,"+OK") )
  500.     {
  501.         doreq("Didn't get +OK",bum);
  502.  
  503.         if (localtemp[0] != '\0')
  504.         {
  505.             doreq(localtemp,bum);
  506.         }
  507.         return(1);
  508.     }
  509.     return(0);
  510. }
  511.  
  512. int trans( int s, char *mybuf )
  513. {
  514.     int foo;
  515.  
  516.     send(s,mybuf,strlen(mybuf),0);
  517.  
  518.     bzero(buf,BUFSIZE);
  519.     foo=recv(s,buf,BUFSIZE-1,0);
  520.     if ( foo < 1 )
  521.     {
  522.         return(0);
  523.     }
  524.  
  525.     buf[foo]='\0';
  526.  
  527.     return (1);
  528. }
  529.  
  530. void settitle( char *newtitle )
  531. {
  532.     if (winop)
  533.     {
  534.         SetWindowTitles(Project0Wnd,newtitle, (UBYTE *) ~0);
  535.     }
  536. }
  537.  
  538. /* Scott, this is a slight modification of your strip.  It has the exact same
  539.    functionality as yours, except it uses dynamic memory instead of the stack
  540.    for the temporary buffer.  If you want to leave your routine here,
  541.    everything should work just the same.  David */
  542.  
  543. /* function strip will strip out all the carraige returns
  544.    from the buffer and return the original pointer */
  545.  
  546. char * strip( char *mybuf )
  547. {
  548.     char tmpbuf[BUFSIZE];
  549.     ULONG x1, x2, len;
  550.  
  551.     len = strlen(mybuf);
  552.  
  553.     /* strip out the CRs */
  554.     for (x1 = x2 = 0 ; x1 < len; x1++)
  555.     {
  556.         tmpbuf[x2] = mybuf[x1];
  557.         if ( tmpbuf[x2] != '\r' ) x2++;
  558.     }
  559.  
  560.     tmpbuf[x2] = '\0';        /* terminate it */
  561.     strcpy(mybuf,tmpbuf);    /* copy back the string */
  562.  
  563.     return(mybuf);        /* return their buf ptr */
  564.  
  565. } /* end of strip */
  566.  
  567. int lastblock (char *segment)
  568. {
  569.     char *found;
  570.     int len = strlen(segment);
  571.  
  572.     if ( (found=strstr(segment,"\r\n.\r\n")))
  573.     {
  574.         /*buf[found-segment]='\n';*/
  575.         buf[found-segment]='\0'; /* used to be found-segment+2 */
  576.         return(0);
  577.     }
  578.  
  579.     if ( (len==2) && (found=strstr(segment,"\r\n")) )
  580.     {
  581.         buf[found-segment]='\0'; /* Added recently */
  582.         return(0);
  583.     }
  584.  
  585.     if ( len==1 ) /* Kludge of the century */
  586.     {
  587.         return(0);
  588.     }
  589.  
  590.     if ( (len <= 4) && (found=strstr(segment,".\r\n")) )
  591.     {
  592.         /*buf[found-segment]='\n';*/
  593.         buf[found-segment]='\0';
  594.         return(0);
  595.     }
  596.  
  597.     return(1);
  598. }
  599.  
  600. BOOL needfrom(char *mybuf,struct AsyncFile *ofp)
  601. {
  602.     if ( !strstr(mybuf,"From ") )
  603.     {
  604.         char *newtemp;
  605.  
  606.         if (newtemp=AllocVec(BIGSTRING,MEMF_CLEAR))
  607.         {
  608.             int tempsize=0;
  609.  
  610.             DoFmt(newtemp,"From %s@%s ", username,pophost);
  611.             tempsize=strlen(newtemp);
  612.             DoFmt((newtemp+tempsize),"%s\n",datestr((newtemp+tempsize)));
  613.             WriteAsync(ofp,newtemp,strlen(newtemp));
  614.             FreeVec(newtemp);
  615.         }
  616.  
  617.         return(TRUE);
  618.     }
  619.     return(FALSE);
  620. }
  621.