}
-int uh_tcp_send(struct client *cl, const char *buf, int len)
+int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len)
{
fd_set writer;
struct timeval timeout;
timeout.tv_sec = cl->server->conf->network_timeout;
timeout.tv_usec = 0;
- if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 )
- {
-#ifdef HAVE_TLS
- if( cl->tls )
- return cl->server->conf->tls_send(cl, (void *)buf, len);
- else
-#endif
- return send(cl->socket, buf, len, 0);
- }
+ if (select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0)
+ return send(cl->socket, buf, len, 0);
return -1;
}
+int uh_tcp_send(struct client *cl, const char *buf, int len)
+{
+#ifdef HAVE_TLS
+ if (cl->tls)
+ return cl->server->conf->tls_send(cl, (void *)buf, len);
+ else
+#endif
+ return uh_tcp_send_lowlevel(cl, buf, len);
+}
+
int uh_tcp_peek(struct client *cl, char *buf, int len)
{
+ /* sanity check, prevent overflowing peek buffer */
+ if (len > sizeof(cl->peekbuf))
+ return -1;
+
int sz = uh_tcp_recv(cl, buf, len);
/* store received data in peek buffer */
return sz;
}
+int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len)
+{
+ fd_set reader;
+ struct timeval timeout;
+
+ FD_ZERO(&reader);
+ FD_SET(cl->socket, &reader);
+
+ timeout.tv_sec = cl->server->conf->network_timeout;
+ timeout.tv_usec = 0;
+
+ if (select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0)
+ return recv(cl->socket, buf, len, 0);
+
+ return -1;
+}
+
int uh_tcp_recv(struct client *cl, char *buf, int len)
{
int sz = 0;
int rsz = 0;
/* first serve data from peek buffer */
- if( cl->peeklen > 0 )
+ if (cl->peeklen > 0)
{
sz = min(cl->peeklen, len);
len -= sz; cl->peeklen -= sz;
-
memcpy(buf, cl->peekbuf, sz);
memmove(cl->peekbuf, &cl->peekbuf[sz], cl->peeklen);
}
/* caller wants more */
- if( len > 0 )
+ if (len > 0)
{
#ifdef HAVE_TLS
- if( cl->tls )
+ if (cl->tls)
rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
else
#endif
- rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
+ rsz = uh_tcp_recv_lowlevel(cl, (void *)&buf[sz], len);
+
+ if (rsz < 0)
+ return rsz;
- if( (sz == 0) || (rsz > 0) )
- sz += rsz;
+ sz += rsz;
}
return sz;
if( len > 0 )
{
- clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
+ clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
ensure_ret(uh_tcp_send(cl, chunk, clen));
ensure_ret(uh_tcp_send(cl, data, len));
ensure_ret(uh_tcp_send(cl, "\r\n", 2));
char *docroot = cl->server->conf->docroot;
char *pathptr = NULL;
+ int slash = 0;
int no_sym = cl->server->conf->no_symlinks;
int i = 0;
struct stat s;
}
/* create canon path */
- for( i = strlen(buffer); i >= 0; i-- )
+ for( i = strlen(buffer), slash = (buffer[max(0, i-1)] == '/'); i >= 0; i-- )
{
if( (buffer[i] == 0) || (buffer[i] == '/') )
{
memcpy(buffer, path_phys, sizeof(buffer));
pathptr = &buffer[strlen(buffer)];
- if( cl->server->conf->index_file )
+ /* if requested url resolves to a directory and a trailing slash
+ is missing in the request url, redirect the client to the same
+ url with trailing slash appended */
+ if( !slash )
+ {
+ uh_http_sendf(cl, NULL,
+ "HTTP/1.1 302 Found\r\n"
+ "Location: %s%s%s\r\n"
+ "Connection: close\r\n\r\n",
+ &path_phys[strlen(docroot)],
+ p.query ? "?" : "",
+ p.query ? p.query : ""
+ );
+
+ p.redirected = 1;
+ }
+ else if( cl->server->conf->index_file )
{
strncat(buffer, cl->server->conf->index_file, sizeof(buffer));
/* found a realm matching the username */
if( realm )
{
- /* is a crypt passwd */
- if( realm->pass[0] == '$' )
- pass = crypt(pass, realm->pass);
-
/* check user pass */
- if( !strcmp(pass, realm->pass) )
+ if (!strcmp(pass, realm->pass) ||
+ !strcmp(crypt(pass, realm->pass), realm->pass))
return 1;
}
}