From 61bced878837f320dbb0d74951e73c98b8d78232 Mon Sep 17 00:00:00 2001
From: "Hahn Axel (hahn)" <axel.hahn@iml.unibe.ch>
Date: Thu, 19 May 2022 14:38:47 +0200
Subject: [PATCH] admin: added - detect wrong hosts

---
 public_html/admin/index.php                  | 155 +++++++++++++++++++
 public_html/admin/main.css                   |  27 ++++
 public_html/classes/redirect.admin.class.php |   8 +-
 3 files changed, 187 insertions(+), 3 deletions(-)
 create mode 100644 public_html/admin/index.php
 create mode 100644 public_html/admin/main.css

diff --git a/public_html/admin/index.php b/public_html/admin/index.php
new file mode 100644
index 0000000..ebddf14
--- /dev/null
+++ b/public_html/admin/index.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * ----------------------------------------------------------------------
+ *   _____ __  __ _        _____          _ _               _   
+ *  |_   _|  \/  | |      |  __ \        | (_)             | |  
+ *    | | | \  / | |      | |__) |___  __| |_ _ __ ___  ___| |_ 
+ *    | | | |\/| | |      |  _  // _ \/ _` | | '__/ _ \/ __| __|
+ *   _| |_| |  | | |____  | | \ \  __/ (_| | | | |  __/ (__| |_ 
+ *  |_____|_|  |_|______| |_|  \_\___|\__,_|_|_|  \___|\___|\__|
+ *
+ * ----------------------------------------------------------------------
+ * admin: list all defined redirections
+ * ----------------------------------------------------------------------
+ * 2022-02-03  v0.1  <axel.hahn@iml.unibe.ch>  initial version 
+ * ----------------------------------------------------------------------
+ */
+
+require_once '../classes/redirect.admin.class.php';
+$oR=new redirectadmin();
+$sHtml='';
+
+// ----------------------------------------------------------------------
+// FUNCTIONS
+// ----------------------------------------------------------------------
+
+function getId($sDomain){
+    return 'id_'.md5($sDomain);
+}
+
+// ----------------------------------------------------------------------
+// MAIN
+// ----------------------------------------------------------------------
+
+if (!$oR->isEnabled()){
+    $sHtml.='<div class="error">Admin is disabled.</div>';
+} else {
+
+    $sUrl=(isset($_GET['url']) && $_GET['url']) ? $sUrl=$_GET['url'] : '';
+
+    // ---------- GET CONFIG DATA
+
+    $aHosts=$oR->getHosts();
+
+    // ---------- SHOW ERRORS
+
+    if(count($aHosts['_errors'])) {
+        $sHtml.= '<h2>Found errors</h2>'
+            .'<ol class="error">'
+            .'<li>' . implode('</li></li>', $aHosts['_errors']).'</li>'
+            .'</ol>'
+            ;
+    }
+    unset($aHosts['_errors']);
+
+    // ---------- LOOP OVER ALL ENTRIES
+
+    $sHtml.='
+    <form>
+        🌐 <input type="text" name="url" size="100" value="'.$sUrl.'" />
+        <button>Http HEAD</button>
+    </form>
+    <br>
+
+    <h2>Domains and their redirects</h2>
+
+    <table class="mydatatable"><thead>
+    <tr>
+    <th>Host</th>
+    <th>Ip address</th>
+    <th>Setup</th>
+    <th>Type</th>
+    <th>From</th>
+    <th>Code</th>
+    <th>Target</th>
+    </tr>
+    </thead><tbody>';
+    foreach($aHosts as $sHost => $aCfg){
+        $sTdFirst='<tr class="cfgtype-'.$aCfg['type'].'">'
+            .'<td><a href="?url=http://'.$sHost.'/">'.$sHost.'</a></td>'
+            .'<td>'
+                .($aCfg['ip'] ? $aCfg['ip'] : '<span class="error">ERROR: unknown host</span>')
+            .'</td>'
+            .'<td>'.$aCfg['type'].'</td>'
+            ;
+        if (isset($aCfg['redirects'])){
+            $iCount=0;
+            foreach(['direct', 'regex'] as $sType){
+                if (count($aCfg['redirects'][$sType])){
+                    foreach($aCfg['redirects'][$sType] as $sFrom=>$aTo){
+                        $iCount++;
+                        $sHtml.=$sTdFirst
+                            .'<td class="type-'.$sType.'">'.$sType.'</td>'
+                            .'<td class="type-'.$sType.'">'
+                                .($sType == 'direct' ? '<a href="?url=http://'.$sHost.'/'.$sFrom.'">'.$sFrom.'</a>' : $sFrom)
+                            .'</td>'
+                            .'<td class="http-'.$aTo['code'].'">'.$aTo['code'].'</td>'
+                            .'<td>🌐 <a href="?url='.$aTo['target'].'">'.$aTo['target'].'</a></td>'
+                            .'</tr>';
+                    }
+                }
+                
+            }
+        } else {
+            // type = alias
+            // $sHtml.='<tr>'.$sTdFirst.'<td></td><td></td><td></td><td>'.(isset($aCfg['target']) ? 'see config for <a href="#'.getId($aCfg['target']).'">'.$aCfg['target'].'</a>' : '').'</td></tr>';
+            $sHtml.=$sTdFirst.'<td></td><td></td><td></td><td>'.(isset($aCfg['target']) ? 'see config for <em>'.$aCfg['target'].'</em>' : '').'</td></tr>';
+        }
+        
+    }
+    $sHtml.='</tbody></table>'
+        /*
+        .'<h2>Config array</h2>
+        <pre>'.print_r($aHosts, 1).'</pre>'
+        */
+        ;
+
+    // ---------- TEST URL
+    if ($sUrl){
+        $sResult=$oR->httpGet($sUrl.'?debugredirect=1',1);
+        $sHtml.= '<div class="overlay" onclick="this.style.display=\'none\';"><div>'
+            . '<h2>🌐 <a href="'.$sUrl.'">'.$sUrl.'</a></h2> (click to open)<br><br>'
+            . '📄 Http response header:<br><br>'.$oR->renderHttpResponseHeader($sResult, 1)
+            . '</div></div>'
+            ;
+    }
+    
+
+}
+
+// ---------- OUTPUT
+
+?><!doctype html>
+<html>
+    <head>
+        <title>Redirects</title>
+        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.11.4/datatables.min.css"/>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+        <script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.11.4/datatables.min.js"></script>
+        <link rel="stylesheet" href="main.css">
+    </head>
+    <body>
+        <h1>⏩ <a href="?">Redirects :: admin</a></h1>
+
+        <?php echo $sHtml; ?>
+        
+        <script>
+            $(document).ready( function () {
+                $('.mydatatable').DataTable({
+                    "lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
+                    stateSave: true
+                });
+            } );
+        </script>
+    </body>
+</html>
diff --git a/public_html/admin/main.css b/public_html/admin/main.css
new file mode 100644
index 0000000..a24ba6c
--- /dev/null
+++ b/public_html/admin/main.css
@@ -0,0 +1,27 @@
+a{color:royalblue;}
+body{background: #f8f8f8; color: #234; font-family: arial;}
+h1{background:rgba(0,0,0,0.05); margin: 0 0 1em;; padding: 0.5em;}
+h1 a{color:#234; text-decoration: none;}
+h2{background:rgba(0,0,0,0.02);  color:#458; margin: 0;}
+h2 a{color:#458; text-decoration: none; }
+pre{background: rgba(0,0,0,0.02);padding: 0.3em 1em; border: 1px solid rgba(0,0,0,0.1); margin-bottom: 2em;}
+
+.error{background: #fcc;}
+
+.cfgtype-alias{color:#89a; }
+.http-301::after{color:#a55; content: ' (Moved Permanently)'}
+.http-307::after{color:#488; content: ' (Temporary Redirect)'}
+.http-308::after{color:#a95; content: ' (Permanent Redirect)'}
+.type-direct{color:#383; }
+.type-regex{color:#838; }
+
+.status{padding: 0.5em 1em; position: relative;top: -0.8em; border: 2px solid; border-left: 1.5em solid;}
+.status-ok{color:#080; background:#cec; }
+.status-redirect{color:#651; background:#fec;}
+.status-error{color:#800; background:#ecc;}
+
+.location{background:#fec;}
+.debug{color:#197;}
+
+.overlay{position: fixed; margin: 0; width: 100%; height: 100%; top: 0; left: 0; background: rgba(0,0,0,0.3);overflow: scroll;}
+.overlay>div{margin: 3% 10%; background: #fff; padding: 1em;box-shadow: 0 0 3em #000; }
diff --git a/public_html/classes/redirect.admin.class.php b/public_html/classes/redirect.admin.class.php
index cc609a6..3968a3b 100644
--- a/public_html/classes/redirect.admin.class.php
+++ b/public_html/classes/redirect.admin.class.php
@@ -107,8 +107,10 @@ class redirectadmin extends redirect {
         return file_exists($sFile2Enable);
     }
 
-    public function httpHead($sUrl){
 
+    protected function _getIp($sHostname){
+        $sIp=gethostbyname($sHostname);
+        return $sIp===$sHostname ? false : $sIp;
     }
 
     /**
@@ -122,7 +124,7 @@ class redirectadmin extends redirect {
             $aReturn[$sMyHost]=array(
                 'type'=>'config',
                 'file'=>$sFilename,
-                'ip'=> gethostbyname($sMyHost),
+                'ip'=> $this->_getIp($sMyHost),
                 'aliases'=>array(),
                 'redirects'=>json_decode(file_get_contents($sFilename), 1),
             );
@@ -139,7 +141,7 @@ class redirectadmin extends redirect {
                     $aReturn[$sAlias]=array(
                         'type'=>'alias',
                         'target'=>$sConfig,
-                        'ip'=> gethostbyname($sMyHost),
+                        'ip'=> $this->_getIp($sAlias),
                     );
                 }
             }
-- 
GitLab