127 |
static void internal_error(Socket_T, int, char *); |
static void internal_error(Socket_T, int, char *); |
128 |
static HttpResponse create_HttpResponse(Socket_T); |
static HttpResponse create_HttpResponse(Socket_T); |
129 |
static int is_authenticated(HttpRequest, HttpResponse); |
static int is_authenticated(HttpRequest, HttpResponse); |
130 |
|
static int get_next_token(char *s, int *cursor, char **r); |
131 |
|
|
132 |
|
|
133 |
/* ------------------------------------------------------------------ Public */ |
/* ------------------------------------------------------------------ Public */ |
512 |
* them to the doXXX methods defined in a cervlet module. |
* them to the doXXX methods defined in a cervlet module. |
513 |
*/ |
*/ |
514 |
static void do_service(Socket_T s) { |
static void do_service(Socket_T s) { |
|
|
|
515 |
volatile HttpResponse res= create_HttpResponse(s); |
volatile HttpResponse res= create_HttpResponse(s); |
516 |
volatile HttpRequest req= create_HttpRequest(s); |
volatile HttpRequest req= create_HttpRequest(s); |
517 |
|
|
518 |
if(res && req) { |
if(res && req) { |
|
|
|
519 |
if(is_authenticated(req, res)) { |
if(is_authenticated(req, res)) { |
|
|
|
520 |
if(IS(req->method, METHOD_GET)) { |
if(IS(req->method, METHOD_GET)) { |
521 |
|
|
522 |
Impl.doGet(req, res); |
Impl.doGet(req, res); |
523 |
|
|
524 |
} |
} else if(IS(req->method, METHOD_POST)) { |
|
else if(IS(req->method, METHOD_POST)) { |
|
525 |
|
|
526 |
Impl.doPost(req, res); |
Impl.doPost(req, res); |
527 |
|
|
528 |
} |
} else { |
|
else { |
|
529 |
|
|
530 |
send_error(res, SC_NOT_IMPLEMENTED, "Method not implemented"); |
send_error(res, SC_NOT_IMPLEMENTED, "Method not implemented"); |
|
|
|
|
} |
|
531 |
|
|
532 |
|
} |
533 |
} |
} |
534 |
|
|
535 |
send_response(res); |
send_response(res); |
536 |
|
|
537 |
} |
} |
538 |
|
|
539 |
done(req, res); |
done(req, res); |
|
|
|
540 |
} |
} |
541 |
|
|
542 |
|
|
618 |
static HttpRequest create_HttpRequest(Socket_T S) { |
static HttpRequest create_HttpRequest(Socket_T S) { |
619 |
|
|
620 |
HttpRequest req; |
HttpRequest req; |
|
char method[STRLEN]; |
|
621 |
char url[REQ_STRLEN]; |
char url[REQ_STRLEN]; |
622 |
char line[REQ_STRLEN]; |
char line[REQ_STRLEN]; |
623 |
char protocol[STRLEN]; |
char protocol[STRLEN]; |
624 |
|
char method[REQ_STRLEN]; |
625 |
|
|
626 |
|
|
627 |
if(socket_readln(S, line, REQ_STRLEN) == NULL) { |
if(socket_readln(S, line, REQ_STRLEN) == NULL) { |
628 |
internal_error(S, SC_BAD_REQUEST, "No request found"); |
internal_error(S, SC_BAD_REQUEST, "No request found"); |
629 |
return NULL; |
return NULL; |
630 |
} |
} |
631 |
|
|
632 |
|
chomp(line); |
633 |
|
|
634 |
if(sscanf(line, "%s %s HTTP/%3[1.0]", method, url, protocol) != 3) { |
if(sscanf(line, "%s %s HTTP/%3[1.0]", method, url, protocol) != 3) { |
635 |
internal_error(S, SC_BAD_REQUEST, "Cannot parse request"); |
internal_error(S, SC_BAD_REQUEST, "Cannot parse request"); |
643 |
|
|
644 |
NEW(req); |
NEW(req); |
645 |
req->S= S; |
req->S= S; |
646 |
chomp(protocol); |
url_decode(url); |
|
unescape_url(url); |
|
647 |
req->url= xstrdup(url); |
req->url= xstrdup(url); |
648 |
req->method= xstrdup(method); |
req->method= xstrdup(method); |
649 |
req->protocol= xstrdup(protocol); |
req->protocol= xstrdup(protocol); |
746 |
int alloc= FALSE; |
int alloc= FALSE; |
747 |
char *query_string= NULL; |
char *query_string= NULL; |
748 |
|
|
749 |
if(IS(req->method, METHOD_POST)) { |
if(IS(req->method, METHOD_POST) && get_header(req, "Content-Length")) { |
750 |
|
int n; |
751 |
|
int len; |
752 |
Socket_T S= req->S; |
Socket_T S= req->S; |
753 |
|
if(1 != sscanf(get_header(req, "Content-Length"), "%d", &len)) { |
754 |
int len; char *l= get_header(req, "Content-Length"); |
return FALSE; |
755 |
|
} |
756 |
if(l && (len= atoi(l))) { |
if(len < 0) |
757 |
|
return FALSE; |
758 |
query_string= xmalloc(sizeof(char) * (len + 1)); |
if(len==0) |
759 |
|
return TRUE; |
760 |
if(socket_read(S, query_string, len) <= 0) { |
|
761 |
|
query_string= xcalloc(sizeof(char), len + 1); |
|
FREE(query_string); |
|
|
return FALSE; |
|
|
|
|
|
} |
|
|
|
|
|
alloc= TRUE; |
|
762 |
|
|
763 |
|
if(((n= socket_read(S, query_string, len)) <= 0) || (n != len)) { |
764 |
|
FREE(query_string); |
765 |
|
return FALSE; |
766 |
} |
} |
767 |
|
query_string[n]= 0; |
768 |
|
alloc= TRUE; |
769 |
} else if(IS(req->method, METHOD_GET)) { |
} else if(IS(req->method, METHOD_GET)) { |
|
|
|
770 |
char *p; |
char *p; |
771 |
|
if(NULL != (p= strchr(req->url, '?'))) { |
772 |
if( NULL != (p= strchr(req->url, '?'))) { |
*p++= 0; |
|
|
|
|
*p++= '\0'; |
|
773 |
query_string= p; |
query_string= p; |
|
|
|
774 |
} |
} |
|
|
|
775 |
} |
} |
776 |
|
|
777 |
if(query_string) { |
if(query_string && *query_string) { |
|
|
|
778 |
char *p; |
char *p; |
779 |
|
if(NULL != (p= strchr(query_string, '/'))) { |
780 |
if( NULL != (p= strchr(query_string, '/'))) { |
*p++= 0; |
|
|
|
|
*p++= '\0'; |
|
781 |
req->pathinfo= p; |
req->pathinfo= p; |
|
|
|
782 |
} |
} |
|
|
|
783 |
req->params= parse_parameters(query_string); |
req->params= parse_parameters(query_string); |
|
|
|
784 |
} |
} |
785 |
|
|
786 |
if(alloc)FREE(query_string); |
if(alloc)FREE(query_string); |
1007 |
*/ |
*/ |
1008 |
static HttpParameter parse_parameters(char *query_string) { |
static HttpParameter parse_parameters(char *query_string) { |
1009 |
|
|
1010 |
int controller= 1000; |
#define KEY 1 |
1011 |
|
#define VALUE 2 |
1012 |
|
|
1013 |
|
int token; |
1014 |
|
int cursor= 0; |
1015 |
|
char *key= NULL; |
1016 |
|
char *value= NULL; |
1017 |
|
char *s= query_string; |
1018 |
HttpParameter head= NULL; |
HttpParameter head= NULL; |
1019 |
|
|
1020 |
while(query_string[0] && controller--) { |
while((token= get_next_token(s, &cursor, &value))) { |
1021 |
|
if(token==KEY) |
1022 |
HttpParameter p; |
key= value; |
1023 |
NEW(p); |
else if(token==VALUE) { |
1024 |
p->value= makeword(query_string,'&'); |
HttpParameter p; |
1025 |
p->name= makeword(p->value,'='); |
if(!key) goto error; |
1026 |
plustospace(p->value); |
NEW(p); |
1027 |
unescape_url(p->value); |
p->name= key; |
1028 |
plustospace(p->name); |
p->value= value; |
1029 |
unescape_url(p->name); |
p->next= head; |
1030 |
p->next= head; |
head= p; |
1031 |
head= p; |
key= NULL; |
1032 |
|
} |
1033 |
} |
} |
1034 |
|
|
1035 |
return head; |
return head; |
1036 |
|
|
1037 |
|
error: |
1038 |
|
FREE(key); |
1039 |
|
FREE(value); |
1040 |
|
destroy_entry(head); |
1041 |
|
|
1042 |
|
return NULL; |
1043 |
|
|
1044 |
} |
} |
1045 |
|
|
1046 |
|
|
1047 |
|
/** |
1048 |
|
* A mini-scanner for tokenizing a query string |
1049 |
|
*/ |
1050 |
|
static int get_next_token(char *s, int *cursor, char **r) { |
1051 |
|
|
1052 |
|
int i= *cursor; |
1053 |
|
|
1054 |
|
while(s[*cursor]) { |
1055 |
|
if(s[*cursor+1]=='=') { |
1056 |
|
*cursor+= 1; |
1057 |
|
*r= xstrndup(&s[i], (*cursor-i)); |
1058 |
|
return KEY; |
1059 |
|
} |
1060 |
|
if(s[*cursor]=='=') { |
1061 |
|
while(s[*cursor] && s[*cursor]!='&') *cursor+= 1; |
1062 |
|
if(s[*cursor]=='&') { |
1063 |
|
*r= xstrndup(&s[i+1], (*cursor-i)-1); |
1064 |
|
*cursor+= 1; |
1065 |
|
} else |
1066 |
|
*r= xstrndup(&s[i+1], (*cursor-i)); |
1067 |
|
return VALUE; |
1068 |
|
} |
1069 |
|
*cursor+= 1; |
1070 |
|
} |
1071 |
|
|
1072 |
|
return FALSE; |
1073 |
|
|
1074 |
|
} |