/* unblock SIGCHLD */
sigemptyset(&ssn);
sigaddset(&ssn, SIGCHLD);
+ sigaddset(&ssn, SIGPIPE);
sigprocmask(SIG_UNBLOCK, &ssn, &sso);
rv = select(n, r, w, e, t);
int sz = 0;
int rsz = 0;
+ fd_set reader;
+ struct timeval timeout;
+
/* first serve data from peek buffer */
if( cl->peeklen > 0 )
{
/* caller wants more */
if( len > 0 )
{
+ 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 )
+ {
#ifdef HAVE_TLS
- if( cl->tls )
- rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
- else
+ 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 = recv(cl->socket, (void *)&buf[sz], len, 0);
- if( (sz == 0) || (rsz > 0) )
- sz += rsz;
+ if( (sz == 0) || (rsz > 0) )
+ sz += rsz;
+ }
+ else if( sz == 0 )
+ {
+ sz = -1;
+ }
}
return sz;
}
-#define ensure(x) \
- do { if( x < 0 ) return -1; } while(0)
int uh_http_sendhf(struct client *cl, int code, const char *summary, const char *fmt, ...)
{
code, summary
);
- ensure(uh_tcp_send(cl, buffer, len));
+ ensure_ret(uh_tcp_send(cl, buffer, len));
va_start(ap, fmt);
len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
- ensure(uh_http_sendc(cl, buffer, len));
- ensure(uh_http_sendc(cl, NULL, 0));
+ ensure_ret(uh_http_sendc(cl, buffer, len));
+ ensure_ret(uh_http_sendc(cl, NULL, 0));
return 0;
}
if( len > 0 )
{
- clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
- ensure(uh_tcp_send(cl, chunk, clen));
- ensure(uh_tcp_send(cl, data, len));
- ensure(uh_tcp_send(cl, "\r\n", 2));
+ 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));
}
else
{
- ensure(uh_tcp_send(cl, "0\r\n\r\n", 5));
+ ensure_ret(uh_tcp_send(cl, "0\r\n\r\n", 5));
}
return 0;
va_end(ap);
if( (req != NULL) && (req->version > 1.0) )
- ensure(uh_http_sendc(cl, buffer, len));
+ ensure_ret(uh_http_sendc(cl, buffer, len));
else if( len > 0 )
- ensure(uh_tcp_send(cl, buffer, len));
+ ensure_ret(uh_tcp_send(cl, buffer, len));
return 0;
}
len = strlen(buf);
if( (req != NULL) && (req->version > 1.0) )
- ensure(uh_http_sendc(cl, buf, len));
+ ensure_ret(uh_http_sendc(cl, buf, len));
else if( len > 0 )
- ensure(uh_tcp_send(cl, buf, len));
+ ensure_ret(uh_tcp_send(cl, buf, len));
return 0;
}
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));
{
struct auth_realm *new = NULL;
struct passwd *pwd;
+
+#ifdef HAVE_SHADOW
struct spwd *spwd;
+#endif
if((new = (struct auth_realm *)malloc(sizeof(struct auth_realm))) != NULL)
{
/* given password refers to a passwd entry */
if( (strlen(pass) > 3) && !strncmp(pass, "$p$", 3) )
{
+#ifdef HAVE_SHADOW
/* try to resolve shadow entry */
if( ((spwd = getspnam(&pass[3])) != NULL) && spwd->sp_pwdp )
{
min(strlen(spwd->sp_pwdp), sizeof(new->pass) - 1));
}
+ else
+#endif
+
/* try to resolve passwd entry */
- else if( ((pwd = getpwnam(&pass[3])) != NULL) && pwd->pw_passwd &&
+ if( ((pwd = getpwnam(&pass[3])) != NULL) && pwd->pw_passwd &&
(pwd->pw_passwd[0] != '!') && (pwd->pw_passwd[0] != 0)
) {
memcpy(new->pass, pwd->pw_passwd,
min(strlen(pwd->pw_passwd), sizeof(new->pass) - 1));
- }
+ }
}
/* ordinary pwd */
req->realm = realm;
break;
}
-
- realm = NULL;
}
/* found a realm matching the username */