<?php
/*
Plugin Name: LinkLift (Widgets)
Plugin URI: http://www.linklift.de/meine-seiten/
Description: LinkLift-Textlinks-Plugin  &nbsp;||&nbsp;  Sell text link ads off your blog for a fixed price per month. Register at <a href="http://www.linklift.de/?ref=2d2abc54341" target="_self">http://www.linklift.de/</a>  &nbsp;||&nbsp;  The plugin automatically downloads your current text link ads from the LinkLift servers and saves them to the options-table of your Wordpress-database ('wp_options').
Author: Andreas Rayo Kniep
Version: 1.3
Author URI: http://www.linklift.de/
*/
// tab-size within this source: 4 spaces



/**	This is the plug-in's name that is used by Wordpress
 *    to identify the LinkLift-textlinks-plug-in internally.
 *  You may change this constant in order to change the plug-in's name
 *    as shown in the Wordpress-Widgets-panel.
 *  Names are usually randomised iff they will appear in the generated source-code of the CMS.
 *    Constant names that appear in the source-code increase the detectability of the plug-in!
 */
define("LL_PLUGIN_NAME"						, "get" );

define("LL_PLUGIN_MENU_FILENAME"			, "linklift-configuration" );
define("LL_PLUGIN_REGISTER_LINK_URL"		, "http://www.linklift.de/?ref=2d2abc54341" );


/**	The following constants contain Wordpress-specific-filenames
 *    that are used within the plug-in in order to generate links between Wordpress-admin-pages.
 */
define("LL_WORDPRESS_FILE_PLUGINS"			, "plugins.php" );
define("LL_WORDPRESS_FILE_THEME_EDITOR"		, "theme-editor.php" );
define("LL_WORDPRESS_FILE_ADMIN_FUNCTIONS"	, "admin-functions.php" );


/**	Checking for Wordpress-widgets-plug-in ...
 * - If pre-installed an admin-file "widgets.php" exists.
 * - If installed as Wordpress-plug-in a respective plug-in exists.
 */
if (file_exists("widgets.php"))
{
	define("LL_WORDPRESS_WIDGETS_INSTALLED"	, TRUE );
	define("LL_WORDPRESS_FILE_WIDGETS"		, "widgets.php" );
	
} else {
	// the function get_plugins is only accessible if the file admin-functions.php has been included
		// if it has not yet been included we will try so, now:
	if (file_exists(LL_WORDPRESS_FILE_ADMIN_FUNCTIONS))
		@include_once(LL_WORDPRESS_FILE_ADMIN_FUNCTIONS);
	
	if (function_exists("get_plugins"))
		$installed_plugins = get_plugins();
	else
		$installed_plugins = array();
	
	
	if (isset($installed_plugins["widgets/widgets.php"]))
	{
		define("LL_WORDPRESS_WIDGETS_INSTALLED"	, TRUE );
		define("LL_WORDPRESS_FILE_WIDGETS"		, "themes.php?page=widgets/widgets.php" );
		
	} else {
		// no Wordpress-widgets-plug-in installed!
		define("LL_WORDPRESS_WIDGETS_INSTALLED"	, FALSE );
	} //if-else
} //if-else




// trying to extract the installed language out of the Wordpress-constant 'WPLANG':
$wordpress_language      = strtolower( substr( WPLANG, 0, 2 ) );
// default language: english
$plugin_default_lang     = "en";

// language-specific texts
$language_file_wordpress = dirname(__FILE__) . "/lang_" . $wordpress_language  . ".inc.php";
$language_file_default   = dirname(__FILE__) . "/lang_" . $plugin_default_lang . ".inc.php";

// all not-translated texts will be taken from the english text-file (if existing) ...
if (file_exists($language_file_wordpress))
    @include_once( $language_file_wordpress );
if (file_exists($language_file_default))
    @include_once( $language_file_default );




/* ****************************************************************
 * http://wordpress-deutschland.org                               *
 * creation date:  2007-07-31                                     *
 * contact:        support@linklift.de                            *
 * script-version: 1.3    (2007-05-14)                            *
 * ****************************************************************/



/**	The script-version-constants are used for a check
 *	if a newer version of your plug-in is available on the LinkLift-server.
 *  Note: the plug-in will not update itself, at this time.
 */
define("LL_PLUGIN_LANGUAGE",	'wordpress' );
define("LL_PLUGIN_VERSION",		'1.3' );
define("LL_PLUGIN_DATE",		'2007-05-22' );


/**	In order to not block the page-load-progrss
 *	a time-limit (in seconds) is set when receiving new data from the LinkLift-server.
 */
define("LL_DATA_TIMEOUT",		7);



/**	Disabling all error- (, warning-, and notice-) messages...
 *	You may want to change this when testing or debugging your own page.
 */
error_reporting( 0 );			/*	default:		E_ERROR | E_WARNING | E_PARSE
								 *	all messages:	E_ALL
								 *	only errors:	E_ERROR
								 *	no messages:	0
								 */


/**
 * The function retrieves textlink-data to your adspace from the LinkLift-server.
 * The data is received in XML-format and contains information about all textlinks currently booked on your adspace.
 * The function is invoked by ll_textlink_code() if the local XML-file is not existent or out-of-date.
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2006-09-18
 * @return string Textlink-data that has just been received from the LinkLift-server in XML-format (without leading HTTP-header-information), or an empty String if an error occured.
 */
function ll_retrieve_xml_from_ll_server()
{
	$xml = "";
	$server_host = "www.linklift.de";
	
	if ($ll_server = fsockopen($server_host, 80, $errno, $errstr, LL_DATA_TIMEOUT))
	{
		if (function_exists("stream_set_blocking"))
			stream_set_blocking($ll_server, FALSE);
		
		if     (function_exists("stream_set_timeout"))
			stream_set_timeout( $ll_server, LL_DATA_TIMEOUT);
		elseif (function_exists("socket_set_timeout"))
			socket_set_timeout( $ll_server, LL_DATA_TIMEOUT);
		
		
		$linklift_website_key = "";
		$linklift_website_key = ll_get_option("linklift_website_key", $linklift_website_key);
		if (empty($linklift_website_key))
			$linklift_website_key = ll_translate( "LINKLIFT_WEBSITE_KEY" );
		
		
		
		$connection_start_time = time();
		
		
		$request =   'GET /external/textlink_data.php5'
					. '?' . 'website_key'				. '=' . $linklift_website_key
					. '&' . 'plugin_language'			. '=' . LL_PLUGIN_LANGUAGE
					. '&' . 'plugin_version'			. '=' . LL_PLUGIN_VERSION
					. '&' . 'http_request_uri'			. '=' . ((isset($_SERVER['REQUEST_URI'])    )?(urlencode($_SERVER['REQUEST_URI'])    ):(''))
					. '&' . 'http_user_agent'			. '=' . ((isset($_SERVER['HTTP_USER_AGENT']))?(urlencode($_SERVER['HTTP_USER_AGENT'])):(''))
					. '&' . 'linklift_title'			. '=' . 'll_get_option( "linklift_title"               , Empfehlungen)'
					. '&' . 'condition_no_css'			. '=' . ((ll_get_option( "linklift_css_no_css"          , TRUE))?('1'):('0'))
					. '&' . 'condition_no_html_tags'	. '=' . ((ll_get_option( "linklift_no_html_tags"        , FALSE))?('1'):('0'))
					. ' '
					
					. "HTTP/1.0\n"
					. "Host: " . $server_host . "\n"
					. "Connection: Close\n"
					. "\n"
					
					. '';
		
		fwrite( $ll_server,	$request );
		
		
		
		while (! feof($ll_server))
		{
			$xml_before = $xml;
			$xml       .= fread($ll_server, 10000); 
			
			// if no data was received (yet) ...
			if ($xml_before == $xml)
			{
				// ... go to sleep for 10 ms, waiting for data.
					// usleep() works on Linux-like servers!
					// On other systems usleep may have no effect
					// PHP 5.0.0 claims that usleep works on Windows-systems, as well ...
					// ... the effect on the system's processor, however, is not known to the writer.
				if (function_exists("usleep"))
					usleep($micro_seconds = 10 * 1000);
				
				// if no data was received and the the data-timout was reached
					// the download-process will be stopped.
				if (LL_DATA_TIMEOUT < time() - $connection_start_time)
				{
					$xml = "";
					break;
				} //if
			} //if
		} //while
		
		fclose($ll_server);
	} //if
	
	
	if (FALSE === strpos($xml, "<?xml"))
		return "";
	return strstr($xml, "<?xml");
} //ll_retrieve_xml_from_ll_server()

/**
 * The function retrieves textlink-data to your adspace from the local XML-file (i.e. the file-system).
 * The data is read in XML-format and contains information about all textlinks currently booked on your adspace.
 * Usually, the local XML-file gets updated after a certain period of time by calling ll_retrieve_xml_from_ll_server().
 * The function is invoked by ll_textlink_code() if there is a local XML-file and it is not out-of-date.
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2006-09-18
 * @return string Textlink-data that has been stored in the local XML-file in XML-format, or an empty String if an error occured.
 */
function ll_retrieve_xml_from_file_system()
{
	$xml = "";
	
	if (   (filesize(LL_TEXTLINK_DATAFILE) > 0)
		&& ($xmlfile = fopen(LL_TEXTLINK_DATAFILE, "r"))   )
	{
		$xml = fread($xmlfile, filesize(LL_TEXTLINK_DATAFILE));
		fclose($xmlfile);
	} //if
	
	return $xml;
} //ll_retrieve_xml_from_file_system()

/**
 * The function writes textlink-data to your adspace into the local XML-file (i.e. the file-system).
 * The data is received in XML-format and contains information about all textlinks currently booked on your adspace.
 * Usually, the delivered textlink-data has just been received, i.e. downloaded, from the LinkLift-server using ll_retrieve_xml_from_ll_server().
 * The function is invoked by ll_textlink_code() after calling ll_retrieve_xml_from_ll_server() and if the received data exceeds a certain length (of bytes).
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2006-09-18
 * @param $xml string The textlink-data in XML-format that, usually, has just been received from the LinkLift-server.
 * @return void
 */
function ll_write_xml_to_file_system($xml)
{
	if ($xmlfile = fopen(LL_TEXTLINK_DATAFILE, "w"))
	{
		fwrite($xmlfile, $xml);
		fclose($xmlfile);
		
		// Removed: not working on all webservers!
		// Read and write for owner, nothing for everybody else
		// chmod(LL_TEXTLINK_DATAFILE, 0600);
	} //if
} //ll_write_xml_to_file_system()

/**
 * This function is added for adspaces using a PHP-version lesser than v4.3.0.
 * The function converts all HTML entities to their applicable characters .
 * The function is the opposite of htmlentities() in that it converts all HTML entities to their applicable characters from string.
 * This function is NOT used at this time!
 *
 * @author php.net (http://de.PHP.net/manual/de/function.html-entity-decode.php)
 * @param $string string containing the HTML-entities that have to be converted to their applicable characters.
 * @return string The converted String.
 */
function un_htmlentities($string) 
{
	$string    = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\1"))', $string);
	$string    = preg_replace('~&#([0-9]+);~e'     , 'chr(\1)'          , $string); 
	
	$trans_tbl = get_html_translation_table(HTML_ENTITIES);
	$trans_tbl = array_flip($trans_tbl);
	
	return strtr($string, $trans_tbl);
} //un_htmlentities()

/**
 * The function parses the textlink-data to your adspace out of a String given in XML-format.
 * Usually, the delivered string contains the XML-data either just received from the LinkLift-server or read out of the local XML-file.
 * The function returns a multi-dimensional Array of textlinks containing information like link_url, link_text, link_prefix, link_postfix, and so on.
 * The function is invoked by ll_textlink_code() after calling either ll_retrieve_xml_from_ll_server() or ll_retrieve_xml_from_file_systems().
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2006-09-18, 2006-12-03
 * @param $xml string The textlink-data as String and in XML-format that either has just been received from the LinkLift-server or read out of the local XML-file.
 * @return array of textlink-data. Each element is representing one actual textlink on your website in that it contains information like link_url, link_text, link_prefix, link_postfix, and so on.
 */
function ll_retrieve_textlink_data_from_xml( $xml = '' )
{
	// well-formedness of XML is assumed!
	preg_match_all ('!<prefix>(.*?)</prefix>!im'          , $xml, $prefix         , PREG_SET_ORDER);
	preg_match_all ('!<url>(.*?)</url>!im'                , $xml, $url            , PREG_SET_ORDER);
	preg_match_all ('!<text>(.*?)</text>!im'              , $xml, $text           , PREG_SET_ORDER);
	preg_match_all ('!<postfix>(.*?)</postfix>!im'        , $xml, $postfix        , PREG_SET_ORDER);
	
	preg_match_all ('!<rss_prefix>(.*?)</rss_prefix>!im'  , $xml, $rss_prefix     , PREG_SET_ORDER);
	preg_match_all ('!<rss_url>(.*?)</rss_url>!im'        , $xml, $rss_url        , PREG_SET_ORDER);
	preg_match_all ('!<rss_text>(.*?)</rss_text>!im'      , $xml, $rss_text       , PREG_SET_ORDER);
	preg_match_all ('!<rss_postfix>(.*?)</rss_postfix>!im', $xml, $rss_postfix    , PREG_SET_ORDER);
	
	preg_match_all ('!<language>(.*?)</language>!im'      , $xml, $plugin_language, PREG_SET_ORDER);
	preg_match_all ('!<version>(.*?)</version>!im'        , $xml, $plugin_version , PREG_SET_ORDER);
	preg_match_all ('!<pl_date>(.*?)</pl_date>!im'        , $xml, $plugin_pl_date , PREG_SET_ORDER);
	
	
	$textlink_data   = array();
	$number_of_links = count($url);
	for ($i = 0; $i < $number_of_links; $i++)
	{
		$textlink_data[] = array	(
									  'prefix'      => $prefix[$i][1]
									, 'url'         => $url[$i][1]
									, 'text'        => $text[$i][1]
									, 'postfix'     => $postfix[$i][1]
									
									, 'rss_prefix'  => $rss_prefix[$i][1]
									, 'rss_url'     => $rss_url[$i][1]
									, 'rss_text'    => $rss_text[$i][1]
									, 'rss_postfix' => $rss_postfix[$i][1]
									);
	} //for($i)
	
	
	$server_plugin     = array();
	$number_of_plugins = count($plugin_language);
	for ($i = 0; $i < $number_of_plugins; $i++)
	{
		if (LL_PLUGIN_LANGUAGE == $plugin_language[$i][1])
		{
			$server_plugin["language"] = $plugin_language[$i][1];
			$server_plugin["version"]  = $plugin_version[$i][1];
			$server_plugin["date"]     = $plugin_pl_date[$i][1];
		} //if
	} //for($i)
	
	
	update_option("linklift_plugin_server_language", $server_plugin["language"]);
	update_option("linklift_plugin_server_version" , $server_plugin["version"]);
	update_option("linklift_plugin_server_date"    , $server_plugin["date"]);
	
	
	return $textlink_data;
} //ll_retrieve_textlink_data_from_xml()

/**
 * This function is the actual "main"-method of the LinkLift-plugin.
 * The function
 *  - retrieves textlink-data to your adspace from the LinkLift-server and stores it in a local XML-file (for reuse) - calling ll_retrieve_xml_from_ll_server();
 *      or retrieves the textlink-data from that local XML-file in order to minimize outbound-traffic - calling ll_retrieve_xml_from_file_systems().
 *  - parses the downloaded or read textlink-data in XML-format into an utilisable array of textlinks - calling ll_retrieve_textlink_data_from_xml().
 *  - generates and outputs plain HTML-links using some CSS-styles in order to obtain the looks you chose on the LinkLift-website;
 *      intentionally, the generated code tries to be as ordinary as possible in order to integrate best with your own HTML-code.
 * 
 * No value is returned since the generated HTML-code is directly outputted to your website (except for delivering $return = TRUE).
 * The function is invoked either at the end of the plugin (using PHP-plugin) or at the position of your choice within your website or blog (using one of the CMS-/Blog-software-plugins).
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2006-09-18, 2006-12-03
 * @param $return a boolean value indicating whether the generated HTML-code should be returned ($return=TRUE), or written to standard-out (echo); default: FALSE.
 * @return the generated HTML-code containing your current textlinks, or void if $return == FALSE, then, HTML will be written to standard-out.
 */
function ll_textlink_code( $return = FALSE )
{
	
	$xml      = ll_get_option("linklift_data", "");
	$xml_time = ll_get_option("linklift_time", 0);
	if (   ($xml_time < time() - 3600)
		|| (strlen($xml) < 40)   )
	{
		$xml = ll_retrieve_xml_from_ll_server();
		
		update_option("linklift_data", $xml);
		update_option("linklift_time", time());
	} //if
	
	
	
	// parsing XML-data
	$textlink_data = ll_retrieve_textlink_data_from_xml($xml);
	
	if (! is_array($textlink_data) )
		return;
	
	
	
	// creating and outputting textlinks
	// generating HTML-links
	// ---------------------------------------------------------------------------v
	
	// the appearance of the generated HTML-links depends on
		// - the default values as chosen on LinkLift's own plug-in-generation-panel
		// - the parameters that have been chosen within the configuration page of your LinkLift-plugin (if possible)
	// --- CSS-parameters ----------------------------------------
	$number_of_links_per_row = ll_get_option( "linklift_links_per_row"       , 1);
	
	$styles_ul   = array();
	$styles_li   = array();
	$styles_a    = array();
	
	$styles_li[] = 'width:' . floor(100 / $number_of_links_per_row -1) . '%;';
	
	$styles_ul[] = "width:100%;";
	$styles_ul[] = "overflow:hidden;";
	$styles_ul[] = "border-spacing:0px;";
	$styles_ul[] = "border:0px none #FFFFFF;";
	$styles_ul[] = "list-style:none;";
	$styles_ul[] = "margin-right:0px;";
	$styles_ul[] = "margin-top:0px;";
	$styles_ul[] = "background-color:" . ll_get_option( "linklift_css_background_color", "") . ";";
	$styles_ul[] = "padding:0px;";
	$styles_ul[] = "margin-bottom:0px;";
	
	
	$styles_li[] = "clear:none;";
	$styles_li[] = "float:left;";
	$styles_li[] = "display:inline;";
	
	
	$styles_a[]  = "line-height:140%;";
	$styles_a[]  = "font-size:" . ll_get_option( "linklift_css_font_size"       , "12px") . ";";
	$styles_a[]  = "color:" . ll_get_option( "linklift_css_color"           , "") . ";";
	
	
	
	
	
	
	// --- style-attributes --------------------------------------
	if (function_exists("array_filter"))
	{
		$styles_ul = array_filter( $styles_ul, create_function('$style', 'return (strpos($style,":;") === FALSE);') );
		$styles_li = array_filter( $styles_li, create_function('$style', 'return (strpos($style,":;") === FALSE);') );
		$styles_a  = array_filter( $styles_a , create_function('$style', 'return (strpos($style,":;") === FALSE);') );
	} //if
	
	// --- style-attributes --------------------------------------
	$css_ul      = ' style="' . implode(' ', $styles_ul) . '"';
	$css_li      = ' style="' . implode(' ', $styles_li) . '"';
	$css_a       = ' style="' . implode(' ', $styles_a ) . '"';
	
	// the following condition will evaluate to TRUE
		// if you have chosen not to use CSS-styles within the generated HTML-links
	if (ll_get_option( "linklift_css_no_css"          , TRUE))
	{
		$css_ul = '';
		$css_a  = '';
		
		if ($number_of_links_per_row <= 1)
			$css_li = '';
	} //if-else
	
	
	
	// --- HTML-Tags ---------------------------------------------
	$tag_ul1     = '<ul' . $css_ul . '>';
	$tag_ul2     = '</ul>';
	$tag_li1     = '<li' . $css_li . '>';
	$tag_li2     = '</li>';
	
	// the following condition will evaluate to TRUE
		// if you have chosen not to use the HTML-tags <ul> and <li> within the generated HTML-links
	if (ll_get_option( "linklift_no_html_tags"        , FALSE))
	{
		$tag_ul1 = '';
		$tag_ul2 = '';
		$tag_li1 = '';
		$tag_li2 = '<br />';
	} //if-else
	
	
	
	// --- HTML --------------------------------------------------
	$output =	  "\r\n"
				. $tag_ul1
				. "\r\n";
	
	foreach ($textlink_data as $link)
	{
		$output .="\t"
				. $tag_li1
				. 	$link["prefix"]
				. 	'<a' . $css_a . ' href="'.$link["url"].'" target="_self">'
				. 		$link["text"]
				. 	'</a>'
				. 	$link["postfix"]
				. $tag_li2
				. "\r\n";
	} //foreach($link)
	
	$output 	.=$tag_ul2
				. "\r\n";
	
	
	if ($return)
		return $output;
	else
		echo $output;
	
	// ---------------------------------------------------------------------------^
	
} //ll_textlink_code()





/**
 * The function adds another action on thw Wordpress "admin_menu"-signal.
 * 
 * The function gets invoked as an action on the Wordpress "init"-signal.
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2007-05-04
 * @return void
 */
function linklift_init()
{
	// adding a new submenu-page to the admin's menu
	add_action("admin_menu", "linklift_config_page");
} //linklift_init()

/**
 * Adds a new submenu-page to the Wordpress-installation.
 * The new submenu-page contains the LinkLift's plug-in-configuration
 *   created by the function linklift_configuration().
 * 
 * The function gets invoked as an action on the Wordpress "admin_menu"-signal.
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2007-05-04
 * @return void
 */
function linklift_config_page()
{
	if ( function_exists('add_submenu_page') )
	{
		add_submenu_page(	  $parent       = LL_WORDPRESS_FILE_PLUGINS
							, $page_title   = ll_translate('LINKLIFT_CONFIG_TAB_TITLE')
							, $menu_title   = ll_translate('LINKLIFT_CONFIG_TAB_TITLE')
							, $access_level = 'manage_options'
							, $file         = LL_PLUGIN_MENU_FILENAME
							, $function     = 'linklift_configuration'
						);
	} //if
} //linklift_config_page()

/**
 * Returns the localised text (or value) of a given text-key.
 * If the (Wordpress/CMS-) software's preset language is available to the plug-in
 *   the returned translation will be language-specific, otherwise english.
 * 
 * The function also replaces type_specifiers (like knwon from sprintf) within the localised text.
 *   Thus, you can fill the localised texts with dynamic (language-independent) values.
 * The replacements have to be delivered as String-array.
 *   If the localised text does not contain enough type-specifiers for all given replacements the remaining will be omitted.
 * 
 * @author akniep (Andreas Rayo Kniep)
 * @since 2007-05-02, 2007-06-10
 * @param $key_text string, the text to be translated
 * @param $replacements array of string-replacements, replacing type_specifiers in the localised text; default: empty array
 * @param $type_specifier string, type-specifier-placeholder; default: %s
 * @return string, translated text of input-parameter
 */
function ll_translate( $key_text, $replacements = array(), $type_specifier = "%s" )
{
	$localised_test = $key_text;
	
	
	if (defined($key_text))
	{
		$defined_constants = get_defined_constants();
		$localised_test = $defined_constants[$key_text];
	} //if
	
	
	// the given $replacements replace string-type-specifiers %s in the localised text.
	foreach ($replacements as $replacement)
	{
		if (($pos = strpos($localised_test, $type_specifier)) !== FALSE)
		{
			$localised_test =	  substr($localised_test, 0, $pos)
								. $replacement
								. substr($localised_test, $pos + strlen($type_specifier))
								. "";
		
		// if there are no more string-type-specifiers, the loop is left
		} else {
			break;
		} //if-else
	} //foreach($replacement)
	
	
    return $localised_test;
} //ll_translate()

/**
 * Returns the value to a given key of the Wordpress-option-table (wp_options).
 * Other than Wordpress' own function get_option()
 *   this function will return a default_value rather than FALSE if the given key is undefined in the Wordpress-options-table (wp_options).
 * The default value can be delivered as second parameter.
 * 
 * @author akniep (Andreas Rayo Kniep)
 * @since 2007-06-10
 * @param $options_table_key string, the key of the value to be retrieved from the Wordpress-options-table (wp_options)
 * @param $default_value string, the default value that should be returned if the given key is undefined in the Wordpress-options-table (wp_options), default: "" (empty string)
 * @return string, the value to the given key retrieved from the Wordpress-options-table (wp_options), or $default_value if the given key is undefined
 */
function ll_get_option( $options_table_key, $default_value = "" )
{
	$options_table_value = get_option($options_table_key);
	
	// if a given key does not exist in the Wordpress-options-table
		// get_option returns FALSE
	if (FALSE === $options_table_value)
		return $default_value;
	else
		return $options_table_value;
} //ll_get_option()

/**
 * Saves new values of LinkLift's configuration-page to the wordress-database, delivered by POST-request.
 * 
 * The function gets invoked by the functions linklift_configuration() and widget_linklift_control().
 *
 * @author akniep (Andreas Rayo Kniep)
 * @since 2007-05-04
 * @param $force_saving boolean, an optional parameter, deliver TRUE if you do not want the function to check wether a Wordpress-form has sent the information; default: FALSE.
 * @return void
 */
function ll_update_plugin( $force_saving = FALSE )
{
	if (   (isset($_POST['submit']) )
		|| ($force_saving)   )
	{
		// resetting the time of the last data-download
			// the linklift_website_key may have been changed ...
		// it's also a way to force an update of the website's textlink-data
		update_option("linklift_time", 0);
		
		
		// possible values of the LinkLift-plug-in's configuration page
		$options_array = array(
								  "linklift_website_key"
								, "linklift_title"
								, "linklift_css_no_css"
								, "linklift_no_html_tags"
								, "linklift_links_per_row"
								, "linklift_css_font_size"
								, "linklift_css_color"
								, "linklift_css_background_color"
								);
		
		
		foreach( $options_array as $option )
		{
			// checkbox-values may not be delivered if the checkbox was left empty ...
				// in order to distinguish between forms that did not contain the checkbox and forms where the checkbox was left empty
				// another hidden field gives us the hint that the field was part of the form and was left empty (on purpose)
			if (   (in_array($option, array("linklift_css_no_css", "linklift_no_html_tags"), $strict = TRUE))
				&& (isset($_POST[$option . "_modified"]))
				&& (! isset($_POST[$option]))   )
			{
				$_POST[$option] = 0;
			} //if
			
			if (isset($_POST[$option]))
			{
				update_option( $option, $_POST[$option] );
			} //if
		} //foreach($option)
		
	} //if
} //ll_update_plugin()

/**
 * Creates the HTML-code for LinkLift's configuration-page within the Wordpress-admin-menu.
 * After the user makes changes to the configuration the values will be saved to the Wordpress-database.
 * 
 * @author akniep (Andreas Rayo Kniep)
 * @since 2007-05-04
 * @return void
 */
function linklift_configuration()
{
	ll_update_plugin();
	
	
	$fieldset_style        = " BORDER:1px solid #CCC; PADDING:12px";
	$field_key_style       = " MARGIN-BOTTOM:5px";
	$field_key_style_tiny  = " MARGIN-BOTTOM:0px";
	$field_value_style     = " MARGIN-TOP:5px";
	
	$field_text_style      = " FONT-FAMILY:'Courier New', Courier, mono; FONT-SIZE:1.5em;";
	$field_text_style_tiny = " FONT-FAMILY:'Courier New', Courier, mono; FONT-SIZE:1.2em;";
	
	$css_top_padding       = " PADDING-TOP:30px; MARGIN-TOP:30px";
	
	$field_text_maxlength  = "15";
	$field_text_size       = "15";
	
	
	// used at least twice:
	$register_link_to_linklift = '<a href="' . LL_PLUGIN_REGISTER_LINK_URL . '" target="_blank" rel="nofollow">';
?>
	
	<?php if (! empty($_POST) )  :  ?>
		<div id="message" class="updated fade">
			<p>
				<strong>
					<?php _e("Options saved."); ?>
				</strong>
			</p>
		</div>
	<?php endif; ?>
	
	
	
	<div class="wrap">
		<h2>
			<?php echo ll_translate('LINKLIFT_CONFIG_TITLE'); ?>
		</h2>
		<div>
			<p>
				<?php
					echo ll_translate('LINKLIFT_PLUGIN_DESCRIPTION_1', array($register_link_to_linklift, '</a>') );
				?>
			</p>
			
			<p>
				<span style="FONT-WEIGHT:bold;">
					<?php echo ll_translate('LINKLIFT_PLUGIN_DESCRIPTION_2'); ?>
				</span>
				<br />
				
				<?php echo ll_translate('LINKLIFT_PLUGIN_DESCRIPTION_3'); ?>
			</p>
			
			<p>
				<?php
					if (LL_WORDPRESS_WIDGETS_INSTALLED)
						$link_url_to_widgets = LL_WORDPRESS_FILE_WIDGETS;
					else
						$link_url_to_widgets = "http://automattic.com/code/widgets/";
					
					
					
					$link_to_widgets      =	  '<a href="' . $link_url_to_widgets . '" target="_self">'
											.   'Widgets'
											. '</a>'
											. '';
											
					$linklift_widget_name =	  '<span style="FONT-WEIGHT:bold;">'
											.   '&quot;'
											.   LL_PLUGIN_NAME
											.   '&quot;'
											. '</span>'
											. '';
				?>
				
				<span style="FONT-WEIGHT:bold;">
					<?php echo ll_translate('LINKLIFT_INSTALLATION_INSTRUCTIONS_1'); ?>
				</span>
				
			</p>
			
			
			<ol>
				<li>
					<?php echo ll_translate('LINKLIFT_INSTALLATION_INSTRUCTIONS_2', array($link_to_widgets, $linklift_widget_name) ); ?>
					<br />
					<br />
				</li>
				
				<li>
					<?php
						$link_to_theme_editor =	  '<a href="' . LL_WORDPRESS_FILE_THEME_EDITOR . '" target="_self">'
												.   'Themes/Theme-Editor'
												. '</a>'
												. '';
						$code_snippet_to_paste = '&lt;?php if (function_exists(&quot;ll_textlink_code&quot;)) ll_textlink_code(); ?&gt;';
					?>
					
					
					<?php echo ll_translate('LINKLIFT_INSTALLATION_INSTRUCTIONS_3', array($link_to_theme_editor) ); ?>
					<br />
					<br />
					
					<span style="COLOR:#FF0000; FONT-WEIGHT:bold;">
						<?php echo $code_snippet_to_paste; ?>
					</span>
					<br />
					<br />
					
					<?php echo ll_translate('LINKLIFT_INSTALLATION_INSTRUCTIONS_4'); ?>
				</li>
			</ol>
			
			
			<p>
				<?php echo ll_translate('LINKLIFT_INSTALLATION_INSTRUCTIONS_5'); ?>
				<br />
			</p>
			
			
			
			
			<form action="" method="post" id="linklift-conf" style="MARGIN-TOP:30Px;">
				
				<fieldset style="<?php echo $fieldset_style; ?>">
					<legend>
						<b>
							<?php echo ll_translate('LINKLIFT_CONFIG_HEADLINE_GENERAL'); ?>
						</b>
					</legend>
					
					
					<h3 style="<?php echo $field_key_style; ?>">
						<label for="key">
							<?php echo ll_translate('LINKLIFT_CONFIG_TITLE_WEBSITE_KEY'); ?>
						</label>
					</h3>
					
					<p style="<?php echo $field_value_style; ?>">
						<input id="linklift_website_key" name="linklift_website_key" type="text" size="15" maxlength="15" value="<?php $linklift_website_key = ll_get_option("linklift_website_key", "");
		if (empty($linklift_website_key))
			$linklift_website_key = ll_translate( "LINKLIFT_WEBSITE_KEY" );
		  echo $linklift_website_key; ?>" style="<?php echo $field_text_style; ?>" />
						
						<?php
							$linklift_url_linklift_website_key = "http://www.linklift.de/faq/linklift-website-key/";
						?>
						(<a href="<?php echo $linklift_url_linklift_website_key; ?>" target="_blank" rel="nofollow">
							<?php echo ll_translate('LINKLIFT_WEBSITE_KEY_EXPLANATION_LINK'); ?>
						</a>)
						
						<div class="description">
							<?php echo ll_translate('LINKLIFT_CONFIG_DESCRIPTION_WEBSITE_KEY'); ?>
							<?php echo ll_translate('LINKLIFT_CONFIG_DESCRIPTION_WEBSITE_KEY_2', array($register_link_to_linklift, '</a>') ); ?>
						</div>
					</p>
					
					
					<h3 style="<?php echo $field_key_style; ?>">
						<label for="key">
							<?php echo ll_translate('LINKLIFT_CONFIG_TITLE_PLUGIN_HEADLINE'); ?>
						</label>
					</h3>
					
					<p style="<?php echo $field_value_style; ?>">
						<input id="linklift_title" name="linklift_title" type="text" size="30" value="<?php echo ll_get_option("linklift_title", Empfehlungen); ?>" style="<?php echo $field_text_style; ?>" />
						
						<?php
							$linklift_url_link_marking			= "http://www.linklift.de/faq/link-marking/";
							$link_to_linklift_faq_link_marking	= '<a href="' . $linklift_url_link_marking . '" target="_blank" rel="nofollow">';
						?>
						<div class="description">
							<?php echo ll_translate('LINKLIFT_CONFIG_DESCRIPTION_PLUGIN_HEADLINE'); ?>
							<?php echo ll_translate('LINKLIFT_CONFIG_DESCRIPTION_PLUGIN_HEADLINE_2', array($link_to_linklift_faq_link_marking, '</a>') ); ?>
						</div>
					</p>
				</fieldset>
				
				
				
				
				
				<fieldset style="<?php echo $fieldset_style; ?> <?php echo $css_top_padding; ?>">
					<legend>
						<b>
							<?php echo ll_translate('LINKLIFT_CONFIG_HEADLINE_OPTIONAL'); ?>
						</b>
					</legend>
					
					<p>
						<?php
							echo ll_translate('LINKLIFT_CONFIG_TEXT_OPTIONAL_VALUES');
						?>
					</p>
					
					
					<?php
						$form = array();
							
						$form["linklift_css_no_css"]
							= array(
									  "#type"          => "checkbox"
									, "#default_value" => ll_get_option( "linklift_css_no_css"          , TRUE)
									, "#title"         => ll_translate('LINKLIFT_CONFIG_TITLE_NO_CSS')
									, "#description"   => ll_translate('LINKLIFT_CONFIG_DESCRIPTION_NO_CSS')
									);
						
						$form["linklift_no_html_tags"]
							= array(
									  "#type"          => "checkbox"
									, "#default_value" => ll_get_option( "linklift_no_html_tags"        , FALSE)
									, "#title"         => ll_translate('LINKLIFT_CONFIG_TITLE_NO_HTML')
									, "#description"   => ll_translate('LINKLIFT_CONFIG_DESCRIPTION_NO_HTML')
									);
						
						$form["linklift_links_per_row"]
							= array(
									  "#type"          => "select"
									, "#options"       => array (1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 10 => 10)
									, "#default_value" => ll_get_option( "linklift_links_per_row"       , 1)
									, "#title"         => ll_translate('LINKLIFT_CONFIG_TITLE_LINKS_PER_ROW')
									, "#description"   => ll_translate('LINKLIFT_CONFIG_DESCRIPTION_LINKS_PER_ROW')
									);
						
						
						$font_sizes = array();
						for ($i = 10; $i <= 18; $i++)
							$font_sizes[$i . "px"] = $i . "px";
						
						$form["linklift_css_font_size"]
							= array(
									  "#type"          => "select"
									, "#options"       => $font_sizes
									, "#default_value" => ll_get_option( "linklift_css_font_size"       , "12px")
									, "#title"         => ll_translate('LINKLIFT_CONFIG_TITLE_FONT_SIZE')
									, "#description"   => ll_translate('LINKLIFT_CONFIG_DESCRIPTION_FONT_SIZE')
									);
						
						$form["linklift_css_color"]
							= array(
									  "#type"          => "textfield"
									, "#size"          => 20
									, "#maxlength"     => 20
									, "#default_value" => ll_get_option( "linklift_css_color"           , "")
									, "#title"         => ll_translate('LINKLIFT_CONFIG_TITLE_LINK_COLOR')
									, "#description"   => ll_translate('LINKLIFT_CONFIG_DESCRIPTION_LINK_COLOR')
									);
						
						$form["linklift_css_background_color"]
							= array(
									  "#type"          => "textfield"
									, "#size"          => 20
									, "#maxlength"     => 20
									, "#default_value" => ll_get_option( "linklift_css_background_color", "")
									, "#title"         => ll_translate('LINKLIFT_CONFIG_TITLE_BG_COLOR')
									, "#description"   => ll_translate('LINKLIFT_CONFIG_DESCRIPTION_BG_COLOR')
									);
						
						
						foreach ($form as $name => $element)
						{
							?>
							<h5 style="<?php echo $field_key_style_tiny; ?>">
								<label for="key">
									<?php echo $element["#title"]; ?>
								</label>
							</h5>

							<p style="<?php echo $field_value_style; ?>">
						<?php
							
							switch ($element["#type"])
							{
								case ("textfield"):
								{
									?>
									<input type="text" name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="<?php echo ll_get_option($name, $element["#default_value"]); ?>" size="<?php echo ((isset($element["#size"]))?($element["#size"]):($field_text_size)); ?>" maxlength="<?php echo ((isset($element["#maxlength"]))?($element["#size"]):($field_text_maxlength)); ?>" style="<?php echo $field_text_style_tiny; ?>" />
								<?php
									
									break;
								} //case()
								
								case ("select"):
								{
									?>
									<select name="<?php echo $name; ?>" id="<?php echo $name; ?>">
									<?php	foreach ($element["#options"] as $key => $value) :  ?>
										<option value="<?php echo $key; ?>" <?php echo (($key == ll_get_option($name, $element["#default_value"]) )?('selected="selected"'):('')); ?>>
											<?php echo $value; ?>
										</option>
									<?php	endforeach;  ?>
									</select>
								<?php
									
									break;
								} //case()
								
								case ("checkbox"):
								{
									?>
									<input type="checkbox" name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="1" <?php echo ((ll_get_option($name, $element["#default_value"]) )?('checked="checked" '):('')); ?>/>
									<input type="hidden" name="<?php echo $name; ?>_modified" id="<?php echo $name; ?>_modified" value="1"/>
								<?php
									
									break;
								} //case()
								
							} //switch($element["#type"])
							
							?>
								<div class="description">
									<?php echo $element["#description"]; ?>
								</div>
							</p>
						<?php
							
						} //foreach($element)
						
					?>
					
					
					<br />
				</fieldset>
				
				
				
				<p class="submit" style="text-align:left;">
					<input type="submit" name="submit" value="<?php _e('Update options &raquo;'); ?>" />
				</p>
				
			</form>
			
			
			<p style="<?php echo $css_top_padding; ?>">
				LinkLift Plugin 
					<?php
						echo '(', LL_PLUGIN_LANGUAGE, ')';
					?>,
				Version
					<?php
						echo LL_PLUGIN_VERSION;
					?>
					<?php
						echo '(', LL_PLUGIN_DATE, ')';
					?>.
				<br />
				
				<?php
					// do you (still) own the latest version?
					$server_plugin_version = ll_get_option( "linklift_plugin_server_version", 0);
					
					if ($server_plugin_version > LL_PLUGIN_VERSION)
						echo ll_translate('LINKLIFT_PLUGIN_OUT_OF_DATE');
					elseif ($server_plugin_version == LL_PLUGIN_VERSION)
						echo ll_translate('LINKLIFT_PLUGIN_UP_TO_DATE');
				?>
			</p>
		</div>
	</div>
	
<?php
	
} //linklift_configuration()



/**
 * The widget-controller (Wordpress-Widget-Plugin) calls this function to generate the plugin's output.
 * The function extracts the plugin's title out of the Wordpress-database (options-table)
 *   and calls the plugin's main-function in order to generate your textlinks and the widget's body around.
 * 
 * The function is invoked by the widget-controller.
 *
 * @author tomk32 (Thomas R. Koll), akniep (Andreas Rayo Kniep)
 * @since 2007-03-06
 * @param $args array, an associative array delivered by the Wordpress Plugin 'Wordpress Widgets'
 * @return void, the widget's body including your textlinks is written to standard-out
 */
function clickdav( $args )
{
	// extracts out of the given array of parameters the variables that are used below
	extract($args);
	
	$linklift_title = ll_get_option("linklift_title", "Empfehlungen");
	
	
	echo	  $before_widget
			, "\n"
			, $before_title
			, $linklift_title
			, $after_title
			
			, ll_textlink_code( TRUE )
			
			, $after_widget;
} //clickdav()

/**
 * The function generates an interface for editing the plugin's attributes / perameters.
 * At this time you can only manipulate the widget's title.
 * 
 * The function is invoked by the widget-controller.
 *
 * @author tomk32 (Thomas R. Koll), akniep (Andreas Rayo Kniep)
 * @since 2007-03-06
 * @return void, the interface is directly outputted to your website
 */
function widget_linklift_control()
{
	ll_update_plugin($force_saving = TRUE);
	
	
	$field_key_style_tiny  = " MARGIN-BOTTOM:0px";
	$field_value_style     = " MARGIN-TOP:5px";
	$field_text_style_tiny = " FONT-FAMILY:'Courier New', Courier, mono; FONT-SIZE:1.2em;";
	$field_text_maxlength  = "15";
	$field_text_size       = "15";
	
?>
	<?php
		$linklift_configuration_page_filename = LL_WORDPRESS_FILE_PLUGINS . "?page=" . LL_PLUGIN_MENU_FILENAME;
		
		if (file_exists(LL_WORDPRESS_FILE_PLUGINS))  :
		
		$link_to_configuration =	  '<a href="' . $linklift_configuration_page_filename . '" target="_self">'
									.   'LinkLift'
									. '</a>'
									. '';
		$linklift_widget_name =	  '<span style="FONT-WEIGHT:bold;">'
								.   LL_PLUGIN_NAME
								. '</span>'
								. '';
	?>
		<p>
			<?php echo ll_translate('LINKLIFT_WIDGETS_CONFIG_REMARK', array($link_to_configuration) ); ?>
			<br />
			<br />
		</p>
	<?php
		endif;
	?>
	
	<h5 style="<?php echo $field_key_style_tiny; ?>">
		<label for="key">
			<?php echo ll_translate('LINKLIFT_CONFIG_TITLE_PLUGIN_HEADLINE'); ?>
		</label>
	</h5>

	<p style="<?php echo $field_value_style; ?>">
		<input id="linklift_title" name="linklift_title" type="text" value="<?php echo ll_get_option("linklift_title", Empfehlungen); ?>"  size="<?php echo ((isset($element["#size"]))?($element["#size"]):($field_text_size)); ?>" maxlength="<?php echo ((isset($element["#maxlength"]))?($element["#size"]):($field_text_maxlength)); ?>" style="<?php echo $field_text_style_tiny; ?>" />
		
		<div class="description">
			<?php echo ll_translate('LINKLIFT_CONFIG_DESCRIPTION_PLUGIN_HEADLINE'); ?>
		</div>
	</p>
<?php
	
} //widget_linklift_control()

/**
 * The function registers the LinkLift-plugin (-widget) with your widget-controller.
 * The widget controller is realised by the "Wordpress Widget-Plugin".
 * 
 * The function is invoked by the widget-controller, the action is added at the end of this plugin.
 *
 * @author tomk32 (Thomas R. Koll), akniep (Andreas Rayo Kniep)
 * @since 2007-03-06
 * @return void
 */
function widget_linklift_init()
{
	if (   (! function_exists( "register_sidebar_widget" ))
		|| (! function_exists( "register_widget_control" ))    )
		return;
	
	register_sidebar_widget( LL_PLUGIN_NAME, "clickdav" );
	register_widget_control( LL_PLUGIN_NAME, "widget_linklift_control" );
} //widget_linklift_init()



// registering the LinkLift-plugin with the Wordpress-admin-menu
add_action( 'init'        , 'linklift_init' );
// registering the LinkLift-widget with the widget-controller ("Wordpress Widget-Plugin")
add_action( 'widgets_init', 'widget_linklift_init' );

?>
