Skip to content

Commit

Permalink
Merge pull request #51 from samih713/CGI-Parser
Browse files Browse the repository at this point in the history
feat(#21): CGI parsing done
  • Loading branch information
Taanviir authored Apr 26, 2024
2 parents 9bdd130 + 26527ed commit 4de2e3b
Show file tree
Hide file tree
Showing 15 changed files with 405 additions and 101 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/compile-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@v3

- name: Set up C++ environment
uses: aminya/setup-cpp@v1
uses: egor-tensin/setup-gcc@v1.3
with:
compiler: gcc

Expand All @@ -30,10 +30,5 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up C++ environment
uses: aminya/setup-cpp@v1
with:
compiler: gcc

- name: Build project
run: make
2 changes: 2 additions & 0 deletions .resources/cgi-bin/file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/python3
print("hello worled")
3 changes: 3 additions & 0 deletions .resources/cgi-bin/file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
echo "Hello, World Bash!"
sleep 20
2 changes: 2 additions & 0 deletions .resources/notes/CGI_ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
https://www.oreilly.com/library/view/cgi-programming-on/9781565921689/04_chapter-01.html //good aticla for CGi
http://www.mnuwer.dbasedeveloper.co.uk/dlearn/web/session01.htm
19 changes: 19 additions & 0 deletions configs/cgitest.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
http {
server {
listen 8080;
client_max_body_size 1M;
server_name localhost;

root ./.resources;
index index.html index.htm;

location / {
root ./.resources/sample_pages;
}

error_page 404 /404.html;
location = /404.html {
root ./.resources/sample_pages;
}
}
}
7 changes: 7 additions & 0 deletions curl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
curl -X GET http://localhost:8080/cgi-bin/file.sh?name=hashim \
-H "Host: Linode.com" \
-H "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.8) Gecko/20091102 Firefox/3.5.5" \
-H "Accept-Encoding: gzip,deflate" \
-H "Accept-Charset: ISO-8859-1,utf-8" \
-H "Cache-Control: no-cache" \
-d $'body\r\n'
274 changes: 212 additions & 62 deletions sources/CGI/Cgi.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,76 @@
#include "Cgi.hpp"
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Cgi.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: hmohamed <hmohamed@student.42abudhabi.ae> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/02/23 12:44:51 by hmohamed #+# #+# */
/* Updated: 2024/04/25 14:04:56 by hmohamed ### ########.fr */
/* */
/* ************************************************************************** */

static char** headers_to_env(const vsp& headers);
static string get_uri(string res);
static string get_query_string(string res);
#include "Cgi.hpp"

Cgi::Cgi(const Request& request)
string getStingQuery(string res)
{
string resource = request.get_resource();
headers = request.get_headers();
environment = headers_to_env(headers);
filePath = get_uri(resource);
queryString = get_query_string(resource);

arguments = new char*[2];
arguments[0] = const_cast<char*>(filePath.c_str());
arguments[1] = NULL;
string resn;
size_t qu;
size_t length;

qu = res.find('?', 0);
length = res.length();
cout<< "the ? :" << qu <<endl;
cout << "lingth:" << length << endl;
resn = res.substr(qu + 1, length);
//result = const_cast<char *>(res.substr(0,qu).c_str());
cout << resn << endl;
return (resn);
}


string geturi(string res)
{
string resn;
size_t qu;

qu = res.find('?', 0);
resn = res.substr(0, qu);
//result = const_cast<char *>(res.substr(0,qu).c_str());
cout << resn << endl;
cout<< "test" << qu <<endl;
return (resn);
}

Cgi::Cgi(const Request &request, const ServerConfig &config): body(request.get_body())
{
string res;

(void)config;
res = const_cast<char *>(request.get_resource().c_str());
filePath = (geturi(res));
headers = request.get_headers();
environment = headersToEnv(request, res, config);
timer = request.timer;
//filePath = const_cast<char *>(geturi(request.get_resource())->c_str());
//queryString = getStingQuery(res);
//filePath = const_cast<char *> (request.get_resource().c_str());
// // Check if the Python script exists
// if (access(filePath, X_OK) == -1)
// {
// std::cerr << "Error: Python script not found or does not have execution permission." << std::endl;
// return ;
// }
cout<< "file path :" << filePath << endl;
arguments = new char *[2];
arguments[0] = const_cast<char *>(filePath.c_str());
arguments[1] = NULL;

// Print out the environment variables
for (int i = 0; environment[i] != NULL; ++i)
{
std::cout << environment[i] << std::endl;
}
}

Cgi::~Cgi()
Expand All @@ -25,6 +81,71 @@ Cgi::~Cgi()
delete[] arguments;
}

char ** Cgi::headersToEnv(const Request &request, const string res, const ServerConfig &config)
{
std::vector<char *> envVector;

(void)config;
(void)request;

string queryString = getStingQuery(res);;
// Iterate through headers
for (vsp::iterator it = headers.begin(); it != headers.end(); ++it)
{
size_t len = it->first.size() + it->second.size() + 2;
char *envEntry = new char[len];
std::snprintf(envEntry, len, "%s=%s", it->first.c_str(), it->second.c_str());
envVector.push_back(envEntry);
}

// std::string gateway_interface = "GATEWAY_INTERFACE=CGI/1.1";
// envVector.push_back(const_cast<char *>(gateway_interface.c_str()));

envVector.push_back(strdup("GATEWAY_INTERFACE=CGI/1.1"));
envVector.push_back(strdup("SERVER_PROTOCOL=HTTP/1.1"));
string val;
val = "SERVER_NAME=" + config.serverName;
envVector.push_back(strdup(val.c_str()));
val = "SERVER_SOFTWARE=" + config.serverName + "/1.0";
envVector.push_back(strdup(val.c_str()));
val = "SERVER_PORT=" + ws_itoa(config.listenerPort);
envVector.push_back(strdup(val.c_str()));
val = "REQUEST_URI=" + request.get_resource();
envVector.push_back(strdup(val.c_str()));
queryString = getStingQuery(res);
// val = "QUERY_STRING=" + queryString;
// envVector.push_back(strdup(val.c_str()));
// "REQUEST_METHOD"
// "PATH_INFO"
// "PATH_TRANSLATED"
// "QUERY_STRING"
// "REMOTEaddr"
// "REMOTE_IDENT"
// "REMOTE_USER"


char* token = strtok(const_cast<char *>(queryString.c_str()), "&");

//cout << token +3 <<endl;
// Iterate through the tokens and push integers onto the stack
while (token != NULL) {
envVector.push_back(strdup(token));
token = strtok(NULL, "&");
}

// Allocate memory for char* array
char **envp = new char *[envVector.size() + 1];

// Copy pointers from vector to char* array
for (size_t i = 0; i < envVector.size(); ++i)
{
envp[i] = envVector[i];
}
envp[envVector.size()] = NULL;

return envp;
}

void Cgi::execute(const string& outputFile)
{
int fd[2];
Expand Down Expand Up @@ -81,6 +202,7 @@ void Cgi::execute(const string& outputFile)
close(fd[0]);
}


string Cgi::execute(void)
{
int fd[2];
Expand All @@ -92,6 +214,7 @@ string Cgi::execute(void)
cerr << "Error creating pipe: " << strerror(errno) << endl;
return NULL;
}
cout<< "FBB" << filePath << endl;

// Fork the process
// TODO fix forking here for sleep
Expand All @@ -113,65 +236,92 @@ string Cgi::execute(void)
}

// Parent process
close(fd[1]); // Close the write end of the pipe

// Wait for the child process to finish
int status;
waitpid(id, &status, 0);
close(fd[1]); // Close the write end of the pipe
int status;
// Wait for the child process to finish or until timeout
while (true) {
// Check if the timeout duration has been reached
if (timer.is_timeout()) {
std::cerr << "Timeout reached. Exiting." << std::endl;
// Terminate the child process
kill(id, SIGTERM);
break;
}

// Read the response from the pipe
char buffer[91];
ssize_t bytesRead;
while ((bytesRead = read(fd[0], buffer, 90)) > 0)
res_body.append(buffer, bytesRead);
// Check if the child process has finished
if (waitpid(id, &status, WNOHANG) == id) {
// Child process has finished
// Read from the pipe
char buffer[1024];
ssize_t bytesRead = read(fd[0], buffer, sizeof(buffer));
if (bytesRead > 0) {
res_body.append(buffer, bytesRead);
} else if (bytesRead == 0) {
break;
} else {
// Error while reading from the pipe
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// No data available yet, continue waiting
usleep(100000);
continue;
} else {
std::cerr << "Error reading from pipe: " << strerror(errno) << std::endl;
break;
}
}
break;
}
usleep(100000);
}


close(fd[0]);
return (res_body);
}

static char** headers_to_env(const vsp& headers)
{
vector<char*> envVector;
// static char** headers_to_env(const vsp& headers)
// {
// vector<char*> envVector;

// Iterate through headers
vsp::const_iterator end = headers.end();
for (vsp::const_iterator it = headers.begin(); it != end; ++it) {
size_t len = it->first.size() + it->second.size() + 2;
char* envEntry = new char[len];
std::snprintf(envEntry, len, "%s=%s", it->first.c_str(), it->second.c_str());
envVector.push_back(envEntry);
}
// // Iterate through headers
// vsp::const_iterator end = headers.end();
// for (vsp::const_iterator it = headers.begin(); it != end; ++it) {
// size_t len = it->first.size() + it->second.size() + 2;
// char* envEntry = new char[len];
// std::snprintf(envEntry, len, "%s=%s", it->first.c_str(), it->second.c_str());
// envVector.push_back(envEntry);
// }

// Allocate memory for char* array
char** envp = new char*[envVector.size() + 1];
// // Allocate memory for char* array
// char** envp = new char*[envVector.size() + 1];

// Copy pointers from vector to char* array
for (size_t i = 0; i < envVector.size(); ++i)
envp[i] = envVector[i];
envp[envVector.size()] = NULL;
// // Copy pointers from vector to char* array
// for (size_t i = 0; i < envVector.size(); ++i)
// envp[i] = envVector[i];
// envp[envVector.size()] = NULL;

return envp;
}
// return envp;
// }

static string get_uri(string res)
{
string resn;
size_t qu;
// static string get_uri(string res)
// {
// string resn;
// size_t qu;

qu = res.find('?', 0);
resn = res.substr(0, qu);
// result = const_cast<char *>(res.substr(0,qu).c_str());
return (resn);
}
// qu = res.find('?', 0);
// resn = res.substr(0, qu);
// // result = const_cast<char *>(res.substr(0,qu).c_str());
// return (resn);
// }

static string get_query_string(string res)
{
string resn;
size_t qu;
size_t length;
// static string get_query_string(string res)
// {
// string resn;
// size_t qu;
// size_t length;

qu = res.find('?', 0);
length = res.length();
resn = res.substr(qu + 1, length);
return (resn);
}
// qu = res.find('?', 0);
// length = res.length();
// resn = res.substr(qu + 1, length);
// return (resn);
// }
Loading

0 comments on commit 4de2e3b

Please sign in to comment.