home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Muddweller 1.2 / source code / Main / MTPStuff.cp < prev    next >
Encoding:
Text File  |  1994-02-14  |  14.5 KB  |  589 lines  |  [TEXT/MPS ]

  1. /* MTPStuff - Implementation of the MTP client routines                       */
  2.  
  3. #include "MTPStuff.h"
  4.  
  5.  
  6.         // • Toolbox
  7. #ifndef __ERRORS__
  8. #include "Errors.h"
  9. #endif
  10.  
  11. #ifndef ipBadLapErr
  12. #include "MacTCPCommonTypes.h"
  13. #endif
  14.  
  15. #ifndef __RESOURCES__
  16. #include "Resources.h"
  17. #endif
  18.  
  19. #ifndef __STDIO__
  20. #include "StdIO.h"
  21. #endif
  22.  
  23. #ifndef TCPCreate
  24. #include "TCPPB.h"
  25. #endif
  26.  
  27.  
  28.         // • Implementation use
  29. #ifndef __FILTERS__
  30. #include "Filters.h"
  31. #endif
  32.  
  33. #ifndef __GLOBALS__
  34. #include "Globals.h"
  35. #endif
  36.  
  37.  
  38. struct mtpheader
  39. {
  40.     unsigned char player[20];        /* name of the wizard */
  41.     unsigned char passwd[15];        /* password */
  42.     unsigned char filename[50];        /* name of the datafile */
  43.     unsigned char directory[20];    /* directory containing datafile */
  44.     unsigned short filelength;        /* length of datablock */
  45.     short flags;                    /* controlflags */
  46. };
  47.  
  48. const int OVERWRITE = 1;
  49. const int RECEIVE = 2;
  50. const int VERSION_TWO = 4;
  51.  
  52. struct mtpmessage
  53. {
  54.     char message[200];
  55.     short quit;
  56. };
  57.  
  58. struct WDSBuffer
  59. {
  60.     unsigned short length;
  61.     unsigned char *ptr;
  62.     short endMarker;
  63. };
  64.  
  65.  
  66. //------------------------------------------------------------------------------
  67.  
  68. const int kTCPBufferSize = 8 * 1024;
  69. const int kTmpBufferSize = 2 * 1024;
  70. const int kMTPTimeout = 30;
  71. const int kMaxFileSize = 65535;
  72.  
  73. //------------------------------------------------------------------------------
  74.  
  75. static long tcpStream;
  76. static Ptr tcpBuffer;
  77. static short dRef, rRef;
  78.  
  79. //------------------------------------------------------------------------------
  80.  
  81. pascal void OpenConn (long tcpAddr, short tcpPort);
  82. pascal long OpenStream ();
  83. pascal void ReceiveData (unsigned char *buf, long len);
  84. pascal void SendData (unsigned char *buf, long len);
  85. pascal void SendFile (TMUDDoc *theDoc, short fRef);
  86. pascal void ShowError (unsigned char *msg, TMUDDoc *aDoc);
  87. pascal void ShowMsg (mtpmessage *msg, TMUDDoc *aDoc);
  88.  
  89. //------------------------------------------------------------------------------
  90.  
  91. #pragma segment SMTPStuff
  92.  
  93. pascal void CloseStream ()
  94. {
  95.     TCPiopb pb;
  96.  
  97.     if (tcpStream != 0) {
  98.         pb.ioNamePtr = NULL;
  99.         pb.ioCRefNum = gTCPRef;
  100.         pb.tcpStream = tcpStream;
  101.         pb.csCode = TCPRelease;
  102.         PBControl ((ParamBlockRec *) &pb, FALSE);
  103.     }
  104.     if (tcpBuffer != NULL) {
  105.         DisposIfPtr (tcpBuffer);
  106.         tcpBuffer = NULL;
  107.     }
  108. }
  109.  
  110. //------------------------------------------------------------------------------
  111.  
  112. #pragma segment SMTPStuff
  113.  
  114. pascal void CopyP2CStr (unsigned char *aPStr, unsigned char *aCStr)
  115. {
  116.     int len;
  117.  
  118.     len = *aPStr++;
  119.     for (int i = 0; i < len; i++) *aCStr++ = *aPStr++;
  120.     *aCStr = 0;
  121. }
  122.  
  123. //------------------------------------------------------------------------------
  124.  
  125. #pragma segment SMTPStuff
  126.  
  127. pascal long GetFileLength (TMUDDoc *theDoc, short fRef)
  128. {
  129.     long length, l, count, pos;
  130.     unsigned char buffer[kTmpBufferSize];
  131.     
  132.     FailOSErr (GetEOF (fRef, &length));
  133.     if (theDoc->fCvtTab) {
  134.         l = length;
  135.         length = 0;
  136.         pos = 0;
  137.         while (l > 0) {
  138.             if (l > kTmpBufferSize)
  139.                 count = kTmpBufferSize;
  140.             else
  141.                 count = l;
  142.             FailOSErr (FSRead (fRef, &count, (Ptr) buffer));
  143.             for (int i = 0; i < count; i ++) {
  144.                 if ((buffer [i] == chReturn) || (buffer [i] == chLineFeed)) {
  145.                     length += pos + 1;
  146.                     pos = 0;
  147.                 } else if (buffer [i] == chTab) {
  148.                     pos += theDoc->fSTab;
  149.                     pos -= pos % theDoc->fSTab;
  150.                 } else
  151.                     pos++;
  152.             }
  153.             l -= count;
  154.         }
  155.         FailOSErr (SetFPos (fRef, fsFromStart, 0));
  156.     }
  157.     return length;
  158. }
  159.  
  160. //------------------------------------------------------------------------------
  161.  
  162. #pragma segment SMTPStuff
  163.  
  164. pascal void MTPBuildPath (TMUDDoc *theDoc, AppFile *aFile, Str255 path)
  165. {
  166.     WDPBRec    pb;
  167.     CInfoPBRec    ipb;
  168.     short vRefNum;
  169.     long dirID;
  170.     Str255 name;
  171.     
  172.     pb.ioNamePtr = NULL;
  173.     pb.ioVRefNum = aFile->vRefNum;
  174.     pb.ioWDIndex = 0;
  175.     pb.ioWDProcID = 0;
  176.     pb.ioWDVRefNum = 0;
  177.     FailOSErr (PBGetWDInfo (&pb, FALSE));
  178.     vRefNum = pb.ioWDVRefNum;
  179.     dirID = pb.ioWDDirID;
  180.     CopyStr255 (aFile->fName, path);
  181.     if (vRefNum == theDoc->fMTPVRefNum) {
  182.         ipb.dirInfo.ioNamePtr = name;
  183.         while ((dirID != 2) && (dirID != theDoc->fMTPDirID)) {
  184.             ipb.dirInfo.ioVRefNum = vRefNum;
  185.             ipb.dirInfo.ioFDirIndex = -1;
  186.             ipb.dirInfo.ioDrDirID = dirID;
  187.             FailOSErr (PBGetCatInfo (&ipb, FALSE));
  188.             PStrCat (name, (unsigned char *) "\p/");
  189.             PStrCat (name, path);
  190.             CopyStr255 (name, path);
  191.             dirID = ipb.dirInfo.ioDrParID;
  192.         }
  193.         if ((path [0] >= 50) || (dirID != theDoc->fMTPDirID))
  194.             CopyStr255 (aFile->fName, path);
  195.     }
  196. }
  197.  
  198. //------------------------------------------------------------------------------
  199.  
  200. #pragma segment SMTPStuff
  201.  
  202. pascal void MTPDirCheck (TMUDDoc *theDoc)
  203. {
  204.     Str255 tmp;
  205.     ParamBlockRec pb;
  206.     OSErr err;
  207.     CInfoPBRec ipb;
  208.     Boolean found;
  209.  
  210.     CopyStr255 (theDoc->fMTPVol, tmp);
  211.     if (tmp [tmp [0] + 1] != ':') tmp [++(tmp [0])] = ':';
  212.     pb.volumeParam.ioNamePtr = tmp;
  213.     pb.volumeParam.ioVRefNum = 0;
  214.     pb.volumeParam.ioVolIndex = -1;
  215.     err = PBGetVInfo (&pb, FALSE);
  216.     if (err != noErr) {
  217.         MTPDirSetup (theDoc, gDefVRefNum, gDefDirID);
  218.         found = FALSE;
  219.     } else {
  220.         theDoc->fMTPVRefNum = pb.volumeParam.ioVRefNum;
  221.         CopyStr255 (pb.volumeParam.ioNamePtr, theDoc->fMTPVol);
  222.         ipb.dirInfo.ioNamePtr = tmp;
  223.         ipb.dirInfo.ioVRefNum = theDoc->fMTPVRefNum;
  224.         ipb.dirInfo.ioDrDirID = theDoc->fMTPDirID;
  225.         ipb.dirInfo.ioFDirIndex = -1;
  226.         err = PBGetCatInfo (&ipb, FALSE);
  227.         if ((err == dirNFErr) || (err == fnfErr)) {
  228.             MTPDirSetup (theDoc, gDefVRefNum, gDefDirID);
  229.             found = FALSE;
  230.         } else {
  231.             FailOSErr (err);
  232.             CopyStr255 (ipb.dirInfo.ioNamePtr, theDoc->fMTPDir);
  233.             found = TRUE;
  234.         }
  235.     }
  236.     if (!found) {
  237.         StdAlert (phNoMTPDirID);
  238.         theDoc->fChangeCount += 1;
  239.     }
  240. }
  241.  
  242. //------------------------------------------------------------------------------
  243.  
  244. #pragma segment SMTPStuff
  245.  
  246. pascal void MTPDirSetup (TMUDDoc *theDoc, short vRefNum, long dirID)
  247. {
  248.     Str255 tmp;
  249.     CInfoPBRec pb;
  250.     OSErr err;
  251.     short refNum;
  252.     
  253.     theDoc->fMTPVRefNum = vRefNum;
  254.     theDoc->fMTPDirID = dirID;
  255.     theDoc->fMTPVol [0] = 0;
  256.     theDoc->fMTPDir [0] = 0;
  257.     pb.dirInfo.ioNamePtr = tmp;
  258.     pb.dirInfo.ioVRefNum = theDoc->fMTPVRefNum;
  259.     pb.dirInfo.ioDrDirID = 2;
  260.     pb.dirInfo.ioFDirIndex = -1;
  261.     err = PBGetCatInfo (&pb, FALSE);
  262.     if (err == dirNFErr) {
  263.         FailOSErr (GetVol ((StringPtr) tmp, &refNum));
  264.         theDoc->fMTPVRefNum = refNum;
  265.         theDoc->fMTPDirID = 2;
  266.         CopyStr255 (tmp, theDoc->fMTPVol);
  267.         CopyStr255 (tmp, theDoc->fMTPDir);
  268.     } else
  269.         FailOSErr (err);
  270.     CopyStr255 (pb.dirInfo.ioNamePtr, theDoc->fMTPVol);
  271.     pb.dirInfo.ioNamePtr = tmp;
  272.     pb.dirInfo.ioVRefNum = theDoc->fMTPVRefNum;
  273.     pb.dirInfo.ioDrDirID = theDoc->fMTPDirID;
  274.     pb.dirInfo.ioFDirIndex = -1;
  275.     err = PBGetCatInfo (&pb, FALSE);
  276.     if (err == dirNFErr) {
  277.         theDoc->fMTPDirID = 2;
  278.         CopyStr255 (theDoc->fMTPVol, theDoc->fMTPDir);
  279.     } else
  280.         FailOSErr (err);
  281.     CopyStr255 (pb.dirInfo.ioNamePtr, theDoc->fMTPDir);
  282. }
  283.  
  284. //------------------------------------------------------------------------------
  285.  
  286. #pragma segment SMTPStuff
  287.  
  288. pascal void MTPReceiveHandler (short , long , void * )
  289. {
  290.     CloseStream ();
  291.     CloseFile (dRef, rRef);
  292. }
  293.  
  294. pascal void MTPReceive (TMUDDoc *theDoc, Str255 path, Str255 fileName,
  295.         short vRefNum)
  296. {
  297.     long length, rest, count;
  298.     FailInfo fi;
  299.     unsigned char hello[1];
  300.     mtpheader header;
  301.     mtpmessage msg;
  302.     unsigned char buffer[kTmpBufferSize];
  303.     
  304.     tcpStream = 0;
  305.     tcpBuffer = NULL;
  306.     FailOSErr (Create (fileName, vRefNum, theDoc->fTextSig, 'TEXT'));
  307.     FailOSErr (MAOpenFile (fileName, vRefNum, TRUE, FALSE, fsWrPerm, fsRdPerm,
  308.         &dRef, &rRef));
  309.     CatchFailures (&fi, MTPReceiveHandler, kDummyLink);
  310.     tcpStream = OpenStream ();
  311.     OpenConn (theDoc->fTCPAddr, theDoc->fMTPPort);
  312.     hello[0] = '@';
  313.     SendData (hello, 1);
  314.     header.filelength = 0;
  315.     header.flags = OVERWRITE + RECEIVE + VERSION_TWO;
  316.     CopyP2CStr (theDoc->fPlayer, header.player);
  317.     CopyP2CStr (theDoc->fPasswd, header.passwd);
  318.     CopyP2CStr (path, header.filename);
  319.     header.directory [0] = 0;
  320.     SendData ((unsigned char *) &header, sizeof (header));
  321.     ReceiveData ((unsigned char *) &msg, sizeof (msg));
  322.     ShowMsg (&msg, theDoc);
  323.     ReceiveData ((unsigned char *) &header, sizeof (header));
  324.     length = header.filelength;
  325.     rest = length;
  326.     while (rest > 0) {
  327.         if (rest > kTmpBufferSize)
  328.             count = kTmpBufferSize;
  329.         else
  330.             count = rest;
  331.         ReceiveData (buffer, count);
  332.         rest -= count;
  333.         for (int i = 0; i < count; i++)
  334.             if (buffer [i] == chLineFeed) buffer [i] = chReturn;
  335.         FailOSErr (FSWrite (dRef, &count, (Ptr) &buffer));
  336.     }
  337.     FailOSErr (SetEOF (dRef, length));
  338.     ReceiveData ((unsigned char *) &msg, sizeof (msg));
  339.     ShowMsg (&msg, theDoc);
  340.     Success (&fi);
  341.     CloseStream ();
  342.     FailOSErr (CloseFile (dRef, rRef));
  343.     FailOSErr (FlushVol (NULL, vRefNum));
  344. }
  345.  
  346. //------------------------------------------------------------------------------
  347.  
  348. #pragma segment SMTPStuff
  349.  
  350. pascal void MTPSendHandler (short , long , void * )
  351. {
  352.     CloseStream ();
  353.     CloseFile (dRef, rRef);
  354. }
  355.  
  356. pascal void MTPSend (TMUDDoc *theDoc, AppFile *theFile, Str255 path)
  357. {
  358.     long length;
  359.     FailInfo fi;
  360.     unsigned char hello[1];
  361.     mtpheader header;
  362.     mtpmessage msg;
  363.     Str255 tmp;
  364.     
  365.     tcpStream = 0;
  366.     tcpBuffer = NULL;
  367.     FailOSErr (MAOpenFile (theFile->fName, theFile->vRefNum, TRUE, FALSE,
  368.         fsRdPerm, fsRdPerm, &dRef, &rRef));
  369.     CatchFailures (&fi, MTPSendHandler, kDummyLink);
  370.     length = GetFileLength (theDoc, dRef);
  371.     if ((length < 0) || (length > kMaxFileSize)) {
  372.         ShowError ((unsigned char *) "MTP error: file too long.\12", theDoc);
  373.         Failure (0, msgCancelled);
  374.     }
  375.     tcpStream = OpenStream ();
  376.     OpenConn (theDoc->fTCPAddr, theDoc->fMTPPort);
  377.     hello[0] = '@';
  378.     SendData (hello, 1);
  379.     header.filelength = (unsigned short) length;
  380.     header.flags = OVERWRITE + VERSION_TWO;
  381.     CopyStr255 (theDoc->fPlayer, tmp);
  382.     if (tmp [0] > 19) tmp [0] = 19;
  383.     CopyP2CStr (tmp, header.player);
  384.     CopyStr255 (theDoc->fPasswd, tmp);
  385.     if (tmp [0] > 14) tmp [0] = 14;
  386.     CopyP2CStr (tmp, header.passwd);
  387.     CopyP2CStr (path, header.filename);
  388.     header.directory [0] = 0;
  389.     SendData ((unsigned char *) &header, sizeof (header));
  390.     ReceiveData ((unsigned char *) &msg, sizeof (msg));
  391.     ShowMsg (&msg, theDoc);
  392.     if (msg.quit == 1) Failure (0, msgCancelled);
  393.     SendFile (theDoc, dRef);
  394.     ReceiveData ((unsigned char *) &msg, sizeof (msg));
  395.     ShowMsg (&msg, theDoc);
  396.     Success (&fi);
  397.     CloseStream ();
  398.     FailOSErr (CloseFile (dRef, rRef));
  399.     FailOSErr (FlushVol (NULL, theFile->vRefNum));
  400. }
  401.  
  402. //------------------------------------------------------------------------------
  403.  
  404. #pragma segment SMTPStuff
  405.  
  406. pascal void OpenConn (long tcpAddr, short tcpPort)
  407. {
  408.     TCPiopb pb;
  409.  
  410.     pb.ioNamePtr = NULL;
  411.     pb.ioCRefNum = gTCPRef;
  412.     pb.tcpStream = tcpStream;
  413.     pb.csCode = TCPActiveOpen;
  414.     pb.csParam.open.ulpTimeoutValue = kMTPTimeout;
  415.     pb.csParam.open.ulpTimeoutAction = 1;
  416.     pb.csParam.open.validityFlags = timeoutValue + timeoutAction;
  417.     pb.csParam.open.remoteHost = tcpAddr;
  418.     pb.csParam.open.remotePort = tcpPort;
  419.     pb.csParam.open.localPort = 0;
  420.     pb.csParam.open.tosFlags = 0;
  421.     pb.csParam.open.precedence = 0;
  422.     pb.csParam.open.dontFrag = FALSE;
  423.     pb.csParam.open.timeToLive = 0;
  424.     pb.csParam.open.security = 0;
  425.     pb.csParam.open.optionCnt = 0;
  426.     FailOSErr (PBControl ((ParamBlockRec *) &pb, FALSE));
  427. }
  428.  
  429. //------------------------------------------------------------------------------
  430.  
  431. #pragma segment SMTPStuff
  432.  
  433. pascal long OpenStream ()
  434. {
  435.     TCPiopb pb;
  436.  
  437.     tcpBuffer = NewPermPtr (kTCPBufferSize);
  438.     FailNIL (tcpBuffer);
  439.     pb.ioNamePtr = NULL;
  440.     pb.ioCRefNum = gTCPRef;
  441.     pb.csCode = TCPCreate;
  442.     pb.csParam.create.rcvBuff = tcpBuffer;
  443.     pb.csParam.create.rcvBuffLen = kTCPBufferSize;
  444.     pb.csParam.create.notifyProc = 0;
  445.     FailOSErr (PBControl ((ParamBlockRec *) &pb, FALSE));
  446.     return pb.tcpStream;
  447. }
  448.  
  449. //------------------------------------------------------------------------------
  450.  
  451. #pragma segment SMTPStuff
  452.  
  453. pascal void PStrCat (unsigned char *str, unsigned char *src)
  454. {
  455.     unsigned char *s2;
  456.     short len;
  457.  
  458.     s2 = str + *str;
  459.     len = *src;
  460.     if (*str + len > 255) len = 255 - *str;
  461.     *str += len;
  462.     for (++len; --len; s2 [len] = src [len]);
  463. }
  464.  
  465. //------------------------------------------------------------------------------
  466.  
  467. #pragma segment SMTPStuff
  468.  
  469. pascal void ReceiveData (unsigned char *buf, long len)
  470. {
  471.     TCPiopb pb;
  472.     unsigned short count;
  473.  
  474.     count = (unsigned short) len;
  475.     while (count > 0) {
  476.         pb.ioNamePtr = NULL;
  477.         pb.ioCRefNum = gTCPRef;
  478.         pb.tcpStream = tcpStream;
  479.         pb.csCode = TCPRcv;
  480.         pb.csParam.receive.commandTimeoutValue = kMTPTimeout;
  481.         pb.csParam.receive.rcvBuff = (Ptr) buf;
  482.         pb.csParam.receive.rcvBuffLen = count;
  483.         pb.csParam.receive.rdsPtr = NULL;
  484.         pb.csParam.receive.rdsLength = 0;
  485.         FailOSErr (PBControl ((ParamBlockRec *) &pb, FALSE));
  486.         count -= pb.csParam.receive.rcvBuffLen;
  487.         buf += pb.csParam.receive.rcvBuffLen;
  488.     }
  489. }
  490.  
  491. //------------------------------------------------------------------------------
  492.  
  493. #pragma segment SMTPStuff
  494.  
  495. pascal void SendData (unsigned char *buf, long len)
  496. {
  497.     TCPiopb pb;
  498.     WDSBuffer wds;
  499.  
  500.     pb.ioNamePtr = NULL;
  501.     pb.ioCRefNum = gTCPRef;
  502.     pb.tcpStream = tcpStream;
  503.     pb.csCode = TCPSend;
  504.     pb.csParam.send.ulpTimeoutValue = kMTPTimeout;
  505.     pb.csParam.send.ulpTimeoutAction = 1;
  506.     pb.csParam.send.validityFlags = timeoutValue + timeoutAction;
  507.     pb.csParam.send.pushFlag = 0;
  508.     pb.csParam.send.urgentFlag = 0;
  509.     pb.csParam.send.wdsPtr = (Ptr) &wds;
  510.     pb.csParam.send.sendFree = 0;
  511.     pb.csParam.send.sendLength = 0;
  512.     pb.csParam.send.userDataPtr = NULL;
  513.     wds.length = (unsigned short) len;
  514.     wds.ptr = buf;
  515.     wds.endMarker = 0;
  516.     FailOSErr (PBControl ((ParamBlockRec *) &pb, FALSE));
  517. }
  518.  
  519. //------------------------------------------------------------------------------
  520.  
  521. #pragma segment SMTPStuff
  522.  
  523. pascal void SendFile (TMUDDoc *theDoc, short fRef)
  524. {
  525.     long length, l, count, pos;
  526.     int oc, i;
  527.     unsigned char inBuf [kTmpBufferSize], outBuf [kTmpBufferSize];
  528.  
  529.     FailOSErr (GetEOF (fRef, &length));
  530.     l = length;
  531.     pos = 0;
  532.     oc = 0;
  533.     while (l > 0) {
  534.         if (l > kTmpBufferSize)
  535.             count = kTmpBufferSize;
  536.         else
  537.             count = l;
  538.         FailOSErr (FSRead (fRef, &count, (Ptr) inBuf));
  539.         i = 0;
  540.         while (i < count) {
  541.             if ((inBuf [i] == chReturn) || (inBuf [i] == chLineFeed)) {
  542.                 outBuf [oc++] = chLineFeed;
  543.                 i++;
  544.                 pos = 0;
  545.             } else if ((inBuf [i] == chTab) && (theDoc->fCvtTab)) {
  546.                 outBuf [oc++] = ' ';
  547.                 pos++;
  548.                 if ((pos % theDoc->fSTab) == 0) i++;
  549.             } else {
  550.                 outBuf [oc++] = inBuf [i];
  551.                 i++;
  552.                 pos++;
  553.             }
  554.             if (oc >= kTmpBufferSize) {
  555.                 SendData (outBuf, oc);
  556.                 oc = 0;
  557.             }
  558.         }
  559.         l -= count;
  560.     }
  561.     if (oc > 0) SendData (outBuf, oc);
  562. }
  563.  
  564. //------------------------------------------------------------------------------
  565.  
  566. #pragma segment SMTPStuff
  567.  
  568. pascal void ShowError (unsigned char *msg, TMUDDoc *aDoc)
  569. {
  570.     long len;
  571.     
  572.     for (len = 0; msg [len] != 0; len++) ;
  573.     aDoc->fEchoFilter->Filter (msg, len);
  574. }
  575.  
  576. //------------------------------------------------------------------------------
  577.  
  578. #pragma segment SMTPStuff
  579.  
  580. pascal void ShowMsg (mtpmessage *msg, TMUDDoc *aDoc)
  581. {
  582.     long len;
  583.     
  584.     for (len = 0; msg->message [len] != 0; len++) ;
  585.     aDoc->fEchoFilter->Filter ((unsigned char *) msg->message, len);
  586. }
  587.  
  588. //------------------------------------------------------------------------------
  589.