📄 xpt-http.c
字号:
if (!xppStricmp (pszToken, "stale") && !xppStricmp (pszValue, "true")) ad.bStale = true; else ad.bStale = false; if (!xppStricmp (pszToken, "domain")) ad.szDomain = pszParm; } authSetType (auth, dest, typ); authSetAuthenticationData (auth, dest, &ad); } }#define EVALUATE_FIELD(f,n,p,t,v) if (!xppStricmp ((t),(f))) {(n)((p),(v)); }#define EVALUATE_AUTH_FIELD(f,n,p,t,v,a,d) if (!xppStricmp ((t),(f))&&((a)!=NULL)) {(n)((p),(v),(a),(d));}/*************************************************************************//* Function: Analyze one line from the HTTP header block, and update *//* the HTTP object store if something interesting was found. *//* In case of an empty string, the function returns true: *//* An empty string indicates the end of the HTTP header block *//*************************************************************************/Bool_t evaluateHttpHeaderLine (HttpBufferPtr_t p, // i: instance object StringBuffer_t pszLine, // i: one HTTP header line HttpAuthenticationPtr_t auth) // i/o: authorization info { Bool_t bFinished = false; CString_t pszToken = NULL; /*******************************************************/ /* An empty line indicates the end of the HTTP header. */ /*******************************************************/ if (pszLine == NULL) return true; // this should never occur. if (pszLine [0] == '\0') { if ( (p->fOpenMode == MODE_HTTP_SERVER) || (p->bEox == false) || (p->iHttpStatus == 204) || (p->iHttpStatus == 205) || (p->iHttpStatus == 304) || (p->iHttpStatus == 100) || (p->iHttpStatus == 101) ) bFinished = true; // Empty Line indicates end of HTTP header! } else { pszLine = splitToken (pszLine, &pszToken); // get the keyword of the HTTP header line if (!pszToken) { bFinished = true; // this could be an error!!! } else { /*********************************************************/ /* The first line of the HTTP header is handled this way */ /*********************************************************/ if ((p->pchRequest == NULL) && (p->fOpenMode == MODE_HTTP_SERVER)) { p->pchRequest = makeString (pszToken); pszLine = splitToken (pszLine, &pszToken); if (pszToken != NULL) { const char *pszURL = getResourceName (pszToken); /*********************/ /* Get the URL name. */ /*********************/ p->pchURI = makeString (pszURL); } } else if ((p->iHttpStatus == HTTP_STATUS_UNDEFINED) && (p->fOpenMode != MODE_HTTP_SERVER)) { while (pszLine [xppStrlen(pszLine)-1] == ' ') pszLine [xppStrlen(pszLine)-1] = '\0'; /* cut trailing blanks */ p->iHttpStatus = xppAtoi (pszLine); } /******************************************************/ /* Look for the keywords that are interesting for me: */ /* Host - IP address of the host */ /* Referer - name of the referenced document */ /* Content-Length - size of the document to receive */ /* Content-Type - Document mime type */ /* Connection - Connection type */ /* Authorization -client authorization data */ /* Authentication-Info - server authentication data */ /* */ /* If Content-Length or Transfer-Encoding is speci- */ /* fied, we recognize that a document is attached to */ /* the HTTP header. */ /* */ /* ignore the other keywords */ /******************************************************/ else { EVALUATE_FIELD ("Host:", evaluateHdrHost, p, pszToken, pszLine) EVALUATE_FIELD ("From:", evaluateHdrFrom, p, pszToken, pszLine) EVALUATE_FIELD ("Referer:", evaluateHdrReferer, p, pszToken, pszLine) EVALUATE_FIELD ("Content-Length:", evaluateHdrContentLength, p, pszToken, pszLine) EVALUATE_FIELD ("Content-Type:", evaluateHdrContentType, p, pszToken, pszLine) EVALUATE_FIELD ("Connection:", evaluateHdrConnection, p, pszToken, pszLine) EVALUATE_FIELD ("Transfer-Encoding:", evaluateHdrTransferEncoding, p, pszToken, pszLine) EVALUATE_FIELD ("x-syncml-hmac:", evaluateHdrXSyncmlHmac, p, pszToken, pszLine) EVALUATE_AUTH_FIELD ("Authorization:", evaluateHdrAuthorization, p, pszToken, pszLine, auth, DEST_SERVER) EVALUATE_AUTH_FIELD ("Authentication-Info:", evaluateHdrAuthenticationInfo, p, pszToken, pszLine, auth, DEST_NONE) EVALUATE_AUTH_FIELD ("WWW-Authenticate:", evaluateHdrWWWAuthenticateInfo, p, pszToken, pszLine, auth, DEST_SERVER) EVALUATE_AUTH_FIELD ("Proxy-Authenticate:", evaluateHdrWWWAuthenticateInfo, p, pszToken, pszLine, auth, DEST_PROXY) } } } return bFinished; }/***********************************************************************************//* Function: Some data have been received to the transfer buffer before, and it is *//* assumed that the data contain HTTP header information. Go and analyze the block *//* The function returns true if the end of the HTTP header has been detected. *//* Those parts of the incoming data that could not be processed remain in the *//* transfer buffer. *//***********************************************************************************/Bool_t evaluateHttpHeaderBlock (HttpBufferPtr_t p, // i: instance object HttpAuthenticationPtr_t auth) // i/o: authorization info { Bool_t bHeaderCompleted = false; // end of HTTP header detected? Ptr_t pszEnd = (Ptr_t )(p->pbCache + p->cbCacheUsed); // end mark StringBuffer_t pszCurrent = (StringBuffer_t) p->pbCache; StringBuffer_t pszLine; /***********************************************/ /* Loop thru the data in the transfer buffer, */ /* and parse the HTTP header data line-by-line */ /***********************************************/ p->pbCache [p->cbCacheUsed] = '\0'; while ((pszCurrent != NULL) && (pszCurrent < (StringBuffer_t) pszEnd) && (bHeaderCompleted == false)) { pszLine = pszCurrent; pszCurrent = splitLine (pszCurrent); if (pszCurrent == NULL) { /*********************************************/ /* We are still waiting for additional data. */ /* We must read the next block! */ /*********************************************/ p->cbCacheUsed -= (BufferSize_t) (pszLine - (StringBuffer_t) p->pbCache); if (p->cbCacheUsed > 0) { xppMemmove (p->pbCache, pszLine, p->cbCacheUsed); p->pbCache [p->cbCacheUsed] = '\0'; } } else if (evaluateHttpHeaderLine (p, pszLine, auth)) { /* T.K. Microsoft IIS 4/5 hack */ /* IIS has the behavior of sending HTTP/1.1 100 Continue just */ /* before sending the HTTP/1.1 200 OK - so we 'peek' in the remaining */ /* buffer and see wether we are really finished or wether we need to go */ /* further. */ /* %%% luz 2002-05-23: this is the wrong place for that, as IIS might choose to delay that "200 OK" header a little. We need to continue reading (in readHttpHeader()) if status was "100 Continue" and check if following data is "HTTP/1.1" again int dummyInt = xppStrncmp(pszCurrent, "HTTP/1.1",8); if (dummyInt == 0) { p->iHttpStatus = HTTP_STATUS_UNDEFINED; // reset the unused status } else */ { /****************************************************************************/ /* The header finished here. Copy the non-processed data (this is the first */ /* block of the data section) to the beginning of the cache, then return to */ /* the caller */ /****************************************************************************/ p->cbCacheUsed = (BufferSize_t) (pszEnd - pszCurrent); if (p->cbCacheUsed > 0) xppMemmove (p->pbCache, pszCurrent, p->cbCacheUsed); bHeaderCompleted = true; } } } return bHeaderCompleted; }#if SYDEBUG>1// %%% luzvoid DebugPrintf(const char *text, ...);#endif/****************************************************************************//* Function: read the HTTP header *//* The function waits for incoming data and processes the HTTP header data. *//* When the function returns, the transfer buffer may already contain the *//* first bytes of the document! *//****************************************************************************/TcpRc_t readHttpHeader (HttpBufferPtr_t p, // i: instance object HttpAuthenticationPtr_t auth) // i/o: authorization info { BufferSize_t uBytesTransmitted; Bool_t bHeaderProcessed = false; /* %%% luz:2002-05-23: several changes (iispeek), see comments below */ Bool_t iispeek; /****************/ /* Set defaults */ /****************/// p->fEncoding = FLAT; p->fTransferCoding = NOT_CHUNKED; p->fTransferMode = MODE_READING; p->bEox = true; p->cbDataLength = UNDEFINED_CONTENT_LENGTH; freeString(p->sXSyncmlHmac.pchHmac); p->sXSyncmlHmac.pchHmac = NULL; p->sXSyncmlHmac.hmacInfo.mac = NULL; p->sXSyncmlHmac.hmacInfo.username = NULL; p->sXSyncmlHmac.hmacInfo.algorithm = NULL; /*****************************************************************/ /* Go and receive all incoming TCP/IP packets */ /* until the HTTP header information has been parsed completely. */ /*****************************************************************/ /* %%% luz:2002-05-23: several changes (iispeek), see comment below */ iispeek=false; // no IIS peek done yet while ((bHeaderProcessed == false) && (p->iRc == TCP_RC_OK)) { /* get the next block of data */ uBytesTransmitted = (BufferSize_t)(sizeof (p->pbCache) - p->cbCacheUsed); p->iRc = tcpReadData (p->pSession, p->pbCache+p->cbCacheUsed, &uBytesTransmitted); if (p->iRc == TCP_RC_OK) { p->cbCacheUsed += uBytesTransmitted; do { // first check if we must peek for IIS before checking header if (iispeek) { // we have already processed a "100 continue" header. // - check if we have at least 7 chars to check if another header is following if (p->cbCacheUsed>7) { iispeek=false; // we can check now, peek ends here // NOTE: under some strange circumstances (special Auth software on IIS // which somehow intervenes normal IIS response, we can have the 100 Continue // followed by a HTTP 1.0 (!!). So we only check for "HTTP/1." here. if (xppStrncmp((StringBuffer_t)p->pbCache, "HTTP/1.",7)==0) { // - yes, parse it as if it was the first one #if SYDEBUG>1 && !defined(__PALM_OS__) // PalmOS has no %0.80s type formatting DebugPrintf("########### p->cbCacheUsed=%ld, p->pbCache[0..79]='%0.80s'",p->cbCacheUsed,p->pbCache); #endif p->iHttpStatus = HTTP_STATUS_UNDEFINED; // reset the unused status } else { // - no, this is NOT IIS 100 continue special case bHeaderProcessed=true; // we are done now break; // done with header (and some bytes in the cache) } } else { // else: iispeek remains pending, we need more data first break; } } // process header only if no iispeek is pending any more if (!iispeek) { bHeaderProcessed = evaluateHttpHeaderBlock (p, auth); /* T.K. Microsoft IIS 4/5 hack */ /* %%% luz:2002-05-23: modified to work, moved here from evaluateHttpHeaderBlock(). IIS has the behavior of sending HTTP/1.1 100 Continue just before sending the HTTP/1.1 200 OK - so we continue reading after status==100 and see wether we are really finished or wether we need to go further. */ if (bHeaderProcessed && p->iHttpStatus==100) { iispeek=true; // we need to do IIS peek bHeaderProcessed=false; // do not stop yet } } // if not peek pending } while(iispeek); } // if TCP read ok else { // %%% luz:2002-11-11 added to allow setting breakpoint on error break; } } // while /*************************************************************************/ /* Dependent on the HTTP header settings, */ /* the instance variable DataToRead must be set: */ /* if CHUNKED transfer coding is selected, the variable keeps the number */ /* of bytes that have not been for the current chunk, if NON_CHUNKED */ /* transfer coding is selected, the number of bytes of the HTTP document */ /* itself is returned. */ /*************************************************************************/ if (p->iRc == TCP_RC_OK) { if (p->fTransferCoding == NOT_CHUNKED) p->cbDataToRead = p->cbDataLength; else p->cbDataToRead = 0L; } return p->iRc; }HttpRc_t continueHttpRequest (HttpBufferPtr_t p, HttpAuthenticationPtr_t auth) // i: ptr to authorization info { HttpRc_t rc = HTTP_RC_OK; p->cbDataLength = 0; writeRequestHeader (p, auth); p->iRc = tcpSendData (p->pSession, p->pbCache, p->cbCacheUsed); if (p->iRc != TCP_RC_OK) rc = HTTP_RC_COMMUNICATION; return rc; }/********************************************************************//* Function: Create an instance of a HTTP object for a client *//* The HTTP doc type is denoted by pszMode. *//********************************************************************/HttpRc_t openClient (HttpBufferPtr_t p, // io: allocated instance object SocketPtr_t pSession, // i: ptr to created TCP/IP socket CString_t pszMode, // i: Type of HTTP document HttpDocumentContextPtr_t settings, // i: document properties HttpAuthenticationPtr_t auth) // i: ptr to authorization info {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -