source: sources/src/cgiDialogue.cc @ 1500:872b0b69e0d5

Revision 1500:872b0b69e0d5, 27.2 KB checked in by niam, 12 months ago (diff)

{issue #103} added implementation of sl- and dl- lists

Line 
1/***************************************************************************
2 *            cgiDialogue.cc
3 *
4 *  Sat Sep  18 2005
5 *  Copyright  2005  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#include <stdio.h>
33#include <string.h>
34#include <stdlib.h>
35#include <errno.h>
36#include <unistd.h>
37
38#include <libdodo/cgiDialogue.h>
39#include <libdodo/types.h>
40#include <libdodo/cgi.h>
41#include <libdodo/cgiExchange.h>
42#include <libdodo/cgiDialogueEx.h>
43#include <libdodo/toolsString.h>
44#include <libdodo/toolsCode.h>
45#include <libdodo/toolsMisc.h>
46
47using namespace dodo::cgi;
48
49const char *dialogue::environmentStatements[] = {
50    "REQUEST_METHOD",
51    "REQUEST_URI",
52    "QUERY_STRING",
53    "CONTENT_TYPE",
54    "CONTENT_LENGTH",
55    "CONTENT_TRANSFER_ENCODING",
56    "HTTP_AUTHORIZATION",
57    "HTTP_HOST",
58    "HTTP_USER_AGENT",
59    "HTTP_COOKIE",
60    "HTTP_DATE",
61    "HTTP_IF_MODIFIED_SINCE",
62    "HTTP_ACCEPT",
63    "HTTP_ACCEPT_LANGUAGE",
64    "HTTP_ACCEPT_ENCODING",
65    "HTTP_ACCEPT_CHARSET",
66    "HTTP_ACCEPT_RANGES",
67    "HTTP_KEEP_ALIVE",
68    "HTTP_CONNECTION",
69    "HTTP_REFERER",
70    "HTTP_VIA",
71    "HTTP_X_FORWARDED_FOR",
72    "REMOTE_ADDR",
73    "REMOTE_PORT",
74    "REDIRECT_STATUS",
75    "REDIRECT_QUERY_STRING",
76    "REDIRECT_URL",
77    "GATEWAY_INTERFACE",
78    "PATH",
79    "DIALOGUE_SIGNATURE",
80    "DIALOGUE_SOFTWARE",
81    "DIALOGUE_NAME",
82    "DIALOGUE_ADDR",
83    "DIALOGUE_PORT",
84    "DIALOGUE_ADMIN",
85    "DIALOGUE_PROTOCOL",
86    "SCRIPT_FILENAME",
87    "SCRIPT_NAME",
88};
89
90//-------------------------------------------------------------------
91
92const dodo::string dialogue::responseHeaderStatements[] = {
93    "Accept-Ranges",
94    "Age",
95    "Allow",
96    "Cache-Control",
97    "Content-Encoding",
98    "Content-Language",
99    "Content-Length",
100    "Content-Location",
101    "Content-Disposition",
102    "Content-MD5",
103    "Content-Range",
104    "Content-Type",
105    "Date",
106    "Last-Modified",
107    "Location",
108    "Server",
109    "WWW-Authenticate",
110    "X-Powered-By",
111};
112
113const dodo::string dialogue::responseStatusStatements[] = {
114    "Status: 100 Continue\r\n",
115    "Status: 101 Switching Protocols\r\n",
116    "Status: 200 OK\r\n",
117    "Status: 201 Created\r\n",
118    "Status: 202 Accepted\r\n",
119    "Status: 203 Non-Authoritative Information\r\n",
120    "Status: 204 No Content\r\n",
121    "Status: 205 Reset Content\r\n",
122    "Status: 206 Partial Content\r\n",
123    "Status: 300 Multiple Choices\r\n",
124    "Status: 301 Moved Permanently\r\n",
125    "Status: 302 Found\r\n",
126    "Status: 303 See Other\r\n",
127    "Status: 304 Not Modified\r\n",
128    "Status: 305 Use Proxy\r\n",
129    "Status: 307 Temporary Redirect\r\n",
130    "Status: 400 Bad Request\r\n",
131    "Status: 401 Unauthorized\r\n",
132    "Status: 402 Payment Required\r\n",
133    "Status: 403 Forbidden\r\n",
134    "Status: 404 Not Found\r\n",
135    "Status: 405 Method Not Allowed\r\n",
136    "Status: 406 Not Acceptable\r\n",
137    "Status: 407 Proxy Authentication Required\r\n",
138    "Status: 408 Request Timeout\r\n",
139    "Status: 409 Conflict\r\n",
140    "Status: 410 Gone\r\n",
141    "Status: 411 Length Required\r\n",
142    "Status: 412 Precondition Failed\r\n",
143    "Status: 413 Request Entity Too Large\r\n",
144    "Status: 414 Request-URI Too Long\r\n",
145    "Status: 415 Unsupported Media Type\r\n",
146    "Status: 416 Requested Range Not Satisfiable\r\n",
147    "Status: 417 Expectation Failed\r\n",
148    "Status: 500 Internal Server Error\r\n",
149    "Status: 501 Not Implemented\r\n",
150    "Status: 502 Bad Gateway\r\n",
151    "Status: 503 Service Unavailable\r\n",
152    "Status: 504 Gateway Timeout\r\n",
153    "Status: 505 HTTP Version Not Supported\r\n",
154};
155
156//-------------------------------------------------------------------
157
158dialogue::dialogue(dialogue &ct) : io(ct.io)
159{
160}
161
162//-------------------------------------------------------------------
163
164dialogue::dialogue(exchange      &a_cf,
165                   unsigned long postSize,
166                   bool          a_autocleanFiles,
167                   bool          a_postFilesInMem,
168                   dodo::string    a_postFilesTmpDir) : returnCode(STATUS_CODE_OK),
169                                                      postFilesInMem(a_postFilesInMem),
170                                                      autocleanFiles(a_autocleanFiles),
171                                                      postFilesTmpDir(a_postFilesTmpDir),
172                                                      io(a_cf),
173                                                      headersPrinted(false)
174
175{
176    authInfo.type = AUTH_NONE;
177
178    dodoMap<short, dodo::string> headers;
179    initHeaders(headers);
180
181    makeEnv();
182
183    makeAuth();
184
185    detectMethod();
186
187    makeContent(postSize);
188    makePost();
189
190    makeKeyValue(COOKIES, ENVIRONMENT[ENVIRONMENT_HTTPCOOKIE], "; ");
191    makeKeyValue(GET, ENVIRONMENT[ENVIRONMENT_QUERYSTRING]);
192}
193
194//-------------------------------------------------------------------
195
196dialogue::dialogue(exchange &a_cf,
197                   dodoMap<short, dodo::string> &headers,
198                   unsigned long postSize,
199                   bool a_autocleanFiles,
200                   bool a_postFilesInMem,
201                   dodo::string a_postFilesTmpDir) : returnCode(STATUS_CODE_OK),
202                                                   postFilesInMem(a_postFilesInMem),
203                                                   autocleanFiles(a_autocleanFiles),
204                                                   postFilesTmpDir(a_postFilesTmpDir),
205                                                   io(a_cf),
206                                                   headersPrinted(false)
207
208{
209    authInfo.type = AUTH_NONE;
210
211    initHeaders(headers);
212
213    printHeaders();
214
215    makeEnv();
216
217    makeAuth();
218
219    detectMethod();
220
221    makeContent(postSize);
222    makePost();
223
224    makeKeyValue(COOKIES, ENVIRONMENT[ENVIRONMENT_HTTPCOOKIE], "; ");
225    makeKeyValue(GET, ENVIRONMENT[ENVIRONMENT_QUERYSTRING]);
226}
227
228//-------------------------------------------------------------------
229
230dialogue::~dialogue()
231{
232    printHeaders();
233
234    if (autocleanFiles)
235        cleanTmp();
236}
237
238//-------------------------------------------------------------------
239
240dialogue::operator exchange
241*()
242{
243    printHeaders();
244
245    return &io;
246}
247
248//-------------------------------------------------------------------
249
250void
251dialogue::flush() const
252{
253    io.flush();
254}
255
256//-------------------------------------------------------------------
257
258unsigned long
259dialogue::printString(const dodo::string &buf)
260{
261    printHeaders();
262
263    return io.writeString(buf);
264}
265
266//-------------------------------------------------------------------
267
268dodo::string
269dialogue::charset()
270{
271    unsigned long temp;
272
273    dodoStringArray::iterator b = contenTypeExtensions.begin(), e = contenTypeExtensions.end();
274    for (; b != e; ++b) {
275        temp = tools::string::find(*b, "charset=", true);
276        if (temp == dodo::string::POSITION_END)
277            continue;
278
279        return dodo::string(b->data() + temp + 8, b->size() - temp - 8);
280    }
281
282    return __dodostring__;
283}
284
285unsigned long
286dialogue::print(const dodo::string &buf)
287{
288    printHeaders();
289
290    unsigned long bsOrig = io.bs;
291
292    io.bs = buf.size();
293    unsigned long printed = io.write(buf);
294
295    io.bs = bsOrig;
296
297    return printed;
298}
299
300//-------------------------------------------------------------------
301
302void
303dialogue::makeAuth()
304{
305    dodo::string &httpAuthorization = ENVIRONMENT[ENVIRONMENT_HTTPAUTHORIZATION];
306
307    if (tools::string::contains(httpAuthorization, "Basic")) {
308        dodoStringArray arr = tools::misc::split(tools::code::decodeBase64(tools::string::trim(dodo::string(httpAuthorization.data() + 6, httpAuthorization.size() - 6), ' ')), ":", 2);
309
310        authInfo.type = AUTH_BASIC;
311        authInfo.user = arr[0];
312        if (arr.size() == 2)
313            authInfo.password = arr[1];
314    } else {
315        if (tools::string::contains(httpAuthorization, "Digest")) {
316            authInfo.type = AUTH_DIGEST;
317
318            dodoStringArray parts = tools::misc::split(dodo::string(httpAuthorization.data() + 7, httpAuthorization.size() - 7), ",");
319
320            dodoStringArray tuple;
321
322            dodoStringArray::iterator i = parts.begin(), j = parts.end();
323            for (; i != j; ++i) {
324                *i = tools::string::trim(*i, ' ');
325                tuple = tools::misc::split(*i, "=", 2);
326                if (tuple.size() != 2)
327                    continue;
328
329                dodo::string &challengePart = tuple[0];
330
331                if (tools::string::iequal(challengePart, "realm"))
332                    authInfo.realm = tools::string::trim(tuple[1], '"');
333                else if (tools::string::iequal(challengePart, "nonce"))
334                    authInfo.nonce = tools::string::trim(tuple[1], '"');
335                else if (tools::string::iequal(challengePart, "opaque"))
336                    authInfo.opaque = tools::string::trim(tuple[1], '"');
337                else if (tools::string::iequal(challengePart, "username"))
338                    authInfo.user = tools::string::trim(tuple[1], '"');
339                else if (tools::string::iequal(challengePart, "uri"))
340                    authInfo.uri = tools::string::trim(tuple[1], '"');
341                else if (tools::string::iequal(challengePart, "qop"))
342                    authInfo.qop = tools::string::trim(tuple[1], '"');
343                else if (tools::string::iequal(challengePart, "nc"))
344                    authInfo.nonceCount = tools::string::trim(tuple[1], '"');
345                else if (tools::string::iequal(challengePart, "cnonce"))
346                    authInfo.cnonce = tools::string::trim(tuple[1], '"');
347                else if (tools::string::iequal(challengePart, "response"))
348                    authInfo.response = tools::string::trim(tuple[1], '"');
349            }
350        } else {
351            authInfo.type = AUTH_NONE;
352        }
353    }
354}
355
356//-------------------------------------------------------------------
357
358void
359dialogue::requestAuthentication(const dodo::string &realm,
360                                short            type)
361{
362    returnCode = STATUS_CODE_UNAUTHORIZED;
363
364    if (type == AUTH_BASIC)
365        HEADERS.insert(std::make_pair(RESPONSE_HEADER_WWWAUTHENTICATE, "Basic realm=\"" + realm + "\""));
366    else if (type == AUTH_DIGEST)
367        HEADERS.insert(std::make_pair(RESPONSE_HEADER_WWWAUTHENTICATE, "Digest realm=\"" +
368                                 realm +
369                                 "\", qop=\"auth\", nonce=\"" +
370                                 tools::code::MD5Hex(tools::misc::randomString(16)) +
371                                 "\", opaque=\"" +
372                                 tools::code::MD5Hex(tools::misc::randomString(16)) + "\""));
373}
374
375//-------------------------------------------------------------------
376
377dodo::cgi::__auth__
378dialogue::authenticationResponse()
379{
380    cgi::__auth__ info = {
381        authInfo.user, authInfo.type
382    };
383
384    return info;
385}
386
387//-------------------------------------------------------------------
388
389bool
390dialogue::isAuthenticated(const dodo::string &user,
391                          const dodo::string &password)
392{
393    if (authInfo.type == AUTH_BASIC)
394        return (tools::string::equal(user, authInfo.user) && tools::string::equal(password, authInfo.password));
395    else if (authInfo.type == AUTH_DIGEST) {
396        unsigned char HA[16];
397        tools::code::__MD5Context__ context;
398
399        tools::code::MD5Init(&context);
400        tools::code::MD5Update(&context, (unsigned char *)authInfo.user.data(), authInfo.user.size());
401        tools::code::MD5Update(&context, (unsigned char *)":", 1);
402        tools::code::MD5Update(&context, (unsigned char *)authInfo.realm.data(), authInfo.realm.size());
403        tools::code::MD5Update(&context, (unsigned char *)":", 1);
404        tools::code::MD5Update(&context, (unsigned char *)password.data(), password.size());
405        tools::code::MD5Final(HA, &context);
406
407        dodo::string HA1 = tools::code::binToHex(dodo::string((char *)&HA, 16));
408
409        dodo::string &methodForAuth = ENVIRONMENT[ENVIRONMENT_REQUESTMETHOD];
410
411        tools::code::MD5Init(&context);
412        tools::code::MD5Update(&context, (unsigned char *)methodForAuth.data(), methodForAuth.size());
413        tools::code::MD5Update(&context, (unsigned char *)":", 1);
414        tools::code::MD5Update(&context, (unsigned char *)authInfo.uri.data(), authInfo.uri.size());
415        tools::code::MD5Final(HA, &context);
416
417        dodo::string HA2 = tools::code::binToHex(dodo::string((char *)&HA, 16));
418
419        tools::code::MD5Init(&context);
420        tools::code::MD5Update(&context, (unsigned char *)HA1.data(), HA1.size());
421        tools::code::MD5Update(&context, (unsigned char *)":", 1);
422        tools::code::MD5Update(&context, (unsigned char *)authInfo.nonce.data(), authInfo.nonce.size());
423        tools::code::MD5Update(&context, (unsigned char *)":", 1);
424        tools::code::MD5Update(&context, (unsigned char *)authInfo.nonceCount.data(), authInfo.nonceCount.size());
425        tools::code::MD5Update(&context, (unsigned char *)":", 1);
426        tools::code::MD5Update(&context, (unsigned char *)authInfo.cnonce.data(), authInfo.cnonce.size());
427        tools::code::MD5Update(&context, (unsigned char *)":", 1);
428        tools::code::MD5Update(&context, (unsigned char *)authInfo.qop.data(), authInfo.qop.size());
429        tools::code::MD5Update(&context, (unsigned char *)":", 1);
430        tools::code::MD5Update(&context, (unsigned char *)HA2.data(), HA2.size());
431        tools::code::MD5Final(HA, &context);
432
433        return tools::string::equal(tools::code::binToHex(dodo::string((char *)&HA, 16)), authInfo.response);
434    } else {
435        return false;
436    }
437}
438
439//-------------------------------------------------------------------
440
441void
442dialogue::cleanTmp()
443{
444    dodoMap<dodo::string, file>::iterator i(FILES.begin()), j(FILES.end());
445    for (; i != j; ++i)
446        if (!postFilesInMem)
447            unlink(i->second.path.data());
448}
449
450//-------------------------------------------------------------------
451
452void
453dialogue::detectMethod()
454{
455    if (tools::string::iequal(ENVIRONMENT[ENVIRONMENT_REQUESTMETHOD], "GET"))
456        requestMethod = REQUEST_METHOD_GET;
457    else if (tools::string::iequal(ENVIRONMENT[ENVIRONMENT_REQUESTMETHOD], "POST") && ENVIRONMENT[ENVIRONMENT_REQUESTMETHOD].empty())
458        requestMethod = REQUEST_METHOD_POST;
459    else
460        requestMethod = REQUEST_METHOD_GET_POST;
461}
462
463//-------------------------------------------------------------------
464
465int
466dialogue::method() const
467{
468    return requestMethod;
469}
470
471//-------------------------------------------------------------------
472
473void
474dialogue::makeKeyValue(dodoStringMap    &val,
475                       const dodo::string &string,
476                       const char       *delim)
477{
478    dodoStringArray getPair = tools::misc::split(tools::code::decodeUrl(string), delim);
479
480    dodoStringArray::iterator l(getPair.begin()), m(getPair.end());
481
482    dodoStringArray temp;
483
484    for (; l != m; ++l) {
485        temp = tools::misc::split(*l, "=");
486        if (temp.size() > 1)
487            val.insert(std::make_pair(temp[0], temp[1]));
488    }
489}
490
491//-------------------------------------------------------------------
492
493void
494dialogue::makeEnv()
495{
496    char *env;
497
498    for (int i = 0; i < ENVIRONMENT_ENUMSIZE; ++i) {
499        env = io.getenv(environmentStatements[i]);
500
501        ENVIRONMENT[i] = env == NULL ? "NULL" : env;
502    }
503
504    dodoStringArray contentTypeParts = tools::misc::split(ENVIRONMENT[ENVIRONMENT_CONTENTTYPE], ";");
505    dodoStringArray::iterator i = contentTypeParts.begin(), j = contentTypeParts.end();
506    for (; i != j; ++i)
507        *i = tools::string::trim(*i, ' ');
508
509    unsigned long size = contentTypeParts.size();
510    if (size > 0) {
511        dodoStringArray::iterator first = contentTypeParts.begin();
512
513        ENVIRONMENT[ENVIRONMENT_CONTENTTYPE] = *first;
514
515        if (size > 1)
516            contenTypeExtensions.insert(contenTypeExtensions.begin(), first + 1, contentTypeParts.end());
517    } else {
518        contentTypeParts = tools::misc::split(ENVIRONMENT[ENVIRONMENT_CONTENTTYPE], ",");
519        i = contentTypeParts.begin();
520        j = contentTypeParts.end();
521        for (; i != j; ++i)
522            *i = tools::string::trim(*i, ' ');
523
524        if (size > 0) {
525            dodoStringArray::iterator first = contentTypeParts.begin();
526
527            ENVIRONMENT[ENVIRONMENT_CONTENTTYPE] = *first;
528
529            if (size > 1)
530                contenTypeExtensions.insert(contenTypeExtensions.begin(), first + 1, contentTypeParts.end());
531        }
532    }
533}
534
535//-------------------------------------------------------------------
536
537void
538dialogue::initHeaders(dodoMap<short, dodo::string> &headers)
539{
540    if (headers.size() > 0) {
541        HEADERS.insert(headers.begin(), headers.end());
542    } else {
543        HEADERS.insert(std::make_pair(RESPONSE_HEADER_CONTENTTYPE, "text/html"));
544        HEADERS.insert(std::make_pair(RESPONSE_HEADER_XPOWEREDBY, PACKAGE_NAME "/" PACKAGE_VERSION));
545    }
546}
547
548//-------------------------------------------------------------------
549
550void
551dialogue::setResponseStatus(short code)
552{
553    if (code <= STATUS_CODE_HTTPVERSIONNOTSUPPORTED)
554        returnCode = code;
555    else
556        dodo_throw exception::basic(exception::MODULE_CGIDIALOGUE, DIALOGUEEX_SETRESPONSESTATUS, exception::ERRNO_LIBDODO, DIALOGUEEX_WRONGSTATUSCODE, CGIDIALOGUEEX_WRONGSTATUSCODE_STR, __LINE__, __FILE__);
557}
558
559//-------------------------------------------------------------------
560
561void
562dialogue::printHeaders() const
563{
564    if (headersPrinted)
565        return;
566
567    headersPrinted = true;
568
569    io.writeString(responseStatusStatements[returnCode]);
570
571    dodoMap<short, dodo::string>::const_iterator i(HEADERS.begin()), j(HEADERS.end());
572    for (; i != j; ++i)
573        io.writeString(responseHeaderStatements[i->first] + ": " + i->second + "\r\n");
574
575    if (cookies.size() > 0) {
576        dodo::slList<cookie>::iterator i(cookies.begin()), j(cookies.end());
577        for (; i != j; ++i) {
578            io.writeString("Set-Cookie: ");
579            io.writeString(i->name + "=" + i->value + "; ");
580            if (i->path.size() > 0)
581                io.writeString("path=" + i->path + "; ");
582            if (i->expires.size() > 0)
583                io.writeString("expires=" + i->expires + "; ");
584            if (i->domain.size() > 0)
585                io.writeString("domain=" + i->domain + "; ");
586            if (i->secure)
587                io.writeString("secure");
588            io.writeString("\r\n");
589        }
590    }
591
592    io.writeString("\r\n");
593    io.flush();
594}
595
596//-------------------------------------------------------------------
597
598void
599dialogue::makeContent(unsigned long postSize)
600{
601    unsigned long bs = tools::string::stringToUL(ENVIRONMENT[ENVIRONMENT_CONTENTLENGTH]);
602    unsigned long bsOrig;
603
604    if (bs <= 0)
605        return ;
606
607    if (bs > postSize)
608        bs = postSize;
609
610    bsOrig = io.bs;
611    io.bs = bs;
612
613    content = io.read();
614
615    io.bs = bsOrig;
616}
617
618//-------------------------------------------------------------------
619
620void
621dialogue::makePost()
622{
623    if (content.size() == 0)
624        return ;
625
626    if (!tools::string::iequal(ENVIRONMENT[ENVIRONMENT_REQUESTMETHOD], "POST"))
627        return ;
628
629    if (tools::string::iequal(ENVIRONMENT[ENVIRONMENT_CONTENTTYPE], "application/x-www-form-urlencoded")) {
630        makeKeyValue(POST, content);
631
632        content.clear();
633    } else {
634        if (tools::string::iequal(ENVIRONMENT[ENVIRONMENT_CONTENTTYPE], "multipart/form-data")) {
635            if (tools::string::iequal(ENVIRONMENT[ENVIRONMENT_CONTENTTRANSFERENCODING], "base64"))
636                content = tools::code::decodeBase64(content);
637
638            unsigned long temp0;
639            dodoStringArray postParts;
640
641            dodoStringArray::iterator b = contenTypeExtensions.begin(), e = contenTypeExtensions.end();
642            for (; b != e; ++b) {
643                temp0 = tools::string::find(*b, "boundary=", true);
644                if (temp0 == dodo::string::POSITION_END)
645                    continue;
646
647                dodo::string delimiter = "--";
648                delimiter += dodo::string(b->data() + temp0 + 9, b->size() - temp0 - 9);
649
650                postParts = tools::misc::split(content, delimiter);
651            }
652
653            if (postParts.size() > 0) {
654                dodoStringArray::iterator i(postParts.begin() + 1), j(postParts.end());
655
656                unsigned long temp1;
657                char *ptr;
658                int fd;
659                unsigned short pathLength = postFilesTmpDir.size() + 18;
660                FILE *fp;
661                const char *argument;
662
663                for (; i != j; ++i) {
664                    if (i->size() == 2 && (*i)[0] == '-' && (*i)[1] == '-') ///< '--' in the last portion
665                        break;
666                    else {
667                        if (i->find("filename") != dodo::string::POSITION_END) {
668                            if ((temp0 = i->find("name=\"")) == dodo::string::POSITION_END)
669                                continue;
670
671                            temp0 += 6;
672
673                            if ((temp1 = i->find("\"", temp0)) == dodo::string::POSITION_END)
674                                continue;
675
676                            dodo::string post_name = dodo::string(i->data() + temp0, temp1 - temp0);
677
678                            file file;
679
680                            temp0 = i->find("filename=\"", temp1);
681                            temp0 += 10;
682                            temp1 = i->find("\"", temp0);
683                            if (temp0 == temp1)
684                                continue;
685
686                            file.name = dodo::string(i->data() + temp0, temp1 - temp0);
687
688                            temp0 = tools::string::find(*i, "Content-Type: ", temp1, true);
689                            temp0 += 14;
690                            temp1 = i->find("\n", temp0);
691                            file.mime = tools::misc::split(dodo::string(i->data() + temp0, temp1 - temp0), ";")[0];
692
693                            unsigned long lIndex = file.mime.size() - 1;
694                            if (file.mime[lIndex] == '\r')
695                                file.mime.erase(lIndex);
696                            temp1 += 3;
697
698                            file.size = i->size() - temp1 - 2;
699
700                            if (postFilesInMem) {
701                                file.data = dodo::string(i->data() + temp1, file.size);
702                            } else {
703                                file.error = FILE_ERROR_NONE;
704
705                                ptr = new char[pathLength];
706                                strncpy(ptr, dodo::string(postFilesTmpDir + "/" + dodo::string("dodo_post_XXXXXX")).data(), pathLength);
707                                fd = mkstemp(ptr);
708                                if (fd == -1) {
709                                    delete [] ptr;
710
711                                    file.error = FILE_ERROR_BAD_FILE_NAME;
712                                    FILES.insert(std::make_pair(post_name, file));
713
714                                    continue;
715                                }
716
717                                file.path = ptr;
718
719                                delete [] ptr;
720
721                                fp = fdopen(fd, "w+");
722                                if (fp == NULL) {
723                                    switch (errno) {
724                                        case EACCES:
725                                        case EISDIR:
726
727                                            file.error = FILE_ERROR_ACCESS_DENY;
728
729                                            break;
730
731                                        case ENAMETOOLONG:
732                                        case ENOTDIR:
733
734                                            file.error = FILE_ERROR_BAD_FILE_NAME;
735
736                                            break;
737
738                                        case ENOMEM:
739
740                                            file.error = FILE_ERROR_NO_SPACE;
741
742                                            break;
743
744                                        default:
745
746                                            dodo_throw exception::basic(exception::MODULE_CGIDIALOGUE, DIALOGUEEX_MAKEPOST, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
747                                    }
748                                } else {
749                                    if (fwrite(i->data() + temp1, file.size, 1, fp) == 0) {
750                                        if (errno == ENOMEM) {
751                                            file.error = FILE_ERROR_NO_SPACE;
752                                        } else {
753                                            if (fclose(fp) != 0)
754                                                dodo_throw exception::basic(exception::MODULE_CGIDIALOGUE, DIALOGUEEX_MAKEPOST, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
755
756                                            dodo_throw exception::basic(exception::MODULE_CGIDIALOGUE, DIALOGUEEX_MAKEPOST, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
757                                        }
758                                    }
759
760                                    if (fclose(fp) != 0)
761                                        dodo_throw exception::basic(exception::MODULE_CGIDIALOGUE, DIALOGUEEX_MAKEPOST, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
762                                }
763                            }
764
765                            FILES.insert(std::make_pair(post_name, file));
766                        } else {
767                            if ((temp0 = i->find("name=\"")) == dodo::string::POSITION_END)
768                                continue;
769
770                            temp0 += 6;
771
772                            if ((temp1 = i->find("\"", temp0)) == dodo::string::POSITION_END)
773                                continue;
774
775                            argument = i->data();
776
777                            POST.insert(std::make_pair(dodo::string(argument + temp0, temp1 - temp0), dodo::string(argument + temp1 + 5, i->size() - temp1 - 7)));
778                        }
779                    }
780                }
781            }
782
783            content.clear();
784        }
785    }
786}
787
788//-------------------------------------------------------------------
789
790const dodo::dodoStringMap &
791dialogue::operator[](short method)
792{
793    if (method == REQUEST_METHOD_POST)
794        return POST;
795    else
796        return GET;
797}
798
799//-------------------------------------------------------------------
800
801dodo::string
802dialogue::operator[](const dodo::string &name)
803{
804    dodoStringMap::iterator item = GET.find(name);
805    if (item != GET.end())
806        return item->second;
807
808    item = POST.find(name);
809    if (item != POST.end())
810        return item->second;
811
812    return __dodostring__;
813}
814
815//-------------------------------------------------------------------
816
817void
818dialogue::setCookie(const cookie &cookie)
819{
820    cookies.push(cookie);
821}
822
823//-------------------------------------------------------------------
824
Note: See TracBrowser for help on using the repository browser.