Patch by Ma Jie: Basically - make Poorman (the webserver) work. Libhttpd from
Jef Poskanzer is providing the backend, but had to be adopted in some ways. Other issues in Poorman have been resolved. When testing the license integration, I stumbled over some AboutSystem bugs, basically clicking licenses would not open them. I fixed those in this patch, sorry for mixing that up. Note to Ma Jie: I changed the encoding of the libhttpd files to UTF-8! (This affects only the (C) glyph.) Thanks a lot for your awesome work on Poorman, it's really appreciated! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29906 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
** Copyright © 1995,1998,1999,2000,2001 by Jef Poskanzer <[email protected]>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
*/
|
||||
@@ -565,7 +565,7 @@ AboutView::AboutView(const BRect &rect)
|
||||
_GetLicensesPath(licensesPath);
|
||||
|
||||
BPath mitPath(licensesPath);
|
||||
mitPath.Append("MIT license");
|
||||
mitPath.Append("MIT");
|
||||
|
||||
font.SetSize(be_bold_font->Size() + 4);
|
||||
font.SetFace(B_BOLD_FACE);
|
||||
@@ -808,6 +808,13 @@ AboutView::AboutView(const BRect &rect)
|
||||
// "http://www.opensound.com");
|
||||
// BSD license
|
||||
|
||||
// libhttpd copyright (used as Poorman backend)
|
||||
AddCopyrightEntry("libhttpd",
|
||||
"Copyright " B_UTF8_COPYRIGHT "1995,1998,1999,2000,2001 by "
|
||||
"Jef Poskanzer. All rights reserved.",
|
||||
Licenses("LibHTTPd", NULL),
|
||||
"http://www.acme.com/software/thttpd/");
|
||||
|
||||
#ifdef __INTEL__
|
||||
// Udis86 copyrights
|
||||
AddCopyrightEntry("Udis86",
|
||||
@@ -1018,7 +1025,7 @@ AboutView::AddCopyrightEntry(const char *name, const char *text,
|
||||
for (int32 i = 0; i < licenses.CountLicenses(); i++) {
|
||||
const char* license = licenses.LicenseAt(i);
|
||||
BString licensePath(licensesPath.Path());
|
||||
licensePath += license;
|
||||
licensePath << '/' << license;
|
||||
|
||||
if (i > 0)
|
||||
fCreditsView->Insert(", ");
|
||||
|
||||
@@ -1,19 +1,53 @@
|
||||
SubDir HAIKU_TOP src apps poorman ;
|
||||
|
||||
SubDirCcFlags [ FDefines HAVE__PROGNAME=1 HAVE_FCNTL_H=1 HAVE_GRP_H=1 HAVE_MEMORY_H=1 HAVE_POLL_H=1 HAVE_SYS_POLL_H=1 TIME_WITH_SYS_TIME=1 HAVE_DIRENT_H=1 HAVE_STRERROR=1 HAVE_WAITPID=1 HAVE_VSNPRINTF=1 HAVE_SETSID=1 HAVE_SIGSET=1 HAVE_ATOLL=1 HAVE_UNISTD_H=1 HAVE_GETPAGESIZE=1 HAVE_MMAP=1 HAVE_SELECT=1 HAVE_POLL=1 HAVE_TM_GMTOFF=1 HAVE_SOCKLENT=1 HAVE_INT64T=1 ] ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps poorman libhttpd ] ;
|
||||
|
||||
rule THTTPMakeHeader header : text
|
||||
{
|
||||
header = [ FGristFiles $(header) ] ;
|
||||
text = [ FGristFiles $(text) ] ;
|
||||
|
||||
SEARCH on $(text) = $(SEARCH_SOURCE) ;
|
||||
MakeLocateArch $(header) ;
|
||||
|
||||
Depends $(header) : $(text) ;
|
||||
LocalClean clean : $(header) ;
|
||||
|
||||
THTTPMakeHeader1 $(header) : $(text) ;
|
||||
}
|
||||
|
||||
actions THTTPMakeHeader1
|
||||
{
|
||||
rm -f $(1)
|
||||
sed < $(2) > $(1) \
|
||||
-e 's/#.*//' -e 's/[ ]*$//' -e '/^$/d' \
|
||||
-e 's/[ ][ ]*/", 0, "/' -e 's/^/{ "/' -e 's/$/", 0 },/'
|
||||
}
|
||||
|
||||
THTTPMakeHeader mime_encodings.h : mime_encodings.txt ;
|
||||
THTTPMakeHeader mime_types.h : mime_types.txt ;
|
||||
|
||||
AddResources PoorMan : PoorMan.rdef ;
|
||||
|
||||
Application PoorMan : PoorMan.cpp
|
||||
PoorManMainView.cpp
|
||||
PoorManWindow.cpp
|
||||
PoorManView.cpp
|
||||
PoorManAdvancedView.cpp
|
||||
StatusSlider.cpp
|
||||
PoorManServer.cpp
|
||||
PoorManSiteView.cpp
|
||||
PoorManLogger.cpp
|
||||
PoorManLoggingView.cpp
|
||||
PoorManPreferencesWindow.cpp
|
||||
PoorManApplication.cpp
|
||||
constants.cpp
|
||||
: be tracker $(TARGET_LIBSTDC++)
|
||||
|
||||
# libhttpd
|
||||
libhttpd.c
|
||||
match.c
|
||||
tdate_parse.c
|
||||
|
||||
: be network tracker $(TARGET_LIBSTDC++)
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -18,4 +18,4 @@ main()
|
||||
//printf("be_app: %p", be_app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,30 +5,35 @@
|
||||
* Version: 0.1
|
||||
*/
|
||||
|
||||
#include <Application.h>
|
||||
#include <Alert.h>
|
||||
#include <Directory.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "PoorManView.h"
|
||||
#include "PoorManApplication.h"
|
||||
|
||||
#include "PoorManWindow.h"
|
||||
|
||||
PoorManApplication::PoorManApplication()
|
||||
: BApplication(STR_APP_SIG),
|
||||
status(false), hits(0)
|
||||
mainWindow(NULL)
|
||||
{
|
||||
// -------------------------------------------
|
||||
// Main Window
|
||||
//PoorManView * mainView;
|
||||
BRect mainRect;
|
||||
|
||||
mainRect.Set(30.0f, 30.0f, 355.0f, 185.0f);
|
||||
BRect mainRect(82.0f, 30.0f, 400.0f, 350.0f);
|
||||
mainWindow = new PoorManWindow(mainRect);
|
||||
mainWindow->Hide();
|
||||
mainWindow->Show();
|
||||
|
||||
//mainRect.OffsetTo(B_ORIGIN);
|
||||
//mainView = new PoorManView(mainRect, STR_APP_NAME);
|
||||
//mainView->SetViewColor(216,216,216,255);
|
||||
BDirectory webDir;
|
||||
if(mainWindow->ReadSettings() != B_OK){
|
||||
if(webDir.SetTo(STR_DEFAULT_WEB_DIRECTORY) != B_OK)
|
||||
mainWindow->DefaultSettings();
|
||||
} else {
|
||||
if(webDir.SetTo(mainWindow->WebDir()) != B_OK)
|
||||
mainWindow->DefaultSettings();
|
||||
}
|
||||
|
||||
mainWindow->Show();
|
||||
mainWindow->StartServer();
|
||||
mainWindow->SetDirLabel(mainWindow->WebDir());
|
||||
mainWindow->Show();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
#include "PoorManWindow.h"
|
||||
#include "PoorManPreferencesWindow.h"
|
||||
class PoorManWindow;
|
||||
//#include "PoorManPreferencesWindow.h"
|
||||
|
||||
|
||||
class PoorManApplication: public BApplication
|
||||
@@ -23,13 +23,13 @@ public:
|
||||
PoorManWindow * GetPoorManWindow() { return mainWindow; }
|
||||
private:
|
||||
PoorManWindow * mainWindow;
|
||||
PoorManPreferencesWindow * prefWindow;
|
||||
//PoorManPreferencesWindow * prefWindow;
|
||||
|
||||
// --------------------------------------------
|
||||
// settings variables
|
||||
bool status;
|
||||
char directory[512];
|
||||
uint32 hits;
|
||||
//bool status;
|
||||
//char directory[512];
|
||||
//uint32 hits;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Author(s):
|
||||
* Ma Jie, china.majie at gmail
|
||||
*/
|
||||
|
||||
#include "PoorManLogger.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <Messenger.h>
|
||||
#include <Message.h>
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#include "PoorManApplication.h"
|
||||
#include "PoorManWindow.h"
|
||||
|
||||
void
|
||||
poorman_log(const char* msg, bool needTimeHeader,
|
||||
in_addr_t addr, rgb_color color)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
|
||||
PoorManWindow* window = static_cast<PoorManApplication*>(be_app)->GetPoorManWindow();
|
||||
|
||||
if(!window->LogConsoleFlag() && !window->LogFileFlag())
|
||||
return;
|
||||
|
||||
BMessenger messenger(window);
|
||||
BMessage message(MSG_LOG);
|
||||
|
||||
if(message.AddString("cstring", msg) != B_OK)
|
||||
return;
|
||||
if(needTimeHeader){
|
||||
if(message.AddData("time_t", B_TIME_TYPE, &now, sizeof(time_t)) != B_OK)
|
||||
return;
|
||||
}
|
||||
if(addr != INADDR_NONE)
|
||||
message.AddData("in_addr_t", B_ANY_TYPE, &addr, sizeof(in_addr_t));
|
||||
|
||||
if(color != BLACK)
|
||||
message.AddData("rgb_color", B_RGB_COLOR_TYPE, &color, sizeof(rgb_color));
|
||||
|
||||
messenger.SendMessage(&message, (BHandler*)NULL, 1000000);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Author(s):
|
||||
* Ma Jie, china.majie at gmail
|
||||
*/
|
||||
#ifndef POOR_MAN_LOG_H
|
||||
#define POOR_MAN_LOG_H
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "constants.h" //for rgb_color BLACK
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
void poorman_log(
|
||||
const char* msg,
|
||||
bool needTimeHeader = true,
|
||||
in_addr_t addr = INADDR_NONE,
|
||||
rgb_color color = BLACK
|
||||
);
|
||||
#else //c version is for libhttpd
|
||||
void poorman_log(
|
||||
const char* msg,
|
||||
bool needTimeHeader,
|
||||
in_addr_t addr,
|
||||
rgb_color color
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
#endif // POOR_MAN_LOG_H
|
||||
@@ -1,29 +0,0 @@
|
||||
/* PoorManMainView.cpp
|
||||
*
|
||||
* Philip Harrison
|
||||
* Started: 5/13/2004
|
||||
* Version: 0.1
|
||||
*/
|
||||
|
||||
|
||||
#include "PoorManMainView.h"
|
||||
|
||||
PoorManMainView::PoorManMainView(BRect rect, char *name)
|
||||
: BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PoorManMainView::AttachedToWindow()
|
||||
{
|
||||
SetPenSize(1);
|
||||
}
|
||||
|
||||
void
|
||||
PoorManMainView::Draw(BRect updateRect)
|
||||
{
|
||||
BRect tempRect;
|
||||
tempRect = updateRect;
|
||||
|
||||
StrokeRect(tempRect, B_SOLID_HIGH);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/* PoorManMainView.h
|
||||
*
|
||||
* Philip Harrison
|
||||
* Started: 5/13/2004
|
||||
* Version: 0.1
|
||||
*/
|
||||
|
||||
#ifndef POOR_MAN_MAIN_VIEW_H
|
||||
#define POOR_MAN_MAIN_VIEW_H
|
||||
|
||||
#include <View.h>
|
||||
|
||||
class PoorManMainView: public BView
|
||||
{
|
||||
public:
|
||||
PoorManMainView(BRect, char *name);
|
||||
virtual void AttachedToWindow();
|
||||
virtual void Draw(BRect updateRect);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -8,13 +8,13 @@
|
||||
#include <Window.h>
|
||||
#include <Box.h>
|
||||
#include <Directory.h>
|
||||
#include <iostream>
|
||||
#include <Debug.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "PoorManWindow.h"
|
||||
#include "PoorManApplication.h"
|
||||
#include "PoorManPreferencesWindow.h"
|
||||
|
||||
#include "PoorManServer.h"
|
||||
|
||||
PoorManPreferencesWindow::PoorManPreferencesWindow(BRect frame, char * name)
|
||||
: BWindow(frame, name, B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE),
|
||||
@@ -102,7 +102,7 @@ PoorManPreferencesWindow::PoorManPreferencesWindow(BRect frame, char * name)
|
||||
BMessenger messenger(this);
|
||||
BMessage message(MSG_FILE_PANEL_SELECT_WEB_DIR);
|
||||
webDirFilePanel = new BFilePanel(B_OPEN_PANEL, &messenger, NULL,
|
||||
B_DIRECTORY_NODE, false, &message);
|
||||
B_DIRECTORY_NODE, false, &message, NULL, true);
|
||||
|
||||
webDirFilePanel->SetPanelDirectory(new BDirectory("/boot/home/public_html"));
|
||||
webDirFilePanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select");
|
||||
@@ -120,39 +120,44 @@ PoorManPreferencesWindow::PoorManPreferencesWindow(BRect frame, char * name)
|
||||
|
||||
}
|
||||
|
||||
|
||||
PoorManPreferencesWindow::~PoorManPreferencesWindow()
|
||||
{
|
||||
delete logFilePanel;
|
||||
delete webDirFilePanel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PoorManPreferencesWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_PREF_BTN_DONE:
|
||||
PoorManWindow * win;
|
||||
PoorManServer* server;
|
||||
win = ((PoorManApplication *)be_app)->GetPoorManWindow();
|
||||
server = win->GetServer();
|
||||
|
||||
std::cout << "Pref Window: sendDir CheckBox: " << siteView->SendDirValue() << std::endl;
|
||||
PRINT(("Pref Window: sendDir CheckBox: %d\n", siteView->SendDirValue()));
|
||||
server->SetListDir(siteView->SendDirValue());
|
||||
win->SetDirListFlag(siteView->SendDirValue());
|
||||
std::cout << "Pref Window: indexFileName TextControl: " << siteView->IndexFileName() << std::endl;
|
||||
win->SetIndexFileName(siteView->IndexFileName());
|
||||
std::cout << "Pref Window: webDir: " << siteView->WebDir() << std::endl;
|
||||
win->SetWebDir(siteView->WebDir());
|
||||
win->SetDirLabel(siteView->WebDir());
|
||||
PRINT(("Pref Window: indexFileName TextControl: %s\n", siteView->IndexFileName()));
|
||||
if(server->SetIndexName(siteView->IndexFileName()) == B_OK)
|
||||
win->SetIndexFileName(siteView->IndexFileName());
|
||||
PRINT(("Pref Window: webDir: %s\n", siteView->WebDir()));
|
||||
if(server->SetWebDir(siteView->WebDir()) == B_OK){
|
||||
win->SetWebDir(siteView->WebDir());
|
||||
win->SetDirLabel(siteView->WebDir());
|
||||
}
|
||||
|
||||
std::cout << "Pref Window: logConsole CheckBox: " << loggingView->LogConsoleValue() << std::endl;
|
||||
PRINT(("Pref Window: logConsole CheckBox: %d\n", loggingView->LogConsoleValue()));
|
||||
win->SetLogConsoleFlag(loggingView->LogConsoleValue());
|
||||
std::cout << "Pref Window: logFile CheckBox: " << loggingView->LogFileValue() << std::endl;
|
||||
PRINT(("Pref Window: logFile CheckBox: %d\n", loggingView->LogFileValue()));
|
||||
win->SetLogFileFlag(loggingView->LogFileValue());
|
||||
std::cout << "Pref Window: logFileName: " << loggingView->LogFileName() << std::endl;
|
||||
PRINT(("Pref Window: logFileName: %s\n", loggingView->LogFileName()));
|
||||
win->SetLogPath(loggingView->LogFileName());
|
||||
|
||||
std::cout << "Pref Window: MaxConnections Slider: " << advancedView->MaxSimultaneousConnections() << std::endl;
|
||||
win->SetMaxConnections(advancedView->MaxSimultaneousConnections());
|
||||
PRINT(("Pref Window: MaxConnections Slider: %ld\n", advancedView->MaxSimultaneousConnections()));
|
||||
server->SetMaxConns(advancedView->MaxSimultaneousConnections());
|
||||
win->SetMaxConnections((int16)advancedView->MaxSimultaneousConnections());
|
||||
|
||||
|
||||
if (Lock())
|
||||
@@ -169,7 +174,7 @@ PoorManPreferencesWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
case MSG_FILE_PANEL_SELECT_WEB_DIR:
|
||||
// handle the open BMessage from the Select Web Directory File Panel
|
||||
std::cout << "Select Web Directory:\n" << std::endl;
|
||||
PRINT(("Select Web Directory:\n"));
|
||||
SelectWebDir(message);
|
||||
break;
|
||||
case MSG_PREF_LOG_BTN_CREATE_FILE:
|
||||
@@ -178,12 +183,12 @@ PoorManPreferencesWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
case MSG_FILE_PANEL_CREATE_LOG_FILE:
|
||||
// handle the save BMessage from the Create Log File Panel
|
||||
std::cout << "Create Log File:\n" << std::endl;
|
||||
PRINT(("Create Log File:\n"));
|
||||
CreateLogFile(message);
|
||||
break;
|
||||
case MSG_PREF_ADV_SLD_MAX_CONNECTION:
|
||||
max_connections = advancedView->MaxSimultaneousConnections();
|
||||
std::cout << "Max Connections: " << max_connections << std::endl;
|
||||
PRINT(("Max Connections: %ld\n", max_connections));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -212,8 +217,20 @@ PoorManPreferencesWindow::SelectWebDir(BMessage * message)
|
||||
// ;//return err;
|
||||
entry.GetPath(&path);
|
||||
|
||||
std::cout << "DIR: " << path.Path() << std::endl;
|
||||
PRINT(("DIR: %s\n", path.Path()));
|
||||
siteView->SetWebDir(path.Path());
|
||||
|
||||
bool temp;
|
||||
if(message->FindBool("Default Dialog", &temp) == B_OK){
|
||||
PoorManWindow* win = ((PoorManApplication *)be_app)->GetPoorManWindow();
|
||||
if(win->GetServer()->SetWebDir(siteView->WebDir()) == B_OK){
|
||||
win->SetWebDir(siteView->WebDir());
|
||||
win->SetDirLabel(siteView->WebDir());
|
||||
}
|
||||
win->StartServer();
|
||||
if(Lock())
|
||||
Quit();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -236,7 +253,7 @@ PoorManPreferencesWindow::CreateLogFile(BMessage * message)
|
||||
// ;//return err;
|
||||
entry.GetPath(&path);
|
||||
path.Append(name);
|
||||
std::cout << "Log File: " << path.Path() << std::endl;
|
||||
PRINT(("Log File: %s\n", path.Path()));
|
||||
|
||||
if (err == B_OK)
|
||||
{
|
||||
@@ -246,3 +263,15 @@ PoorManPreferencesWindow::CreateLogFile(BMessage * message)
|
||||
|
||||
// mark the checkbox
|
||||
}
|
||||
|
||||
/*A special version for "the default dialog", don't use it in MessageReceived()*/
|
||||
void
|
||||
PoorManPreferencesWindow::ShowWebDirFilePanel()
|
||||
{
|
||||
BMessage message(MSG_FILE_PANEL_SELECT_WEB_DIR);
|
||||
message.AddBool("Default Dialog", true);
|
||||
|
||||
webDirFilePanel->SetMessage(&message);
|
||||
if(!webDirFilePanel->IsShowing())
|
||||
webDirFilePanel->Show();
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
|
||||
virtual void MessageReceived(BMessage * message);
|
||||
|
||||
void ShowWebDirFilePanel() { if (!webDirFilePanel->IsShowing()) webDirFilePanel->Show(); }
|
||||
void ShowWebDirFilePanel();
|
||||
void SelectWebDir(BMessage * message);
|
||||
void CreateLogFile(BMessage * message);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright 2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Author(s):
|
||||
* Ma Jie, china.majie at gmail
|
||||
*/
|
||||
|
||||
#include "PoorManServer.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h> //for struct timeval
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <File.h>
|
||||
#include <Debug.h>
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
#include <StorageDefs.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "PoorManApplication.h"
|
||||
#include "PoorManLogger.h"
|
||||
#include "PoorManWindow.h"
|
||||
#include "libhttpd/libhttpd.h"
|
||||
|
||||
PoorManServer::PoorManServer(const char* webDir,
|
||||
int32 maxConns, bool listDir,const char* idxName)
|
||||
:fIsRunning(false),
|
||||
fMaxConns(maxConns),
|
||||
fIndexName(new char[strlen(idxName)+1]),
|
||||
fCurConns(0)
|
||||
{
|
||||
fHttpdServer = httpd_initialize(
|
||||
(char*)0,//hostname
|
||||
(httpd_sockaddr*)0,//sa4P
|
||||
(httpd_sockaddr*)0,//sa6P
|
||||
(unsigned short)80,//port
|
||||
(char*)0,//cgi pattern
|
||||
0,//cgi_limit
|
||||
"iso-8859-1",//charset
|
||||
"",//p3p
|
||||
-1,//max_age
|
||||
const_cast<char*>(webDir),//cwd
|
||||
1,//no_log
|
||||
(FILE*)0,//logfp
|
||||
0,//no_symlink_check
|
||||
0,//vhost
|
||||
0,//global_passwd
|
||||
(char*)0,//url_pattern
|
||||
(char*)0,//local_pattern
|
||||
0//no_empty_referers
|
||||
);
|
||||
|
||||
strcpy(fIndexName, idxName);
|
||||
|
||||
size_t cwdLen = strlen(fHttpdServer->cwd);
|
||||
if(fHttpdServer->cwd[cwdLen-1] == '/'){
|
||||
fHttpdServer->cwd[cwdLen-1] = '\0';
|
||||
}
|
||||
|
||||
fHttpdServer->do_list_dir = (listDir?1:0);
|
||||
fHttpdServer->index_name = fIndexName;
|
||||
|
||||
pthread_rwlock_init(&fWebDirLock, NULL);
|
||||
pthread_rwlock_init(&fIndexNameLock, NULL);
|
||||
}
|
||||
|
||||
PoorManServer::~PoorManServer()
|
||||
{
|
||||
Stop();
|
||||
httpd_terminate(fHttpdServer);
|
||||
delete[] fIndexName;
|
||||
pthread_rwlock_destroy(&fWebDirLock);
|
||||
pthread_rwlock_destroy(&fIndexNameLock);
|
||||
}
|
||||
|
||||
status_t PoorManServer::Run()
|
||||
{
|
||||
if(chdir(fHttpdServer->cwd) == -1){
|
||||
poorman_log("no web directory, can't start up.\n", false, INADDR_NONE, RED);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
httpd_sockaddr sa4;
|
||||
memset(&sa4,0,sizeof(httpd_sockaddr));
|
||||
sa4.sa_in.sin_family = AF_INET;
|
||||
sa4.sa_in.sin_port = htons(80);
|
||||
sa4.sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
fHttpdServer->listen4_fd = httpd_initialize_listen_socket(&sa4);
|
||||
if(fHttpdServer->listen4_fd == -1)
|
||||
return B_ERROR;
|
||||
|
||||
fListenerTid = spawn_thread(
|
||||
PoorManServer::_Listener,
|
||||
"www listener",
|
||||
B_NORMAL_PRIORITY,
|
||||
static_cast<void*>(this)
|
||||
);
|
||||
if(fListenerTid < B_OK){
|
||||
poorman_log("can't create listener thread.\n", false, INADDR_NONE, RED);
|
||||
return B_ERROR;
|
||||
}
|
||||
fIsRunning = true;
|
||||
if(resume_thread(fListenerTid) != B_OK){
|
||||
fIsRunning = false;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
//our server is up and running
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t PoorManServer::Stop()
|
||||
{
|
||||
if(fIsRunning){
|
||||
fIsRunning = false;
|
||||
httpd_unlisten(fHttpdServer);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*The Web Dir is not changed if an error occured.
|
||||
*/
|
||||
status_t PoorManServer::SetWebDir(const char* webDir)
|
||||
{
|
||||
if(chdir(webDir) == -1){
|
||||
//log it
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
char* tmp = strdup(webDir);
|
||||
if(tmp == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
if(pthread_rwlock_wrlock(&fWebDirLock) == 0){
|
||||
free(fHttpdServer->cwd);
|
||||
fHttpdServer->cwd = tmp;
|
||||
if(tmp[strlen(tmp)-1] == '/'){
|
||||
tmp[strlen(tmp)-1] = '\0';
|
||||
}
|
||||
pthread_rwlock_unlock(&fWebDirLock);
|
||||
} else {
|
||||
free(tmp);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t PoorManServer::SetMaxConns(int32 count)
|
||||
{
|
||||
fMaxConns = count;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t PoorManServer::SetListDir(bool listDir)
|
||||
{
|
||||
fHttpdServer->do_list_dir = (listDir?1:0);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t PoorManServer::SetIndexName(const char* idxName)
|
||||
{
|
||||
size_t length = strlen(idxName);
|
||||
if(length > B_PATH_NAME_LENGTH+1)
|
||||
return B_ERROR;
|
||||
|
||||
char* tmp = new char[length+1];
|
||||
if(tmp == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
strcpy(tmp, idxName);
|
||||
if(pthread_rwlock_wrlock(&fIndexNameLock) == 0){
|
||||
delete[] fIndexName;
|
||||
fIndexName = tmp;
|
||||
fHttpdServer->index_name = fIndexName;
|
||||
pthread_rwlock_unlock(&fIndexNameLock);
|
||||
} else {
|
||||
delete[] tmp;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
int32 PoorManServer::_Listener(void* data)
|
||||
{
|
||||
PRINT(("The listener thread is working.\n"));
|
||||
int retval;
|
||||
thread_id tid;
|
||||
httpd_conn* hc;
|
||||
PoorManServer* s = static_cast<PoorManServer*>(data);
|
||||
|
||||
while(s->fIsRunning){
|
||||
hc = new httpd_conn;
|
||||
hc->initialized = 0;
|
||||
PRINT(("calling httpd_get_conn()\n"));
|
||||
retval = //accept(), blocked here
|
||||
httpd_get_conn(s->fHttpdServer, s->fHttpdServer->listen4_fd, hc);
|
||||
switch (retval){
|
||||
case GC_OK:
|
||||
break;
|
||||
case GC_FAIL:
|
||||
httpd_destroy_conn(hc);
|
||||
delete hc;
|
||||
s->fIsRunning = false;
|
||||
return -1;
|
||||
case GC_NO_MORE: //should not happen, since we have a blocking socket
|
||||
httpd_destroy_conn(hc);
|
||||
continue;
|
||||
break;
|
||||
default: //shouldn't happen
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if(s->fCurConns > s->fMaxConns){
|
||||
httpd_send_err(hc, 503,
|
||||
httpd_err503title, "", httpd_err503form, "");
|
||||
httpd_write_response(hc);
|
||||
continue;
|
||||
}
|
||||
|
||||
tid = spawn_thread(
|
||||
PoorManServer::_Worker,
|
||||
"www connection",
|
||||
B_NORMAL_PRIORITY,
|
||||
static_cast<void*>(s)
|
||||
);
|
||||
if(tid < B_OK){
|
||||
continue;
|
||||
}
|
||||
/*We don't check the return code here.
|
||||
*As we can't kill a thread that doesn't receive the
|
||||
*httpd_conn, we simply let it die itself.
|
||||
*/
|
||||
send_data(tid, 512, &hc, sizeof(httpd_conn*));
|
||||
atomic_add(&s->fCurConns, 1);
|
||||
resume_thread(tid);
|
||||
}//while
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 PoorManServer::_Worker(void* data)
|
||||
{
|
||||
static const struct timeval kTimeVal = {60, 0};
|
||||
PoorManServer* s = static_cast<PoorManServer*>(data);
|
||||
httpd_conn* hc;
|
||||
int retval;
|
||||
|
||||
if(has_data(find_thread(NULL))){
|
||||
thread_id sender;
|
||||
if(receive_data(&sender, &hc, sizeof(httpd_conn*)) != 512)
|
||||
goto cleanup;
|
||||
} else {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
PRINT(("A worker thread starts to work.\n"));
|
||||
|
||||
setsockopt(hc->conn_fd, SOL_SOCKET, SO_RCVTIMEO, &kTimeVal, sizeof(struct timeval));
|
||||
retval = recv(
|
||||
hc->conn_fd,
|
||||
&(hc->read_buf[hc->read_idx]),
|
||||
hc->read_size - hc->read_idx,
|
||||
0
|
||||
);
|
||||
if(retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
hc->read_idx += retval;
|
||||
switch(httpd_got_request(hc)){
|
||||
case GR_GOT_REQUEST:
|
||||
break;
|
||||
case GR_BAD_REQUEST:
|
||||
httpd_send_err(hc,400,httpd_err400title,"",httpd_err400form,"");
|
||||
httpd_write_response(hc);//fall through
|
||||
case GR_NO_REQUEST: //fall through
|
||||
default: //won't happen
|
||||
goto cleanup;
|
||||
break;
|
||||
}
|
||||
|
||||
if(httpd_parse_request(hc) < 0){
|
||||
httpd_write_response(hc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
retval = httpd_start_request(hc,(struct timeval*)0);
|
||||
if(retval < 0){
|
||||
httpd_write_response(hc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*true means the connection is already handled
|
||||
*by the directory index generator in httpd_start_request().
|
||||
*/
|
||||
if(hc->file_address == (char*) 0){
|
||||
static_cast<PoorManApplication*>(be_app)->GetPoorManWindow()->SetHits(
|
||||
static_cast<PoorManApplication*>(be_app)->GetPoorManWindow()->GetHits()+1
|
||||
);
|
||||
hc->conn_fd = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
switch(hc->method){
|
||||
case METHOD_GET:
|
||||
s->_HandleGet(hc);
|
||||
break;
|
||||
case METHOD_HEAD:
|
||||
s->_HandleHead(hc);
|
||||
break;
|
||||
case METHOD_POST:
|
||||
s->_HandlePost(hc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cleanup: ;
|
||||
httpd_close_conn(hc,(struct timeval*)0);
|
||||
httpd_destroy_conn(hc);
|
||||
|
||||
delete hc;
|
||||
atomic_add(&s->fCurConns, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t PoorManServer::_HandleGet(httpd_conn* hc)
|
||||
{
|
||||
PRINT(("HandleGet() called\n"));
|
||||
|
||||
off_t length;
|
||||
ssize_t bytesRead;
|
||||
uint8* buf;
|
||||
BString log;
|
||||
|
||||
BFile file(hc->expnfilename, B_READ_ONLY);
|
||||
if(file.InitCheck() != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
buf = new uint8[POOR_MAN_BUF_SIZE];
|
||||
if(buf == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
if(hc->got_range == 1)
|
||||
length = hc->last_byte_index + 1 - hc->first_byte_index;
|
||||
else
|
||||
length = hc->sb.st_size;
|
||||
|
||||
static_cast<PoorManApplication*>(be_app)->GetPoorManWindow()->SetHits(
|
||||
static_cast<PoorManApplication*>(be_app)->GetPoorManWindow()->GetHits()+1
|
||||
);
|
||||
|
||||
log.SetTo("Sending file: ");
|
||||
if(pthread_rwlock_rdlock(&fWebDirLock) == 0){
|
||||
log << hc->hs->cwd;
|
||||
pthread_rwlock_unlock(&fWebDirLock);
|
||||
}
|
||||
log << '/' << hc->expnfilename << '\n';
|
||||
poorman_log(log.String(), true, hc->client_addr.sa_in.sin_addr.s_addr);
|
||||
|
||||
//send mime headers
|
||||
if(send(hc->conn_fd,hc->response,hc->responselen,0) < 0){
|
||||
delete [] buf;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
file.Seek(hc->first_byte_index, SEEK_SET);
|
||||
while(true){
|
||||
bytesRead = file.Read(buf, POOR_MAN_BUF_SIZE);
|
||||
if(bytesRead == 0)
|
||||
break;
|
||||
else if(bytesRead < 0){
|
||||
delete [] buf;
|
||||
return B_ERROR;
|
||||
}
|
||||
if(send(hc->conn_fd, (void*)buf, bytesRead, 0) < 0){
|
||||
log.SetTo("Error sending file: ");
|
||||
if(pthread_rwlock_rdlock(&fWebDirLock) == 0){
|
||||
log << hc->hs->cwd;
|
||||
pthread_rwlock_unlock(&fWebDirLock);
|
||||
}
|
||||
log << '/' << hc->expnfilename << '\n';
|
||||
poorman_log(log.String(), true, hc->client_addr.sa_in.sin_addr.s_addr, RED);
|
||||
delete [] buf;
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] buf;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t PoorManServer::_HandleHead(httpd_conn* hc)
|
||||
{
|
||||
int retval = send(hc->conn_fd,hc->response,hc->responselen,0);
|
||||
if(retval == -1)
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t PoorManServer::_HandlePost(httpd_conn* hc)
|
||||
{
|
||||
//not implemented
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
pthread_rwlock_t* get_web_dir_lock()
|
||||
{
|
||||
return static_cast<PoorManApplication*>(be_app)->
|
||||
GetPoorManWindow()->GetServer()->GetWebDirLock();
|
||||
}
|
||||
|
||||
pthread_rwlock_t* get_index_name_lock()
|
||||
{
|
||||
return static_cast<PoorManApplication*>(be_app)->
|
||||
GetPoorManWindow()->GetServer()->GetIndexNameLock();
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Author(s):
|
||||
* Ma Jie, china.majie at gmail
|
||||
*/
|
||||
#ifndef POOR_MAN_SERVER_H
|
||||
#define POOR_MAN_SERVER_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <OS.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "libhttpd/libhttpd.h"
|
||||
|
||||
#define POOR_MAN_BUF_SIZE 1048576ll
|
||||
|
||||
#ifdef __cplusplus
|
||||
class PoorManServer{
|
||||
public:
|
||||
PoorManServer(const char* webDir, int32 maxConns,
|
||||
bool listDir, const char* idxName);
|
||||
virtual ~PoorManServer();
|
||||
|
||||
status_t Run();
|
||||
status_t Stop();
|
||||
|
||||
bool IsRunning()const{return fIsRunning;}
|
||||
|
||||
status_t SetWebDir(const char* webDir);
|
||||
status_t SetMaxConns(int32 count);
|
||||
status_t SetListDir(bool listDir);
|
||||
status_t SetIndexName(const char* idxName);
|
||||
|
||||
pthread_rwlock_t* GetWebDirLock(){return &fWebDirLock;}
|
||||
pthread_rwlock_t* GetIndexNameLock(){return &fIndexNameLock;}
|
||||
private:
|
||||
bool fIsRunning;
|
||||
int32 fMaxConns;//Max Thread Count
|
||||
char* fIndexName;//Index File Name
|
||||
|
||||
thread_id fListenerTid;
|
||||
int32 fCurConns;
|
||||
httpd_server* fHttpdServer;
|
||||
|
||||
pthread_rwlock_t fWebDirLock;
|
||||
pthread_rwlock_t fIndexNameLock;
|
||||
|
||||
PoorManServer(){}
|
||||
PoorManServer(PoorManServer& s){}
|
||||
PoorManServer& operator=(PoorManServer& s){return *this;}
|
||||
|
||||
//two thread functions.
|
||||
static int32 _Listener(void* data);
|
||||
static int32 _Worker(void* data);
|
||||
|
||||
status_t _HandleGet(httpd_conn* hc);
|
||||
status_t _HandleHead(httpd_conn* hc);
|
||||
status_t _HandlePost(httpd_conn* hc);
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
pthread_rwlock_t* get_web_dir_lock();
|
||||
pthread_rwlock_t* get_index_name_lock();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //POOR_MAN_SERVER_H
|
||||
+392
-138
@@ -5,28 +5,54 @@
|
||||
* Version: 0.1
|
||||
*/
|
||||
|
||||
#include "PoorManApplication.h"
|
||||
#include "PoorManPreferencesWindow.h"
|
||||
#include "PoorManWindow.h"
|
||||
#include "constants.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Box.h>
|
||||
#include <Directory.h>
|
||||
#include <Alert.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Path.h>
|
||||
#include <ScrollBar.h>
|
||||
#include <ScrollView.h>
|
||||
#include <StringView.h>
|
||||
#include <TypeConstants.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
//#include <iostream>
|
||||
#include "PoorManApplication.h"
|
||||
#include "PoorManPreferencesWindow.h"
|
||||
#include "PoorManView.h"
|
||||
#include "PoorManServer.h"
|
||||
#include "PoorManLogger.h"
|
||||
#include "constants.h"
|
||||
|
||||
PoorManWindow::PoorManWindow(BRect frame)
|
||||
: BWindow(frame, STR_APP_NAME, B_TITLED_WINDOW, 0),
|
||||
status(false), hits(0), last_width(325), last_height(155)
|
||||
{
|
||||
DefaultSettings();
|
||||
status(false), hits(0), prefWindow(NULL), fLogFile(NULL), fServer(NULL)
|
||||
{
|
||||
//preferences init
|
||||
web_directory.SetTo(STR_DEFAULT_WEB_DIRECTORY);
|
||||
index_file_name.SetTo("index.html");
|
||||
dir_list_flag = false;
|
||||
|
||||
log_console_flag = true;
|
||||
log_file_flag = false;
|
||||
log_path.SetTo("");
|
||||
|
||||
max_connections = (int16)32;
|
||||
|
||||
is_zoomed = true;
|
||||
last_width = 318.0f;
|
||||
last_height = 320.0f;
|
||||
this->frame = frame;
|
||||
setwindow_frame.Set(112.0f, 60.0f, 492.0f, 340.0f);
|
||||
|
||||
// PoorMan Window
|
||||
SetSizeLimits(318, 1600, 53, 1200);
|
||||
@@ -45,10 +71,10 @@ PoorManWindow::PoorManWindow(BRect frame)
|
||||
mainView->SetFont(be_bold_font);
|
||||
mainView->SetFontSize(12);
|
||||
AddChild(mainView);
|
||||
|
||||
|
||||
// BBox tests
|
||||
BRect br;
|
||||
br = frame;
|
||||
br = mainView->Bounds();
|
||||
br.top = 1.0;
|
||||
|
||||
BBox * bb = new BBox(br, "Background", B_FOLLOW_ALL_SIDES,
|
||||
@@ -67,7 +93,7 @@ PoorManWindow::PoorManWindow(BRect frame)
|
||||
statusRect.left += 5;
|
||||
statusRect.top += 3;
|
||||
statusRect.bottom = statusRect.top + 15;
|
||||
statusRect.right = statusRect.left + 75; // make the width wide enough for the string to display
|
||||
statusRect.right = statusRect.left + 100; // make the width wide enough for the string to display
|
||||
|
||||
statusView = new BStringView(statusRect, "Status View", "Status: Stopped");
|
||||
bb->AddChild(statusView);
|
||||
@@ -80,13 +106,13 @@ PoorManWindow::PoorManWindow(BRect frame)
|
||||
dirRect.left = statusRect.left;
|
||||
dirRect.right -= 5;
|
||||
|
||||
dirView = new BStringView(dirRect, "Dir View", "Directory: /boot/home/", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
|
||||
dirView = new BStringView(dirRect, "Dir View", "Directory: (none)", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
|
||||
bb->AddChild(dirView);
|
||||
|
||||
// Hits String
|
||||
BRect hitsRect;
|
||||
hitsRect = bb->Bounds();
|
||||
hitsRect.InsetBy(5, 5);
|
||||
hitsRect.InsetBy(5.0f, 5.0f);
|
||||
hitsRect.top = statusRect.top;
|
||||
hitsRect.bottom = statusRect.bottom;
|
||||
hitsRect.left = statusRect.right + 20;
|
||||
@@ -99,34 +125,37 @@ PoorManWindow::PoorManWindow(BRect frame)
|
||||
// Logging View
|
||||
|
||||
// logRect
|
||||
BRect logRect(5.0, 36.0, 306.0, 131.0);
|
||||
BRect logRect = bb->Bounds();//(5.0, 36.0, 306.0, 131.0);
|
||||
logRect.InsetBy(5, 5);
|
||||
logRect.top = 36.0f;
|
||||
logRect.right -= B_V_SCROLL_BAR_WIDTH;
|
||||
|
||||
// textRect
|
||||
BRect textRect; //(1.0, 1.0, 175.0, 75.0);
|
||||
textRect = logRect;
|
||||
textRect.InsetBy(1.0, 1.0);
|
||||
textRect.top = 0.0;
|
||||
textRect.left = 0.0;
|
||||
textRect.left = 2.0;
|
||||
textRect.right = logRect.right - logRect.left - 2.0;
|
||||
textRect.bottom = logRect.bottom - logRect.top;
|
||||
|
||||
fLogViewFont = new BFont(be_plain_font);
|
||||
fLogViewFont->SetSize(11.0);
|
||||
|
||||
loggingView = new BTextView(logRect, STR_TXT_VIEW, textRect,
|
||||
B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
|
||||
fLogViewFont, NULL, B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
|
||||
|
||||
loggingView->MakeEditable(false); // user cannot change the text
|
||||
loggingView->MakeSelectable(true);
|
||||
loggingView->SetViewColor(WHITE);
|
||||
|
||||
loggingView->Insert("This is PoorMan.\n"); // text_run_array
|
||||
//loggingView->MakeFocus(true);
|
||||
//AddChild(loggingView);
|
||||
|
||||
|
||||
loggingView->SetStylable(true);
|
||||
|
||||
// create the scroll view
|
||||
scrollView = new BScrollView("Scroll View", loggingView, B_FOLLOW_ALL_SIDES,
|
||||
B_WILL_DRAW | B_FRAME_EVENTS,
|
||||
// Make sure articles on border do not occur when resizing
|
||||
false, true);
|
||||
bb->AddChild(scrollView);
|
||||
|
||||
loggingView->MakeFocus(true);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -177,9 +206,19 @@ PoorManWindow::PoorManWindow(BRect frame)
|
||||
|
||||
|
||||
AddChild(FileMenuBar);
|
||||
|
||||
pthread_rwlock_init(&fLogFileLock, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
PoorManWindow::~PoorManWindow()
|
||||
{
|
||||
delete fServer;
|
||||
delete fLogViewFont;
|
||||
delete fLogFile;
|
||||
pthread_rwlock_destroy(&fLogFileLock);
|
||||
}
|
||||
|
||||
void
|
||||
PoorManWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
@@ -198,33 +237,20 @@ PoorManWindow::MessageReceived(BMessage* message)
|
||||
SaveConsole(message, true);
|
||||
break;
|
||||
case MSG_MENU_EDIT_PREF:
|
||||
prefWindow = new PoorManPreferencesWindow(BRect(30.0f, 30.0f, 410.0f, 310.0f), STR_WIN_NAME_PREF);
|
||||
prefWindow = new PoorManPreferencesWindow(
|
||||
setwindow_frame,
|
||||
STR_WIN_NAME_PREF
|
||||
);
|
||||
break;
|
||||
case MSG_MENU_CTRL_RUN:
|
||||
BMenuItem * RunServer;
|
||||
RunServer = ControlsMenu->FindItem(STR_MNU_CTRL_RUN_SERVER);
|
||||
if (RunServer)
|
||||
{
|
||||
//status = httpd->Run();
|
||||
/* For Testing
|
||||
if (status)
|
||||
status = false;
|
||||
else
|
||||
status = true;
|
||||
*/
|
||||
|
||||
UpdateStatusLabel(status);
|
||||
if (status)
|
||||
{
|
||||
RunServer->SetMarked(true);
|
||||
} else {
|
||||
RunServer->SetMarked(false);
|
||||
}
|
||||
}
|
||||
if(status)
|
||||
StopServer();
|
||||
else
|
||||
StartServer();
|
||||
break;
|
||||
case MSG_MENU_CTRL_CLEAR_HIT:
|
||||
SetHits(0);
|
||||
UpdateHitsLabel();
|
||||
//UpdateHitsLabel();
|
||||
break;
|
||||
case MSG_MENU_CTRL_CLEAR_CONSOLE:
|
||||
loggingView->SelectAll();
|
||||
@@ -235,12 +261,95 @@ PoorManWindow::MessageReceived(BMessage* message)
|
||||
f = fopen(log_path.String(), "w");
|
||||
fclose(f);
|
||||
break;
|
||||
case MSG_LOG:
|
||||
{
|
||||
if(!log_console_flag && !log_file_flag)
|
||||
break;
|
||||
|
||||
time_t time;
|
||||
in_addr_t address;
|
||||
rgb_color color;
|
||||
const void* pointer;
|
||||
ssize_t size;
|
||||
const char* msg;
|
||||
BString line;
|
||||
|
||||
if(message->FindString("cstring", &msg) != B_OK)
|
||||
break;
|
||||
if(message->FindData("time_t", B_TIME_TYPE, &pointer, &size) != B_OK)
|
||||
time = -1;
|
||||
else
|
||||
time = *static_cast<time_t*>(pointer);
|
||||
if(message->FindData("in_addr_t", B_ANY_TYPE, &pointer, &size) != B_OK)
|
||||
address = INADDR_NONE;
|
||||
else
|
||||
address = *static_cast<in_addr_t*>(pointer);
|
||||
if(message->FindData("rgb_color", B_RGB_COLOR_TYPE, &pointer, &size) != B_OK)
|
||||
color = BLACK;
|
||||
else
|
||||
color = *static_cast<rgb_color*>(pointer);
|
||||
|
||||
if(time != -1){
|
||||
char timeString[26];
|
||||
if(ctime_r(&time, timeString) != NULL){
|
||||
timeString[24] = '\0';
|
||||
line << '[' << timeString << "]: ";
|
||||
}
|
||||
}
|
||||
|
||||
if(address != INADDR_NONE){
|
||||
char addr[INET_ADDRSTRLEN];
|
||||
struct in_addr sin_addr;
|
||||
sin_addr.s_addr = address;
|
||||
if(inet_ntop(AF_INET, &sin_addr, addr, sizeof(addr)) != NULL){
|
||||
addr[strlen(addr)] = '\0';
|
||||
line << '(' << addr << ") ";
|
||||
}
|
||||
}
|
||||
|
||||
line << msg;
|
||||
|
||||
text_run run;
|
||||
text_run_array runs;
|
||||
|
||||
run.offset = 0;
|
||||
run.font = *fLogViewFont;
|
||||
run.color = color;
|
||||
|
||||
runs.count = 1;
|
||||
runs.runs[0] = run;
|
||||
|
||||
if(Lock()){
|
||||
if(log_console_flag){
|
||||
loggingView->Insert(loggingView->TextLength(),
|
||||
line.String(), line.Length(), &runs);
|
||||
loggingView->ScrollToOffset(loggingView->TextLength());
|
||||
}
|
||||
|
||||
if(log_file_flag){
|
||||
if(pthread_rwlock_rdlock(&fLogFileLock) == 0){
|
||||
fLogFile->Write(line.String(), line.Length());
|
||||
pthread_rwlock_unlock(&fLogFileLock);
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PoorManWindow::FrameMoved(BPoint origin)
|
||||
{
|
||||
frame.left = origin.x;
|
||||
frame.top = origin.y;
|
||||
}
|
||||
|
||||
void
|
||||
PoorManWindow::FrameResized(float width, float height)
|
||||
@@ -250,35 +359,64 @@ PoorManWindow::FrameResized(float width, float height)
|
||||
last_width = width;
|
||||
last_height = height;
|
||||
}
|
||||
printf("(%f, %f)\n", width, height);
|
||||
}
|
||||
|
||||
bool
|
||||
bool
|
||||
PoorManWindow::QuitRequested()
|
||||
{
|
||||
if(status){
|
||||
time_t now = time(NULL);
|
||||
char line[] = "[Thu Jan 1 00:00:00 1970]: Shutting down.\n";
|
||||
|
||||
ctime_r(&now, line+1);
|
||||
line[25] = ']';
|
||||
line[26] = ' ';
|
||||
|
||||
if(log_console_flag){
|
||||
loggingView->Insert(loggingView->TextLength(),
|
||||
line, strlen(line));
|
||||
loggingView->ScrollToOffset(loggingView->TextLength());
|
||||
}
|
||||
|
||||
if(log_file_flag){
|
||||
if(pthread_rwlock_rdlock(&fLogFileLock) == 0){
|
||||
fLogFile->Write(line, strlen(line));
|
||||
pthread_rwlock_unlock(&fLogFileLock);
|
||||
}
|
||||
}
|
||||
|
||||
fServer->Stop();
|
||||
status = false;
|
||||
UpdateStatusLabelAndMenuItem();
|
||||
}
|
||||
|
||||
SaveSettings();
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return (true);
|
||||
be_app_messenger.SendMessage(B_QUIT_REQUESTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PoorManWindow::Zoom(BPoint origin, float width, float height)
|
||||
{
|
||||
printf("Zoom: Is Zoomed before: %d (%f, %f)\n", is_zoomed, width, height);
|
||||
if (is_zoomed)
|
||||
{ // Change to the Minimal size
|
||||
is_zoomed = false;
|
||||
ResizeTo(318, 53);
|
||||
printf("ResizedTo(318, 53)\n");
|
||||
}
|
||||
else
|
||||
{ // Change to the Zoomed size
|
||||
is_zoomed = true;
|
||||
ResizeTo(last_width, last_height);
|
||||
printf("ResizedTo(%f, %f)\n", last_width, last_height);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PoorManWindow::SetHits(uint32 num)
|
||||
{
|
||||
hits = num;
|
||||
UpdateHitsLabel();
|
||||
}
|
||||
|
||||
// Private: Methods ------------------------------------------
|
||||
|
||||
BMenu *
|
||||
@@ -368,11 +506,7 @@ void
|
||||
PoorManWindow::SetDirLabel(const char * name)
|
||||
{
|
||||
BString dirPath("Directory: ");
|
||||
int32 length = dirPath.Length() + 1;
|
||||
dirPath.LockBuffer(length);
|
||||
dirPath.Append(name);
|
||||
|
||||
dirPath.UnlockBuffer(length + strlen(name));
|
||||
|
||||
if (Lock())
|
||||
{
|
||||
@@ -382,15 +516,15 @@ PoorManWindow::SetDirLabel(const char * name)
|
||||
}
|
||||
|
||||
void
|
||||
PoorManWindow::UpdateStatusLabel(bool set)
|
||||
PoorManWindow::UpdateStatusLabelAndMenuItem()
|
||||
{
|
||||
if (Lock())
|
||||
{
|
||||
if (set)
|
||||
if (status)
|
||||
statusView->SetText("Status: Running");
|
||||
else
|
||||
statusView->SetText("Status: Stopped");
|
||||
|
||||
ControlsMenu->FindItem(STR_MNU_CTRL_RUN_SERVER)->SetMarked(status);
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
@@ -417,13 +551,13 @@ PoorManWindow::SaveConsole(BMessage * message, bool selection)
|
||||
status_t err = B_OK;
|
||||
FILE *f;
|
||||
|
||||
if (err = message->FindRef("directory", &ref) != B_OK)
|
||||
if ((err = message->FindRef("directory", &ref)) != B_OK)
|
||||
return err;
|
||||
|
||||
if (err = message->FindString("name", &name) != B_OK)
|
||||
if ((err = message->FindString("name", &name)) != B_OK)
|
||||
return err;
|
||||
|
||||
if (err = entry.SetTo(&ref) != B_OK)
|
||||
if ((err = entry.SetTo(&ref)) != B_OK)
|
||||
return err;
|
||||
|
||||
entry.GetPath(&path);
|
||||
@@ -433,7 +567,7 @@ PoorManWindow::SaveConsole(BMessage * message, bool selection)
|
||||
return B_ERROR;
|
||||
|
||||
if (!selection)
|
||||
{
|
||||
{
|
||||
// write the data to the file
|
||||
err = fwrite(loggingView->Text(), 1, loggingView->TextLength(), f);
|
||||
} else {
|
||||
@@ -455,88 +589,208 @@ PoorManWindow::SaveConsole(BMessage * message, bool selection)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
PoorManWindow::DefaultSettings()
|
||||
{
|
||||
// Site Tab
|
||||
SetIndexFileName("index.html");
|
||||
SetDirListFlag(false);
|
||||
// Logging Tab
|
||||
SetLogConsoleFlag(true);
|
||||
SetLogFileFlag(false);
|
||||
// Advanced Tab
|
||||
SetMaxConnections(32);
|
||||
BAlert* serverAlert = new BAlert("Error Server", STR_ERR_CANT_START, "OK");
|
||||
BAlert* dirAlert = new BAlert("Error Dir", STR_ERR_WEB_DIR,
|
||||
"Cancel", "Select", "Default", B_WIDTH_AS_USUAL, B_OFFSET_SPACING);
|
||||
dirAlert->SetShortcut(0, B_ESCAPE);
|
||||
int32 buttonIndex = dirAlert->Go();
|
||||
|
||||
BDirectory webDir;
|
||||
if (!webDir.Contains("/boot/home/public_html", B_DIRECTORY_NODE))
|
||||
{
|
||||
BAlert * serverAlert = new BAlert("Error Server", STR_ERR_CANT_START, "OK");
|
||||
|
||||
BAlert * dirAlert = new BAlert("Error Dir", STR_ERR_WEB_DIR,
|
||||
"Cancel", "Select", "Default", B_WIDTH_AS_USUAL, B_OFFSET_SPACING);
|
||||
dirAlert->SetShortcut(0, B_ESCAPE);
|
||||
int32 buttonIndex = dirAlert->Go();
|
||||
|
||||
|
||||
|
||||
// process dirAlert
|
||||
switch (buttonIndex)
|
||||
{
|
||||
case 0:
|
||||
serverAlert->Go();
|
||||
QuitRequested();
|
||||
break;
|
||||
case 1:
|
||||
serverAlert->Go();
|
||||
prefWindow = new PoorManPreferencesWindow(BRect(30.0f, 30.0f, 410.0f, 310.0f), STR_WIN_NAME_PREF);
|
||||
prefWindow->ShowWebDirFilePanel();
|
||||
break;
|
||||
case 2:
|
||||
|
||||
break;
|
||||
switch (buttonIndex){
|
||||
case 0:
|
||||
serverAlert->Go();
|
||||
SetWebDir("");
|
||||
break;
|
||||
case 1:
|
||||
prefWindow = new PoorManPreferencesWindow(
|
||||
setwindow_frame,
|
||||
STR_WIN_NAME_PREF
|
||||
);
|
||||
serverAlert->Go();
|
||||
prefWindow->ShowWebDirFilePanel();
|
||||
break;
|
||||
case 2:
|
||||
if(create_directory(STR_DEFAULT_WEB_DIRECTORY, 0755) != B_OK){
|
||||
serverAlert->Go();
|
||||
SetWebDir("");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf("BDirectory contains: /boot/home/public_html\n");
|
||||
SetWebDir("/boot/home/public_html");
|
||||
BAlert* dirCreatedAlert =
|
||||
new BAlert("Dir Created",STR_DIR_CREATED,"OK");
|
||||
dirCreatedAlert->Go();
|
||||
SetWebDir(STR_DEFAULT_WEB_DIRECTORY);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
status_t
|
||||
status_t
|
||||
PoorManWindow::ReadSettings()
|
||||
{
|
||||
BPath p;
|
||||
BFile f;
|
||||
BMessage m;
|
||||
|
||||
if(find_directory(B_USER_SETTINGS_DIRECTORY, &p) != B_OK)
|
||||
return B_ERROR;
|
||||
p.Append(STR_SETTINGS_FILE_NAME);
|
||||
|
||||
f.SetTo(p.Path(), B_READ_ONLY);
|
||||
if(f.InitCheck()!=B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if(m.Unflatten(&f)!=B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if(MSG_PREF_FILE != m.what)
|
||||
return B_ERROR;
|
||||
|
||||
//site tab
|
||||
if(m.FindString("web_directory", &web_directory) != B_OK)
|
||||
web_directory.SetTo(STR_DEFAULT_WEB_DIRECTORY);
|
||||
if(m.FindString("index_file_name", &index_file_name) != B_OK)
|
||||
index_file_name.SetTo("index.html");
|
||||
if(m.FindBool("dir_list_flag", &dir_list_flag) != B_OK)
|
||||
dir_list_flag = false;
|
||||
|
||||
//logging tab
|
||||
if(m.FindBool("log_console_flag", &log_console_flag) != B_OK)
|
||||
log_console_flag = true;
|
||||
if(m.FindBool("log_file_flag", &log_file_flag) != B_OK)
|
||||
log_file_flag = false;
|
||||
if(m.FindString("log_path", &log_path) != B_OK)
|
||||
log_path.SetTo("");
|
||||
|
||||
//advance tab
|
||||
if(m.FindInt16("max_connections", &max_connections) != B_OK)
|
||||
max_connections = (int16)32;
|
||||
|
||||
//windows' position and size
|
||||
if(m.FindRect("frame", &frame) != B_OK)
|
||||
frame.Set(82.0f, 30.0f, 400.0f, 350.0f);
|
||||
if(m.FindRect("setwindow_frame", &setwindow_frame) != B_OK)
|
||||
setwindow_frame.Set(112.0f, 60.0f, 492.0f, 340.0f);
|
||||
if(m.FindBool("is_zoomed", &is_zoomed) != B_OK)
|
||||
is_zoomed = true;
|
||||
if(m.FindFloat("last_width", &last_width) != B_OK)
|
||||
last_width = 318.0f;
|
||||
if(m.FindFloat("last_height", &last_height) != B_OK)
|
||||
last_height = 320.0f;
|
||||
|
||||
is_zoomed?ResizeTo(last_width, last_height):ResizeTo(318, 53);
|
||||
MoveTo(frame.left, frame.top);
|
||||
|
||||
fLogFile = new BFile(log_path.String(), B_CREATE_FILE|B_WRITE_ONLY|B_OPEN_AT_END);
|
||||
if(fLogFile->InitCheck() != B_OK){
|
||||
log_file_flag = false;
|
||||
//log it to console, "log to file unavailable."
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
SetDirLabel(web_directory.String());
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
status_t
|
||||
PoorManWindow::SaveSettings()
|
||||
{
|
||||
FILE * f;
|
||||
size_t s;
|
||||
BPath p;
|
||||
BFile f;
|
||||
BMessage m(MSG_PREF_FILE);
|
||||
|
||||
//site tab
|
||||
m.AddString("web_directory", web_directory);
|
||||
m.AddString("index_file_name", index_file_name);
|
||||
m.AddBool("dir_list_flag", dir_list_flag);
|
||||
|
||||
f = fopen(STR_SETTINGS_NEW_FILE_PATH, "wb");
|
||||
if (f)
|
||||
{
|
||||
// Need to rewrite
|
||||
/*
|
||||
//fprintf(f, "%s", web_directory.String());
|
||||
s = fwrite(web_directory.String(), sizeof(char), web_directory.Length() + 1, f);
|
||||
|
||||
fprintf(f, "%s", index_file_name.String());
|
||||
fwrite(dir_list_flag, sizeof(bool), 1, f);
|
||||
//fprintf(f, "%uc", dir_list_flag);
|
||||
|
||||
// logging tab
|
||||
fwrite(log_file_flag, sizeof(bool), 1, f);
|
||||
//fprintf(f, "%uc", log_console_flag);
|
||||
fprintf(f, "%uc", log_file_flag);
|
||||
fprintf(f, "%s", log_path.String());
|
||||
// advanced tab
|
||||
fprintf(f, "%ld", max_connections);
|
||||
//logging tab
|
||||
m.AddBool("log_console_flag", log_console_flag);
|
||||
m.AddBool("log_file_flag", log_file_flag);
|
||||
m.AddString("log_path", log_path);
|
||||
|
||||
fprintf(f, "%uc", is_zoomed);
|
||||
fprintf(f, "%f", last_width);
|
||||
fprintf(f, "%f", last_height);
|
||||
*/
|
||||
}
|
||||
fclose(f);
|
||||
//advance tab
|
||||
m.AddInt16("max_connections", max_connections);
|
||||
|
||||
//windows' position and size
|
||||
m.AddRect("frame", frame);
|
||||
m.AddRect("setwindow_frame", setwindow_frame);
|
||||
m.AddBool("is_zoomed", is_zoomed);
|
||||
m.AddFloat("last_width", last_width);
|
||||
m.AddFloat("last_height", last_height);
|
||||
|
||||
if(find_directory(B_USER_SETTINGS_DIRECTORY, &p) != B_OK)
|
||||
return B_ERROR;
|
||||
p.Append(STR_SETTINGS_FILE_NAME);
|
||||
|
||||
f.SetTo(p.Path(), B_WRITE_ONLY| B_ERASE_FILE| B_CREATE_FILE);
|
||||
if(f.InitCheck()!=B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if(m.Flatten(&f)!=B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
PoorManWindow::StartServer()
|
||||
{
|
||||
if(NULL == fServer)
|
||||
fServer = new PoorManServer(
|
||||
web_directory.String(),
|
||||
max_connections,
|
||||
dir_list_flag,
|
||||
index_file_name.String()
|
||||
);
|
||||
|
||||
poorman_log("Starting up... ");
|
||||
if(fServer->Run() != B_OK){
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status = true;
|
||||
UpdateStatusLabelAndMenuItem();
|
||||
poorman_log("done.\n", false, INADDR_NONE, GREEN);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
PoorManWindow::StopServer()
|
||||
{
|
||||
if(NULL == fServer)
|
||||
return B_ERROR;
|
||||
|
||||
poorman_log("Shutting down.\n");
|
||||
fServer->Stop();
|
||||
status = false;
|
||||
UpdateStatusLabelAndMenuItem();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PoorManWindow::SetLogPath(const char* str)
|
||||
{
|
||||
if(log_path == str)
|
||||
return;
|
||||
|
||||
BFile* temp = new BFile(str, B_CREATE_FILE|B_WRITE_ONLY|B_OPEN_AT_END);
|
||||
|
||||
if(temp->InitCheck() != B_OK){
|
||||
delete temp;
|
||||
return;
|
||||
}
|
||||
|
||||
if(pthread_rwlock_wrlock(&fLogFileLock) == 0){
|
||||
delete fLogFile;
|
||||
fLogFile = temp;
|
||||
pthread_rwlock_unlock(&fLogFileLock);
|
||||
} else {
|
||||
delete temp;
|
||||
return;
|
||||
}
|
||||
|
||||
log_path.SetTo(str);
|
||||
}
|
||||
|
||||
@@ -8,29 +8,36 @@
|
||||
#ifndef POOR_MAN_WINDOW_H
|
||||
#define POOR_MAN_WINDOW_H
|
||||
|
||||
#include <Window.h>
|
||||
#include <Point.h>
|
||||
#include <FilePanel.h>
|
||||
#include <Path.h>
|
||||
#include <Message.h>
|
||||
#include <MenuBar.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuItem.h>
|
||||
#include <TextView.h>
|
||||
#include <StringView.h>
|
||||
#include <ScrollView.h>
|
||||
#include <String.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "PoorManView.h"
|
||||
#include "PoorManPreferencesWindow.h"
|
||||
#include <SupportDefs.h>
|
||||
#include <Window.h>
|
||||
#include <String.h>
|
||||
|
||||
class BPoint;
|
||||
class BFilePanel;
|
||||
class BMessage;
|
||||
class BMenuBar;
|
||||
class BMenu;
|
||||
class BTextView;
|
||||
class BStringView;
|
||||
class BScrollView;
|
||||
class BRect;
|
||||
class BFile;
|
||||
class BFont;
|
||||
|
||||
class PoorManView;
|
||||
class PoorManPreferencesWindow;
|
||||
class PoorManServer;
|
||||
|
||||
class PoorManWindow: public BWindow
|
||||
{
|
||||
public:
|
||||
PoorManWindow(BRect frame);
|
||||
virtual ~PoorManWindow();
|
||||
virtual void MessageReceived(BMessage * message);
|
||||
|
||||
virtual void FrameMoved(BPoint origin);
|
||||
virtual void FrameResized(float width, float height);
|
||||
virtual bool QuitRequested();
|
||||
virtual void Zoom(BPoint origin, float width, float height);
|
||||
@@ -38,11 +45,18 @@ virtual void Zoom(BPoint origin, float width, float height);
|
||||
// -------------------------------------------
|
||||
// Public PoorMan Window Methods
|
||||
void SetDirLabel(const char * name);
|
||||
void SetHits(uint32 num) { hits = num;}
|
||||
void SetHits(uint32 num);
|
||||
uint32 GetHits() { return hits; }
|
||||
status_t SaveConsole(BMessage * message, bool);
|
||||
status_t SaveSettings();
|
||||
|
||||
status_t SaveSettings();
|
||||
status_t ReadSettings();
|
||||
void DefaultSettings();
|
||||
|
||||
status_t StartServer();
|
||||
status_t StopServer();
|
||||
|
||||
PoorManServer* GetServer()const{return fServer;}
|
||||
// -------------------------------------------
|
||||
// Preferences and Settings
|
||||
// Site Tab
|
||||
@@ -58,19 +72,16 @@ virtual void Zoom(BPoint origin, float width, float height);
|
||||
bool LogFileFlag() { return log_file_flag; }
|
||||
void SetLogFileFlag(bool flag) { log_file_flag = flag; }
|
||||
const char * LogPath() { return log_path.String(); }
|
||||
void SetLogPath(const char * str) { log_path.SetTo(str); }
|
||||
void SetLogPath(const char * str);
|
||||
// Advanced Tab
|
||||
int32 MaxConnections() { return max_connections; }
|
||||
void SetMaxConnections(int32 num) { max_connections = num; }
|
||||
int16 MaxConnections() { return max_connections; }
|
||||
void SetMaxConnections(int16 num) { max_connections = num; }
|
||||
|
||||
|
||||
private:
|
||||
// -------------------------------------------
|
||||
// PoorMan Window Methods
|
||||
status_t ReadSettings();
|
||||
void DefaultSettings();
|
||||
|
||||
void UpdateStatusLabel(bool);
|
||||
void UpdateStatusLabelAndMenuItem();
|
||||
void UpdateHitsLabel();
|
||||
|
||||
private:
|
||||
@@ -121,8 +132,9 @@ private:
|
||||
bool log_console_flag;
|
||||
bool log_file_flag;
|
||||
BString log_path;
|
||||
|
||||
// advanced tab
|
||||
int32 max_connections;
|
||||
int16 max_connections;
|
||||
|
||||
bool is_zoomed;
|
||||
float last_width;
|
||||
@@ -130,11 +142,16 @@ private:
|
||||
BRect frame;
|
||||
BRect setwindow_frame;
|
||||
|
||||
|
||||
// File Panels
|
||||
BFilePanel * saveConsoleFilePanel;
|
||||
BFilePanel * saveConsoleSelectionFilePanel;
|
||||
|
||||
BFile* fLogFile;
|
||||
BFont* fLogViewFont;
|
||||
|
||||
PoorManServer* fServer;
|
||||
|
||||
pthread_rwlock_t fLogFileLock;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,4 +38,4 @@ StatusSlider::UpdateText() const
|
||||
sprintf(temp, "%ld %s", Value(), StatusPrefix);
|
||||
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef STATUS_SLIDER
|
||||
#define STATUS_SLIDER
|
||||
|
||||
#define BEOS_R5_COMPATIBLE
|
||||
//#define BEOS_R5_COMPATIBLE
|
||||
|
||||
#include <Slider.h>
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@ extern const char* STR_ERR_WEB_DIR
|
||||
"Do you wish to select a folder to publish on the Web?";
|
||||
extern const char* STR_ERR_CANT_START
|
||||
= "Can't Start the Server";
|
||||
extern const char* STR_DIR_CREATED
|
||||
= "A default Web directory has been created for you "
|
||||
"at \"/boot/home/public_html.\"\nMake sure an HTML "
|
||||
"document named \"index.html\" is in that directory.";
|
||||
|
||||
extern const char* STR_MNU_FILE
|
||||
= "File";
|
||||
@@ -58,11 +62,12 @@ extern const char* STR_TXT_VIEW
|
||||
char* STR_WIN_NAME_PREF
|
||||
= "PoorMan Settings";
|
||||
|
||||
extern const char* STR_SETTINGS_FILE_PATH
|
||||
= "/boot/home/config/settings/PoorMan Settings";
|
||||
extern const char* STR_SETTINGS_NEW_FILE_PATH
|
||||
= "/boot/home/config/settings/OBOS PoorMan Settings";
|
||||
|
||||
extern const char* STR_SETTINGS_FILE_NAME
|
||||
= "PoorMan Settings";
|
||||
extern const char* STR_SETTINGS_NEW_FILE_NAME
|
||||
= "OBOS PoorMan Settings";
|
||||
extern const char* STR_DEFAULT_WEB_DIRECTORY
|
||||
= "/boot/home/public_html";
|
||||
extern const char* STR_TAB_SITE
|
||||
= "Site";
|
||||
extern const char* STR_BBX_LOCATION
|
||||
@@ -123,12 +128,14 @@ extern const char* STR_ABOUT_BUTTON
|
||||
= "OK";
|
||||
extern const char* STR_ABOUT_DESC
|
||||
= "Poor Man's Web Server\n"
|
||||
"Copyright © 2004 Haiku\n"
|
||||
"Copyright " B_UTF8_COPYRIGHT " 2004-2009 Haiku\n"
|
||||
"All rights reserved.\n\n"
|
||||
"Written by: Philip Harrison";
|
||||
"Written by: Philip Harrison, Ma Jie";
|
||||
|
||||
// --------------------------------
|
||||
extern const rgb_color WHITE = { 255, 255, 255, 255 };
|
||||
extern const rgb_color GRAY = { 184, 184, 184, 255 };
|
||||
extern const rgb_color BACKGROUND_COLOR = { 216, 216, 216, 255 };
|
||||
extern const rgb_color BLACK = { 0, 0, 0, 255 };
|
||||
extern const rgb_color RED = { 255, 0, 0, 255};
|
||||
extern const rgb_color GREEN = { 0, 255, 0, 255};
|
||||
|
||||
@@ -32,12 +32,18 @@ const int32 MSG_FILE_PANEL_CREATE_LOG_FILE = 'oCLF';
|
||||
// Advanced Tab
|
||||
const int32 MSG_PREF_ADV_SLD_MAX_CONNECTION = 'PASM';
|
||||
|
||||
// BMessage Preferences File
|
||||
const uint32 MSG_PREF_FILE = 'pref';
|
||||
|
||||
//BMessage for Logger
|
||||
const int32 MSG_LOG = 'logg';
|
||||
// ------------------------------------------------------
|
||||
// PoorMan Window
|
||||
extern const char* STR_APP_SIG;
|
||||
extern char* STR_APP_NAME;
|
||||
extern const char* STR_ERR_WEB_DIR; // Alert Box
|
||||
extern const char* STR_ERR_CANT_START;
|
||||
extern const char* STR_DIR_CREATED;
|
||||
|
||||
extern const char* STR_MNU_FILE;
|
||||
extern const char* STR_MNU_FILE_SAVE_AS;
|
||||
@@ -61,9 +67,9 @@ extern const char* STR_TXT_VIEW;
|
||||
// ------------------------------------------------------
|
||||
// Preferences Window
|
||||
extern char* STR_WIN_NAME_PREF;
|
||||
extern const char* STR_SETTINGS_FILE_PATH;
|
||||
extern const char* STR_SETTINGS_NEW_FILE_PATH;
|
||||
|
||||
extern const char* STR_SETTINGS_FILE_NAME;
|
||||
extern const char* STR_SETTINGS_NEW_FILE_NAME;
|
||||
extern const char* STR_DEFAULT_WEB_DIRECTORY;
|
||||
|
||||
extern const char* STR_TAB_SITE;
|
||||
extern const char* STR_BBX_LOCATION;
|
||||
@@ -104,4 +110,6 @@ extern const rgb_color WHITE;
|
||||
extern const rgb_color GRAY;
|
||||
extern const rgb_color BACKGROUND_COLOR;
|
||||
extern const rgb_color BLACK;
|
||||
extern const rgb_color RED;
|
||||
extern const rgb_color GREEN;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
This is libhttpd from thttpd v2.25b, which is written by Jef Poskanzer.
|
||||
This version of libhttpd is modified to fit into the multithreaded PoorMan application.
|
||||
|
||||
For more information about thttpd, please visit:
|
||||
http://www.acme.com/software/thttpd/
|
||||
@@ -0,0 +1,398 @@
|
||||
/* config.h - configuration defines for thttpd and libhttpd
|
||||
**
|
||||
** Copyright © 1995,1998,1999,2000,2001 by Jef Poskanzer <jef@mail.acme.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
|
||||
/* The following configuration settings are sorted in order of decreasing
|
||||
** likelihood that you'd want to change them - most likely first, least
|
||||
** likely last.
|
||||
**
|
||||
** In case you're not familiar with the convention, "#ifdef notdef"
|
||||
** is a Berkeleyism used to indicate temporarily disabled code.
|
||||
** The idea here is that you re-enable it by just moving it outside
|
||||
** of the ifdef.
|
||||
*/
|
||||
|
||||
/* CONFIGURE: CGI programs must match this pattern to get executed. It's
|
||||
** a simple shell-style wildcard pattern, with * meaning any string not
|
||||
** containing a slash, ** meaning any string at all, and ? meaning any
|
||||
** single character; or multiple such patterns separated by |. The
|
||||
** patterns get checked against the filename part of the incoming URL.
|
||||
**
|
||||
** Restricting CGI programs to a single directory lets the site administrator
|
||||
** review them for security holes, and is strongly recommended. If there
|
||||
** are individual users that you trust, you can enable their directories too.
|
||||
**
|
||||
** You can also specify a CGI pattern on the command line, with the -c flag.
|
||||
** Such a pattern overrides this compiled-in default.
|
||||
**
|
||||
** If no CGI pattern is specified, neither here nor on the command line,
|
||||
** then CGI programs cannot be run at all. If you want to disable CGI
|
||||
** as a security measure that's how you do it, just don't define any
|
||||
** pattern here and don't run with the -c flag.
|
||||
*/
|
||||
#ifdef notdef
|
||||
/* Some sample patterns. Allow programs only in one central directory: */
|
||||
#define CGI_PATTERN "/cgi-bin/*"
|
||||
/* Allow programs in a central directory, or anywhere in a trusted
|
||||
** user's tree: */
|
||||
#define CGI_PATTERN "/cgi-bin/*|/jef/**"
|
||||
/* Allow any program ending with a .cgi: */
|
||||
#define CGI_PATTERN "**.cgi"
|
||||
/* When virtual hosting, enable the central directory on every host: */
|
||||
#define CGI_PATTERN "/*/cgi-bin/*"
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: How many seconds to allow CGI programs to run before killing
|
||||
** them. This is in case someone writes a CGI program that goes into an
|
||||
** infinite loop, or does a massive database lookup that would take hours,
|
||||
** or whatever. If you don't want any limit, comment this out, but that's
|
||||
** probably a really bad idea.
|
||||
*/
|
||||
//#define CGI_TIMELIMIT 30
|
||||
|
||||
/* CONFIGURE: Maximum number of simultaneous CGI programs allowed.
|
||||
** If this many are already running, then attempts to run more will
|
||||
** return an HTTP 503 error. If this is not defined then there's
|
||||
** no limit (and you'd better have a lot of memory). This can also be
|
||||
** set in the runtime config file.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define CGI_LIMIT 50
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: How many seconds to allow for reading the initial request
|
||||
** on a new connection.
|
||||
*/
|
||||
#define IDLE_READ_TIMELIMIT 60
|
||||
|
||||
/* CONFIGURE: How many seconds before an idle connection gets closed.
|
||||
*/
|
||||
#define IDLE_SEND_TIMELIMIT 300
|
||||
|
||||
/* CONFIGURE: The syslog facility to use. Using this you can set up your
|
||||
** syslog.conf so that all thttpd messages go into a separate file. Note
|
||||
** that even if you use the -l command line flag to send logging to a
|
||||
** file, errors still get sent via syslog.
|
||||
*/
|
||||
#define LOG_FACILITY LOG_DAEMON
|
||||
|
||||
/* CONFIGURE: Tilde mapping. Many URLs use ~username to indicate a
|
||||
** user's home directory. thttpd provides two options for mapping
|
||||
** this construct to an actual filename.
|
||||
**
|
||||
** 1) Map ~username to <prefix>/username. This is the recommended choice.
|
||||
** Each user gets a subdirectory in the main chrootable web tree, and
|
||||
** the tilde construct points there. The prefix could be something
|
||||
** like "users", or it could be empty. See also the makeweb program
|
||||
** for letting users create their own web subdirectories.
|
||||
**
|
||||
** 2) Map ~username to <user's homedir>/<postfix>. The postfix would be
|
||||
** the name of a subdirectory off of the user's actual home dir, something
|
||||
** like "public_html". This is what Apache and other servers do. The problem
|
||||
** is, you can't do this and chroot() at the same time, so it's inherently
|
||||
** a security hole. This is strongly dis-recommended, but it's here because
|
||||
** some people really want it. Use at your own risk.
|
||||
**
|
||||
** You can also leave both options undefined, and thttpd will not do
|
||||
** anything special about tildes. Enabling both options is an error.
|
||||
*/
|
||||
//#ifdef notdef
|
||||
//#define TILDE_MAP_1 "users"
|
||||
//#define TILDE_MAP_2 "public_html"
|
||||
//#endif
|
||||
|
||||
/* CONFIGURE: The file to use for authentication. If this is defined then
|
||||
** thttpd checks for this file in the local directory before every fetch.
|
||||
** If the file exists then authentication is done, otherwise the fetch
|
||||
** proceeds as usual.
|
||||
**
|
||||
** If you undefine this then thttpd will not implement authentication
|
||||
** at all and will not check for auth files, which saves a bit of CPU time.
|
||||
*/
|
||||
//#define AUTH_FILE ".htpasswd"
|
||||
|
||||
/* CONFIGURE: The default character set name to use with text MIME types.
|
||||
** This gets substituted into the MIME types where they have a "%s".
|
||||
**
|
||||
** You can override this in the config file with the "charset" setting,
|
||||
** or on the command like with the -T flag.
|
||||
*/
|
||||
#define DEFAULT_CHARSET "iso-8859-1"
|
||||
|
||||
|
||||
/* Most people won't want to change anything below here. */
|
||||
|
||||
/* CONFIGURE: This controls the SERVER_NAME environment variable that gets
|
||||
** passed to CGI programs. By default thttpd does a gethostname(), which
|
||||
** gives the host's canonical name. If you want to always use some other name
|
||||
** you can define it here.
|
||||
**
|
||||
** Alternately, if you want to run the same thttpd binary on multiple
|
||||
** machines, and want to build in alternate names for some or all of
|
||||
** them, you can define a list of canonical name to altername name
|
||||
** mappings. thttpd seatches the list and when it finds a match on
|
||||
** the canonical name, that alternate name gets used. If no match
|
||||
** is found, the canonical name gets used.
|
||||
**
|
||||
** If both SERVER_NAME and SERVER_NAME_LIST are defined here, thttpd searches
|
||||
** the list as above, and if no match is found then SERVER_NAME gets used.
|
||||
**
|
||||
** In any case, if thttpd is started with the -h flag, that name always
|
||||
** gets used.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define SERVER_NAME "your.hostname.here"
|
||||
#define SERVER_NAME_LIST \
|
||||
"canonical.name.here/alternate.name.here", \
|
||||
"canonical.name.two/alternate.name.two"
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: Undefine this if you want thttpd to hide its specific version
|
||||
** when returning into to browsers. Instead it'll just say "thttpd" with
|
||||
** no version.
|
||||
*/
|
||||
//#define SHOW_SERVER_VERSION
|
||||
|
||||
/* CONFIGURE: Define this if you want to always chroot(), without having
|
||||
** to give the -r command line flag. Some people like this as a security
|
||||
** measure, to prevent inadvertant exposure by accidentally running without -r.
|
||||
** You can still disable it at runtime with the -nor flag.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define ALWAYS_CHROOT
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: Define this if you want to always do virtual hosting, without
|
||||
** having to give the -v command line flag. You can still disable it at
|
||||
** runtime with the -nov flag.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define ALWAYS_VHOST
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: If you're using the vhost feature and you have a LOT of
|
||||
** virtual hostnames (like, hundreds or thousands), you will want to
|
||||
** enable this feature. It avoids a problem with most Unix filesystems,
|
||||
** where if there are a whole lot of items in a directory then name lookup
|
||||
** becomes very slow. This feature makes thttpd use subdirectories
|
||||
** based on the first characters of each hostname. You can set it to use
|
||||
** from one to three characters. If the hostname starts with "www.", that
|
||||
** part is skipped over. Dots are also skipped over, and if the name isn't
|
||||
** long enough then "_"s are used. Here are some examples of how hostnames
|
||||
** would get turned into directory paths, for each different setting:
|
||||
** 1: www.acme.com -> a/www.acme.com
|
||||
** 1: foobar.acme.com -> f/foobar.acme.com
|
||||
** 2: www.acme.com -> a/c/www.acme.com
|
||||
** 2: foobar.acme.com -> f/o/foobar.acme.com
|
||||
** 3: www.acme.com -> a/c/m/www.acme.com
|
||||
** 3: foobar.acme.com -> f/o/o/foobar.acme.com
|
||||
** 3: m.tv -> m/t/v/m.tv
|
||||
** 4: m.tv -> m/t/v/_/m.tv
|
||||
** Note that if you compile this setting in but then forget to set up
|
||||
** the corresponding subdirectories, the only error indication you'll
|
||||
** get is a "404 Not Found" when you try to visit a site. So be careful.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define VHOST_DIRLEVELS 1
|
||||
#define VHOST_DIRLEVELS 2
|
||||
#define VHOST_DIRLEVELS 3
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: Define this if you want to always use a global passwd file,
|
||||
** without having to give the -P command line flag. You can still disable
|
||||
** it at runtime with the -noP flag.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define ALWAYS_GLOBAL_PASSWD
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: When started as root, the default username to switch to after
|
||||
** initializing. If this user (or the one specified by the -u flag) does
|
||||
** not exist, the program will refuse to run.
|
||||
*/
|
||||
#define DEFAULT_USER "nobody"
|
||||
|
||||
/* CONFIGURE: When started as root, the program can automatically chdir()
|
||||
** to the home directory of the user specified by -u or DEFAULT_USER.
|
||||
** An explicit -d still overrides this.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define USE_USER_DIR
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: If this is defined, some of the built-in error pages will
|
||||
** have more explicit information about exactly what the problem is.
|
||||
** Some sysadmins don't like this, for security reasons.
|
||||
*/
|
||||
#define EXPLICIT_ERROR_PAGES
|
||||
|
||||
/* CONFIGURE: Subdirectory for custom error pages. The error filenames are
|
||||
** $WEBDIR/$ERR_DIR/err%d.html - if virtual hosting is enabled then
|
||||
** $WEBDIR/hostname/$ERR_DIR/err%d.html is searched first. This allows
|
||||
** different custom error pages for each virtual hosting web server. If
|
||||
** no custom page for a given error can be found, the built-in error page
|
||||
** is generated. If ERR_DIR is not defined at all, only the built-in error
|
||||
** pages will be generated.
|
||||
*/
|
||||
#define ERR_DIR "errors"
|
||||
|
||||
/* CONFIGURE: Define this if you want a standard HTML tail containing
|
||||
** $SERVER_SOFTWARE and $SERVER_ADDRESS to be appended to the custom error
|
||||
** pages. (It is always appended to the built-in error pages.)
|
||||
*/
|
||||
#define ERR_APPEND_SERVER_INFO
|
||||
|
||||
/* CONFIGURE: nice(2) value to use for CGI programs. If this is undefined,
|
||||
** CGI programs run at normal priority.
|
||||
*/
|
||||
//#define CGI_NICE 10
|
||||
|
||||
/* CONFIGURE: $PATH to use for CGI programs.
|
||||
*/
|
||||
#define CGI_PATH "/usr/local/bin:/usr/ucb:/bin:/usr/bin"
|
||||
|
||||
/* CONFIGURE: If defined, $LD_LIBRARY_PATH to use for CGI programs.
|
||||
*/
|
||||
#ifdef notdef
|
||||
#define CGI_LD_LIBRARY_PATH "/usr/local/lib:/usr/lib"
|
||||
#endif
|
||||
|
||||
/* CONFIGURE: How often to run the occasional cleanup job.
|
||||
*/
|
||||
#define OCCASIONAL_TIME 120
|
||||
|
||||
/* CONFIGURE: Seconds between stats syslogs. If this is undefined then
|
||||
** no stats are accumulated and no stats syslogs are done.
|
||||
*/
|
||||
#define STATS_TIME 3600
|
||||
|
||||
/* CONFIGURE: The mmap cache tries to keep the total number of mapped
|
||||
** files below this number, so you don't run out of kernel file descriptors.
|
||||
** If you have reconfigured your kernel to have more descriptors, you can
|
||||
** raise this and thttpd will keep more maps cached. However it's not
|
||||
** a hard limit, thttpd will go over it if you really are accessing
|
||||
** a whole lot of files.
|
||||
*/
|
||||
#define DESIRED_MAX_MAPPED_FILES 1000
|
||||
|
||||
/* CONFIGURE: The mmap cache also tries to keep the total mapped bytes
|
||||
** below this number, so you don't run out of address space. Again
|
||||
** it's not a hard limit, thttpd will go over it if you really are
|
||||
** accessing a bunch of large files.
|
||||
*/
|
||||
#define DESIRED_MAX_MAPPED_BYTES 1000000000
|
||||
|
||||
/* CONFIGURE: Minimum and maximum intervals between child-process reaping,
|
||||
** in seconds.
|
||||
*/
|
||||
#define MIN_REAP_TIME 30
|
||||
#define MAX_REAP_TIME 900
|
||||
|
||||
|
||||
/* You almost certainly don't want to change anything below here. */
|
||||
|
||||
/* CONFIGURE: When throttling CGI programs, we don't know how many bytes
|
||||
** they send back to the client because it would be inefficient to
|
||||
** interpose a counter. CGI programs are much more expensive than
|
||||
** regular files to serve, so we set an arbitrary and high byte count
|
||||
** that gets applied to all CGI programs for throttling purposes.
|
||||
*/
|
||||
#define CGI_BYTECOUNT 25000
|
||||
|
||||
/* CONFIGURE: The default port to listen on. 80 is the standard HTTP port.
|
||||
*/
|
||||
#define DEFAULT_PORT 80
|
||||
|
||||
/* CONFIGURE: A list of index filenames to check. The files are searched
|
||||
** for in this order.
|
||||
*/
|
||||
//#define INDEX_NAMES "index.html", "index.htm", "index.xhtml", "index.xht", "Default.htm", "index.cgi"
|
||||
|
||||
/* CONFIGURE: If this is defined then thttpd will automatically generate
|
||||
** index pages for directories that don't have an explicit index file.
|
||||
** If you want to disable this behavior site-wide, perhaps for security
|
||||
** reasons, just undefine this. Note that you can disable indexing of
|
||||
** individual directories by merely doing a "chmod 711" on them - the
|
||||
** standard Unix file permission to allow file access but disable "ls".
|
||||
*/
|
||||
#define GENERATE_INDEXES
|
||||
|
||||
/* CONFIGURE: Whether to log unknown request headers. Most sites will not
|
||||
** want to log them, which will save them a bit of CPU time.
|
||||
*/
|
||||
//#ifdef notdef
|
||||
//#define LOG_UNKNOWN_HEADERS
|
||||
//#endif
|
||||
|
||||
/* CONFIGURE: Whether to fflush() the log file after each request. If
|
||||
** this is turned off there's a slight savings in CPU cycles.
|
||||
*/
|
||||
#define FLUSH_LOG_EVERY_TIME
|
||||
|
||||
/* CONFIGURE: Time between updates of the throttle table's rolling averages. */
|
||||
#define THROTTLE_TIME 2
|
||||
|
||||
/* CONFIGURE: The listen() backlog queue length. The 1024 doesn't actually
|
||||
** get used, the kernel uses its maximum allowed value. This is a config
|
||||
** parameter only in case there's some OS where asking for too high a queue
|
||||
** length causes an error. Note that on many systems the maximum length is
|
||||
** way too small - see http://www.acme.com/software/thttpd/notes.html
|
||||
*/
|
||||
#define LISTEN_BACKLOG 1024
|
||||
|
||||
/* CONFIGURE: Maximum number of throttle patterns that any single URL can
|
||||
** be included in. This has nothing to do with the number of throttle
|
||||
** patterns that you can define, which is unlimited.
|
||||
*/
|
||||
#define MAXTHROTTLENUMS 10
|
||||
|
||||
/* CONFIGURE: Number of file descriptors to reserve for uses other than
|
||||
** connections. Currently this is 10, representing one for the listen fd,
|
||||
** one for dup()ing at connection startup time, one for reading the file,
|
||||
** one for syslog, and possibly one for the regular log file, which is
|
||||
** five, plus a factor of two for who knows what.
|
||||
*/
|
||||
#define SPARE_FDS 10
|
||||
|
||||
/* CONFIGURE: How many milliseconds to leave a connection open while doing a
|
||||
** lingering close.
|
||||
*/
|
||||
#define LINGER_TIME 500
|
||||
|
||||
/* CONFIGURE: Maximum number of symbolic links to follow before
|
||||
** assuming there's a loop.
|
||||
*/
|
||||
#define MAX_LINKS 32
|
||||
|
||||
/* CONFIGURE: You don't even want to know.
|
||||
*/
|
||||
#define MIN_WOULDBLOCK_DELAY 100L
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,301 @@
|
||||
/* libhttpd.h - defines for libhttpd
|
||||
**
|
||||
** Copyright © 1995,1998,1999,2000,2001 by Jef Poskanzer <jef@mail.acme.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBHTTPD_H_
|
||||
#define _LIBHTTPD_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED)
|
||||
#define USE_IPV6
|
||||
#endif
|
||||
|
||||
|
||||
/* A few convenient defines. */
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#define NEW(t,n) ((t*) malloc( sizeof(t) * (n) ))
|
||||
#define RENEW(o,t,n) ((t*) realloc( (void*) o, sizeof(t) * (n) ))
|
||||
|
||||
|
||||
/* The httpd structs. */
|
||||
|
||||
/* A multi-family sockaddr. */
|
||||
typedef union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa_in;
|
||||
#ifdef USE_IPV6
|
||||
struct sockaddr_in6 sa_in6;
|
||||
struct sockaddr_storage sa_stor;
|
||||
#endif /* USE_IPV6 */
|
||||
} httpd_sockaddr;
|
||||
|
||||
/* A server. */
|
||||
typedef struct {
|
||||
char* binding_hostname;
|
||||
char* server_hostname;
|
||||
unsigned short port;
|
||||
char* cgi_pattern;
|
||||
int cgi_limit, cgi_count;
|
||||
char* charset;
|
||||
char* p3p;
|
||||
int max_age;
|
||||
char* cwd;
|
||||
int listen4_fd, listen6_fd;
|
||||
int no_log;
|
||||
FILE* logfp;
|
||||
int no_symlink_check;
|
||||
int vhost;
|
||||
int global_passwd;
|
||||
char* url_pattern;
|
||||
char* local_pattern;
|
||||
int no_empty_referers;
|
||||
//added for poorman
|
||||
int do_list_dir;
|
||||
char* index_name;
|
||||
} httpd_server;
|
||||
|
||||
/* A connection. */
|
||||
typedef struct {
|
||||
int initialized;
|
||||
httpd_server* hs;
|
||||
httpd_sockaddr client_addr;
|
||||
char* read_buf;
|
||||
size_t read_size, read_idx, checked_idx;
|
||||
int checked_state;
|
||||
int method;
|
||||
int status;
|
||||
off_t bytes_to_send;
|
||||
off_t bytes_sent;
|
||||
char* encodedurl;
|
||||
char* decodedurl;
|
||||
char* protocol;
|
||||
char* origfilename;
|
||||
char* expnfilename;
|
||||
char* encodings;
|
||||
char* pathinfo;
|
||||
char* query;
|
||||
char* referer;
|
||||
char* useragent;
|
||||
char* accept;
|
||||
char* accepte;
|
||||
char* acceptl;
|
||||
char* cookie;
|
||||
char* contenttype;
|
||||
char* reqhost;
|
||||
char* hdrhost;
|
||||
char* hostdir;
|
||||
char* authorization;
|
||||
char* remoteuser;
|
||||
char* response;
|
||||
size_t maxdecodedurl, maxorigfilename, maxexpnfilename, maxencodings,
|
||||
maxpathinfo, maxquery, maxaccept, maxaccepte, maxreqhost, maxhostdir,
|
||||
maxremoteuser, maxresponse;
|
||||
#ifdef TILDE_MAP_2
|
||||
char* altdir;
|
||||
size_t maxaltdir;
|
||||
#endif /* TILDE_MAP_2 */
|
||||
size_t responselen;
|
||||
time_t if_modified_since, range_if;
|
||||
size_t contentlength;
|
||||
char* type; /* not malloc()ed */
|
||||
char* hostname; /* not malloc()ed */
|
||||
int mime_flag;
|
||||
int one_one; /* HTTP/1.1 or better */
|
||||
int got_range;
|
||||
int tildemapped; /* this connection got tilde-mapped */
|
||||
off_t first_byte_index, last_byte_index;
|
||||
int keep_alive;
|
||||
int should_linger;
|
||||
struct stat sb;
|
||||
int conn_fd;
|
||||
char* file_address;
|
||||
} httpd_conn;
|
||||
|
||||
/* Methods. */
|
||||
#define METHOD_UNKNOWN 0
|
||||
#define METHOD_GET 1
|
||||
#define METHOD_HEAD 2
|
||||
#define METHOD_POST 3
|
||||
|
||||
/* States for checked_state. */
|
||||
#define CHST_FIRSTWORD 0
|
||||
#define CHST_FIRSTWS 1
|
||||
#define CHST_SECONDWORD 2
|
||||
#define CHST_SECONDWS 3
|
||||
#define CHST_THIRDWORD 4
|
||||
#define CHST_THIRDWS 5
|
||||
#define CHST_LINE 6
|
||||
#define CHST_LF 7
|
||||
#define CHST_CR 8
|
||||
#define CHST_CRLF 9
|
||||
#define CHST_CRLFCR 10
|
||||
#define CHST_BOGUS 11
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializes. Does the socket(), bind(), and listen(). Returns an
|
||||
** httpd_server* which includes a socket fd that you can select() on.
|
||||
** Return (httpd_server*) 0 on error.
|
||||
*/
|
||||
extern httpd_server* httpd_initialize(
|
||||
char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P,
|
||||
unsigned short port, char* cgi_pattern, int cgi_limit, char* charset,
|
||||
char* p3p, int max_age, char* cwd, int no_log, FILE* logfp,
|
||||
int no_symlink_check, int vhost, int global_passwd, char* url_pattern,
|
||||
char* local_pattern, int no_empty_referers );
|
||||
|
||||
/* PoorMan: Initialize_listen_socket() is changed from static to extern.
|
||||
** httpd_unlisten() needs an opposite operation that can be accessed from
|
||||
** outside libhttpd. So this is it.
|
||||
*/
|
||||
extern int httpd_initialize_listen_socket( httpd_sockaddr* saP );
|
||||
|
||||
/* Change the log file. */
|
||||
extern void httpd_set_logfp( httpd_server* hs, FILE* logfp );
|
||||
|
||||
/* Call to unlisten/close socket(s) listening for new connections. */
|
||||
extern void httpd_unlisten( httpd_server* hs );
|
||||
|
||||
/* Call to shut down. */
|
||||
extern void httpd_terminate( httpd_server* hs );
|
||||
|
||||
|
||||
/* When a listen fd is ready to read, call this. It does the accept() and
|
||||
** returns an httpd_conn* which includes the fd to read the request from and
|
||||
** write the response to. Returns an indication of whether the accept()
|
||||
** failed, succeeded, or if there were no more connections to accept.
|
||||
**
|
||||
** In order to minimize malloc()s, the caller passes in the httpd_conn.
|
||||
** The caller is also responsible for setting initialized to zero before the
|
||||
** first call using each different httpd_conn.
|
||||
*/
|
||||
extern int httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc );
|
||||
#define GC_FAIL 0
|
||||
#define GC_OK 1
|
||||
#define GC_NO_MORE 2
|
||||
|
||||
/* Checks whether the data in hc->read_buf constitutes a complete request
|
||||
** yet. The caller reads data into hc->read_buf[hc->read_idx] and advances
|
||||
** hc->read_idx. This routine checks what has been read so far, using
|
||||
** hc->checked_idx and hc->checked_state to keep track, and returns an
|
||||
** indication of whether there is no complete request yet, there is a
|
||||
** complete request, or there won't be a valid request due to a syntax error.
|
||||
*/
|
||||
extern int httpd_got_request( httpd_conn* hc );
|
||||
#define GR_NO_REQUEST 0
|
||||
#define GR_GOT_REQUEST 1
|
||||
#define GR_BAD_REQUEST 2
|
||||
|
||||
/* Parses the request in hc->read_buf. Fills in lots of fields in hc,
|
||||
** like the URL and the various headers.
|
||||
**
|
||||
** Returns -1 on error.
|
||||
*/
|
||||
extern int httpd_parse_request( httpd_conn* hc );
|
||||
|
||||
/* Starts sending data back to the client. In some cases (directories,
|
||||
** CGI programs), finishes sending by itself - in those cases, hc->file_fd
|
||||
** is <0. If there is more data to be sent, then hc->file_fd is a file
|
||||
** descriptor for the file to send. If you don't have a current timeval
|
||||
** handy just pass in 0.
|
||||
**
|
||||
** Returns -1 on error.
|
||||
*/
|
||||
extern int httpd_start_request( httpd_conn* hc, struct timeval* nowP );
|
||||
|
||||
/* Actually sends any buffered response text. */
|
||||
extern void httpd_write_response( httpd_conn* hc );
|
||||
|
||||
/* Call this to close down a connection and free the data. A fine point,
|
||||
** if you fork() with a connection open you should still call this in the
|
||||
** parent process - the connection will stay open in the child.
|
||||
** If you don't have a current timeval handy just pass in 0.
|
||||
*/
|
||||
extern void httpd_close_conn( httpd_conn* hc, struct timeval* nowP );
|
||||
|
||||
/* Call this to de-initialize a connection struct and *really* free the
|
||||
** mallocced strings.
|
||||
*/
|
||||
extern void httpd_destroy_conn( httpd_conn* hc );
|
||||
|
||||
|
||||
/* Send an error message back to the client. */
|
||||
extern void httpd_send_err(
|
||||
httpd_conn* hc, int status, char* title, char* extraheads, char* form, char* arg );
|
||||
|
||||
/* Some error messages. */
|
||||
extern char* httpd_err400title;
|
||||
extern char* httpd_err400form;
|
||||
extern char* httpd_err408title;
|
||||
extern char* httpd_err408form;
|
||||
extern char* httpd_err503title;
|
||||
extern char* httpd_err503form;
|
||||
|
||||
/* Generate a string representation of a method number. */
|
||||
extern char* httpd_method_str( int method );
|
||||
|
||||
/* Reallocate a string. */
|
||||
extern void httpd_realloc_str( char** strP, size_t* maxsizeP, size_t size );
|
||||
|
||||
/* Format a network socket to a string representation. */
|
||||
extern char* httpd_ntoa( httpd_sockaddr* saP );
|
||||
|
||||
/* Set NDELAY mode on a socket. */
|
||||
extern void httpd_set_ndelay( int fd );
|
||||
|
||||
/* Clear NDELAY mode on a socket. */
|
||||
extern void httpd_clear_ndelay( int fd );
|
||||
|
||||
/* Read the requested buffer completely, accounting for interruptions. */
|
||||
extern int httpd_read_fully( int fd, void* buf, size_t nbytes );
|
||||
|
||||
/* Write the requested buffer completely, accounting for interruptions. */
|
||||
extern int httpd_write_fully( int fd, const void* buf, size_t nbytes );
|
||||
|
||||
/* Generate debugging statistics syslog message. */
|
||||
extern void httpd_logstats( long secs );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBHTTPD_H_ */
|
||||
@@ -0,0 +1,88 @@
|
||||
/* match.c - simple shell-style filename matcher
|
||||
**
|
||||
** Only does ? * and **, and multiple patterns separated by |. Returns 1 or 0.
|
||||
**
|
||||
** Copyright © 1995,2000 by Jef Poskanzer <jef@mail.acme.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "match.h"
|
||||
|
||||
static int match_one( const char* pattern, int patternlen, const char* string );
|
||||
|
||||
int
|
||||
match( const char* pattern, const char* string )
|
||||
{
|
||||
const char* or;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
or = strchr( pattern, '|' );
|
||||
if ( or == (char*) 0 )
|
||||
return match_one( pattern, strlen( pattern ), string );
|
||||
if ( match_one( pattern, or - pattern, string ) )
|
||||
return 1;
|
||||
pattern = or + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
match_one( const char* pattern, int patternlen, const char* string )
|
||||
{
|
||||
const char* p;
|
||||
|
||||
for ( p = pattern; p - pattern < patternlen; ++p, ++string )
|
||||
{
|
||||
if ( *p == '?' && *string != '\0' )
|
||||
continue;
|
||||
if ( *p == '*' )
|
||||
{
|
||||
int i, pl;
|
||||
++p;
|
||||
if ( *p == '*' )
|
||||
{
|
||||
/* Double-wildcard matches anything. */
|
||||
++p;
|
||||
i = strlen( string );
|
||||
}
|
||||
else
|
||||
/* Single-wildcard matches anything but slash. */
|
||||
i = strcspn( string, "/" );
|
||||
pl = patternlen - ( p - pattern );
|
||||
for ( ; i >= 0; --i )
|
||||
if ( match_one( p, pl, &(string[i]) ) )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if ( *p != *string )
|
||||
return 0;
|
||||
}
|
||||
if ( *string == '\0' )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/* match.h - simple shell-style filename patcher
|
||||
**
|
||||
** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MATCH_H_
|
||||
#define _MATCH_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Simple shell-style filename pattern matcher. Only does ? * and **, and
|
||||
** multiple patterns separated by |. Returns 1 or 0.
|
||||
*/
|
||||
extern int match( const char* pattern, const char* string );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MATCH_H_ */
|
||||
@@ -0,0 +1,8 @@
|
||||
# mime_encodings.txt
|
||||
#
|
||||
# A list of file extensions followed by the corresponding MIME encoding.
|
||||
# Extensions not found in the table proceed to the mime_types table.
|
||||
|
||||
Z compress
|
||||
gz gzip
|
||||
uu x-uuencode
|
||||
@@ -0,0 +1,195 @@
|
||||
# mime_types.txt
|
||||
#
|
||||
# A list of file extensions followed by the corresponding MIME type.
|
||||
# Extensions not found in the table are returned as text/plain.
|
||||
|
||||
a application/octet-stream
|
||||
aab application/x-authorware-bin
|
||||
aam application/x-authorware-map
|
||||
aas application/x-authorware-seg
|
||||
ai application/postscript
|
||||
aif audio/x-aiff
|
||||
aifc audio/x-aiff
|
||||
aiff audio/x-aiff
|
||||
asc text/plain
|
||||
asf video/x-ms-asf
|
||||
asx video/x-ms-asf
|
||||
au audio/basic
|
||||
avi video/x-msvideo
|
||||
bcpio application/x-bcpio
|
||||
bin application/octet-stream
|
||||
bmp image/bmp
|
||||
cdf application/x-netcdf
|
||||
class application/x-java-vm
|
||||
cpio application/x-cpio
|
||||
cpt application/mac-compactpro
|
||||
crl application/x-pkcs7-crl
|
||||
crt application/x-x509-ca-cert
|
||||
csh application/x-csh
|
||||
css text/css
|
||||
dcr application/x-director
|
||||
dir application/x-director
|
||||
djv image/vnd.djvu
|
||||
djvu image/vnd.djvu
|
||||
dll application/octet-stream
|
||||
dms application/octet-stream
|
||||
doc application/msword
|
||||
dtd text/xml
|
||||
dump application/octet-stream
|
||||
dvi application/x-dvi
|
||||
dxr application/x-director
|
||||
eps application/postscript
|
||||
etx text/x-setext
|
||||
exe application/octet-stream
|
||||
ez application/andrew-inset
|
||||
fgd application/x-director
|
||||
fh image/x-freehand
|
||||
fh4 image/x-freehand
|
||||
fh5 image/x-freehand
|
||||
fh7 image/x-freehand
|
||||
fhc image/x-freehand
|
||||
gif image/gif
|
||||
gtar application/x-gtar
|
||||
hdf application/x-hdf
|
||||
hqx application/mac-binhex40
|
||||
htm text/html
|
||||
html text/html
|
||||
ice x-conference/x-cooltalk
|
||||
ief image/ief
|
||||
iges model/iges
|
||||
igs model/iges
|
||||
iv application/x-inventor
|
||||
jar application/x-java-archive
|
||||
jfif image/jpeg
|
||||
jpe image/jpeg
|
||||
jpeg image/jpeg
|
||||
jpg image/jpeg
|
||||
js application/x-javascript
|
||||
kar audio/midi
|
||||
latex application/x-latex
|
||||
lha application/octet-stream
|
||||
lzh application/octet-stream
|
||||
m3u audio/x-mpegurl
|
||||
man application/x-troff-man
|
||||
mathml application/mathml+xml
|
||||
me application/x-troff-me
|
||||
mesh model/mesh
|
||||
mid audio/midi
|
||||
midi audio/midi
|
||||
mif application/vnd.mif
|
||||
mime message/rfc822
|
||||
mml application/mathml+xml
|
||||
mov video/quicktime
|
||||
movie video/x-sgi-movie
|
||||
mp2 audio/mpeg
|
||||
mp3 audio/mpeg
|
||||
mp4 video/mp4
|
||||
mpe video/mpeg
|
||||
mpeg video/mpeg
|
||||
mpg video/mpeg
|
||||
mpga audio/mpeg
|
||||
ms application/x-troff-ms
|
||||
msh model/mesh
|
||||
mv video/x-sgi-movie
|
||||
mxu video/vnd.mpegurl
|
||||
nc application/x-netcdf
|
||||
o application/octet-stream
|
||||
oda application/oda
|
||||
ogg application/x-ogg
|
||||
pac application/x-ns-proxy-autoconfig
|
||||
pbm image/x-portable-bitmap
|
||||
pdb chemical/x-pdb
|
||||
pdf application/pdf
|
||||
pgm image/x-portable-graymap
|
||||
pgn application/x-chess-pgn
|
||||
png image/png
|
||||
pnm image/x-portable-anymap
|
||||
ppm image/x-portable-pixmap
|
||||
ppt application/vnd.ms-powerpoint
|
||||
ps application/postscript
|
||||
qt video/quicktime
|
||||
ra audio/x-realaudio
|
||||
ram audio/x-pn-realaudio
|
||||
ras image/x-cmu-raster
|
||||
rdf application/rdf+xml
|
||||
rgb image/x-rgb
|
||||
rm audio/x-pn-realaudio
|
||||
roff application/x-troff
|
||||
rpm audio/x-pn-realaudio-plugin
|
||||
rss application/rss+xml
|
||||
rtf text/rtf
|
||||
rtx text/richtext
|
||||
sgm text/sgml
|
||||
sgml text/sgml
|
||||
sh application/x-sh
|
||||
shar application/x-shar
|
||||
silo model/mesh
|
||||
sit application/x-stuffit
|
||||
skd application/x-koan
|
||||
skm application/x-koan
|
||||
skp application/x-koan
|
||||
skt application/x-koan
|
||||
smi application/smil
|
||||
smil application/smil
|
||||
snd audio/basic
|
||||
so application/octet-stream
|
||||
spl application/x-futuresplash
|
||||
src application/x-wais-source
|
||||
stc application/vnd.sun.xml.calc.template
|
||||
std application/vnd.sun.xml.draw.template
|
||||
sti application/vnd.sun.xml.impress.template
|
||||
stw application/vnd.sun.xml.writer.template
|
||||
sv4cpio application/x-sv4cpio
|
||||
sv4crc application/x-sv4crc
|
||||
svg image/svg+xml
|
||||
svgz image/svg+xml
|
||||
swf application/x-shockwave-flash
|
||||
sxc application/vnd.sun.xml.calc
|
||||
sxd application/vnd.sun.xml.draw
|
||||
sxg application/vnd.sun.xml.writer.global
|
||||
sxi application/vnd.sun.xml.impress
|
||||
sxm application/vnd.sun.xml.math
|
||||
sxw application/vnd.sun.xml.writer
|
||||
t application/x-troff
|
||||
tar application/x-tar
|
||||
tcl application/x-tcl
|
||||
tex application/x-tex
|
||||
texi application/x-texinfo
|
||||
texinfo application/x-texinfo
|
||||
tif image/tiff
|
||||
tiff image/tiff
|
||||
tr application/x-troff
|
||||
tsp application/dsptype
|
||||
tsv text/tab-separated-values
|
||||
txt text/plain
|
||||
ustar application/x-ustar
|
||||
vcd application/x-cdlink
|
||||
vrml model/vrml
|
||||
vx video/x-rad-screenplay
|
||||
wav audio/x-wav
|
||||
wax audio/x-ms-wax
|
||||
wbmp image/vnd.wap.wbmp
|
||||
wbxml application/vnd.wap.wbxml
|
||||
wm video/x-ms-wm
|
||||
wma audio/x-ms-wma
|
||||
wmd application/x-ms-wmd
|
||||
wml text/vnd.wap.wml
|
||||
wmlc application/vnd.wap.wmlc
|
||||
wmls text/vnd.wap.wmlscript
|
||||
wmlsc application/vnd.wap.wmlscriptc
|
||||
wmv video/x-ms-wmv
|
||||
wmx video/x-ms-wmx
|
||||
wmz application/x-ms-wmz
|
||||
wrl model/vrml
|
||||
wsrc application/x-wais-source
|
||||
wvx video/x-ms-wvx
|
||||
xbm image/x-xbitmap
|
||||
xht application/xhtml+xml
|
||||
xhtml application/xhtml+xml
|
||||
xls application/vnd.ms-excel
|
||||
xml text/xml
|
||||
xpm image/x-xpixmap
|
||||
xsl text/xml
|
||||
xwd image/x-xwindowdump
|
||||
xyz chemical/x-xyz
|
||||
zip application/zip
|
||||
@@ -0,0 +1,356 @@
|
||||
/* tdate_parse - parse string dates into internal form, stripped-down version
|
||||
**
|
||||
** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This is a stripped-down version of date_parse.c, available at
|
||||
** http://www.acme.com/software/date_parse/
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tdate_parse.h"
|
||||
|
||||
|
||||
struct strlong {
|
||||
char* s;
|
||||
long l;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
pound_case( char* str )
|
||||
{
|
||||
for ( ; *str != '\0'; ++str )
|
||||
{
|
||||
if ( isupper( (int) *str ) )
|
||||
*str = tolower( (int) *str );
|
||||
}
|
||||
}
|
||||
|
||||
//static int
|
||||
//strlong_compare( v1, v2 )
|
||||
// char* v1;
|
||||
// char* v2;
|
||||
// {
|
||||
// return strcmp( ((struct strlong*) v1)->s, ((struct strlong*) v2)->s );
|
||||
// }
|
||||
|
||||
|
||||
static int
|
||||
strlong_search( char* str, const struct strlong* tab, int n, long* lP )
|
||||
{
|
||||
int i, h, l, r;
|
||||
|
||||
l = 0;
|
||||
h = n - 1;
|
||||
for (;;)
|
||||
{
|
||||
i = ( h + l ) / 2;
|
||||
r = strcmp( str, tab[i].s );
|
||||
if ( r < 0 )
|
||||
h = i - 1;
|
||||
else if ( r > 0 )
|
||||
l = i + 1;
|
||||
else
|
||||
{
|
||||
*lP = tab[i].l;
|
||||
return 1;
|
||||
}
|
||||
if ( h < l )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
scan_wday( char* str_wday, long* tm_wdayP )
|
||||
{
|
||||
// static struct strlong wday_tab[] = {
|
||||
// { "sun", 0 }, { "sunday", 0 },
|
||||
// { "mon", 1 }, { "monday", 1 },
|
||||
// { "tue", 2 }, { "tuesday", 2 },
|
||||
// { "wed", 3 }, { "wednesday", 3 },
|
||||
// { "thu", 4 }, { "thursday", 4 },
|
||||
// { "fri", 5 }, { "friday", 5 },
|
||||
// { "sat", 6 }, { "saturday", 6 },
|
||||
// };
|
||||
// static int sorted = 0;
|
||||
//
|
||||
// if ( ! sorted )
|
||||
// {
|
||||
// (void) qsort(
|
||||
// wday_tab, sizeof(wday_tab)/sizeof(struct strlong),
|
||||
// sizeof(struct strlong), strlong_compare );
|
||||
// sorted = 1;
|
||||
// }
|
||||
|
||||
/*manually sorted wday_tab to avoid concurrent accessing problem*/
|
||||
static const struct strlong wday_tab[] = {
|
||||
{ "fri", 5 }, { "friday", 5 },
|
||||
{ "mon", 1 }, { "monday", 1 },
|
||||
{ "sat", 6 }, { "saturday", 6 },
|
||||
{ "sun", 0 }, { "sunday", 0 },
|
||||
{ "thu", 4 }, { "thursday", 4 },
|
||||
{ "tue", 2 }, { "tuesday", 2 },
|
||||
{ "wed", 3 }, { "wednesday", 3 }
|
||||
};
|
||||
|
||||
pound_case( str_wday );
|
||||
return strlong_search(
|
||||
str_wday, wday_tab, sizeof(wday_tab)/sizeof(struct strlong), tm_wdayP );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
scan_mon( char* str_mon, long* tm_monP )
|
||||
{
|
||||
// static struct strlong mon_tab[] = {
|
||||
// { "jan", 0 }, { "january", 0 },
|
||||
// { "feb", 1 }, { "february", 1 },
|
||||
// { "mar", 2 }, { "march", 2 },
|
||||
// { "apr", 3 }, { "april", 3 },
|
||||
// { "may", 4 },
|
||||
// { "jun", 5 }, { "june", 5 },
|
||||
// { "jul", 6 }, { "july", 6 },
|
||||
// { "aug", 7 }, { "august", 7 },
|
||||
// { "sep", 8 }, { "september", 8 },
|
||||
// { "oct", 9 }, { "october", 9 },
|
||||
// { "nov", 10 }, { "november", 10 },
|
||||
// { "dec", 11 }, { "december", 11 },
|
||||
// };
|
||||
// static int sorted = 0;
|
||||
//
|
||||
// if ( ! sorted )
|
||||
// {
|
||||
// (void) qsort(
|
||||
// mon_tab, sizeof(mon_tab)/sizeof(struct strlong),
|
||||
// sizeof(struct strlong), strlong_compare );
|
||||
// sorted = 1;
|
||||
// }
|
||||
|
||||
/*manually sorted mon_tab to avoid concurrent accessing problem*/
|
||||
static const struct strlong mon_tab[] = {
|
||||
{ "apr", 3 }, { "april", 3 },
|
||||
{ "aug", 7 }, { "august", 7 },
|
||||
{ "dec", 11}, { "december", 11 },
|
||||
{ "feb", 1 }, { "february", 1 },
|
||||
{ "jan", 0 }, { "january", 0 },
|
||||
{ "jul", 6 }, { "july", 6 },
|
||||
{ "jun", 5 }, { "june", 5 },
|
||||
{ "mar", 2 }, { "march", 2 },
|
||||
{ "may", 4 },
|
||||
{ "nov", 10}, { "november", 10 },
|
||||
{ "oct", 9 }, { "october", 9 },
|
||||
{ "sep", 8 }, { "september", 8 }
|
||||
};
|
||||
|
||||
pound_case( str_mon );
|
||||
return strlong_search(
|
||||
str_mon, mon_tab, sizeof(mon_tab)/sizeof(struct strlong), tm_monP );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
is_leap( int year )
|
||||
{
|
||||
return year % 400? ( year % 100 ? ( year % 4 ? 0 : 1 ) : 0 ) : 1;
|
||||
}
|
||||
|
||||
|
||||
/* Basically the same as mktime(). */
|
||||
static time_t
|
||||
tm_to_time( struct tm* tmP )
|
||||
{
|
||||
time_t t;
|
||||
static int monthtab[12] = {
|
||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||||
|
||||
/* Years since epoch, converted to days. */
|
||||
t = ( tmP->tm_year - 70 ) * 365;
|
||||
/* Leap days for previous years. */
|
||||
t += ( tmP->tm_year - 69 ) / 4;
|
||||
/* Days for the beginning of this month. */
|
||||
t += monthtab[tmP->tm_mon];
|
||||
/* Leap day for this year. */
|
||||
if ( tmP->tm_mon >= 2 && is_leap( tmP->tm_year + 1900 ) )
|
||||
++t;
|
||||
/* Days since the beginning of this month. */
|
||||
t += tmP->tm_mday - 1; /* 1-based field */
|
||||
/* Hours, minutes, and seconds. */
|
||||
t = t * 24 + tmP->tm_hour;
|
||||
t = t * 60 + tmP->tm_min;
|
||||
t = t * 60 + tmP->tm_sec;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
time_t
|
||||
tdate_parse( char* str )
|
||||
{
|
||||
struct tm tm;
|
||||
char* cp;
|
||||
char str_mon[500], str_wday[500];
|
||||
int tm_sec, tm_min, tm_hour, tm_mday, tm_year;
|
||||
long tm_mon, tm_wday;
|
||||
time_t t;
|
||||
|
||||
/* Initialize. */
|
||||
(void) memset( (char*) &tm, 0, sizeof(struct tm) );
|
||||
|
||||
/* Skip initial whitespace ourselves - sscanf is clumsy at this. */
|
||||
for ( cp = str; *cp == ' ' || *cp == '\t'; ++cp )
|
||||
continue;
|
||||
|
||||
/* And do the sscanfs. WARNING: you can add more formats here,
|
||||
** but be careful! You can easily screw up the parsing of existing
|
||||
** formats when you add new ones. The order is important.
|
||||
*/
|
||||
|
||||
/* DD-mth-YY HH:MM:SS GMT */
|
||||
if ( sscanf( cp, "%d-%400[a-zA-Z]-%d %d:%d:%d GMT",
|
||||
&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
|
||||
&tm_sec ) == 6 &&
|
||||
scan_mon( str_mon, &tm_mon ) )
|
||||
{
|
||||
tm.tm_mday = tm_mday;
|
||||
tm.tm_mon = tm_mon;
|
||||
tm.tm_year = tm_year;
|
||||
tm.tm_hour = tm_hour;
|
||||
tm.tm_min = tm_min;
|
||||
tm.tm_sec = tm_sec;
|
||||
}
|
||||
|
||||
/* DD mth YY HH:MM:SS GMT */
|
||||
else if ( sscanf( cp, "%d %400[a-zA-Z] %d %d:%d:%d GMT",
|
||||
&tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
|
||||
&tm_sec) == 6 &&
|
||||
scan_mon( str_mon, &tm_mon ) )
|
||||
{
|
||||
tm.tm_mday = tm_mday;
|
||||
tm.tm_mon = tm_mon;
|
||||
tm.tm_year = tm_year;
|
||||
tm.tm_hour = tm_hour;
|
||||
tm.tm_min = tm_min;
|
||||
tm.tm_sec = tm_sec;
|
||||
}
|
||||
|
||||
/* HH:MM:SS GMT DD-mth-YY */
|
||||
else if ( sscanf( cp, "%d:%d:%d GMT %d-%400[a-zA-Z]-%d",
|
||||
&tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon,
|
||||
&tm_year ) == 6 &&
|
||||
scan_mon( str_mon, &tm_mon ) )
|
||||
{
|
||||
tm.tm_hour = tm_hour;
|
||||
tm.tm_min = tm_min;
|
||||
tm.tm_sec = tm_sec;
|
||||
tm.tm_mday = tm_mday;
|
||||
tm.tm_mon = tm_mon;
|
||||
tm.tm_year = tm_year;
|
||||
}
|
||||
|
||||
/* HH:MM:SS GMT DD mth YY */
|
||||
else if ( sscanf( cp, "%d:%d:%d GMT %d %400[a-zA-Z] %d",
|
||||
&tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon,
|
||||
&tm_year ) == 6 &&
|
||||
scan_mon( str_mon, &tm_mon ) )
|
||||
{
|
||||
tm.tm_hour = tm_hour;
|
||||
tm.tm_min = tm_min;
|
||||
tm.tm_sec = tm_sec;
|
||||
tm.tm_mday = tm_mday;
|
||||
tm.tm_mon = tm_mon;
|
||||
tm.tm_year = tm_year;
|
||||
}
|
||||
|
||||
/* wdy, DD-mth-YY HH:MM:SS GMT */
|
||||
else if ( sscanf( cp, "%400[a-zA-Z], %d-%400[a-zA-Z]-%d %d:%d:%d GMT",
|
||||
str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
|
||||
&tm_sec ) == 7 &&
|
||||
scan_wday( str_wday, &tm_wday ) &&
|
||||
scan_mon( str_mon, &tm_mon ) )
|
||||
{
|
||||
tm.tm_wday = tm_wday;
|
||||
tm.tm_mday = tm_mday;
|
||||
tm.tm_mon = tm_mon;
|
||||
tm.tm_year = tm_year;
|
||||
tm.tm_hour = tm_hour;
|
||||
tm.tm_min = tm_min;
|
||||
tm.tm_sec = tm_sec;
|
||||
}
|
||||
|
||||
/* wdy, DD mth YY HH:MM:SS GMT */
|
||||
else if ( sscanf( cp, "%400[a-zA-Z], %d %400[a-zA-Z] %d %d:%d:%d GMT",
|
||||
str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
|
||||
&tm_sec ) == 7 &&
|
||||
scan_wday( str_wday, &tm_wday ) &&
|
||||
scan_mon( str_mon, &tm_mon ) )
|
||||
{
|
||||
tm.tm_wday = tm_wday;
|
||||
tm.tm_mday = tm_mday;
|
||||
tm.tm_mon = tm_mon;
|
||||
tm.tm_year = tm_year;
|
||||
tm.tm_hour = tm_hour;
|
||||
tm.tm_min = tm_min;
|
||||
tm.tm_sec = tm_sec;
|
||||
}
|
||||
|
||||
/* wdy mth DD HH:MM:SS GMT YY */
|
||||
else if ( sscanf( cp, "%400[a-zA-Z] %400[a-zA-Z] %d %d:%d:%d GMT %d",
|
||||
str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec,
|
||||
&tm_year ) == 7 &&
|
||||
scan_wday( str_wday, &tm_wday ) &&
|
||||
scan_mon( str_mon, &tm_mon ) )
|
||||
{
|
||||
tm.tm_wday = tm_wday;
|
||||
tm.tm_mon = tm_mon;
|
||||
tm.tm_mday = tm_mday;
|
||||
tm.tm_hour = tm_hour;
|
||||
tm.tm_min = tm_min;
|
||||
tm.tm_sec = tm_sec;
|
||||
tm.tm_year = tm_year;
|
||||
}
|
||||
else
|
||||
return (time_t) -1;
|
||||
|
||||
if ( tm.tm_year > 1900 )
|
||||
tm.tm_year -= 1900;
|
||||
else if ( tm.tm_year < 70 )
|
||||
tm.tm_year += 100;
|
||||
|
||||
t = tm_to_time( &tm );
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/* tdate_parse.h - parse string dates into internal form, stripped-down version
|
||||
**
|
||||
** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TDATE_PARSE_H_
|
||||
#define _TDATE_PARSE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern time_t tdate_parse( char* str );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TDATE_PARSE_H_ */
|
||||
@@ -0,0 +1,9 @@
|
||||
/* version.h - version defines for thttpd and libhttpd */
|
||||
|
||||
#ifndef _VERSION_H_
|
||||
#define _VERSION_H_
|
||||
|
||||
#define SERVER_SOFTWARE "Haiku/PoorMan"
|
||||
#define SERVER_ADDRESS "http://www.haiku-os.org/"
|
||||
|
||||
#endif /* _VERSION_H_ */
|
||||
Reference in New Issue
Block a user