diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79f21cc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +juggl/config/config.txt +juggl/config/config.path diff --git a/juggl/config/config.path.sample b/juggl/config/config.path.sample new file mode 100644 index 0000000..35b61a7 --- /dev/null +++ b/juggl/config/config.path.sample @@ -0,0 +1 @@ +relativepath=config/config.txt \ No newline at end of file diff --git a/juggl/config/config.txt.sample b/juggl/config/config.txt.sample new file mode 100644 index 0000000..b102c26 --- /dev/null +++ b/juggl/config/config.txt.sample @@ -0,0 +1,4 @@ +host=HOST +dbname=DBNAME +username=USERNAME +password=PASSWORD \ No newline at end of file diff --git a/juggl/services/apiBranch.inc.php b/juggl/services/apiBranch.inc.php new file mode 100644 index 0000000..62601e9 --- /dev/null +++ b/juggl/services/apiBranch.inc.php @@ -0,0 +1,38 @@ +isAuthenticated($_SESSION, $_REQUEST)) { + $this->authenticationMissing($this->getParams()); + return; + } + } + + $currentType = currentRequestType(); + if($currentType === RequestType::GET) { + $this->get($this->getParams()); + } else if ($currentType === RequestType::POST) { + $this->post($this->getParams()); + } + } + + private function getParams() { + $content = json_decode(file_get_contents('php://input'), true); + $contentArray = array("json" => $content); + return new ParamCleaner(array_merge($contentArray, $_REQUEST, $_SESSION, $_FILES)); + } +} +?> \ No newline at end of file diff --git a/juggl/services/authenticator.inc.php b/juggl/services/authenticator.inc.php new file mode 100644 index 0000000..8cb07d9 --- /dev/null +++ b/juggl/services/authenticator.inc.php @@ -0,0 +1,43 @@ +select("api_keys", array("quota_max", "client_key")); + $db->where("client_key", Comparison::EQUAL, $key); + + $result = $db->execute(); + + if (count($result) == 1 && $result[0]['quota_max'] > 0) + return true; + else + return false; + } + + function isSessionAuthenticated($session) { + if (isset($session['stayloggedin'])) { + if($session["stayloggedin"]) { + return true; + } + } + + if (!isset($session['until'])) { + return false; + } + + if ($session['until'] > time() || $session['until'] == 0) + return true; + else + return false; + } + + function isAuthenticated($session, $request) { + if (isset($request['key'])) { + return $this->isApiKeyAuthenticated($request['key']); + } else { + return $this->isSessionAuthenticated($session); + } + } +} +?> \ No newline at end of file diff --git a/juggl/services/basicEnum.inc.php b/juggl/services/basicEnum.inc.php new file mode 100644 index 0000000..5805eea --- /dev/null +++ b/juggl/services/basicEnum.inc.php @@ -0,0 +1,33 @@ +getConstants(); + } + return self::$constCacheArray[$calledClass]; + } + + public static function isValidName($name, $strict = false) { + $constants = self::getConstants(); + + if ($strict) { + return array_key_exists($name, $constants); + } + + $keys = array_map('strtolower', array_keys($constants)); + return in_array(strtolower($name), $keys); + } + + public static function isValidValue($value, $strict = true) { + $values = array_values(self::getConstants()); + return in_array($value, $values, $strict); + } +} +?> \ No newline at end of file diff --git a/juggl/services/configReader.inc.php b/juggl/services/configReader.inc.php new file mode 100644 index 0000000..c9bcd69 --- /dev/null +++ b/juggl/services/configReader.inc.php @@ -0,0 +1,45 @@ +configuration = array(); + foreach (file($path) as $line) { + $valuePair = $this->convertLine(trim($line)); + + if ($valuePair === false) + continue; + $this->configuration[$valuePair['key']] = $valuePair['value']; + } + } + + function getSetting ($key) { + if (array_key_exists($key, $this->configuration) == false) + return NULL; + + return $this->configuration[$key]; + } + + private function convertLine($line) { + if ($line == "") + return False; + + $splitted = explode (self::VALUE_SEPARATOR, $line, 2); + $key = $splitted[0]; + + $value = ""; + for ($i = 1; $i < sizeof($splitted); $i++) { + if ($i > 1) { + $value .= "="; + } + $value .= $splitted[$i]; + } + + return ['key' => $key, 'value' => $value]; + } +} +?> \ No newline at end of file diff --git a/juggl/services/dbOperations.inc.php b/juggl/services/dbOperations.inc.php new file mode 100644 index 0000000..e73ecb9 --- /dev/null +++ b/juggl/services/dbOperations.inc.php @@ -0,0 +1,190 @@ +resetQuery(); + } + + function resetQuery() { + $this->query = ""; + $this->data = array(); + $this->table = ""; + } + + private function openConnection () { + $config = new ConfigReader(); + $config->readFile(__DIR__."/../config/config.path"); + $config->readFile(__DIR__."/../".$config->getSetting("relativepath")); + + $host = $config->getSetting('host'); + $dbname = $config->getSetting('dbname'); + $dsn = "mysql:host=$host;dbname=$dbname"; + + $options = array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC); + + $this->pdo = new PDO($dsn, $config->getSetting('username'), $config->getSetting('password'), $options); + } + + function select (string $table, array $attributes = array()) { + $this->table = $table; + if (count($attributes) == 0) + $formattedAttributes = "*"; + else { + for($i = 0; $i < count($attributes); $i++){ + $a = $attributes[$i]; + if (strpos($a, ".") === false) { + $attributes[$i] = "$this->table.$a"; + } + } + $formattedAttributes = implode(', ', $attributes); + } + + $this->addToQuery("SELECT $formattedAttributes FROM $table"); + + return $this; + } + + + function orderBy (string $attribute, string $order = Order::ASC) { + $this->addToQuery("ORDER BY $attribute $order"); + + return $this; + } + + static function getLatestIdInTable (string $table, string $attribute = "id") { + $db = new DbOperations(); + $db->select($table, array($attribute)); + $db->orderBy($attribute, Order::DESC); + + return $db->execute()[0][$attribute]; + } + + function insert (string $table, array $data) { + $this->table = $table; + + $attributes = implode(", ", array_keys($data)); + $valuesIds = array(); + foreach($data as $attribute => $value) { + $valuesIds[] = $this->addData($value, $attribute); + } + $values = implode(" , ", $valuesIds); + + $this->addToQuery("INSERT INTO $table ( $attributes ) VALUES ( $values )"); + + return $this; + } + + function update (string $table, array $data) { + $this->table = $table; + + $sets = array(); + foreach($data as $attribute => $value) { + $valueId = $this->addData($value, $attribute); + $sets[] = "$attribute = $valueId"; + } + $setString = implode(", ", $sets); + + $this->addToQuery("UPDATE $table SET $setString"); + + return $this; + } + + function delete (string $table) { + $this->table = $table; + + $this->addToQuery("DELETE FROM $table"); + + return $this; + } + + private function addToQuery (string $phrase) { + $delimeter = " "; + $this->query = implode($delimeter, array($this->query, $phrase)); + } + + function where (string $attribute, string $comparison, $value, string $connector = Combination::AND) { + if (Comparison::isValidValue($comparison) == false) + return; + + $keyWord = "WHERE"; + if (!(strpos($this->query, $keyWord) === false)) + $keyWord = $connector; + + $valueId = $this->addData($value, $attribute); + $this->addToQuery("$keyWord $attribute $comparison $valueId"); + + return $this; + } + + function innerJoin (string $table, string $externAttribute, string $internAttribute, string $internTable = "") { + if ($internTable === "") { + $internTable = $this->table; + } + + $innerJoin = "INNER JOIN $table ON $table.$externAttribute = $internTable.$internAttribute"; + + $this->addToQuery($innerJoin); + + return $this; + } + + private function addData($data, $attribute) { + $name = str_replace(".", "", $attribute); + + $this->data[$name] = $data; + return ":".$name; + } + + function execute() { + try{ + $this->openConnection(); + + $pdoQuery = $this->pdo->prepare($this->query); + $pdoQuery->execute($this->data); + + $results = array(); + while($row = $pdoQuery->fetch()) { + $results[] = $row; + } + + $this->resetQuery(); + + return $results; + } catch (PDOException $e) { + // TODO: Hide errors from user and log them + print($e); + return array(); + } + } + + function sql(string $sqlStatement, array $data) { + $this->query = $sqlStatement; + + foreach($data as $attribute => $value) { + $this->addData($value, $attribute); + } + } +} + +abstract class Comparison extends BasicEnum { + const EQUAL = "="; + const GREATER_THAN = ">"; + const GREATER_THAN_OR_EQUAL = ">="; + const LESS_THAN = "<"; + const LESS_THAN_OR_EQUAL = "<="; + const UNEQUAL = "!="; + const LIKE = "LIKE"; +} + +abstract class Combination extends BasicEnum { + const AND = "AND"; + const OR = "OR"; +} + +abstract class Order extends BasicEnum { + const ASC = "ASC"; + const DESC = "DESC"; +} +?> \ No newline at end of file diff --git a/juggl/services/jsonBuilder.inc.php b/juggl/services/jsonBuilder.inc.php new file mode 100644 index 0000000..9cb0577 --- /dev/null +++ b/juggl/services/jsonBuilder.inc.php @@ -0,0 +1,37 @@ +jsonData = array(); + } + + function getJson () { + return json_encode($this->jsonData, JSON_FORCE_OBJECT); + } + + function getArray () { + return $this->jsonData; + } + + function addCategories (array $categories) { + $columns = array("id" => "", + "name" => ""); + + foreach ($categories as $category) { + $this->jsonData['categories'] = array(); + $this->jsonData['categories'][] = $this->createJsonArray($category, $columns); + } + return $this; + } + + private function createJsonArray (array $data, array $columns) { + $jsonArray = array(); + foreach ($columns as $key => $column) { + if ($column === "") { + $column = $key; + } + $jsonArray[$key] = $data[$column]; + } + return $jsonArray; + } +} +?> \ No newline at end of file diff --git a/juggl/services/paramCleaner.inc.php b/juggl/services/paramCleaner.inc.php new file mode 100644 index 0000000..e6ef868 --- /dev/null +++ b/juggl/services/paramCleaner.inc.php @@ -0,0 +1,41 @@ +sourceParams = $params; + $this->selectedParams = $params; + $this->errorCount = 0; + $this->errorMessage = ""; + } + + function select (string $prop = "") { + if ($prop == "") { + $this->selectedParams = $this->sourceParams; + } else { + $this->selectedParams = $this->selectedParams[$prop]; + } + } + + function get (string $prop) { + if(isset($this->selectedParams[$prop])) { + return $this->selectedParams[$prop]; + } else { + $this->errorCount += 1; + $this->errorMessage .= "Property \"{$prop}\" missing. "; + return null; + } + } + + function hasErrorOccurred () { + return $this->errorCount > 0; + } + + function getErrorMessage () { + return $this->errorMessage; + } + + function resetErrors () { + $this->errorMessage = ""; + $this->errorCount = 0; + } +} +?> \ No newline at end of file diff --git a/juggl/services/requestTypes.inc.php b/juggl/services/requestTypes.inc.php new file mode 100644 index 0000000..97607e6 --- /dev/null +++ b/juggl/services/requestTypes.inc.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/juggl/services/responses.inc.php b/juggl/services/responses.inc.php new file mode 100644 index 0000000..51c0cb7 --- /dev/null +++ b/juggl/services/responses.inc.php @@ -0,0 +1,25 @@ +getJson()); +} + +function respondHtml(string $html) { + print($html); +} + +function respondStatus(int $statusCode, string $message = "") { + http_response_code($statusCode); + die($message); +} + +function redirectBack() { + header("Location: {$_SERVER['HTTP_REFERER']}"); +} + +function redirectTo($url) { + header("Location: {$url}"); +} +?> \ No newline at end of file diff --git a/juggl/timetracking.php b/juggl/timetracking.php new file mode 100644 index 0000000..246799e --- /dev/null +++ b/juggl/timetracking.php @@ -0,0 +1,17 @@ +execute(); +?> \ No newline at end of file