Skip to content

Commit

Permalink
Merge pull request #37 from saladuit/configsyntax
Browse files Browse the repository at this point in the history
Configsyntax
  • Loading branch information
saladuit authored Dec 1, 2023
2 parents 0656c86 + b308b19 commit 1e5d0eb
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 68 deletions.
26 changes: 12 additions & 14 deletions config/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,34 @@

server {
listen localhost:8080; # [M - O] choose a Host:Port combination ; IPv4:{1 - 16bit} ; default: INADDR_ANY:8080
server_name localhost; # [M - O] Setup the server_names ; [A-Za-z_]* ; default: [EMPTY]
server_name localhost; # [M - O] Setup the server_names ; [A-Za-z_]* ; default: [EMPTY]
error_dir /error; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY]
client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB

location / {
root /data/www; # [1 - O] Set up the root directory for the server ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www
location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a /
alias /data/www; # [1 - O] links the stated Direcotry as the RequestTarget Location ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www
index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html
allowed_methods GET; # [M - O] Define a list of accepted HTTP methods for the route; GET/POST/DELETE ; Default: GET
autoindex on; # [B - O] Turn on or off directory listing; on; Default: off
}

location /python {
root /cgi_bin/python; # already defined;
cgi_path /bin/python3; # [1 - O] Set a Path to where the CGI can find the Binary; [A-Za-z_/.]* ; Default: [EMPTY]
}

location /images {
location /python/ {
alias /cgi/python; # already defined;
cgi .py /bin/python3; # [1 - O] Set a Path to where the CGI can find the Binary; [A-Za-z_/.]* ; Default: [EMPTY]
}

location /images/ {
root /data/images; # already defined;
allow_methods GET POST; # already defined;
autoindex off; # already defined;
}

location /upload {
location /upload/ {
root /data/upload;
allowed_moteds POST DELETE;
}

location /removed_folder {
location /removed_folder/ {
return localhost; # [1 - O] Reroute a directory to another URL; URL ; Default: []
}

return {URL};
}
}
2 changes: 1 addition & 1 deletion include/ConfigParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ConfigParser
std::vector<ServerSettings> _server_settings;

std::stringstream OpenFile();
void syntaxCheck(std::vector<Token>::iterator);
void syntax(std::vector<Token> token);

public:
ConfigParser(const std::string &file_path);
Expand Down
7 changes: 3 additions & 4 deletions include/LocationSettings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#include <Token.hpp>

#include <string>
#include <unordered_map>
#include <vector>

class LocationSettings
{
Expand All @@ -18,7 +16,7 @@ class LocationSettings

// Functionality:
// getters:
const std::string &getDir() const;
const std::string &getRequestTarget() const;
const std::string &getAlias() const;
const std::string &getIndex() const;
const std::string &getAllowedMethods() const;
Expand All @@ -32,7 +30,7 @@ class LocationSettings
void printLocationSettings() const;

private:
std::string _directory;
std::string _requesttarget;

std::string _alias;
std::string _index;
Expand All @@ -43,6 +41,7 @@ class LocationSettings

void parseAlias(const Token token);
void parseIndex(const Token token);
void parseAutoIndex(const Token token);
void parseAllowedMethods(const Token token);
void parseCgiPath(const Token token);
void parseReturn(const Token token);
Expand Down
5 changes: 1 addition & 4 deletions include/ServerSettings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
#include <LocationSettings.hpp>
#include <Token.hpp>

#include <regex>
#include <string>
#include <vector>

class ServerSettings
{
Expand All @@ -19,8 +17,7 @@ class ServerSettings
ServerSettings &operator=(const ServerSettings &rhs) = delete;

// Functionality:
const LocationSettings *resolveLocation(const std::string &request_target,
HTTPMethod input_method);
const LocationSettings &resolveLocation(const std::string &request_target);
const std::string &getListen() const;
const std::string &getServerName() const;
const std::string &getErrorDir() const;
Expand Down
4 changes: 3 additions & 1 deletion include/Token.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ enum class TokenType
SEMICOLON,
OPEN_BRACKET,
CLOSE_BRACKET,
PATH,
WORD,
};

Expand All @@ -26,11 +27,12 @@ class Token
const Token &operator=(const Token &rhs) = delete;

TokenType getType() const;
void setType(TokenType);
const std::string &getString() const;
std::string typeToString() const;

private:
const TokenType _type;
TokenType _type;
const std::string _string;
};

Expand Down
3 changes: 2 additions & 1 deletion makerc/options.mk
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Flags
ifdef DEBUG
CFLAGS +=-g
CFLAGS +=-g -fstandalone-debug

endif

ifdef FSAN
Expand Down
17 changes: 13 additions & 4 deletions src/ConfigParser.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include <ConfigParser.hpp>
#include <LocationSettings.hpp>
#include <Logger.hpp>
#include <ServerSettings.hpp>
#include <Token.hpp>
Expand Down Expand Up @@ -47,14 +48,22 @@ void ConfigParser::ParseConfig()
std::vector<Token> tokenlist;

tokenizeStream(OpenFile(), tokenlist);
syntaxCheck(tokenlist.begin());

syntax(tokenlist);
logger.log(INFO, "Syntax of " + _config_file_path + " finished");

for (std::vector<Token>::iterator it = tokenlist.begin();
it != tokenlist.end(); it++)
_server_settings.emplace_back(ServerSettings(it));

for (auto &it : _server_settings)
it.printServerSettings();

// {
// const LocationSettings &loc = it.resolveLocation("/t/");
//
// logger.log(DEBUG, "LocationSettings.getRequestTarget: " +
// loc.getRequestTarget() +
// "\tcheck: " + loc.getIndex());
// }
//
//
logger.log(INFO, "Parsed configfile: " + _config_file_path);
}
141 changes: 139 additions & 2 deletions src/ConfigSyntax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,144 @@
#include <Logger.hpp>
#include <Token.hpp>

void ConfigParser::syntaxCheck(std::vector<Token>::iterator token)
#include <iterator>
#include <stdexcept>
#include <string>

std::vector<Token>::iterator findBlockEnd(std::vector<Token> &tokens,
size_t pos)
{
std::vector<Token>::iterator it = tokens.begin() + pos;
std::vector<Token>::iterator blockidentifier = it;

it++;
if (blockidentifier->getString() == "location")
it++; // to skip the directory specified in locationblock

if (it->getType() != TokenType::OPEN_BRACKET)
throw std::runtime_error("Syntax Error: '" +
blockidentifier->getString() +
"' Block isn't opened");
it++;

size_t stack = 1;
while (it != tokens.end() && stack != 0)
{
it++;
if (it->getType() == TokenType::OPEN_BRACKET)
stack++;
else if (it->getType() == TokenType::CLOSE_BRACKET)
stack--;
}

if (stack != 0)
throw std::runtime_error(
"Syntax Error: " + blockidentifier->getString() +
" Block isn't closed");

return (it);
}

void syntaxRequestTarget(std::vector<Token>::iterator &it)
{
const std::string reqtarget = it->getString();

if (reqtarget.find_first_of("/") != 0)
throw std::runtime_error("Syntax Error: locationBlock RequestTarget "
"doesn't start with '/' : " +
reqtarget);
if (reqtarget.length() == 1)
return;

if (reqtarget.find_last_of("/") != reqtarget.length() - 1)
throw std::runtime_error("Syntax Error: locationBlock RequestTarget "
"doesn't end with '/' : " +
reqtarget);
}

void syntaxLine(std::vector<Token>::iterator &it)
{
(void)token;
if (it->getType() != TokenType::WORD)
throw std::runtime_error(
"Syntax Error: Line doesn't start with TokenType WORD" +
it->getString());
Token &lineidentifier = *it;
size_t words = 0;

while (it->getType() == TokenType::WORD)
{
words++;
it++;
}

if (words <= 1)
throw std::runtime_error(
"Syntax Error: Line doesn't contain KEY:VALUE pair in block: " +
lineidentifier.getString());
else if (it->getType() != TokenType::SEMICOLON)
throw std::runtime_error(
"Syntax Error: Line doesn't end with ';' in block. near token: " +
lineidentifier.getString());
}

void syntaxLocationBlock(std::vector<Token> &tokens,
std::vector<Token>::iterator &it)
{
std::vector<Token>::iterator closing_token =
findBlockEnd(tokens, std::distance(tokens.begin(), it));

if (it->getString() != "location")
throw std::runtime_error(
"Syntax Error: locationBlock starts with unfamiliar identifier: " +
it->getString());
it++;
syntaxRequestTarget(it);
it += 2;

while (it != closing_token)
{

syntaxLine(it);
it++;
}
}

void syntaxServerBlock(std::vector<Token> &tokens,
std::vector<Token>::iterator &it)
{
std::vector<Token>::iterator closing_token;
if (it == tokens.begin())
closing_token = findBlockEnd(tokens, 0);
else
closing_token = findBlockEnd(tokens, std::distance(tokens.begin(), it));

if (it->getString() != "server")
throw std::runtime_error(
"Syntax Error: ServerBlock starts with unfamiliar identifier: " +
it->getString());
it += 2;

while (it != closing_token)
{
if (it->getString() == "location")
syntaxLocationBlock(tokens, it);
else
syntaxLine(it);
it++;
}
}

void ConfigParser::syntax(std::vector<Token> tokenlist)
{
std::vector<Token>::iterator it = tokenlist.begin();

while (it != tokenlist.end())
{
if (it->getString() == "server")
syntaxServerBlock(tokenlist, it);
else
throw std::runtime_error(
"Syntax Error: unknown block identifier: " + it->getString());
it++;
}
}
Loading

0 comments on commit 1e5d0eb

Please sign in to comment.