various code simplifications to reduce nesting depth,

minor optimizations to avoid extra calls of strlen(),
and some variable localization.

One feature worth backporting is the move of ast_variables_destroy()
to a different place in handle_uri() to avoid leaking memory
in case a uri is not found.



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@45463 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Luigi Rizzo
2006-10-18 04:05:56 +00:00
parent bb8926d50c
commit d1058df18f

View File

@@ -285,23 +285,21 @@ void ast_http_uri_unlink(struct ast_http_uri *urih)
static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies)
{
char *c;
char *params;
char *params = uri;
struct ast_http_uri *urih=NULL;
int prefix_len;
int l;
struct ast_variable *vars=NULL, *v, *prev = NULL;
strsep(&params, "?");
/* Extract arguments from the request and store them in variables. */
params = strchr(uri, '?');
if (params) {
char *var, *val;
*params++ = '\0';
while ((var = strsep(&params, "&"))) {
val = strchr(var, '=');
if (val) {
*val++ = '\0';
while ((val = strsep(&params, "&"))) {
var = strsep(&val, "=");
if (val)
ast_uri_decode(val);
} else
else
val = "";
ast_uri_decode(var);
if ((v = ast_variable_new(var, val))) {
@@ -316,7 +314,7 @@ static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **
/*
* Append the cookies to the variables (the only reason to have them
* at the end is to avoid another pass of the cookies list to find
* the tail.
* the tail).
*/
if (prev)
prev->next = *cookies;
@@ -326,38 +324,40 @@ static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **
ast_uri_decode(uri);
/* We want requests to start with the prefix and '/' */
prefix_len = strlen(prefix);
if (prefix_len && !strncasecmp(uri, prefix, prefix_len) && uri[prefix_len] == '/') {
uri += prefix_len + 1;
l = strlen(prefix);
if (l && !strncasecmp(uri, prefix, l) && uri[l] == '/') {
uri += l + 1;
/* scan registered uris to see if we match one. */
for (urih = uris; urih; urih = urih->next) {
int len = strlen(urih->uri);
if (!strncasecmp(urih->uri, uri, len)) {
if (!uri[len] || uri[len] == '/') {
char *turi = uri + len; /* possible candidate */
if (*turi == '/')
turi++;
if (!*turi || urih->has_subtree) {
uri = turi;
l = strlen(urih->uri);
c = uri + l; /* candidate */
if (strncasecmp(urih->uri, uri, l) /* no match */
|| (*c && *c != '/')) /* substring */
continue;
if (*c == '/')
c++;
if (!*c || urih->has_subtree) {
uri = c;
break;
}
}
}
}
}
if (urih) {
c = urih->callback(sin, uri, vars, status, title, contentlength);
ast_variables_destroy(vars);
} else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
/* Special case: If no prefix, and no URI, send to /static/index.html */
c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "This is not the page you are looking for...");
/* Special case: no prefix, no URI, send to /static/index.html */
c = ast_http_error(302, "Moved Temporarily",
"Location: /static/index.html\r\n",
"This is not the page you are looking for...");
*status = 302;
*title = strdup("Moved Temporarily");
} else {
c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
c = ast_http_error(404, "Not Found", NULL,
"The requested URL was not found on this server.");
*status = 404;
*title = strdup("Not Found");
}
ast_variables_destroy(vars);
return c;
}
@@ -365,15 +365,14 @@ static void *ast_httpd_helper_thread(void *data)
{
char buf[4096];
char cookie[4096];
char timebuf[256];
struct ast_http_server_instance *ser = data;
struct ast_variable *var, *prev=NULL, *vars=NULL;
char *uri, *c, *title=NULL;
char *vname, *vval;
int status = 200, contentlength = 0;
time_t t;
if (fgets(buf, sizeof(buf), ser->f)) {
if (!fgets(buf, sizeof(buf), ser->f))
goto done;
uri = ast_skip_nonblanks(buf); /* Skip method */
if (*uri)
*uri++ = '\0';
@@ -388,6 +387,9 @@ static void *ast_httpd_helper_thread(void *data)
/* process "Cookie: " lines */
while (fgets(cookie, sizeof(cookie), ser->f)) {
char *vname, *vval;
int l;
/* Trim trailing characters */
ast_trim_blanks(cookie);
if (ast_strlen_zero(cookie))
@@ -395,8 +397,6 @@ static void *ast_httpd_helper_thread(void *data)
if (strncasecmp(cookie, "Cookie: ", 8))
continue;
/* XXX fix indentation */
/* TODO - The cookie parsing code below seems to work
in IE6 and FireFox 1.5. However, it is not entirely
correct, and therefore may not work in all
@@ -410,28 +410,25 @@ static void *ast_httpd_helper_thread(void *data)
/* If we got a FireFox cookie string, the name's right
after "Cookie: " */
vname = cookie + 8;
vname = ast_skip_blanks(cookie + 8);
/* If we got an IE cookie string, we need to skip to
past the version to get to the name */
if (*vname == '$') {
vname = strchr(vname, ';');
if (vname) {
vname++;
if (*vname == ' ')
vname++;
strsep(&vname, ";");
if (!vname) /* no name ? */
continue;
vname = ast_skip_blanks(vname);
}
}
if (vname) {
vval = strchr(vname, '=');
if (vval) {
if (!vval)
continue;
/* Ditch the = and the quotes */
*vval++ = '\0';
if (*vval)
vval++;
if (strlen(vval))
vval[strlen(vval) - 1] = '\0';
if ( (l = strlen(vval)) )
vval[l - 1] = '\0'; /* trim trailing quote */
var = ast_variable_new(vname, vval);
if (var) {
if (prev)
@@ -441,16 +438,14 @@ static void *ast_httpd_helper_thread(void *data)
prev = var;
}
}
}
}
if (*uri) {
if (!strcasecmp(buf, "get"))
c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
else
c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
} else
if (!*uri)
c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
else if (strcasecmp(buf, "get"))
c = ast_http_error(501, "Not Implemented", NULL,
"Attempt to use unimplemented / unsupported method");
else /* try to serve it */
c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
/* If they aren't mopped up already, clean up the cookies */
if (vars)
@@ -459,17 +454,20 @@ static void *ast_httpd_helper_thread(void *data)
if (!c)
c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
if (c) {
time(&t);
time_t t = time(NULL);
char timebuf[256];
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
ast_cli(ser->fd, "Server: Asterisk\r\n");
ast_cli(ser->fd, "Date: %s\r\n", timebuf);
ast_cli(ser->fd, "Connection: close\r\n");
if (contentlength) {
char *tmp;
tmp = strstr(c, "\r\n\r\n");
char *tmp = strstr(c, "\r\n\r\n");
if (tmp) {
ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
/* first write the header, then the body */
write(ser->fd, c, (tmp + 4 - c));
write(ser->fd, tmp + 4, contentlength);
}
@@ -479,7 +477,8 @@ static void *ast_httpd_helper_thread(void *data)
}
if (title)
free(title);
}
done:
fclose(ser->f);
free(ser);
return NULL;