home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / e_mac / e_cgi_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-25  |  21.0 KB  |  753 lines  |  [TEXT/CWIE]

  1. // e_cgi_main.c
  2. // 14May97 e
  3.  
  4. // a substitute MacOS pacifier and AppleEvent Handler for mosml cgi programs
  5.  
  6. #include "os_mac.h"
  7. #include <signal.h>
  8.  
  9. #define CRLF_TRANSLATE 1
  10.  
  11. long next_eventchk_ticks;
  12. long gWaitTicksBG =   6; /* in ticks, should be 6..60 */
  13. long gWaitTicksFG =   1; /* in ticks, should be 1..15 */
  14. long gMaxSleep    =  18;
  15.  
  16. char *image_name = NULL;
  17. FSSpec appFSS;
  18.  
  19. RgnHandle gCursorRgn;
  20.  
  21. short interrupted =   0;
  22.  
  23. char      gReceivedAE = 0;
  24. Boolean   gMadeAppFSS = false;
  25. Boolean   gDoQuit = false;
  26. Boolean   gInBackground = false;
  27. Boolean   gHasAppleEvents = false;
  28. Boolean     gAESuspn = false;
  29. AppleEvent  gAEEvent;
  30. AppleEvent  gAEReply;
  31.  
  32. MenuRef f_menu, a_menu;
  33.  
  34. // utils
  35.  
  36. static void ParamText1( Str255 text )
  37. {
  38.   ParamText( text, "\p", "\p", "\p" );
  39. }
  40.  
  41. static void path_too_long_err( Str255 name )
  42. { ParamText( "\pPath to file \"", name, "\p\" is too long.", "\p" );
  43.   SysBeep( 10 );
  44.   StopAlert( ok_alertID, 0L );
  45. }
  46.  
  47. void io_err( short io )
  48. { unsigned char errnostr[16];
  49.   switch (io)
  50.   { case wrPermErr    : ParamText1( "\pCan't write file!" ); break;
  51.     case dupFNErr     : ParamText1( "\pDuplicate file name!" ); break;
  52.     case fBsyErr      : ParamText1( "\pFile is busy!" ); break;
  53.     case vLckdErr     : ParamText1( "\pVolume is locked!" ); break;
  54.     case fLckdErr     : ParamText1( "\pFile is locked!" ); break;
  55.     case fnfErr       : ParamText1( "\pFile not found!" ); break;
  56.     case bdNamErr     : ParamText1( "\pBad filename!" ); break;
  57.     case ioErr        : ParamText1( "\pIO transfer error!" ); break;
  58.     case dskFulErr    : ParamText1( "\pDisk full!" ); break;
  59.     case dirFulErr    : ParamText1( "\pDirectory full!" ); break;
  60.     case mFulErr      : ParamText1( "\pFile is too large for memory!" ); break;
  61.                         
  62.     case -4101        : ParamText1( "\pNo printer selected. Use the Chooser." ); break;
  63.     default           : NumToString( io, errnostr );
  64.                         ParamText( "\pIO Error! Mac error number: ", errnostr, "\p", "\p" );
  65.                         break;
  66.   }
  67.   SysBeep( 10 );
  68.   StopAlert( ok_alertID, 0L );
  69. }
  70.  
  71. short getfullpath( 
  72.     short vRefNum,
  73.     long dirID,
  74.     Str255 fName,
  75.     char *Path,
  76.     short MaxLength,
  77.     short warn )
  78. {
  79.   char *p, *q;
  80.   long len;
  81.   CInfoPBRec block;
  82.   Str255 directoryName;
  83.  
  84.   p = &Path[MaxLength];
  85.   *--p = '\0';
  86.  
  87.   len = (unsigned char)fName[0];
  88.   p -= len;
  89.   if (p < Path) goto too_long;
  90.   BlockMove( &fName[1], p, len );
  91.  
  92.   block.dirInfo.ioNamePtr = directoryName;
  93.   block.dirInfo.ioDrParID = dirID;
  94.  
  95.   do
  96.   { block.dirInfo.ioVRefNum = vRefNum;
  97.     block.dirInfo.ioFDirIndex = -1;
  98.     block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
  99.  
  100.     if (PBGetCatInfoSync( &block ) != noErr) return 0;
  101.     *--p = ':';
  102.     len = (unsigned char)directoryName[0];
  103.     p -= len;
  104.     if (p < Path) goto too_long;
  105.     BlockMove( &directoryName[1], p, len );
  106.   } while ( block.dirInfo.ioDrDirID != fsRtDirID );
  107.  
  108.   q = Path;
  109.   while (*p != '\0') *q++ = *p++;
  110.   *q = '\0';
  111.  
  112.   return (short )( q - Path );
  113.  
  114.   too_long:
  115.   if (warn) path_too_long_err( fName );
  116.   return 0;
  117. }
  118.  
  119. // ********************* events **********************
  120.  
  121. long os_get_next_event( EventRecord *event )
  122. { long result = 0;
  123.   if (1) // do_tasks()
  124.   { beg_mf_time();
  125.     result = (long)( gInBackground
  126.                    ? gWaitTicksBG 
  127.                    : (long )( (gWaitTicksFG > gMaxSleep) ? gMaxSleep : gWaitTicksFG) );
  128.     result = WaitNextEvent( everyEvent, event, result, gCursorRgn );
  129.     end_mf_time();
  130.   }
  131.   return result;
  132. }
  133.  
  134. long os_handle_event( EventRecord *event )
  135. {
  136.   WindowPtr window;
  137.   short theItem, theMenu;
  138.   
  139.   switch (event->what)
  140.   { 
  141.     case keyDown:
  142.     case autoKey:
  143.     { unsigned char c = event->message & charCodeMask;
  144.       if( (event->modifiers & cmdKey) != 0 && (c == 'q' || c == 'Q') )
  145.       { gDoQuit = 1;
  146.         os_quit();
  147.       }
  148.       break;
  149.     }
  150.  
  151.     case mouseDown:
  152.       if (FindWindow( event->where, &window ) == inMenuBar)
  153.       {
  154.         long menuChoice = MenuSelect( event->where );
  155.         theItem = LoWord(menuChoice);
  156.         theMenu = HiWord(menuChoice);
  157.         if( theMenu == fileID && theItem == 1 )
  158.         {
  159.           gDoQuit = 1;
  160.           os_quit();
  161.         }
  162.         else if( theMenu == appleID && theItem > 2 )
  163.         {
  164.           Str255 name;
  165.           GetMenuItemText( a_menu, theItem, name );
  166.           OpenDeskAcc( name );
  167.         }
  168.         //else SysBeep( 3 );
  169.         HiliteMenu(0);
  170.       }
  171.       break;
  172.  
  173.     case kHighLevelEvent:
  174.       AEProcessAppleEvent(event);
  175.       if (gDoQuit) os_quit();
  176.       break;
  177.  
  178.     default: ;
  179.   }
  180.   return 1;
  181. }
  182.  
  183. void os_event_check( void )
  184. { EventRecord event;
  185.   os_get_next_event( &event );
  186.   os_handle_event( &event );
  187. #if USE_EVENTCHK_TIMER
  188.   next_eventchk_ticks = 0;
  189. #else
  190.   next_eventchk_ticks = LMGetTicks() + TicksBetweenEventChecks;
  191. #endif
  192.   if ( interrupted ) { interrupted = 0; raise(SIGINT); }
  193. }
  194.  
  195. // ********************* console **********************
  196.  
  197. static void init_all(void);
  198.  
  199. static short console_initialized = 0;
  200. static long handleSizeOut;
  201. static long stringSizeOut;
  202. static Handle the_output;
  203. static long stringSizeIn;
  204. static long stringUsedIn;
  205. static Handle the_input;
  206.  
  207. #define osc_INIT_SIZE  4096
  208. #define osc_RESIZE_ADD 4096
  209.  
  210. void os_quit()
  211. #if ANSIquitP
  212.   exit(0);
  213. #else
  214. #if USE_EVENTCHK_TIMER
  215.   cancel_eck_timer();
  216. #endif
  217.   ExitToShell();
  218. #endif
  219. }
  220.  
  221. // stub
  222.  
  223. int ecommand(unsigned char ***av)
  224. {
  225.   #pragma unused( av )
  226.   return 0;
  227. }
  228.  
  229. WindowPeek os_console_new( unsigned char *name )
  230. {
  231.   #pragma unused( name )
  232.   WindowPeek wp;
  233.   if( !console_initialized )
  234.   { init_all();
  235.     console_initialized = 1;
  236.   }
  237.   wp = (WindowPeek )NewHandle(osc_INIT_SIZE); // what a hack
  238.   the_output = (Handle )wp;
  239.   if( wp )
  240.   {
  241.     **(char **)wp = 0;
  242.     handleSizeOut = osc_INIT_SIZE;
  243.     stringSizeOut = 0;
  244.     stringSizeIn = 0;
  245.     stringUsedIn = 0;
  246.     the_input = NULL;
  247.   }
  248.   return(wp);
  249. }
  250.  
  251. long os_console_read_nohang( WindowPeek wp, unsigned char *ptr, long cnt )
  252. {
  253.   #pragma unused(wp)
  254.   long room;
  255.   os_event_check();
  256.   if( the_input == NULL ) cnt = 0;
  257.   room = stringSizeIn - stringUsedIn;
  258.   if( cnt > room ) cnt = room;
  259.   if( cnt > 0 )
  260.   {
  261.     HLock( the_input );
  262.     strncpy( (char *)ptr, &((char *)(*the_input))[stringUsedIn], cnt );
  263.     stringUsedIn += cnt;
  264.     HUnlock( the_input );
  265.   }
  266.   return cnt;
  267. }
  268.  
  269. long os_console_write( WindowPeek wp, unsigned char *ptr, long cnt)
  270. {
  271.   Handle h = (Handle )wp; // what a hack
  272.   long room;
  273.   // another hack to accommodate main()'s use of puts() to init console
  274.   if( stringSizeOut == 0 && cnt == 2 && ptr[0] == ' ' && ptr[1] == '\r' )
  275.     return 2;
  276.   if( stringSizeOut + cnt > handleSizeOut )
  277.   {
  278.     SetHandleSize( h, stringSizeOut + cnt + osc_RESIZE_ADD );
  279.     handleSizeOut = GetHandleSize( h );
  280.   }
  281.   room = handleSizeOut - stringSizeOut - 1;
  282.   if( cnt > room ) cnt = room; // only if resize failed
  283.   if( cnt > 0 )
  284.   {
  285.     HLock( h );
  286.     strncpy( &((char *)(*h))[stringSizeOut], (char *)ptr, cnt );
  287.     stringSizeOut += cnt;
  288.     ((char *)(*h))[stringSizeOut] = 0;
  289.     HUnlock( h );
  290.   }
  291.   return cnt;
  292. }
  293.  
  294. /*--------------------------------------------------------------------------*/
  295.  
  296. /* Used to check for any unread required parameters. Returns true if we
  297. ** missed at least one. */
  298.  
  299. static Boolean MissedAnyParameters(AppleEvent *message)
  300. {
  301.   OSErr        err;
  302.   DescType    ignoredActualType;
  303.   AEKeyword    missedKeyword;
  304.   Size        ignoredActualSize;
  305.   EventRecord    event;
  306.  
  307.   err = AEGetAttributePtr(            // SEE IF PARAMETERS ARE ALL USED UP.
  308.         message,              // AppleEvent to check.
  309.         keyMissedKeywordAttr, // Look for unread parameters.
  310.         typeWildCard,         // So we can see what type we missed, if any.
  311.         &ignoredActualType,   // What it would have been if not coerced.
  312.         (Ptr)&missedKeyword,  // Data area.  (Keyword not handled.)
  313.         sizeof(missedKeyword),// Size of data area.
  314.         &ignoredActualSize    // Actual data size.
  315.     );
  316.   /* No error means that we found some unused parameters. */
  317.   if (err == noErr)
  318.   {
  319.     event.message = *(long *) &ignoredActualType;
  320.     event.where = *(Point *) &missedKeyword;
  321.     err = errAEEventNotHandled;
  322.   }
  323.   /* errAEDescNotFound means that there are no more parameters.  If we get
  324.   ** an error code other than that, flag it. */
  325.   return(err != errAEDescNotFound);
  326. }
  327.  
  328. static OSErr OpenDocEventHandler(AppleEvent *message, AppleEvent *reply, short mode)
  329. {
  330.   #pragma unused( reply, mode )
  331.   OSErr     err;
  332.   OSErr     err2;
  333.   AEDesc    theDesc;
  334.   FSSpec    theFSS;
  335.   short     loop;
  336.   long      numFilesToOpen;
  337.   AEKeyword ignoredKeyWord;
  338.   DescType  ignoredType;
  339.   Size      ignoredSize;
  340.   char      path[512];
  341.   short     w;
  342.   FInfo     theFInfo;
  343.  
  344.   theDesc.dataHandle = nil;
  345.   /* Make sure disposing of the descriptors is okay in all cases.
  346.   ** This will not be necessary after 7.0b3, since the calls that
  347.   ** attempt to create the descriptors will nil automatically
  348.   ** upon failure. */
  349.  
  350.   if ( (err = AEGetParamDesc( message, keyDirectObject, typeAEList, &theDesc )) != 0 )
  351.     return(err);
  352.  
  353.   if ( ! MissedAnyParameters( message ) && !(err = AECountItems(&theDesc, &numFilesToOpen)))
  354.   { /* We have numFilesToOpen that need opening, as either a window
  355.     ** or to be printed.  Go to it... */
  356.  
  357.     for (loop = 1; ((loop <= numFilesToOpen) && (!err)); ++loop)
  358.     { err = AEGetNthPtr(// GET NEXT IN THE LIST...
  359.       &theDesc,         // List of file names.
  360.       loop,             // Item # in the list.
  361.       typeFSS,          // Item is of type FSSpec.
  362.       &ignoredKeyWord,  // Returned keyword -- we know.
  363.       &ignoredType,     // Returned type -- we know.
  364.       (Ptr)&theFSS,     // Where to put the FSSpec info.
  365.       sizeof(theFSS),   // Size of the FSSpec info.
  366.       &ignoredSize      // Actual size -- we know.
  367.       );
  368.       if (err) break;
  369.  
  370.       FSpGetFInfo( &theFSS, &theFInfo );
  371.       if ( theFInfo.fdType != 'TEXT' )
  372.       { 
  373.         w = getfullpath( theFSS.vRefNum, theFSS.parID, theFSS.name, path, 511, 1 );
  374.         if( theFInfo.fdType == 'BINA' && theFInfo.fdCreator == 'Moml' )
  375.         {
  376.           image_name = malloc( w + 1 );
  377.           if( image_name ) strncpy( image_name, path, w + 1 );
  378.         }
  379.         else
  380.           SysBeep( 3 );
  381.         continue;
  382.       }
  383.       else SysBeep( 3 ); // err = errAEEventNotHandled;
  384.     }
  385.   }
  386.   err2 = AEDisposeDesc(&theDesc);
  387.   return(err ? err : err2);
  388. }
  389.  
  390. static pascal OSErr DoAEOpenApplication( AppleEvent *message, AppleEvent *reply, long refcon )
  391. {
  392.   #pragma unused( message, reply, refcon )
  393.   //DebugStr( "\pDoAEOpenApplication" );
  394.   return(noErr);
  395. }
  396.  
  397. static pascal OSErr DoAEOpenDocuments( AppleEvent *message, AppleEvent *reply, long refcon )
  398. {
  399.   #pragma unused( refcon )
  400.   return( OpenDocEventHandler( message, reply, 0 ) ); /* 0 means regular open document */
  401. }
  402.  
  403. static pascal OSErr DoAEPrintDocuments(AppleEvent *message, AppleEvent *reply, long refcon)
  404. {
  405.   #pragma unused( message, reply, refcon )
  406.   return(noErr);
  407. }
  408.  
  409. static pascal OSErr DoAEQuitApplication( AppleEvent *message, AppleEvent *reply, long refcon )
  410. {
  411.   #pragma unused( message, reply, refcon )
  412.   gDoQuit = 1;
  413.   return noErr;
  414. }
  415.  
  416. static pascal OSErr DoAEwww2( AppleEvent *theAEEvent, AppleEvent *theAEReply, long *theRefCon)
  417. {
  418.   #pragma unused( theAEEvent, theRefCon )
  419.   OSErr     theErr = noErr;
  420.   //char      ourScriptText[256];
  421.  
  422.   if( gAESuspn )
  423.   {
  424.     int i;
  425.     char *p, c;
  426.     Handle h = the_output; // what a hack
  427.     HLock( h );
  428.     p = *h;
  429. #if ( CRLF_TRANSLATE )
  430.     for( i = 0; i < stringSizeOut; i++ )
  431.     { c = p[i];
  432.       if     ( c == '\r' ) p[i] = '\n';
  433.       else if( c == '\n' ) p[i] = '\r';
  434.     }
  435. #endif
  436. /* */
  437. //sprintf( ourScriptText+1, "www: %x", *h );
  438. //ourScriptText[0] = strlen(ourScriptText+1);
  439. //DebugStr( (unsigned char *)ourScriptText ); 
  440. /* */
  441.     theErr = AEPutParamPtr( theAEReply, keyDirectObject, typeChar, (Ptr)p, stringSizeOut+1);
  442.     HUnlock( h );
  443.     gAESuspn = 0;
  444.   }
  445.   return theErr;
  446. }
  447.  
  448. #define ARG_SIZE 4096
  449. extern int e_setenv(const char *name, const char *text, int rewrite);
  450.  
  451. static OSErr aeparm_to_env( AppleEvent *inEvent, AEKeyword kwrd, char *envname )
  452. {
  453.   OSErr    err = noErr;
  454.   DescType theType;
  455.   Size     theSize;
  456.   char  theArg[ARG_SIZE];
  457.   
  458.   err = AEGetParamPtr(inEvent, kwrd, typeChar, &theType, theArg, ARG_SIZE, &theSize);
  459.   if( theSize != 0 && theSize < ARG_SIZE )
  460.   {
  461.     theArg[theSize] = '\0';
  462.     e_setenv( envname, theArg, 0 );
  463.   }
  464.   //else ???
  465.   return err;
  466.  
  467. static OSErr aeparm_to_stdin( AppleEvent *inEvent, AEKeyword kwrd )
  468. {
  469.   OSErr    err = noErr;
  470.   DescType theType;
  471.   Size     theSize;
  472.   char  theArg[ARG_SIZE];
  473.   
  474.   stringUsedIn = 0;
  475.   the_input = NULL;
  476.   err = AEGetParamPtr( inEvent, kwrd, typeChar, &theType, theArg, ARG_SIZE, &theSize );
  477.   if( theSize == 0 )
  478.   {
  479.     stringSizeIn = 0;
  480.   }
  481.   else
  482.   {
  483.     the_input = NewHandle( theSize );
  484.     if( the_input == NULL )
  485.     {
  486.       stringSizeIn = 0;
  487.     }
  488.     else
  489.     { int i;
  490.       char *p, c;
  491.       p = *the_input;
  492.       stringSizeIn = theSize;
  493.       if( theSize <= ARG_SIZE )
  494.       {
  495.         HLock( the_input );
  496.         strncpy( p, theArg, theSize );
  497.       }
  498.       else
  499.       {
  500.         HLock( the_input );
  501.         err = AEGetParamPtr( inEvent, kwrd, typeChar, &theType, p, theSize, &theSize );
  502.         // what if stringSizeIn != theSize ??
  503.       }
  504. #if ( CRLF_TRANSLATE )
  505.       for( i = 0; i < stringSizeIn; i++ )
  506.       { c = p[i];
  507.         if     ( c == '\r' ) p[i] = '\n';
  508.         else if( c == '\n' ) p[i] = '\r';
  509.       }
  510. #endif
  511.       HUnlock( the_input );
  512.       sprintf( theArg, "%d", stringSizeIn );
  513.       e_setenv( "CONTENT_LENGTH", theArg, 0 );
  514.     }
  515.   }
  516.   return err;
  517. }
  518.  
  519. static void cgi_get_app_name( void )
  520. {
  521.   //unsigned char *CurApName = LMGetCurApName();
  522.   ProcessInfoRec pir;
  523.   ProcessSerialNumber psn;
  524.   char      path[512];
  525.   short     w;
  526.   
  527.   psn.highLongOfPSN = 0;
  528.   psn.lowLongOfPSN = kCurrentProcess;
  529.   pir.processInfoLength = sizeof(pir);
  530.   pir.processName = 0;
  531.   pir.processAppSpec = &appFSS;
  532.   GetProcessInformation( &psn, &pir );
  533.   w = getfullpath( appFSS.vRefNum, appFSS.parID, appFSS.name, path, 511, 1 );
  534.   e_setenv( "PATH_TRANSLATED", path, 0 );
  535.   if( strcmp( ".cgi", &path[w-4] ) == 0 && w < 510 )
  536.   { // make image name from app name: app.cgi => app.image
  537.     strcpy( &path[w-3], "image" );
  538.     image_name = malloc( w + 3 );
  539.     if( image_name ) strncpy( image_name, path, w + 3 );
  540.   }
  541.   gMadeAppFSS = true;
  542. }
  543.  
  544. static pascal OSErr DoAEwww( AppleEvent *inEvent, AppleEvent *outReply, long *theRefCon)
  545. {
  546.   #pragma unused( theRefCon )
  547.   OSErr    err = noErr;
  548.  
  549.   // env vars
  550.   // missing:      SERVER_SOFTWARE SERVER_PROTOCOL AUTH_TYPE REMOTE_IDENT
  551.   // questionable: GATEWAY_INTERFACE PATH_TRANSLATED
  552.   // wrong:        REMOTE_HOST (can be same as REMOTE_ADDR if resolution turned off)
  553.   // invented:     REMOTE_PASS
  554.   
  555.   // SERVER_SOFTWARE = NCSA/1.5.2
  556.   // SERVER_PROTOCOL = HTTP/1.0
  557.   // GATEWAY_INTERFACE = CGI/1.1
  558.   
  559.   // create PATH_TRANSLATED  and maybe set image_name
  560.   cgi_get_app_name();
  561.  
  562.   // Path Arguments ('----') PATH_INFO
  563.   // This the data following the '$' in a URL, but preceding the '?', if one is present.
  564.   // This is a common method of passing arguments to a CGI. 
  565.   // Note that the path arguments in a UNIX server a delimited by a '/', not a '$'.
  566.   // The '$' is a peculiarity of the Macintosh CGI "standard"
  567.   err = aeparm_to_env( inEvent, '----', "PATH_INFO" );
  568.  
  569.   // Search Arguments ('kfor') QUERY_STRING
  570.   // This is the data that follows the '?' in a URL, if any is present. 
  571.   // Search arguments
  572.   err = aeparm_to_env( inEvent, 'kfor', "QUERY_STRING" );
  573.  
  574.   // Post Arguments ('post') -> std_in
  575.   // The post parameter contains the data passed in the body of a POST request,
  576.   // usually data from a form.
  577.   err = aeparm_to_stdin( inEvent, 'post' );
  578.   
  579.   // Username ('user') REMOTE_USER
  580.   // If the user supplied a username for authentication, this filed contains the name entered.
  581.   err = aeparm_to_env( inEvent, 'user', "REMOTE_USER" );
  582.   
  583.   // Password ('pass') ???? AUTH_TYPE? REMOTE_IDENT?
  584.   // The password the user entered, if authentication was required.
  585.   err = aeparm_to_env( inEvent, 'pass', "REMOTE_PASS" );
  586.  
  587.   // Method ('meth') REQUEST_METHOD
  588.   // The HTTP method that was used for the request, usually 'GET' or 'POST'. 
  589.   err = aeparm_to_env( inEvent, 'meth', "REQUEST_METHOD" );
  590.   
  591.   // Client Address ('addr') REMOTE_HOST -- but only if it's a host name?
  592.   // The IP address or domain name of the client, depending on whether or not the 
  593.   // "Lookup Client Address with DNS" option is enabled, and the client has a DNS entry.
  594.   err = aeparm_to_env( inEvent, 'addr', "REMOTE_HOST" );
  595.  
  596.   // Client IP ('Kcip') REMOTE_ADDR
  597.   // The IP address of the client.
  598.   err = aeparm_to_env( inEvent, 'Kcip', "REMOTE_ADDR" );
  599.  
  600.   // Server Name ('svnm') SERVER_NAME
  601.   // The name of the web server.
  602.   err = aeparm_to_env( inEvent, 'svnm', "SERVER_NAME" );
  603.   
  604.   // Server Port ('svpt') SERVER_PORT
  605.   // The TCP port on which the server is listening for connections (usually 80) 
  606.   err = aeparm_to_env( inEvent, 'svpt', "SERVER_PORT" );
  607.  
  608.   // Script Name ('scnm') SCRIPT_NAME
  609.   // This is the URL path to the CGI application. If the CGI is running as an action,
  610.   // this parameter contains the path to the file specified by the URL.
  611.   err = aeparm_to_env( inEvent, 'scnm', "SCRIPT_NAME" );
  612.  
  613.   // Referrer ('refr') HTTP_REFERER e.g., "http://208.146.140.3/html/cgiexamples.html"
  614.   // The URL of the page that the user was on when she clicked on the CGI's URL.
  615.   err = aeparm_to_env( inEvent, 'refr', "HTTP_REFERER" );
  616.  
  617.   // User Agent ('Agnt') HTTP_USER_AGENT e.g., "Mozilla/3.01 (Macintosh; U; PPC)"
  618.   // The name of the client software, such as "Mozilla" for Netscape Navigator. 
  619.   err = aeparm_to_env( inEvent, 'Agnt', "HTTP_USER_AGENT" );
  620.  
  621.   // Content Type ('ctyp') CONTENT_TYPE
  622.   // The MIME type of the POST data, if present. 
  623.   err = aeparm_to_env( inEvent, 'ctyp', "CONTENT_TYPE" );
  624.  
  625.   // Action ('Kact') ???? GATEWAY_INTERFACE?
  626.   // The type of CGI that is being run, such as "CGI", "ACGI", "PREPROCESSOR", or
  627.   // "POSTPROCESSOR". If the CGI is running as an action, this contains the name of the action.
  628.   // Action name
  629.   err = aeparm_to_env( inEvent, 'Kact', "GATEWAY_INTERFACE" );
  630.   
  631.   // Action Path ('Kapt') ???? punt?
  632.   // When running as an action, this contains the path to the action.
  633.   // If running as a CGI, this is identical to the Script Name ('scnm') parameter.
  634.   //err = aeparm_to_env( inEvent, 'Kapt', "" );
  635.   // We don't do anything with the Action Path.
  636.  
  637.   // Full Request ('Kfrq')
  638.   // The entire text of the request as received by the server, with no processing whatsoever.
  639.   // Full, unprocessed request (including the HTTP header)
  640.   //err = aeparm_to_env( inEvent, 'Kfrq', "" );
  641.   // We don't do anything with the Full Request.
  642.   
  643.   // From User ('frmu') ???? (obsolete)
  644.   // If the HTTP header of the client request contained a "From:" field,
  645.   // this parameter contains the information from that field,
  646.   // usually the user's email address.
  647.   //err = aeparm_to_env( inEvent, 'frmu', "" );
  648.  
  649.   // Connection ID ('Kcid')
  650.   // A long integer identifying the connection corresponding to the CGI request.
  651.   // This is the only parameter that is not typeChar. It's used for partial replies.
  652.   // We don't do anything with the Connection ID.
  653.   
  654.   gAEEvent = *inEvent;
  655.   gAEReply = *outReply;
  656.   gAESuspn = 1;
  657.   gReceivedAE = 1;
  658.   return AESuspendTheCurrentEvent( inEvent );
  659. }
  660.  
  661. OSErr finish_AEDoScript( void )
  662. {
  663.   if( gAESuspn )
  664.   {
  665.     //int i;
  666.     AEEventHandlerUPP upp = NewAEEventHandlerProc(DoAEwww2);
  667.     OSErr err = AEResumeTheCurrentEvent( &gAEEvent, &gAEReply, upp, 0 );
  668.     //if( gAESuspn && err == noErr ) 
  669.     //  for( i = 0; gAESuspn && i < 10; i++ ) os_event_check();
  670.     return err;
  671.   }
  672.   return errAEEventNotHandled;
  673. }
  674.  
  675. // ********************* init **********************
  676.  
  677. //static GrowZoneUPP mem_full_errUPP;
  678.  
  679. static Boolean install_aehandler( AEEventClass cl, AEEventID id, ProcPtr p )
  680. { OSErr    err;
  681.   AEEventHandlerUPP upp = NewAEEventHandlerProc(p);
  682.   
  683.   if ( upp == NULL ) err = memFullErr;
  684.   else err = AEInstallEventHandler( cl, id, upp, 0L, false );
  685.   if (err)
  686.   { io_err(err);
  687.     return false;
  688.   }
  689.   return true;
  690. }
  691.  
  692. static void init_ae()
  693. {
  694.   long result;
  695.  
  696.   gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &result) ? false : result != 0);
  697.  
  698.   if (gHasAppleEvents)
  699.     install_aehandler( kCoreEventClass, kAEOpenApplication, (ProcPtr )DoAEOpenApplication )
  700.      && install_aehandler( kCoreEventClass, kAEOpenDocuments, (ProcPtr )DoAEOpenDocuments )
  701.      && install_aehandler( kCoreEventClass, kAEPrintDocuments, (ProcPtr )DoAEPrintDocuments )
  702.      && install_aehandler( kCoreEventClass, kAEQuitApplication, (ProcPtr )DoAEQuitApplication )
  703.      && install_aehandler( 'WWWΩ', 'sdoc', (ProcPtr )DoAEwww )
  704.      ;
  705.   else ExitToShell();
  706. }
  707.  
  708. static void hack_remove_console( void )
  709. {
  710.   gDoQuit = 1; // prevents RemoveConsole from doing SetWTitle on wp
  711. }
  712.  
  713. static void init_all(void)
  714. { short i;
  715.  
  716.   MaxApplZone();
  717.   for (i = 0; i < 10; i++) MoreMasters();
  718.   // mem_full_errUPP = NewGrowZoneProc(mem_full_err);
  719.   // SetGrowZone( mem_full_errUPP );
  720.  
  721.   InitGraf( &qd.thePort );
  722.   InitFonts();
  723.   //FlushEvents( everyEvent, 0 );
  724.   InitWindows();
  725.   InitMenus();
  726.   TEInit();
  727.   InitDialogs( 0L );
  728.   InitCursor();
  729.  
  730.   gCursorRgn = NewRgn();
  731.   SetRectRgn(gCursorRgn, -32768, -32768, 32766, 32766);
  732.  
  733.   a_menu = GetMenu( appleID );
  734.   AppendResMenu( a_menu, 'DRVR' );
  735.   f_menu = GetMenu( fileID );
  736.   ClearMenuBar();
  737.   InsertMenu( a_menu, 0);
  738.   InsertMenu( f_menu, 0);
  739.   DrawMenuBar();
  740.   
  741.   atexit(hack_remove_console);
  742.  
  743.   init_ae();
  744.  
  745. #if USE_EVENTCHK_TIMER
  746.   init_eck_timer();
  747. #endif
  748. }
  749.  
  750. // end.
  751.