swinput.c
上传用户:aidanglao
上传日期:2007-01-07
资源大小:69k
文件大小:11k
源码类别:

Oracle数据库

开发平台:

Unix_Linux

  1. /* swinput.c - input processor
  2. /*
  3. /* Copyright (c) 1995-1999 Applied Information Technologies, Inc.
  4. /* All Rights Reserved.
  5. /*  
  6. /* Distributed uder the GNU General Public License which was included in
  7. /* the file named "LICENSE" in the package that you recieved.
  8. /* If not, write to:
  9. /* The Free Software Foundation, Inc.,
  10. /* 675 Mass Ave, Cambridge, MA 02139, USA.
  11.  */
  12. #include <stdio.h>
  13. #include <errno.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #include <sys/types.h>
  17. #include <string.h>
  18. #include "sqlweb.h"
  19. extern char **environ;
  20. LIST *glCookie;
  21. /* Internal (private) Functions
  22.  */
  23. static eBoolean_t ParseMultiPartFormData(char *pContent,long lInSize);
  24. static eBoolean_t getHeaderItem (char *pHeader
  25. ,char *pAttrName
  26. ,char **pNameValue);
  27. eBoolean_t
  28. swinput()
  29. {
  30.     char **pEnv
  31. ,sContent[MAX_BUFSIZ]
  32. ,sCookie[MAX_BUFSIZ]
  33. ,sContentLength[MAX_TOKVAL_SIZE]
  34. ,sBuf[MAX_TOK_SIZE + MAX_TOKVAL_SIZE]
  35. ,*pContent
  36. ,*pContentType
  37. ,*pValue
  38. ,cSectionID
  39. ;
  40.     long
  41.  lContentLength = 0
  42. ;
  43.     FILE *pIniFile=0;
  44.     /*
  45.     /* Load Entire ENV into SymbolTable
  46.      */
  47.     for(pEnv=environ;*pEnv;++pEnv){
  48. register char
  49.  *pName
  50. ,*pValue
  51. ;
  52. pName = (char*)strcpy(sContent,*pEnv);
  53. pValue = strchr(pName,'=');
  54. if(pValue) {
  55.     *(pValue)=0;
  56.     ++pValue;
  57. } else {
  58.     pValue = 0;
  59. }
  60. ENVSym(DupBuf(pName),DupBuf(pValue));
  61.     }
  62.     /*
  63.     /* Then the INI File
  64.     /* First Choice(s) -i inifile or $SQLWEB_INI
  65.      */
  66.     pValue= gpIniFile ?gpIniFile :getenv("SQLWEB_INI");
  67.     if(pValue){
  68. pIniFile=fopen(pValue,"r");
  69.     }
  70.     if(!pIniFile){
  71. char sIniFilename[BUFSIZ];
  72. /* Second Choice, ./sqlweb.ini
  73.  */
  74. sprintf(sIniFilename,"./%s.ini", gpProgram);
  75. pIniFile=fopen(sIniFilename,"r");
  76. if(!pIniFile){
  77.     /* Third Choice, The global INI_PATH (/etc/sqlweb.ini)
  78.      */
  79.     sprintf(sIniFilename,"/etc/%s.ini", gpProgram);
  80.     pIniFile=fopen(sIniFilename,"r");
  81.     if(!pIniFile){
  82. /* Third swing, Yeeerrrrr OUT!
  83.  */
  84. MsgPush("Failed to Open(%s),errno=%d",sIniFilename,errno);
  85. return(eFalse);
  86.     }
  87. }
  88.     }
  89.     cSectionID = 'S';
  90.     while(fgets(sBuf,MAX_TOK_SIZE+MAX_TOKVAL_SIZE,pIniFile) != 0){
  91. /*
  92. /* Comments start with # or ; in position 1
  93.  */
  94. if(*sBuf=='#' || *sBuf==';' || iStrLen(sBuf)<2)
  95.     continue;
  96. /*
  97. /* Section Header
  98.  */
  99. if(*sBuf=='[') {
  100.     cSectionID = sBuf[1]==' '?sBuf[2]:sBuf[1];
  101.     continue;
  102. }
  103. /*
  104. /* Don't forget to CHOP newline...
  105.  */
  106. sBuf[ iStrLen(sBuf)-1 ] = 0; /* CHOP */
  107. /*
  108. /* Add The Exception Tags into the TagList
  109.  */
  110. if(cSectionID=='T') {
  111.     if(ISeFalse(LoadTag(sBuf))) {
  112. MsgPush("Failed to Create TAG");
  113.     }
  114.     continue;
  115. }
  116. /*
  117. /* Put EnvTags into the Env
  118.  */
  119. if(cSectionID=='E'){
  120.     putenv(DupBuf(sBuf));
  121. }
  122. /*
  123. /* Put Symbol and EnvTags into SymbolTable
  124.  */
  125. if(cSectionID=='E' || cSectionID=='S') {
  126.     /* look for '=' sign...
  127.      */
  128.     pValue = strchr(sBuf,'=');
  129.     if(pValue) {
  130. *(pValue)=0; /* Null sBuf, symbol name */
  131. ++pValue; /* Symbol Value.. */
  132. /* Add the INI Symbol to SYMBOL Table
  133.  */
  134. INISym(DupBuf(sBuf),DupBuf(pValue));
  135.     }
  136. }
  137.     }
  138.     /*
  139.     /* Implement the POST METHOD-- I've modified this to try to read until
  140.     /*  the input is all received, previously only attempted a single read
  141.     /*  This should alievate swinput errors...
  142.      */
  143.     /* Read the Input -- if it's there.
  144.      */
  145.     if(ISeTrue(GetSymbolValue("CONTENT_LENGTH",sContentLength)) ){
  146. long lBytesRead
  147.     ,lOneReadCount
  148.     ;
  149. lContentLength = atoi(sContentLength);
  150. pContent = malloc(lContentLength+1);
  151. if(!pContent){
  152.     /* We got a problem.....
  153.      */
  154.     MsgPush("Failed to malloc %d bytes" ,lContentLength);
  155.     return(eFalse);
  156. }
  157. *pContent=0;
  158. /* sContent[0]=0;
  159.  */
  160. if( lContentLength >0 ) {
  161.     for( lBytesRead=0, lOneReadCount=1
  162. ;lBytesRead<lContentLength && lOneReadCount>0
  163. ;lOneReadCount=read(0
  164.    ,pContent+lBytesRead
  165.    ,lContentLength-lBytesRead)
  166.  ,lBytesRead += lOneReadCount)
  167.     {
  168. ; /* The null for loop */
  169.     }
  170.     /* Testing indicates it's possible to over shoot... 
  171.     /* if(lBytesRead != lContentLength)
  172.      */
  173.     if(lBytesRead < lContentLength) {
  174.   /* We got a problem.....
  175.    */
  176.   MsgPush("Read only %d bytes of %d Content"
  177.       ,lBytesRead
  178.       ,lContentLength
  179.       );
  180.   return(eFalse);
  181.     }
  182.     /* Using contentLength because it's possible to read
  183.     /* More that the specified chars, so since we only test
  184.     /* for underflow, it's best to use the passed-in value
  185.     /* to null the string.
  186.      */
  187.     /* sContent[lContentLength]=0;
  188.      */
  189.     *(pContent+lContentLength)=0;
  190. }
  191.     }
  192.     /* Parse POSTED FORM.
  193.      */
  194.     if(lContentLength>0) {
  195. ENVSym(DupBuf("CONTENTS"),DupBuf(pContent));
  196. if(ISeTrue(GetSymbolValueREF("CONTENT_TYPE",&pContentType))
  197.      && (bStrNMatch(pContentType,"multipart/form-data",19)))
  198. {
  199.     if( ISeFalse(ParseMultiPartFormData(pContent,lContentLength)) ){
  200. MsgPush("Failed to Parse multipart/form-data");
  201. return(eFalse);
  202.     }
  203. } else {
  204.     if( ISeFalse(BuildSymbolTable(pContent)) ){
  205. MsgPush("Failed to build SymbolTable from CONTENT");
  206. return(eFalse);
  207.     }
  208. }
  209.     }
  210.     /*
  211.     /* Look for QUERY_STRING
  212.      */
  213.     if(ISeTrue(GetSymbolValue("QUERY_STRING",sContent)) ){
  214. /* First, check for ISMAP....
  215.  */
  216. if( !(strchr(sContent,'=')) ) {
  217.     char *pX, *pY;
  218.     pX = sContent;
  219.     pY=strchr(sContent,',');
  220.     if(pY) {
  221. *pY = 0; /* replace "," with NULL */
  222. pY++; /* Move to one past the "," */
  223. /*
  224. /* Ok, lets add (X,Y) the the Symbol Table
  225.  */
  226. ENVSym("X_CLICK",DupBuf(pX));
  227. ENVSym("Y_CLICK",DupBuf(pY));
  228.     }
  229. } else if( ISeFalse(BuildSymbolTable(sContent)) ){
  230.     MsgPush("Failed to build SymbolTable from QUERY_STRING");
  231.     return(eFalse);
  232. }
  233.     }
  234.     if(ISeTrue(GetSymbolValue("HTTP_COOKIE",sCookie)) ){
  235. char *pCookieName, *pCookieValue, *pCookieEnd;
  236. SYMBOL *pSym;
  237. for( pCookieName=sCookie;
  238.      pCookieName;
  239.      pCookieName=pCookieEnd )
  240. {
  241.     if((pCookieValue=strchr(pCookieName,'=')))
  242.     {
  243. *pCookieValue++=0;     /* NULLs end of pCookieName */
  244. pCookieEnd=strchr(pCookieValue,';');
  245. if(pCookieEnd) {
  246.     *pCookieEnd++=0; /* NULL pCookieValue */
  247. }
  248. /* OK, we've got a COOKIE; let's stuff it on
  249. /* the GLOBAL COOKIE LIST glCookie
  250.  */
  251. if(glCookie==NULL_LIST){
  252.     glCookie=l_create("INORDER");
  253.     if(!glCookie) {
  254. MsgPush("l_create failed in Cookie ...");
  255. return(eFalse);
  256.     }
  257. }
  258. pSym = NewPIA();
  259. if(!pSym){
  260.     MsgPush("swinput: Cookie, NewPIA failed");
  261.     return(eFalse);
  262. }
  263. pSym->iType=0; /* Not used, best init it, though */
  264. pSym->pName=DupBuf(pCookieName);
  265. pSym->pValue=DupBuf(pCookieValue);
  266. pSym->lSize=strlen(pCookieValue);
  267. ENQ(glCookie,pSym);
  268. continue;
  269.     }
  270.     /* ... potential invalid cookie ... 
  271.      */
  272.     break;
  273. }
  274.     }
  275.     return(eTrue);
  276. }
  277. /*
  278. /* Parse a Multipart/form-data buffer
  279. /* first line is the "delimiter"
  280. /* then a series of "parts" each made up of a Header and Body
  281. /* Header begins with a "content-disposition" header and
  282. /* optionally more headers like content-type
  283. /* The Body follows a blank line after the Headers and continues
  284. /* to the next "delimiter".  The last NEWLINE should be stripped
  285. /* off of the end of the field.
  286.  */
  287. static eBoolean_t
  288. ParseMultiPartFormData(char *pIn, long lInSize)
  289. {
  290.     char *pBoundry = pIn
  291. ,*pName    = 0
  292. ,*pUnixEOL = "n"
  293. ,*pUnixEOH = "nn"
  294. ,*pDosEOL  = "rn"
  295. ,*pDosEOH  = "rnrn"
  296. ,*pEOL     = pUnixEOL
  297. ,*pEOH     = pUnixEOH
  298. ;
  299.     FILE *pF, *fopen();
  300.     /* First line is multi-part delimiter
  301.      */
  302.     for(pBoundry=pIn;*pIn;++pIn) {
  303. if(bStrNMatch(pDosEOL,pIn,iStrLen(pDosEOL))) {
  304.     pEOL = pDosEOL;
  305.     pEOH = pDosEOH;
  306.     break;
  307. }
  308. if(bStrNMatch(pUnixEOL,pIn,iStrLen(pUnixEOL))) {
  309.     pEOL = pUnixEOL;
  310.     pEOH = pUnixEOH;
  311.     break;
  312. }
  313.     }
  314.     if(*pIn==0){
  315. MsgPush("Failed to find Border in ParseMultiPartFormData");
  316. return(eFalse);
  317.     }
  318.     *pIn=0; /* NULL the Delimiter String */
  319.     pIn += iStrLen(pEOL); /* Set pointer */
  320. #ifdef DEBUG
  321.     pF=fopen("/tmp/sqlweb.log","a");
  322.     fprintf(pF,"********************************************n");
  323.     fprintf(pF,"DELIM=^%s^n",pBoundry);
  324.     fflush(pF);
  325. #endif
  326.     while(*pIn && pIn-pBoundry<lInSize) {
  327. char *pStart
  328.     ,*pEnd
  329.     ,*pBody
  330.     ;
  331. /*
  332. /* Let's build the Parts, pBody is used below as a
  333. /* temporary variable for walking through binary data
  334. /* in case the file is a image/jpeg file.
  335. /* This loop sets pEnd which marks the end of the Body
  336.  */
  337. pBody = pStart = pIn;
  338. while( (long)(pBody-pBoundry) <lInSize) {
  339.     pEnd = (char*)strstr(pBody,pBoundry);
  340.     if(pEnd)
  341. break;
  342.     pBody += iStrLen(pBody)+1;
  343.     while((*pBody)!=(*pBoundry) && (long)(pBody-pBoundry)<lInSize)
  344. ++pBody;
  345. }
  346. if(!pEnd) {
  347.     MsgPush("No Boundry in Multipart/form-data");
  348.     return(eFalse);
  349. }
  350. pEnd = pEnd-iStrLen(pEOL);
  351. *pEnd=0;
  352. /*
  353. /* Let's get the Header
  354.  */
  355. pBody = (char*)strstr(pStart,pEOH);
  356. if(!pBody){
  357.     MsgPush("No Separator after Headers in MultiPart/Form-data [%s]"
  358.    ,pStart
  359.    );
  360.     return(eFalse);
  361. }
  362. *pBody=0; /* NULL header */
  363. pBody += iStrLen(pEOH);
  364. #ifdef DEBUG
  365. fprintf(pF,"pHeader[%d]=^%s^n",(pEnd-pBody),pStart);
  366. /*
  367. /* fprintf(pF,"pValue=^%s^n",pBody);
  368.  */
  369. #endif
  370. if(ISeTrue(getHeaderItem(pStart,"name=",&pName))) {
  371.     char *pFileName;
  372.     RAWSym(DupBuf(pName)
  373.   ,(char *)DupMem(pBody,(pEnd-pBody)+1)
  374.   ,(pEnd-pBody)+1 /* +1 adds the NULL */
  375.   );
  376.     if(ISeTrue(getHeaderItem(pStart,"filename=",&pFileName))) {
  377. char sBuf[MAX_TOK_SIZE];
  378. sprintf(sBuf,"%s_filename",pName);
  379. FRMSym(DupBuf(sBuf),DupBuf(pFileName));
  380. /*
  381. /* Since it's a FILE, let's try to get the TYPE
  382.  */
  383. if(ISeTrue(getHeaderItem(pStart,"Content-Type:",&pFileName))){
  384.     char sBuf[MAX_TOK_SIZE];
  385.     sprintf(sBuf,"%s_content_type",pName);
  386.     FRMSym(DupBuf(sBuf),DupBuf(pFileName));
  387. }
  388.     } else {
  389. ;
  390. #ifdef DEBUG
  391. /* Since it's NOT a FILE, let's have a look see
  392.  */
  393. fprintf(pF,"pValue=^%s^n",pBody);
  394. #endif
  395.     }
  396. } else {
  397.     MsgPush("No Name in Headers in MultiPart/Form-data");
  398.     return(eFalse);
  399. }
  400. /* Advance pIn */
  401. pIn = pEnd + iStrLen(pEOL) + iStrLen(pBoundry);
  402. if( *pIn=='-' && *(pIn+1)=='-') {
  403.     return(eTrue);
  404. }
  405. pIn += iStrLen(pEOL);
  406.     }
  407.     fclose(pF);
  408.     return(eTrue);
  409. }
  410. static eBoolean_t
  411. getHeaderItem(char *pHeader, char *pAttrName, char **pNameValue)
  412. {
  413.     char *pStart, *pEnd
  414. ,sBuf[MAX_TOK_SIZE]
  415. ;
  416.     int i;
  417.     *pNameValue = 0;
  418.     pStart = strstr(pHeader,pAttrName);
  419.     if(!pStart) {
  420. /* MsgPush("Missing Attribute "%s" in Headers in MultiPart/Form-data"
  421. /* ,pAttrName
  422. /* );
  423.  */
  424. return(eFalse);
  425.     }
  426.     for(pStart+=iStrLen(pAttrName);*pStart && !isalnum(*pStart);pStart++)
  427. ;
  428.     for( i=0,pEnd=pStart
  429. ;*pEnd &&i<MAX_TOK_SIZE
  430. && *pEnd!='"' && *pEnd!=';' && *pEnd!='n' && *pEnd!='r'
  431. ;pEnd++,i++)
  432.     {
  433. sBuf[i]= *pEnd;
  434.     }
  435.     sBuf[i]=0;
  436.     *pNameValue = DupBuf(sBuf);
  437.     return(eTrue);
  438. }