<?php

// Reminder: always indent with 4 spaces (no tabs).
// +---------------------------------------------------------------------------+
// | Links Plugin 2.0                                                          |
// +---------------------------------------------------------------------------+
// | functions.inc                                                             |
// |                                                                           |
// | This file does two things: 1) it implements the necessary Geeklog Plugin  |
// | API method and 2) implements all the common code needed by the Links      |
// | Plugins' PHP files.                                                       |
// +---------------------------------------------------------------------------+
// | Copyright (C) 2000-2008 by the following authors:                         |
// |                                                                           |
// | Authors: Tony Bibbs         - tony AT tonybibbs DOT com                   |
// |          Mark Limburg       - mlimburg AT users.sourceforge DOT net       |
// |          Jason Whittenburg  - jwhitten AT securitygeeks DOT com           |
// |          Dirk Haun          - dirk AT haun-online DOT de                  |
// |          Trinity Bays       - trinity93 AT gmail DOT com                  |
// |          Oliver Spiesshofer - oliver AT spiesshofer DOT com               |
// |          Euan McKay         - info AT heatherengineering DOT com          |
// +---------------------------------------------------------------------------+
// |                                                                           |
// | This program is licensed under the terms of the GNU General Public License|
// | as published by the Free Software Foundation; either version 2            |
// | of the License, or (at your option) any later version.                    |
// |                                                                           |
// | This program is distributed in the hope that it will be useful,           |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of            |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                      |
// | See the GNU General Public License for more details.                      |
// |                                                                           |
// | You should have received a copy of the GNU General Public License         |
// | along with this program; if not, write to the Free Software Foundation,   |
// | Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           |
// |                                                                           |
// +---------------------------------------------------------------------------+
//
// $Id: functions.inc,v 1.111 2008/09/21 08:37:08 dhaun Exp $

if (strpos(strtolower($_SERVER['PHP_SELF']), 'functions.inc') !== false) {
    die('This file can not be used on its own.');
}

$plugin_path = $_CONF['path'] . 'plugins/links/';
$langfile = $plugin_path . 'language/' . $_CONF['language'] . '.php';

if (file_exists($langfile)) {
    require_once $langfile;
} else {
    require_once $plugin_path . 'language/english.php';
}

/*
* Check and see if we need to load the plugin configuration
*/
if (!isset($_LI_CONF['linksloginrequired'])) {
    require_once $_CONF['path_system'] . 'classes/config.class.php';

    $li_config = config::get_instance();
    $_LI_CONF = $li_config->get_config('links');
}

$_LI_CONF['version'] = '2.0.0';

// +---------------------------------------------------------------------------+
// | Geeklog Plugin API Implementation                                         |
// +---------------------------------------------------------------------------+

/**
* Returns the items for this plugin that should appear on the main menu
*
* NOTE: this MUST return the url/value pairs in the following format
* $<arrayname>[<label>] = <url>
*
* @return   mixed   menu entry, or boolean false if disabled / hidden
*
*/
function plugin_getmenuitems_links()
{
    global $_CONF, $_USER, $_LI_CONF, $LANG_LINKS;

    $anon = (empty ($_USER['uid']) || ($_USER['uid'] <= 1)) ? true : false;
    if (($_LI_CONF['hidelinksmenu'] == 1) || ($anon &&
                ($_CONF['loginrequired'] || $_LI_CONF['linksloginrequired']))) {
        return false;
    }

    $menuitems[$LANG_LINKS[114]] = $_CONF['site_url'] . '/links/index.php';

    return $menuitems;
}

/**
* Return headlines for New Links section in the What's New block, if enabled
*
* @return   mixed       array(headline, byline), or boolean false is disabled
*
*/
function plugin_whatsnewsupported_links()
{
    global $_TABLES, $_LI_CONF, $LANG_LINKS, $LANG_WHATSNEW;

    if ( $_LI_CONF['hidenewlinks'] == 0 ) {
        $retval = array( $LANG_LINKS[84],
                         COM_formatTimeString( $LANG_WHATSNEW['new_last'],
                                               $_LI_CONF['newlinksinterval'] )
                       );
    } else {
        $retval = false;
    }

    return $retval;
}

/**
* Return new links for the What's New block
*
* @return   string  HTML list of new links
*
*/
function plugin_getwhatsnew_links()
{
    global $_CONF, $_TABLES, $_USER, $_LI_CONF, $LANG_LINKS;

    $retval = '';

    // Get newest links
    $sql = "SELECT lid,title FROM {$_TABLES['links']} WHERE (date >= (DATE_SUB(NOW(), INTERVAL {$_LI_CONF['newlinksinterval']} SECOND)))" . COM_getPermSQL( 'AND' ) . ' ORDER BY date DESC LIMIT 15';
    $result = DB_query($sql);
    $nrows = DB_numRows($result);

    if ($nrows > 0) {
        $newlinks = array();
        for ($x = 0; $x < $nrows; $x++) {
            $A = DB_fetchArray($result);
            $A['title'] = stripslashes($A['title']);

            // redirect link via portal.php so we can count the clicks
            $lcount = COM_buildUrl($_CONF['site_url']
                    . '/links/portal.php?what=link&amp;item=' . $A['lid']);

            $title = COM_truncate($A['title'], $_CONF['title_trim_length'],
                                  '...');
            $link_title = array();
            if ($title != $A['title']) {
                $link_title = array('title' => $A['title']);
            }

            $newlinks[] = COM_createLink($title, $lcount, $link_title) . LB;
        }

        $retval .= COM_makeList($newlinks, 'list-new-plugins');
    } else {
        $retval .= $LANG_LINKS[88] . '<br' . XHTML . '>' . LB;
    }

    return $retval;
}

/**
* Implements the [link:] autotag.
*
* @param    string  $op         operation to perform
* @param    string  $content    item (e.g. story text), including the autotag
* @param    array   $autotag    parameters used in the autotag
* @param    mixed               tag names (for $op='tagname') or formatted content
*
*/
function plugin_autotags_links($op, $content = '', $autotag = '')
{
    global $_CONF, $_TABLES, $LANG_DIRECTION;

    if ($op == 'tagname' ) {
        return 'link';
    } else if ($op == 'parse') {
        $lid = COM_applyFilter($autotag['parm1']);
        $url = COM_buildUrl($_CONF['site_url']
                            . '/links/portal.php?what=link&amp;item=' . $lid);
        if (empty($autotag['parm2'])) {
            $result = DB_query("SELECT url, title FROM {$_TABLES['links']} WHERE lid = '$lid'");
            list($siteurl, $linktext) = DB_fetchArray($result);
        } else {
            $linktext = $autotag['parm2'];
            $siteurl = DB_getItem($_TABLES['links'], 'url', "lid = '$lid'");
        }
        $class = 'ext-link';
        if ((!empty($LANG_DIRECTION)) && ($LANG_DIRECTION == 'rtl')) {
            $class .= '-rtl';
        }
        $attr = array(
                    'title' => $siteurl,
                    'class' => $class
                     );
        $link = COM_createLink($linktext, $url, $attr);
        $content = str_replace($autotag['tagstr'], $link, $content);

        return $content;
    }
}

/**
* Called by the plugin Editor to display the current plugin code version
* This may be different than the version installed and registered currently.
* If newer then you may want to run the update
*
* @return   string  version number
*
*/
function plugin_chkVersion_links ()
{
    global $_LI_CONF;

    return $_LI_CONF['version'];
}

/**
* Helper function: count number of links and total number of clicks
*
* @return   array(number of links, number of clicks);
*
*/
function LINKS_countLinksAndClicks ()
{
    global $_TABLES;

    $result = DB_query ("SELECT COUNT(*) AS count,SUM(hits) AS clicks FROM {$_TABLES['links']}" . COM_getPermSQL ());
    $A = DB_fetchArray ($result);
    $total_links = $A['count'];
    $total_clicks = $A['clicks'];
    if (empty ($total_clicks)) {
        $total_clicks = 0;
    }

    return array ($total_links, $total_clicks);
}

/**
* Shows the statistics for the links plugin on stats.php.
* If $showsitestats is 1 then we are to only print the overall stats in the
* 'site statistics box' otherwise we show the detailed stats
*
* @param    int     $showsitestate  Flag to let us know which stats to get
* @param    string                  HTML for the stats section
*
*/
function plugin_showstats_links ($showsitestats)
{
    global $_CONF, $_TABLES, $LANG_LINKS_STATS;

    require_once ($_CONF['path_system'] . 'lib-admin.php');

    $retval = '';

    $result = DB_query ("SELECT lid,url,title,hits FROM {$_TABLES['links']} WHERE (hits > 0)" . COM_getPermSQL ('AND') . " ORDER BY hits DESC LIMIT 10");
    $nrows  = DB_numRows ($result);
    if ($nrows > 0) {
        $header_arr = array(
            array('text'         => $LANG_LINKS_STATS['stats_page_title'],
                  'field'        => 'sid',
                  'header_class' => 'stats-header-title'
            ),
            array('text'         => $LANG_LINKS_STATS['stats_hits'],
                  'field'        => 'hits',
                  'header_class' => 'stats-header-count',
                  'field_class'  => 'stats-list-count'
            )
        );
        $data_arr = array();
        $text_arr = array('has_menu' => false,
                          'title'    => $LANG_LINKS_STATS['stats_headline'],
        );
        for ($i = 0; $i < $nrows; $i++) {
            $A = DB_fetchArray ($result);
            $title = stripslashes (str_replace ('$', '&#36;', $A['title']));
            $url = COM_buildUrl ($_CONF['site_url']
                        . '/links/portal.php?what=link&amp;item=' . $A['lid']);
            $sid = COM_createLink($title, $url, array('title' => $A['url']));
            $hits = COM_numberFormat ($A['hits']);
            $data_arr[] = array('title' => $title,
                                'sid' => $sid,
                                'hits' => $hits
                          );
        }
        $retval .= ADMIN_simpleList ('', $header_arr, $text_arr, $data_arr);
    } else {
        $retval .= COM_startBlock ($LANG_LINKS_STATS['stats_headline']);
        $retval .= $LANG_LINKS_STATS['stats_no_hits'];
        $retval .= COM_endBlock ();
    }

    return $retval;
}

/**
* New stats plugin API function for proper integration with the site stats
*
* @return   array(item text, item count);
*
*/
function plugin_statssummary_links ()
{
    global $LANG_LINKS_STATS;

    list($total_links, $total_clicks) = LINKS_countLinksAndClicks ();

    $item_count = COM_NumberFormat ($total_links)
                . ' (' . COM_NumberFormat ($total_clicks) . ')';


    return array ($LANG_LINKS_STATS['links'], $item_count);
}

/**
* Geeklog is asking us to provide any items that show up in the type
* drop-down on search.php.  Let's users search for links.
*
* @return   array   (plugin name/entry title) pair for the dropdown
*
*/
function plugin_searchtypes_links()
{
    global $LANG_LINKS;

    $tmp['links'] = $LANG_LINKS[14];

    return $tmp;
}


/**
* This searches for links matching the user query and returns an array for the
* header and table rows back to search.php where it will be formated and printed
*
* @param    string  $query      Keywords user is looking for
* @param    date    $datestart  Start date to get results for
* @param    date    $dateend    End date to get results for
* @param    string  $topic      The topic they were searching in
* @param    string  $type       Type of items they are searching, or 'all'
* @param    int     $author     Get all results by this author
* @param    string  $keyType    search key type: 'all', 'phrase', 'any'
* @param    int     $page       page number of current search
* @param    int     $perpage    number of results per page
* @return   object              search result object
*
*/
function plugin_dopluginsearch_links($query, $datestart, $dateend, $topic, $type, $author, $keyType, $page, $perpage)
{
    global $_CONF, $_TABLES, $LANG_LINKS_SEARCH;

    if (empty ($type)) {
        $type = 'all';
    }

    // Bail if we aren't supppose to do our search
    if ($type <> 'all' AND $type <> 'links') {
        $plugin_results = new Plugin();
        $plugin_results->plugin_name = 'links';
        $plugin_results->searchlabel = $LANG_LINKS_SEARCH['results'];

        return $plugin_results;
    }

    // link search
    $select = 'SELECT lid,title,url,owner_id,hits,UNIX_TIMESTAMP(date) AS day';
    $sql = " FROM {$_TABLES['links']} WHERE date <> 1 ";

    if (!empty ($query)) {
        if ($keyType == 'phrase') {
            $mysearchterm = addslashes ($query);
            $sql .= " AND (description LIKE '%$mysearchterm%')"
                 . " OR (title LIKE '%$mysearchterm%')";
        } else if ($keyType == 'all') {
            $mywords = explode (' ', $query);
            $sql .= ' AND (';
            $tmp = '';
            foreach ($mywords AS $mysearchterm) {
                $mysearchterm = addslashes (trim ($mysearchterm));
                if (!empty ($mysearchterm)) {
                    $tmp .= "(description LIKE '%$mysearchterm%')"
                         . " OR (title LIKE '%$mysearchterm%') AND ";
                }
            }
            $tmp = substr ($tmp, 0, strlen ($tmp) - 5);
            $sql .= $tmp . ')';
        } else if ($keyType == 'any') {
            $mywords = explode (' ', $query);
            $sql .= ' AND (';
            $tmp = '';
            foreach ($mywords AS $mysearchterm) {
                $mysearchterm = addslashes (trim ($mysearchterm));
                if (!empty ($mysearchterm)) {
                    $tmp .= "(description LIKE '%$mysearchterm%')"
                         . " OR (title LIKE '%$mysearchterm%') OR ";
                }
            }
            $tmp = substr ($tmp, 0, strlen ($tmp) - 4);
            $sql .= $tmp . ')';
        } else {  // quick search
            $mysearchterm = addslashes ($query);
            $sql .= " AND (description LIKE '%$mysearchterm%')"
                 . " OR (title LIKE '%$mysearchterm%')";
        }
    }

    if (!empty ($datestart) && !empty ($dateend)) {
        $delim = substr ($datestart, 4, 1);
        if (!empty($delim)) {
            $DS = explode ($delim, $datestart);
            $DE = explode ($delim, $dateend);
            $startdate = mktime (0, 0, 0, $DS[1], $DS[2], $DS[0]);
            $enddate = mktime (23, 59, 59, $DE[1], $DE[2], $DE[0]);
            $sql .= " AND (UNIX_TIMESTAMP(date) BETWEEN '$startdate' AND '$enddate')";
        }
    }

    if (!empty ($author)) {
        $sql .= "AND (owner_id = '$author')";
    }
    $sql .= COM_getPermSQL ('AND');
    $sql .= ' GROUP BY date, lid, cid, url, description, title, hits, owner_id, group_id, perm_owner, perm_group, perm_members, perm_anon ORDER BY date DESC';
    $l = ($perpage * $page) - $perpage;
    $sql .= ' LIMIT ' . $l . ',' . $perpage;

    // Perform search
    $result = DB_query ($select . $sql);
    $mycount = DB_numRows ($result);
    $result_count = DB_query ('SELECT COUNT(*)' . $sql);
    $B = DB_fetchArray ($result_count, true);

    $plugin_results = new Plugin();
    $plugin_results->plugin_name = 'links';
    $plugin_results->searchlabel = $LANG_LINKS_SEARCH['results'];
    $plugin_results->addSearchHeading ($LANG_LINKS_SEARCH['title']);
    $plugin_results->addSearchHeading ($LANG_LINKS_SEARCH['date']);
    $plugin_results->addSearchHeading ($LANG_LINKS_SEARCH['author']);
    $plugin_results->addSearchHeading ($LANG_LINKS_SEARCH['hits']);
    $plugin_results->num_searchresults = 0;
    $plugin_results->num_itemssearched = $B[0];
    $plugin_results->supports_paging = true;

    // NOTE if any of your data items need to be links then add them here!
    // make sure data elements are in an array and in the same order as your
    // headings above!
    for ($i = 0; $i < $mycount; $i++) {
        $A = DB_fetchArray ($result);

        $thetime = COM_getUserDateTimeFormat ($A['day']);
        $A['title'] = stripslashes ($A['title']);
        $submitter = COM_getDisplayName ($A['owner_id']);
        if ($A['owner_id'] > 1) {
            $profile_url = $_CONF['site_url']
                     . '/users.php?mode=profile&amp;uid=' . $A['owner_id'];
            $profile = COM_createLink($submitter, $profile_url);
        } else {
            $profile = $submitter;
        }
        $linkUrl = COM_buildUrl($_CONF['site_url']
                                . '/links/portal.php?what=link&amp;item='
                                . $A['lid']);
        $anchor = COM_createLink($A['title'], $linkUrl,
                                 array('title' => $A['url']));
        $row = array ($anchor, $thetime[0], $profile,
                      COM_NumberFormat ($A['hits']));
        $plugin_results->addSearchResult ($row);
        $plugin_results->num_searchresults++;
    }

    return $plugin_results;
}


/**
* This will put an option for links in the command and control block on
* moderation.php
*
* @return   mixed   array(title, url, icon), or boolean false when not allowed
*
*/
function plugin_cclabel_links()
{
    global $_CONF, $LANG_LINKS;

    if (SEC_hasRights ('links.edit')) {
        return array ($LANG_LINKS[14],
                      $_CONF['site_admin_url'] . '/plugins/links/index.php',
                      plugin_geticon_links ());
    }

    return false;
}

/**
* returns the administrative option for this plugin
*
* @return   mixed   array(title, url, num. links), or void when not allowed
*
*/
function plugin_getadminoption_links()
{
    global $_CONF, $_TABLES, $LANG_LINKS;

    if (SEC_hasRights ('links.edit,links.delete', 'OR')) {
        $total_links = DB_getItem ($_TABLES['links'], 'COUNT(*)',
                                   COM_getPermSql (''));

        return array ($LANG_LINKS[14],
                      $_CONF['site_admin_url'] . '/plugins/links/index.php',
                      $total_links);
    }
}

/**
* A user is about to be deleted. Update ownership of any links owned
* by that user or delete them.
*
* @param    int     $uid    User id of deleted user
* @return   void
*
*/
function plugin_user_delete_links ($uid)
{
    global $_TABLES, $_LI_CONF;

    if (DB_count ($_TABLES['links'], 'owner_id', $uid) == 0) {
        return;
    }

    if ($_LI_CONF['delete_links'] == 1) {
        // delete the links
        DB_query ("DELETE FROM {$_TABLES['links']} WHERE owner_id = $uid");
    } else {
        // assign ownership to a user from the Root group
        $rootgroup = DB_getItem ($_TABLES['groups'], 'grp_id',
                                 "grp_name = 'Root'");
        $result = DB_query ("SELECT DISTINCT ug_uid FROM {$_TABLES['group_assignments']} WHERE ug_main_grp_id = $rootgroup ORDER BY ug_uid LIMIT 1");
        $A = DB_fetchArray ($result);
        $rootuser = $A['ug_uid'];
        DB_query ("UPDATE {$_TABLES['links']} SET owner_id = $rootuser WHERE owner_id = $uid");
    }
}

/**
* Do we support feeds?
*
* @return   array   id/name pairs of all supported feeds
*
*/
function plugin_getfeednames_links()
{
    global $_TABLES;

    $feeds = array ();

    $result = DB_query ("SELECT cid,category FROM {$_TABLES['linkcategories']} GROUP BY category ORDER BY category ASC");
    $num = DB_numRows ($result);

    if ($num > 0) {
        $feeds[] = array ('id' => 'all', 'name' => 'all categories');

        for ($i = 0; $i < $num; $i++) {
            $A = DB_fetchArray ($result);
            $feeds[] = array ('id' => $A['cid'], 'name' => $A['category']);
        }
    }

    return $feeds;
}

/**
* Provide feed data
*
* @param    int     $feed       feed ID
* @param    ref     $link
* @param    ref     $update
* @return   array               feed entries
*
*/
function plugin_getfeedcontent_links ($feed, &$link, &$update)
{
    global $_CONF, $_TABLES;

    $result = DB_query( "SELECT topic,limits,content_length FROM {$_TABLES['syndication']} WHERE fid = '$feed'" );
    $S = DB_fetchArray( $result );

    $result = DB_query( "SELECT lid,owner_id,title,description,UNIX_TIMESTAMP(date) AS modified FROM " . $_TABLES['links'] . links_buildSql ($S['topic'], $S['limits']) );

    $content = array();
    $lids = array();
    $nrows = DB_numRows( $result );

    for( $i = 0; $i < $nrows; $i++ )
    {
        $row = DB_fetchArray( $result );
        $lids[] = $row['lid'];

        $linktitle = stripslashes( $row['title'] );
        $linkdesc = stripslashes( $row['description'] );

        $linklink = COM_buildUrl( $_CONF['site_url']
                  . '/links/portal.php?what=link&amp;item=' . $row['lid'] );

        $content[] = array( 'title'   => $linktitle,
                            'summary' => $linkdesc,
                            'link'    => $linklink,
                            'uid'     => $row['owner_id'],
                            'author'  => COM_getDisplayName( $row['owner_id'] ),
                            'date'    => $row['modified'],
                            'format'  => 'plaintext'
                          );
    }

    $link = $_CONF['site_url'] . '/links/index.php';
    $update = implode( ',', $lids );

    return $content;
}

/**
* Helper function: Build part of an SQL request
*
* @param    string  $cid        category id
* @param    string  $limits     limit (number of entries or number of hours)
* @return   string              part of an SQL request
*
*/
function links_buildSql($cid, $limits)
{
    $where = '';
    if ($cid != 'all') {
        $where = "cid='" . addslashes($cid) . "'";
    }

    $limitsql = '';
    if (!empty ($limits)) {
        if (substr ($limits, -1) == 'h') { // last xx hours
            $limitsql = '';
            $hours = substr ($limits, 0, -1);
            if (!empty ($where)) {
                $where .= ' AND ';
            }
            $where .= "date >= DATE_SUB(NOW(),INTERVAL $hours HOUR)";
        } else {
            $limitsql = ' LIMIT ' . $limits;
        }
    }
    else
    {
        $limitsql = ' LIMIT 10';
    }

    if (!empty ($where)) {
        $where = ' WHERE ' . $where;
    }

    $sql = $where . ' ORDER BY date DESC' . $limitsql;

    return $sql;
}

/**
* Checking if links feeds are up to date
*
* @param    int     $feed           id of feed to be checked
* @param    string  $topic          topic (actually: cid)
* @param    string  $update_data    data describing current feed contents
* @param    string  $limit          number of entries or number of hours
* @param    string  $updated_type   (optional) type of feed to be updated
* @param    string  $updated_topic  (optional) feed's "topic" to be updated
* @param    string  $updated_id     (optional) id of entry that has changed
* @return   boolean                 true: feed data is up to date; false: isn't
*
*/
function plugin_feedupdatecheck_links ($feed, $topic, $update_data, $limit, $updated_type = '', $updated_topic = '', $updated_id = '')
{
    global $_TABLES;

    $is_current = true;

    if ($updated_type != 'links') {
        // we're not interested
        $updated_type = '';
        $updated_topic = '';
        $updated_id = '';
    }

    $sql = "SELECT lid FROM {$_TABLES['links']}" . links_buildSql ($topic, $limit);
    $result = DB_query ($sql);
    $num = DB_numRows ($result);

    $lids = array ();
    for ($i = 0; $i < $num; $i++) {
        $A = DB_fetchArray ($result);

        if ($A['lid'] == $updated_id) {
            // this feed has to be updated - no further checks needed
            return false;
        }

        $lids[] = $A['lid'];
    }
    $current = implode (',', $lids);

    return ($current != $update_data) ? false : true;
}

/**
* Update the Links plugin
*
* @return   int     Number of message to display (true = generic success msg)
*
*/
function plugin_upgrade_links()
{
    // the plugin needs these function so complain when they don't exist
    if (!function_exists('PLG_uninstall') ||
            !function_exists('COM_createLink')) {
        return 3002;
    }

    // upgrades are done by the install script - return a generic error
    COM_errorLog("Plugin upgrade function not implemented");
    return 3001;
}

/**
* Geeklog informs us that we're about to be enabled or disabled
*
* @param    boolean     $enable     true = we're being enabled, false = disabled
* @return   void
*
*/
function plugin_enablestatechange_links ($enable)
{
    global $_TABLES;

    $is_enabled = $enable ? 1 : 0;

    // toggle links feeds
    DB_query ("UPDATE {$_TABLES['syndication']} SET is_enabled = $is_enabled WHERE type = 'links'");
}

/**
* Counts the items that are submitted
*
* @return   int     number of items in submission queue
*
*/
function plugin_submissioncount_links()
{
    global $_TABLES;

    $retval = 0;

    if (plugin_ismoderator_links ()) {
        $retval = DB_count ($_TABLES['linksubmission']);
    }

    return $retval;
}

/**
* Checks that the current user has the rights to moderate the
* plugin, returns true if this is the case, false otherwise
*
* @return        boolean       Returns true if moderator
*
*/
function plugin_ismoderator_links()
{
    return SEC_hasRights ('links.moderate');
}


/**
* Returns SQL & Language texts to moderation.php
*
* @return   mixed   plugin object or void if not allowed
*
*/
function plugin_itemlist_links()
{
    global $_TABLES, $LANG_LINKS_SUBMIT;

    if (plugin_ismoderator_links()) {
        $plugin = new Plugin();
        $plugin->submissionlabel = $LANG_LINKS_SUBMIT[11];
        $plugin->submissionhelpfile = 'cclinksubmission.html';
        $plugin->getsubmissionssql = "SELECT lid AS id,title,cid AS category,url FROM {$_TABLES['linksubmission']} ORDER BY title ASC";
        $plugin->addSubmissionHeading($LANG_LINKS_SUBMIT[8]);
        $plugin->addSubmissionHeading($LANG_LINKS_SUBMIT[10]);
        $plugin->addSubmissionHeading($LANG_LINKS_SUBMIT[9]);

        return $plugin;
    }
}

/**
* returns list of moderation values
*
* The array returned contains (in order): the row 'id' label, main plugin
* table, moderation fields (comma seperated), and plugin submission table
*
* @return       array        Returns array of useful moderation values
*
*/
function plugin_moderationvalues_links()
{
    global $_TABLES;

    return array ('lid',
                  $_TABLES['links'],
                  'lid,cid,url,description,title,date,owner_id',
                  $_TABLES['linksubmission']);
}


/**
* Performs plugin exclusive work for items approved by moderation
*
* While moderation.php handles the actual move from linkssubmission
* to links tables, within the function we handle all other approval
* relate tasks
*
* @param    string  $id     Identifying string
* @return   string          Any wanted HTML output
*
*/
function plugin_moderationapprove_links($id)
{
    global $_TABLES, $_USER, $_GROUPS, $_LI_CONF;

    // The linksubmission only keeps track of the submitter's uid, but not
    // of grous and permissions. So set those to sensible defaults.

    if (isset($_GROUPS['Links Admin'])) {
        $group_id = $_GROUPS['Links Admin'];
    } else {
        $group_id = SEC_getFeatureGroup('links.moderate');
    }

    $A = array();
    SEC_setDefaultPermissions($A, $_LI_CONF['default_permissions']);

    DB_query("UPDATE {$_TABLES['links']} SET group_id = '$group_id', perm_owner = '{$A['perm_owner']}', perm_group = '{$A['perm_group']}', perm_members = '{$A['perm_members']}', perm_anon = '{$A['perm_anon']}' WHERE lid = '$id'");

    return '';
}

/**
* Performs plugin exclusive work for items deleted by moderation
*
* While moderation.php handles the actual removal from <plugin>submission
* table, within this function we handle all other deletion
* related tasks
*
* @param    string  $id     Identifying string
* @return   string          Any wanted HTML output
*
*/
function plugin_moderationdelete_links($id)
{
    global $_TABLES;

    // these tables should not contain any rows with ml_id = $id
    // this is done 'just in case'
    DB_delete ($_TABLES['linksubmission'], 'lid', $id);

    return '';
}

/**
* Check submission form values and save if OK. Else show form again
*
* @param    array   $A  The link record
* @return   string      Any wanted HTML output
*
*/
function plugin_savesubmission_links($A)
{
    global $LANG12;

    $retval = '';

    if (!empty ($A['title']) && !empty ($A['description']) &&
                !empty ($A['url'])) {
        $retval = plugin_save_submit_links ($A);
    } else {
        $retval .= COM_siteHeader()
            . COM_startBlock ($LANG12[22], '',
                           COM_getBlockTemplate ('_msg_block', 'header'))
            . $LANG12[23]
            . COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'))
            . submissionform('links')
            . COM_siteFooter ();
    }

    return $retval;
}

/**
* Shows link submission form
*
* @return   string  HTML for the link submission form
*
*/
function plugin_submit_links()
{
    global $_CONF, $LANG_LINKS_SUBMIT, $LANG12;

    $retval = COM_startBlock ($LANG_LINKS_SUBMIT[1], 'submitlink.html');

    $linkform = new Template($_CONF['path'] . 'plugins/links/templates');
    $linkform->set_file('linkform', 'submitlink.thtml');
    $linkform->set_var('site_url', $_CONF['site_url']);
    $linkform->set_var('layout_url', $_CONF['layout_url']);
    $linkform->set_var('lang_title', $LANG12[10]);
    $linkform->set_var('lang_link', $LANG_LINKS_SUBMIT[2]);
    $linkform->set_var('lang_category', $LANG_LINKS_SUBMIT[3]);
    $category = '';
    if (isset($_REQUEST['cid'])) {
        $category = $_REQUEST['cid'];
    }
    $linkform->set_var('link_category_options', links_select_box(2, $category));
    $linkform->set_var('lang_description', $LANG12[15]);
    $linkform->set_var('lang_htmlnotallowed', $LANG12[35]);
    $linkform->set_var('lang_submit', $LANG12[8]);
    $linkform->set_var('max_url_length', 255);
    $linkform->set_var('xhtml', XHTML);
    $linkform->parse('theform', 'linkform');
    $retval .= $linkform->finish($linkform->get_var('theform'));
    $retval .= COM_endBlock();

    return $retval;
}

/**
* Saves a link submission
*
* @param    array   $A  Data for that submission
* @return   string      HTML redirect
*
*/
function plugin_save_submit_links($A)
{
    global $_CONF, $_TABLES, $_USER, $_LI_CONF, $LANG12;

    $retval = '';

    // pseudo-formatted link description for the spam check
    $spamcheck = '<p>'. COM_createLink($A['title'], $A['url']) .' ('
               . $A['categorydd'] . ')<br' . XHTML . '>' . $A['description']
               . '</p>';
    $result = PLG_checkforSpam($spamcheck, $_CONF['spamx']);
    if ($result > 0) {
        COM_updateSpeedlimit('submit');
        COM_displayMessageAndAbort($result, 'spamx', 403, 'Forbidden');
    }

    $A['cid'] = strip_tags(COM_stripslashes($A['categorydd']));

    $validcat = false;
    if (!empty($A['cid'])) {
        $cid = addslashes($A['cid']);
        $cat = DB_getItem($_TABLES['linkcategories'], 'category',
                          "cid = '$cid'");
        if (!empty($cat)) {
            $validcat = true;
        }
    }
    if (!$validcat) {
        $retval .= COM_startBlock($LANG12[22], '',
                       COM_getBlockTemplate('_msg_block', 'header'))
                . $LANG12[23]
                . COM_endBlock(COM_getBlockTemplate('_msg_block', 'footer'))
                . submissionform('links')
                . COM_siteFooter();

        return $retval;
    }

    $A['cid'] = addslashes($A['cid']);
    $A['description'] = addslashes(htmlspecialchars(COM_checkWords($A['description'])));
    $A['title'] = addslashes(strip_tags(COM_checkWords($A['title'])));
    $A['url'] = addslashes(COM_sanitizeUrl($A['url']));
    $A['lid'] = addslashes(COM_makeSid());

    COM_updateSpeedlimit('submit');
    if (COM_isAnonUser()) {
        $owner_id = 1; // anonymous user
    } else {
        $owner_id = $_USER['uid'];
    }

    if (($_LI_CONF['linksubmission'] == 1) && !SEC_hasRights('links.submit')) {
        $result = DB_save($_TABLES['linksubmission'],
                    'lid,cid,url,description,title,date,owner_id',
                    "{$A['lid']},'{$A['cid']}','{$A['url']}','{$A['description']}','{$A['title']}',NOW(),$owner_id");

        if ($_LI_CONF['notification'] == 1) {
            LINKS_sendNotification($_TABLES['linksubmission'], $A);
        }

        $retval = COM_refresh($_CONF['site_url']
                              . '/index.php?msg=1&amp;plugin=links');

    } else { // add link directly

        if (SEC_hasRights('links.submit')) {
            $A['group_id'] = SEC_getFeatureGroup('links.submit');
        } else {
            $A['group_id'] = DB_getItem($_TABLES['groups'], 'grp_id',
                                        "grp_name = 'All Users'");
        }
        SEC_setDefaultPermissions($A, $_LI_CONF['default_permissions']);

        $result = DB_save($_TABLES['links'],
                    'lid,cid,url,description,title,date,owner_id,group_id,perm_owner,perm_group,perm_members,perm_anon',
                    "{$A['lid']},'{$A['cid']}','{$A['url']}','{$A['description']}','{$A['title']}',NOW(),$owner_id,{$A['group_id']},{$A['perm_owner']},{$A['perm_group']},{$A['perm_members']},{$A['perm_anon']}");

        if ($_LI_CONF['notification'] == 1) {
            LINKS_sendNotification($_TABLES['links'], $A);
        }
        COM_rdfUpToDateCheck('links', $A['cid'], $A['lid']);

        $retval = COM_refresh($_CONF['site_url']
                              . '/index.php?msg=4&amp;plugin=links');
    }

    return $retval;
}

/**
* Send an email notification for a new submission.
*
* @param    string  $table  Table where the new submission can be found
* @param    array   $A      submission data
*
*/
function LINKS_sendNotification ($table, $A)
{
    global $_CONF, $_TABLES, $LANG_LINKS, $LANG_LINKS_SUBMIT, $LANG08;

    $title = stripslashes ($A['title']);
    $description = stripslashes ($A['description']);

    $mailbody = "$LANG_LINKS_SUBMIT[8]: $title\n"
              . "$LANG_LINKS_SUBMIT[9]: <{$A['url']}>\n"
              . "$LANG_LINKS_SUBMIT[3]: {$A['category']}\n\n"
              . $description . "\n\n";
    if ($table == $_TABLES['linksubmission']) {
        $mailbody .= "$LANG_LINKS[10] <{$_CONF['site_admin_url']}/moderation.php>\n\n";
    } else {
        $mailbody .= "$LANG_LINKS[114] <{$_CONF['site_url']}/links/index.php?category=" . urlencode ($A['category']) . ">\n\n";
    }
    $mailsubject = $_CONF['site_name'] . ' ' . $LANG_LINKS_SUBMIT[11];

    $mailbody .= "\n------------------------------\n";
    $mailbody .= "\n$LANG08[34]\n";
    $mailbody .= "\n------------------------------\n";

    COM_mail ($_CONF['site_mail'], $mailsubject, $mailbody);
}

/**
* Returns the URL of the plugin's icon
*
* @return   string      URL of the icon
*
*/
function plugin_geticon_links ()
{
    global $_CONF;

    return $_CONF['site_url'] . '/links/images/links.png';
}

function plugin_getListField_links($fieldname, $fieldvalue, $A, $icon_arr)
{
    global $_CONF, $LANG_ACCESS, $LANG_LINKS_ADMIN;

    $retval = '';

    $access = SEC_hasAccess($A['owner_id'],$A['group_id'],$A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']);
    if ($access > 0) {
        switch($fieldname) {
            case 'edit':
                if ($access == 3) {
                    $retval = COM_createLink(
                        $icon_arr['edit'],
                        "{$_CONF['site_admin_url']}/plugins/links/index.php?mode=edit&amp;lid={$A['lid']}"
                    );
                }
                break;
            case 'access':
                if ($access == 3) {
                   $retval = $LANG_ACCESS['edit'];
                } else {
                   $retval = $LANG_ACCESS['readonly'];
                }
                break;
            case 'title':
                $retval = COM_createLink(stripslashes($A['title']), $A['url']);
                break;
            case 'dovalidate';
                $retval = links_validateUrl($A['url']);
                break;
            case 'beforevalidate';
                $retval = $LANG_LINKS_ADMIN[57];
                break;
            case 'category':
                if (isset($A['indent'])) {
                    $indent = ($A['indent'] - 1) * 20;
                } else {
                    $indent = 0;
                }
                $cat = COM_createLink($A['category'],
                        "{$_CONF['site_url']}/links/index.php?category="
                        . urlencode($A['cid']));
                $retval = "<span style=\"padding-left:{$indent}px;\">$cat</span>";
                break;
                break;
            default:
                $retval = $fieldvalue;
                break;
        }
    }

    return $retval;
}

function plugin_getListField_categories($fieldname, $fieldvalue, $A, $icon_arr)
{
    global $_CONF, $_TABLES, $LANG_ACCESS, $LANG_LINKS_ADMIN;

    $retval = '';

    $access = SEC_hasAccess($A['owner_id'],$A['group_id'],$A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']);
    if ($access > 0) {
        switch($fieldname) {
            case 'edit':
                if ($access == 3) {
                    $retval = COM_createLink(
                        $icon_arr['edit'],
                        "{$_CONF['site_admin_url']}/plugins/links/category.php?mode=edit&amp;cid=" . urlencode($A['cid'])
                    );
                }
                break;
            case 'access':
                if ($access == 3) {
                   $retval = $LANG_ACCESS['edit'];
                } else {
                   $retval = $LANG_ACCESS['readonly'];
                }
                break;
            case 'category':
                $indent = ($A['indent'] - 1) * 20;
                $cat = COM_createLink($A['category'],
                        "{$_CONF['site_url']}/links/index.php?category="
                        . urlencode($A['cid']));
                $retval = "<span style=\"padding-left:{$indent}px;\">$cat</span>";
                break;
            case 'addchild';
                if ($access == 3) {
                    $retval = COM_createLink(
                        $icon_arr['addchild'],
                        "{$_CONF['site_admin_url']}/plugins/links/category.php?mode=edit&amp;pid=" . urlencode($A['cid'])
                    );
                }
                break;
            case 'tid';
                if ($A['tid'] == 'all') {
                    $retval = $LANG_LINKS_ADMIN[35];
                } else {
                    $retval = DB_getItem($_TABLES['topics'], 'topic',
                                         "tid = '{$A['tid']}'");
                }
                if (empty($retval)) {
                    $retval = $A['tid'];
                }
                break;
            default:
                $retval = $fieldvalue;
                break;
        }
    }

    return $retval;
}


function links_validateUrl($url)
{
    global $LANG_LINKS_STATUS;

    require_once 'HTTP/Request.php';

    $retval = '';

    $req = new HTTP_Request($url);
    $req->setMethod(HTTP_REQUEST_METHOD_HEAD);
    $req->addHeader('User-Agent', 'Geeklog/' . VERSION);

    $response = $req->sendRequest();
    if (PEAR::isError($response)) {
        $retval = $response->getMessage();
    } else {
        $status_code = $req->getResponseCode();
        if (isset($LANG_LINKS_STATUS[$status_code])) {
            $retval = $status_code . ": " . $LANG_LINKS_STATUS[$status_code];
        } else {
            $retval = $LANG_LINKS_STATUS[999];
        }
    }

    return $retval;
}

/**
* Set template variables
*
* @param    string  $templatename   name of template, e.g. 'header'
* @param    ref     $template       reference of actual template
* @return   void
*
* Note: A plugin should use its name as a prefix for the names of its
* template variables, e.g. 'links_xxx' and 'lang_links_xxx'.
* 'button_links' is an exception, as such a variable existed for header.thtml
* in Geeklog 1.3.11 and earlier, where the Links section was an integral part
* of Geeklog. It is added here for backward-compatibility.
*
*/
function plugin_templatesetvars_links ($templatename, &$template)
{
    global $LANG_LINKS;

    if ($templatename == 'header') {
        $template->set_var ('button_links', $LANG_LINKS[14]);
    }
}

/**
* Automatic uninstall function for plugins
*
* @return   array
*
* This code is automatically uninstalling the plugin.
* It passes an array to the core code function that removes
* tables, groups, features and php blocks from the tables.
* Additionally, this code can perform special actions that cannot be
* foreseen by the core code (interactions with other plugins for example)
*
*/
function plugin_autouninstall_links ()
{
    $out = array (
        /* give the name of the tables, without $_TABLES[] */
        'tables' => array('links','linksubmission','linkcategories'),
        /* give the full name of the group, as in the db */
        'groups' => array('Links Admin'),
        /* give the full name of the feature, as in the db */
        'features' => array('links.edit', 'links.moderate', 'links.submit'),
        /* give the full name of the block, including 'phpblock_', etc */
        'php_blocks' => array('phpblock_topic_categories', 'phpblock_topic_links'),
        /* give all vars with their name */
        'vars'=> array()
    );
    return $out;
}

// +--------------------------------------------------------------------------+
// | Category HTML functions                                                  |
// | Functions for building select boxes and breadcrumb trails etc.           |
// +--------------------------------------------------------------------------+

/*
* Build selection list
*/
function links_select_box ($access, $sel = '')
{
    global $_CONF, $LANG_LINKS, $_LI_CONF;

    // set root value
    $menu = '<option value="' . $_LI_CONF['root'] . '">' . $LANG_LINKS['root'] . '</option>';
    // get option values
    $list = links_select_box_recursive($menu, $_LI_CONF['root'], $sel, '&nbsp;&nbsp;', $access);
    // return list of options
    return $list;
}


/*
* Build recursive tree
*/
function links_select_box_recursive (&$menu, $cid, $sel, $indent, $access)
{
    global $_CONF, $_TABLES;

    $cat = addslashes($cid);
    $sql = "SELECT cid,category
            FROM {$_TABLES['linkcategories']}
            WHERE (pid='{$cat}') " . COM_getPermSQL('AND', 0, $access) . "
            ORDER BY category";
    $query = DB_query($sql);
    while (list($cid, $category) = DB_fetchArray($query)) {
        // set selected item
        if ($cid == $sel) {
            // yes, selected
            $menu .= '<option value="' . htmlspecialchars($cid)
                  . '" selected="selected">' . $indent . $category
                  . '</option>';
        } else {
            // no, not selected
            $menu .= '<option value="' . htmlspecialchars($cid) . '">'
                  . $indent . $category . '</option>';
        }
        // Check and see if this category has any sub categories
        if (DB_count($_TABLES['linkcategories'], 'pid', addslashes($cid)) > 0) {
            // yes, call self
            $dum = links_select_box_recursive ($menu, $cid, $sel,
                        $indent . '&nbsp;&nbsp;', $access);
        }
   }

   return $menu;
}


/*
* Build breadcrumb trail
*
* Breadcrumb trail does not use the "root" category in the database: the top
* level category is set from the language file using $LANG_LINKS['root']
*/
function links_breadcrumbs($root, $cid)
{
    global $_CONF, $_TABLES, $LANG_LINKS;

    $breadcrumb = '';
    $separator  = ' &gt; ';

    $cat = addslashes($cid);
    $c = $cid;
    $pid = '';
    if ($root != $cid) {
        while ($pid != $root) {
            $parent = DB_query("SELECT cid,pid,category FROM {$_TABLES['linkcategories']} WHERE cid='{$cat}'");
            $A = DB_fetchArray($parent);
            if ($cid != $c) {
                $content = stripslashes($A['category']);
                $url = $_CONF['site_url'] . '/links/index.php?category='
                                          . urlencode($A['cid']);
                $breadcrumb = COM_createLink($content, $url) . $separator
                            . $breadcrumb;
            } else {
                $breadcrumb = '<b>' . $A['category'] . '</b>' . $breadcrumb;
            }
            $pid = $A['pid'];
            $c = $A['pid'];
            $cat = addslashes($c);
        }
    }

    $url = $_CONF['site_url'] . '/links/index.php';
    if (empty($breadcrumb)) {
        $breadcrumb = '<b>' . $LANG_LINKS['root'] . '</b>';
    } else {
        $breadcrumb = COM_createLink($LANG_LINKS['root'], $url) . $separator . $breadcrumb;
    }

    $breadcrumb = '<span class="links-breadcrumb">' . $LANG_LINKS[126] . ' '
                . $breadcrumb . '</span>';

    return $breadcrumb;
}



// +--------------------------------------------------------------------------+
// | PHP Block functions                                                      |
// +--------------------------------------------------------------------------+

/**
 * Returns a list of links that belong to categories associated with
 * the current topic
 *
 * Relies on the fact that $topic is set (and sanitized) in lib-common.php
 */
function phpblock_topic_links()
{
    global $_CONF, $_TABLES, $LANG_LINKS, $topic;

    $retval = '';

    if (!empty($topic)) {
        $tid = addslashes($topic);
        $result = DB_query("SELECT l.lid, l.title, l.url, c.cid FROM {$_TABLES['links']} AS l LEFT JOIN {$_TABLES['linkcategories']} AS c ON l.cid=c.cid WHERE c.tid='{$tid}' OR c.tid='all'" . COM_getPermSQL('AND', 0, 2, 'c'));
        $nrows = DB_numRows($result);
        if ($nrows > 0) {
            for ($i = 0; $i < $nrows; $i++) {
                $A = DB_fetchArray($result);
                $content = stripslashes($A['title']);
                $url = COM_buildUrl($_CONF['site_url']
                     . '/links/portal.php?what=link&amp;item=' . $A['lid']);
                $retval .= COM_createLink($content, $url,
                                          array('title' => $A['url']))
                        . '<br' . XHTML . '>';
            }
        }
    }

    return $retval;
}


/**
 * Returns a list of categories that are associated with the current topic
 *
 * Relies on the fact that $topic is set (and sanitized) in lib-common.php
 */
function phpblock_topic_categories()
{
    global $_CONF, $_TABLES, $LANG_LINKS, $topic;

    $retval = '';

    if (!empty($topic)) {
        $tid = addslashes($topic);
        $result = DB_query("SELECT category, cid FROM {$_TABLES['linkcategories']} WHERE tid='{$tid}' OR tid='all'" . COM_getPermSQL ('AND'));
        $nrows = DB_numRows($result);
        if ($nrows > 0) {
            for ($i = 0; $i < $nrows; $i++) {
                $A = DB_fetchArray($result);
                $content = stripslashes($A['category']);
                $url = $_CONF['site_url'] . '/links/index.php?category='
                                          . urlencode($A['cid']);
                $retval .= COM_createLink($content, $url) . '<br' . XHTML . '>';
            }
        }
    }

    return $retval;
}

?>
