Git-Import
authorMalte Bublitz <malte@rolltreppe3.de>
Sun, 8 May 2022 03:47:39 +0000 (05:47 +0200)
committerMalte Bublitz <malte@rolltreppe3.de>
Sun, 8 May 2022 03:47:39 +0000 (05:47 +0200)
21 files changed:
.htaccess [new file with mode: 0644]
98.php [new file with mode: 0644]
API.md [new file with mode: 0644]
ad.inc.php [new file with mode: 0644]
api.php [new file with mode: 0644]
assets/css/98.css [new file with mode: 0644]
assets/css/ipinfo98.css [new file with mode: 0644]
assets/css/style.css [new file with mode: 0644]
assets/img/favicon.png [new file with mode: 0644]
assets/img/favicon98.png [new file with mode: 0644]
assets/js/getipv4.js [new file with mode: 0644]
assets/otf/SourceCodePro-Regular.otf [new file with mode: 0644]
assets/otf/SourceCodePro-Semibold.otf [new file with mode: 0644]
clientinfo.class.php [new file with mode: 0644]
config.inc.php [new file with mode: 0644]
debug.php [new file with mode: 0644]
index.php [new file with mode: 0644]
info.php [new file with mode: 0644]
ip.php [new file with mode: 0644]
template.inc.php [new file with mode: 0644]
widget.php [new file with mode: 0644]

diff --git a/.htaccess b/.htaccess
new file mode 100644 (file)
index 0000000..f1e829a
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,13 @@
+# 
+# ip.malte70.de/.htaccess
+# 
+
+<IfModule mod_rewrite.c>
+       RewriteEngine On
+       
+       RewriteBase /
+       
+       # The widget should be accessed using a filename
+       # containing the correct extendion for a PNG image
+       RewriteRule ^widget.png$ widget.php [QSA]
+</IfModule>
diff --git a/98.php b/98.php
new file mode 100644 (file)
index 0000000..fa497c4
--- /dev/null
+++ b/98.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * IPInfo ip.malte70.de Windows 98 Style
+ */
+
+require_once("config.inc.php");
+require_once("clientinfo.class.php");
+
+$info = new ClientInfo();
+
+$Languages = Array(
+       "de"    => "Deutsch",
+       "de_DE" => "Deutsch (Deutschland)",
+       "de_AT" => "Deutsch (Österreich)",
+       "de_CH" => "Deutsch (Schweiz)",
+       "en"    => "Englisch",
+       "en_UK" => "Englisch (Vereinigtes Königreich)",
+       "en_US" => "Englisch (USA)",
+       "tlh"   => "Klingonisch"
+);
+
+
+/**
+ * Retrieve GeoIP data
+ */
+$geo = $info->getGeoIPCity();
+if (empty($geo[1])) {
+    $geo = False;
+}
+
+
+$Data = Array(
+       "IP"         => $info->getIP(),
+       "RealIP"     => $info->getRealIP(),
+       "Host"       => $info->getHostname() != $info->getIP() ? $info->getHostname() : NULL,
+       "Browser"    => $info->getBrowser(),
+       "OS"         => $info->getOS(),
+       "Lang"       => array_key_exists($info->getLanguage(),$Languages) ? $Languages[$info->getLanguage()]." (".$info->getLanguage().")" : $info->getLanguage(),
+       "UserAgent"  => $info->getUserAgent(),
+       "GeoIP"      => $geo,
+       //"Stylesheet" => "https://unpkg.com/98.css",
+       "Stylesheet" => Array(
+               "/assets/css/98.css",
+               "/assets/css/ipinfo98.css"
+       ),
+       "Favicon"    => Array(
+               "MIMEType" => "image/png",
+               "Size"     => "48x48",
+               "URL"      => "/assets/img/favicon98.png"
+       )
+);
+
+?><!DOCTYPE html>
+<html lang="de">
+       <head>
+               <meta charset="UTF-8">
+               <meta name="viewport" content="width=device-width, initial-scale=1.0">
+               
+               <title>Deine IP &mdash; ip.malte70.de</title>
+               
+               <meta name="author" content="Malte Bublitz">
+<?php foreach ($Data["Stylesheet"] as $css): ?>
+               <link rel="stylesheet" type="text/css" href="<?=$css?>">
+<?php endforeach; ?>
+               <link rel="icon" type="<?=$Data["Favicon"]["MIMEType"]?>" sizes="<?=$Data["Favicon"]["Size"]?>" href="<?=$Data["Favicon"]["URL"]?>">
+       </head>
+       <body id="top">
+               <main>
+
+                       <div class="window">
+                               <div class="title-bar">
+                                       <div class="title-bar-text">Deine IP</div>
+                                       <div class="title-bar-controls">
+                                               <button id="minimize" aria-label="Minimize"></button>
+                                               <button id="maximize" aria-label="Maximize"></button>
+                                               <button id="close" aria-label="Close"></button>
+                                       </div>
+                               </div>
+                               <div class="window-body">
+                                       <div class="field-row">
+                                               <label for="ip">IP-Adresse</label>
+                                               <input id="ip" type="text" value="<?=$Data["IP"]?>" readonly>
+                                       </div>
+                                       
+<?php if (!empty($Data["RealIP"])): ?>
+                                       <div class="field-row">
+                                               <label for="real_ip">Reale IP</label>
+                                               <input id="real_ip" type="text" value="<?=$Data["RealIP"]?>" readonly>
+                                       </div>
+                                       
+<?php endif; ?>
+<?php if (!empty($Data["Host"])): ?>
+                                       <div class="field-row">
+                                               <label for="host">Hostname</label>
+                                               <input id="host" type="text" value="<?=$Data["Host"]?>" readonly>
+                                       </div>
+                                       
+<?php endif; ?>
+<?php if (!empty($Data["GeoIP"])): ?>
+                                       <div class="field-row">
+                                               <label for="host">Ort</label>
+                                               <input id="host" type="text" value="<?=$Data["GeoIP"][0]?>, <?=$info->getGeoIPCountry()?>" readonly>
+                                       </div>
+                                       
+<?php endif; ?>
+                                       <div class="field-row">
+                                               <label for="browser">Browser</label>
+                                               <input id="browser" type="text" value="<?=$Data["Browser"]?>" readonly>
+                                       </div>
+                                       
+                                       <div class="field-row">
+                                               <label for="os">Betriebssystem</label>
+                                               <input id="os" type="text" value="<?=$Data["OS"]?>" readonly>
+                                       </div>
+
+                                       <div class="field-row">
+                                               <label for="lang">Sprache</label>
+                                               <input id="lang" type="text" value="<?=$Data["Lang"]?>" readonly>
+                                       </div>
+                                       
+                                       <div class="field-row">
+                                               <label for="ua">User-Agent</label>
+                                               <input id="ua" type="text" value="<?=$Data["UserAgent"]?>" readonly>
+                                       </div>
+                                       
+                                       <p>
+                                               <a href="https://speedtest.malte70.de"><button>Speedtest</button></a>
+                                       </p>
+                               </div>
+                       </div>
+               </main>
+               
+<?php /*
+               <footer>
+                       <p>
+                               © <?=date("Y")?> <a href="https://malte70.de" rel="me nofollow">malte70</a>
+                       </p>
+               </footer>
+               
+*/ ?>
+               <script>
+                       document.getElementById("minimize").onclick = function() {
+                               if (document.getElementsByClassName("window-body")[0].style.display != "none") {
+                                       document.getElementsByClassName("window-body")[0].style.display = "none";
+                               } else {
+                                       document.getElementsByClassName("window-body")[0].style.display = "";
+                               }
+                       };
+                       document.getElementById("maximize").onclick = function() {
+                               if (document.getElementsByTagName("main")[0].className != "maximized") {
+                                       document.getElementsByTagName("main")[0].className = "maximized";
+                               } else {
+                                       document.getElementsByTagName("main")[0].className = "";
+                               }
+                       };
+                       document.getElementById("close").onclick = function() {
+                               document.querySelector(".window").setAttribute("style", "display:none;");
+                       };
+               </script>
+       </body>
+</html>
diff --git a/API.md b/API.md
new file mode 100644 (file)
index 0000000..7872833
--- /dev/null
+++ b/API.md
@@ -0,0 +1,20 @@
+# ip.malte70.de API
+
+You can access the API at:
+
+       https://ip.malte70.de/api.php/*query*
+
+Query might be one of the following values:
+
+- ip
+- hostname
+- useragent
+- browser
+- operatingsystem
+- lang
+- country
+- city
+- postal_code
+- coordinates
+- latitute
+- longitude
diff --git a/ad.inc.php b/ad.inc.php
new file mode 100644 (file)
index 0000000..f9fd719
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * "Ad" for 98.css-IPInfo or the finger protocol interface.
+ */
+
+function get_ad() {
+       if (date("w") % 2 == 0) {
+               $ad = <<<EOT
+<p>
+       <em style="font-weight:bolder;">Neu!</em> Zugriff via Finger-Protokoll:
+</p>
+<p><code><pre>$ <b>finger <em>ip</em>@ip.malte70.de</b>
+5.1.92.135</pre></code></p>
+<p><code><pre>$ <b>finger <em>myip</em>@ip.malte70.de</b>
+Your IP: 5.1.92.135
+Your Hostname: spandau.rolltreppe3.de</pre></code></p>
+EOT;
+               
+       } else {
+               $ad = "<p>\n\t";
+               $ad.= "<a href=\"98.php\">IPInfo feat. 98.css</a>\n\t</p>\n";
+               
+       }
+       
+       return $ad;
+}
+
+?>
diff --git a/api.php b/api.php
new file mode 100644 (file)
index 0000000..5332705
--- /dev/null
+++ b/api.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * ip.malte70.de/api.php
+ * 
+ * A very tiny API for ipinfo
+ */
+require_once("config.inc.php");
+require_once("clientinfo.class.php");
+
+$info = new ClientInfo();
+
+$id = "ip";
+if (array_key_exists("PATH_INFO", $_SERVER)) {
+       $id = strtolower(substr($_SERVER["PATH_INFO"], 1));
+}
+
+header("Content-Type: text/plain; charset=UTF-8");
+header("Access-Control-Allow-Origin: *");
+
+switch ($id) {
+       case "ip":
+               print $info->getIP();
+               break;
+               
+       case "hostname":
+       case "host":
+       case "fqdn":
+               print $info->getHostname();
+               break;
+               
+       case "useragent":
+       case "user-agent":
+       case "ua":
+               print $info->getUserAgent("");
+               break;
+               
+       case "browser":
+       case "client":
+               print $info->getBrowser("");
+               break;
+               
+       case "os":
+       case "operatingsystem":
+       case "operating-system":
+               print $info->getOS("");
+               break;
+               
+       case "lang":
+       case "language":
+       case "locale":
+               print $info->getLanguage("");
+               break;
+               
+       case "country":
+               print $info->getGeoIPCountry();
+               break;
+               
+       case "region_code":
+               $region = $info->getGeoIPRegion();
+               if (is_array($region))
+                       print $region[0];
+               break;
+               
+       case "region":
+               $region = $info->getGeoIPRegion();
+               if (is_array($region))
+                       print $region[1];
+               break;
+               
+       case "city":
+               $city = $info->getGeoIPCity();
+               if ($city)
+                       print $city[0];
+               break;
+               
+       case "zip":
+       case "postal_code":
+               $city = $info->getGeoIPCity();
+               if ($city)
+                       print $city[1];
+               break;
+               
+       case "coordinates":
+       case "gps":
+               $city = $info->getGeoIPCity();
+               if ($city)
+                       print $city[2][0] . " " . $city[2][1];
+               break;
+               
+       case "latitude":
+               $city = $info->getGeoIPCity();
+               if ($city)
+                       print $city[2][0];
+               break;
+               
+       case "longitude":
+               $city = $info->getGeoIPCity();
+               if ($city)
+                       print $city[2][1];
+               break;
+               
+       default:
+               print "Error: Invalid query";
+               
+}
+
+?>
\ No newline at end of file
diff --git a/assets/css/98.css b/assets/css/98.css
new file mode 100644 (file)
index 0000000..0e5a2b4
--- /dev/null
@@ -0,0 +1,513 @@
+/**\r
+ * 98.css\r
+ * Copyright (c) 2020 Jordan Scales <thatjdanisso.cool>\r
+ * https://github.com/jdan/98.css/blob/master/LICENSE\r
+ */\r
+\r
+:root {\r
+  /* Color */\r
+  --surface: #c0c0c0;\r
+  --button-highlight: #ffffff;\r
+  --button-face: #dfdfdf;\r
+  --button-shadow: #808080;\r
+  --window-frame: #0a0a0a;\r
+  --dialog-blue: #000080;\r
+  --dialog-blue-light: #1084d0;\r
+  --link-blue: #0000ff;\r
+\r
+  /* Spacing */\r
+  --element-spacing: 8px;\r
+  --grouped-button-spacing: 4px;\r
+  --grouped-element-spacing: 6px;\r
+  --radio-width: 12px;\r
+  --checkbox-width: 13px;\r
+  --radio-label-spacing: 6px;\r
+\r
+  /* Some detailed computations for radio buttons and checkboxes */\r
+  --radio-total-width-precalc: 12px + 6px;\r
+  --radio-total-width: 18px;\r
+  --radio-left: -6px;\r
+  --radio-dot-width: 4px;\r
+  --radio-dot-top: 4px;\r
+  --radio-dot-left: -14px;\r
+\r
+  --checkbox-total-width-precalc: 13px +\r
+    6px;\r
+  --checkbox-total-width: 19px;\r
+  --checkbox-left: -7px;\r
+  --checkmark-width: 7px;\r
+  --checkmark-top: 3px;\r
+  --checkmark-left: 3px;\r
+\r
+  /* Borders */\r
+  --border-width: 1px;\r
+  --border-raised-outer: inset -1px -1px #0a0a0a,\r
+    inset 1px 1px #ffffff;\r
+  --border-raised-inner: inset -2px -2px #808080,\r
+    inset 2px 2px #dfdfdf;\r
+  --border-sunken-outer: inset -1px -1px #ffffff,\r
+    inset 1px 1px #0a0a0a;\r
+  --border-sunken-inner: inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #808080;\r
+\r
+  /* Field borders (checkbox, input, etc) flip window-frame and button-shadow */\r
+  --border-field: inset -1px -1px #ffffff,\r
+    inset 1px 1px #808080, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #0a0a0a;\r
+}\r
+\r
+* {\r
+  font-family: Arial;\r
+  font-size: 12px;\r
+  letter-spacing: -0.03ch;\r
+  -webkit-font-smoothing: none;\r
+  color: #222222;\r
+}\r
+\r
+h1 {\r
+  font-size: 5rem;\r
+}\r
+\r
+h2 {\r
+  font-size: 2.5rem;\r
+}\r
+\r
+h3 {\r
+  font-size: 2rem;\r
+}\r
+\r
+h4 {\r
+  font-size: 1.5rem;\r
+}\r
+\r
+u {\r
+  text-decoration: none;\r
+  border-bottom: 0.5px solid #222222;\r
+}\r
+\r
+button {\r
+  box-sizing: border-box;\r
+  border: none;\r
+  background: #c0c0c0;\r
+  box-shadow: inset -1px -1px #0a0a0a,\r
+    inset 1px 1px #ffffff, inset -2px -2px #808080,\r
+    inset 2px 2px #dfdfdf;\r
+\r
+  min-width: 75px;\r
+  min-height: 23px;\r
+  padding: 0 12px;\r
+}\r
+\r
+button:active {\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #0a0a0a, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #808080;\r
+}\r
+\r
+button:focus {\r
+  outline: 1px dotted #000000;\r
+  outline-offset: -4px;\r
+}\r
+\r
+:disabled {\r
+  color: #808080;\r
+  text-shadow: 1px 1px 0 #ffffff;\r
+}\r
+\r
+:disabled + label {\r
+  color: #808080;\r
+  text-shadow: 1px 1px 0 #ffffff;\r
+}\r
+\r
+.window {\r
+  box-shadow: inset -1px -1px #0a0a0a,\r
+    inset 1px 1px #ffffff, inset -2px -2px #808080,\r
+    inset 2px 2px #dfdfdf;\r
+  background: #c0c0c0;\r
+  padding: 3px;\r
+}\r
+\r
+.title-bar {\r
+  background: linear-gradient(\r
+    90deg,\r
+    #000080,\r
+    #1084d0\r
+  );\r
+  padding: 2px;\r
+  display: flex;\r
+  justify-content: space-between;\r
+  align-items: center;\r
+}\r
+\r
+.title-bar-text {\r
+  font-weight: bold;\r
+  color: white;\r
+  letter-spacing: 0;\r
+  margin-right: 24px;\r
+}\r
+\r
+.title-bar-controls {\r
+  display: flex;\r
+}\r
+\r
+.title-bar-controls button {\r
+  padding: 0;\r
+  display: block;\r
+  min-width: 14px;\r
+  min-height: 12px;\r
+}\r
+\r
+.title-bar-controls button:focus {\r
+  outline: none;\r
+}\r
+\r
+.title-bar-controls button[aria-label="Minimize"] {\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='6' height='2' viewBox='0 0 6 2' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Crect width='6' height='2' fill='black'/%3E %3C/svg%3E");\r
+  background-repeat: no-repeat;\r
+  background-position: bottom 2px left 3px;\r
+}\r
+\r
+.title-bar-controls button[aria-label="Maximize"] {\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='9' height='8' viewBox='0 0 9 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 2V7V8H1H8H9V7V2V0H8H1H0V2ZM8 7V2H1V7H8Z' fill='black'/%3E %3C/svg%3E");\r
+  background-repeat: no-repeat;\r
+  /* Off by 1px because contents can't go above the inner shadow */\r
+  /* Should be 9px by 9px, with top 1px */\r
+  background-position: top 2px left 2px;\r
+}\r
+\r
+.title-bar-controls button[aria-label="Close"] {\r
+  margin-left: 2px;\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='8' height='7' viewBox='0 0 8 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0H1H2V1H3V2H4H5V1H6V0H7H8V1H7V2H6V3H5V4H6V5H7V6H8V7H7H6V6H5V5H4H3V6H2V7H1H0V6H1V5H2V4H3V3H2V2H1V1H0V0Z' fill='black'/%3E %3C/svg%3E");\r
+  background-repeat: no-repeat;\r
+  background-position: top 2px center;\r
+}\r
+\r
+.window-body {\r
+  margin: 8px;\r
+}\r
+\r
+fieldset {\r
+  border: none;\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #0a0a0a, inset -2px -2px #808080,\r
+    inset 2px 2px #dfdfdf;\r
+  padding: 10px;\r
+  padding-block-start: 8px;\r
+  margin: 0;\r
+}\r
+\r
+legend {\r
+  background: #c0c0c0;\r
+}\r
+\r
+.field-row {\r
+  display: flex;\r
+  align-items: center;\r
+}\r
+\r
+[class^="field-row"] + [class^="field-row"] {\r
+  margin-top: 6px;\r
+}\r
+\r
+.field-row * + * {\r
+  margin-left: 6px;\r
+}\r
+\r
+.field-row-stacked {\r
+  display: flex;\r
+  flex-direction: column;\r
+}\r
+\r
+.field-row-stacked * + * {\r
+  margin-top: 6px;\r
+}\r
+\r
+label {\r
+  display: inline-flex;\r
+  line-height: 1;\r
+  align-items: center;\r
+}\r
+\r
+input[type="radio"],\r
+input[type="checkbox"] {\r
+  appearance: none;\r
+  -webkit-appearance: none;\r
+  -moz-appearance: none;\r
+  margin: 0;\r
+  border: none;\r
+}\r
+\r
+input[type="radio"] + label {\r
+  position: relative;\r
+  margin-left: 18px;\r
+}\r
+\r
+input[type="radio"] + label::before {\r
+  content: "";\r
+  position: absolute;\r
+  left: -18px;\r
+  display: inline-block;\r
+  width: 12px;\r
+  height: 12px;\r
+  margin-right: 6px;\r
+  background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='white'/%3E %3C/svg%3E");\r
+}\r
+\r
+input[type="radio"]:checked + label::after {\r
+  content: "";\r
+  display: block;\r
+  width: 4px;\r
+  height: 4px;\r
+  top: 4px;\r
+  left: -14px;\r
+  position: absolute;\r
+  background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='4' height='4' viewBox='0 0 4 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M3 0H1V1H0V2V3H1V4H3V3H4V2V1H3V0Z' fill='black'/%3E %3C/svg%3E");\r
+}\r
+\r
+input[type="radio"]:focus + label,\r
+input[type="checkbox"]:focus + label {\r
+  outline: 1px dotted #000000;\r
+}\r
+\r
+input[type="radio"][disabled] + label::before {\r
+  background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='%23C0C0C0'/%3E %3C/svg%3E");\r
+}\r
+\r
+input[type="radio"][disabled]:checked + label::after {\r
+  background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='4' height='4' viewBox='0 0 4 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M3 0H1V1H0V2V3H1V4H3V3H4V2V1H3V0Z' fill='%23808080'/%3E %3C/svg%3E");\r
+}\r
+\r
+input[type="checkbox"] + label {\r
+  position: relative;\r
+  margin-left: 19px;\r
+}\r
+\r
+input[type="checkbox"] + label::before {\r
+  content: "";\r
+  position: absolute;\r
+  left: -19px;\r
+  display: inline-block;\r
+  width: 13px;\r
+  height: 13px;\r
+  background: #ffffff;\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #808080, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #0a0a0a;\r
+  margin-right: 6px;\r
+}\r
+\r
+input[type="checkbox"]:checked + label::after {\r
+  content: "";\r
+  display: block;\r
+  width: 7px;\r
+  height: 7px;\r
+  position: absolute;\r
+  top: 3px;\r
+  left: -16px;\r
+  background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='7' height='7' viewBox='0 0 7 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 0H6V1H5V2H4V3H3V4H2V3H1V2H0V5H1V6H2V7H3V6H4V5H5V4H6V3H7V0Z' fill='black'/%3E %3C/svg%3E");\r
+}\r
+\r
+input[type="checkbox"][disabled] + label::before {\r
+  background: #c0c0c0;\r
+}\r
+\r
+input[type="checkbox"][disabled]:checked + label::after {\r
+  background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='7' height='7' viewBox='0 0 7 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 0H6V1H5V2H4V3H3V4H2V3H1V2H0V5H1V6H2V7H3V6H4V5H5V4H6V3H7V0Z' fill='%23808080'/%3E %3C/svg%3E");\r
+}\r
+\r
+input[type="text"] {\r
+  padding: 3px 4px;\r
+  border: none;\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #808080, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #0a0a0a;\r
+  background-color: #ffffff;\r
+  box-sizing: border-box;\r
+}\r
+\r
+select {\r
+  padding: 3px 4px;\r
+  border: none;\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #808080, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #0a0a0a;\r
+  background-color: #ffffff;\r
+  box-sizing: border-box;\r
+}\r
+\r
+textarea {\r
+  padding: 3px 4px;\r
+  border: none;\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #808080, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #0a0a0a;\r
+  background-color: #ffffff;\r
+  box-sizing: border-box;\r
+}\r
+\r
+input[type="text"],\r
+select {\r
+  height: 21px;\r
+}\r
+\r
+input[type="text"] {\r
+  /* For some reason descenders are getting cut off without this */\r
+  line-height: 2;\r
+}\r
+\r
+select {\r
+  appearance: none;\r
+  -webkit-appearance: none;\r
+  -moz-appearance: none;\r
+  position: relative;\r
+  padding-right: 32px;\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' viewBox='0 0 16 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 0H0V1V16H1V1H15V0Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 1H1V15H2V2H14V1H2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 17H15H0V16H15V0H16V17Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 1H14V15H1V16H14H15V1Z' fill='%23808080'/%3E %3Crect x='2' y='2' width='12' height='13' fill='%23C0C0C0'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 6H4V7H5V8H6V9H7V10H8V9H9V8H10V7H11V6Z' fill='black'/%3E %3C/svg%3E");\r
+  background-position: top 2px right 2px;\r
+  background-repeat: no-repeat;\r
+}\r
+\r
+select:focus,\r
+input[type="text"]:focus,\r
+textarea:focus {\r
+  outline: none;\r
+}\r
+\r
+select:focus {\r
+  color: #ffffff;\r
+  background-color: #000080;\r
+}\r
+select:focus option {\r
+  color: #000;\r
+  background-color: #fff;\r
+}\r
+\r
+select:active {\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' viewBox='0 0 16 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0H15H16V17H15H0V16V1V0ZM1 16H15V1H1V16Z' fill='%23808080'/%3E %3Crect x='1' y='1' width='14' height='15' fill='%23C0C0C0'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 7H5V8H6V9H7V10H8V11H9V10H10V9H11V8H12V7Z' fill='black'/%3E %3C/svg%3E");\r
+}\r
+\r
+a {\r
+  color: #0000ff;\r
+}\r
+\r
+a:focus {\r
+  outline: 1px dotted #0000ff;\r
+}\r
+\r
+ul.tree-view {\r
+  display: block;\r
+  background: #ffffff;\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #808080, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #0a0a0a;\r
+  padding: 6px;\r
+  margin: 0;\r
+}\r
+\r
+ul.tree-view li {\r
+  list-style-type: none;\r
+}\r
+\r
+ul.tree-view a {\r
+  text-decoration: none;\r
+  color: #000;\r
+}\r
+\r
+ul.tree-view a:focus {\r
+  background-color: #000080;\r
+  color: #ffffff;\r
+}\r
+\r
+ul.tree-view ul,\r
+ul.tree-view li {\r
+  margin-top: 3px;\r
+}\r
+\r
+ul.tree-view ul {\r
+  margin-left: 16px;\r
+  padding-left: 16px;\r
+  /* Goes down too far */\r
+  border-left: 1px dotted #808080;\r
+}\r
+\r
+ul.tree-view ul > li {\r
+  position: relative;\r
+}\r
+ul.tree-view ul > li::before {\r
+  content: "";\r
+  display: block;\r
+  position: absolute;\r
+  left: -16px;\r
+  top: 6px;\r
+  width: 12px;\r
+  border-bottom: 1px dotted #808080;\r
+}\r
+\r
+/* Cover the bottom of the left dotted border */\r
+ul.tree-view ul > li:last-child::after {\r
+  content: "";\r
+  display: block;\r
+  position: absolute;\r
+  left: -20px;\r
+  top: 7px;\r
+  bottom: 0px;\r
+  width: 8px;\r
+  background: #ffffff;\r
+}\r
+\r
+pre {\r
+  display: block;\r
+  background: #ffffff;\r
+  box-shadow: inset -1px -1px #ffffff,\r
+    inset 1px 1px #808080, inset -2px -2px #dfdfdf,\r
+    inset 2px 2px #0a0a0a;\r
+  padding: 12px 8px;\r
+  margin: 0;\r
+}\r
+\r
+code,\r
+code * {\r
+  font-family: monospace;\r
+}\r
+\r
+summary:focus {\r
+  outline: 1px dotted #000000;\r
+}\r
+\r
+::-webkit-scrollbar {\r
+  width: 16px;\r
+}\r
+::-webkit-scrollbar:horizontal {\r
+  height: 17px;\r
+}\r
+\r
+::-webkit-scrollbar-corner {\r
+  background: #dfdfdf;\r
+}\r
+\r
+::-webkit-scrollbar-track {\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='2' height='2' viewBox='0 0 2 2' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M1 0H0V1H1V2H2V1H1V0Z' fill='%23C0C0C0'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 0H1V1H0V2H1V1H2V0Z' fill='white'/%3E %3C/svg%3E");\r
+}\r
+\r
+::-webkit-scrollbar-thumb {\r
+  background-color: #dfdfdf;\r
+  box-shadow: inset -1px -1px #0a0a0a,\r
+    inset 1px 1px #ffffff, inset -2px -2px #808080,\r
+    inset 2px 2px #dfdfdf;\r
+}\r
+\r
+::-webkit-scrollbar-button:vertical:start {\r
+  height: 17px;\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' viewBox='0 0 16 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 0H0V1V16H1V1H15V0Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 1H1V15H2V2H14V1H2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 17H15H0V16H15V0H16V17Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 1H14V15H1V16H14H15V1Z' fill='%23808080'/%3E %3Crect x='2' y='2' width='12' height='13' fill='%23C0C0C0'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 6H7V7H6V8H5V9H4V10H11V9H10V8H9V7H8V6Z' fill='black'/%3E %3C/svg%3E");\r
+}\r
+::-webkit-scrollbar-button:vertical:end {\r
+  height: 17px;\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' viewBox='0 0 16 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 0H0V1V16H1V1H15V0Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 1H1V15H2V2H14V1H2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 17H15H0V16H15V0H16V17Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 1H14V15H1V16H14H15V1Z' fill='%23808080'/%3E %3Crect x='2' y='2' width='12' height='13' fill='%23C0C0C0'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 6H4V7H5V8H6V9H7V10H8V9H9V8H10V7H11V6Z' fill='black'/%3E %3C/svg%3E");\r
+}\r
+::-webkit-scrollbar-button:horizontal:start {\r
+  width: 16px;\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' viewBox='0 0 16 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 0H0V1V16H1V1H15V0Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 1H1V15H2V2H14V1H2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 17H15H0V16H15V0H16V17Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 1H14V15H1V16H14H15V1Z' fill='%23808080'/%3E %3Crect x='2' y='2' width='12' height='13' fill='%23C0C0C0'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 4H8V5H7V6H6V7H5V8H6V9H7V10H8V11H9V4Z' fill='black'/%3E %3C/svg%3E");\r
+}\r
+::-webkit-scrollbar-button:horizontal:end {\r
+  width: 16px;\r
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='17' viewBox='0 0 16 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 0H0V1V16H1V1H15V0Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M2 1H1V15H2V2H14V1H2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 17H15H0V16H15V0H16V17Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15 1H14V15H1V16H14H15V1Z' fill='%23808080'/%3E %3Crect x='2' y='2' width='12' height='13' fill='%23C0C0C0'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 4H6V11H7V10H8V9H9V8H10V7H9V6H8V5H7V4Z' fill='black'/%3E %3C/svg%3E");\r
+}\r
diff --git a/assets/css/ipinfo98.css b/assets/css/ipinfo98.css
new file mode 100644 (file)
index 0000000..497e261
--- /dev/null
@@ -0,0 +1,35 @@
+@charset "UTF-8";
+*, *:before, *:after {
+       box-sizing: border-box;
+}
+body {
+       background: #00807F;
+}
+.window {
+       width: 450px;
+       max-width: 100%;
+       margin: 80px auto 50px;
+}
+main.maximized {
+       position: absolute;
+       left: 0;
+       right: 0;
+       top: 0;
+       bottom: 0;
+}
+main.maximized .window {
+       height: 100%;
+       width: 100%;
+       margin: 0;
+}
+label {
+       display: inline-block;
+       width: 20%;
+}
+input {
+       display: inline-block;
+       width: 80%;
+}
+p {
+       text-align: right;
+}
\ No newline at end of file
diff --git a/assets/css/style.css b/assets/css/style.css
new file mode 100644 (file)
index 0000000..24acdbb
--- /dev/null
@@ -0,0 +1,94 @@
+@charset "UTF-8";
+/**
+ * Stylesheet for ip.malte70.de
+ */
+
+@import url(https://fonts.googleapis.com/css?family=Source+Serif+Pro|Source+Sans+Pro|Inconsolata&subset=latin,latin-ext);
+
+*,
+*:before,
+*:after {
+       box-sizing: border-box;
+}
+
+html {
+       margin: 0;
+       padding: 0;
+}
+body {
+       margin: 0;
+       padding: 0;
+       background: #EDEBE6;
+       font: 18px "Source Serif Pro", serif;
+       color: #403B33;
+}
+
+a:link,
+a:visited {
+       color: #A40114;
+}
+a:hover,
+a:active {
+       color: #94C7B6;
+}
+.text-center {
+       text-align: center;
+       margin-bottom: 8em;
+}
+
+h1 {
+       margin: 0;
+       padding: 14px 10px 10px;
+       text-align: center;
+       border-bottom: 4px solid #94c7b6;
+       background: #94c7b6;
+}
+h1 a:link, h1 a:visited {
+       color: #403B33;
+       text-decoration: none;
+}
+h1 a:hover, h1 a:active {
+       /*color: #94c7b6;*/
+       text-decoration: underline;
+}
+h2 {
+       font: 1.6em "Source Sans Pro", sans-serif;
+       font-weight: normal;
+}
+main {
+       margin: 1em .5em 2em;
+}
+@media (min-width: 800px) {
+       main {
+               margin-left: auto;
+               margin-right: auto;
+               width: 600px;
+       }
+}
+
+main h3, main .lead {
+       font: 1.3em "Source Sans Pro", sans-serif;
+       font-weight: normal;
+}
+
+main .lead {
+    margin-top: 3em;
+}
+
+main p.info {
+       /*font-family: "Source Code Pro", monospace;*/
+       font-family: "Inconsolata", monospace;
+}
+
+footer {
+       font: 0.7em "Inconsolata", monospace;
+       text-align: center;
+}
+footer p {
+       margin: .5em 0;
+}
+footer a:link,
+footer a:visited {
+       color: #403B33;
+       text-decoration: underline;
+}
diff --git a/assets/img/favicon.png b/assets/img/favicon.png
new file mode 100644 (file)
index 0000000..c993918
Binary files /dev/null and b/assets/img/favicon.png differ
diff --git a/assets/img/favicon98.png b/assets/img/favicon98.png
new file mode 100644 (file)
index 0000000..e65b07b
Binary files /dev/null and b/assets/img/favicon98.png differ
diff --git a/assets/js/getipv4.js b/assets/js/getipv4.js
new file mode 100644 (file)
index 0000000..c38ccea
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * ip.malte70.de/assets/js/getipv4.js
+ * 
+ * Get IPv4 address if site is accessed via IPv6
+ */
+
+$(function(){
+       api_url_v4         = "https://ip4.malte70.de/api.php";
+       api_url_v6         = "https://ip6.malte70.de/api.php";
+       elem_ipv4          = $("#ipv4");
+       elem_ipv6          = $("#ipv6");
+       elem_ipv6_headline = $("#ipv6_headline");
+       
+       if (elem_ipv6.html().length > 4) {
+               // Site accessed via IPv6, so dynamically add IPv4
+               $.get(api_url_v4, function(data) {
+                       elem_ipv4.html(data);
+               });
+               
+       } else {
+               // Site accessed via IPv4, so remove IPv6 blocks
+               console.log("IPv4 access detected!");
+               elem_ipv6_headline.remove();
+               elem_ipv6.remove();
+       }
+});
\ No newline at end of file
diff --git a/assets/otf/SourceCodePro-Regular.otf b/assets/otf/SourceCodePro-Regular.otf
new file mode 100644 (file)
index 0000000..1bae002
Binary files /dev/null and b/assets/otf/SourceCodePro-Regular.otf differ
diff --git a/assets/otf/SourceCodePro-Semibold.otf b/assets/otf/SourceCodePro-Semibold.otf
new file mode 100644 (file)
index 0000000..a61686c
Binary files /dev/null and b/assets/otf/SourceCodePro-Semibold.otf differ
diff --git a/clientinfo.class.php b/clientinfo.class.php
new file mode 100644 (file)
index 0000000..e751843
--- /dev/null
@@ -0,0 +1,635 @@
+<?php
+/**
+ * clientinfo.class.php
+ *     ClientInfo class, responsible for detecting
+ *     all the information
+ */
+
+class ClientInfo {
+       private $IP= "";
+       private $realIP = "";
+       private $hostname = "";
+       private $userAgent = "";
+       private $browser = "";
+       private $OS = "";
+       private $language = "";
+       private $geoip_db_country_available = FALSE;
+       private $geoip_db_region_available = FALSE;
+       private $geoip_db_city_available = FALSE;
+       private $geoip_country = "";
+       private $geoip_region = "";
+       private $geoip_city = "";
+       
+    public function getIP() {
+        if (empty($this->IP)) {
+            $this->IP = $_SERVER["REMOTE_ADDR"];
+        }
+        
+        return $this->IP;
+    }
+    public function isIPv6() {
+        return stristr($this->getIP(), ":");
+       }
+       public function getRealIP() {
+               if (empty($this->realIP)) {
+                       if (@!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
+                               $this->realIP = $_SERVER["HTTP_X_FORWARDED_FOR"];
+                       } elseif (@!empty($_SERVER["HTTP_CLIENT_IP"])) {
+                               $this->realIP = $_SERVER["HTTP_CLIENT_IP"];
+                       }
+               }
+               
+               return $this->realIP;
+       }
+    public function getHostname() {
+        if (empty($this->hostname)) {
+            $this->hostname = gethostbyaddr(
+                $this->getIP()
+            );
+        }
+        
+        return $this->hostname;
+    }
+    public function getUserAgent() {
+        if (empty($this->userAgent)) {
+            $this->userAgent = $_SERVER["HTTP_USER_AGENT"];
+        }
+        
+        return $this->userAgent;
+    }
+       
+       public function getBrowser($fallback = "Unknown") {
+               if (empty($this->browser)) {
+                       $ua = $this->getUserAgent();
+                       
+                       if (stripos($ua, "PaleMoon") !== false) {
+                               $this->browser = "Pale Moon";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "PaleMoon/"
+                               ) + strlen("PaleMoon/");
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "K-Meleon") !== false) {
+                               $this->browser = "K-Meleon";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "K-Meleon/"
+                               ) + strlen("K-Meleon/");
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "Firefox") !== false) {
+                               $this->browser = "Mozilla Firefox";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Firefox/"
+                               ) + strlen("Firefox/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "FxiOS") !== false) {
+                               $this->browser = "Mozilla Firefox";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "FxiOS/"
+                               ) + strlen("FxiOS/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "Edge") !== false) {
+                               $this->browser = "Microsoft Edge";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Edge/"
+                               ) + strlen("Edge/");
+                               
+                               $version = substr($ua, $pos_version_start);
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "EdgA") !== false) {
+                               $this->browser = "Microsoft Edge for Android";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "EdgA/"
+                               ) + strlen("EdgA/");
+                               
+                               $version = substr($ua, $pos_version_start);
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "MSIE") !== false) {
+                               $this->browser = "Microsoft Internet Explorer";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "MSIE"
+                               ) + strlen("MSIE ");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       ";",
+                                       $pos_version_start
+                               );
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "QupZilla") !== false) {
+                               $this->browser = "QupZilla";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "QupZilla/"
+                               ) + strlen("QupZilla/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "Vivaldi") !== false) {
+                               $this->browser = "Vivaldi";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Vivaldi/"
+                               ) + strlen("Vivaldi/");
+                               
+                               $version = explode(
+                                       ".",
+                                       substr(
+                                               $ua,
+                                               $pos_version_start
+                                       )
+                               );
+                               
+                               $this->browser .= " " . $version[0] . "." . $version[1];
+                               
+                       } elseif (stripos($ua, "OPR") !== false) {
+                               $this->browser = "Opera";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "OPR/"
+                               ) + strlen("OPR/");
+                               $version = explode(
+                                       ".",
+                                       substr(
+                                               $ua,
+                                               $pos_version_start
+                                       )
+                               );
+                               
+                               $this->browser .= " " . $version[0] . "." . $version[1];
+                               
+                       } elseif (stripos($ua, "Otter") !== false) {
+                               $this->browser = "Otter";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Otter/"
+                               ) + strlen("Otter/");
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "PlayStation 4") !== false) {
+                               $this->browser = "PlayStation 4 Browser";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "PlayStation 4 "
+                               ) + strlen("PlayStation 4 ");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       ")",
+                                       $pos_version_start
+                               );
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "Valve Steam GameOverlay") !== false) {
+                               $this->browser = "Steam Game-Overlay";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "GameOverlay/"
+                               ) + strlen("GameOverlay/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       ";",
+                                       $pos_version_start
+                               );
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               $this->browser .= " " . $version;
+                               
+            } elseif (stripos($ua, "Eolie") !== false) {
+                $this->browser = "Eolie";
+                
+                       } elseif (stripos($ua, "Chrome") !== false) {
+                               $this->browser = "Google Chrome";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Chrome/"
+                               ) + strlen("Chrome/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               $version = explode(
+                                       ".",
+                                       substr(
+                                               $ua,
+                                               $pos_version_start,
+                                               $pos_version_end - $pos_version_start
+                                       )
+                               );
+                               $version = $version[0] . "." . $version[1];
+                               if (stripos($ua, "Mobile") !== false) {
+                                       // Mobile Chrome (Android)
+                                       $this->browser .= " Mobile";
+                               }
+                               $this->browser .= " " . $version;
+                               
+                       } else if (stripos($ua, "Epiphany") !== false) {
+                               $this->browser = "GNOME Web (Epiphany)";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Epiphany/"
+                               ) + strlen("Epiphany/");
+                               /*$pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );*/
+                               $pos_version_end = strlen($ua);
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               
+                               //$this->browser .= " " . $version;
+                               
+                       } else if (stripos($ua, "Safari") !== false) {
+                               $this->browser = "Apple Safari";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Version/"
+                               ) + strlen("Version/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "ELinks") !== false) {
+                               $this->browser = "ELinks";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "ELinks/"
+                               ) + strlen("ELinks/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               //$version = $version[0] . "." . $version[1];
+                               $this->browser .= " " . $version;
+                               
+                       } elseif (stripos($ua, "NetSurf") !== false) {
+                               $this->browser = "NetSurf";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "NetSurf/"
+                               ) + strlen("NetSurf/");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               $version = substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                               $this->browser .= " " . $version;
+                               
+                       } else {
+                               $this->browser = $fallback;
+                       }
+               }
+               
+               return $this->browser;
+       }
+       
+       public function getOS($fallback = "Unknown") {
+               if (empty($this->OS)) {
+                       $this->OS = "AbsolutelyEpicOS";
+                       
+                       $ua = $this->getUserAgent();
+                       if (stripos($ua, "Android") !== false) {
+                               // Check for Android before checking for GNU/Linux,
+                               // since (at least) Android's Chrome identifies itself
+                               // as “Linux”, since it simply is.
+                               $this->OS = "Android ";
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "Android"
+                               ) + strlen("Android");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       ";",
+                                       $pos_version_start
+                               );
+                               $this->OS .= substr(
+                                       $ua,
+                                       $pos_version_start,
+                                       $pos_version_end - $pos_version_start
+                               );
+                       } elseif (stripos($ua, "PlayStation 4") !== false) {
+                               $this->OS = "PlayStation 4 System";
+                               
+                       } elseif (stripos($ua, "FreeBSD") !== false) {
+                               $this->OS = "FreeBSD";
+                               
+                       } elseif (stripos($ua, "DragonFly") !== false) {
+                               $this->OS = "DragonFly BSD";
+                               
+                       } elseif (stripos($ua, "OpenBSD") !== false) {
+                               $this->OS = "OpenBSD";
+                               
+                       } elseif (stripos($ua, "Windows") !== false) {
+                               $this->OS = "MS Windows";
+                               
+                               if (stripos($ua, "Windows NT 10.0") !== false || stripos($ua, "Windows 10") !== false) {
+                                       $this->OS .= " 10";
+                               } else if (stripos($ua, "Windows NT 6.3") !== false || stripos($ua, "Windows 8.1") !== false) {
+                                       $this->OS .= " 8.1";
+                               } else if (stripos($ua, "Windows NT 6.2") !== false || stripos($ua, "Windows 8") !== false) {
+                                       $this->OS .= " 8";
+                               } else if (stripos($ua, "Windows NT 6.1") !== false || stripos($ua, "Windows 7") !== false) {
+                                       $this->OS .= " 7";
+                               } else if (stripos($ua, "Windows NT 6.0") !== false || stripos($ua, "Windows Vista") !== false) {
+                                       $this->OS .= " Vista";
+                               } else if (stripos($ua, "Windows NT 5.1") !== false || stripos($ua, "Windows XP") !== false) {
+                                       $this->OS .= " XP";
+                               }
+                               
+                       } elseif (stripos($ua, "Linux") !== false) {
+                               $this->OS = "GNU/Linux";
+                               
+                       } elseif (stripos($ua, "iPhone OS") !== false) {
+                               $this->OS = "iOS";
+                               
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "iPhone OS"
+                               ) + strlen("iPhone OS ");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               $version = explode(
+                                       "_",
+                                       substr(
+                                               $ua,
+                                               $pos_version_start,
+                                               $pos_version_end - $pos_version_start
+                                       )
+                               );
+                               
+                               $this->OS .= " " . implode($version, ".");
+                               
+                       } elseif (stripos($ua, "iPhone") !== false) {
+                               $this->OS = "iOS";
+                               
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "CPU OS"
+                               ) + strlen("CPU OS ");
+                               $pos_version_end = stripos(
+                                       $ua,
+                                       " ",
+                                       $pos_version_start
+                               );
+                               $version = explode(
+                                       "_",
+                                       substr(
+                                               $ua,
+                                               $pos_version_start,
+                                               $pos_version_end - $pos_version_start
+                                       )
+                               );
+                               
+                               $this->OS .= " " . implode($version, ".");
+                               
+                       } elseif (stripos($ua, "Macintosh") !== false) {
+                               $this->OS = "Apple OS X";
+                               
+                               $pos_version_start = stripos(
+                                       $ua,
+                                       "OS X"
+                               ) + strlen("OS X ");
+                               $pos_version_bracket = stripos(
+                                       $ua,
+                                       ")",
+                                       $pos_version_start
+                               );
+                               $pos_version_semicolon = stripos(
+                                       $ua,
+                                       ";",
+                                       $pos_version_start
+                               );
+                               if ($pos_version_bracket > 1 && $pos_version_semicolon > 1) {
+                                       $pos_version_end = min(
+                                               $pos_version_bracket,
+                                               $pos_version_semicolon
+                                       );
+                               } elseif ($pos_version_bracket > 1) {
+                                       $pos_version_end = $pos_version_bracket;
+                               } else {
+                                       $pos_version_end = $pos_version_semicolon;
+                               }
+                               $version = explode(
+                                       "_",
+                                       substr(
+                                               $ua,
+                                               $pos_version_start,
+                                               $pos_version_end - $pos_version_start
+                                       )
+                               );
+                               
+                               $this->OS .= " " . implode($version, ".");
+                       } else {
+                               $this->OS = $fallback;
+                               
+                       }
+               }
+               
+               return $this->OS;
+       }
+       
+       public function getLanguage($fallback = "en") {
+               if (empty($this->language)) {
+                       $accept_languages = @$_SERVER["HTTP_ACCEPT_LANGUAGE"];
+                       if (empty($accept_languages)) {
+                               $this->language = $fallback;
+                               return $this->language;
+                       }
+                       
+                       $this->language = explode(
+                               ";",
+                               explode(
+                                       ",",
+                                       $accept_languages
+                               )[0]
+                       )[0];
+                       // Fix to look right (de_DE, not de-DE)
+                       $this->language = str_replace(
+                               "-",
+                               "_",
+                               $this->language
+                       );
+               }
+               
+               return $this->language;
+       }
+       
+       public function getGeoIPCountry() {
+               if ($this->geoip_country!==FALSE && empty($this->geoip_country)) {
+                       if ($this->geoip_db_country_available) {
+                               $this->geoip_country = geoip_country_name_by_name($this->getIP());
+                       }
+               }
+               
+               return $this->geoip_country;
+       }
+       
+       public function getGeoIPRegion() {
+               if ($this->geoip_region!==FALSE && empty($this->geoip_region)) {
+                       if ($this->geoip_db_region_available) {
+                               $record = geoip_region_by_name($this->getIP());
+                               if ($record===FALSE) {
+                                       $this->geoip_region = FALSE;
+                                       
+                               } else {
+                                       $this->geoip_region = Array(
+                                               $record["region"],
+                                               geoip_region_name_by_code(
+                                                       $record["country_code"],
+                                                       $record["region"]
+                                               )
+                                       );
+                                       
+                               }
+                       }
+               }
+               
+               return $this->geoip_region;
+       }
+       
+       public function getGeoIPCity() {
+               if ($this->geoip_city!==FALSE && empty($this->geoip_city)) {
+                       if ($this->geoip_db_city_available) {
+                               $record = geoip_record_by_name($this->getIP());
+
+                               $this->geoip_city = Array(
+                                       $record["city"],
+                                       $record["postal_code"],
+                                       Array(
+                                               $record["latitude"],
+                                               $record["longitude"]
+                                       )
+                               );
+                       }
+               }
+               
+               return $this->geoip_city;
+       }
+       
+       public function getGeoIPCoordinates() {
+               $city = $this->getGeoIPCity();
+               if ($city !== FALSE) {
+                       $coord = $city[2];
+               } else {
+                       $coord = FALSE;
+               }
+
+               return $coord;
+       }
+       public function __construct() {
+               $this->geoip_db_country_available = TRUE; //geoip_db_avail(GEOIP_COUNTRY_EDITION);
+               $this->geoip_db_region_available  = FALSE; //geoip_db_avail(GEOIP_REGION_EDITION_REV1);
+               $this->geoip_db_city_available    = TRUE; //geoip_db_avail(GEOIP_CITY_EDITION_REV1);
+       }
+}
+
+?>
diff --git a/config.inc.php b/config.inc.php
new file mode 100644 (file)
index 0000000..eb52c10
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/**
+ * config.inc.php
+ *     Application info and configuration
+ *
+ */
+
+/**
+ * Basic application info
+ */
+$AppInfo = Array(
+       "Name"      => "ip.malte70.de",
+       "URL"       => "https://github.com/projekt-ancistrus/ipinfo",
+       "Copyright" => Array(
+               "Year"       => "2016-".date("Y"),
+               "AuthorName" => "malte70",
+               "AuthorLink" => "https://malte70.de/"
+       )
+);
+
+
+/**
+ * Configuration for the widget
+ * 
+ * Array keys should be mostly self-explaining; colors
+ * are given as RGB values. Y start coordinates are measured
+ * from the lower left corner of the first character, so don't
+ * forget to add the font size to a margin from top upper left
+ * image corner!
+ */
+$WidgetConfig = Array(
+       "Type"            => "image/png",
+       "Size"            => Array(320, 200),
+//     "BackgroundColor" => Array( 17,  17,  17),
+//     "TextColor"       => Array(  1, 255, 112),
+//     "HeadingColor"    => Array(255, 255, 255),
+       "BackgroundColor" => Array(237, 235, 230),
+       "TextColor"       => Array(164,   1,  20),
+       "HeadingColor"    => Array(  0,   0,   0),
+       "FontSize"        => 12,
+       "FontFamily"      => "assets/otf/SourceCodePro-Regular.otf",
+       "FontSizeBig"     => 13,
+       "FontFamilyBig"   => "assets/otf/SourceCodePro-Semibold.otf",
+       "YCoords"         => Array(
+               "Title"   => Array( 32,  40),
+               "IP"      => Array( 60,  85),
+               "Browser" => Array(110, 130),
+               "OS"      => Array(155, 175),
+       ),
+);
+
+@$debug = in_array(
+       strtolower($_GET["debug"]),
+       Array(
+               "yes",
+               "on",
+               "true"
+       )
+);
+if ($debug) {
+       error_reporting(E_ALL);
+       ini_set("display_errors", "On");
+}
+
+?>
\ No newline at end of file
diff --git a/debug.php b/debug.php
new file mode 100644 (file)
index 0000000..05cbd99
--- /dev/null
+++ b/debug.php
@@ -0,0 +1,7 @@
+<?php
+
+header("Content-type: text/plain; charset=UTF-8");
+
+print_r(
+       geoip_db_get_all_info()
+);
diff --git a/index.php b/index.php
new file mode 100644 (file)
index 0000000..b4377c4
--- /dev/null
+++ b/index.php
@@ -0,0 +1,76 @@
+<?php
+/*
+https://mirrors-cdn.liferay.com/geolite.maxmind.com/download/geoip/database/
+*/
+
+require_once("config.inc.php");
+require_once("clientinfo.class.php");
+
+require_once("ad.inc.php");
+
+$info = new ClientInfo();
+
+if (stripos("validator", $_SERVER["HTTP_USER_AGENT"]) !== false) {
+       $target_new = "_blank";
+} else {
+       $target_new = "_new";
+}
+
+$c = "<section class=\"text-center\">\n";
+$c .= " \t<h2>" . $info->getIP() . "</h2>\n";
+$c .= "\t<p>\n\t\t";
+$c .= '<b><a href="info.php">Details</a></b>';
+$c .= " \n\t</p>\n";
+$c .= "\t<p>\n\t\t";
+$c .= '<a href="https://speedtest.malte70.de" target="'.$target_new.'">Speedtest</a>';
+$c .= " \n\t</p>\n";
+$c .= get_ad();
+$c .= "</section>\n";
+
+$contentData = Array(
+       "Main" => $c
+);
+$footerData = Array(
+       "© " . $AppInfo["Copyright"]["Year"] . ' <a href="' . $AppInfo["Copyright"]["AuthorLink"] . '" rel="me nofollow">' . $AppInfo["Copyright"]["AuthorName"] . '</a>',
+       'Powered by <a href="' . $AppInfo["URL"] . '">' . $AppInfo["Name"] . '</a>',
+       '<a href="API.md">API</a>'
+);
+
+$lang = substr(
+       $info->getLanguage(),
+       0,
+       2
+);
+if ($lang == "de") {
+       $msg_your_ip = "Deine IP–Adresse";
+} else {
+       $msg_your_ip = "Your IP";
+}
+$Data = Array(
+       "Meta" => Array(
+               "Lang" => $lang,
+               "Charset" => "UTF-8",
+               "Title" => $msg_your_ip . " :: " . $AppInfo["Name"],
+               "Author" => "Malte Bublitz",
+               "HumansTXT" => false,
+               "Stylesheet" => "assets/css/style.css"
+       ),
+       "Content" => Array(
+               "Header" => Array(
+                       "LinkURL" => "./",
+                       "Title" => $msg_your_ip
+               ),
+               "Content" => $contentData,
+               "Footer" => $footerData
+       )
+);
+
+if ($debug) {
+       header("Content-Type: text/plain; charset=".$Data["Meta"]["Charset"]);
+       print "==> \$Data\n";
+       print_r($Data);
+} else {
+       require_once("template.inc.php");
+}
+
+?>
\ No newline at end of file
diff --git a/info.php b/info.php
new file mode 100644 (file)
index 0000000..31b7d76
--- /dev/null
+++ b/info.php
@@ -0,0 +1,128 @@
+<?php
+
+require_once("config.inc.php");
+require_once("clientinfo.class.php");
+
+$info = new ClientInfo();
+
+$hostContent =$info->getIP();
+if ($info->getHostname() != $info->getIP()) {
+       $hostContent .= " / " . $info->getHostname();
+}
+$lang = substr(
+       $info->getLanguage(),
+       0,
+       2
+);
+function getMsg($lang, $id) {
+       global $info;
+       $is_ipv6 = $info->isIPv6();
+       $Translations = Array(
+               "de" => Array(
+                       "Title"   => "Deine IP",
+                       "IP"      => "IP-Adresse" . ($is_ipv6 ? " (IPv6)" : " (IPv4)"),
+                       "IPv4"    => "IP-Adresse (IPv4)",
+                       "IPv6"    => "IP-Adresse (IPv6)",
+                       "Browser" => "Browser",
+                       "OS"      => "Betriebssystem",
+                       "Lang"    => "Sprache",
+                       "UA"      => "User-Agent",
+                       "Loc"     => "Ort"
+               ),
+               "en" => Array(
+                       "Title"   => "Your IP",
+                       "IP"      => "IP Address" . ($is_ipv6 ? " (IPv6)" : " (IPv4)"),
+                       "IPv4"    => "IP Address (IPv4)",
+                       "IPv6"    => "IP Address (IPv6)",
+                       "Browser" => "Browser",
+                       "OS"      => "Operating System",
+                       "Lang"    => "Language",
+                       "UA"      => "User Agent",
+                       "Loc"     => "Location"
+               )
+       );
+       
+       return $Translations[$lang][$id];
+}
+ob_start();
+?>
+<!--
+<h3><?=getMsg($lang, "IP")?></h3>
+<p class="info" id="ip">
+       <?=$hostContent?>
+</p>
+-->
+<h3 id="ipv4_headline"><?=getMsg($lang, "IPv4")?></h3>
+<p class="info" id="ipv4">
+       <?=($info->isIPv6() ? "" : $hostContent)?>
+</p>
+<h3 id="ipv6_headline"><?=getMsg($lang, "IPv6")?></h3>
+<p class="info" id="ipv6">
+       <?=($info->isIPv6() ? $hostContent : "")?>
+</p>
+<h3><?=getMsg($lang, "Browser")?></h3>
+<p class="info" id="browser">
+       <?=$info->getBrowser()?>
+</p>
+<h3><?=getMsg($lang, "OS")?></h3>
+<p class="info" id="os">
+       <?=$info->getOS()?> (<?=getMsg($lang, "Lang")?>: <?=$info->getLanguage()?>)
+</p>
+<?php
+if ($debug) {
+       print '<pre>';
+       print "\$info->getGeoIPCountry() = " . $info->getGeoIPCountry() . "\n";
+
+       print "\n\$info->getGeoIPCity() = ";
+       print_r($info->getGeoIPCity());
+       print '</pre>';
+}
+if (!empty($info->getGeoIPCity()[0])) {
+       $coord = Array(
+               number_format($info->getGeoIPCity()[2][0], 4, ".", ""),
+               number_format($info->getGeoIPCity()[2][1], 4, ".", "")
+       );
+?>
+<h3><?=getMsg($lang, "Loc")?></h3>
+<p class="info" id="location">
+       <?=$info->getGeoIPCity()[0]?>, <?=$info->getGeoIPCountry()?>
+</p>
+<?php } ?>
+<h3><?=getMsg($lang, "UA")?></h3>
+<p class="info" id="user-agent">
+       <?=$info->getUserAgent()?>
+</p>
+<?php
+
+$contentData = Array(
+       "Main" => ob_get_clean()
+);
+$footerData = Array(
+       "© " . $AppInfo["Copyright"]["Year"] . ' <a href="' . $AppInfo["Copyright"]["AuthorLink"] . '" rel="me nofollow">' . $AppInfo["Copyright"]["AuthorName"] . '</a>',
+       'Powered by <a href="' . $AppInfo["URL"] . '">' . $AppInfo["Name"] . '</a>',
+       '<a href="API.md">API</a>'
+);
+
+$Data = Array(
+       "Meta" => Array(
+               "Lang"       => $lang,
+               "Charset"    => "UTF-8",
+               "Title"      => getMsg($lang, "Title") . " :: " . $AppInfo["Name"],
+               "Author"     => "Malte Bublitz",
+               "HumansTXT"  => false,
+               "Stylesheet" => "assets/css/style.css"
+       ),
+       "Content" => Array(
+               "Header" => Array(
+                       //"LinkURL" => "./",
+                       "LinkURL" => "https://ip.malte70.de/",
+                       "Title"   => getMsg($lang, "Title")
+               ),
+               "Content" => $contentData,
+               "Footer" => $footerData
+       )
+);
+
+require_once("template.inc.php");
+
+?>
diff --git a/ip.php b/ip.php
new file mode 100644 (file)
index 0000000..4d5eedf
--- /dev/null
+++ b/ip.php
@@ -0,0 +1,49 @@
+<?php
+
+require_once("config.inc.php");
+require_once("clientinfo.class.php");
+
+$info = new ClientInfo();
+
+$c = "<section class=\"text-center\">\n";
+$c .= " \t<h2>" . $info->getIP() . "</h2>\n";
+$c .= "\t<p>\n\t\t";
+$c .= '<a href="info.php">Details</a>';
+$c .= " \n\t</p>\n</section>\n";
+
+$contentData = Array(
+       "Main" => $c
+);
+$footerData = Array(
+       "© " . $AppInfo["Copyright"]["Year"] . ' <a href="' . $AppInfo["Copyright"]["AuthorLink"] . '" rel="me nofollow">' . $AppInfo["Copyright"]["AuthorName"] . '</a>',
+       'Powered by <a href="' . $AppInfo["URL"] . '">' . $AppInfo["Name"] . '</a>'
+);
+
+$lang = substr(
+       $info->getLanguage(),
+       0,
+       2
+);
+if ($lang == "de") {
+       $msg_your_ip = "Deine IP–Adresse";
+} else {
+       $msg_your_ip = "Your IP";
+}
+$Data = Array(
+       "Meta" => Array(
+               "Lang" => $lang,
+               "Charset" => "UTF-8",
+               "Title" => $msg_your_ip . " :: " . $AppInfo["Name"],
+               "Author" => "Malte Bublitz",
+               "HumansTXT" => false,
+               "Stylesheet" => "assets/css/style.css"
+       ),
+       "Content" => Array(
+               "Header" => NULL,
+               "Content" => $contentData,
+               "Footer" => $footerData
+       )
+);
+
+require_once("template.inc.php");
+?>
diff --git a/template.inc.php b/template.inc.php
new file mode 100644 (file)
index 0000000..40df25c
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+// Check that this file is not accessed directly
+if (!@isset($Data)) {
+       die('<h3 style="color:red;text-align:center;margin-top:6em;">This file should <u>never</u> be accessed direct.</h3>');
+}
+
+?><!DOCTYPE html>
+<html lang="<?=$Data["Meta"]["Lang"]?>">
+       <head>
+               <meta charset="<?=$Data["Meta"]["Charset"]?>">
+               <meta name="viewport" content="width=device-width, initial-scale=1.0">
+               
+               <title><?=$Data["Meta"]["Title"]?></title>
+               
+               <meta name="author" content="<?=$Data["Meta"]["Author"]?>">
+               
+               <link rel="stylesheet" type="text/css" href="<?=$Data["Meta"]["Stylesheet"]?>">
+               <link rel="icon" type="image/png" sizes="128x128" href="/assets/img/favicon.png">
+<?php if ($Data["Meta"]["HumansTXT"]): ?>
+               <link rel="author" type="text/plain" href="/humans.txt">
+<?php endif; ?>
+       </head>
+       <body id="top">
+<?php if ($Data["Content"]["Header"]): ?>
+               <header>
+                       <h1>
+                               <a href="<?=$Data["Content"]["Header"]["LinkURL"]?>"><?=$Data["Content"]["Header"]["Title"]?></a>
+                       </h1>
+               </header>
+               
+<?php endif; ?>
+               <main>
+<?=$Data["Content"]["Content"]["Main"]?>
+               </main>
+<?php if (!empty($Data["Content"]["Footer"])): ?>
+               
+               <footer>
+<?php
+foreach ($Data["Content"]["Footer"] as $p) {
+       print "\t\t\t<p>\n\t\t\t\t" . $p . "\n\t\t\t</p>\n";
+}
+?>
+               </footer>
+<?php endif; ?>
+<?php if ("info.php" == basename($_SERVER["SCRIPT_FILENAME"])): ?>
+               
+               <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
+               <script src="/assets/js/getipv4.js"></script>
+<?php endif; ?>
+       </body>
+</html>
\ No newline at end of file
diff --git a/widget.php b/widget.php
new file mode 100644 (file)
index 0000000..871613f
--- /dev/null
@@ -0,0 +1,197 @@
+<?php
+/**
+ * ip.tmkng.de/widget.php
+ * 
+ * IP Info widget, displayed as a PNG image
+ * 
+ * @see https://www.plus2net.com/php_tutorial/gd-imagestring.php
+ * @see http://www.phpforkids.com/php/php-gd-library-create-image.php
+ * @see https://code.tutsplus.com/de/tutorials/manipulating-images-in-php-using-gd--cms-31701
+ * @see http://php.net/manual/de/image.examples-png.php
+ * @see https://www.sitepoint.com/simple-captchas-php-gd/
+ * @see http://php.net/manual/de/function.imagettftext.php
+ * @see https://f.malte70.de/colors/
+ * @see http://forums.devnetwork.net/viewtopic.php?t=59622
+ * 
+ * Inspiration:
+ *  - http://www.dnstools.ch/ip-adresse-anzeigen.html
+ *  - https://www.internet-dsl.net/ip-adresse-anzeigen/
+ *  - https://www.dein-ip-check.de/tools/homepage
+ *  - http://wie-ist-meine-ip-adresse.com/index.php?p=webmaster
+ */
+
+
+/**
+ * Basic configuration and ClientInfo class
+ */
+require_once("config.inc.php");
+require_once("clientinfo.class.php");
+
+
+/**
+ * Automagically get client information
+ */
+$info = new ClientInfo();
+
+
+/**
+ * Create true color GD image
+ */
+$im = @imagecreatetruecolor(
+       $WidgetConfig["Size"][0],
+       $WidgetConfig["Size"][1]
+) or die("<b>Fatal PHP-GD error!</b> Cannot initialize new GD image stream.");
+
+
+// Background/Text/Heading color
+$background_color = imagecolorallocate(
+       $im,
+       $WidgetConfig["BackgroundColor"][0],
+       $WidgetConfig["BackgroundColor"][1],
+       $WidgetConfig["BackgroundColor"][2]
+);
+$text_color       = imagecolorallocate(
+       $im,
+       $WidgetConfig["TextColor"][0],
+       $WidgetConfig["TextColor"][1],
+       $WidgetConfig["TextColor"][2]
+);
+$heading_color    = imagecolorallocate(
+       $im,
+       $WidgetConfig["HeadingColor"][0],
+       $WidgetConfig["HeadingColor"][1],
+       $WidgetConfig["HeadingColor"][2]
+);
+
+
+/**
+ * Fill with background color
+ */
+imagefill($im, 0, 0, $background_color);
+
+
+/**
+ * Headline
+ */
+$headline     = $AppInfo["Name"];
+$headline_box = imagettfbbox(
+       $WidgetConfig["FontSizeBig"],
+       0,
+       $WidgetConfig["FontFamilyBig"],
+       $headline
+);
+$center       = (imagesx($im)/2) - ($headline_box[2] - $headline_box[0])/2;
+imagettftext(
+       $im,
+       $WidgetConfig["FontSizeBig"],
+       0,
+       $center,
+       $WidgetConfig["YCoords"]["Title"][0],
+       $heading_color,
+       $WidgetConfig["FontFamilyBig"],
+       $headline
+);
+
+/**
+ * IP
+ */
+imagettftext(
+       $im,
+       $WidgetConfig["FontSize"],
+       0,
+       25,
+       $WidgetConfig["YCoords"]["IP"][0],
+       $heading_color,
+       $WidgetConfig["FontFamily"],
+       "IP"
+);
+imagettftext(
+       $im,
+       $WidgetConfig["FontSize"],
+       0,
+       35,
+       $WidgetConfig["YCoords"]["IP"][1],
+       $text_color,
+       $WidgetConfig["FontFamily"],
+       $info->getIP()
+);
+
+
+/**
+ * Browser (Heading)
+ */
+// ImageString(
+//     $im,
+//     $WidgetConfig["FontSize"],
+//     10,
+//     $WidgetConfig["YCoords"]["Browser"][0],
+//     'Browser',
+//     $heading_color
+// );
+// // Browser (Value)
+// ImageString(
+//     $im,
+//     $WidgetConfig["FontSize"],
+//     18,
+//     $WidgetConfig["YCoords"]["Browser"][1],
+//     $info->getBrowser(),
+//     $text_color
+// );
+imagettftext(
+       $im,
+       $WidgetConfig["FontSize"],
+       0,
+       25,
+       $WidgetConfig["YCoords"]["Browser"][0],
+       $heading_color,
+       $WidgetConfig["FontFamily"],
+       "Browser"
+);
+imagettftext(
+       $im,
+       $WidgetConfig["FontSize"],
+       0,
+       35,
+       $WidgetConfig["YCoords"]["Browser"][1],
+       $text_color,
+       $WidgetConfig["FontFamily"],
+       $info->getBrowser()
+);
+
+
+/**
+ * Operating System
+ */
+imagettftext(
+       $im,
+       $WidgetConfig["FontSize"],
+       0,
+       25,
+       $WidgetConfig["YCoords"]["OS"][0],
+       $heading_color,
+       $WidgetConfig["FontFamily"],
+       "Betriebssystem"
+);
+imagettftext(
+       $im,
+       $WidgetConfig["FontSize"],
+       0,
+       35,
+       $WidgetConfig["YCoords"]["OS"][1],
+       $text_color,
+       $WidgetConfig["FontFamily"],
+       $info->getOS()
+);
+
+
+/**
+ * Send Content-Type header
+ */
+header("Content-Type: ".$WidgetConfig["Type"]);
+header("Cache-Control: no-cache"); // HTTP/1.1
+header("Pragma: no-cache");        // HTTP/1.0
+
+imagepng($im);
+imagedestroy($im);
+
+?>