Added url variables, removed exec pages
This commit is contained in:
@@ -38,10 +38,30 @@ typedef enum {
|
|||||||
* */
|
* */
|
||||||
} RequestType;
|
} 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 {
|
typedef struct {
|
||||||
long fieldCount;
|
long fieldCount;
|
||||||
Field *fields;
|
Field *fields;
|
||||||
char *path;
|
Path path;
|
||||||
RequestType type;
|
RequestType type;
|
||||||
} Request;
|
} Request;
|
||||||
/*HTTP request, pretty self explanatory*/
|
/*HTTP request, pretty self explanatory*/
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ sitefiles also allow comments with #
|
|||||||
* ```set [variable] [value]``` - sets some local variable for the following pages
|
* ```set [variable] [value]``` - sets some local variable for the following pages
|
||||||
* ```define [variable] [value]``` - sets some global variable
|
* ```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.
|
* ```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
|
* ```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.
|
* ```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.
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
#include <swebs/swebs.h>
|
#include <swebs/swebs.h>
|
||||||
|
|
||||||
int getResponse(Request *request, Response *response) {
|
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->type = BUFFER;
|
||||||
response->response.buffer.data = malloc(100);
|
response->response.buffer.data = malloc(100);
|
||||||
strcpy(response->response.buffer.data, str);
|
strcpy(response->response.buffer.data, str);
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo "<p>By the way today's date is $(date)</p>"
|
|
||||||
@@ -3,5 +3,4 @@
|
|||||||
<h3>It's not very polished but it's certainly a website</h3>
|
<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-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>
|
<a href="blog/forbidden">The forbidden blog post</a>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ set host localhost:8000
|
|||||||
read / site/index.html
|
read / site/index.html
|
||||||
read /hello site/hello.html
|
read /hello site/hello.html
|
||||||
throw /blog/forbidden 403
|
throw /blog/forbidden 403
|
||||||
exec /blog/2022-1-31 site/blog/blog/2022-1-31.sh
|
|
||||||
read /blog/.* site/blog/
|
read /blog/.* site/blog/
|
||||||
#/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html
|
#/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html
|
||||||
linked /library
|
linked /library
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -45,7 +46,15 @@ int newConnection(Stream *stream, Connection *ret) {
|
|||||||
return 1;
|
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;
|
ret->body = NULL;
|
||||||
/*
|
/*
|
||||||
* pointers to things that are allocated within functions should be
|
* 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, ¤tTime) < 0) {
|
if (clock_gettime(CLOCK_MONOTONIC, ¤tTime) < 0) {
|
||||||
free(ret->currLine);
|
free(ret->currLine);
|
||||||
|
free(ret->fields);
|
||||||
|
free(ret->pathFields);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memcpy(&ret->lastdata, ¤tTime, sizeof(struct timespec));
|
memcpy(&ret->lastdata, ¤tTime, sizeof(struct timespec));
|
||||||
@@ -61,20 +72,146 @@ int newConnection(Stream *stream, Connection *ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resetConnection(Connection *conn) {
|
void resetConnection(Connection *conn) {
|
||||||
|
long i;
|
||||||
conn->progress = RECEIVE_REQUEST;
|
conn->progress = RECEIVE_REQUEST;
|
||||||
conn->fieldCount = 0;
|
conn->fieldCount = 0;
|
||||||
free(conn->body);
|
free(conn->body);
|
||||||
free(conn->path);
|
|
||||||
conn->body = NULL;
|
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) {
|
void freeConnection(Connection *conn) {
|
||||||
|
long i;
|
||||||
freeStream(conn->stream);
|
freeStream(conn->stream);
|
||||||
free(conn->currLine);
|
free(conn->currLine);
|
||||||
free(conn->path);
|
|
||||||
free(conn->fields);
|
free(conn->fields);
|
||||||
free(conn->body);
|
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) {
|
static int processRequest(Connection *conn) {
|
||||||
@@ -102,10 +239,8 @@ static int processRequest(Connection *conn) {
|
|||||||
for (i = 0;; i++) {
|
for (i = 0;; i++) {
|
||||||
if (line[i] == ' ') {
|
if (line[i] == ' ') {
|
||||||
line[i] = '\0';
|
line[i] = '\0';
|
||||||
conn->path = malloc(i + 1);
|
if (processPath(conn, line))
|
||||||
if (conn->path == NULL)
|
|
||||||
return 1;
|
return 1;
|
||||||
memcpy(conn->path, line, i + 1);
|
|
||||||
line += i + 1;
|
line += i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -231,14 +366,8 @@ int updateConnection(Connection *conn, Sitefile *site) {
|
|||||||
diff(&conn->lastdata, ¤tTime) > site->timeout)
|
diff(&conn->lastdata, ¤tTime) > site->timeout)
|
||||||
return 1;
|
return 1;
|
||||||
received = recvStream(conn->stream, buff, sizeof(buff));
|
received = recvStream(conn->stream, buff, sizeof(buff));
|
||||||
if (received < 0) {
|
if (received < 0)
|
||||||
char log[200];
|
|
||||||
sprintf(log,
|
|
||||||
"recvStream() returned %ld, with errno %d, received %lu bytes this iteration "
|
|
||||||
"of updateConnection",
|
|
||||||
received, errno, totalReceived);
|
|
||||||
return errno != EAGAIN;
|
return errno != EAGAIN;
|
||||||
}
|
|
||||||
if (received == 0)
|
if (received == 0)
|
||||||
return 1;
|
return 1;
|
||||||
totalReceived += received;
|
totalReceived += received;
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ static int readResponse(Connection *conn, char *path) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (S_ISDIR(statbuf.st_mode)) {
|
if (S_ISDIR(statbuf.st_mode)) {
|
||||||
long reqPathLen = strlen(conn->path);
|
size_t reqPathLen = conn->path.len;
|
||||||
long pathLen = strlen(path);
|
size_t pathLen = strlen(path);
|
||||||
char *assembledPath = malloc(reqPathLen + pathLen + 1);
|
char *assembledPath = malloc(reqPathLen + pathLen + 1);
|
||||||
char requestPath[PATH_MAX], responsePath[PATH_MAX];
|
char requestPath[PATH_MAX], responsePath[PATH_MAX];
|
||||||
size_t responsePathLen;
|
size_t responsePathLen;
|
||||||
@@ -46,7 +46,8 @@ static int readResponse(Connection *conn, char *path) {
|
|||||||
if (assembledPath == NULL)
|
if (assembledPath == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
memcpy(assembledPath, path, pathLen);
|
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 (realpath(assembledPath, requestPath) == NULL) {
|
||||||
if (errno == ENOENT) {
|
if (errno == ENOENT) {
|
||||||
@@ -101,56 +102,6 @@ forbidden:
|
|||||||
return 1;
|
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,
|
static int linkedResponse(Connection *conn,
|
||||||
int (*getResponse)(Request *request, Response *response)) {
|
int (*getResponse)(Request *request, Response *response)) {
|
||||||
Request request;
|
Request request;
|
||||||
@@ -160,7 +111,9 @@ static int linkedResponse(Connection *conn,
|
|||||||
|
|
||||||
request.fieldCount = conn->fieldCount;
|
request.fieldCount = conn->fieldCount;
|
||||||
request.fields = conn->fields;
|
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.type = conn->type;
|
||||||
request.body = conn->body;
|
request.body = conn->body;
|
||||||
request.bodylen = conn->bodylen;
|
request.bodylen = conn->bodylen;
|
||||||
@@ -212,16 +165,12 @@ int sendResponse(Connection *conn, Sitefile *site) {
|
|||||||
continue;
|
continue;
|
||||||
if (fullmatch(&site->content[i].host, host))
|
if (fullmatch(&site->content[i].host, host))
|
||||||
continue;
|
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) {
|
switch (site->content[i].command) {
|
||||||
case READ:
|
case READ:
|
||||||
readResponse(conn,
|
readResponse(conn,
|
||||||
site->content[i].arg);
|
site->content[i].arg);
|
||||||
break;
|
break;
|
||||||
case EXEC:
|
|
||||||
execResponse(conn,
|
|
||||||
site->content[i].arg);
|
|
||||||
break;
|
|
||||||
case THROW:
|
case THROW:
|
||||||
sendErrorResponse(conn->stream,
|
sendErrorResponse(conn->stream,
|
||||||
site->content[i].arg);
|
site->content[i].arg);
|
||||||
|
|||||||
@@ -71,12 +71,6 @@ remove:
|
|||||||
|
|
||||||
if (fds[0].revents & POLLIN) {
|
if (fds[0].revents & POLLIN) {
|
||||||
Stream *newstream;
|
Stream *newstream;
|
||||||
{
|
|
||||||
char log[200];
|
|
||||||
sprintf(log,
|
|
||||||
"Thread %d received a connection (it now has %d connections)",
|
|
||||||
id, connCount);
|
|
||||||
}
|
|
||||||
if (connCount >= allocConns) {
|
if (connCount >= allocConns) {
|
||||||
struct pollfd *newfds;
|
struct pollfd *newfds;
|
||||||
Connection *newconns;
|
Connection *newconns;
|
||||||
|
|||||||
@@ -287,14 +287,6 @@ Sitefile *parseSitefile(char *path) {
|
|||||||
goto error;
|
goto error;
|
||||||
ret->content[ret->size].command = READ;
|
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) {
|
else if (strcmp(argv[0], "throw") == 0) {
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#ifndef HAVE_CONNECTIONS
|
#ifndef HAVE_CONNECTIONS
|
||||||
#define HAVE_CONNECTIONS
|
#define HAVE_CONNECTIONS
|
||||||
|
|
||||||
|
#include <swebs/types.h>
|
||||||
#include <swebs/runner.h>
|
#include <swebs/runner.h>
|
||||||
#include <swebs/sockets.h>
|
#include <swebs/sockets.h>
|
||||||
#include <swebs/sitefile.h>
|
#include <swebs/sitefile.h>
|
||||||
@@ -36,7 +37,10 @@ typedef struct Connection {
|
|||||||
/* the last time that data was received from this connection. */
|
/* the last time that data was received from this connection. */
|
||||||
|
|
||||||
RequestType type;
|
RequestType type;
|
||||||
char *path;
|
BinaryString path;
|
||||||
|
long pathFieldCount;
|
||||||
|
long allocatedPathFields;
|
||||||
|
PathField *pathFields;
|
||||||
/* ephemeral */
|
/* ephemeral */
|
||||||
|
|
||||||
Field *fields;
|
Field *fields;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
READ,
|
READ,
|
||||||
EXEC,
|
|
||||||
THROW,
|
THROW,
|
||||||
LINKED
|
LINKED
|
||||||
} Command;
|
} Command;
|
||||||
|
|||||||
@@ -41,6 +41,26 @@ typedef enum {
|
|||||||
* */
|
* */
|
||||||
} RequestType;
|
} 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 {
|
typedef struct {
|
||||||
char *field;
|
char *field;
|
||||||
char *value;
|
char *value;
|
||||||
@@ -49,7 +69,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
long fieldCount;
|
long fieldCount;
|
||||||
Field *fields;
|
Field *fields;
|
||||||
char *path;
|
Path path;
|
||||||
RequestType type;
|
RequestType type;
|
||||||
void *body;
|
void *body;
|
||||||
size_t bodylen;
|
size_t bodylen;
|
||||||
|
|||||||
Reference in New Issue
Block a user