Added url variables, removed exec pages

This commit is contained in:
Nate Choe
2022-02-20 21:43:19 -06:00
parent 458c0a545d
commit 4366c8ad65
13 changed files with 202 additions and 98 deletions

View File

@@ -38,10 +38,30 @@ typedef enum {
* */
} RequestType;
typedef struct {
char *data;
/* data is guarunteed to be NULL terminated, although not necessarily
* once. */
size_t len;
size_t allocatedLen;
/* The amount of bytes allocated, for internal use. */
} BinaryString;
typedef struct {
BinaryString var;
BinaryString value;
} PathField;
typedef struct {
BinaryString path;
long fieldCount;
PathField *fields;
} Path;
typedef struct {
long fieldCount;
Field *fields;
char *path;
Path path;
RequestType type;
} Request;
/*HTTP request, pretty self explanatory*/

View File

@@ -14,7 +14,6 @@ sitefiles also allow comments with #
* ```set [variable] [value]``` - sets some local variable for the following pages
* ```define [variable] [value]``` - sets some global variable
* ```read [http path] [file path]``` - if the requested path matches ```[http path]```, return the contents of ```[file path]```. If [file path] is a directory, then the http path is appended to [file path] and that is read instead.
* ```exec [http path] [file path]``` - if the requested path matches ```[http path]```, execute ```[file path]``` and send the the contents of stdout. ```argv[0]``` is the requested path, ```argv[1]``` is a header, ```argv[2]``` is the value for that header, ```argv[3]``` is the next header, and so on.
* ```linked``` - Run getResponse() from the library loaded from the library global variable
* ```throw [http path] [error code]``` - If the requested path matches ```[http path]```, send back the http error code ```[error code]```. For standardization purposes, these error codes are just the number.

View File

@@ -5,7 +5,10 @@
#include <swebs/swebs.h>
int getResponse(Request *request, Response *response) {
char *str = request->path;
printf("%d\n", request->path.fieldCount);
for (int i = 0; i < request->path.fieldCount; i++)
printf("%s: %s\n", request->path.fields[i].var.data, request->path.fields[i].value.data);
char *str = request->path.path.data;
response->type = BUFFER;
response->response.buffer.data = malloc(100);
strcpy(response->response.buffer.data, str);

View File

@@ -1,3 +0,0 @@
#!/bin/sh
echo "<p>By the way today's date is $(date)</p>"

View File

@@ -3,5 +3,4 @@
<h3>It's not very polished but it's certainly a website</h3>
<a href="blog/2022-1-25.html">2021-1-25</a>
<a href="blog/2022-1-31">2021-1-31</a>
<a href="blog/forbidden">The forbidden blog post</a>

View File

@@ -10,7 +10,6 @@ set host localhost:8000
read / site/index.html
read /hello site/hello.html
throw /blog/forbidden 403
exec /blog/2022-1-31 site/blog/blog/2022-1-31.sh
read /blog/.* site/blog/
#/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html
linked /library

View File

@@ -16,6 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -45,7 +46,15 @@ int newConnection(Stream *stream, Connection *ret) {
return 1;
}
ret->path = NULL;
ret->allocatedPathFields = 10;
ret->pathFields = malloc(ret->allocatedPathFields * sizeof(PathField));
if (ret->pathFields == NULL) {
free(ret->currLine);
free(ret->fields);
return 1;
}
ret->pathFieldCount = 0;
ret->body = NULL;
/*
* pointers to things that are allocated within functions should be
@@ -54,6 +63,8 @@ int newConnection(Stream *stream, Connection *ret) {
if (clock_gettime(CLOCK_MONOTONIC, &currentTime) < 0) {
free(ret->currLine);
free(ret->fields);
free(ret->pathFields);
return 1;
}
memcpy(&ret->lastdata, &currentTime, sizeof(struct timespec));
@@ -61,20 +72,146 @@ int newConnection(Stream *stream, Connection *ret) {
}
void resetConnection(Connection *conn) {
long i;
conn->progress = RECEIVE_REQUEST;
conn->fieldCount = 0;
free(conn->body);
free(conn->path);
conn->body = NULL;
conn->path = NULL;
conn->pathFieldCount = 0;
for (i = 0; i < conn->pathFieldCount; i++) {
free(conn->pathFields[i].var.data);
free(conn->pathFields[i].value.data);
}
}
void freeConnection(Connection *conn) {
long i;
freeStream(conn->stream);
free(conn->currLine);
free(conn->path);
free(conn->fields);
free(conn->body);
for (i = 0; i < conn->fieldCount; i++) {
free(conn->pathFields[i].var.data);
free(conn->pathFields[i].value.data);
}
free(conn->pathFields);
}
static int createBinaryString(BinaryString *ret) {
ret->allocatedLen = 50;
ret->data = malloc(ret->allocatedLen);
if (ret->data == NULL)
return 1;
ret->len = 0;
return 0;
}
static int appendBinaryString(BinaryString *ret, char c) {
if (ret->len >= ret->allocatedLen) {
char *newdata;
ret->allocatedLen *= 2;
newdata = realloc(ret->data, ret->allocatedLen);
if (newdata == NULL) {
free(ret->data);
return 1;
}
ret->data = newdata;
}
ret->data[ret->len++] = c;
return 0;
}
static int hexval(char c) {
if (isdigit(c))
return c - '0';
if ('a' <= c && c <= 'f')
return c - 'a' + 10;
if ('A' <= c && c <= 'F')
return c - 'A' + 10;
return -1;
}
static int getBinaryString(BinaryString *ret, char *path, char stop,
long *lenReturn) {
long i;
createBinaryString(ret);
for (i = 0; path[i] != stop && path[i] != '\0'; i++) {
char c;
if (path[i] == '%') {
int v;
v = hexval(path[i + 1]);
if (v < 0) {
free(ret->data);
return 1;
}
c = v << 4;
v = hexval(path[i + 2]);
if (v < 0) {
free(ret->data);
return 1;
}
c |= v;
i += 2;
}
else
c = path[i];
appendBinaryString(ret, c);
}
appendBinaryString(ret, '\0');
*lenReturn = i;
return 0;
}
static int processPath(Connection *conn, char *path) {
long len;
if (getBinaryString(&conn->path, path, '?', &len))
return 1;
path += len;
while (path[0] != '\0') {
if (conn->pathFieldCount >= conn->allocatedPathFields) {
PathField *newPathFields;
conn->allocatedPathFields *= 2;
newPathFields = realloc(conn->pathFields,
conn->allocatedPathFields *
sizeof(PathField));
if (newPathFields == NULL)
goto error;
conn->pathFields = newPathFields;
}
path++;
if (getBinaryString(
&conn->pathFields[conn->pathFieldCount].var,
path, '=', &len))
goto error;
path += len;
if (path[0] == '\0') {
free(conn->pathFields[conn->pathFieldCount].var.data);
goto error;
}
path++;
if (getBinaryString(
&conn->pathFields[conn->pathFieldCount].value,
path, '&', &len)) {
free(conn->pathFields[conn->pathFieldCount].var.data);
goto error;
}
conn->pathFieldCount++;
path += len;
}
return 0;
error:
{
long i;
for (i = 0; i < conn->fieldCount; i++) {
free(conn->pathFields[i].var.data);
free(conn->pathFields[i].value.data);
}
free(conn->pathFields);
free(conn->path.data);
return 1;
}
}
static int processRequest(Connection *conn) {
@@ -102,10 +239,8 @@ static int processRequest(Connection *conn) {
for (i = 0;; i++) {
if (line[i] == ' ') {
line[i] = '\0';
conn->path = malloc(i + 1);
if (conn->path == NULL)
if (processPath(conn, line))
return 1;
memcpy(conn->path, line, i + 1);
line += i + 1;
break;
}
@@ -231,14 +366,8 @@ int updateConnection(Connection *conn, Sitefile *site) {
diff(&conn->lastdata, &currentTime) > site->timeout)
return 1;
received = recvStream(conn->stream, buff, sizeof(buff));
if (received < 0) {
char log[200];
sprintf(log,
"recvStream() returned %ld, with errno %d, received %lu bytes this iteration "
"of updateConnection",
received, errno, totalReceived);
if (received < 0)
return errno != EAGAIN;
}
if (received == 0)
return 1;
totalReceived += received;

View File

@@ -37,8 +37,8 @@ static int readResponse(Connection *conn, char *path) {
return 1;
}
if (S_ISDIR(statbuf.st_mode)) {
long reqPathLen = strlen(conn->path);
long pathLen = strlen(path);
size_t reqPathLen = conn->path.len;
size_t pathLen = strlen(path);
char *assembledPath = malloc(reqPathLen + pathLen + 1);
char requestPath[PATH_MAX], responsePath[PATH_MAX];
size_t responsePathLen;
@@ -46,7 +46,8 @@ static int readResponse(Connection *conn, char *path) {
if (assembledPath == NULL)
goto error;
memcpy(assembledPath, path, pathLen);
memcpy(assembledPath + pathLen, conn->path, reqPathLen + 1);
memcpy(assembledPath + pathLen,
conn->path.data, reqPathLen + 1);
if (realpath(assembledPath, requestPath) == NULL) {
if (errno == ENOENT) {
@@ -101,56 +102,6 @@ forbidden:
return 1;
}
static int execResponse(Connection *conn, char *path) {
int output[2];
int status;
pid_t pid;
if (pipe(output))
goto error;
pid = fork();
if (pid < 0)
goto error;
if (pid == 0) {
char **args;
int i;
close(1);
close(output[0]);
dup2(output[1], 1);
args = malloc((conn->fieldCount*2 + 2) * sizeof(char *));
if (args == NULL) {
close(output[1]);
exit(EXIT_FAILURE);
}
args[0] = conn->path;
for (i = 0; i < conn->fieldCount; i++) {
args[i * 2 + 1] = conn->fields[i].field;
args[i * 2 + 2] = conn->fields[i].value;
}
args[conn->fieldCount*2 + 1] = NULL;
if (execv(path, args) < 0) {
close(output[1]);
free(args);
exit(EXIT_FAILURE);
}
close(output[1]);
free(args);
exit(EXIT_SUCCESS);
}
close(output[1]);
status = sendPipe(conn->stream, CODE_200, output[0]);
{
int exitcode;
waitpid(pid, &exitcode, 0);
}
return status;
error:
sendErrorResponse(conn->stream, ERROR_500);
return 1;
}
static int linkedResponse(Connection *conn,
int (*getResponse)(Request *request, Response *response)) {
Request request;
@@ -160,7 +111,9 @@ static int linkedResponse(Connection *conn,
request.fieldCount = conn->fieldCount;
request.fields = conn->fields;
request.path = conn->path;
request.path.path = conn->path;
request.path.fieldCount = conn->pathFieldCount;
request.path.fields = conn->pathFields;
request.type = conn->type;
request.body = conn->body;
request.bodylen = conn->bodylen;
@@ -212,16 +165,12 @@ int sendResponse(Connection *conn, Sitefile *site) {
continue;
if (fullmatch(&site->content[i].host, host))
continue;
if (fullmatch(&site->content[i].path, conn->path) == 0) {
if (fullmatch(&site->content[i].path, conn->path.data) == 0) {
switch (site->content[i].command) {
case READ:
readResponse(conn,
site->content[i].arg);
break;
case EXEC:
execResponse(conn,
site->content[i].arg);
break;
case THROW:
sendErrorResponse(conn->stream,
site->content[i].arg);

View File

@@ -71,12 +71,6 @@ remove:
if (fds[0].revents & POLLIN) {
Stream *newstream;
{
char log[200];
sprintf(log,
"Thread %d received a connection (it now has %d connections)",
id, connCount);
}
if (connCount >= allocConns) {
struct pollfd *newfds;
Connection *newconns;

View File

@@ -287,14 +287,6 @@ Sitefile *parseSitefile(char *path) {
goto error;
ret->content[ret->size].command = READ;
}
else if (strcmp(argv[0], "exec") == 0) {
if (argc < 3)
goto error;
ret->content[ret->size].arg = strdup(argv[2]);
if (ret->content[ret->size].arg == NULL)
goto error;
ret->content[ret->size].command = EXEC;
}
else if (strcmp(argv[0], "throw") == 0) {
if (argc < 3)
goto error;

View File

@@ -18,6 +18,7 @@
#ifndef HAVE_CONNECTIONS
#define HAVE_CONNECTIONS
#include <swebs/types.h>
#include <swebs/runner.h>
#include <swebs/sockets.h>
#include <swebs/sitefile.h>
@@ -36,7 +37,10 @@ typedef struct Connection {
/* the last time that data was received from this connection. */
RequestType type;
char *path;
BinaryString path;
long pathFieldCount;
long allocatedPathFields;
PathField *pathFields;
/* ephemeral */
Field *fields;

View File

@@ -25,7 +25,6 @@
typedef enum {
READ,
EXEC,
THROW,
LINKED
} Command;

View File

@@ -41,6 +41,26 @@ typedef enum {
* */
} RequestType;
typedef struct {
char *data;
/* data is guarunteed to be NULL terminated, although not necessarily
* once. */
size_t len;
size_t allocatedLen;
/* The amount of bytes allocated, for internal use. */
} BinaryString;
typedef struct {
BinaryString var;
BinaryString value;
} PathField;
typedef struct {
BinaryString path;
long fieldCount;
PathField *fields;
} Path;
typedef struct {
char *field;
char *value;
@@ -49,7 +69,7 @@ typedef struct {
typedef struct {
long fieldCount;
Field *fields;
char *path;
Path path;
RequestType type;
void *body;
size_t bodylen;