This commit is contained in:
hyung-hwan 2008-02-03 05:27:18 +00:00
parent da81db7a34
commit 70fcb6a8c6
6 changed files with 263 additions and 4 deletions

190
ase/utl/http.c Normal file
View 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
View 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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)