00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00022 #include "common.h"
00023
00024 #include <ctype.h>
00025 #include <errno.h>
00026
00027
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #ifdef TM_IN_SYS_TIME
00031 # include <sys/time.h>
00032 #else
00033 # include <time.h>
00034 #endif
00035 #include <unistd.h>
00036
00037 #include "logger.h"
00038 #include "http.h"
00039
00040 #include "buffer.h"
00041 #include "bufplist.h"
00042 #include "conftable.h"
00043 #include "conn_handler.h"
00044 #include "misc.h"
00045 #include "reqhandler_file.h"
00046 #include "xmalloc.h"
00047
00048
00050 int reply_server_name;
00051
00052
00054 enum Method {MUNKNOWN, GET, HEAD, POST};
00056 enum HttpVer {VUNKNOWN, V09, V10, V11};
00058 enum Encoding {EUNKNOWN, IDENTITY, GZIP, COMPRESS};
00060 enum Connection {CUNKNOWN, CLOSE, KEEPALIVE};
00061
00062
00064 struct Uri
00065 {
00066 char* server;
00067 int port;
00068 char* path;
00069 int valid;
00070 };
00071
00073 struct HttpRequestHdr
00074 {
00075 enum Method mthd;
00076 enum HttpVer ver;
00077 struct Uri uri;
00078
00079 enum Encoding content_encoding;
00080 time_t if_mod_since;
00081 char* from;
00082 char* usr_agent;
00083 struct Uri referer;
00084 enum Connection connection;
00085
00086
00087 };
00088
00089
00090
00095 struct HttpProtHandler
00096 {
00097 ConnHandler parent;
00098 ReqHandlerFile rh_file;
00099 int status;
00100 int entity_available;
00101
00102
00103
00104 BufpList hdr_list;
00105
00106
00107 struct Buffer line_buf;
00108 ssize_t last_cr_pos;
00109 int newline;
00110
00111 struct HttpRequestHdr req_hdr;
00112 int header_read;
00113 int method_read;
00114
00115 int header_sent;
00116
00117 int data_pending;
00118 int error;
00119 };
00120
00124
00125
00126 int htRecvLine(HttpProtHandler this, const char* str);
00127 int copyRequestLine(HttpProtHandler this, struct Buffer* buf);
00128 int htMthdParse(HttpProtHandler this, const char* str);
00129 int htAddData(struct HttpRequestHdr* hdr, const char* str);
00130 struct Uri resolvURI(const char* str);
00131 const char* getStatusAsText(HttpProtHandler this);
00132 int buildBasicHeader(HttpProtHandler this);
00133 int buildEntityHeader(HttpProtHandler this);
00134 int appendHdrField(BufpList hdr_list, char* prefix, char* data);
00135 int err2Status(int err);
00136
00140
00141
00142 int htModulePreInit()
00143 {
00144 if (strcmp(getEntryDefl(CONFENTRY_KEY_REPLYSERVERNAME,
00145 STD_CONFENTRY_VAL_REPLYSERVERNAME),
00146 CONFENTRY_VAL_TRUE) == 0)
00147 {
00148 reply_server_name = true;
00149 }
00150
00151 return 0;
00152 }
00153
00154
00155 int htModuleTerminate()
00156 {
00157 return 0;
00158 }
00159
00163
00164
00165 HttpProtHandler htInit(ConnHandler parent)
00166 {
00167 HttpProtHandler this = (HttpProtHandler) pd_malloc(sizeof(struct HttpProtHandler));
00168 memset(this, 0, sizeof(struct HttpProtHandler));
00169 this->parent = parent;
00170
00171 this->status = 200;
00172 this->entity_available = false;
00173 this->hdr_list = bufpListInit();
00174
00175 this->line_buf = bufInit((char*) pd_malloc(256), 256, 0);
00176
00177 return this;
00178 }
00179
00180
00181
00182 int htReceive(HttpProtHandler this, struct Buffer buf)
00183 {
00184 if (this->header_read == false)
00185 {
00186 while (copyRequestLine(this, &buf) == 0
00187 && this->error == E_SUCCESS
00188 && this->header_read == false)
00189 {
00190
00191 htRecvLine(this, this->line_buf.data);
00192 this->line_buf.pos = 0;
00193 }
00194
00195 if (this->header_read == false)
00196 this->last_cr_pos -= buf.len;
00197 else
00198 {
00200 }
00201 }
00202
00203 return (this->error == E_SUCCESS) ? 0 : -1;
00204 }
00205
00206
00207
00208 int htSend(HttpProtHandler this, struct Buffer** buf)
00209 {
00210 if (this->header_sent != true)
00211 {
00212
00213 *buf = bufpListGetPayload(this->hdr_list);
00214 bufpListNext(this->hdr_list);
00215
00216
00217 if (bufpListIsTail(this->hdr_list) == true)
00218 {
00219 this->header_sent = true;
00220
00221
00222 this->data_pending = (this->entity_available) ? false : true;
00223 }
00224 }
00225 else
00226 {
00227 if (this->req_hdr.mthd == HEAD)
00228 {
00229 pd_free((*buf)->data);
00230 (*buf)->data = NULL;
00231 }
00232 else if (rhfIsDataPending(this->rh_file) == true)
00233 rhfSend(this->rh_file, buf);
00234 }
00235 return 0;
00236 }
00237
00238
00239
00240 int htProcess(HttpProtHandler this)
00241 {
00242
00243 if (this->rh_file == NULL)
00244 return 0;
00245 else
00246 return rhfProcess(this->rh_file);
00247 }
00248
00249
00250
00251 int htIsDataPending(HttpProtHandler this)
00252 {
00253 return (this->data_pending
00254 || ((this->rh_file != NULL) ? rhfIsDataPending(this->rh_file) : 0));
00255 }
00256
00257
00258
00259 int htTerminate(HttpProtHandler this)
00260 {
00261 if (this == NULL) return -1;
00262
00263 rhfTerminate(this->rh_file);
00264
00265
00266 bufpListFirst(this->hdr_list);
00267 while(!bufpListIsTail(this->hdr_list))
00268 {
00269 struct Buffer* buf = bufpListGetPayload(this->hdr_list);
00270 pd_free(buf->data);
00271 pd_free(buf);
00272 bufpListDelete(this->hdr_list);
00273 }
00274 bufpListTerminate(this->hdr_list);
00275
00276
00277 pd_free(this->line_buf.data);
00278 pd_free(this->req_hdr.uri.server);
00279 pd_free(this->req_hdr.uri.path);
00280 pd_free(this->req_hdr.from);
00281 pd_free(this->req_hdr.usr_agent);
00282 pd_free(this->req_hdr.referer.server);
00283 pd_free(this->req_hdr.referer.path);
00284
00285
00286 pd_free(this);
00287
00288 return 0;
00289 }
00290
00291
00292 int htGetError(HttpProtHandler this)
00293 {
00294 return this->error;
00295 }
00296
00300
00301
00302
00304 int htRecvLine(HttpProtHandler this, const char* line)
00305 {
00306
00307
00308 char* err_msg_data = NULL;
00309
00310
00311 if (this->header_read == false)
00312 {
00313
00314 if (*line == '\0')
00315 this->header_read = true;
00316 else
00317 {
00318
00319 if (this->method_read == false)
00320 {
00321 memset(&this->req_hdr, 0, sizeof(struct HttpRequestHdr));
00322 if (htMthdParse(this, line) >= 0)
00323 {
00324
00325 this->method_read = true;
00326
00327 if (this->req_hdr.ver == V09)
00328 this->header_read = true;
00329 }
00330 }
00331 else
00332
00333 htAddData(&this->req_hdr, line);
00334 }
00335 }
00336
00337
00338 if (this->header_read == true)
00339 {
00340
00341 if(this->rh_file == NULL)
00342 {
00343
00344 if (this->req_hdr.mthd == GET
00345 || (this->req_hdr.mthd == HEAD && this->req_hdr.ver != V09))
00346 {
00347 int err;
00348
00349 this->rh_file = rhfInit(this, this->req_hdr.uri.path, true);
00350
00351 if ((err = rhfGetError(this->rh_file)) == E_SUCCESS)
00352 {
00353
00354 this->entity_available = true;
00355 } else
00356
00357 this->status = err2Status(err);
00358
00359
00360 if (this->status == 200 && this->req_hdr.if_mod_since != 0)
00361 {
00362 if (difftime(this->req_hdr.if_mod_since, rhfGetModTime(this->rh_file)) >= 0)
00363
00364 this->status = 304;
00365 }
00366
00367 }
00368 else
00369 {
00370 if (this->req_hdr.mthd == MUNKNOWN
00371 || (this->req_hdr.mthd == HEAD && this->req_hdr.ver == V09))
00372
00373 this->status = 400;
00374 else
00375
00376 this->status = 501;
00377 }
00378
00379
00380 if (this->status != 200)
00381 {
00382 char errfile[9];
00383
00384
00385 if (this->rh_file != NULL)
00386 rhfTerminate(this->rh_file);
00387 snprintf(errfile, 9, "%d.html", this->status);
00388 this->rh_file = rhfInit(this, errfile, false);
00389
00390 if (rhfGetError(this->rh_file) != E_SUCCESS)
00391 {
00392 char errmsg[] = "<html>"
00393 "<head><title>Error %d while processing request</title></head>"
00394 "<body>Error %d occured while processing your request.</body>"
00395 "</html>";
00396 err_msg_data = (char*) pd_malloc(strlen(errmsg)+3);
00397 sprintf(err_msg_data, errmsg, this->status, this->status);
00398
00399 this->entity_available = false;
00400 }
00401 else
00402 {
00403
00404 if (this->req_hdr.ver == V09)
00405 this->req_hdr.mthd = GET;
00406 this->entity_available = true;
00407 }
00408 }
00409 }
00410
00411
00412 if (this->req_hdr.ver == V09 )
00413 {
00414 if (err_msg_data == NULL)
00415 this->header_sent = true;
00416 }
00417 else
00418 {
00419
00420 buildBasicHeader(this);
00421
00422 if (this->entity_available
00423 && (this->req_hdr.mthd == GET || this->req_hdr.mthd == HEAD))
00424 {
00425 buildEntityHeader(this);
00426 }
00427
00428 if (err_msg_data == NULL)
00429 {
00430
00431 appendHdrField(this->hdr_list, NULL, NULL);
00432 } else {
00433
00434 appendHdrField(this->hdr_list, "Content-Type", "text/html");
00435 appendHdrField(this->hdr_list, NULL, NULL);
00436
00437
00438
00439
00440
00441 }
00442
00443
00444 }
00445
00446
00447 if (err_msg_data != NULL)
00448 {
00449 if (this->req_hdr.mthd == GET || this->req_hdr.ver == V09)
00450 appendHdrField(this->hdr_list, NULL, err_msg_data);
00451
00452 this->req_hdr.mthd = HEAD;
00453 pd_free(err_msg_data);
00454 }
00455
00456
00457 bufpListFirst(this->hdr_list);
00458
00459
00460 this->data_pending = true;
00461 }
00462 return 0;
00463 }
00464
00465
00474 int copyRequestLine(HttpProtHandler this, struct Buffer* buf )
00475 {
00476 int real_newline = 0;
00477 size_t last_lf_pos;
00478
00479 for (; buf->pos < buf->len; ++buf->pos)
00480 {
00481 char cur_chr = *(buf->data + buf->pos);
00482
00483 if (this->newline && cur_chr != ' ') break;
00484 switch(cur_chr)
00485 {
00486 case '\n':
00487 last_lf_pos = buf->pos;
00488 if (this->last_cr_pos == (ssize_t) buf->pos-1) this->newline = 1;
00489 break;
00490 case '\r':
00491 this->last_cr_pos = buf->pos;
00492 break;
00493 default:
00494 *(this->line_buf.data + this->line_buf.pos++) = cur_chr;
00495
00496 if (this->line_buf.pos == this->line_buf.len)
00497 {
00498 char* new_buf = pd_realloc(this->line_buf.data, this->line_buf.len+=1024);
00499 if (new_buf == NULL)
00500 {
00501 logerr(PROT_HANDLER, CRITICAL, ENOMEM, "out of memory");
00503 exit(EXIT_FAILURE);
00504 }
00505 this->line_buf.data = new_buf;
00506 }
00507 }
00508 }
00509
00510
00511
00512
00513 if (buf->pos != buf->len
00514 || (this->line_buf.pos == 0 && this->newline == true)
00515 || (this->method_read == false && this->newline == true))
00516 {
00517 this->newline = false;
00518 real_newline = true;
00519 }
00520 else
00521 real_newline = false;
00522
00523
00524 if (real_newline) *(this->line_buf.data + this->line_buf.pos) = '\0';
00525
00526 return real_newline ? 0 : -1;
00527 }
00528
00529
00531 #define MKHTTPRESPONSE_TIME_BUF_LEN 30
00532
00534
00535 char* timetToStr(time_t t, struct Buffer* time_buf)
00536 {
00537 size_t time_str_len;
00538
00539 time_str_len = strftime(time_buf->data, time_buf->len,
00540 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
00541
00542 return (time_str_len == 0) ? "" : time_buf->data;
00543 }
00544
00546 time_t strToTimet(const char* str)
00547 {
00548 time_t time;
00549 struct tm t;
00550 int offset = 0;
00551
00552
00553 memset(&t, 0, sizeof(struct tm));
00554
00555
00556 while (isspace((int) *(str+offset))) offset++;
00557
00558
00559 if (strptime(str+offset, "%a, %d %b %Y %T GMT", &t) != NULL) ;
00560
00561 else if(strptime(str+offset, "%a, %d-%m-%Y %T GMT", &t) != NULL);
00562
00563 else if(strptime(str+offset, "%a %b %d %T %Y", &t) != NULL);
00564 else
00565 {
00566 logger(PROT_HANDLER, WARNING, "A time-string could not be handled (strptime)");
00567 return -1;
00568 }
00569
00570 if ((time = mktime(&t)) < 0)
00571 {
00572 logger(PROT_HANDLER, WARNING, "A time-string could not be handled (mktime)");
00573 return -1;
00574 }
00575
00576
00577 #ifdef HAVE_STRUCT_TM_GMTOFF
00578
00579 time += t.tm_gmtoff;
00580 #else
00581
00582 time -= timezone;
00583
00584
00585 #endif
00586
00587 return time;
00588 }
00589
00598 int buildBasicHeader(HttpProtHandler this)
00599 {
00600 struct Buffer* hdr_field;
00601 char time_buf[MKHTTPRESPONSE_TIME_BUF_LEN];
00602 const char* tmp_chr;
00603 struct Buffer* tmp_buf;
00604 time_t tmp_time = time(NULL);
00605 size_t len;
00606
00607
00608
00609 tmp_chr = getStatusAsText(this);
00610 len = 4 + 1 + 3 + 2 + 3 + strlen(tmp_chr) + 2 + 1;
00611 hdr_field = bufpInit((char*) pd_malloc(len), len-1, 0);
00612 snprintf(hdr_field->data, len, "HTTP/1.0 %d %s\r\n", this->status, tmp_chr);
00613 bufpListAppend(this->hdr_list, hdr_field);
00614
00615
00616
00617 len = 6 + MKHTTPRESPONSE_TIME_BUF_LEN + 2;
00618 hdr_field = bufpInit((char*) pd_malloc(len), len-1, 0);
00619 tmp_buf = bufpInit(time_buf, MKHTTPRESPONSE_TIME_BUF_LEN, 0);
00620 snprintf(hdr_field->data, len, "Date: %s\r\n", timetToStr(tmp_time, tmp_buf));
00621 pd_free(tmp_buf);
00622 bufpListAppend(this->hdr_list, hdr_field);
00623
00624
00625 if (reply_server_name)
00626 {
00627 len = 6 + 2 + strlen(SERVERNAME_NSP) + 1 + strlen(SERVERVERSION_NSP) + 2 + 1;
00628 hdr_field = bufpInit((char*) pd_malloc(len), len-1, 0);
00629 snprintf(hdr_field->data, len, "Server: %s/%s\r\n", SERVERNAME_NSP, SERVERVERSION_NSP);
00630 bufpListAppend(this->hdr_list, hdr_field);
00631 }
00632
00633
00634 len = 17 + 2 + 1;
00635 hdr_field = bufpInit((char*) pd_malloc(len), len-1, 0);
00636 snprintf(hdr_field->data, len, "%s", "Connection: close\r\n");
00637 bufpListAppend(this->hdr_list, hdr_field);
00638
00639 return 0;
00640 }
00641
00649 int buildEntityHeader(HttpProtHandler this)
00650 {
00651
00652 struct Buffer buf;
00653 buf.data = (char*)rhfGetAllow(this->rh_file);
00654 appendHdrField(this->hdr_list, "Allow", buf.data);
00655
00656
00657 buf.data = (char*)rhfGetContentType(this->rh_file);
00658 if (buf.data != NULL)
00659 appendHdrField(this->hdr_list, "Content-Type", buf.data);
00660
00661
00662 buf.data = (char*) pd_malloc(100);
00663 snprintf(buf.data, 100, "%u", rhfGetSourceSize(this->rh_file));
00664 appendHdrField(this->hdr_list, "Content-Length", buf.data);
00665 pd_free(buf.data);
00666
00667
00668 buf.len = MKHTTPRESPONSE_TIME_BUF_LEN;
00669 buf.data = (char*) pd_malloc(buf.len);
00670 timetToStr(rhfGetModTime(this->rh_file), &buf);
00671 appendHdrField(this->hdr_list, "Last-Modified", buf.data);
00672 pd_free(buf.data);
00673
00674 return 0;
00675 }
00676
00679 int appendHdrField(BufpList hdr_list, char* prefix, char* data)
00680 {
00681 struct Buffer* buf = (struct Buffer*) pd_malloc(sizeof(struct Buffer));
00682 size_t prefix_len;
00683
00684 buf->pos = 0;
00685 if (prefix == NULL && data == NULL)
00686 {
00687 buf->len = 2;
00688 buf->data = (char*) pd_malloc(buf->len+1);
00689 }
00690 else if (data == NULL)
00691 return -1;
00692 else
00693 {
00694 if (prefix == NULL)
00695 {
00696 prefix_len = 0;
00697 buf->len = strlen(data) + 2;
00698 buf->data = (char*) pd_malloc(buf->len+1);
00699 } else {
00700 prefix_len = strlen(prefix);
00701
00702 buf->len = prefix_len + 2 + strlen(data) + 2;
00703 buf->data = (char*) pd_malloc(buf->len+1);
00704 strcpy(buf->data, prefix);
00705
00706 buf->data[prefix_len++] = ':';
00707 buf->data[prefix_len++] = ' ';
00708 }
00709 strcpy(buf->data + prefix_len, data);
00710 }
00711
00712 buf->data[buf->len - 2] = '\r';
00713 buf->data[buf->len - 1] = '\n';
00714 buf->data[buf->len - 0] = '\0';
00715
00716
00717 bufpListAppend(hdr_list, buf);
00718
00719 return 0;
00720 }
00721
00723 int htMthdParse(HttpProtHandler this, const char* str)
00724 {
00725 int beg = 0;
00726 int end = 0;
00727 int crlf = 0;
00728
00729
00730
00731 if ((crlf = getNextValue(&beg, &end, end, str)) != 0)
00732 this->status = 400;
00733 else
00734 {
00735
00736 if ((strncmp(str+beg, "GET", end-beg+1) == 0) && ((end-beg+1) == (int)strlen("GET")))
00737 this->req_hdr.mthd = GET;
00738 else if ((strncmp(str+beg, "HEAD", end-beg+1) == 0) && ((end-beg+1) == (int)strlen("HEAD")))
00739 this->req_hdr.mthd = HEAD;
00740 else if ((strncmp(str+beg, "POST", end-beg+1) == 0) && ((end-beg+1) == (int)strlen("POST")))
00741 this->req_hdr.mthd = POST;
00742 else
00743 {
00744 this->req_hdr.mthd = MUNKNOWN;
00745
00746 this->status = 400;
00747 }
00748 }
00749
00750
00751 if((crlf = getNextValue(&beg, &end, end+1, str)) != 0)
00752 this->status = 400;
00753 else
00754 {
00755 char* tmp = pd_malloc(end-beg+2);
00756
00757 strncpy(tmp, str+beg, end-beg+1);
00758 *(tmp+end-beg+1) = '\0';
00759 this->req_hdr.uri = resolvURI(tmp);
00760
00761 pd_free(tmp);
00762 }
00763
00764
00765 if((crlf = getNextValue(&beg, &end, end+1, str)) != 0)
00766 this->req_hdr.ver = V09;
00767 else
00768 {
00769 if (strncmp(str+beg,"HTTP/0.9",end-beg+1) == 0 && ((end-beg+1) == 8))
00770 this->req_hdr.ver = V09;
00771 else if (strncmp(str+beg,"HTTP/1.0",end-beg+1) == 0 && ((end-beg+1) == 8))
00772 this->req_hdr.ver = V10;
00773 else if (strncmp(str+beg,"HTTP/1.1",end-beg+1) == 0 && ((end-beg+1) == 8))
00774 this->req_hdr.ver = V11;
00775 else
00776 this->req_hdr.ver = VUNKNOWN;
00777 }
00778 return (this->status == 200) ? 0 : -1;
00779 }
00780
00782 int htAddData(struct HttpRequestHdr* hdr, const char* str)
00783 {
00784 char* pos = strchr(str, ':');
00785 char* datpos = pos+1;
00786 while(isspace((int) *datpos))
00787 datpos++;
00788
00789 if (hdr == NULL) return -2;
00790
00791 if (pos - str < (int)strlen(str))
00792 {
00793
00794
00795
00796
00797 if (strncmp(str,"From:",pos-str) == 0)
00798 {
00799 hdr->from = (char*)pd_malloc(strlen(str)-(datpos-str)+1);
00800 strcpy(hdr->from, datpos);
00801 }
00802 else if (strncmp(str,"If-Modified-Since:",pos-str) == 0)
00803 {
00804 hdr->if_mod_since = strToTimet(pos+1);
00805 }
00806 else if (strncmp(str,"Referer:",pos-str) == 0)
00807 {
00808 hdr->referer = resolvURI(pos+1);
00809 }
00810 else if (strncmp(str,"User-Agent:",pos-str) == 0)
00811 {
00812 hdr->usr_agent = (char*)pd_malloc(strlen(str)-(datpos-str)+1);
00813 strcpy(hdr->usr_agent, datpos);
00814 }
00815 else if (strncmp(str,"Host:",pos-str) == 0)
00816 {
00817 struct Uri tmpuri;
00818 char* http = "http://";
00819 size_t len_http = 7;
00820 char* tmp = pd_malloc(strlen(str)-(datpos-str)+len_http+1);
00821
00822 strcpy(tmp, http);
00823 strcat(tmp, datpos);
00824
00825 tmpuri = resolvURI(tmp);
00826
00827 if (tmpuri.valid)
00828 {
00829 if (hdr->uri.server != NULL)
00830 pd_free(hdr->uri.server);
00831 hdr->uri.server = tmpuri.server;
00832 hdr->uri.port = tmpuri.port;
00833 }
00834
00835 pd_free(tmpuri.path);
00836 pd_free(tmp);
00837 }
00838 }
00839 return 0;
00840 }
00841
00843 const char* getStatusAsText(HttpProtHandler this)
00844 {
00845 switch(this->status)
00846 {
00847 case(200): return "OK";
00848 case(201): return "Created";
00849 case(202): return "Accepted";
00850 case(204): return "No Content";
00851 case(301): return "Moved Permanently";
00852 case(302): return "Moved Temporarily";
00853 case(304): return "Not Modified";
00854 case(400): return "Bad Request";
00855 case(401): return "Unauthorized";
00856 case(403): return "Forbidden";
00857 case(404): return "Not Found";
00858 case(500): return "Internal Server Error";
00859 case(501): return "Not Implemented";
00860 case(502): return "Bad Gateway";
00861 case(503): return "Service Unavailable";
00862 default: return "Unknown";
00863 }
00864 }
00865
00867 struct Uri resolvURI(const char* pstr)
00868 {
00869 struct Uri uri;
00870 size_t pos = 0;
00871 size_t len_http = 7;
00872
00873
00874 int offset = 0;
00875
00876 char* str = (char*)pd_malloc(strlen(pstr)+1);
00877
00878 uri.valid = true;
00879
00880 while (isspace((int) *(pstr+offset)))
00881 offset++;
00882 strcpy(str, pstr+offset);
00883
00884
00885 if (strncmp(str, "http://", len_http) == 0)
00886 {
00887 pos += len_http;
00888
00889 while ((isalnum((int) *(str+pos))
00890 || *(str+pos) == '.' || *(str+pos) == '_' || *(str+pos) == '-')
00891 && pos < strlen(str))
00892 pos++;
00893
00894 if (pos == strlen(str))
00895 {
00896 uri.path = pd_malloc(2);
00897 strcpy(uri.path, "/");
00898 uri.server = pd_malloc(strlen(str)-len_http);
00899 strcpy(uri.server, str+len_http);
00900 uri.port = 0;
00901 }
00902 else if (*(str+pos) == ':')
00903 {
00904 size_t oldpos = pos++;
00905
00906
00907 while(isdigit((int) *(str+pos)) && pos < strlen(str))
00908 pos++;
00909
00910 if (pos == strlen(str))
00911 {
00912 uri.path = pd_malloc(2);
00913 strcpy(uri.path, "/");
00914 uri.server = pd_malloc(oldpos-len_http+1);
00915 strncpy(uri.server, str+len_http, oldpos-len_http);
00916 *(uri.server+oldpos-len_http-1+1) = '\0';
00917 }
00918 else
00919 {
00920 uri.path = pd_malloc(strlen(str)-pos+1);
00921 strcpy(uri.path, str+pos);
00922
00923 uri.server = pd_malloc(oldpos-len_http+1);
00924 strncpy(uri.server, str+len_http, oldpos-len_http);
00925 *(uri.server+oldpos-len_http-1+1) = '\0';
00926 }
00927
00928
00929 if (pos == oldpos+1)
00930 uri.port = 0;
00931 else
00932 {
00933 char* tmp = pd_malloc(pos - oldpos);
00934
00935 strncpy(tmp, str+oldpos+1, pos-oldpos-1);
00936 *(tmp+pos-oldpos-1) = '\0';
00937 uri.port = atoi(tmp);
00938 pd_free(tmp);
00939
00940 if (uri.port < 1 || uri.port > 65535)
00941 uri.port = 0;
00942 }
00943 }
00944 else
00945 {
00946 uri.path = pd_malloc(strlen(str)-pos+1);
00947 strncpy(uri.path, str+pos, strlen(str)-pos);
00948 *(uri.path+strlen(str)-pos+1) = '\0';
00949 if (pos == len_http )
00950 uri.server = NULL;
00951 else
00952 {
00953 uri.server = pd_malloc(pos-len_http);
00954 strncpy(uri.server, str+len_http, pos-len_http);
00955 *(uri.server+pos-len_http) = '\0';
00956 }
00957 uri.port = 0;
00958 }
00959 }
00960 else
00961 {
00962 uri.path = pd_malloc(strlen(str)+1);
00963 strcpy(uri.path, str);
00964 uri.server = NULL;
00965 uri.port = 0;
00966 }
00967 pd_free(str);
00968 return uri;
00969 }
00970
00972 int err2Status(int err)
00973 {
00974 switch (err)
00975 {
00976 case(ENOENT):
00977 case(ENOTDIR):
00978
00979 return 404;
00980 case(EACCES):
00981
00982 return 403;
00983 case(EIO):
00984 default:
00985
00986 return 500;
00987 }
00988 }