home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993 October: Windmill on DISC / ADC Developer CD (1993-10) (''Windmill On DISC'')_iso / Dev.CD Oct 93.iso / System Software / U.S. System Software / System 7 Pro™ Beta 11 / Development Tools / Sample Code / Messaging Service Access Module / Internet PMSAM / Internet PMSAM source / pop.protocol.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-19  |  9.3 KB  |  445 lines  |  [TEXT/MPS ]

  1. /*-------------------------------------------------------------------
  2.  
  3. AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
  4. Mail Service Access Module
  5.  
  6. written by Steve Falkenburg-- MacDTS
  7. ©1991-1993 Apple Computer, Inc.
  8.  
  9. --------------
  10. change history
  11. --------------
  12.  
  13. SJF        02/19/93    update for beta build    b1
  14. SJF        10/29/92    update to a11            a11
  15. SJF        06/08/92    update to a8            a8
  16. SJF        02/15/92    first working version    a4.5
  17. SJF        10/16/91    initial coding            a3
  18.  
  19. ---------------------------------------------------------------------*/
  20.  
  21. #ifndef __TYPES__
  22. #include <Types.h>
  23. #endif
  24.  
  25. #ifndef __PACKAGES__
  26. #include <Packages.h>
  27. #endif
  28.  
  29. #include <string.h>
  30.  
  31. #ifdef applec
  32. #include <strings.h>
  33. #endif
  34.  
  35. #include "const.h"
  36. #include "gwerrors.h"
  37. #include "mytypes.h"
  38. #include "globals.h"
  39. #include "utils.h"
  40. #include "network.h"
  41. #include "pop.types.h"
  42. #include "pop.constants.h"
  43. #include "parser.h"
  44.  
  45. #include "pop.protocol.h"
  46.  
  47. OSErr POP_InitiateConnection(unsigned long popAddress,unsigned short popPort,char *user,char *password,unsigned long *connID)
  48. {
  49.     OSErr err;
  50.     Ptr response;
  51.     unsigned long responseLength;
  52.     char command[256];
  53.     
  54.     TCP_FlushBytes();
  55.     
  56.     err = TCP_CreateStream(connID);
  57.     if (err!=noErr) {
  58.         return err;
  59.     }
  60.  
  61.     err = TCP_ActiveOpen(*connID,popAddress,popPort,kPOPTimeout);
  62.     if (err!=noErr) {
  63.         TCP_ReleaseStream(*connID);
  64.         return kInvalidPopServer;
  65.     }
  66.     
  67.     POP_GetTextToCRLF(*connID,&response,&responseLength);
  68.     if (response)
  69.         DisposPtrChk(response);
  70.         
  71.     strcpy(command,"USER ");
  72.     strcat(command,user);
  73.     err = POP_Command(*connID,command,&response,&responseLength);
  74.     if (err!=noErr) {
  75.         POP_CloseConnection(*connID);
  76.         if (err==kPOPError)
  77.             err = kInvalidUsername;
  78.         return err;
  79.     }
  80.     DisposPtrChk(response);
  81.     
  82.     strcpy(command,"PASS ");
  83.     strcat(command,password);
  84.     err = POP_Command(*connID,command,&response,&responseLength);
  85.     if (err!=noErr) {
  86.         POP_CloseConnection(*connID);
  87.         if (err==kPOPError)
  88.             err = kInvalidPasssword;
  89.         return err;
  90.     }
  91.     DisposPtrChk(response);
  92.     
  93.     return err;
  94. }
  95.  
  96.  
  97. OSErr POP_GetDropStats(unsigned long connID,short *numMessages,long *messageSize)
  98. {
  99.     char command[256];
  100.     char *word,*responsePtr;
  101.     Ptr response;
  102.     unsigned long responseLength;
  103.     long number;
  104.     OSErr err;
  105.     
  106.     strcpy(command,"STAT");
  107.     err = POP_Command(connID,command,&response,&responseLength);
  108.     if (err!=noErr) {
  109.         return err;
  110.     }
  111.     
  112.     /* get drop text */
  113.     
  114.     responsePtr = (char *)response;
  115.     GetWord(&word,&responsePtr);            // get rid of +OK / -ERR
  116.     GetNumber(&number,&responsePtr);        // get number of messages
  117.     *numMessages = (short) number;
  118.     GetNumber(&number,&responsePtr);        // get size of mailbox in bytes
  119.     *messageSize = number;
  120.     
  121.     DisposPtrChk(response);
  122.     return err;
  123. }
  124.  
  125.  
  126. OSErr POP_GetMessageIDs(unsigned long connID,TMsgIDList *messageIDList,short *numMessageIDs)
  127. {
  128.     char command[256];
  129.     Ptr response;
  130.     unsigned long responseLength;
  131.     char *responsePtr;
  132.     long number;
  133.     short numMsgs,msgIndex;
  134.     OSErr err;
  135.     
  136.     strcpy(command,"LIST");
  137.     err = POP_Command(connID,command,&response,&responseLength);
  138.     if (err!=noErr) {
  139.         return err;
  140.     }
  141.     DisposPtrChk(response);
  142.     
  143.     err = POP_GetTextToTerminator(connID,&response,&responseLength);
  144.     if (err!=noErr) {
  145.         return err;
  146.     }
  147.  
  148.     if (responseLength==0) {
  149.         *numMessageIDs = 0;
  150.         return err;
  151.     }
  152.         
  153.     responsePtr = (char *)response;
  154.     numMsgs = *numMessageIDs = CountLines(responsePtr);
  155.     if (numMsgs > 0) {
  156.     
  157.         *messageIDList = (TMsgIDList)NewPtrChk(sizeof(TMsgID)*numMsgs);
  158.         if ((err=MemError())!=noErr) {
  159.             DisposPtrChk(response);
  160.             return err;
  161.         }
  162.         
  163.         msgIndex = 0;
  164.         while (*responsePtr) {
  165.             GetNumber(&number,&responsePtr);    // get message ID
  166.             (*messageIDList)[msgIndex] = (TMsgID)number;
  167.             GetNumber(&number,&responsePtr);    // get message size & discard in this version
  168.             msgIndex++;
  169.         }
  170.         
  171.     }
  172.     DisposPtrChk(response);
  173.     return err;
  174. }
  175.  
  176.  
  177. OSErr POP_GetMessage(unsigned long connID,TMsgID messageID,Ptr *messageData)
  178. {
  179.     char command[256],messageIDStr[256];
  180.     Ptr response;
  181.     unsigned long responseLength;
  182.     OSErr err;
  183.     
  184.     strcpy(command,"RETR ");
  185.     MessageIDToString(messageID,messageIDStr);
  186.     strcat(command,messageIDStr);
  187.     err = POP_Command(connID,command,&response,&responseLength);
  188.     if (err!=noErr) {
  189.         return err;
  190.     }
  191.     DisposPtrChk(response);
  192.     
  193.     err = POP_GetTextToTerminator(connID,&response,&responseLength);
  194.     if (err!=noErr) {
  195.         return err;
  196.     }
  197.  
  198.     if (responseLength==0)
  199.         return kErrResponse;
  200.         
  201.     StripLF((char *)response,&responseLength);
  202.     
  203.     *messageData = response;
  204.     return err;
  205. }
  206.  
  207.  
  208. OSErr POP_DeleteMessage(unsigned long connID,TMsgID messageID)
  209. {
  210.     char command[256],messageIDStr[256];
  211.     Ptr response;
  212.     unsigned long responseLength;
  213.     OSErr err;
  214.     
  215.     strcpy(command,"DELE ");
  216.     MessageIDToString(messageID,messageIDStr);
  217.     strcat(command,messageIDStr);
  218.     err = POP_Command(connID,command,&response,&responseLength);
  219.     if (err!=noErr) {
  220.         return err;
  221.     }
  222.     DisposPtrChk(response);
  223.     return err;
  224. }
  225.  
  226.  
  227. OSErr POP_CloseConnection(unsigned long connID)
  228. {
  229.     char command[256];
  230.     Ptr response;
  231.     unsigned long responseLength;
  232.     OSErr err;
  233.     
  234.     strcpy(command,"QUIT");
  235.     err = POP_Command(connID,command,&response,&responseLength);
  236.     if (err==noErr) {
  237.         DisposPtrChk(response);
  238.     }
  239.     
  240.     err = TCP_CloseConnection(connID,kPOPTimeout);
  241.     err = TCP_ReleaseStream(connID);
  242.     
  243.     TCP_FlushBytes();
  244.     
  245.     return err;
  246. }
  247.  
  248.  
  249. OSErr POP_Command(unsigned long connID,char *command,Ptr *response,unsigned long *responseLength)
  250. {
  251.     char sendCommand[256];
  252.     unsigned short sendLength;
  253.     OSErr err;
  254.     
  255.     strcpy(sendCommand,command);
  256.     strcat(sendCommand,kCRLF);
  257.     sendLength = strlen(sendCommand);
  258.     
  259.     err = TCP_Send(connID,sendCommand,sendLength,true,kPOPTimeout);
  260.     if (err!=noErr)
  261.         return err;
  262.     
  263.     err = POP_GetTextToCRLF(connID,response,responseLength);
  264.     if (err!=noErr)
  265.         return err;
  266.     
  267.     if (*responseLength>0 && (*response)[0]=='-') {
  268.         DisposPtrChk(*response);
  269.         return kPOPError;
  270.     }
  271.     
  272.     return noErr;
  273. }
  274.  
  275.  
  276. OSErr POP_GetTextToTerminator(unsigned long connID,Ptr *response,unsigned long *responseLength)
  277. {
  278.     OSErr err;
  279.     unsigned long receivedBytes;
  280.     Handle dataHandle;
  281.     Ptr dataPtr;
  282.     unsigned long handleSize;
  283.     unsigned char dataByte;
  284.     GetTermStates stateMachine;
  285.     
  286.     receivedBytes = 0;
  287.     handleSize = kTransactionBite;
  288.     dataHandle = NewHandleChk(handleSize);
  289.     if (MemError()!=noErr)
  290.         return MemError();
  291.     MoveHHi(dataHandle);
  292.     HLock(dataHandle);
  293.     dataPtr = *dataHandle;
  294.     
  295.     stateMachine = sGotLF;
  296.     
  297.     do {
  298.         err = TCP_ReadByte(connID,&dataByte,kPOPTimeout);
  299.         if (err==noErr) {
  300.         
  301.             /* store data */
  302.             
  303.             dataPtr[receivedBytes++] = dataByte;
  304.             
  305.             /* advance state machine */
  306.             
  307.             if (dataByte==CR) {
  308.                 if (stateMachine==sNormal || stateMachine==sGotTerminator)
  309.                     stateMachine++;
  310.                 else
  311.                     stateMachine==sNormal;
  312.             }
  313.             else if (dataByte==LF) {
  314.                 if (stateMachine==sGotCR || stateMachine==sGotPostTermCR)
  315.                     stateMachine++;
  316.                 else
  317.                     stateMachine==sNormal;
  318.             }
  319.             else if (dataByte==kMessageTerminator) {
  320.                 if (stateMachine==sGotLF)
  321.                     stateMachine++;
  322.                 else
  323.                     stateMachine==sNormal;
  324.             }
  325.             else
  326.                 stateMachine = sNormal;
  327.             
  328.             if (receivedBytes==handleSize) {
  329.                 handleSize += kTransactionBite;
  330.                 HUnlock(dataHandle);
  331.                 SetHandleSize(dataHandle,handleSize);
  332.                 err = MemError();
  333.                 MoveHHi(dataHandle);
  334.                 HLock(dataHandle);
  335.                 dataPtr = *dataHandle;
  336.             }
  337.         }
  338.     } while (err==noErr && handleSize <= kMaxPOPTransactionSize && stateMachine!=sFinished);
  339.     
  340.     if (stateMachine==sFinished)
  341.         receivedBytes -= 3;
  342.         
  343.     *responseLength = receivedBytes;
  344.  
  345.     if (receivedBytes!=0) {
  346.         *response = NewPtrChk(receivedBytes+1);
  347.         if (MemError()!=noErr)
  348.             return MemError();
  349.         BlockMove(dataPtr,*response,receivedBytes);
  350.         (*response)[receivedBytes++] = '\0';        // null terminate response
  351.     }
  352.     
  353.     DisposHandleChk(dataHandle);
  354.     
  355.     return err;
  356. }
  357.  
  358.  
  359. OSErr POP_GetTextToCRLF(unsigned long connID,Ptr *response,unsigned long *responseLength)
  360. {
  361.     OSErr err;
  362.     unsigned long receivedBytes;
  363.     Handle dataHandle;
  364.     Ptr dataPtr;
  365.     unsigned long handleSize;
  366.     unsigned char dataByte;
  367.     GetCRLFStates stateMachine;
  368.     
  369.     receivedBytes = 0;
  370.     handleSize = kTransactionBite;
  371.     dataHandle = NewHandleChk(handleSize);
  372.     if (MemError()!=noErr)
  373.         return MemError();
  374.     MoveHHi(dataHandle);
  375.     HLock(dataHandle);
  376.     dataPtr = *dataHandle;
  377.     
  378.     stateMachine = sCRLFNormal;
  379.     
  380.     do {
  381.         err = TCP_ReadByte(connID,&dataByte,kPOPTimeout);
  382.         if (err==noErr) {
  383.         
  384.             /* store data */
  385.             
  386.             dataPtr[receivedBytes++] = dataByte;
  387.             
  388.             /* advance state machine */
  389.             
  390.             if (dataByte==CR) {
  391.                 if (stateMachine==sCRLFNormal)
  392.                     stateMachine++;
  393.                 else
  394.                     stateMachine==sCRLFNormal;
  395.             }
  396.             else if (dataByte==LF) {
  397.                 if (stateMachine==sCRLFGotCR)
  398.                     stateMachine++;
  399.                 else
  400.                     stateMachine==sCRLFNormal;
  401.             }
  402.             else
  403.                 stateMachine = sCRLFNormal;
  404.             
  405.             if (receivedBytes==handleSize) {
  406.                 handleSize += kTransactionBite;
  407.                 HUnlock(dataHandle);
  408.                 SetHandleSize(dataHandle,handleSize);
  409.                 err = MemError();
  410.                 MoveHHi(dataHandle);
  411.                 HLock(dataHandle);
  412.                 dataPtr = *dataHandle;
  413.             }
  414.         }
  415.     } while (err==noErr && handleSize <= kMaxPOPTransactionSize && stateMachine!=sCRLFFinished);
  416.     
  417.     if (stateMachine==sCRLFFinished)
  418.         receivedBytes -= 2;
  419.     
  420.     *responseLength = receivedBytes;
  421.     
  422.     if (receivedBytes!=0) {
  423.         *response = NewPtrChk(receivedBytes+1);
  424.         if ((err = MemError())!=noErr) {
  425.             DisposHandleChk(dataHandle);
  426.             return err;
  427.         }
  428.         BlockMove(dataPtr,*response,receivedBytes);
  429.         (*response)[receivedBytes++] = '\0';        // null terminate response
  430.         DisposHandleChk(dataHandle);
  431.     }
  432.     
  433.     return err;
  434. }
  435.  
  436.  
  437. void MessageIDToString(TMsgID messageID,char *messageIDStr)
  438. {
  439.     long msgIDLong;
  440.     
  441.     msgIDLong = (long) messageID;
  442.     NumToString(msgIDLong,(StringPtr)messageIDStr);
  443.     p2cstr(messageIDStr);
  444. }
  445.