home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / frntpage.sdk / cgi / olecgi / olecgi.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-31  |  8.7 KB  |  389 lines

  1.  
  2. /* OLE-CGI: interface to OLE servers created by VB from standard CGI */
  3.  
  4. #include "stdio.h"
  5. #include "malloc.h"
  6. #include "fcntl.h"
  7. #include "windows.h"
  8. #include "tchar.h"
  9. #include "oleauto.h"
  10. #include "io.h"
  11. #include "noafxstr.h"
  12.  
  13. /* text macros borrowed from MFC header files */
  14.  
  15. LPWSTR NoAfxA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars)
  16. {
  17.     if (lpa == NULL)
  18.         return NULL;
  19.     // verify that no illegal character present
  20.     // since lpw was allocated based on the size of lpa
  21.     // don't worry about the number of chars
  22.     lpw[0] = '\0';
  23.     MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars);
  24.     return lpw;
  25. }
  26.  
  27. LPSTR NoAfxW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars)
  28. {
  29.     if (lpw == NULL)
  30.         return NULL;
  31.     // verify that no illegal character present
  32.     // since lpa was allocated based on the size of lpw
  33.     // don't worry about the number of chars
  34.     lpa[0] = '\0';
  35.     WideCharToMultiByte(CP_ACP, 0, lpw, -1, lpa, nChars, NULL, NULL);
  36.     return lpa;
  37. }
  38.  
  39. extern char *getenv();
  40. extern char *strrchr();
  41. extern int atoi();
  42.  
  43. int glob_argc = 0;
  44. char **glob_argv = NULL;
  45. char **glob_env = NULL;
  46. int glob_clen = 0;
  47. char *glob_content = NULL;
  48.  
  49. int glob_cgiwin = 0;  /* if true, running under CGI-WIN interface */
  50. char glob_cgiwin_out[_MAX_PATH];
  51.  
  52. /* ---- cgi_error ---- */
  53.  
  54. int cgi_error(char *s, int ret_code)
  55. {
  56. int i = 0;
  57. FILE *fp = stdout;
  58.  
  59.     if(glob_cgiwin)
  60.         fp = fopen(glob_cgiwin_out,"w");
  61.  
  62.     fprintf(fp,"Content-type: text/plain\n\n");
  63.     
  64.     fprintf(fp,"Error in CGI-OLE gateway script.\n\nReason: %s.\n\n",s);
  65.  
  66.     fprintf(fp,"-----------------------------------------\n");
  67.     fprintf(fp,"Command-line arguments (%d)\n\n",glob_argc);
  68.     for(i=0;i<glob_argc;i++)
  69.         fprintf(fp,"\t[%d]: '%s'\n",i,glob_argv[i]);
  70.     fprintf(fp,"-----------------------------------------\n");
  71.     fprintf(fp,"Environment variables\n\n");
  72.     for(i=0;glob_env[i] != NULL;i++)
  73.         fprintf(fp,"\t'%s'\n",glob_env[i]);
  74.  
  75.     if(glob_clen > 0)
  76.     {
  77.         fprintf(fp,"-----------------------------------------\n");
  78.         fprintf(fp,"Content (%d)\n\n",glob_clen);
  79.         for(i=0;i<glob_clen;i++)
  80.             fputc(glob_content[i],fp);
  81.     }
  82.  
  83.     fflush(fp);
  84.  
  85.     return ret_code;
  86. }
  87.  
  88. char *strsave(char *s)
  89. {
  90.     char *p = NULL;
  91.     int len = 0;
  92.     if(!s)
  93.         return NULL;
  94.     len = strlen(s);
  95.     p = (char *)malloc(len+1);
  96.     if(!p)
  97.         return NULL;
  98.     strcpy(p,s);
  99.     return p;
  100. }
  101.  
  102. char *UrlEncode(char *s)
  103. {
  104.     char *out = (char *)malloc(strlen(s)*3 + 1);
  105.     char *p = out;
  106.     int i = 0;
  107.     int slen = strlen(s);
  108.     int ch;
  109.  
  110.     for(i=0;i<slen;i++)
  111.     {
  112.         ch = s[i];
  113.         if(ch == ' ')
  114.             *p++ = '+';
  115.         else if(ch > ' ' && ch <= '~' && ch != '&' && ch != '+' && ch != '%' && ch != '=')
  116.             *p++ = ch;
  117.         else
  118.         {
  119.             // convert to hex
  120.             *p++ = '%';
  121.             sprintf(p,"%02x",ch);
  122.             p += 2;
  123.         }
  124.     }
  125.  
  126.     *p = 0;
  127.  
  128.     return out;
  129. }
  130.  
  131. char *make_env_str()
  132. {
  133.     int tlen = 0;
  134.     int i = 0;
  135.  
  136.     /* get required length */
  137.     for(i=0;glob_env[i] != NULL;i++)
  138.     {
  139.         tlen += strlen(glob_env[i]);
  140.     }
  141.  
  142.     char *str = (char *)malloc(tlen * 3 + 1);
  143.     str[0] = 0;
  144.     char *p = str;
  145.     int first = 1;
  146.  
  147.     /* create form-url-encoded dictionary string */
  148.     for(i=0;glob_env[i] != NULL;i++)
  149.     {
  150.         if(first)
  151.             first = 0;
  152.         else
  153.             *p++ = '&';
  154.         char *attr = strsave(glob_env[i]);
  155.         char *value = strchr(attr,'=');
  156.         *value++ = 0;
  157.         char *u_attr = UrlEncode(attr);
  158.         char *u_value = UrlEncode(value);
  159.         sprintf(p,"%s=%s",u_attr,u_value);
  160.         p += strlen(p);
  161.         free(attr);
  162.         free(u_attr);
  163.         free(u_value);
  164.     }
  165.  
  166.     return str;
  167. }
  168.  
  169. int do_ole_stuff()
  170. {
  171.     CLSID clsid;
  172.     HRESULT hresult;
  173.     char *path_info = getenv("PATH_INFO");
  174.     char progid[_MAX_PATH];
  175.     char msg[_MAX_PATH];
  176.     int failed = 0;
  177.     DISPID dispid;
  178.     DISPPARAMS dispparams;
  179.     VARIANTARG varg[2];
  180.     VARIANTARG vargResult;
  181.     int MaxParms = 2;
  182.     int i;
  183.     char *envstr = NULL;
  184.     IDispatch FAR *pIDispatch;
  185.     IUnknown FAR *punk = NULL;
  186.     char *pMeth = _T("CGI");
  187.     OLECHAR FAR *szMethodName = NULL;
  188.     BSTR arg1 = NULL;
  189.     BSTR arg2 = NULL;
  190.     EXCEPINFO exinfo;
  191.     char *emsg = NULL;
  192.  
  193.     USES_CONVERSION;
  194.     szMethodName = T2OLE(pMeth);
  195.  
  196.     if(!path_info)
  197.     {
  198.         return cgi_error("script wasn't given PATH_INFO argument",1);
  199.     }
  200.  
  201.     if(OleInitialize(NULL) != S_OK)
  202.     {
  203.         return cgi_error("unable to initialize OLE library",1);
  204.     }
  205.  
  206.     sprintf(progid,"CGIHandler.%s",path_info+1);  // skip initial slash
  207.     hresult = CLSIDFromProgID(T2OLE(progid),&clsid);
  208.     if(FAILED(hresult))
  209.     {
  210.         sprintf(msg,"unable to find OLE object '%s' in registry",progid);
  211.         cgi_error(msg,1);
  212.         goto OleShutdown;
  213.     }
  214.  
  215.     hresult = CoCreateInstance(clsid,NULL,CLSCTX_SERVER,
  216.         IID_IUnknown,(void FAR * FAR *)&punk);
  217.     if(FAILED(hresult))
  218.     {
  219.         sprintf(msg,"unable to get OLE IUnknown interface to object '%s'",progid);
  220.         cgi_error(msg,1);
  221.         goto OleShutdown;
  222.     }
  223.  
  224.     hresult = punk->QueryInterface(IID_IDispatch,(void FAR * FAR *)&pIDispatch);
  225.     if(FAILED(hresult))
  226.     {
  227.         punk->Release();
  228.         sprintf(msg,"unable to get OLE IDispatch interface to object '%s'",progid);
  229.         cgi_error(msg,1);
  230.         goto OleShutdown;
  231.     }
  232.  
  233.     punk->Release();
  234.  
  235.     // init variables
  236.     for(i=0;i<MaxParms;i++)
  237.         VariantInit(&varg[i]);
  238.     VariantInit(&vargResult);
  239.  
  240.     envstr = make_env_str();
  241.  
  242.     arg1 = envstr ? SysAllocString(T2OLE(envstr)) : SysAllocString(T2OLE(""));
  243.     arg2 = glob_content ? SysAllocString(T2OLE(glob_content)) : SysAllocString(T2OLE(""));
  244.  
  245.     /* sending to VB OLE server, arg passing order gets reversed;
  246.        like arg3=arg1, arg2=arg2, arg3=arg1; so reverse them here */
  247.     V_VT(&varg[0]) = VT_BSTR;
  248.     V_BSTR(&varg[0]) = arg2;
  249.     V_VT(&varg[1]) = VT_BSTR;
  250.     V_BSTR(&varg[1]) = arg1;
  251.     
  252.     dispparams.rgvarg = varg;
  253.     dispparams.rgdispidNamedArgs = NULL;
  254.     dispparams.cArgs = MaxParms;
  255.     dispparams.cNamedArgs = 0;
  256.  
  257.     hresult = pIDispatch->GetIDsOfNames(IID_NULL,&szMethodName,1,
  258.         LOCALE_SYSTEM_DEFAULT,&dispid);
  259.     if(FAILED(hresult))
  260.     {
  261.         sprintf(msg,"unable to get OLE DispID for '%s' method of object '%s'",pMeth,progid);
  262.         cgi_error(msg,1);
  263.         failed = 1;
  264.         goto ClearArgs;
  265.     }
  266.  
  267.     hresult = pIDispatch->Invoke(dispid,IID_NULL,LOCALE_SYSTEM_DEFAULT,
  268.         DISPATCH_METHOD,&dispparams,&vargResult,&exinfo,NULL);
  269.     if(FAILED(hresult))
  270.     {
  271.         sprintf(msg,"unable to perform OLE Invoke of '%s' method of object '%s'",pMeth,progid);
  272.         cgi_error(msg,1);
  273.         if(hresult == DISP_E_EXCEPTION)
  274.         {
  275.             if(exinfo.pfnDeferredFillIn != NULL)
  276.                 (*exinfo.pfnDeferredFillIn)(&exinfo);
  277.             printf("\n\n-----------------------\n");
  278.             printf("OLE Dispatch Exception Info\n\n");
  279.             emsg = exinfo.bstrSource ? OLE2T(exinfo.bstrSource) : "(not set)";
  280.             printf("Object: %s\n",emsg);
  281.             emsg = exinfo.bstrDescription ? OLE2T(exinfo.bstrDescription) : "(not set)";
  282.             printf("Description: %s\n",emsg);
  283.             printf("wCode: %d\n",exinfo.wCode);
  284.             printf("scode: 0x%08x\n",exinfo.scode);
  285.             SysFreeString(exinfo.bstrDescription);
  286.             SysFreeString(exinfo.bstrHelpFile);
  287.         }
  288.         failed = 1;
  289.         goto ClearReturn;
  290.     }        
  291.  
  292.     /* see if got a BSTR */
  293.     if(V_VT(&vargResult) != VT_BSTR)
  294.     {
  295.         sprintf(msg,"value returned from OLE Invoke of '%s' method of object '%s' is not BSTR",szMethodName,progid);
  296.         cgi_error(msg,1);
  297.         failed = 1;
  298.     }
  299.  
  300.     /* send results back to server */
  301.     fwrite(OLE2T(V_BSTR(&vargResult)),1,strlen(OLE2T(V_BSTR(&vargResult))),stdout);
  302.     
  303. ClearReturn:
  304.     VariantClear(&vargResult);    
  305. ClearArgs:
  306.     for(i=0;i<MaxParms;i++)
  307.         VariantClear(&varg[i]);
  308.     
  309.     pIDispatch->Release();
  310.  
  311. OleShutdown:
  312.     OleUninitialize();
  313.  
  314.     if(envstr)
  315.         free(envstr);
  316.  
  317.     return failed;
  318. }
  319.  
  320. /* ---- main --------- */
  321.  
  322. int main(int argc, char *argv[], char *env[])
  323. {
  324.     char *exe_path = NULL;
  325.     int clen = 0;
  326.     char *p = NULL;
  327.     char *query_info = NULL;
  328.     int tmpnum = 0;
  329.     FILE *fp = NULL;
  330.     int i = 0;
  331.  
  332.     /* set up globals so cgi_error can report them */
  333.     glob_argc = argc;
  334.     glob_argv = &argv[0];
  335.     glob_env = &env[0];
  336.  
  337.     /* XXX - if we're running under CGI-WIN interface, should report 
  338.        error and exit; but it doesn't work yet */
  339.  
  340.     /*
  341.     p = getenv("GATEWAY_INTERFACE");
  342.     if(!p || strstr(p,"(Win)"))
  343.     {
  344.         if(argc > 1)
  345.         {
  346.             glob_cgiwin = 1;
  347.             glob_cgiwin_out[0] = 0;
  348.             return 0;
  349.         }
  350.     }
  351.     else
  352.         return cgi_error("expected GATEWAY_INTERFACE environment variable",0);
  353.     */
  354.  
  355.     /* read in any content */
  356.  
  357.     p = getenv("CONTENT_LENGTH");
  358.     if(p)
  359.         clen = atoi(p);
  360.     if(clen > 0)
  361.     {
  362.         // extern int _setmode(int,int);
  363.         int fd = -1;
  364.         /* must reset to binary mode to read in content */
  365.         p = (char *)malloc(clen+1);
  366.         if(!p)
  367.             return cgi_error("out of memory",0);
  368.         fd = _fileno(stdin);
  369.         _setmode(fd,_O_BINARY);
  370.         if(fread(p,1,clen,stdin) != (unsigned int)clen)
  371.         {
  372.             free(p);
  373.             return cgi_error("couldn't read content",0);
  374.         }
  375.         glob_content = p;
  376.         glob_clen = clen;
  377.         glob_content[glob_clen] = 0;
  378.     }
  379.  
  380.     /* attach OLE server, pass data to it, get results, return them, detach server */
  381.     do_ole_stuff();
  382.  
  383.     if(glob_content)
  384.         free(glob_content);
  385.  
  386.     return 0;
  387. }
  388.  
  389.