<?php
/**
 *  Secioss_AuthManager.php
 *
 *  @author     {$author}
 *  @package    Secioss
 *  @version    $Id: skel.app_manager.php,v 1.2 2006/11/06 14:31:24 cocoitiban Exp $
 */
require_once 'Lism_AppManager.php';
require_once 'Secioss_User.php';
require_once 'Secioss_Category.php';
require_once 'Secioss_Unit.php';
require_once 'Secioss_Area.php';

define("PWD_LEN", 8);

/**
 *  Secioss_AuthManager
 *
 *  @author     {$author}
 *  @access     public
 *  @package    Secioss
 */
class Secioss_AuthManager extends Lism_AppManager
{
    /**
     * ファイルのダウンロード
     *
     * クライアントにファイルのダウンロードダイアログを表示させる。
     * @param string        ファイル名
     * @return boolen
     */
    function downloadFile($file) {
        if (!file_exists($file)) {
            return false;
        }

        header("Content-Disposition: attachment; filename=\"".basename($file)."\"");
        header("Content-Length: ".filesize($file));
        header("Content-Type: application/octet-stream");

        if (!readfile($file)) {
            return false;
        }

        return TRUE;
    }

    /**
     *  属性の一覧を返す
     *
     *  @access public
     *  @param  string  $attr_name  属性の名前(変数名)
     *  @return array   属性値一覧
     */
    function getAttrList($attr_name)
    {
        $conf = $this->config->get('secioss');

        $list = array();
        if ($attr_name == 'group' || $attr_name == 'category'  || preg_match('/^unit_.*$/', $attr_name)) {
            if (preg_match('/^(unit)_(.*)$/', $attr_name, $matches)) {
                $attr_name = $matches[1];
                $object = $matches[2];
            }

            if (!isset($conf[$attr_name])) {
                return $list;
            }

            $filter = array($conf[$attr_name]['id'] => '*');
            if (isset($conf['system'])) {
                $filter['system'] = 'master';
            }

            $r = $this->getObjectPropList($attr_name, null, $filter);
            if (Ethna::isError($r)) {
                return $r;
            }

            for ($i = 0; $i < $r[0]; $i++) {
                $dn = $r[1][$i]['id'];
                if ($attr_name == 'unit') {
                    $dn = $conf[$object]['objectdn'].','.$dn;
                }
                $list[$dn] =  $this->getAttrName($attr_name, $r[1][$i]['id']);
            }
            return $list;
        } else if ($attr_name == 'system' || $attr_name == 'cluster') {
            if (!isset($conf['system'])) {
                return $list;
            }

            $clusters = $this->readCluster('cluster');
            if (Ethna::isError($clusters)) {
                return $clusters;
            }

            if ($attr_name == 'system') {
                $list['Master'] = 'マスタ';
            }
            foreach ($clusters as $cluster) {
                if ($cluster) {
                    $list[$cluster] = $cluster;
                }
            }

            return $list;
        } else {
            if (!isset($conf[$attr_name])) {
                return $list;
            }

            $filter = array($conf[$attr_name]['id'] => '*');
            if (isset($conf['system'])) {
                $filter['system'] = 'master';
            }
            $r = $this->getObjectPropList($attr_name, null, $filter);
            if (Ethna::isError($r)) {
                return $r;
            }

            $idattr = $conf['area']['id'];
            for ($i = 0; $i < $r[0]; $i++) {
                $list[$r[1][$i][$idattr]] =  $r[1][$i][$idattr];
            }
            return $list;
        }

        return parent::getAttrList($attr_name);
    }

    /**
     *  属性の表示名を返す
     *
     *  @access public
     *  @param  string  $attr_name  属性の名前(変数名)
     *  @param  mixed   $id         属性ID
     *  @return string  属性の表示名
     */
    function getAttrName($attr_name, $id)
    {
        $conf = $this->config->get('secioss');

        if ($attr_name == 'unit' || $attr_name == 'category' || $attr_name == 'group') {
            $basedn = isset($conf['system']) ? 'ou=[^,]+,'.$conf['basedn'] : $conf['basedn'];
            $objectdn = $conf['user']['objectdn'];
            if (isset($conf['group']) && isset($conf['group']['objectdn'])) {
                $objectdn = "($objectdn|".$conf['group']['objectdn'].")";
            }
            $id = preg_replace("/$objectdn,/i", '', $id);
            preg_match_all('/[^,=]+=([^,=]+),/', preg_replace("/$basedn$/i", '', $id), $matches);

            return join('/', array_reverse($matches[1]));
        }

        return parent::getAttrName($attr_name, $id);
    }

    /**
     * ランダムパスワードの取得
     *
     * 標準で使用が許可されている文字を使用した最大文字数のパスワードを取得する。
     * @access public
     * @return string
     */
    function random () {
        $passwd_chars = array();
        $token = array(array(), array(), array());

        foreach(range('a','z') as $value){
            if($value == 'l') continue;
            array_push($token[1], $value);
        }
        foreach(range('A','Z') as $value){
            if($value == "O" || $value == "I") continue;
            array_push($token[2], $value);
        }
        foreach(range('2','9') as $value){
            array_push($token[0], $value);
        }

        mt_srand();
        for ($i = 0; $i < 3; $i++) {
            for ($j = 0; $j < ceil(PWD_LEN/3) && count($passwd_chars) < PWD_LEN; $j++) {
                 $passwd_chars[] = $token[$i][mt_rand(0, count($token[$i]) - 1)];
            }
        }

        shuffle($passwd_chars);

        return implode('', $passwd_chars);
    }

    /**
     * lismsync readコマンドを実行
     * added by okazaki 20090316
     * @param string,string　システム名、フィルター
     * @return
     */
     function readSync($datas = null, $syncfilter = null, $base = null){
        $SYNCATTR = 'lismSyncStatus';
        $NODEATTR = 'lismSyncErrNode';
        $FILTERATTR = 'lismSyncFilter';
        $BASEATTR = 'lismSyncBase';
        $OPTATTR = 'lismCmdOption';

        $conf = $this->config->get('ldap');
        $secioss = $this->config->get('secioss');
        $filter = '';

        if(is_array($datas)){
            foreach($datas as $data){
                $filter = $filter ? "(&$filter($NODEATTR=$data))" : $filter = "($NODEATTR=$data)";
            }
        }
        if($syncfilter){
            $syncfilter = preg_replace(array("/\(/","/\)/"), array('\\\28','\\\29'), $syncfilter);
            $filter = $filter ? "(&$filter($FILTERATTR=$syncfilter))" : "($FILTERATTR=$syncfilter)";
        }
        if($base){
            $base = "$base,".$secioss['basedn'];
            $filter = $filter ? "(&$filter($BASEATTR=$base))" : "($BASEATTR=$base)";
        }

        if(!$filter){
            $filter = "(objectClass=*)";
        }

        if (isset($secioss['suffix'])) {
            $suffix = $secioss['suffix'];
        } else {
            $suffix = $secioss['basedn'];
        }

        $dn = 'cn=sync,'.$suffix;
        $ldap = ldap_connect($conf['uri']);
        if(!$ldap){
            return Ethna::raiseError("Could not connect to LDAP server.", E_DB_CONNECT);
        }
        $lr = ldap_read($ldap, $dn, $filter);
        $entry = ldap_first_entry($ldap, $lr);
        $attrs = ldap_get_attributes($ldap, $entry);

        return $attrs;

     }

    /**
     * lismsync updateコマンドを実行
     * added by okazaki 20090326
     * @param string,string  システム名、フィルター
     * @return boolean
     */
     function updateSync($datas = null, $filter = null, $base = null){
        $lism = $this->config->get('lism');
        $secioss = $this->config->get('secioss');
        $cmd;
        $out = array();
        $dopt = '';
        $fopt = '';
        $bopt = '';

        if($datas) $dopt = ' -d "'.$datas.'"';
        if($filter){
            $fopt = ' -f "'.$filter.'"';
        }
        if($base) $bopt = " -b ou=$base,".$secioss['basedn'];
        $cmd = LISMSYNC.$dopt.$fopt.$bopt." update all";
        exec($cmd, $out, $rc);

        return $rc;
    }

    function readCluster($type) {
        $MASTERATTR = 'lismClusterMaster';
        $ACTIVEATTR = 'lismClusterActive';

        $conf = $this->config->get('secioss');
        $ldapconf = $this->config->get('ldap');

        $ldap = ldap_connect($ldapconf['uri']);
        if(!$ldap){
            return Ethna::raiseError("Could not connect to LDAP server.", E_DB_CONNECT);
        }

        if (isset($conf['suffix'])) {
            $suffix = $conf['suffix'];
        } else {
            $suffix = $conf['basedn'];
        }
        if (!($lr = ldap_read($ldap, 'cn=cluster,'.$suffix, '(objectClass=*)'))) {
            return Ethna::raiseError("Could not get cluster information.", E_DB_CONNECT);
        }

        $entry = ldap_first_entry($ldap, $lr);
        $attrs = ldap_get_attributes($ldap, $entry);
        $master = isset($attrs[$MASTERATTR]) ? $attrs[$MASTERATTR][0] : '';

        if ($type == 'master') {
            return $master;
        } else if ($type == 'cluster') {
            $vals = array();
            if (isset($attrs[$ACTIVEATTR])) {
                for ($i = 0; $i < $attrs[$ACTIVEATTR]['count']; $i++) {
                    $vals[] = $attrs[$ACTIVEATTR][$i];
                }
            }
            return $vals;
        }

        return null;
    }
}
?>
