/*
** Copyright (C) Roman Ukhov 2000
** e-mail: r_ukhov@yahoo.com
** http://rukhov.newmail.ru
*/
#include "http_server.hpp"
#include "http_date.hpp"
#include "request.h"
#include "respond.h"
#include <malloc.h>
using namespace std;
static const char szHttp_endl[]="\r\n";
static const char szHttp_1_0[]="HTTP/1.0";
static const char szHttp_1_1[]="HTTP/1.1";
static const char sz200[]="OK";
static const char sz206[]="Partial content";
static const char sz302[]="Object Moved";
static const char sz304[]="Not Modified";
static const char sz403[]="Acces Forbidden";
static const char sz404[]="Not Found";
static const char sz405[]="Method Not Allowed";
static const char sz408[]="Request Timeout";
static const char sz414[]="Request-URI Too Long";
static const char sz416[]="Requested Range Not Satisfiable";
static const char sz501[]="Not Implemented";
static const char szHTML_BR[]="<br>";
static const char* ContentTypes[]={
"application/octet-stream",
"text/html",
"application/pdf",
"image/gif",
"application/msword",
"application/x-rar-compressed",
"text/plain",
"image/jpeg",
"application/zip",
"application/x-mswrite"
};
typedef struct
{
char *ext;
cont_types_t type;
}file_ext_to_cont_type_t;
static const file_ext_to_cont_type_t FileExtensions[]={
"htm", html,
"html", html,
"gif", gif,
"rar", rar,
"zip", zip,
"exe", unknown,
"tgz", unknown,
"pdf", pdf,
"doc", msword,
"txt", txt,
"h", txt,
"hpp", txt,
"c", txt,
"cpp", txt,
"cxx", txt,
"pas", txt,
"asm", txt,
"s", txt,
"for", txt,
"jpeg", jpeg,
"jpg", jpeg,
"wri", wri
};
static const bool is_html_simbol[256]=
{
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
/*0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*1*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*2*/ 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1,
/*3*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*4*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*5*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*6*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*7*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*8*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*9*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*a*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*b*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*c*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*d*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*e*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*f*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
static
const std::string
to_http_string(const std::string& str)
{
string temp;
int len=str.size();
unsigned char c;
char szTmp[10];
for(int i=0; i<len; i++){
c=str[i];
if(is_html_simbol[c] == false){
wsprintf(szTmp, "%%%02X", c);
temp+=szTmp;
}else{
temp+=str[i];
}
}
return temp;
}
static
const std::string
from_http_string(const std::string& http_str)
{
string temp;
int len=http_str.size();
unsigned char c;
char szHex[3];
for(int i=0; i<len; i++){
c=http_str[i];
if( c=='%' ){
char* hexEndP;
if(i<=len-3){
i++;
szHex[0]=http_str[i++];
szHex[1]=http_str[i];
szHex[2]=0;
unsigned long cr=strtoul(szHex, &hexEndP, 16);
if(cr<256){
c=cr;
}
}
}
temp+=c;
}
return temp;
}
respond::respond(
const std::string _host_name,
const std::string _root_dir,
const std::string _index_file_name,
bool _allow_directory_browsing/* = true*/):
hFile(INVALID_HANDLE_VALUE),
err_code(0),
file_size(0),
file_pos(0),
file_end_pos(0),
start_from(0),
cb_buffered(0),
buff_pos(0),
content_type(unknown),
host_name(_host_name),
root_dir(_root_dir),
allow_directory_browsing(_allow_directory_browsing),
index_file_name(_index_file_name)
{
}
respond::~respond()
{
if(hFile != INVALID_HANDLE_VALUE){
CloseHandle(hFile);
}
}
bool
respond::make_respond(request& rqu)
{
char szTmp[1024];
char szHttpErr[128];
b_have_body=false;
if(rqu.http_version_major == 1 &&
rqu.http_version_minor == 1){
respond_str=szHttp_1_1;
}else{
respond_str=szHttp_1_0;
}
if(rqu.host.size()>0){
host_name=rqu.host;
}
{
SYSTEMTIME sys_time;
GetSystemTime(&sys_time);
str_date=std::string(http_date(sys_time));
}
if(rqu.type==request::get ||
rqu.type==request::get_if_modified ||
rqu.type==request::head){
if(rqu.type==request::head)
log_str+="\nHEAD ";
else
log_str+="\nGET ";
bool b_dir(false);
log_str+=from_http_string(rqu.requested_target);
if(rqu.Request_URI_Too_Long==true){
uri_too_long(rqu, szHttpErr);
}else
if(parse_url(rqu.requested_target, &b_dir)==false){
if(not_found_stuff(rqu, szHttpErr) == false)
return false;
}else{
what_content_type(rqu);
if(b_dir == true && index_file_name.size()==0 && allow_directory_browsing == true){
if(ditectory_stuff(rqu, szHttpErr) == false){
if(not_found_stuff(rqu, szHttpErr) == false)
return false;
}
}else{
if(open_file(rqu, szHttpErr, b_dir) == false){
if(b_dir == true && index_file_name.size()>0){
if(allow_directory_browsing){
if(ditectory_stuff(rqu, szHttpErr) == false){
if(not_found_stuff(rqu, szHttpErr) == false)
return false;
}
}else{
if(forbidden_stuff(rqu, szHttpErr, b_dir)==false)
return false;
}
}else{
if(b_dir && redirect_stuff(rqu, szHttpErr)==false){
if(not_found_stuff(rqu, szHttpErr) == false)
return false;
}else{
if(not_found_stuff(rqu, szHttpErr) == false)
return false;
}
}
}
}
}
}else if(rqu.type==request::timeout){
log_str+="\nRequest timeout ";
if(request_timeout_stuff(rqu, szHttpErr)==false)
return false;
}else{
log_str+="\nNot implemented ";
if(not_implemented_stuff(rqu, szHttpErr)==false)
return false;
}
wsprintf(szTmp, " %u", err_code);
log_str+=szTmp;
respond_str+=szTmp;
respond_str+=szHttpErr;
respond_str+=szHttp_endl;
respond_str+=add_to_header;
respond_str+="Server: ";
respond_str+=szAppName;
respond_str+=' ';
respond_str+=szCopyright;
respond_str+=szHttp_endl;
respond_str+="Date: ";
respond_str+=str_date;
respond_str+=szHttp_endl;
respond_str+="Connection: ";
if(rqu.keep_alive == true){
respond_str+="Keep-Alive";
}else{
respond_str+="close";
}
respond_str+=szHttp_endl;
if(b_have_body==true){
if(hFile != INVALID_HANDLE_VALUE){
std::string temp;
content_type_to_str(content_type, &temp);
respond_str+="Content-Type: ";
respond_str+=temp;
respond_str+=szHttp_endl;
}
if(rqu.http_version_major == 1 &&
rqu.http_version_minor == 1 &&
(
err_code == 200 ||
err_code == 206
)){
respond_str+="Accept-Ranges: bytes";
respond_str+=szHttp_endl;
}
if(hFile != INVALID_HANDLE_VALUE){
respond_str+="Last-Modified: ";
respond_str+=std::string(http_date(file_time));
respond_str+=szHttp_endl;
}
respond_str+="Content-length: ";
if(hFile != INVALID_HANDLE_VALUE){
wsprintf(szTmp, "%u", file_end_pos-start_from);
}
respond_str+=szTmp;
respond_str+=szHttp_endl;
if(hFile != INVALID_HANDLE_VALUE){
if(rqu.http_version_major == 1 &&
rqu.http_version_minor == 1 && err_code == 206){
respond_str+="Content-Range: bytes ";
wsprintf(szTmp, "%u-%u/%u",
start_from,
file_end_pos-1,
file_size);
respond_str+=szTmp;
respond_str+=szHttp_endl;
}
}
}
respond_str+=szHttp_endl;
err_code=0;
strcpy(buffer, respond_str.c_str());
cb_buffered=strlen(buffer);
if(cb_buffered == 0){
move_pointers(0);
}
return true;
}
void
respond::add_header_to
- 1
- 2
- 3
- 4
前往页