<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * FedoraClient is a PHP class to interact with web services
 *
 * PHP version 5
 *
 * Copyright (C) 2010  Remi Collet
 * http://github.com/remicollet/rpmphp.
 *
 * Inspired from python-fedora
 *
 * FedoraClient 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 2.1 of the License, or (at your option) any later version.
 *
 * FedoraClient 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.
 *
 * See <http://www.gnu.org/licenses/>
 *
 * @category  Main
 * @package   FedoraClient
 *
 * @author    Remi Collet <unknown@unknwown.com>
 * @author    Johan Cwiklinski <johan@x-tnd.be>
 * @copyright 2010 Remi Collet
 * @license   http://www.gnu.org/licenses/lgpl-2.1.txt LGPL License 2.1 or (at your option) any later version
 * @link      http://github.com/remicollet/rpmphp/
 * @since     The begining of times.
 */

if (!function_exists('curl_version')) {
    die("curl extension required\n");
}
require_once 'Cache/Lite.php';

abstract class FedoraClient
{
    const VERSION='0.2.0-dev';
    protected $url;
    private $_agent;
    private $_debug = 0;
    protected $cache;

    function __construct ($url, array $options)
    {
        $dir = "/tmp/cachelite-".posix_getlogin()."/";
        @mkdir($dir);
        $this->cache = new Cache_Lite(
            array(
                'memoryCaching'             => true,
                'cacheDir'                  => $dir,
                'automaticSerialization'    => true
            )
        );

        if (isset($options['debug']) && intval($options['debug'])>0) {
            $this->_debug = intval($options['debug']);
        }

        $this->setUrl($url);

        if (isset($options['agent']) && !empty($options['agent'])) {
            $this->_agent = $options['agent'];
        } else {
            $this->_agent = 'Fedora PHPClient/'.self::VERSION;
        }

        $this->logDebug(
            3,
            __CLASS__."::".__FUNCTION__.": agent='".$this->_agent."'"
        );
    }

    function setUrl($url)
    {
        $this->url = $url;
        $this->logDebug(
            3,
            __CLASS__."::".__FUNCTION__.": url='$url'"
        );
    }

    function logDebug($level, $msg)
    {
        if ($this->_debug>=$level) {
            echo "[debug][$level] $msg\n";
        }
    }

    function sendRequest($method, array $options=array())
    {
        $curl = curl_init();
        // And join to make our url.
        $url = $this->url.$method;
        curl_setopt($curl, CURLOPT_URL, $url);
        // Boilerplate so pycurl processes cookies
        curl_setopt($curl, CURLOPT_COOKIEFILE, '/dev/null');

        //# Associate with the response to accumulate data
        $this->data='';
        curl_setopt($curl, CURLOPT_WRITEFUNCTION, array($this, 'receive'));

        // Follow redirect
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($curl, CURLOPT_MAXREDIRS, 5);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

        // Set standard headers
        curl_setopt(
            $curl,
            CURLOPT_HTTPHEADER,
            array('User-agent: '.$this->_agent, 'Accept: application/json')
        );

        // run the request
        $this->logDebug(
            2,
            __CLASS__."::".__FUNCTION__.": call '$url'"
        );
        curl_exec($curl);


        // Check for auth failures
        // Note: old TG apps returned 403 Forbidden on authentication failures.
        // Updated apps return 401 Unauthorized
        // We need to accept both until all apps are updated to return 401.
        $http_status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        if ($http_status==401 || $http_status==403) {
            $this->logDebug(
                1,
                __CLASS__."::".__FUNCTION__.
                ": http_status '$http_status' Authentication failed logging in"
            );
            return array();
        } else if ($http_status>=400) {
            $this->logDebug(
                1,
                __CLASS__."::".__FUNCTION__.
                ": http_status '$http_status' Unknown HTTP Server Response"
            );
            return array();
        } else {
            $this->logDebug(
                2,
                __CLASS__."::".__FUNCTION__.": http_status '$http_status'"
            );
        }

        $this->logDebug(
            2,
            __CLASS__."::".__FUNCTION__.": close connexion"
        );

        curl_close($curl);
        return json_decode($this->data, true);
    }

    function receive($curl, $data)
    {
        $this->logDebug(
            9,
            __CLASS__."::".__FUNCTION__.": $data"
        );
        $this->data .= $data;
        return strlen($data);
    }
}