commit bda6f5faf23138e06a3953bf705d667cb42c2277 Author: Jill Stingray Date: Fri May 29 21:49:16 2020 +0300 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fe420c9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +* text=auto +*.* text eol=lf + +*.dat binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e15301f --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +/vendor +/chandler.yml + +/extensions/available/* +/extensions/enabled/* +!/extensions/available/.gitkeep +!/extensions/enabled/.gitkeep + +/tmp/cache/di_* +/tmp/plugin_artifacts/* +/tmp/cache/database/* +/tmp/cache/templates/* +/tmp/cache/yaml/* +!/tmp/plugin_artifacts/.gitkeep +!/tmp/cache/database/.gitkeep +!/tmp/cache/templates/.gitkeep +!/tmp/cache/yaml/.gitkeep + +/htdocs/* +!/htdocs/.htaccess +!/htdocs/index.php diff --git a/3rdparty/maxmind/GeoIP.dat b/3rdparty/maxmind/GeoIP.dat new file mode 100644 index 0000000..8106a53 Binary files /dev/null and b/3rdparty/maxmind/GeoIP.dat differ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..264cb45 --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2020, Veselcraft Originals + +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. diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..7b902dc --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,23 @@ +You will need the following software for the installation: +* Apache Web Server (2.4 or later) +* Composer (for setup) +* `ln` program (for setup, comes with GNU Coreutils) +* PHP (7.3 or later) +* YAML extension +* Percona Server or MySQL 8+ (with legacy auth mechanism) + +Please note that libchandler uses Sodium PHP extension. +This extension is included in default php7.3+ setup, but some hosting providers disable it. +Please, contact your hosting provider and ask them whether sodium is available. +Also, some plugins may require some additional dependencies from Packagist/NPM, so, you +may need to have Yarn installed to correctly setup dependencies. + +Installation steps: +* Download this repo as archive and extract it +* Run `composer install` +* Download plugin, that provides Web App and extract it to `extensions/available` +* Symlink plugin folder from `extensions/available` to `extensions/enabled` +* Edit example config and remove `-example` from its name +* * Set root app to your Web App plugin +* * Generate your secret key (Random string, which length is exactly 128 characters) +* Create new VHost and point it's documentroot to `htdocs` folder diff --git a/README.md b/README.md new file mode 100644 index 0000000..71104e6 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Chandler +Chandler is PHP-based web-framework/web-portal. By itself it's pretty useless, but you can install plugins/apps. + +# Plugins +Plugins may provide a Web Application or be a library or hook. +Web Apps are mounted to a path like this: `/` (where `id = app id`), but one app can be mounted to root. + +# State of this repo +This product is still in development phase, we are currently writing documentation/tests and API is going to change. diff --git a/chandler-example.yml b/chandler-example.yml new file mode 100644 index 0000000..79e4ac6 --- /dev/null +++ b/chandler-example.yml @@ -0,0 +1,18 @@ +chandler: + debug: true + websiteUrl: null + rootApp: "root" + + preferences: + appendExtension: "xhtml" + adminUrl: "/chandlerd" + exposeChandler: true + + database: + dsn: "mysql:host=localhost;dbname=db" + user: "root" + password: "root" + + security: + secret: "" + sessionDuration: 14 diff --git a/chandler/Bootstrap.php b/chandler/Bootstrap.php new file mode 100644 index 0000000..d5c8697 --- /dev/null +++ b/chandler/Bootstrap.php @@ -0,0 +1,140 @@ + + * @internal + */ +class Bootstrap +{ + /** + * Starts Tracy debugger session and installs panels. + * + * @internal + * @return void + */ + private function registerDebugger(): void + { + Debugger::enable(CHANDLER_ROOT_CONF["debug"] ? Debugger::DEVELOPMENT : Debugger::PRODUCTION); + Debugger::getBar()->addPanel(new Chandler\Debug\DatabasePanel); + } + + /** + * Loads procedural APIs. + * + * @internal + * @return void + */ + private function registerFunctions(): void + { + foreach(glob(CHANDLER_ROOT . "/chandler/procedural/*.php") as $procDef) + require $procDef; + } + + /** + * Set ups autoloaders. + * + * @internal + * @return void + */ + private function registerAutoloaders(): void + { + spl_autoload_register(function($class): void + { + if(strpos($class, "Chandler\\") !== 0) return; + + require_once(str_replace("\\", "/", str_replace("Chandler\\", CHANDLER_ROOT . "/chandler/", $class)) . ".php"); + }, true, true); + } + + /** + * Defines constant CONNECTING_IP, that stores end user's IP address. + * Uses X-Forwarded-For if present. + * + * @internal + * @return void + */ + private function defineIP(): void + { + if(isset($_SERVER["HTTP_X_FORWARDED_FOR"])) { + $path = explode(", ", $_SERVER["HTTP_X_FORWARDED_FOR"]); + $ip = $path[0]; + } else { + $ip = $_SERVER["REMOTE_ADDR"]; + } + + define("CONNECTING_IP", $ip, false); + } + + /** + * Initializes GeoIP, sets DB directory. + * + * @internal + * @return void + */ + private function setupGeoIP(): void + { + geoip_setup_custom_directory(CHANDLER_ROOT . "/3rdparty/maxmind/"); + } + + /** + * Bootstraps extensions. + * + * @internal + * @return void + */ + private function igniteExtensions(): void + { + Chandler\Extensions\ExtensionManager::i(); + } + + /** + * Starts router and serves request. + * + * @internal + * @param string $url Request URL + * @return void + */ + private function route(string $url): void + { + ob_start(); + + $router = Chandler\MVC\Routing\Router::i(); + if(($output = $router->execute($url, NULL)) !== null) + echo $output; + else + chandler_http_panic(404, "Not Found", "No routes for $url."); + + ob_flush(); + ob_end_flush(); + flush(); + } + + /** + * Starts framework. + * + * @internal + * @return void + */ + function ignite(): void + { + header("Referrer-Policy: strict-origin-when-cross-origin"); + + $this->registerFunctions(); + $this->registerAutoloaders(); + $this->defineIP(); + $this->registerDebugger(); + $this->igniteExtensions(); + $this->route(function_exists("get_current_url") ? get_current_url() : $_SERVER["REQUEST_URI"]); + } +} + +return new Bootstrap; diff --git a/chandler/ControlPanel/includes/assert_user.php b/chandler/ControlPanel/includes/assert_user.php new file mode 100644 index 0000000..8c6449e --- /dev/null +++ b/chandler/ControlPanel/includes/assert_user.php @@ -0,0 +1,13 @@ +getUser(); + if(!$user) return NULL; + + return $user->can("access")->model("admin")->whichBelongsTo(NULL); +}); \ No newline at end of file diff --git a/chandler/ControlPanel/users/al_api_info.phtml b/chandler/ControlPanel/users/al_api_info.phtml new file mode 100644 index 0000000..715167b --- /dev/null +++ b/chandler/ControlPanel/users/al_api_info.phtml @@ -0,0 +1,50 @@ +getContext(); +$user = $db->table("ChandlerUsers")->where("id", $_GET["GUID"])->fetch(); +if(!$user) exit(header("HTTP/1.1 404 Not Found")); + +$info = [ + "id" => $user->id, + "login" => $user->login, + "isDeleted" => (bool) $user->deleted, +]; + +if($_GET["includeActionList"] ?? false) { + $info["permissions"] = []; + foreach((new Chandler\Security\User($user))->getPermissions()->getPermissions() as $perm) { + $info["permissions"][] = [ + "state" => [ + "humanReadable" => "Explicitly " . ucfirst($perm->status ? "allowed" : "disallowed"), + "state" => (bool) $perm->status, + ], + "conditions" => [ + ["humanReadable" => is_null($perm->context) + ? "Rule applied in all situations" + : ($perm->context === 0 + ? "Models, that are owned by $user->login" + : "Only model with ID = $perm->context"), + "context" => $perm->context,], + ], + "action" => $perm->action, + "model" => $perm->model, + ]; + } +} + +if($_GET["includeSessions"] ?? false) { + $info["sessions"] = []; + foreach($user->related("ChandlerTokens.user") as $token) { + $info["sessions"][] = [ + "token" => $token->token, + "ip" => $token->ip, + "userAgent" => $token->ua, + ]; + } +} + +header("Content-Type: application/json"); +echo json_encode($info); \ No newline at end of file diff --git a/chandler/Database/DBEntity.php b/chandler/Database/DBEntity.php new file mode 100644 index 0000000..321710d --- /dev/null +++ b/chandler/Database/DBEntity.php @@ -0,0 +1,102 @@ +getTable()->getName(); + if($_table !== $this->tableName) + throw new ISE("Invalid data supplied for model: table $_table is not compatible with table" . $this->tableName); + + $this->record = $row; + } + + function __call(string $fName, array $args) + { + if(substr($fName, 0, 3) === "set") { + $field = mb_strtolower(substr($fName, 3)); + $this->stateChanges($field, $args[0]); + } else { + throw new \Error("Call to undefined method " . get_class($this) . "::$fName"); + } + } + + private function getTable(): Selection + { + return DatabaseConnection::i()->getContext()->table($this->tableName); + } + + protected function getRecord(): ?ActiveRow + { + return $this->record; + } + + protected function stateChanges(string $column, $value): void + { + if(!is_null($this->record)) + $t = $this->record->{$column}; #Test if column exists + + $this->changes[$column] = $value; + } + + function getId(): int + { + return $this->getRecord()->id; + } + + function isDeleted(): bool + { + return (bool) $this->getRecord()->deleted; + } + + function delete(bool $softly = true): void + { + if(is_null($this->record)) + throw new ISE("Can't delete a model, that hasn't been flushed to DB. Have you forgotten to call save() first?"); + + if($softly) { + $this->record = $this->getTable()->where("id", $this->record->id)->update(["deleted" => true]); + } else { + $this->record->delete(); + $this->deleted = true; + } + } + + function undelete(): void + { + if(is_null($this->record)) + throw new ISE("Can't undelete a model, that hasn't been flushed to DB. Have you forgotten to call save() first?"); + + $this->getTable()->where("id", $this->record->id)->update(["deleted" => false]); + } + + function save(): void + { + if(is_null($this->record)) { + $this->record = $this->getTable()->insert($this->changes); + } else if($this->deleted) { + $this->record = $this->getTable()->insert((array) $this-->record); + } else { + $this->record->getTable()->where("id", $this->record->id)->update($this->changes); + $this->record = $this->getTable()->get($this->record->id); + } + + $this->changes = []; + } + + use \Nette\SmartObject; +} diff --git a/chandler/Database/DatabaseConnection.php b/chandler/Database/DatabaseConnection.php new file mode 100644 index 0000000..b530b88 --- /dev/null +++ b/chandler/Database/DatabaseConnection.php @@ -0,0 +1,82 @@ +connection = $connection; + $this->context = $context; + + if(CHANDLER_ROOT_CONF["debug"]) + $this->connection->onQuery = $this->getQueryCallback(); + } + + private function __clone() {} + private function __wakeup() {} + + protected function getQueryCallback(): array + { + return [(function($connection, $result) { + if($result instanceof \Nette\Database\DriverException) + return; + + if(!isset($GLOBALS["dbgSqlQueries"])) { + $GLOBALS["dbgSqlQueries"] = []; + $GLOBALS["dbgSqlTime"] = 0; + } + + $params = $result->getParameters(); + $GLOBALS["dbgSqlQueries"][] = str_replace(str_split(str_repeat("?", sizeof($params))), $params, $result->getQueryString()); + $GLOBALS["dbgSqlTime"] += $result->getTime(); + })]; + } + + function getConnection(): Database\Connection + { + return $this->connection; + } + + function getContext(): Database\Context + { + return $this->context; + } + + static function i(): DatabaseConnection + { + return static::$self ?? static::$self = new static( + CHANDLER_ROOT_CONF["database"]["dsn"], + CHANDLER_ROOT_CONF["database"]["user"], + CHANDLER_ROOT_CONF["database"]["password"] + ); + } + + static function connect(array $options): DatabaseConnection + { + $id = sha1(serialize($options)) . "__DATABASECONNECTION\$feafccc"; + if(!isset($GLOBALS[$id])) { + $GLOBALS[$id] = new static( + $options["dsn"], + $options["user"], + $options["password"], + isset($options["caching"]) ? ($options["caching"]["folder"] ?? NULL) : NULL + ); + } + + return $GLOBALS[$id]; + } +} diff --git a/chandler/Debug/DatabasePanel.php b/chandler/Debug/DatabasePanel.php new file mode 100644 index 0000000..ad437ea --- /dev/null +++ b/chandler/Debug/DatabasePanel.php @@ -0,0 +1,41 @@ + + $svg + $count queries ($time ms) + +EOF; + } + + public function getPanel() + { + $html = <<Queries: +
+
+ +HTML; + + foreach($GLOBALS["dbgSqlQueries"] as $query) { + $query = DbHelpers::dumpSql($query); + $html .= ""; + } + + $html .= "
$query
"; + + return $html; + } +} \ No newline at end of file diff --git a/chandler/Debug/templates/db-icon.svg b/chandler/Debug/templates/db-icon.svg new file mode 100644 index 0000000..f76c26a --- /dev/null +++ b/chandler/Debug/templates/db-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/chandler/Email/Email.php b/chandler/Email/Email.php new file mode 100644 index 0000000..feee839 --- /dev/null +++ b/chandler/Email/Email.php @@ -0,0 +1,24 @@ +setUsername(CHANDLER_ROOT_CONF["email"]["addr"]); + $transport->setPassword(CHANDLER_ROOT_CONF["email"]["pass"]); + + $message = new Swift_Message($subject); + $message->getHeaders()->addTextHeader("Sensitivity", "Company-Confidential"); + $message->setFrom(CHANDLER_ROOT_CONF["email"]["addr"]); + $message->setTo($to); + $message->setBody($html, "text/html"); + + $mailer = new Swift_Mailer($transport); + return $mailer->send($message); + } +} \ No newline at end of file diff --git a/chandler/Eventing/EventDispatcher.php b/chandler/Eventing/EventDispatcher.php new file mode 100644 index 0000000..e176997 --- /dev/null +++ b/chandler/Eventing/EventDispatcher.php @@ -0,0 +1,33 @@ +hooks[] = $hook; + + return true; + } + + function pushEvent(Events\Event $event): Events\Event + { + foreach($hooks as $hook) { + if($event instanceof Events\Cancelable) + if($event->isCancelled()) + break; + + $method = "on" . str_replace("Event", "", get_class($event)); + if(!method_exists($hook, $methodName)) continue; + + $hook->$method($event); + } + + return $event; + } + + use TSimpleSingleton; +} diff --git a/chandler/Eventing/Events/Cancelable.php b/chandler/Eventing/Events/Cancelable.php new file mode 100644 index 0000000..0cfd8e8 --- /dev/null +++ b/chandler/Eventing/Events/Cancelable.php @@ -0,0 +1,11 @@ +data = $data; + $this->code = $code; + $this->time = time(); + } + + function getData() + { + return $this->data; + } + + function getCode() + { + return $this->code; + } + + function getTime() + { + return $this->time; + } + + function isTainted() + { + return !$this->pristine; + } +} diff --git a/chandler/Extensions/ExtensionManager.php b/chandler/Extensions/ExtensionManager.php new file mode 100644 index 0000000..a95a298 --- /dev/null +++ b/chandler/Extensions/ExtensionManager.php @@ -0,0 +1,120 @@ +in(CHANDLER_EXTENSIONS_AVAILABLE) as $directory) { + $extensionName = $directory->getFilename(); + $directory = $directory->getRealPath(); + $config = "$directory/manifest.yml"; + + if(!file_exists($config)) { + trigger_error("Skipping $extensionName for not having a valid configuration file ($config is not found)", E_USER_WARNING); + continue; + } + + $this->extensions[$extensionName] = (object) chandler_parse_yaml($config); + $this->extensions[$extensionName]->id = $extensionName; + $this->extensions[$extensionName]->rawName = $directory; + $this->extensions[$extensionName]->enabled = false; + } + + foreach(Finder::find("*")->in(CHANDLER_EXTENSIONS_ENABLED) as $directory) { #findDirectories doesn't work with symlinks + if(!is_dir($directory->getRealPath())) continue; + + $extension = $directory->getFilename(); + + if(!array_key_exists($extension, $this->extensions)) { + trigger_error("Extension $extension is enabled, but not available, skipping", E_USER_WARNING); + continue; + } + + $this->extensions[$extension]->enabled = true; + } + + if(!array_key_exists(CHANDLER_ROOT_CONF["rootApp"], $this->extensions) || !$this->extensions[CHANDLER_ROOT_CONF["rootApp"]]->enabled) { + trigger_error("Selected root app is not available", E_USER_ERROR); + } + + $this->rootApp = CHANDLER_ROOT_CONF["rootApp"]; + $this->eventLoop = EventDispatcher::i(); + $this->router = Router::i(); + + $this->init(); + } + + private function init(): void + { + foreach($this->getExtensions(true) as $name => $configuration) { + spl_autoload_register(@create_function("\$class", " + if(!substr(\$class, 0, " . iconv_strlen("$name\\") . ") === \"$name\\\\\") return false; + + require_once CHANDLER_ROOT . \"/extensions/enabled/\" . str_replace(\"\\\\\", \"/\", \$class) . \".php\"; + ")); + + define(mb_strtoupper($name) . "_ROOT", CHANDLER_ROOT . "/extensions/enabled/$name", false); + define(mb_strtoupper($name) . "_ROOT_CONF", chandler_parse_yaml(CHANDLER_ROOT . "/extensions/enabled/$name/$name.yml"), false); + + if(isset($configuration->init)) + (require(CHANDLER_ROOT . "/extensions/enabled/$name/" . $configuration->init))(); + + if(is_dir($hooks = CHANDLER_EXTENSIONS_ENABLED . "/$name/Hooks")) { + foreach(Finder::findFiles("*Hook.php")->in($hooks) as $hookFile) { + $hookClassName = "$name\\Hooks\\" . str_replace(".php", "", end(explode("/", $hookFile))); + $hook = new $hookClassName; + + $this->eventLoop->addListener($hook); + } + } + + if(is_dir($app = CHANDLER_EXTENSIONS_ENABLED . "/$name/Web")) #"app" means "web app", thus variable is called $app + $this->router->readRoutes("$app/routes.yml", $name, $this->rootApp !== $name); + } + } + + function getExtensions(bool $onlyEnabled = false): array + { + return $onlyEnabled + ? array_filter($this->extensions, function($e) { return $e->enabled; }) + : $this->extensions; + } + + function getExtension(string $name): ?object + { + return @$this->extensions[$name]; + } + + function disableExtension(string $name): void + { + if(!array_key_exists($name, $this->getExtensions(true))) return; + + if(!unlink(CHANDLER_EXTENSIONS_ENABLED . "/$name")) throw new \Exception("Could not disable extension"); + } + + function enableExtension(string $name): void + { + if(array_key_exists($name, $this->getExtensions(true))) return; + + $path = CHANDLER_EXTENSIONS_AVAILABLE . "/$name"; + if(!is_dir($path)) throw new \Exception("Extension doesn't exist"); + + if(!symlink($path, str_replace("available", "enabled", $path))) throw new \Exception("Could not enable extension"); + } + + use TSimpleSingleton; +} diff --git a/chandler/MVC/Exceptions/InterruptedException.php b/chandler/MVC/Exceptions/InterruptedException.php new file mode 100644 index 0000000..b95c387 --- /dev/null +++ b/chandler/MVC/Exceptions/InterruptedException.php @@ -0,0 +1,5 @@ +)%"; + const ALIAS_REGEX = "%{(\??\!?([A-z]++))}%"; + + private $url = NULL; + private $routes = []; + private $statics = []; + private $scope = []; + + private $events; + + protected $types = [ + "num" => "(-?\d++)", + "text" => "([A-z0-9]++)", + "slug" => "([A-z0-9А-я\-_ ]++)", + ]; + + private function __construct() + { + $this->events = EventDispatcher::i(); + } + + private function computeRegExp(string $route, array $customAliases = [], ?string $prefix = NULL): string + { + $regexp = preg_replace_callback(Router::ALIAS_REGEX, function($matches) use ($customAliases) { + if($matches[1][0] === "?") { + $replacement = !isset($customAliases[$matches[2]]) + ? NULL + : ($matches[1][1] !== "!" ? "(" : "(?:") . $customAliases[$matches[2]] . ")"; + } else { + $replacement = $this->types[$matches[1]]; + } + + if(!$replacement) { + $exMessage = "Unknown type alias: $matches[1]."; + $exMessage .= " (Available options are: " . implode(", ", array_keys($this->types)); + if(sizeof($customAliases) > 0) + $exMessage .= " or any of these user-defined aliases: " . implode(", ", array_keys($customAliases)) . ")"; + else + $exMessage .= ")"; + + throw new Exceptions\UnknownTypeAliasException($exMessage); + } + + return $replacement; + }, addslashes($route)); + + if(!is_null($prefix)) { + $regexp = "\\/$prefix\\" . ($route === "/" ? "/" : "/$regexp"); + } + + return "%^$regexp$%"; + } + + function makeCSRFToken(Route $route, string $nonce): string + { + $key = hash("snefru", CHANDLER_ROOT_CONF["security"]["secret"] . bin2hex($nonce)); + + $data = $route->namespace; + $data .= Session::i()->get("tok", -1); + + return hash_hmac("snefru", $data, $key) . "#" . bin2hex($nonce); + } + + private function setCSRFStatus(Route $route): void + { + $GLOBALS["csrfCheck"] = false; + + $hash = ($_GET["hash"] ?? ($_POST["hash"] ?? false)); + if($hash !== false) { + $data = explode("#", $hash); + + try { + if(!isset($data[0]) || !isset($data[1])) throw new \SodiumException; + [$hash, $nonce] = $data; + + if(sodium_memcmp($this->makeCSRFToken($route, hex2bin($nonce)), "$hash#$nonce") === 0) + $GLOBALS["csrfCheck"] = true; + } catch(\SodiumException $ex) {} + } + + $GLOBALS["csrfToken"] = $this->makeCSRFToken($route, openssl_random_pseudo_bytes(4)); + } + + private function getDI(string $namespace): DI\Container + { + $loader = new DI\ContainerLoader(CHANDLER_ROOT . "/tmp/cache/di_$namespace", true); + $class = $loader->load(function($compiler) use ($namespace) { + $fileLoader = new \Nette\DI\Config\Loader; + $fileLoader->addAdapter("yml", \Nette\DI\Config\Adapters\NeonAdapter::class); + + $compiler->loadConfig(CHANDLER_EXTENSIONS_ENABLED . "/$namespace/Web/di.yml", $fileLoader); + }); + + return new $class; + } + + private function getPresenter(string $namespace, string $presenterName): ?IPresenter + { + $di = $this->getDI($namespace); + + $services = $di->findByType("\\$namespace\\Web\\Presenters\\$presenterName" . "Presenter", false); + return $di->getService($services[0], false); + } + + private function delegateView(string $filename, IPresenter $presenter): string + { + return $presenter->getTemplatingEngine()->renderToString($filename, $this->scope); + } + + private function delegateController(string $namespace, string $presenterName, string $action, array $parameters = []): string + { + $presenter = $this->getPresenter($namespace, $presenterName); + $action = ucfirst($action); + + try { + $presenter->onStartup(); + $presenter->{"render$action"}(...$parameters); + $presenter->onBeforeRender(); + + $this->scope += array_merge_recursive($presenter->getTemplateScope(), []); #TODO: add default parameters + #TODO: move this to delegateView + $output = $this->delegateView( + $this->scope["_template"] ?? CHANDLER_EXTENSIONS_ENABLED . "/$namespace/Web/Presenters/templates/$presenterName/$action.xml", + $presenter + ); + + $presenter->onAfterRender(); + } catch(InterruptedException $ex) {} + + $presenter->onStop(); + $presenter->onDestruction(); + $presenter = NULL; + + return $output; + } + + private function delegateRoute(Route $route, array $matches): string + { + $parameters = []; + + foreach($matches as $param) + $parameters[] = is_numeric($param) ? (int) $param : $param; + + $this->setCSRFStatus($route); + return $this->delegateController($route->namespace, $route->presenter, $route->action, $parameters); + } + + function delegateStatic(string $namespace, string $path): string + { + $static = $static = $this->statics[$namespace]; + if(!isset($static)) return "Fatal error: no route"; + + if(!file_exists($file = "$static/$path")) + return "Fatal error: no resource"; + + $hash = "W/\"" . hash_file("snefru", $file) . "\""; + if(isset($_SERVER["HTTP_IF_NONE_MATCH"])) + if($_SERVER["HTTP_IF_NONE_MATCH"] === $hash) + exit(header("HTTP/1.1 304")); + + header("Content-Type: " . system_extension_mime_type($file)); + header("Content-Size: " . filesize($file)); + header("ETag: $hash"); + + readfile($file); + + exit; + } + + function reverse(string $hotlink, ...$parameters): ?string + { + if(sizeof($j = explode("!", $hotlink)) === 2) + [$namespace, $hotlink] = $j; + else + $namespace = explode("\\", $this->scope["parentModule"])[0]; + + [$presenter, $action] = preg_split(Router::HANDLER_DELIMITER, $hotlink); + + foreach($this->routes as $route) { + if($route->namespace !== $namespace || $route->presenter !== $presenter) continue; + if(!is_null($action) && $route->action != $action) continue; + + $count = preg_match_all(Router::ALIAS_REGEX, $route->raw); + if($count != sizeof($parameters)) continue; + + $i = 0; + return preg_replace_callback(Router::ALIAS_REGEX, function() use ($parameters, &$i) { + return $parameters[$i++]; + }, $route->raw); + } + + return NULL; + } + + function push(?string $prefix, string $url, string $namespace, string $presenter, string $action, array $ph): void + { + $route = new Route; + $route->raw = $url; + if(!is_null($prefix)) + $route->raw = "/$prefix" . $route->raw; + + $route->regex = $this->computeRegExp($url, $ph, $prefix); + $route->namespace = $namespace; + $route->presenter = $presenter; + $route->action = $action; + + $this->routes[] = $route; + } + + function pushStatic(string $namespace, string $path): void + { + $this->statics[$namespace] = $path; + } + + function readRoutes(string $filename, string $namespace, bool $autoprefix = true): void + { + $config = yaml_parse_file($filename); + + if(isset($config["static"])) + $this->pushStatic($namespace, CHANDLER_EXTENSIONS_ENABLED . "/$namespace/Web/$config[static]"); + + foreach($config["routes"] as $route) { + $route = (object) $route; + $placeholders = $route->placeholders ?? []; + [$presenter, $action] = preg_split(Router::HANDLER_DELIMITER, $route->handler); + + $this->push($autoprefix ? $namespace : NULL, $route->url, $namespace, $presenter, $action, $placeholders); + } + } + + function getMatchingRoute(string $url): ?array + { + foreach($this->routes as $route) + if(preg_match($route->regex, $url, $matches)) + return [$route, array_slice($matches, 1)]; + + return NULL; + } + + function execute(string $url, ?string $parentModule = null): ?string + { + $this->url = parse_url($url, PHP_URL_PATH); + if(!is_null($parentModule)) { + $GLOBALS["parentModule"] = $parentModule; + $this->scope["parentModule"] = $GLOBALS["parentModule"]; + } + + if(preg_match("%^\/assets\/packages\/static\/([A-z_\\-]++)\/(.++)$%", $this->url, $matches)) { + [$j, $namespace, $file] = $matches; + return $this->delegateStatic($namespace, $file); + } + + $match = $this->getMatchingRoute($this->url); + if(!$match) + return NULL; + + return $this->delegateRoute(...$match); + } + + use TSimpleSingleton; +} diff --git a/chandler/MVC/SimplePresenter.php b/chandler/MVC/SimplePresenter.php new file mode 100644 index 0000000..347abb8 --- /dev/null +++ b/chandler/MVC/SimplePresenter.php @@ -0,0 +1,207 @@ +template = (object) []; + } + + function getTemplatingEngine(): TemplatingEngine + { + $latte = new TemplatingEngine; + $macros = new \Latte\Macros\MacroSet($latte->getCompiler()); + $latte->setTempDirectory(CHANDLER_ROOT . "/tmp/cache/templates"); + + $macros->addMacro("css", ' + $domain = "' . explode("\\", static::class)[0] . '"; + $file = (%node.array)[0]; + $realpath = CHANDLER_EXTENSIONS_ENABLED . "/$domain/Web/static/$file"; + if(file_exists($realpath)) { + $hash = "sha384-" . base64_encode(hash_file("sha384", $realpath, true)); + $mod = bin2hex(filemtime($realpath)); + echo ""; + } else { + echo ""; + } + '); + $macros->addMacro("script", ' + $domain = "' . explode("\\", static::class)[0] . '"; + $file = (%node.array)[0]; + $realpath = CHANDLER_EXTENSIONS_ENABLED . "/$domain/Web/static/$file"; + if(file_exists($realpath)) { + $hash = "sha384-" . base64_encode(hash_file("sha384", $realpath, true)); + $mod = bin2hex(filemtime($realpath)); + echo ""; + } else { + echo ""; + } + '); + $macros->addMacro("presenter", ' + $input = (%node.array); + + echo ""; + + $router = \Chandler\MVC\Routing\Router::i(); + $__out = $router->execute($router->reverse(...$input), "' . static::class . '"); + echo $__out; + + echo ""; + ' + ); + + return $latte; + } + + protected function throwError(int $code = 400, string $desc = "Bad Request", string $message = ""): void + { + if(!is_null($this->errorTemplate)) { + header("HTTP/1.0 $code $desc"); + + $ext = explode("\\", get_class($this))[0]; + $path = CHANDLER_EXTENSIONS_ENABLED . "/$ext/Web/Presenters/templates/" . $this->errorTemplate . ".xml"; + + $latte = new TemplatingEngine; + $latte->setTempDirectory(CHANDLER_ROOT . "/tmp/cache/templates"); + $latte->render($path, array_merge_recursive([ + "code" => $code, + "desc" => $desc, + "msg" => $message, + ], $this->getTemplateScope())); + exit; + } else { + chandler_http_panic($code, $desc, $message); + } + } + + protected function assertNoCSRF(): void + { + if(!$GLOBALS["csrfCheck"]) + $this->throwError(400, "Bad Request", "CSRF token is missing or invalid."); + } + + protected function terminate(): void + { + throw new Exceptions\InterruptedException; + } + + protected function notFound(): void + { + $this->throwError( + 404, + "Not Found", + "The resource you are looking for has been deleted, had its name changed or doesn't exist." + ); + } + + protected function getCaller(): string + { + return $GLOBALS["parentModule"] ?? "libchandler:absolute.0"; + } + + protected function redirect(string $location, int $code = 2): void + { + $code = 300 + $code; + if(($code <=> 300) !== 0 && $code > 399) return; + + header("HTTP/1.1 $code"); + header("Location: $location"); + exit; + } + + protected function pass(string $to, ...$args): void + { + $args = array_merge([$to], $args); + $router = \Chandler\MVC\Routing\Router::i(); + $__out = $router->execute($router->reverse(...$args), "libchandler:absolute.0"); + exit($__out); + } + + protected function sendmail(string $to, string $template, array $params): void + { + $emailDir = pathinfo($template, PATHINFO_DIRNAME); + $template .= ".eml.latte"; + + $renderedHTML = (new TemplatingEngine)->renderToString($template, $params); + $document = new \DOMDocument(); + $document->loadHTML($renderedHTML, LIBXML_NOEMPTYTAG); + $querySel = new \DOMXPath($document); + + $subject = $querySel->query("//title/text()")->item(0)->data; + + foreach($querySel->query("//link[@rel='stylesheet']") as $link) { + $style = $document->createElement("style"); + $style->setAttribute("id", uniqid("mail", true)); + $style->appendChild(new \DOMText(file_get_contents("$emailDir/assets/css/" . $link->getAttribute("href")))); + + $link->parentNode->appendChild($style); + $link->parentNode->removeChild($link); + } + + foreach($querySel->query("//img") as $image) { + $imagePath = "$emailDir/assets/res/" . $image->getAttribute("src"); + $type = pathinfo($imagePath, PATHINFO_EXTENSION); + $contents = base64_encode(file_get_contents($imagePath)); + + $image->setAttribute("src", "data:image/$type;base64,$contents"); + } + + \Chandler\Email\Email::send($to, $subject, $document->saveHTML()); + } + + protected function queryParam(string $index): ?string + { + return $_GET[$index] ?? NULL; + } + + protected function postParam(string $index): ?string + { + $this->assertNoCSRF(); + + return $_POST[$index] ?? NULL; + } + + protected function checkbox(string $name): bool + { + return ($this->postParam($name) ?? "off") === "on"; + } + + function getTemplateScope(): array + { + return (array) $this->template; + } + + function onStartup(): void + { + date_default_timezone_set("UTC"); + } + + function onBeforeRender(): void + { + $this->template->csrfToken = $GLOBALS["csrfToken"]; + } + + function onAfterRender(): void + {} + + function onStop(): void + {} + + function onDestruction(): void + {} + + use SmartObject; +} diff --git a/chandler/Patterns/ActiveRecord.php.old b/chandler/Patterns/ActiveRecord.php.old new file mode 100644 index 0000000..fae4254 --- /dev/null +++ b/chandler/Patterns/ActiveRecord.php.old @@ -0,0 +1,34 @@ +db = DatabaseConnection::i(); + $this->table = $this->db->table($this->tableName); + if(!is_null($row)) $this->row = $row; + + $this->resetQuery(); + } + + private function resetQuery(): void + { + $this->query = clone $this->table; + } + + function __call() +} diff --git a/chandler/Patterns/TSimpleSingleton.php b/chandler/Patterns/TSimpleSingleton.php new file mode 100644 index 0000000..d055b02 --- /dev/null +++ b/chandler/Patterns/TSimpleSingleton.php @@ -0,0 +1,16 @@ +db = DatabaseConnection::i()->getContext(); + $this->session = Session::i(); + } + + private function verifySuRights(string $uId): bool + { + + } + + private function makeToken(string $user, string $ip, string $ua): string + { + $data = ["user" => $user, "ip" => $ip, "ua" => $ua]; + $token = $this->db + ->table("ChandlerTokens") + ->where($data) + ->fetch(); + if(!$token) { + $this->db->table("ChandlerTokens")->insert($data); + $token = $this->db->table("ChandlerTokens")->where($data)->fetch(); + } + + return $token->token; + } + + static function verifyHash(string $input, string $hash): bool + { + try { + [$hash, $salt] = explode("$", $hash); + $userHash = bin2hex( + sodium_crypto_pwhash( + 16, + $input, + hex2bin($salt), + SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 + ) + ); + if(sodium_memcmp($hash, $userHash) !== 0) return false; + } catch(\SodiumException $ex) { + return false; + } + + return true; + } + + function getUser(): ?User + { + $token = $this->session->get("tok"); + if(!$token) return null; + + $token = $this->db + ->table("ChandlerTokens") + ->where([ + "token" => $token, + ]) + ->fetch(); + if(!$token) return null; + + if($token->ip === CONNECTING_IP && $token->ua === $_SERVER["HTTP_USER_AGENT"]) { + $su = $this->session->get("_su"); + $user = $this->db->table("ChandlerUsers")->get($su ?? $token->user); + if(!$user) return null; + + return new User($user, !is_null($su)); + } + + return null; + } + + function authenticate(string $user): void + { + $this->session->set("tok", $this->makeToken($user, CONNECTING_IP, $_SERVER["HTTP_USER_AGENT"])); + } + + function login(string $id, string $password): bool + { + $user = $this->db->table("ChandlerUsers")->get($id); + if(!$user) + return false; + else if(!$this->verifyHash($password, $user->passwordHash)) + return false; + + $this->authenticate($id); + return true; + } + + function logout(bool $revoke = false): bool + { + $token = $this->session->get("tok"); + if(!$token) return false; + + if($revoke) $this->db->table("ChandlerTokens")->where("id", $token)->delete(); + + $this->session->set("tok", NULL); + + return true; + } + + use TSimpleSingleton; +} diff --git a/chandler/Security/Authorization/Permission.php b/chandler/Security/Authorization/Permission.php new file mode 100644 index 0000000..9dccc5f --- /dev/null +++ b/chandler/Security/Authorization/Permission.php @@ -0,0 +1,17 @@ +perm = new Permission; + + $this->permissionManager = $permMan; + } + + function can(string $action): PermissionBuilder + { + $this->perm->action = $action; + + return $this; + } + + function model(string $model): PermissionBuilder + { + $this->perm->model = $model; + + return $this; + } + + function whichBelongsTo(?int $to) + { + $this->perm->context = $to; + + return is_null($this->permissionManager) + ? $this + : $this->permissionManager->hasPermission($this->build()); + } + + function build(): Permission + { + return $this->perm; + } +} diff --git a/chandler/Security/Authorization/Permissions.php b/chandler/Security/Authorization/Permissions.php new file mode 100644 index 0000000..7bd5536 --- /dev/null +++ b/chandler/Security/Authorization/Permissions.php @@ -0,0 +1,61 @@ +db = DatabaseConnection::i()->getContext(); + $this->user = $user; + + $this->init(); + } + + private function init() + { + $uGroups = $this->user->getRaw()->related("ChandlerACLRelations.user")->order("priority ASC")->select("group"); + $groups = array_map(function($j) { + return $j->group; + }, iterator_to_array($uGroups)); + + $permissionsAllowed = $this->db->table("ChandlerACLGroupsPermissions")->where("group IN (?)", $groups); + $permissionsDenied = iterator_to_array((clone $permissionsAllowed)->where("status", false)); + $permissionsDenied = array_merge($permissionsDenied, iterator_to_array($this->db->table("ChandlerACLUsersPermissions")->where("user", $this->user->getId()))); + $permissionsAllowed = $permissionsAllowed->where("status", true); + + foreach($permissionsAllowed as $perm) { + foreach($permissionsDenied as $denied) + if($denied->model === $perm->model && $denied->context === $perm->context && $denied->permission === $perm->permission) + continue 2; + + $pm = new Permission; + $pm->action = $perm->permission; + $pm->model = $perm->model; + $pm->context = $perm->context; + $pm->status = true; + + $this->perms[] = $pm; + } + } + + function getPermissions(): array + { + return $this->perms; + } + + function hasPermission(Permission $pm): bool + { + foreach($this->perms as $perm) + if($perm->model === $pm->model && $perm->context === $pm->context && $perm->action === $pm->action) + return true; + + return false; + } +} diff --git a/chandler/Security/User.php b/chandler/Security/User.php new file mode 100644 index 0000000..c0f14b2 --- /dev/null +++ b/chandler/Security/User.php @@ -0,0 +1,182 @@ + + */ +class User +{ + /** + * @var \Nette\Database\Context DB Explorer + */ + private $db; + + /** + * @var \Nette\Database\Table\ActiveRow ActiveRow that represents user + */ + private $user; + /** + * @var bool Does this user is not the one who is logged in, but substituted? + */ + private $tainted; + + /** + * @param \Nette\Database\Table\ActiveRow $user ActiveRow that represents user + * @param bool $tainted Does this user is not the one who is logged in, but substituted? + */ + function __construct(ActiveRow $user, bool $tainted = false) + { + $this->db = DatabaseConnection::i()->getContext(); + $this->user = $user; + $this->tainted = $tainted; + } + + /** + * Computes hash for a password. + * + * @param string $password password + * @return string hash + */ + private function makeHash(string $password): string + { + $salt = openssl_random_pseudo_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES); + $hash = sodium_crypto_pwhash( + 16, + $password, + $salt, + SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 + ); + + return bin2hex($hash) . "$" . bin2hex($salt); + } + + /** + * Get user's GUID. + * + * @return string GUID + */ + function getId(): string + { + return $this->user->id; + } + + /** + * Get user's DB data as an array. + * + * @return array DB data in form of associative array + */ + function getAttributes(): array + { + return (array) $this->user; + } + + /** + * Get Permission Manager object. + * + * @api + * @see \Chandler\Security\User::can + * @return \Chandler\Security\Authorization\Permissions Permission Manager + */ + function getPermissions(): Permissions + { + return new Permissions($this); + } + + /** + * Get ActiveRow that represents user + * + * @return \Nette\Database\Table\ActiveRow ActiveRow + */ + function getRaw(): ActiveRow + { + return $this->user; + } + + /** + * Checks if this user is not the one who is logged in, but substituted + * + * @return bool Does this user is not the one who is logged in, but substituted? + */ + function isTainted(): bool + { + return $this->tainted; + } + + /** + * Begins to build permission for checking it's status using Permission Builder. + * To get permission status you should chain methods like this: + * $user->can('do something')->model('\app\Web\Models\MyModel')->whichBelongsTo(10); + * In this case whichBelongsTo will automatically build permission and check if user + * has it. If you need to build permission for something another use {@see \Chandler\Security\User::getPermissions}. + * + * @api + * @uses \Chandler\Security\Authorization\PermissionBuilder::can + * @return \Chandler\Security\Authorization\Permissions Permission Manager + */ + function can(string $action): PermissionBuilder + { + $pb = new PermissionBuilder($this->getPermissions()); + + return $pb->can($action); + } + + /** + * Updates user password. + * If $oldPassword parameter is passed it will update password only if current + * user password (not the new one) matches $oldPassword. + * + * @api + * @param string $password New Password + * @param string|null $oldPassword Current Password + * @return bool False if token manipulation error has been thrown + */ + function updatePassword(string $password, ?string $oldPassword = NULL): bool + { + if(!is_null($oldPassword)) + if(!Authenticator::verifyHash($oldPassword, $this->getRaw()->passwordHash)) + return false; + + $users = DatabaseConnection::i()->getContext()->table("ChandlerUsers"); + $users->where("id", $this->getId())->update([ + "passwordHash" => $this->makeHash($password), + ]); + + return true; + } + + /** + * Creates new user if login has not been taken yet. + * + * @api + * @param string $login Login (usually an email) + * @param string $password Password + * @return self|null New user if successful, null otherwise + */ + static function create(string $login, string $password): ?User + { + $users = DatabaseConnection::i()->getContext()->table("ChandlerUsers"); + $hash = self::makeHash($password); + + try { + $users->insert([ + "login" => $login, + "passwordHash" => $hash, + ]); + + $user = $users->where("login", $login)->fetch(); + } catch(UniqueConstraintViolationException $ex) { + return null; + } + + return new static($user); + } +} diff --git a/chandler/Session/Session.php b/chandler/Session/Session.php new file mode 100644 index 0000000..5f3c092 --- /dev/null +++ b/chandler/Session/Session.php @@ -0,0 +1,136 @@ + + */ +class Session +{ + /** + * @var array Associative array of session variables + */ + private $data; + /** + * @var string Web-portal secret key + */ + private $key; + + /** + * @internal + */ + private function __construct() + { + $this->key = strtr(CHANDLER_ROOT_CONF["security"]["secret"], "-_", "+/"); + + if(!isset($_COOKIE["CHANDLERSESS"])) + $this->initSession(); + else + $this->bootstrapData(); + } + + /** + * Sets CHANDLERSESS cookie to specified token. + * + * @internal + * @param string $token Token + * @return void + */ + private function setSessionCookie(string $token): void + { + setcookie( + "CHANDLERSESS", + $token, + time() + 60 * 60 * 24 * ((int) CHANDLER_ROOT_CONF["security"]["sessionDuration"]), + "/", + "", + false, + true + ); + } + + /** + * Calculates session token and sets session cookie value to it. + * This function skips empty keys. + * + * @internal + * @return void + */ + private function updateSessionCookie(): void + { + $this->data = array_filter($this->data, function($data) { + return !(is_null($data) && $data !== ""); + }); + + $this->setSessionCookie(JWT::encode($this->data, ($this->key), "HS512")); + } + + /** + * Initializes session cookie with empty stub and loads no data. + * + * @internal + * @return void + */ + private function initSession(): void + { + $token = JWT::encode([], ($this->key), "HS512"); + $this->setSessionCookie($token); + + $this->data = []; + } + + /** + * Reads data from cookie. + * If cookie is corrupted, session terminates and starts again. + * + * @internal + * @uses \Chandler\Session\Session::initSession + * @return void + */ + private function bootstrapData(): void + { + try { + $this->data = (array) JWT::decode($_COOKIE["CHANDLERSESS"], ($this->key), ["HS512"]); + } catch(\Exception $ex) { + $this->initSession(); + } + } + + /** + * Gets session variable. + * May also set a variable if default value is present and + * setting keys to default is permitted. + * + * @api + * @param string $key Session variable name + * @param scalar $default Default value + * @param bool $ser Set variable to default value if no data is present + * @uses \Chandler\Session\Session::set + * @return scalar + */ + function get(string $key, $default = null, bool $set = false) + { + return $this->data[sha1($key)] ?? ($set ? $this->set($key, $default) : $default); + } + + /** + * Sets session variable. + * + * @api + * @param string $key Session variable name + * @param scalar $value Value + * @return scalar Value + */ + function set(string $key, $value) + { + $this->data[sha1($key)] = $value; + $this->updateSessionCookie(); + + return $value; + } + + use TSimpleSingleton; +} diff --git a/chandler/Signaling/SignalManager.php b/chandler/Signaling/SignalManager.php new file mode 100644 index 0000000..be33ac5 --- /dev/null +++ b/chandler/Signaling/SignalManager.php @@ -0,0 +1,102 @@ + + */ +class SignalManager +{ + /** + * @var int Latest event timestamp. + */ + private $since; + /** + * @var \PDO PDO Connection to events SQLite DB. + */ + private $connection; + + /** + * @internal + */ + private function __construct() + { + $this->since = time(); + $this->connection = new \PDO( + 'sqlite:' . CHANDLER_ROOT . '/tmp/events.bin', + null, + null, + [\PDO::ATTR_PERSISTENT => true] + ); + $this->connection->query("CREATE TABLE IF NOT EXISTS pool(id INTEGER PRIMARY KEY AUTOINCREMENT, since INTEGER, for INTEGER, event TEXT);"); + } + + /** + * Waits for event for user with ID = $for. + * This function is blocking. + * + * @internal + * @param int $for User ID + * @return array|null Array of events if there are any, null otherwise + */ + private function eventFor(int $for): ?array + { + $since = $this->since - 1; + $statement = $this->connection->query("SELECT * FROM pool WHERE `for` = $for AND `since` > $since ORDER BY since DESC"); + $event = $statement->fetch(\PDO::FETCH_LAZY); + if(!$event) return null; + + $this->since = time(); + return [$event->id, unserialize(hex2bin($event->event))]; + } + + /** + * Set ups listener. + * This function blocks the thread and calls $callback each time + * a signal is recieved for user with ID = $for + * + * @api + * @param \Closure $callback Callback + * @param int $for User ID + * @uses \Chandler\Signaling\SignalManager::eventFor + * @return void + */ + function listen(\Closure $callback, int $for): void + { + $this->since = time() - 1; + for($i = 0; $i < 25; $i++) { + sleep(1); + + $event = $this->eventFor($for); + if(!$event) continue; + + list($id, $evt) = $event; + $id = crc32($id); + $callback($evt, $id); + } + + exit("[]"); + } + + /** + * Triggers event for user and sends signal to DB and listeners. + * + * @api + * @param object $event Event + * @param int $for User ID + * @return bool Success state + */ + function triggerEvent(object $event, int $for): bool + { + $event = bin2hex(serialize($event)); + $since = time(); + + $this->connection->query("INSERT INTO pool VALUES (NULL, $since, $for, '$event')"); + return true; + } + + use TSimpleSingleton; +} \ No newline at end of file diff --git a/chandler/bindata/mime.types b/chandler/bindata/mime.types new file mode 100644 index 0000000..ed5fedd --- /dev/null +++ b/chandler/bindata/mime.types @@ -0,0 +1,1913 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +application/chemtool cht +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +application/dicom dcm +# application/dns +application/docbook+xml docbook dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/flash-video flv +application/font-tdpfr pfr +# application/framework-attributes+xml +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +application/illustrator ai +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +application/jsonml+json jsonml +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica nb ma mb +application/mathml+xml mathml +# application/mathml-content+xml +# application/mathml-presentation+xml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp pgp +application/pgp-encrypted pgp gpg +# application/pgp-keys +application/pgp-keys skr pkr +application/pgp-signature sig asc +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ps ai eps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil smil smi sml +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +application/stuffit sit +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.corel-draw cdr +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.ds-keypoint kpxx +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fujixerox.hbpl +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 wk1 wk3 wk4 wks +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlc xll xlm xlw xla xlt xld +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppz ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printing.printticket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.quobject-quoxdocument +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-secure rms +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.chart sds +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd sdp +application/vnd.stardivision.mail smd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor sgl +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +# application/vnd.sun.wadl+xml +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw abw.CRASHED abw.gz zabw +application/x-ace-compressed ace +# application/x-amf +application/x-amipro sam +application/x-anjuta-project prj +application/x-apple-diskimage dmg +application/x-applix-spreadsheet as +application/x-applix-word aw +application/x-arc +application/x-archive a +application/x-arj arj +application/x-asax asax +application/x-ascx ascx +application/x-ashx ashx +application/x-asix asix +application/x-asmx asmx +application/x-asp asp +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-awk +application/x-axd axd +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blender blender blend BLEND +application/x-blorb blb blorb +application/x-bzip bz bz2 +application/x-bzip-compressed-tar tar.bz tar.bz2 tbz tbz2 +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cd-image iso +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-cgi cgi +application/x-chat chat +application/x-chess-pgn pgn +application/x-chm chm +application/x-class-file +application/x-cmbx cmbx +# application/x-compress +application/x-compress Z +application/x-compressed-tar tar.gz tar.Z tgz taz +application/x-conference nsc +application/x-config config +application/x-core +application/x-cpio cpio +application/x-cpio-compressed cpio.gz +application/x-csh csh +application/x-cue cue +application/x-dbase dbf +application/x-dbm +application/x-dc-rom dc +application/x-deb deb +application/x-debian-package deb udeb +application/x-designer ui +application/x-desktop desktop kdelnk +application/x-devhelp devhelp +application/x-dgc-compressed dgc +application/x-dia-diagram dia +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-disco disco +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-e-theme etheme +application/x-egon egon +application/x-envoy evy +application/x-eva eva +application/x-executable exe +application/x-font-afm afm +application/x-font-bdf bdf +# application/x-font-dos +application/x-font-dos +# application/x-font-framemaker +application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf pcf.gz +application/x-font-snf snf +# application/x-font-speedo +application/x-font-speedo spd +# application/x-font-sunos-news +application/x-font-sunos-news +application/x-font-tex +application/x-font-tex-tfm +application/x-font-ttf ttc TTC ttf +application/x-font-type1 pfa pfb gsf pcf.Z pfm afm +# application/x-font-vfont +application/x-font-vfont +application/x-font-woff woff +application/x-frame +application/x-freearc arc +application/x-frontline aop +application/x-futuresplash spl +application/x-gameboy-rom gb +application/x-gca-compressed gca +application/x-gdbm +application/x-gdesklets-display display +application/x-genesis-rom gen smd +application/x-gettext-translation gmo +application/x-glabels glabels +application/x-glade glade +application/x-glulx ulx +application/x-gmc-link +application/x-gnome-db-connection connection +application/x-gnome-db-database database +application/x-gnome-stones caves +application/x-gnucash gnucash gnc xac +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-graphite gra +application/x-gtar gtar +application/x-gtktalog +# application/x-gzip +application/x-gzip gz +application/x-gzpostscript ps.gz +application/x-hdf hdf +application/x-ica ica +application/x-install-instructions install +application/x-ipod-firmware +application/x-iso9660-image iso +application/x-jamin jam +application/x-jar jar +application/x-java class +application/x-java-archive jar ear war +application/x-java-jnlp-file jnlp +application/x-jbuilder-project jpr jpx +application/x-karbon karbon +application/x-kchart chrt +application/x-kformula kfo +application/x-killustrator kil +application/x-kivio flw +application/x-kontour kon +application/x-kpovmodeler kpm +application/x-kpresenter kpr kpt +application/x-krita kra +application/x-kspread ksp +application/x-kspread-crypt +application/x-ksysv-package +application/x-kugar kud +application/x-kword kwd kwt +application/x-kword-crypt +application/x-latex latex +application/x-lha lha lzh +application/x-lhz lhz +application/x-linguist ts +application/x-lyx lyx +application/x-lzh-compressed lzh lha +application/x-lzop lzo +application/x-lzop-compressed-tar tar.lzo tzo +application/x-macbinary +application/x-machine-config +application/x-magicpoint mgp +application/x-master-page master +application/x-matroska mkv +application/x-mdp mdp +application/x-mds mds +application/x-mdsx mdsx +application/x-mergeant mergeant +application/x-mie mie +application/x-mif mif +application/x-mobipocket-ebook prc mobi +application/x-mozilla-bookmarks +application/x-mps mps +application/x-ms-application application +application/x-ms-dos-executable exe +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswinurl +application/x-mswrite wri +application/x-msx-rom msx +application/x-n64-rom n64 +application/x-nautilus-link +application/x-nes-rom nes +application/x-netcdf cdf nc +application/x-netscape-bookmarks +application/x-nzb nzb +application/x-object o +application/x-ole-storage +application/x-oleo oleo +application/x-palm-database pdb prc +application/x-par2 PAR2 par2 +application/x-pef-executable +application/x-perl pl pm al perl +application/x-php php php3 php4 +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-planner planner mrproject +application/x-planperfect pln +application/x-prjx prjx +application/x-profile +application/x-ptoptimizer-script pto +application/x-pw pw +application/x-python-bytecode pyc pyo +application/x-quattro-pro wb1 wb2 wb3 +application/x-quattropro wb1 wb2 wb3 +application/x-qw qif +application/x-rar rar +application/x-rar-compressed rar +application/x-rdp rdp +application/x-reject rej +application/x-remoting rem +application/x-research-info-systems ris +application/x-resources resources +application/x-resourcesx resx +application/x-rpm rpm +application/x-ruby +application/x-sc sc +application/x-scribus sla sla.gz scd scd.gz +application/x-sh sh +application/x-shar shar +application/x-shared-library-la la +application/x-sharedlib so +application/x-shellscript sh +application/x-shockwave-flash swf +application/x-siag siag +application/x-silverlight-app xap +application/x-slp +application/x-smil kino smi smil +application/x-sms-rom sms gg +application/x-soap-remoting soap +application/x-sql sql +application/x-streamingmedia ssm +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tarz tar.Z +application/x-tcl tcl +application/x-tex tex +application/x-tex-gf gf +application/x-tex-pk k +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-theme theme +application/x-toc toc +application/x-toutdoux +application/x-trash bak old sik +application/x-troff tr roff t +application/x-troff-man man +application/x-troff-man-compressed +application/x-tzo tar.lzo tzo +application/x-ustar ustar +application/x-wais-source src +application/x-web-config +application/x-wpg wpg +application/x-wsdl wsdl +application/x-x509-ca-cert der cer crt cert pem +application/x-xbel xbel +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zerosize +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +application/x-zoo zoo +# application/x400-bp +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info+xml +# application/xcon-conference-info-diff+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/ac3 ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mp3 mpga mp2 mp2a m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg oga ogg spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu +# audio/pcmu-wb +# audio/prs.sid +audio/prs.sid sid psid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv-qcp +# audio/smv0 +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +audio/vnd.rn-realaudio ra +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-adpcm +audio/x-aifc +audio/x-aiff aif aiff aifc +audio/x-aiffc +audio/x-caf caf +audio/x-flac flac +audio/x-m4a m4a +audio/x-matroska mka +audio/x-mod mod ult uni XM m15 mtm 669 +audio/x-mp3-playlist +audio/x-mpeg +audio/x-mpegurl m3u +audio/x-ms-asx +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ra ram rm rmm +audio/x-pn-realaudio-plugin rmp +audio/x-riff +audio/x-s3m s3m +audio/x-scpls pls xpl +audio/x-stm stm +# audio/x-tta +audio/x-voc voc +audio/x-wav wav +audio/x-xi xi +audio/x-xm xm +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +image/dpx +# image/example +image/fax-g3 g3 +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +image/jpeg2000 jp2 +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/rle rle +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tif tiff +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.djvu djvu djv +image/vnd.dvb.subtitle sub +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-3ds 3ds +image/x-applix-graphics ag +image/x-cmu-raster ras +image/x-cmx cmx +image/x-compressed-xcf xcf.gz xcf.bz2 +image/x-dcraw bay BAY bmq BMQ cr2 CR2 crw CRW cs1 CS1 dc2 DC2 dcr DCR fff FFF k25 K25 kdc KDC mos MOS mrw MRW nef NEF orf ORF pef PEF raf RAF rdc RDC srf SRF x3f X3F +image/x-dib +image/x-eps eps epsi epsf +image/x-fits fits +image/x-fpx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icb icb +image/x-ico ico +image/x-icon ico +image/x-iff iff +image/x-ilbm ilbm +image/x-jng jng +image/x-lwo lwo lwob +image/x-lws lws +image/x-mrsid-image sid +image/x-msod msod +image/x-niff +image/x-pcx pcx +image/x-photo-cd pcd +image/x-pict pict pict1 pict2 pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-psd psd +image/x-rgb rgb +image/x-sgi sgi +image/x-sun-raster sun +image/x-tga tga +image/x-win-bitmap cur +image/x-wmf wmf +image/x-xbitmap xbm +image/x-xcf xcf +image/x-xfig fig +image/x-xpixmap xpm +image/x-xwindowdump xwd +inode/blockdevice +inode/chardevice +inode/directory +inode/fifo +inode/mount-point +inode/socket +inode/symlink +# message/cpim +# message/delivery-status +message/delivery-status +# message/disposition-notification +message/disposition-notification +# message/example +# message/external-body +message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +message/news +# message/partial +message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +message/x-gnu-rmail +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# multipart/alternative +multipart/alternative +# multipart/appledouble +multipart/appledouble +# multipart/byteranges +# multipart/digest +multipart/digest +# multipart/encrypted +multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +multipart/mixed +# multipart/parallel +# multipart/related +multipart/related +# multipart/report +multipart/report +# multipart/signed +multipart/signed +# multipart/voice-message +multipart/x-mixed-replace +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar vcs ics ifb +text/css css CSSL +text/csv csv +# text/directory +text/directory vcf vct gcrd +# text/dns +# text/ecmascript +# text/enriched +text/enriched +# text/example +# text/fwdred +text/html html htm +text/htmlh +# text/javascript +text/mathml mml +text/n3 n3 +# text/parityfec +text/plain txt asc text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +text/rdf rdf +# text/red +# text/rfc822-headers +text/rfc822-headers +text/richtext rtx +text/rss rss +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +text/spreadsheet sylk slk +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.mcurl mcurl +text/vnd.curl.scurl scurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.radisys.msml-basic-layout +text/vnd.rn-realtext rt +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-adasrc adb ads +text/x-asm s asm +text/x-authors +text/x-bibtex bib +text/x-boo boo +text/x-c c cc cxx cpp h hh dic +text/x-c++hdr hh +text/x-c++src cpp cxx cc C c++ +text/x-chdr h h++ hp +text/x-comma-separated-values csv +text/x-copying +text/x-credits +text/x-csrc c +text/x-dcl dcl +text/x-dsl dsl +text/x-dsrc d +text/x-dtd dtd +text/x-emacs-lisp el +text/x-fortran f for f77 f90 +text/x-gettext-translation po +text/x-gettext-translation-template pot +text/x-gtkrc +text/x-haskell hs +text/x-idl idl +text/x-install +text/x-java java +text/x-java-source java +text/x-ksysv-log +text/x-literate-haskell lhs +text/x-log log +text/x-makefile +text/x-moc moc +text/x-msil il +text/x-nemerle n +text/x-nfo nfo +text/x-objcsrc m +text/x-opml opml +text/x-pascal p pas +text/x-patch diff patch +text/x-python py +text/x-readme +text/x-rng rng +text/x-scheme scm +text/x-setext etx +text/x-sfv sfv +text/x-speech +text/x-sql sql +text/x-suse-ymp ymp +text/x-suse-ymu ymu +text/x-tcl tcl tk +text/x-tex tex ltx sty cls +text/x-texinfo texi texinfo +text/x-texmacs tm ts +text/x-troff-me me +text/x-troff-mm mm +text/x-troff-ms ms +text/x-uil uil +text/x-uri uri url +text/x-uuencode uu +text/x-vb vb +text/x-vcalendar vcs +text/x-vcard vcf +text/x-xds xds +text/x-xmi xmi +text/x-xsl xsl +text/x-xslfo fo xslfo +text/x-xslt xslt xsl +text/xmcd +# text/xml +text/xml xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +video/dv dv dif +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/isivideo +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mp2 mpe vob dat m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov moov qtvr +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +video/vivo +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +video/vnd.rn-realvideo rv +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/wavelet +video/webm webm +video/x-3gpp2 3g2 +video/x-anim anim[1-9j] +video/x-avi +video/x-f4v f4v +video/x-fli fli +video/x-flic fli flc +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-nsv nsv NSV +video/x-real-video +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice diff --git a/chandler/procedural/mimes.php b/chandler/procedural/mimes.php new file mode 100644 index 0000000..645b393 --- /dev/null +++ b/chandler/procedural/mimes.php @@ -0,0 +1,73 @@ + "png", + ]; + + static $types; + if(!isset($types)) + $types = system_extension_mime_types(); + $ext = pathinfo($file, PATHINFO_EXTENSION); + if(!$ext) + $ext = $file; + $ext = strtolower($ext); + $ext = $aliases[$ext] ?? $ext; + return isset($types[$ext]) ? $types[$ext] : null; +} + +function system_mime_type_extensions(): array +{ + # Returns the system MIME type mapping of MIME types to extensions, as defined in /etc/mime.types (considering the first + # extension listed to be canonical). + $out = []; + $file = fopen('/etc/mime.types', 'r'); + while(($line = fgets($file)) !== false) { + $line = trim(preg_replace('/#.*/', '', $line)); + if(!$line) + continue; + $parts = preg_split('/\s+/', $line); + if(count($parts) == 1) + continue; + $type = array_shift($parts); + if(!isset($out[$type])) + $out[$type] = array_shift($parts); + } + fclose($file); + return $out; +} + +function system_mime_type_extension(string $type): string +{ + # Returns the canonical file extension for the MIME type specified, as defined in /etc/mime.types (considering the first + # extension listed to be canonical). + # + # $type - the MIME type + static $exts; + if(!isset($exts)) + $exts = system_mime_type_extensions(); + return isset($exts[$type]) ? $exts[$type] : null; +} \ No newline at end of file diff --git a/chandler/procedural/panic.php b/chandler/procedural/panic.php new file mode 100644 index 0000000..39ad7d1 --- /dev/null +++ b/chandler/procedural/panic.php @@ -0,0 +1,57 @@ + + * @param int $code HTTP Error code + * @param string $description HTTP Error description + * @param string $message Additional message to show to client + * @return void + */ +function chandler_http_panic(int $code = 400, string $description = "Bad Request", string $message = ""): void +{ + $error = << + + + + + + + + + +
+ libchandler +
+
+
+ Error summary + +

HTTP Error $code.0 - $description

+

$message

+
+
+ + + +EOE; + + header("HTTP/1.0 $code $description"); + exit($error); +} \ No newline at end of file diff --git a/chandler/procedural/yaml.php b/chandler/procedural/yaml.php new file mode 100644 index 0000000..8810fcc --- /dev/null +++ b/chandler/procedural/yaml.php @@ -0,0 +1,34 @@ + + * @param string $filename Path to file + * @return array Array + */ +function chandler_parse_yaml(string $filename): array +{ + $cache = $GLOBALS["ymlCa"]; + $id = sha1($filename); + + $result = $cache->load($id); + if(!$result) { + $result = yaml_parse_file($filename); + $cache->save($id, $result, [ + Cache::EXPIRE => "1 day", + Cache::SLIDING => TRUE, + Cache::FILES => $filename, + ]); + } + + return $result; +} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..91603cf --- /dev/null +++ b/composer.json @@ -0,0 +1,17 @@ +{ + "require": { + "php": "~7.3", + "ext-yaml": "*", + + "nette/utils": "^3.0", + "nette/di": "^3.0", + "nette/database": "^3.0", + "swiftmailer/swiftmailer": "^6.2", + "latte/latte": "2.6.2", + "nette/safe-stream": "^2.4", + "nette/tokenizer": "^3.1", + "firebase/php-jwt": "^5.0", + "tracy/tracy": "^2.7", + "symfony/translation": "^5.0" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..097b4e7 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1544 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "d4f9716af64d4febc1f82eb3f8975cd9", + "packages": [ + { + "name": "doctrine/lexer", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2019-10-30T14:39:59+00:00" + }, + { + "name": "egulias/email-validator", + "version": "2.1.17", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "ade6887fd9bd74177769645ab5c474824f8a418a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ade6887fd9bd74177769645ab5c474824f8a418a", + "reference": "ade6887fd9bd74177769645ab5c474824f8a418a", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1.0.1", + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.10" + }, + "require-dev": { + "dominicsayers/isemail": "^3.0.7", + "phpunit/phpunit": "^4.8.36|^7.5.15", + "satooshi/php-coveralls": "^1.0.1" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "EmailValidator" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "time": "2020-02-13T22:36:52+00:00" + }, + { + "name": "firebase/php-jwt", + "version": "v5.2.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/feb0e820b8436873675fd3aca04f3728eb2185cb", + "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8 <=9" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "time": "2020-03-25T18:49:23+00:00" + }, + { + "name": "latte/latte", + "version": "v2.6.2", + "source": { + "type": "git", + "url": "https://github.com/nette/latte.git", + "reference": "bb3e57a815cb48ed282671ec206caae531aa2985" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/latte/zipball/bb3e57a815cb48ed282671ec206caae531aa2985", + "reference": "bb3e57a815cb48ed282671ec206caae531aa2985", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.1" + }, + "conflict": { + "nette/application": "<2.4.1" + }, + "require-dev": { + "nette/tester": "~2.0", + "nette/utils": "^3.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-fileinfo": "to use filter |datastream", + "ext-iconv": "to use filters |reverse, |substring", + "ext-mbstring": "to use filters like lower, upper, capitalize, ...", + "nette/utils": "to use filter |webalize" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites. Introduces context-sensitive escaping.", + "homepage": "https://latte.nette.org", + "keywords": [ + "context-sensitive", + "engine", + "escaping", + "html", + "nette", + "security", + "template", + "twig" + ], + "time": "2020-03-04T09:44:23+00:00" + }, + { + "name": "nette/caching", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/nette/caching.git", + "reference": "b9ecbf920f240bd1ab14900d9a77876924ad7fb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/caching/zipball/b9ecbf920f240bd1ab14900d9a77876924ad7fb4", + "reference": "b9ecbf920f240bd1ab14900d9a77876924ad7fb4", + "shasum": "" + }, + "require": { + "nette/finder": "^2.4 || ^3.0", + "nette/utils": "^2.4 || ^3.0", + "php": ">=7.1" + }, + "require-dev": { + "latte/latte": "^2.4", + "nette/di": "^v3.0", + "nette/tester": "^2.0", + "tracy/tracy": "^2.4" + }, + "suggest": { + "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.", + "homepage": "https://nette.org", + "keywords": [ + "cache", + "journal", + "memcached", + "nette", + "sqlite" + ], + "time": "2019-11-19T18:41:40+00:00" + }, + { + "name": "nette/database", + "version": "v3.0.6", + "source": { + "type": "git", + "url": "https://github.com/nette/database.git", + "reference": "daccbd526f74311549e5c81d3181fc74f87c6733" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/database/zipball/daccbd526f74311549e5c81d3181fc74f87c6733", + "reference": "daccbd526f74311549e5c81d3181fc74f87c6733", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "nette/caching": "^3.0", + "nette/utils": "^3.1", + "php": ">=7.1" + }, + "conflict": { + "nette/di": "<3.0-stable" + }, + "require-dev": { + "mockery/mockery": "^1.0.0", + "nette/di": "^v3.0", + "nette/tester": "^2.0", + "phpstan/phpstan-nette": "^0.12", + "tracy/tracy": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💾 Nette Database: layer with a familiar PDO-like API but much more powerful. Building queries, advanced joins, drivers for MySQL, PostgreSQL, SQLite, MS SQL Server and Oracle.", + "homepage": "https://nette.org", + "keywords": [ + "database", + "mssql", + "mysql", + "nette", + "notorm", + "oracle", + "pdo", + "postgresql", + "queries", + "sqlite" + ], + "time": "2020-02-04T12:48:51+00:00" + }, + { + "name": "nette/di", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/nette/di.git", + "reference": "77d69061cbf8f9cfb7363dd983136f51213d3e41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/di/zipball/77d69061cbf8f9cfb7363dd983136f51213d3e41", + "reference": "77d69061cbf8f9cfb7363dd983136f51213d3e41", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/neon": "^3.0", + "nette/php-generator": "^3.3.3", + "nette/robot-loader": "^3.2", + "nette/schema": "^1.0", + "nette/utils": "^3.1", + "php": ">=7.1" + }, + "conflict": { + "nette/bootstrap": "<3.0" + }, + "require-dev": { + "nette/tester": "^2.2", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.", + "homepage": "https://nette.org", + "keywords": [ + "compiled", + "di", + "dic", + "factory", + "ioc", + "nette", + "static" + ], + "time": "2020-01-20T12:14:54+00:00" + }, + { + "name": "nette/finder", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/nette/finder.git", + "reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/finder/zipball/4ad2c298eb8c687dd0e74ae84206a4186eeaed50", + "reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4 || ^3.0", + "php": ">=7.1" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "^2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🔍 Nette Finder: find files and directories with an intuitive API.", + "homepage": "https://nette.org", + "keywords": [ + "filesystem", + "glob", + "iterator", + "nette" + ], + "time": "2020-01-03T20:35:40+00:00" + }, + { + "name": "nette/neon", + "version": "v3.1.2", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "3c3dcbc6bf6c80dc97b1fc4ba9a22ae67930fc0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/3c3dcbc6bf6c80dc97b1fc4ba9a22ae67930fc0e", + "reference": "3c3dcbc6bf6c80dc97b1fc4ba9a22ae67930fc0e", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-json": "*", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍸 Nette NEON: encodes and decodes NEON file format.", + "homepage": "https://ne-on.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "time": "2020-03-04T11:47:04+00:00" + }, + { + "name": "nette/php-generator", + "version": "v3.3.4", + "source": { + "type": "git", + "url": "https://github.com/nette/php-generator.git", + "reference": "8fe7e699dca7db186f56d75800cb1ec32e39c856" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/php-generator/zipball/8fe7e699dca7db186f56d75800cb1ec32e39c856", + "reference": "8fe7e699dca7db186f56d75800cb1ec32e39c856", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4.2 || ^3.0", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.4 features.", + "homepage": "https://nette.org", + "keywords": [ + "code", + "nette", + "php", + "scaffolding" + ], + "time": "2020-02-09T14:39:09+00:00" + }, + { + "name": "nette/robot-loader", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/nette/robot-loader.git", + "reference": "726c462e73e739e965ec654a667407074cfe83c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/726c462e73e739e965ec654a667407074cfe83c0", + "reference": "726c462e73e739e965ec654a667407074cfe83c0", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/finder": "^2.5 || ^3.0", + "nette/utils": "^3.0", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", + "homepage": "https://nette.org", + "keywords": [ + "autoload", + "class", + "interface", + "nette", + "trait" + ], + "time": "2020-02-28T13:10:07+00:00" + }, + { + "name": "nette/safe-stream", + "version": "v2.4.1", + "source": { + "type": "git", + "url": "https://github.com/nette/safe-stream.git", + "reference": "ae6f314041892138cb38b4ff8782e92e03750918" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/safe-stream/zipball/ae6f314041892138cb38b4ff8782e92e03750918", + "reference": "ae6f314041892138cb38b4ff8782e92e03750918", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "files": [ + "src/loader.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "Nette SafeStream: atomic and safe manipulation with files via native PHP functions.", + "homepage": "https://nette.org", + "keywords": [ + "atomic", + "filesystem", + "nette", + "safe" + ], + "time": "2020-03-16T14:26:30+00:00" + }, + { + "name": "nette/schema", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "febf71fb4052c824046f5a33f4f769a6e7fa0cb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/febf71fb4052c824046f5a33f4f769a6e7fa0cb4", + "reference": "febf71fb4052c824046f5a33f4f769a6e7fa0cb4", + "shasum": "" + }, + "require": { + "nette/utils": "^3.1", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.2", + "phpstan/phpstan-nette": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "time": "2020-01-06T22:52:48+00:00" + }, + { + "name": "nette/tokenizer", + "version": "v3.1.0", + "source": { + "type": "git", + "url": "https://github.com/nette/tokenizer.git", + "reference": "14d42330fb299e877ad5a01f955098e35190c042" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tokenizer/zipball/14d42330fb299e877ad5a01f955098e35190c042", + "reference": "14d42330fb299e877ad5a01f955098e35190c042", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "~2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "Nette Tokenizer", + "homepage": "https://nette.org", + "time": "2019-09-13T11:28:17+00:00" + }, + { + "name": "nette/utils", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "2c17d16d8887579ae1c0898ff94a3668997fd3eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/2c17d16d8887579ae1c0898ff94a3668997fd3eb", + "reference": "2c17d16d8887579ae1c0898ff94a3668997fd3eb", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "~2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize() and toAscii()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "time": "2020-02-09T14:10:55+00:00" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v6.2.3", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9", + "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9", + "shasum": "" + }, + "require": { + "egulias/email-validator": "~2.0", + "php": ">=7.0.0", + "symfony/polyfill-iconv": "^1.0", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "^3.4.19|^4.1.8" + }, + "suggest": { + "ext-intl": "Needed to support internationalized email addresses", + "true/punycode": "Needed to support internationalized email addresses, if ext-intl is not installed" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "https://swiftmailer.symfony.com", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2019-11-12T09:31:26+00:00" + }, + { + "name": "symfony/polyfill-iconv", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-iconv.git", + "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", + "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-iconv": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Iconv\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Iconv extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "iconv", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-03-09T19:04:49+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-03-09T19:04:49+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-03-09T19:04:49+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "37b0976c78b94856543260ce09b460a7bc852747" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", + "reference": "37b0976c78b94856543260ce09b460a7bc852747", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.15-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-02-27T09:26:54+00:00" + }, + { + "name": "symfony/translation", + "version": "v5.0.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "99b831770e10807dca0979518e2c89edffef5978" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/99b831770e10807dca0979518e2c89edffef5978", + "reference": "99b831770e10807dca0979518e2c89edffef5978", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2" + }, + "conflict": { + "symfony/config": "<4.4", + "symfony/dependency-injection": "<5.0", + "symfony/http-kernel": "<5.0", + "symfony/twig-bundle": "<5.0", + "symfony/yaml": "<4.4" + }, + "provide": { + "symfony/translation-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/dependency-injection": "^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/intl": "^4.4|^5.0", + "symfony/service-contracts": "^1.1.2|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-03-27T16:56:45+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "tracy/tracy", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/nette/tracy.git", + "reference": "344c77293038173f49678d9a95c27da6cbdbccd0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tracy/zipball/344c77293038173f49678d9a95c27da6cbdbccd0", + "reference": "344c77293038173f49678d9a95c27da6cbdbccd0", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-session": "*", + "php": ">=7.1" + }, + "conflict": { + "nette/di": "<3.0" + }, + "require-dev": { + "latte/latte": "^2.5", + "nette/di": "^3.0", + "nette/mail": "^3.0", + "nette/tester": "^2.2", + "nette/utils": "^3.0", + "phpstan/phpstan": "^0.12", + "psr/log": "^1.0" + }, + "suggest": { + "https://nette.org/donate": "Please support Tracy via a donation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "classmap": [ + "src" + ], + "files": [ + "src/Tracy/shortcuts.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.", + "homepage": "https://tracy.nette.org", + "keywords": [ + "Xdebug", + "debug", + "debugger", + "nette", + "profiler" + ], + "time": "2020-02-23T18:40:15+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "~7.3", + "ext-yaml": "*" + }, + "platform-dev": [], + "plugin-api-version": "1.1.0" +} diff --git a/docs/.gitkeep b/docs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/extensions/available/.gitkeep b/extensions/available/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/extensions/enabled/.gitkeep b/extensions/enabled/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/htdocs/.htaccess b/htdocs/.htaccess new file mode 100644 index 0000000..b89051b --- /dev/null +++ b/htdocs/.htaccess @@ -0,0 +1,10 @@ +RewriteEngine On + +RewriteRule ^(.+)-datastore/(.+) datafwd.php?extension=$1&file=$2 [L] + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule (.*) index.php [QSA] + +php_flag display_errors on +php_flag display_startup_errors on \ No newline at end of file diff --git a/htdocs/index.php b/htdocs/index.php new file mode 100644 index 0000000..a6b22cc --- /dev/null +++ b/htdocs/index.php @@ -0,0 +1,7 @@ +ignite(); diff --git a/tmp/cache/database/.gitkeep b/tmp/cache/database/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tmp/cache/templates/.gitkeep b/tmp/cache/templates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tmp/cache/yaml/.gitkeep b/tmp/cache/yaml/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tmp/events.bin b/tmp/events.bin new file mode 100644 index 0000000..2362982 Binary files /dev/null and b/tmp/events.bin differ diff --git a/tmp/plugins-artifacts/.gitkeep b/tmp/plugins-artifacts/.gitkeep new file mode 100644 index 0000000..e69de29