📄 http4u.c
字号:
/*
* Tcp4u v 3.30 Last Revision 27/06/1997 3.10
*
*===========================================================================
*
* Project: Tcp4u, Library for tcp protocol
* File: http4u.c
* Purpose: manage http 1.0 protocol
*
*===========================================================================
*
* This software is Copyright (c) 1996-1998 by Philippe Jounin and Laurent Le Bras
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*
* If you make modifications to this software that you feel
* increases it usefulness for the rest of the community, please
* email the changes, enhancements, bug fixes as well as any and
* all ideas to me. This software is going to be maintained and
* enhanced as deemed necessary by the community.
*
*
* Philippe Jounin (ph.jounin@computer.org)
*/
static char szWhat[]="@(#)http4u by Ph. Jounin and L. Le Bras version 3.11";
#include "build.h"
/******************************
* Http4u internal structures
******************************/
/* status-line for http 1.0 answers */
struct S_HttpStatus
{
int nVersion; /* version should be 1 */
int nMinor; /* revision (0 or 1) */
int code; /* status-code (ex: 200 ) */
char reason[64]; /* reason (ex: "OK") */
};
/*******************************
* A few globals variables
*******************************/
static unsigned int s_uHttp4uTimeout = DFLT_TIMEOUT;
static unsigned int s_uHttp4uBufferSize = DFLT_BUFFERSIZE;
static DO_NOT_LOG = HFILE_ERROR;
/*=====================================================================
* PRIVATE FUNCTION SOURCES
*===================================================================*/
/*######################################################################
*##
*## NAME: HttpProcessAnswer
*##
*## PURPOSE: get HTTP version + HTTP return code + data string
*## fully reeentrant
*##
*####################################################################*/
static int HttpProcessAnswer (LPCSTR szAns, int far *pnVer, int far *pnMinor,
int far *pnAnswer, LPSTR szData, int nDataSize)
{
LPCSTR p;
Tcp4uLog (LOG4U_INTERN, "HttpProcessAnswer");
if (memcmp (szAns, "HTTP/", sizeof ("HTTP/") - 1)!=0)
{
Tcp4uLog (LOG4U_ERROR, "HttpProcessAnswer: bad protocol returned (%s)", szAns);
return HTTP4U_PROTOCOL_ERROR;
}
/* 27/06/97: ignore version numbers (RFC2145) */
*pnAnswer=1; *pnMinor=0;
/* search for a space character, then skip it */
p = szAns + sizeof "HTTP/";
while (*p!=0 && !isspace(*p)) p++;
while (*p!=0 && isspace(*p)) p++;
if (*p==0)
{
Tcp4uLog (LOG4U_ERROR, "HttpProcessAnswer: bad protocol returned (%s)", szAns);
return HTTP4U_PROTOCOL_ERROR;
}
*pnAnswer = Tcp4uAtoi (p);
/* continue only if szData is to be filled */
if (szData!=NULL && nDataSize>0)
{
/* search for a non-digit then skips spaces */
while (*p!=0 && isdigit(*p)) p++;
while (*p!=0 && isspace(*p)) p++;
Strcpyn (szData, p, nDataSize);
}
return HTTP4U_SUCCESS;
} /* HttpProcessAnswer */
/*######################################################################
*##
*## NAME: HttpSendAdditionnalHeader
*##
*## PURPOSE: Send a http 1.0 general-header
*##
*####################################################################*/
static int HttpSendAdditionnalHeader(SOCKET CSock)
{
int Ark;
int Rc;
static LPCSTR szAdditionnalStrings[] =
{
"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*",
"User-Agent: Http4u by Ph. Jounin and L. Le Bras",
"",
};
Tcp4uLog (LOG4U_INTERN, "HttpSendAdditionnalHeader");
/* sending request, if successful send Request Header */
for (Rc=TCP4U_SUCCESS,Ark=0 ; Rc==TCP4U_SUCCESS && Ark<SizeOfTab(szAdditionnalStrings); Ark++)
Rc = TnSend (CSock, szAdditionnalStrings[Ark], FALSE, DO_NOT_LOG);
return Rc==TCP4U_SUCCESS ? HTTP4U_SUCCESS : HTTP4U_TCP_FAILED;
} /* END HttpSendAdditionnalHeader */
/*######################################################################
*##
*## NAME: HttpSendRequest10
*##
*## PURPOSE: Send an http 1.0 method request-line
*## Note: szReq can be "HEAD ", "POST ", "GET ", ..
*##
*####################################################################*/
static int HttpSendRequest10(SOCKET CSock, /* socket decriptor */
LPCSTR szReq, /* request to be sent */
LPCSTR szURL /* URL or URI */)
{
LPSTR sRequest = NULL;
int Rc;
Tcp4uLog (LOG4U_INTERN, "HttpSendRequest10");
/* allocate buffer wide eough to contain all data */
sRequest = Calloc (sizeof(" HTTP/1.0 ") + Strlen (szURL) + Strlen(szReq),
sizeof(char));
if (sRequest == NULL) return HTTP4U_INSMEMORY;
/* compose request with reentrant functions */
Strcpy(sRequest, szReq);
Strcat(sRequest, szURL);
Strcat(sRequest, " HTTP/1.0");
/* send the request then forget it */
Rc = TnSend (CSock, sRequest, FALSE, DO_NOT_LOG);
Free (sRequest);
if (Rc!=TCP4U_SUCCESS) return HTTP4U_TCP_FAILED ;
/* Send general-header */
return HttpSendAdditionnalHeader(CSock);
} /* END HttpSendRequestHEAD10 */
/*######################################################################
*##
*## NAME: HttpRecvRespStatus
*##
*## PURPOSE: Get the status-line of the http answer
*## The data are copied into saRespStatus and szAnswer
*##
*####################################################################*/
static int HttpRecvRespStatus(SOCKET CSock,
struct S_HttpStatus far *saRespStatus,
LPSTR szAnswer, int nAnswerSize)
{
#define RECV_BUF_SIZE 1024
LPSTR sBufStatus;
int nBufStatusLen = RECV_BUF_SIZE ;
int Rc;
Tcp4uLog (LOG4U_INTERN, "HttpRecvRespStatus");
if (szAnswer !=NULL && nAnswerSize > 0) szAnswer[0]=0;
/* If ye can keep user's buffer */
if (szAnswer!=NULL && nAnswerSize >= RECV_BUF_SIZE)
{
sBufStatus = szAnswer;
nBufStatusLen = nAnswerSize;
}
else
{
sBufStatus = Calloc (RECV_BUF_SIZE, sizeof (char));
if (sBufStatus == NULL) return HTTP4U_INSMEMORY;
}
/* receive data */
Rc = TnReadLine (CSock,sBufStatus,nBufStatusLen,s_uHttp4uTimeout, DO_NOT_LOG);
switch(Rc)
{
case TCP4U_SUCCESS: break;
case TCP4U_OVERFLOW: return HTTP4U_OVERFLOW;
case TCP4U_TIMEOUT: return HTTP4U_TIMEOUT;
case TCP4U_CANCELLED: return HTTP4U_CANCELLED;
case TCP4U_ERROR: return HTTP4U_TCP_FAILED;
case TCP4U_SOCKETCLOSED: return HTTP4U_PROTOCOL_ERROR;
default: return HTTP4U_TCP_FAILED;
}
/* control format */
Rc = HttpProcessAnswer ( sBufStatus,
& saRespStatus->nVersion,
& saRespStatus->nMinor,
& saRespStatus->code,
saRespStatus->reason,
sizeof saRespStatus->reason);
/* Copy data, free buffer */
if (sBufStatus != szAnswer)
{
if (szAnswer != NULL) Strcpyn (szAnswer, sBufStatus, nAnswerSize);
Free (sBufStatus);
}
return Rc;
#undef RECV_BUF_SIZE
} /* END HttpRecvRespStatus */
/*######################################################################
*##
*## NAME: HttpRecvHeaders10
*##
*## PURPOSE: Return the headers section of the http respons
*## sBufHeaders Can not be NULL, but sBufHeadersLen can !!
*##
*####################################################################*/
static int HttpRecvHeaders10 (SOCKET CSock,
LPSTR sBufHeaders,
int nBufHeadersLen)
{
int Rc;
int nRcvd, nLineLength;
LPSTR p;
#define EMPTY(s) ((s)[0]=='\r' || (s)[0]=='\n')
Tcp4uLog (LOG4U_INTERN, "Http4RecvHeaders10");
if (sBufHeaders==NULL) return HTTP4U_BAD_PARAM;
memset(sBufHeaders, 0, nBufHeadersLen);
/* Keep space for last ending line and nul character */
nBufHeadersLen -= sizeof SYSTEM_EOL;
/* receive data from distant http server. Must use loop on TcpRecvUntilStr */
/* since some unix servers send \n\n instead of regular \n\r\n.... */
nRcvd = 0 ;
do
{
p = & sBufHeaders[nRcvd];
Rc = InternalTnReadLine (CSock,
p, nBufHeadersLen-nRcvd,
s_uHttp4uTimeout, DO_NOT_LOG);
Strcat (p, SYSTEM_EOL);
nLineLength = Strlen (p); /* 0 on error */
nRcvd += nLineLength;
} /* loop until error or empty line */
while (Rc==TCP4U_SUCCESS && !EMPTY(p) && nRcvd < nBufHeadersLen);
/* translate return code */
switch(Rc)
{
/* remember to put the last \n into destination string */
case TCP4U_SUCCESS: Tcp4uDump (sBufHeaders, nRcvd, DUMP4U_RCVD);
return nRcvd >= nBufHeadersLen ?
HTTP4U_OVERFLOW : HTTP4U_SUCCESS;
case TCP4U_OVERFLOW: return HTTP4U_OVERFLOW;
case TCP4U_TIMEOUT: return HTTP4U_TIMEOUT;
case TCP4U_CANCELLED: return HTTP4U_CANCELLED;
case TCP4U_ERROR: return HTTP4U_TCP_FAILED;
case TCP4U_INSMEMORY: return HTTP4U_INSMEMORY;
case TCP4U_SOCKETCLOSED: return HTTP4U_PROTOCOL_ERROR;
default: return HTTP4U_TCP_FAILED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -