mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-09-02 10:21:10 +02:00
yWeb 2.8.a.3 Alpha-Version
git-svn-id: file:///home/bas/coolstream_public_svn/THIRDPARTY/applications/neutrino-experimental@406 e54a6e83-5905-42d5-8d5c-058d10e6a962
This commit is contained in:
@@ -13,6 +13,6 @@ AM_CPPFLAGS = -fno-rtti -fno-exceptions
|
||||
noinst_LIBRARIES = libyhttpd.a
|
||||
|
||||
libyhttpd_a_SOURCES = \
|
||||
ylogging.cpp helper.cpp \
|
||||
ylogging.cpp helper.cpp ylanguage.cpp\
|
||||
ywebserver.cpp yconnection.cpp yrequest.cpp yresponse.cpp yhook.cpp ysocket.cpp
|
||||
|
||||
|
@@ -73,7 +73,7 @@ std::string timeString(time_t time)
|
||||
return std::string("??:??");
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// Printf and return formatet String. Buffer-save!
|
||||
// Printf and return formatet String. Buffer-save!
|
||||
// max length up to bufferlen -> then snip
|
||||
//-------------------------------------------------------------------------
|
||||
#define bufferlen 4*1024
|
||||
@@ -82,7 +82,7 @@ std::string string_printf(const char *fmt, ...)
|
||||
char buffer[bufferlen];
|
||||
va_list arglist;
|
||||
va_start( arglist, fmt );
|
||||
// if(arglist)
|
||||
if(arglist)
|
||||
vsnprintf( buffer, bufferlen, fmt, arglist );
|
||||
va_end(arglist);
|
||||
return std::string(buffer);
|
||||
@@ -93,7 +93,7 @@ std::string string_printf(const char *fmt, ...)
|
||||
//-------------------------------------------------------------------------
|
||||
bool ySplitString(std::string str, std::string delimiter, std::string& left, std::string& right)
|
||||
{
|
||||
unsigned int pos;
|
||||
std::string::size_type pos;
|
||||
if ((pos = str.find_first_of(delimiter)) != std::string::npos)
|
||||
{
|
||||
left = str.substr(0, pos);
|
||||
@@ -112,7 +112,7 @@ bool ySplitString(std::string str, std::string delimiter, std::string& left, std
|
||||
//-------------------------------------------------------------------------
|
||||
bool ySplitStringExact(std::string str, std::string delimiter, std::string& left, std::string& right)
|
||||
{
|
||||
unsigned int pos;
|
||||
std::string::size_type pos;
|
||||
if ((pos = str.find(delimiter)) != std::string::npos)
|
||||
{
|
||||
left = str.substr(0, pos);
|
||||
@@ -131,7 +131,7 @@ bool ySplitStringExact(std::string str, std::string delimiter, std::string& left
|
||||
//-------------------------------------------------------------------------
|
||||
bool ySplitStringLast(std::string str, std::string delimiter, std::string& left, std::string& right)
|
||||
{
|
||||
unsigned int pos;
|
||||
std::string::size_type pos;
|
||||
if ((pos = str.find_last_of(delimiter)) != std::string::npos)
|
||||
{
|
||||
left = str.substr(0, pos);
|
||||
@@ -165,7 +165,7 @@ CStringArray ySplitStringVector(std::string str, std::string delimiter)
|
||||
//-------------------------------------------------------------------------
|
||||
// trim whitespaces
|
||||
//-------------------------------------------------------------------------
|
||||
std::string trim(std::string const& source, char const* delims)
|
||||
std::string trim(std::string const& source, char const* delims)
|
||||
{
|
||||
std::string result(source);
|
||||
std::string::size_type index = result.find_last_not_of(delims);
|
||||
@@ -180,6 +180,19 @@ std::string trim(std::string const& source, char const* delims)
|
||||
return result;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// replace all occurrences find_what
|
||||
//-------------------------------------------------------------------------
|
||||
void replace(std::string &str, const std::string &find_what, const std::string &replace_with)
|
||||
{
|
||||
std::string::size_type pos=0;
|
||||
while((pos=str.find(find_what, pos))!=std::string::npos)
|
||||
{
|
||||
str.erase(pos, find_what.length());
|
||||
str.insert(pos, replace_with);
|
||||
pos+=replace_with.length();
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// equal-function for case insensitive compare
|
||||
//-------------------------------------------------------------------------
|
||||
bool nocase_compare (char c1, char c2)
|
||||
@@ -228,7 +241,7 @@ std::string decodeString(std::string encodedString)
|
||||
std::string encodeString(std::string decodedString)
|
||||
{
|
||||
unsigned int len = sizeof(char) * decodedString.length()*5 + 1;
|
||||
std::string result( len, '\0' );
|
||||
std::string result( len, '\0' );
|
||||
char *newString = (char *)result.c_str();
|
||||
char *dstring = (char *)decodedString.c_str();
|
||||
char one_char;
|
||||
@@ -236,9 +249,9 @@ std::string encodeString(std::string decodedString)
|
||||
{
|
||||
while((one_char = *dstring++)) /* use the null character as a loop terminator */
|
||||
{
|
||||
if(isalnum(one_char))
|
||||
if(isalnum(one_char))
|
||||
*newString++ = one_char;
|
||||
else
|
||||
else
|
||||
newString += sprintf(newString, "&#%d;", (unsigned char) one_char);
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,7 @@ std::string string_tolower(std::string str);
|
||||
// String Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string trim(std::string const& source, char const* delims = " \t\r\n");
|
||||
void replace(std::string &str, const std::string &find_what, const std::string &replace_with);
|
||||
std::string string_printf(const char *fmt, ...);
|
||||
bool ySplitString(std::string str, std::string delimiter, std::string& left, std::string& right);
|
||||
bool ySplitStringExact(std::string str, std::string delimiter, std::string& left, std::string& right);
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <strings.h>
|
||||
|
||||
// yhttpd
|
||||
#include "yhook.h"
|
||||
@@ -18,7 +19,7 @@
|
||||
THookList CyhookHandler::HookList;
|
||||
|
||||
//=============================================================================
|
||||
// Hook Handling
|
||||
// Hook Handling
|
||||
//=============================================================================
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hook Dispatcher for Session Hooks
|
||||
@@ -65,8 +66,8 @@ THandleStatus CyhookHandler::Hooks_PrepareResponse()
|
||||
log_level_printf(8,"PrepareResponse Hook-List Result:\n%s\n", yresult.c_str());
|
||||
status = _status;
|
||||
return _status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hook Dispatcher for Server based Hooks
|
||||
// Execute every Hook in HookList until State change != HANDLED_NONE and
|
||||
@@ -88,7 +89,7 @@ THandleStatus CyhookHandler::Hooks_ReadConfig(CConfigFile *Config, CStringList &
|
||||
}
|
||||
log_level_printf(4,"ReadConfig Hook-List End\n");
|
||||
return _status;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hook Dispatcher for EndConnection
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -156,7 +157,7 @@ THandleStatus CyhookHandler::Hooks_UploadReady(const std::string& Filename)
|
||||
//=============================================================================
|
||||
// Output helpers
|
||||
//=============================================================================
|
||||
void CyhookHandler::session_init(CStringList _ParamList, CStringList _UrlData, CStringList _HeaderList,
|
||||
void CyhookHandler::session_init(CStringList _ParamList, CStringList _UrlData, CStringList _HeaderList,
|
||||
CStringList& _ConfigList, THttp_Method _Method, bool _keep_alive)
|
||||
{
|
||||
ParamList = _ParamList;
|
||||
@@ -210,7 +211,7 @@ void CyhookHandler::session_init(CStringList _ParamList, CStringList _UrlData, C
|
||||
// | Server ; implemented
|
||||
// | Vary ; not implemented
|
||||
// | WWW-Authenticate ; implemented (by mod_auth and SendHeader)
|
||||
//
|
||||
//
|
||||
// entity-header = Allow ; not implemented
|
||||
// | Content-Encoding ; not implemented
|
||||
// | Content-Language ; not implemented
|
||||
@@ -223,12 +224,12 @@ void CyhookHandler::session_init(CStringList _ParamList, CStringList _UrlData, C
|
||||
// | Last-Modified ; implemented for static files
|
||||
// | extension-header
|
||||
//
|
||||
// extension-header = message-header
|
||||
// extension-header = message-header
|
||||
//=============================================================================
|
||||
std::string CyhookHandler::BuildHeader(bool cache)
|
||||
{
|
||||
std::string result="";
|
||||
|
||||
|
||||
const char *responseString = "";
|
||||
const char *infoString = 0;
|
||||
|
||||
@@ -256,7 +257,7 @@ std::string CyhookHandler::BuildHeader(bool cache)
|
||||
// Status HTTP_*_TEMPORARILY (redirection)
|
||||
result += string_printf("Location: %s\r\n",NewURL.c_str());
|
||||
// NO break HERE !!!
|
||||
|
||||
|
||||
default:
|
||||
time_t timer = time(0);
|
||||
char timeStr[80];
|
||||
@@ -285,26 +286,29 @@ std::string CyhookHandler::BuildHeader(bool cache)
|
||||
#else
|
||||
result += "Connection: close\r\n";
|
||||
#endif
|
||||
// gzipped ?
|
||||
if(UrlData["fileext"] == "gz")
|
||||
result += "Content-Encoding: gzip\r\n";
|
||||
// content-len, last-modified
|
||||
if(httpStatus == HTTP_NOT_MODIFIED ||httpStatus == HTTP_NOT_FOUND)
|
||||
result += "Content-Length: 0\r\n";
|
||||
else if(GetContentLength() >0)
|
||||
{
|
||||
{
|
||||
time_t mod_time = time(NULL);
|
||||
if(LastModified != (time_t)-1)
|
||||
mod_time = LastModified;
|
||||
|
||||
|
||||
strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&mod_time));
|
||||
result += string_printf("Last-Modified: %s\r\nContent-Length: %ld\r\n", timeStr, GetContentLength());
|
||||
}
|
||||
}
|
||||
result += "\r\n"; // End of Header
|
||||
break;
|
||||
}
|
||||
|
||||
// Body
|
||||
if (Method != M_HEAD)
|
||||
switch (httpStatus)
|
||||
{
|
||||
switch (httpStatus)
|
||||
{
|
||||
case HTTP_OK:
|
||||
case HTTP_NOT_MODIFIED:
|
||||
case HTTP_CONTINUE:
|
||||
@@ -317,13 +321,13 @@ std::string CyhookHandler::BuildHeader(bool cache)
|
||||
case HTTP_MOVED_TEMPORARILY:
|
||||
case HTTP_MOVED_PERMANENTLY:
|
||||
result += "<html><head><title>Object moved</title></head><body>";
|
||||
result += string_printf("302 : Object moved.<br/>If you dont get redirected click <a href=\"%s\">here</a></body></html>\n",NewURL.c_str());
|
||||
break;
|
||||
result += string_printf("302 : Object moved.<br/>If you dont get redirected click <a href=\"%s\">here</a></body></html>\n",NewURL.c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
// Error pages
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -94,13 +94,13 @@ public:
|
||||
virtual std::string getHookVersion(void) {return std::string("0.0.0");}
|
||||
virtual std::string getHookName(void) {return std::string("Abstract Hook Class");}
|
||||
// CWebserverConnection based hooks
|
||||
virtual THandleStatus Hook_PrepareResponse(CyhookHandler */*hh*/){return HANDLED_NONE;};
|
||||
virtual THandleStatus Hook_SendResponse(CyhookHandler */*hh*/){return HANDLED_NONE;};
|
||||
virtual THandleStatus Hook_EndConnection(CyhookHandler */*hh*/){return HANDLED_NONE;}
|
||||
virtual THandleStatus Hook_UploadSetFilename(CyhookHandler */*hh*/, std::string &/*Filename*/){return HANDLED_NONE;}
|
||||
virtual THandleStatus Hook_UploadReady(CyhookHandler */*hh*/, std::string /*Filename*/){return HANDLED_NONE;}
|
||||
virtual THandleStatus Hook_PrepareResponse(CyhookHandler *){return HANDLED_NONE;};
|
||||
virtual THandleStatus Hook_SendResponse(CyhookHandler *){return HANDLED_NONE;};
|
||||
virtual THandleStatus Hook_EndConnection(CyhookHandler *){return HANDLED_NONE;}
|
||||
virtual THandleStatus Hook_UploadSetFilename(CyhookHandler *, std::string &){return HANDLED_NONE;}
|
||||
virtual THandleStatus Hook_UploadReady(CyhookHandler *, std::string){return HANDLED_NONE;}
|
||||
// Cyhttpd based hooks
|
||||
virtual THandleStatus Hook_ReadConfig(CConfigFile */*Config*/, CStringList &/*ConfigList*/){return HANDLED_NONE;};
|
||||
virtual THandleStatus Hook_ReadConfig(CConfigFile *, CStringList &){return HANDLED_NONE;};
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
92
src/nhttpd/yhttpd_core/ylanguage.cpp
Normal file
92
src/nhttpd/yhttpd_core/ylanguage.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
//=============================================================================
|
||||
// YHTTPD
|
||||
// Language
|
||||
//=============================================================================
|
||||
|
||||
// c
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
// yhttpd
|
||||
#include "yconfig.h"
|
||||
#include "yhttpd.h"
|
||||
#include "ytypes_globals.h"
|
||||
#include "ylanguage.h"
|
||||
#include "yconnection.h"
|
||||
//=============================================================================
|
||||
// Instance Handling - like Singelton Pattern
|
||||
//=============================================================================
|
||||
//-----------------------------------------------------------------------------
|
||||
// Init as Singelton
|
||||
//-----------------------------------------------------------------------------
|
||||
CLanguage* CLanguage::instance = NULL;
|
||||
CConfigFile* CLanguage::DefaultLanguage = NULL;
|
||||
CConfigFile* CLanguage::ConfigLanguage = NULL;
|
||||
std::string CLanguage::language = "";
|
||||
std::string CLanguage::language_dir = "";
|
||||
//-----------------------------------------------------------------------------
|
||||
// There is only one Instance
|
||||
//-----------------------------------------------------------------------------
|
||||
CLanguage *CLanguage::getInstance(void){
|
||||
if (!instance)
|
||||
instance = new CLanguage();
|
||||
return instance;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CLanguage::deleteInstance(void){
|
||||
if (instance)
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CLanguage::CLanguage(void)
|
||||
{
|
||||
DefaultLanguage = new CConfigFile(',');
|
||||
ConfigLanguage = new CConfigFile(',');
|
||||
language = "";
|
||||
language_dir =getLanguageDir();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CLanguage::~CLanguage(void)
|
||||
{
|
||||
delete DefaultLanguage;
|
||||
delete ConfigLanguage;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CLanguage::setLanguage(std::string _language){
|
||||
language=_language;
|
||||
ConfigLanguage->loadConfig(language_dir + "/" + _language);
|
||||
DefaultLanguage->loadConfig(language_dir + "/" + HTTPD_DEFAULT_LANGUAGE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// return translation for "id" if not found use default language
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string CLanguage::getTranslation(std::string id){
|
||||
std::string trans=ConfigLanguage->getString(id,"");
|
||||
if(trans=="")
|
||||
trans=DefaultLanguage->getString(id,"");
|
||||
return trans;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Find language directory
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string CLanguage::getLanguageDir(void){
|
||||
std::string tmpfilename = "/"+Cyhttpd::ConfigList["Language.directory"],dir="";
|
||||
|
||||
if( access(std::string(Cyhttpd::ConfigList["PublicDocumentRoot"] + tmpfilename).c_str(),4) == 0)
|
||||
dir = Cyhttpd::ConfigList["PublicDocumentRoot"] + tmpfilename;
|
||||
else if(access(std::string(Cyhttpd::ConfigList["PrivatDocumentRoot"] + tmpfilename).c_str(),4) == 0)
|
||||
dir = Cyhttpd::ConfigList["PrivatDocumentRoot"] + tmpfilename;
|
||||
return dir;
|
||||
}
|
||||
|
44
src/nhttpd/yhttpd_core/ylanguage.h
Normal file
44
src/nhttpd/yhttpd_core/ylanguage.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//=============================================================================
|
||||
// YHTTPD
|
||||
// Language
|
||||
//=============================================================================
|
||||
#ifndef __yhttpd_language_h__
|
||||
#define __yhttpd_language_h__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <configfile.h>
|
||||
// yhttpd
|
||||
#include "yconfig.h"
|
||||
#include "ytypes_globals.h"
|
||||
#include "ywebserver.h"
|
||||
|
||||
// forward declaration
|
||||
class CWebserverConnection;
|
||||
|
||||
class CLanguage
|
||||
{
|
||||
protected:
|
||||
static CLanguage *instance;
|
||||
CLanguage(void);
|
||||
~CLanguage(void);
|
||||
|
||||
static CConfigFile *DefaultLanguage;
|
||||
static CConfigFile *ConfigLanguage;
|
||||
|
||||
public:
|
||||
// Instance Handling
|
||||
static CLanguage *getInstance(void);
|
||||
static void deleteInstance(void);
|
||||
|
||||
// Language
|
||||
static std::string language;
|
||||
static std::string language_dir;
|
||||
|
||||
void setLanguage(std::string _language);
|
||||
std::string getLanguage(void) {return language;};
|
||||
std::string getLanguageDir(void);
|
||||
|
||||
std::string getTranslation(std::string id);
|
||||
};
|
||||
|
||||
#endif /* __yttpd_language_h__ */
|
@@ -81,14 +81,15 @@ void CLogging::printf ( const char *fmt, ... )
|
||||
|
||||
va_list arglist;
|
||||
va_start( arglist, fmt );
|
||||
// if(arglist)
|
||||
if(arglist)
|
||||
vsnprintf( buffer, bufferlen, fmt, arglist );
|
||||
va_end(arglist);
|
||||
|
||||
pthread_mutex_lock( &Log_mutex );
|
||||
::printf(buffer);
|
||||
if(LogToFile)
|
||||
usleep(0); //FIXME Logging to File
|
||||
if(LogToFile) {
|
||||
; //FIXME Logging to File
|
||||
}
|
||||
pthread_mutex_unlock( &Log_mutex );
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,7 @@
|
||||
// c++
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <errno.h>
|
||||
// system
|
||||
@@ -40,7 +40,7 @@ CWebserverRequest::CWebserverRequest(CWebserver *pWebserver)
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Parsing Request
|
||||
// Parsing Request
|
||||
//=============================================================================
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main Request Parsing
|
||||
@@ -80,14 +80,14 @@ bool CWebserverRequest::HandleRequest(void)
|
||||
if(Connection->Method == M_GET || Connection->Method == M_HEAD)
|
||||
{
|
||||
std::string tmp_line;
|
||||
//read header (speed up: read rest of request in blockmode)
|
||||
//read header (speed up: read rest of request in blockmode)
|
||||
tmp_line = Connection->sock->ReceiveBlock();
|
||||
if(!Connection->sock->isValid)
|
||||
{
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(tmp_line == "")
|
||||
{
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
@@ -97,12 +97,12 @@ bool CWebserverRequest::HandleRequest(void)
|
||||
}
|
||||
// Other Methods
|
||||
if(Connection->Method == M_DELETE || Connection->Method == M_PUT || Connection->Method == M_TRACE)
|
||||
{
|
||||
{
|
||||
//todo: implement
|
||||
aprintf("HTTP Method not implemented :%d\n",Connection->Method);
|
||||
Connection->Response.SendError(HTTP_NOT_IMPLEMENTED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// handle POST (read header & body)
|
||||
if(Connection->Method == M_POST)
|
||||
{
|
||||
@@ -118,7 +118,7 @@ bool CWebserverRequest::HandleRequest(void)
|
||||
// Parse the start-line
|
||||
// from RFC2616 / 5.1 Request-Line (start-line):
|
||||
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF (SP=Space)
|
||||
//
|
||||
//
|
||||
// Determine Reqest-Method, URL, HTTP-Version and Split Parameters
|
||||
// Split URL into path, filename, fileext .. UrlData[]
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -161,7 +161,7 @@ bool CWebserverRequest::ParseStartLine(std::string start_line)
|
||||
// attribute = token
|
||||
// value = token | quoted-string
|
||||
//
|
||||
// If parameter attribute is multiple times given, the values are stored like this:
|
||||
// If parameter attribute is multiple times given, the values are stored like this:
|
||||
// <attribute>=<value1>,<value2>,..,<value n>
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWebserverRequest::ParseParams(std::string param_string)
|
||||
@@ -175,7 +175,7 @@ bool CWebserverRequest::ParseParams(std::string param_string)
|
||||
ende = true;
|
||||
if(ySplitStringExact(param,"=",name,value))
|
||||
{
|
||||
value = trim(value);
|
||||
value = trim(decodeString(value));
|
||||
if(ParameterList[name].empty())
|
||||
ParameterList[name] = value;
|
||||
else
|
||||
@@ -228,7 +228,7 @@ bool CWebserverRequest::ParseHeader(std::string header)
|
||||
void CWebserverRequest::analyzeURL(std::string url)
|
||||
{
|
||||
ParameterList.clear();
|
||||
// URI decode
|
||||
// URI decode
|
||||
url = decodeString(url);
|
||||
url = trim(url, "\r\n"); // non-HTTP-Standard: allow \r or \n in URL. Delete it.
|
||||
UrlData["fullurl"] = url;
|
||||
@@ -237,7 +237,7 @@ void CWebserverRequest::analyzeURL(std::string url)
|
||||
ParseParams(UrlData["paramstring"]); // split params to ParameterList
|
||||
else // No Params
|
||||
UrlData["url"] = url;
|
||||
|
||||
|
||||
if(!ySplitStringLast(UrlData["url"],"/",UrlData["path"],UrlData["filename"]))
|
||||
{
|
||||
UrlData["path"] = "/"; // Set "/" if not contained
|
||||
@@ -258,7 +258,7 @@ void CWebserverRequest::analyzeURL(std::string url)
|
||||
bool CWebserverRequest::HandlePost()
|
||||
{
|
||||
//read header: line by line
|
||||
std::string raw_header, tmp_line;
|
||||
std::string raw_header, tmp_line;
|
||||
do
|
||||
{
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
@@ -306,11 +306,13 @@ bool CWebserverRequest::HandlePost()
|
||||
std::string post_header;
|
||||
// get message-body
|
||||
post_header = Connection->sock->ReceiveBlock();
|
||||
if(post_header.length() < content_len)
|
||||
while(post_header.length() < content_len)
|
||||
{
|
||||
aprintf("POST form less data then expected\n");
|
||||
post_header += Connection->sock->ReceiveBlock();
|
||||
/* aprintf("POST form less data then expected\n");
|
||||
Connection->Response.SendError(HTTP_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
// parse the params in post_header (message-body) an add them to ParameterList
|
||||
ParseParams(post_header);
|
||||
@@ -320,51 +322,51 @@ bool CWebserverRequest::HandlePost()
|
||||
//-----------------------------------------------------------------------------
|
||||
// POST multipart ! FILE UPLOAD!
|
||||
//
|
||||
// No 'Content-type: multipart/mixed' now supported
|
||||
// No 'Content-type: multipart/mixed' now supported
|
||||
// designed for recursion for different boundaries.
|
||||
//
|
||||
// from RFC 1867:
|
||||
// 2. HTML forms with file submission
|
||||
//
|
||||
//
|
||||
// The current HTML specification defines eight possible values for the
|
||||
// attribute TYPE of an INPUT element: CHECKBOX, HIDDEN, IMAGE,
|
||||
// PASSWORD, RADIO, RESET, SUBMIT, TEXT.
|
||||
//
|
||||
//
|
||||
// In addition, it defines the default ENCTYPE attribute of the FORM
|
||||
// element using the POST METHOD to have the default value
|
||||
// "application/x-www-form-urlencoded"
|
||||
//
|
||||
// 6. Examples
|
||||
//
|
||||
//
|
||||
// Suppose the server supplies the following HTML:
|
||||
//
|
||||
//
|
||||
// <FORM ACTION="http://server.dom/cgi/handle"
|
||||
// ENCTYPE="multipart/form-data"
|
||||
// METHOD=POST>
|
||||
// What is your name? <INPUT TYPE=TEXT NAME=submitter>
|
||||
// What files are you sending? <INPUT TYPE=FILE NAME=pics>
|
||||
// </FORM>
|
||||
//
|
||||
//
|
||||
// and the user types "Joe Blow" in the name field, and selects a text
|
||||
// file "file1.txt" for the answer to 'What files are you sending?'
|
||||
//
|
||||
//
|
||||
// The client might send back the following data:
|
||||
//
|
||||
//
|
||||
// Content-type: multipart/form-data, boundary=AaB03x
|
||||
//
|
||||
//
|
||||
// --AaB03x
|
||||
// content-disposition: form-data; name="field1"
|
||||
//
|
||||
//
|
||||
// Joe Blow
|
||||
// --AaB03x
|
||||
// content-disposition: form-data; name="pics"; filename="file1.txt"
|
||||
// Content-Type: text/plain
|
||||
//
|
||||
//
|
||||
// ... contents of file1.txt ...
|
||||
// --AaB03x--
|
||||
//
|
||||
// 7. Registration of multipart/form-data
|
||||
//
|
||||
//
|
||||
// The media-type multipart/form-data follows the rules of all multipart
|
||||
// MIME data streams as outlined in RFC 1521. It is intended for use in
|
||||
// returning the data that comes about from filling out a form. In a
|
||||
@@ -372,7 +374,7 @@ bool CWebserverRequest::HandlePost()
|
||||
// are a series of fields to be supplied by the user who fills out the
|
||||
// form. Each field has a name. Within a given form, the names are
|
||||
// unique.
|
||||
//
|
||||
//
|
||||
// multipart/form-data contains a series of parts. Each part is expected
|
||||
// to contain a content-disposition header where the value is "form-
|
||||
// data" and a name attribute specifies the field name within the form,
|
||||
@@ -380,7 +382,7 @@ bool CWebserverRequest::HandlePost()
|
||||
// the field name corresponding to that field. Field names originally in
|
||||
// non-ASCII character sets may be encoded using the method outlined in
|
||||
// RFC 1522.
|
||||
//
|
||||
//
|
||||
// As with all multipart MIME types, each part has an optional Content-
|
||||
// Type which defaults to text/plain. If the contents of a file are
|
||||
// returned via filling out a form, then the file input is identified as
|
||||
@@ -388,11 +390,11 @@ bool CWebserverRequest::HandlePost()
|
||||
// multiple files are to be returned as the result of a single form
|
||||
// entry, they can be returned as multipart/mixed embedded within the
|
||||
// multipart/form-data.
|
||||
//
|
||||
//
|
||||
// Each part may be encoded and the "content-transfer-encoding" header
|
||||
// supplied if the value of that part does not conform to the default
|
||||
// encoding.
|
||||
//
|
||||
//
|
||||
// File inputs may also identify the file name. The file name may be
|
||||
// described using the 'filename' parameter of the "content-disposition"
|
||||
// header. This is not required, but is strongly recommended in any case
|
||||
@@ -417,7 +419,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
return 0;
|
||||
}
|
||||
log_level_printf(7,"<POST Boundary> Boundary START found\n");
|
||||
|
||||
|
||||
// read content-disposition: ...
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
content_len -= tmp_line.length();
|
||||
@@ -455,7 +457,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
return 0;
|
||||
}
|
||||
var_value = trim(var_value);
|
||||
ParameterList[var_name] = var_value;
|
||||
ParameterList[var_name] = var_value;
|
||||
log_level_printf(7,"<POST Boundary> filename found. name:(%s) value:(%s)\n", var_name.c_str(), var_value.c_str());
|
||||
|
||||
//read 'Content-Type: <mime>'
|
||||
@@ -468,7 +470,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
return 0;
|
||||
}
|
||||
var_value = trim(right);
|
||||
ParameterList[var_name+"_mime"] = var_value;
|
||||
ParameterList[var_name+"_mime"] = var_value;
|
||||
log_level_printf(7,"<POST Boundary> Content-Type found. name:(%s_mime) value:(%s)\n", var_name.c_str(), var_value.c_str());
|
||||
|
||||
|
||||
@@ -479,20 +481,20 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
{
|
||||
log_level_printf(7,"<POST Boundary> no empty line found. line:(%s)\n", tmp_line.c_str());
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
log_level_printf(7,"<POST Boundary> read file Start\n");
|
||||
|
||||
|
||||
std::string upload_filename;
|
||||
upload_filename = UPLOAD_TMP_FILE;
|
||||
// Hook for Filename naming
|
||||
Connection->HookHandler.Hooks_UploadSetFilename(upload_filename);
|
||||
// Set upload filename to ParameterList["<name>_upload_filename"]="<upload_filename>"
|
||||
ParameterList[var_name+"_upload_filename"] = upload_filename;
|
||||
ParameterList[var_name+"_upload_filename"] = upload_filename;
|
||||
|
||||
// open file for write
|
||||
int fd = open(upload_filename.c_str(), O_WRONLY|O_CREAT|O_TRUNC);
|
||||
if (fd<0)
|
||||
if (fd<=0)
|
||||
{
|
||||
aprintf("cannot open file %s: ", upload_filename.c_str());
|
||||
dperror("");
|
||||
@@ -500,7 +502,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
}
|
||||
|
||||
// ASSUMPTION: the complete multipart has no more then SEARCH_BOUNDARY_LEN bytes after the file.
|
||||
// It only works, if no multipart/mixed is used (e.g. in file attachments). Not nessesary in embedded systems.
|
||||
// It only works, if no multipart/mixed is used (e.g. in file attachments). Not nessesary in embedded systems.
|
||||
// To speed up uploading, read content_len - SEARCH_BOUNDARY_LEN bytes in blockmode.
|
||||
// To save memory, write them direct into the file.
|
||||
#define SEARCH_BOUNDARY_LEN 2*RECEIVE_BLOCK_LEN // >= RECEIVE_BLOCK_LEN in ySocket
|
||||
@@ -510,19 +512,19 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
_readbytes = Connection->sock->ReceiveFileGivenLength(fd, content_len - SEARCH_BOUNDARY_LEN);
|
||||
content_len -= _readbytes;
|
||||
log_level_printf(8,"<POST Boundary> read block (already:%d all:%d)\n", _readbytes, content_len);
|
||||
}
|
||||
}
|
||||
|
||||
// read rest of file and check for boundary end
|
||||
_readbytes = 0;
|
||||
bool is_CRLF = false;
|
||||
|
||||
|
||||
bool found_end_boundary = false;
|
||||
do
|
||||
{
|
||||
// read line by line
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
_readbytes += tmp_line.length();
|
||||
|
||||
|
||||
// is this line a boundary?
|
||||
if(tmp_line.find(boundary) != std::string::npos)
|
||||
{
|
||||
@@ -533,21 +535,21 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
else // no Boundary: write CRFL if found in last line
|
||||
{
|
||||
if(is_CRLF)
|
||||
if ((unsigned int)write(fd, "\r\n", 2) != 2)
|
||||
{
|
||||
if ((unsigned int)write(fd, "\r\n", 2) != 2)
|
||||
{
|
||||
perror("write file failed\n");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// normal line: write it to file
|
||||
// CRLF at end? Maybe CRLF before boundary. Can not decide yet
|
||||
is_CRLF = (tmp_line.length()>=2 && tmp_line[tmp_line.length()-2]=='\r' && tmp_line[tmp_line.length()-1]=='\n');
|
||||
int write_len = is_CRLF ? tmp_line.length()-2 : tmp_line.length();
|
||||
if (write(fd, tmp_line.c_str(), write_len) != write_len)
|
||||
{
|
||||
if (write(fd, tmp_line.c_str(), write_len) != write_len)
|
||||
{
|
||||
perror("write file failed\n");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
log_level_printf(2,"<POST Boundary> read file (already:%d all:%d)\n", _readbytes, content_len);
|
||||
}
|
||||
while((_readbytes < content_len) && (tmp_line.length() != 0));
|
||||
@@ -556,7 +558,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
log_level_printf(2,"<POST Boundary> read file End\n");
|
||||
if(found_end_boundary) // upload ok?
|
||||
{
|
||||
|
||||
|
||||
Connection->HookHandler.Hooks_UploadReady(upload_filename);
|
||||
return 0;
|
||||
}
|
||||
@@ -577,7 +579,7 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
log_level_printf(7,"<POST Boundary> no var_name END found. line:(%s)\n", tmp_line.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//read empty line as separator
|
||||
tmp_line = Connection->sock->ReceiveLine();
|
||||
content_len -= tmp_line.length();
|
||||
@@ -585,15 +587,15 @@ unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigne
|
||||
{
|
||||
log_level_printf(7,"<POST Boundary> no empty line found. line:(%s)\n", tmp_line.c_str());
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
//read var_value line
|
||||
// ASSUMPTION!!!! Only one Line for value, new line is a boundary again
|
||||
// ATTENTION!! var_name must not be unique. So Parameters are store by number too.
|
||||
var_value = Connection->sock->ReceiveLine();
|
||||
content_len -= tmp_line.length();
|
||||
var_value = trim(var_value);
|
||||
ParameterList[var_name] = var_value;
|
||||
var_value = trim(decodeString(var_value));
|
||||
ParameterList[var_name] = var_value;
|
||||
log_level_printf(7,"<POST Boundary> Parameter found. name:(%s) value:(%s)\n", var_name.c_str(), var_value.c_str());
|
||||
}
|
||||
}
|
||||
|
@@ -73,7 +73,7 @@ public:
|
||||
// send & receive
|
||||
int SendFile(int filed); // Send a File
|
||||
std::string ReceiveBlock(); // receive a Block. Look at length
|
||||
unsigned int ReceiveFileGivenLength(int filed, unsigned int _length); // Receive File of given length
|
||||
unsigned int ReceiveFileGivenLength(int filed, unsigned int _length); // Receive File of given length
|
||||
std::string ReceiveLine(); // receive until "\n"
|
||||
|
||||
protected:
|
||||
|
@@ -5,7 +5,6 @@
|
||||
// c++
|
||||
#include <cerrno>
|
||||
#include <csignal>
|
||||
#include <cstdio>
|
||||
|
||||
// system
|
||||
#include <arpa/inet.h>
|
||||
@@ -49,8 +48,10 @@ CWebserver::CWebserver()
|
||||
FD_ZERO(&read_fds);
|
||||
fdmax = 0;
|
||||
open_connections = 0;
|
||||
//pthread_attr_init(&attr);
|
||||
//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
#ifdef Y_CONFIG_BUILD_AS_DAEMON
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
#endif
|
||||
port=80;
|
||||
|
||||
|
||||
@@ -128,7 +129,7 @@ bool CWebserver::run(void)
|
||||
|
||||
// initialize values for select
|
||||
int listener = listenSocket.get_socket();// Open Listener
|
||||
struct timeval tv; // timeout struct
|
||||
struct timeval tv; // timeout struct
|
||||
FD_SET(listener, &master); // add the listener to the master set
|
||||
fdmax = listener; // init max fd
|
||||
fcntl(listener, F_SETFD , O_NONBLOCK); // listener master socket non-blocking
|
||||
@@ -157,8 +158,8 @@ bool CWebserver::run(void)
|
||||
// Socket Error?
|
||||
if(fd == -1 && errno != EINTR)
|
||||
{
|
||||
perror("select");
|
||||
return false;
|
||||
perror("select");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Socket Timeout?
|
||||
@@ -419,11 +420,14 @@ bool CWebserver::handle_connection(CySocket *newSock)
|
||||
newConn->ySock = newSock;
|
||||
newConn->ySock->handling = true;
|
||||
newConn->WebserverBackref = this;
|
||||
//newConn->is_treaded = is_threading;
|
||||
#ifdef Y_CONFIG_BUILD_AS_DAEMON
|
||||
newConn->is_treaded = is_threading;
|
||||
#else
|
||||
newConn->is_treaded = false;
|
||||
|
||||
#endif
|
||||
int index = -1;
|
||||
if(0) /*if(is_threading) FIXME not work */
|
||||
#ifdef Y_CONFIG_BUILD_AS_DAEMON
|
||||
if(is_threading)
|
||||
{
|
||||
pthread_mutex_lock( &mutex );
|
||||
// look for free Thread slot
|
||||
@@ -449,6 +453,7 @@ bool CWebserver::handle_connection(CySocket *newSock)
|
||||
dperror("Could not create Connection-Thread\n");
|
||||
}
|
||||
else // non threaded
|
||||
#endif
|
||||
WebThread((void *)newConn);
|
||||
return ((index != -1) || !is_threading);
|
||||
}
|
||||
|
Reference in New Issue
Block a user