<?php
// $Id: rssc_xml_object.php,v 1.11 2006/09/19 03:18:30 ohwada Exp $

// 2006-09-18 K.OHWADA
// highlight keyword
// some RSS have twe or more enclosure tag
// add set_control_obj() is_rss() is_arom()
// add _build_content_for_format() _format_guid_url()
// BUG: Fatal error: Call to a member function on a non-object
// BUG: sometime cannot parse

// 2006-07-18 K.OHWADA
// REQ 4146: some feed have no link
// add _build_link()

// 2006-07-10 K.OHWADA
// use happy_linux_basic happy_linux_strings happy_linux_convert_encoding
// add class rssc_xml_channel, rssc_xml_items, etc
// support podcast

// 2006-06-04 K.OHWADA
// this is new file
// merge view_format, sanitize

//=========================================================
// Rss Center Module
// this file contains 7 classes
//   rssc_xml
//   rssc_xml_basic
//   rssc_xml_channel
//   rssc_xml_image
//   rssc_xml_textinput
//   rssc_xml_items
//   rssc_xml_item_single
// 2006-06-04 K.OHWADA
//=========================================================

// === class begin ===
if( !class_exists('rssc_xml') ) 
{

//=========================================================
// class rssc_xml
//=========================================================
class rssc_xml
{
// object
	var $_control_obj     = null;
	var $_channel_obj     = null;
	var $_image_obj       = null;
	var $_textinput_obj   = null;
	var $_items_obj       = null;
	var $_single_item_obj = null;

// cached data
	var $_converted_data;

// set param
	var $_flag_title_html   = false;
	var $_flag_content_html = false;
	var $_max_summary = 250;
	var $_max_title   =   -1;	// unlimited
	var $_max_content =   -1;	// unlimited
	var $_flag_highlight = false;
	var $_keyword_array  = null;

// encoding
	var $_local_encoding  = _CHARSET;
	var $_xml_encoding    = 'utf-8';

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function rssc_xml()
{
	// dummy
}

//---------------------------------------------------------
// set & get vars
//---------------------------------------------------------
function set_vars_from_parse( &$obj )
{
	$control = array(
		'feed_type'       => $obj->feed_type,
		'feed_version'    => $obj->feed_version,
		'source_encoding' => $obj->source_encoding,
		'encoding'        => $obj->encoding,
	);

	$this->set_control(   $control );
	$this->set_channel(   $obj->channel );
	$this->set_image(     $obj->image );
	$this->set_textinput( $obj->textinput );
	$this->set_items(     $obj->items );
}

function set_vars($arr)
{
	if ( isset($arr['control']) )
	{
		$this->set_control( $arr['control'] );
	}

	if ( isset($arr['channel']) )
	{
		$this->set_channel( $arr['channel'] );
	}

	if ( isset($arr['image']) )
	{
		$this->set_image( $arr['image'] );
	}

	if ( isset($arr['textinput']) )
	{
		$this->set_textinput( $arr['textinput'] );
	}

	if ( isset($arr['items']) )
	{
		$this->set_items( $arr['items'] );
	}
}

function set_control($arr)
{
	if ( is_array($arr) &&  ( count($arr) > 0 ) )
	{
		$this->_control_obj =& new happy_linux_basic();
		$this->_control_obj->set_vars( $arr );
	}
}

function set_channel($arr)
{
	if ( is_array($arr) &&  ( count($arr) > 0 ) )
	{
		$this->_channel_obj =& new rssc_xml_channel();
		$this->_channel_obj->set_vars( $arr );
	}
}

function set_image($arr)
{
	if ( is_array($arr) && ( count($arr) > 0 ) )
	{
		$this->_image_obj =& new rssc_xml_image();
		$this->_image_obj->set_vars( $arr );
	}
}

function set_textinput($arr)
{
	if ( is_array($arr) && ( count($arr) > 0 ) )
	{
		$this->_textinput_obj =& new rssc_xml_textinput();
		$this->_textinput_obj->set_vars( $arr );
	}
}

function set_items($items)
{
	if ( is_array($items) && ( count($items) > 0 ) )
	{
		$this->_items_obj =& new rssc_xml_items();
		$this->_items_obj->set_vars( $items );
	}
}

function set_single_item($arr)
{
	if ( is_array($arr) && ( count($arr) > 0 ) )
	{
		$this->_single_item_obj =& new rssc_xml_item_single();
		$this->_single_item_obj->set_vars( $arr );
	}
}

function &get_vars()
{
	$arr = array(
		'control'   => $this->get_control(),
		'channel'   => $this->get_channel(),
		'image'     => $this->get_image(),
		'textinput' => $this->get_textinput(),
		'items'     => $this->get_items(),
	);
	return $arr;
}

function &get_control()
{
	$ret = false;
	if ( isset($this->_control_obj) && is_object($this->_control_obj) )
	{
		$ret =& $this->_control_obj->get_vars();
	}
	return $ret;
}

function &get_channel()
{
	$ret = false;
	if ( isset($this->_channel_obj) && is_object($this->_channel_obj) )
	{
		$ret =& $this->_channel_obj->get_vars();
	}
	return $ret;
}

function &get_image()
{
	$ret = false;
	if ( isset($this->_image_obj) && is_object($this->_image_obj) )
	{
		$ret =& $this->_image_obj->get_vars();
	}
	return $ret;
}

function &get_textinput()
{
	$ret = false;
	if ( isset($this->_textinput_obj) && is_object($this->_textinput_obj) )
	{
		$ret =& $this->_textinput_obj->get_vars();
	}
	return $ret;
}

function &get_items()
{
	$ret = false;
	if ( isset($this->_items_obj) && is_object($this->_items_obj) )
	{
		$ret =& $this->_items_obj->get_vars();
	}
	return $ret;
}

function &get_single_item()
{
	$ret = false;
	if ( isset($this->_single_item_obj) && is_object($this->_single_item_obj) )
	{
		$ret =& $this->_single_item_obj->get_vars();
	}
	return $ret;
}

function get_source_encoding()
{
	$arr = $this->get_control();

	$ret = false;
	if ( isset($arr['source_encoding']) )
	{
		$ret =& $arr['source_encoding'];
	}
	return $ret;
}

function &get_channel_by_key($key)
{
	$arr = $this->get_channel();

	$ret = false;
	if ( isset($arr[$key]) )
	{
		$ret =& $arr[$key];
	}
	return $ret;
}

function &get_converted_data()
{
	$ret = false;
	if ( isset($this->_converted_data) )
	{
		$ret =& $this->_converted_data;
	}
	return $ret;
}

//---------------------------------------------------------
// convert from parse to local
//---------------------------------------------------------
function convert_to_local()
{
	$to   = $this->_local_encoding;
	$from = $this->_xml_encoding;

// BUG: sometime cannot parse
	if ( isset($this->_channel_obj) && is_object($this->_channel_obj) )
	{
		$this->_channel_obj->convert($to, $from);
	}

	if ( isset($this->_items_obj) && is_object($this->_items_obj) )
	{
		$this->_items_obj->convert($to, $from);
	}

	if ( isset($this->_image_obj) && is_object($this->_image_obj) )
	{
		$this->_image_obj->convert($to, $from);
	}

	if ( isset($this->_textinput_obj) && is_object($this->_textinput_obj) )
	{
		$this->_textinput_obj->convert($to, $from);
	}

	$this->_converted_data =& $this->get_vars();
}

//---------------------------------------------------------
// build_for_store
//---------------------------------------------------------
function build_for_store()
{
// BUG: sometime cannot parse
	if ( isset($this->_items_obj) && is_object($this->_items_obj) )
	{
		$site_title = $this->get_channel_by_key('title');
		$site_link  = $this->get_channel_by_key('link');
		$this->_items_obj->build($site_title, $site_link, $this->_control_obj);
	}
}

//---------------------------------------------------------
// view format
//---------------------------------------------------------
function view_format()
{
	if ( isset($this->_channel_obj) && is_object($this->_channel_obj) )
	{
		$this->_channel_obj->format();
	}

	if ( isset($this->_items_obj) && is_object($this->_items_obj) )
	{
		$this->_items_obj->format_from_parse();
	}
}

function view_format_items()
{
// BUG: Fatal error: Call to a member function on a non-object
	if ( isset($this->_items_obj) && is_object($this->_items_obj) )
	{
		$this->_items_obj->format_from_db();
	}
}

function view_format_single_item()
{
	if ( isset($this->_single_item_obj) && is_object($this->_single_item_obj) )
	{
		$this->_single_item_obj->format_from_db();
	}
}

//---------------------------------------------------------
// view sanitize
//---------------------------------------------------------
function view_sanitize()
{
	if ( isset($this->_channel_obj) && is_object($this->_channel_obj) )
	{
		$this->_channel_obj->sanitize();
	}

	if ( isset($this->_items_obj) && is_object($this->_items_obj) )
	{
		$this->_items_obj->sanitize( $this->_get_sanitize_param() );
	}

	if ( isset($this->_image_obj) && is_object($this->_image_obj) )
	{
		$this->_image_obj->sanitize();
	}

	if (  isset($this->_textinput_obj) && is_object($this->_textinput_obj) )
	{
		$this->_textinput_obj->sanitize();
	}
}

function view_sanitize_items()
{
	if ( isset($this->_items_obj) && is_object($this->_items_obj) )
	{
		$this->_items_obj->sanitize( $this->_get_sanitize_param() );
	}
}

function view_sanitize_single_item()
{
	if ( isset($this->_single_item_obj) && is_object($this->_single_item_obj) )
	{
		$this->_single_item_obj->sanitize( $this->_get_sanitize_param() );
	}
}

function &_get_sanitize_param()
{
	$arr = array(
		'flag_title_html'   => $this->_flag_title_html,
		'max_title'         => $this->_max_title, 
		'flag_content_html' => $this->_flag_content_html, 
		'max_content'       => $this->_max_content, 
		'max_summary'       => $this->_max_summary, 
		'keyword_array'     => $this->_keyword_array,
		'flag_highlight'    => $this->_flag_highlight,
	);
	return $arr;
}

//---------------------------------------------------------
// set and get property
//---------------------------------------------------------
function set_xml_encoding($value)
{
	$this->_xml_encoding = $value;
}

function set_local_encoding($value)
{
	$this->_local_encoding = $value;
}

function set_title_html($value)
{
	$this->_flag_title_html = (bool)$value;
}

function set_content_html($value)
{
	$this->_flag_content_html = (bool)$value;
}

function set_max_title($value)
{
	$this->_max_title = intval($value);
}

function set_max_summary($value)
{
	$this->_max_summary = intval($value);
}

function set_max_content($value)
{
	$this->_max_content = intval($value);
}

function set_flag_highlight($value)
{
	$this->_flag_highlight = (bool)$value;
}

function set_keyword_array($value)
{
	if ( is_array($value) )
	{
		$this->_keyword_array = $value;
	}
}

// --- class end ---
}


//=========================================================
// class rssc_xml_basic
//=========================================================
class rssc_xml_basic extends happy_linux_basic 
{
// class
	var $_strings;
	var $_convert;
	var $_xml_utility;

// constant
	var $_TITLE_SUBSTITUTE = '---';

// control
	var $_feed_type = null;
	var $_feed_version;
	var $_source_encoding;
	var $_encoding;

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function rssc_xml_basic()
{
	$this->happy_linux_basic();

// class
	$this->_strings     =& happy_linux_strings::getInstance();
	$this->_convert     =& happy_linux_convert_encoding::getInstance();
	$this->_xml_utility =& rssc_xml_utility::getInstance();
}

//---------------------------------------------------------
// is set & array
//---------------------------------------------------------
function get($key1, $key2=false)
{
	$ret = false;
	if ( isset($this->_vars[$key1]) )
	{
		if ( $key2 )
		{
			if ( isset($this->_vars[$key1][$key2]) )
			{
				$ret = $this->_vars[$key1][$key2];
			}
		}
		else
		{
			$ret = $this->_vars[$key1];
		}
	}
	return $ret;
}

function is_set($key1, $key2=false)
{
	if ( isset($this->_vars[$key1]) )
	{
		if ( $key2 )
		{
			if ( is_array($this->_vars[$key1]) && isset($this->_vars[$key1][$key2]) )
			{
				return true;
			}
		}
		else
		{
			return true;
		}
	}
	return false;
}

//---------------------------------------------------------
// convert parse to local
//---------------------------------------------------------
function convert($str, $to, $from)
{
	// no action
}

function &_convert_block($arr, $to, $from)
{
	$ret =& $this->_convert->convert_array( $arr, $to, $from );
	return $ret;
}

function &_convert_strings($text, $to, $from)
{
	$ret = $this->_convert->convert( $text, $to, $from );
	return $ret;
}

//---------------------------------------------------------
// build
//---------------------------------------------------------
function build()
{
	// no action
}

function format()
{
	// no action
}

function _set_unixtime($key, $time_unix)
{
	if ($time_unix)
	{
		$this->set($key, $time_unix);
		$this->set($key.'_long',  formatTimestamp( $time_unix, 'l' ) );
		$this->set($key.'_short', formatTimestamp( $time_unix, 's' ) );
		$this->set($key.'_mysql', formatTimestamp( $time_unix, 'mysql' ) );
	}
}

//---------------------------------------------------------
// control
//---------------------------------------------------------
function set_control_obj($obj)
{
	if ( is_object($obj) )
	{
		$this->_feed_type       = $obj->get('feed_type');
		$this->_feed_version    = $obj->get('feed_version');
		$this->_source_encoding = $obj->get('source_encoding');
		$this->_encoding        = $obj->get('encoding');
	}

}

function is_rss()
{
	if ( $this->_feed_type == RSSC_MAGPIE_RSS )
	{
		return true;
	}
	return false;
}

function is_atom()
{
	if ( $this->_feed_type == RSSC_MAGPIE_ATOM )
	{
		return true;
	}
	return false;
}

//---------------------------------------------------------
// substitute_title
// some feed have no title
// subsutute by ---
//---------------------------------------------------------
function _substitute_title($key)
{
	if ( $this->is_set($key) )
	{
		$val = $this->get($key);
		if ( $this->_strings->check_valid($val) )
		{
			return $val;
		}
	}

	return $this->_TITLE_SUBSTITUTE;
}

//---------------------------------------------------------
// sanitize
//---------------------------------------------------------
function sanitize()
{
	// no action
}

function _sanitize_allow_html( $text, $flag, $max )
{
// allow HTML tag & under max content
	if ( $flag )
	{
		if ( ($max < 0) || (strlen($text) <= $max) )
		{
			$ret = $this->_strings->replace_javascript($text);

			if ( !$this->_strings->check_javascript($ret) )
			{
				return $ret;
			}
		}
	}

	$ret =$this->_sanitize_summary($text, $max);
	return $ret;
}

//---------------------------------------------------------
// use xml_utility class
//---------------------------------------------------------
function get_unixtime_rfc822( $datetime )
{
	$ret = $this->_xml_utility->get_unixtime_rfc822( $datetime );
	return $ret;
}

function get_unixtime_w3cdtf( $datetime )
{
	$ret = $this->_xml_utility->get_unixtime_w3cdtf( $datetime );
	return $ret;
}

//---------------------------------------------------------
// use string class
//---------------------------------------------------------
function &_sanitize_block($arr)
{
	$ret =& $this->_strings->sanitize_array_text($arr);
	return $ret;
}

function _sanitize_html_url($text)
{
	$ret = $this->_strings->sanitize_url($text);
	return $ret;
}

function _sanitize_html_text($text)
{
	$ret = $this->_strings->sanitize_text($text);
	return $ret;
}

function _sanitize_summary($text, $max, $keyword_array=null)
{
	$ret = $this->_strings->build_summary($text, $max, $keyword_array, 's');
	return $ret;
}

//---------------------------------------------------------
// set parameter
//---------------------------------------------------------
function set_local_encoding($val)
{
	$this->_local_encoding  = $val;
}

// --- class end ---
}

//=========================================================
// class rssc_xml_channel
//=========================================================
class rssc_xml_channel extends rssc_xml_basic
{
	// RSS
	var $DATE_RFC822_LIST = array('pubdate', 'lastbuilddate'); 

	var $DATE_W3C_LIST = array(
	// ATOM 1.0
		'published', 'updated',
	// ATOM 0.3
		'modified', 'issued', 'created'
	);

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function rssc_xml_channel()
{
	$this->rssc_xml_basic();
}

//---------------------------------------------------------
// convert parse to local
//---------------------------------------------------------
function convert($to, $from)
{
	$arr =& $this->_convert_block( $this->get_vars(), $to, $from );
	$this->set_vars( $arr );
}

//---------------------------------------------------------
// view format
//---------------------------------------------------------
function format()
{
	$this->set('title', $this->_substitute_title('title') );

// RFC882
	foreach ($this->DATE_RFC822_LIST as $key)
	{
		if ( $this->get($key) )
		{
			$time_unix = $this->get_unixtime_rfc822( $this->get($key) );
			$this->_set_unixtime($key, $time_unix);
		}
	}

// W3C format
	foreach ($this->DATE_W3C_LIST as $key)
	{
		if ( $this->get($key) )
		{
			$time_unix = $this->get_unixtime_w3cdtf( $this->get($key) );
			$this->_set_unixtime($key, $time_unix);
		}
	}

// dc:date
	if ( $this->is_set('dc','date') )
	{
		$time_unix = $this->get_unixtime_w3cdtf( $this->get('dc','date') );
		$this->_set_unixtime($key, $time_unix);
	}
}

//---------------------------------------------------------
// for rssc_headline xoopsheadline
// $format_date: l=long, r=rfc822
//---------------------------------------------------------
function format_for_rss( $format_date='l' )
{
	$date_unix = 0;

// ATOM 1.0
	if ( $this->is_set('updated') )
	{
		$date_unix = $this->get_unixtime_w3cdtf( $this->get('updated') );
	}

// ATOM 0.3
	elseif ( $this->is_set('modified') )
	{
		$date_unix = $this->get_unixtime_w3cdtf( $this->get('modified') );
	}

// DC
	elseif ( $this->is_set('dc','date') )
	{
		$date_unix = $this->get_unixtime_w3cdtf( $this->get('dc','date') );
	}

	if ( $date_unix )
	{
		$date_long   = formatTimestamp( $date_unix, 'l' );
		$date_rfc822 = date("r", $date_unix );
	}

	if ( $this->is_set('pubdate') )
	{
		$pubdate_unix = $this->get_unixtime_rfc822( $this->get('pubdate') );
		$pubdate_long = formatTimestamp( $pubdate_unix, 'l' );

		if ( $format_date == 'l' )
		{
			$this->set('pubdate', $pubdate_long );
		}
	}
	elseif ( $date_unix )
	{
		if ( $format_date == 'l' )
		{
			$this->set('pubdate', $date_long );
		}
		else
		{
			$this->set('pubdate', $date_rfc822 );
		}
	}

	if ( $this->is_set('lastbuilddate') )
	{
		$lastbuilddate_unix = $this->get_unixtime_rfc822( $this->get('lastbuilddate') );
		$lastbuilddate_long = formatTimestamp( $lastbuilddate_unix, 'l' );

		if ( $format_date == 'l' )
		{
			$this->set('lastbuilddate', $lastbuilddate_long );
		}
	}
	elseif ( $date_unix )
	{
		if ( $format_date == 'l' )
		{
			$this->set('lastbuilddate', $date_long );
		}
		else
		{
			$this->set('lastbuilddate', $date_rfc822 );
		}
	}

	if ( !$this->is_set('webmaster') )
	{
// ATOM
		if ( $this->is_set('author_email') )
		{
			$this->set('webmaster', $this->get('author_email') );
		}
		elseif ( $this->is_set('author_name') )
		{
			$this->set('webmaster', $this->get('author_name') );
		}
// DC
		elseif ( $this->is_set('dc','creator') )
		{
			$this->set('webmaster', $this->get('dc','creator') );
		}
		elseif ( $this->is_set('dc','publisher') )
		{
			$this->set('webmaster', $this->get('dc','publisher') );
		}
	}

	if ( !$this->is_set('copyright') )
	{
// ATOM
		if ( $this->is_set('rights') )
		{
			$this->set('copyright', $this->get('rights') );
		}
// DC
		elseif ( $this->is_set('dc','rights') )
		{
			$this->set('copyright', $this->get('dc','rights') );
		}
	}

	if ( !$this->is_set('category') )
	{
// DC
		if ( $this->is_set('dc','subject') )
		{
			$this->set('category', $this->get('dc','subject') );
		}
	}

	if ( !$this->is_set('language') )
	{
// DC
		if ( $this->is_set('dc','language') )
		{
			$this->set('language', $this->get('dc','language') );
		}
	}

}

//---------------------------------------------------------
// view sanitize
//---------------------------------------------------------
function sanitize()
{
	$arr = array();

	foreach ($this->get_vars() as $k => $v)
	{
		switch ($k)
		{
			case 'link':
			case 'link_self':
			case 'author_uri':
			case 'author_url':
			case 'contributor_uri':
			case 'contributor_url':
				$val = $this->_sanitize_html_url($v);
				break;

			default:
				$val = $this->_sanitize_block($v);
				break;
		}

		$arr[$k] = $val;
	}

	$this->set_vars( $arr );
}

// --- class end ---
}


//=========================================================
// class rssc_xml_image
//=========================================================
class rssc_xml_image extends rssc_xml_basic
{

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function rssc_xml_image()
{
	$this->rssc_xml_basic();
}

//---------------------------------------------------------
// convert parse to local
//---------------------------------------------------------
function convert($to, $from)
{
	$arr =& $this->_convert_block( $this->get_vars(), $to, $from );
	$this->set_vars( $arr );
}

//---------------------------------------------------------
// sanitize
//---------------------------------------------------------
function sanitize()
{
	$arr = array();

	foreach ($this->get_vars() as $k => $v)
	{
		switch ($k)
		{
			case 'link':
			case 'url':
				$val = $this->_sanitize_html_url($v);
				break;

			case 'width':
			case 'height':
				$val = intval($v);
				break;

			default:
				$val = $this->_sanitize_html_text($v);
				break;
		}

		$arr[$k] = $val;
	}

	if ( count($arr) > 0 )
	{
		$arr['show'] = 1;
	}

	$this->set_vars( $arr );
}

// --- class end ---
}


//=========================================================
// class rssc_xml_textinput
//=========================================================
class rssc_xml_textinput extends rssc_xml_basic
{

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function rssc_xml_textinput()
{
	$this->rssc_xml_basic();
}

//---------------------------------------------------------
// convert parse to local
//---------------------------------------------------------
function convert($to, $from)
{
	$arr =& $this->_convert_block( $this->get_vars(), $to, $from );
	$this->set_vars( $arr );
}

//---------------------------------------------------------
// sanitize
//---------------------------------------------------------
function sanitize()
{
	$arr = array();

	foreach ($this->get_vars() as $k => $v)
	{
		switch ($k)
		{
			case 'link':
				$val = $this->_sanitize_html_url($v);
				break;

			default:
				$val = $this->_sanitize_html_text($v);
				break;
		}

		$arr[$k] = $val;
	}

	if ( count($arr) > 0 )
	{
		$arr['show'] = 1;
	}

	$this->set_vars( $arr );
}

// --- class end ---
}


//=========================================================
// class rssc_xml_items
//=========================================================
class rssc_xml_items
{
	var $_item_objs = array();

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function rssc_xml_items()
{
	// dummy();
}

//---------------------------------------------------------
// set & get var
//---------------------------------------------------------
function set_vars($items)
{
	$this->_item_objs = array();
	foreach ($items as $v)
	{
		$item_obj =& new rssc_xml_item_single();
		$item_obj->set_vars( $v );
		$this->_item_objs[] =& $item_obj;
	}
}

function &get_vars()
{
	$arr = array();
	foreach ($this->_item_objs as $item_obj)
	{
		$arr[] = $item_obj->get_vars();
	}
	return $arr;
}

//---------------------------------------------------------
// cnvert
//---------------------------------------------------------
function convert($to, $from)
{
	foreach ($this->_item_objs as $i => $obj)
	{
		$this->_item_objs[$i]->convert($to, $from);
	}
}

//---------------------------------------------------------
// build for store
//---------------------------------------------------------
function build($site_title, $site_link, $control_obj)
{
	foreach ($this->_item_objs as $i => $obj)
	{
		$this->_item_objs[$i]->build($site_title, $site_link, $control_obj);
	}
}

//---------------------------------------------------------
// format
//---------------------------------------------------------
function format_from_parse()
{
	foreach ($this->_item_objs as $i => $obj)
	{
		$this->_item_objs[$i]->format_from_parse();
	}
}

function format_from_db()
{
	foreach ($this->_item_objs as $i => $obj)
	{
		$this->_item_objs[$i]->format_from_db();
	}
}

//---------------------------------------------------------
// for rssc_headline xoopsheadline
//---------------------------------------------------------
function format_for_rss( $format_date='l' )
{
	foreach ($this->_item_objs as $i => $obj)
	{
		$this->_item_objs[$i]->format_for_rss($format_date);
	}
}

//---------------------------------------------------------
// sanitize
//---------------------------------------------------------
function sanitize( &$param )
{
	foreach ($this->_item_objs as $i => $obj)
	{
		$this->_item_objs[$i]->sanitize( $param );
	}
}

// --- class end ---
}


//=========================================================
// class rssc_xml_item_single
//=========================================================
class rssc_xml_item_single extends rssc_xml_basic
{
	// RSS
	var $DATE_RFC822_LIST = array('pubdate'); 

	var $DATE_W3C_LIST = array(
	// ATOM 1.0
		'published', 'updated',
	// ATOM 0.3
		'modified', 'issued', 'created'
	);

	var $_highlight;

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function rssc_xml_item_single()
{
	$this->rssc_xml_basic();

	$this->_highlight =& happy_linux_highlight::getInstance();
	$this->_highlight->set_replace_callback( 'happy_linux_highlighter_by_class' );
	$this->_highlight->set_class( 'rssc_highlight' );
}

//---------------------------------------------------------
// convert from parse tolocal
//---------------------------------------------------------
function convert($to, $from)
{
	$arr = $this->_convert_block( $this->get_vars(), $to, $from );
	$this->set_vars( $arr );
}

//---------------------------------------------------------
// build for store
//---------------------------------------------------------
function build($site_title, $site_link, $control_obj)
{
	$this->set_control_obj( $control_obj );

	$item_orig = $this->get_vars();	// save original value
	list($enc_url, $enc_type, $enc_length) = $this->_build_enclosure();

	$arr = array(
		'site_title'     => $site_title,
		'site_link'      => $site_link,
		'title'          => $this->get('title'),
		'link'           => $this->_build_link(),
		'entry_id'       => $this->get('id'),
		'guid'           => $this->get('guid'),
		'category'       => $this->_build_category(),
		'author_name'    => $this->_build_author_name(),
		'author_email'   => $this->_build_author_email(),
		'author_uri'     => $this->_build_author_uri(),
		'published_unix' => $this->_build_published_unix(),
		'updated_unix'   => $this->_build_updated_unix(),
		'content'        => $this->_build_content(),
		'summary'        => $this->_build_summary_for_format(),
		'item_orig'      => $item_orig,

// enclosure
		'enclosure_url'    => $enc_url,
		'enclosure_type'   => $enc_type,
		'enclosure_length' => $enc_length,
	);

	$this->set_vars( $arr );

}

//-------------------------------------------------
// restrict feed_type
//-------------------------------------------------
// some feed have no link
// ex) http://radiozzz.com/Podcast/casty/rss.xml
//-------------------------------------------------
function _build_link()
{
	if ( $this->is_set('link') )
	{
		return $this->get('link');
	}
	elseif ( $this->is_rss() && $this->is_set('guid') )
	{
		return $this->get('guid');
	}
	elseif ( $this->is_rss() && $this->is_set('enclosure_url') )
	{
		return $this->get('enclosure_url');
	}
	return false;
}

function _build_category()
{
// ATOM, RSS
	if ( $this->is_set('category') )
	{
		return $this->get('category');
	}

// ATOM 0.3, RDF
	elseif ( $this->is_set('dc','subject') )
	{
		return $this->get('dc','subject');
	}

	return false;
}

function _build_author_name()
{
// ATOM
	if ( $this->is_set('author_name') )
	{
		return $this->get('author_name');
	}

// RSS, RDF
	elseif ( $this->is_set('dc','creator') )
	{
		return $this->get('dc','creator');
	}

	return false;
}

function _build_author_email()
{
// ATOM
	if ( $this->is_set('author_email') )
	{
		return $this->get('author_email');
	}

// RSS
	elseif ( $this->is_rss() && $this->is_set('author') )
	{
		return $this->get('author');
	}

	return false;
}

function _build_author_uri()
{
// ATOM
	if ( $this->is_set('author_uri') )
	{
		return $this->get('author_uri');
	}

// ATOM 0.3
	elseif ( $this->is_atom() && $this->is_set('author_url') )
	{
		return $this->get('author_url');
	}

	return false;
}

function _build_content()
{
	$val = false;

// ATOM content
	if ( $this->is_atom() && $this->is_set('atom_content') && $this->get('atom_content') )
	{
		$val = $this->get('atom_content');
	}

// RSS, RDF content
	elseif ( $this->is_rss() && $this->is_set('content','encoded') )
	{
		$val = $this->get('content','encoded');
	}

// ATOM content
	elseif ( $this->is_atom() && $this->is_set('content') && $this->get('content') )
	{
		$val = $this->get('content');
	}

// ATOM summary
	elseif ( $this->is_atom() && $this->is_set('summary') )
	{
		$val = $this->get('summary');
	}

// RSS, RDF summary
	elseif ( $this->is_rss() && $this->is_set('description') )
	{
		$val = $this->get('description');
	}
	elseif ( $this->is_set('dc','description') )
	{
		$val = $this->get('dc','description');
	}

	return $val;
}

function _build_published_unix()
{
	$unixtime = 0;

// ATOM
	if ( $this->is_set('published') )
	{
		$unixtime = $this->get_unixtime_w3cdtf( $this->get('published') );
	}

// ATOM 0.3
	elseif ( $this->is_atom() && $this->is_set('issued') )
	{
		$unixtime = $this->get_unixtime_w3cdtf( $this->get('issued') );
	}

// RSS
	elseif ( $this->is_rss() && $this->is_set('pubdate') )
	{
		$unixtime = $this->get_unixtime_rfc822( $this->get('pubdate') );
	}

// RDF
	elseif ( $this->is_set('dc','date') )
	{
		$unixtime = $this->get_unixtime_w3cdtf( $this->get('dc','date') );
	}

	return $unixtime;
}

function _build_updated_unix()
{
	$unixtime = 0;

// ATOM
	if ( $this->is_set('updated') )
	{
		$unixtime = $this->get_unixtime_w3cdtf( $this->get('updated') );
	}

// ATOM 0.3
	elseif ( $this->is_atom() && $this->is_set('modified') )
	{
		$unixtime = $this->get_unixtime_w3cdtf( $this->get('modified') );
	}

// RSS
	elseif ( $this->is_rss() && $this->is_set('pubdate') )
	{
		$unixtime = $this->get_unixtime_rfc822( $this->get('pubdate') );
	}

// RDF
	elseif ( $this->is_set('dc','date') )
	{
		$unixtime = $this->get_unixtime_w3cdtf( $this->get('dc','date') );
	}

	return $unixtime;
}

function _build_enclosure()
{
	$url    = null;
	$type   = null;
	$length = null;

// RSS
	if ( $this->is_rss() )
	{
		list($url, $type, $length) = $this->_get_enclosure_list();
	}

	return array($url, $type, $length);
}

// some RSS have twe or more enclosure tag
// set first one
function _get_enclosure_list()
{
	$url    = null;
	$type   = null;
	$length = null;

	if ( $this->is_set('enclosure') )
	{
		$enc = $this->get('enclosure');

		if ( isset($enc[0]['url']) )
		{
			$url = $enc[0]['url'];
		}
		if ( isset($enc[0]['type']) )
		{
			$type = $enc[0]['type'];
		}
		if ( isset($enc[0]['length']) )
		{
			$length = intval( $enc[0]['length'] );
		}
	}

	return array($url, $type, $length);
}

//-------------------------------------------------
// non restrict feed_type
// caller build, format_from_parse, format_from_db
//-------------------------------------------------
function _build_content_for_format()
{
	$val = false;

// ATOM content
	if ( $this->is_set('atom_content') && $this->get('atom_content') )
	{
		$val = $this->get('atom_content');
	}

// RSS, RDF content
	elseif ( $this->is_set('content','encoded') )
	{
		$val = $this->get('content','encoded');
	}

// ATOM content
	elseif ( $this->is_set('content') && $this->get('content') )
	{
		$val = $this->get('content');
	}

// ATOM summary
	elseif ( $this->is_set('summary') )
	{
		$val = $this->get('summary');
	}

// RSS, RDF summary
	elseif ( $this->is_set('description') )
	{
		$val = $this->get('description');
	}
	elseif ( $this->is_set('dc','description') )
	{
		$val = $this->get('dc','description');
	}

	return $val;
}

function _build_summary_for_format()
{
	$val = '';

// ATOM summary
	if ( $this->is_set('summary') )
	{
		$val = $this->get('summary');
	}

// RSS, RDF summary
	elseif ( $this->is_set('description') )
	{
		$val = $this->get('description');
	}

	elseif ( $this->is_set('dc', 'description') )
	{
		$val = $this->get('dc', 'description');
	}

// RSS, RDF content
	elseif ( $this->is_set('content', 'encoded') )
	{
		$val = $this->get('content', 'encoded');
	}

// ATOM content
	elseif ( $this->is_set('content') && $this->get('content') )
	{
		$val = $this->get('content');
	}

	$val = $this->_strings->strip_tags_for_text( $val );

	return $val;
}

//---------------------------------------------------------
// view format
//---------------------------------------------------------
function format_from_parse()
{
	$this->set('site_title', $this->_substitute_title('site_title') );
	$this->set('title'     , $this->_substitute_title('title') );
	$this->set('content',    $this->_build_content_for_format() );
	$this->set('summary',    $this->_build_summary_for_format() );
	$this->_format_enclosure();

// RFC882
	foreach ($this->DATE_RFC822_LIST as $key)
	{
		if ( $this->get($key) )
		{
			$time_unix = $this->get_unixtime_rfc822( $this->get($key) );
			$this->_set_unixtime($key, $time_unix);
		}
	}

// W3C format
	foreach ($this->DATE_W3C_LIST as $key)
	{
		if ( $this->get($key) )
		{
			$time_unix = $this->get_unixtime_w3cdtf( $this->get($key) );
			$this->_set_unixtime($key, $time_unix);
		}
	}

// dc:date
	if ( $this->is_set('dc','date') )
	{
		$time_unix = $this->get_unixtime_w3cdtf( $this->get('dc','date') );
		$this->_set_unixtime($key, $time_unix);
	}

// updated_long
	if ( !$this->is_set('updated_long') )
	{
		$time_unix = $this->_build_updated_unix();
		$this->_set_unixtime('updated', $time_unix);
	}

}

function format_from_db()
{
	$this->set('site_title', $this->_substitute_title('site_title') );
	$this->set('title'     , $this->_substitute_title('title') );
	$this->set('content',    $this->_build_content_for_format() );
	$this->set('summary',    $this->_build_summary_for_format() );
	$this->_format_guid_url();
	$this->_set_unixtime('updated',   $this->get('updated_unix') );
	$this->_set_unixtime('published', $this->get('published_unix') );
}

// some feed have non URL formated guid
// http://news.google.com/news?ned=us&output=rss
// tag:news.google.com,2005:cluster=421c2ca3
function _format_guid_url()
{
	$val = $this->get('guid');
	$val = $this->_strings->allow_http($val);
	$val = $this->_strings->deny_http_only($val);
	$this->set('guid_url', $val );
}

function _format_enclosure()
{
	list($enc_url, $enc_type, $enc_length) = $this->_get_enclosure_list();
	$this->set('enclosure_url',    $enc_url);
	$this->set('enclosure_type',   $enc_type);
	$this->set('enclosure_length', $enc_length);
}

//---------------------------------------------------------
// for rssc_headline xoopsheadline
// $format_date: l=long, r=rfc822
//---------------------------------------------------------
function format_for_rss( $format_date='l' )
{
	if ( $this->is_set('pubdate')  )
	{
		if ( $format_date == 'l' )
		{
			$pubdate_unix = $this->get_unixtime_rfc822( $this->get('pubdate') );
			$pubdate_long = formatTimestamp( $pubdate, 'l' );
			$this->set('pubdate', $pubdate_long );
		}
	}
	elseif ( $this->is_set('published_unix') )
	{
		$published_unix = $this->get('published_unix');
	
		if ( $format_date == 'l' )
		{
			$published_long = formatTimestamp( $published_unix, 'l' );
			$this->set('pubdate', $published_long );
		}
		else
		{
			$published_rfc822 = date( "r", $published_unix );
			$this->set('pubdate', $published_rfc822 );
		}
	}

	if ( !$this->is_set('description') && $this->is_set('content') )
	{
		$this->set('description', $this->get('content') );
	}
}

//---------------------------------------------------------
// view sanitize
//---------------------------------------------------------
function sanitize( &$param )
{
	$flag_title_html   = $param['flag_title_html'];
	$max_title         = $param['max_title'];
	$flag_content_html = $param['flag_content_html'];
	$max_content       = $param['max_content'];
	$max_summary       = $param['max_summary'];
	$keyword_array     = $param['keyword_array'];
	$flag_highlight    = $param['flag_highlight'];

	$arr = array();

	foreach ($this->get_vars() as $k => $v)
	{
		switch ($k)
		{
			case 'link':
			case 'author_uri':
			case 'author_url':
			case 'contributor_uri':
			case 'contributor_url':
			case 'enclosure_url':
			case 'guid_url':
				$val = $this->_sanitize_html_url($v);
				break;

			case 'title':
				$val = $this->_sanitize_allow_html( $v, $flag_title_html, $max_title );
				break;

			case 'content':
				$v1 = $v;
				if ( is_array($v) && isset($v['encoded']) )
				{
					$v1 = $v['encoded'];
				}
				$val = $this->_sanitize_allow_html( $v1, $flag_content_html, $max_content );
				if ($flag_highlight)
				{
					$val = $this->_highlight->build_highlight_keyword_array($val, $keyword_array);
				}
				break;

			case 'summary':
				$val = $this->_sanitize_summary($v, $max_summary, $keyword_array);
				if ($flag_highlight)
				{
					$val = $this->_highlight->build_highlight_keyword_array($val, $keyword_array);
				}
				break;

			case 'raws':
			case 'item_orig':
				$val = '';
				break;

			default:
//			echo "$k |$v| <br>\n";
				$val = $this->_sanitize_block($v);
				break;
		}

		$arr[$k] = $val;
	}

	$this->set_vars( $arr );
}

// --- class end ---
}

// === class end ===
}

?>