Yet Another Intercepting Proxy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

134 lines
3.7 KiB

#include "response.h"
Response* newResponse(){
Response *response = malloc( sizeof( Response ) );
memset(response, 0, sizeof(Response));
response->headers = NULL;
response->statusMessage = NULL;
response->body = NULL;
return response;
}
void responseBarebones(Response *rsp){
rsp->headers = malloc( sizeof( HeaderList ) );
rsp->headers->header = newHeader("Content-Length: 0");
rsp->headers->next = NULL;
addHeader(rsp->headers, "Content-Type: text/plain");
rsp->statusCode = 200;
rsp->statusMessage = strdup("OK");
rsp->version = 1.1;
}
void connectionEstablished(Response *rsp){
rsp->statusCode = 200;
rsp->statusMessage = strdup("Connection Established");
rsp->version = 1.1;
}
char* responseToString( Response *rsp ){
// HTTP/x.x xxx OK \r\n
int fullLength = 13 + strlen(rsp->statusMessage) + 2 +
// Headers \r\n\r\n
headerListCharLength(rsp->headers) + 4;
if ( rsp->body != NULL ) fullLength += strlen(rsp->body) + 2;
char retString[fullLength];
sprintf(retString, "HTTP/%.1f %3d %s\r\n%s\r\n", rsp->version, rsp->statusCode,
rsp->statusMessage,headersToString(rsp->headers));
if ( rsp->body != NULL ) sprintf(retString + strlen(retString), "%s\r\n", (char *)rsp->body);
return strdup(retString);
}
void responseSetBody(Response *rsp, char *string, bool updateContentLength){
rsp->body = strdup(string);
if ( updateContentLength ){
Header *contentLengthHeader = getHeader(rsp->headers, "content-length");
if ( contentLengthHeader == NULL ){
responseAddHeader( rsp, "content-length: 0" );
contentLengthHeader = getHeader(rsp->headers, "content-length");
}
char *value = malloc(sizeof(char) * 20);
sprintf(value, "%lu", strlen(string) );
contentLengthHeader->value = strdup(value);
}
}
void responseAddHeader(Response *rsp, char header[]){
if ( rsp->headers == NULL ){
rsp->headers = malloc(sizeof( HeaderList ));
rsp->headers->header = newHeader( header );
rsp->headers->next = NULL;
} else
addHeader( rsp->headers, header );
}
void responseFirstLine( Response *rsp, char line[] ){
// HTTP/1.1 200 OK
float version = 0;
int statusCode = 0;
char statusMessage[256] = {'\0'};
sscanf( line, "HTTP/%f %i %255[^\n]", &version, &statusCode, statusMessage );
rsp->version = version;
rsp->statusCode = statusCode;
rsp->statusMessage = strdup(statusMessage);
}
Response* newResponseFromSocket(int socket){
Response *rsp = newResponse();
int valread;
char line[1024] = {0};
Header *contentLength = NULL;
unsigned int bodySize = 0, bodyRead = 0;
valread = fdReadLine( socket, line, 1024);
responseFirstLine(rsp, line);
//a length of 2 will indicate an empty line which will split the headers
//from the body (if there is a body)
valread = fdReadLine( socket, line, 1024);
while ( valread > 2 ){
responseAddHeader( rsp, line );
valread = fdReadLine( socket , line, 1024);
}
//I believe at this point all the headers are done.
contentLength = getHeader( rsp->headers, "content-length" );
if ( contentLength != NULL ){
bodySize = atoi( contentLength->value );
if (bodySize > 0){
//When the body is not binary data, it is useful to treat it as a
//string. For this reason, I want the bite immediately after it to
//be \0
rsp->body = malloc( bodySize + 1 );
memset( rsp->body + bodySize + 1, '\0', 1 );
while ( bodyRead < bodySize ){
valread=read( socket, rsp->body + bodyRead, bodySize - bodyRead );
if (valread < 0){
perror("Unable to read");
return NULL;
}
bodyRead += valread;
}
}
}
return rsp;
}
void freeResponse( Response *rsp ){
free(rsp->statusMessage);
freeHeaderList( rsp->headers );
free(rsp->body);
free(rsp);
}