<?php
/**
 * @package JAdmin!
 * @version 1.5.3.0
 * @copyright (C) Copyright 2008-2010 CMS Fruit, CMSFruit.com. All rights reserved.
 * @license GNU/LGPL http://www.gnu.org/licenses/lgpl-3.0.txt

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; either version 3 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 Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public License
 along with this program.  If not, see http://www.gnu.org/licenses/.
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );

class JAdminModelSimpleXML
{
    var $result = array();
    var $ignore_level = 0;
    var $skip_empty_values = false;
    var $php_errormsg;
    var $evalCode = '';
    
    /**
     * Adds Items to Array
     *
     * @param int $level
     * @param array $tags
     * @param $value
     * @param string $type
     */
    function array_insert($level, $tags, $value, $type)
    {
        $temp = '';
        for ($c = $this->ignore_level + 1; $c < $level + 1; $c++)
        {
            if (isset($tags[$c]) && (is_numeric(trim($tags[$c])) || trim($tags[$c])))
            {
                if (is_numeric($tags[$c]))
                {
                    $temp .= '[' . $tags[$c] . ']';
                } else
                {
                    $temp .= '["' . $tags[$c] . '"]';
                }
            }
        }
        $this->evalCode .= '$this->result' . $temp . "=\"" . addslashes($value) . "\";//(" . $type . ")\n";
    #echo $code. "\n";
    }

    /**
     * Define the repeated tags in XML file so we can set an index
     *
     * @param array $array
     * @return array
     */
    function xml_tags($array)
    {
        $repeats_temp = array();
        $repeats_count = array();
        $repeats = array();

        if (is_array($array))
        {
            $n = count($array) - 1;
            for ($i = 0; $i < $n; $i++)
            {
                $idn = $array[$i]['tag'].$array[$i]['level'];
                if(in_array($idn,$repeats_temp))
                {
                    $repeats_count[array_search($idn,$repeats_temp)]+=1;
                }else
                {
                    array_push($repeats_temp,$idn);
                    $repeats_count[array_search($idn,$repeats_temp)]=1;
                }
            }
        }
        $n = count($repeats_count);
        for($i=0;$i<$n;$i++)
        {
            if($repeats_count[$i]>1)
            {
                array_push($repeats,$repeats_temp[$i]);
            }
        }
        unset($repeats_temp);
        unset($repeats_count);
        return array_unique($repeats);
    }


    /**
     * Converts Array Variable to Object Variable
     *
     * @param array $arg_array
     * @return $tmp
     */
    function array2object ($arg_array)
    {
        if (is_array($arg_array))
        {
            $keys = array_keys($arg_array);
            if(!is_numeric($keys[0])) $tmp = new SimpleXMLObject;
            foreach ($keys as $key)
            {
                if (is_numeric($key)) $has_number = true;
                if (is_string($key)) $has_string = true;
            }
            if (isset($has_number) and !isset($has_string))
            {
                foreach ($arg_array as $key => $value)
                {
                    $tmp[] = $this->array2object($value);
                }
            } elseif (isset($has_string))
            {
                foreach ($arg_array as $key => $value)
                {
                    if (is_string($key))
                        $tmp->$key = $this->array2object($value);
                }
            }
        } elseif (is_object($arg_array))
        {
            foreach ($arg_array as $key => $value)
            {
                if (is_array($value) or is_object($value))
                    $tmp->$key = $this->array2object($value);
                else
                    $tmp->$key = $value;
            }
        } else
        {
            $tmp = $arg_array;
        }
        return $tmp; //return the object
    }

    /**
     * Reindexes the whole array with ascending numbers
     *
     * @param array $array
     * @return array
     */
    function array_reindex($array)
    {
        if (is_array($array))
        {
            if(count($array) == 1 && $array[0])
            {
                return $this->array_reindex($array[0]);
            }else
            {
                foreach($array as $keys => $items)
                {
                    if (is_array($items))
                    {
                        if (is_numeric($keys))
                        {
                            $array[$keys] = $this->array_reindex($items);
                        } else
                        {
                            $array[$keys] = $this->array_reindex(array_merge(array(), $items));
                        }
                    }
                }
            }
        }

        return $array;
    }


    /**
     * Parse the XML generation to array object
     *
     * @param array $array
     * @return array
     */
    function xml_reorganize($array)
    {
        $count = count($array);
        $repeat = $this->xml_tags($array);
        $repeatedone = false;
        $tags = array();
        $k = 0;
        for ($i = 0; $i < $count; $i++)
        {
            switch ($array[$i]['type'])
            {
                case 'open':
                    array_push($tags, $array[$i]['tag']);
                    if ($i > 0 && ($array[$i]['tag'] == $array[$i-1]['tag']) && ($array[$i-1]['type'] == 'close'))
                        $k++;
                    if (isset($array[$i]['value']) && ($array[$i]['value'] || !$this->skip_empty_values))
                    {
                        array_push($tags, '@content');
                        $this->array_insert(count($tags), $tags, $array[$i]['value'], "open");
                        array_pop($tags);
                    }

                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat))
                    {
                        if (($repeatedone == $array[$i]['tag'] . $array[$i]['level']) && ($repeatedone))
                        {
                            array_push($tags, strval($k++));
                        } else
                        {
                            $repeatedone = $array[$i]['tag'] . $array[$i]['level'];
                            array_push($tags, strval($k));
                        }
                    }

                    if (isset($array[$i]['attributes']) && $array[$i]['attributes'] && $array[$i]['level'] != $this->ignore_level)
                    {
                        array_push($tags, '@attributes');
                        foreach ($array[$i]['attributes'] as $attrkey => $attr)
                        {
                            array_push($tags, $attrkey);
                            $this->array_insert(count($tags), $tags, $attr, "open");
                            array_pop($tags);
                        }
                        array_pop($tags);
                    }
                    break;

                case 'close':
                    array_pop($tags);
                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat))
                    {
                        if ($repeatedone == $array[$i]['tag'] . $array[$i]['level'])
                        {
                            array_pop($tags);
                        } else
                        {
                            $repeatedone = $array[$i + 1]['tag'] . $array[$i + 1]['level'];
                            array_pop($tags);
                        }
                    }
                    break;

                case 'complete':
                    array_push($tags, $array[$i]['tag']);
                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat))
                    {
                        if ($repeatedone == $array[$i]['tag'] . $array[$i]['level'] && $repeatedone)
                        {
                            array_push($tags, strval($k));
                        } else
                        {
                            $repeatedone = $array[$i]['tag'] . $array[$i]['level'];
                            array_push($tags, strval($k));
                        }
                    }

                    if (isset($array[$i]['value']) && ($array[$i]['value'] || !$this->skip_empty_values))
                    {
                        if (isset($array[$i]['attributes']) && $array[$i]['attributes'])
                        {
                            array_push($tags, '@content');
                            $this->array_insert(count($tags), $tags, $array[$i]['value'], "complete");
                            array_pop($tags);
                        } else
                        {
                            $this->array_insert(count($tags), $tags, $array[$i]['value'], "complete");
                        }
                    }

                    if (isset($array[$i]['attributes']) && $array[$i]['attributes'])
                    {
                        array_push($tags, '@attributes');
                        foreach ($array[$i]['attributes'] as $attrkey => $attr)
                        {
                            array_push($tags, $attrkey);
                            $this->array_insert(count($tags), $tags, $attr, "complete");
                            array_pop($tags);
                        }
                        array_pop($tags);
                    }

                    if (in_array($array[$i]['tag'] . $array[$i]['level'], $repeat))
                    {
                        array_pop($tags);
                        $k++;
                    }

                    array_pop($tags);
                    break;
            }
        }
        eval($this->evalCode);
        $last = $this->array_reindex($this->result);
        return $last;
    }

    /**
     * Get the XML contents and parse like SimpleXML
     *
     * @param string $file
     * @param string $resulttype
     * @param string $encoding
     * @return array/object
     */
    function xml_load_file($file, $resulttype = 'object', $encoding = 'UTF-8')
    {
        $php_errormsg="";
        $this->result="";
        $this->evalCode="";
        $values="";
	
	if(function_exists('curl_init'))
	{
	    $data = $this->url_get_contents($file);
	}
	elseif(ini_get('allow_url_fopen') == 1 || ini_get('allow_url_fopen') == 'On')
	{
	    $data = file_get_contents($file);
	}
	else
	{
	    $data = false;
	}

        if (!$data)
            return false;

        $parser = xml_parser_create($encoding);
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        $ok = xml_parse_into_struct($parser, $data, $values);
        if (!$ok)
        {
            $errmsg = sprintf("XML parse error %d '%s' at line %d, column %d (byte index %d)",
                xml_get_error_code($parser),
                xml_error_string(xml_get_error_code($parser)),
                xml_get_current_line_number($parser),
                xml_get_current_column_number($parser),
                xml_get_current_byte_index($parser));
        }

        xml_parser_free($parser);

        if (!$ok)
            return false;

        if ($resulttype == 'array')
            return $this->xml_reorganize($values);

        // default $resulttype is 'object'
        return $this->array2object($this->xml_reorganize($values));
    }

    function url_get_contents($url, $useragent='cURL', $headers=false,  $follow_redirects=false, $debug=false)
    {
	# initialise the CURL library
	$ch = curl_init();

	# specify the URL to be retrieved
	curl_setopt($ch, CURLOPT_URL,$url);

	# we want to get the contents of the URL and store it in a variable
	curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

	# specify the useragent: this is a required courtesy to site owners
	curl_setopt($ch, CURLOPT_USERAGENT, $useragent);

	# ignore SSL errors
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

	curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
	
	# return headers as requested
	if ($headers==true)
	{
	    curl_setopt($ch, CURLOPT_HEADER,1);
	}

	# only return headers
	if ($headers=='headers only')
	{
	    curl_setopt($ch, CURLOPT_NOBODY ,1);
	}

	# follow redirects - note this is disabled by default in most PHP installs from 4.4.4 up
	if ($follow_redirects==true)
	{
	    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	}

	require_once dirname(__FILE__).DS.'setting.php';

	$settings =& JModel::getInstance('Setting', 'JAdminModel');

	if($settings->getSetting('use_proxy') == 1)
	{
	    // Use proxy server
	    curl_setopt($ch, CURLOPT_PROXY, $settings->getSetting('proxy_uri'));

	    $proxyAuth = $settings->getSetting('proxy_auth');
	    
	    if($settings->getSetting('proxy_port') > 0) curl_setopt($ch, CURLOPT_PROXYPORT, $settings->getSetting('proxy_port'));
	    if(!empty($proxyAuth)) curl_setopt($ch, CURLOPT_PROXYUSERPWD, $settings->getSetting('proxy_auth'));
	    if($settings->getSetting('use_socks') > 0) curl_setopt($ch, CURLOPT_PROXYTYPE, 5);
	}

	# if debugging, return an array with CURL's debug info and the URL contents
	if ($debug==true)
	{
	    $result['contents']=curl_exec($ch);
	    $result['info']=curl_getinfo($ch);
	}

	# otherwise just return the contents as a variable
	else $result=curl_exec($ch);

	# free resources
	curl_close($ch);

	# send back the data
	return $result;
    }

}

if(!class_exists('SimpleXMLObject'))
{
    /**
     * If the result will be an object, this container class is used.
     *
     */

    class SimpleXMLObject
    {
	function attributes()
	{
	    $container = get_object_vars($this);
	    return (object) $container["@attributes"];
	}

	function content()
	{
	    $container = get_object_vars($this);
	    return (object) $container["@content"];
	}
    }
}