Skip to content

Instantly share code, notes, and snippets.

@drushadrusha
Created July 7, 2023 17:15
Show Gist options
  • Save drushadrusha/ca522d3bf9bca2804a48c5b72892cc09 to your computer and use it in GitHub Desktop.
Save drushadrusha/ca522d3bf9bca2804a48c5b72892cc09 to your computer and use it in GitHub Desktop.
PHP Gemini Client
<?php
// This is a simple PHP script that can be used to fetch a Gemini URL and return the contents.
// Example usage:
try {
echo gemini_get_contents('gemini://gemini.circumlunar.space');
} catch(Exception $e) {
echo $e->getMessage();
}
function gemini_get_contents($url, $redirectIndex = 0){
if($redirectIndex > 5){
throw new Exception("Too many redirects.");
}
$hostname = parse_url($url, PHP_URL_HOST);
$port = parse_url($url, PHP_URL_PORT);
if (!$port) {
$port = 1965;
}
$context = stream_context_create(['ssl' => ['verify_peer' => false]]);
$socket = stream_socket_client('ssl://' . $hostname . ':' . $port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
if (!$socket) {
throw new Exception("$errstr ($errno)");
}
$request = $url . "\r\n";
fwrite($socket, $request);
$response = '';
while (!feof($socket)) {
$data = fgets($socket);
$response .= $data;
}
$status_code = substr($response, 0, 2);
switch($status_code){
case 10:
case 11:
throw new Exception("Server requested input. Not supported.");
break;
case 20:
$response = substr($response, strpos($response, "\n")+1);
break;
case 30:
case 31:
$url = substr($response, 3, -2);
return gemini_get_contents($url, $redirectIndex + 1);
break;
case 40:
throw new Exception("Temporary failure.");
break;
case 41:
throw new Exception("Server unavailable.");
break;
case 42:
throw new Exception("CGI error.");
break;
case 43:
throw new Exception("Proxy error.");
break;
case 44:
throw new Exception("Slow down.");
break;
case 50:
throw new Exception("Permanent failure.");
break;
case 51:
throw new Exception("Not found.");
break;
case 52:
throw new Exception("Gone.");
break;
case 53:
throw new Exception("Proxy request refused.");
break;
case 59:
throw new Exception("Bad request.");
break;
case 60:
throw new Exception("Client certificate required.");
break;
case 61:
throw new Exception("Certificate not authorized.");
break;
case 62:
throw new Exception("Certificate not valid.");
break;
default:
throw new Exception("Invalid response code.");
break;
}
fclose($socket);
return $response;
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment