+++ /dev/null
-
-/* -}{----------------------------------------------------------------------- */
-
-#include <kernelapi.h>
-#undef PUBLIC
-#define PUBLIC EXPORT
-#include <ni.h>
-
-/* -}{---- ------------------------------------------------------------------ */
-
-static k_hashtable* entity_headers;
-
-/* -}{---- ------------------------------------------------------------------ */
-
-#define TMPBUFSIZE 4096
-static char tmpbuf[TMPBUFSIZE];
-
-/* -}{----------------------------------------------------------------------- */
-
-static char* get_request( char* header, k_hashtable*, k_hashtable*);
-static char* get_response(char* header, k_hashtable*, k_hashtable*);
-static char* get_val(char** atp);
-static char* end_of_val(char* at);
-static void fix_keepalive(k_hashtable* evt_head);
-static void fix_cache_control(k_hashtable* ent_head);
-static void fix_uri(k_hashtable* ent_head);
-static void fix_subscribe(k_hashtable*, k_hashtable*);
-
-/* -}{----------------------------------------------------------------------- */
-
-#define WHITESPACEH " \t"
-#define WHITESPACEV "\012\015"
-#define WHITESPACE WHITESPACEH WHITESPACEV
-
-EXPORT ni_event* ni_get_request_headers(char* header)
-{
- k_hashtable* evt_head=k_hashtable_new("vHeaders/get_req_hdrs", 1);
- k_hashtable* ent_head=k_hashtable_new("nHeaders/get_req_hdrs", 1);
- k_hashtable_put(ent_head, "", header);
-
- char* h=get_request(header, evt_head, ent_head);
- if(!h){
- k_hashtable_delete(evt_head);
- k_hashtable_delete(ent_head);
- return 0;
- }
-
- h=ni_get_headers(h, evt_head, ent_head);
- if(!h){
- k_hashtable_delete(evt_head);
- k_hashtable_delete(ent_head);
- return 0;
- }
-
- fix_keepalive(evt_head);
- fix_cache_control(ent_head);
- fix_uri(ent_head);
- fix_subscribe(evt_head, ent_head);
-
- ni_event* evq=ni_event_new(0, evt_head, ent_head, 0);
-
- return evq;
-}
-
-EXPORT ni_event* ni_get_response_headers(char* header)
-{
- k_hashtable* evt_head=k_hashtable_new("vHeaders/get_resp_hdrs", 1);
- k_hashtable* ent_head=k_hashtable_new("nHeaders/get_resp_hdrs", 1);
- k_hashtable_put(ent_head, "", header);
-
- char* h=get_response(header, evt_head, ent_head);
- if(!h){
- k_hashtable_delete(evt_head);
- k_hashtable_delete(ent_head);
- return 0;
- }
-
- h=ni_get_headers(h, evt_head, ent_head);
- if(!h){
- k_hashtable_delete(evt_head);
- k_hashtable_delete(ent_head);
- return 0;
- }
-
- ni_event* evt=ni_event_new(0, evt_head, ent_head, 0);
-
- return evt;
-}
-
-EXPORT char* ni_get_headers(char* header,
- k_hashtable* evt_head,
- k_hashtable* ent_head)
-{
- char* at=header;
- char* tag;
- char* val;
- while(*at){
-
- tag=at;
- at=strpbrk(at, WHITESPACE);
- if(!at || at==tag) return 0;
- char* e=at;
- val=get_val(&at);
- *e=0;
-
- if(strlen(val) > 2048) return 0;
-
- k_hashtable* h;
- h=k_hashtable_get(entity_headers, tag)? ent_head: evt_head;
- if(h){
- char* old=k_hashtable_get(h, tag);
- if(!old) k_hashtable_set(h, tag, val);
- }
- }
- return at;
-}
-
-EXPORT void ni_fix_http_headers(k_hashtable* ent_head)
-{
- if(k_hashtable_is(ent_head, "Status:", "260")){
- char* crn=k_hashtable_get(ent_head, "Content-Range:");
- char* clg=k_hashtable_get(ent_head, "Content-Length-Given:");
- if(crn || clg){
- k_hashtable_set(ent_head, "Status:", "206");
- k_hashtable_set(ent_head, "Status-Text:", "Partial Content");
- }
- else{
- k_hashtable_set(ent_head, "Status:", "200");
- k_hashtable_set(ent_head, "Status-Text:", "OK");
- }
- }
- k_hashtable_remove(ent_head, "URI:");
- k_hashtable_remove(ent_head, "Method:");
- k_hashtable_remove(ent_head, "From:");
- k_hashtable_remove(ent_head, "Content-Length-Given:");
- k_hashtable_remove(ent_head, "Last-Modified-Epoch:");
-
- char* cc=k_hashtable_get(ent_head, "Cache-Control:");
- if(cc && strstr(cc, "no-cache")){
- k_hashtable_set(ent_head, "Pragma:", "no-cache");
- }
-}
-
-EXPORT void ni_fix_ni_headers(k_hashtable* ent_head, int methead)
-{
- if(methead && (k_hashtable_is(ent_head, "Status:", "200") ||
- k_hashtable_is(ent_head, "Status:", "206") )){
-
- k_hashtable_set(ent_head, "Status:", "260");
- k_hashtable_set(ent_head, "Status-Text:", "Headers Only");
- }
- k_hashtable_remove(ent_head, "Method:");
- k_hashtable_remove(ent_head, "Sub-To:");
- k_hashtable_remove(ent_head, "Via:");
- k_hashtable_set( ent_head, "From:", ni_hostname());
-
- char* uri=k_hashtable_get(ent_head, "URI:");
- if(*uri=='.'){
- snprintf(tmpbuf, TMPBUFSIZE, "%s/%s", ni_hostname(), uri+2);
- k_hashtable_put_dup(ent_head, "URI:", tmpbuf);
- }
-}
-
-EXPORT void ni_response(ni_event* evt,
- char* to,
- char* method,
- char* protocol,
- char* connection,
- k_channel* chan)
-{
- int L=0;
- snprintf(tmpbuf, TMPBUFSIZE, "%s", k_time_to_rfc_relative(0));
- k_hashtable_put_dup(evt->evt_head, "Date:", tmpbuf);
- k_hashtable_set( evt->evt_head, "Server:", k_version);
- if(connection)
- k_hashtable_put_dup(evt->evt_head, "Connection:", connection);
-
- int status =k_hashtable_get_int(evt->ent_head, "Status:");
- char* statustext=k_hashtable_get( evt->ent_head, "Status-Text:");
- int datalength=k_hashtable_get_int(evt->ent_head, "Content-Length:");
- int constant =k_hashtable_is( evt->ent_head, "CUX:", "C");
-
- char* buf =tmpbuf;
- int bufsize=TMPBUFSIZE;
- int ln=0;
-
- ln+=snprintf(buf+ln, bufsize-ln, "%s %d %s" CRLF,
- protocol, status, statustext);
- if(ln>=bufsize) return;
-
- static char* exheaders[]={ "Status:", "Status-Text:",
- "Protocol:", "CUX:", 0 };
-
- ln+=k_hashtable_snprintf_x(evt->evt_head, buf+ln,bufsize-ln, exheaders);
- if(ln>=bufsize) return;
-
- ln+=k_hashtable_snprintf_x(evt->ent_head, buf+ln,bufsize-ln, exheaders);
- if(ln>=bufsize) return;
-
- ln+=snprintf(buf+ln, bufsize-ln, CRLF);
- if(ln>=bufsize) return;
-
- char* head=k_strdup(buf);
- if(L) k_log_out("Actual response headers:\n%s", head);
- k_channel_send(chan, head, ln, FREE_ON_SENT);
-
- if(evt->entity && datalength){
- k_channel_send(chan, evt->entity, datalength, !constant);
- }
- else{
- datalength=0;
- if(!constant) k_free(evt->entity);
- }
- k_log_out("%s %s %s %d %d", to, method, evt->uri, status, datalength);
-}
-
-EXPORT void ni_request(ni_event* evt, char* to, char* method, k_channel* chan)
-{
- k_hashtable* sub=evt->ent_head;
-
- int ln=0;
- int bufsize=TMPBUFSIZE;
-
- ln+=snprintf(tmpbuf+ln, bufsize-ln, "%s //%s ni/0.5" CRLF, method, to);
- if(ln>=bufsize) return;
-
- ln+=k_hashtable_snprintf(sub, tmpbuf+ln, bufsize-ln);
- if(ln>=bufsize) return;
-
- ln+=snprintf(tmpbuf+ln, bufsize-ln, CRLF);
- if(ln>=bufsize) return;
-
- char* head=k_strdup(tmpbuf);
- if(0) k_log_out("Actual request headers:\n%s", head);
- k_channel_send(chan, head, ln, FREE_ON_SENT);
-}
-
-/* -}{----------------------------------------------------------------------- */
-
-char* get_request(char* header, k_hashtable* evt_head, k_hashtable* ent_head)
-{
- char* at=header;
- char* method=at;
- at=strpbrk(at, WHITESPACEH);
- if(!at) return 0;
- *at++=0;
-
- k_hashtable_set(ent_head, "Method:", method);
-
- char* file=0;
- char* host=0;
- if(strcmp(method, "PING")){
-
- at+=strspn(at, WHITESPACEH);
- file=at;
- at=strpbrk(at, WHITESPACEH);
- if(!at) return 0;
- *at++=0;
- if(strlen(file) > 1024 ) return 0;
-
- if(!strncmp(file, "http://", 7)){
- char* s=file+7;
- if(!*s || *s=='/') return 0;
- char* e=strchr(s, '/');
- if(!e) return 0;
- host=s;
- *e++=0;
- file=e;
- }
- else
- if(*file=='/') file++;
- else return 0;
-
- if(*file=='/'){
- char* s=file+1;
- if(!*s || *s=='/') return 0;
- char* e=strchr(s, '/');
- if(!e) return 0;
- host=s;
- *e++=0;
- file=e;
- }
- }
- if(file) k_hashtable_set(evt_head, "File:", file);
- if(host) k_hashtable_set(evt_head, "Host:", host);
-
- at+=strspn(at, WHITESPACEH);
- char* protocol=at;
- at=strpbrk(at, WHITESPACE);
- if(!at) at=protocol+strlen(protocol);
- else *at++=0;
-
- k_hashtable_set(evt_head, "Protocol:", protocol);
-
- at+=strspn(at, WHITESPACE);
- return at;
-}
-
-char* get_response(char* header, k_hashtable* evt_head, k_hashtable* ent_head)
-{
- char* at=header;
- char* protocol=at;
- at=strpbrk(at, WHITESPACEH);
- if(!at) return 0;
- *at++=0;
-
- k_hashtable_set(evt_head, "Protocol:", protocol);
-
- at+=strspn(at, WHITESPACEH);
- char* status=at;
- at=strpbrk(at, WHITESPACEH);
- if(!at) return 0;
- *at++=0;
-
- at+=strspn(at, WHITESPACEH);
- char* statustext=at;
- at=strpbrk(at, WHITESPACEV);
- if(!at) return 0;
- *at++=0;
-
- k_hashtable_set(ent_head, "Status:", status);
- k_hashtable_set(ent_head, "Status-Text:", statustext);
-
- at+=strspn(at, WHITESPACE);
- return at;
-}
-
-char* get_val(char** atp)
-{
- char* at=*atp;
- char* val=at;
-
- val+=strspn(val, WHITESPACEH);
- val+=strspn(val, WHITESPACEV);
-
- char* eov=end_of_val(at);
- if(eov<val) val=eov;
- if(*eov) *eov++=0;
-
- *atp=eov+strspn(eov, WHITESPACEV);
- return val;
-}
-
-char* end_of_val(char* at)
-{
- char* eov;
- do{
- char* v=strpbrk(at, WHITESPACEV);
- if(!v) return at+strlen(at);
- eov=v;
- at=v+strspn(v, WHITESPACEV);
-
- }while(strspn(at, WHITESPACEH));
-
- return eov;
-}
-
-void fix_keepalive(k_hashtable* evt_head)
-{
- int keepalive=0;
- int is11=k_hashtable_is( evt_head, "Protocol:", "HTTP/1.1");
- int isps=k_hashtable_isn(evt_head, "Protocol:", "ni/", 4);
- int iska=k_hashtable_isi(evt_head, "Connection:", "Keep-Alive");
- int iscl=k_hashtable_isi(evt_head, "Connection:", "close");
- if((!is11 && iska) || (is11 && !iscl) || isps){
- keepalive=1;
- }
- if(0) k_log_out("is11=%d iska=%d iscl=%d isps=%d ka=%d",
- is11, iska, iscl, isps, keepalive);
- k_hashtable_set(evt_head, "Connection:",
- keepalive? "Keep-Alive": "close");
-}
-
-void fix_cache_control(k_hashtable* ent_head)
-{
- char* cachec=k_hashtable_get( ent_head, "Cache-Control:");
- char* pragma=k_hashtable_extract(ent_head, "Pragma:");
- if(!cachec && pragma && strstr(pragma, "no-cache")){
- k_hashtable_set( ent_head, "Cache-Control:","no-cache");
- }
-}
-
-void fix_uri(k_hashtable* ent_head)
-{
- char* uri=k_hashtable_get(ent_head, "URI:");
- if(!uri) return;
- char* nihostname=ni_hostname();
- int l=strlen(nihostname);
- if(strncmp(uri, nihostname, l)) return;
- snprintf(tmpbuf, TMPBUFSIZE, ".%s", uri+l);
- k_hashtable_put_dup(ent_head, "URI:", tmpbuf);
-}
-
-void fix_subscribe(k_hashtable* evt_head, k_hashtable* ent_head)
-{
- char* host=k_hashtable_extract(evt_head, "Host:");
- char* file=k_hashtable_extract(evt_head, "File:");
- if(host){
- k_string_url_decode(host);
- int localhostdns=!strcmp( host, "localhost") ||
- !strncmp(host, "localhost:", 10);
- int localhostni=!strcmp(host, ni_hostname());
- char* lastdot=strrchr(host, '.');
- int dotdotnumber=lastdot && atoi(lastdot+1) >0;
- if(localhostdns || localhostni || dotdotnumber){
- host=".";
- }
- }
- else{
- host=".";
- }
- if(file){
- k_string_url_decode(file);
- snprintf(tmpbuf, TMPBUFSIZE, "%s/%s", host, file);
- k_hashtable_put_dup(ent_head, "Sub-To:", tmpbuf);
- k_hashtable_set( ent_head, "Sub-Type:", "Original");
- }
-}
-
-void init_headers(void)
-{
- entity_headers =k_hashtable_new("Entity Headers", 1);
-
- k_hashtable_set(entity_headers, "URI:", (void*)1);
- k_hashtable_set(entity_headers, "From:", (void*)1);
- k_hashtable_set(entity_headers, "To:", (void*)1);
- k_hashtable_set(entity_headers, "Via:", (void*)1);
- k_hashtable_set(entity_headers, "Sub-To:", (void*)1);
- k_hashtable_set(entity_headers, "Sub-Type:", (void*)1);
- k_hashtable_set(entity_headers, "Method:", (void*)1);
- k_hashtable_set(entity_headers, "Status:", (void*)1);
- k_hashtable_set(entity_headers, "Status-Text:", (void*)1);
- k_hashtable_set(entity_headers, "Last-Modified-Epoch:", (void*)1);
- k_hashtable_set(entity_headers, "CUX:", (void*)1);
-
- k_hashtable_set(entity_headers, "Range:", (void*)1);
- k_hashtable_set(entity_headers, "If-Modified-Since:", (void*)1);
- k_hashtable_set(entity_headers, "If-None-Match:", (void*)1);
- k_hashtable_set(entity_headers, "Cache-Control:", (void*)1);
- k_hashtable_set(entity_headers, "Pragma:", (void*)1);
-
- k_hashtable_set(entity_headers, "Content-Length:", (void*)1);
- k_hashtable_set(entity_headers, "Content-Type:", (void*)1);
- k_hashtable_set(entity_headers, "Content-Encoding:", (void*)1);
- k_hashtable_set(entity_headers, "Content-Location:", (void*)1);
- k_hashtable_set(entity_headers, "Content-MD5:", (void*)1);
- k_hashtable_set(entity_headers, "Content-Language:", (void*)1);
- k_hashtable_set(entity_headers, "Content-Range:", (void*)1);
- k_hashtable_set(entity_headers, "Last-Modified:", (void*)1);
- k_hashtable_set(entity_headers, "ETag:", (void*)1);
- k_hashtable_set(entity_headers, "Expires:", (void*)1);
-
- k_hashtable_set(entity_headers, "Allow:", (void*)1);
-}
-
-void drop_entity_headers(k_hashtable* ent_head)
-{
- k_hashtable_remove(ent_head, "Content-Length:");
- k_hashtable_remove(ent_head, "Content-Range:");
- k_hashtable_remove(ent_head, "Content-Type:");
- k_hashtable_remove(ent_head, "Content-Encoding:");
- k_hashtable_remove(ent_head, "Content-Location:");
- k_hashtable_remove(ent_head, "Last-Modified:");
-#ifdef DO_THESE_ONES_TOO
- k_hashtable_remove(ent_head, "Allow:");
- k_hashtable_remove(ent_head, "Content-Language:");
- k_hashtable_remove(ent_head, "Content-MD5:");
- k_hashtable_remove(ent_head, "Expires:");
-#endif
-}
-
-void fill_headers(k_hashtable* ent_head,
- char* status,
- char* statustext,
- char* uri,
- time_t modifitime,
- int datalength,
- char* mimetype,
- char* encoding,
- int nocache)
-{
- if(status){
- k_hashtable_put_dup(ent_head, "Status:", status);
- k_hashtable_put_dup(ent_head, "Status-Text:", statustext);
- }
- if(uri){
- k_hashtable_put_dup(ent_head, "URI:", uri);
- }
- if(modifitime>=0){
- snprintf(tmpbuf, TMPBUFSIZE, "%s", k_time_to_rfc(modifitime));
- k_hashtable_put_dup(ent_head, "Last-Modified:", tmpbuf);
- }
- if(datalength>=0){
- snprintf(tmpbuf, TMPBUFSIZE, "%d", datalength);
- k_hashtable_put_dup(ent_head, "Content-Length:", tmpbuf);
- }
- if(mimetype){
- k_hashtable_put_dup(ent_head, "Content-Type:", mimetype);
- }
- if(encoding){
- k_hashtable_put_dup(ent_head, "Content-Encoding:", encoding);
- }
- if(nocache==1){
- k_hashtable_put_dup(ent_head, "Cache-Control:",
- "no-cache,no-store");
- }
- else
- if(nocache==0){
- long maxage=31449600;
- snprintf(tmpbuf, TMPBUFSIZE, "max-age=%ld", maxage);
- char* maxages=k_time_to_rfc_relative(maxage);
- k_hashtable_put_dup(ent_head, "Cache-Control:", tmpbuf);
- k_hashtable_put_dup(ent_head, "Expires:", maxages);
- }
- else
- if(nocache== -1){
- k_hashtable_remove(ent_head, "Cache-Control:");
- k_hashtable_remove(ent_head, "Expires:");
- }
-}
-
-/* -}{---- ------------------------------------------------------------------ */
-