diff --git a/.htaccess b/.htaccess
index 73a6f2f..5ce41cb 100644
--- a/.htaccess
+++ b/.htaccess
@@ -2,8 +2,15 @@ php_flag display_errors on
Options -Indexes
RedirectMatch 404 /\.git
+RedirectMatch 404 /src
+RedirectMatch 404 /test
RewriteEngine On
-RewriteRule ^api/(.*)?$ index.php?api=$1&$2 [L,QSA]
-RewriteRule ^admin(/(.*)?)?$ index.php?site=admin&$1 [L,QSA]
-RewriteRule ^((?!((js|css|img|fonts|api|docs)($|/)))(.*)?)$ index.php?site=$1&$2 [L,QSA]
+RewriteRule ^api(/.*)?$ /index.php?api=$1 [L,QSA]
+
+
+ RewriteEngine On
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteRule ^(.*)$ /index.php?site=$1 [L,QSA]
+
\ No newline at end of file
diff --git a/core/Api/Routes/Fetch.class.php b/core/Api/Routes/Fetch.class.php
index 6180801..7ff247e 100644
--- a/core/Api/Routes/Fetch.class.php
+++ b/core/Api/Routes/Fetch.class.php
@@ -7,8 +7,6 @@ use \Driver\SQL\Condition\Compare;
class Fetch extends Request {
- private array $notifications;
-
public function __construct($user, $externalCall = false) {
parent::__construct($user, $externalCall, array());
$this->loginRequired = true;
diff --git a/core/Api/Routes/Find.class.php b/core/Api/Routes/Find.class.php
new file mode 100644
index 0000000..328720e
--- /dev/null
+++ b/core/Api/Routes/Find.class.php
@@ -0,0 +1,61 @@
+ new StringType('request', 128, true, '/')
+ ));
+
+ $this->isPublic = false;
+ }
+
+ public function execute($values = array()) {
+ if(!parent::execute($values)) {
+ return false;
+ }
+
+ $request = $this->getParam('request');
+ if (!startsWith($request, '/')) {
+ $request = "/$request";
+ }
+
+ $sql = $this->user->getSQL();
+
+ $res = $sql
+ ->select("uid", "request", "action", "target", "extra")
+ ->from("Route")
+ ->where(new CondBool("active"))
+ ->where(new Regex("^$request$", new Column("request")))
+ ->limit(1)
+ ->execute();
+
+ $this->lastError = $sql->getLastError();
+ $this->success = ($res !== FALSE);
+
+ if ($this->success) {
+ if (!empty($res)) {
+ $row = $res[0];
+ $this->result["route"] = array(
+ "uid" => intval($row["uid"]),
+ "request" => $row["request"],
+ "action" => $row["action"],
+ "target" => $row["target"],
+ "extra" => $row["extra"]
+ );
+ } else {
+ $this->result["route"] = NULL;
+ }
+ }
+
+ return $this->success;
+ }
+}
\ No newline at end of file
diff --git a/core/Configuration/CreateDatabase.class.php b/core/Configuration/CreateDatabase.class.php
index 9e3b561..7a9c36d 100755
--- a/core/Configuration/CreateDatabase.class.php
+++ b/core/Configuration/CreateDatabase.class.php
@@ -129,7 +129,8 @@ class CreateDatabase {
->primaryKey("uid");
$queries[] = $sql->insert("Route", array("request", "action", "target"))
- ->addRow("/admin(/.*)?", "dynamic", "\\Core\\Documents\\AdminDashboard");
+ ->addRow("/admin(/.*)?", "dynamic", "\\Core\\Documents\\AdminDashboard")
+ ->addRow("/api/(.*)", "dynamic", "\\Core\\Api\\$1");
return $queries;
}
diff --git a/core/Driver/SQL/Condition/Regex.class.php b/core/Driver/SQL/Condition/Regex.class.php
new file mode 100644
index 0000000..f0ba2bf
--- /dev/null
+++ b/core/Driver/SQL/Condition/Regex.class.php
@@ -0,0 +1,17 @@
+leftExpression = $leftExpression;
+ $this->rightExpression = $rightExpression;
+ }
+
+ public function getLeftExp() { return $this->leftExpression; }
+ public function getRightExp() { return $this->rightExpression; }
+}
\ No newline at end of file
diff --git a/core/Driver/SQL/SQL.class.php b/core/Driver/SQL/SQL.class.php
index 743ce06..341ba2c 100644
--- a/core/Driver/SQL/SQL.class.php
+++ b/core/Driver/SQL/SQL.class.php
@@ -6,6 +6,7 @@ use Driver\SQL\Column\Column;
use Driver\SQL\Condition\Compare;
use Driver\SQL\Condition\CondBool;
use Driver\SQL\Condition\CondOr;
+use Driver\SQL\Condition\Regex;
use Driver\SQL\Constraint\Constraint;
use \Driver\SQL\Constraint\Unique;
use \Driver\SQL\Constraint\PrimaryKey;
@@ -326,11 +327,17 @@ abstract class SQL {
return $this->buildCondition($condition[0], $params);
} else {
$conditions = array();
- foreach($condition as $cond) {
+ foreach ($condition as $cond) {
$conditions[] = $this->buildCondition($cond, $params);
}
return implode(" AND ", $conditions);
}
+ } else if ($condition instanceof Regex) {
+ $left = $condition->getLeftExp();
+ $right = $condition->getRightExp();
+ $left = ($left instanceof Column) ? $this->columnName($left->getName()) : $this->addValue($left, $params);
+ $right = ($right instanceof Column) ? $this->columnName($right->getName()) : $this->addValue($right, $params);
+ return $left . " REGEXP " . $right;
} else {
$this->lastError = "Unsupported condition type: " . get_class($condition);
return false;
diff --git a/core/core.php b/core/core.php
index 42fa3f6..d51fbea 100644
--- a/core/core.php
+++ b/core/core.php
@@ -85,6 +85,7 @@
function getClassPath($class, $suffix=true) {
$path = str_replace('\\', '/', $class);
+ if (startsWith($path, "/")) $path = substr($path, 1);
$suffix = ($suffix ? ".class" : "");
return "core/$path$suffix.php";
}
diff --git a/index.php b/index.php
index 90c82ae..c85e0b3 100644
--- a/index.php
+++ b/index.php
@@ -60,7 +60,7 @@ if(isset($_GET["api"]) && is_string($_GET["api"])) {
}
}
} else {
- $documentName = $_GET["site"];
+ $documentName = $_GET["site"] ?? "/";
if ($installation) {
if ($documentName !== "" && $documentName !== "index.php") {
$response = "Redirecting to /";
@@ -70,24 +70,47 @@ if(isset($_GET["api"]) && is_string($_GET["api"])) {
$response = $document->getCode();
}
} else {
- if(empty($documentName) || strcasecmp($documentName, "install") === 0) {
- $documentName = "home";
- } else if(!preg_match("/[a-zA-Z]+(\/[a-zA-Z]+)*/", $documentName)) {
- $documentName = "Document404";
- }
- $documentName = strtoupper($documentName[0]) . substr($documentName, 1);
- $documentName = str_replace("/", "\\", $documentName);
- $class = "\\Documents\\$documentName";
- $file = getClassPath($class);
- if(!file_exists($file) || !is_subclass_of($class, Document::class)) {
- $document = new Document404($user);
+ $req = new \Api\Routes\Find($user);
+ $success = $req->execute(array("request" => $documentName));
+ $response = "";
+ if (!$success) {
+ $response = "Unable to find route: " . $req->getLastError();
} else {
- $document = new $class($user);
+ $route = $req->getResult()["route"];
+ if (is_null($route)) {
+ $response = (new Document404($user))->getCode();
+ } else {
+ $target = trim(explode("\n", $route["target"])[0]);
+ switch ($route["action"]) {
+ case "redirect_temporary":
+ http_send_status(307);
+ header("Location: $target");
+ break;
+ case "redirect_permanently":
+ http_send_status(308);
+ header("Location: $target");
+ break;
+ case "static":
+ http_send_status(501);
+ $response = "Not implemented yet.";
+ break;
+ case "dynamic":
+ $view = $route["extra"] ?? "";
+ $file = getClassPath($target);
+ if(!file_exists($file) || !is_subclass_of($target, Document::class)) {
+ $document = new Document404($user);
+ } else {
+ $document = new $target($user);
+ }
+
+ $response = $document->getCode();
+ break;
+ }
+ }
}
$user->processVisit();
- $response = $document->getCode();
}
}
diff --git a/src/src/.htaccess b/src/src/.htaccess
deleted file mode 100644
index 3bc3c22..0000000
--- a/src/src/.htaccess
+++ /dev/null
@@ -1 +0,0 @@
-DENY FROM ALL;
\ No newline at end of file
diff --git a/test/.htaccess b/test/.htaccess
deleted file mode 100644
index d3223d4..0000000
--- a/test/.htaccess
+++ /dev/null
@@ -1 +0,0 @@
-DENY FROM ALL