Newer
Older
if(session->req.ld!=NULL) {
FREE_AND_NULL(session->req.ld->user);
/* FREE()d in http_logging_thread */
session->req.ld->user=strdup(session->req.auth.username);
if(session->parsed_vpath == PARSED_VPATH_FULL) {
if(is_download_free(&scfg, session->file.dir, &session->user, &session->client)
|| session->user.cdt >= session->file.cost)
authorized = can_user_download(&scfg, session->file.dir, &session->user, &session->client, NULL);
else
authorized = FALSE;
} else {
ar = arstr(NULL,session->req.ars,&scfg,NULL);
authorized=chk_ar(&scfg,ar,&session->user,&session->client);
if(ar!=NULL)
FREE_AND_NULL(ar);
}
case AUTHENTICATION_TLS_PSK:
add_env(session,"AUTH_TYPE","TLS-PSK");
break;
case AUTHENTICATION_BASIC:
add_env(session,"AUTH_TYPE","Basic");
break;
case AUTHENTICATION_DIGEST:
add_env(session,"AUTH_TYPE","Digest");
break;
/* Should use real name if set to do so somewhere ToDo */
add_env(session,"REMOTE_USER",session->user.alias);
if(thisuser.pass[0])
loginSuccess(startup->login_attempt_list, &session->addr);
return(TRUE);
/* Should go to the hack log? */
lprintf(LOG_WARNING,"%04d !AUTHORIZATION FAILURE for user %s, ARS: %s"
,session->socket,session->req.auth.username,session->req.ars);
if(startup->sound.hack[0] && !sound_muted(&scfg))
PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
return(FALSE);
}
static named_string_t** read_ini_list(char* path, char* section, char* desc
,named_string_t** list, bool warn)
size_t i;
list=iniFreeNamedStringList(list);
if((fp=iniOpenFile(path, /* create? */FALSE))!=NULL) {
list=iniReadNamedStringList(fp,section);
iniCloseFile(fp);
COUNT_LIST_ITEMS(list,i);
if(i)
lprintf(LOG_DEBUG,"Read %lu %s from %s section of %s"
,(ulong)i,desc,section==NULL ? "root":section,path);
lprintf(warn ? LOG_WARNING : LOG_DEBUG, "Error %d opening %s", errno, path);
return(list);
static int sess_recv(http_session_t *session, char *buf, size_t length, int flags)
{
int len=0;
if (session->is_tls) {
if (flags == MSG_PEEK) {
if (session->peeked_valid) {
buf[0] = session->peeked;
return 1;
}
if (HANDLE_CRYPT_CALL_EXCEPT2(cryptPopData(session->tls_sess, &session->peeked, 1, &len), session, "popping data", CRYPT_ERROR_TIMEOUT, CRYPT_ERROR_COMPLETE)) {
if (len == 1) {
session->peeked_valid = TRUE;
buf[0] = session->peeked;
return 1;
}
return 0;
}
return -1;
}
else {
if (session->peeked_valid) {
buf[0] = session->peeked;
session->peeked_valid = FALSE;
return 1;
}
if (HANDLE_CRYPT_CALL_EXCEPT2(cryptPopData(session->tls_sess, buf, length, &len), session, "popping data", CRYPT_ERROR_TIMEOUT, CRYPT_ERROR_COMPLETE)) {
len = -1;
}
return len;
}
return -1;
}
}
else {
return recv(session->socket, buf, length, flags);
}
}
static int sockreadline(http_session_t * session, char *buf, size_t length)
{
char ch;
DWORD i;
DWORD chucked=0;
if(session->socket==INVALID_SOCKET)
return(-1);
if (socket_readable(session->socket, startup->max_inactivity * 1000)) {
if (session->is_tls)
session->tls_pending=TRUE;
}
else {
/* Timeout */
lprintf(LOG_NOTICE,"%04d Session timeout due to inactivity (%d seconds)",session->socket,startup->max_inactivity);
return(-1);
case -1:
if(startup->options&WEB_OPT_DEBUG_RX)
lprintf(LOG_DEBUG,"%04d !ERROR %d receiving on socket",session->socket,ERROR_VALUE);
return(-1);
}
break;
case 0:
return(-1);
}
if(ch=='\n')
break;
if(i<length)
buf[i++]=ch;
else
chucked++;
/* Terminate at length if longer */
if(i>length)
i=length;
while(i>0 && buf[i-1]=='\r')
i--;
buf[i]=0;
if(startup->options&WEB_OPT_DEBUG_RX) {
lprintf(LOG_DEBUG,"%04d RX: %s",session->socket,buf);
lprintf(LOG_DEBUG,"%04d Long header, chucked %d bytes",session->socket,chucked);
}
#if defined(_WIN32)
static int pipereadline(HANDLE pipe, char *buf, size_t length, char *fullbuf, size_t fullbuf_len)
#else
static int pipereadline(int pipe, char *buf, size_t length, char *fullbuf, size_t fullbuf_len)
#endif
{
char ch;
DWORD i;
/* Terminate buffers */
if(buf != NULL)
buf[0]=0;
if(fullbuf != NULL)
fullbuf[0]=0;
for(i=0;TRUE;) {
#if defined(_WIN32)
ret=0;
ReadFile(pipe, &ch, 1, (DWORD*)&ret, NULL);
#else
if (!socket_readable(pipe, startup->max_cgi_inactivity * 1000))
#endif
if(fullbuf != NULL && i < (fullbuf_len-1)) {
fullbuf[i]=ch;
fullbuf[i+1]=0;
}
if(ch=='\n')
break;
}
}
/* Terminate at length if longer */
if(i>length)
i=length;
static int recvbufsocket(http_session_t *session, char *buf, long count)
{
int rd=0;
if(count<1) {
errno=ERANGE;
return(0);
}
while(rd<count && session_check(session,NULL,NULL,startup->max_inactivity*1000)) {
i=sess_recv(session,buf+rd,count-rd,0);
switch(i) {
case -1:
if (ERROR_VALUE == EAGAIN && !session->is_tls)
break;
// Fall-through...
case 0:
*buf=0;
return(0);
}
if(rd==count) {
return(rd);
}
*buf=0;
}
static void unescape(char *p)
{
char * dst;
char code[3];
dst=p;
for(;*p;p++) {
if(*p=='%' && IS_HEXDIGIT(*(p+1)) && IS_HEXDIGIT(*(p+2))) {
sprintf(code,"%.2s",p+1);
*(dst++)=(char)strtol(code,NULL,16);
p+=2;
}
else {
if(*p=='+') {
*(dst++)=' ';
}
else {
*(dst++)=*p;
}
}
}
*(dst)=0;
}
static void js_add_queryval(http_session_t * session, char *key, char *value)
JSObject* keyarray;
jsval val;
int alen;
/* Return existing object if it's already been created */
if(JS_GetProperty(session->js_cx,session->js_query,key,&val) && val!=JSVAL_VOID) {
keyarray = JSVAL_TO_OBJECT(val);
alen=-1;
}
else {
keyarray = JS_NewArrayObject(session->js_cx, 0, NULL);
if(!JS_DefineProperty(session->js_cx, session->js_query, key, OBJECT_TO_JSVAL(keyarray)
, NULL, NULL, JSPROP_ENUMERATE))
return;
alen=0;
}
if(alen==-1) {
if(JS_GetArrayLength(session->js_cx, keyarray, &len)==JS_FALSE)
return;
}
lprintf(LOG_DEBUG,"%04d Adding query value %s=%s at pos %d",session->socket,key,value,alen);
val=STRING_TO_JSVAL(JS_NewStringCopyZ(session->js_cx,value));
JS_SetElement(session->js_cx, keyarray, alen, &val);
}
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
static void js_add_cookieval(http_session_t * session, char *key, char *value)
{
JSObject* keyarray;
jsval val;
jsuint len;
int alen;
/* Return existing object if it's already been created */
if(JS_GetProperty(session->js_cx,session->js_cookie,key,&val) && val!=JSVAL_VOID) {
keyarray = JSVAL_TO_OBJECT(val);
alen=-1;
}
else {
keyarray = JS_NewArrayObject(session->js_cx, 0, NULL);
if(!JS_DefineProperty(session->js_cx, session->js_cookie, key, OBJECT_TO_JSVAL(keyarray)
, NULL, NULL, JSPROP_ENUMERATE))
return;
alen=0;
}
if(alen==-1) {
if(JS_GetArrayLength(session->js_cx, keyarray, &len)==JS_FALSE)
return;
alen=len;
}
lprintf(LOG_DEBUG,"%04d Adding cookie value %s=%s at pos %d",session->socket,key,value,alen);
val=STRING_TO_JSVAL(JS_NewStringCopyZ(session->js_cx,value));
JS_SetElement(session->js_cx, keyarray, alen, &val);
}
static void js_add_request_property(http_session_t * session, char *key, char *value, size_t len, bool writeable)
{
JSString* js_str;
if(session->js_cx==NULL || session->js_request==NULL)
return;
if(value == NULL) {
// Remove property
JS_DeleteProperty(session->js_cx, session->js_request, key);
} else {
if(len)
js_str=JS_NewStringCopyN(session->js_cx, value, len);
else
js_str=JS_NewStringCopyZ(session->js_cx, value);
if(js_str == NULL)
return;
uintN attrs = JSPROP_ENUMERATE;
if(!writeable)
attrs |= JSPROP_READONLY;
JS_DefineProperty(session->js_cx, session->js_request, key, STRING_TO_JSVAL(js_str)
,NULL,NULL,attrs);
}
static void js_add_request_prop_writeable(http_session_t * session, char *key, char *value)
js_add_request_property(session, key, value, 0, /* writeable: */true);
}
static void js_add_request_prop(http_session_t * session, char *key, char *value)
{
js_add_request_property(session, key, value, 0, /* writeable: */false);
static void js_add_header(http_session_t * session, char *key, char *value)
{
JSString* js_str;
char *lckey;
return;
strlwr(lckey);
if((js_str=JS_NewStringCopyZ(session->js_cx, value))==NULL) {
return;
}
JS_DefineProperty(session->js_cx, session->js_header, lckey, STRING_TO_JSVAL(js_str)
,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
}
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
#if 0
static void js_parse_multipart(http_session_t * session, char *p) {
size_t key_len;
size_t value_len;
char *lp;
char *key;
char *value;
if(p == NULL)
return;
lp=p;
while((key_len=strcspn(lp,"="))!=0) {
key=lp;
lp+=key_len;
if(*lp) {
*lp=0;
lp++;
}
value_len=strcspn(lp,"&");
value=lp;
lp+=value_len;
if(*lp) {
*lp=0;
lp++;
}
unescape(value);
unescape(key);
js_add_queryval(session, key, value);
}
}
#endif
static void js_parse_query(http_session_t * session, char *p) {
size_t key_len;
size_t value_len;
char *lp;
char *key;
char *value;
if(p == NULL)
return;
lp=p;
key=lp;
lp+=key_len;
value_len=strcspn(lp,"&");
value=lp;
unescape(value);
unescape(key);
js_add_queryval(session, key, value);
}
}
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
static char *get_token_value(char **p)
{
char *pos=*p;
char *start;
char *out;
BOOL escaped=FALSE;
start=pos;
out=start;
if(*pos=='"') {
for(pos++; *pos; pos++) {
if(escaped && *pos)
*(out++)=*pos;
else if(*pos=='"') {
pos++;
break;
}
else if(*pos=='\\')
escaped=TRUE;
else
*(out++)=*pos;
}
}
else {
for(; *pos; pos++) {
if(iscntrl(*pos))
break;
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
switch(*pos) {
case 0:
case '(':
case ')':
case '<':
case '>':
case '@':
case ',':
case ';':
case ':':
case '\\':
case '"':
case '/':
case '[':
case ']':
case '?':
case '=':
case '{':
case '}':
case ' ':
case '\t':
goto end_of_text;
}
*(out++)=*pos;
}
}
end_of_text:
while(*pos==',' || IS_WHITESPACE(*pos))
pos++;
*out=0;
*p=pos;
return(start);
}
static int hexval(unsigned char ch)
{
ch-='0';
if(ch<10)
return(ch);
ch-=7;
if(ch<16 && ch>9)
return(ch);
if(ch>41) {
ch-=32;
if(ch<16 && ch>9)
return(ch);
}
return(0);
}
static BOOL parse_headers(http_session_t * session)
{
char *p;
int i;
size_t idx;
size_t content_len=0;
for(idx=0;session->req.headers[idx]!=NULL;idx++) {
/* TODO: strdup() is possibly too slow here... */
head_line=strdup(session->req.headers[idx]);
if((strtok_r(head_line,":",&last))!=NULL && (value=strtok_r(NULL,"",&last))!=NULL) {
i=get_header_type(head_line);
while(*value && *value<=' ') value++;
switch(i) {
case HEAD_AUTH:
/* If you're authenticated via TLS-PSK, you can't use basic or digest */
if (session->req.auth.type != AUTHENTICATION_TLS_PSK) {
if((p=strtok_r(value," ",&last))!=NULL) {
if(stricmp(p, "Basic")==0) {
p=strtok_r(NULL," ",&last);
if(p==NULL)
while(*p && *p<' ') p++;
b64_decode(p,strlen(p),p,strlen(p));
p=strtok_r(p,":",&last);
SAFECOPY(session->req.auth.username, p);
p=strtok_r(NULL,":",&last);
if(p) {
if(strlen(p) >= sizeof(session->req.auth.password))
break;
SAFECOPY(session->req.auth.password, p);
session->req.auth.type=AUTHENTICATION_BASIC;
}
else if(stricmp(p, "Digest")==0) {
p=strtok_r(NULL, "", &last);
/* Defaults */
session->req.auth.algorithm=ALGORITHM_MD5;
session->req.auth.type=AUTHENTICATION_DIGEST;
/* Parse out values one at a time and store */
while(p != NULL && *p) {
while(IS_WHITESPACE(*p))
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
p++;
if(strnicmp(p,"username=",9)==0) {
p+=9;
tvalue=get_token_value(&p);
if(strlen(tvalue) >= sizeof(session->req.auth.username))
break;
SAFECOPY(session->req.auth.username, tvalue);
}
else if(strnicmp(p,"realm=",6)==0) {
p+=6;
session->req.auth.realm=strdup(get_token_value(&p));
}
else if(strnicmp(p,"nonce=",6)==0) {
p+=6;
session->req.auth.nonce=strdup(get_token_value(&p));
}
else if(strnicmp(p,"uri=",4)==0) {
p+=4;
session->req.auth.digest_uri=strdup(get_token_value(&p));
}
else if(strnicmp(p,"response=",9)==0) {
p+=9;
tvalue=get_token_value(&p);
if(strlen(tvalue)==32) {
for(i=0; i<16; i++) {
session->req.auth.digest[i]=hexval(tvalue[i*2])<<4 | hexval(tvalue[i*2+1]);
}
else if(strnicmp(p,"algorithm=",10)==0) {
p+=10;
tvalue=get_token_value(&p);
if(stricmp(tvalue,"MD5")==0) {
session->req.auth.algorithm=ALGORITHM_MD5;
}
else {
session->req.auth.algorithm=ALGORITHM_UNKNOWN;
}
else if(strnicmp(p,"cnonce=",7)==0) {
p+=7;
session->req.auth.cnonce=strdup(get_token_value(&p));
else if(strnicmp(p,"qop=",4)==0) {
p+=4;
tvalue=get_token_value(&p);
if(stricmp(tvalue,"auth")==0) {
session->req.auth.qop_value=QOP_AUTH;
}
else if (stricmp(tvalue,"auth-int")==0) {
session->req.auth.qop_value=QOP_AUTH_INT;
}
else {
session->req.auth.qop_value=QOP_UNKNOWN;
}
else if(strnicmp(p,"nc=",3)==0) {
p+=3;
session->req.auth.nonce_count=strdup(get_token_value(&p));
while(*p && *p != '=')
p++;
if(*p == '=')
get_token_value(&p);
if(session->req.auth.digest_uri==NULL)
session->req.auth.digest_uri=strdup(session->req.request_line);
/* Validate that we have the required values... */
switch(session->req.auth.qop_value) {
case QOP_NONE:
if(session->req.auth.realm==NULL
|| session->req.auth.nonce==NULL
|| session->req.auth.digest_uri==NULL)
send_error(session,__LINE__,"400 Bad Request");
break;
case QOP_AUTH:
case QOP_AUTH_INT:
if(session->req.auth.realm==NULL
|| session->req.auth.nonce==NULL
|| session->req.auth.nonce_count==NULL
|| session->req.auth.cnonce==NULL
|| session->req.auth.digest_uri==NULL)
send_error(session,__LINE__,"400 Bad Request");
send_error(session,__LINE__,"400 Bad Request");
break;
case HEAD_LENGTH:
add_env(session,"CONTENT_LENGTH",value);
break;
case HEAD_IFMODIFIED:
session->req.if_modified_since=decode_date(value);
break;
case HEAD_CONNECTION:
if(!stricmp(value,"Keep-Alive")) {
session->req.keep_alive=TRUE;
}
if(!stricmp(value,"Close")) {
session->req.keep_alive=FALSE;
}
case HEAD_REFERER:
if(session->req.ld!=NULL) {
FREE_AND_NULL(session->req.ld->referrer);
/* FREE()d in http_logging_thread() */
session->req.ld->referrer=strdup(value);
break;
case HEAD_AGENT:
if(session->req.ld!=NULL) {
FREE_AND_NULL(session->req.ld->agent);
/* FREE()d in http_logging_thread() */
session->req.ld->agent=strdup(value);
break;
case HEAD_TRANSFER_ENCODING:
if(!stricmp(value,"chunked"))
session->req.read_chunked=TRUE;
else
send_error(session,__LINE__,"501 Not Implemented");
break;
if(!stricmp(value,"bytes=")) {
send_error(session,__LINE__,error_416);
break;
}
value+=6;
if(strchr(value,',')!=NULL) { /* We don't do multiple ranges yet - TODO */
send_error(session,__LINE__,error_416);
break;
}
/* Check for offset from end. */
if(*value=='-') {
session->req.range_start=strtol(value,NULL,10);
session->req.range_end=-1;
break;
}
if((p=strtok_r(value,"-",&last))!=NULL) {
session->req.range_start=strtol(p,NULL,10);
if((p=strtok_r(NULL,"-",&last))!=NULL)
session->req.range_end=strtol(p,NULL,10);
else
session->req.range_end=-1;
send_error(session,__LINE__,error_416);
break;
case HEAD_IFRANGE:
session->req.if_range=decode_date(value);
break;
case HEAD_TYPE:
add_env(session,"CONTENT_TYPE",value);
break;
case HEAD_UPGRADEINSECURE:
if (startup->options & WEB_OPT_HSTS_SAFE) {
if (strcmp(value, "1") == 0) {
if (!session->is_tls) {
portstr[0] = 0;
if (startup->tls_port != 443)
sprintf(portstr, ":%hu", startup->tls_port);
p = realloc(session->req.vary_list, (session->req.vary_list ? strlen(session->req.vary_list) + 2 : 0) + strlen(get_header(HEAD_UPGRADEINSECURE)) + 1);
if (p == NULL)
send_error(session, __LINE__, error_500);
else {
if (session->req.vary_list)
strcat(p, ", ");
else
*p = '\0';
strcat(p, get_header(HEAD_UPGRADEINSECURE));
session->req.vary_list = p;
session->req.send_location = MOVED_TEMPREDIR;
session->req.upgrading = TRUE;
session->req.keep_alive = FALSE;
FREE_AND_NULL(session->req.location_to_send);
if (asprintf(&session->req.location_to_send, "https://%s%s%s", session->req.vhost, portstr, session->req.virtual_path) < 0)
send_error(session, __LINE__, error_500);
}
}
}
}
break;
default:
break;
}
SAFEPRINTF(env_name,"HTTP_%s",head_line);
add_env(session,env_name,value);
}
free(head_line);
}
if(content_len)
session->req.post_len = content_len;
add_env(session,"SERVER_NAME",session->req.host[0] ? session->req.host : server_host_name() );
return TRUE;
}
static BOOL parse_js_headers(http_session_t * session)
{
char *head_line;
char *value;
char *last;
char *p;
int i;
size_t idx;
for(idx=0;session->req.headers[idx]!=NULL;idx++) {
head_line=session->req.headers[idx];
if((strtok_r(head_line,":",&last))!=NULL && (value=strtok_r(NULL,"",&last))!=NULL) {
i=get_header_type(head_line);
while(*value && *value<=' ') value++;
js_add_header(session,head_line,value);
switch(i) {
case HEAD_TYPE:
if(session->req.dynamic==IS_SSJS) {
/*
* We need to parse out the files based on RFC1867
*
* And example reponse looks like this:
* Content-type: multipart/form-data, boundary=AaB03x
* --AaB03x
* content-disposition: form-data; name="field1"
* Joe Blow
* --AaB03x
* content-disposition: form-data; name="pics"
* Content-type: multipart/mixed, boundary=BbC04y
* --BbC04y
* Content-disposition: attachment; filename="file1.txt"
* ... contents of file1.txt ...
* --BbC04y
* Content-disposition: attachment; filename="file2.gif"
* Content-type: image/gif
* Content-Transfer-Encoding: binary
* ...contents of file2.gif...
* --BbC04y--
* --AaB03x--
case HEAD_COOKIE:
if(session->req.dynamic==IS_SSJS) {
char *key;
char *val;
p=value;
while((key=strtok_r(p,"=",&last))!=NULL) {
while(IS_WHITESPACE(*key))
p=NULL;
if((val=strtok_r(p,";\t\n\v\f\r ",&last))!=NULL) { /* Whitespace */
js_add_cookieval(session,key,val);
}
}
}
break;
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
default:
break;
}
}
}
return TRUE;
}
static int get_version(char *p)
{
int i;
if(p==NULL)
return(0);
while(*p && *p<' ') p++;
if(*p==0)
return(0);
for(i=1;http_vers[i]!=NULL;i++) {
if(!stricmp(p,http_vers[i])) {
return(i);
}
}
return(i-1);
}
static int is_dynamic_req(http_session_t* session)
{
char drive[4];
char cgidrive[4];
char dir[MAX_PATH+1];
char cgidir[MAX_PATH+1];
char fname[MAX_PATH+1];
char ext[MAX_PATH+1];
if(session->parsed_vpath == PARSED_VPATH_FULL)
return IS_STATIC;
check_extra_path(session);
_splitpath(session->req.physical_path, drive, dir, fname, ext);
if(!(startup->options&WEB_OPT_NO_CGI)) {
if (session->req.fastcgi_socket) {
init_enviro(session);
return IS_FASTCGI;
}
}
if(stricmp(ext,startup->ssjs_ext)==0)
i=IS_SSJS;
else if(get_xjs_handler(ext,session))
i=IS_SSJS;
if(!(startup->options&BBS_OPT_NO_JAVASCRIPT) && i) {
lprintf(LOG_DEBUG,"%04d Setting up JavaScript support", session->socket);
if(!js_setup(session)) {
lprintf(LOG_ERR,"%04d !ERROR setting up JavaScript support", session->socket);
send_error(session,__LINE__,error_500);
return(IS_STATIC);
}
if(!(startup->options&WEB_OPT_NO_CGI)) {
for(i=0; startup->cgi_ext!=NULL && startup->cgi_ext[i]!=NULL; i++) {
if(stricmp(ext,startup->cgi_ext[i])==0) {
return(IS_CGI);
}
}
_splitpath(session->req.cgi_dir?session->req.cgi_dir:cgi_dir, cgidrive, cgidir, fname, ext);
if(stricmp(dir,cgidir)==0 && stricmp(drive,cgidrive)==0) {
}
}
return(IS_STATIC);
}
char *ret = NULL;
if (IS_DIGIT(*p)) {
/*
* If the first and last : are not the same, and it doesn't
* start with '[', there's no port part.
*/
if (host[0] != '[') {
if (strchr(host, ':') != strrchr(host, ':'))
return NULL;
}
for(; p >= host; p--) {
if (*p == ':') {
*p = 0;
ret = p+1;
break;
}
if (!IS_DIGIT(*p))
break;
// Now, remove []s...
if (host[0] == '[') {
memmove(host, host+1, strlen(host));
p=strchr(host, ']');
if (p)
*p = 0;
}
return ret;
}
static void remove_port_part(char *host)
{
split_port_part(host);
static char *get_request(http_session_t * session, char *req_line)
char* p;
char* retval;
const char* scheme = NULL;
size_t scheme_len;