summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpixel <pixel>2007-10-12 13:07:19 +0000
committerpixel <pixel>2007-10-12 13:07:19 +0000
commit54885ea33f4022e552784e63df1c75fc26e181dd (patch)
tree1d0d6d53d20f5956caf194ce0d537c10cb6678dc
parentcb1744c5ddd08593ec2e5370a4d6a9c625fda794 (diff)
Almost done for the file uploading.
-rw-r--r--lib/HttpServ.cc228
1 files changed, 218 insertions, 10 deletions
diff --git a/lib/HttpServ.cc b/lib/HttpServ.cc
index 23f45d4..57afd20 100644
--- a/lib/HttpServ.cc
+++ b/lib/HttpServ.cc
@@ -17,7 +17,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* $Id: HttpServ.cc,v 1.58 2007-09-28 09:23:36 pixel Exp $ */
+/* $Id: HttpServ.cc,v 1.59 2007-10-12 13:07:19 pixel Exp $ */
+
+#include <vector>
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -35,12 +37,57 @@
#include "HashFunction.h"
#include "gettext.h"
+#define MAXLEN 4*1024*1024
+
+/*
+ stuff we should support...
+
+ Etags:
+ Server: ETag: "27b42a-134-46cece08"
+ Client: If-None-Match: "27b42a-146-46cecd32"
+
+ Last-Modified:
+ Server: Last-Modified: Fri, 24 Aug 2007 12:24:40 GMT
+ Client: If-Modified-Since: Fri, 24 Aug 2007 12:21:06 GMT
+
+ Multipart stuff:
+
+----8<-----Example-------8<--------
+Content-Type: multipart/form-data; boundary=---------------------------163944935918044553841983937859
+Content-Length: 377
+
+-----------------------------163944935918044553841983937859
+Content-Disposition: form-data; name="textline"
+
+
+-----------------------------163944935918044553841983937859
+Content-Disposition: form-data; name="datafile"; filename="tst-user-agent.txt"
+Content-Type: text/plain
+
+User-Agent: CFNetwork/129.20
+
+-----------------------------163944935918044553841983937859--
+----8<-----Example-------8<--------
+
+*/
+
+
+
String endhl = "\r\n", endnl = "\n";
+struct multipart_file {
+ multipart_file(Buffer * _file, const String & _type, const String & _filename, const String & _varname) : file(_file), type(_type), filename(_filename), varname(_varname) { }
+ ~multipart_file() { }
+ Buffer * file;
+ String type, filename, varname;
+};
+
+typedef std::vector<struct multipart_file> multipart_files;
+
class ProcessRequest : public Task {
public:
ProcessRequest(Action * action, const Socket & out, const String & server_name, int server_port, const String & root = "/bin/start");
- virtual ~ProcessRequest() {}
+ virtual ~ProcessRequest();
virtual String GetName();
protected:
virtual int Do() throw (GeneralException);
@@ -49,6 +96,7 @@ class ProcessRequest : public Task {
String UnMangle(const String &, int p = 0);
bool ParseUri(String &, String &, String &, Handle *);
void ParseVars(Handle *, int);
+ void ParseMultipart(Handle *, int);
void ShowError(Handle *);
void SendHeads(Handle *, const String &, const String & = "", time_t = -1);
void SendRedirect(Handle *);
@@ -61,10 +109,12 @@ class ProcessRequest : public Task {
Action * p;
Socket s;
Domain * d;
-
- String name, host, gvars, login, password, root;
+
+ multipart_files m_files;
+
+ String name, host, gvars, login, password, root, boundary;
Variables * Vars, * Heads;
- bool bad, hasvars, post;
+ bool bad, hasvars, post, multipart, content_type;
HttpResponse response;
};
@@ -73,6 +123,14 @@ ProcessRequest::ProcessRequest(Action * ap, const Socket & as, const String & an
SetBurst();
}
+ProcessRequest::~ProcessRequest() {
+ std::vector<struct multipart_file>::iterator i;
+
+ for (i = m_files.begin(); i != m_files.end(); i++) {
+ delete i->file;
+ }
+}
+
String ProcessRequest::GetName() {
return _("Processing HTTP request");
}
@@ -100,6 +158,7 @@ int ProcessRequest::Do() throw(GeneralException) {
Vars = new Variables();
len = -1;
+ content_type = false;
do {
int p;
b >> t;
@@ -107,6 +166,8 @@ int ProcessRequest::Do() throw(GeneralException) {
if ((t.strstr("Content-Length: ") == 0) || (t.strstr("Content-length: ") == 0)) {
// std::cerr << "Saw 'Content-Lenght:', reading length from '" << t.extract(16) << "'\n";
len = t.extract(16).to_int();
+ if (len > MAXLEN)
+ len = -1;
}
if (t.strstr("Host: ") == 0) {
host = t.extract(6);
@@ -125,6 +186,16 @@ int ProcessRequest::Do() throw(GeneralException) {
free(credentials);
}
+ if (t.strstr("Content-Type: application/x-www-form-urlencoded") == 0) {
+ // basic post method
+ multipart = false;
+ content_type = true;
+ }
+ if (t.strstr("Content-Type: multipart/form-data; boundary=") == 0) {
+ multipart = true;
+ content_type = true;
+ boundary = "--" + t.extract(44);
+ }
if ((p = t.strchr(':')) >= 0) {
String s = t.extract(0, p - 1);
@@ -149,14 +220,18 @@ int ProcessRequest::Do() throw(GeneralException) {
// Les variables seront initialisées ici.
hasvars = true;
}
+
+ if (!content_type) {
+ bad = true;
+ }
}
current = 2;
- if (hasvars && (len)) {
+ if (hasvars && len) {
c = new CopyJob(&s, &b, len);
WaitFor(c);
Suspend();
- } else {
+ } else {
c = 0;
}
@@ -166,9 +241,13 @@ int ProcessRequest::Do() throw(GeneralException) {
b2 << gvars;
ParseVars(&b2, gvars.strlen());
}
- if (hasvars) {
- if (c) delete c;
- ParseVars(&b, len);
+ if (hasvars && len) {
+ delete c;
+ if (!multipart) {
+ ParseVars(&b, len);
+ } else {
+ ParseMultipart(&b, len);
+ }
}
std::cerr << " Domain = '" << domain << "' - File = '" << file << "'\n";
@@ -274,6 +353,133 @@ int ProcessRequest::Do() throw(GeneralException) {
return TASK_DONE;
}
+void ProcessRequest::ParseMultipart(Handle * s, int len) {
+ String t, crboundary, k, v, disposition, type;
+ char redo[256], r, tmp[4];
+ int p, i, rl;
+ bool done = false, in_headers = true, is_file = false;
+ Buffer * out = 0;
+ std::vector<struct multipart_file>::iterator mf_p;
+ Variables * dispos_headers;
+
+ crboundary = "\r\n" + boundary;
+
+ redo[0] = p = 0;
+ i = 1;
+ while (i < crboundary.strlen()) {
+ if (crboundary[i] == crboundary[p]) {
+ redo[i++] = ++p;
+ } else if (p > 0) {
+ p = redo[p - 1];
+ } else {
+ redo[i++] = 0;
+ }
+ }
+
+ p = 0;
+ (*s) >> t;
+ if (t != boundary) {
+ return;
+ }
+ while (!done) {
+ if (in_headers) {
+ (*s) >> t;
+ if (t != "") {
+ // Content-Disposition: form-data; name="datafile"; filename="tst-user-agent.txt"
+ // Content-Type: text/plain
+ if (t.strstr("Content-Disposition: form-data; ") == 0) {
+ disposition = t.extract(32);
+ dispos_headers = new Variables();
+ // ****
+ } else if (t.strstr("Content-Type: ") == 0) {
+ type = t.extract(14);
+ } else {
+ printm(M_WARNING, "Unknown header in multipart chunk: " + t + "\n");
+ }
+ } else {
+ in_headers = false;
+ if ((type != "") && ((*dispos_headers)["filename"] != "")) {
+ is_file = true;
+ out = new Buffer();
+ } else {
+ k = (*dispos_headers)["name"];
+ }
+ }
+ } else {
+ rl = 0;
+
+ r = s->readU8();
+ if (crboundary[p] == r) {
+ p++;
+ rl = 1;
+ } else {
+ for (i = 0; i <= p; i++) {
+ if (is_file) {
+ out->writeU8(crboundary[i]);
+ } else {
+ v += crboundary[i];
+ }
+ }
+ if (p > 0)
+ p = redo[p - 1];
+ }
+
+ if (p == crboundary.strlen()) {
+ p = 0;
+ tmp[0] = s->readU8();
+ tmp[1] = s->readU8();
+
+ if ((t[0] == 13) && (t[1] == 10)) {
+ in_headers = true;
+
+ if (is_file) {
+ m_files.push_back(multipart_file(out, type, (*dispos_headers)["filename"], (*dispos_headers)["name"]));
+ out = 0;
+ } else {
+ Vars->Add(k + "=" + v);
+ }
+
+ k = "";
+ v = "";
+ type = "";
+ delete dispos_headers;
+ } else if ((tmp[0] == '-') && (tmp[1] == '-')) {
+ tmp[2] = s->readU8();
+ tmp[3] = s->readU8();
+ if ((tmp[2] == 13) && (tmp[3] == 10)) {
+ // end of streams
+
+ if (is_file) {
+ m_files.push_back(multipart_file(out, type, (*dispos_headers)["filename"], (*dispos_headers)["name"]));
+ out = 0;
+ } else {
+ Vars->Add(k + "=" + v);
+ }
+ return;
+ } else {
+ rl = 4;
+ }
+ } else {
+ rl = 2;
+ }
+ }
+
+ for (i = 0; i < rl; i++) {
+ if (is_file) {
+ out->writeU8(r);
+ } else {
+ v += r;
+ }
+
+ r = tmp[0];
+ tmp[0] = tmp[1];
+ tmp[1] = tmp[2];
+ tmp[2] = tmp[3];
+ }
+ }
+ }
+}
+
void ProcessRequest::ParseVars(Handle * s, int len) {
String t, v;
char conv[3], l;
@@ -290,6 +496,8 @@ void ProcessRequest::ParseVars(Handle * s, int len) {
// Les variables sont sous la forme 'var1=val1&var2=val2&val3=var3'. Donc le nombre d'occurences
// du caractère '=' indique le nombre de variables.
+
+ // WRONG! WRONG!
nbvars = t.strchrcnt('=');
for (int i = 0; i < nbvars; i++) {