Merge branch 'release-1.4.0' into stable
This commit is contained in:
commit
371c44c29d
451 changed files with 45228 additions and 3093 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
nbproject/
|
||||
.idea/
|
||||
completer.hist
|
||||
feed/
|
||||
node_modules/
|
||||
|
|
|
@ -1,24 +1,54 @@
|
|||
[S] = stable release
|
||||
[B] = beta release
|
||||
[D] = development release
|
||||
# Changelog
|
||||
|
||||
[S] release are always compared to the previous [S] release.
|
||||
- [S] = stable release
|
||||
- [B] = beta release
|
||||
- [D] = development release
|
||||
|
||||
Version 1.3.0 (2016-02-16) [S]
|
||||
=============
|
||||
- [S] release are always compared to the previous [S] release.
|
||||
|
||||
## Version 1.4.0 (2016-05-07) [S]
|
||||
|
||||
- Fix: Feeds contain no text
|
||||
- Switch to YAML as config language
|
||||
- Scripts for
|
||||
- Switching from config.php to config.yaml
|
||||
- Initializing RCC
|
||||
- Initializing Rangitaki
|
||||
- Rangitaki API
|
||||
- Switch from JavaScript to CoffeeScript
|
||||
- Switch from CSS to SASS
|
||||
- Building and minimizing with Gulp
|
||||
- Open links in articles in a new tab
|
||||
- Better code style: PSR-2
|
||||
|
||||
## Version 1.4.0-beta (2016-04-27) [B]
|
||||
|
||||
- Fix: Feeds contain no text
|
||||
- Switch to YAML as config language
|
||||
- Scripts for
|
||||
- Switching from config.php to config.yaml
|
||||
- Initializing RCC
|
||||
- Initializing Rangitaki
|
||||
- Rangitaki API
|
||||
- Switch from JavaScript to CoffeeScript
|
||||
- Switch from CSS to SASS
|
||||
- Building and minimizing with Gulp
|
||||
- Open links in articles in a new tab
|
||||
- Better code style: PSR-2
|
||||
|
||||
|
||||
## Version 1.3.0 (2016-02-16) [S]
|
||||
|
||||
- Respecting do-not-track
|
||||
- Atom feed
|
||||
- Title fix
|
||||
- Switch to composer
|
||||
|
||||
Version 1.2.1 (2016-01-11) [S]
|
||||
=============
|
||||
## Version 1.2.1 (2016-01-11) [S]
|
||||
|
||||
- Support for PHP 7
|
||||
|
||||
Version 1.2.0 (2015-12-24) [S]
|
||||
=============
|
||||
## Version 1.2.0 (2015-12-24) [S]
|
||||
|
||||
- Pagination: Split your blog posts over several page
|
||||
- JavaScript Extension Support
|
||||
|
@ -27,20 +57,17 @@ Version 1.2.0 (2015-12-24) [S]
|
|||
- RCC: Upload Media
|
||||
- RCC: Edit Posts
|
||||
|
||||
Version 1.1.90 (2015-12-21) [B]
|
||||
==============
|
||||
## Version 1.1.90 (2015-12-21) [B]
|
||||
|
||||
- BUGFIX: ArticleGenerator error when no tags set
|
||||
- Pagination: Localized strings
|
||||
|
||||
Version 1.1.2 (2015-12-20) [D]
|
||||
=============
|
||||
## Version 1.1.2 (2015-12-20) [D]
|
||||
|
||||
- Pagination
|
||||
- Code style imporvements
|
||||
|
||||
Version 1.1.1 (2015-12-07) [D]
|
||||
=============
|
||||
## Version 1.1.1 (2015-12-07) [D]
|
||||
|
||||
- BUGFIX: RCC: new post: post title was the blog title
|
||||
- BUGFIX: RCC: new post filename just the date without the time.
|
||||
|
@ -50,8 +77,7 @@ Version 1.1.1 (2015-12-07) [D]
|
|||
- RCC: Delete posts
|
||||
- RCC: Edit posts
|
||||
|
||||
Version 1.1.0 (2015-11-22) [D]
|
||||
=============
|
||||
## Version 1.1.0 (2015-11-22) [D]
|
||||
|
||||
- RCC: Write blog posts
|
||||
- RCC: Media Upload
|
||||
|
@ -61,8 +87,7 @@ Version 1.1.0 (2015-11-22) [D]
|
|||
- Metatags / Title based on subblog and / or article
|
||||
- Update script
|
||||
|
||||
Version 1.0.0 (2015-08-22) [S]
|
||||
=============
|
||||
## Version 1.0.0 (2015-08-22) [S]
|
||||
|
||||
- Post writing in Markdown with a few keywords for the title, tags, date and the author (all optional)
|
||||
- Multiple blogs
|
||||
|
@ -82,8 +107,7 @@ Version 1.0.0 (2015-08-22) [S]
|
|||
- Rangitaki Control Center (aka RCC; optional, Read the RCC Documentation)
|
||||
- Online post upload
|
||||
|
||||
Version 0.9.0 (2015-07-25) [B]
|
||||
=============
|
||||
## Version 0.9.0 (2015-07-25) [B]
|
||||
|
||||
- BUGFIX: 'Blogs of {BLOG NAME}' always shown (even if there are no other blogs)
|
||||
- pictures in articles not centred
|
||||
|
@ -91,53 +115,46 @@ Version 0.9.0 (2015-07-25) [B]
|
|||
- Localization strings are now grouped in one array
|
||||
- Better code (in some parts)
|
||||
|
||||
Version 0.8.0 (2015-07-14) [B]
|
||||
=============
|
||||
## Version 0.8.0 (2015-07-14) [B]
|
||||
|
||||
- Bugfixes and other improvements
|
||||
|
||||
Version 0.7.0 (2015-07-05) [D]
|
||||
=============
|
||||
## Version 0.7.0 (2015-07-05) [D]
|
||||
|
||||
Version 0.6.0 (2015-07-03) [D]
|
||||
=============
|
||||
## Version 0.6.0 (2015-07-03) [D]
|
||||
|
||||
- Localization support. More information will follow soon
|
||||
- Theme support. More information will follow (hopefully) soon
|
||||
- Various improvements (Check the commits for more)
|
||||
|
||||
Version 0.5.0 (2015-06-16) [D]
|
||||
=============
|
||||
## Version 0.5.0 (2015-06-16) [D]
|
||||
|
||||
- Improvements to the Rangitaki Control Center (rcc)
|
||||
- Material Design (Blog and rcc)
|
||||
|
||||
Version 0.4 (2015-06-14) [D]
|
||||
===========
|
||||
## Version 0.4 (2015-06-14) [D]
|
||||
|
||||
- Multiple Blogs
|
||||
- Online post upload (optional)
|
||||
- Tags
|
||||
- Author
|
||||
|
||||
Version 0.3 (2015-06-11) [D]
|
||||
===========
|
||||
## Version 0.3 (2015-06-11) [D]
|
||||
|
||||
- Portation of all main features of Version 0.2.2
|
||||
- Code highlighting
|
||||
|
||||
The first release with the name Rangitaki.
|
||||
The following releases are of pBlog.
|
||||
*The first release with the name Rangitaki.
|
||||
The following releases are of pBlog.*
|
||||
|
||||
Version 0.2.2 (2015-05-13) [S]
|
||||
=============
|
||||
## Version 0.2.2 (2015-05-13) [S]
|
||||
|
||||
- Links are now underlined, when you hover over them
|
||||
- Simplified it to add the disqus comments
|
||||
- Added and configuration option for setting a favicon
|
||||
- Added the option to use Google Analytics
|
||||
|
||||
Version 0.2.1 / pBlog 2.1 (2015-03-29) [S]
|
||||
=============
|
||||
## Version 0.2.1 / pBlog 2.1 (2015-03-29) [S]
|
||||
|
||||
- Fix problems when creating article links
|
||||
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Marcel Kapfer
|
||||
Copyright (c) 2015 - 2016 Marcel Kapfer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
67
bin/config.php
Normal file
67
bin/config.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
// Marcel Kapfer (mmk2410)
|
||||
// Script for moving from config.php to config.yaml
|
||||
// License: MIT
|
||||
|
||||
require 'res/php/Config.php';
|
||||
|
||||
require 'config.php';
|
||||
|
||||
use mmk2410\rbe\config\Config as Config;
|
||||
|
||||
if ($bloghome == "yes") {
|
||||
$bloghome = "on";
|
||||
}
|
||||
|
||||
if ($blogintro == "yes") {
|
||||
$blogintro = "on";
|
||||
}
|
||||
|
||||
if ($sharefab == "yes") {
|
||||
$sharefab = "on";
|
||||
}
|
||||
|
||||
if ($rcc == "yes") {
|
||||
$rcc = "on";
|
||||
}
|
||||
|
||||
if ($nav_drawer == "yes") {
|
||||
$nav_drawer = "on";
|
||||
}
|
||||
|
||||
$yaml = array(
|
||||
"blog" => array(
|
||||
"title" => $blogtitle,
|
||||
"author" => $blogauthor,
|
||||
"description" => $blogdescription,
|
||||
"home" => $bloghome,
|
||||
"homeurl" => $bloghomeurl,
|
||||
"homename" => $bloghomename,
|
||||
"mainname" => $blogmainname,
|
||||
"intro" => $blogintro,
|
||||
"disqus" => $blogdisqus,
|
||||
"analytics" => $bloganalytics,
|
||||
"footer" => $blogfooter,
|
||||
"url" => $blogurl
|
||||
),
|
||||
"design" => array(
|
||||
"fab" => $sharefab,
|
||||
"drawer" => $nav_drawer,
|
||||
"theme" => $theme,
|
||||
"pagination" => $pagination,
|
||||
"favicon" => $favicon,
|
||||
),
|
||||
"rcc" => array(
|
||||
"rcc" => "off",
|
||||
"api" => "off",
|
||||
),
|
||||
"language" => $language,
|
||||
);
|
||||
|
||||
$config = new Config('config.yaml', 'vendor/autoload.php');
|
||||
|
||||
if ($config->writeConfig($yaml)) {
|
||||
echo "YAML config saved.\nYou can delete the config.php file\n";
|
||||
} else {
|
||||
echo "Failed to save YAML config.";
|
||||
}
|
107
bin/init.php
Normal file
107
bin/init.php
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
// Marcel Kapfer (mmk2410)
|
||||
// PHP script for initializing Rangitaki
|
||||
// MIT License
|
||||
|
||||
error_reporting(0);
|
||||
|
||||
require 'res/php/Config.php';
|
||||
|
||||
use mmk2410\rbe\config\Config as Config;
|
||||
|
||||
$config = new Config('config.yaml', 'vendor/autoload.php');
|
||||
|
||||
if (!file_exists('config.yaml')) {
|
||||
$yaml = array();
|
||||
} else {
|
||||
$yaml = $config->getConfig();
|
||||
}
|
||||
|
||||
// blog part
|
||||
$yaml["blog"]["title"] = get("Title of your blog", $yaml["blog"]["title"], "Example Blog");
|
||||
$yaml["blog"]["author"] = get("Your name:", $yaml["blog"]["author"], "John");
|
||||
$yaml["blog"]["description"] = get("A description of your blog:", $yaml["blog"]["description"], "A short description of your blog");
|
||||
$yaml["blog"]["home"] = getBool("Do you have a top site? (on/off)", $yaml["blog"]["home"], "on");
|
||||
if ($yaml["blog"]["home"] == "on") {
|
||||
$yaml["blog"]["homeurl"] = get("Path / Url to home page", $yaml["blog"]["homeurl"], "../");
|
||||
$yaml["blog"]["homename"] = get("Name of your home page", $yaml["blog"]["homename"], "Home");
|
||||
}
|
||||
$yaml["blog"]["mainname"] = get("Name of the main blog (if empty, the blog title will be used)", "");
|
||||
$yaml["blog"]["intro"] = getBool("Do you want a blog intro text? (on/off)", $yaml["blog"]["intro"], "on");
|
||||
$yaml["blog"]["disqus"] = get("Your Disqus shortname (Leave empty to disable)", $yaml["blog"]["disqus"], "");
|
||||
$yaml["blog"]["analytics"] = get("Google Analytics ID (Leave empty to disable)", $yaml["blog"]["analytics"], "");
|
||||
$yaml["blog"]["footer"] = get("The footer of your blog", $yaml["blog"]["footer"], "Example Blog 2016 CC-BY-SA 4.0");
|
||||
|
||||
// design part
|
||||
$yaml["design"]["fab"] = getBool("Would you like to use the share buttons (on/off)", $yaml["design"]["blog"], "on");
|
||||
$yaml["design"]["drawer"] = getBool("Would you like the use the navigation drawer? (on/off)", $yaml["design"]["drawer"], "on");
|
||||
$themes = getDir('./themes');
|
||||
$yaml["design"]["theme"] = get("Which theme would you like to use? (" . $themes . ")", $yaml["design"]["theme"], "material-light");
|
||||
$yaml["design"]["pagination"] =
|
||||
get("Which posts should be displayed on one page (0 to disable)", $yaml["design"]["pagination"], "0");
|
||||
$yaml["design"]["favicon"] = get("URL to your favicon", $yaml["design"]["favicon"], "https://example.com/fav.ico");
|
||||
|
||||
// rcc
|
||||
$yaml["rcc"]["rcc"] = "off";
|
||||
$yaml["rcc"]["api"] = "off";
|
||||
|
||||
// languages
|
||||
$langs = getDir('./lang');
|
||||
$yaml["language"] = get("Choose a language (" . $langs . ")", $yaml["language"], "en");
|
||||
|
||||
$config->writeConfig($yaml);
|
||||
|
||||
function get($question, $value, $default)
|
||||
{
|
||||
if (isset($value) && $value != "") {
|
||||
$input = readline($question . " (" . $value . "): ");
|
||||
if ($input == "") {
|
||||
return $value;
|
||||
} else {
|
||||
return $input;
|
||||
}
|
||||
} else {
|
||||
$input = readline($question . " (" . $default . ")" . ": ");
|
||||
if ($input == "") {
|
||||
return $default;
|
||||
} else {
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getBool($question, $value, $default)
|
||||
{
|
||||
if (isset($value) && $value != "") {
|
||||
$input = "someval";
|
||||
while (!in_array($input, array("on", "off", ""))) {
|
||||
$input = readline($question . " (" . $value . "): ");
|
||||
}
|
||||
if ($input == "") {
|
||||
return $value;
|
||||
} else {
|
||||
return $input;
|
||||
}
|
||||
} else {
|
||||
$input = "";
|
||||
while (!in_array($input, array("on", "off"))) {
|
||||
$input = readline($question . " (" . $default . ")" . ": ");
|
||||
}
|
||||
if ($input == "") {
|
||||
return $default;
|
||||
} else {
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getDir($path)
|
||||
{
|
||||
$dir = scandir($path, SCANDIR_SORT_DESCENDING);
|
||||
|
||||
unset($dir[sizeof($dir) - 1]);
|
||||
unset($dir[sizeof($dir) - 1]);
|
||||
|
||||
return implode(", ", $dir);
|
||||
}
|
70
bin/init_rcc.php
Normal file
70
bin/init_rcc.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
// Marcel Kapfer (mmk2410)
|
||||
// PHP script for initializing the RCC
|
||||
// License: MIT
|
||||
|
||||
require 'res/php/Config.php';
|
||||
|
||||
use mmk2410\rbe\config\Config as Config;
|
||||
|
||||
echo 'RCC Initializion Script' . "\n";
|
||||
$username = readline("Username: ");
|
||||
|
||||
if ($username == "") {
|
||||
echo "No username given. Aborting...\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
echo 'Password: ';
|
||||
$password = readline("Password: ");
|
||||
|
||||
if ($password == "") {
|
||||
echo "No password given. Aborting...\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
$username = '$username = "' . $username . '";';
|
||||
$password = '$password = "' . $password . '";';
|
||||
|
||||
$file = '<?php' . "\n" . $username . "\n" . $password . "\n";
|
||||
|
||||
if (file_put_contents('./rcc/password.php', $file)) {
|
||||
chmod('./rcc/password.php', 0640);
|
||||
echo "\nPassword successfully saved.\n";
|
||||
}
|
||||
|
||||
$config = new Config('config.yaml', 'vendor/autoload.php');
|
||||
|
||||
$yaml = $config->getConfig();
|
||||
|
||||
$rccOn = "";
|
||||
|
||||
while (!(in_array($rccOn, array("y", "Y", "n", "N")))) {
|
||||
$rccOn = readline("Enable RCC: (y/n) ");
|
||||
}
|
||||
|
||||
if (in_array($rccOn, array("y", "Y"))) {
|
||||
$yaml["rcc"]["rcc"] = "on";
|
||||
} else {
|
||||
$yaml["rcc"]["rcc"] = "off";
|
||||
}
|
||||
|
||||
$apiOn = "";
|
||||
|
||||
while (!(in_array($apiOn, array("Y", "y", "n", "N")))) {
|
||||
$apiOn = readline("Enable RCC API: (y/n) ");
|
||||
}
|
||||
|
||||
if (in_array($apiOn, array("y", "Y"))) {
|
||||
$yaml["rcc"]["api"] = "on";
|
||||
} else {
|
||||
$yaml["rcc"]["api"] = "off";
|
||||
}
|
||||
|
||||
$config = new Config('config.yaml', 'vendor/autoload.php');
|
||||
|
||||
if ($config->writeConfig($yaml)) {
|
||||
echo "Changes saved.\n";
|
||||
} else {
|
||||
echo "Failed to save changes.\n";
|
||||
}
|
|
@ -4,12 +4,15 @@
|
|||
"type": "project",
|
||||
"require": {
|
||||
"erusev/parsedown": "^1.6",
|
||||
"fguillot/picofeed": "^0.1.18"
|
||||
"fguillot/picofeed": "^0.1.18",
|
||||
"slim/slim": "^3.0",
|
||||
"symfony/yaml": "^3.0",
|
||||
"codeguy/upload": "^1.3"
|
||||
},
|
||||
"license": "MIT License",
|
||||
"authors": [
|
||||
{
|
||||
"name": "mmk2410",
|
||||
"name": "Marcel Kapfer (mmk2410)",
|
||||
"email": "marcelmichaelkapfer@yahoo.co.nz"
|
||||
}
|
||||
],
|
||||
|
|
391
composer.lock
generated
391
composer.lock
generated
|
@ -4,9 +4,132 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "4f3494edee00a6dd92be308e4f860622",
|
||||
"content-hash": "d93c93221ea797a445a0313f18feccda",
|
||||
"hash": "bf0772b9501ce6231c06bfbcdb671d1d",
|
||||
"content-hash": "49b3f5550e60b62ffeb5306a75a87d97",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bshaffer/oauth2-server-php",
|
||||
"version": "v1.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bshaffer/oauth2-server-php.git",
|
||||
"reference": "058c98f73209f9c49495e1799d32c035196fe8b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/058c98f73209f9c49495e1799d32c035196fe8b8",
|
||||
"reference": "058c98f73209f9c49495e1799d32c035196fe8b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"suggest": {
|
||||
"aws/aws-sdk-php": "~2.8 is required to use the DynamoDB storage engine",
|
||||
"firebase/php-jwt": "~2.2 is required to use JWT features",
|
||||
"predis/predis": "Required to use the Redis storage engine",
|
||||
"thobbs/phpcassa": "Required to use the Cassandra storage engine"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"OAuth2": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Brent Shaffer",
|
||||
"email": "bshafs@gmail.com",
|
||||
"homepage": "http://brentertainment.com"
|
||||
}
|
||||
],
|
||||
"description": "OAuth2 Server for PHP",
|
||||
"homepage": "http://github.com/bshaffer/oauth2-server-php",
|
||||
"keywords": [
|
||||
"auth",
|
||||
"oauth",
|
||||
"oauth2"
|
||||
],
|
||||
"time": "2015-09-18 18:05:10"
|
||||
},
|
||||
{
|
||||
"name": "codeguy/upload",
|
||||
"version": "1.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codeguy/Upload.git",
|
||||
"reference": "6a9e5e1fb58d65346d0e557db2d46fb25efd3e37"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/codeguy/Upload/zipball/6a9e5e1fb58d65346d0e557db2d46fb25efd3e37",
|
||||
"reference": "6a9e5e1fb58d65346d0e557db2d46fb25efd3e37",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-fileinfo": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "3.7.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Upload": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Josh Lockhart",
|
||||
"email": "info@joshlockhart.com",
|
||||
"homepage": "http://www.joshlockhart.com/"
|
||||
}
|
||||
],
|
||||
"description": "Handle file uploads with extensible validation and storage strategies",
|
||||
"homepage": "http://github.com/codeguy/Upload",
|
||||
"keywords": [
|
||||
"file",
|
||||
"upload",
|
||||
"validation"
|
||||
],
|
||||
"time": "2013-07-07 17:01:41"
|
||||
},
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/container-interop.git",
|
||||
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e",
|
||||
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/Interop/Container/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"time": "2014-12-30 15:22:37"
|
||||
},
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
"version": "1.6.0",
|
||||
|
@ -48,16 +171,16 @@
|
|||
},
|
||||
{
|
||||
"name": "fguillot/picofeed",
|
||||
"version": "v0.1.18",
|
||||
"version": "v0.1.23",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fguillot/picoFeed.git",
|
||||
"reference": "8f776343b0dada397c2a950a7c3f7be57442fa35"
|
||||
"reference": "a7c3d420c239fe9ffc39b0d06b6e57db39ce3797"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fguillot/picoFeed/zipball/8f776343b0dada397c2a950a7c3f7be57442fa35",
|
||||
"reference": "8f776343b0dada397c2a950a7c3f7be57442fa35",
|
||||
"url": "https://api.github.com/repos/fguillot/picoFeed/zipball/a7c3d420c239fe9ffc39b0d06b6e57db39ce3797",
|
||||
"reference": "a7c3d420c239fe9ffc39b0d06b6e57db39ce3797",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -92,7 +215,261 @@
|
|||
],
|
||||
"description": "Modern library to handle RSS/Atom feeds",
|
||||
"homepage": "https://github.com/fguillot/picoFeed",
|
||||
"time": "2016-02-09 02:49:54"
|
||||
"time": "2016-04-17 22:31:55"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v0.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/FastRoute.git",
|
||||
"reference": "31fa86924556b80735f98b294a7ffdfb26789f22"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/31fa86924556b80735f98b294a7ffdfb26789f22",
|
||||
"reference": "31fa86924556b80735f98b294a7ffdfb26789f22",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov",
|
||||
"email": "nikic@php.net"
|
||||
}
|
||||
],
|
||||
"description": "Fast request router for PHP",
|
||||
"keywords": [
|
||||
"router",
|
||||
"routing"
|
||||
],
|
||||
"time": "2015-06-18 19:15:47"
|
||||
},
|
||||
{
|
||||
"name": "pimple/pimple",
|
||||
"version": "v3.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/silexphp/Pimple.git",
|
||||
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
|
||||
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Pimple": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Pimple, a simple Dependency Injection Container",
|
||||
"homepage": "http://pimple.sensiolabs.org",
|
||||
"keywords": [
|
||||
"container",
|
||||
"dependency injection"
|
||||
],
|
||||
"time": "2015-09-11 15:10:35"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
|
||||
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2015-05-04 20:22:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "939f2e85d57508de9cff241d10091cd972f221c3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/939f2e85d57508de9cff241d10091cd972f221c3",
|
||||
"reference": "939f2e85d57508de9cff241d10091cd972f221c3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/container-interop": "^1.1",
|
||||
"nikic/fast-route": "^0.6",
|
||||
"php": ">=5.5.0",
|
||||
"pimple/pimple": "^3.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^2.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Slim\\": "Slim"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rob Allen",
|
||||
"email": "rob@akrabat.com",
|
||||
"homepage": "http://akrabat.com"
|
||||
},
|
||||
{
|
||||
"name": "Josh Lockhart",
|
||||
"email": "hello@joshlockhart.com",
|
||||
"homepage": "https://joshlockhart.com"
|
||||
},
|
||||
{
|
||||
"name": "Gabriel Manricks",
|
||||
"email": "gmanricks@me.com",
|
||||
"homepage": "http://gabrielmanricks.com"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Smith",
|
||||
"email": "a.smith@silentworks.co.uk",
|
||||
"homepage": "http://silentworks.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
|
||||
"homepage": "http://slimframework.com",
|
||||
"keywords": [
|
||||
"api",
|
||||
"framework",
|
||||
"micro",
|
||||
"router"
|
||||
],
|
||||
"time": "2016-03-10 21:37:40"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v3.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "0047c8366744a16de7516622c5b7355336afae96"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/0047c8366744a16de7516622c5b7355336afae96",
|
||||
"reference": "0047c8366744a16de7516622c5b7355336afae96",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
},
|
||||
"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 Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-03-04 07:55:57"
|
||||
},
|
||||
{
|
||||
"name": "zendframework/zendxml",
|
||||
|
|
87
config.php
87
config.php
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* Rangitaki Project
|
||||
* This is the configuration file. You can configure here all necessary
|
||||
* (and possible) options without editing the index.php file.
|
||||
* Every line has an description about what you can change here.
|
||||
* Don't delete any strings. You can set your value after the '=' sign
|
||||
* and between the apostrophes.
|
||||
*
|
||||
* Make sure that every line ends with an semicolon (';').
|
||||
*
|
||||
* @category Config
|
||||
* @package Rbe
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link http://marcel-kapfer.de/rangitaki
|
||||
*/
|
||||
|
||||
// Blog Title / Set here an individual title of yourblog by replacing
|
||||
// Rangitaki Blog with it.
|
||||
$blogtitle = 'Example Blog';
|
||||
|
||||
// Blog Author - Set here your name
|
||||
$blogauthor = 'John';
|
||||
|
||||
// Blog description
|
||||
$blogdescription = 'A short description of your blog';
|
||||
|
||||
// Home - set yes if you want to link to your homepage and no if not
|
||||
$bloghome = 'yes';
|
||||
|
||||
// Home URL - Set here the url to your main page. Either as a path (e.g. '../')
|
||||
// or as an url (e.g. 'http://github.com')
|
||||
$bloghomeurl = '../';
|
||||
|
||||
// Home name - Set here an individual name for your main page
|
||||
$bloghomename = 'Home';
|
||||
|
||||
// Main Blog name -> Set a specific name for your main blog
|
||||
// This value is empty by default
|
||||
$blogmainname = '';
|
||||
|
||||
// Intro - set yes if you have a blog intro and no if you don't have one
|
||||
$blogintro = 'yes';
|
||||
|
||||
// Disqus - Provide here your Disqus shortname. Leave empty if you don't
|
||||
// want to use it.
|
||||
$blogdisqus = 'rangitaki';
|
||||
|
||||
// Share FAB - this enables or disables the share button
|
||||
$sharefab = 'yes';
|
||||
|
||||
// Google Analytics - Provide here your Google Analytics Tracking-ID. Leave
|
||||
// empty if you don't want to use it.
|
||||
$bloganalytics = '';
|
||||
|
||||
// Footer - set here the text for your footer (e.g. a copyright info). You can
|
||||
// replace the whole text after the '=' with your own one.
|
||||
$blogfooter = 'Rangitaki ' . date("Y") .
|
||||
' <a href="https://github.com/mmk2410/Rangitaki" target="blank">
|
||||
github.com/mmk2410/Rangitaki</a>';
|
||||
|
||||
// This enables the optional rangitaki control center. Please read the
|
||||
// documentation before you enable it.
|
||||
$rcc = 'yes';
|
||||
|
||||
// Here you can disable and enable the navigation menu. Usefull if you have
|
||||
// no subblogs and no home directory
|
||||
$nav_drawer = 'yes';
|
||||
|
||||
// Set here the name of your theme. Read the documentation for more themes
|
||||
$theme = 'material-light';
|
||||
|
||||
// Set here your language. The file must exist in the lang directory
|
||||
$language = "en";
|
||||
|
||||
// pagination: how many articles should be on one page
|
||||
// set to 0 to disable it
|
||||
$pagination = 0;
|
||||
|
||||
// Favicon - Set here the path to your favicon
|
||||
$favicon = "http://example.com/res/img/favicon.png";
|
||||
|
||||
// Blog url - set here the blog url
|
||||
$blogurl = "https://example.com/blog/";
|
23
config.yaml
Normal file
23
config.yaml
Normal file
|
@ -0,0 +1,23 @@
|
|||
blog:
|
||||
title: 'Example Blog'
|
||||
author: John
|
||||
description: 'A short description of your blog'
|
||||
home: 'on'
|
||||
homeurl: ../
|
||||
homename: Home
|
||||
mainname: ''
|
||||
intro: 'on'
|
||||
disqus: rangitaki
|
||||
analytics: ''
|
||||
footer: "Rangitaki 2016 <a href=\"https://github.com/mmk2410/Rangitaki\" target=\"blank\">\n github.com/mmk2410/Rangitaki</a>"
|
||||
url: 'https://example.com/blog/'
|
||||
design:
|
||||
fab: 'on'
|
||||
drawer: 'on'
|
||||
theme: material-light
|
||||
pagination: 0
|
||||
favicon: 'http://example.com/res/img/favicon.png'
|
||||
rcc:
|
||||
rcc: 'on'
|
||||
api: 'on'
|
||||
language: en
|
|
@ -1,11 +1 @@
|
|||
/**
|
||||
* Created by mmk2410 on 12/5/15.
|
||||
*
|
||||
* Example JavaScript file to demonstrate the rangitaki extension support
|
||||
*/
|
||||
|
||||
function main() {
|
||||
console.log("Welcome Developer! \nYou're seeing the output of a javascript extension for the rangitaki blogging engine.")
|
||||
}
|
||||
|
||||
$(document).ready(main());
|
||||
(function(){var e;e=function(){return console.log("Welcome Developer! \nYou're seeing the output of a\nJavaScript extension for the Rangitaki blogging engine.")},$(document).ready(e())}).call(this);
|
67
gulpfile.coffee
Normal file
67
gulpfile.coffee
Normal file
|
@ -0,0 +1,67 @@
|
|||
###
|
||||
|
||||
2015 - 2016 (c) by Marcel Kapfer (mmk2410)
|
||||
|
||||
Licensed under MIT License
|
||||
|
||||
Rangitaki Gulp File
|
||||
|
||||
###
|
||||
|
||||
gulp = require 'gulp'
|
||||
sass = require 'gulp-sass'
|
||||
sourcemaps = require 'gulp-sourcemaps'
|
||||
minifyCss = require 'gulp-csso'
|
||||
coffee = require 'gulp-coffee'
|
||||
coffeelint = require 'gulp-coffeelint'
|
||||
uglify = require 'gulp-uglify'
|
||||
merge = require 'merge-stream'
|
||||
del = require 'del'
|
||||
size = require 'gulp-size'
|
||||
|
||||
gulp.task 'coffee', ->
|
||||
main = gulp.src './src/coffee/*.coffee'
|
||||
.pipe coffeelint()
|
||||
.pipe coffeelint.reporter()
|
||||
.pipe coffee()
|
||||
.pipe uglify()
|
||||
.pipe gulp.dest './res/js/'
|
||||
|
||||
extensions = gulp.src './src/coffee-extensions/*.coffee'
|
||||
.pipe coffeelint()
|
||||
.pipe coffeelint.reporter()
|
||||
.pipe coffee()
|
||||
.pipe uglify()
|
||||
.pipe gulp.dest './extensions/'
|
||||
|
||||
merge(main, extensions)
|
||||
.pipe size {title: 'Coffee'}
|
||||
|
||||
gulp.task 'sass', ->
|
||||
main = gulp.src './src/sass/*.sass'
|
||||
.pipe sourcemaps.init()
|
||||
.pipe sass {
|
||||
outputStyle: 'compressed'
|
||||
}
|
||||
.pipe sourcemaps.write './'
|
||||
.pipe gulp.dest './res/css/'
|
||||
|
||||
theme = gulp.src './src/sass-themes/*.sass'
|
||||
.pipe sourcemaps.init()
|
||||
.pipe sass {
|
||||
outputStyle: 'compressed'
|
||||
}
|
||||
.pipe sourcemaps.write './'
|
||||
.pipe gulp.dest './themes/'
|
||||
|
||||
merge(theme, main)
|
||||
.pipe size {title: 'SASS'}
|
||||
|
||||
gulp.task 'clean', del.bind null, ['res/css/no-nav.css', 'res/css/rangitaki.css', 'themes/', 'res/js/app.js']
|
||||
|
||||
gulp.task 'init', ['coffee', 'sass']
|
||||
|
||||
gulp.task 'default', ->
|
||||
gulp.watch './src/**/*.sass', ['sass']
|
||||
gulp.watch './src/**/*.coffee', ['coffee']
|
||||
|
106
index.php
106
index.php
|
@ -1,15 +1,11 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Rangitaki Blogging Engine
|
||||
GitHub: https://github.com/mmk2410/Rangitaki
|
||||
Code: https://gitlab.com/mmk2410/rangitaki
|
||||
Issus and Project Management: https://phab.mmk2410.org
|
||||
Web: https://marcel-kapfer.de/rangitaki
|
||||
Twitter: @Rangitaki
|
||||
Google+: +Rangitaki
|
||||
-->
|
||||
<!--
|
||||
COPYRIGHT (c) 2015 mmk2410
|
||||
|
||||
MIT License
|
||||
2015 - 2016 Marcel Kapfer (mmk2410)
|
||||
License: MIT
|
||||
-->
|
||||
<html>
|
||||
<?php
|
||||
|
@ -28,8 +24,14 @@ MIT License
|
|||
date_default_timezone_set('UTC');
|
||||
require __DIR__ . '/vendor/autoload.php'; // loading composer libs
|
||||
|
||||
require 'config.php'; // Config file (this must be the first line)
|
||||
require './lang/' . $language . ".php"; // Language file
|
||||
require './res/php/Config.php';
|
||||
use mmk2410\rbe\config\Config as Config;
|
||||
|
||||
$configParser = new Config('config.yaml', 'vendor/autoload.php');
|
||||
|
||||
$config = $configParser->getConfig();
|
||||
|
||||
require './lang/' . $config["language"] . ".php"; // Language file
|
||||
require_once 'res/php/ArticleGenerator.php'; // The article generator
|
||||
require_once './res/php/BlogListGenerator.php'; // and the blog list generator
|
||||
|
||||
|
@ -42,16 +44,16 @@ $url = "http://" . filter_input(INPUT_SERVER, "HTTP_HOST") .
|
|||
$pagenumber = filter_input(INPUT_GET, "page"); // get the pagenumber
|
||||
|
||||
// Pagination algorithm
|
||||
if ($pagination == 0) {
|
||||
$pagination = false;
|
||||
if ($config["design"]["pagination"] == 0) {
|
||||
$config["design"]["pagination"] = false;
|
||||
} else {
|
||||
// pag_max: the newest post to show on a page
|
||||
$pag_max = $pagination * ( $pagenumber + 1 );
|
||||
$pag_max = $config["design"]["pagination"] * ( $pagenumber + 1 );
|
||||
// pag_min: the oldest post to show on a page
|
||||
$pag_min = $pag_max - $pagination;
|
||||
$pag_min = $pag_max - $config["design"]["pagination"];
|
||||
if ($pagenumber > 0) {
|
||||
// Disable the blog intro if not on first page
|
||||
$blogintro = "no";
|
||||
$config["blog"]["intro"] = "off";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,10 +74,10 @@ if (isset($getarticle)) {
|
|||
= ArticleGenerator::getTitle($articlesdir, $getarticle . '.md');
|
||||
}
|
||||
// Make sure that the entry has a title, because main.md hasn't one
|
||||
if (empty($blogmainname)) {
|
||||
$blogmaintitle = $blogtitle;
|
||||
if (empty($config["blog"]["mainname"])) {
|
||||
$blogmaintitle = $config["blog"]["title"];
|
||||
} else {
|
||||
$blogmaintitle = $blogmainname;
|
||||
$blogmaintitle = $config["blog"]["mainname"];
|
||||
}
|
||||
if (isset($getblog)) {
|
||||
$subblogtitle = BlogListGenerator::getName('./blogs/' . $getblog . '.md');
|
||||
|
@ -90,18 +92,18 @@ if (isset($getarticle)) {
|
|||
}
|
||||
|
||||
// url of the feed
|
||||
$feedurl = $blogurl . "/feed/" . $blog . ".atom";
|
||||
$feedurl = $config["blog"]["url"] . "/feed/" . $blog . ".atom";
|
||||
|
||||
?>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?php echo $blogtitle . " » " .$hd_subblog_title; ?></title>
|
||||
<title><?php echo $config["blog"]["title"] . " » " .$hd_subblog_title; ?></title>
|
||||
<!--Metatags-->
|
||||
<meta name="author"
|
||||
content="<?php echo $blogauthor; // Set the blog author ?>"/>
|
||||
content="<?php echo $config["blog"]["author"]; // Set the blog author ?>"/>
|
||||
<meta name="description"
|
||||
content="<?php echo $blogdescription; // the blog description ?>"/>
|
||||
content="<?php echo $config["blog"]["description"]; // the blog description ?>"/>
|
||||
<!-- Meta tag for responsive ui-->
|
||||
<meta name='viewport'
|
||||
content='width=device-width, initial-scale=1.0,
|
||||
|
@ -110,15 +112,15 @@ $feedurl = $blogurl . "/feed/" . $blog . ".atom";
|
|||
<meta property="og:title" content="<?php echo $hd_subblog_title; ?>"/>
|
||||
<meta property="og:type" content="website"/>
|
||||
<meta property="og:url" content="<?php echo $url; ?>"/>
|
||||
<meta property="og:image" content="<?php echo $favicon; ?>"/>
|
||||
<meta property="og:description" content="<?php echo $blogdescription; ?>"/>
|
||||
<meta property="og:image" content="<?php echo $config['design']['favicon']; ?>"/>
|
||||
<meta property="og:description" content="<?php echo $config['blog']['description']; ?>"/>
|
||||
<meta property="og:locale:alternate" content="<?php echo $lang; ?>"/>
|
||||
<!-- Twitter meta tags -->
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
<meta name="twitter:site" content="<?php echo $twitter; ?>"/>
|
||||
<meta name="twitter:title" content="<?php echo $hd_subblog_title; ?>"/>
|
||||
<meta name="twitter:description" content="<?php echo $blogdescription; ?>"/>
|
||||
<meta name="twitter:image" content="<?php echo $favicon; ?>"/>
|
||||
<meta name="twitter:description" content="<?php echo $config['blog']['description']; ?>"/>
|
||||
<meta name="twitter:image" content="<?php echo $config['design']['favicon']; ?>"/>
|
||||
<meta name="twitter:url" content="<?php echo $url; ?>"/>
|
||||
<!-- atom feed -->
|
||||
<?php
|
||||
|
@ -136,10 +138,10 @@ $feedurl = $blogurl . "/feed/" . $blog . ".atom";
|
|||
<!-- stylesheet for code highlighting-->
|
||||
<link rel="stylesheet" href="./res/css/github-gist.css">
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="themes/<?php echo $theme; // getting the theme stylesheet?>.css"/>
|
||||
href="themes/<?php echo $config['design']['theme']; // getting the theme stylesheet?>.css"/>
|
||||
<?php
|
||||
// Checking if the drawer is enabled
|
||||
if ($nav_drawer == 'no') {
|
||||
if ($config["design"]["drawer"] != 'on') {
|
||||
// Loading additional stylesheet for disabling the drawer?>
|
||||
<link rel="stylesheet" type="text/css" href="res/css/no-nav.css"/>
|
||||
<?php
|
||||
|
@ -150,8 +152,8 @@ $feedurl = $blogurl . "/feed/" . $blog . ".atom";
|
|||
type='text/css'> <!--Font-->
|
||||
<!--Favicons-->
|
||||
<link rel="shortcut icon" type="image/x-icon"
|
||||
href="<?php echo $favicon; ?>"/>
|
||||
<link rel="apple-touch-icon-precomposed" href="<?php echo $favicon; ?>">
|
||||
href="<?php echo $config['design']['favicon']; ?>"/>
|
||||
<link rel="apple-touch-icon-precomposed" href="<?php echo $config['design']['favicon']; ?>">
|
||||
<!-- JavaScript Pt. 1: HightlightJS (get and load): Code highlighting-->
|
||||
<script src="./res/js/highlight.pack.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
|
@ -160,7 +162,7 @@ $feedurl = $blogurl . "/feed/" . $blog . ".atom";
|
|||
<body>
|
||||
<?php
|
||||
// Checking if the navigation drawer is enabled. If not -> skip it
|
||||
if ($nav_drawer == "yes") {
|
||||
if ($config["design"]["drawer"] == "on") {
|
||||
?>
|
||||
<!--
|
||||
Darken the background when fading the drawer in. See also the JS file
|
||||
|
@ -181,8 +183,8 @@ if ($nav_drawer == "yes") {
|
|||
echo "<section>";
|
||||
// 1. Set localized string 2. Set blogtitle
|
||||
echo "<div class='nav-item-static'>" .
|
||||
$BLOGLANG['Blogs on'] .
|
||||
" $blogtitle:</div>";
|
||||
$BLOGLANG['Blogs on'] . $config["blog"]["title"] .
|
||||
":</div>";
|
||||
// iterating through the blogs/ directory
|
||||
foreach ($blogs as $navblog) {
|
||||
// check if filename is larger than three chars and if the
|
||||
|
@ -192,7 +194,7 @@ if ($nav_drawer == "yes") {
|
|||
if ($navblog != "main.md") { // excluding main blog
|
||||
// creating navigation item
|
||||
BlogListGenerator::listBlog(
|
||||
"./blogs/", $navblog, $blogtitle
|
||||
"./blogs/", $navblog, $config["blog"]["title"]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -215,11 +217,11 @@ if ($nav_drawer == "yes") {
|
|||
<a class="nav-item" onclick="goBack()">Go back</a>
|
||||
<?php
|
||||
}
|
||||
if ($bloghome == "yes") { // If a blog home is existend
|
||||
if ($config["blog"]["home"] == "on") { // If a blog home is existend
|
||||
?>
|
||||
<div class="divider"></div>
|
||||
<a class="nav-item" href="<?php echo $bloghomeurl; ?>">
|
||||
<?php echo $bloghomename; ?>
|
||||
<a class="nav-item" href="<?php echo $config['blog']['homeurl']; ?>">
|
||||
<?php echo $config['blog']['homename']; ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
@ -246,13 +248,13 @@ if ($nav_drawer == "yes") {
|
|||
<img src="./res/img/menu.svg" class="nav-img"/>
|
||||
<!-- Blog title with subblog title and links to each one-->
|
||||
<!-- link to main blog-->
|
||||
<nobr><span class="title"><a href="./"><?php echo $blogtitle; ?>
|
||||
<nobr><span class="title"><a href="./"><?php echo $config["blog"]["title"]; ?>
|
||||
<?php
|
||||
if (empty($getblog)) { // if not on a subblog
|
||||
if (!empty($blogmainname)) {
|
||||
if (!empty($config['blog']['mainname'])) {
|
||||
// If you see a › (square) here : This is not a bug,
|
||||
// but a missing sign in your font
|
||||
echo "›" . $blogmainname;
|
||||
echo "›" . $config['blog']['mainname'];
|
||||
}
|
||||
} else { // On subblog: set also a link to the subblog
|
||||
?>
|
||||
|
@ -276,7 +278,7 @@ if ($nav_drawer == "yes") {
|
|||
// Blog Intro text
|
||||
if (file_exists("blogs/$blog.md")
|
||||
&& $getarticle == ""
|
||||
&& $blogintro == "yes"
|
||||
&& $config["blog"]["intro"] == "on"
|
||||
&& $gettag == ""
|
||||
) {
|
||||
// only shown if not in article or tag view
|
||||
|
@ -292,11 +294,11 @@ if ($nav_drawer == "yes") {
|
|||
?>
|
||||
<section class="card" id="intro">
|
||||
<div class="articletext">
|
||||
<?php // generate the html text from the markdown file
|
||||
$intro = Parsedown::instance()
|
||||
->setBreaksEnabled(true)// with linebreaks
|
||||
->text($file);
|
||||
echo $intro; // PRINTS THE SH****
|
||||
<?php // generate the html text from the markdown file
|
||||
$intro = Parsedown::instance()
|
||||
->setBreaksEnabled(true)// with linebreaks
|
||||
->text($file);
|
||||
echo $intro; // PRINTS THE SH****
|
||||
?>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -332,7 +334,7 @@ if ($nav_drawer == "yes") {
|
|||
// check if the file is a article file
|
||||
if (strlen($article) >= 3 && substr($article, -3) == ".md") {
|
||||
// generate the article
|
||||
if ($pagination) {
|
||||
if ($config["design"]["pagination"]) {
|
||||
if ($posts_amount < $pag_max && $posts_amount >= $pag_min) {
|
||||
ArticleGenerator::newArticle(
|
||||
$articlesdir, $article, $getblog
|
||||
|
@ -346,7 +348,7 @@ if ($nav_drawer == "yes") {
|
|||
}
|
||||
$posts_amount++;
|
||||
}
|
||||
if ($pagination) {
|
||||
if ($config["design"]["pagination"]) {
|
||||
include './res/php/Pagination.php';
|
||||
}
|
||||
} elseif (isset($getarticle)) { // ARTICLE VIEW
|
||||
|
@ -360,16 +362,16 @@ if ($nav_drawer == "yes") {
|
|||
}
|
||||
?>
|
||||
<div class="footer">
|
||||
<?php echo $blogfooter; //print the blog footer?>
|
||||
<?php echo $config["blog"]["footer"]; //print the blog footer?>
|
||||
</div>
|
||||
<?php
|
||||
// show the fab if it's enabled
|
||||
if ($sharefab == "yes") {
|
||||
if ($config["design"]["fab"] == "on") {
|
||||
?>
|
||||
<div class="fabmenu">
|
||||
<div class="subfab"><!--Email subfab-->
|
||||
<a href='mailto:?subject=<?php
|
||||
echo $blogtitle;
|
||||
echo $config["blog"]["title"];
|
||||
?>&body=<?php
|
||||
echo $BLOGLANG['Check out this blog'];
|
||||
?>: <?php
|
||||
|
@ -398,7 +400,7 @@ if ($nav_drawer == "yes") {
|
|||
<a href='https://www.facebook.com/sharer/sharer.php?u=<?php
|
||||
echo $url;
|
||||
?>&t=<?php
|
||||
echo "echo $blogtitle"
|
||||
echo "echo " . $config["blog"]["title"];
|
||||
?>' target="blank">
|
||||
<img src="./res/img/facebook.svg" class="subfab-img"/>
|
||||
</a>
|
||||
|
|
35
package.json
Normal file
35
package.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "rangitaki",
|
||||
"version": "1.4.0",
|
||||
"description": "A simple PHP blogging engine without any database dependencies",
|
||||
"main": "index.php",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@gitlab.com/mmk2410/rangitaki.git"
|
||||
},
|
||||
"keywords": [
|
||||
"blogging",
|
||||
"php"
|
||||
],
|
||||
"author": "Marcel Kapfer (mmk2410)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/mmk2410/rangitaki/issues"
|
||||
},
|
||||
"homepage": "https://gitlab.com/mmk2410/rangitaki#README",
|
||||
"devDependencies": {
|
||||
"del": "^2.2.0",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-coffee": "^2.3.2",
|
||||
"gulp-coffeelint": "^0.6.0",
|
||||
"gulp-csso": "^2.0.0",
|
||||
"gulp-sass": "^2.3.1",
|
||||
"gulp-size": "^2.1.0",
|
||||
"gulp-sourcemaps": "^2.0.0-alpha",
|
||||
"gulp-uglify": "^1.5.3",
|
||||
"merge-stream": "^1.0.0"
|
||||
}
|
||||
}
|
52
rcc/api/auth/DigestAuth.php
Normal file
52
rcc/api/auth/DigestAuth.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* Authentication Helper Class
|
||||
*
|
||||
* @category Authentication
|
||||
* @package Rbe
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link http://marcel-kapfer.de/rangitaki
|
||||
*/
|
||||
namespace mmk2410\rbe\digestAuth;
|
||||
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* Authentication Helper Class
|
||||
*
|
||||
* @category Authentication
|
||||
* @package Rbe
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link http://marcel-kapfer.de/rangitaki
|
||||
*/
|
||||
class DigestAuth
|
||||
{
|
||||
|
||||
/**
|
||||
* parser for http digest
|
||||
*
|
||||
* @param $txt data to parse
|
||||
*
|
||||
* @return parsed data or FALSE
|
||||
*/
|
||||
public function httpDigestParse($txt)
|
||||
{
|
||||
// protect against missing data
|
||||
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
|
||||
$data = array();
|
||||
$keys = implode('|', array_keys($needed_parts));
|
||||
|
||||
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
|
||||
|
||||
foreach ($matches as $m) {
|
||||
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
|
||||
unset($needed_parts[$m[1]]);
|
||||
}
|
||||
|
||||
return $needed_parts ? false : $data;
|
||||
}
|
||||
}
|
39
rcc/api/auth/auth.php
Normal file
39
rcc/api/auth/auth.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
// Marcel Kapfer (mmk2410)
|
||||
// License: MIT License
|
||||
// api digest auth
|
||||
|
||||
require 'DigestAuth.php';
|
||||
|
||||
require '../../password.php';
|
||||
|
||||
use \mmk2410\rbe\digestAuth\DigestAuth as DigestAuth;
|
||||
|
||||
$realm = 'Restricted area';
|
||||
|
||||
$users = array($username => $password);
|
||||
|
||||
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
header('WWW-Authenticate: Digest realm="'.$realm.
|
||||
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
|
||||
|
||||
die('Access to RCC API not granted');
|
||||
}
|
||||
|
||||
|
||||
// analyze the PHP_AUTH_DIGEST variable
|
||||
if (!($data = DigestAuth::httpDigestParse($_SERVER['PHP_AUTH_DIGEST'])) ||
|
||||
!isset($users[$data['username']])) {
|
||||
die('Wrong Credentials!');
|
||||
}
|
||||
|
||||
|
||||
// generate the valid response
|
||||
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
|
||||
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
|
||||
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
|
||||
|
||||
if ($data['response'] != $valid_response) {
|
||||
die('Wrong Credentials!');
|
||||
}
|
59
rcc/api/list/index.php
Normal file
59
rcc/api/list/index.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
// Marcel Kapfer (mmk2410)
|
||||
// License: MIT License
|
||||
// api for fetching various lists
|
||||
|
||||
use \Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use \Psr\Http\Message\ResponseInterface as Response;
|
||||
|
||||
require '../../../vendor/autoload.php';
|
||||
require '../../../res/php/Config.php';
|
||||
|
||||
include '../auth/auth.php';
|
||||
|
||||
use \mmk2410\rbe\config\Config as Config;
|
||||
|
||||
$config = new Config("../../../config.yaml", '../../../vendor/autoload.php');
|
||||
$settings = $config->getConfig();
|
||||
|
||||
if ($settings["rcc"]["api"] == "on" && $settings["rcc"]["rcc"] == "on") {
|
||||
$app = new \Slim\App();
|
||||
|
||||
/**
|
||||
* api for get the list of blogs and if $_GET["blog"] is set the list of
|
||||
* blogs posts in that blog
|
||||
*
|
||||
* @param string $_GET["blog"] optional name of the blog
|
||||
*
|
||||
* @return JSON json string containing the blogs / blog posts
|
||||
*/
|
||||
$app->get('/', function (Request $request, Response $response) {
|
||||
$blog = $_GET["blog"];
|
||||
|
||||
|
||||
if (!isset($blog)) {
|
||||
$files = scandir('../../../blogs/', SCANDIR_SORT_DESCENDING);
|
||||
|
||||
unset($files[sizeof($files) - 1]);
|
||||
unset($files[sizeof($files) - 1]);
|
||||
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($files, 201);
|
||||
return $response;
|
||||
}
|
||||
|
||||
$path = "../../../articles/" . $blog . "/";
|
||||
|
||||
$files = scandir($path, SCANDIR_SORT_DESCENDING);
|
||||
|
||||
unset($files[sizeof($files) - 1]);
|
||||
unset($files[sizeof($files) - 1]);
|
||||
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($files, 201);
|
||||
|
||||
return $response;
|
||||
});
|
||||
|
||||
$app->run();
|
||||
}
|
48
rcc/api/media/index.php
Normal file
48
rcc/api/media/index.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
// Marcel Kapfer (mmk2410)
|
||||
// License: MIT License
|
||||
// api for uploading files
|
||||
|
||||
use \Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use \Psr\Http\Message\ResponseInterface as Response;
|
||||
|
||||
require '../../../vendor/autoload.php';
|
||||
require '../../../res/php/Config.php';
|
||||
require '../../../res/php/ArticleGenerator.php';
|
||||
|
||||
include '../auth/auth.php';
|
||||
|
||||
use \mmk2410\rbe\config\Config as Config;
|
||||
|
||||
$config = new Config("../../../config.yaml", '../../../vendor/autoload.php');
|
||||
$settings = $config->getConfig();
|
||||
|
||||
if ($settings["rcc"]["api"] == "on" && $settings["rcc"]["rcc"] == "on") {
|
||||
$app = new \Slim\App();
|
||||
|
||||
/**
|
||||
* api for uploading files
|
||||
*
|
||||
* @return JSON json string with status
|
||||
*/
|
||||
$app->post('/', function (Request $request, Response $response) {
|
||||
$storage = new \Upload\Storage\FileSystem('../../../media/');
|
||||
$file = new \Upload\File('file', $storage);
|
||||
|
||||
try {
|
||||
$file->upload();
|
||||
$data = array("code" => 201);
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 201);
|
||||
} catch (\Exception $e) {
|
||||
$errors = $file->getErrors();
|
||||
$data = array("code" => 500, "error" => $Errors);
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 500);
|
||||
}
|
||||
|
||||
return $response;
|
||||
});
|
||||
|
||||
$app->run();
|
||||
}
|
141
rcc/api/post/index.php
Normal file
141
rcc/api/post/index.php
Normal file
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
// Marcel Kapfer (mmk2410)
|
||||
// License: MIT License
|
||||
// api for accessing blog posts
|
||||
|
||||
use \Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use \Psr\Http\Message\ResponseInterface as Response;
|
||||
|
||||
require '../../../vendor/autoload.php';
|
||||
require '../../../res/php/Config.php';
|
||||
require '../../../res/php/ArticleGenerator.php';
|
||||
|
||||
include '../auth/auth.php';
|
||||
|
||||
use \mmk2410\rbe\config\Config as Config;
|
||||
|
||||
$config = new Config("../../../config.yaml", '../../../vendor/autoload.php');
|
||||
$settings = $config->getConfig();
|
||||
|
||||
if ($settings["rcc"]["api"] == "on" && $settings["rcc"]["rcc"] == "on") {
|
||||
$app = new \Slim\App();
|
||||
|
||||
/**
|
||||
* api for fetching a blog post
|
||||
*
|
||||
* @param string $_GET["blog"] name of the blog
|
||||
* @param string $_GET["post"] filename of the blog post
|
||||
*
|
||||
* @return JSON json string containing the blog post
|
||||
*/
|
||||
$app->get('/', function (Request $request, Response $response) {
|
||||
$blog = $_GET["blog"];
|
||||
$post = $_GET["post"];
|
||||
|
||||
if (!isset($blog) || !isset($post)) {
|
||||
$data = array('code' => 400, 'status' => 'Bad Request', 'error' => 'Not enough arguments');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 400);
|
||||
return $response;
|
||||
}
|
||||
|
||||
$path = "../../../articles/" . $blog . "/";
|
||||
$data =
|
||||
ArticleGenerator::getArray($path, $post);
|
||||
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 201);
|
||||
|
||||
return $response;
|
||||
});
|
||||
|
||||
/**
|
||||
* api for changing/creating a blog post
|
||||
*
|
||||
* @param string $_POST["data"] all data
|
||||
*/
|
||||
$app->post('/', function (Request $request, Response $response) {
|
||||
$blog = $_POST["blog"];
|
||||
$post = $_POST["post"];
|
||||
$title = $_POST["title"];
|
||||
$author = $_POST["author"];
|
||||
$date = $_POST["date"];
|
||||
$tags = $_POST["tags"];
|
||||
$text = $_POST["text"];
|
||||
|
||||
if (!isset($blog) || !isset($post) || (!isset($title) && !isset($text))) {
|
||||
$data = array('code' => 400, 'status' => 'Bad Request', 'error' => 'Not enough arguments');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 400);
|
||||
return $response;
|
||||
}
|
||||
|
||||
$text = str_replace('\n', '<br>', $text);
|
||||
|
||||
$md = <<<EOD
|
||||
%TITLE: $title
|
||||
%DATE: $date
|
||||
%AUTHOR: $author
|
||||
%TAGS: $tags
|
||||
|
||||
$text
|
||||
EOD;
|
||||
|
||||
$path = "../../../articles/$blog/$post";
|
||||
if (file_put_contents($path, $md)) {
|
||||
$data = array('code' => 201, 'status' => 'Post created successfully');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 201);
|
||||
} else {
|
||||
$data = array('code' => 500, 'status' => 'Internal server error');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 500);
|
||||
}
|
||||
|
||||
return $response;
|
||||
});
|
||||
|
||||
/**
|
||||
* api for deleting a blog post
|
||||
*
|
||||
* @param string $_GET["blog"] name of the blog
|
||||
* @param string $_GET["post"] filename of the blog post
|
||||
*
|
||||
* @return JSON json string containing the blog post
|
||||
*/
|
||||
$app->delete('/', function (Request $request, Response $response) {
|
||||
$blog = $_GET["blog"];
|
||||
$post = $_GET["post"];
|
||||
|
||||
if (!isset($blog) || !isset($post)) {
|
||||
$data = array('code' => 400, 'status' => 'Bad Request', 'error' => 'Not enough arguments');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 400);
|
||||
return $response;
|
||||
}
|
||||
|
||||
$path = "../../../articles/$blog/$post";
|
||||
|
||||
if (!file_exists($path)) {
|
||||
$data = array('code' => 400, 'status' => 'Bad Request', 'error' => 'No such file');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 400);
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!unlink($path)) {
|
||||
$data = array('code' => 500, 'status' => 'Bad Request', 'error' => 'Internal server error');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 500);
|
||||
return $response;
|
||||
}
|
||||
|
||||
$data = array('code' => 201, 'status' => 'File successfully deleted');
|
||||
$response = $response->withHeader('Content-type', 'application/json');
|
||||
$response = $response->withJson($data, 201);
|
||||
|
||||
return $response;
|
||||
});
|
||||
|
||||
$app->run();
|
||||
}
|
|
@ -1,112 +1,172 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
* Edit page of RCC (Rangitaki Control Center)
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
date_default_timezone_set('UTC');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Rangitaki Control Center</title>
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
|
||||
|
||||
<meta name="robots" content="nofollow, noindex, noarchive, nosnippet">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
|
||||
user-scalable=0" name="viewport"/>
|
||||
|
||||
<meta name="theme-color" content="#383838">
|
||||
<meta name="description" content="Rangitaki Control Center (RCC)">
|
||||
|
||||
<link rel="stylesheet" href="../res/rcc.css"/>
|
||||
|
||||
<link href='//fonts.googleapis.com/css?family=Roboto:400,500,700,300,
|
||||
400italic,100,100italic,900' rel='stylesheet'
|
||||
type='text/css'> <!--Font-->
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
<?php
|
||||
session_start();
|
||||
if ($_SESSION['login']) {
|
||||
include_once("../../res/php/ArticleGenerator.php");
|
||||
$directory = "./../../articles/" . $_GET['blog'] . "/";
|
||||
$article = $_GET['post'] . ".md";
|
||||
?>
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
<?php
|
||||
session_start();
|
||||
if ($_SESSION['login']) {
|
||||
include_once "../../res/php/ArticleGenerator.php";
|
||||
$directory = "./../../articles/" . $_GET['blog'] . "/";
|
||||
$article = $_GET['post'] . ".md";
|
||||
?>
|
||||
<!-- Edit Post -->
|
||||
<section class="card">
|
||||
|
||||
<div class="headline">Edit Post</div>
|
||||
<p>Title:<br><br><input type="text" class="itextfield"
|
||||
value="<?php echo ArticleGenerator::getTitle($directory, $article) ?>"
|
||||
name="title"
|
||||
id="title"/>
|
||||
|
||||
<p>Title:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield"
|
||||
value="<?php
|
||||
echo ArticleGenerator::getTitle($directory, $article);
|
||||
?>" name="title" id="title"/>
|
||||
</p>
|
||||
|
||||
<p>Date:<br><br><input type="text" class="itextfield"
|
||||
value="<?php echo ArticleGenerator::getDate($directory, $article) ?>" name="date"
|
||||
id="date"/>
|
||||
<p>Date:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield"
|
||||
value="<?php
|
||||
echo ArticleGenerator::getDate($directory, $article);
|
||||
?>" name="date" id="date"/>
|
||||
</p>
|
||||
|
||||
<p>Author:<br><br><input type="text"
|
||||
value="<?php echo ArticleGenerator::getAuthor($directory, $article) ?>"
|
||||
class="itextfield" name="author"
|
||||
id="author"/></p>
|
||||
<p>Author:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield"
|
||||
value="<?php
|
||||
echo ArticleGenerator::getAuthor($directory, $article);
|
||||
?>" name="author" id="author"/>
|
||||
</p>
|
||||
|
||||
<p>Tags:<br><br><input type="text"
|
||||
value="<?php
|
||||
$tags = "";
|
||||
foreach (ArticleGenerator::getTags($directory, $article) as $tag) {
|
||||
$tags = $tags . ', ' . $tag;
|
||||
}
|
||||
$tags = substr($tags, 2);
|
||||
echo $tags;
|
||||
?>"
|
||||
class="itextfield" name="tags"
|
||||
id="tags"/></p>
|
||||
<p>Tags:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield"
|
||||
value="<?php
|
||||
$tags = "";
|
||||
foreach (
|
||||
ArticleGenerator::getTags($directory, $article)
|
||||
as $tag) {
|
||||
$tags = $tags . ', ' . $tag;
|
||||
}
|
||||
$tags = substr($tags, 2);
|
||||
echo $tags;
|
||||
?>" name="tags" id="tags"/>
|
||||
</p>
|
||||
|
||||
<p>Text:</p>
|
||||
<textarea class="itextarea" name="text" id="text">
|
||||
<?php echo ArticleGenerator::getText($directory, $article) ?>
|
||||
<?php
|
||||
echo ArticleGenerator::getText($directory, $article);
|
||||
?>
|
||||
</textarea>
|
||||
|
||||
<br><br>
|
||||
<a class="button" id="save_changes">SAVE CHANGES</a>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- Go Back -->
|
||||
<section class="card">
|
||||
|
||||
<div class="headline">Back</div>
|
||||
|
||||
<p>
|
||||
Go back to the RCC home. All changes will be lost.
|
||||
</p>
|
||||
|
||||
<a class="button" href="../">BACK</a>
|
||||
|
||||
</section>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
|
||||
<!-- Access denied -->
|
||||
<section class="card">
|
||||
|
||||
<div class="headline">Access denied</div>
|
||||
|
||||
<p>
|
||||
The access to this area is not granted. Make sure you're logged in.
|
||||
The access to this area is not granted. Make sure you're logged
|
||||
in.
|
||||
</p>
|
||||
|
||||
<a class="button" href="../">BACK</a>
|
||||
|
||||
</section>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<script>
|
||||
var getVariables = <?php echo json_encode($_GET); ?>;
|
||||
</script>
|
||||
<script src="../../res/js/jquery-2.1.4.min.js"></script>
|
||||
<script src="../res/rcc.js"></script>
|
||||
<script src="../res/edit.js"></script>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var getVariables = <?php echo json_encode($_GET); ?>;
|
||||
</script>
|
||||
<script src="../../res/js/jquery-2.1.4.min.js"></script>
|
||||
<script src="../res/rcc.js"></script>
|
||||
<script src="../res/edit.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
* PHP Version 7
|
||||
*
|
||||
* @category Atom_Feed
|
||||
* @package Rbe
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://github.com/mmk2410/rangitaki
|
||||
*
|
||||
* Feed Generator
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
|
@ -49,7 +51,7 @@ if ($_SESSION['login']) {
|
|||
|
||||
$writer->title = $blogtitle;
|
||||
$writer->site_url = $blogurl;
|
||||
$writer->feed_url = $blogurl . "/feed/feed.atom";
|
||||
$writer->feed_url = $blogurl . "/feed/" . $_GET['blog'] . ".atom";
|
||||
$writer->author = array(
|
||||
'name' => $blogauthor,
|
||||
'url' => $blogurl,
|
||||
|
@ -65,6 +67,10 @@ if ($_SESSION['login']) {
|
|||
if ($amount == 10) {
|
||||
break;
|
||||
} else {
|
||||
$file = ArticleGenerator::getText($art_dir, $article);
|
||||
$text = Parsedown::instance()
|
||||
->setBreaksEnabled(true)// with linebreaks
|
||||
->text($file);
|
||||
$writer->items[] = array(
|
||||
'title' => ArticleGenerator::getTitle($art_dir, $article),
|
||||
'updated' => strtotime(
|
||||
|
@ -73,11 +79,9 @@ if ($_SESSION['login']) {
|
|||
'url' => $blogurl . "./?article=" .
|
||||
substr($article, 0, strlen($article) - 3),
|
||||
'summary'=> ArticleGenerator::getSummary(
|
||||
$art_dir, $articles
|
||||
$art_dir, $article
|
||||
),
|
||||
'content' => "<p>" . ArticleGenerator::getText(
|
||||
$art_dir, $articles
|
||||
) . "</p>"
|
||||
'content' => $text
|
||||
);
|
||||
$amount += 1;
|
||||
}
|
||||
|
@ -88,11 +92,14 @@ if ($_SESSION['login']) {
|
|||
$feed = $writer->execute();
|
||||
|
||||
$file = fopen($feed_path, "w");
|
||||
|
||||
if (fwrite($file, $feed) === false) {
|
||||
echo "-1";
|
||||
exit;
|
||||
}
|
||||
|
||||
fclose($file);
|
||||
|
||||
echo "0";
|
||||
}
|
||||
?>
|
||||
|
|
477
rcc/index.php
477
rcc/index.php
|
@ -1,207 +1,308 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
* Main page of RCC (Rangitaki Control Center)
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!--
|
||||
Rangitaki Blogging Engine - RCC (Rangitaki Control Center)
|
||||
|
||||
Copyright (c) 2016 by Marcel Kapfer (mmk2410)
|
||||
|
||||
MIT License
|
||||
-->
|
||||
<title>Rangitaki Control Center</title>
|
||||
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport'/>
|
||||
|
||||
<meta name="robots" content="nofollow, noindex, noarchive, nosnippet">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
|
||||
user-scalable=0" name="viewport"/>
|
||||
|
||||
<meta name="theme-color" content="#383838">
|
||||
<meta name="description" content="Rangitaki Control Center (RCC)">
|
||||
|
||||
<link rel="stylesheet" href="./res/rcc.css"/>
|
||||
|
||||
<link href='//fonts.googleapis.com/css?family=Roboto:400,500,700,300,
|
||||
400italic,100,100italic,900' rel='stylesheet'
|
||||
type='text/css'> <!--Font-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<a href="./" class="title">Rangitaki Control Center</a>
|
||||
<a href="../" class="back">Back to the blog</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
|
||||
<div class="header">
|
||||
<a href="./" class="title">Rangitaki Control Center</a>
|
||||
<a href="../" class="back">Back to the blog</a>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<?php
|
||||
require '../res/php/Config.php';
|
||||
use mmk2410\rbe\config\Config as Config;
|
||||
|
||||
$configParser = new Config('../config.yaml', '../vendor/autoload.php');
|
||||
|
||||
$config = $configParser->getConfig();
|
||||
|
||||
if ($config["rcc"]["rcc"] == "on") {
|
||||
include 'password.php';
|
||||
session_start();
|
||||
|
||||
if (isset($_POST['passwd'])) {
|
||||
$passwd = $_POST['passwd'];
|
||||
$_SESSION['passwd'] = $_POST['passwd'];
|
||||
} elseif (isset($_SESSION['passwd'])) {
|
||||
$passwd = $_SESSION['passwd'];
|
||||
}
|
||||
|
||||
if ($passwd == "") {
|
||||
?>
|
||||
|
||||
<!-- Login Card -->
|
||||
<section class="card">
|
||||
<div class="headline">Log In</div>
|
||||
<form action="./" method="post">
|
||||
<p>Password:
|
||||
<br><br>
|
||||
<input type="password" class="itextfield" name="passwd"/>
|
||||
</p>
|
||||
|
||||
<input type="Submit" class="button" value="Log in"/>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<?php
|
||||
require '../config.php';
|
||||
if ($rcc == "yes") {
|
||||
include 'password.php';
|
||||
session_start();
|
||||
if (isset($_POST['passwd'])) {
|
||||
$passwd = $_POST['passwd'];
|
||||
$_SESSION['passwd'] = $_POST['passwd'];
|
||||
} else if (isset($_SESSION['passwd'])) {
|
||||
$passwd = $_SESSION['passwd'];
|
||||
}
|
||||
if ($passwd == "") {
|
||||
?>
|
||||
<section class="card">
|
||||
<div class="headline">Log In</div>
|
||||
<form action="./" method="post">
|
||||
<p>Password:<br><br><input type="password" class="itextfield" name="passwd"/></p>
|
||||
<input type="Submit" class="button" value="Log in"/>
|
||||
</form>
|
||||
</section>
|
||||
<?php
|
||||
} else {
|
||||
if ($passwd == $password) {
|
||||
$_SESSION['login'] = true;
|
||||
include_once("./../res/php/BlogListGenerator.php");
|
||||
?>
|
||||
<section class="card">
|
||||
<div class="headline">Post Upload</div>
|
||||
<form enctype="multipart/form-data" action="uploaded/" method="POST">
|
||||
<select name="blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="100000"/>
|
||||
<input id="" name="userfile" type="file" value="Choose a file"/>
|
||||
<br>
|
||||
<br>
|
||||
<input id="button" type="submit" value="Upload" class="button"/>
|
||||
</form>
|
||||
</section>
|
||||
<section class="card">
|
||||
<div class="headline">New Post</div>
|
||||
<form action="newpost/" method="POST">
|
||||
<p>Blog:</p>
|
||||
<select name="blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
<p>Title:<br><br><input type="text" class="itextfield" name="title"/></p>
|
||||
|
||||
<p>Date:<br><br><input type="text" class="itextfield" name="date"/></p>
|
||||
|
||||
<p>Author:<br><br><input type="text" class="itextfield" name="author"/></p>
|
||||
|
||||
<p>Tags:<br><br><input type="text" class="itextfield" name="tags"/></p>
|
||||
|
||||
<p>Text:</p>
|
||||
<textarea class="itextarea" name="text"></textarea>
|
||||
<br><br>
|
||||
<input id="button" type="submit" value="Post" class="button"/>
|
||||
</form>
|
||||
</section>
|
||||
<section class="card">
|
||||
<div class="headline">Edit post</div>
|
||||
<p>
|
||||
First select the blog of the post you wan't to edit.
|
||||
</p>
|
||||
|
||||
<p id="edit_select_blog">
|
||||
<select name="blog" id="edit_selected_blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
<a class="button" id="edit_get_posts">GET POSTS</a>
|
||||
</section>
|
||||
<section class="card">
|
||||
<div class="headline">Delete Post</div>
|
||||
<p>
|
||||
First select the subblog of the post you want to delete.
|
||||
</p>
|
||||
|
||||
<p id="delete_select_blog">
|
||||
<select name="blog" id="delete_selected_blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
<a class="button" id="delete_get_posts">GET POSTS</a>
|
||||
</section>
|
||||
<section class="card">
|
||||
<div class="headline">Media Upload</div>
|
||||
<form enctype="multipart/form-data" action="media/" method="POST">
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="100000000000"/>
|
||||
<input id="" name="userfile" type="file" value="Choose a file"/>
|
||||
<br>
|
||||
<br>
|
||||
<input id="button" type="submit" value="Upload" class="button"/>
|
||||
</form>
|
||||
</section>
|
||||
<section class="card">
|
||||
<div class="headline">Atom Feed Generator</div>
|
||||
<p>
|
||||
<select name="blog" id="generate_atom_blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
<a class="button" id="generate_atom">GENERATE</a>
|
||||
</section>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<section class="card">
|
||||
<div class="headline">Wrong Password</div>
|
||||
<p>
|
||||
Please go back and try again.
|
||||
</p>
|
||||
<a href="./" class="button">GO BACK</a>
|
||||
</section>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($passwd == $password) {
|
||||
$_SESSION['login'] = true;
|
||||
include_once "./../res/php/BlogListGenerator.php";
|
||||
?>
|
||||
|
||||
<!-- Post Upload -->
|
||||
<section class="card">
|
||||
<div class="headline">Post Upload</div>
|
||||
<form enctype="multipart/form-data" action="uploaded/"
|
||||
method="POST">
|
||||
|
||||
<select name="blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="100000"/>
|
||||
<input id="" name="userfile" type="file" value="Choose a file"/>
|
||||
<br><br>
|
||||
|
||||
<input id="button" type="submit" value="Upload" class="button"/>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<!-- New Post -->
|
||||
<section class="card">
|
||||
<div class="headline">New Post</div>
|
||||
<form action="newpost/" method="POST">
|
||||
<p>Blog:</p>
|
||||
<select name="blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
<p>Title:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield" name="title"/>
|
||||
</p>
|
||||
|
||||
<p>Date:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield" name="date"/>
|
||||
</p>
|
||||
|
||||
<p>Author:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield" name="author"/>
|
||||
</p>
|
||||
|
||||
<p>Tags:
|
||||
<br><br>
|
||||
<input type="text" class="itextfield" name="tags"/>
|
||||
</p>
|
||||
|
||||
<p>Text:</p>
|
||||
<textarea class="itextarea" name="text"></textarea>
|
||||
<br><br>
|
||||
<input id="button" type="submit" value="Post"
|
||||
class="button"/>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<!-- Edit post -->
|
||||
<section class="card">
|
||||
<div class="headline">Edit post</div>
|
||||
<p>
|
||||
First select the blog of the post you wan't to edit.
|
||||
</p>
|
||||
|
||||
<p id="edit_select_blog">
|
||||
<select name="blog" id="edit_selected_blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
<a class="button" id="edit_get_posts">GET POSTS</a>
|
||||
</section>
|
||||
|
||||
<!-- Delete Post -->
|
||||
<section class="card">
|
||||
<div class="headline">Delete Post</div>
|
||||
<p>
|
||||
First select the subblog of the post you want to delete.
|
||||
</p>
|
||||
|
||||
<p id="delete_select_blog">
|
||||
<select name="blog" id="delete_selected_blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
<a class="button" id="delete_get_posts">GET POSTS</a>
|
||||
</section>
|
||||
|
||||
<!-- Media Upload -->
|
||||
<section class="card">
|
||||
<div class="headline">Media Upload</div>
|
||||
<form enctype="multipart/form-data" action="media/" method="POST">
|
||||
<input type="hidden" name="MAX_FILE_SIZE"
|
||||
value="100000000000"/>
|
||||
<input id="" name="userfile" type="file" value="Choose a file"/>
|
||||
<br><br>
|
||||
<input id="button" type="submit" value="Upload" class="button"/>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<!-- Atom Feed Generator -->
|
||||
<section class="card">
|
||||
<div class="headline">Atom Feed Generator</div>
|
||||
<p>
|
||||
<select name="blog" id="generate_atom_blog">
|
||||
<?php
|
||||
$blogs = scandir("../blogs/");
|
||||
foreach ($blogs as $blog) {
|
||||
if (strlen($blog) >= 3 && substr($blog, -3) == ".md") {
|
||||
$blog = substr($blog, 0, -3);
|
||||
echo "<option value='$blog'>$blog</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
<a class="button" id="generate_atom">GENERATE</a>
|
||||
</section>
|
||||
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
|
||||
<!-- Wrong Password -->
|
||||
<section class="card">
|
||||
<div class="headline">Wrong Password</div>
|
||||
<p>
|
||||
The entered password was wrong, please try again.
|
||||
</p>
|
||||
<form action="./" method="post">
|
||||
<p>Password:
|
||||
<br><br>
|
||||
<input type="password" class="itextfield" name="passwd"/>
|
||||
</p>
|
||||
|
||||
<input type="Submit" class="button" value="Log in"/>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<?php
|
||||
}
|
||||
}
|
||||
} else {
|
||||
?>
|
||||
|
||||
<!-- Not enabled -->
|
||||
<section class="card">
|
||||
<div class="headline">Rangitaki Control Center</div>
|
||||
<p>
|
||||
The Rangitaki Control Center is disabled. You can enable it in
|
||||
your config file. But please read first the documentation.
|
||||
The Rangitaki Control Center is disabled. You can enable
|
||||
it in your config file. But please read first the
|
||||
documentation.
|
||||
</p>
|
||||
</section>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<section class="card" id="back-card">
|
||||
<div class="headline">Back</div>
|
||||
<p>
|
||||
Go back to your blog.
|
||||
</p>
|
||||
<a href="../" class="button">GO BACK</a>
|
||||
</section>
|
||||
</div>
|
||||
<script src="./res/rcc.js"></script>
|
||||
<script src="../res/js/jquery-2.1.4.min.js"></script>
|
||||
<script src="./res/delete.js"></script>
|
||||
<script src="./res/edit.js"></script>
|
||||
<script src="./res/atom.js"></script>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- Back -->
|
||||
<section class="card" id="back-card">
|
||||
<div class="headline">Back</div>
|
||||
<p>Go back to your blog.</p>
|
||||
<a href="../" class="button">GO BACK</a>
|
||||
</section>
|
||||
</div>
|
||||
<script src="./res/rcc.js"></script>
|
||||
<script src="../res/js/jquery-2.1.4.min.js"></script>
|
||||
<script src="./res/delete.js"></script>
|
||||
<script src="./res/edit.js"></script>
|
||||
<script src="./res/atom.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,60 +1,100 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
* Media page of RCC (Rangitaki Control Center)
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Rangitaki Control Center</title>
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
|
||||
<link rel="stylesheet" href="../res/rcc.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
<section class="card">
|
||||
<div class="headline">File Upload</div>
|
||||
<?php
|
||||
session_start();
|
||||
if($_SESSION['login']) {
|
||||
if ($_FILES['userfile']['name'] == "") {
|
||||
echo "<p>You have to choose a file!</p>";
|
||||
} else {
|
||||
$uploaddir = "../../media/";
|
||||
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
|
||||
echo "<p>The post was successfully uploaded and is now published.</p>";
|
||||
} else {
|
||||
echo "<p>During the uploading process an error occured! <br> Error Code:" . ($_FILES['userfile']['error'] . "</p>");
|
||||
}
|
||||
}
|
||||
?><a href="../" class="button">GO BACK</a><?php
|
||||
}
|
||||
?>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
<title>Rangitaki Control Center</title>
|
||||
|
||||
<meta name="robots" content="nofollow, noindex, noarchive, nosnippet">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
|
||||
user-scalable=0" name="viewport"/>
|
||||
|
||||
<meta name="theme-color" content="#383838">
|
||||
<meta name="description" content="Rangitaki Control Center (RCC)">
|
||||
|
||||
<link rel="stylesheet" href="../res/rcc.css"/>
|
||||
|
||||
<link href='//fonts.googleapis.com/css?family=Roboto:400,500,700,300,
|
||||
400italic,100,100italic,900' rel='stylesheet'
|
||||
type='text/css'> <!--Font-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
|
||||
<section class="card">
|
||||
<div class="headline">File Upload</div>
|
||||
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
if ($_SESSION['login']) {
|
||||
if ($_FILES['userfile']['name'] == "") {
|
||||
echo "<p>You have to choose a file!</p>";
|
||||
} else {
|
||||
$uploaddir = "../../media/";
|
||||
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
|
||||
|
||||
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
|
||||
echo
|
||||
"<p>
|
||||
The post was successfully uploaded and is now published.
|
||||
</p>";
|
||||
} else {
|
||||
echo
|
||||
"<p>During the uploading process an error occured! <br>
|
||||
Error Code:"
|
||||
. ($_FILES['userfile']['error'] . "</p>");
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<a href="../" class="button">GO BACK</a>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,54 +1,82 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
* Newpost page of RCC (Rangitaki Control Center)
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
date_default_timezone_set('UTC');
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Rangitaki Control Center</title>
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
|
||||
|
||||
<meta name="robots" content="nofollow, noindex, noarchive, nosnippet">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
|
||||
user-scalable=0" name="viewport"/>
|
||||
|
||||
<meta name="theme-color" content="#383838">
|
||||
<meta name="description" content="Rangitaki Control Center (RCC)">
|
||||
|
||||
<link rel="stylesheet" href="../res/rcc.css"/>
|
||||
|
||||
<link href='//fonts.googleapis.com/css?family=Roboto:400,500,700,300,
|
||||
400italic,100,100italic,900' rel='stylesheet'
|
||||
type='text/css'> <!--Font-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
<section class="card">
|
||||
<div class="headline">New Post</div>
|
||||
<?php
|
||||
session_start();
|
||||
if ($_SESSION['login']) {
|
||||
$title = $_POST["title"];
|
||||
$date = $_POST["date"];
|
||||
$author = $_POST["author"];
|
||||
$tags = $_POST["tags"];
|
||||
$text = $_POST["text"];
|
||||
$blog = $_POST["blog"];
|
||||
$md = <<<EOD
|
||||
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<section class="card">
|
||||
<div class="headline">New Post</div>
|
||||
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
if ($_SESSION['login']) {
|
||||
$title = $_POST["title"];
|
||||
$date = $_POST["date"];
|
||||
$author = $_POST["author"];
|
||||
$tags = $_POST["tags"];
|
||||
$text = $_POST["text"];
|
||||
$blog = $_POST["blog"];
|
||||
$md = <<<EOD
|
||||
%TITLE: $title
|
||||
%DATE: $date
|
||||
%AUTHOR: $author
|
||||
|
@ -56,18 +84,23 @@ THE SOFTWARE.
|
|||
|
||||
$text
|
||||
EOD;
|
||||
$filename = date("Y-m-d-H-i-s") . ".md";
|
||||
$handle = fopen("../../articles/$blog/$filename", "c");
|
||||
fwrite($handle, $md);
|
||||
if (fclose($handle)) {
|
||||
echo "Post successfully published.";
|
||||
} else {
|
||||
echo "Some error happend, while publishing.";
|
||||
}
|
||||
?><a href="../" class="button">GO BACK</a><?php
|
||||
}
|
||||
?>
|
||||
</section>
|
||||
</div>
|
||||
$filename = date("Y-m-d-H-i-s") . ".md";
|
||||
$handle = fopen("../../articles/$blog/$filename", "c");
|
||||
fwrite($handle, $md);
|
||||
if (fclose($handle)) {
|
||||
echo "Post successfully published.";
|
||||
} else {
|
||||
echo "Some error happend, while publishing.";
|
||||
}
|
||||
?>
|
||||
|
||||
<a href="../" class="button">GO BACK</a>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<?php
|
||||
// Set here your RCC password
|
||||
$password = "setyourpassword";
|
||||
$username = "example";
|
||||
$password = "example";
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
/**
|
||||
* Created by mmk2410 on 2016-02-16.
|
||||
*
|
||||
* JavaScript for the ajax request to generate a atom feed
|
||||
*
|
||||
* Copyright (c) 2016 by mmk2410
|
||||
* License: MIT License
|
||||
*/
|
||||
|
||||
|
||||
function main() {
|
||||
// listener and function for calling the ajax request to create the
|
||||
// requested atom feed
|
||||
|
|
|
@ -1,30 +1,45 @@
|
|||
/**
|
||||
* Created by mmk2410 on 12/6/15.
|
||||
* JavaScript for the ajax request to delete blog post
|
||||
*
|
||||
* JavaScript for the functionality to delete blogs
|
||||
* Copyright (c) 2016 by mmk2410
|
||||
* License: MIT License
|
||||
*/
|
||||
|
||||
function main() {
|
||||
|
||||
// listener and function for recieving the posts of the selected blogs
|
||||
$("#delete_get_posts").click(function () {
|
||||
|
||||
var selectedBlog = $("#delete_selected_blog").val();
|
||||
|
||||
$.get("res/get_posts.php", {
|
||||
blog: selectedBlog
|
||||
}, function (data) {
|
||||
|
||||
$("#delete_select_post").remove();
|
||||
$("#delete_select_post_info").remove();
|
||||
$("#delete_post_button").remove();
|
||||
$("#delete_get_posts").after("<p id='delete_select_post'></p>");
|
||||
$("#delete_get_posts").after("<p id='delete_select_post_info'>Now select the post you want to delete. " +
|
||||
"Remember that once a post is deleted it can't be restored.</p>");
|
||||
$("#delete_select_post").append("<select id='delete_selected_post'></select>");
|
||||
$("#delete_get_posts").after(
|
||||
"<p id='delete_select_post_info'>" +
|
||||
"Now select the post you want to delete. " +
|
||||
"Remember that once a post is deleted it can't be restored.</p>"
|
||||
);
|
||||
$("#delete_select_post").append(
|
||||
"<select id='delete_selected_post'></select>"
|
||||
);
|
||||
|
||||
$.each($.parseJSON(data), function (index, value) {
|
||||
var post = value.substring(0, value.length - 3);
|
||||
$("#delete_selected_post").append("<option value='" + post + "'>" + post + "</option>");
|
||||
$("#delete_selected_post").append(
|
||||
"<option value='" + post + "'>" + post + "</option>"
|
||||
);
|
||||
});
|
||||
$("#delete_select_post").after("<a class='button' id='delete_post_button' " +
|
||||
"onclick='deletePostButton()'>DELETE POST</a>")
|
||||
|
||||
$("#delete_select_post").after(
|
||||
"<a class='button' id='delete_post_button' " +
|
||||
"onclick='deletePostButton()'>DELETE POST</a>"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -37,10 +52,12 @@ function deletePostButton() {
|
|||
|
||||
var selectedBlog = $("#delete_selected_blog").val();
|
||||
var selectedPost = $("#delete_selected_post").val();
|
||||
|
||||
$.get("res/delete_post.php", {
|
||||
blog: selectedBlog,
|
||||
post: selectedPost
|
||||
}, function (data) {
|
||||
|
||||
$("#delete_select_post").remove();
|
||||
$("#delete_select_post_info").remove();
|
||||
$("#delete_post_button").remove();
|
||||
|
@ -51,7 +68,10 @@ function deletePostButton() {
|
|||
} else if (data == "941") {
|
||||
alert("ERROR 941: No blog as get argument given");
|
||||
} else if (data == "961") {
|
||||
alert("ERROR 961: Error while deleting the file. Check if the web server has the permission to do so.");
|
||||
alert(
|
||||
"ERROR 961: Error while deleting the file. Check if the" +
|
||||
"web server has the permission to do so."
|
||||
);
|
||||
} else if (data == "0") {
|
||||
alert("Post successfully deleted.");
|
||||
}
|
||||
|
@ -59,4 +79,4 @@ function deletePostButton() {
|
|||
|
||||
}
|
||||
|
||||
$(document).ready(main());
|
||||
$(document).ready(main());
|
||||
|
|
|
@ -2,8 +2,35 @@
|
|||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* User: mmk2410
|
||||
* Date: 12/6/15
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
* delete post script
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Error Codes:
|
||||
* 901 No post given as get argument
|
||||
|
@ -11,17 +38,24 @@
|
|||
* 941 No blog given as get argument
|
||||
* 961 Error while deleting the post
|
||||
*/
|
||||
|
||||
$post = $_GET["post"];
|
||||
$blog = $_GET["blog"];
|
||||
if (!isset($post)) {
|
||||
echo "901";
|
||||
} else if (!isset($blog)) {
|
||||
echo "941";
|
||||
} else if (!file_exists("./../../articles/$blog/$post.md")) {
|
||||
echo "921";
|
||||
} else {
|
||||
if (unlink("./../../articles/$blog/$post.md")) {
|
||||
echo "0";
|
||||
|
||||
session_start();
|
||||
if ($_SESSION['login']) {
|
||||
if (!isset($post)) {
|
||||
echo "901";
|
||||
} else if (!isset($blog)) {
|
||||
echo "941";
|
||||
} else if (!file_exists("./../../articles/$blog/$post.md")) {
|
||||
echo "921";
|
||||
} else {
|
||||
if (unlink("./../../articles/$blog/$post.md")) {
|
||||
echo "0";
|
||||
}
|
||||
echo "961";
|
||||
}
|
||||
echo "961";
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,41 +1,54 @@
|
|||
/**
|
||||
* Created by mmk2410 on 12/6/15.
|
||||
* JavaScript for the ajax request to edit a article
|
||||
*
|
||||
* JavaScript for the functionality to delete blogs
|
||||
* Copyright (c) 2016 by mmk2410
|
||||
* License: MIT License
|
||||
*/
|
||||
|
||||
function main() {
|
||||
|
||||
// listener and function for recieving the posts of the selected blogs
|
||||
$("#edit_get_posts").click(function () {
|
||||
|
||||
var selectedBlog = $("#edit_selected_blog").val();
|
||||
$.get("res/get_posts.php", {
|
||||
blog: selectedBlog
|
||||
}, function (data) {
|
||||
|
||||
$("#edit_select_post").remove();
|
||||
$("#edit_select_post_info").remove();
|
||||
$("#edit_post_button").remove();
|
||||
$("#edit_get_posts").after("<p id='edit_select_post'></p>");
|
||||
$("#edit_get_posts").after("<p id='edit_select_post_info'>Now select the post you want to edit.</p>");
|
||||
$("#edit_select_post").append("<select id='edit_selected_post'></select>");
|
||||
$("#edit_get_posts").after(
|
||||
"<p id='edit_select_post_info'>" +
|
||||
"Now select the post you want to edit.</p>"
|
||||
);
|
||||
$("#edit_select_post").append(
|
||||
"<select id='edit_selected_post'></select>"
|
||||
);
|
||||
$.each($.parseJSON(data), function (index, value) {
|
||||
var post = value.substring(0, value.length - 3);
|
||||
$("#edit_selected_post").append("<option value='" + post + "'>" + post + "</option>");
|
||||
$("#edit_selected_post").append(
|
||||
"<option value='" + post + "'>" + post + "</option>"
|
||||
);
|
||||
});
|
||||
$("#edit_select_post").after("<a class='button' id='edit_post_button' " +
|
||||
"onclick='editPostButton()'>EDIT POST</a>")
|
||||
$("#edit_select_post").after(
|
||||
"<a class='button' id='edit_post_button' " +
|
||||
"onclick='editPostButton()'>EDIT POST</a>"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
$("#save_changes").click(function () {
|
||||
|
||||
var postTitle = $("#title").val();
|
||||
var postDate = $("#date").val();
|
||||
var postAuthor = $("#author").val();
|
||||
var postTags = $("#tags").val();
|
||||
var postText = $("#text").val();
|
||||
|
||||
var file = "../../articles/" + getVariables['blog'] + "/" + getVariables['post'] + ".md";
|
||||
console.log(file);
|
||||
var file = "../../articles/" + getVariables.blog +
|
||||
"/" + getVariables.post + ".md";
|
||||
|
||||
$.post("../res/save.php", {
|
||||
title: postTitle,
|
||||
|
@ -69,4 +82,4 @@ function editPostButton() {
|
|||
|
||||
}
|
||||
|
||||
$(document).ready(main());
|
||||
$(document).ready(main());
|
||||
|
|
|
@ -2,26 +2,57 @@
|
|||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* User: mmk2410
|
||||
* Date: 12/6/15
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
* get post script
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Error Codes:
|
||||
* 901 No blog given as get argument
|
||||
* 921 No blog with the given name available
|
||||
*/
|
||||
$blog = $_GET["blog"];
|
||||
if (!isset($blog)) {
|
||||
echo "901";
|
||||
} else if (!file_exists("./../../blogs/$blog.md")) {
|
||||
echo "921";
|
||||
} else {
|
||||
$posts = array();
|
||||
$i = 0;
|
||||
foreach (scandir("./../../articles/$blog/") as $article) {
|
||||
if (substr($article, -3) == ".md") {
|
||||
$posts[$i] = $article;
|
||||
$i++;
|
||||
|
||||
session_start();
|
||||
if ($_SESSION['login']) {
|
||||
$blog = $_GET["blog"];
|
||||
if (!isset($blog)) {
|
||||
echo "901";
|
||||
} else if (!file_exists("./../../blogs/$blog.md")) {
|
||||
echo "921";
|
||||
} else {
|
||||
$posts = array();
|
||||
$i = 0;
|
||||
foreach (scandir("./../../articles/$blog/") as $article) {
|
||||
if (substr($article, -3) == ".md") {
|
||||
$posts[$i] = $article;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
print json_encode($posts);
|
||||
}
|
||||
print json_encode($posts);
|
||||
}
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Created on : Jun 14, 2015, 6:13:38 PM
|
||||
Author : mmk2410
|
||||
*/
|
||||
* RCC cascade style sheet
|
||||
*
|
||||
* Copyright (C) 2015-2016 Marcel Kapfer (mmk2410)
|
||||
* MIT License
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* BODY */
|
||||
|
||||
|
@ -38,19 +37,19 @@ body{
|
|||
.main{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin-left: 0px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* HEADER */
|
||||
.header{
|
||||
background-color: #ff4415;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
left: 0px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
box-shadow: 2px 0px 2px 2px rgba(62, 62, 62, 0.45);
|
||||
box-shadow: 2px 0 2px 2px rgba(62, 62, 62, 0.45);
|
||||
}
|
||||
|
||||
.title{
|
||||
|
@ -82,7 +81,7 @@ body{
|
|||
background: #fff;
|
||||
border-radius: 2px;
|
||||
padding: 24px;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
margin-bottom: 40px;
|
||||
max-width: 1160px;
|
||||
}
|
||||
|
@ -145,9 +144,9 @@ body{
|
|||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #ff4415;
|
||||
box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
-moz-box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
-webkit-box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
-moz-box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
border-radius: 2px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 5px;
|
||||
|
@ -158,6 +157,10 @@ body{
|
|||
transition-delay: 50ms;
|
||||
transition-duration: 125ms;
|
||||
transition-timing-function: ease;
|
||||
-o-transition-property: box-shadow;
|
||||
-o-transition-delay: 50ms;
|
||||
-o-transition-duration: 125ms;
|
||||
-o-transition-timing-function: ease;
|
||||
-moz-transition-property: box-shadow;
|
||||
-moz-transition-delay: 50ms;
|
||||
-moz-transition-duration: 125ms;
|
||||
|
@ -170,12 +173,13 @@ body{
|
|||
}
|
||||
|
||||
.button:hover, .button:hover {
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
|
||||
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa; }
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
|
||||
}
|
||||
|
||||
input.button{
|
||||
padding: 0px 8px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
/* INPUT FIELD */
|
||||
|
@ -192,6 +196,10 @@ input.button{
|
|||
transition-delay: 50ms;
|
||||
transition-duration: 125ms;
|
||||
transition-timing-function: ease;
|
||||
-o-transition-property: border-bottom-color;
|
||||
-o-transition-delay: 50ms;
|
||||
-o-transition-duration: 125ms;
|
||||
-o-transition-timing-function: ease;
|
||||
-moz-transition-property: border-bottom-color;
|
||||
-moz-transition-delay: 50ms;
|
||||
-moz-transition-duration: 125ms;
|
||||
|
@ -224,6 +232,10 @@ input.button{
|
|||
transition-delay: 50ms;
|
||||
transition-duration: 125ms;
|
||||
transition-timing-function: ease;
|
||||
-o-transition-property: border-bottom-color;
|
||||
-o-transition-delay: 50ms;
|
||||
-o-transition-duration: 125ms;
|
||||
-o-transition-timing-function: ease;
|
||||
-moz-transition-property: border-bottom-color;
|
||||
-moz-transition-delay: 50ms;
|
||||
-moz-transition-duration: 125ms;
|
||||
|
@ -273,4 +285,4 @@ form{
|
|||
#back-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,32 @@
|
|||
/**
|
||||
* JavaScript for RCC
|
||||
*
|
||||
* Copyright (c) 2016 by mmk2410
|
||||
* License: MIT License
|
||||
*/
|
||||
|
||||
window.onload = function () {
|
||||
var t = document.getElementsByTagName('textarea')[0];
|
||||
var offset = !window.opera ? (t.offsetHeight - t.clientHeight) : (t.offsetHeight + parseInt(window.getComputedStyle(t, null).getPropertyValue('border-top-width')));
|
||||
var offset = !window.opera ? (t.offsetHeight - t.clientHeight) : (
|
||||
t.offsetHeight + parseInt(
|
||||
window.getComputedStyle(t, null).getPropertyValue('border-top-width')
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The following three code clocks are for proper resizing of the input textarea
|
||||
* The following three code clocks are for proper resizing of the input
|
||||
* textarea
|
||||
*/
|
||||
var resize = function (t) {
|
||||
t.style.height = 'auto';
|
||||
t.style.height = (t.scrollHeight + offset ) + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
t.addEventListener && t.addEventListener('input', function (event) {
|
||||
resize(t);
|
||||
});
|
||||
|
||||
t['attachEvent'] && t.attachEvent('onkeyup', function () {
|
||||
t.attachEvent && t.attachEvent('onkeyup', function () {
|
||||
resize(t);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,11 +1,46 @@
|
|||
<?php
|
||||
$title = $_POST["title"];
|
||||
$date = $_POST["date"];
|
||||
$author = $_POST["author"];
|
||||
$tags = $_POST["tags"];
|
||||
$text = $_POST["text"];
|
||||
$filename = $_POST["file"];
|
||||
$md = <<<EOD
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
session_start();
|
||||
if ($_SESSION['login']) {
|
||||
$title = $_POST["title"];
|
||||
$date = $_POST["date"];
|
||||
$author = $_POST["author"];
|
||||
$tags = $_POST["tags"];
|
||||
$text = $_POST["text"];
|
||||
$filename = $_POST["file"];
|
||||
$md = <<<EOD
|
||||
%TITLE: $title
|
||||
%DATE: $date
|
||||
%AUTHOR: $author
|
||||
|
@ -13,10 +48,11 @@ $md = <<<EOD
|
|||
|
||||
$text
|
||||
EOD;
|
||||
if (file_put_contents($filename, $md)) {
|
||||
echo 0;
|
||||
} else if (file_exists(($filename))) {
|
||||
echo 1;
|
||||
} else {
|
||||
echo -1;
|
||||
if (file_put_contents($filename, $md)) {
|
||||
echo 0;
|
||||
} else if (file_exists(($filename))) {
|
||||
echo 1;
|
||||
} else {
|
||||
echo -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* @category Blogging
|
||||
* @package Rcc
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link https://mmk2410.org/rangitaki
|
||||
*
|
||||
* Main page of RCC (Rangitaki Control Center)
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Rangitaki Control Center</title>
|
||||
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
|
||||
<link rel="stylesheet" href="../res/rcc.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
<div class="main">
|
||||
<section class="card">
|
||||
<div class="headline">File Upload</div>
|
||||
<?php
|
||||
session_start();
|
||||
if($_SESSION['login']) {
|
||||
if ($_FILES['userfile']['name'] == "") {
|
||||
echo "<p>You have to choose a file!</p>";
|
||||
} else {
|
||||
$blog = filter_input(INPUT_POST, "blog");
|
||||
$uploaddir = "../..//articles/$blog/";
|
||||
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
|
||||
echo "<p>The post was successfully uploaded and is now published.</p>";
|
||||
} else {
|
||||
echo "<p>During the uploading process an error occured! <br> Error Code:" . ($_FILES['userfile']['error'] . "</p>");
|
||||
}
|
||||
}
|
||||
?><a href="../" class="button">GO BACK</a><?php
|
||||
}
|
||||
?>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
<title>Rangitaki Control Center</title>
|
||||
|
||||
<meta name="robots" content="nofollow, noindex, noarchive, nosnippet">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
|
||||
user-scalable=0" name="viewport"/>
|
||||
|
||||
<meta name="theme-color" content="#383838">
|
||||
<meta name="description" content="Rangitaki Control Center (RCC)">
|
||||
|
||||
<link rel="stylesheet" href="./res/rcc.css"/>
|
||||
|
||||
<link href='//fonts.googleapis.com/css?family=Roboto:400,500,700,300,
|
||||
400italic,100,100italic,900' rel='stylesheet'
|
||||
type='text/css'> <!--Font-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
<a href="../" class="title">Rangitaki Control Center</a>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<section class="card">
|
||||
<div class="headline">File Upload</div>
|
||||
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
if ($_SESSION['login']) {
|
||||
|
||||
if ($_FILES['userfile']['name'] == "") {
|
||||
echo "<p>You have to choose a file!</p>";
|
||||
} else {
|
||||
$blog = filter_input(INPUT_POST, "blog");
|
||||
$uploaddir = "../..//articles/$blog/";
|
||||
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
|
||||
|
||||
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
|
||||
echo
|
||||
"<p>The post was successfully uploaded and is now
|
||||
published.</p>";
|
||||
} else {
|
||||
echo
|
||||
"<p>During the uploading process an error occured! <br>
|
||||
Error Code:"
|
||||
. ($_FILES['userfile']['error'] . "</p>");
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<a href="../" class="button">GO BACK</a>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,57 +1,3 @@
|
|||
/*
|
||||
Rangitaki Project
|
||||
.nav{display:none}.nav-img{display:none}@media screen and (min-width: 1440px){.header{left:0}.main{margin-left:0;width:100%}}@media screen and (max-width: 720px){.title{left:25px}}
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Created on : Jun 18, 2015, 7:07:45 PM
|
||||
Author : mmk2410
|
||||
*/
|
||||
/*
|
||||
A stylesheet for overriding the default styles if the navigation drawer is disabled
|
||||
*/
|
||||
|
||||
.nav{ /* hide the navigation drawer */
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-img{ /* hide the hamburger icon */
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1440px) { /* large devices */
|
||||
.header { /* full width */
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.main{ /* full width */
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 720px){ /* small devices */
|
||||
.title{ /* move the title more to the left */
|
||||
left: 25px;
|
||||
}
|
||||
}
|
||||
/*# sourceMappingURL=no-nav.css.map */
|
||||
|
|
1
res/css/no-nav.css.map
Normal file
1
res/css/no-nav.css.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"no-nav.css","sources":["no-nav.sass"],"sourcesContent":["/*\n * Rangitaki Project\n *\n * The MIT License\n *\n * Copyright 2015 mmk2410.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * A stylesheet for overriding the default styles if the navigation drawer is disabled\n */\n\n.nav {\n display: none; }\n\n.nav-img {\n display: none; }\n\n@media screen and (min-width: 1440px) {\n .header {\n left: 0; }\n\n .main {\n margin-left: 0;\n width: 100%; } }\n\n@media screen and (max-width: 720px) {\n\n .title {\n left: 25px; } }\n"],"mappings":"AA4BA,AAAA,IAAI,AAAC,CACD,OAAO,CAAE,IAAK,CAAG,AAErB,AAAA,QAAQ,AAAC,CACL,OAAO,CAAE,IAAK,CAAG,AAErB,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,MAAM,EACzB,AAAA,OAAO,AAAC,CACJ,IAAI,CAAE,CAAE,CAAG,AAEf,AAAA,KAAK,AAAC,CACF,WAAW,CAAE,CAAE,CACf,KAAK,CAAE,IAAK,CAAG,CAEvB,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,KAAK,EAExB,AAAA,MAAM,AAAC,CACH,IAAI,CAAE,IAAK,CAAG","names":[]}
|
|
@ -1,305 +1,3 @@
|
|||
/*
|
||||
Rangitaki Project
|
||||
body{margin-top:94px}.main{height:100%;margin-left:0}.overlay{opacity:0;position:fixed;top:0;left:0;background-color:black;width:100%;z-index:30;height:100%;display:none}.header{top:0;right:0;left:0;width:100%;height:64px;position:absolute}.title{color:#fff;font-size:23px;text-decoration:none;line-height:64px;vertical-align:middle;left:75px}.title>a{text-decoration:none;color:#fff}.fadeout{position:absolute;height:64px;top:0;right:0;width:40px}.nav-img{height:26px;padding:19px;cursor:pointer}.nav{width:300px;position:fixed;height:100%;top:0;left:-301px;z-index:40}.nav-item,.nav-item-static{text-decoration:none;text-indent:0;display:inline-block;height:48px;vertical-align:middle;width:284px;line-height:48px;padding-left:16px;transition:background-color 125ms ease-in-out 0ms}.nav-close{cursor:pointer}.nav-close-img{height:35px;padding:12px}.nav-item{cursor:pointer}.divider{width:100%}.card{margin-right:auto;margin-left:auto;width:75%;padding:24px;margin-bottom:40px;max-width:1160px}.card a{-moz-hyphens:auto;-epub-hyphens:auto;-ms-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;word-wrap:break-word}.headline{display:block;padding-bottom:8px}.card img{max-width:100%;max-height:400px;display:block;margin-left:auto;margin-right:auto}.author{display:block}.fabmenu{position:fixed;bottom:20px;right:20px}.fab{height:60px;width:60px;border-radius:30px;cursor:pointer}.fab-img{width:28px;padding:15px}.subfab{height:45px;width:45px;border-radius:30px;margin-right:auto;margin-left:auto;margin-bottom:25px;display:none}.subfab-img{width:22px;padding:12px}.pag_buttons{margin-right:auto;margin-left:auto;width:calc(75% + 48px);margin-bottom:80px;max-width:1160px;text-align:right}.button{text-decoration:none;color:#fff;line-height:36px;min-width:64px;text-align:center;height:36px;padding:8px;margin-top:4px;margin-bottom:5px;cursor:pointer}.pag_next{margin-left:8px}.footer a{transition:border-bottom-color 150ms ease-in-out 100ms}.footer a:hover{border-bottom-color:#383838}@media screen and (min-width: 1440px){.nav{left:0;padding-top:64px}.nav-close-img{display:none}.nav-close{display:none}.nav-img{display:none}.header{left:300px}.main{margin-left:300px;width:calc(100% - 300px)}}@media screen and (max-width: 720px){.card{width:82%}.pag_buttons{width:calc(82% + 48px)}}
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Created on : Jun 14, 2015, 6:13:38 PM
|
||||
Author : mmk2410
|
||||
*/
|
||||
|
||||
/* BODY */
|
||||
|
||||
body{
|
||||
margin-top: 94px; /* Set enough space for the header */
|
||||
}
|
||||
|
||||
.main{ /* main content */
|
||||
height: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.overlay { /* overlay: used for a darker background when the navigation drawer is open */
|
||||
opacity: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: black;
|
||||
width: 100%;
|
||||
z-index: 30;
|
||||
height: 100%;
|
||||
display: none; /* because the thing is hidden at the beginning and shown with js */
|
||||
}
|
||||
|
||||
/* HEADER */
|
||||
.header{
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.title{ /* title in the header */
|
||||
color: #fff;
|
||||
font-size: 23px;
|
||||
text-decoration: none;
|
||||
line-height: 64px;
|
||||
vertical-align: middle;
|
||||
left: 75px;
|
||||
}
|
||||
|
||||
.title > a{ /* and a a styling */
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fadeout{ /* a fadeout if the title is to long */
|
||||
position: absolute;
|
||||
height: 64px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.nav-img{ /* the hamburger icon */
|
||||
height: 26px;
|
||||
padding: 19px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* NAV DRAWER */
|
||||
|
||||
.nav{ /* the main object */
|
||||
width: 300px;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: -301px;
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
.nav-item, .nav-item-static{ /* a nav-item */
|
||||
text-decoration: none;
|
||||
text-indent: 0;
|
||||
display: inline-block;
|
||||
height: 48px;
|
||||
vertical-align: middle;
|
||||
width: 284px;
|
||||
line-height: 48px;
|
||||
padding-left: 16px;
|
||||
transition: background-color 125ms ease-in-out 0ms;
|
||||
}
|
||||
|
||||
.nav-close {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-close-img{ /* the hamburger icon */
|
||||
height: 35px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.nav-item{ /* additional setting for clickable nav items */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.divider{ /* a simple divider with all options. better than <hr> */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* MAIN */
|
||||
|
||||
.card{ /* just a card */
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
width: 75%;
|
||||
padding: 24px;
|
||||
margin-bottom: 40px;
|
||||
max-width: 1160px;
|
||||
}
|
||||
|
||||
.card a{ /* and another a styling */
|
||||
-moz-hyphens: auto;
|
||||
-epub-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
word-wrap: break-word; /* until here: break long links */
|
||||
}
|
||||
|
||||
.card a:hover{ /* hovered card links; just here to help you create a own theme*/
|
||||
|
||||
}
|
||||
|
||||
.headline{ /* title in a card */
|
||||
display: block;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
.card img{ /* image in a card*/
|
||||
max-width: 100%; /* regulate width */
|
||||
max-height: 400px; /* regulate height */
|
||||
display: block; /* centered */
|
||||
margin-left: auto; /* centerd */
|
||||
margin-right: auto; /* centred */
|
||||
}
|
||||
|
||||
.date{ /* possibility to style the date */
|
||||
|
||||
}
|
||||
|
||||
.articletext{ /* posibitlity to style the text */
|
||||
|
||||
}
|
||||
|
||||
.author{ /* styling for the author */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tag{ /* possibility to style the text */
|
||||
|
||||
}
|
||||
|
||||
/* FAB */
|
||||
|
||||
.fabmenu{ /* surrounds the complete fab menu */
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.fab{ /* the main fab (always visible if enabled) */
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
border-radius: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fab-img{ /* fab image for the main fab */
|
||||
width: 28px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.subfab{ /* a smaller fab in the fab menu */
|
||||
height: 45px;
|
||||
width: 45px;
|
||||
border-radius: 30px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
margin-bottom: 25px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.subfab-img{ /* and the image for it */
|
||||
width: 22px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* BUTTON */
|
||||
|
||||
.pag_buttons {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
width: calc(75% + 48px);
|
||||
margin-bottom: 80px;
|
||||
max-width: 1160px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.button {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
line-height: 36px;
|
||||
min-width: 64px;
|
||||
text-align: center;
|
||||
height: 36px;
|
||||
padding: 8px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pag_next{
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
/* FOOTER */
|
||||
|
||||
.footer{ /* possibility for styling the footer */
|
||||
|
||||
}
|
||||
|
||||
|
||||
.footer a{ /* styling of the footer a */
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms;
|
||||
}
|
||||
|
||||
.footer a:hover{ /* and the hovered one*/
|
||||
border-bottom-color: #383838;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1440px) { /* make it responsive: large devices */
|
||||
|
||||
.nav{ /* always show navigation bar */
|
||||
left: 0;
|
||||
padding-top: 64px;
|
||||
}
|
||||
|
||||
.nav-close-img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-close {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-img{ /* always hide navigation bar icon*/
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header{ /* move header to the right */
|
||||
left: 300px;
|
||||
}
|
||||
|
||||
.main{ /* move main content to the right and limit its width */
|
||||
margin-left: 300px;
|
||||
width: calc(100% - 300px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 720px){ /* make it responsive: small devices */
|
||||
|
||||
.card{ /* wider cards */
|
||||
width: 82%;
|
||||
}
|
||||
|
||||
.pag_buttons {
|
||||
width: calc(82% + 48px);
|
||||
}
|
||||
|
||||
}
|
||||
/*# sourceMappingURL=rangitaki.css.map */
|
||||
|
|
1
res/css/rangitaki.css.map
Normal file
1
res/css/rangitaki.css.map
Normal file
File diff suppressed because one or more lines are too long
113
res/js/app.js
113
res/js/app.js
|
@ -1,112 +1 @@
|
|||
/*
|
||||
* Rangitaki Project
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var main = function () { // main function; called below
|
||||
|
||||
var fabActive = false; // fab hidden at begin
|
||||
$('.fabmenu').click( // action on fab click
|
||||
function () {
|
||||
if (!(fabActive)) { // if fab is hidden
|
||||
fabFadeIn(); // fade fab in
|
||||
fabActive = true; // fab = active
|
||||
} else { // if fab is shown
|
||||
fabFadeOut(); // fade fab out
|
||||
fabActive = false; // fab = hidden
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var navOpen = false; // nav hidden at begin
|
||||
$('.nav-img, .overlay, .nav-close').click( // action on hamburger click
|
||||
function () {
|
||||
if (!(navOpen)) { // if nav is hidden
|
||||
openNav(); // open the nav drawer
|
||||
navOpen = true; // nav = open
|
||||
} else { // if nav is closed
|
||||
closeNav(); // close the nav drawer
|
||||
navOpen = false; // nav = closed
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Keyhandling for the navigation drawer.
|
||||
* opens the drawer on 'm' (key code: 77)
|
||||
* closes the drawer on 'Esc' (key code: 27)
|
||||
*/
|
||||
$(document).keyup(function (e) {
|
||||
if (navOpen && (e.which === 27)) {
|
||||
closeNav();
|
||||
navOpen = false;
|
||||
} else if (!(navOpen) && (e.which === 77)) {
|
||||
openNav();
|
||||
navOpen = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
$(document).ready(main); // run if document is loaded
|
||||
|
||||
function goBack() { // go back function
|
||||
history.go(-1);
|
||||
}
|
||||
|
||||
function fabFadeIn() { // fade fab in
|
||||
$('.subfab').fadeIn(125); // fade subfabs in
|
||||
$('.fab-img').fadeOut( // fade fab share image out
|
||||
60, function callback() {
|
||||
$('.fab-img').attr("src", "./res/img/close.svg"); // change to fab close image
|
||||
}
|
||||
);
|
||||
$('.fab-img').fadeIn(60); // fade fab close image in
|
||||
}
|
||||
|
||||
function fabFadeOut() { // fade fab out
|
||||
$('.subfab').fadeOut(125); // fade subfabs out
|
||||
$('.fab-img').fadeOut( // fade fab close image out
|
||||
60, function callback() {
|
||||
$('.fab-img').attr("src", "./res/img/share.svg"); // change to fab share image
|
||||
}
|
||||
);
|
||||
$('.fab-img').fadeIn(60); // fade fab share image in
|
||||
}
|
||||
|
||||
function openNav() { // fade navigation drawer in
|
||||
$('.nav').animate({"left": "0px"}, 125); // slide in
|
||||
$('.overlay').show(); // set overlay to show ...
|
||||
$('.overlay').animate({"opacity": "0.4"}, 125); // ... and fade to a darker transparent color
|
||||
}
|
||||
|
||||
function closeNav() { // fade navigation drawer out
|
||||
$('.nav').animate({"left": "-301px"}, 125); // slide out
|
||||
$('.overlay').animate(
|
||||
{"opacity": "0.0"}, 125, function () { // fade the overlay to complete transparency
|
||||
$('.overlay').hide(); // hide it then
|
||||
}
|
||||
);
|
||||
}
|
||||
(function(){var n,t,a,e,r,i;r=function(){var e,r;return e=!1,$(".fabmenu").click(function(){return e?(a(),e=!1):(t(),e=!0)}),r=!1,$(".nav-img, .overlay, .nav-close").click(function(){return r?(n(),r=!1):(i(),r=!0)}),$(document).keyup(function(t){return r&&27===t.which?(n(),r=!1):r||77!==t.which?void 0:(i(),r=!0)}),$(".articletext a").attr("target","_blank")},$(document).ready(r),e=function(){return history.go(-1)},t=function(){return $(".subfab").fadeIn(125),$(".fab-img").fadeOut(60,function(){return $(".fab-img").attr("src","./res/img/close.svg"),$(".fab-img").fadeIn(60)})},a=function(){return $(".subfab").fadeOut(125),$(".fab-img").fadeOut(60,function(){return $(".fab-img").attr("src","./res/img/share.svg"),$(".fab-img").fadeIn(60)})},i=function(){return $(".nav").animate({left:"0px"},125),$(".overlay").show(),$(".overlay").animate({opacity:"0.4"},125)},n=function(){return $(".nav").animate({left:"-301px"},125),$(".overlay").animate({opacity:"0.0"},125,function(){return $(".overlay").hide})}}).call(this);
|
|
@ -265,4 +265,46 @@ class ArticleGenerator
|
|||
return $article;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to get a array of the article
|
||||
*
|
||||
* @param $directory The directory where the article is stored
|
||||
* @param $articlefile The name of the article file
|
||||
* @return string
|
||||
*/
|
||||
public function getArray($directory, $articlefile)
|
||||
{
|
||||
$article = file_get_contents($directory . $articlefile);
|
||||
|
||||
if (substr($article, 0, 6) == "%TITLE") { // get and remove the title
|
||||
$title = substr($article, 8, strpos($article, "\n") - 8);
|
||||
$article = substr($article, strpos($article, "\n") + 1);
|
||||
}
|
||||
|
||||
if (substr($article, 0, 5) == "%DATE") { // get and remove the title
|
||||
$date = substr($article, 7, strpos($article, "\n") - 7);
|
||||
$article = substr($article, strpos($article, "\n") + 1);
|
||||
}
|
||||
|
||||
if (substr($article, 0, 7) == "%AUTHOR") { // get and remove the title
|
||||
$author = substr($article, 9, strpos($article, "\n") - 9);
|
||||
$article = substr($article, strpos($article, "\n") + 1);
|
||||
}
|
||||
|
||||
if (substr($article, 0, 5) == "%TAGS") { // get and remove the tags
|
||||
$tags = substr($article, 7, strpos($article, "\n") - 7); // get the tags
|
||||
$tags = explode(", ", $tags); // split them into an array
|
||||
$article = substr($article, strpos($article, "\n") + 1);
|
||||
}
|
||||
|
||||
$data = array(
|
||||
"title" => $title,
|
||||
"date" => $date,
|
||||
"author" => $author,
|
||||
"tags" => $tags,
|
||||
"text" => $article
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
74
res/php/Config.php
Normal file
74
res/php/Config.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* Configuration parser for yaml configuration files
|
||||
*
|
||||
* @category Configuration
|
||||
* @package Rbe
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link http://marcel-kapfer.de/rangitaki
|
||||
*/
|
||||
namespace mmk2410\rbe\config;
|
||||
|
||||
/**
|
||||
* PHP Version 7
|
||||
*
|
||||
* Configuration parser for yaml configuration files
|
||||
*
|
||||
* @category Configuration
|
||||
* @package Rbe
|
||||
* @author Marcel Kapfer (mmk2410) <marcelmichaelkapfer@yahoo.co.nz>
|
||||
* @license MIT License
|
||||
* @link http://marcel-kapfer.de/rangitaki
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
|
||||
/**
|
||||
* Path to yaml file
|
||||
* @var string
|
||||
*/
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* Constructor for the Config class
|
||||
*
|
||||
* @param $config path to the yaml file
|
||||
* @param $composer path to the composer autoload
|
||||
*/
|
||||
public function __construct($config, $composer)
|
||||
{
|
||||
$this->file = $config;
|
||||
require $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return yaml config as PHP array
|
||||
*
|
||||
* @return config array
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
$yaml = new \Symfony\Component\Yaml\Parser();
|
||||
return $yaml->parse(file_get_contents($this->file));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write array into confi*
|
||||
* Write array into config file
|
||||
*
|
||||
* @param array config new config
|
||||
*
|
||||
* @return FALSE if failed to write
|
||||
*/
|
||||
public function writeConfig($config)
|
||||
{
|
||||
$dumper = new \Symfony\Component\Yaml\Dumper();
|
||||
|
||||
$yaml = $dumper->dump($config, 2);
|
||||
|
||||
return file_put_contents($this->file, $yaml);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ THE SOFTWARE.
|
|||
<div id="disqus_thread"></div>
|
||||
<script type="text/javascript">
|
||||
/* * * CONFIGURATION VARIABLES * * */
|
||||
var disqus_shortname = '<?php echo $blogdisqus; ?>';
|
||||
var disqus_shortname = '<?php echo $config['blog']['disqus']; ?>';
|
||||
|
||||
/* * * DON'T EDIT BELOW THIS LINE * * */
|
||||
(function () {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
|
||||
if ($bloganalytics) { // check if google analytics is enabled
|
||||
if ($config["blog"]["analytics"]) { // check if google analytics is enabled
|
||||
if (!($_SERVER['HTTP_DNT'] == 1)) {
|
||||
?>
|
||||
<script>
|
||||
|
|
|
@ -11,26 +11,32 @@
|
|||
* @link http://marcel-kapfer.de/rangitaki
|
||||
*/
|
||||
require_once "BlogListGenerator.php";
|
||||
require_once "config.php";
|
||||
require_once "lang/" . $language . ".php";
|
||||
|
||||
if ($pagination) {
|
||||
require_once './res/php/Config.php';
|
||||
|
||||
$configParser = new mmk2410\rbe\config\Config('./config.yaml', './vendor/autoload.php');
|
||||
|
||||
$conf = $configParser->getConfig();
|
||||
|
||||
require_once "lang/" . $config["language"] . ".php";
|
||||
|
||||
if ($blog["design"]["pagination"]) {
|
||||
?>
|
||||
<div class="pag_buttons">
|
||||
<?php
|
||||
<?php
|
||||
if ($pag_min > 0) {
|
||||
if (isset($getblog)) {
|
||||
?>
|
||||
?>
|
||||
<a href="<?php
|
||||
echo "?blog=" . $getblog . "&page=" . ($pagenumber - 1);
|
||||
?>" class="pag_prev button"><?php echo $BLOGLANG["Previous Page"]; ?></a>
|
||||
<?php
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
?>
|
||||
<a href="<?php
|
||||
echo "?page=" . ($pagenumber - 1);
|
||||
?>" class="pag_prev button"><?php echo $BLOGLANG['Previous Page']; ?></a>
|
||||
<?php
|
||||
<?php
|
||||
}
|
||||
}
|
||||
if (isset($getblog)) {
|
||||
|
@ -40,20 +46,20 @@ if ($pagination) {
|
|||
}
|
||||
if ($pag_max < BlogListGenerator::getArticleAmount($pag_blog)) {
|
||||
if (isset($getblog)) {
|
||||
?>
|
||||
?>
|
||||
<a href="<?php
|
||||
echo "?blog=" . $getblog . "&page=" . ($pagenumber + 1);
|
||||
?>" class="pag_next button"><?php echo $BLOGLANG["Next Page"]; ?></a>
|
||||
<?php
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
?>
|
||||
<a href="<?php
|
||||
echo "?page=" . ($pagenumber + 1);
|
||||
?>" class="pag_next button"><?php echo $BLOGLANG["Next Page"];?></a>
|
||||
<?php
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
|
38
src/coffee-extensions/example.coffee
Normal file
38
src/coffee-extensions/example.coffee
Normal file
|
@ -0,0 +1,38 @@
|
|||
###
|
||||
Rangitaki Project
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
###
|
||||
|
||||
###
|
||||
This is a example JavaScript extension for Rangitaki
|
||||
###
|
||||
|
||||
main = () ->
|
||||
console.log """
|
||||
Welcome Developer! \nYou're seeing the output of a
|
||||
JavaScript extension for the Rangitaki blogging engine.
|
||||
"""
|
||||
|
||||
$(document).ready main()
|
||||
|
91
src/coffee/app.coffee
Normal file
91
src/coffee/app.coffee
Normal file
|
@ -0,0 +1,91 @@
|
|||
###
|
||||
Rangitaki Project
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
###
|
||||
|
||||
main = () ->
|
||||
|
||||
# FAB
|
||||
fabActive = false
|
||||
$('.fabmenu').click ->
|
||||
if !fabActive
|
||||
fabFadeIn()
|
||||
fabActive = true
|
||||
else
|
||||
fabFadeOut()
|
||||
fabActive = false
|
||||
|
||||
# Navigation Drawer
|
||||
navOpen = false
|
||||
$('.nav-img, .overlay, .nav-close').click ->
|
||||
if !navOpen
|
||||
openNav()
|
||||
navOpen = true
|
||||
else
|
||||
closeNav()
|
||||
navOpen = false
|
||||
|
||||
###
|
||||
Keyhandling for the navigation drawer.
|
||||
opens the drawer on 'm' (key code: 77)
|
||||
closes the drawer on 'Esc' (key code: 27)
|
||||
###
|
||||
$(document).keyup (e) ->
|
||||
if navOpen and e.which is 27
|
||||
closeNav()
|
||||
navOpen = false
|
||||
else if !navOpen and e.which == 77
|
||||
openNav()
|
||||
navOpen = true
|
||||
|
||||
# Make every link in articles target="_blank"
|
||||
$('.articletext a').attr 'target', '_blank'
|
||||
|
||||
$(document).ready main
|
||||
|
||||
goBack = () ->
|
||||
history.go -1
|
||||
|
||||
fabFadeIn = () ->
|
||||
$('.subfab').fadeIn 125
|
||||
$('.fab-img').fadeOut 60, ->
|
||||
$('.fab-img').attr "src", "./res/img/close.svg"
|
||||
$('.fab-img').fadeIn 60
|
||||
|
||||
fabFadeOut = () ->
|
||||
$('.subfab').fadeOut 125
|
||||
$('.fab-img').fadeOut 60, ->
|
||||
$('.fab-img').attr "src", "./res/img/share.svg"
|
||||
$('.fab-img').fadeIn 60
|
||||
|
||||
openNav = () ->
|
||||
$('.nav').animate {"left": "0px"}, 125
|
||||
$('.overlay').show()
|
||||
$('.overlay').animate {"opacity": "0.4"}, 125
|
||||
|
||||
closeNav = () ->
|
||||
$('.nav').animate {"left": "-301px"}, 125
|
||||
$('.overlay').animate {"opacity": "0.0"}, 125, ->
|
||||
$('.overlay').hide
|
||||
|
179
src/sass-themes/background-img.sass
Normal file
179
src/sass-themes/background-img.sass
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Rangitaki Project
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
body
|
||||
font-family: "Roboto", sans-serif
|
||||
background: #f6f6f6
|
||||
color: #383838
|
||||
background-image: url(//example.com/res/img/intro.svg)
|
||||
background-size: cover
|
||||
background-attachment: fixed
|
||||
background-position: top center
|
||||
background-repeat: no-repeat
|
||||
|
||||
.header
|
||||
background-color: rgba(0, 0, 0, 0.45)
|
||||
position: fixed
|
||||
|
||||
.title
|
||||
color: #fff
|
||||
position: absolute
|
||||
|
||||
.title > a
|
||||
color: #fff
|
||||
|
||||
.fadeout
|
||||
background: -moz-linear-gradient(left, rgba(30,87,153,0) 0%, rgba(0, 0, 0, 0.45) 100%)
|
||||
background: -webkit-linear-gradient(left, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%)
|
||||
background: -o-linear-gradient(left, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%)
|
||||
background: -ms-linear-gradient(left, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%)
|
||||
background: linear-gradient(to right, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%)
|
||||
|
||||
.nav
|
||||
background-color: #fff
|
||||
border-right: 1px solid #e0e0e0
|
||||
|
||||
.nav-item, .nav-item-static
|
||||
color: #383838
|
||||
|
||||
.nav-item
|
||||
font-weight: 600
|
||||
|
||||
.nav-item:active
|
||||
background-color: #e2e2e2
|
||||
|
||||
.divider
|
||||
border-bottom: 1px solid #e0e0e0
|
||||
|
||||
.card
|
||||
background: #fff
|
||||
border-radius: 2px
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(62, 62, 62, 0.3)
|
||||
|
||||
.card a
|
||||
color: #ff4415
|
||||
text-decoration: none
|
||||
border-bottom: 1px solid transparent
|
||||
border-bottom-color: transparent
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms
|
||||
|
||||
.card a:hover
|
||||
border-bottom-color: #ff4415
|
||||
|
||||
.headline
|
||||
font-size: 24px
|
||||
color: #383838!important
|
||||
text-decoration: none
|
||||
border-bottom: none!important
|
||||
|
||||
.headline:hover
|
||||
color: #ff4415!important
|
||||
|
||||
.date
|
||||
font-size: 13px
|
||||
|
||||
.articletext
|
||||
font-size: 14px
|
||||
line-height: 24px
|
||||
|
||||
.author
|
||||
font-size: 13px
|
||||
|
||||
.tag
|
||||
font-size: 13px
|
||||
|
||||
.fab
|
||||
background-color: #ff4415
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(62, 62, 62, 0.3)
|
||||
|
||||
.subfab
|
||||
background-color: #fff
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(62, 62, 62, 0.3)
|
||||
|
||||
.button
|
||||
border-width: 1px
|
||||
border-style: solid
|
||||
text-transform: uppercase
|
||||
-webkit-box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
-moz-box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
border-radius: 2px
|
||||
letter-spacing: 0.4px
|
||||
font-weight: 700
|
||||
font-size: 14px
|
||||
transition-property: box-shadow
|
||||
transition-delay: 50ms
|
||||
transition-duration: 125ms
|
||||
transition-timing-function: ease
|
||||
-o-transition-property: box-shadow
|
||||
-o-transition-delay: 50ms
|
||||
-o-transition-duration: 125ms
|
||||
-o-transition-timing-function: ease
|
||||
-moz-transition-property: box-shadow
|
||||
-moz-transition-delay: 50ms
|
||||
-moz-transition-duration: 125ms
|
||||
-moz-transition-timing-function: ease
|
||||
-webkit-transition-property: box-shadow
|
||||
-webkit-transition-delay: 50ms
|
||||
-webkit-transition-duration: 125ms
|
||||
-webkit-transition-timing-function: ease
|
||||
|
||||
.button:hover, .button:hover
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85)
|
||||
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85)
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85)
|
||||
|
||||
.pag_next
|
||||
background-color: #ff4415
|
||||
border-color: #ff4415
|
||||
|
||||
.pag_prev
|
||||
background-color: #fff
|
||||
border-color: #fff
|
||||
color: #383838
|
||||
|
||||
.footer
|
||||
font-size: 12px
|
||||
text-align: center
|
||||
color: #fff
|
||||
text-shadow: 1px 1px rgba(55, 55, 55, 0.3)
|
||||
|
||||
.footer a
|
||||
color: #fff
|
||||
text-shadow: 1px 1px rgba(175, 175, 175, 0.3)
|
||||
text-decoration: none
|
||||
border-bottom: 1px solid transparent
|
||||
border-bottom-color: transparent
|
||||
|
||||
.footer a:hover
|
||||
border-bottom-color: #fff
|
||||
|
||||
@media screen and (min-width: 1440px)
|
||||
|
||||
.nav
|
||||
background-color: rgba(255, 255, 255, 0.8)
|
||||
|
161
src/sass-themes/material-dark.sass
Normal file
161
src/sass-themes/material-dark.sass
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Rangitaki Project
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
body
|
||||
font-family: "Roboto", sans-serif
|
||||
background: #303030
|
||||
color: #fff
|
||||
|
||||
.header
|
||||
background-color: #212121
|
||||
position: fixed
|
||||
box-shadow: 2px 0 2px 2px rgba(32, 32, 32, 0.85)
|
||||
|
||||
.title
|
||||
color: #fff
|
||||
position: absolute
|
||||
> a
|
||||
color: #fff
|
||||
|
||||
.fadeout
|
||||
background: -moz-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #212121 100%)
|
||||
/* FF3.6+
|
||||
background: -webkit-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #212121 100%)
|
||||
/* Chrome10+,Safari5.1+
|
||||
background: -o-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #212121 100%)
|
||||
/* Opera 11.10+
|
||||
background: -ms-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #212121 100%)
|
||||
/* IE10+
|
||||
background: linear-gradient(to right, rgba(30, 87, 153, 0) 0%, #212121 100%)
|
||||
/* W3C
|
||||
|
||||
.nav
|
||||
background-color: #424242
|
||||
border-right: 1px solid #1f1f1f
|
||||
|
||||
.nav-item, .nav-item-static
|
||||
color: #fff
|
||||
|
||||
.nav-item
|
||||
font-weight: 600
|
||||
&:active
|
||||
background-color: #383838
|
||||
|
||||
.divider
|
||||
border-bottom: 1px solid #1f1f1f
|
||||
|
||||
.card
|
||||
background: #424242
|
||||
border-radius: 2px
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
a
|
||||
color: #ff4415
|
||||
text-decoration: none
|
||||
border-bottom: 1px solid transparent
|
||||
border-bottom-color: transparent
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms
|
||||
&:hover
|
||||
border-bottom-color: #ff4415
|
||||
|
||||
.headline
|
||||
font-size: 24px
|
||||
color: #fff !important
|
||||
text-decoration: none
|
||||
border-bottom: none !important
|
||||
&:hover
|
||||
color: #ff4415 !important
|
||||
|
||||
.date
|
||||
font-size: 13px
|
||||
|
||||
.articletext
|
||||
font-size: 14px
|
||||
line-height: 24px
|
||||
|
||||
.author, .tag
|
||||
font-size: 13px
|
||||
|
||||
.fab
|
||||
background-color: #ff4415
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
|
||||
.subfab
|
||||
background-color: #424242
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
|
||||
.button
|
||||
text-transform: uppercase
|
||||
border-width: 1px
|
||||
border-style: solid
|
||||
-webkit-box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
-moz-box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(42, 42, 42, 0.65)
|
||||
border-radius: 2px
|
||||
letter-spacing: 0.4px
|
||||
font-weight: 700
|
||||
font-size: 14px
|
||||
transition-property: box-shadow
|
||||
transition-delay: 50ms
|
||||
transition-duration: 125ms
|
||||
transition-timing-function: ease
|
||||
-o-transition-property: box-shadow
|
||||
-o-transition-delay: 50ms
|
||||
-o-transition-duration: 125ms
|
||||
-o-transition-timing-function: ease
|
||||
-moz-transition-property: box-shadow
|
||||
-moz-transition-delay: 50ms
|
||||
-moz-transition-duration: 125ms
|
||||
-moz-transition-timing-function: ease
|
||||
-webkit-transition-property: box-shadow
|
||||
-webkit-transition-delay: 50ms
|
||||
-webkit-transition-duration: 125ms
|
||||
-webkit-transition-timing-function: ease
|
||||
&:hover
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85)
|
||||
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85)
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85)
|
||||
|
||||
.pag_next
|
||||
background-color: #ff4415
|
||||
border-color: #ff4415
|
||||
|
||||
.pag_prev
|
||||
background-color: #424242
|
||||
border-color: #424242
|
||||
color: #CCCCCC
|
||||
|
||||
.footer
|
||||
font-size: 12px
|
||||
text-align: center
|
||||
color: #fff
|
||||
a
|
||||
color: #fff
|
||||
text-decoration: none
|
||||
border-bottom: 1px solid transparent
|
||||
border-bottom-color: transparent
|
||||
&:hover
|
||||
border-bottom-color: #fff
|
156
src/sass-themes/material-light.sass
Normal file
156
src/sass-themes/material-light.sass
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Rangitaki Project
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
body
|
||||
font-family: "Roboto", sans-serif
|
||||
background: #f6f6f6
|
||||
color: #383838
|
||||
|
||||
.header
|
||||
background-color: #ff4415
|
||||
position: fixed
|
||||
box-shadow: 2px 0 2px 2px rgba(62, 62, 62, 0.45)
|
||||
|
||||
.title
|
||||
color: #fff
|
||||
position: absolute
|
||||
> a
|
||||
color: #fff
|
||||
|
||||
.fadeout
|
||||
background: -moz-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #ff4415 100%)
|
||||
background: -webkit-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #ff4415 100%)
|
||||
background: -o-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #ff4415 100%)
|
||||
background: -ms-linear-gradient(left, rgba(30, 87, 153, 0) 0%, #ff4415 100%)
|
||||
background: linear-gradient(to right, rgba(30, 87, 153, 0) 0%, #ff4415 100%)
|
||||
/* W3C
|
||||
|
||||
.nav
|
||||
background-color: #fff
|
||||
border-right: 1px solid #e0e0e0
|
||||
|
||||
.nav-item, .nav-item-static
|
||||
color: #383838
|
||||
|
||||
.nav-item
|
||||
font-weight: 600
|
||||
&:hover, &:active
|
||||
background-color: #e2e2e2
|
||||
|
||||
.divider
|
||||
border-bottom: 1px solid #e0e0e0
|
||||
|
||||
.card
|
||||
background: #fff
|
||||
border-radius: 2px
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(62, 62, 62, 0.3)
|
||||
a
|
||||
color: #ff4415
|
||||
text-decoration: none
|
||||
border-bottom: 1px solid transparent
|
||||
border-bottom-color: transparent
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms
|
||||
&:hover
|
||||
border-bottom-color: #ff4415
|
||||
|
||||
.headline
|
||||
font-size: 24px
|
||||
color: #383838 !important
|
||||
text-decoration: none
|
||||
border-bottom: none !important
|
||||
&:hover
|
||||
color: #ff4415 !important
|
||||
|
||||
.date
|
||||
font-size: 13px
|
||||
|
||||
.articletext
|
||||
font-size: 14px
|
||||
line-height: 24px
|
||||
|
||||
.author, .tag
|
||||
font-size: 13px
|
||||
|
||||
.fab
|
||||
background-color: #ff4415
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(62, 62, 62, 0.3)
|
||||
|
||||
.subfab
|
||||
background-color: #fff
|
||||
box-shadow: 0 1px 1.5px 1.5px rgba(62, 62, 62, 0.3)
|
||||
|
||||
.button
|
||||
text-transform: uppercase
|
||||
border-width: 1px
|
||||
border-style: solid
|
||||
-webkit-box-shadow: 0.4px 1px 1.5px 1px #aaa
|
||||
-moz-box-shadow: 0.4px 1px 1.5px 1px #aaa
|
||||
box-shadow: 0.4px 1px 1.5px 1px #aaa
|
||||
border-radius: 2px
|
||||
letter-spacing: 0.4px
|
||||
font-weight: 700
|
||||
font-size: 14px
|
||||
transition-property: box-shadow
|
||||
transition-delay: 50ms
|
||||
transition-duration: 125ms
|
||||
transition-timing-function: ease
|
||||
-o-transition-property: box-shadow
|
||||
-o-transition-delay: 50ms
|
||||
-o-transition-duration: 125ms
|
||||
-o-transition-timing-function: ease
|
||||
-moz-transition-property: box-shadow
|
||||
-moz-transition-delay: 50ms
|
||||
-moz-transition-duration: 125ms
|
||||
-moz-transition-timing-function: ease
|
||||
-webkit-transition-property: box-shadow
|
||||
-webkit-transition-delay: 50ms
|
||||
-webkit-transition-duration: 125ms
|
||||
-webkit-transition-timing-function: ease
|
||||
&:hover
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa
|
||||
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa
|
||||
|
||||
.pag_next
|
||||
background-color: #ff4415
|
||||
border-color: #ff4415
|
||||
|
||||
.pag_prev
|
||||
background-color: #fff
|
||||
border-color: #fff
|
||||
color: #383838
|
||||
|
||||
.footer
|
||||
font-size: 12px
|
||||
text-align: center
|
||||
a
|
||||
color: #383838
|
||||
text-decoration: none
|
||||
border-bottom: 1px solid transparent
|
||||
border-bottom-color: transparent
|
||||
&:hover
|
||||
border-bottom-color: #383838
|
46
src/sass/no-nav.sass
Normal file
46
src/sass/no-nav.sass
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Rangitaki Project
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* A stylesheet for overriding the default styles if the navigation drawer is disabled
|
||||
*/
|
||||
|
||||
.nav
|
||||
display: none
|
||||
|
||||
.nav-img
|
||||
display: none
|
||||
|
||||
@media screen and (min-width: 1440px)
|
||||
.header
|
||||
left: 0
|
||||
|
||||
.main
|
||||
margin-left: 0
|
||||
width: 100%
|
||||
|
||||
@media screen and (max-width: 720px)
|
||||
|
||||
.title
|
||||
left: 25px
|
249
src/sass/rangitaki.sass
Normal file
249
src/sass/rangitaki.sass
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* Rangitaki Project
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright 2015 mmk2410.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* A stylesheet for overriding the default styles if the navigation drawer is disabled
|
||||
*/
|
||||
|
||||
/* BODY */
|
||||
|
||||
body
|
||||
margin-top: 94px
|
||||
|
||||
.main
|
||||
height: 100%
|
||||
margin-left: 0
|
||||
|
||||
.overlay
|
||||
opacity: 0
|
||||
position: fixed
|
||||
top: 0
|
||||
left: 0
|
||||
background-color: black
|
||||
width: 100%
|
||||
z-index: 30
|
||||
height: 100%
|
||||
display: none
|
||||
|
||||
/* HEADER */
|
||||
.header
|
||||
top: 0
|
||||
right: 0
|
||||
left: 0
|
||||
width: 100%
|
||||
height: 64px
|
||||
position: absolute
|
||||
|
||||
.title
|
||||
color: #fff
|
||||
font-size: 23px
|
||||
text-decoration: none
|
||||
line-height: 64px
|
||||
vertical-align: middle
|
||||
left: 75px
|
||||
|
||||
.title > a
|
||||
text-decoration: none
|
||||
color: #fff
|
||||
|
||||
.fadeout
|
||||
position: absolute
|
||||
height: 64px
|
||||
top: 0
|
||||
right: 0
|
||||
width: 40px
|
||||
|
||||
.nav-img
|
||||
height: 26px
|
||||
padding: 19px
|
||||
cursor: pointer
|
||||
|
||||
/* NAV DRAWER */
|
||||
|
||||
.nav
|
||||
width: 300px
|
||||
position: fixed
|
||||
height: 100%
|
||||
top: 0
|
||||
left: -301px
|
||||
z-index: 40
|
||||
|
||||
.nav-item, .nav-item-static
|
||||
text-decoration: none
|
||||
text-indent: 0
|
||||
display: inline-block
|
||||
height: 48px
|
||||
vertical-align: middle
|
||||
width: 284px
|
||||
line-height: 48px
|
||||
padding-left: 16px
|
||||
transition: background-color 125ms ease-in-out 0ms
|
||||
|
||||
.nav-close
|
||||
cursor: pointer
|
||||
|
||||
.nav-close-img
|
||||
height: 35px
|
||||
padding: 12px
|
||||
|
||||
.nav-item
|
||||
cursor: pointer
|
||||
|
||||
.divider
|
||||
width: 100%
|
||||
|
||||
/* MAIN */
|
||||
|
||||
.card
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
width: 75%
|
||||
padding: 24px
|
||||
margin-bottom: 40px
|
||||
max-width: 1160px
|
||||
|
||||
.card a
|
||||
-moz-hyphens: auto
|
||||
-epub-hyphens: auto
|
||||
-ms-hyphens: auto
|
||||
-webkit-hyphens: auto
|
||||
hyphens: auto
|
||||
word-wrap: break-word
|
||||
|
||||
.card a:hover
|
||||
|
||||
.headline
|
||||
display: block
|
||||
padding-bottom: 8px
|
||||
|
||||
.card img
|
||||
max-width: 100%
|
||||
max-height: 400px
|
||||
display: block
|
||||
margin-left: auto
|
||||
margin-right: auto
|
||||
|
||||
.date
|
||||
|
||||
.articletext
|
||||
|
||||
.author
|
||||
display: block
|
||||
|
||||
.tag
|
||||
|
||||
/* FAB */
|
||||
|
||||
.fabmenu
|
||||
position: fixed
|
||||
bottom: 20px
|
||||
right: 20px
|
||||
|
||||
.fab
|
||||
height: 60px
|
||||
width: 60px
|
||||
border-radius: 30px
|
||||
cursor: pointer
|
||||
|
||||
.fab-img
|
||||
width: 28px
|
||||
padding: 15px
|
||||
|
||||
.subfab
|
||||
height: 45px
|
||||
width: 45px
|
||||
border-radius: 30px
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
margin-bottom: 25px
|
||||
display: none
|
||||
|
||||
.subfab-img
|
||||
width: 22px
|
||||
padding: 12px
|
||||
|
||||
/* BUTTON */
|
||||
|
||||
.pag_buttons
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
width: calc(75% + 48px)
|
||||
margin-bottom: 80px
|
||||
max-width: 1160px
|
||||
text-align: right
|
||||
|
||||
.button
|
||||
text-decoration: none
|
||||
color: #fff
|
||||
line-height: 36px
|
||||
min-width: 64px
|
||||
text-align: center
|
||||
height: 36px
|
||||
padding: 8px
|
||||
margin-top: 4px
|
||||
margin-bottom: 5px
|
||||
cursor: pointer
|
||||
|
||||
.pag_next
|
||||
margin-left: 8px
|
||||
|
||||
/* FOOTER */
|
||||
|
||||
.footer
|
||||
|
||||
.footer a
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms
|
||||
|
||||
.footer a:hover
|
||||
border-bottom-color: #383838
|
||||
|
||||
@media screen and (min-width: 1440px)
|
||||
|
||||
.nav
|
||||
left: 0
|
||||
padding-top: 64px
|
||||
|
||||
.nav-close-img
|
||||
display: none
|
||||
|
||||
.nav-close
|
||||
display: none
|
||||
|
||||
.nav-img
|
||||
display: none
|
||||
|
||||
.header
|
||||
left: 300px
|
||||
|
||||
.main
|
||||
margin-left: 300px
|
||||
width: calc(100% - 300px)
|
||||
|
||||
@media screen and (max-width: 720px)
|
||||
|
||||
.card
|
||||
width: 82%
|
||||
|
||||
.pag_buttons
|
||||
width: calc(82% + 48px)
|
|
@ -1,207 +1,3 @@
|
|||
/*
|
||||
The MIT License
|
||||
body{font-family:"Roboto", sans-serif;background:#f6f6f6;color:#383838;background-image:url(//example.com/res/img/intro.svg);background-size:cover;background-attachment:fixed;background-position:top center;background-repeat:no-repeat}.header{background-color:rgba(0,0,0,0.45);position:fixed}.title{color:#fff;position:absolute}.title>a{color:#fff}.fadeout{background:-moz-linear-gradient(left, rgba(30,87,153,0) 0%, rgba(0,0,0,0.45) 100%);background:-webkit-linear-gradient(left, rgba(30,87,153,0) 0%, rgba(0,0,0,0.45) 100%);background:-o-linear-gradient(left, rgba(30,87,153,0) 0%, rgba(0,0,0,0.45) 100%);background:-ms-linear-gradient(left, rgba(30,87,153,0) 0%, rgba(0,0,0,0.45) 100%);background:linear-gradient(to right, rgba(30,87,153,0) 0%, rgba(0,0,0,0.45) 100%)}.nav{background-color:#fff;border-right:1px solid #e0e0e0}.nav-item,.nav-item-static{color:#383838}.nav-item{font-weight:600}.nav-item:active{background-color:#e2e2e2}.divider{border-bottom:1px solid #e0e0e0}.card{background:#fff;border-radius:2px;box-shadow:0 1px 1.5px 1.5px rgba(62,62,62,0.3)}.card a{color:#ff4415;text-decoration:none;border-bottom:1px solid transparent;border-bottom-color:transparent;transition:border-bottom-color 150ms ease-in-out 100ms}.card a:hover{border-bottom-color:#ff4415}.headline{font-size:24px;color:#383838 !important;text-decoration:none;border-bottom:none !important}.headline:hover{color:#ff4415 !important}.date{font-size:13px}.articletext{font-size:14px;line-height:24px}.author{font-size:13px}.tag{font-size:13px}.fab{background-color:#ff4415;box-shadow:0 1px 1.5px 1.5px rgba(62,62,62,0.3)}.subfab{background-color:#fff;box-shadow:0 1px 1.5px 1.5px rgba(62,62,62,0.3)}.button{border-width:1px;border-style:solid;text-transform:uppercase;-webkit-box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65);-moz-box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65);box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65);border-radius:2px;letter-spacing:0.4px;font-weight:700;font-size:14px;transition-property:box-shadow;transition-delay:50ms;transition-duration:125ms;transition-timing-function:ease;-o-transition-property:box-shadow;-o-transition-delay:50ms;-o-transition-duration:125ms;-o-transition-timing-function:ease;-moz-transition-property:box-shadow;-moz-transition-delay:50ms;-moz-transition-duration:125ms;-moz-transition-timing-function:ease;-webkit-transition-property:box-shadow;-webkit-transition-delay:50ms;-webkit-transition-duration:125ms;-webkit-transition-timing-function:ease}.button:hover,.button:hover{-webkit-box-shadow:0.5px 1.8px 2.1px 1.4px rgba(32,32,32,0.85);-moz-box-shadow:0.5px 1.8px 2.1px 1.4px rgba(32,32,32,0.85);box-shadow:0.5px 1.8px 2.1px 1.4px rgba(32,32,32,0.85)}.pag_next{background-color:#ff4415;border-color:#ff4415}.pag_prev{background-color:#fff;border-color:#fff;color:#383838}.footer{font-size:12px;text-align:center;color:#fff;text-shadow:1px 1px rgba(55,55,55,0.3)}.footer a{color:#fff;text-shadow:1px 1px rgba(175,175,175,0.3);text-decoration:none;border-bottom:1px solid transparent;border-bottom-color:transparent}.footer a:hover{border-bottom-color:#fff}@media screen and (min-width: 1440px){.nav{background-color:rgba(255,255,255,0.8)}}
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Created on : Jun 18, 2015, 6:39:37 PM
|
||||
Author : mmk2410
|
||||
*/
|
||||
|
||||
body{
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #f6f6f6;
|
||||
color: #383838;
|
||||
background-image: url(//marcel-kapfer.de/res/img/intro.svg);
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
background-position: top center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.header{
|
||||
background-color: rgba(0, 0, 0, 0.45);
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.title{
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.title > a{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fadeout{
|
||||
background: -moz-linear-gradient(left, rgba(30,87,153,0) 0%, rgba(0, 0, 0, 0.45) 100%); /* FF3.6+ */
|
||||
background: -webkit-linear-gradient(left, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(left, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(left, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%); /* IE10+ */
|
||||
background: linear-gradient(to right, rgba(30,87,153,0) 0%,rgba(0, 0, 0, 0.45) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.nav{
|
||||
background-color: #fff;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.nav-item, .nav-item-static{
|
||||
color: #383838;
|
||||
}
|
||||
|
||||
.nav-item{
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nav-item:active{
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.divider{
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.card{
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
|
||||
.card a{
|
||||
color: #ff4415;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-bottom-color: transparent;
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms;
|
||||
}
|
||||
|
||||
.card a:hover{
|
||||
border-bottom-color: #ff4415;
|
||||
}
|
||||
|
||||
.headline{
|
||||
font-size: 24px;
|
||||
color: #383838!important;
|
||||
text-decoration: none;
|
||||
border-bottom: none!important;
|
||||
}
|
||||
|
||||
.headline:hover {
|
||||
color: #ff4415!important;
|
||||
}
|
||||
|
||||
.date{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.articletext{
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.author{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tag{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.fab{
|
||||
background-color: #ff4415;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
.subfab{
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
.button {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
text-transform: uppercase;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
-moz-box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
-webkit-box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
border-radius: 2px;
|
||||
letter-spacing: 0.4px;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
transition-property: box-shadow;
|
||||
transition-delay: 50ms;
|
||||
transition-duration: 125ms;
|
||||
transition-timing-function: ease;
|
||||
-moz-transition-property: box-shadow;
|
||||
-moz-transition-delay: 50ms;
|
||||
-moz-transition-duration: 125ms;
|
||||
-moz-transition-timing-function: ease;
|
||||
-webkit-transition-property: box-shadow;
|
||||
-webkit-transition-delay: 50ms;
|
||||
-webkit-transition-duration: 125ms;
|
||||
-webkit-transition-timing-function: ease;
|
||||
}
|
||||
|
||||
.button:hover, .button:hover {
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85);
|
||||
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85);
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85);
|
||||
}
|
||||
|
||||
.pag_next{
|
||||
background-color: #ff4415;
|
||||
border-color: #ff4415;
|
||||
}
|
||||
|
||||
.pag_prev{
|
||||
background-color: #fff;
|
||||
border-color: #fff;
|
||||
color: #383838;
|
||||
}
|
||||
|
||||
.footer{
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px rgba(55, 55, 55, 0.3);
|
||||
}
|
||||
|
||||
.footer a{
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px rgba(175, 175, 175, 0.3);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.footer a:hover{
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1440px) {
|
||||
|
||||
.nav{
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
}
|
||||
/*# sourceMappingURL=background-img.css.map */
|
||||
|
|
1
themes/background-img.css.map
Normal file
1
themes/background-img.css.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,193 +1,3 @@
|
|||
/*
|
||||
The MIT License
|
||||
body{font-family:"Roboto", sans-serif;background:#303030;color:#fff}.header{background-color:#212121;position:fixed;box-shadow:2px 0 2px 2px rgba(32,32,32,0.85)}.title{color:#fff;position:absolute}.title>a{color:#fff}.fadeout{background:-moz-linear-gradient(left, rgba(30,87,153,0) 0%, #212121 100%);background:-webkit-linear-gradient(left, rgba(30,87,153,0) 0%, #212121 100%);background:-o-linear-gradient(left, rgba(30,87,153,0) 0%, #212121 100%);background:-ms-linear-gradient(left, rgba(30,87,153,0) 0%, #212121 100%);background:linear-gradient(to right, rgba(30,87,153,0) 0%, #212121 100%)}.nav{background-color:#424242;border-right:1px solid #1f1f1f}.nav-item,.nav-item-static{color:#fff}.nav-item{font-weight:600}.nav-item:active{background-color:#383838}.divider{border-bottom:1px solid #1f1f1f}.card{background:#424242;border-radius:2px;box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65)}.card a{color:#ff4415;text-decoration:none;border-bottom:1px solid transparent;border-bottom-color:transparent;transition:border-bottom-color 150ms ease-in-out 100ms}.card a:hover{border-bottom-color:#ff4415}.headline{font-size:24px;color:#fff !important;text-decoration:none;border-bottom:none !important}.headline:hover{color:#ff4415 !important}.date{font-size:13px}.articletext{font-size:14px;line-height:24px}.author,.tag{font-size:13px}.fab{background-color:#ff4415;box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65)}.subfab{background-color:#424242;box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65)}.button{text-transform:uppercase;border-width:1px;border-style:solid;-webkit-box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65);-moz-box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65);box-shadow:0 1px 1.5px 1.5px rgba(42,42,42,0.65);border-radius:2px;letter-spacing:0.4px;font-weight:700;font-size:14px;transition-property:box-shadow;transition-delay:50ms;transition-duration:125ms;transition-timing-function:ease;-o-transition-property:box-shadow;-o-transition-delay:50ms;-o-transition-duration:125ms;-o-transition-timing-function:ease;-moz-transition-property:box-shadow;-moz-transition-delay:50ms;-moz-transition-duration:125ms;-moz-transition-timing-function:ease;-webkit-transition-property:box-shadow;-webkit-transition-delay:50ms;-webkit-transition-duration:125ms;-webkit-transition-timing-function:ease}.button:hover{-webkit-box-shadow:0.5px 1.8px 2.1px 1.4px rgba(32,32,32,0.85);-moz-box-shadow:0.5px 1.8px 2.1px 1.4px rgba(32,32,32,0.85);box-shadow:0.5px 1.8px 2.1px 1.4px rgba(32,32,32,0.85)}.pag_next{background-color:#ff4415;border-color:#ff4415}.pag_prev{background-color:#424242;border-color:#424242;color:#CCCCCC}.footer{font-size:12px;text-align:center;color:#fff}.footer a{color:#fff;text-decoration:none;border-bottom:1px solid transparent;border-bottom-color:transparent}.footer a:hover{border-bottom-color:#fff}
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Created on : Jun 18, 2015, 6:39:37 PM
|
||||
Author : mmk2410
|
||||
*/
|
||||
|
||||
body{
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #303030;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.header{
|
||||
background-color: #212121;
|
||||
position: fixed;
|
||||
box-shadow: 2px 0px 2px 2px rgba(32, 32, 32, 0.85);
|
||||
}
|
||||
|
||||
.title{
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.title > a{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fadeout{
|
||||
background: -moz-linear-gradient(left, rgba(30,87,153,0) 0%, #212121 100%); /* FF3.6+ */
|
||||
background: -webkit-linear-gradient(left, rgba(30,87,153,0) 0%,#212121 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(left, rgba(30,87,153,0) 0%,#212121 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(left, rgba(30,87,153,0) 0%,#212121 100%); /* IE10+ */
|
||||
background: linear-gradient(to right, rgba(30,87,153,0) 0%,#212121 100%); /* W3C */
|
||||
}
|
||||
|
||||
.nav{
|
||||
background-color: #424242;
|
||||
border-right: 1px solid #1f1f1f;
|
||||
}
|
||||
|
||||
.nav-item, .nav-item-static{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav-item{
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nav-item:active{
|
||||
background-color: #383838;
|
||||
}
|
||||
|
||||
.divider{
|
||||
border-bottom: 1px solid #1f1f1f;
|
||||
}
|
||||
|
||||
.card{
|
||||
background: #424242;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
}
|
||||
|
||||
|
||||
.card a{
|
||||
color: #ff4415;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-bottom-color: transparent;
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms;
|
||||
}
|
||||
|
||||
.card a:hover{
|
||||
border-bottom-color: #ff4415;
|
||||
}
|
||||
|
||||
.headline{
|
||||
font-size: 24px;
|
||||
color: #fff!important;
|
||||
text-decoration: none;
|
||||
border-bottom: none!important;
|
||||
}
|
||||
|
||||
.headline:hover {
|
||||
color: #ff4415!important;
|
||||
}
|
||||
|
||||
.date{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.articletext{
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.author{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tag{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.fab{
|
||||
background-color: #ff4415;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
}
|
||||
|
||||
.subfab{
|
||||
background-color: #424242;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
}
|
||||
|
||||
.button{
|
||||
text-transform: uppercase;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
-moz-box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
-webkit-box-shadow: 0px 1px 1.5px 1.5px rgba(42, 42, 42, 0.65);
|
||||
border-radius: 2px;
|
||||
letter-spacing: 0.4px;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
transition-property: box-shadow;
|
||||
transition-delay: 50ms;
|
||||
transition-duration: 125ms;
|
||||
transition-timing-function: ease;
|
||||
-moz-transition-property: box-shadow;
|
||||
-moz-transition-delay: 50ms;
|
||||
-moz-transition-duration: 125ms;
|
||||
-moz-transition-timing-function: ease;
|
||||
-webkit-transition-property: box-shadow;
|
||||
-webkit-transition-delay: 50ms;
|
||||
-webkit-transition-duration: 125ms;
|
||||
-webkit-transition-timing-function: ease;
|
||||
}
|
||||
|
||||
.button:hover, .button:hover {
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85);
|
||||
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85);
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px rgba(32, 32, 32, 0.85);
|
||||
}
|
||||
|
||||
.pag_next{
|
||||
background-color: #ff4415;
|
||||
border-color: #ff4415;
|
||||
}
|
||||
|
||||
.pag_prev{
|
||||
background-color: #424242;
|
||||
border-color: #424242;
|
||||
color: #CCCCCC;
|
||||
}
|
||||
|
||||
.footer{
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.footer a{
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.footer a:hover{
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
/*# sourceMappingURL=material-dark.css.map */
|
||||
|
|
1
themes/material-dark.css.map
Normal file
1
themes/material-dark.css.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,196 +1,3 @@
|
|||
/*
|
||||
The MIT License
|
||||
body{font-family:"Roboto", sans-serif;background:#f6f6f6;color:#383838}.header{background-color:#ff4415;position:fixed;box-shadow:2px 0 2px 2px rgba(62,62,62,0.45)}.title{color:#fff;position:absolute}.title>a{color:#fff}.fadeout{background:-moz-linear-gradient(left, rgba(30,87,153,0) 0%, #ff4415 100%);background:-webkit-linear-gradient(left, rgba(30,87,153,0) 0%, #ff4415 100%);background:-o-linear-gradient(left, rgba(30,87,153,0) 0%, #ff4415 100%);background:-ms-linear-gradient(left, rgba(30,87,153,0) 0%, #ff4415 100%);background:linear-gradient(to right, rgba(30,87,153,0) 0%, #ff4415 100%)}.nav{background-color:#fff;border-right:1px solid #e0e0e0}.nav-item,.nav-item-static{color:#383838}.nav-item{font-weight:600}.nav-item:hover,.nav-item:active{background-color:#e2e2e2}.divider{border-bottom:1px solid #e0e0e0}.card{background:#fff;border-radius:2px;box-shadow:0 1px 1.5px 1.5px rgba(62,62,62,0.3)}.card a{color:#ff4415;text-decoration:none;border-bottom:1px solid transparent;border-bottom-color:transparent;transition:border-bottom-color 150ms ease-in-out 100ms}.card a:hover{border-bottom-color:#ff4415}.headline{font-size:24px;color:#383838 !important;text-decoration:none;border-bottom:none !important}.headline:hover{color:#ff4415 !important}.date{font-size:13px}.articletext{font-size:14px;line-height:24px}.author,.tag{font-size:13px}.fab{background-color:#ff4415;box-shadow:0 1px 1.5px 1.5px rgba(62,62,62,0.3)}.subfab{background-color:#fff;box-shadow:0 1px 1.5px 1.5px rgba(62,62,62,0.3)}.button{text-transform:uppercase;border-width:1px;border-style:solid;-webkit-box-shadow:0.4px 1px 1.5px 1px #aaa;-moz-box-shadow:0.4px 1px 1.5px 1px #aaa;box-shadow:0.4px 1px 1.5px 1px #aaa;border-radius:2px;letter-spacing:0.4px;font-weight:700;font-size:14px;transition-property:box-shadow;transition-delay:50ms;transition-duration:125ms;transition-timing-function:ease;-o-transition-property:box-shadow;-o-transition-delay:50ms;-o-transition-duration:125ms;-o-transition-timing-function:ease;-moz-transition-property:box-shadow;-moz-transition-delay:50ms;-moz-transition-duration:125ms;-moz-transition-timing-function:ease;-webkit-transition-property:box-shadow;-webkit-transition-delay:50ms;-webkit-transition-duration:125ms;-webkit-transition-timing-function:ease}.button:hover{-webkit-box-shadow:0.5px 1.8px 2.1px 1.4px #aaa;-moz-box-shadow:0.5px 1.8px 2.1px 1.4px #aaa;box-shadow:0.5px 1.8px 2.1px 1.4px #aaa}.pag_next{background-color:#ff4415;border-color:#ff4415}.pag_prev{background-color:#fff;border-color:#fff;color:#383838}.footer{font-size:12px;text-align:center}.footer a{color:#383838;text-decoration:none;border-bottom:1px solid transparent;border-bottom-color:transparent}.footer a:hover{border-bottom-color:#383838}
|
||||
|
||||
Copyright 2015 mmk2410.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Created on : Jun 18, 2015, 6:39:37 PM
|
||||
Author : mmk2410
|
||||
*/
|
||||
|
||||
body{
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: #f6f6f6;
|
||||
color: #383838;
|
||||
}
|
||||
|
||||
.header{
|
||||
background-color: #ff4415;
|
||||
position: fixed;
|
||||
box-shadow: 2px 0px 2px 2px rgba(62, 62, 62, 0.45);
|
||||
}
|
||||
|
||||
.title{
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.title > a{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fadeout{
|
||||
background: -moz-linear-gradient(left, rgba(30,87,153,0) 0%, #ff4415 100%); /* FF3.6+ */
|
||||
background: -webkit-linear-gradient(left, rgba(30,87,153,0) 0%,#ff4415 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(left, rgba(30,87,153,0) 0%,#ff4415 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(left, rgba(30,87,153,0) 0%,#ff4415 100%); /* IE10+ */
|
||||
background: linear-gradient(to right, rgba(30,87,153,0) 0%,#ff4415 100%); /* W3C */
|
||||
}
|
||||
|
||||
.nav{
|
||||
background-color: #fff;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.nav-item, .nav-item-static{
|
||||
color: #383838;
|
||||
}
|
||||
|
||||
.nav-item{
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nav-item:hover{
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.nav-item:active{
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.divider{
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.card{
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
|
||||
.card a{
|
||||
color: #ff4415;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-bottom-color: transparent;
|
||||
transition: border-bottom-color 150ms ease-in-out 100ms;
|
||||
}
|
||||
|
||||
.card a:hover{
|
||||
border-bottom-color: #ff4415;
|
||||
}
|
||||
|
||||
.headline{
|
||||
font-size: 24px;
|
||||
color: #383838!important;
|
||||
text-decoration: none;
|
||||
border-bottom: none!important;
|
||||
}
|
||||
|
||||
.headline:hover {
|
||||
color: #ff4415!important;
|
||||
}
|
||||
|
||||
.date{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.articletext{
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.author{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tag{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.fab{
|
||||
background-color: #ff4415;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
.subfab{
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 1px 1.5px 1.5px rgba(62, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
.button {
|
||||
text-transform: uppercase;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
-moz-box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
-webkit-box-shadow: 0.4px 1px 1.5px 1px #aaa;
|
||||
border-radius: 2px;
|
||||
letter-spacing: 0.4px;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
transition-property: box-shadow;
|
||||
transition-delay: 50ms;
|
||||
transition-duration: 125ms;
|
||||
transition-timing-function: ease;
|
||||
-moz-transition-property: box-shadow;
|
||||
-moz-transition-delay: 50ms;
|
||||
-moz-transition-duration: 125ms;
|
||||
-moz-transition-timing-function: ease;
|
||||
-webkit-transition-property: box-shadow;
|
||||
-webkit-transition-delay: 50ms;
|
||||
-webkit-transition-duration: 125ms;
|
||||
-webkit-transition-timing-function: ease;
|
||||
}
|
||||
|
||||
.button:hover, .button:hover {
|
||||
box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
|
||||
-moz-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
|
||||
-webkit-box-shadow: 0.5px 1.8px 2.1px 1.4px #aaa;
|
||||
}
|
||||
|
||||
.pag_next{
|
||||
background-color: #ff4415;
|
||||
border-color: #ff4415;
|
||||
}
|
||||
|
||||
.pag_prev{
|
||||
background-color: #fff;
|
||||
border-color: #fff;
|
||||
color: #383838;
|
||||
}
|
||||
|
||||
.footer{
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer a{
|
||||
color: #383838;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.footer a:hover{
|
||||
border-bottom-color: #383838;
|
||||
}
|
||||
/*# sourceMappingURL=material-light.css.map */
|
||||
|
|
1
themes/material-light.css.map
Normal file
1
themes/material-light.css.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -9,7 +9,7 @@ conf="./config.php"
|
|||
echo "Downloading version $version from GitHub..."
|
||||
mkdir $new
|
||||
cd $new || exit
|
||||
wget -c https://github.com/mmk2410/Rangitaki/archive/"$version".zip
|
||||
wget -c https://github.com/mmk2410/Rangitaki/archive/v"$version".zip
|
||||
|
||||
echo "Extracting"
|
||||
unzip v"$version".zip
|
||||
|
|
80
update-scripts/1-3-0_1-4-0.sh
Normal file
80
update-scripts/1-3-0_1-4-0.sh
Normal file
|
@ -0,0 +1,80 @@
|
|||
#!/bin/bash
|
||||
# Update script for Rangitaki from version 1.3.0 to 1.4.0
|
||||
|
||||
version="1.4.0"
|
||||
new="./rbe-new"
|
||||
|
||||
echo "Downloading version $version from GitLab..."
|
||||
git clone https://gitlab.com/mmk2410/rangitaki.git "$new"
|
||||
|
||||
if [[ $1 == "--debug" ]]; then
|
||||
cd $new
|
||||
git checkout master
|
||||
cd ../
|
||||
fi
|
||||
|
||||
echo "Updating ressources..."
|
||||
rm -rf ./res/
|
||||
mv $new/res/ ./
|
||||
|
||||
echo "Updating extensions..."
|
||||
rm ./extensions/example.js
|
||||
mv $new/extensions/* ./extensions/
|
||||
|
||||
echo "Importing binaries..."
|
||||
mv $new/bin/ ./
|
||||
|
||||
echo "Importing source files..."
|
||||
mv $new/src/ ./
|
||||
|
||||
echo "Updating extensions..."
|
||||
rm ./themes/material-light.css
|
||||
rm ./themes/material-dark.css
|
||||
rm ./themes/background-img.css
|
||||
mv $new/themes/* ./themes/
|
||||
|
||||
echo "Updating RCC..."
|
||||
rm -rf ./rcc
|
||||
mv $new/rcc ./
|
||||
rm ./rcc/password.php
|
||||
|
||||
echo "Updating core..."
|
||||
rm ./index.php
|
||||
mv $new/index.php ./
|
||||
|
||||
echo "Preparing composer..."
|
||||
rm -rf ./vendor/
|
||||
rm composer.lock
|
||||
rm composer.json
|
||||
mv $new/vendor ./
|
||||
mv $new/composer.lock ./
|
||||
mv $new/composer.json ./
|
||||
|
||||
echo "Preparing npm..."
|
||||
mv $new/package.json ./
|
||||
|
||||
echo "Updating Changelog..."
|
||||
|
||||
if [ -f ./CHANGELOG.txt ]; then
|
||||
rm CHANGELOG.txt
|
||||
fi
|
||||
|
||||
mv $new/CHANGELOG.md ./
|
||||
|
||||
echo "Preparing gulp..."
|
||||
mv $new/gulpfile.coffee ./
|
||||
|
||||
echo "Cleaning up..."
|
||||
if [[ $1 != "--debug" ]]; then
|
||||
rm -rf $new
|
||||
fi
|
||||
|
||||
echo "Update config file..."
|
||||
php bin/config.php
|
||||
|
||||
if [ -d "./update-scripts" ]; then
|
||||
echo "Remove obsolete update scripts folder."
|
||||
rm -rf "./update-scripts"
|
||||
fi
|
||||
|
||||
echo "Your Rangitaki installation is updated to version $version"
|
2
vendor/autoload.php
vendored
2
vendor/autoload.php
vendored
|
@ -4,4 +4,4 @@
|
|||
|
||||
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInite149f47a700f596a9845d47c917afeaf::getLoader();
|
||||
return ComposerAutoloaderInitd1db2574a85c0ba6f142743249ba228f::getLoader();
|
||||
|
|
5
vendor/bshaffer/oauth2-server-php/.gitignore
vendored
Normal file
5
vendor/bshaffer/oauth2-server-php/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Test Files #
|
||||
test/config/test.sqlite
|
||||
vendor
|
||||
composer.lock
|
||||
.idea
|
25
vendor/bshaffer/oauth2-server-php/.travis.yml
vendored
Normal file
25
vendor/bshaffer/oauth2-server-php/.travis.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
language: php
|
||||
sudo: false
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- hhvm
|
||||
env:
|
||||
global:
|
||||
- SKIP_MONGO_TESTS=1
|
||||
- secure: Bc5ZqvZ1YYpoPZNNuU2eCB8DS6vBYrAdfBtTenBs5NSxzb+Vjven4kWakbzaMvZjb/Ib7Uph7DGuOtJXpmxnvBXPLd707LZ89oFWN/yqQlZKCcm8iErvJCB5XL+/ONHj2iPdR242HJweMcat6bMCwbVWoNDidjtWMH0U2mYFy3M=
|
||||
- secure: R3bXlymyFiY2k2jf7+fv/J8i34wtXTkmD4mCr5Ps/U+vn9axm2VtvR2Nj+r7LbRjn61gzFE/xIVjYft/wOyBOYwysrfriydrnRVS0owh6y+7EyOyQWbRX11vVQMf8o31QCQE5BY58V5AJZW3MjoOL0FVlTgySJiJvdw6Pv18v+E=
|
||||
services:
|
||||
- mongodb
|
||||
- redis-server
|
||||
- cassandra
|
||||
before_script:
|
||||
- psql -c 'create database oauth2_server_php;' -U postgres
|
||||
- composer require predis/predis:dev-master
|
||||
- composer require thobbs/phpcassa:dev-master
|
||||
- composer require 'aws/aws-sdk-php:~2.8'
|
||||
- composer require 'firebase/php-jwt:~2.2'
|
||||
after_script:
|
||||
- php test/cleanup.php
|
165
vendor/bshaffer/oauth2-server-php/CHANGELOG.md
vendored
Normal file
165
vendor/bshaffer/oauth2-server-php/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
CHANGELOG for 1.x
|
||||
=================
|
||||
|
||||
This changelog references the relevant changes (bug and security fixes) done
|
||||
in 1.x minor versions.
|
||||
|
||||
To see the files changed for a given bug, go to https://github.com/bshaffer/oauth2-server-php/issues/### where ### is the bug number
|
||||
To get the diff between two versions, go to https://github.com/bshaffer/oauth2-server-php/compare/v1.0...v1.1
|
||||
To get the diff for a specific change, go to https://github.com/bshaffer/oauth2-server-php/commit/XXX where XXX is the change hash
|
||||
|
||||
* 1.8.0 (2015-09-18)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/643
|
||||
|
||||
* bug #594 - adds jti
|
||||
* bug #598 - fixes lifetime configurations for JWTs
|
||||
* bug #634 - fixes travis builds, upgrade to containers
|
||||
* bug #586 - support for revoking tokens
|
||||
* bug #636 - Adds FirebaseJWT bridge
|
||||
* bug #639 - Mongo HHVM compatibility
|
||||
|
||||
* 1.7.0 (2015-04-23)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/572
|
||||
|
||||
* bug #500 - PDO fetch mode changed from FETCH_BOTH to FETCH_ASSOC
|
||||
* bug #508 - Case insensitive for Bearer token header name ba716d4
|
||||
* bug #512 - validateRedirectUri is now public
|
||||
* bug #530 - Add PublicKeyInterface, UserClaimsInterface to Cassandra Storage
|
||||
* bug #505 - DynamoDB storage fixes
|
||||
* bug #556 - adds "code id_token" return type to openid connect
|
||||
* bug #563 - Include "issuer" config key for JwtAccessToken
|
||||
* bug #564 - Fixes JWT vulnerability
|
||||
* bug #571 - Added unset_refresh_token_after_use option
|
||||
|
||||
* 1.6 (2015-01-16)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/496
|
||||
|
||||
* bug 437 - renames CryptoToken to JwtAccessToken / use_crypto_tokens to use_jwt_access_tokens
|
||||
* bug 447 - Adds a Couchbase storage implementation
|
||||
* bug 460 - Rename JWT claims to match spec
|
||||
* bug 470 - order does not matter for multi-valued response types
|
||||
* bug 471 - Make validateAuthorizeRequest available for POST in addition to GET
|
||||
* bug 475 - Adds JTI table definitiion
|
||||
* bug 481 - better randomness for generating access tokens
|
||||
* bug 480 - Use hash_equals() for signature verification (prevents remote timing attacks)
|
||||
* bugs 489, 491, 498 - misc other fixes
|
||||
|
||||
* 1.5 (2014-08-27)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/446
|
||||
|
||||
* bug #399 - Add DynamoDB Support
|
||||
* bug #404 - renamed error name for malformed/expired tokens
|
||||
* bug #412 - Openid connect: fixes for claims with more than one scope / Add support for the prompt parameter ('consent' and 'none')
|
||||
* bug #411 - fixes xml output
|
||||
* bug #413 - fixes invalid format error
|
||||
* bug #401 - fixes code standards / whitespace
|
||||
* bug #354 - bundles PDO SQL with the library
|
||||
* [BC] bug #397 - refresh tokens should not be encrypted
|
||||
* bug #423 - makes "scope" optional for refresh token storage
|
||||
|
||||
* 1.4 (2014-06-12)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/392
|
||||
|
||||
* bug #189 Storage\PDO - allows DSN string in constructor
|
||||
* bug #233 Bearer Tokens - allows token in request body for PUT requests
|
||||
* bug #346 Fixes open_basedir warning
|
||||
* bug #351 Adds OpenID Connect support
|
||||
* bug #355 Adds php 5.6 and HHVM to travis.ci testing
|
||||
* [BC] bug #358 Adds `getQuerystringIdentifier()` to the GrantType interface
|
||||
* bug #363 Encryption\JWT - Allows for subclassing JWT Headers
|
||||
* bug #349 Bearer Tokens - adds requestHasToken method for when access tokens are optional
|
||||
* bug #301 Encryption\JWT - fixes urlSafeB64Encode(): ensures newlines are replaced as expected
|
||||
* bug #323 ResourceController - client_id is no longer required to be returned when calling getAccessToken
|
||||
* bug #367 Storage\PDO - adds Postgres support
|
||||
* bug #368 Access Tokens - use mcrypt_create_iv or openssl_random_pseudo_bytes to create token string
|
||||
* bug #376 Request - allows case insensitive headers
|
||||
* bug #384 Storage\PDO - can pass in PDO options in constructor of PDO storage
|
||||
* misc fixes #361, #292, #373, #374, #379, #396
|
||||
* 1.3 (2014-02-27)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/325
|
||||
|
||||
* bug #311 adds cassandra storage
|
||||
* bug #298 fixes response code for user credentials grant type
|
||||
* bug #318 adds 'use_crypto_tokens' config to Server class for better DX
|
||||
* [BC] bug #320 pass client_id to getDefaultScope
|
||||
* bug #324 better feedback when running tests
|
||||
* bug #335 adds support for non-expiring refresh tokens
|
||||
* bug #333 fixes Pdo storage for getClientKey
|
||||
* bug #336 fixes Redis storage for expireAuthorizationCode
|
||||
|
||||
* 1.3 (2014-02-27)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/325
|
||||
|
||||
* bug #311 adds cassandra storage
|
||||
* bug #298 fixes response code for user credentials grant type
|
||||
* bug #318 adds 'use_crypto_tokens' config to Server class for better DX
|
||||
* bug #320 pass client_id to getDefaultScope
|
||||
* bug #324 better feedback when running tests
|
||||
* bug #335 adds support for non-expiring refresh tokens
|
||||
* bug #333 fixes Pdo storage for getClientKey
|
||||
* bug #336 fixes Redis storage for expireAuthorizationCode
|
||||
|
||||
* 1.2 (2014-01-03)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/288
|
||||
|
||||
* bug #285 changed response header from 200 to 401 when empty token received
|
||||
* bug #286 adds documentation and links to spec for not including error messages when no token is supplied
|
||||
* bug #280 ensures PHP warnings do not get thrown as a result of an invalid argument to $jwt->decode()
|
||||
* bug #279 predis wrong number of arguments
|
||||
* bug #277 Securing JS WebApp client secret w/ password grant type
|
||||
|
||||
* 1.1 (2013-12-17)
|
||||
|
||||
PR: https://github.com/bshaffer/oauth2-server-php/pull/276
|
||||
|
||||
* bug #278 adds refresh token configuration to Server class
|
||||
* bug #274 Supplying a null client_id and client_secret grants API access
|
||||
* bug #244 [MongoStorage] More detailed implementation info
|
||||
* bug #268 Implement jti for JWT Bearer tokens to prevent replay attacks.
|
||||
* bug #266 Removing unused argument to getAccessTokenData
|
||||
* bug #247 Make Bearer token type consistent
|
||||
* bug #253 Fixing CryptoToken refresh token lifetime
|
||||
* bug #246 refactors public key logic to be more intuitive
|
||||
* bug #245 adds support for JSON crypto tokens
|
||||
* bug #230 Remove unused columns in oauth_clients
|
||||
* bug #215 makes Redis Scope Storage obey the same paradigm as PDO
|
||||
* bug #228 removes scope group
|
||||
* bug #227 squelches open basedir restriction error
|
||||
* bug #223 Updated docblocks for RefreshTokenInterface.php
|
||||
* bug #224 Adds protected properties
|
||||
* bug #217 Implement ScopeInterface for PDO, Redis
|
||||
|
||||
* 1.0 (2013-08-12)
|
||||
|
||||
* bug #203 Add redirect\_status_code config param for AuthorizeController
|
||||
* bug #205 ensures unnecessary ? is not set when ** bug
|
||||
* bug #204 Fixed call to LogicException
|
||||
* bug #202 Add explode to checkRestrictedGrant in PDO Storage
|
||||
* bug #197 adds support for 'false' default scope ** bug
|
||||
* bug #192 reference errors and adds tests
|
||||
* bug #194 makes some appropriate properties ** bug
|
||||
* bug #191 passes config to HttpBasic
|
||||
* bug #190 validates client credentials before ** bug
|
||||
* bug #171 Fix wrong redirect following authorization step
|
||||
* bug #187 client_id is now passed to getDefaultScope().
|
||||
* bug #176 Require refresh_token in getRefreshToken response
|
||||
* bug #174 make user\_id not required for refresh_token grant
|
||||
* bug #173 Duplication in JwtBearer Grant
|
||||
* bug #168 user\_id not required for authorization_code grant
|
||||
* bug #133 hardens default security for user object
|
||||
* bug #163 allows redirect\_uri on authorization_code to be NULL in docs example
|
||||
* bug #162 adds getToken on ResourceController for convenience
|
||||
* bug #161 fixes fatal error
|
||||
* bug #163 Invalid redirect_uri handling
|
||||
* bug #156 user\_id in OAuth2\_Storage_AuthorizationCodeInterface::getAuthorizationCode() response
|
||||
* bug #157 Fix for extending access and refresh tokens
|
||||
* bug #154 ResponseInterface: getParameter method is used in the library but not defined in the interface
|
||||
* bug #148 Add more detail to examples in Readme.md
|
21
vendor/bshaffer/oauth2-server-php/LICENSE
vendored
Normal file
21
vendor/bshaffer/oauth2-server-php/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License
|
||||
|
||||
Copyright (c) 2014 Brent Shaffer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
8
vendor/bshaffer/oauth2-server-php/README.md
vendored
Normal file
8
vendor/bshaffer/oauth2-server-php/README.md
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
oauth2-server-php
|
||||
=================
|
||||
|
||||
[![Build Status](https://travis-ci.org/bshaffer/oauth2-server-php.svg?branch=develop)](https://travis-ci.org/bshaffer/oauth2-server-php)
|
||||
|
||||
[![Total Downloads](https://poser.pugx.org/bshaffer/oauth2-server-php/downloads.png)](https://packagist.org/packages/bshaffer/oauth2-server-php)
|
||||
|
||||
View the [complete documentation](http://bshaffer.github.io/oauth2-server-php-docs/)
|
27
vendor/bshaffer/oauth2-server-php/composer.json
vendored
Normal file
27
vendor/bshaffer/oauth2-server-php/composer.json
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "bshaffer/oauth2-server-php",
|
||||
"description":"OAuth2 Server for PHP",
|
||||
"keywords":["oauth","oauth2","auth"],
|
||||
"type":"library",
|
||||
"license":"MIT",
|
||||
"authors":[
|
||||
{
|
||||
"name":"Brent Shaffer",
|
||||
"email": "bshafs@gmail.com",
|
||||
"homepage":"http://brentertainment.com"
|
||||
}
|
||||
],
|
||||
"homepage": "http://github.com/bshaffer/oauth2-server-php",
|
||||
"require":{
|
||||
"php":">=5.3.9"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "OAuth2": "src/" }
|
||||
},
|
||||
"suggest": {
|
||||
"predis/predis": "Required to use the Redis storage engine",
|
||||
"thobbs/phpcassa": "Required to use the Cassandra storage engine",
|
||||
"aws/aws-sdk-php": "~2.8 is required to use the DynamoDB storage engine",
|
||||
"firebase/php-jwt": "~2.2 is required to use JWT features"
|
||||
}
|
||||
}
|
25
vendor/bshaffer/oauth2-server-php/phpunit.xml
vendored
Normal file
25
vendor/bshaffer/oauth2-server-php/phpunit.xml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="test/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Oauth2 Test Suite">
|
||||
<directory>./test/OAuth2/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./src/OAuth2/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
48
vendor/bshaffer/oauth2-server-php/src/OAuth2/Autoloader.php
vendored
Normal file
48
vendor/bshaffer/oauth2-server-php/src/OAuth2/Autoloader.php
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2;
|
||||
|
||||
/**
|
||||
* Autoloads OAuth2 classes
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
* @license MIT License
|
||||
*/
|
||||
class Autoloader
|
||||
{
|
||||
private $dir;
|
||||
|
||||
public function __construct($dir = null)
|
||||
{
|
||||
if (is_null($dir)) {
|
||||
$dir = dirname(__FILE__).'/..';
|
||||
}
|
||||
$this->dir = $dir;
|
||||
}
|
||||
/**
|
||||
* Registers OAuth2\Autoloader as an SPL autoloader.
|
||||
*/
|
||||
public static function register($dir = null)
|
||||
{
|
||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||
spl_autoload_register(array(new self($dir), 'autoload'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles autoloading of classes.
|
||||
*
|
||||
* @param string $class A class name.
|
||||
*
|
||||
* @return boolean Returns true if the class has been loaded
|
||||
*/
|
||||
public function autoload($class)
|
||||
{
|
||||
if (0 !== strpos($class, 'OAuth2')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_exists($file = $this->dir.'/'.str_replace('\\', '/', $class).'.php')) {
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\ClientAssertionType;
|
||||
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Interface for all OAuth2 Client Assertion Types
|
||||
*/
|
||||
interface ClientAssertionTypeInterface
|
||||
{
|
||||
public function validateRequest(RequestInterface $request, ResponseInterface $response);
|
||||
public function getClientId();
|
||||
}
|
123
vendor/bshaffer/oauth2-server-php/src/OAuth2/ClientAssertionType/HttpBasic.php
vendored
Normal file
123
vendor/bshaffer/oauth2-server-php/src/OAuth2/ClientAssertionType/HttpBasic.php
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\ClientAssertionType;
|
||||
|
||||
use OAuth2\Storage\ClientCredentialsInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Validate a client via Http Basic authentication
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
class HttpBasic implements ClientAssertionTypeInterface
|
||||
{
|
||||
private $clientData;
|
||||
|
||||
protected $storage;
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @param OAuth2\Storage\ClientCredentialsInterface $clientStorage REQUIRED Storage class for retrieving client credentials information
|
||||
* @param array $config OPTIONAL Configuration options for the server
|
||||
* <code>
|
||||
* $config = array(
|
||||
* 'allow_credentials_in_request_body' => true, // whether to look for credentials in the POST body in addition to the Authorize HTTP Header
|
||||
* 'allow_public_clients' => true // if true, "public clients" (clients without a secret) may be authenticated
|
||||
* );
|
||||
* </code>
|
||||
*/
|
||||
public function __construct(ClientCredentialsInterface $storage, array $config = array())
|
||||
{
|
||||
$this->storage = $storage;
|
||||
$this->config = array_merge(array(
|
||||
'allow_credentials_in_request_body' => true,
|
||||
'allow_public_clients' => true,
|
||||
), $config);
|
||||
}
|
||||
|
||||
public function validateRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (!$clientData = $this->getClientCredentials($request, $response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($clientData['client_id'])) {
|
||||
throw new \LogicException('the clientData array must have "client_id" set');
|
||||
}
|
||||
|
||||
if (!isset($clientData['client_secret']) || $clientData['client_secret'] == '') {
|
||||
if (!$this->config['allow_public_clients']) {
|
||||
$response->setError(400, 'invalid_client', 'client credentials are required');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->storage->isPublicClient($clientData['client_id'])) {
|
||||
$response->setError(400, 'invalid_client', 'This client is invalid or must authenticate using a client secret');
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif ($this->storage->checkClientCredentials($clientData['client_id'], $clientData['client_secret']) === false) {
|
||||
$response->setError(400, 'invalid_client', 'The client credentials are invalid');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->clientData = $clientData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getClientId()
|
||||
{
|
||||
return $this->clientData['client_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function used to get the client credentials from HTTP basic
|
||||
* auth or POST data.
|
||||
*
|
||||
* According to the spec (draft 20), the client_id can be provided in
|
||||
* the Basic Authorization header (recommended) or via GET/POST.
|
||||
*
|
||||
* @return
|
||||
* A list containing the client identifier and password, for example
|
||||
* @code
|
||||
* return array(
|
||||
* "client_id" => CLIENT_ID, // REQUIRED the client id
|
||||
* "client_secret" => CLIENT_SECRET, // OPTIONAL the client secret (may be omitted for public clients)
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-2.3.1
|
||||
*
|
||||
* @ingroup oauth2_section_2
|
||||
*/
|
||||
public function getClientCredentials(RequestInterface $request, ResponseInterface $response = null)
|
||||
{
|
||||
if (!is_null($request->headers('PHP_AUTH_USER')) && !is_null($request->headers('PHP_AUTH_PW'))) {
|
||||
return array('client_id' => $request->headers('PHP_AUTH_USER'), 'client_secret' => $request->headers('PHP_AUTH_PW'));
|
||||
}
|
||||
|
||||
if ($this->config['allow_credentials_in_request_body']) {
|
||||
// Using POST for HttpBasic authorization is not recommended, but is supported by specification
|
||||
if (!is_null($request->request('client_id'))) {
|
||||
/**
|
||||
* client_secret can be null if the client's password is an empty string
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-2.3.1
|
||||
*/
|
||||
|
||||
return array('client_id' => $request->request('client_id'), 'client_secret' => $request->request('client_secret'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($response) {
|
||||
$message = $this->config['allow_credentials_in_request_body'] ? ' or body' : '';
|
||||
$response->setError(400, 'invalid_client', 'Client credentials were not found in the headers'.$message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
383
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/AuthorizeController.php
vendored
Normal file
383
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/AuthorizeController.php
vendored
Normal file
|
@ -0,0 +1,383 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Controller;
|
||||
|
||||
use OAuth2\Storage\ClientInterface;
|
||||
use OAuth2\ScopeInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
use OAuth2\Scope;
|
||||
|
||||
/**
|
||||
* @see OAuth2\Controller\AuthorizeControllerInterface
|
||||
*/
|
||||
class AuthorizeController implements AuthorizeControllerInterface
|
||||
{
|
||||
private $scope;
|
||||
private $state;
|
||||
private $client_id;
|
||||
private $redirect_uri;
|
||||
private $response_type;
|
||||
|
||||
protected $clientStorage;
|
||||
protected $responseTypes;
|
||||
protected $config;
|
||||
protected $scopeUtil;
|
||||
|
||||
/**
|
||||
* @param OAuth2\Storage\ClientInterface $clientStorage REQUIRED Instance of OAuth2\Storage\ClientInterface to retrieve client information
|
||||
* @param array $responseTypes OPTIONAL Array of OAuth2\ResponseType\ResponseTypeInterface objects. Valid array
|
||||
* keys are "code" and "token"
|
||||
* @param array $config OPTIONAL Configuration options for the server
|
||||
* <code>
|
||||
* $config = array(
|
||||
* 'allow_implicit' => false, // if the controller should allow the "implicit" grant type
|
||||
* 'enforce_state' => true // if the controller should require the "state" parameter
|
||||
* 'require_exact_redirect_uri' => true, // if the controller should require an exact match on the "redirect_uri" parameter
|
||||
* 'redirect_status_code' => 302, // HTTP status code to use for redirect responses
|
||||
* );
|
||||
* </code>
|
||||
* @param OAuth2\ScopeInterface $scopeUtil OPTIONAL Instance of OAuth2\ScopeInterface to validate the requested scope
|
||||
*/
|
||||
public function __construct(ClientInterface $clientStorage, array $responseTypes = array(), array $config = array(), ScopeInterface $scopeUtil = null)
|
||||
{
|
||||
$this->clientStorage = $clientStorage;
|
||||
$this->responseTypes = $responseTypes;
|
||||
$this->config = array_merge(array(
|
||||
'allow_implicit' => false,
|
||||
'enforce_state' => true,
|
||||
'require_exact_redirect_uri' => true,
|
||||
'redirect_status_code' => 302,
|
||||
), $config);
|
||||
|
||||
if (is_null($scopeUtil)) {
|
||||
$scopeUtil = new Scope();
|
||||
}
|
||||
$this->scopeUtil = $scopeUtil;
|
||||
}
|
||||
|
||||
public function handleAuthorizeRequest(RequestInterface $request, ResponseInterface $response, $is_authorized, $user_id = null)
|
||||
{
|
||||
if (!is_bool($is_authorized)) {
|
||||
throw new \InvalidArgumentException('Argument "is_authorized" must be a boolean. This method must know if the user has granted access to the client.');
|
||||
}
|
||||
|
||||
// We repeat this, because we need to re-validate. The request could be POSTed
|
||||
// by a 3rd-party (because we are not internally enforcing NONCEs, etc)
|
||||
if (!$this->validateAuthorizeRequest($request, $response)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If no redirect_uri is passed in the request, use client's registered one
|
||||
if (empty($this->redirect_uri)) {
|
||||
$clientData = $this->clientStorage->getClientDetails($this->client_id);
|
||||
$registered_redirect_uri = $clientData['redirect_uri'];
|
||||
}
|
||||
|
||||
// the user declined access to the client's application
|
||||
if ($is_authorized === false) {
|
||||
$redirect_uri = $this->redirect_uri ?: $registered_redirect_uri;
|
||||
$this->setNotAuthorizedResponse($request, $response, $redirect_uri, $user_id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// build the parameters to set in the redirect URI
|
||||
if (!$params = $this->buildAuthorizeParameters($request, $response, $user_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$authResult = $this->responseTypes[$this->response_type]->getAuthorizeResponse($params, $user_id);
|
||||
|
||||
list($redirect_uri, $uri_params) = $authResult;
|
||||
|
||||
if (empty($redirect_uri) && !empty($registered_redirect_uri)) {
|
||||
$redirect_uri = $registered_redirect_uri;
|
||||
}
|
||||
|
||||
$uri = $this->buildUri($redirect_uri, $uri_params);
|
||||
|
||||
// return redirect response
|
||||
$response->setRedirect($this->config['redirect_status_code'], $uri);
|
||||
}
|
||||
|
||||
protected function setNotAuthorizedResponse(RequestInterface $request, ResponseInterface $response, $redirect_uri, $user_id = null)
|
||||
{
|
||||
$error = 'access_denied';
|
||||
$error_message = 'The user denied access to your application';
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $this->state, $error, $error_message);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have made this protected so this class can be extended to add/modify
|
||||
* these parameters
|
||||
*/
|
||||
protected function buildAuthorizeParameters($request, $response, $user_id)
|
||||
{
|
||||
// @TODO: we should be explicit with this in the future
|
||||
$params = array(
|
||||
'scope' => $this->scope,
|
||||
'state' => $this->state,
|
||||
'client_id' => $this->client_id,
|
||||
'redirect_uri' => $this->redirect_uri,
|
||||
'response_type' => $this->response_type,
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
public function validateAuthorizeRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
// Make sure a valid client id was supplied (we can not redirect because we were unable to verify the URI)
|
||||
if (!$client_id = $request->query('client_id', $request->request('client_id'))) {
|
||||
// We don't have a good URI to use
|
||||
$response->setError(400, 'invalid_client', "No client id supplied");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get client details
|
||||
if (!$clientData = $this->clientStorage->getClientDetails($client_id)) {
|
||||
$response->setError(400, 'invalid_client', 'The client id supplied is invalid');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$registered_redirect_uri = isset($clientData['redirect_uri']) ? $clientData['redirect_uri'] : '';
|
||||
|
||||
// Make sure a valid redirect_uri was supplied. If specified, it must match the clientData URI.
|
||||
// @see http://tools.ietf.org/html/rfc6749#section-3.1.2
|
||||
// @see http://tools.ietf.org/html/rfc6749#section-4.1.2.1
|
||||
// @see http://tools.ietf.org/html/rfc6749#section-4.2.2.1
|
||||
if ($supplied_redirect_uri = $request->query('redirect_uri', $request->request('redirect_uri'))) {
|
||||
// validate there is no fragment supplied
|
||||
$parts = parse_url($supplied_redirect_uri);
|
||||
if (isset($parts['fragment']) && $parts['fragment']) {
|
||||
$response->setError(400, 'invalid_uri', 'The redirect URI must not contain a fragment');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate against the registered redirect uri(s) if available
|
||||
if ($registered_redirect_uri && !$this->validateRedirectUri($supplied_redirect_uri, $registered_redirect_uri)) {
|
||||
$response->setError(400, 'redirect_uri_mismatch', 'The redirect URI provided is missing or does not match', '#section-3.1.2');
|
||||
|
||||
return false;
|
||||
}
|
||||
$redirect_uri = $supplied_redirect_uri;
|
||||
} else {
|
||||
// use the registered redirect_uri if none has been supplied, if possible
|
||||
if (!$registered_redirect_uri) {
|
||||
$response->setError(400, 'invalid_uri', 'No redirect URI was supplied or stored');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count(explode(' ', $registered_redirect_uri)) > 1) {
|
||||
$response->setError(400, 'invalid_uri', 'A redirect URI must be supplied when multiple redirect URIs are registered', '#section-3.1.2.3');
|
||||
|
||||
return false;
|
||||
}
|
||||
$redirect_uri = $registered_redirect_uri;
|
||||
}
|
||||
|
||||
// Select the redirect URI
|
||||
$response_type = $request->query('response_type', $request->request('response_type'));
|
||||
|
||||
// for multiple-valued response types - make them alphabetical
|
||||
if (false !== strpos($response_type, ' ')) {
|
||||
$types = explode(' ', $response_type);
|
||||
sort($types);
|
||||
$response_type = ltrim(implode(' ', $types));
|
||||
}
|
||||
|
||||
$state = $request->query('state', $request->request('state'));
|
||||
|
||||
// type and client_id are required
|
||||
if (!$response_type || !in_array($response_type, $this->getValidResponseTypes())) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'invalid_request', 'Invalid or missing response type', null);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($response_type == self::RESPONSE_TYPE_AUTHORIZATION_CODE) {
|
||||
if (!isset($this->responseTypes['code'])) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unsupported_response_type', 'authorization code grant type not supported', null);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!$this->clientStorage->checkRestrictedGrantType($client_id, 'authorization_code')) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unauthorized_client', 'The grant type is unauthorized for this client_id', null);
|
||||
|
||||
return false;
|
||||
}
|
||||
if ($this->responseTypes['code']->enforceRedirect() && !$redirect_uri) {
|
||||
$response->setError(400, 'redirect_uri_mismatch', 'The redirect URI is mandatory and was not supplied');
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!$this->config['allow_implicit']) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unsupported_response_type', 'implicit grant type not supported', null);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!$this->clientStorage->checkRestrictedGrantType($client_id, 'implicit')) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'unauthorized_client', 'The grant type is unauthorized for this client_id', null);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// validate requested scope if it exists
|
||||
$requestedScope = $this->scopeUtil->getScopeFromRequest($request);
|
||||
|
||||
if ($requestedScope) {
|
||||
// restrict scope by client specific scope if applicable,
|
||||
// otherwise verify the scope exists
|
||||
$clientScope = $this->clientStorage->getClientScope($client_id);
|
||||
if ((is_null($clientScope) && !$this->scopeUtil->scopeExists($requestedScope))
|
||||
|| ($clientScope && !$this->scopeUtil->checkScope($requestedScope, $clientScope))) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'invalid_scope', 'An unsupported scope was requested', null);
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// use a globally-defined default scope
|
||||
$defaultScope = $this->scopeUtil->getDefaultScope($client_id);
|
||||
|
||||
if (false === $defaultScope) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $state, 'invalid_client', 'This application requires you specify a scope parameter', null);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$requestedScope = $defaultScope;
|
||||
}
|
||||
|
||||
// Validate state parameter exists (if configured to enforce this)
|
||||
if ($this->config['enforce_state'] && !$state) {
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, null, 'invalid_request', 'The state parameter is required');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// save the input data and return true
|
||||
$this->scope = $requestedScope;
|
||||
$this->state = $state;
|
||||
$this->client_id = $client_id;
|
||||
// Only save the SUPPLIED redirect URI (@see http://tools.ietf.org/html/rfc6749#section-4.1.3)
|
||||
$this->redirect_uri = $supplied_redirect_uri;
|
||||
$this->response_type = $response_type;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the absolute URI based on supplied URI and parameters.
|
||||
*
|
||||
* @param $uri An absolute URI.
|
||||
* @param $params Parameters to be append as GET.
|
||||
*
|
||||
* @return
|
||||
* An absolute URI with supplied parameters.
|
||||
*
|
||||
* @ingroup oauth2_section_4
|
||||
*/
|
||||
private function buildUri($uri, $params)
|
||||
{
|
||||
$parse_url = parse_url($uri);
|
||||
|
||||
// Add our params to the parsed uri
|
||||
foreach ($params as $k => $v) {
|
||||
if (isset($parse_url[$k])) {
|
||||
$parse_url[$k] .= "&" . http_build_query($v, '', '&');
|
||||
} else {
|
||||
$parse_url[$k] = http_build_query($v, '', '&');
|
||||
}
|
||||
}
|
||||
|
||||
// Put humpty dumpty back together
|
||||
return
|
||||
((isset($parse_url["scheme"])) ? $parse_url["scheme"] . "://" : "")
|
||||
. ((isset($parse_url["user"])) ? $parse_url["user"]
|
||||
. ((isset($parse_url["pass"])) ? ":" . $parse_url["pass"] : "") . "@" : "")
|
||||
. ((isset($parse_url["host"])) ? $parse_url["host"] : "")
|
||||
. ((isset($parse_url["port"])) ? ":" . $parse_url["port"] : "")
|
||||
. ((isset($parse_url["path"])) ? $parse_url["path"] : "")
|
||||
. ((isset($parse_url["query"]) && !empty($parse_url['query'])) ? "?" . $parse_url["query"] : "")
|
||||
. ((isset($parse_url["fragment"])) ? "#" . $parse_url["fragment"] : "")
|
||||
;
|
||||
}
|
||||
|
||||
protected function getValidResponseTypes()
|
||||
{
|
||||
return array(
|
||||
self::RESPONSE_TYPE_ACCESS_TOKEN,
|
||||
self::RESPONSE_TYPE_AUTHORIZATION_CODE,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method for validating redirect URI supplied
|
||||
*
|
||||
* @param string $inputUri The submitted URI to be validated
|
||||
* @param string $registeredUriString The allowed URI(s) to validate against. Can be a space-delimited string of URIs to
|
||||
* allow for multiple URIs
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-3.1.2
|
||||
*/
|
||||
protected function validateRedirectUri($inputUri, $registeredUriString)
|
||||
{
|
||||
if (!$inputUri || !$registeredUriString) {
|
||||
return false; // if either one is missing, assume INVALID
|
||||
}
|
||||
|
||||
$registered_uris = preg_split('/\s+/', $registeredUriString);
|
||||
foreach ($registered_uris as $registered_uri) {
|
||||
if ($this->config['require_exact_redirect_uri']) {
|
||||
// the input uri is validated against the registered uri using exact match
|
||||
if (strcmp($inputUri, $registered_uri) === 0) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// the input uri is validated against the registered uri using case-insensitive match of the initial string
|
||||
// i.e. additional query parameters may be applied
|
||||
if (strcasecmp(substr($inputUri, 0, strlen($registered_uri)), $registered_uri) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience methods to access the parameters derived from the validated request
|
||||
*/
|
||||
|
||||
public function getScope()
|
||||
{
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
public function getState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
public function getClientId()
|
||||
{
|
||||
return $this->client_id;
|
||||
}
|
||||
|
||||
public function getRedirectUri()
|
||||
{
|
||||
return $this->redirect_uri;
|
||||
}
|
||||
|
||||
public function getResponseType()
|
||||
{
|
||||
return $this->response_type;
|
||||
}
|
||||
}
|
43
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/AuthorizeControllerInterface.php
vendored
Normal file
43
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/AuthorizeControllerInterface.php
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Controller;
|
||||
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* This controller is called when a user should be authorized
|
||||
* by an authorization server. As OAuth2 does not handle
|
||||
* authorization directly, this controller ensures the request is valid, but
|
||||
* requires the application to determine the value of $is_authorized
|
||||
*
|
||||
* ex:
|
||||
* > $user_id = $this->somehowDetermineUserId();
|
||||
* > $is_authorized = $this->somehowDetermineUserAuthorization();
|
||||
* > $response = new OAuth2\Response();
|
||||
* > $authorizeController->handleAuthorizeRequest(
|
||||
* > OAuth2\Request::createFromGlobals(),
|
||||
* > $response,
|
||||
* > $is_authorized,
|
||||
* > $user_id);
|
||||
* > $response->send();
|
||||
*
|
||||
*/
|
||||
interface AuthorizeControllerInterface
|
||||
{
|
||||
/**
|
||||
* List of possible authentication response types.
|
||||
* The "authorization_code" mechanism exclusively supports 'code'
|
||||
* and the "implicit" mechanism exclusively supports 'token'.
|
||||
*
|
||||
* @var string
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4.1.1
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4.2.1
|
||||
*/
|
||||
const RESPONSE_TYPE_AUTHORIZATION_CODE = 'code';
|
||||
const RESPONSE_TYPE_ACCESS_TOKEN = 'token';
|
||||
|
||||
public function handleAuthorizeRequest(RequestInterface $request, ResponseInterface $response, $is_authorized, $user_id = null);
|
||||
|
||||
public function validateAuthorizeRequest(RequestInterface $request, ResponseInterface $response);
|
||||
}
|
111
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/ResourceController.php
vendored
Normal file
111
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/ResourceController.php
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Controller;
|
||||
|
||||
use OAuth2\TokenType\TokenTypeInterface;
|
||||
use OAuth2\Storage\AccessTokenInterface;
|
||||
use OAuth2\ScopeInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
use OAuth2\Scope;
|
||||
|
||||
/**
|
||||
* @see OAuth2\Controller\ResourceControllerInterface
|
||||
*/
|
||||
class ResourceController implements ResourceControllerInterface
|
||||
{
|
||||
private $token;
|
||||
|
||||
protected $tokenType;
|
||||
protected $tokenStorage;
|
||||
protected $config;
|
||||
protected $scopeUtil;
|
||||
|
||||
public function __construct(TokenTypeInterface $tokenType, AccessTokenInterface $tokenStorage, $config = array(), ScopeInterface $scopeUtil = null)
|
||||
{
|
||||
$this->tokenType = $tokenType;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
|
||||
$this->config = array_merge(array(
|
||||
'www_realm' => 'Service',
|
||||
), $config);
|
||||
|
||||
if (is_null($scopeUtil)) {
|
||||
$scopeUtil = new Scope();
|
||||
}
|
||||
$this->scopeUtil = $scopeUtil;
|
||||
}
|
||||
|
||||
public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, $scope = null)
|
||||
{
|
||||
$token = $this->getAccessTokenData($request, $response);
|
||||
|
||||
// Check if we have token data
|
||||
if (is_null($token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check scope, if provided
|
||||
* If token doesn't have a scope, it's null/empty, or it's insufficient, then throw 403
|
||||
* @see http://tools.ietf.org/html/rfc6750#section-3.1
|
||||
*/
|
||||
if ($scope && (!isset($token["scope"]) || !$token["scope"] || !$this->scopeUtil->checkScope($scope, $token["scope"]))) {
|
||||
$response->setError(403, 'insufficient_scope', 'The request requires higher privileges than provided by the access token');
|
||||
$response->addHttpHeaders(array(
|
||||
'WWW-Authenticate' => sprintf('%s realm="%s", scope="%s", error="%s", error_description="%s"',
|
||||
$this->tokenType->getTokenType(),
|
||||
$this->config['www_realm'],
|
||||
$scope,
|
||||
$response->getParameter('error'),
|
||||
$response->getParameter('error_description')
|
||||
)
|
||||
));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// allow retrieval of the token
|
||||
$this->token = $token;
|
||||
|
||||
return (bool) $token;
|
||||
}
|
||||
|
||||
public function getAccessTokenData(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
// Get the token parameter
|
||||
if ($token_param = $this->tokenType->getAccessTokenParameter($request, $response)) {
|
||||
// Get the stored token data (from the implementing subclass)
|
||||
// Check we have a well formed token
|
||||
// Check token expiration (expires is a mandatory paramter)
|
||||
if (!$token = $this->tokenStorage->getAccessToken($token_param)) {
|
||||
$response->setError(401, 'invalid_token', 'The access token provided is invalid');
|
||||
} elseif (!isset($token["expires"]) || !isset($token["client_id"])) {
|
||||
$response->setError(401, 'malformed_token', 'Malformed token (missing "expires")');
|
||||
} elseif (time() > $token["expires"]) {
|
||||
$response->setError(401, 'expired_token', 'The access token provided has expired');
|
||||
} else {
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
$authHeader = sprintf('%s realm="%s"', $this->tokenType->getTokenType(), $this->config['www_realm']);
|
||||
|
||||
if ($error = $response->getParameter('error')) {
|
||||
$authHeader = sprintf('%s, error="%s"', $authHeader, $error);
|
||||
if ($error_description = $response->getParameter('error_description')) {
|
||||
$authHeader = sprintf('%s, error_description="%s"', $authHeader, $error_description);
|
||||
}
|
||||
}
|
||||
|
||||
$response->addHttpHeaders(array('WWW-Authenticate' => $authHeader));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// convenience method to allow retrieval of the token
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
}
|
26
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/ResourceControllerInterface.php
vendored
Normal file
26
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/ResourceControllerInterface.php
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Controller;
|
||||
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* This controller is called when a "resource" is requested.
|
||||
* call verifyResourceRequest in order to determine if the request
|
||||
* contains a valid token.
|
||||
*
|
||||
* ex:
|
||||
* > if (!$resourceController->verifyResourceRequest(OAuth2\Request::createFromGlobals(), $response = new OAuth2\Response())) {
|
||||
* > $response->send(); // authorization failed
|
||||
* > die();
|
||||
* > }
|
||||
* > return json_encode($resource); // valid token! Send the stuff!
|
||||
*
|
||||
*/
|
||||
interface ResourceControllerInterface
|
||||
{
|
||||
public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, $scope = null);
|
||||
|
||||
public function getAccessTokenData(RequestInterface $request, ResponseInterface $response);
|
||||
}
|
274
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/TokenController.php
vendored
Normal file
274
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/TokenController.php
vendored
Normal file
|
@ -0,0 +1,274 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Controller;
|
||||
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
use OAuth2\ClientAssertionType\ClientAssertionTypeInterface;
|
||||
use OAuth2\GrantType\GrantTypeInterface;
|
||||
use OAuth2\ScopeInterface;
|
||||
use OAuth2\Scope;
|
||||
use OAuth2\Storage\ClientInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @see OAuth2\Controller\TokenControllerInterface
|
||||
*/
|
||||
class TokenController implements TokenControllerInterface
|
||||
{
|
||||
protected $accessToken;
|
||||
protected $grantTypes;
|
||||
protected $clientAssertionType;
|
||||
protected $scopeUtil;
|
||||
protected $clientStorage;
|
||||
|
||||
public function __construct(AccessTokenInterface $accessToken, ClientInterface $clientStorage, array $grantTypes = array(), ClientAssertionTypeInterface $clientAssertionType = null, ScopeInterface $scopeUtil = null)
|
||||
{
|
||||
if (is_null($clientAssertionType)) {
|
||||
foreach ($grantTypes as $grantType) {
|
||||
if (!$grantType instanceof ClientAssertionTypeInterface) {
|
||||
throw new \InvalidArgumentException('You must supply an instance of OAuth2\ClientAssertionType\ClientAssertionTypeInterface or only use grant types which implement OAuth2\ClientAssertionType\ClientAssertionTypeInterface');
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->clientAssertionType = $clientAssertionType;
|
||||
$this->accessToken = $accessToken;
|
||||
$this->clientStorage = $clientStorage;
|
||||
foreach ($grantTypes as $grantType) {
|
||||
$this->addGrantType($grantType);
|
||||
}
|
||||
|
||||
if (is_null($scopeUtil)) {
|
||||
$scopeUtil = new Scope();
|
||||
}
|
||||
$this->scopeUtil = $scopeUtil;
|
||||
}
|
||||
|
||||
public function handleTokenRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if ($token = $this->grantAccessToken($request, $response)) {
|
||||
// @see http://tools.ietf.org/html/rfc6749#section-5.1
|
||||
// server MUST disable caching in headers when tokens are involved
|
||||
$response->setStatusCode(200);
|
||||
$response->addParameters($token);
|
||||
$response->addHttpHeaders(array('Cache-Control' => 'no-store', 'Pragma' => 'no-cache'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant or deny a requested access token.
|
||||
* This would be called from the "/token" endpoint as defined in the spec.
|
||||
* You can call your endpoint whatever you want.
|
||||
*
|
||||
* @param $request - RequestInterface
|
||||
* Request object to grant access token
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws LogicException
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-10.6
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4.1.3
|
||||
*
|
||||
* @ingroup oauth2_section_4
|
||||
*/
|
||||
public function grantAccessToken(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (strtolower($request->server('REQUEST_METHOD')) != 'post') {
|
||||
$response->setError(405, 'invalid_request', 'The request method must be POST when requesting an access token', '#section-3.2');
|
||||
$response->addHttpHeaders(array('Allow' => 'POST'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine grant type from request
|
||||
* and validate the request for that grant type
|
||||
*/
|
||||
if (!$grantTypeIdentifier = $request->request('grant_type')) {
|
||||
$response->setError(400, 'invalid_request', 'The grant type was not specified in the request');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isset($this->grantTypes[$grantTypeIdentifier])) {
|
||||
/* TODO: If this is an OAuth2 supported grant type that we have chosen not to implement, throw a 501 Not Implemented instead */
|
||||
$response->setError(400, 'unsupported_grant_type', sprintf('Grant type "%s" not supported', $grantTypeIdentifier));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$grantType = $this->grantTypes[$grantTypeIdentifier];
|
||||
|
||||
/**
|
||||
* Retrieve the client information from the request
|
||||
* ClientAssertionTypes allow for grant types which also assert the client data
|
||||
* in which case ClientAssertion is handled in the validateRequest method
|
||||
*
|
||||
* @see OAuth2\GrantType\JWTBearer
|
||||
* @see OAuth2\GrantType\ClientCredentials
|
||||
*/
|
||||
if (!$grantType instanceof ClientAssertionTypeInterface) {
|
||||
if (!$this->clientAssertionType->validateRequest($request, $response)) {
|
||||
return null;
|
||||
}
|
||||
$clientId = $this->clientAssertionType->getClientId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the grant type information from the request
|
||||
* The GrantTypeInterface object handles all validation
|
||||
* If the object is an instance of ClientAssertionTypeInterface,
|
||||
* That logic is handled here as well
|
||||
*/
|
||||
if (!$grantType->validateRequest($request, $response)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($grantType instanceof ClientAssertionTypeInterface) {
|
||||
$clientId = $grantType->getClientId();
|
||||
} else {
|
||||
// validate the Client ID (if applicable)
|
||||
if (!is_null($storedClientId = $grantType->getClientId()) && $storedClientId != $clientId) {
|
||||
$response->setError(400, 'invalid_grant', sprintf('%s doesn\'t exist or is invalid for the client', $grantTypeIdentifier));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the client can use the requested grant type
|
||||
*/
|
||||
if (!$this->clientStorage->checkRestrictedGrantType($clientId, $grantTypeIdentifier)) {
|
||||
$response->setError(400, 'unauthorized_client', 'The grant type is unauthorized for this client_id');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the scope of the token
|
||||
*
|
||||
* requestedScope - the scope specified in the token request
|
||||
* availableScope - the scope associated with the grant type
|
||||
* ex: in the case of the "Authorization Code" grant type,
|
||||
* the scope is specified in the authorize request
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-3.3
|
||||
*/
|
||||
|
||||
$requestedScope = $this->scopeUtil->getScopeFromRequest($request);
|
||||
$availableScope = $grantType->getScope();
|
||||
|
||||
if ($requestedScope) {
|
||||
// validate the requested scope
|
||||
if ($availableScope) {
|
||||
if (!$this->scopeUtil->checkScope($requestedScope, $availableScope)) {
|
||||
$response->setError(400, 'invalid_scope', 'The scope requested is invalid for this request');
|
||||
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// validate the client has access to this scope
|
||||
if ($clientScope = $this->clientStorage->getClientScope($clientId)) {
|
||||
if (!$this->scopeUtil->checkScope($requestedScope, $clientScope)) {
|
||||
$response->setError(400, 'invalid_scope', 'The scope requested is invalid for this client');
|
||||
|
||||
return false;
|
||||
}
|
||||
} elseif (!$this->scopeUtil->scopeExists($requestedScope)) {
|
||||
$response->setError(400, 'invalid_scope', 'An unsupported scope was requested');
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} elseif ($availableScope) {
|
||||
// use the scope associated with this grant type
|
||||
$requestedScope = $availableScope;
|
||||
} else {
|
||||
// use a globally-defined default scope
|
||||
$defaultScope = $this->scopeUtil->getDefaultScope($clientId);
|
||||
|
||||
// "false" means default scopes are not allowed
|
||||
if (false === $defaultScope) {
|
||||
$response->setError(400, 'invalid_scope', 'This application requires you specify a scope parameter');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$requestedScope = $defaultScope;
|
||||
}
|
||||
|
||||
return $grantType->createAccessToken($this->accessToken, $clientId, $grantType->getUserId(), $requestedScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* addGrantType
|
||||
*
|
||||
* @param grantType - OAuth2\GrantTypeInterface
|
||||
* the grant type to add for the specified identifier
|
||||
* @param identifier - string
|
||||
* a string passed in as "grant_type" in the response that will call this grantType
|
||||
*/
|
||||
public function addGrantType(GrantTypeInterface $grantType, $identifier = null)
|
||||
{
|
||||
if (is_null($identifier) || is_numeric($identifier)) {
|
||||
$identifier = $grantType->getQuerystringIdentifier();
|
||||
}
|
||||
|
||||
$this->grantTypes[$identifier] = $grantType;
|
||||
}
|
||||
|
||||
public function handleRevokeRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if ($this->revokeToken($request, $response)) {
|
||||
$response->setStatusCode(200);
|
||||
$response->addParameters(array('revoked' => true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke a refresh or access token. Returns true on success and when tokens are invalid
|
||||
*
|
||||
* Note: invalid tokens do not cause an error response since the client
|
||||
* cannot handle such an error in a reasonable way. Moreover, the
|
||||
* purpose of the revocation request, invalidating the particular token,
|
||||
* is already achieved.
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @return bool|null
|
||||
*/
|
||||
public function revokeToken(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (strtolower($request->server('REQUEST_METHOD')) != 'post') {
|
||||
$response->setError(405, 'invalid_request', 'The request method must be POST when revoking an access token', '#section-3.2');
|
||||
$response->addHttpHeaders(array('Allow' => 'POST'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$token_type_hint = $request->request('token_type_hint');
|
||||
if (!in_array($token_type_hint, array(null, 'access_token', 'refresh_token'), true)) {
|
||||
$response->setError(400, 'invalid_request', 'Token type hint must be either \'access_token\' or \'refresh_token\'');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$token = $request->request('token');
|
||||
if ($token === null) {
|
||||
$response->setError(400, 'invalid_request', 'Missing token parameter to revoke');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// @todo remove this check for v2.0
|
||||
if (!method_exists($this->accessToken, 'revokeToken')) {
|
||||
$class = get_class($this->accessToken);
|
||||
throw new \RuntimeException("AccessToken {$class} does not implement required revokeToken method");
|
||||
}
|
||||
|
||||
$this->accessToken->revokeToken($token, $token_type_hint);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
32
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/TokenControllerInterface.php
vendored
Normal file
32
vendor/bshaffer/oauth2-server-php/src/OAuth2/Controller/TokenControllerInterface.php
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Controller;
|
||||
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* This controller is called when a token is being requested.
|
||||
* it is called to handle all grant types the application supports.
|
||||
* It also validates the client's credentials
|
||||
*
|
||||
* ex:
|
||||
* > $tokenController->handleTokenRequest(OAuth2\Request::createFromGlobals(), $response = new OAuth2\Response());
|
||||
* > $response->send();
|
||||
*
|
||||
*/
|
||||
interface TokenControllerInterface
|
||||
{
|
||||
/**
|
||||
* handleTokenRequest
|
||||
*
|
||||
* @param $request
|
||||
* OAuth2\RequestInterface - The current http request
|
||||
* @param $response
|
||||
* OAuth2\ResponseInterface - An instance of OAuth2\ResponseInterface to contain the response data
|
||||
*
|
||||
*/
|
||||
public function handleTokenRequest(RequestInterface $request, ResponseInterface $response);
|
||||
|
||||
public function grantAccessToken(RequestInterface $request, ResponseInterface $response);
|
||||
}
|
11
vendor/bshaffer/oauth2-server-php/src/OAuth2/Encryption/EncryptionInterface.php
vendored
Normal file
11
vendor/bshaffer/oauth2-server-php/src/OAuth2/Encryption/EncryptionInterface.php
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Encryption;
|
||||
|
||||
interface EncryptionInterface
|
||||
{
|
||||
public function encode($payload, $key, $algorithm = null);
|
||||
public function decode($payload, $key, $algorithm = null);
|
||||
public function urlSafeB64Encode($data);
|
||||
public function urlSafeB64Decode($b64);
|
||||
}
|
47
vendor/bshaffer/oauth2-server-php/src/OAuth2/Encryption/FirebaseJwt.php
vendored
Normal file
47
vendor/bshaffer/oauth2-server-php/src/OAuth2/Encryption/FirebaseJwt.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Encryption;
|
||||
|
||||
/**
|
||||
* Bridge file to use the firebase/php-jwt package for JWT encoding and decoding.
|
||||
* @author Francis Chuang <francis.chuang@gmail.com>
|
||||
*/
|
||||
class FirebaseJwt implements EncryptionInterface
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (!class_exists('\JWT')) {
|
||||
throw new \ErrorException('firebase/php-jwt must be installed to use this feature. You can do this by running "composer require firebase/php-jwt"');
|
||||
}
|
||||
}
|
||||
|
||||
public function encode($payload, $key, $alg = 'HS256', $keyId = null)
|
||||
{
|
||||
return \JWT::encode($payload, $key, $alg, $keyId);
|
||||
}
|
||||
|
||||
public function decode($jwt, $key = null, $allowedAlgorithms = null)
|
||||
{
|
||||
try {
|
||||
|
||||
//Maintain BC: Do not verify if no algorithms are passed in.
|
||||
if (!$allowedAlgorithms) {
|
||||
$key = null;
|
||||
}
|
||||
|
||||
return (array)\JWT::decode($jwt, $key, $allowedAlgorithms);
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function urlSafeB64Encode($data)
|
||||
{
|
||||
return \JWT::urlsafeB64Encode($data);
|
||||
}
|
||||
|
||||
public function urlSafeB64Decode($b64)
|
||||
{
|
||||
return \JWT::urlsafeB64Decode($b64);
|
||||
}
|
||||
}
|
173
vendor/bshaffer/oauth2-server-php/src/OAuth2/Encryption/Jwt.php
vendored
Normal file
173
vendor/bshaffer/oauth2-server-php/src/OAuth2/Encryption/Jwt.php
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\Encryption;
|
||||
|
||||
/**
|
||||
* @link https://github.com/F21/jwt
|
||||
* @author F21
|
||||
*/
|
||||
class Jwt implements EncryptionInterface
|
||||
{
|
||||
public function encode($payload, $key, $algo = 'HS256')
|
||||
{
|
||||
$header = $this->generateJwtHeader($payload, $algo);
|
||||
|
||||
$segments = array(
|
||||
$this->urlSafeB64Encode(json_encode($header)),
|
||||
$this->urlSafeB64Encode(json_encode($payload))
|
||||
);
|
||||
|
||||
$signing_input = implode('.', $segments);
|
||||
|
||||
$signature = $this->sign($signing_input, $key, $algo);
|
||||
$segments[] = $this->urlsafeB64Encode($signature);
|
||||
|
||||
return implode('.', $segments);
|
||||
}
|
||||
|
||||
public function decode($jwt, $key = null, $allowedAlgorithms = true)
|
||||
{
|
||||
if (!strpos($jwt, '.')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tks = explode('.', $jwt);
|
||||
|
||||
if (count($tks) != 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
list($headb64, $payloadb64, $cryptob64) = $tks;
|
||||
|
||||
if (null === ($header = json_decode($this->urlSafeB64Decode($headb64), true))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null === $payload = json_decode($this->urlSafeB64Decode($payloadb64), true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sig = $this->urlSafeB64Decode($cryptob64);
|
||||
|
||||
if ((bool) $allowedAlgorithms) {
|
||||
if (!isset($header['alg'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if bool arg supplied here to maintain BC
|
||||
if (is_array($allowedAlgorithms) && !in_array($header['alg'], $allowedAlgorithms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->verifySignature($sig, "$headb64.$payloadb64", $key, $header['alg'])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
private function verifySignature($signature, $input, $key, $algo = 'HS256')
|
||||
{
|
||||
// use constants when possible, for HipHop support
|
||||
switch ($algo) {
|
||||
case'HS256':
|
||||
case'HS384':
|
||||
case'HS512':
|
||||
return $this->hash_equals(
|
||||
$this->sign($input, $key, $algo),
|
||||
$signature
|
||||
);
|
||||
|
||||
case 'RS256':
|
||||
return openssl_verify($input, $signature, $key, defined('OPENSSL_ALGO_SHA256') ? OPENSSL_ALGO_SHA256 : 'sha256') === 1;
|
||||
|
||||
case 'RS384':
|
||||
return @openssl_verify($input, $signature, $key, defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'sha384') === 1;
|
||||
|
||||
case 'RS512':
|
||||
return @openssl_verify($input, $signature, $key, defined('OPENSSL_ALGO_SHA512') ? OPENSSL_ALGO_SHA512 : 'sha512') === 1;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unsupported or invalid signing algorithm.");
|
||||
}
|
||||
}
|
||||
|
||||
private function sign($input, $key, $algo = 'HS256')
|
||||
{
|
||||
switch ($algo) {
|
||||
case 'HS256':
|
||||
return hash_hmac('sha256', $input, $key, true);
|
||||
|
||||
case 'HS384':
|
||||
return hash_hmac('sha384', $input, $key, true);
|
||||
|
||||
case 'HS512':
|
||||
return hash_hmac('sha512', $input, $key, true);
|
||||
|
||||
case 'RS256':
|
||||
return $this->generateRSASignature($input, $key, defined('OPENSSL_ALGO_SHA256') ? OPENSSL_ALGO_SHA256 : 'sha256');
|
||||
|
||||
case 'RS384':
|
||||
return $this->generateRSASignature($input, $key, defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'sha384');
|
||||
|
||||
case 'RS512':
|
||||
return $this->generateRSASignature($input, $key, defined('OPENSSL_ALGO_SHA512') ? OPENSSL_ALGO_SHA512 : 'sha512');
|
||||
|
||||
default:
|
||||
throw new \Exception("Unsupported or invalid signing algorithm.");
|
||||
}
|
||||
}
|
||||
|
||||
private function generateRSASignature($input, $key, $algo)
|
||||
{
|
||||
if (!openssl_sign($input, $signature, $key, $algo)) {
|
||||
throw new \Exception("Unable to sign data.");
|
||||
}
|
||||
|
||||
return $signature;
|
||||
}
|
||||
|
||||
public function urlSafeB64Encode($data)
|
||||
{
|
||||
$b64 = base64_encode($data);
|
||||
$b64 = str_replace(array('+', '/', "\r", "\n", '='),
|
||||
array('-', '_'),
|
||||
$b64);
|
||||
|
||||
return $b64;
|
||||
}
|
||||
|
||||
public function urlSafeB64Decode($b64)
|
||||
{
|
||||
$b64 = str_replace(array('-', '_'),
|
||||
array('+', '/'),
|
||||
$b64);
|
||||
|
||||
return base64_decode($b64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to create a custom header
|
||||
*/
|
||||
protected function generateJwtHeader($payload, $algorithm)
|
||||
{
|
||||
return array(
|
||||
'typ' => 'JWT',
|
||||
'alg' => $algorithm,
|
||||
);
|
||||
}
|
||||
|
||||
protected function hash_equals($a, $b)
|
||||
{
|
||||
if (function_exists('hash_equals')) {
|
||||
return hash_equals($a, $b);
|
||||
}
|
||||
$diff = strlen($a) ^ strlen($b);
|
||||
for ($i = 0; $i < strlen($a) && $i < strlen($b); $i++) {
|
||||
$diff |= ord($a[$i]) ^ ord($b[$i]);
|
||||
}
|
||||
|
||||
return $diff === 0;
|
||||
}
|
||||
}
|
100
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/AuthorizationCode.php
vendored
Normal file
100
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/AuthorizationCode.php
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\GrantType;
|
||||
|
||||
use OAuth2\Storage\AuthorizationCodeInterface;
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
class AuthorizationCode implements GrantTypeInterface
|
||||
{
|
||||
protected $storage;
|
||||
protected $authCode;
|
||||
|
||||
/**
|
||||
* @param OAuth2\Storage\AuthorizationCodeInterface $storage REQUIRED Storage class for retrieving authorization code information
|
||||
*/
|
||||
public function __construct(AuthorizationCodeInterface $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
public function getQuerystringIdentifier()
|
||||
{
|
||||
return 'authorization_code';
|
||||
}
|
||||
|
||||
public function validateRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (!$request->request('code')) {
|
||||
$response->setError(400, 'invalid_request', 'Missing parameter: "code" is required');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$code = $request->request('code');
|
||||
if (!$authCode = $this->storage->getAuthorizationCode($code)) {
|
||||
$response->setError(400, 'invalid_grant', 'Authorization code doesn\'t exist or is invalid for the client');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* 4.1.3 - ensure that the "redirect_uri" parameter is present if the "redirect_uri" parameter was included in the initial authorization request
|
||||
* @uri - http://tools.ietf.org/html/rfc6749#section-4.1.3
|
||||
*/
|
||||
if (isset($authCode['redirect_uri']) && $authCode['redirect_uri']) {
|
||||
if (!$request->request('redirect_uri') || urldecode($request->request('redirect_uri')) != $authCode['redirect_uri']) {
|
||||
$response->setError(400, 'redirect_uri_mismatch', "The redirect URI is missing or do not match", "#section-4.1.3");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($authCode['expires'])) {
|
||||
throw new \Exception('Storage must return authcode with a value for "expires"');
|
||||
}
|
||||
|
||||
if ($authCode["expires"] < time()) {
|
||||
$response->setError(400, 'invalid_grant', "The authorization code has expired");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($authCode['code'])) {
|
||||
$authCode['code'] = $code; // used to expire the code after the access token is granted
|
||||
}
|
||||
|
||||
$this->authCode = $authCode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getClientId()
|
||||
{
|
||||
return $this->authCode['client_id'];
|
||||
}
|
||||
|
||||
public function getScope()
|
||||
{
|
||||
return isset($this->authCode['scope']) ? $this->authCode['scope'] : null;
|
||||
}
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return isset($this->authCode['user_id']) ? $this->authCode['user_id'] : null;
|
||||
}
|
||||
|
||||
public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope)
|
||||
{
|
||||
$token = $accessToken->createAccessToken($client_id, $user_id, $scope);
|
||||
$this->storage->expireAuthorizationCode($this->authCode['code']);
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
67
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/ClientCredentials.php
vendored
Normal file
67
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/ClientCredentials.php
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\GrantType;
|
||||
|
||||
use OAuth2\ClientAssertionType\HttpBasic;
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
use OAuth2\Storage\ClientCredentialsInterface;
|
||||
|
||||
/**
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*
|
||||
* @see OAuth2\ClientAssertionType_HttpBasic
|
||||
*/
|
||||
class ClientCredentials extends HttpBasic implements GrantTypeInterface
|
||||
{
|
||||
private $clientData;
|
||||
|
||||
public function __construct(ClientCredentialsInterface $storage, array $config = array())
|
||||
{
|
||||
/**
|
||||
* The client credentials grant type MUST only be used by confidential clients
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4.4
|
||||
*/
|
||||
$config['allow_public_clients'] = false;
|
||||
|
||||
parent::__construct($storage, $config);
|
||||
}
|
||||
|
||||
public function getQuerystringIdentifier()
|
||||
{
|
||||
return 'client_credentials';
|
||||
}
|
||||
|
||||
public function getScope()
|
||||
{
|
||||
$this->loadClientData();
|
||||
|
||||
return isset($this->clientData['scope']) ? $this->clientData['scope'] : null;
|
||||
}
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
$this->loadClientData();
|
||||
|
||||
return isset($this->clientData['user_id']) ? $this->clientData['user_id'] : null;
|
||||
}
|
||||
|
||||
public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope)
|
||||
{
|
||||
/**
|
||||
* Client Credentials Grant does NOT include a refresh token
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4.4.3
|
||||
*/
|
||||
$includeRefreshToken = false;
|
||||
|
||||
return $accessToken->createAccessToken($client_id, $user_id, $scope, $includeRefreshToken);
|
||||
}
|
||||
|
||||
private function loadClientData()
|
||||
{
|
||||
if (!$this->clientData) {
|
||||
$this->clientData = $this->storage->getClientDetails($this->getClientId());
|
||||
}
|
||||
}
|
||||
}
|
20
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/GrantTypeInterface.php
vendored
Normal file
20
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/GrantTypeInterface.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\GrantType;
|
||||
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Interface for all OAuth2 Grant Types
|
||||
*/
|
||||
interface GrantTypeInterface
|
||||
{
|
||||
public function getQuerystringIdentifier();
|
||||
public function validateRequest(RequestInterface $request, ResponseInterface $response);
|
||||
public function getClientId();
|
||||
public function getUserId();
|
||||
public function getScope();
|
||||
public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope);
|
||||
}
|
226
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/JwtBearer.php
vendored
Normal file
226
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/JwtBearer.php
vendored
Normal file
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\GrantType;
|
||||
|
||||
use OAuth2\ClientAssertionType\ClientAssertionTypeInterface;
|
||||
use OAuth2\Storage\JwtBearerInterface;
|
||||
use OAuth2\Encryption\Jwt;
|
||||
use OAuth2\Encryption\EncryptionInterface;
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* The JWT bearer authorization grant implements JWT (JSON Web Tokens) as a grant type per the IETF draft.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-04#section-4
|
||||
*
|
||||
* @author F21
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
class JwtBearer implements GrantTypeInterface, ClientAssertionTypeInterface
|
||||
{
|
||||
private $jwt;
|
||||
|
||||
protected $storage;
|
||||
protected $audience;
|
||||
protected $jwtUtil;
|
||||
protected $allowedAlgorithms;
|
||||
|
||||
/**
|
||||
* Creates an instance of the JWT bearer grant type.
|
||||
*
|
||||
* @param OAuth2\Storage\JWTBearerInterface|JwtBearerInterface $storage A valid storage interface that implements storage hooks for the JWT bearer grant type.
|
||||
* @param string $audience The audience to validate the token against. This is usually the full URI of the OAuth token requests endpoint.
|
||||
* @param EncryptionInterface|OAuth2\Encryption\JWT $jwtUtil OPTONAL The class used to decode, encode and verify JWTs.
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(JwtBearerInterface $storage, $audience, EncryptionInterface $jwtUtil = null, array $config = array())
|
||||
{
|
||||
$this->storage = $storage;
|
||||
$this->audience = $audience;
|
||||
|
||||
if (is_null($jwtUtil)) {
|
||||
$jwtUtil = new Jwt();
|
||||
}
|
||||
|
||||
$this->config = array_merge(array(
|
||||
'allowed_algorithms' => array('RS256', 'RS384', 'RS512')
|
||||
), $config);
|
||||
|
||||
$this->jwtUtil = $jwtUtil;
|
||||
|
||||
$this->allowedAlgorithms = $this->config['allowed_algorithms'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the grant_type get parameter to identify the grant type request as JWT bearer authorization grant.
|
||||
*
|
||||
* @return
|
||||
* The string identifier for grant_type.
|
||||
*
|
||||
* @see OAuth2\GrantType\GrantTypeInterface::getQuerystringIdentifier()
|
||||
*/
|
||||
public function getQuerystringIdentifier()
|
||||
{
|
||||
return 'urn:ietf:params:oauth:grant-type:jwt-bearer';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the data from the decoded JWT.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the JWT request is valid and can be decoded. Otherwise, FALSE is returned.
|
||||
*
|
||||
* @see OAuth2\GrantType\GrantTypeInterface::getTokenData()
|
||||
*/
|
||||
public function validateRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (!$request->request("assertion")) {
|
||||
$response->setError(400, 'invalid_request', 'Missing parameters: "assertion" required');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Store the undecoded JWT for later use
|
||||
$undecodedJWT = $request->request('assertion');
|
||||
|
||||
// Decode the JWT
|
||||
$jwt = $this->jwtUtil->decode($request->request('assertion'), null, false);
|
||||
|
||||
if (!$jwt) {
|
||||
$response->setError(400, 'invalid_request', "JWT is malformed");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// ensure these properties contain a value
|
||||
// @todo: throw malformed error for missing properties
|
||||
$jwt = array_merge(array(
|
||||
'scope' => null,
|
||||
'iss' => null,
|
||||
'sub' => null,
|
||||
'aud' => null,
|
||||
'exp' => null,
|
||||
'nbf' => null,
|
||||
'iat' => null,
|
||||
'jti' => null,
|
||||
'typ' => null,
|
||||
), $jwt);
|
||||
|
||||
if (!isset($jwt['iss'])) {
|
||||
$response->setError(400, 'invalid_grant', "Invalid issuer (iss) provided");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isset($jwt['sub'])) {
|
||||
$response->setError(400, 'invalid_grant', "Invalid subject (sub) provided");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isset($jwt['exp'])) {
|
||||
$response->setError(400, 'invalid_grant', "Expiration (exp) time must be present");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check expiration
|
||||
if (ctype_digit($jwt['exp'])) {
|
||||
if ($jwt['exp'] <= time()) {
|
||||
$response->setError(400, 'invalid_grant', "JWT has expired");
|
||||
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
$response->setError(400, 'invalid_grant', "Expiration (exp) time must be a unix time stamp");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check the not before time
|
||||
if ($notBefore = $jwt['nbf']) {
|
||||
if (ctype_digit($notBefore)) {
|
||||
if ($notBefore > time()) {
|
||||
$response->setError(400, 'invalid_grant', "JWT cannot be used before the Not Before (nbf) time");
|
||||
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
$response->setError(400, 'invalid_grant', "Not Before (nbf) time must be a unix time stamp");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the audience if required to match
|
||||
if (!isset($jwt['aud']) || ($jwt['aud'] != $this->audience)) {
|
||||
$response->setError(400, 'invalid_grant', "Invalid audience (aud)");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check the jti (nonce)
|
||||
// @see http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-13#section-4.1.7
|
||||
if (isset($jwt['jti'])) {
|
||||
$jti = $this->storage->getJti($jwt['iss'], $jwt['sub'], $jwt['aud'], $jwt['exp'], $jwt['jti']);
|
||||
|
||||
//Reject if jti is used and jwt is still valid (exp parameter has not expired).
|
||||
if ($jti && $jti['expires'] > time()) {
|
||||
$response->setError(400, 'invalid_grant', "JSON Token Identifier (jti) has already been used");
|
||||
|
||||
return null;
|
||||
} else {
|
||||
$this->storage->setJti($jwt['iss'], $jwt['sub'], $jwt['aud'], $jwt['exp'], $jwt['jti']);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the iss's public key
|
||||
// @see http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06#section-4.1.1
|
||||
if (!$key = $this->storage->getClientKey($jwt['iss'], $jwt['sub'])) {
|
||||
$response->setError(400, 'invalid_grant', "Invalid issuer (iss) or subject (sub) provided");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Verify the JWT
|
||||
if (!$this->jwtUtil->decode($undecodedJWT, $key, $this->allowedAlgorithms)) {
|
||||
$response->setError(400, 'invalid_grant', "JWT failed signature verification");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->jwt = $jwt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getClientId()
|
||||
{
|
||||
return $this->jwt['iss'];
|
||||
}
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->jwt['sub'];
|
||||
}
|
||||
|
||||
public function getScope()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an access token that is NOT associated with a refresh token.
|
||||
* If a subject (sub) the name of the user/account we are accessing data on behalf of.
|
||||
*
|
||||
* @see OAuth2\GrantType\GrantTypeInterface::createAccessToken()
|
||||
*/
|
||||
public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope)
|
||||
{
|
||||
$includeRefreshToken = false;
|
||||
|
||||
return $accessToken->createAccessToken($client_id, $user_id, $scope, $includeRefreshToken);
|
||||
}
|
||||
}
|
111
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/RefreshToken.php
vendored
Normal file
111
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/RefreshToken.php
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\GrantType;
|
||||
|
||||
use OAuth2\Storage\RefreshTokenInterface;
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
class RefreshToken implements GrantTypeInterface
|
||||
{
|
||||
private $refreshToken;
|
||||
|
||||
protected $storage;
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @param OAuth2\Storage\RefreshTokenInterface $storage REQUIRED Storage class for retrieving refresh token information
|
||||
* @param array $config OPTIONAL Configuration options for the server
|
||||
* <code>
|
||||
* $config = array(
|
||||
* 'always_issue_new_refresh_token' => true, // whether to issue a new refresh token upon successful token request
|
||||
* 'unset_refresh_token_after_use' => true // whether to unset the refresh token after after using
|
||||
* );
|
||||
* </code>
|
||||
*/
|
||||
public function __construct(RefreshTokenInterface $storage, $config = array())
|
||||
{
|
||||
$this->config = array_merge(array(
|
||||
'always_issue_new_refresh_token' => false,
|
||||
'unset_refresh_token_after_use' => true
|
||||
), $config);
|
||||
|
||||
// to preserve B.C. with v1.6
|
||||
// @see https://github.com/bshaffer/oauth2-server-php/pull/580
|
||||
// @todo - remove in v2.0
|
||||
if (isset($config['always_issue_new_refresh_token']) && !isset($config['unset_refresh_token_after_use'])) {
|
||||
$this->config['unset_refresh_token_after_use'] = $config['always_issue_new_refresh_token'];
|
||||
}
|
||||
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
public function getQuerystringIdentifier()
|
||||
{
|
||||
return 'refresh_token';
|
||||
}
|
||||
|
||||
public function validateRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (!$request->request("refresh_token")) {
|
||||
$response->setError(400, 'invalid_request', 'Missing parameter: "refresh_token" is required');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$refreshToken = $this->storage->getRefreshToken($request->request("refresh_token"))) {
|
||||
$response->setError(400, 'invalid_grant', 'Invalid refresh token');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($refreshToken['expires'] > 0 && $refreshToken["expires"] < time()) {
|
||||
$response->setError(400, 'invalid_grant', 'Refresh token has expired');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// store the refresh token locally so we can delete it when a new refresh token is generated
|
||||
$this->refreshToken = $refreshToken;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getClientId()
|
||||
{
|
||||
return $this->refreshToken['client_id'];
|
||||
}
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return isset($this->refreshToken['user_id']) ? $this->refreshToken['user_id'] : null;
|
||||
}
|
||||
|
||||
public function getScope()
|
||||
{
|
||||
return isset($this->refreshToken['scope']) ? $this->refreshToken['scope'] : null;
|
||||
}
|
||||
|
||||
public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope)
|
||||
{
|
||||
/*
|
||||
* It is optional to force a new refresh token when a refresh token is used.
|
||||
* However, if a new refresh token is issued, the old one MUST be expired
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-6
|
||||
*/
|
||||
$issueNewRefreshToken = $this->config['always_issue_new_refresh_token'];
|
||||
$unsetRefreshToken = $this->config['unset_refresh_token_after_use'];
|
||||
$token = $accessToken->createAccessToken($client_id, $user_id, $scope, $issueNewRefreshToken);
|
||||
|
||||
if ($unsetRefreshToken) {
|
||||
$this->storage->unsetRefreshToken($this->refreshToken['refresh_token']);
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
83
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/UserCredentials.php
vendored
Normal file
83
vendor/bshaffer/oauth2-server-php/src/OAuth2/GrantType/UserCredentials.php
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\GrantType;
|
||||
|
||||
use OAuth2\Storage\UserCredentialsInterface;
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
class UserCredentials implements GrantTypeInterface
|
||||
{
|
||||
private $userInfo;
|
||||
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* @param OAuth2\Storage\UserCredentialsInterface $storage REQUIRED Storage class for retrieving user credentials information
|
||||
*/
|
||||
public function __construct(UserCredentialsInterface $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
public function getQuerystringIdentifier()
|
||||
{
|
||||
return 'password';
|
||||
}
|
||||
|
||||
public function validateRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (!$request->request("password") || !$request->request("username")) {
|
||||
$response->setError(400, 'invalid_request', 'Missing parameters: "username" and "password" required');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$this->storage->checkUserCredentials($request->request("username"), $request->request("password"))) {
|
||||
$response->setError(401, 'invalid_grant', 'Invalid username and password combination');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$userInfo = $this->storage->getUserDetails($request->request("username"));
|
||||
|
||||
if (empty($userInfo)) {
|
||||
$response->setError(400, 'invalid_grant', 'Unable to retrieve user information');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isset($userInfo['user_id'])) {
|
||||
throw new \LogicException("you must set the user_id on the array returned by getUserDetails");
|
||||
}
|
||||
|
||||
$this->userInfo = $userInfo;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getClientId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userInfo['user_id'];
|
||||
}
|
||||
|
||||
public function getScope()
|
||||
{
|
||||
return isset($this->userInfo['scope']) ? $this->userInfo['scope'] : null;
|
||||
}
|
||||
|
||||
public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope)
|
||||
{
|
||||
return $accessToken->createAccessToken($client_id, $user_id, $scope);
|
||||
}
|
||||
}
|
106
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/AuthorizeController.php
vendored
Normal file
106
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/AuthorizeController.php
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\Controller;
|
||||
|
||||
use OAuth2\Controller\AuthorizeController as BaseAuthorizeController;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @see OAuth2\Controller\AuthorizeControllerInterface
|
||||
*/
|
||||
class AuthorizeController extends BaseAuthorizeController implements AuthorizeControllerInterface
|
||||
{
|
||||
private $nonce;
|
||||
|
||||
protected function setNotAuthorizedResponse(RequestInterface $request, ResponseInterface $response, $redirect_uri, $user_id = null)
|
||||
{
|
||||
$prompt = $request->query('prompt', 'consent');
|
||||
if ($prompt == 'none') {
|
||||
if (is_null($user_id)) {
|
||||
$error = 'login_required';
|
||||
$error_message = 'The user must log in';
|
||||
} else {
|
||||
$error = 'interaction_required';
|
||||
$error_message = 'The user must grant access to your application';
|
||||
}
|
||||
} else {
|
||||
$error = 'consent_required';
|
||||
$error_message = 'The user denied access to your application';
|
||||
}
|
||||
|
||||
$response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $this->getState(), $error, $error_message);
|
||||
}
|
||||
|
||||
protected function buildAuthorizeParameters($request, $response, $user_id)
|
||||
{
|
||||
if (!$params = parent::buildAuthorizeParameters($request, $response, $user_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate an id token if needed.
|
||||
if ($this->needsIdToken($this->getScope()) && $this->getResponseType() == self::RESPONSE_TYPE_AUTHORIZATION_CODE) {
|
||||
$params['id_token'] = $this->responseTypes['id_token']->createIdToken($this->getClientId(), $user_id, $this->nonce);
|
||||
}
|
||||
|
||||
// add the nonce to return with the redirect URI
|
||||
$params['nonce'] = $this->nonce;
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
public function validateAuthorizeRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (!parent::validateAuthorizeRequest($request, $response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$nonce = $request->query('nonce');
|
||||
|
||||
// Validate required nonce for "id_token" and "id_token token"
|
||||
if (!$nonce && in_array($this->getResponseType(), array(self::RESPONSE_TYPE_ID_TOKEN, self::RESPONSE_TYPE_ID_TOKEN_TOKEN))) {
|
||||
$response->setError(400, 'invalid_nonce', 'This application requires you specify a nonce parameter');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->nonce = $nonce;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getValidResponseTypes()
|
||||
{
|
||||
return array(
|
||||
self::RESPONSE_TYPE_ACCESS_TOKEN,
|
||||
self::RESPONSE_TYPE_AUTHORIZATION_CODE,
|
||||
self::RESPONSE_TYPE_ID_TOKEN,
|
||||
self::RESPONSE_TYPE_ID_TOKEN_TOKEN,
|
||||
self::RESPONSE_TYPE_CODE_ID_TOKEN,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current request needs to generate an id token.
|
||||
*
|
||||
* ID Tokens are a part of the OpenID Connect specification, so this
|
||||
* method checks whether OpenID Connect is enabled in the server settings
|
||||
* and whether the openid scope was requested.
|
||||
*
|
||||
* @param $request_scope
|
||||
* A space-separated string of scopes.
|
||||
*
|
||||
* @return
|
||||
* TRUE if an id token is needed, FALSE otherwise.
|
||||
*/
|
||||
public function needsIdToken($request_scope)
|
||||
{
|
||||
// see if the "openid" scope exists in the requested scope
|
||||
return $this->scopeUtil->checkScope('openid', $request_scope);
|
||||
}
|
||||
|
||||
public function getNonce()
|
||||
{
|
||||
return $this->nonce;
|
||||
}
|
||||
}
|
10
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/AuthorizeControllerInterface.php
vendored
Normal file
10
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/AuthorizeControllerInterface.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\Controller;
|
||||
|
||||
interface AuthorizeControllerInterface
|
||||
{
|
||||
const RESPONSE_TYPE_ID_TOKEN = 'id_token';
|
||||
const RESPONSE_TYPE_ID_TOKEN_TOKEN = 'id_token token';
|
||||
const RESPONSE_TYPE_CODE_ID_TOKEN = 'code id_token';
|
||||
}
|
58
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/UserInfoController.php
vendored
Normal file
58
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/UserInfoController.php
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\Controller;
|
||||
|
||||
use OAuth2\Scope;
|
||||
use OAuth2\TokenType\TokenTypeInterface;
|
||||
use OAuth2\Storage\AccessTokenInterface;
|
||||
use OAuth2\OpenID\Storage\UserClaimsInterface;
|
||||
use OAuth2\Controller\ResourceController;
|
||||
use OAuth2\ScopeInterface;
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @see OAuth2\Controller\UserInfoControllerInterface
|
||||
*/
|
||||
class UserInfoController extends ResourceController implements UserInfoControllerInterface
|
||||
{
|
||||
private $token;
|
||||
|
||||
protected $tokenType;
|
||||
protected $tokenStorage;
|
||||
protected $userClaimsStorage;
|
||||
protected $config;
|
||||
protected $scopeUtil;
|
||||
|
||||
public function __construct(TokenTypeInterface $tokenType, AccessTokenInterface $tokenStorage, UserClaimsInterface $userClaimsStorage, $config = array(), ScopeInterface $scopeUtil = null)
|
||||
{
|
||||
$this->tokenType = $tokenType;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->userClaimsStorage = $userClaimsStorage;
|
||||
|
||||
$this->config = array_merge(array(
|
||||
'www_realm' => 'Service',
|
||||
), $config);
|
||||
|
||||
if (is_null($scopeUtil)) {
|
||||
$scopeUtil = new Scope();
|
||||
}
|
||||
$this->scopeUtil = $scopeUtil;
|
||||
}
|
||||
|
||||
public function handleUserInfoRequest(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
if (!$this->verifyResourceRequest($request, $response, 'openid')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$token = $this->getToken();
|
||||
$claims = $this->userClaimsStorage->getUserClaims($token['user_id'], $token['scope']);
|
||||
// The sub Claim MUST always be returned in the UserInfo Response.
|
||||
// http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
|
||||
$claims += array(
|
||||
'sub' => $token['user_id'],
|
||||
);
|
||||
$response->addParameters($claims);
|
||||
}
|
||||
}
|
23
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/UserInfoControllerInterface.php
vendored
Normal file
23
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Controller/UserInfoControllerInterface.php
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\Controller;
|
||||
|
||||
use OAuth2\RequestInterface;
|
||||
use OAuth2\ResponseInterface;
|
||||
|
||||
/**
|
||||
* This controller is called when the user claims for OpenID Connect's
|
||||
* UserInfo endpoint should be returned.
|
||||
*
|
||||
* ex:
|
||||
* > $response = new OAuth2\Response();
|
||||
* > $userInfoController->handleUserInfoRequest(
|
||||
* > OAuth2\Request::createFromGlobals(),
|
||||
* > $response;
|
||||
* > $response->send();
|
||||
*
|
||||
*/
|
||||
interface UserInfoControllerInterface
|
||||
{
|
||||
public function handleUserInfoRequest(RequestInterface $request, ResponseInterface $response);
|
||||
}
|
33
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/GrantType/AuthorizationCode.php
vendored
Normal file
33
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/GrantType/AuthorizationCode.php
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\GrantType;
|
||||
|
||||
use OAuth2\GrantType\AuthorizationCode as BaseAuthorizationCode;
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
class AuthorizationCode extends BaseAuthorizationCode
|
||||
{
|
||||
public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope)
|
||||
{
|
||||
$includeRefreshToken = true;
|
||||
if (isset($this->authCode['id_token'])) {
|
||||
// OpenID Connect requests include the refresh token only if the
|
||||
// offline_access scope has been requested and granted.
|
||||
$scopes = explode(' ', trim($scope));
|
||||
$includeRefreshToken = in_array('offline_access', $scopes);
|
||||
}
|
||||
|
||||
$token = $accessToken->createAccessToken($client_id, $user_id, $scope, $includeRefreshToken);
|
||||
if (isset($this->authCode['id_token'])) {
|
||||
$token['id_token'] = $this->authCode['id_token'];
|
||||
}
|
||||
|
||||
$this->storage->expireAuthorizationCode($this->authCode['code']);
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
60
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/AuthorizationCode.php
vendored
Normal file
60
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/AuthorizationCode.php
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
use OAuth2\ResponseType\AuthorizationCode as BaseAuthorizationCode;
|
||||
use OAuth2\OpenID\Storage\AuthorizationCodeInterface as AuthorizationCodeStorageInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
class AuthorizationCode extends BaseAuthorizationCode implements AuthorizationCodeInterface
|
||||
{
|
||||
public function __construct(AuthorizationCodeStorageInterface $storage, array $config = array())
|
||||
{
|
||||
parent::__construct($storage, $config);
|
||||
}
|
||||
|
||||
public function getAuthorizeResponse($params, $user_id = null)
|
||||
{
|
||||
// build the URL to redirect to
|
||||
$result = array('query' => array());
|
||||
|
||||
$params += array('scope' => null, 'state' => null, 'id_token' => null);
|
||||
|
||||
$result['query']['code'] = $this->createAuthorizationCode($params['client_id'], $user_id, $params['redirect_uri'], $params['scope'], $params['id_token']);
|
||||
|
||||
if (isset($params['state'])) {
|
||||
$result['query']['state'] = $params['state'];
|
||||
}
|
||||
|
||||
return array($params['redirect_uri'], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the creation of the authorization code.
|
||||
*
|
||||
* @param $client_id
|
||||
* Client identifier related to the authorization code
|
||||
* @param $user_id
|
||||
* User ID associated with the authorization code
|
||||
* @param $redirect_uri
|
||||
* An absolute URI to which the authorization server will redirect the
|
||||
* user-agent to when the end-user authorization step is completed.
|
||||
* @param $scope
|
||||
* (optional) Scopes to be stored in space-separated string.
|
||||
* @param $id_token
|
||||
* (optional) The OpenID Connect id_token.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4
|
||||
* @ingroup oauth2_section_4
|
||||
*/
|
||||
public function createAuthorizationCode($client_id, $user_id, $redirect_uri, $scope = null, $id_token = null)
|
||||
{
|
||||
$code = $this->generateAuthorizationCode();
|
||||
$this->storage->setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, time() + $this->config['auth_code_lifetime'], $scope, $id_token);
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
27
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/AuthorizationCodeInterface.php
vendored
Normal file
27
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/AuthorizationCodeInterface.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
use OAuth2\ResponseType\AuthorizationCodeInterface as BaseAuthorizationCodeInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
interface AuthorizationCodeInterface extends BaseAuthorizationCodeInterface
|
||||
{
|
||||
/**
|
||||
* Handle the creation of the authorization code.
|
||||
*
|
||||
* @param $client_id Client identifier related to the authorization code
|
||||
* @param $user_id User ID associated with the authorization code
|
||||
* @param $redirect_uri An absolute URI to which the authorization server will redirect the
|
||||
* user-agent to when the end-user authorization step is completed.
|
||||
* @param $scope OPTIONAL Scopes to be stored in space-separated string.
|
||||
* @param $id_token OPTIONAL The OpenID Connect id_token.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc6749#section-4
|
||||
* @ingroup oauth2_section_4
|
||||
*/
|
||||
public function createAuthorizationCode($client_id, $user_id, $redirect_uri, $scope = null, $id_token = null);
|
||||
}
|
24
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/CodeIdToken.php
vendored
Normal file
24
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/CodeIdToken.php
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
class CodeIdToken implements CodeIdTokenInterface
|
||||
{
|
||||
protected $authCode;
|
||||
protected $idToken;
|
||||
|
||||
public function __construct(AuthorizationCodeInterface $authCode, IdTokenInterface $idToken)
|
||||
{
|
||||
$this->authCode = $authCode;
|
||||
$this->idToken = $idToken;
|
||||
}
|
||||
|
||||
public function getAuthorizeResponse($params, $user_id = null)
|
||||
{
|
||||
$result = $this->authCode->getAuthorizeResponse($params, $user_id);
|
||||
$id_token = $this->idToken->createIdToken($params['client_id'], $user_id, $params['nonce']);
|
||||
$result[1]['query']['id_token'] = $id_token;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
9
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/CodeIdTokenInterface.php
vendored
Normal file
9
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/CodeIdTokenInterface.php
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
use OAuth2\ResponseType\ResponseTypeInterface;
|
||||
|
||||
interface CodeIdTokenInterface extends ResponseTypeInterface
|
||||
{
|
||||
}
|
124
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdToken.php
vendored
Normal file
124
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdToken.php
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
use OAuth2\Encryption\EncryptionInterface;
|
||||
use OAuth2\Encryption\Jwt;
|
||||
use OAuth2\Storage\PublicKeyInterface;
|
||||
use OAuth2\OpenID\Storage\UserClaimsInterface;
|
||||
|
||||
class IdToken implements IdTokenInterface
|
||||
{
|
||||
protected $userClaimsStorage;
|
||||
protected $publicKeyStorage;
|
||||
protected $config;
|
||||
protected $encryptionUtil;
|
||||
|
||||
public function __construct(UserClaimsInterface $userClaimsStorage, PublicKeyInterface $publicKeyStorage, array $config = array(), EncryptionInterface $encryptionUtil = null)
|
||||
{
|
||||
$this->userClaimsStorage = $userClaimsStorage;
|
||||
$this->publicKeyStorage = $publicKeyStorage;
|
||||
if (is_null($encryptionUtil)) {
|
||||
$encryptionUtil = new Jwt();
|
||||
}
|
||||
$this->encryptionUtil = $encryptionUtil;
|
||||
|
||||
if (!isset($config['issuer'])) {
|
||||
throw new \LogicException('config parameter "issuer" must be set');
|
||||
}
|
||||
$this->config = array_merge(array(
|
||||
'id_lifetime' => 3600,
|
||||
), $config);
|
||||
}
|
||||
|
||||
public function getAuthorizeResponse($params, $userInfo = null)
|
||||
{
|
||||
// build the URL to redirect to
|
||||
$result = array('query' => array());
|
||||
$params += array('scope' => null, 'state' => null, 'nonce' => null);
|
||||
|
||||
// create the id token.
|
||||
list($user_id, $auth_time) = $this->getUserIdAndAuthTime($userInfo);
|
||||
$userClaims = $this->userClaimsStorage->getUserClaims($user_id, $params['scope']);
|
||||
|
||||
$id_token = $this->createIdToken($params['client_id'], $userInfo, $params['nonce'], $userClaims, null);
|
||||
$result["fragment"] = array('id_token' => $id_token);
|
||||
if (isset($params['state'])) {
|
||||
$result["fragment"]["state"] = $params['state'];
|
||||
}
|
||||
|
||||
return array($params['redirect_uri'], $result);
|
||||
}
|
||||
|
||||
public function createIdToken($client_id, $userInfo, $nonce = null, $userClaims = null, $access_token = null)
|
||||
{
|
||||
// pull auth_time from user info if supplied
|
||||
list($user_id, $auth_time) = $this->getUserIdAndAuthTime($userInfo);
|
||||
|
||||
$token = array(
|
||||
'iss' => $this->config['issuer'],
|
||||
'sub' => $user_id,
|
||||
'aud' => $client_id,
|
||||
'iat' => time(),
|
||||
'exp' => time() + $this->config['id_lifetime'],
|
||||
'auth_time' => $auth_time,
|
||||
);
|
||||
|
||||
if ($nonce) {
|
||||
$token['nonce'] = $nonce;
|
||||
}
|
||||
|
||||
if ($userClaims) {
|
||||
$token += $userClaims;
|
||||
}
|
||||
|
||||
if ($access_token) {
|
||||
$token['at_hash'] = $this->createAtHash($access_token, $client_id);
|
||||
}
|
||||
|
||||
return $this->encodeToken($token, $client_id);
|
||||
}
|
||||
|
||||
protected function createAtHash($access_token, $client_id = null)
|
||||
{
|
||||
// maps HS256 and RS256 to sha256, etc.
|
||||
$algorithm = $this->publicKeyStorage->getEncryptionAlgorithm($client_id);
|
||||
$hash_algorithm = 'sha' . substr($algorithm, 2);
|
||||
$hash = hash($hash_algorithm, $access_token);
|
||||
$at_hash = substr($hash, 0, strlen($hash) / 2);
|
||||
|
||||
return $this->encryptionUtil->urlSafeB64Encode($at_hash);
|
||||
}
|
||||
|
||||
protected function encodeToken(array $token, $client_id = null)
|
||||
{
|
||||
$private_key = $this->publicKeyStorage->getPrivateKey($client_id);
|
||||
$algorithm = $this->publicKeyStorage->getEncryptionAlgorithm($client_id);
|
||||
|
||||
return $this->encryptionUtil->encode($token, $private_key, $algorithm);
|
||||
}
|
||||
|
||||
private function getUserIdAndAuthTime($userInfo)
|
||||
{
|
||||
$auth_time = null;
|
||||
|
||||
// support an array for user_id / auth_time
|
||||
if (is_array($userInfo)) {
|
||||
if (!isset($userInfo['user_id'])) {
|
||||
throw new \LogicException('if $user_id argument is an array, user_id index must be set');
|
||||
}
|
||||
|
||||
$auth_time = isset($userInfo['auth_time']) ? $userInfo['auth_time'] : null;
|
||||
$user_id = $userInfo['user_id'];
|
||||
} else {
|
||||
$user_id = $userInfo;
|
||||
}
|
||||
|
||||
if (is_null($auth_time)) {
|
||||
$auth_time = time();
|
||||
}
|
||||
|
||||
// userInfo is a scalar, and so this is the $user_id. Auth Time is null
|
||||
return array($user_id, $auth_time);
|
||||
}
|
||||
}
|
29
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdTokenInterface.php
vendored
Normal file
29
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdTokenInterface.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
use OAuth2\ResponseType\ResponseTypeInterface;
|
||||
|
||||
interface IdTokenInterface extends ResponseTypeInterface
|
||||
{
|
||||
/**
|
||||
* Create the id token.
|
||||
*
|
||||
* If Authorization Code Flow is used, the id_token is generated when the
|
||||
* authorization code is issued, and later returned from the token endpoint
|
||||
* together with the access_token.
|
||||
* If the Implicit Flow is used, the token and id_token are generated and
|
||||
* returned together.
|
||||
*
|
||||
* @param string $client_id The client id.
|
||||
* @param string $user_id The user id.
|
||||
* @param string $nonce OPTIONAL The nonce.
|
||||
* @param string $userClaims OPTIONAL Claims about the user.
|
||||
* @param string $access_token OPTIONAL The access token, if known.
|
||||
*
|
||||
* @return string The ID Token represented as a JSON Web Token (JWT).
|
||||
*
|
||||
* @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken
|
||||
*/
|
||||
public function createIdToken($client_id, $userInfo, $nonce = null, $userClaims = null, $access_token = null);
|
||||
}
|
27
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdTokenToken.php
vendored
Normal file
27
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdTokenToken.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
use OAuth2\ResponseType\AccessTokenInterface;
|
||||
|
||||
class IdTokenToken implements IdTokenTokenInterface
|
||||
{
|
||||
protected $accessToken;
|
||||
protected $idToken;
|
||||
|
||||
public function __construct(AccessTokenInterface $accessToken, IdTokenInterface $idToken)
|
||||
{
|
||||
$this->accessToken = $accessToken;
|
||||
$this->idToken = $idToken;
|
||||
}
|
||||
|
||||
public function getAuthorizeResponse($params, $user_id = null)
|
||||
{
|
||||
$result = $this->accessToken->getAuthorizeResponse($params, $user_id);
|
||||
$access_token = $result[1]['fragment']['access_token'];
|
||||
$id_token = $this->idToken->createIdToken($params['client_id'], $user_id, $params['nonce'], null, $access_token);
|
||||
$result[1]['fragment']['id_token'] = $id_token;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
9
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdTokenTokenInterface.php
vendored
Normal file
9
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/ResponseType/IdTokenTokenInterface.php
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\ResponseType;
|
||||
|
||||
use OAuth2\ResponseType\ResponseTypeInterface;
|
||||
|
||||
interface IdTokenTokenInterface extends ResponseTypeInterface
|
||||
{
|
||||
}
|
37
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Storage/AuthorizationCodeInterface.php
vendored
Normal file
37
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Storage/AuthorizationCodeInterface.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\Storage;
|
||||
|
||||
use OAuth2\Storage\AuthorizationCodeInterface as BaseAuthorizationCodeInterface;
|
||||
/**
|
||||
* Implement this interface to specify where the OAuth2 Server
|
||||
* should get/save authorization codes for the "Authorization Code"
|
||||
* grant type
|
||||
*
|
||||
* @author Brent Shaffer <bshafs at gmail dot com>
|
||||
*/
|
||||
interface AuthorizationCodeInterface extends BaseAuthorizationCodeInterface
|
||||
{
|
||||
/**
|
||||
* Take the provided authorization code values and store them somewhere.
|
||||
*
|
||||
* This function should be the storage counterpart to getAuthCode().
|
||||
*
|
||||
* If storage fails for some reason, we're not currently checking for
|
||||
* any sort of success/failure, so you should bail out of the script
|
||||
* and provide a descriptive fail message.
|
||||
*
|
||||
* Required for OAuth2::GRANT_TYPE_AUTH_CODE.
|
||||
*
|
||||
* @param $code authorization code to be stored.
|
||||
* @param $client_id client identifier to be stored.
|
||||
* @param $user_id user identifier to be stored.
|
||||
* @param string $redirect_uri redirect URI(s) to be stored in a space-separated string.
|
||||
* @param int $expires expiration to be stored as a Unix timestamp.
|
||||
* @param string $scope OPTIONAL scopes to be stored in space-separated string.
|
||||
* @param string $id_token OPTIONAL the OpenID Connect id_token.
|
||||
*
|
||||
* @ingroup oauth2_section_4
|
||||
*/
|
||||
public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null);
|
||||
}
|
38
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Storage/UserClaimsInterface.php
vendored
Normal file
38
vendor/bshaffer/oauth2-server-php/src/OAuth2/OpenID/Storage/UserClaimsInterface.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace OAuth2\OpenID\Storage;
|
||||
|
||||
/**
|
||||
* Implement this interface to specify where the OAuth2 Server
|
||||
* should retrieve user claims for the OpenID Connect id_token.
|
||||
*/
|
||||
interface UserClaimsInterface
|
||||
{
|
||||
// valid scope values to pass into the user claims API call
|
||||
const VALID_CLAIMS = 'profile email address phone';
|
||||
|
||||
// fields returned for the claims above
|
||||
const PROFILE_CLAIM_VALUES = 'name family_name given_name middle_name nickname preferred_username profile picture website gender birthdate zoneinfo locale updated_at';
|
||||
const EMAIL_CLAIM_VALUES = 'email email_verified';
|
||||
const ADDRESS_CLAIM_VALUES = 'formatted street_address locality region postal_code country';
|
||||
const PHONE_CLAIM_VALUES = 'phone_number phone_number_verified';
|
||||
|
||||
/**
|
||||
* Return claims about the provided user id.
|
||||
*
|
||||
* Groups of claims are returned based on the requested scopes. No group
|
||||
* is required, and no claim is required.
|
||||
*
|
||||
* @param $user_id
|
||||
* The id of the user for which claims should be returned.
|
||||
* @param $scope
|
||||
* The requested scope.
|
||||
* Scopes with matching claims: profile, email, address, phone.
|
||||
*
|
||||
* @return
|
||||
* An array in the claim => value format.
|
||||
*
|
||||
* @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
|
||||
*/
|
||||
public function getUserClaims($user_id, $scope);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue