<?php
/**
 * shaargem
 *
 * This plugin provides gemini support
 */

use Shaarli\Config\ConfigManager;
use Shaarli\Plugin\PluginManager;
use Shaarli\Render\TemplatePage;

static $redirect_counter = 0;
/**
 * In the footer hook, there is a working example of a translation extension for Shaarli.
 *
 * The extension must be attached to a new translation domain (i.e. NOT 'shaarli').
 * Use case: any custom theme or non official plugin can use the translation system.
 *
 * See the documentation for more information.
 */
const EXT_TRANSLATION_DOMAIN = 'shaargem';


/*
 * This is not necessary, but it's easier if you don't want Poedit to mix up your translations.
 */
function shaargem_t($text, $nText = '', $nb = 1)
{
	return t($text, $nText, $nb, EXT_TRANSLATION_DOMAIN);
}

/**
 * Initialization function.
 * It will be called when the plugin is loaded.
 * This function can be used to return a list of initialization errors.
 *
 * @param $conf ConfigManager instance.
 *
 * @return array List of errors (optional).
 */
function shaargem_init($conf)
{
    if (! $conf->exists('translation.extensions.shaargem')) {
        // Custom translation with the domain 'shaargem'
        $conf->set('translation.extensions.shaargem', 'plugins/shaargem/languages/');
        $conf->write(true);
    }

    //$errors[] = 'This a shaargem init error.';
    return $errors;
}

/**
 * Hook render_editlink.
 *
 * Template placeholders:
 *   - field_plugin: add link fields after tags.
 *
 * @param array $data data passed to plugin
 *
 * @return array altered $data.
 */
function hook_shaargem_render_editlink($data)
{
	$data['link']['title'] = fetch_iri_title($data['link']['url']);
	return $data;
}

/**
 * Hook savelink.
 *
 * Triggered when a link is save (new or edit).
 * All new links now contain a 'stuff' value.
 *
 * @param array $data contains the new link data.
 *
 * @return array altered $data.
 */
function hook_shaargem_save_link($data)
{
	// ugly hack to get scheme
	if(isset($_POST['lf_url'])) {
		if(strstr($_POST['lf_url'],"gemini://"))
		{
			$new_url = str_replace("http://","gemini://",$data['url']);
			$data['url'] = $new_url;
		}
	}
	return $data;
}

/**
 * Hook render_linklist.
 *
 * Template placeholders:
 *   - action_plugin: next to 'private only' button.
 *   - plugin_start_zone: page start
 *   - plugin_end_zone: page end
 *   - link_plugin: icons below each links.
 *
 * Data:
 *   - _LOGGEDIN_: true/false
 *
 * @param array $data data passed to plugin
 *
 * @return array altered $data.
 */
function hook_shaargem_render_linklist($data)
{
	foreach ($data['links'] as &$value) {
		$value['description'] = preg_replace(',gemini://([\d\w\.\+\-@\:%._\~#=/]+),','<a href="gemini://\1">gemini://\1</a>',$value['description']);
	}
	return $data;
}

/**
 * This function is never called, but contains translation calls for GNU gettext extraction.
 */
function shaargem_dummy_translation()
{
	// meta
	t('Provides Gemini protocol support.');
}

/**
 * Find capsule's title
 */
function fetch_iri_title($iri)
{
	$ret = preg_match(",gemini://([\d\w\.\+\-@\:%._\~#=]+)/?,", $iri ,$domain);
	static $redirect_counter = 0;
	if ($ret)
	{
		$stream_context = stream_context_create([ 'ssl' => [
			'verify_peer'       => false,
			'verify_peer_name'  => false,
			'allow_self_signed' => true,
			'verify_depth'      => 0 ]]);

		$fp = stream_socket_client("tls://".$domain[1].":1965", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $stream_context);

		if (!$fp) {
			error_log("$errstr ($errno)");
		} else {
			fwrite($fp, $iri."\r\n");
			$header = fgets($fp);
			$ret = preg_match(",^(\d\d) (.*)\r\n$,", $header, $headers);
			$status = $headers[1];
			$meta = $headers[2];
			$max_redirects = 10;

			error_log("status:".$status.", meta:".$meta);

			// status 1x cannot be handled by shaarli, but input field can be used as title
			if ($status[0] == 1)
			{
				return $meta;
			}
			// status 2x ok
			elseif ($status[0] == 2)
			{
				$nblines = 1;
				while($line = fgets($fp)) {
				$ret = preg_match(",# (.*),",$line,$title);
				if ($title[0] or $nblines > 100 ) {
					break;
					}
				$nblines++;
				}
			}
			// status 3x redirect
			elseif ($status[0] == 3 and $redirect_counter < $max_redirects) 
			{
				$redirect_counter++;
				error_log("[shaargem] found status 30. redirecting to ".$meta." (".$redirect_counter."/".$max_redirects.")");
				$title[1] = fetch_iri_title($meta);
			} 
			// 4x 5x 6x are error statuses, should find a better way to display that
			elseif ($status[0] == 4)
			{
				return 'Status '.$status.' (TEMPORARY FAILURE): '.$meta;
			}
			elseif ($status[0] == 5)
			{
				return 'Status '.$status.' (PERMANENT FAILURE): '.$meta;
			}
			elseif ($status[0] == 6)
			{
				return 'Status '.$status.' (CLIENT CERTIFICATE REQUIRED): '.$meta;
			}
			else
			{
				return "Invalid response:".$header;
			}
			fclose($fp);
		}
	}
	return $title[1];
}