diff --git a/config/aliases.json.dist b/config/aliases.json.dist index 8c8e9760d78169b96da4dfc934757296d3b23cfd..6473bd24d8426fd36064e5c7f41339d1ab2440a5 100644 --- a/config/aliases.json.dist +++ b/config/aliases.json.dist @@ -1,3 +1,3 @@ { - "sub.domain.example.com": "domain.example.com" + "sub.domain.example.com": "www.example.com" } \ No newline at end of file diff --git a/config/redirects_www.example.com.json b/config/redirects_www.example.com.json new file mode 100644 index 0000000000000000000000000000000000000000..83d3db03cbb3717c74b58e5f69c4b68dd7e6a8ba --- /dev/null +++ b/config/redirects_www.example.com.json @@ -0,0 +1,9 @@ +{ + "comment": "Example redirect configuration file for domain.example.com", + "direct":{ + "/mail": {"code": 301, "target": "https://www.example.com/webmail" } + }, + "regex":{ + ".*": {"code": 307, "target": "https://www.example.com/" } + } +} diff --git a/config/redirects_www.example.com.json.dist b/config/redirects_www.example.com.json.dist index a2ff96dfba2f571787fe71643547095aea30f94c..83d3db03cbb3717c74b58e5f69c4b68dd7e6a8ba 100644 --- a/config/redirects_www.example.com.json.dist +++ b/config/redirects_www.example.com.json.dist @@ -1,7 +1,7 @@ { "comment": "Example redirect configuration file for domain.example.com", "direct":{ - "mail": {"code": 301, "target": "https://www.example.com/mail" } + "/mail": {"code": 301, "target": "https://www.example.com/webmail" } }, "regex":{ ".*": {"code": 307, "target": "https://www.example.com/" } diff --git "a/docs/20_\342\226\266\357\270\217_Installation.md" "b/docs/20_\342\226\266\357\270\217_Installation.md" index 8b227806f3b0630a44f3c7dd5f332da6eb8ce6ca..37b0e1ab2e027512d75931467406b3b74d0284ca 100644 --- "a/docs/20_\342\226\266\357\270\217_Installation.md" +++ "b/docs/20_\342\226\266\357\270\217_Installation.md" @@ -1,6 +1,6 @@ -# Installation # +## Installation -## Get the files ## +### Get the files The repository contains a subfolder *public_html*. Run `git clone` or extract the downloaded archive 1 level above webroot. The document root of the web must point to the public_html directory. The config folder is outside the webroot. @@ -23,7 +23,7 @@ to the public_html directory. The config folder is outside the webroot. └── readme.md ``` -## Redirect all requests to index.php ## +### Redirect all requests to index.php Redirect all requests to the index.php. Activate the .htaccess or (better) add the config to the vhost config. diff --git "a/docs/30_\342\232\231\357\270\217_Configuration.md" "b/docs/30_\342\232\231\357\270\217_Configuration.md" index 210eab0d1092964479e78ad2678b79e6c07d61c2..9045a308fd74ee3c2befba62caf6be3faa0789a0 100644 --- "a/docs/30_\342\232\231\357\270\217_Configuration.md" +++ "b/docs/30_\342\232\231\357\270\217_Configuration.md" @@ -1,12 +1,13 @@ +## Configuration -# Configuration # +### Files In the *./config/* folder are json files. Copy the dist files to the same filename without ".dist" -* redirects_[FQDN].json - -* aliases.json - +* `redirects_<FQDN>.json` - Config with redirects per domain +* `aliases.json` - list of domain aliases -You can create multipe redirect files `redirects_[FQDN].json`. We suggest to use the main domain as FQDN. +You can create multipe redirect files `redirects_<FQDN>.json`. We suggest to use the main domain as FQDN. If you have multiple domains that should use exactly the same redirects then use the `aliases.json`. Other requirements: @@ -14,7 +15,23 @@ Other requirements: * In the DNS you must point each domain to the redirect website. * In the apache web with multiple vhosts: add the need a server alias to process the hostname in the wanted vhost -## Redirects ## +### Redirects + +Let's start with an example for a `redirects_<FQDN>.json`: + +```json +{ + "direct":{ + "/heise": {"code": 307, "target": "https://www.heise.de" } + }, + + "regex":{ + "^/$": {"code": 307, "target": "https://www.iml.unibe.ch" }, + "^/ax.l.*": {"code": 307, "target": "https://www.axel-hahn.de" }, + ".*": {"code": 301, "target": "https://www2.example.com" } + } +} +``` There are 2 required sections to define redirects: @@ -30,9 +47,21 @@ first matching regex. If no rule matches a 404 will be shown. +#### Section "direct" + +This section has keys für direct matches to a webservice like location as string eg. "/mail". +This entry will match for a request to location /mail only - but not /mail2. + +#### Section "regex" + +This section has keys für direct matches to a webservice like location as regex eg. "^/mail" +This entry will match for a request to all locations starting with /mail: /mail and /mail2 as well. Use the dollar sign to define + Hint: if you set regex ".*" as last entry it works as a catchall for unmatched requests and you can define a default redirect target instead of showing a 404. +#### Define redirect + Both redirect section contain a redirect definition * code - http status code for redirection @@ -50,22 +79,7 @@ Suggestion for redirection lifecycle: * if the redirect has finished its life, switch the code to 308 or 301. * remove the redirect (which results into 404) -Example: - -```json -{ - "direct":{ - "heise": {"code": 307, "target": "https://www.heise.de" } - }, - - "regex":{ - "^$": {"code": 307, "target": "https://www.iml.unibe.ch" }, - "^ax.l.*": {"code": 307, "target": "https://www.axel-hahn.de" } - } -} -``` - -## Server aliases ## +### Server aliases If you have multiple domains with the same rules you can define aliases. @@ -78,8 +92,8 @@ Example: } ``` -The key is the name of the alias. The value is a domain for that was written a -redirect_[hostname].json already. +The key is the name of the alias. The value is a domain for that was a written +`redirect_<FQDN>.json` already. The existance of a redirect config has higher priority than an entry in the aliases config. diff --git a/docs/style.css b/docs/style.css index 18463c799d9cd101d8f9b27a282128cde4494d99..45383c3288f17a74d88fc2ffca48307f794d4592 100644 --- a/docs/style.css +++ b/docs/style.css @@ -1,13 +1,14 @@ /* override css elements of daux.io blue theme - version 2022-11-30 + version 2023-11-10 */ :root { /* Axels Overrides */ - --color-text: #222; - --link-color: #822; - --brand-color: var(--color-secondary); + --color-text: #234; + --link-color: #228; + --brand-color: var(--color-text); --brand-background: var(--body-background); + --code-tag-border-color: #d8d8d8; --hr-color: none; --search-field-background: none; --search-field-border-color: none; @@ -24,29 +25,32 @@ --axel_brand-pre-background-hover: rgb(255, 0, 51); ; --axel_h1_header: none; - --axel_h1: #345; + --axel_h1: #111; --axel_h1-bg: none; --axel_h1-bottom: 3px solid none; - --axel_h2: #156; - --axel_h2-bg: #f8fafb; - --axel_h2-bottom: 2px solid #467; + --axel_h2: #222; + --axel_h2-bg: none; + --axel_h2-bottom: 0px solid #467; --axel_h2-hero-bottom: 2px solid #912; - --axel_h3: #278; - --axel_h3-bottom: 1px solid #ddd; + --axel_h3: #333; + --axel_h3-bottom: 0px solid #ddd; + --axel_h4: #444; --axel_hero_bg: #f8f8f8; + --axel_img-border: 2px dashed #ccc; --axel_nav-bg: #fcfcfc; --axel_nav-buttomborder: #ddd; --axel_pre-background: #f8f8f8; - --axel-th-background: #d0e0e8; + --axel-th-background: #e0e4e8; --axel-article-nav-border-top: 0px dotted #ddd; } .dark { /* Axels Overrides */ --color-text: #c0c0c0; - --link-color: #b44; + --link-color: #88e; --brand-color: var(--color-text); --brand-background: var(--body-background); + --body-background: #101418; --hr-color: none; --code-tag-background-color_: #bcc; --search-field-background: none; @@ -63,16 +67,17 @@ --axel_brand-pre-background-hover: rgb(255, 0, 51); ; --axel_h1_header: none; - --axel_h1: #777; + --axel_h1: #578; --axel_h1-bg: none; --axel_h1-bottom: none; --axel_h2: #467; - --axel_h2-bg: #202020; - --axel_h2-bottom: 2px solid #256; + --axel_h2-bg: none; + --axel_h2-bottom: 0px solid #256; --axel_h2-hero-bottom: 2px solid #712; --axel_h3: #589; - --axel_h3-bottom: 1px solid #333; + --axel_h3-bottom: 0px solid #333; --axel_hero_bg: #242424; + --axel_img-border: 2px dashed #555; --axel_nav-bg: #242424; --axel_nav-buttomborder: #555; --axel_pre-background: #bcc; @@ -133,7 +138,7 @@ a.Brand { .s-content h2 { background: var(--axel_h2-bg); color: var(--axel_h2); - font-size: 180%; + font-size: 190%; font-weight: bold; margin-top: 4em; border-bottom: var(--axel_h2-bottom); @@ -147,6 +152,12 @@ h2:first-of-type { margin-top: 0em; } +img{ + border: var(--axel_img-border); + border-radius: 1.5em; + padding: 0.7em; +} + .s-content h3 { background: var(--axel_h3-bg); color: var(--axel_h3); @@ -156,14 +167,26 @@ h2:first-of-type { border-bottom: var(--axel_h3-bottom); } -.s-content h4 { - margin: 0; - font-size: 100%; + +.s-content > h4 { + color: var(--axel_h4); + font-size: 135%; + font-weight: bold; + margin: 2em 0; +} + +.s-content .TableOfContentsContainer h4 { + margin: 1em 0; + font-size: 110%; text-align: center; - background-color: rgba(0, 0, 0, 0.05); + background-color: rgba(0, 0, 0, 0.1); padding: 0.3em; + font-weight: bold; + font-family: Arial; +} +ul.TableOfContents a{ + color: var(--color-text); } - .s-content pre { background: var(--axel_pre-background); } @@ -264,4 +287,4 @@ ul.TableOfContents ul { .Links a[href^="https://os-docs.iml.unibe.ch"]::before { content: '📗 '; -} \ No newline at end of file +} diff --git a/public_html/admin/index.php b/public_html/admin/index.php index 74c931cf6babd09c289c1569cc8aa4abda0a9943..f09c4897bb47ad6434516e32bac79df9227e3d15 100644 --- a/public_html/admin/index.php +++ b/public_html/admin/index.php @@ -26,7 +26,7 @@ $aIco=[ 'h1'=>'⏩', 'h2_head'=>'✔️', - 'h2_err'=>'🔔', + 'h2_err'=>'⚠️', 'h2_config'=>'🛠️', 'h2_file'=>'📄', @@ -71,7 +71,7 @@ if (!$oR->isEnabled()){ if ($sUrl){ $sResult=$oR->httpGet($sUrl,1); echo '<h2>Response of a http HEAD request to '.$aIco['url'].' <a href="'.$sUrl.'">'.$sUrl.'</a></h2>' - . $oR->renderHttpResponseHeader($sResult, 1) + . $oR->renderHttpResponseHeader($sResult) ; return true; } @@ -145,7 +145,7 @@ if (!$oR->isEnabled()){ .'<td class="type-'.$sType.'">'.$sType.'</td>' .'<td class="type-'.$sType.'">' .($sType == 'direct' - ? '<a href="?url=http://'.$sHost.'/'.$sFrom.'" title="click to test http://'.$sHost.'/'.$sFrom.'" onclick="showInOverlay(this); return false;">/'.$sFrom.'</a>' + ? '<a href="?url=http://'.$sHost.$sFrom.'" title="click to test http://'.$sHost.'/'.$sFrom.'" onclick="showInOverlay(this); return false;">'.$sFrom.'</a>' : $sFrom ) .'</td>' diff --git a/public_html/admin/main.css b/public_html/admin/main.css index 224eebe01ee21135fc46250bd46fceb738f863d4..7b23959c2995b327c6ab6692c426817bcac4b9ed 100644 --- a/public_html/admin/main.css +++ b/public_html/admin/main.css @@ -12,7 +12,7 @@ footer{background:rgba(0,0,0,0.03); margin-top: 4em; text-align: right;padding: .content{margin: 0 1em;} .legend{background: #fff; padding: 1em;} -.error{background: #fcc; padding: 0.2em 1em;} +.error{background: #fcc; padding: 0.2em 1.5em;} .warning{color:#651; background:#fec; padding: 0.2em 1em;} .cfgtype-alias{color:#89a;} diff --git a/public_html/classes/redirect.admin.class.php b/public_html/classes/redirect.admin.class.php index d11fbe0ffcca843ff61d96ecb6247703e3833291..9a1ed976c69ddc31599ab96b986100258b15b1fd 100644 --- a/public_html/classes/redirect.admin.class.php +++ b/public_html/classes/redirect.admin.class.php @@ -18,7 +18,7 @@ require_once 'redirect.class.php'; * 2022-05-23 v1.6 ah add http head check+render output; * 2022-05-31 v1.7 ah optical changes * 2023-08-28 v1.8 ah remove php warning if there is no config yet - * 2024-10-03 v1.9 ah php8 only: typed variables + * 2024-10-04 v1.9 ah php8 only: typed variables */ /** diff --git a/public_html/classes/redirect.class.php b/public_html/classes/redirect.class.php index 168151820d4dfb956b28d09f83b9ced86a023f86..ae8b2e9986a1f5654ead6b828176a298614eb538 100644 --- a/public_html/classes/redirect.class.php +++ b/public_html/classes/redirect.class.php @@ -24,7 +24,7 @@ * 2020-05-06 v1.3 ah added aliases for multiple domains with the same config * 2020-05-06 v1.4 ah rewrite as class * 2023-08-28 v1.5 ah fix loop over config with missing regex section. - * 2024-10-03 v1.6 ah php8 only: typed variables + * 2024-10-04 v1.6 ah php8 only: typed variables */ /** @@ -55,7 +55,7 @@ class redirect * About message * @var string */ - protected string $sAbout = 'IML redirect <small>v1.4</small>'; + protected string $sAbout = 'IML redirect <small>v1.6</small>'; /** * Hostname @@ -278,7 +278,7 @@ class redirect public function setRequest(string $sRequest): bool { $this->sRequest = $sRequest; - $this->aRedirect = false; + $this->aRedirect = []; return true; } @@ -294,7 +294,7 @@ class redirect */ public function getRedirect(): array { - if (is_array($this->aRedirect)) { + if (is_array($this->aRedirect) && count($this->aRedirect)) { return $this->aRedirect; } @@ -341,7 +341,7 @@ class redirect public function getRedirectTarget(): string { $aRedirect = $this->getRedirect(); - return $aRedirect['target'] ?? ''; + return isset($aRedirect['target']) ? $aRedirect['target'] : false; } diff --git a/public_html/index.php b/public_html/index.php index 46ee3078c9ec1bf85a31a61a9eac02f753a1772a..2dcec2a9acf66eaa0610080652dd81e3d258118a 100755 --- a/public_html/index.php +++ b/public_html/index.php @@ -17,9 +17,8 @@ require_once 'classes/redirect.class.php'; $sHostname = $_SERVER['SERVER_NAME']; -// find redirect ... the part between starting "/" to "?" or end of line -$sRequest = preg_replace('#^(.*)\?.*$#', "$1", substr($_SERVER['REQUEST_URI'], 1)); - +// find request ... the part between starting "/" to "?" or end of line +$sRequest = preg_replace('#^(.*)\?.*$#', "$1", substr($_SERVER['REQUEST_URI'], 0)); $oR=new redirect(); $oR->setDebug(isset($_GET['debugredirect']) && $_GET['debugredirect'] ? true : false); diff --git a/test/get_redirect.php b/test/get_redirect.php new file mode 100644 index 0000000000000000000000000000000000000000..5af232230a4c9719c6610e3fba82eaddf40fb7eb --- /dev/null +++ b/test/get_redirect.php @@ -0,0 +1,104 @@ +<?php +/** + * + * TEST + * Verify if a redirect works + * + * Usage: + * cd ./tests + * php get_redirect.php + * + */ +require_once '../public_html/classes/redirect.class.php'; + +// ------------------------------------------------------------------------ +// CONFIG +// ------------------------------------------------------------------------ +$aTests=[ + 'www.example.com - static entry /mail' => [ + 'host'=>'www.example.com', + 'request'=>'/mail', + + 'target'=>'https://www.example.com/webmail', + 'code'=>301, + ], + 'www.example.com - /mail2 should not match /mail but the regex' => [ + 'host'=>'www.example.com', + 'request'=>'/mail2', + + 'target'=>'https://www.example.com/', + 'code'=>307, + ], + 'www.example.com - regex' => [ + 'host'=>'www.example.com', + 'request'=>'/somethingold', + + 'target'=>'https://www.example.com/', + 'code'=>307, + ], + 'www.example.com - /iml must match regex ^/iml' => [ + 'host'=>'www.example.com', + 'request'=>'/iml', + + 'target'=>'https://www.iml.unibe.ch/', + 'code'=>307, + ], + 'www.example.com - /iml2 must match regex ^/iml too' => [ + 'host'=>'www.example.com', + 'request'=>'/iml2', + + 'target'=>'https://www.iml.unibe.ch/', + 'code'=>307, + ], +]; + +// ------------------------------------------------------------------------ +// INIT +// ------------------------------------------------------------------------ + +$oR=new redirect(); +$oR->setDebug(isset($_GET['debugredirect']) && $_GET['debugredirect'] ? true : false); + +echo "\n"; +echo "##################### TEST REDIRECT #####################\n"; +echo "\n"; + + +// ------------------------------------------------------------------------ +// LOOP :: Redirects +// ------------------------------------------------------------------------ + +foreach ($aTests as $sTestName => $aTest) { + echo "==========| $sTestName |==> ".$aTest['host']." - ".$aTest['request']." \n"; + // echo "To check\n"; + // print_r($aTest); + + // set data + $oR->setHost($aTest['host']); + $oR->setRequest($aTest['request']); + + // verify + $bOk=true; + + if ($oR->getRedirectTarget() != $aTest['target']) { + $bOk=false; + echo ">>>> CONFIG FAILED: target returned ".$oR->getRedirectTarget()." - not ".$aTest['target']."\n"; + } + if ($oR->getRedirectCode() != $aTest['code']) { + $bOk=false; + echo ">>>> CONFIG FAILED: Redirect code retuned ".$oR->getRedirectCode()." - not ".$aTest['code']."\n"; + } + if($bOk) { + echo ">>>> OK: redirects with ".$aTest['code']." to ".$aTest['target']."\n"; + } else { + echo "Detected redirect from config\n"; + print_r($oR->getRedirect()); + echo "\n"; + } + echo "\n"; +} + + +echo "DONE\n"; + +// ------------------------------------------------------------------------