summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Buffer.cc9
-rw-r--r--lib/CopyJob.cc8
-rw-r--r--lib/Exceptions.cc55
-rw-r--r--lib/Handle.cc8
-rw-r--r--lib/HttpServ.cc59
-rw-r--r--lib/InPipe.cc31
-rw-r--r--lib/Input.cc16
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/OutPipe.cc31
-rw-r--r--lib/String.cc38
-rw-r--r--lib/Variables.cc8
11 files changed, 206 insertions, 59 deletions
diff --git a/lib/Buffer.cc b/lib/Buffer.cc
index b3cb10b..afbaa6f 100644
--- a/lib/Buffer.cc
+++ b/lib/Buffer.cc
@@ -10,6 +10,9 @@ Buffer::~Buffer() {
}
ssize_t Buffer::write(const void *buf, size_t count) {
+ if (!count) {
+ return 0;
+ }
if (count + realsiz > bufsiz) {
int numblocks = (count + realsiz) / realloc_threshold;
int remains = (count + realsiz) % realloc_threshold;
@@ -33,10 +36,10 @@ ssize_t Buffer::read(void *buf, size_t count) throw (GeneralException) {
if (ptr >= realloc_threshold) {
int numblocks = (bufsiz / realloc_threshold) - (ptr / realloc_threshold);
- memmove(buffer, buffer + numblocks * realloc_threshold, numblocks * realloc_threshold);
+ memmove(buffer, buffer + (bufsiz - numblocks * realloc_threshold), numblocks * realloc_threshold);
+ ptr -= (bufsiz - numblocks * realloc_threshold);
+ realsiz -= (bufsiz - numblocks * realloc_threshold);
buffer = (char *) realloc(buffer, bufsiz = (numblocks * realloc_threshold));
- ptr -= numblocks * realloc_threshold;
- realsiz -= numblocks * realloc_threshold;
}
return count;
diff --git a/lib/CopyJob.cc b/lib/CopyJob.cc
index 7b4694a..a736e9d 100644
--- a/lib/CopyJob.cc
+++ b/lib/CopyJob.cc
@@ -4,7 +4,6 @@
CopyJob::CopyJob(Handle * as, Handle * ad, ssize_t asiz, bool ads) : s(as), d(ad), ds(ads), siz(asiz), cursiz(0), r(0) {
WaitFor(s, W4_STICKY | W4_READING);
WaitFor(d, W4_STICKY | W4_WRITING);
- cerr << "Creating a copyjob from " << s->GetName() << " to " << d->GetName() << " of " << siz << " bytes.\n";
}
CopyJob::~CopyJob() { }
@@ -12,18 +11,13 @@ CopyJob::~CopyJob() { }
int CopyJob::Do() throw (GeneralException) {
int tr;
- cerr << GetName() << " running...\n";
-
switch (current) {
case 0:
tr = siz >= 0 ? siz - cursiz : COPY_BUFSIZ;
- cerr << "Reading " << tr << " bytes.\n";
try {
r = s->read(buffer, MIN(COPY_BUFSIZ, tr));
- cerr << "Got " << r << " bytes.\n";
}
catch (IOAgain e) {
- cerr << "Not enough bytes. Suspending.\n";
Suspend();
}
case 1:
@@ -31,12 +25,10 @@ int CopyJob::Do() throw (GeneralException) {
return TASK_DONE;
}
try {
- cerr << "Writing " << r << " bytes.\n";
d->write(buffer, r);
}
catch (IOAgain e) {
current = 1;
- cerr << "No more byte in the output. Suspending.\n";
Suspend();
}
current = 0;
diff --git a/lib/Exceptions.cc b/lib/Exceptions.cc
index 585b946..6e4ddbe 100644
--- a/lib/Exceptions.cc
+++ b/lib/Exceptions.cc
@@ -6,6 +6,7 @@
#include "config.h"
#include "String.h"
#include "Exceptions.h"
+#include "General.h"
char GeneralException::t[BUFSIZ];
@@ -60,35 +61,49 @@ TaskSwitch::TaskSwitch() : GeneralException(_("Switching task in a non-tasked en
#endif
}
-char * xstrdup(const char * s) throw (GeneralException) {
+char * xstrdup(const char * s) {
char * r;
- if (!(r = ::strdup(s))) {
- throw MemoryException(strlen(s + 1));
- }
-
+ r = (char *) xmalloc(strlen(s) + 1);
+ strcpy(r, s);
return r;
}
-void * xmalloc(ssize_t s) throw (GeneralException) {
- void * r;
+void * xmalloc(size_t s) throw (GeneralException) {
+ char * r;
+
+ if (!s) {
+ return 0;
+ }
- if (!(r = ::malloc(s))) {
- throw MemoryException(s);
+ if (!(r = (char *) ::malloc(s + sizeof(size_t)))) {
+ throw MemoryException(s + sizeof(size_t));
}
- memset(r, 0, s);
+ memset(r, 0, s + sizeof(size_t));
+
+ *((size_t *)r) = s;
- return r;
+ return (void *)(r + sizeof(size_t));
}
-void * xrealloc(void * ptr, size_t s) throw (GeneralException) {
- void * r;
+void * xrealloc(void * ptr, size_t s) {
+ char * r;
+ size_t os;
- if (!(r = ::realloc(ptr, s))) {
- throw MemoryException(s);
+ if (!ptr) {
+ return xmalloc(s);
}
+ os = *(((size_t *) ptr) - 1);
+
+ r = (char *) xmalloc(s);
+
+ if (s) {
+ memcpy(r, ptr, MIN(s, os));
+ }
+
+ xfree(ptr);
return r;
}
@@ -98,7 +113,15 @@ void * xrealloc(void * ptr, size_t s) throw (GeneralException) {
void xfree(void *& p) {
if (p) {
- ::free(p);
+ ::free(((char *)p) - sizeof(size_t));
p = 0;
}
}
+
+int xpipe(int * p, int flag) throw (GeneralException) {
+ if (pipe(p)) {
+ throw GeneralException(String("Error creating pipe: ") + strerror(errno));
+ }
+
+ return p[flag];
+}
diff --git a/lib/Handle.cc b/lib/Handle.cc
index 30ad7ef..e158511 100644
--- a/lib/Handle.cc
+++ b/lib/Handle.cc
@@ -147,3 +147,11 @@ bool Handle::CanWrite(void) {
String Handle::GetName(void) {
return _("Bare Handle - should not happend");
}
+
+off_t Handle::GetSize(void) {
+ return -1;
+}
+
+time_t Handle::GetModif(void) {
+ return -1;
+}
diff --git a/lib/HttpServ.cc b/lib/HttpServ.cc
index 1fa656a..8b28878 100644
--- a/lib/HttpServ.cc
+++ b/lib/HttpServ.cc
@@ -21,7 +21,7 @@ class ProcessRequest : public Task {
bool ParseUri(String &, String &, Handle *);
void ParseVars(Handle *, int);
void ShowError(Handle *);
- void SendHeads(Handle *, const String &);
+ void SendHeads(Handle *, const String &, const String & = "", time_t = -1);
void SendRedirect(Handle *);
String file, domain, t;
@@ -58,19 +58,21 @@ int ProcessRequest::Do() {
bad = false;
- cerr << "Got a request\n----\n";
+ cerr << "---- Got a request\n";
post = ParseUri(file, domain, &b);
len = -1;
do {
b >> t;
- // cerr << t << endl;
+ cerr << "Read Request (n): " << t << endl;
if ((t.strstr("Content-Length: ") == 0) || (t.strstr("Content-length: ") == 0)) {
cerr << "Saw 'Content-Lenght:', reading length from '" << t.extract(16) << "'\n";
len = t.extract(16).to_int();
}
} while (t.strlen());
+
+ cerr << "---- Processing it.\n";
hasvars = false;
@@ -78,6 +80,7 @@ int ProcessRequest::Do() {
// On a pas eu de ligne 'Content-Length' mais on a eu une méthode POST.
// Cela est une erreur.
if (len == -1) {
+ cerr << "Error: method POST but no Content-Length\n";
bad = true;
Vars = new Variables();
} else {
@@ -114,6 +117,9 @@ int ProcessRequest::Do() {
if (domain == "/image") bad = false;
if (domain == "/bin") bad = false;
if (domain == "/") bad = false;
+ if (bad) {
+ cerr << "Error: bad domain.\n";
+ }
} else {
// L'url sans domaine ni fichier est valide. (cela arrive sur certains navigateurs...)
bad = (file != "");
@@ -132,7 +138,7 @@ int ProcessRequest::Do() {
} else if (domain == "/bin") {
// Le domaine 'bin' est réservé aux actions. On cherche donc l'action à effectuer.
if ((f = p->Look4URL(file))) {
- SendHeads(&s, "text/html");
+ SendHeads(&b, "text/html");
a = f->Do(Vars, &s);
} else {
ShowError(&b);
@@ -143,8 +149,8 @@ int ProcessRequest::Do() {
// d'input renvoie une erreur.
try {
Handle * i = new Input(String("datas/") + file);
- SendHeads(&b, GetMime(file));
- a = new CopyJob(i, &s, -1, true);
+ SendHeads(&b, GetMime(file), String("Accept-Ranges: bytes") + endhl + "Content-Length: " + (unsigned long long int) i->GetSize() + endhl, i->GetModif());
+ a = new CopyJob(i, &s);
cerr << "File found, dumping.\n";
}
catch (IOGeneral e) {
@@ -157,7 +163,8 @@ int ProcessRequest::Do() {
if (a) a->Stop();
delete Vars;
- c = new CopyJob(&b, &s);
+ cerr << "---- Sending header buffer.\n";
+ c = new CopyJob(&b, &s, -1, false);
WaitFor(c);
current = 3;
Suspend();
@@ -166,6 +173,7 @@ int ProcessRequest::Do() {
delete c;
if (a) {
+ cerr << "---- Sending contents.\n";
a->Restart();
WaitFor(a);
current = 4;
@@ -175,7 +183,7 @@ int ProcessRequest::Do() {
case 4:
if (a) delete a;
- cerr << "----\n";
+ cerr << "---- End of Request.\n";
}
return TASK_DONE;
}
@@ -247,34 +255,31 @@ bool ProcessRequest::ParseUri(String & file, String & domain, Handle * s) {
ssize_t sppos;
*s >> t;
- cerr << t << endl;
+ cerr << "Read Request (1): " << t << endl;
bad = false;
// p nous indiquera la position de la chaîne URL.
switch (t[0]) {
case 'P': /* POST? */
- cerr << "Do we have a POST request? ";
if (t.extract(1, 4) == "OST ") {
- cerr << "Yes.\n";
p = t.to_charp(5);
post = true;
} else {
- cerr << "No.\n";
+ cerr << "Error: unknow request.\n";
bad = true;
}
break;
case 'G': /* GET? */
- cerr << "Do we have a GET request? ";
if (t.extract(1, 3) == "ET ") {
- cerr << "Yes.\n";
p = t.to_charp(4);
} else {
- cerr << "No.\n";
+ cerr << "Error: unknow request.\n";
bad = true;
}
break;
default:
+ cerr << "Error: unknow request.\n";
bad = true;
}
@@ -314,7 +319,7 @@ void ProcessRequest::SendRedirect(Handle * s) {
"Server: " << name << endhl <<
"Location: http://127.0.0.1:" << localport << "/bin/start" << endhl <<
"Cache-Control: no-cache" << endhl <<
- "Connection-Type: closed" << endhl <<
+ "Connection: closed" << endhl <<
"Content-Type: text/html" << endhl << endhl <<
"<HTML><HEAD><TITLE>301 - Moved Permanently</TITLE></HEAD>" << endnl <<
"<BODY><center><b><h2>You should be redirected to the " << endnl << endnl <<
@@ -326,12 +331,22 @@ void ProcessRequest::SendRedirect(Handle * s) {
* Nous envoyons les entetes de réponse HTTP.
*/
-void ProcessRequest::SendHeads(Handle * s, const String & mime) {
+void ProcessRequest::SendHeads(Handle * s, const String & mime, const String & extra, time_t lm) {
+ time_t t = time(NULL);
+ struct tm * ft = gmtime(&t);
+ char buf[1024];
+ strftime(buf, 1024, "%a, %d %b %Y %H:%M:%S GMT", ft);
*s << "HTTP/1.1 200 OK" << endhl <<
- "Server: " << name << endhl <<
- "Cache-Control: no-cache" << endhl <<
- "Connection-Type: closed" << endhl <<
- "Content-Type: " << mime << endhl << endhl;
+ "Date: " << buf << endhl <<
+ "Server: " << name << endhl;
+ if (lm >=0) {
+ ft = gmtime(&lm);
+ strftime(buf, 1024, "%a, %d %b %Y %H:%M:%S GMT", ft);
+ }
+ *s << "Last-Modified: " << buf << endhl << extra <<
+ "Keep-Alive: timeout=0, max=0" << endhl <<
+ "Connection: Keep-Alive" << endhl <<
+ "Content-Type: " << mime << endhl << endhl;
}
/*
@@ -342,7 +357,7 @@ void ProcessRequest::ShowError(Handle * s) {
*s << "HTTP/1.1 404 Not Found" << endhl <<
"Server: " << name << endhl <<
"Cache-Control: no-cache" << endhl <<
- "Connection-Type: closed" << endhl <<
+ "Connection: closed" << endhl <<
"Content-Type: text/html" << endhl << endhl <<
"<HTML><HEAD><TITLE>404 - Error</TITLE></HEAD>" << endnl <<
"<BODY><center><b><h2>The server was unable to process your query</h2></b></center>" << endnl <<
diff --git a/lib/InPipe.cc b/lib/InPipe.cc
new file mode 100644
index 0000000..60f3751
--- /dev/null
+++ b/lib/InPipe.cc
@@ -0,0 +1,31 @@
+#include "InPipe.h"
+#include "Output.h"
+
+InPipe::InPipe() : Handle(pipe(p, 0)), hooked(0) { }
+
+InPipe::~InPipe() {
+ if (hooked) {
+ ::close(1);
+ dup(Stdout.GetHandle());
+ }
+}
+
+void InPipe::Hook() {
+ if (!hooked) {
+ hooked = 1;
+ ::close(1);
+ dup(p[1]);
+ }
+}
+
+bool InPipe::CanWrite() {
+ return false;
+}
+
+bool InPipe::CanRead() {
+ return true;
+}
+
+String InPipe::GetName() {
+ return (String("Input pipe from stdout (") + (hooked ? "" : "not ") + "hooked)");
+}
diff --git a/lib/Input.cc b/lib/Input.cc
index df0222a..a466468 100644
--- a/lib/Input.cc
+++ b/lib/Input.cc
@@ -18,6 +18,14 @@ Input::Input(String no) throw (GeneralException) :
}
cerr << "File " << no << " is opened with handle " << GetHandle() << endl;
+ size = lseek(GetHandle(), 0, SEEK_END);
+ lseek(GetHandle(), 0, SEEK_SET);
+
+ struct stat s;
+
+ fstat(GetHandle(), &s);
+
+ date_modif = s.st_mtime;
}
bool Input::CanWrite() {
@@ -32,6 +40,14 @@ String Input::GetName() {
return n;
}
+off_t Input::GetSize() {
+ return size;
+}
+
+time_t Input::GetModif() {
+ return date_modif;
+}
+
Stdin_t::Stdin_t() : Handle(dup(0)) { }
bool Stdin_t::CanWrite() {
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9778018..a88f7be 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -8,6 +8,6 @@ lib_LTLIBRARIES = libBaltisot.la
libBaltisot_la_SOURCES = Exceptions.cc Handle.cc Output.cc String.cc\
Socket.cc Input.cc HttpServ.cc Variables.cc Action.cc Menu.cc Message.cc\
Form.cc Confirm.cc Table.cc checkargs.c datecalc.c IRC.cc Task.cc Buffer.cc\
- CopyJob.cc ReadJob.cc Regex.cc TaskMan.cc
+ CopyJob.cc ReadJob.cc Regex.cc TaskMan.cc InPipe.cc OutPipe.cc
libBaltisot_la_LDFLAGS = -release $(Baltisot_VERSION_INFO)
diff --git a/lib/OutPipe.cc b/lib/OutPipe.cc
new file mode 100644
index 0000000..456a5bd
--- /dev/null
+++ b/lib/OutPipe.cc
@@ -0,0 +1,31 @@
+#include "OutPipe.h"
+#include "Input.h"
+
+OutPipe::OutPipe() : Handle(pipe(p, 1)), hooked(0) { }
+
+OutPipe::~OutPipe() {
+ if (hooked) {
+ ::close(0);
+ dup(Stdin.GetHandle());
+ }
+}
+
+void OutPipe::Hook() {
+ if (!hooked) {
+ hooked = 1;
+ ::close(0);
+ dup(p[0]);
+ }
+}
+
+bool OutPipe::CanWrite() {
+ return false;
+}
+
+bool OutPipe::CanRead() {
+ return true;
+}
+
+String OutPipe::GetName() {
+ return (String("Input pipe from stdout (") + (hooked ? "" : "not ") + "hooked)");
+}
diff --git a/lib/String.cc b/lib/String.cc
index 39ea9d8..fa1db50 100644
--- a/lib/String.cc
+++ b/lib/String.cc
@@ -12,7 +12,7 @@ extern "C" {
char String::t[BUFSIZ + 1];
-String::String(const String & s) : str(::strdup(s.str)), siz(s.siz) { }
+String::String(const String & s) : str(Base::strdup(s.str)), siz(s.siz) { }
String::String(char c) : siz(1) {
char * t = (char *) malloc(2);
@@ -21,17 +21,41 @@ String::String(char c) : siz(1) {
str = t;
}
-String::String(const char * s) : str(s ? ::strdup(s) : ::strdup("")) {
+String::String(const char * s) : str(s ? Base::strdup(s) : Base::strdup("")) {
siz = ::strlen(str);
}
-String::String(int hs, const char * s) : str(s ? ::strdup(s) : ::strdup("")), siz(hs) { }
+String::String(int hs, const char * s) : str(s ? Base::strdup(s) : Base::strdup("")), siz(hs) { }
String::String(int i) {
char t[20];
sprintf(t, "%i", i);
- str = ::strdup(t);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::String(unsigned int i) {
+ char t[20];
+
+ sprintf(t, "%u", i);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::String(long long l) {
+ char t[40];
+
+ sprintf(t, "%lld", l);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::String(unsigned long long l) {
+ char t[40];
+
+ sprintf(t, "%llu", l);
+ str = Base::strdup(t);
siz = ::strlen(str);
}
@@ -39,7 +63,7 @@ String::String(double d) {
char t[30];
sprintf(t, "%g", d);
- str = ::strdup(t);
+ str = Base::strdup(t);
siz = ::strlen(str);
}
@@ -53,7 +77,7 @@ const char * String::set(char * s, ...) {
va_start(ap, s);
vsnprintf(t, BUFSIZ, s, ap);
free(str);
- str = ::strdup(t);
+ str = Base::strdup(t);
va_end(ap);
siz = ::strlen(str);
return t;
@@ -89,7 +113,7 @@ String String::extract(size_t from, ssize_t to) const {
}
char * String::strdup(size_t from, ssize_t to) const {
- return ::strdup(to_charp(from, to));
+ return Base::strdup(to_charp(from, to));
}
int String::to_int(void) const {
diff --git a/lib/Variables.cc b/lib/Variables.cc
index 0bb8c01..6b23d9c 100644
--- a/lib/Variables.cc
+++ b/lib/Variables.cc
@@ -37,7 +37,7 @@ int Variables::GetNb(void) {
return nbvars;
}
-void Variables::Dump(Handle * h) {
+void Variables::Dump(Handle * h, const String & format) {
int i, eqp;
String Vn, Vv;
@@ -45,7 +45,11 @@ void Variables::Dump(Handle * h) {
eqp = Vars[i].strchr('=');
Vn = Vars[i].extract(0, eqp - 1);
Vv = Vars[i].extract(eqp + 1);
- (*h) << "<INPUT TYPE=\"HIDDEN\" NAME=\"" << Vn << "\" VALUE=\"" << Vv << "\">" << endnl;
+ if (format == "") {
+ (*h) << "<INPUT TYPE=\"HIDDEN\" NAME=\"" << Vn << "\" VALUE=\"" << Vv << "\">" << endnl;
+ } else {
+ // Use format here...
+ }
}
}