diff --git a/ministatisticsaog.php b/ministatisticsaog.php new file mode 100644 index 0000000..282e02c --- /dev/null +++ b/ministatisticsaog.php @@ -0,0 +1,650 @@ +') !== false) { + $xml = @simplexml_load_string($payload); + if ($xml !== false) { + $data = array(); + foreach ($xml->children() as $key => $value) { + $k = strtolower(trim((string) $key)); + if ($k !== '') { + $data[$k] = trim((string) $value); + } + } + if (!empty($data)) { + return $data; + } + } + } + + $data = array(); + $lines = preg_split('/\r\n|\r|\n/', $payload); + foreach ($lines as $line) { + $line = trim($line); + if ($line === '' || strpos($line, '=') === false) { + continue; + } + + list($key, $value) = array_map('trim', explode('=', $line, 2)); + if ($key !== '') { + $data[strtolower($key)] = $value; + } + } + + return $data; +} + +function fetch_public_grid_info($loginUri) +{ + $urls = build_grid_info_urls($loginUri); + if (empty($urls)) { + return array(); + } + + foreach ($urls as $url) { + $context = stream_context_create(array( + 'http' => array( + 'method' => 'GET', + 'timeout' => 1.5, + 'ignore_errors' => true, + 'header' => "User-Agent: oswebinterface-gridinfo/1.0\r\n", + ), + 'ssl' => array( + 'verify_peer' => false, + 'verify_peer_name' => false, + ), + )); + + $payload = @file_get_contents($url, false, $context); + if ($payload === false) { + continue; + } + + $parsed = parse_grid_info_payload($payload); + if (!empty($parsed)) { + $parsed['_source_url'] = $url; + return $parsed; + } + } + + return array(); +} + +function read_grid_info_cache($cacheFile) +{ + if (!is_readable($cacheFile)) { + return array(); + } + + $raw = @file_get_contents($cacheFile); + if ($raw === false || $raw === '') { + return array(); + } + + $decoded = json_decode($raw, true); + return is_array($decoded) ? $decoded : array(); +} + +function write_grid_info_cache($cacheFile, $cacheData) +{ + @file_put_contents($cacheFile, json_encode($cacheData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); +} + +function find_grid_info_value($gridInfo, $keys) +{ + foreach ($keys as $key) { + $lower = strtolower($key); + if (isset($gridInfo[$lower]) && trim((string) $gridInfo[$lower]) !== '') { + return trim((string) $gridInfo[$lower]); + } + if (isset($gridInfo[$key]) && trim((string) $gridInfo[$key]) !== '') { + return trim((string) $gridInfo[$key]); + } + } + + return ''; +} + +function viewer_default_login_page($gridUri, $loginUri) +{ + $gridHost = host_from_uri($gridUri); + if ($gridHost === '') { + $gridHost = host_from_uri($loginUri); + } + + if ($gridHost === '') { + return ''; + } + + return 'http://' . $gridHost . '/'; +} + +function csv_output_and_exit($rows) +{ + $filename = 'mini-active-opensim-grids-' . date('Ymd-His') . '.csv'; + + header('Content-Type: text/csv; charset=UTF-8'); + header('Content-Disposition: attachment; filename=' . $filename); + + $out = fopen('php://output', 'w'); + if ($out === false) { + http_response_code(500); + echo 'CSV export failed.'; + exit; + } + + fputcsv($out, array('Grid Name', 'Grid-URI', 'Login-Seite', 'LoginURI', 'HG-address', 'GridUser Count', 'UserInfo Count', 'Total')); + + foreach ($rows as $row) { + fputcsv($out, array( + $row['grid_name'], + $row['grid_uri'], + $row['login_page'], + $row['login_uri'], + $row['hg_address'], + $row['griduser_count'], + $row['userinfo_count'], + $row['total_count'], + )); + } + + fclose($out); + exit; +} + +$extendedCsvFile = __DIR__ . '/include/minigroundgridlist.csv'; +$gridInfoCacheFile = __DIR__ . '/include/minigroundgridinfo_cache.json'; +$gridInfoCacheTtl = 43200; +$completeRefreshMode = true; + +$mysqli = @mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME); +if ($mysqli === false) { + http_response_code(500); + echo 'Datenbankverbindung fehlgeschlagen.'; + exit; +} + +$gridMap = array(); + +$gridUserQuery = mysqli_query($mysqli, 'SELECT * FROM `GridUser` ORDER BY `GridUser`.`UserID` DESC'); +if ($gridUserQuery !== false) { + while ($row = mysqli_fetch_assoc($gridUserQuery)) { + $userId = isset($row['UserID']) ? $row['UserID'] : ''; + $loginUri = parse_grid_user_login_uri($userId); + if ($loginUri === '') { + continue; + } + + if (!isset($gridMap[$loginUri])) { + $gridMap[$loginUri] = array( + 'grid_name' => derive_grid_name($loginUri), + 'grid_uri' => '', + 'login_page' => '', + 'login_uri' => $loginUri, + 'hg_address' => $loginUri, + 'griduser_count' => 0, + 'userinfo_count' => 0, + ); + } + + $gridMap[$loginUri]['griduser_count']++; + } + mysqli_free_result($gridUserQuery); +} + +$userInfoQuery = mysqli_query($mysqli, 'SELECT * FROM `userinfo` ORDER BY `userinfo`.`serverurl` ASC'); +if ($userInfoQuery !== false) { + while ($row = mysqli_fetch_assoc($userInfoQuery)) { + $hgAddress = isset($row['serverurl']) ? parse_hg_address($row['serverurl']) : ''; + if ($hgAddress === '') { + continue; + } + + if (!isset($gridMap[$hgAddress])) { + $gridMap[$hgAddress] = array( + 'grid_name' => derive_grid_name($hgAddress), + 'grid_uri' => '', + 'login_page' => '', + 'login_uri' => '', + 'hg_address' => $hgAddress, + 'griduser_count' => 0, + 'userinfo_count' => 0, + ); + } + + $gridMap[$hgAddress]['userinfo_count']++; + $gridMap[$hgAddress]['hg_address'] = $hgAddress; + } + mysqli_free_result($userInfoQuery); +} + +mysqli_close($mysqli); + +$gridInfoCache = read_grid_info_cache($gridInfoCacheFile); +$cacheChanged = false; +$now = time(); +$refreshCount = 0; +$rowsChanged = false; + +$rows = array_values($gridMap); +foreach ($rows as &$row) { + $queryUri = $row['login_uri'] !== '' ? $row['login_uri'] : $row['hg_address']; + $cacheKey = sanitize_grid_uri($queryUri); + + if ($cacheKey === '') { + $row['total_count'] = (int) $row['griduser_count'] + (int) $row['userinfo_count']; + continue; + } + + $gridInfo = array(); + if (isset($gridInfoCache[$cacheKey]['data']) && is_array($gridInfoCache[$cacheKey]['data'])) { + $gridInfo = $gridInfoCache[$cacheKey]['data']; + } + + if ($completeRefreshMode || empty($gridInfo)) { + $refreshCount++; + $gridInfo = fetch_public_grid_info($queryUri); + $gridInfoCache[$cacheKey] = array( + 'fetched_at' => $now, + 'data' => $gridInfo, + ); + $cacheChanged = true; + } + + if (!empty($gridInfo)) { + $publicName = find_grid_info_value($gridInfo, array('gridname', 'gridnick', 'label')); + if ($publicName !== '') { + if ($row['grid_name'] !== $publicName) { + $rowsChanged = true; + } + $row['grid_name'] = $publicName; + } + + $publicGridUri = find_grid_info_value($gridInfo, array('name', 'griduri', 'grid_uri', 'gridurl', 'grid_url', 'gridnick')); + if ($publicGridUri !== '') { + if ($row['grid_uri'] !== $publicGridUri) { + $rowsChanged = true; + $row['grid_uri'] = $publicGridUri; + } + } + + $publicLoginPage = find_grid_info_value($gridInfo, array('loginpage', 'login_page')); + if ($publicLoginPage !== '') { + if ($row['login_page'] !== $publicLoginPage) { + $rowsChanged = true; + $row['login_page'] = $publicLoginPage; + } + } + + $publicLogin = find_grid_info_value($gridInfo, array('login', 'loginuri', 'login_uri')); + if ($publicLogin !== '') { + $newLogin = sanitize_grid_uri($publicLogin); + if ($newLogin !== '') { + if (is_hg_address_uri($newLogin)) { + $row['hg_address'] = $newLogin; + } else { + $row['login_uri'] = $newLogin; + } + $rowsChanged = true; + } + } + } + + if ($row['login_page'] === '') { + $fallbackLoginPage = viewer_default_login_page($row['grid_uri'], $row['login_uri']); + if ($fallbackLoginPage !== '') { + $row['login_page'] = $fallbackLoginPage; + $rowsChanged = true; + } + } + + $row['total_count'] = (int) $row['griduser_count'] + (int) $row['userinfo_count']; +} +unset($row); + +if ($cacheChanged) { + write_grid_info_cache($gridInfoCacheFile, $gridInfoCache); +} + +usort($rows, function ($a, $b) { + if ($a['total_count'] === $b['total_count']) { + return strcmp($a['grid_name'], $b['grid_name']); + } + return $b['total_count'] <=> $a['total_count']; +}); + +$needsCsvWrite = $rowsChanged || !is_file($extendedCsvFile); +if ($needsCsvWrite) { + $writeHandle = @fopen($extendedCsvFile, 'w'); + if ($writeHandle !== false) { + fputcsv($writeHandle, array('Grid Name', 'Grid-URI', 'Login-Seite', 'LoginURI', 'HG-address', 'GridUser Count', 'UserInfo Count', 'Total')); + foreach ($rows as $row) { + fputcsv($writeHandle, array( + $row['grid_name'], + $row['grid_uri'], + $row['login_page'], + $row['login_uri'], + $row['hg_address'], + $row['griduser_count'], + $row['userinfo_count'], + $row['total_count'], + )); + } + fclose($writeHandle); + } +} + +if (isset($_GET['download']) && $_GET['download'] === '1') { + csv_output_and_exit($rows); +} +?> + + + + + + Mini Statistics Active OpenSim Grids + + + +
+
+

Mini Statistics Active OpenSim Grids

+

Nur Datenbankdaten (GridUser + userinfo), ohne include/gridlist.csv.

+ +
+ CSV Download + Datensaetze: + Exportdatei: include/minigroundgridlist.csv + Grid-Info Refresh: +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Grid NameGrid-URILogin-SeiteLoginURIHG-addressGridUserUserInfoTotal
Keine Daten vorhanden.
+
+
+
+ + diff --git a/statisticsaog.php b/statisticsaog.php new file mode 100644 index 0000000..91d02b4 --- /dev/null +++ b/statisticsaog.php @@ -0,0 +1,770 @@ +') !== false) { + $xml = @simplexml_load_string($payload); + if ($xml !== false) { + $data = array(); + foreach ($xml->children() as $key => $value) { + $k = strtolower(trim((string) $key)); + if ($k !== '') { + $data[$k] = trim((string) $value); + } + } + if (!empty($data)) { + return $data; + } + } + } + + $data = array(); + $lines = preg_split('/\r\n|\r|\n/', $payload); + foreach ($lines as $line) { + $line = trim($line); + if ($line === '' || strpos($line, '=') === false) { + continue; + } + + list($key, $value) = array_map('trim', explode('=', $line, 2)); + if ($key !== '') { + $data[strtolower($key)] = $value; + } + } + + return $data; +} + +function viewer_default_login_page($gridUri, $loginUri) +{ + $gridHost = host_from_uri($gridUri); + if ($gridHost === '') { + $gridHost = host_from_uri($loginUri); + } + + if ($gridHost === '') { + return ''; + } + + //return 'http://' . $gridHost . '/app/login/'; + return 'http://' . $gridHost . '/'; +} + +function fetch_public_grid_info($loginUri) +{ + $urls = build_grid_info_urls($loginUri); + if (empty($urls)) { + return array(); + } + + foreach ($urls as $url) { + $context = stream_context_create(array( + 'http' => array( + 'method' => 'GET', + 'timeout' => 1.5, + 'ignore_errors' => true, + 'header' => "User-Agent: oswebinterface-gridinfo/1.0\r\n", + ), + 'ssl' => array( + 'verify_peer' => false, + 'verify_peer_name' => false, + ), + )); + + $payload = @file_get_contents($url, false, $context); + if ($payload === false) { + continue; + } + + $parsed = parse_grid_info_payload($payload); + if (!empty($parsed)) { + $parsed['_source_url'] = $url; + return $parsed; + } + } + + return array(); +} + +function read_grid_info_cache($cacheFile) +{ + if (!is_readable($cacheFile)) { + return array(); + } + + $raw = @file_get_contents($cacheFile); + if ($raw === false || $raw === '') { + return array(); + } + + $decoded = json_decode($raw, true); + return is_array($decoded) ? $decoded : array(); +} + +function write_grid_info_cache($cacheFile, $cacheData) +{ + @file_put_contents($cacheFile, json_encode($cacheData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); +} + +function find_grid_info_value($gridInfo, $keys) +{ + foreach ($keys as $key) { + $lower = strtolower($key); + if (isset($gridInfo[$lower]) && trim((string) $gridInfo[$lower]) !== '') { + return trim((string) $gridInfo[$lower]); + } + if (isset($gridInfo[$key]) && trim((string) $gridInfo[$key]) !== '') { + return trim((string) $gridInfo[$key]); + } + } + + return ''; +} + +function csv_output_and_exit($rows) +{ + $filename = 'active-opensim-grids-' . date('Ymd-His') . '.csv'; + + header('Content-Type: text/csv; charset=UTF-8'); + header('Content-Disposition: attachment; filename=' . $filename); + + $out = fopen('php://output', 'w'); + if ($out === false) { + http_response_code(500); + echo 'CSV export failed.'; + exit; + } + + fputcsv($out, array('Grid Name', 'Grid-URI', 'Login-Seite', 'LoginURI', 'HG-address', 'GridUser Count', 'UserInfo Count', 'Total')); + + foreach ($rows as $row) { + fputcsv($out, array( + $row['grid_name'], + $row['grid_uri'], + $row['login_page'], + $row['login_uri'], + $row['hg_address'], + $row['griduser_count'], + $row['userinfo_count'], + $row['total_count'], + )); + } + + fclose($out); + exit; +} + +$baseCsvFile = __DIR__ . '/include/gridlist.csv'; +$extendedCsvFile = __DIR__ . '/include/groundgridlist.csv'; +$gridInfoCacheFile = __DIR__ . '/include/groundgridinfo_cache.json'; +$gridInfoCacheTtl = 43200; +$gridInfoRefreshPerRequest = 999999; +$completeRefreshMode = true; + +$mysqli = @mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME); +if ($mysqli === false) { + http_response_code(500); + echo 'Datenbankverbindung fehlgeschlagen.'; + exit; +} + +$gridMap = array(); + +if (is_readable($baseCsvFile)) { + $handle = fopen($baseCsvFile, 'r'); + if ($handle !== false) { + while (($data = fgetcsv($handle)) !== false) { + if (!isset($data[0], $data[1])) { + continue; + } + + $nameRaw = trim($data[0]); + $uriRaw = trim($data[1]); + + if ($nameRaw === '' || $uriRaw === '') { + continue; + } + + if (strtolower($nameRaw) === 'gridname' || strtolower($nameRaw) === 'grid name') { + continue; + } + + $loginUri = sanitize_grid_uri($uriRaw); + if ($loginUri === '') { + continue; + } + + $key = $loginUri; + if (!isset($gridMap[$key])) { + $gridMap[$key] = array( + 'grid_name' => $nameRaw, + 'grid_uri' => '', + 'login_page' => '', + 'login_uri' => $loginUri, + 'hg_address' => $loginUri, + 'griduser_count' => 0, + 'userinfo_count' => 0, + 'source' => 'include/gridlist.csv', + ); + } + } + fclose($handle); + } +} + +$gridUserRows = array(); +$gridUserQuery = mysqli_query($mysqli, 'SELECT * FROM `GridUser` ORDER BY `GridUser`.`UserID` DESC'); +if ($gridUserQuery !== false) { + while ($row = mysqli_fetch_assoc($gridUserQuery)) { + $gridUserRows[] = $row; + } + mysqli_free_result($gridUserQuery); +} + +foreach ($gridUserRows as $row) { + $userId = isset($row['UserID']) ? $row['UserID'] : ''; + $loginUri = parse_grid_user_login_uri($userId); + if ($loginUri === '') { + continue; + } + + if (!isset($gridMap[$loginUri])) { + $gridMap[$loginUri] = array( + 'grid_name' => derive_grid_name($loginUri), + 'grid_uri' => '', + 'login_page' => '', + 'login_uri' => $loginUri, + 'hg_address' => $loginUri, + 'griduser_count' => 0, + 'userinfo_count' => 0, + 'source' => 'database/GridUser', + ); + } + + $gridMap[$loginUri]['griduser_count']++; + if ($gridMap[$loginUri]['source'] === 'include/gridlist.csv') { + $gridMap[$loginUri]['source'] = 'include/gridlist.csv + database/GridUser'; + } +} + +$userInfoRows = array(); +$userInfoQuery = mysqli_query($mysqli, 'SELECT * FROM `userinfo` ORDER BY `userinfo`.`serverurl` ASC'); +if ($userInfoQuery !== false) { + while ($row = mysqli_fetch_assoc($userInfoQuery)) { + $userInfoRows[] = $row; + } + mysqli_free_result($userInfoQuery); +} + +foreach ($userInfoRows as $row) { + $hgAddress = isset($row['serverurl']) ? parse_hg_address($row['serverurl']) : ''; + if ($hgAddress === '') { + continue; + } + + if (!isset($gridMap[$hgAddress])) { + $gridMap[$hgAddress] = array( + 'grid_name' => derive_grid_name($hgAddress), + 'grid_uri' => '', + 'login_page' => '', + 'login_uri' => '', + 'hg_address' => $hgAddress, + 'griduser_count' => 0, + 'userinfo_count' => 0, + 'source' => 'database/userinfo', + ); + } + + $gridMap[$hgAddress]['hg_address'] = $hgAddress; + $gridMap[$hgAddress]['userinfo_count']++; + + if (strpos($gridMap[$hgAddress]['source'], 'database/userinfo') === false) { + $gridMap[$hgAddress]['source'] .= ' + database/userinfo'; + } +} + +mysqli_close($mysqli); + +$gridInfoCache = read_grid_info_cache($gridInfoCacheFile); +$cacheChanged = false; +$now = time(); +$refreshCount = 0; +$rowsChanged = false; + +$rows = array_values($gridMap); +foreach ($rows as &$row) { + $queryUri = $row['login_uri'] !== '' ? $row['login_uri'] : $row['hg_address']; + $cacheKey = sanitize_grid_uri($queryUri); + + if ($cacheKey === '') { + $row['total_count'] = (int) $row['griduser_count'] + (int) $row['userinfo_count']; + continue; + } + + $hasCache = isset($gridInfoCache[$cacheKey]) + && isset($gridInfoCache[$cacheKey]['data']) + && is_array($gridInfoCache[$cacheKey]['data']); + + $cacheFresh = isset($gridInfoCache[$cacheKey]) + && isset($gridInfoCache[$cacheKey]['fetched_at']) + && ($now - (int) $gridInfoCache[$cacheKey]['fetched_at'] <= $gridInfoCacheTtl) + && isset($gridInfoCache[$cacheKey]['data']) + && is_array($gridInfoCache[$cacheKey]['data']); + + if ($hasCache) { + $gridInfo = $gridInfoCache[$cacheKey]['data']; + } else { + $gridInfo = array(); + } + + $shouldRefresh = false; + if ($completeRefreshMode) { + $shouldRefresh = true; + } elseif (!$cacheFresh && $refreshCount < $gridInfoRefreshPerRequest) { + $shouldRefresh = true; + } + + if ($shouldRefresh) { + $refreshCount++; + $gridInfo = fetch_public_grid_info($queryUri); + $gridInfoCache[$cacheKey] = array( + 'fetched_at' => $now, + 'data' => $gridInfo, + ); + $cacheChanged = true; + } + + if (!empty($gridInfo)) { + // Firestorm/OpenSim keys from get_grid_info: gridname (label), name (grid uri), login, loginpage. + $publicName = find_grid_info_value($gridInfo, array('gridname', 'gridnick', 'label')); + if ($publicName !== '') { + if ($row['grid_name'] !== $publicName) { + $rowsChanged = true; + } + $row['grid_name'] = $publicName; + } + + $publicGridUri = find_grid_info_value($gridInfo, array('name', 'griduri', 'grid_uri', 'gridurl', 'grid_url', 'gridnick')); + if ($publicGridUri !== '') { + if ($row['grid_uri'] !== $publicGridUri) { + $rowsChanged = true; + $row['grid_uri'] = $publicGridUri; + } + } + + $publicLoginPage = find_grid_info_value($gridInfo, array('loginpage', 'login_page')); + if ($publicLoginPage !== '') { + if ($row['login_page'] !== $publicLoginPage) { + $rowsChanged = true; + $row['login_page'] = $publicLoginPage; + } + } + + $publicLogin = find_grid_info_value($gridInfo, array('login', 'loginuri', 'login_uri')); + if ($publicLogin !== '') { + $newLogin = sanitize_grid_uri($publicLogin); + if ($newLogin !== '') { + if (is_hg_address_uri($newLogin)) { + if ($row['hg_address'] !== $newLogin) { + $rowsChanged = true; + $row['hg_address'] = $newLogin; + } + } elseif ($row['login_uri'] !== $newLogin) { + $rowsChanged = true; + $row['login_uri'] = $newLogin; + } + } + } + + $publicHg = find_grid_info_value($gridInfo, array('hglogin', 'hg_login', 'hgaddress', 'hg_address', 'homeuri', 'home_uri')); + if ($publicHg !== '') { + $newHg = sanitize_grid_uri($publicHg); + if ($newHg !== '' && $row['hg_address'] !== $newHg) { + $rowsChanged = true; + $row['hg_address'] = $newHg; + } + } + } + + if ($row['login_page'] === '') { + $fallbackLoginPage = viewer_default_login_page($row['grid_uri'], $row['login_uri']); + if ($fallbackLoginPage !== '') { + $row['login_page'] = $fallbackLoginPage; + $rowsChanged = true; + } + } + + $row['total_count'] = (int) $row['griduser_count'] + (int) $row['userinfo_count']; +} +unset($row); + +if ($cacheChanged) { + write_grid_info_cache($gridInfoCacheFile, $gridInfoCache); +} + +usort($rows, function ($a, $b) { + if ($a['total_count'] === $b['total_count']) { + return strcmp($a['grid_name'], $b['grid_name']); + } + return $b['total_count'] <=> $a['total_count']; +}); + +$needsCsvWrite = $rowsChanged || !is_file($extendedCsvFile); +if ($needsCsvWrite) { + $writeHandle = @fopen($extendedCsvFile, 'w'); + if ($writeHandle !== false) { + fputcsv($writeHandle, array('Grid Name', 'Grid-URI', 'Login-Seite', 'LoginURI', 'HG-address', 'GridUser Count', 'UserInfo Count', 'Total')); + foreach ($rows as $row) { + fputcsv($writeHandle, array( + $row['grid_name'], + $row['grid_uri'], + $row['login_page'], + $row['login_uri'], + $row['hg_address'], + $row['griduser_count'], + $row['userinfo_count'], + $row['total_count'], + )); + } + fclose($writeHandle); + } +} + +if (isset($_GET['download']) && $_GET['download'] === '1') { + csv_output_and_exit($rows); +} +?> + + + + + + Statistics Active OpenSim Grids + + + +
+
+

Statistics Active OpenSim Grids

+

Quelle: include/gridlist.csv + Robust DB (GridUser, userinfo) + oeffentliche Grid-Daten via HTTP GET /get_grid_info. Vorbild: hypergridbusiness.com/statistics/active-grids/

+ +
+ CSV Download + Datensaetze: + Exportdatei: include/groundgridlist.csv + Grid-Info Refresh: / +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Grid NameGrid-URILogin-SeiteLoginURIHG-addressGridUserUserInfoTotal
Keine Daten vorhanden.
+
+
+
+ +