further php support
This commit is contained in:
125
cmd/server.c
125
cmd/server.c
@@ -32,7 +32,7 @@ int printDebug(char message[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void php_cgi(char *sPath) {
|
char *php_cgi(char *sPath, struct HTTPRequest *r) {
|
||||||
int phpPipe[2];
|
int phpPipe[2];
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
size_t bufLen = 1024;
|
size_t bufLen = 1024;
|
||||||
@@ -41,10 +41,12 @@ void php_cgi(char *sPath) {
|
|||||||
pipe(phpPipe);
|
pipe(phpPipe);
|
||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int status = 0;
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) { // Child fork
|
||||||
char script[500];
|
char script[500];
|
||||||
|
char *queryString = NULL;
|
||||||
close(phpPipe[0]);
|
close(phpPipe[0]);
|
||||||
dup2(phpPipe[1], STDOUT_FILENO);
|
dup2(phpPipe[1], STDOUT_FILENO);
|
||||||
strcpy(script, "SCRIPT_FILENAME=");
|
strcpy(script, "SCRIPT_FILENAME=");
|
||||||
@@ -52,15 +54,48 @@ void php_cgi(char *sPath) {
|
|||||||
strcat(script, sPath);
|
strcat(script, sPath);
|
||||||
putenv("GATEWAY_INTERFACE=CGI/1.1");
|
putenv("GATEWAY_INTERFACE=CGI/1.1");
|
||||||
putenv(script);
|
putenv(script);
|
||||||
putenv("QUERY_STRING=");
|
|
||||||
putenv("REQUEST_METHOD=GET");
|
|
||||||
putenv("REDIRECT_STATUS=true");
|
putenv("REDIRECT_STATUS=true");
|
||||||
putenv("SERVER_PROTOCOL=HTTP/1.1");
|
putenv("SERVER_PROTOCOL=HTTP/1.1");
|
||||||
putenv("REMOTE_HOST=127.0.0.1");
|
putenv("REMOTE_HOST=127.0.0.1");
|
||||||
execl("/usr/bin/php-cgi", "php-cgi", NULL);
|
if (!strcmp(r->requestType, "POST")) {
|
||||||
} else if (pid < 0) {
|
putenv("REQUEST_METHOD=POST");
|
||||||
|
char conLenString[256];
|
||||||
|
sprintf(conLenString, "CONTENT_LENGTH=%zu", r->requestBodyLen);
|
||||||
|
putenv(conLenString);
|
||||||
|
putenv("CONTENT_TYPE=application/x-www-form-urlencoded");
|
||||||
|
queryString = malloc(r->requestBodyLen + 24);
|
||||||
|
sprintf(queryString, "QUERY_STRING=%s", r->requestBody);
|
||||||
|
putenv(queryString);
|
||||||
|
|
||||||
|
// Starting fork to pipe stdin into php-cgi
|
||||||
|
int phpPipe2[2];
|
||||||
|
pipe(phpPipe2);
|
||||||
|
pid_t pid2;
|
||||||
|
pid2 = fork();
|
||||||
|
|
||||||
|
if (pid2 == 0) { // Child fork
|
||||||
|
close(phpPipe2[0]);
|
||||||
|
dup2(phpPipe2[1], STDOUT_FILENO);
|
||||||
|
printf("%s", r->requestBody);
|
||||||
|
close(phpPipe2[1]);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
} else if (pid < 0) { // Error forking
|
||||||
|
printDebug("Error in stdin php frok");
|
||||||
|
} else { // Parent fork
|
||||||
|
close(phpPipe[1]);
|
||||||
|
dup2(phpPipe2[0], STDIN_FILENO);
|
||||||
|
execlp("/usr/bin/php-cgi", "php-cgi", NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
queryString = malloc(strlen(r->requestVars) + 24);
|
||||||
|
sprintf(queryString, "QUERY_STRING=%s", r->requestVars);
|
||||||
|
putenv(queryString);
|
||||||
|
putenv("REQUEST_METHOD=GET");
|
||||||
|
execl("/usr/bin/php-cgi", "php-cgi", NULL);
|
||||||
|
}
|
||||||
|
} else if (pid < 0) { // Error forking
|
||||||
printDebug("Error forking php exec");
|
printDebug("Error forking php exec");
|
||||||
} else {
|
} else { // Parent fork
|
||||||
size_t buffCount;
|
size_t buffCount;
|
||||||
close(phpPipe[1]);
|
close(phpPipe[1]);
|
||||||
do {
|
do {
|
||||||
@@ -70,11 +105,16 @@ void php_cgi(char *sPath) {
|
|||||||
buf = realloc(buf, bufLen);
|
buf = realloc(buf, bufLen);
|
||||||
}
|
}
|
||||||
} while (buffCount == 0);
|
} while (buffCount == 0);
|
||||||
|
do {
|
||||||
|
waitpid(pid, &status, WUNTRACED);
|
||||||
|
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
close(phpPipe[0]);
|
close(phpPipe[0]);
|
||||||
printf("PHP: %s\n", buf);
|
if (status != 0) {
|
||||||
return;
|
return NULL;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) {
|
int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) {
|
||||||
@@ -88,6 +128,7 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) {
|
|||||||
|
|
||||||
// Creating empty requestBody
|
// Creating empty requestBody
|
||||||
r->requestBody = calloc(8, sizeof(char));
|
r->requestBody = calloc(8, sizeof(char));
|
||||||
|
r->requestBodyLen = 0;
|
||||||
|
|
||||||
for (int i = 0; i <= strlen((char *)buffer); i++) {
|
for (int i = 0; i <= strlen((char *)buffer); i++) {
|
||||||
temp[0] = buffer[i];
|
temp[0] = buffer[i];
|
||||||
@@ -101,7 +142,7 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) {
|
|||||||
// HTTP Request Type
|
// HTTP Request Type
|
||||||
if ((!strcmp(token, "GET")) || (!strcmp(token, "POST")) ||
|
if ((!strcmp(token, "GET")) || (!strcmp(token, "POST")) ||
|
||||||
(!strcmp(token, "PUT")) || (!strcmp(token, "DELETE")) ||
|
(!strcmp(token, "PUT")) || (!strcmp(token, "DELETE")) ||
|
||||||
(!strcmp(token, "CONNECT"))) {
|
(!strcmp(token, "CONNECT")) || (!strcmp(token, "HEAD"))) {
|
||||||
// Grabbing HTTP Request Type
|
// Grabbing HTTP Request Type
|
||||||
r->requestType = malloc(strlen(token));
|
r->requestType = malloc(strlen(token));
|
||||||
strcpy(r->requestType, token);
|
strcpy(r->requestType, token);
|
||||||
@@ -130,7 +171,8 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) {
|
|||||||
(strlen((char *)checkLine) + strlen((char *)r->requestBody) + 1));
|
(strlen((char *)checkLine) + strlen((char *)r->requestBody) + 1));
|
||||||
strcat((char *)r->requestBody, (char *)checkLine);
|
strcat((char *)r->requestBody, (char *)checkLine);
|
||||||
// Adding newline to requestBody
|
// Adding newline to requestBody
|
||||||
sprintf((char *)r->requestBody, "%s\n", r->requestBody);
|
strcat((char *)r->requestBody, "\n");
|
||||||
|
r->requestBodyLen += strlen((char *)checkLine);
|
||||||
} else { // Information parsing !content
|
} else { // Information parsing !content
|
||||||
if (strlen((char *)checkLine) == 1) { // Looking for blank empty line to end header info
|
if (strlen((char *)checkLine) == 1) { // Looking for blank empty line to end header info
|
||||||
contentCheck = 1;
|
contentCheck = 1;
|
||||||
@@ -185,6 +227,29 @@ int handleGetRequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
|||||||
unsigned char *fileContent = calloc(size, sizeof(unsigned char));
|
unsigned char *fileContent = calloc(size, sizeof(unsigned char));
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *workingReqDir;
|
char *workingReqDir;
|
||||||
|
|
||||||
|
char *phpReturn = NULL;
|
||||||
|
char phpEnd[5] = ".php";
|
||||||
|
bool endsWithPhp = false;
|
||||||
|
if (strlen(phpEnd) <= strlen(r->requestDir)) {
|
||||||
|
for (int i = 0; i < strlen(phpEnd); i++) {
|
||||||
|
if (r->requestDir[i + strlen(r->requestDir) - strlen(phpEnd)] != phpEnd[i]) {
|
||||||
|
endsWithPhp = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
endsWithPhp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endsWithPhp) {
|
||||||
|
phpReturn = php_cgi(r->requestDir, r);
|
||||||
|
if (phpReturn != NULL) {
|
||||||
|
return returnPHPRequest(socket, phpReturn, ssl);
|
||||||
|
} else {
|
||||||
|
return return500Request(socket, ssl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If requesting root directory change to index.html
|
// If requesting root directory change to index.html
|
||||||
if (!strcmp(r->requestDir, "/")) {
|
if (!strcmp(r->requestDir, "/")) {
|
||||||
workingReqDir = "index.html";
|
workingReqDir = "index.html";
|
||||||
@@ -281,26 +346,42 @@ int handleDELETERequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int handlePOSTRequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
int handlePOSTRequest(int socket, struct HTTPRequest *r, SSL *ssl) {
|
||||||
|
char *phpReturn = NULL;
|
||||||
// Supported data types application/x-www-form-urlencoded application/json
|
// Supported data types application/x-www-form-urlencoded application/json
|
||||||
if (r->requestConLen == NULL) { // Return 411 if length var not specified
|
if (r->requestConLen == NULL) { // Return 411 if length var not specified
|
||||||
printDebug("Content Length was not sent in POST request");
|
printDebug("Content Length was not sent in POST request");
|
||||||
return return411Request(socket, ssl);
|
return return411Request(socket, ssl);
|
||||||
}
|
}
|
||||||
//r->requestBody[strlen((char *)r->requestBody) - 1] = '\0'; // Resetting request content length to remove trailing newline
|
|
||||||
|
|
||||||
if (r->requestConType != NULL) {
|
if (r->requestConType != NULL) {
|
||||||
if (!strcmp(r->requestConType, "application/json")) {
|
if (!strcmp(r->requestConType, "application/x-www-form-utlencoded") == 0) {
|
||||||
printf("JSON Request\n");
|
printDebug("Application From Selected");
|
||||||
} else if (!strcmp(r->requestConType, "application/x-www-form-utlencoded")) {
|
} else {
|
||||||
printf("Application form\n");
|
printDebug("Content will likely get parsed wrong");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
printf("HERE\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
php_cgi(r->requestDir);
|
char phpEnd[5] = ".php";
|
||||||
|
bool endsWithPhp = false;
|
||||||
|
if (strlen(phpEnd) <= strlen(r->requestDir)) {
|
||||||
|
for (int i = 0; i < strlen(phpEnd); i++) {
|
||||||
|
if (r->requestDir[i + strlen(r->requestDir) - strlen(phpEnd)] != phpEnd[i]) {
|
||||||
|
endsWithPhp = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
endsWithPhp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return return501Request(socket, ssl);
|
if (endsWithPhp) {
|
||||||
|
phpReturn = php_cgi(r->requestDir, r);
|
||||||
|
if (phpReturn != NULL) {
|
||||||
|
return returnPHPRequest(socket, phpReturn, ssl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return return200Request(socket, NULL, ssl);
|
||||||
|
}
|
||||||
|
return return500Request(socket, ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int handleRequest(unsigned char buffer[], int socket, SSL *ssl) {
|
int handleRequest(unsigned char buffer[], int socket, SSL *ssl) {
|
||||||
@@ -312,7 +393,7 @@ int handleRequest(unsigned char buffer[], int socket, SSL *ssl) {
|
|||||||
// Grabbing relevant information out of request
|
// Grabbing relevant information out of request
|
||||||
checkerr = parseHTTPRequest(buffer, &r);
|
checkerr = parseHTTPRequest(buffer, &r);
|
||||||
if (checkerr != 0) { // Checking for HTTP parsing error
|
if (checkerr != 0) { // Checking for HTTP parsing error
|
||||||
printDebug("Error ;(");
|
printDebug("Error parsing...");
|
||||||
if (checkerr == -1) {
|
if (checkerr == -1) {
|
||||||
printDebug("Error reading request, returning empty 500");
|
printDebug("Error reading request, returning empty 500");
|
||||||
return500Request(socket, ssl);
|
return500Request(socket, ssl);
|
||||||
@@ -335,6 +416,8 @@ int handleRequest(unsigned char buffer[], int socket, SSL *ssl) {
|
|||||||
handleDELETERequest(socket, &r, ssl);
|
handleDELETERequest(socket, &r, ssl);
|
||||||
} else if (!strcmp(r.requestType, "CONNECT")) {
|
} else if (!strcmp(r.requestType, "CONNECT")) {
|
||||||
return200Request(socket, NULL, ssl);
|
return200Request(socket, NULL, ssl);
|
||||||
|
} else if (!strcmp(r.requestType, "HEAD")) {
|
||||||
|
return200Request(socket, NULL, ssl);
|
||||||
} else {
|
} else {
|
||||||
return500Request(socket, ssl);
|
return500Request(socket, ssl);
|
||||||
}
|
}
|
||||||
|
|||||||
4
content/vardumpGET.php
Normal file
4
content/vardumpGET.php
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
print("Hello World\n");
|
||||||
|
var_dump($_GET);
|
||||||
|
?>
|
||||||
8
content/vardumpPOST.php
Normal file
8
content/vardumpPOST.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
print("Hello World\n");
|
||||||
|
$output=null;
|
||||||
|
var_dump($_POST);
|
||||||
|
exec('printenv', $output);
|
||||||
|
print_r($output);
|
||||||
|
var_dump($HTTP_RAW_POST_DATA);
|
||||||
|
?>
|
||||||
@@ -11,4 +11,5 @@ struct HTTPRequest {
|
|||||||
char *requestConType;
|
char *requestConType;
|
||||||
char *requestConLen;
|
char *requestConLen;
|
||||||
unsigned char *requestBody;
|
unsigned char *requestBody;
|
||||||
|
size_t requestBodyLen;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,3 +15,5 @@ int return500Request(int socket, SSL *ssl);
|
|||||||
int return501Request(int socket, SSL *ssl);
|
int return501Request(int socket, SSL *ssl);
|
||||||
int return505Request(int socket, SSL *ssl);
|
int return505Request(int socket, SSL *ssl);
|
||||||
|
|
||||||
|
int returnPHPRequest(int socket, char *content, SSL *ssl);
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ int return200Request(int socket, unsigned char *content, SSL *ssl) {
|
|||||||
char *message = "";
|
char *message = "";
|
||||||
if (content != NULL) {
|
if (content != NULL) {
|
||||||
message = calloc(strlen((char *)content) + 128, sizeof(char));
|
message = calloc(strlen((char *)content) + 128, sizeof(char));
|
||||||
sprintf(message, "HTTP/1.1 200 OK\nContent-Length: %zu\nConnection: close\n\n%s\n",
|
sprintf(message, "HTTP/1.1 200 OK\nContent-Length: %zu\nConnection: close\n\n%s",
|
||||||
strlen((char *)content), content);
|
strlen((char *)content), content);
|
||||||
} else { // Sending empty response
|
} else { // Sending empty response
|
||||||
message = calloc(128, sizeof(char));
|
message = calloc(128, sizeof(char));
|
||||||
@@ -65,7 +65,7 @@ int return411Request(int socket, SSL *ssl) {
|
|||||||
|
|
||||||
int return418Request(int socket, SSL *ssl) {
|
int return418Request(int socket, SSL *ssl) {
|
||||||
char *message=calloc(128, sizeof(char));
|
char *message=calloc(128, sizeof(char));
|
||||||
sprintf(message, "HTTP/1.1 418 I'm a teapotnContent-Length: 0\nConnection: close\n\n");
|
sprintf(message, "HTTP/1.1 418 I'm a teapot\nContent-Length: 0\nConnection: close\n\n");
|
||||||
return returnRequest(socket, message, 418, ssl);
|
return returnRequest(socket, message, 418, ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,3 +86,34 @@ int return505Request(int socket, SSL *ssl) {
|
|||||||
sprintf(message, "HTTP/1.1 505 HTTP Version Not Supported\nContent-Length: 0\nConnection: close\n\n");
|
sprintf(message, "HTTP/1.1 505 HTTP Version Not Supported\nContent-Length: 0\nConnection: close\n\n");
|
||||||
return returnRequest(socket, message, 505, ssl);
|
return returnRequest(socket, message, 505, ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int returnPHPRequest(int socket, char *content, SSL *ssl) {
|
||||||
|
char *message = malloc(1024);
|
||||||
|
memset(message, 0, 1024);
|
||||||
|
char *line = malloc(1024);
|
||||||
|
memset(line, 0, 1024);
|
||||||
|
char temp[1];
|
||||||
|
size_t lineNum = 0;
|
||||||
|
for (int i = 0; i <= strlen(content); i++) {
|
||||||
|
temp[0] = content[i];
|
||||||
|
if (((!strcmp(temp, "\n")) && (i != 0)) || (i == strlen(content))) {
|
||||||
|
if (lineNum != 0) {
|
||||||
|
strcat(message, line);
|
||||||
|
strcat(message, "\n");
|
||||||
|
}
|
||||||
|
if (strlen(line) > 0) {
|
||||||
|
memset(line, 0, strlen(line));
|
||||||
|
}
|
||||||
|
lineNum++;
|
||||||
|
} else {
|
||||||
|
strcat(line, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
if (strlen(message) == 0) { // Return 500 on error parsing
|
||||||
|
free(message);
|
||||||
|
return return500Request(socket, ssl);
|
||||||
|
}
|
||||||
|
return return200Request(socket, (unsigned char *)message, ssl);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user