diff --git a/.htaccess b/.htaccess index 3db7ac6..7d971ed 100644 --- a/.htaccess +++ b/.htaccess @@ -3,3 +3,4 @@ Options -Indexes RewriteEngine On RewriteRule ^api/(.*)?$ index.php?api=$1&$2 [L,QSA] +RewriteRule ^(?!((js|css|img|fonts|api)($|\/)))(.*)?$ index.php?site=$1&$2 [L,QSA] diff --git a/core/Api/CreateApiKey.class.php b/core/Api/CreateApiKey.class.php new file mode 100644 index 0000000..80ff0e4 --- /dev/null +++ b/core/Api/CreateApiKey.class.php @@ -0,0 +1,31 @@ +apiKeyAllowed = false; + $this->loginRequired = true; + } + + public function execute($values = array()) { + + if(!parent::execute($values)) { + return false; + } + + $apiKey = generateRandomString(64); + $query = "INSERT INTO ApiKey (uidUser, api_key, valid_until) VALUES (?,?,(SELECT DATE_ADD(now(), INTERVAL 30 DAY)))"; + $request = new ExecuteStatement($this->user); + $this->success = $request->execute(array("query" => $query, $this->user->getId(), $apiKey)); + $this->lastError = $request->getLastError(); + $this->result["api_key"] = $apiKey; + $this->result["valid_until"] = "TODO"; + $this->result["uid"] = $this->user->getSQL()->getLastInsertId(); + return $this->success; + } +}; + +?> diff --git a/core/Api/External/RequestData.class.php b/core/Api/External/RequestData.class.php new file mode 100644 index 0000000..468883b --- /dev/null +++ b/core/Api/External/RequestData.class.php @@ -0,0 +1,82 @@ + new StringType("url", 256) + )); + $this->isPublic = false; + } + + private function requestURL() { + $url = $this->getParam("url"); + + $ckfile = tempnam("/tmp", 'cookiename'); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + // curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_COOKIESESSION, true); + curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); + curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); + $data = curl_exec($ch); + $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + $success = false; + if(curl_errno($ch)) { + $this->lastError = curl_error($ch); + } else if($statusCode != 200) { + $this->lastError = "External Site returned status code: " . $statusCode; + } else { + $this->result["data"] = $data; + $this->result["cached"] = false; + $success = true; + } + + unlink($ckfile); + curl_close ($ch); + return $success; + } + + public function execute($values = array()) { + if(!parent::execute($values)) { + return false; + } + + $url = $this->getParam("url"); + $expires = $this->getParam("expires"); + + $query = "SELECT data, expires FROM ExternalSiteCache WHERE url=?"; + $req = new \Api\ExecuteSelect($this->user); + $this->success = $req->execute(array("query" => $query, $url)); + $this->lastError = $req->getLastError(); + + if($this->success) { + $mustRevalidate = true; + + if(!empty($req->getResult()['rows'])) { + $row = $req->getResult()['rows'][0]; + if($row["expires"] == null || !isinPast($row["expires"])) { + $mustRevalidate = false; + $this->result["data"] = $row["data"]; + $this->result["expires"] = $row["expires"]; + $this->result["cached"] = true; + } + } + + if($mustRevalidate) { + $this->success = $this->requestURL(); + } + } + + return $this->success; + } +}; + +?> diff --git a/core/Api/External/WriteData.class.php b/core/Api/External/WriteData.class.php new file mode 100644 index 0000000..d982a13 --- /dev/null +++ b/core/Api/External/WriteData.class.php @@ -0,0 +1,44 @@ + new StringType("url", 256), + "data" => new StringType("data", -1), + "expires" => new Parameter("expires", Parameter::TYPE_INT, false, 0), + )); + $this->isPublic = false; + } + + public function execute($values = array()) { + if(!parent::execute($values)) { + return false; + } + + $url = $this->getParam("url"); + $data = $this->getParam("data"); + $expires = $this->getParam("expires"); + + if($expires > 0) { + $expires = getDateTime(new \DateTime("+${expires} seconds")); + } else { + $expires = null; + } + + $query = "INSERT INTO ExternalSiteCache (url, data, expires) VALUES(?,?,?) + ON DUPLICATE KEY UPDATE data=?, expires=?"; + + $request = new \Api\ExecuteStatement($this->user); + $this->success = $request->execute(array("query" => $query, $url, $data, $expires, $data, $expires)); + $this->lastError = $request->getLastError(); + + return $this->lastError; + } +} + +?> diff --git a/core/Api/GetApiKeys.class.php b/core/Api/GetApiKeys.class.php new file mode 100644 index 0000000..bad7539 --- /dev/null +++ b/core/Api/GetApiKeys.class.php @@ -0,0 +1,33 @@ +loginRequired = true; + } + + public function execute($values = array()) { + if(!parent::execute($values)) { + return false; + } + + $query = "SELECT ApiKey.uid, ApiKey.api_key, ApiKey.valid_until + FROM ApiKey + WHERE ApiKey.uidUser = ? + AND ApiKey.valid_until > now()"; + $request = new ExecuteSelect($this->user); + $this->success = $request->execute(array("query" => $query, $this->user->getId())); + $this->lastError = $request->getLastError(); + + if($this->success) { + $this->result["api_keys"] = $request->getResult()['rows']; + } + + return $this->success; + } +}; + +?> diff --git a/core/Api/RefreshApiKey.class.php b/core/Api/RefreshApiKey.class.php new file mode 100644 index 0000000..cb43765 --- /dev/null +++ b/core/Api/RefreshApiKey.class.php @@ -0,0 +1,48 @@ + new Parameter("id", Parameter::TYPE_INT), + )); + $this->loginRequired = true; + } + + private function apiKeyExists() { + $id = $this->getParam("id"); + $query = "SELECT * FROM ApiKey WHERE uid = ? AND uidUser = ? AND valid_until > now()"; + $request = new ExecuteSelect($this->user); + $this->success = $request->execute(array("query" => $query, $id, $this->user->getId())); + $this->lastError = $request->getLastError(); + + if($this->success && count($request->getResult()['rows']) == 0) { + $this->success = false; + $this->lastError = "This API-Key does not exist."; + } + + return $this->success; + } + + public function execute($values = array()) { + if(!parent::execute($values)) { + return false; + } + + $id = $this->getParam("id"); + if(!$this->apiKeyExists()) + return false; + + $query = "UPDATE ApiKey SET valid_until = (SELECT DATE_ADD(now(), INTERVAL 30 DAY)) WHERE uid = ? AND uidUser = ? AND valid_until > now()"; + $request = new ExecuteStatement($this->user); + $this->success = $request->execute(array("query" => $query, $id, $this->user->getId())); + $this->lastError = $request->getLastError(); + + return $this->success; + } +}; + +?> diff --git a/core/Api/RevokeApiKey.class.php b/core/Api/RevokeApiKey.class.php new file mode 100644 index 0000000..8ff01fa --- /dev/null +++ b/core/Api/RevokeApiKey.class.php @@ -0,0 +1,48 @@ + new Parameter("id", Parameter::TYPE_INT), + )); + $this->loginRequired = true; + } + + private function apiKeyExists() { + $id = $this->getParam("id"); + $query = "SELECT * FROM ApiKey WHERE uid = ? AND uidUser = ? AND valid_until > now()"; + $request = new ExecuteSelect($this->user); + $this->success = $request->execute(array("query" => $query, $id, $this->user->getId())); + $this->lastError = $request->getLastError(); + + if($this->success && count($request->getResult()['rows']) == 0) { + $this->success = false; + $this->lastError = "This API-Key does not exist."; + } + + return $this->success; + } + + public function execute($aValues = array()) { + if(!parent::execute($aValues)) { + return false; + } + + $id = $this->getParam("id"); + if(!$this->apiKeyExists()) + return false; + + $query = "DELETE FROM ApiKey WHERE valid_until < now() OR (uid = ? AND uidUser = ?)"; + $request = new ExecuteStatement($this->user); + $this->success = $request->execute(array("query" => $query, $id, $this->user->getId())); + $this->lastError = $request->getLastError(); + + return $this->success; + } +}; + +?> diff --git a/core/Api/SendMail.class.php b/core/Api/SendMail.class.php new file mode 100644 index 0000000..d1d80fa --- /dev/null +++ b/core/Api/SendMail.class.php @@ -0,0 +1,58 @@ + new Parameter('from', Parameter::TYPE_EMAIL), + 'to' => new Parameter('to', Parameter::TYPE_EMAIL), + 'subject' => new StringType('subject', -1), + 'body' => new StringType('body', -1), + 'fromName' => new StringType('fromName', -1, true, ''), + 'replyTo' => new Parameter('to', Parameter::TYPE_EMAIL, true, ''), + )); + $this->isPublic = false; + } + + public function execute($values = array()) { + if(!parent::execute($values)) { + return false; + } + + $mailData = getMailData(); + $mail = new \External\PHPMailer\PHPMailer; + $mail->IsSMTP(); + $mail->setFrom($this->getParam('from'), $this->getParam('fromName')); + $mail->addAddress($this->getParam('to')); + $mail->Subject = $this->getParam('subject'); + $mail->SMTPDebug = 0; + $mail->Host = $mailData->getHost(); + $mail->Port = $mailData->getPort(); + $mail->SMTPAuth = true; + $mail->Username = $mailData->getLogin(); + $mail->Password = $mailData->getPassword(); + $mail->SMTPSecure = 'tls'; + $mail->IsHTML(true); + $mail->CharSet = 'UTF-8'; + $mail->Body = $this->getParam('body'); + + $replyTo = $this->getParam('replyTo'); + if(!is_null($replyTo) && !empty($replyTo)) { + $mail->AddReplyTo($replyTo, $this->getParam('fromName')); + } + + $this->success = @$mail->Send(); + if (!$this->success) { + $this->lastError = 'Error sending Mail: ' . $mail->ErrorInfo; + error_log("sendMail() failed: " . $mail->ErrorInfo); + } + + return $this->success; + } +}; + +?> diff --git a/core/Api/SetLanguage.php b/core/Api/SetLanguage.class.php similarity index 100% rename from core/Api/SetLanguage.php rename to core/Api/SetLanguage.class.php diff --git a/core/Documents/Install.class.php b/core/Documents/Install.class.php index 77a2f3e..f917714 100644 --- a/core/Documents/Install.class.php +++ b/core/Documents/Install.class.php @@ -685,13 +685,13 @@ namespace Documents\Install { die(json_encode($response)); } - if($this->currentStep == self::CHECKING_REQUIRMENTS) { + /*if($this->currentStep == self::CHECKING_REQUIRMENTS) { $this->getDocument()->getHead()->addJSCode(" $(document).ready(function() { retry(); }); "); - } + }*/ $progressSidebar = $this->createProgressSidebar(); $progressMainview = $this->createProgessMainview(); diff --git a/core/Views/Login.class.php b/core/Views/Login.class.php index 46ae1c8..3d12b20 100644 --- a/core/Views/Login.class.php +++ b/core/Views/Login.class.php @@ -43,7 +43,7 @@ class Login extends \View {
$flags - $iconBack$backToStartPage + $iconBack $backToStartPage $accountCreated "; diff --git a/core/core.php b/core/core.php index 4eb87e5..b4be22a 100644 --- a/core/core.php +++ b/core/core.php @@ -25,7 +25,7 @@ } function getProtocol() { - return stripos($_SERVER['SERVER_PROTOCOL'],'https') === 0 ? 'https://' : 'http://'; + return stripos($_SERVER['SERVER_PROTOCOL'],'https') === 0 ? 'https' : 'http'; } function includeDir($dir, $aIgnore = array(), $recursive = false) { diff --git a/index.php b/index.php index 5d2dbeb..cb17715 100644 --- a/index.php +++ b/index.php @@ -41,14 +41,19 @@ if(isset($_GET["api"]) && is_string($_GET["api"])) { header("403 Forbidden"); $response = ""; } else if(!preg_match("/[a-zA-Z]+(\/[a-zA-Z]+)*/", $apiFunction)) { + header("400 Bad Request"); $response = createError("Invalid Method"); } else { $apiFunction = strtoupper($apiFunction[0]) . substr($apiFunction, 1); + $apiFunction = str_replace("/", "\\", $apiFunction); $class = "\\Api\\$apiFunction"; $file = getClassPath($class); if(!file_exists($file)) { header("404 Not Found"); $response = createError("Not found"); + } else if(!is_subclass_of($class, \Api\Request::class)) { + header("400 Bad Request"); + $response = createError("Inalid Method"); } else { $request = new $class($user, true); $success = $request->execute();