Browse Source

Remove ArrayList

task/remove_strings
Jessica James 3 years ago
parent
commit
3a11bda36d
  1. 52
      src/common/Command.cpp
  2. 217
      src/common/File.cpp
  3. 197
      src/common/GenericCommand.cpp
  4. 598
      src/common/HTTP_Server.cpp
  5. 93
      src/common/IRC_Client.cpp
  6. 270
      src/common/Plugin.cpp
  7. 257
      src/include/Jupiter/ArrayList.h
  8. 5
      src/include/Jupiter/Command.h
  9. 4
      src/include/Jupiter/File.h
  10. 17
      src/include/Jupiter/GenericCommand.h
  11. 20
      src/include/Jupiter/HTTP_Server.h
  12. 5
      src/include/Jupiter/Plugin.h

52
src/common/Command.cpp

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2013-2015 Jessica James. * Copyright (C) 2013-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -17,55 +17,43 @@
*/ */
#include <cstring> #include <cstring>
#include "ArrayList.h"
#include "Functions.h"
#include "Command.h" #include "Command.h"
#include "String.hpp" #include "String.hpp"
struct Jupiter::Command::Data struct Jupiter::Command::Data { // TODO: remove pimpl
{ std::vector<Jupiter::StringS> triggers;
public:
Jupiter::ArrayList<Jupiter::StringS> triggers;
}; };
Jupiter::Command::Command() Jupiter::Command::Command() {
{ m_data = new Data();
Jupiter::Command::data_ = new Jupiter::Command::Data();
} }
Jupiter::Command::Command(const Command &command) Jupiter::Command::Command(const Command &command) {
{ m_data = new Data();
Jupiter::Command::data_ = new Jupiter::Command::Data(); //for (size_t i = 0; i != m_data->triggers.size(); i++) // triggers.size() would always be 0? this code does nothing?
for (size_t i = 0; i != Jupiter::Command::data_->triggers.size(); i++) // m_data->triggers.add(new Jupiter::StringS(*command.m_data->triggers.get(i)));
Jupiter::Command::data_->triggers.add(new Jupiter::StringS(*command.data_->triggers.get(i)));
} }
Jupiter::Command::~Command() Jupiter::Command::~Command() {
{ delete m_data;
Jupiter::Command::data_->triggers.emptyAndDelete();
delete Jupiter::Command::data_;
} }
// Command Functions // Command Functions
void Jupiter::Command::addTrigger(const Jupiter::ReadableString &trigger) void Jupiter::Command::addTrigger(const Jupiter::ReadableString &trigger) {
{ m_data->triggers.emplace_back(trigger);
Jupiter::Command::data_->triggers.add(new Jupiter::StringS(trigger));
} }
const Jupiter::ReadableString &Jupiter::Command::getTrigger(size_t index) const const Jupiter::ReadableString &Jupiter::Command::getTrigger(size_t index) const {
{ return m_data->triggers[index];
return *Jupiter::Command::data_->triggers.get(index);
} }
size_t Jupiter::Command::getTriggerCount() const size_t Jupiter::Command::getTriggerCount() const {
{ return m_data->triggers.size();
return Jupiter::Command::data_->triggers.size();
} }
bool Jupiter::Command::matches(const Jupiter::ReadableString &trigger) const bool Jupiter::Command::matches(const Jupiter::ReadableString &in_trigger) const {
{ for (const auto& trigger : m_data->triggers)
for (size_t i = 0; i != Jupiter::Command::data_->triggers.size(); i++) if (trigger.equalsi(in_trigger)) return true;
if (Jupiter::Command::data_->triggers.get(i)->equalsi(trigger)) return true;
return false; return false;
} }

217
src/common/File.cpp

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2014-2015 Jessica James. * Copyright (C) 2014-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -20,19 +20,12 @@
#include <string> #include <string>
#include "File.h" #include "File.h"
#include "String.hpp" #include "String.hpp"
#include "ArrayList.h"
/**
* TODO:
* Consider replacing the ArrayList of Strings with a Rope (requires a Rope implementation).
*/
#if defined _WIN32 #if defined _WIN32
#define stat64 _stat64 #define stat64 _stat64
#endif #endif
int64_t getFileSize(const char *file) int64_t getFileSize(const char *file) {
{
struct stat64 data; struct stat64 data;
if (stat64(file, &data) == 0) return data.st_size; if (stat64(file, &data) == 0) return data.st_size;
return -1; return -1;
@ -46,10 +39,9 @@ const size_t defaultBufferSize = 8192;
#pragma warning(disable: 4251) #pragma warning(disable: 4251)
#endif #endif
struct JUPITER_API Jupiter::File::Data struct JUPITER_API Jupiter::File::Data { // TODO: remove pimpl
{
std::string fileName; std::string fileName;
Jupiter::ArrayList<Jupiter::StringS> lines; std::vector<Jupiter::StringS> lines;
Data(); Data();
Data(const Data &data); Data(const Data &data);
@ -61,125 +53,119 @@ struct JUPITER_API Jupiter::File::Data
#pragma warning(pop) #pragma warning(pop)
#endif #endif
Jupiter::File::Data::Data() Jupiter::File::Data::Data() {
{
} }
Jupiter::File::Data::Data(const Jupiter::File::Data &data) Jupiter::File::Data::Data(const Jupiter::File::Data &data) {
{ fileName = data.fileName;
Jupiter::File::Data::fileName = data.fileName;
for (size_t i = 0; i != Jupiter::File::Data::lines.size(); i++) // TODO: fix or remove this
Jupiter::File::Data::lines.add(new Jupiter::StringS(*data.lines.get(i))); //for (size_t i = 0; i != lines.size(); i++) // lines.size() will always be 0 here; this code does nothing?
// lines.emplace_back(data.lines[i]);
} }
Jupiter::File::Data::~Data() Jupiter::File::Data::~Data() {
{
Jupiter::File::Data::lines.emptyAndDelete();
} }
Jupiter::File::File() Jupiter::File::File() {
{ m_data = new Data();
Jupiter::File::data_ = new Jupiter::File::Data();
} }
Jupiter::File::File(File &&file) Jupiter::File::File(File &&file) {
{ m_data = file.m_data;
Jupiter::File::data_ = file.data_; file.m_data = new Data();
file.data_ = new Jupiter::File::Data();
} }
Jupiter::File::File(const File &file) Jupiter::File::File(const File &file) {
{ m_data = new Data(*file.m_data);
Jupiter::File::data_ = new Jupiter::File::Data(*file.data_);
} }
Jupiter::File::~File() Jupiter::File::~File() {
{ delete m_data; // TODO: remove raw delete
delete Jupiter::File::data_;
} }
size_t Jupiter::File::getLineCount() const size_t Jupiter::File::getLineCount() const {
{ return m_data->lines.size();
return Jupiter::File::data_->lines.size();
} }
const Jupiter::ReadableString &Jupiter::File::getLine(size_t line) const const Jupiter::ReadableString &Jupiter::File::getLine(size_t line) const {
{ return m_data->lines[line];
return *Jupiter::File::data_->lines.get(line);
} }
const std::string &Jupiter::File::getFileName() const const std::string &Jupiter::File::getFileName() const {
{ return m_data->fileName;
return Jupiter::File::data_->fileName;
} }
bool Jupiter::File::addData(const Jupiter::ReadableString &data) bool Jupiter::File::addData(const Jupiter::ReadableString &data) {
{ unsigned int word_count = data.wordCount(ENDL);
unsigned int wc = data.wordCount(ENDL); if (word_count == 0) return false;
if (wc == 0) return false;
for (unsigned int i = 0; i < wc; i++) Jupiter::File::data_->lines.add(new Jupiter::StringS(std::move(Jupiter::StringS::getWord(data, i, ENDL)))); for (unsigned int i = 0; i < word_count; i++) {
m_data->lines.emplace_back(std::move(Jupiter::StringS::getWord(data, i, ENDL)));
}
return true; return true;
} }
bool Jupiter::File::load(const char *file) bool Jupiter::File::load(const char *file) {
{
FILE *filePtr = fopen(file, "rb"); FILE *filePtr = fopen(file, "rb");
if (filePtr == nullptr) return false; if (filePtr == nullptr) {
if (Jupiter::File::data_->fileName.empty()) return false;
Jupiter::File::data_->fileName = file; }
bool r = Jupiter::File::load(filePtr);
if (m_data->fileName.empty()) {
m_data->fileName = file;
}
bool result = load(filePtr);
fclose(filePtr); fclose(filePtr);
return r; return result;
} }
bool Jupiter::File::load(const Jupiter::ReadableString &file) bool Jupiter::File::load(const Jupiter::ReadableString &file) {
{
std::string fileName = static_cast<std::string>(file); std::string fileName = static_cast<std::string>(file);
FILE *filePtr = fopen(fileName.c_str(), "rb"); FILE *filePtr = fopen(fileName.c_str(), "rb");
if (filePtr == nullptr) return false; if (filePtr == nullptr) {
if (Jupiter::File::data_->fileName.empty()) return false;
Jupiter::File::data_->fileName = fileName; }
bool r = Jupiter::File::load(filePtr);
if (m_data->fileName.empty()) {
m_data->fileName = fileName;
}
bool r = load(filePtr);
fclose(filePtr); fclose(filePtr);
return r; return r;
} }
bool Jupiter::File::load(FILE *file) bool Jupiter::File::load(FILE *file) {
{
Jupiter::String buffer(defaultBufferSize); Jupiter::String buffer(defaultBufferSize);
int chr; int chr;
while (true) while (true) {
{
chr = fgetc(file); chr = fgetc(file);
if (chr == EOF) if (chr == EOF) {
{ if (buffer.isNotEmpty()) {
if (buffer.isNotEmpty()) m_data->lines.emplace_back(buffer);
{
Jupiter::File::data_->lines.add(new Jupiter::StringS(buffer));
return true; return true;
} }
return Jupiter::File::data_->lines.size() != 0; return !m_data->lines.empty();
} }
if (static_cast<char>(chr) == '\r') // new line // TODO: refactor this nonsense
{ if (static_cast<char>(chr) == '\r') { // new line
new_line_r: new_line_r:
Jupiter::File::data_->lines.add(new Jupiter::StringS(buffer)); m_data->lines.emplace_back(buffer);
buffer.erase(); buffer.erase();
// check for optional trailing \n // check for optional trailing \n
chr = fgetc(file); chr = fgetc(file);
switch (chr) switch (chr) {
{
case EOF: case EOF:
return true; return true;
@ -196,19 +182,17 @@ bool Jupiter::File::load(FILE *file)
continue; continue;
} }
if (static_cast<char>(chr) == '\n') // new line if (static_cast<char>(chr) == '\n') { // new line
{
new_line_n: new_line_n:
Jupiter::File::data_->lines.add(new Jupiter::StringS(buffer)); m_data->lines.emplace_back(buffer);
buffer.erase(); buffer.erase();
// check for optional trailing \r // check for optional trailing \r
chr = fgetc(file); chr = fgetc(file);
switch (chr) switch (chr) {
{
case EOF: case EOF:
return true; return true;
@ -229,63 +213,60 @@ bool Jupiter::File::load(FILE *file)
} }
} }
void Jupiter::File::unload() void Jupiter::File::unload() {
{ m_data->fileName.clear();
Jupiter::File::data_->fileName.clear(); m_data->lines.clear();
Jupiter::File::data_->lines.emptyAndDelete();
} }
bool Jupiter::File::reload() bool Jupiter::File::reload() {
{ if (m_data->fileName.empty()) {
if (Jupiter::File::data_->fileName.empty())
return false; return false;
std::string fileName(std::move(Jupiter::File::data_->fileName)); }
Jupiter::File::unload();
return Jupiter::File::load(fileName.c_str()); std::string fileName(std::move(m_data->fileName));
unload();
return load(fileName.c_str());
} }
bool Jupiter::File::reload(const char *file) bool Jupiter::File::reload(const char *file) {
{ unload();
Jupiter::File::unload(); return load(file);
return Jupiter::File::load(file);
} }
bool Jupiter::File::reload(const Jupiter::ReadableString &file) bool Jupiter::File::reload(const Jupiter::ReadableString &file) {
{ unload();
Jupiter::File::unload(); return load(file);
return Jupiter::File::load(file);
} }
bool Jupiter::File::reload(FILE *file) bool Jupiter::File::reload(FILE *file) {
{ unload();
Jupiter::File::unload(); return load(file);
return Jupiter::File::load(file);
} }
bool Jupiter::File::sync() bool Jupiter::File::sync() {
{ if (m_data->fileName.empty()) {
if (Jupiter::File::data_->fileName.empty())
return false; return false;
return Jupiter::File::sync(Jupiter::File::data_->fileName.c_str()); }
return sync(m_data->fileName.c_str());
} }
bool Jupiter::File::sync(const char *file) bool Jupiter::File::sync(const char *file) {
{
FILE *filePtr = fopen(file, "wb"); FILE *filePtr = fopen(file, "wb");
if (filePtr == nullptr) return false; if (filePtr == nullptr) return false;
Jupiter::File::sync(filePtr); // Always returns true. sync(filePtr); // Always returns true.
fclose(filePtr); fclose(filePtr);
return true; return true;
} }
bool Jupiter::File::sync(const Jupiter::ReadableString &file) bool Jupiter::File::sync(const Jupiter::ReadableString &file) {
{ return sync(static_cast<std::string>(file).c_str());
return Jupiter::File::sync(static_cast<std::string>(file).c_str());
} }
bool Jupiter::File::sync(FILE *file) bool Jupiter::File::sync(FILE *file) {
{ for (const auto& line : m_data->lines) {
for (size_t i = 0; i != Jupiter::File::data_->lines.size(); i++) line.println(file);
Jupiter::File::data_->lines.get(i)->println(file); }
return true; return true;
} }

197
src/common/GenericCommand.cpp

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2015-2016 Jessica James. * Copyright (C) 2015-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -29,96 +29,91 @@ Jupiter::GenericCommandNamespace &Jupiter::g_generic_commands = o_generic_comman
/** GenericCommand */ /** GenericCommand */
Jupiter::GenericCommand::GenericCommand() Jupiter::GenericCommand::GenericCommand() {
{ if (&o_generic_commands != this) {
if (&o_generic_commands != this)
Jupiter::GenericCommand::setNamespace(o_generic_commands); Jupiter::GenericCommand::setNamespace(o_generic_commands);
}
} }
Jupiter::GenericCommand::~GenericCommand() Jupiter::GenericCommand::~GenericCommand() {
{
// Inform the parent // Inform the parent
if (GenericCommand::m_parent != nullptr) if (GenericCommand::m_parent != nullptr) {
GenericCommand::m_parent->removeCommand(*this); GenericCommand::m_parent->removeCommand(*this);
}
// Notify plugins // Notify plugins
for (size_t index = 0; index != Jupiter::plugins->size(); ++index) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(index)->OnGenericCommandRemove(*this); plugin->OnGenericCommandRemove(*this);
}
} }
bool Jupiter::GenericCommand::isNamespace() const bool Jupiter::GenericCommand::isNamespace() const {
{
return false; return false;
} }
void Jupiter::GenericCommand::setNamespace(const Jupiter::ReadableString &in_namespace) void Jupiter::GenericCommand::setNamespace(const Jupiter::ReadableString &in_namespace) {
{ if (in_namespace.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) {
if (in_namespace.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0)
return; // We're already here return; // We're already here
}
if (Jupiter::GenericCommand::m_parent == nullptr) if (Jupiter::GenericCommand::m_parent == nullptr) {
return; // We have no parent to start from return; // We have no parent to start from
}
Jupiter::GenericCommand *command = Jupiter::GenericCommand::m_parent->getCommand(in_namespace); Jupiter::GenericCommand *command = Jupiter::GenericCommand::m_parent->getCommand(in_namespace);
if (command != nullptr && command->isNamespace()) if (command != nullptr && command->isNamespace())
Jupiter::GenericCommand::setNamespace(*reinterpret_cast<Jupiter::GenericCommandNamespace *>(command)); Jupiter::GenericCommand::setNamespace(*static_cast<Jupiter::GenericCommandNamespace *>(command));
} }
void Jupiter::GenericCommand::setNamespace(Jupiter::GenericCommandNamespace &in_namespace) void Jupiter::GenericCommand::setNamespace(Jupiter::GenericCommandNamespace &in_namespace) {
{ if (Jupiter::GenericCommand::m_parent != nullptr) { // Remove from previous parent
if (Jupiter::GenericCommand::m_parent != nullptr) // Remove from previous parent
Jupiter::GenericCommand::m_parent->removeCommand(*this); Jupiter::GenericCommand::m_parent->removeCommand(*this);
}
// Add to new parent // Add to new parent
Jupiter::GenericCommand::m_parent = &in_namespace; Jupiter::GenericCommand::m_parent = &in_namespace;
in_namespace.addCommand(*this); in_namespace.addCommand(*this);
} }
Jupiter::GenericCommandNamespace *Jupiter::GenericCommand::getNamespace() const Jupiter::GenericCommandNamespace *Jupiter::GenericCommand::getNamespace() const {
{ return m_parent;
return Jupiter::GenericCommand::m_parent;
} }
/** GenericCommand::ResponseLine */ /** GenericCommand::ResponseLine */
Jupiter::GenericCommand::ResponseLine::ResponseLine(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_) Jupiter::GenericCommand::ResponseLine::ResponseLine(const Jupiter::ReadableString &in_response, GenericCommand::DisplayType in_type)
{ : response{ in_response },
GenericCommand::ResponseLine::response = response_; type{ in_type } {
GenericCommand::ResponseLine::type = type_;
} }
Jupiter::GenericCommand::ResponseLine *Jupiter::GenericCommand::ResponseLine::set(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_) Jupiter::GenericCommand::ResponseLine* Jupiter::GenericCommand::ResponseLine::set(const Jupiter::ReadableString &in_response, GenericCommand::DisplayType in_type) {
{ response = in_response;
GenericCommand::ResponseLine::response = response_; type = in_type;
GenericCommand::ResponseLine::type = type_;
return this; return this;
} }
/** GenericCommandNamespace */ /** GenericCommandNamespace */
Jupiter::GenericCommandNamespace::~GenericCommandNamespace() Jupiter::GenericCommandNamespace::~GenericCommandNamespace() {
{
// Murder the children
Jupiter::GenericCommandNamespace::m_commands.emptyAndDelete();
} }
Jupiter::GenericCommand::ResponseLine *Jupiter::GenericCommandNamespace::trigger(const Jupiter::ReadableString &in_input) Jupiter::GenericCommand::ResponseLine* Jupiter::GenericCommandNamespace::trigger(const Jupiter::ReadableString &in_input) {
{ GenericCommand* command;
GenericCommand *command;
Jupiter::ReferenceString input(in_input); Jupiter::ReferenceString input(in_input);
if (input.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) // No parameters; list commands if (input.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) { // No parameters; list commands
return new Jupiter::GenericCommand::ResponseLine(Jupiter::GenericCommandNamespace::m_help, Jupiter::GenericCommand::DisplayType::PrivateSuccess); return new Jupiter::GenericCommand::ResponseLine(m_help,Jupiter::GenericCommand::DisplayType::PrivateSuccess);
}
command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS)); command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS));
if (command != nullptr) if (command != nullptr) {
return command->trigger(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS)); return command->trigger(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS));
}
return new Jupiter::GenericCommand::ResponseLine(Jupiter::ReferenceString::empty, Jupiter::GenericCommand::DisplayType::PrivateError); return new Jupiter::GenericCommand::ResponseLine(Jupiter::ReferenceString::empty, Jupiter::GenericCommand::DisplayType::PrivateError);
} }
const Jupiter::ReadableString &Jupiter::GenericCommandNamespace::getHelp(const Jupiter::ReadableString &parameters) const Jupiter::ReadableString &Jupiter::GenericCommandNamespace::getHelp(const Jupiter::ReadableString &parameters) {
{
static Jupiter::ReferenceString not_found = "Error: Command not found"_jrs; static Jupiter::ReferenceString not_found = "Error: Command not found"_jrs;
if (parameters.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) // No parameters; list commands if (parameters.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) // No parameters; list commands
@ -134,136 +129,110 @@ const Jupiter::ReadableString &Jupiter::GenericCommandNamespace::getHelp(const J
// Search for command // Search for command
command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS)); command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS));
if (command != nullptr) if (command != nullptr) {
return command->getHelp(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS)); return command->getHelp(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS));
}
// Command not found // Command not found
return not_found; return not_found;
} }
bool Jupiter::GenericCommandNamespace::isNamespace() const bool Jupiter::GenericCommandNamespace::isNamespace() const {
{
return true; return true;
} }
bool Jupiter::GenericCommandNamespace::isUsing() const bool Jupiter::GenericCommandNamespace::isUsing() const {
{
return m_using; return m_using;
} }
void Jupiter::GenericCommandNamespace::setUsing(bool in_value) void Jupiter::GenericCommandNamespace::setUsing(bool in_value) {
{
m_using = in_value; m_using = in_value;
if (Jupiter::GenericCommand::m_parent != nullptr) if (Jupiter::GenericCommand::m_parent != nullptr)
Jupiter::GenericCommand::m_parent->updateHelp(); Jupiter::GenericCommand::m_parent->updateHelp();
} }
Jupiter::ArrayList<Jupiter::GenericCommand> Jupiter::GenericCommandNamespace::getCommands() const std::vector<Jupiter::GenericCommand*> Jupiter::GenericCommandNamespace::getCommands() const {
{ std::vector<Jupiter::GenericCommand*> result(m_commands.size());
Jupiter::ArrayList<Jupiter::GenericCommand> result(Jupiter::GenericCommandNamespace::m_commands.size());
Jupiter::GenericCommand *command;
size_t tmp_index;
for (size_t command_index = 0; command_index != Jupiter::GenericCommandNamespace::m_commands.size(); ++command_index) for (const auto& command : m_commands) {
{ result.push_back(command);
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index);
result.add(command);
if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing()) if (command->isNamespace() && static_cast<GenericCommandNamespace*>(command)->isUsing()) {
{
// Add commands from namespace // Add commands from namespace
Jupiter::ArrayList<Jupiter::GenericCommand> tmp = reinterpret_cast<GenericCommandNamespace *>(command)->getCommands(); auto namespace_commands = static_cast<GenericCommandNamespace*>(command)->getCommands();
for (const auto& namespace_command : namespace_commands)
for (tmp_index = 0; tmp_index != tmp.size(); ++tmp_index) result.push_back(namespace_command);
result.add(tmp.get(tmp_index));
} }
} }
return result; return result;
} }
Jupiter::GenericCommand *Jupiter::GenericCommandNamespace::getCommand(const Jupiter::ReadableString &in_command) const Jupiter::GenericCommand *Jupiter::GenericCommandNamespace::getCommand(const Jupiter::ReadableString &in_command) const {
{
Jupiter::GenericCommand *command;
size_t command_index, namespaces = 0;
/** This is broken into 2 loops in order to insure that exact matches are ALWAYS prioritized over inexact matches */ /** This is broken into 2 loops in order to insure that exact matches are ALWAYS prioritized over inexact matches */
// Search commands // Search commands
for (command_index = 0; command_index != Jupiter::GenericCommandNamespace::m_commands.size(); ++command_index) for (const auto& command : m_commands) {
{ if (command->matches(in_command)) {// Command found
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index);
if (command->matches(in_command)) // Command found
return command; return command;
else if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing()) // Search namespace for matches }
++namespaces;
} }
// None found; check namespaces // None found; check namespaces
for (command_index = 0; namespaces != 0; ++command_index) for (const auto& command : m_commands) {
{ if (command->isNamespace() && static_cast<GenericCommandNamespace*>(command)->isUsing()) {
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index); auto result_command = static_cast<GenericCommandNamespace*>(command)->getCommand(in_command);
if (result_command != nullptr) { // match found
if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing()) return result_command;
{ }
command = reinterpret_cast<GenericCommandNamespace *>(command)->getCommand(in_command);
if (command != nullptr) // match found
return command;
--namespaces;
} }
} }
return nullptr; return nullptr;
} }
void Jupiter::GenericCommandNamespace::addCommand(Jupiter::GenericCommand &in_command) void Jupiter::GenericCommandNamespace::addCommand(Jupiter::GenericCommand &in_command) {
{ if (in_command.getNamespace() != this) {
if (in_command.getNamespace() != this)
in_command.setNamespace(*this); in_command.setNamespace(*this);
else }
{ else {
Jupiter::GenericCommandNamespace::m_commands.add(&in_command); m_commands.push_back(&in_command);
Jupiter::GenericCommandNamespace::m_should_update_help = true; m_should_update_help = true;
} }
} }
void Jupiter::GenericCommandNamespace::removeCommand(Jupiter::GenericCommand &in_command) void Jupiter::GenericCommandNamespace::removeCommand(Jupiter::GenericCommand &in_command) {
{ for (auto itr = m_commands.begin(); itr != m_commands.end(); ++itr) {
for (size_t index = 0; index != Jupiter::GenericCommandNamespace::m_commands.size(); ++index) if (*itr == &in_command) {
if (Jupiter::GenericCommandNamespace::m_commands.get(index) == &in_command) m_commands.erase(itr);
{ m_should_update_help = true;
Jupiter::GenericCommandNamespace::m_commands.remove(index);
Jupiter::GenericCommandNamespace::m_should_update_help = true;
return; return;
} }
}
} }
void Jupiter::GenericCommandNamespace::removeCommand(const Jupiter::ReadableString &in_command) void Jupiter::GenericCommandNamespace::removeCommand(const Jupiter::ReadableString &in_command)
{ {
for (size_t index = 0; index != Jupiter::GenericCommandNamespace::m_commands.size(); ++index) for (auto itr = m_commands.begin(); itr != m_commands.end(); ++itr) {
if (Jupiter::GenericCommandNamespace::m_commands.get(index)->matches(in_command)) if ((*itr)->matches(in_command)) {
{ m_commands.erase(itr);
Jupiter::GenericCommandNamespace::m_commands.remove(index); m_should_update_help = true;
Jupiter::GenericCommandNamespace::m_should_update_help = true;
return; return;
} }
}
} }
void Jupiter::GenericCommandNamespace::updateHelp() void Jupiter::GenericCommandNamespace::updateHelp() {
{ m_should_update_help = false;
Jupiter::GenericCommandNamespace::m_should_update_help = false;
Jupiter::ArrayList<Jupiter::GenericCommand> commands = Jupiter::GenericCommandNamespace::getCommands(); std::vector<Jupiter::GenericCommand*> commands = getCommands();
Jupiter::StringL tmp_help(commands.size() * 8); Jupiter::StringL tmp_help(commands.size() * 8);
for (size_t index = 0; index != commands.size(); ++index) for (const auto& command : commands) {
{ tmp_help += command->getTrigger();
tmp_help += commands.get(index)->getTrigger();
tmp_help += ' '; tmp_help += ' ';
} }
Jupiter::GenericCommandNamespace::m_help = tmp_help; m_help = tmp_help;
} }

598
src/common/HTTP_Server.cpp

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2015-2016 Jessica James. * Copyright (C) 2015-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -21,7 +21,6 @@
#include "String.hpp" #include "String.hpp"
#include "Reference_String.h" #include "Reference_String.h"
#include "TCPSocket.h" #include "TCPSocket.h"
#include "ArrayList.h"
#include "HTTP.h" #include "HTTP.h"
#include "HTTP_Server.h" #include "HTTP_Server.h"
@ -50,131 +49,108 @@ enum HTTPVersion
// HTTP::Server::Content // HTTP::Server::Content
Jupiter::HTTP::Server::Content::Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function) : name(in_name) Jupiter::HTTP::Server::Content::Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function) : name(in_name) {
{
Jupiter::HTTP::Server::Content::function = in_function; Jupiter::HTTP::Server::Content::function = in_function;
Jupiter::HTTP::Server::Content::name_checksum = Jupiter::HTTP::Server::Content::name.calcChecksum(); // switch to calcChecksumi to make case-insensitive Jupiter::HTTP::Server::Content::name_checksum = Jupiter::HTTP::Server::Content::name.calcChecksum(); // switch to calcChecksumi to make case-insensitive
} }
Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(const Jupiter::ReadableString &query_string) Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(const Jupiter::ReadableString &query_string) {
{
return Jupiter::HTTP::Server::Content::function(query_string); return Jupiter::HTTP::Server::Content::function(query_string);
} }
// HTTP::Server::Directory // HTTP::Server::Directory
Jupiter::HTTP::Server::Directory::Directory(const Jupiter::ReadableString &in_name) : name(in_name) Jupiter::HTTP::Server::Directory::Directory(const Jupiter::ReadableString &in_name) : name(in_name) {
{
name_checksum = Jupiter::HTTP::Server::Directory::name.calcChecksum(); name_checksum = Jupiter::HTTP::Server::Directory::name.calcChecksum();
} }
Jupiter::HTTP::Server::Directory::~Directory() Jupiter::HTTP::Server::Directory::~Directory() {
{
Jupiter::HTTP::Server::Directory::directories.emptyAndDelete();
Jupiter::HTTP::Server::Directory::content.emptyAndDelete();
} }
// host/dir/content // host/dir/content
// .hook("dir/subdir/", content) // .hook("dir/subdir/", content)
void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_name, Content *in_content) void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_name, std::unique_ptr<Content> in_content) {
{
Jupiter::ReferenceString in_name_ref = in_name; Jupiter::ReferenceString in_name_ref = in_name;
in_name_ref.shiftRight(in_name_ref.span('/')); in_name_ref.shiftRight(in_name_ref.span('/'));
if (in_name_ref.isEmpty()) // Hook content if (in_name_ref.isEmpty()) { // Hook content
Jupiter::HTTP::Server::Directory::content.add(in_content); content.push_back(std::move(in_content));
else return;
{ }
size_t index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name;
if (index == Jupiter::INVALID_INDEX)
dir_name = in_name_ref;
else
dir_name = in_name_ref.substring(size_t{ 0 }, index);
in_name_ref.shiftRight(dir_name.size());
Jupiter::HTTP::Server::Directory *directory;
unsigned int dir_name_checksum = dir_name.calcChecksum();
index = Jupiter::HTTP::Server::Directory::directories.size();
while (index != 0)
{
directory = Jupiter::HTTP::Server::Directory::directories.get(--index);
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name))
{
directory->hook(in_name_ref, in_content);
return;
}
}
// create directories size_t index = in_name_ref.find('/');
directory = new Jupiter::HTTP::Server::Directory(dir_name); Jupiter::ReferenceString dir_name;
Jupiter::HTTP::Server::Directory::directories.add(directory); if (index == Jupiter::INVALID_INDEX) {
dir_name = in_name_ref;
}
else {
dir_name = in_name_ref.substring(size_t{ 0 }, index);
}
directory_add_loop: in_name_ref.shiftRight(dir_name.size());
in_name_ref.shiftRight(in_name_ref.span('/')); unsigned int dir_name_checksum = dir_name.calcChecksum();
if (in_name_ref.isNotEmpty()) index = directories.size();
{ for (auto& directory : directories) {
// add directory if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) {
index = in_name_ref.find('/'); directory->hook(in_name_ref, std::move(in_content));
if (index != Jupiter::INVALID_INDEX) return;
{
directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref.substring(size_t{ 0 }, index)));
directory = directory->directories.get(directories.size() - 1);
in_name_ref.shiftRight(index + 1);
goto directory_add_loop;
}
directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref));
directory = directory->directories.get(directories.size() - 1);
} }
}
// add content // create directories
directory->content.add(in_content); Directory* directory = directories.emplace_back(std::make_unique<Directory>(dir_name)).get();
directory_add_loop: // TODO: for the love of god, why why why
in_name_ref.shiftRight(in_name_ref.span('/'));
if (in_name_ref.isNotEmpty()) {
// add directory
index = in_name_ref.find('/');
if (index != Jupiter::INVALID_INDEX) {
directory->directories.push_back(std::make_unique<Directory>(in_name_ref.substring(size_t{ 0 }, index)));
directory = directory->directories[directories.size() - 1].get();
in_name_ref.shiftRight(index + 1);
goto directory_add_loop;
}
directory->directories.push_back(std::make_unique<Directory>(in_name_ref));
directory = directory->directories[directories.size() - 1].get();
} }
// add content
directory->content.push_back(std::move(in_content));
} }
bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &content_name) bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &content_name) {
{
size_t index;
Jupiter::ReferenceString in_name_ref = path; Jupiter::ReferenceString in_name_ref = path;
in_name_ref.shiftRight(in_name_ref.span('/')); in_name_ref.shiftRight(in_name_ref.span('/'));
unsigned int checksum; unsigned int checksum;
if (in_name_ref.isEmpty()) // Remove content if (in_name_ref.isEmpty()) { // Remove content
{
Jupiter::HTTP::Server::Content *content_node;
checksum = content_name.calcChecksum(); checksum = content_name.calcChecksum();
index = Jupiter::HTTP::Server::Directory::content.size(); for (auto itr = content.begin(); itr != content.end(); ++itr) {
while (index != 0) auto& content_node = *itr;
{ if (content_node->name_checksum == checksum && content_node->name.equals(content_name)) {
content_node = Jupiter::HTTP::Server::Directory::content.get(--index); content.erase(itr);
if (content_node->name_checksum == checksum && content_node->name.equals(content_name))
{
delete Jupiter::HTTP::Server::Directory::content.remove(index);
return true; return true;
} }
} }
return false; return false;
} }
else // Call remove() on next directory in path
{ // Call remove() on next directory in path
index = in_name_ref.find('/'); size_t index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name; Jupiter::ReferenceString dir_name;
if (index == Jupiter::INVALID_INDEX) if (index == Jupiter::INVALID_INDEX)
dir_name = in_name_ref; dir_name = in_name_ref;
else else
dir_name = in_name_ref.substring(size_t{ 0 }, index); dir_name = in_name_ref.substring(size_t{ 0 }, index);
in_name_ref.shiftRight(dir_name.size()); in_name_ref.shiftRight(dir_name.size());
Jupiter::HTTP::Server::Directory *directory; checksum = dir_name.calcChecksum();
checksum = dir_name.calcChecksum(); for (auto& directory : directories) {
index = Jupiter::HTTP::Server::Directory::directories.size(); if (directory->name_checksum == checksum && directory->name.equals(dir_name)) {
while (index != 0) return directory->remove(in_name_ref, content_name);
{
directory = Jupiter::HTTP::Server::Directory::directories.get(--index);
if (directory->name_checksum == checksum && directory->name.equals(dir_name))
return directory->remove(in_name_ref, content_name);
} }
} }
return false; return false;
@ -182,7 +158,7 @@ bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &pat
bool Jupiter::HTTP::Server::Directory::has(const Jupiter::ReadableString &in_name) bool Jupiter::HTTP::Server::Directory::has(const Jupiter::ReadableString &in_name)
{ {
return this->find(in_name) != nullptr; return find(in_name) != nullptr;
} }
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jupiter::ReadableString &in_name) Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jupiter::ReadableString &in_name)
@ -191,96 +167,86 @@ Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jup
in_name_ref.shiftRight(in_name_ref.span("/"_jrs)); in_name_ref.shiftRight(in_name_ref.span("/"_jrs));
size_t index = in_name_ref.find('/'); size_t index = in_name_ref.find('/');
if (index == Jupiter::INVALID_INDEX) // Search content if (index == Jupiter::INVALID_INDEX) { // Search content
{
unsigned int content_name_checksum = in_name_ref.calcChecksum(); unsigned int content_name_checksum = in_name_ref.calcChecksum();
index = Jupiter::HTTP::Server::Directory::content.size(); index = content.size();
Jupiter::HTTP::Server::Content *content_itr; for (auto& content_item : content) {
while (index != 0) if (content_item->name_checksum == content_name_checksum && content_item->name.equals(in_name_ref)) {
{ return content_item.get();
content_itr = Jupiter::HTTP::Server::Directory::content.get(--index); }
if (content_itr->name_checksum == content_name_checksum && content_itr->name.equals(in_name_ref))
return content_itr;
} }
return nullptr; // No such content return nullptr; // No such content
} }
Jupiter::ReferenceString dir_name(in_name_ref.ptr(), index); Jupiter::ReferenceString dir_name(in_name_ref.ptr(), index);
in_name_ref.shiftRight(dir_name.size() + 1); in_name_ref.shiftRight(dir_name.size() + 1);
Jupiter::HTTP::Server::Directory *directory;
unsigned int dir_name_checksum = dir_name.calcChecksum(); unsigned int dir_name_checksum = dir_name.calcChecksum();
index = Jupiter::HTTP::Server::Directory::directories.size();
while (index != 0) for (auto& directory : directories) {
{ if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) {
directory = Jupiter::HTTP::Server::Directory::directories.get(--index);
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name))
return directory->find(in_name_ref); return directory->find(in_name_ref);
}
} }
return nullptr; // No such directory return nullptr; // No such directory
} }
Jupiter::ReadableString *Jupiter::HTTP::Server::Directory::execute(const Jupiter::ReadableString &in_name, const Jupiter::ReadableString &query_string) Jupiter::ReadableString* Jupiter::HTTP::Server::Directory::execute(const Jupiter::ReadableString &in_name, const Jupiter::ReadableString &query_string) {
{ Jupiter::HTTP::Server::Content *content_ptr = find(in_name);
Jupiter::HTTP::Server::Content *content_ptr = Jupiter::HTTP::Server::Directory::find(in_name);
if (content_ptr == nullptr) if (content_ptr == nullptr)
return nullptr; return nullptr;
return content_ptr->execute(query_string); return content_ptr->execute(query_string);
} }
// HTTP::Server::Host // HTTP::Server::Host
Jupiter::HTTP::Server::Host::Host(const Jupiter::ReadableString &in_name) : Directory(in_name) Jupiter::HTTP::Server::Host::Host(const Jupiter::ReadableString &in_name) : Directory(in_name) {
{
name_checksum = Jupiter::HTTP::Server::Host::name.calcChecksumi(); name_checksum = Jupiter::HTTP::Server::Host::name.calcChecksumi();
} }
// HTTPSession struct // HTTPSession struct
struct HTTPSession struct HTTPSession {
{
Jupiter::Socket sock; Jupiter::Socket sock;
Jupiter::String request; Jupiter::String request;
bool keep_alive = false; bool keep_alive = false;
Jupiter::HTTP::Server::Host *host = nullptr; Jupiter::HTTP::Server::Host* host = nullptr;
HTTPVersion version = HTTPVersion::HTTP_1_0; HTTPVersion version = HTTPVersion::HTTP_1_0;
std::chrono::steady_clock::time_point last_active = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point last_active = std::chrono::steady_clock::now();
HTTPSession(Jupiter::Socket &&in_sock); HTTPSession(Jupiter::Socket&& in_sock);
~HTTPSession(); ~HTTPSession();
}; };
HTTPSession::HTTPSession(Jupiter::Socket &&in_sock) : sock(std::move(in_sock)) HTTPSession::HTTPSession(Jupiter::Socket&& in_sock)
{ : sock(std::move(in_sock)) {
} }
HTTPSession::~HTTPSession() HTTPSession::~HTTPSession() {
{
} }
// Server::Data struct // Server::Data struct
struct Jupiter::HTTP::Server::Data struct Jupiter::HTTP::Server::Data {
{
/** Data */ /** Data */
Jupiter::ArrayList<Jupiter::HTTP::Server::Host> hosts; std::vector<std::unique_ptr<Jupiter::HTTP::Server::Host>> m_hosts;
Jupiter::ArrayList<Socket> ports; std::vector<std::unique_ptr<Socket>> m_ports;
Jupiter::ArrayList<HTTPSession> sessions; std::vector<std::unique_ptr<HTTPSession>> m_sessions;
std::chrono::milliseconds session_timeout = std::chrono::milliseconds(2000); // TODO: Config variable std::chrono::milliseconds session_timeout = std::chrono::milliseconds(2000); // TODO: Config variable
std::chrono::milliseconds keep_alive_session_timeout = std::chrono::milliseconds(5000); // TODO: Config variable std::chrono::milliseconds keep_alive_session_timeout = std::chrono::milliseconds(5000); // TODO: Config variable
size_t max_request_size = 8192; // TODO: Config variable size_t max_request_size = 8192; // TODO: Config variable
bool permit_keept_alive = true; // TODO: Config variable bool permit_keept_alive = true; // TODO: Config variable
/** Foward functions */ /** Foward functions */
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, Content *in_content); void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
bool remove(const Jupiter::ReadableString &hostname); bool remove(const Jupiter::ReadableString &hostname);
//bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path); //bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path);
bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name); bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
bool has(const Jupiter::ReadableString &hostname); bool has(const Jupiter::ReadableString &hostname);
bool has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name); bool has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name);
Jupiter::HTTP::Server::Host *find_host(const Jupiter::ReadableString &name); Jupiter::HTTP::Server::Host *find_host(const Jupiter::ReadableString &name);
Content *find(const Jupiter::ReadableString &name); Content* find(const Jupiter::ReadableString &name);
Content *find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name); Content* find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string); Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string); Jupiter::ReadableString *execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
@ -297,54 +263,43 @@ struct Jupiter::HTTP::Server::Data
// Data constructor // Data constructor
Jupiter::HTTP::Server::Data::Data() Jupiter::HTTP::Server::Data::Data() {
{
// hosts[0] is always the "global" namespace. // hosts[0] is always the "global" namespace.
Jupiter::HTTP::Server::Data::hosts.add(new Jupiter::HTTP::Server::Host(Jupiter::HTTP::Server::global_namespace)); m_hosts.push_back(std::make_unique<Host>(Jupiter::HTTP::Server::global_namespace));
} }
// Data destructor // Data destructor
Jupiter::HTTP::Server::Data::~Data() Jupiter::HTTP::Server::Data::~Data() {
{
Jupiter::HTTP::Server::Data::hosts.emptyAndDelete();
Jupiter::HTTP::Server::Data::sessions.emptyAndDelete();
Jupiter::HTTP::Server::Data::ports.emptyAndDelete();
} }
// Data functions // Data functions
void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &in_path, Content *in_content) void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &in_path, std::unique_ptr<Content> in_content) {
{
Jupiter::ReferenceString path = in_path; Jupiter::ReferenceString path = in_path;
Jupiter::ReferenceString dir_name; Jupiter::ReferenceString dir_name;
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname); Jupiter::HTTP::Server::Host* host = find_host(hostname);
if (host == nullptr) if (host == nullptr) {
{ //host = new Jupiter::HTTP::Server::Host(hostname);
host = new Jupiter::HTTP::Server::Host(hostname); host = m_hosts.emplace_back(std::make_unique<Host>(hostname)).get();
Jupiter::HTTP::Server::Data::hosts.add(host);
// OPTIMIZE: create directory tree and return. // OPTIMIZE: create directory tree and return.
} }
path.shiftRight(path.span('/')); path.shiftRight(path.span('/'));
if (path.isEmpty()) if (path.isEmpty()) {
host->content.add(in_content); host->content.push_back(std::move(in_content));
else }
host->hook(path, in_content); else {
host->hook(path, std::move(in_content));
}
} }
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname) bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname) {
{
unsigned int name_checksum = hostname.calcChecksumi(); unsigned int name_checksum = hostname.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); for (auto host_itr = m_hosts.begin(); host_itr != m_hosts.end(); ++host_itr) {
Jupiter::HTTP::Server::Host *host; if (name_checksum == (*host_itr)->name_checksum && (*host_itr)->name.equalsi(hostname)) {
while (index != 0) m_hosts.erase(host_itr);
{
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(hostname))
{
delete Jupiter::HTTP::Server::Data::hosts.remove(index);
return true; return true;
} }
} }
@ -352,46 +307,34 @@ bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname
} }
// name: path/to/resource OR path/ // name: path/to/resource OR path/
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) {
{ Jupiter::HTTP::Server::Host *host = find_host(hostname);
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname); if (host == nullptr) {
if (host == nullptr)
return false; return false;
}
return host->remove(path, name); return host->remove(path, name);
} }
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname) bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname) {
{
unsigned int name_checksum = hostname.calcChecksumi(); unsigned int name_checksum = hostname.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); for (const auto& host : m_hosts) {
Jupiter::HTTP::Server::Host *host; if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) {
while (index != 0)
{
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(hostname))
return true; return true;
}
} }
return false; return false;
} }
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) {
{
unsigned int name_checksum = hostname.calcChecksumi(); unsigned int name_checksum = hostname.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); for (const auto& host : m_hosts) {
Jupiter::HTTP::Server::Host *host; if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) {
while (index != 0)
{
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(hostname))
{
name_checksum = name.calcChecksum(); // switch to equalsi to make case-insensitive name_checksum = name.calcChecksum(); // switch to equalsi to make case-insensitive
index = host->content.size(); for (const auto& content : host->content) {
Jupiter::HTTP::Server::Content *content; if (name_checksum == content->name_checksum && content->name.equals(name)) { // switch to equalsi to make case-insensitive
while (index != 0)
{
content = host->content.get(--index);
if (name_checksum == content->name_checksum && content->name.equals(name)) // switch to equalsi to make case-insensitive
return true; return true;
}
} }
return false; return false;
} }
@ -399,60 +342,53 @@ bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, c
return false; return false;
} }
Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupiter::ReadableString &name) Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupiter::ReadableString &name) {
{
unsigned int name_checksum = name.calcChecksumi(); unsigned int name_checksum = name.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); for (const auto& host : m_hosts) {
Jupiter::HTTP::Server::Host *host; if (name_checksum == host->name_checksum && host->name.equalsi(name)) {
while (index != 0) return host.get();
{ }
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(name))
return host;
} }
return nullptr; return nullptr;
} }
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &name) Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &name) {
{ return m_hosts[0]->find(name);
return Jupiter::HTTP::Server::Data::hosts.get(0)->find(name);
} }
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) {
{ Jupiter::HTTP::Server::Host *host = find_host(hostname);
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname);
if (host == nullptr) if (host == nullptr)
return nullptr; return nullptr;
return host->find(name); return host->find(name);
} }
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
{ Jupiter::HTTP::Server::Content *content = find(name);
Jupiter::HTTP::Server::Content *content = Jupiter::HTTP::Server::Data::find(name);
if (content == nullptr) if (content == nullptr)
return nullptr; return nullptr;
return content->execute(query_string); return content->execute(query_string);
} }
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
{ Jupiter::HTTP::Server::Content *content = find(hostname, name);
Jupiter::HTTP::Server::Content *content = Jupiter::HTTP::Server::Data::find(hostname, name);
if (content == nullptr) if (content == nullptr)
return nullptr; return nullptr;
return content->execute(query_string); return content->execute(query_string);
} }
char *html_time() char* html_time() {
{
time_t rawtime = time(0); time_t rawtime = time(0);
char *rtime = new char[64]; char *rtime = new char[64];
strftime(rtime, 64, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&rawtime)); strftime(rtime, 64, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&rawtime));
return rtime; return rtime;
} }
int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
{
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> lines = Jupiter::ReferenceString::tokenize(session.request, STRING_LITERAL_AS_REFERENCE(ENDL)); Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> lines = Jupiter::ReferenceString::tokenize(session.request, STRING_LITERAL_AS_REFERENCE(ENDL));
HTTPCommand command = HTTPCommand::NONE_SPECIFIED; HTTPCommand command = HTTPCommand::NONE_SPECIFIED;
Content *content = nullptr; Content *content = nullptr;
@ -589,7 +525,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
session.request.shiftRight(get_line_offset(index)); session.request.shiftRight(get_line_offset(index));
if (session.request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // there's another full request already received if (session.request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // there's another full request already received
return Jupiter::HTTP::Server::Data::process_request(session); return process_request(session);
break; break;
} }
@ -600,12 +536,12 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
{ {
first_token.truncate(1); // trim trailing ':' first_token.truncate(1); // trim trailing ':'
if (first_token.equalsi("HOST"_jrs)) if (first_token.equalsi("HOST"_jrs))
session.host = Jupiter::HTTP::Server::Data::find_host(line.getWord(1, " ")); session.host = find_host(line.getWord(1, " "));
else if (first_token.equalsi("CONNECTION"_jrs)) else if (first_token.equalsi("CONNECTION"_jrs))
{ {
Jupiter::ReferenceString connection_type = line.getWord(1, " "); Jupiter::ReferenceString connection_type = line.getWord(1, " ");
if (connection_type.equalsi("keep-alive"_jrs)) if (connection_type.equalsi("keep-alive"_jrs))
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; session.keep_alive = permit_keept_alive;
} }
} }
else // command else // command
@ -619,7 +555,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
if (span == Jupiter::INVALID_INDEX) if (span == Jupiter::INVALID_INDEX)
{ {
if (session.host == nullptr) if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string); content = find(query_string);
else else
content = session.host->find(query_string); content = session.host->find(query_string);
query_string.erase(); query_string.erase();
@ -627,7 +563,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else else
{ {
if (session.host == nullptr) if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span)); content = find(query_string.substring(size_t{ 0 }, span));
else else
content = session.host->find(query_string.substring(size_t{ 0 }, span)); content = session.host->find(query_string.substring(size_t{ 0 }, span));
query_string.shiftRight(span + 1); query_string.shiftRight(span + 1);
@ -640,7 +576,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else if (protocol_str.equalsi("http/1.1"_jrs)) else if (protocol_str.equalsi("http/1.1"_jrs))
{ {
session.version = HTTPVersion::HTTP_1_1; session.version = HTTPVersion::HTTP_1_1;
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; session.keep_alive = permit_keept_alive;
} }
} }
else if (first_token.equals("HEAD"_jrs)) else if (first_token.equals("HEAD"_jrs))
@ -652,7 +588,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
if (span == Jupiter::INVALID_INDEX) if (span == Jupiter::INVALID_INDEX)
{ {
if (session.host == nullptr) if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string); content = find(query_string);
else else
content = session.host->find(query_string); content = session.host->find(query_string);
query_string.erase(); query_string.erase();
@ -660,7 +596,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else else
{ {
if (session.host == nullptr) if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span)); content = find(query_string.substring(size_t{ 0 }, span));
else else
content = session.host->find(query_string.substring(size_t{ 0 }, span)); content = session.host->find(query_string.substring(size_t{ 0 }, span));
query_string.shiftRight(span + 1); query_string.shiftRight(span + 1);
@ -673,7 +609,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else if (protocol_str.equalsi("http/1.1"_jrs)) else if (protocol_str.equalsi("http/1.1"_jrs))
{ {
session.version = HTTPVersion::HTTP_1_1; session.version = HTTPVersion::HTTP_1_1;
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; session.keep_alive = permit_keept_alive;
} }
} }
else else
@ -687,188 +623,172 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
// Server constructors // Server constructors
Jupiter::HTTP::Server::Server() Jupiter::HTTP::Server::Server() {
{ m_data = new Data();
Jupiter::HTTP::Server::data_ = new Jupiter::HTTP::Server::Data();
} }
Jupiter::HTTP::Server::Server(Jupiter::HTTP::Server &&source) Jupiter::HTTP::Server::Server(Jupiter::HTTP::Server &&source) {
{ m_data = source.m_data;
Jupiter::HTTP::Server::data_ = source.data_; source.m_data = new Data();
source.data_ = new Jupiter::HTTP::Server::Data();
} }
Jupiter::HTTP::Server::~Server() Jupiter::HTTP::Server::~Server() {
{ delete m_data;
delete Jupiter::HTTP::Server::data_;
} }
// Server functions // Server functions
void Jupiter::HTTP::Server::hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, Content *content) void Jupiter::HTTP::Server::hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, std::unique_ptr<Content> content) {
{ return m_data->hook(host, name, std::move(content));
return Jupiter::HTTP::Server::data_->hook(host, name, content);
} }
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host) bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host) {
{ return m_data->remove(host);
return Jupiter::HTTP::Server::data_->remove(host);
} }
/*bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path) /*bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path) {
{ return m_data->remove(host, path);
return Jupiter::HTTP::Server::data_->remove(host, path);
}*/ }*/
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) {
{ return m_data->remove(host, path, name);
return Jupiter::HTTP::Server::data_->remove(host, path, name);
} }
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host) bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host) {
{ return m_data->has(host);
return Jupiter::HTTP::Server::data_->has(host);
} }
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) {
{ return m_data->has(host, name);
return Jupiter::HTTP::Server::data_->has(host, name);
} }
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &name) Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &name) {
{ return m_data->find(name);
return Jupiter::HTTP::Server::data_->find(name);
} }
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) {
{ return m_data->find(host, name);
return Jupiter::HTTP::Server::data_->find(host, name);
} }
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
{ return m_data->execute(name, query_string);
return Jupiter::HTTP::Server::data_->execute(name, query_string);
} }
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
{ return m_data->execute(host, name, query_string);
return Jupiter::HTTP::Server::data_->execute(host, name, query_string);
} }
bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port) bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port) {
{ auto socket = std::make_unique<Jupiter::TCPSocket>();
Jupiter::TCPSocket *socket = new Jupiter::TCPSocket(); if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) {
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true))
{
socket->setBlocking(false); socket->setBlocking(false);
Jupiter::HTTP::Server::data_->ports.add(socket); m_data->m_ports.push_back(std::move(socket));
return true; return true;
} }
delete socket;
return false; return false;
} }
bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port) bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port) {
{ auto socket = std::make_unique<Jupiter::SecureTCPSocket>();
Jupiter::SecureTCPSocket *socket = new Jupiter::SecureTCPSocket(); if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) {
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) m_data->m_ports.push_back(std::move(socket));
{
Jupiter::HTTP::Server::data_->ports.add(socket);
return true; return true;
} }
delete socket;
return false; return false;
} }
int Jupiter::HTTP::Server::think() int Jupiter::HTTP::Server::think() {
{
Jupiter::Socket *socket;
HTTPSession *session;
// Process existing clients // Process existing clients
size_t index = Jupiter::HTTP::Server::data_->sessions.size(); auto sessions_end = m_data->m_sessions.end();
while (index != 0) for (auto itr = m_data->m_sessions.begin(); itr != sessions_end;) {
{ auto& session = *itr;
session = Jupiter::HTTP::Server::data_->sessions.get(--index); if (session->sock.isShutdown()) {
if (session->sock.isShutdown()) if (session->sock.recv() == 0) {
{ itr = m_data->m_sessions.erase(itr + 1);
if (session->sock.recv() == 0) continue;
delete Jupiter::HTTP::Server::data_->sessions.remove(index); }
} }
else if ((std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->keep_alive_session_timeout) else if ((std::chrono::steady_clock::now() > session->last_active + m_data->keep_alive_session_timeout)
|| (session->keep_alive == false && std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->session_timeout)) || (session->keep_alive == false && std::chrono::steady_clock::now() > session->last_active + m_data->session_timeout)) {
delete Jupiter::HTTP::Server::data_->sessions.remove(index); itr = m_data->m_sessions.erase(itr + 1);
//session->sock.shutdown(); continue;
else if (session->sock.recv() > 0) }
{ else if (session->sock.recv() > 0) {
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer(); const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer();
if (session->request.size() + sock_buffer.size() <= Jupiter::HTTP::Server::data_->max_request_size) // accept if (session->request.size() + sock_buffer.size() <= m_data->max_request_size) { // accept
{
session->request += sock_buffer; session->request += sock_buffer;
if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // completed request if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request
{
session->last_active = std::chrono::steady_clock::now(); session->last_active = std::chrono::steady_clock::now();
Jupiter::HTTP::Server::data_->process_request(*session); m_data->process_request(*session);
if (session->keep_alive == false) // remove completed session if (session->keep_alive == false) { // remove completed session
delete Jupiter::HTTP::Server::data_->sessions.remove(index); itr = m_data->m_sessions.erase(itr + 1);
//session->sock.shutdown(); //session->sock.shutdown();
continue;
}
// else // keep_alive: session not deleted
} }
else if (session->request.size() == Jupiter::HTTP::Server::data_->max_request_size) // reject (full buffer) else if (session->request.size() == m_data->max_request_size) { // reject (full buffer)
delete Jupiter::HTTP::Server::data_->sessions.remove(index); itr = m_data->m_sessions.erase(itr + 1);
continue;
}
// else // request not over: session not deleted
}
else { // reject
itr = m_data->m_sessions.erase(itr + 1);
continue;
} }
else // reject
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
} }
else if (session->sock.getLastError() != JUPITER_SOCK_EWOULDBLOCK) else if (session->sock.getLastError() != JUPITER_SOCK_EWOULDBLOCK) {
delete Jupiter::HTTP::Server::data_->sessions.remove(index); itr = m_data->m_sessions.erase(itr + 1);
continue;
}
// else // EWOULDBLOCK: session not deleted
++itr;
} }
// Process incoming clients // Process incoming clients
index = Jupiter::HTTP::Server::data_->ports.size(); std::unique_ptr<Jupiter::Socket> socket;
while (index != 0) for (auto& port : m_data->m_ports) {
{ socket.reset(socket->accept());
socket = Jupiter::HTTP::Server::data_->ports.get(--index); if (socket != nullptr) {
socket = socket->accept();
if (socket != nullptr)
{
socket->setBlocking(false); socket->setBlocking(false);
session = new HTTPSession(std::move(*socket)); auto session = std::make_unique<HTTPSession>(std::move(*socket));
if (session->sock.recv() > 0) // data received if (session->sock.recv() > 0) { // data received
{
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer(); const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer();
if (sock_buffer.size() < Jupiter::HTTP::Server::data_->max_request_size) // accept if (sock_buffer.size() < m_data->max_request_size) { // accept
{
session->request = session->sock.getBuffer(); session->request = session->sock.getBuffer();
if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // completed request if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request
{ m_data->process_request(*session);
Jupiter::HTTP::Server::data_->process_request(*session); if (session->keep_alive) { // session will live for 30 seconds.
if (session->keep_alive) // session will live for 30 seconds. m_data->m_sessions.push_back(std::move(session));
Jupiter::HTTP::Server::data_->sessions.add(session); }
else // session completed // else // session completed
delete session; }
else { // store for more processing
m_data->m_sessions.push_back(std::move(session));
} }
else // store for more processing
Jupiter::HTTP::Server::data_->sessions.add(session);
} }
else if (sock_buffer.size() == Jupiter::HTTP::Server::data_->max_request_size) else if (sock_buffer.size() == m_data->max_request_size) {
{ if (sock_buffer.find(HTTP_REQUEST_ENDING) == Jupiter::INVALID_INDEX) { // reject (too large)
if (sock_buffer.find(HTTP_REQUEST_ENDING) == Jupiter::INVALID_INDEX) // reject (too large) continue;
delete session;
else // accept (max size, completed request)
{
session->request = session->sock.getBuffer();
Jupiter::HTTP::Server::data_->process_request(*session);
if (session->keep_alive) // session will live for 30 seconds.
Jupiter::HTTP::Server::data_->sessions.add(session);
else // session completed
delete session;
} }
// accept (max size, completed request)
session->request = session->sock.getBuffer();
m_data->process_request(*session);
if (session->keep_alive) { // session will live for 30 seconds.
m_data->m_sessions.push_back(std::move(session));
}
// else // session completed
} }
else // reject (too large) // else // reject (too large)
delete session; }
else if (session->sock.getLastError() == JUPITER_SOCK_EWOULDBLOCK) { // store for more processing
m_data->m_sessions.push_back(std::move(session));
} }
else if (session->sock.getLastError() == JUPITER_SOCK_EWOULDBLOCK) // store for more processing
Jupiter::HTTP::Server::data_->sessions.add(session);
} }
} }
return 0; return 0;

93
src/common/IRC_Client.cpp

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2013-2017 Jessica James. * Copyright (C) 2013-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -805,7 +805,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
m_connection_status = 5; m_connection_status = 5;
m_reconnect_attempts = 0; m_reconnect_attempts = 0;
this->OnConnect(); this->OnConnect();
for (i = 0; i < Jupiter::plugins->size(); i++) Jupiter::plugins->get(i)->OnConnect(this); for (auto& plugin : Jupiter::plugins) {
plugin->OnConnect(this);
}
} }
break; break;
} }
@ -832,8 +834,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
if (command.equals("ACTION")) if (command.equals("ACTION"))
{ {
this->OnAction(chan, nick, message); this->OnAction(chan, nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnAction(this, chan, nick, message); plugin->OnAction(this, chan, nick, message);
}
} }
else else
{ {
@ -861,16 +864,18 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
response += IRCCTCP ENDL; response += IRCCTCP ENDL;
m_socket->send(response); m_socket->send(response);
this->OnCTCP(chan, nick, command, message); this->OnCTCP(chan, nick, command, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnCTCP(this, chan, nick, message); plugin->OnCTCP(this, chan, nick, message);
}
} }
} }
else else
{ {
Jupiter::ReferenceString message = premessage; Jupiter::ReferenceString message = premessage;
this->OnChat(chan, nick, message); this->OnChat(chan, nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnChat(this, chan, nick, message); plugin->OnChat(this, chan, nick, message);
}
} }
} }
} }
@ -886,8 +891,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
{ {
auto nick = Jupiter::ReferenceString::substring(line, 1, pos); auto nick = Jupiter::ReferenceString::substring(line, 1, pos);
this->OnNotice(chan, nick, message); this->OnNotice(chan, nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnNotice(this, chan, nick, message); plugin->OnNotice(this, chan, nick, message);
}
} }
else else
{ {
@ -895,8 +901,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
if (sender.isNotEmpty()) if (sender.isNotEmpty())
{ {
this->OnServerNotice(chan, sender, message); this->OnServerNotice(chan, sender, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnServerNotice(this, chan, sender, message); plugin->OnServerNotice(this, chan, sender, message);
}
} }
} }
} }
@ -916,8 +923,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
user->m_nickname = newnick; user->m_nickname = newnick;
this->OnNick(nick, newnick); this->OnNick(nick, newnick);
} }
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnNick(this, nick, newnick); plugin->OnNick(this, nick, newnick);
}
} }
else if (w2.equalsi("JOIN")) else if (w2.equalsi("JOIN"))
{ {
@ -952,8 +960,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
this->OnJoin(chan, nick); this->OnJoin(chan, nick);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnJoin(this, chan, nick); plugin->OnJoin(this, chan, nick);
}
} }
else if (w2.equalsi("PART")) else if (w2.equalsi("PART"))
{ {
@ -977,9 +986,10 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
reason = Jupiter::ReferenceString::substring(line, pos + 1); reason = Jupiter::ReferenceString::substring(line, pos + 1);
this->OnPart(chan, nick, reason); this->OnPart(chan, nick, reason);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnPart(this, chan, nick, reason); plugin->OnPart(this, chan, nick, reason);
}
if (nick.equalsi(m_nickname)) if (nick.equalsi(m_nickname))
Client::delChannel(chan); Client::delChannel(chan);
@ -1017,8 +1027,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
this->OnKick(chan, kicker, kicked, reason); this->OnKick(chan, kicker, kicked, reason);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnKick(this, chan, kicker, kicked, reason); plugin->OnKick(this, chan, kicker, kicked, reason);
}
if (kicked.equalsi(m_nickname)) if (kicked.equalsi(m_nickname))
{ {
@ -1048,8 +1059,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
this->OnQuit(nick, message); this->OnQuit(nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnQuit(this, nick, message); plugin->OnQuit(this, nick, message);
}
m_users.erase(nick); m_users.erase(nick);
} }
@ -1060,8 +1072,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
Jupiter::ReferenceString invited = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE); Jupiter::ReferenceString invited = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1); Jupiter::ReferenceString chan = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
this->OnInvite(chan, inviter, invited); this->OnInvite(chan, inviter, invited);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnInvite(this, chan, inviter, invited); plugin->OnInvite(this, chan, inviter, invited);
}
} }
else if (w2.equalsi("MODE")) else if (w2.equalsi("MODE"))
{ {
@ -1122,8 +1135,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
} }
} }
this->OnMode(chan, nick, modestring); this->OnMode(chan, nick, modestring);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnMode(this, chan, nick, modestring); plugin->OnMode(this, chan, nick, modestring);
}
} }
} }
} }
@ -1177,8 +1191,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
{ {
Jupiter::ReferenceString reason = Jupiter::ReferenceString::substring(line, line.find(':') + 1); Jupiter::ReferenceString reason = Jupiter::ReferenceString::substring(line, line.find(':') + 1);
this->OnError(reason); this->OnError(reason);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnError(this, reason); plugin->OnError(this, reason);
}
Jupiter::IRC::Client::disconnect(); Jupiter::IRC::Client::disconnect();
} }
else if (w1.equals("AUTHENTICATE")) else if (w1.equals("AUTHENTICATE"))
@ -1198,13 +1213,15 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
if (numeric != 0) if (numeric != 0)
{ {
this->OnNumeric(numeric, line); this->OnNumeric(numeric, line);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnNumeric(this, numeric, line); plugin->OnNumeric(this, numeric, line);
}
} }
} }
this->OnRaw(line); this->OnRaw(line);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnRaw(this, line); plugin->OnRaw(this, line);
}
} }
return 0; return 0;
@ -1253,8 +1270,9 @@ void Jupiter::IRC::Client::disconnect(bool stayDead)
m_socket.reset(t); m_socket.reset(t);
} }
} }
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnDisconnect(this); plugin->OnDisconnect(this);
}
} }
void Jupiter::IRC::Client::disconnect(const Jupiter::ReadableString &message, bool stayDead) void Jupiter::IRC::Client::disconnect(const Jupiter::ReadableString &message, bool stayDead)
@ -1269,8 +1287,9 @@ void Jupiter::IRC::Client::reconnect()
m_reconnect_attempts++; m_reconnect_attempts++;
bool successConnect = Jupiter::IRC::Client::connect(); bool successConnect = Jupiter::IRC::Client::connect();
this->OnReconnectAttempt(successConnect); this->OnReconnectAttempt(successConnect);
for (size_t i = 0; i < Jupiter::plugins->size(); i++) for (auto& plugin : Jupiter::plugins) {
Jupiter::plugins->get(i)->OnReconnectAttempt(this, successConnect); plugin->OnReconnectAttempt(this, successConnect);
}
} }
int Jupiter::IRC::Client::think() int Jupiter::IRC::Client::think()

270
src/common/Plugin.cpp

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2014-2016 Jessica James. * Copyright (C) 2014-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -27,8 +27,8 @@
#endif // _WIN32 #endif // _WIN32
#include "Plugin.h" #include "Plugin.h"
#include <memory>
#include "Functions.h" #include "Functions.h"
#include "ArrayList.h"
#include "String.hpp" #include "String.hpp"
using namespace Jupiter::literals; using namespace Jupiter::literals;
@ -40,21 +40,25 @@ constexpr char directory_character = '\\';
constexpr char directory_character = '/'; constexpr char directory_character = '/';
#endif // _WIN32 #endif // _WIN32
struct dlib struct dlib {
{ dlib() = default;
Jupiter::Plugin *plugin = nullptr;
// Ensure the lib handle doesn't get duplicated / prevent double free
dlib(const dlib&) = delete;
dlib(dlib&&) = delete;
dlib& operator=(const dlib&) = delete;
dlib& operator=(dlib&&) = delete;
#if defined _WIN32 #if defined _WIN32
HMODULE lib = nullptr; HMODULE lib = nullptr;
#else // _WIN32 #else // _WIN32
void *lib = nullptr; void* lib = nullptr;
#endif // _WIN32 #endif // _WIN32
~dlib(); ~dlib();
}; };
dlib::~dlib() dlib::~dlib() {
{ if (dlib::lib != nullptr) {
if (dlib::lib != nullptr)
{
#if defined _WIN32 #if defined _WIN32
FreeLibrary(dlib::lib); FreeLibrary(dlib::lib);
#else // _WIN32 #else // _WIN32
@ -74,23 +78,19 @@ const Jupiter::ReferenceString config_file_extension = ".ini"_jrs;
Jupiter::StringS plugins_directory = "Plugins"_jrs + directory_character; Jupiter::StringS plugins_directory = "Plugins"_jrs + directory_character;
Jupiter::StringS plugin_configs_directory = "Configs"_jrs + directory_character; Jupiter::StringS plugin_configs_directory = "Configs"_jrs + directory_character;
Jupiter::ArrayList<Jupiter::Plugin> _plugins; std::vector<Jupiter::Plugin*> g_plugins; // Array of weak pointers to plugin instances generally stored in static memory
Jupiter::ArrayList<Jupiter::Plugin> *Jupiter::plugins = &_plugins; std::vector<Jupiter::Plugin*>& Jupiter::plugins = g_plugins;
Jupiter::ArrayList<dlib> _libList; std::vector<std::unique_ptr<dlib>> g_libList;
/** Jupiter::Plugin Implementation */ /** Jupiter::Plugin Implementation */
Jupiter::Plugin::Plugin() Jupiter::Plugin::Plugin() {
{
} }
Jupiter::Plugin::~Plugin() Jupiter::Plugin::~Plugin() {
{ for (auto itr = g_plugins.begin(); itr != g_plugins.end(); ++itr) {
for (size_t index = 0; index != _plugins.size(); ++index) if (*itr == this) {
{ g_plugins.erase(itr);
if (_plugins.get(index) == this)
{
_plugins.remove(index);
break; break;
} }
} }
@ -98,58 +98,50 @@ Jupiter::Plugin::~Plugin()
// Instance Functions // Instance Functions
bool Jupiter::Plugin::shouldRemove() const bool Jupiter::Plugin::shouldRemove() const {
{ return _shouldRemove;
return Jupiter::Plugin::_shouldRemove;
} }
const Jupiter::ReadableString &Jupiter::Plugin::getName() const const Jupiter::ReadableString &Jupiter::Plugin::getName() const {
{ return name;
return Jupiter::Plugin::name;
} }
Jupiter::Config &Jupiter::Plugin::getConfig() Jupiter::Config &Jupiter::Plugin::getConfig() {
{ return config;
return Jupiter::Plugin::config;
} }
bool Jupiter::Plugin::initialize() bool Jupiter::Plugin::initialize() {
{
return true; return true;
} }
void Jupiter::Plugin::OnPostInitialize() void Jupiter::Plugin::OnPostInitialize() {
{
} }
// Static Functions // Static Functions
void Jupiter::Plugin::setDirectory(const Jupiter::ReadableString &dir) void Jupiter::Plugin::setDirectory(const Jupiter::ReadableString &dir) {
{ if (plugins_directory.set(dir) != 0 && plugins_directory.get(plugins_directory.size() - 1) != directory_character) {
if (plugins_directory.set(dir) != 0 && plugins_directory.get(plugins_directory.size() - 1) != directory_character)
plugins_directory += directory_character; plugins_directory += directory_character;
}
} }
const Jupiter::ReadableString &Jupiter::Plugin::getDirectory() const Jupiter::ReadableString &Jupiter::Plugin::getDirectory() {
{
return plugins_directory; return plugins_directory;
} }
void Jupiter::Plugin::setConfigDirectory(const Jupiter::ReadableString &dir) void Jupiter::Plugin::setConfigDirectory(const Jupiter::ReadableString &dir) {
{ if (plugin_configs_directory.set(dir) != 0 && plugin_configs_directory.get(plugin_configs_directory.size() - 1) != directory_character) {
if (plugin_configs_directory.set(dir) != 0 && plugin_configs_directory.get(plugin_configs_directory.size() - 1) != directory_character)
plugin_configs_directory += directory_character; plugin_configs_directory += directory_character;
}
} }
const Jupiter::ReadableString &Jupiter::Plugin::getConfigDirectory() const Jupiter::ReadableString &Jupiter::Plugin::getConfigDirectory() {
{
return plugin_configs_directory; return plugin_configs_directory;
} }
Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName) Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName) {
{
std::string file = static_cast<std::string>(plugins_directory) + static_cast<std::string>(pluginName) + module_file_extension; std::string file = static_cast<std::string>(plugins_directory) + static_cast<std::string>(pluginName) + module_file_extension;
dlib *dPlug = new dlib(); std::unique_ptr<dlib> dPlug{ std::make_unique<dlib>() };
// Load the library // Load the library
#if defined _WIN32 #if defined _WIN32
@ -157,12 +149,12 @@ Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName
#else // _WIN32 #else // _WIN32
dPlug->lib = dlopen(file.c_str(), RTLD_NOW); dPlug->lib = dlopen(file.c_str(), RTLD_NOW);
#endif // _WIN32 #endif // _WIN32
if (dPlug->lib == nullptr) if (dPlug->lib == nullptr) {
{
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (File failed to load)" ENDL, file.c_str()); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (File failed to load)" ENDL, file.c_str());
goto fail; return nullptr;
} }
Plugin* weak_plugin;
{ {
// Get the "getPlugin" function // Get the "getPlugin" function
typedef Jupiter::Plugin *(*func_type)(void); typedef Jupiter::Plugin *(*func_type)(void);
@ -171,24 +163,22 @@ Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName
#else // _WIN32 #else // _WIN32
func_type func = (func_type)dlsym(dPlug->lib, "getPlugin"); func_type func = (func_type)dlsym(dPlug->lib, "getPlugin");
#endif // _WIN32 #endif // _WIN32
if (func == nullptr) if (func == nullptr) {
{
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Invalid plugin)" ENDL, file.c_str()); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Invalid plugin)" ENDL, file.c_str());
goto fail; return nullptr;
} }
// Get the plugin // Get the plugin
dPlug->plugin = func(); weak_plugin = func();
if (dPlug->plugin == nullptr) if (weak_plugin == nullptr) {
{
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to initialize)" ENDL, file.c_str()); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to initialize)" ENDL, file.c_str());
goto fail; return nullptr;
} }
// Initialize the plugin // Initialize the plugin
dPlug->plugin->name.set(pluginName); weak_plugin->name.set(pluginName);
dPlug->plugin->config.read(plugin_configs_directory + pluginName + config_file_extension); weak_plugin->config.read(plugin_configs_directory + pluginName + config_file_extension);
dPlug->plugin->initialize(); weak_plugin->initialize();
} }
{ {
// Get and execute the "load" function if it exists // Get and execute the "load" function if it exists
@ -198,85 +188,81 @@ Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName
#else // _WIN32 #else // _WIN32
func_type func = (func_type)dlsym(dPlug->lib, "load"); func_type func = (func_type)dlsym(dPlug->lib, "load");
#endif // _WIN32 #endif // _WIN32
if (func != nullptr && func() == false) if (func != nullptr && func() == false) {
{
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to load)" ENDL, file.c_str()); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to load)" ENDL, file.c_str());
goto fail; return nullptr;
} }
} }
_libList.add(dPlug); g_libList.push_back(std::move(dPlug));
_plugins.add(dPlug->plugin); g_plugins.push_back(weak_plugin);
return dPlug->plugin;
fail: return weak_plugin;
delete dPlug;
return nullptr;
} }
bool Jupiter::Plugin::free(size_t index) bool Jupiter::Plugin::free(size_t index) {
{ if (index < g_plugins.size()) {
if (index < _plugins.size()) // Do not free() the plugin; plugin gets free'd either by FreeLibrary() during static memory deallocation or unload.
{ g_plugins.erase(g_plugins.begin() + index);
// Do not free() the plugin; plugin gets free'd by FreeLibrary(). auto dPlugItr = g_libList.begin() + index;
_plugins.remove(index); std::unique_ptr<dlib> dPlug = std::move(*dPlugItr);
dlib *dPlug = _libList.remove(index); g_libList.erase(dPlugItr);
typedef void(*func_type)(void); typedef void(*func_type)(void);
#if defined _WIN32 #if defined _WIN32
func_type func = (func_type)GetProcAddress(dPlug->lib, "unload"); func_type unload_func = (func_type)GetProcAddress(dPlug->lib, "unload");
#else // _WIN32 #else // _WIN32
func_type func = (func_type)dlsym(dPlug->lib, "unload"); func_type unload_func = (func_type)dlsym(dPlug->lib, "unload");
#endif // _WIN32 #endif // _WIN32
if (func != nullptr) func(); if (unload_func != nullptr) {
unload_func();
delete dPlug; }
return true; return true;
} }
return false; return false;
} }
bool Jupiter::Plugin::free(Jupiter::Plugin *plugin) bool Jupiter::Plugin::free(Jupiter::Plugin *plugin) {
{ if (plugin == nullptr) {
if (plugin == nullptr)
return false; return false;
}
for (size_t index = 0; index != _plugins.size(); ++index) for (size_t index = 0; index != g_plugins.size(); ++index) {
if (_plugins.get(index) == plugin) if (g_plugins[index] == plugin) {
return Jupiter::Plugin::free(index); return Jupiter::Plugin::free(index);
}
}
return false; return false;
} }
bool Jupiter::Plugin::free(const Jupiter::ReadableString &pluginName) bool Jupiter::Plugin::free(const Jupiter::ReadableString &pluginName) {
{ if (pluginName == nullptr) {
if (pluginName == nullptr)
return false; return false;
}
for (size_t index = 0; index != _plugins.size(); ++index) for (size_t index = 0; index != g_plugins.size(); ++index) {
if (pluginName.matchi(_plugins.get(index)->getName())) if (pluginName.matchi(g_plugins[index]->getName())) {
return Jupiter::Plugin::free(index); return Jupiter::Plugin::free(index);
}
}
return false; return false;
} }
Jupiter::Plugin *Jupiter::Plugin::get(size_t index) Jupiter::Plugin *Jupiter::Plugin::get(size_t index) {
{ if (index < g_plugins.size()) {
if (index < _plugins.size()) return g_plugins[index];
return _plugins.get(index); }
return nullptr; return nullptr;
} }
Jupiter::Plugin *Jupiter::Plugin::get(const Jupiter::ReadableString &pluginName) Jupiter::Plugin *Jupiter::Plugin::get(const Jupiter::ReadableString &pluginName) {
{ for (const auto& plugin : g_plugins) {
Jupiter::Plugin *plugin; if (pluginName.matchi(plugin->getName())) {
for (size_t index = 0; index != _plugins.size(); ++index)
{
plugin = _plugins.get(index);
if (pluginName.matchi(plugin->getName()))
return plugin; return plugin;
}
} }
return nullptr; return nullptr;
@ -284,124 +270,100 @@ Jupiter::Plugin *Jupiter::Plugin::get(const Jupiter::ReadableString &pluginName)
// Event Implementations // Event Implementations
int Jupiter::Plugin::think() int Jupiter::Plugin::think() {
{
return 0; return 0;
} }
int Jupiter::Plugin::OnRehash() int Jupiter::Plugin::OnRehash() {
{ config.reload();
Jupiter::Plugin::config.reload();
return 0; return 0;
} }
bool Jupiter::Plugin::OnBadRehash(bool removed) bool Jupiter::Plugin::OnBadRehash(bool removed) {
{ _shouldRemove = removed;
Jupiter::Plugin::_shouldRemove = removed;
return false; return false;
} }
// Event Placeholders // Event Placeholders
void Jupiter::Plugin::OnConnect(Jupiter::IRC::Client *) void Jupiter::Plugin::OnConnect(Jupiter::IRC::Client *) {
{
return; return;
} }
void Jupiter::Plugin::OnDisconnect(Jupiter::IRC::Client *) void Jupiter::Plugin::OnDisconnect(Jupiter::IRC::Client *) {
{
return; return;
} }
void Jupiter::Plugin::OnReconnectAttempt(Jupiter::IRC::Client *, bool) void Jupiter::Plugin::OnReconnectAttempt(Jupiter::IRC::Client *, bool) {
{
return; return;
} }
void Jupiter::Plugin::OnRaw(Jupiter::IRC::Client *, const Jupiter::ReadableString &) void Jupiter::Plugin::OnRaw(Jupiter::IRC::Client *, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnNumeric(Jupiter::IRC::Client *, long int, const Jupiter::ReadableString &) void Jupiter::Plugin::OnNumeric(Jupiter::IRC::Client *, long int, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnError(Jupiter::IRC::Client *, const Jupiter::ReadableString &) void Jupiter::Plugin::OnError(Jupiter::IRC::Client *, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnChat(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnChat(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnServerNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnServerNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnCTCP(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnCTCP(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnAction(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnAction(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnInvite(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnInvite(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnJoin(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnJoin(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnPart(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnPart(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnNick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnNick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnKick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnKick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnQuit(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnQuit(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnMode(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) void Jupiter::Plugin::OnMode(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
{
return; return;
} }
void Jupiter::Plugin::OnThink(Jupiter::IRC::Client *) void Jupiter::Plugin::OnThink(Jupiter::IRC::Client *) {
{
return; return;
} }
void Jupiter::Plugin::OnGenericCommandAdd(Jupiter::GenericCommand &) void Jupiter::Plugin::OnGenericCommandAdd(Jupiter::GenericCommand &) {
{
} }
void Jupiter::Plugin::OnGenericCommandRemove(Jupiter::GenericCommand &) void Jupiter::Plugin::OnGenericCommandRemove(Jupiter::GenericCommand &) {
{
} }

257
src/include/Jupiter/ArrayList.h

@ -1,257 +0,0 @@
/**
* Copyright (C) 2013-2016 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _ARRAYLIST_H_HEADER
#define _ARRAYLIST_H_HEADER
/**
* @file ArrayList.h
* @brief Provides an array-based list implementation using the List interface.
*/
#include "Jupiter.h"
#include "DataBuffer.h"
namespace Jupiter
{
/**
* @brief Provides an array-based list implementation using the List interface.
*/
template<typename T> class ArrayList
{
public:
/**
* @brief Gets the data at a specified index.
*
* @param index Index of the data to get.
* @return Data stored at the specified index.
*/
T *get(size_t index) const;
/**
* @brief Removes the data at a specified index from the list, and returns the removed data.
*
* @param n Index of the node to remove.
* @return Data removed.
*/
T *remove(size_t index);
/**
* @brief Removes the last element in the list, and returns the data removed.
*
* @return Data removed.
*/
T *pop();
/**
* @brief Adds data to the list at a specified index.
*
* @param data Data to add to the list.
* @param index Position in the list to add the data to.
*/
void add(T *data, size_t index);
/**
* @brief Adds data to the end of the list.
*
* @param data Data to add to the list.
*/
void add(T *data);
/**
* @brief Returns the size of the list.
*
* @return Number of nodes in the list.
*/
size_t size() const { return m_length; };
/**
* @brief Empties the ArrayList of all elements.
*/
void empty();
/**
* @brief Remove and deletes all elements within the ArrayList.
*/
void emptyAndDelete();
/**
* @brief Default constructor for the ArrayList class.
*/
ArrayList();
/**
* @brief Initializes the ArrayList's underlying array to a specified size.
*/
ArrayList(size_t length);
/**
* @brief Copy constructor for the ArrayList class.
*/
ArrayList(const ArrayList<T> &);
/**
* @brief Move constructor for the ArrayList class.
*/
ArrayList(ArrayList<T> &&);
/**
* @brief Destructor for the ArrayList class.
* Note: This does not delete data added to the list.
*/
~ArrayList();
/** Initial size constant */
static const size_t start_size = 8;
/** Access Operator */
inline T *operator[](size_t index) { return this->get(index); };
/** Private members */
private:
T **data;
size_t dataSize;
size_t m_length;
size_t expandArray();
};
}
// Implementation
template<typename T> size_t Jupiter::ArrayList<T>::expandArray()
{
T **tmp = new T *[Jupiter::ArrayList<T>::dataSize * 2];
for (size_t i = 0; i < Jupiter::ArrayList<T>::dataSize; i++)
tmp[i] = data[i];
delete[] Jupiter::ArrayList<T>::data;
Jupiter::ArrayList<T>::data = tmp;
Jupiter::ArrayList<T>::dataSize *= 2;
return Jupiter::ArrayList<T>::dataSize;
}
template<typename T> Jupiter::ArrayList<T>::ArrayList() : ArrayList(Jupiter::ArrayList<T>::start_size)
{
}
template<typename T> Jupiter::ArrayList<T>::ArrayList(size_t length_)
{
Jupiter::ArrayList<T>::dataSize = length_;
Jupiter::ArrayList<T>::data = new T*[Jupiter::ArrayList<T>::dataSize];
m_length = 0;
}
template<typename T> Jupiter::ArrayList<T>::ArrayList(const Jupiter::ArrayList<T> &source)
{
Jupiter::ArrayList<T>::dataSize = source.dataSize;
Jupiter::ArrayList<T>::data = new T*[Jupiter::ArrayList<T>::dataSize];
m_length = 0;
while (m_length != source.m_length)
{
Jupiter::ArrayList<T>::data[m_length] = source.data[m_length];
++m_length;
}
}
template<typename T> Jupiter::ArrayList<T>::ArrayList(ArrayList<T> &&source)
{
Jupiter::ArrayList<T>::dataSize = source.dataSize;
Jupiter::ArrayList<T>::data = source.data;
m_length = source.m_length;
source.dataSize = Jupiter::ArrayList<T>::start_size;
source.data = new T*[source.dataSize];
source.m_length = 0;
}
template<typename T> Jupiter::ArrayList<T>::~ArrayList()
{
delete[] Jupiter::ArrayList<T>::data;
}
template<typename T> T *Jupiter::ArrayList<T>::get(size_t index) const
{
return Jupiter::ArrayList<T>::data[index];
}
template<typename T> T *Jupiter::ArrayList<T>::remove(size_t index)
{
T *r = Jupiter::ArrayList<T>::data[index];
Jupiter::ArrayList<T>::data[index] = nullptr;
for (size_t i = index + 1; i < m_length; i++)
Jupiter::ArrayList<T>::data[i - 1] = Jupiter::ArrayList<T>::data[i];
--m_length;
return r;
}
template<typename T> T *Jupiter::ArrayList<T>::pop()
{
return Jupiter::ArrayList<T>::data[--m_length];
}
template<typename T> void Jupiter::ArrayList<T>::add(T *ndata, size_t index)
{
if (m_length == Jupiter::ArrayList<T>::dataSize) Jupiter::ArrayList<T>::expandArray();
for (size_t i = m_length; i > index; i--)
Jupiter::ArrayList<T>::data[i] = Jupiter::ArrayList<T>::data[i - 1];
Jupiter::ArrayList<T>::data[index] = ndata;
++m_length;
}
template<typename T> void Jupiter::ArrayList<T>::add(T *ndata)
{
Jupiter::ArrayList<T>::add(ndata, m_length);
}
template<typename T> void Jupiter::ArrayList<T>::empty()
{
m_length = 0;
}
template<typename T> void Jupiter::ArrayList<T>::emptyAndDelete()
{
while (m_length != 0)
delete Jupiter::ArrayList<T>::data[--m_length];
}
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::ArrayList>
{
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::ArrayList<Y> *data)
{
buffer->push<size_t>(data->size());
for (size_t index = 0; index != data->size(); index++)
buffer->push<Y>(*data->get(index));
};
template<typename Y> static Jupiter::ArrayList<Y> interpret(uint8_t *&head)
{
size_t size_ = *reinterpret_cast<size_t *>(head);
head += sizeof(size_t);
Jupiter::ArrayList<Y> r = Jupiter::ArrayList<Y>(size_);
while (size_-- != 0)
r.add(Jupiter::DataBuffer::interpret_data<Y>(head));
return r;
}
};
#endif // _ARRAYLIST_H_HEADER

5
src/include/Jupiter/Command.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2013-2015 Jessica James. * Copyright (C) 2013-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -25,7 +25,6 @@
*/ */
#include "Jupiter.h" #include "Jupiter.h"
#include "ArrayList.h"
#include "Reference_String.h" #include "Reference_String.h"
namespace Jupiter namespace Jupiter
@ -94,7 +93,7 @@ namespace Jupiter
/** Private members */ /** Private members */
private: private:
struct Data; struct Data;
Data *data_; Data *m_data;
}; };
} }

4
src/include/Jupiter/File.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2014-2015 Jessica James. * Copyright (C) 2014-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -158,7 +158,7 @@ namespace Jupiter
/** Private members */ /** Private members */
private: private:
struct Data; struct Data;
Data *data_; Data *m_data;
}; };
} }

17
src/include/Jupiter/GenericCommand.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2015-2016 Jessica James. * Copyright (C) 2015-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -24,9 +24,9 @@
* @brief Provides an extendable command system. * @brief Provides an extendable command system.
*/ */
#include <memory>
#include "Command.h" #include "Command.h"
#include "String.hpp" #include "String.hpp"
#include "ArrayList.h"
/** DLL Linkage Nagging */ /** DLL Linkage Nagging */
#if defined _MSC_VER #if defined _MSC_VER
@ -41,8 +41,9 @@ namespace Jupiter
/** /**
* @brief Provides the base for generic commands. * @brief Provides the base for generic commands.
*/ */
class JUPITER_API GenericCommand : public Jupiter::Command class JUPITER_API GenericCommand : public Jupiter::Command, public std::enable_shared_from_this<GenericCommand> {
{ // Note: only needs shared_from_this because of the horrendous way this was originally written before shared_ptr
// This isn't worth improving since it should be replaced eventually
public: public:
/** Enumerated class to guide output in generic command interpreters */ /** Enumerated class to guide output in generic command interpreters */
enum class DisplayType enum class DisplayType
@ -138,7 +139,7 @@ namespace Jupiter
bool isUsing() const; bool isUsing() const;
void setUsing(bool in_value); void setUsing(bool in_value);
Jupiter::ArrayList<GenericCommand> getCommands() const; // differs from m_commands in that it checks if it's using a namespace std::vector<GenericCommand*> getCommands() const; // differs from m_commands in that it checks if it's using a namespace
GenericCommand *getCommand(const Jupiter::ReadableString &in_command) const; GenericCommand *getCommand(const Jupiter::ReadableString &in_command) const;
void addCommand(GenericCommand &in_command); void addCommand(GenericCommand &in_command);
@ -151,7 +152,7 @@ namespace Jupiter
protected: protected:
bool m_using; bool m_using;
Jupiter::ArrayList<GenericCommand> m_commands; std::vector<GenericCommand*> m_commands;
private: private:
bool m_should_update_help = true; bool m_should_update_help = true;
@ -183,8 +184,8 @@ class CLASS : public Jupiter::GenericCommand { \
class CLASS ## _Init : public CLASS { \ class CLASS ## _Init : public CLASS { \
public: \ public: \
CLASS ## _Init() { \ CLASS ## _Init() { \
for (size_t index = 0; index != Jupiter::plugins->size(); ++index) \ for (auto& plugin : Jupiter::plugins) \
Jupiter::plugins->get(index)->OnGenericCommandAdd(*this); \ plugin->OnGenericCommandAdd(*this); \
} }; \ } }; \
CLASS ## _Init CLASS ## _instance = CLASS ## _Init (); \ CLASS ## _Init CLASS ## _instance = CLASS ## _Init (); \
CLASS & CLASS :: instance = CLASS ## _instance; CLASS & CLASS :: instance = CLASS ## _instance;

20
src/include/Jupiter/HTTP_Server.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2015-2016 Jessica James. * Copyright (C) 2015-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -24,10 +24,10 @@
* @brief Provides an interface to distribute data using HTTP. * @brief Provides an interface to distribute data using HTTP.
*/ */
#include <memory>
#include "Jupiter.h" #include "Jupiter.h"
#include "Thinker.h" #include "Thinker.h"
#include "Readable_String.h" #include "Readable_String.h"
#include "ArrayList.h"
/** DLL Linkage Nagging */ /** DLL Linkage Nagging */
#if defined _MSC_VER #if defined _MSC_VER
@ -67,18 +67,20 @@ namespace Jupiter
class JUPITER_API Directory class JUPITER_API Directory
{ {
public: public:
Jupiter::ArrayList<Jupiter::HTTP::Server::Directory> directories; std::vector<std::unique_ptr<Server::Directory>> directories;
Jupiter::ArrayList<Jupiter::HTTP::Server::Content> content; std::vector<std::unique_ptr<Server::Content>> content;
Jupiter::StringS name; Jupiter::StringS name;
unsigned int name_checksum; unsigned int name_checksum;
virtual void hook(const Jupiter::ReadableString &path, Content *in_content); virtual void hook(const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
//virtual bool remove(const Jupiter::ReadableString &path); //virtual bool remove(const Jupiter::ReadableString &path);
virtual bool remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &name); virtual bool remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
virtual bool has(const Jupiter::ReadableString &name); virtual bool has(const Jupiter::ReadableString &name);
virtual Jupiter::HTTP::Server::Content *find(const Jupiter::ReadableString &name); virtual Jupiter::HTTP::Server::Content* find(const Jupiter::ReadableString &name);
virtual Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string); virtual Jupiter::ReadableString* execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
Directory(const Directory&) = delete;
Directory& operator=(const Directory&) = delete;
Directory(const Jupiter::ReadableString &in_name); Directory(const Jupiter::ReadableString &in_name);
virtual ~Directory(); virtual ~Directory();
}; };
@ -95,7 +97,7 @@ namespace Jupiter
Host(const Jupiter::ReadableString &in_name); Host(const Jupiter::ReadableString &in_name);
}; };
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, Content *in_content); void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
bool remove(const Jupiter::ReadableString &host); bool remove(const Jupiter::ReadableString &host);
//bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path); //bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path);
bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name); bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
@ -115,7 +117,7 @@ namespace Jupiter
/** Private members */ /** Private members */
private: private:
struct Data; struct Data;
Data *data_; Data *m_data;
}; // Jupiter::HTTP::Server class }; // Jupiter::HTTP::Server class
} // Jupiter::HTTP namespace } // Jupiter::HTTP namespace
} // Jupiter namespace } // Jupiter namespace

5
src/include/Jupiter/Plugin.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2014-2016 Jessica James. * Copyright (C) 2014-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -24,7 +24,6 @@
* @brief Provides a hot-swapable plugin system. * @brief Provides a hot-swapable plugin system.
*/ */
#include "ArrayList.h"
#include "Thinker.h" #include "Thinker.h"
#include "Rehash.h" #include "Rehash.h"
#include "INIConfig.h" #include "INIConfig.h"
@ -376,7 +375,7 @@ namespace Jupiter
}; };
/** The list containing pointers to plugins */ /** The list containing pointers to plugins */
JUPITER_API extern Jupiter::ArrayList<Jupiter::Plugin> *plugins; JUPITER_API extern std::vector<Jupiter::Plugin*>& plugins; // TODO: There are better ways to expose this
} }
/** Re-enable warnings */ /** Re-enable warnings */

Loading…
Cancel
Save