This commit is contained in:
parent
da81db7a34
commit
70fcb6a8c6
190
ase/utl/http.c
Normal file
190
ase/utl/http.c
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ase/utl/http.h>
|
||||||
|
#include <ase/utl/ctype.h>
|
||||||
|
|
||||||
|
static int is_http_space (ase_char_t c)
|
||||||
|
{
|
||||||
|
return ase_isspace(c) && c != ASE_T('\r') && c != ASE_T('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
#define is_http_ctl(c) ase_iscntrl(c)
|
||||||
|
|
||||||
|
static int is_http_separator (ase_char_t c)
|
||||||
|
{
|
||||||
|
return c == ASE_T('(') ||
|
||||||
|
c == ASE_T(')') ||
|
||||||
|
c == ASE_T('<') ||
|
||||||
|
c == ASE_T('>') ||
|
||||||
|
c == ASE_T('@') ||
|
||||||
|
c == ASE_T(',') ||
|
||||||
|
c == ASE_T(';') ||
|
||||||
|
c == ASE_T(':') ||
|
||||||
|
c == ASE_T('\\') ||
|
||||||
|
c == ASE_T('\"') ||
|
||||||
|
c == ASE_T('/') ||
|
||||||
|
c == ASE_T('[') ||
|
||||||
|
c == ASE_T(']') ||
|
||||||
|
c == ASE_T('?') ||
|
||||||
|
c == ASE_T('=') ||
|
||||||
|
c == ASE_T('{') ||
|
||||||
|
c == ASE_T('}') ||
|
||||||
|
c == ASE_T('\t') ||
|
||||||
|
c == ASE_T(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_http_token (ase_char_t c)
|
||||||
|
{
|
||||||
|
return ase_isprint(c) && !is_http_ctl(c) && !is_http_separator(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int digit_to_num (ase_char_t c)
|
||||||
|
{
|
||||||
|
if (c >= ASE_T('0') && c <= ASE_T('9')) return c - ASE_T('0');
|
||||||
|
if (c >= ASE_T('A') && c <= ASE_T('Z')) return c - ASE_T('A') + 10;
|
||||||
|
if (c >= ASE_T('a') && c <= ASE_T('z')) return c - ASE_T('a') + 10;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ase_char_t* ase_parsehttpreq (ase_char_t* buf, ase_http_req_t* req)
|
||||||
|
{
|
||||||
|
ase_char_t* p = buf, * x;
|
||||||
|
|
||||||
|
/* ignore leading spaces */
|
||||||
|
while (is_http_space(*p)) p++;
|
||||||
|
|
||||||
|
/* the method should start with an alphabet */
|
||||||
|
if (!ase_isalpha(*p)) return ASE_NULL;
|
||||||
|
|
||||||
|
/* scan the method */
|
||||||
|
req->method = p; while (ase_isalpha(*p)) p++;
|
||||||
|
|
||||||
|
/* the method should be followed by a space */
|
||||||
|
if (!is_http_space(*p)) return ASE_NULL;
|
||||||
|
|
||||||
|
/* null-terminate the method */
|
||||||
|
*p++ = ASE_T('\0');
|
||||||
|
|
||||||
|
/* skip spaces */
|
||||||
|
while (is_http_space(*p)) p++;
|
||||||
|
|
||||||
|
/* scan the url */
|
||||||
|
req->path.ptr = p;
|
||||||
|
req->args.ptr = ASE_NULL;
|
||||||
|
|
||||||
|
x = p;
|
||||||
|
while (ase_isprint(*p) && !ase_isspace(*p))
|
||||||
|
{
|
||||||
|
if (*p == ASE_T('%') && ase_isxdigit(*(p+1)) && ase_isxdigit(*(p+2)))
|
||||||
|
{
|
||||||
|
*x++ = (digit_to_num(*(p+1)) << 4) + digit_to_num(*(p+2));
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
else if (*p == ASE_T('?') && req->args.ptr == ASE_NULL)
|
||||||
|
{
|
||||||
|
/* ? must be explicit to be a argument instroducer.
|
||||||
|
* %3f is just a literal. */
|
||||||
|
req->path.len = x - req->path.ptr;
|
||||||
|
*x++ = ASE_T('\0');
|
||||||
|
req->args.ptr = x;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else *x++ = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the url should be followed by a space */
|
||||||
|
if (!is_http_space(*p)) return ASE_NULL;
|
||||||
|
|
||||||
|
/* null-terminate the url and store the length */
|
||||||
|
if (req->args.ptr != ASE_NULL)
|
||||||
|
req->args.len = x - req->args.ptr;
|
||||||
|
else
|
||||||
|
req->path.len = x - req->path.ptr;
|
||||||
|
*x++ = ASE_T('\0');
|
||||||
|
|
||||||
|
/* path should start with a slash */
|
||||||
|
if (req->path.len <= 0 || req->path.ptr[0] != ASE_T('/')) return ASE_NULL;
|
||||||
|
|
||||||
|
/* skip spaces */
|
||||||
|
do { p++; } while (is_http_space(*p));
|
||||||
|
|
||||||
|
/* check http version */
|
||||||
|
if ((p[0] == ASE_T('H') || p[0] == ASE_T('h')) &&
|
||||||
|
(p[1] == ASE_T('T') || p[1] == ASE_T('t')) &&
|
||||||
|
(p[2] == ASE_T('T') || p[2] == ASE_T('t')) &&
|
||||||
|
(p[3] == ASE_T('P') || p[3] == ASE_T('p')) &&
|
||||||
|
p[4] == ASE_T('/') && p[6] == ASE_T('.'))
|
||||||
|
{
|
||||||
|
if (!ase_isdigit(p[5])) return ASE_NULL;
|
||||||
|
if (!ase_isdigit(p[7])) return ASE_NULL;
|
||||||
|
req->vers.major = p[5] - ASE_T('0');
|
||||||
|
req->vers.minor = p[7] - ASE_T('0');
|
||||||
|
p += 8;
|
||||||
|
}
|
||||||
|
else return ASE_NULL;
|
||||||
|
|
||||||
|
while (ase_isspace(*p))
|
||||||
|
{
|
||||||
|
if (*p++ == ASE_T('\n')) goto ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not terminating with a new line.
|
||||||
|
* maybe garbage after the request line */
|
||||||
|
if (*p != ASE_T('\0')) return ASE_NULL;
|
||||||
|
|
||||||
|
ok:
|
||||||
|
/* returns the next position */
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ase_char_t* ase_parsehttphdr (ase_char_t* buf, ase_http_hdr_t* hdr)
|
||||||
|
{
|
||||||
|
ase_char_t* p = buf, * last;
|
||||||
|
|
||||||
|
/* ignore leading spaces including CR and NL */
|
||||||
|
while (ase_isspace(*p)) p++;
|
||||||
|
|
||||||
|
if (*p == ASE_T('\0'))
|
||||||
|
{
|
||||||
|
/* no more header line */
|
||||||
|
ase_memset (hdr, 0, ASE_SIZEOF(*hdr));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_http_token(*p)) return ASE_NULL;
|
||||||
|
|
||||||
|
hdr->name.ptr = p;
|
||||||
|
do { p++; } while (is_http_token(*p));
|
||||||
|
|
||||||
|
last = p;
|
||||||
|
hdr->name.len = last - hdr->name.ptr;
|
||||||
|
|
||||||
|
while (is_http_space(*p)) p++;
|
||||||
|
if (*p != ASE_T(':')) return ASE_NULL;
|
||||||
|
|
||||||
|
*last = ASE_T('\0');
|
||||||
|
|
||||||
|
do { p++; } while (is_http_space(*p));
|
||||||
|
|
||||||
|
hdr->value.ptr = last = p;
|
||||||
|
while (ase_isprint(*p))
|
||||||
|
{
|
||||||
|
if (!ase_isspace(*p++)) last = p;
|
||||||
|
}
|
||||||
|
hdr->value.len = last - hdr->value.ptr;
|
||||||
|
|
||||||
|
while (ase_isspace(*p))
|
||||||
|
{
|
||||||
|
if (*p++ == ASE_T('\n')) goto ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not terminating with a new line.
|
||||||
|
* maybe garbage after the header line */
|
||||||
|
if (*p != ASE_T('\0')) return ASE_NULL;
|
||||||
|
|
||||||
|
ok:
|
||||||
|
*last = ASE_T('\0');
|
||||||
|
return p;
|
||||||
|
}
|
53
ase/utl/http.h
Normal file
53
ase/utl/http.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASE_UTL_HTTP_H_
|
||||||
|
#define _ASE_UTL_HTTP_H_
|
||||||
|
|
||||||
|
#include <ase/cmn/types.h>
|
||||||
|
#include <ase/cmn/macros.h>
|
||||||
|
|
||||||
|
/* returns the type of http method */
|
||||||
|
typedef struct ase_http_req_t ase_http_req_t;
|
||||||
|
typedef struct ase_http_hdr_t ase_http_hdr_t;
|
||||||
|
|
||||||
|
struct ase_http_req_t
|
||||||
|
{
|
||||||
|
ase_char_t* method;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ase_char_t* ptr;
|
||||||
|
ase_size_t len;
|
||||||
|
} path;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ase_char_t* ptr;
|
||||||
|
ase_size_t len;
|
||||||
|
} args;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char major;
|
||||||
|
char minor;
|
||||||
|
} vers;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ase_http_hdr_t
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ase_char_t* ptr;
|
||||||
|
ase_size_t len;
|
||||||
|
} name;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ase_char_t* ptr;
|
||||||
|
ase_size_t len;
|
||||||
|
} value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -21,7 +21,8 @@ TMP_DIR = $(MODE)
|
|||||||
OBJ_FILES = \
|
OBJ_FILES = \
|
||||||
$(TMP_DIR)/main.o \
|
$(TMP_DIR)/main.o \
|
||||||
$(TMP_DIR)/ctype.o \
|
$(TMP_DIR)/ctype.o \
|
||||||
$(TMP_DIR)/stdio.o
|
$(TMP_DIR)/stdio.o \
|
||||||
|
$(TMP_DIR)/http.o \
|
||||||
|
|
||||||
lib: $(OUT_FILE)
|
lib: $(OUT_FILE)
|
||||||
|
|
||||||
@ -38,6 +39,9 @@ $(TMP_DIR)/ctype.o: ctype.c
|
|||||||
$(TMP_DIR)/stdio.o: stdio.c
|
$(TMP_DIR)/stdio.o: stdio.c
|
||||||
$(CC) $(CFLAGS) -o $@ -c stdio.c
|
$(CC) $(CFLAGS) -o $@ -c stdio.c
|
||||||
|
|
||||||
|
$(TMP_DIR)/http.o: http.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c http.c
|
||||||
|
|
||||||
$(OUT_DIR):
|
$(OUT_DIR):
|
||||||
mkdir -p $(OUT_DIR)
|
mkdir -p $(OUT_DIR)
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@ TMP_DIR = $(MODE)
|
|||||||
OBJ_FILES_LIB = \
|
OBJ_FILES_LIB = \
|
||||||
$(TMP_DIR)\main.obj \
|
$(TMP_DIR)\main.obj \
|
||||||
$(TMP_DIR)\ctype.obj \
|
$(TMP_DIR)\ctype.obj \
|
||||||
$(TMP_DIR)\stdio.obj
|
$(TMP_DIR)\stdio.obj \
|
||||||
|
$(TMP_DIR)\http.obj
|
||||||
|
|
||||||
all: lib
|
all: lib
|
||||||
|
|
||||||
@ -39,6 +40,9 @@ $(TMP_DIR)\ctype.obj: ctype.c
|
|||||||
$(TMP_DIR)\stdio.obj: stdio.c
|
$(TMP_DIR)\stdio.obj: stdio.c
|
||||||
$(CC) $(CFLAGS) -o$@ -c stdio.c
|
$(CC) $(CFLAGS) -o$@ -c stdio.c
|
||||||
|
|
||||||
|
$(TMP_DIR)\http.obj: http.c
|
||||||
|
$(CC) $(CFLAGS) -o$@ -c http.c
|
||||||
|
|
||||||
$(OUT_DIR):
|
$(OUT_DIR):
|
||||||
-md $(OUT_DIR)
|
-md $(OUT_DIR)
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ TMP_DIR = $(MODE)
|
|||||||
OBJ_FILES_LIB = \
|
OBJ_FILES_LIB = \
|
||||||
$(TMP_DIR)\main.obj \
|
$(TMP_DIR)\main.obj \
|
||||||
$(TMP_DIR)\ctype.obj \
|
$(TMP_DIR)\ctype.obj \
|
||||||
$(TMP_DIR)\stdio.obj
|
$(TMP_DIR)\stdio.obj \
|
||||||
|
$(TMP_DIR)\http.obj
|
||||||
|
|
||||||
all: lib
|
all: lib
|
||||||
|
|
||||||
@ -43,6 +44,9 @@ $(TMP_DIR)\ctype.obj: ctype.c
|
|||||||
$(TMP_DIR)\stdio.obj: stdio.c
|
$(TMP_DIR)\stdio.obj: stdio.c
|
||||||
$(CC) $(CFLAGS) /Fo$@ /c stdio.c
|
$(CC) $(CFLAGS) /Fo$@ /c stdio.c
|
||||||
|
|
||||||
|
$(TMP_DIR)\http.obj: http.c
|
||||||
|
$(CC) $(CFLAGS) /Fo$@ /c http.c
|
||||||
|
|
||||||
$(OUT_DIR):
|
$(OUT_DIR):
|
||||||
-md $(OUT_DIR)
|
-md $(OUT_DIR)
|
||||||
|
|
||||||
|
@ -19,7 +19,8 @@ TMP_DIR = $(MODE)
|
|||||||
OBJ_FILES_LIB = \
|
OBJ_FILES_LIB = \
|
||||||
$(TMP_DIR)\main.obj \
|
$(TMP_DIR)\main.obj \
|
||||||
$(TMP_DIR)\ctype.obj \
|
$(TMP_DIR)\ctype.obj \
|
||||||
$(TMP_DIR)\stdio.obj
|
$(TMP_DIR)\stdio.obj \
|
||||||
|
$(TMP_DIR)\http.obj
|
||||||
|
|
||||||
all: $(OUT_FILE_LIB)
|
all: $(OUT_FILE_LIB)
|
||||||
|
|
||||||
@ -35,6 +36,9 @@ $(TMP_DIR)\ctype.obj: ctype.c
|
|||||||
$(TMP_DIR)\stdio.obj: stdio.c
|
$(TMP_DIR)\stdio.obj: stdio.c
|
||||||
$(CC) $(CFLAGS) -o$@ -c stdio.c
|
$(CC) $(CFLAGS) -o$@ -c stdio.c
|
||||||
|
|
||||||
|
$(TMP_DIR)\http.obj: http.c
|
||||||
|
$(CC) $(CFLAGS) -o$@ -c http.c
|
||||||
|
|
||||||
$(OUT_DIR):
|
$(OUT_DIR):
|
||||||
md $(OUT_DIR)
|
md $(OUT_DIR)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user