•Each release branch of PHP is fully supported for two years from its initial stable release https://www.php.net/supported-versions.php
PHP Backup: https://ry3yr.github.io/php.zip
Run php server locally (android): https://apkcombo.com/de/palapa-web-server/com.alfanla.android.pws/download/apk#urusai.social/@alcea/111761622206017944#i.ibb.co/cx175BB/Screenshot-20240115-165447-Opera.png
Install ComposerPackagesManually(Windows) https://m.youtube.com/watch?v=j8kpwzE6ju0
https://alcea-wisteria.de/PHP/composer-packages/
___________________________________________________________________________________________________________________
_____https://stackoverflow.com/questions/40545795/how-do-i-install-composer-php-packages-without-composer------
*php-install
NintendoNews parser (exclude ninteverything )
--------------
]*>.*? ]*src=["\']([^"\']+)["\'][^>]*>.*?
]*class=["\']summary[^"\']*["\']>(.*?)
)?.*?data-timestamp=["\']([^"\']+)["\']#si';
if (preg_match_all($pattern, $html, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$link = trim($m[2]);
$blocked = false;
foreach ($blocked_domains as $d) {
if (stripos($link, $d) !== false) { $blocked = true; break; }
}
if ($blocked) continue;
$host = parse_url($link, PHP_URL_HOST);
$badge = strtoupper(preg_replace('/^www\./','',$host));
$articles[] = [
'image' => normalize_image_url($m[1], $base_url),
'link' => $link,
'title' => trim(htmlspecialchars_decode($m[3])),
'excerpt' => isset($m[5]) ? trim(htmlspecialchars_decode($m[5])) : '',
'badge' => $badge,
'date' => isset($m[6]) ? $m[6] : ''
];
}
}
return $articles;
}
$base_url = 'https://nintendonews.com/news';
$blocked_domains = ['nintendolife.de','nintendoeverything.com'];
$per_page = 10;
$page_param = isset($_GET['page']) ? max(1,intval($_GET['page'])) : 1;
$autopage = isset($_GET['autopage']);
$url = $base_url . '?page=' . $page_param;
$html = fetch_url_content($url);
$all_articles = $html ? parse_articles_regex($html, $base_url, $blocked_domains) : [];
$total_articles = count($all_articles);
$total_pages = 100;
$current_page = $page_param;
$articles_to_show = $all_articles;
if ($autopage && isset($_GET['ajax'])) {
header('Content-Type: application/json');
echo json_encode([
'articles' => $articles_to_show,
'current' => $current_page,
'total' => $total_pages
]);
exit;
}
?>
Nintendo News
Latest Nintendo News
=htmlspecialchars($a['date'])?>
=htmlspecialchars($a['excerpt'])?>
=htmlspecialchars($a['badge'])?>
Page =$current_page?>
Fedi is Missing
------------------------
filereport.php
--
[
'timeout' => 15,
'header' => "User-Agent: FediversePostFetcher/1.0\r\nAccept: application/json\r\n"
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false
]
]);
// If we have a status ID but no username, fetch the post to get the username
if ($status_id && !$username) {
// Try different API endpoints for different platforms
$api_urls = [
"https://$domain/api/v1/statuses/$status_id", // Mastodon/Pleroma standard
"https://$domain/objects/$status_id", // Akkoma alternative
];
$post_data = null;
foreach ($api_urls as $api_url) {
$response = @file_get_contents($api_url, false, $context);
if ($response !== false) {
$post_data = json_decode($response, true);
if ($post_data) break;
}
}
if (!$post_data) {
die("Error fetching post data from the server.");
}
// Extract username from post data - ensure we get the full @user@domain format
if (isset($post_data['account']['acct'])) {
$acct = $post_data['account']['acct'];
// Check if the acct already contains a domain
if (strpos($acct, '@') === false) {
// If not, add the domain
$username = '@' . $acct . '@' . $domain;
} else {
$username = '@' . $acct;
}
} else if (isset($post_data['account']['username'])) {
$acct = $post_data['account']['username'];
// Try to get the full acct (username@domain) if possible
if (isset($post_data['account']['url'])) {
$account_url = parse_url($post_data['account']['url']);
if (isset($account_url['host']) && $account_url['host'] !== $domain) {
$username = '@' . $acct . '@' . $account_url['host'];
} else {
$username = '@' . $acct . '@' . $domain;
}
} else {
$username = '@' . $acct . '@' . $domain;
}
} else {
die("Unable to extract user information from post.");
}
} else if ($username) {
// If we already have a username from the URL, ensure it's in the full @user@domain format
$username_parts = explode('@', $username);
if (count($username_parts) === 2) {
// Only username part is present, add domain
$username = $username . '@' . $domain;
}
}
// Now get the user's latest post using the username
// Extract just the username part without @ for lookup
$lookup_username = substr($username, 1); // Remove the leading @
$lookup_username_parts = explode('@', $lookup_username);
$local_username = $lookup_username_parts[0];
// Try different lookup endpoints
$lookup_urls = [
"https://$domain/api/v1/accounts/lookup?acct=" . urlencode($lookup_username), // Standard
"https://$domain/users/" . urlencode($local_username) . ".json", // Akkoma alternative
];
$account_data = null;
foreach ($lookup_urls as $lookup_url) {
$response = @file_get_contents($lookup_url, false, $context);
if ($response !== false) {
$account_data = json_decode($response, true);
if ($account_data) break;
}
}
$user_id = null;
$user_acct = $lookup_username; // Default to the full username we already have
if ($account_data) {
if (isset($account_data['id'])) {
$user_id = $account_data['id'];
}
// Get the proper account identifier
if (isset($account_data['acct'])) {
$acct = $account_data['acct'];
// Check if the acct already contains a domain
if (strpos($acct, '@') === false) {
// If not, add the domain
$user_acct = $acct . '@' . $domain;
} else {
$user_acct = $acct;
}
}
}
$latest_post_url = null;
$created_at = null;
// If we couldn't get user ID through lookup, try to get statuses directly
if (!$user_id) {
// Try different statuses endpoints
$statuses_urls = [
"https://$domain/users/$local_username/outbox?page=true&limit=1", // ActivityPub
"https://$domain/api/v1/accounts/$local_username/statuses?limit=1", // Mastodon API
"https://$domain/@$local_username.json?limit=1", // Alternative
];
$statuses = null;
foreach ($statuses_urls as $statuses_url) {
$response = @file_get_contents($statuses_url, false, $context);
if ($response !== false) {
$data = json_decode($response, true);
// Handle different response formats
if (isset($data['orderedItems'])) {
// ActivityPub format
if (!empty($data['orderedItems']) && isset($data['orderedItems'][0]['published'])) {
$created_at = $data['orderedItems'][0]['published'];
if (isset($data['orderedItems'][0]['id'])) {
$latest_post_url = $data['orderedItems'][0]['id'];
}
$statuses = [['created_at' => $created_at]];
break;
}
} else if (is_array($data) && !empty($data) && isset($data[0]['created_at'])) {
// Standard API format
$statuses = $data;
$created_at = $data[0]['created_at'];
if (isset($data[0]['url'])) {
$latest_post_url = $data[0]['url'];
}
break;
}
}
}
if (!$statuses || empty($statuses)) {
die("No posts found for the user.");
}
} else {
// Get statuses using the user ID
$statuses_url = "https://$domain/api/v1/accounts/$user_id/statuses?limit=1";
$response = @file_get_contents($statuses_url, false, $context);
if ($response === false) {
die("Error fetching user's latest post.");
}
$statuses = json_decode($response, true);
if (empty($statuses)) {
die("No posts found for the user.");
}
$created_at = $statuses[0]['created_at'];
if (isset($statuses[0]['url'])) {
$latest_post_url = $statuses[0]['url'];
}
}
// If we don't have a post URL, try to construct one
if (!$latest_post_url && isset($statuses[0]['id'])) {
$post_id = $statuses[0]['id'];
$latest_post_url = "https://$domain/@$user_acct/$post_id";
}
// Format the date to yyyymmdd
$date = date('Ymd', strtotime($created_at));
// Prepare the data for saving to the JSON file
$entry = [
'username' => "@$user_acct",
'date' => $date,
'post_url' => $latest_post_url
];
// Load the existing JSON data
$filename = 'fedimissing.json';
$json_data = [];
if (file_exists($filename)) {
$json_content = file_get_contents($filename);
if ($json_content !== false) {
$json_data = json_decode($json_content, true);
}
if (!is_array($json_data)) {
$json_data = [];
}
}
// Check if the user already exists
$user_exists = false;
foreach ($json_data as $existing_entry) {
if ($existing_entry['username'] === "@$user_acct") {
$user_exists = true;
break;
}
}
if ($user_exists) {
die("User @$user_acct already exists in the JSON file.");
}
// Prepend the new entry to the array
array_unshift($json_data, $entry);
// Save the updated data back to the JSON file
if (file_put_contents($filename, json_encode($json_data, JSON_PRETTY_PRINT))) {
echo "Latest post date saved successfully: @$user_acct $date";
if ($latest_post_url) {
echo " Post URL: $latest_post_url ";
}
} else {
echo "Error saving to JSON file. Please check file permissions.";
}
} else {
// Display the HTML form
?>
Fediverse Post Fetcher
Fetch Latest Post From Fediverse User
This tool will always get the date of the user's NEWEST post, regardless of which post URL you provide.
Supported formats:
https://mastodon.social/@username
https://instance.tld/@username/1234567890 (any post URL)
https://instance.tld/notice/ABC123 (Pleroma/Akkoma)
https://instance.tld/objects/ABC123 (Akkoma)
https://instance.tld/users/username (Akkoma)
Note: Some instances may have API limitations or require authentication.
index.html
--
Fediverse Missing Posts
post.php
--
Missing Fedi person: (update) ';
foreach ($missingPersons as $person) {
$username = htmlspecialchars($person['username']);
$postUrl = htmlspecialchars($person['post_url']);
$date = $person['date'];
// Calculate days missing
$today = new DateTime();
$missingDate = DateTime::createFromFormat('Ymd', $date);
if ($missingDate) {
$interval = $today->diff($missingDate);
$daysMissing = $interval->days;
$daysText = $daysMissing == 1 ? 'day' : 'days';
} else {
$daysMissing = 'unknown';
$daysText = 'days';
}
$htmlContent .= "$username - $daysMissing $daysText missing ";
}
// Prepare API request
$apiEndpoint = rtrim($instanceUrl, '/') . '/api/v1/statuses';
$postData = [
'status' => $htmlContent,
'content_type' => 'text/html',
'visibility' => 'public'
];
// Headers for Akkoma API
$headers = [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json'
];
// Initialize cURL
$ch = curl_init();
if (!empty($oldPostUrl)) {
// Edit existing post - extract status ID from URL
$urlParts = parse_url($oldPostUrl);
$pathParts = explode('/', trim($urlParts['path'], '/'));
$statusId = end($pathParts);
curl_setopt_array($ch, [
CURLOPT_URL => $apiEndpoint . '/' . $statusId,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => json_encode($postData),
CURLOPT_HTTPHEADER => $headers
]);
$action = "editing";
} else {
// Create new post
curl_setopt_array($ch, [
CURLOPT_URL => $apiEndpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($postData),
CURLOPT_HTTPHEADER => $headers
]);
$action = "posting";
}
// Execute API request
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_error($ch)) {
http_response_code(500);
echo "Error: cURL error - " . curl_error($ch);
curl_close($ch);
exit;
}
curl_close($ch);
// Handle response
if ($httpCode >= 200 && $httpCode < 300) {
$responseData = json_decode($response, true);
$postUrl = $responseData['url'] ?? $oldPostUrl;
echo "Successfully $action post: " . $postUrl . "\n";
echo "Generated content:\n\n";
echo $htmlContent;
} else {
http_response_code($httpCode);
echo "Error: API returned status code $httpCode\n";
echo "Response: " . $response;
}
?>
updatereport.php
--
[
'timeout' => 15,
'header' => "User-Agent: FediversePostUpdater/1.0\r\nAccept: application/json\r\n"
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false
]
]);
// Iterate over all entries
foreach ($json_data as &$entry) {
$username = $entry['username']; // e.g. @user@domain
$parts = explode('@', $username);
if (count($parts) < 3) {
echo "Skipping invalid username format: $username ";
continue;
}
$local_user = $parts[1];
$domain = $parts[2];
// Look up account to get ID
$lookup_urls = [
"https://$domain/api/v1/accounts/lookup?acct=" . urlencode("$local_user@$domain"),
"https://$domain/users/" . urlencode($local_user) . ".json",
];
$account_data = null;
foreach ($lookup_urls as $lookup_url) {
$response = @file_get_contents($lookup_url, false, $context);
if ($response !== false) {
$account_data = json_decode($response, true);
if ($account_data) break;
}
}
$user_id = null;
if ($account_data && isset($account_data['id'])) {
$user_id = $account_data['id'];
}
$latest_post_url = null;
$created_at = null;
if ($user_id) {
// Get statuses by user ID
$statuses_url = "https://$domain/api/v1/accounts/$user_id/statuses?limit=1";
$response = @file_get_contents($statuses_url, false, $context);
if ($response !== false) {
$statuses = json_decode($response, true);
if (is_array($statuses) && !empty($statuses)) {
$created_at = $statuses[0]['created_at'];
if (isset($statuses[0]['url'])) {
$latest_post_url = $statuses[0]['url'];
}
}
}
}
if (!$created_at) {
echo "No posts found for $username ";
continue;
}
// Format date
$date = date('Ymd', strtotime($created_at));
// Only update if date is newer
if ($date > $entry['date']) {
$entry['date'] = $date;
$entry['post_url'] = $latest_post_url;
echo "Updated $username → $date ($latest_post_url) ";
} else {
echo "No new posts for $username (latest: {$entry['date']}) ";
}
}
// Save updated JSON
if (file_put_contents($filename, json_encode($json_data, JSON_PRETTY_PRINT))) {
echo " JSON file updated successfully.";
} else {
echo " Error saving JSON file. Check permissions.";
}
?>
Fedi Follow List Creator
----------------
index.html
--
adduser
Fediverse Posts Browser
saveuser.php
--
false, 'message' => 'Invalid URL format'];
}
$domain = $parsedUrl['host'];
$username = null;
// Check if it's a direct @user@domain style URL (like Mastodon)
if (preg_match('#/@([^/@]+)(?:@[^/]+)?/(?:posts/)?\d+#', $parsedUrl['path'] ?? '', $matches)) {
$username = $matches[1];
}
// Check for notice/status IDs (like Pleroma/Akkoma)
else if (preg_match('#/notice/([^/?]+)#', $parsedUrl['path'] ?? '', $matches)) {
$statusId = $matches[1];
$username = resolveUsernameFromNotice($domain, $statusId);
if (!$username) {
// Prompt for username if resolution fails
if (isset($_POST['username']) && !empty($_POST['username'])) {
$username = $_POST['username'];
} else {
return [
'success' => false,
'needs_username' => true,
'url' => $url,
'domain' => $domain,
'message' => 'Could not resolve username automatically. Please enter it below.'
];
}
}
} else {
return ['success' => false, 'message' => 'URL format not recognized: ' . ($parsedUrl['path'] ?? 'no path')];
}
// Try to fetch profile picture
$pfpUrl = null;
if (!isset($_POST['pfp_url'])) {
$pfpUrl = fetchProfilePicture($domain, $username);
} else if (!empty($_POST['pfp_url'])) {
$pfpUrl = $_POST['pfp_url'];
}
// If we couldn't get the pfp URL and it wasn't provided, prompt for it
if (!$pfpUrl && !isset($_POST['pfp_url'])) {
return [
'success' => false,
'needs_pfp' => true,
'url' => $url,
'domain' => $domain,
'username' => $username,
'message' => 'Could not fetch profile picture automatically. Please enter the URL below.'
];
}
// Save to JSON
$userIdentifier = "$username@$domain";
$success = saveToJson($userIdentifier, $url, $pfpUrl);
if ($success) {
return ['success' => true, 'user' => $userIdentifier, 'url' => $url, 'pfp' => $pfpUrl];
} else {
return ['success' => false, 'message' => 'Failed to save to JSON file'];
}
}
function resolveUsernameFromNotice($domain, $statusId) {
// Try to fetch the status information using ActivityPub or Mastodon API
$apiUrl = "https://$domain/api/v1/statuses/$statusId";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'Fediverse-User-Resolver/1.0');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$data = json_decode($response, true);
if (isset($data['account']['acct'])) {
return $data['account']['acct'];
}
if (isset($data['account']['username'])) {
return $data['account']['username'];
}
}
return null;
}
function fetchProfilePicture($domain, $username) {
// Try to fetch user information using Mastodon API
$apiUrl = "https://$domain/api/v1/accounts/lookup?acct=$username";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'Fediverse-User-Resolver/1.0');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$data = json_decode($response, true);
if (isset($data['avatar'])) {
return $data['avatar'];
}
}
return null;
}
function saveToJson($userIdentifier, $url, $pfpUrl) {
$filename = 'fediusers.json';
$data = [];
// Read existing data if file exists
if (file_exists($filename)) {
$existingData = file_get_contents($filename);
if ($existingData) {
$data = json_decode($existingData, true) ?: [];
}
}
// Check if this user already exists
$exists = false;
foreach ($data as $entry) {
if ($entry['user'] === $userIdentifier) {
$exists = true;
break;
}
}
// Add new entry if it doesn't exist
if (!$exists) {
$data[] = [
'user' => $userIdentifier,
'url' => $url,
'pfp' => $pfpUrl,
'added' => date('Y-m-d H:i:s')
];
// Write back to file
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
return file_put_contents($filename, $json) !== false;
}
return true; // Already exists, consider it a success
}
?>
Fediverse User Saver
Fediverse User Saver
Error:
Supported formats:
Mastodon: https://mastodon.example/@username/123456789
Pleroma/Akkoma: https://instance.example/notice/ABC123DEF456
fediusers.json
--
[
{
"user": "alcea@alceawis.com",
"url": "https://alceawis.com/notice/AxWUaYZukUOVrhcSrQ",
"pfp": "https://alceawis.com/uploads/7ec207e13c920294e202c8007828db61de0e0e72fa3dd8f0dc6e94783d38a4c5.png",
"added": "2025-08-25 09:17:58"
},
{
"user": "Samb@mastodon.gamedev.place",
"url": "https://mastodon.gamedev.place/@Samb/112933762886991797",
"pfp": "https://cdn.masto.host/mastodongamedevplace/accounts/avatars/109/270/815/057/921/135/original/8e1fecc5ec4ed0c6.jpg",
"added": "2025-08-25 09:18:09"
},
{
"user": "dr_muesli@woof.tech",
"url": "https://woof.tech/@dr_muesli/115056046900787616",
"pfp": "https://cdn.woof.tech/accounts/avatars/113/820/856/641/199/543/original/f17907d049782ede.png",
"added": "2025-08-25 09:18:15"
}
]
EmojiShorthandDownloader (Zip & single dld)
----------------------
💾 Save Emoji List
$emoji['url'],
'shortcode' => $emoji['shortcode']
];
}
return $emojis;
}
}
// If still no content, return null
if (!$html) {
return null;
}
// Use DOMDocument to parse the HTML and extract emoji data
$dom = new DOMDocument();
@$dom->loadHTML($html);
$emojis = [];
$emojiElements = $dom->getElementsByTagName('div');
foreach ($emojiElements as $element) {
$imgElement = $element->getElementsByTagName('img');
$ddElement = $element->getElementsByTagName('dd');
// Check if we have the necessary elements
if ($imgElement->length > 0 && $ddElement->length > 0) {
$url = $imgElement->item(0)->getAttribute('src');
$shortcode = trim($ddElement->item(0)->nodeValue);
$emojis[] = ['url' => $url, 'shortcode' => $shortcode];
}
}
return $emojis;
}
// Function to download and cache emoji
function cache_emoji($url, $shortcode) {
$extension = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION);
if (empty($extension)) {
$extension = 'png'; // default extension
}
$filename = preg_replace('/[^a-zA-Z0-9_-]/', '', $shortcode) . '.' . $extension;
$cache_dir = __DIR__ . '/emoji_cache/';
if (!file_exists($cache_dir)) {
mkdir($cache_dir, 0755, true);
}
$cache_path = $cache_dir . $filename;
// If not cached or cache is older than 1 day
if (!file_exists($cache_path) || (time() - filemtime($cache_path) > 86400)) {
$image_data = fetch_via_curl($url);
if ($image_data) {
file_put_contents($cache_path, $image_data);
}
}
if (file_exists($cache_path)) {
return [
'path' => $cache_path,
'filename' => $filename,
'mime' => mime_content_type($cache_path)
];
}
return false;
}
$filtered = [];
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Handle emoji download
if (isset($_POST['download_single'])) {
$url = $_POST['url'];
$shortcode = $_POST['shortcode'];
$cached = cache_emoji($url, $shortcode);
if ($cached) {
header('Content-Type: ' . $cached['mime']);
header('Content-Disposition: attachment; filename="' . $cached['filename'] . '"');
readfile($cached['path']);
exit;
} else {
header("HTTP/1.0 404 Not Found");
echo "Failed to download emoji";
exit;
}
}
// Handle ZIP download
if (isset($_POST['download_all'])) {
$instance = $_POST['instance'];
$keyword = $_POST['keyword'];
// Fetch emojis again to ensure we have fresh data
$emojis = fetch_emojis($instance);
if ($emojis !== null) {
$filtered = [];
foreach ($emojis as $emoji) {
if (empty($keyword) || stripos($emoji['shortcode'], $keyword) !== false) {
$filtered[] = $emoji;
}
}
}
if (!empty($filtered)) {
$zip = new ZipArchive();
$zip_filename = 'emojis_' . time() . '.zip';
$zip_path = sys_get_temp_dir() . '/' . $zip_filename;
if ($zip->open($zip_path, ZipArchive::CREATE) === TRUE) {
foreach ($filtered as $emoji) {
$cached = cache_emoji($emoji['url'], $emoji['shortcode']);
if ($cached) {
$zip->addFile($cached['path'], $cached['filename']);
}
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zip_filename . '"');
header('Content-Length: ' . filesize($zip_path));
readfile($zip_path);
unlink($zip_path);
exit;
}
}
header("HTTP/1.0 404 Not Found");
echo "Failed to create ZIP file";
exit;
}
// Handle the form submission for searching
$instance = isset($_POST['instance']) ? trim($_POST['instance']) : '';
$keyword = isset($_POST['keyword']) ? trim($_POST['keyword']) : '';
if (empty($instance)) {
$error = "Instance URL is required.";
} else {
// Fetch emojis from the instance URL
$emojis = fetch_emojis($instance);
if ($emojis === null) {
$error = "Failed to fetch from $instance";
} else {
// Filter emojis by keyword
foreach ($emojis as $emoji) {
if (empty($keyword) || stripos($emoji['shortcode'], $keyword) !== false) {
$filtered[] = $emoji;
}
}
}
}
}
?>
Emoji Fetcher
Emoji Fetcher
= htmlspecialchars($error) ?>
Matched Emojis (= count($filtered) ?>)
:= htmlspecialchars($emoji['shortcode']) ?>:
Pixiv fetch user artwork stats (via api)
---------------------
singlefetch.php
--
$apiUrl,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
'Referer: https://www.pixiv.net/',
// Uncomment if accessing private/NSFW works (replace XXX with your PHPSESSID):
// 'Cookie: PHPSESSID=XXX;',
],
CURLOPT_ENCODING => 'gzip',
CURLOPT_SSL_VERIFYPEER => false, // Disable if SSL issues occur
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
return ['error' => true, 'message' => "HTTP {$httpCode} - API request failed"];
}
return json_decode($response, true);
}
// Fetch artwork data
$artworkData = fetchPixivData($artworkId);
// Handle errors
if (isset($artworkData['error']) && $artworkData['error']) {
die("Error: " . ($artworkData['message'] ?? 'Failed to fetch artwork'));
}
// Extract data
$title = $artworkData['body']['title'] ?? 'No Title';
$imageUrl = $artworkData['body']['urls']['original'] ?? $artworkData['body']['urls']['regular'] ?? null;
$views = $artworkData['body']['viewCount'] ?? 0;
$bookmarks = $artworkData['body']['bookmarkCount'] ?? 0;
$likes = $artworkData['body']['likeCount'] ?? 0;
$comments = $artworkData['body']['commentCount'] ?? 0;
$artworkUrl = $defaultBaseUrl . $artworkId;
echo ''
. htmlspecialchars($title) . ' ';
if ($imageUrl) {
$proxyImageUrl = "https://i.pixiv.re/" . basename($imageUrl);
echo ''
. ' ';
}
echo sprintf(
'Views: %s | Bookmarks: %s | Likes: %s | Comments: %s',
htmlspecialchars($views),
htmlspecialchars($bookmarks),
htmlspecialchars($likes),
htmlspecialchars($comments)
);
?>
fetchfive.php
--
Cea ';
echo 'Alcea ';
echo 'PixivFE instances ';
/**
* Gets the latest 5 artwork IDs from Pixiv user profile
*/
function getPixivArtworkIds($userId, $limit = 5) {
$apiUrl = "https://www.pixiv.net/ajax/user/{$userId}/profile/all";
$context = stream_context_create([
'http' => [
'header' => "User-Agent: Mozilla/5.0\r\nReferer: https://www.pixiv.net/"
],
'ssl' => [
'verify_peer' => false
]
]);
$response = @file_get_contents($apiUrl, false, $context);
if (!$response) return [];
$data = json_decode($response, true);
if (empty($data['body']['illusts'])) return [];
// Get the most recent artwork IDs
$artworkIds = array_keys($data['body']['illusts']);
return array_slice($artworkIds, 0, $limit);
}
// Configuration: Default userId to Alcea's if not specified
$userId = $_GET['userId'] ?? '75406576'; // Default: Alcea
// Get the latest 5 artwork IDs
$artworkIds = getPixivArtworkIds($userId, 5);
// Loop through artwork IDs and fetch their data via the custom URL
foreach ($artworkIds as $artworkId) {
// Generate the full URL to fetch the artwork
$singlefetchUrl = "https://alceawis.de/other/extra/fetchdata/singlefetch.php?url=" . urlencode("https://www.pixiv.net/artworks/{$artworkId}");
// Fetch the output from the generated URL
$output = @file_get_contents($singlefetchUrl, false, stream_context_create([
'http' => ['timeout' => 5]
]));
// Display the result or an error message if loading failed
echo $output ?: "Failed to load artwork: {$artworkId} ";
}
?>
Pixiv image gallery
------------------
";
if ($page > 1) {
echo "<< Previous ";
}
echo "Page {$page} of {$totalPages} ";
if ($page < $totalPages) {
echo "Next >> ";
}
echo "";
// Start container for inline artworks
echo "";
// Display current batch of artworks in one line
foreach ($currentArtworkIds as $artId) {
$artLink = "https://www.pixiv.net/artworks/{$artId}";
$artImageUrl = "https://embed.pixiv.net/artwork.php?illust_id={$artId}";
// Fetch details only for the current artwork
$html = @file_get_contents($artLink);
$artTitle = "Untitled";
if ($html !== false) {
$dom = new DOMDocument();
@$dom->loadHTML($html);
$titleTag = $dom->getElementsByTagName('title')->item(0);
$artTitle = $titleTag ? $titleTag->textContent : "Untitled";
$artTitle = rtrim($artTitle, ' - pixiv');
}
echo "
";
$safeTitle = htmlspecialchars(addslashes($artTitle), ENT_QUOTES);
$safeImageUrl = htmlspecialchars($artImageUrl, ENT_QUOTES);
echo "
";
echo "
";
echo "
";
}
echo "
"; // Close artworks-container
// Display navigation buttons again at bottom
echo "";
if ($page > 1) {
echo "<< Previous ";
}
echo "Page {$page} of {$totalPages} ";
if ($page < $totalPages) {
echo "Next >> ";
}
echo "
";
// Display total count
echo "Total artworks: {$totalArtworks}
";
// Display all links in details section
echo "";
echo "Click to view all artwork links ";
echo "";
foreach ($artworkIds as $artId) {
echo "https://www.pixiv.net/artworks/{$artId}\n";
}
echo " ";
echo " ";
} else {
echo "No artworks found for the given user.
";
}
}
// Get parameters from URL
$userId = isset($_GET['userId']) ? $_GET['userId'] : '75406576'; // Default user ID
$random = isset($_GET['random']);
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Add user ID input form
echo '';
echo '';
echo '
';
// Display artworks
getPixivUserArt($userId, $random, $page);
?>
×
Uptime Checker
--------------------
check.php
--
['mode' => 'response_code'],
'alceawis.com' => ['mode' => 'file_check'],
'alcea-wisteria.de' => ['mode' => 'response_code']
];
// cURL request with timeout and response code check
function curlGetResponseCode($url, $timeout = 30) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true,
CURLOPT_TIMEOUT => $timeout,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
curl_exec($ch);
$responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_errno($ch);
curl_close($ch);
// Timeout or other error? Treat as 404
if ($error) {
return 404;
}
return $responseCode ?: 404;
}
function checkFileExistence($url, $filename) {
$fullUrl = $url . '/' . $filename;
$responseCode = curlGetResponseCode($fullUrl, 30);
return $responseCode === 200;
}
foreach ($domains as $domain => $config) {
$date = date('Y-m-d H:i:s');
$mode = $config['mode'];
$responseData = [
'date' => $date,
'mode' => $mode,
'domainname' => $domain,
'response_code' => 0
];
if ($mode === 'file_check') {
$exists = checkFileExistence("https://$domain", 'favicon.png') ||
checkFileExistence("https://$domain", 'index.html');
$responseData['response_code'] = $exists ? 200 : 404;
}
if ($mode === 'response_code') {
$responseData['response_code'] = curlGetResponseCode("https://$domain", 30);
}
$filename = "$domain.json";
$existingData = [];
if (file_exists($filename)) {
$json = file_get_contents($filename);
$decoded = json_decode($json, true);
if (is_array($decoded) && array_keys($decoded) === range(0, count($decoded) - 1)) {
$existingData = $decoded;
}
}
$existingData[] = $responseData;
file_put_contents($filename, json_encode($existingData, JSON_PRETTY_PRINT));
echo "Test result for $domain saved/updated in $filename\n";
}
?>
status.html
--
Domain Uptime Monitor
sync.php
--
'ftp.alcea-wisteria.de',
'user' => 'add@alcea-wisteria.de',
'pass' => '', // Replace with actual password
'remoteDir' => 'PHP/0demo/2025-08-04-UptimeCheck',
'localDir' => '/storage/emulated/0/pws/www/2025-08-04-UptimeCheck',
'successMessage' => 'Successfully uploaded to alcea-wisteria.de'
],
[
'host' => 'ftp.alceawis.de',
'user' => 'add@alceawis.de',
'pass' => '', // Replace with actual password
'remoteDir' => 'alceawis.de/other/extra/fetchdata/2025-08-04-UptimeCheck',
'localDir' => '/storage/emulated/0/pws/www/2025-08-04-UptimeCheck',
'successMessage' => 'Successfully uploaded to alceawis.de'
]
];
// Files to be uploaded
$files = [
'alceawis.com.json',
'alceawis.de.json',
'alcea-wisteria.de.json'
];
foreach ($servers as $server) {
foreach ($files as $file) {
$localFile = "{$server['localDir']}/$file";
$remoteFile = "{$server['remoteDir']}/$file";
// Check if local file exists
if (!file_exists($localFile)) {
echo "Local file not found: $localFile\n";
continue;
}
// Open local file
$fp = fopen($localFile, 'r');
if (!$fp) {
echo "Failed to open local file: $localFile\n";
continue;
}
// Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "ftp://{$server['host']}/$remoteFile");
curl_setopt($ch, CURLOPT_USERPWD, "{$server['user']}:{$server['pass']}");
curl_setopt($ch, CURLOPT_UPLOAD, true);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
curl_setopt($ch, CURLOPT_VERBOSE, true); // Optional: shows transfer details
// Execute the file upload
$result = curl_exec($ch);
if (!$result) {
echo "Upload failed for $file to {$server['host']}: " . curl_error($ch) . "\n";
} else {
echo "{$server['successMessage']}: $file\n";
}
// Clean up
curl_close($ch);
fclose($fp);
}
}
?>
Execute multi/different vps .sh via SSH ..
-------------------------
Load Akkoma Script
Load Nginx Script
";
$formSubmitted = true;
} else {
echo "Failed to move the uploaded file. ";
exit(1);
}
} else {
echo "Upload error code: " . $_FILES['ppkFile']['error'] . " ";
exit(1);
}
}
if ($formSubmitted && file_exists($uploadedKey)) {
chmod($uploadedKey, 0600);
// Escape the remote script path safely for bash on remote (no extra quotes)
$escapedRemoteScriptPath = escapeshellcmd($remoteScriptPath);
// Compose SSH command
$sshCommand = "ssh -i " . escapeshellarg($uploadedKey) .
" -o StrictHostKeyChecking=no " . escapeshellarg($remoteServer) .
" 'bash " . $escapedRemoteScriptPath . " > $logFile 2>&1'";
exec($sshCommand, $output, $returnVar);
echo $returnVar === 0 ? "Remote script executed successfully. " : "Remote script failed to execute. ";
// Get the log output from remote
$logContents = shell_exec("ssh -i " . escapeshellarg($uploadedKey) .
" -o StrictHostKeyChecking=no " . escapeshellarg($remoteServer) .
" 'cat $logFile'");
echo $logContents ? "" . htmlspecialchars($logContents) . " " : "No log output. ";
// Cleanup
if (file_exists($uploadedKey)) {
unlink($uploadedKey);
echo "File deleted! ";
}
}
?>
Upload Key and Run
Upload OpenSSH Private Key
Execute remote vps .sh via ssh and openSSHKey and report back (here: check letsencrypt status)
-------------------------
";
$formSubmitted = true;
} else {
echo "Failed to move the uploaded file. ";
exit(1);
}
} else {
echo "Upload error code: " . $_FILES['ppkFile']['error'] . " ";
exit(1);
}
}
if ($formSubmitted && file_exists($uploadedKey)) {
chmod($uploadedKey, 0600);
$sshCommand = "ssh -i $uploadedKey -o StrictHostKeyChecking=no $remoteServer 'bash $remoteScriptPath > $logFile 2>&1'";
exec($sshCommand, $output, $returnVar);
echo $returnVar === 0 ? "Remote script executed successfully. " : "Remote script failed to execute. ";
$logContents = shell_exec("ssh -i $uploadedKey -o StrictHostKeyChecking=no $remoteServer 'cat $logFile'");
echo $logContents ? "" . htmlspecialchars($logContents) . " " : "No log output. ";
// Cleanup
if (file_exists($uploadedKey)) {
unlink($uploadedKey);
echo "File deleted! ";
}
}
?>
Upload Key and Run
Upload OpenSSH Private Key
Folder md5 Hashes (track dir&indir changes)
---------------------
isDir() && !$file->isDot()) {
$subfolderPath = $file->getPathname();
$subdirHash = hashFolderContents($subfolderPath);
$subdirs[] = $file->getFilename() . ' - ' . $subdirHash;
}
}
sort($subdirs); // Sort alphabetically by folder name
return $subdirs;
}
function hashFolderContents($folder) {
$items = [];
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
if ($file->isFile()) {
$relativePath = substr($file->getPathname(), strlen($folder));
$items[] = $relativePath . $file->getSize() . $file->getMTime();
}
}
sort($items); // Ensure consistent sorting for hashing
return md5(implode('', $items));
}
// === Function to load existing hashes from file
function loadExistingHashes($file) {
$hashes = [];
$lines = file($file, FILE_IGNORE_NEW_LINES);
foreach ($lines as $line) {
list($folderName, $hash) = explode(' - ', $line);
$hashes[$folderName] = $hash;
}
return $hashes;
}
// === Function to generate comparison data
function compareHashes($subdirectories, $existingHashes) {
$totalFolders = count($subdirectories);
$missingFolders = 0;
$changedFolders = 0;
$comparisonResult = [];
foreach ($subdirectories as $line) {
list($folderName, $currentHash) = explode(' - ', $line);
if (isset($existingHashes[$folderName])) {
if ($existingHashes[$folderName] !== $currentHash) {
$comparisonResult[$folderName] = ['status' => 'changed', 'hash' => $currentHash];
$changedFolders++;
} else {
$comparisonResult[$folderName] = ['status' => 'same', 'hash' => $currentHash];
}
} else {
$comparisonResult[$folderName] = ['status' => 'missing', 'hash' => $currentHash];
$missingFolders++;
}
}
return [
'total' => $totalFolders,
'missing' => $missingFolders,
'changed' => $changedFolders,
'comparison' => $comparisonResult
];
}
$comparisonData = compareHashes($subdirectories, $existingHashes);
?>
Directory Hashes
📁 Subdirectory MD5 Hashes
Subdirectory Name
MD5 Hash
Status
$data): ?>
✅ File saved: folder.md5hash.txt
Summary
Total Folders: Missing Folders: Changed Folders:
Fediverse Instance Diagnostic Checker
------------------
$emoji $label: $extra";
}
function discover_actor_url($domain, $username = null) {
$base = "https://$domain";
// If username is not provided, try to infer from domain (before first dot)
if ($username === null) {
$username = explode('.', $domain)[0];
}
$guesses = [
"$base/$username",
"$base/users/$username",
"$base/users/admin",
"$base/@$username",
];
if ($domain === "mastodon.social") {
$guesses[] = "$base/users/gargron";
}
foreach ($guesses as $url) {
[$actor, $code, $raw] = fetch_json($url, "application/activity+json");
if ($actor && isset($actor['id'])) {
return [$url, $actor];
}
}
return [null, null];
}
?>
Fediverse Instance Checker
🌐 Fediverse Instance Checker
🔍 Checking $domain ";
// Nodeinfo
$nodeinfo_url = get_nodeinfo_url($domain);
if ($nodeinfo_url) {
[$nodeinfo, $code] = fetch_json($nodeinfo_url);
display_result("NodeInfo (2.0)", true, "Found");
$software = $nodeinfo['software']['name'] ?? 'Unknown';
$version = $nodeinfo['software']['version'] ?? 'Unknown';
$users = $nodeinfo['usage']['users']['total'] ?? 'n/a';
$statuses = $nodeinfo['usage']['localPosts'] ?? 'n/a';
$start_time = $nodeinfo['metadata']['start_time'] ?? null;
echo "Software: $software
";
echo "Version: $version
";
echo "Users: $users
";
echo "Statuses: $statuses
";
if ($start_time) {
$since = (new DateTime())->diff(new DateTime($start_time));
echo "Online since: $start_time (~{$since->days} days)
";
}
} else {
display_result("NodeInfo", false, "Not found");
}
// Webfinger
[$webfinger, $code] = fetch_json("$base/.well-known/webfinger?resource=acct:example@$domain");
display_result("Webfinger", $code === 200, "HTTP $code");
// Instance info
[$instance, $code] = fetch_json("$base/api/v1/instance");
display_result("Instance Metadata", is_array($instance), $instance['uri'] ?? '');
// Emojis
[$emojis, $code] = fetch_json("$base/api/v1/custom_emojis");
display_result("Custom Emojis", is_array($emojis), is_array($emojis) ? count($emojis) . " found" : "");
// Peers
[$peers, $code] = fetch_json("$base/api/v1/instance/peers");
display_result("Federation Peers", is_array($peers), is_array($peers) ? count($peers) . " connected" : "");
// ActivityPub endpoints
echo "📬 ActivityPub Endpoint Discovery ";
list($actor_url, $actor_json) = discover_actor_url($domain);
if (!$actor_json) {
display_result("Actor Discovery", false, "No actor found via smart guessing.");
} else {
display_result("Actor Found", true, $actor_json['preferredUsername'] ?? $actor_json['id']);
// INBOX
$inbox_url = $actor_json['inbox'] ?? null;
if ($inbox_url) {
$headers = @get_headers($inbox_url, 1);
$inbox_status = is_array($headers) && preg_match("/2\d\d|405|403/", $headers[0]);
display_result("Inbox", $inbox_status, "URL: $inbox_url");
} else {
display_result("Inbox", false);
}
// OUTBOX
$outbox_url = $actor_json['outbox'] ?? null;
if ($outbox_url) {
[$outbox_json, $outbox_code] = fetch_json($outbox_url, "application/activity+json");
$valid = $outbox_code === 200 && isset($outbox_json['type']) && stripos($outbox_json['type'], 'OrderedCollection') !== false;
display_result("Outbox", $valid, "URL: $outbox_url");
// Statuses
if (isset($outbox_json['orderedItems'][0]['id'])) {
$status_url = $outbox_json['orderedItems'][0]['id'];
[$status_json, $status_code] = fetch_json($status_url, "application/activity+json");
$valid_status = $status_code === 200 && isset($status_json['type']);
display_result("Statuses", $valid_status, "1st post: $status_url");
} else {
display_result("Statuses", false, "No recent status found");
}
} else {
display_result("Outbox", false);
display_result("Statuses", false, "No outbox to check");
}
}
// Heuristic
echo "Instance Type Guess ";
if (isset($software)) {
if (stripos($software, 'akkoma') !== false) {
echo "This is likely an Akkoma instance.
";
} elseif (stripos($software, 'mastodon') !== false) {
echo "This is likely a Mastodon instance.
";
} elseif (stripos($software, 'pleroma') !== false) {
echo "This is likely a Pleroma instance.
";
} else {
echo "Software type: $software
";
}
}
endif;
?>
.htaccess redirect url only if requested from Domain xy
------------------------
# Match /alceawis/status/* URLs,
RewriteCond %{REQUEST_URI} ^/alceawis/status/.+$
RewriteCond %{HTTP_REFERER} ^https?://(www\.)?alceawis\.com [NC]
RewriteRule ^alceawis/status/(.+)$ /_https://alceawis.com/alceawis/status/$1 [R=301,L]
ActiPub Post JSON fetch
----------------------------
Fetch Mastodon Post ActivityPub Data
Fetch Mastodon Post ActivityPub Data
= $errorMessage ?>
ActivityPub JSON-LD Response:
Password protect php file SECURE (put at file start!)(extrasecure-hashed pass + logout)
----------------------
true,'httponly' => true,'samesite' => 'Strict']);
session_start();
$session_lifetime = 3 * 60; // Session timeout
$correct_username = "admin";
$correct_password_hash = '$2y$10$S9naYnE6MqP14zVRfIsig.A98jBGzEImaGLgKVuiSGKpI7yr7XeGG'; // password: 4869
//echo password_hash("pass", PASSWORD_DEFAULT); //generate
if (isset($_GET['logout'])) {
session_unset();
session_destroy();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['heartbeat'])) {
$_SESSION['last_activity'] = time();
exit;
}
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if ($username === $correct_username && password_verify($password, $correct_password_hash)) {
session_regenerate_id(true);
$_SESSION['logged_in'] = true;
$_SESSION['last_activity'] = time();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
} else {
$error = "Invalid username or password.";
}
}
?>
$error"; ?>
$session_lifetime) {
session_unset();
session_destroy();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
$_SESSION['last_activity'] = time(); // Refresh session activity
$remaining_time = ($_SESSION['last_activity'] + $session_lifetime) - time();
?>
Welcome, you are logged in!
Logout
Mastodon Remote Follow (via APIKey)
----------------------------------
"$remoteUser@$remoteDomain"]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $accessToken"]);
$response = curl_exec($ch);
curl_close($ch);
if ($response === false) {
return false;
}
$data = json_decode($response, true);
// If data has "id", assume fetched successfully
return isset($data['id']);
}
$yourInstance = $_POST['your_instance'] ?? '';
$accessToken = $_POST['access_token'] ?? '';
$remoteUserRaw = $_POST['remote_user'] ?? '';
$result = '';
$error = '';
$offerFetch = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$yourInstance = rtrim(trim($yourInstance), '/');
$accessToken = trim($accessToken);
$remoteUserRaw = trim($remoteUserRaw);
list($remoteUser, $remoteDomain) = resolveAcct($remoteUserRaw);
if ($yourInstance === '' || $accessToken === '' || $remoteUser === '' || $remoteDomain === '') {
$error = "Your Instance URL, Access Token, and Remote User (user@domain) are required.";
} else {
$ch = curl_init();
// Search using just the username (remoteUser)
$searchUrl = $yourInstance . '/api/v2/search?q=' . urlencode($remoteUser) . '&type=accounts&limit=10';
curl_setopt($ch, CURLOPT_URL, $searchUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $accessToken"]);
$searchResponse = curl_exec($ch);
if ($searchResponse === false) {
$error = "Search failed: " . curl_error($ch);
} else {
$searchData = json_decode($searchResponse, true);
$foundUser = null;
foreach ($searchData['accounts'] ?? [] as $account) {
if (strcasecmp($account['acct'] ?? '', "$remoteUser@$remoteDomain") === 0) {
$foundUser = $account;
break;
}
if (domainFromUrl($account['url'] ?? '') === $remoteDomain) {
$acctUser = explode('@', $account['acct'])[0];
if (strcasecmp($acctUser, $remoteUser) === 0) {
$foundUser = $account;
break;
}
}
}
if (!$foundUser) {
// Offer remote fetch option
$offerFetch = true;
$error = "Remote user not found or not federated yet. You can try to fetch the remote user first.";
} else {
// Verify credentials (get own user id)
$verifyUrl = $yourInstance . '/api/v1/accounts/verify_credentials';
curl_setopt($ch, CURLOPT_URL, $verifyUrl);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $accessToken"]);
$verifyResp = curl_exec($ch);
if ($verifyResp === false) {
$error = "Verify credentials failed: " . curl_error($ch);
} else {
$myData = json_decode($verifyResp, true);
if (isset($myData['id']) && $myData['id'] == $foundUser['id']) {
$error = "Cannot follow your own account.";
} else {
$userId = $foundUser['id'];
$followUrl = $yourInstance . "/api/v1/accounts/$userId/follow";
curl_setopt($ch, CURLOPT_URL, $followUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $accessToken"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$followResponse = curl_exec($ch);
if ($followResponse === false) {
$error = "Follow failed: " . curl_error($ch);
} else {
$result = $followResponse;
}
}
}
}
}
curl_close($ch);
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['remote_fetch'])) {
// User requested remote fetch
list($remoteUser, $remoteDomain) = resolveAcct($remoteUserRaw);
if ($yourInstance !== '' && $accessToken !== '' && $remoteUser !== '' && $remoteDomain !== '') {
if (remoteFetch($yourInstance, $accessToken, $remoteUser, $remoteDomain)) {
$result = "Remote user fetched successfully. Please try following again.";
$offerFetch = false;
} else {
$error = "Remote fetch failed.";
}
} else {
$error = "Invalid data for remote fetch.";
}
}
?>
Remote Follow via Mastodon API
Remote Follow on Mastodon
Error
= htmlspecialchars($error) ?>
Response
= htmlspecialchars($result) ?>
Mail client (with broken send)
-----------------
mailclient.php
--
[debug
] IONOS (?)
Error: ' . imap_last_error();
} else {
$folders = imap_list($mailbox, "{" . $customImapHost . "}", "*");
$selectedMailbox = @imap_open($mailboxString . $selectedFolder, $username, $password);
if ($selectedMailbox) {
$emails = imap_search($selectedMailbox, 'ALL', SE_UID);
$emailData = [];
if ($emails) {
rsort($emails);
foreach (array_slice($emails, 0, 30) as $emailNumber) {
$header = imap_headerinfo($selectedMailbox, $emailNumber);
$body = imap_fetchbody($selectedMailbox, $emailNumber, 1);
$decodedBody = imap_qprint($body);
$emailData[] = [
'uid' => $emailNumber,
'from' => $header->fromaddress ?? '',
'subject' => $header->subject ?? '',
'date' => $header->date ?? '',
'body' => htmlspecialchars(substr($decodedBody, 0, 300)) . '...',
'fullBody' => htmlspecialchars($decodedBody),
];
}
}
imap_close($selectedMailbox);
}
imap_close($mailbox);
}
}
?>
Mail Client
IONOS Mail Client
Select Folder:
Compose New Email
Emails from
No emails found in this folder.
send.php
--
Debug Info Received Parameters ";
foreach ($_POST as $key => $value) {
if (stripos($key, 'pass') !== false) {
echo "$key: " . str_repeat('*', strlen($value)) . "\n";
} else {
echo "$key: $value\n";
}
}
echo " ";
// SMTP Mail Function
function sendSMTPMail($smtpHost, $smtpPort, $encryption, $username, $password, $to, $subject, $body) {
$newline = "\r\n";
$timeout = 30;
$contextOptions = [];
// Set encryption socket
$remoteSocket = "$smtpHost:$smtpPort";
if (stripos($encryption, 'ssl') !== false) {
$remoteSocket = "ssl://$smtpHost:$smtpPort";
} elseif (stripos($encryption, 'tls') !== false) {
$contextOptions['ssl'] = ['crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT];
}
$context = stream_context_create($contextOptions);
$socket = @stream_socket_client($remoteSocket, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context);
if (!$socket) {
return "Connection failed: $errstr ($errno)";
}
$sendCmd = function($cmd, $expectCode = 250) use ($socket, $newline) {
if ($cmd !== null) fwrite($socket, $cmd . $newline);
$response = '';
while ($line = fgets($socket, 515)) {
$response .= $line;
if (preg_match('/^\d{3} /', $line)) break;
}
$code = (int)substr($response, 0, 3);
if ($code !== $expectCode && !in_array($expectCode, [0, $code])) {
throw new Exception("SMTP error ($code): $response");
}
return $response;
};
try {
$sendCmd(null, 220);
$sendCmd("EHLO localhost");
if (stripos($encryption, 'tls') !== false) {
$sendCmd("STARTTLS", 220);
if (!stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
throw new Exception("Failed to enable TLS encryption.");
}
$sendCmd("EHLO localhost");
}
$sendCmd("AUTH LOGIN", 334);
$sendCmd(base64_encode($username), 334);
$sendCmd(base64_encode($password), 235);
$sendCmd("MAIL FROM: <$username>");
$sendCmd("RCPT TO: <$to>");
$sendCmd("DATA", 354);
$headers = "From: <$username>$newline";
$headers .= "To: <$to>$newline";
$headers .= "Subject: $subject$newline";
$headers .= "MIME-Version: 1.0$newline";
$headers .= "Content-Type: text/plain; charset=UTF-8$newline";
$headers .= $newline;
$message = $headers . $body . $newline . ".";
$sendCmd($message, 250);
$sendCmd("QUIT", 221);
fclose($socket);
return "Email sent successfully.";
} catch (Exception $e) {
fclose($socket);
return "Error: " . $e->getMessage();
}
}
// Handle POST form
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$to = $_POST['to'] ?? '';
$subject = $_POST['subject'] ?? '';
$body = $_POST['body'] ?? '';
$smtpHost = $_POST['smtpHost'] ?? 'smtp.ionos.de';
$smtpPort = (int)($_POST['smtpPort'] ?? 465);
$smtpEncryption = $_POST['smtpEncryption'] ?? 'SSL';
if ($username && $password && $to && $subject && $body) {
$result = sendSMTPMail($smtpHost, $smtpPort, $smtpEncryption, $username, $password, $to, $subject, $body);
} else {
$result = "Missing required fields.";
}
echo "Result $result
Go Back ";
}
?>
debug.php
--
";
echo "🔍 SMTP Diagnostics for: $smtp_host (user: $username)\n";
echo "_______________________________\n";
// ✅ 1. Ping test
echo "\n📶 Pinging host $smtp_host ...\n";
$ping_result = null;
if (stripos(PHP_OS, 'WIN') === 0) {
$ping_result = shell_exec("ping -n 1 " . escapeshellarg($smtp_host));
$success = strpos($ping_result, 'TTL=') !== false;
} else {
$ping_result = shell_exec("ping -c 1 " . escapeshellarg($smtp_host));
$success = strpos($ping_result, '1 received') !== false || strpos($ping_result, 'bytes from') !== false;
}
echo $success ? "✅ Ping successful.\n" : "⚠️ Ping failed or blocked (not always critical).\n";
// ✅ 2. Define SMTP ports and expected encryption
$ports = [
25 => 'tls',
465 => 'ssl',
587 => 'tls'
];
// ✅ 3. Loop through each port
foreach ($ports as $port => $expected_encryption) {
echo "\n🌐 Testing port $port (expected encryption: $expected_encryption)\n";
// TCP connectivity test
echo "🔌 Testing TCP connection to $smtp_host:$port ... ";
$fp = @fsockopen($smtp_host, $port, $errno, $errstr, 5);
if (!$fp) {
echo "❌ Connection failed: $errstr ($errno)\n";
continue;
} else {
echo "✅ TCP connection successful.\n";
fclose($fp);
}
// PHPMailer test
echo "📤 Sending test email using PHPMailer on port $port...\n";
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = $smtp_host;
$mail->SMTPAuth = true;
$mail->Username = $username;
$mail->Password = $password;
$mail->Port = $port;
if ($port == 465) {
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
} else {
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
}
$mail->setFrom($username, 'SMTP Debug');
$mail->addAddress($username);
$mail->Subject = "SMTP Test via port $port";
$mail->Body = "This is a test email sent at " . date('Y-m-d H:i:s') . " via port $port.";
$mail->send();
echo "✅ Email sent successfully on port $port\n";
} catch (Exception $e) {
echo "❌ PHPMailer error on port $port: " . $mail->ErrorInfo . "\n";
}
}
echo "\n✅ Diagnostics complete.\n";
S/FTP & WebDAV Uploader
----------------------
upload.php
--
[
"method"=>"HEAD",
"header"=>"Authorization: Basic ".base64_encode("$username:$password"),
"ignore_errors"=>true
]];
$ctxCheck = stream_context_create($optsCheck);
@file_get_contents($url,false,$ctxCheck);
if (isset($http_response_header)) {
foreach($http_response_header as $line){
if (preg_match('#HTTP/\d+\.\d+\s+(\d+)#', $line, $m)){
$code = intval($m[1]);
if($code >= 200 && $code < 300){
$debug[] = "WebDAV upload canceled: '$remoteFile' already exists.";
return false;
}
break;
}
}
}
// 2. Upload
$data = file_get_contents($localFile);
$opts = ["http"=>[
"method"=>"PUT",
"header"=>"Authorization: Basic ".base64_encode("$username:$password")."\r\nContent-Length: ".strlen($data),
"content"=>$data,
"ignore_errors"=>true
]];
$ctx = stream_context_create($opts);
$res = @file_get_contents($url,false,$ctx);
if ($res === false) {
$debug[] = "WebDAV upload failed: Cannot reach server or unauthorized.";
return false;
}
if (isset($http_response_header) && is_array($http_response_header)) {
$statusLine = $http_response_header[0];
preg_match('#HTTP/\d+\.\d+\s+(\d+)#', $statusLine, $matches);
$code = isset($matches[1]) ? intval($matches[1]) : 0;
if ($code >= 200 && $code < 300) {
$debug[] = "WebDAV upload successful: $remoteFile (HTTP $code)";
return true;
} else {
$debug[] = "WebDAV upload failed: HTTP $code - " . $statusLine;
return false;
}
}
$debug[] = "WebDAV upload unknown result.";
return false;
}
function buildUrl($protocol,$server,$path) {
$scheme=($protocol==='webdav')?'https':$protocol;
return "$scheme://$server$path";
}
function listDirectory($protocol, $server, $username, $password, $path, &$debug) {
$files=[];
if ($protocol==='ftp') {
$conn=@ftp_connect($server);
if($conn&&@ftp_login($conn,$username,$password)){
ftp_pasv($conn,true);
if(@ftp_chdir($conn,$path)){
$raw=ftp_rawlist($conn,".");
foreach($raw as $line){
$parts=preg_split("/\s+/",$line,9);
if(count($parts)===9){
$files[]=['name'=>$parts[8],'type'=>$parts[0][0]==='d'?'dir':'file'];
}
}
}
ftp_close($conn);
}
} elseif($protocol==='sftp') {
$conn=@ssh2_connect($server);
if($conn&&@ssh2_auth_password($conn,$username,$password)){
$sftp=ssh2_sftp($conn);
$dh=@opendir("ssh2.sftp://$sftp$path");
if($dh){while(($f=readdir($dh))!==false){if($f==='.'||$f==='..')continue;$fp="ssh2.sftp://$sftp$path$f";$files[]=['name'=>$f,'type'=>is_dir($fp)?'dir':'file'];}closedir($dh);}
}
} elseif($protocol==='webdav') {
$url=buildUrl($protocol,$server,$path);
$opts=["http"=>["method"=>"PROPFIND","header"=>"Authorization: Basic ".base64_encode("$username:$password")."\r\nDepth: 1","content"=>""]];
$ctx=stream_context_create($opts);
$res=@file_get_contents($url,false,$ctx);
if($res!==false){preg_match_all('/(.*?)<\/d:href>/i',$res,$m);foreach($m[1] as $href){$nm=basename(parse_url($href,PHP_URL_PATH));if($nm&&$nm!==basename($path)){$files[]=['name'=>$nm,'type'=>(substr($href,-1)==='/')?'dir':'file'];}}}
}
return $files;
}
// -- FORM VALUES --
$username = getQuery('username');
$password = getQuery('password');
$server = getQuery('server');
$path = getQuery('path', '/');
$protocol = getQuery('protocol', 'ftp');
$uploadType = getQuery('upload_type', 'url');
$anonymous = getQuery('anonymous', '') ? true : false;
if ($anonymous) {
$username = 'anonymous';
$password = 'anonymous@domain.com';
}
$isDir = substr($path, -1) === '/';
$files = [];
$debug = [];
// -- HANDLE UPLOAD --
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($uploadType==='file' && !empty($_FILES['upload_file']['tmp_name'])) {
$file = $_FILES['upload_file'];
$remoteFile = basename($file['name']);
$tmpFile = $file['tmp_name'];
if($protocol==='ftp') ftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
elseif($protocol==='sftp') sftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
elseif($protocol==='webdav') webdavUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
} elseif($uploadType==='url' && !empty($_POST['upload_url'])) {
$urlFile = $_POST['upload_url'];
$remoteFile = basename(parse_url($urlFile, PHP_URL_PATH));
$tmpFile = tempnam(sys_get_temp_dir(), 'up');
if(file_put_contents($tmpFile, file_get_contents($urlFile))===false){
$debug[] = "Download from URL failed: $urlFile";
} else {
if($protocol==='ftp') ftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
elseif($protocol==='sftp') sftpUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
elseif($protocol==='webdav') webdavUpload($server,$username,$password,$path,$tmpFile,$remoteFile,$debug);
}
unlink($tmpFile);
}
if(!empty($debug)){
echo "";
foreach($debug as $d) echo htmlspecialchars($d) . " ";
echo "
";
}
}
// -- HTML FORM --
echo '
Upload type:
File
URL
Anonymous Login
Username:
Password:
Server:
Path:
Protocol:
FTP
SFTP
WebDAV
Select file to upload:
Enter URL to upload:
';
// -- Directory listing --
if ($server && $isDir) {
$files = listDirectory($protocol, $server, $username, $password, $path, $debug);
if ($path !== '/') {
$parent = rtrim($path, '/');
$parent = substr($parent, 0, strrpos($parent, '/') + 1);
echo '.. (Parent directory) ';
}
echo "";
foreach ($files as $file) {
$name = $file['name'];
$type = $file['type'];
$urlPath = $path . $name . ($type === 'dir' ? '/' : '');
echo '';
if ($type === 'dir') {
echo "📁 " . htmlspecialchars($name) . " ";
} else {
$downloadUrl = "download.php?protocol=" . urlencode($protocol) .
"&server=" . urlencode($server) .
"&path=" . urlencode($urlPath) .
"&username=" . urlencode($username) .
"&password=" . urlencode($password) .
"&anonymous=" . ($anonymous?1:0);
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if (in_array($ext, ['mp3','mp4','png','jpg','jpeg','gif'])) {
echo "📄 " . htmlspecialchars($name) . " ";
} else {
echo "📄 " . htmlspecialchars($name) . " ";
}
}
echo " ";
}
echo " ";
}
?>
download.php
--
'audio/mpeg',
'mp4' => 'video/mp4',
'png' => 'image/png',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'gif' => 'image/gif'
);
$contentType = isset($mime[$ext]) ? $mime[$ext] : 'application/octet-stream';
// Build remote URL
$url = ($protocol === 'webdav' ? 'https' : $protocol) . "://$username:$password@$server$path";
// Stream to browser
header("Content-Type: $contentType");
header('Content-Disposition: inline; filename="' . basename($path) . '"');
readfile($url);
exit;
?>
streamtplink.php
--
$size - 1) $end = $size - 1;
$length = $end - $start + 1;
$status = 206;
}
// Set headers
if (function_exists('http_response_code')) {
http_response_code($status);
} else {
header($_SERVER["SERVER_PROTOCOL"] . " " . $status);
}
header("Content-Type: video/mp4");
header("Accept-Ranges: bytes");
header("Content-Length: $length");
header('Content-Disposition: inline; filename="' . basename($remoteFile) . '"');
if ($status === 206) {
header("Content-Range: bytes $start-$end/$size");
}
// Open a temporary local stream for output buffering
// Use ftp_nb_fget to fetch from FTP in chunks and output directly
$tmpStream = fopen('php://output', 'wb');
if (!$tmpStream) {
ftp_close($ftp);
http_response_code(500);
echo "Failed to open output stream.";
exit;
}
// ftp_nb_fget doesn't support offset, so we have to download full or partial file manually
// We'll download full file into php://output but skip bytes before $start by reading and discarding
// Unfortunately, FTP protocol itself doesn't support partial retrieval starting at offset
// so we have to download and skip bytes, or use ftp_raw to send REST command (some FTP servers support it)
// We'll try REST command
ftp_raw($ftp, "TYPE I"); // Switch to binary mode
// Attempt REST command for offset
$restResp = ftp_raw($ftp, "REST $start");
if (strpos(implode("\n", $restResp), '350') === false) {
// REST not supported or failed - fallback to downloading entire file and skipping in PHP
$start = 0; // ignore range start - will download entire file
$length = $size;
$status = 200;
}
$ret = ftp_nb_fget($ftp, $tmpStream, $remoteFile, FTP_BINARY);
$bytesSent = 0;
while ($ret == FTP_MOREDATA) {
flush();
$ret = ftp_nb_continue($ftp);
}
fclose($tmpStream);
ftp_close($ftp);
}
// If cached file does NOT exist, do caching download with progress page and play button
if (!file_exists($cacheFile)) {
// Show progress bar page with play button, video, speed and ETR display and direct play button
echo 'Downloading... ';
echo "Downloading and caching video file... ";
echo '
Direct Play
Play Now
';
echo '';
echo 'Speed: 0 KB/s | Estimated time remaining: calculating...
';
echo ' ';
echo '';
flush();
// Connect FTP
$ftp = ftp_connect($server);
if (!$ftp || !ftp_login($ftp, $username, $password)) {
http_response_code(500);
echo "FTP connection failed.
";
exit;
}
ftp_pasv($ftp, true);
// Get file size for progress calculation
$ftpSize = ftp_size($ftp, $relativePath);
if ($ftpSize <= 0) {
echo "Failed to get remote file size.