diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Buffer.cc | 9 | ||||
-rw-r--r-- | lib/CopyJob.cc | 8 | ||||
-rw-r--r-- | lib/Exceptions.cc | 55 | ||||
-rw-r--r-- | lib/Handle.cc | 8 | ||||
-rw-r--r-- | lib/HttpServ.cc | 59 | ||||
-rw-r--r-- | lib/InPipe.cc | 31 | ||||
-rw-r--r-- | lib/Input.cc | 16 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/OutPipe.cc | 31 | ||||
-rw-r--r-- | lib/String.cc | 38 | ||||
-rw-r--r-- | lib/Variables.cc | 8 |
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... + } } } |