<?php   if(!defined('DEDEINC')) exit("Request Error!");
/**
 *
 *  本類用於指定一個 MySQL 的數據表
 *  自動生成列出、修改、刪除、增加等操作
 *
 *   2010-11-17 [修復]啟用request類默認數據處理問題
 *   2010-11-17 [修復]如果存在UNIQUE表字段分析錯誤的問題
 *   2010-11-17 [增加]增加檢索條件匹配方法
 *   2010-11-16 [增加]如果表字段存在註釋,則列表項的title中則直接顯示註釋信息
 *   2010-11-14 [修復]數據表存在前綴,模板名稱解析問題,同時可以對Lurd單獨設定模板
 *
 *
 * @version        $Id: lurd.class.php 6 11:19 2010-11-26 IT柏拉圖,tianya $
 * @package        DedeCMS.Libraries
 * @copyright      Copyright (c) 2007 - 2010, DesDev, Inc.
 * @license        http://help.dedecms.com/usersguide/license.html
 * @link           http://www.dedecms.com
 */

require_once(DEDEINC.'/datalistcp.class.php');

/***********************************
 @ class lurd

***********************************/
class Lurd extends DataListCP
{
    // 固定屬性
    var $dateTypes = array('DATE', 'DATETIME', 'TIMESTAMP', 'TIME', 'YEAR');
    var $floatTypes = array('FLOAT', 'DOUBLE', 'DECIMAL');
    var $intTypes = array('TINYINT', 'SMALLINT', 'MEDIUMINT', 'INT', 'BIGINT');
    var $charTypes = array('VARCHAR', 'CHAR', 'TINYTEXT');
    var $textTypes = array('TEXT', 'MEDIUMTEXT', 'LONGTEXT');
    var $binTypes = array('TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB', 'BINARY', 'VARBINARY');
    var $emTypes = array('ENUM', 'SET');
    // 普通屬性
    var $tableName = '';
    var $templateDir = '';
    var $lurdTempdir = '';
    var $tplName = '';
    var $appName = '';
    var $primaryKey = '';
    var $autoField = '';
    var $orderQuery = '';
    // 所的字段及屬性數組
    var $fields = array(); 
    // 當這個值為TRUE，每次都會生成新模板，用於調試模式
    var $isDebug = FALSE;
    // 文本內容安全級別 
    // 0 為不處理， 1 為禁止不安全HTML內容(javascript等)，2完全禁止HTML內容，並替換部份不安全字符串（如：eval(、union、CONCAT(、--、等）
    var $stringSafe = 1;
    // 這個變量用於存放連結表的參數
    // 可以通過 $lurd->AddLinkTable($tablelurd, linkfields, mylinkid, linkid); 聯結一個表
    var $linkTables = array();
    // 聯結表的指定字段(如果後一個表的字段和前一個重名, 前者會被替換)
    var $addFields = array();
    // 查詢條件
    var $searchParameters = array();

    //構造函數，指定要操作的表名
    function __construct($tablename, $templatedir='', $lurdtempdir='')
    {
        global $dsql;
        $prefix = "#@__";
        $this->tplName = str_replace($prefix, '', $tablename);
        $this->tableName = str_replace($prefix, $dsql->dbPrefix, $tablename);
        $this->templateDir = $templatedir;
        $this->lurdTempdir = empty($lurdtempdir) ? $this->templateDir.'/lurd' : $lurdtempdir;
        parent::__construct();
        $this->AnalyseTable();
        if(!empty($GLOBALS['ct']))
        {
            $this->SetParameter('ct', $GLOBALS['ct']);
        }
        $this->SetParameter('ac', 'list');
    }
    
    //監聽器，根據指定的ac(ac)調用相應處理方法
    function ListenAll($listfield = '', $wherequery = '', $orderquery ='')
    {
        global $ac;
        if(empty($ac)) $ac = '';
        switch($ac)
        {
            case 'add' :
                $this->AddData();
                break;
            case 'edit':
                $this->EditData();
                break;
            case 'del':
                $this->DelData();
                break;
            case 'saveadd':
                $this->SaveAddData();
                break;
            case 'saveedit':
                $this->SaveEditData();
                break;
            default:
                $this->ListData($listfield, $wherequery, $orderquery);
                break;
        }
    }

    // 指定主鍵
    // 在數據表沒有主鍵的情況下，必須指定一個字段為主鍵字段，否則系統用所有數據的md5值作為主鍵
    function AddPriKey($fieldname)
    {
        $this->primaryKey = $fieldname;
    }
    
    // 指定應用的名稱
    function AddAppName($appname)
    {
        $this->appName = $appname;
    }
    
    //設置用於排序的SQL，如 order by id desc
    function SetOrderQuery($query)
    {
        $this->orderQuery = $query;
    }
    
    //強制指定字段為其它類型
    function BindType($fieldname, $ftype, $format='')
    {
        //'type' =>'','length' =>'0','unsigned'=>FALSE,'autokey'=>FALSE,
        //'null'=>FALSE,default'=>'','em'=>'','format'=>'','listtemplate'=>'','edittemplate'=>''
        $typesArr = array_merge($this->dateTypes, $this->floatTypes, $this->intTypes, $this->charTypes, $this->textTypes, $this->binTypes, $this->emTypes);
        if( isset($this->fields[$fieldname]) && in_array(strtoupper($ftype), $typesArr) )
        {
            $this->fields[$fieldname]['type'] = $ftype;
            $this->fields[$fieldname]['format'] = $format;
        }
    }
    
    //強制指定字模板（列表list和編輯edit、增加add模板裡用）
    function BindTemplate($fieldname, $tmptype='list', $temp='')
    {
        if( isset($this->fields[$fieldname]) )
        {
            $this->fields[$fieldname][$tmptype.'template'] = $temp;
        }
    }
    
    // 列出數據
    /*********************************
     * $listfield = '' 指定要列出的字段(默認為'*') ，只需填寫當前表
                                                  聯結表出的字段在 AddLinkTable 指定， 因此不需要 表名.字段名 方式識別
     * $wherequery = '' 查詢query，如果聯結了其它表，需用 表名.字段名 識別字段
     * $orderquery = '' 排序query，如果聯結了其它表，需用 表名.字段名 識別字段
     **********************************/
    function ListData($listfield = '*', $wherequery = '', $orderquery ='', $Suff = '_list.htm')
    {
        $listdd = '';
        if(trim($listfield)=='') $listfield = '*';
        
        $template = $this->templateDir.'/'.$this->tplName.$Suff;
        //生成列表模板
        if( !file_exists($template) || $this->isDebug )
        {
            $this->MakeListTemplate($listfield);
        }
        
        // 獲取檢索條件
        if( $wherequery == '' )
        {
            $wherequery = $this->GetSearchQuery();
        }

        //是否有聯結其它的表
        $islink = count($this->linkTables) > 0 ? TRUE : FALSE;
        //主表索引字段(Select * From 部份)
        $listfields = explode(',', $listfield);
        foreach($listfields as $v)
        {
                $v = trim($v);
                if( !isset($this->fields[$v]) && $v != '*' ) continue;
                if($islink) {
                    $listdd .= ($listdd=='' ? "{$this->tableName}.{$v}" : ", {$this->tableName}.{$v} ");
                }
                else {
                    if($v=='*') $listdd .= ' * ';
                    else $listdd .= ($listdd=='' ? "`$v`" : ",`$v`");
                }
        }
        if($listdd=='') $listdd = " * ";
        
        //聯結表索引字段
        if($islink)
        {
            $joinQuery = '';
            foreach($this->linkTables as $k=>$linkTable)
            {
                $k++;
                $linkTableName = $linkTable[0]->tableName;
                $joinQuery .= " LEFT JOIN `{$linkTableName}` ON {$linkTableName}.{$linkTable[2]} = {$this->tableName}.{$linkTable[1]} ";
                foreach($this->addFields as $f=>$v)
                {
                    if($v['table'] != $linkTableName) continue;
                    $listdd .= ", {$linkTableName}.{$f} ";
                }
            }
            $query = "SELECT $listdd FROM `{$this->tableName}` $joinQuery $wherequery $orderquery ";
        }
        else
        {
            $query = "SELECT $listdd FROM `{$this->tableName}` $wherequery $orderquery ";
        }
        
        $this->SaveCurUrl();
        $this->SetTemplate($template);
        $this->SetSource($query);
        $this->Display();
    }
    
    //記錄列表網址到cookie，方便返回時調用
    function SaveCurUrl()
    {
        setcookie('LURD_GOBACK_URL', $this->GetCurFullUrl(), time()+3600, '/');
    }
    
    function GetCurFullUrl()
    {
        if(!empty($_SERVER["REQUEST_URI"]))
        {
            $scriptName = $_SERVER["REQUEST_URI"];
            $nowurl = $scriptName;
        }
        else
        {
            $scriptName = $_SERVER["PHP_SELF"];
            $nowurl = empty($_SERVER["QUERY_STRING"]) ? $scriptName : $scriptName."?".$_SERVER["QUERY_STRING"];
        }
        return $nowurl;
    }
    
    //生成全部模板
    function MakeAllTemplate($listfield = '')
    {
        $this->MakeListTemplate($listfield);
        $this->MakeAddEditTemplate('add');
        $this->MakeAddEditTemplate('edit');
    }
    
    //生成列表模板
    function MakeListTemplate($listfield = '')
    {
        $templateTemplate = $this->lurdTempdir.'/lurd-list.htm';
        $template = $this->templateDir.'/'.$this->tplName.'_list.htm';
        $tempstr = '';
        $fp = fopen($templateTemplate, 'r');
        while( !feof($fp) ) $tempstr .= fread($fp, 1024);
        fclose($fp);
        $tempItems = array('appname'=>'', 'totalitem'=>'', 'titleitem'=>'', 'fielditem'=>'');
        $tempItems['appname'] = empty($this->appName) ? "管理數據表： ".$this->tableName : $this->appName;
        //設置選擇項
        $tempItems['totalitem'] = 1;
        $titleitem = "    <td class='nowrap'>選擇</td>\r\n";
        if( !preg_match("/,/", $this->primaryKey) )
        {
                $fielditem = "    <td class='nowrap'><input type=\"checkbox\" name=\"{$this->primaryKey}[]\" value=\"{dede:field name='{$this->primaryKey}' /}\" /></td>\r\n";
        }
        else
        {
                $prikeys = explode(',', $this->primaryKey);
                $prikeyValue = '<'.'?php echo md5("key"';
                foreach($prikeys as $v)
                {
                    $prikeyValue .= '.$fields["'.$v.'"]';
                }
                $prikeyValue .= '); ?'.'>';
                $fielditem = "    <td class='nowrap'><input type=\"checkbox\" name=\"primarykey[]\" value=\"{$prikeyValue}\" /></td>\r\n";
        }
        //使用手工指定列出字段
        if(!empty($listfield) && $listfield != '*' )
        {
            $listfields = explode(',', $listfield);
            $tempItems['totalitem'] = count($listfields) + 1;
            foreach($listfields as $k)
            {
                $k = trim($k);
                if( !isset($this->fields[$k]) ) continue;
                $v = $this->fields[$k];
                $title = isset($v['comment'])? $v['comment'] : $k;
                $titleitem .= "    <td class='nowrap'>$title</td>\r\n";
                if( !empty($v['listtemplate']) )
                {
                    $fielditem .= "    <td class='nowrap'>{$v['listtemplate']}</td>\r\n";
                }
                else
                {
                    $dofunc = $dtype = $fformat = '';
                    $dtype = !empty($v['type']) ? $v['type'] : 'check';
                    if(isset($v['format']))
                    {
                        $fformat = $v['format'];
                    }
                    if(isset($v['dofunc']))
                    {
                        $dofunc = $v['dofunc'];
                    }
                    if(isset($v['type']))
                    {
                        $this->fields[$k]['type'] = $v['type'];
                    }
                    if( in_array($v['type'], $this->floatTypes) ) 
                    {
                        $dtype = 'float';
                        $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatFloat(@me, '$fformat')\"" : '');
                    }
                    if( in_array($v['type'], $this->dateTypes) )
                    {
                        $dtype = 'date';
                        $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatDate(@me, '{$this->fields[$k]['type']}', '$fformat')\"" : '');
                    }
                    $fielditem .= "    <td class='nowrap'>{dede:field name='{$k}' $dofunc /}</td>\r\n";
                }
            }//End foreach
        }
        //自動處理
        else
        {
            foreach($this->fields as $k=>$v)
            {
                if(in_array($v['type'], $this->binTypes) )
                {
                    continue;
                }
                $tempItems['totalitem']++;
                $titleitem .= "    <td class='nowrap'>$k</td>\r\n";
                $dofunc = $dtype = $fformat = '';
                if(isset($v['format']))
                {
                        $fformat = $v['format'];
                }
                if( in_array($v['type'], $this->floatTypes) ) 
                {
                    $dtype = 'float';
                    $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatFloat(@me, '$fformat')\"" : '');
                }
                if( in_array($v['type'], $this->dateTypes) )
                {
                    $dtype = 'date';
                    $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatDate(@me, '{$this->fields[$k]['type']}', '$fformat')\"" : '');
                }
                $fielditem .= "    <td class='nowrap'>{dede:field name='{$k}' $dofunc /}</td>\r\n";
            }
        }
        //是否有聯結其它的表
        $islink = count($this->linkTables) > 0 ? TRUE : FALSE;
        //附加表的字段
        if($islink)
        {
            foreach($this->addFields as $k=>$v)
            {
                if(in_array($v['type'], $this->binTypes) )
                {
                    continue;
                }
                $tempItems['totalitem']++;
                $titleitem .= "    <td class='nowrap'>$k</td>\r\n";
                $dofunc = $dtype = $fformat = '';
                if( in_array($v['type'], $this->floatTypes) ) 
                {
                    $dtype = 'float';
                    $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatFloat(@me, '$fformat')\"" : '');
                }
                if( in_array($v['type'], $this->dateTypes) )
                {
                    $dtype = 'date';
                    $dofunc = ($dofunc=='' ? "function=\"Lurd::FormatDate(@me, '{$this->fields[$k]['type']}', '$fformat')\"" : '');
                }
                $fielditem .= "    <td class='nowrap'>{dede:field name='{$k}' $dofunc /}</td>\r\n";
            }
        }
        $tempItems['titleitem'] = $titleitem;
        $tempItems['fielditem'] = $fielditem;
        foreach($tempItems as $k => $v)
        {
            $tempstr = str_replace("~$k~", $v, $tempstr);
        }
        $fp = fopen($template, 'w');
        fwrite($fp, $tempstr);
        fclose($fp);
    }
    
    //生成發佈或編輯模板
    function MakeAddEditTemplate($getTemplets='add')
    {
        $templateTemplate = $this->lurdTempdir."/lurd-{$getTemplets}.htm";
        $template = $this->templateDir.'/'.$this->tplName."_{$getTemplets}.htm";
        $tempstr = '';
        $fp = fopen($templateTemplate, 'r');
        while( !feof($fp) ) $tempstr .= fread($fp, 1024);
        fclose($fp);
        $tempItems = array('appname'=>'', 'fields'=>'', 'primarykey'=>'');
        $tempItems['appname'] = empty($this->appName) ? "在 {$this->tableName} ".($getTemplets=='add' ? '添加數據' : '編輯數據' ) : $this->appName;
        $tempItems['fields'] = '';
        if( !preg_match("/,/", $this->primaryKey) )
        {
            $tempItems['primarykey'] = "    <input type=\"hidden\" name=\"{$this->primaryKey}\" value=\"{dede:field name='{$this->primaryKey}' /}\" />\r\n";
        }
        else
        {
            $prikeys = explode(',', $this->primaryKey);
            $prikeyValue = '<'.'?php echo md5("key"';
            foreach($prikeys as $v)
            {
                $prikeyValue .= '.$fields["'.$v.'"]';
            }
            $prikeyValue .= '); ?'.'>';
            $tempItems['primarykey'] = "    <input type=\"hidden\" name=\"primarykey[]\" value=\"{$prikeyValue}\" />\r\n";
        }
        $fielditem = '';
        foreach($this->fields as $k=>$v)
        {
            $aeform = $dtype = $defaultvalue = $fformat = '';
            //在指定了字段模板情況下不使用自動生成
            if(isset($this->fields[$k][$getTemplets.'template']))
            {
                $fielditem .= $this->fields[$k][$getTemplets.'template'];
                continue;
            }
            //排除自動遞增鍵
            if($k==$this->autoField)
            {
                continue;
            }
            //編輯時，排除主鍵
            if($k==$this->primaryKey && $getTemplets=='edit')
            {
                continue;
            }
            //格式化選項(編輯時用)
            if(isset($this->fields[$k]['format']))
            {
                $fformat = $this->fields[$k]['format'];
            }
            //獲得字段默認值（編輯時從數據庫獲取）
            if($getTemplets=='edit')
            {
                if( in_array($this->fields[$k]['type'], $this->binTypes) ) $dfvalue = '';
                else $dfvalue = "{dede:field name='$k' /}";
            }
            else
            {
                $dfvalue = $this->fields[$k]['default'];
            }
            //小數類型
            if( in_array($this->fields[$k]['type'], $this->floatTypes) ) 
            {
                if($getTemplets=='edit')
                {
                    $dfvalue = "{dede:field name='$k' function=\"Lurd::FormatFloat(@me, '$fformat')\" /}";
                }
                else if($this->fields[$k]['default']=='')
                {
                    $dfvalue = 0;
                }
                $aeform  = "<input type='input' name='{$k}' class='txtnumber' value='$dfvalue' />";
            }
            //整數類型
            if( in_array($this->fields[$k]['type'], $this->intTypes) ) 
            {
                $aeform  = "<input type='input' name='{$k}' class='txtnumber' value='$dfvalue' />";
            }
            //時間類型
            else if( in_array($this->fields[$k]['type'], $this->dateTypes))
            {
                if(empty($fformat)) $fformat = 'Y-m-d H:i:s';
                if($getTemplets=='edit')
                {
                    $dfvalue = "{dede:field name='$k' function=\"MyDate(@me, '$fformat')\" /}";
                }
                else if(empty($this->fields[$k]['default']))
                {
                    $dfvalue = "{dede:var.a function=\"MyDate(time(), '$fformat')\" /}";
                }
                $aeform  = "<input type='input' name='{$k}' class='txtdate' value='$dfvalue' />";
            }
            //長文本類型
            else if( in_array($this->fields[$k]['type'], $this->textTypes))
            {
                $aeform  = "<textarea name='$k' class='txtarea'>{$dfvalue}</textarea>";
            }
            //二進制類型
            else if( in_array($this->fields[$k]['type'], $this->textTypes))
            {
                $aeform = "<input type='file' name='$k' size='45' />";
            }
            //SET類型
            else if( $this->fields[$k]['type']=='SET' )
            {
                $ems = explode(',', $this->fields[$k]['em']);
                if($getTemplets=='edit')
                {
                    $aeform .= '<'.'?php $enumItems = explode(\',\', $fields[\''.$k.'\']); ?'.'>';
                }
                foreach($ems as $em)
                {
                    if($getTemplets=='add')
                    {
                        $aeform .= "<input type='checkbox' name='{$k}[]' value='$em' />$em \r\n";
                    }
                    else
                    {
                        $aeform .= "<input type='checkbox' name='{$k}[]' value='$em' {dede:if in_array('$em', \$enumItems)}checked{/dede:if} />$em \r\n";
                    }
                }
            }
            //ENUM類型
            else if( $this->fields[$k]['type']=='ENUM' )
            {
                $ems = explode(',', $this->fields[$k]['em']);
                foreach($ems as $em)
                {
                    if($getTemplets=='edit') {
                        $aeform .= "<input type='radio' name='$k' value='$em' {dede:if \$fields['$k']}=='$em'}checked{/dede:if} />$em \r\n";
                    }
                    else {
                        $aeform .= "<input type='radio' name='$k' value='$em' />$em \r\n";
                    }
                }
            }
            else
            {
                $aeform  = "<input type='input' name='{$k}' class='txt' value='$dfvalue' />";
            }
            $fielditem .= "    <tr>\r\n<td height='28' align='center' bgcolor='#FFFFFF'>{$k}</td>\r\n<td bgcolor='#FFFFFF'>{$aeform}</td>\r\n</tr>\r\n";
        }
        $tempItems['fields'] = $fielditem;
        foreach($tempItems as $k=>$v)
        {
            $tempstr = str_replace("~$k~", $v, $tempstr);
        }
        $fp = fopen($template, 'w');
        fwrite($fp, $tempstr);
        fclose($fp);
    }

    // 讀取數據
    function EditData()
    {
        $template = $this->templateDir.'/'.$this->tplName.'_edit.htm';
        //生成列表模板
        if( !file_exists($template) || $this->isDebug )
        {
            $this->MakeAddEditTemplate('edit');
        }
        $whereQuery = '';
        $GLOBALS[$this->primaryKey] = isset($GLOBALS[$this->primaryKey])? $GLOBALS[$this->primaryKey] : request($this->primaryKey);
        if(empty($GLOBALS['primarykey'][0]) && empty($GLOBALS[$this->primaryKey][0]))
        {
            ShowMsg('請選擇要修改的記錄！', '-1');
            exit();
        }
        if(preg_match("/,/", $this->primaryKey))
        {
            $whereQuery = "WHERE md5(CONCAT('key', `".str_replace(',', '`,`', $this->primaryKey)."`) = '{$GLOBALS['primarykey'][0]}' ";
        }
        else
        {
            $whereQuery = "WHERE `{$this->primaryKey}` = '".$GLOBALS[$this->primaryKey][0]."' ";
        }

        //列出數據
        $query = "SELECT * FROM `{$this->tableName}` $whereQuery ";
        $this->SetTemplate($template);
        $this->SetSource($query);
        $this->Display();
    }

    // 新增數據
    function AddData()
    {
        $template = $this->templateDir.'/'.$this->tplName.'_add.htm';
        //生成列表模板
        if( !file_exists($template) || $this->isDebug )
        {
            $this->MakeAddEditTemplate('add');
        }
        //生成發佈表單數據
        $this->SetTemplate($template);
        $this->Display();
        exit();
    }

    // 保存新增數據
    function SaveAddData($isturn=TRUE)
    {
        $allfield = $allvalue = '';
        foreach($this->fields as $k=>$v)
        {
            //自動遞增鍵不處理
            if($k==$this->autoField)
            {
                continue;
            }
            $allfield .= ($allfield=='' ? "`$k`" : ' , '."`$k`");
            $v = $this->GetData($k);
            $allvalue .= ($allvalue=='' ? "'$v'" : ' , '."'$v'");
        }
        $inQuery = "INSERT INTO `$this->tableName`($allfield) VALUES($allvalue); ";
        $rs = $this->dsql->ExecuteNoneQuery($inQuery);
        
        //只返回結果
        if(!$isturn)
        {
            return $rs;
        }
        //完全處理模式
        $gourl = !empty($_COOKIE['LURD_GOBACK_URL']) ? $_COOKIE['LURD_GOBACK_URL'] : '-1';
        if(!$rs)
        {
            $this->dsql->SaveErrorLog($inQuery);
            ShowMsg('保存數據失敗，請檢查數據庫錯誤日誌！', $gourl);
            exit();
        }
        else
        {
            ShowMsg('成功保存一組數據！', $gourl);
            exit();
        }
    }

    // 保存編輯數據
    function SaveEditData($isturn=TRUE)
    {
        $editfield = '';
        foreach($this->fields as $k=>$v)
        {
            //自動遞增鍵不處理
            $GLOBALS[$k] = isset($GLOBALS[$k])? $GLOBALS[$k] : request::$forms[$k];
            if($k==$this->autoField || !isset($GLOBALS[$k]))
            {
                continue;
            }
            $v = $this->GetData($k);
            $editfield .= ($editfield=='' ? " `$k`='$v' " : ",\n `$k`='$v' ");
        }
        //獲得主鍵值
        if(preg_match("#,#", $this->primaryKey))
        {
            $keyvalue = (isset($GLOBALS['primarykey']) ? $GLOBALS['primarykey'] : '');
        }
        else
        {
            $keyvalue = $this->GetData($this->primaryKey);
        }
        $keyvalue = preg_replace("#[^0-9a-z]#i", "", $keyvalue);
        if( !preg_match("#,#", $this->primaryKey) )
        {
            $inQuery = " UPDATE `$this->tableName` SET $editfield WHERE `{$this->primaryKey}`='{$keyvalue}' ";
        }
        else
        {
            $inQuery = " UPDATE `$this->tableName` SET $editfield WHERE md5('key', `".str_replace(',','`,`',$this->primaryKey)."`='{$keyvalue}' ";
        }
        $rs = $this->dsql->ExecuteNoneQuery($inQuery);
        //只返回結果
        if(!$isturn)
        {
            return $rs;
        }
        //完全處理模式
        $gourl = !empty($_COOKIE['LURD_GOBACK_URL']) ? $_COOKIE['LURD_GOBACK_URL'] : '-1';
        if(!$rs)
        {
            $this->dsql->SaveErrorLog($inQuery);
            ShowMsg('保存數據失敗，請檢查數據庫錯誤日誌！', $gourl);
            exit();
        }
        else
        {
            ShowMsg('成功保存一組數據！', $gourl);
            exit();
        }
    }

    // 刪除數據
    function DelData($isturn=TRUE)
    {
        $GLOBALS[$this->primaryKey] = isset($GLOBALS[$this->primaryKey])? $GLOBALS[$this->primaryKey] : request($this->primaryKey);
        if(preg_match("#,#", $this->primaryKey))
        {
            $keyArr = (isset($GLOBALS['primarykey']) ? $GLOBALS['primarykey'] : '');
        }
        else
        {
            $keyArr = isset($GLOBALS[$this->primaryKey]) ? $GLOBALS[$this->primaryKey] : '';
        }
        if(!is_array($keyArr))
        {
            ShowMsg('沒指定要刪除的記錄！', '-1');
            exit();
        }
        else
        {
            $isid = !preg_match("#,#", $this->primaryKey) ? TRUE : FALSE;
            $i = 0;
            foreach($keyArr as $v)
            {
                $v = preg_replace("#[^0-9a-z]#i", '', $v);
                if(empty($v)) continue;
                $i++;
                if($isid)
                {
                    $this->dsql->ExecuteNoneQuery("DELETE FROM `{$this->tableName}` WHERE `$this->primaryKey`='$v' ");
                }
                else
                {
                    $this->dsql->ExecuteNoneQuery("DELETE FROM `{$this->tableName}` WHERE md5('key', `".str_replace(',','`,`',$this->primaryKey)."`='$v' ");
                }
            }
            if($isturn)
            {
                $gourl = !empty($_COOKIE['LURD_GOBACK_URL']) ? $_COOKIE['LURD_GOBACK_URL'] : '-1';
                ShowMsg('成功刪除指定的記錄！', $gourl);
                exit();
            }
            else
            {
                return $i;
            }
        }
    }
    
    //聯結其它表(用於數據查詢的情況)
    //$tablelurd 目標表lurd對像, $linkfields select的字段
    //$mylinkid 當前表用於聯結的字段
    //$linkid 目標表用於聯結的字段
    function AddLinkTable(&$tablelurd, $mylinkid, $linkid, $linkfields='*')
    {
        if(trim($linkfields)=='') $linkfields = '*';
        $this->linkTables[] = array($tablelurd, $mylinkid, $linkid, $linkfields);
        //記錄附加表的字段信息
        if($linkfields != '*')
        {
            $fs = explode(',', $linkfields);
            foreach($fs as $f)
            {
                $f = trim($f);
                if(isset($tablelurd->fields[$f]))
                {
                    $this->addFields[$f] = $tablelurd->fields[$f];
                    $this->addFields[$f]['table'] = $tablelurd->tableName;
                }
            }
        }
        else
        {
            foreach($tablelurd->fields as $k=>$v) 
            {
                $this->addFields[$k] = $v;
                $this->addFields[$k]['table'] = $tablelurd->tableName;
            }
        }
    }

    //分析表結構
    function AnalyseTable()
    {
        if($this->tableName == '')
        {
            exit(" No Input Table! ");
        }
        
        $this->dsql->Execute('ana', " SHOW CREATE TABLE `{$this->tableName}`; ");
        $row = $this->dsql->GetArray('ana', MYSQL_NUM);
        if(!is_array($row))
        {
            exit(" Analyse Table `$tablename` Error! ");
        }

        // 先去掉內容中的註釋
        // $row[1] = preg_replace('#COMMENT \'(.*?)\'#i', '', $row[1]);
        // echo $row[1];exit;
        $flines = explode("\n", $row[1]);
        $parArray = array('date', 'float', 'int', 'char', 'text', 'bin', 'em');
        $prikeyTmp = '';
        for($i=1; $i < count($flines)-1; $i++ )
        {
            $line = trim($flines[$i]);
            $lines = explode(' ', str_replace('`', '', $line));

            if( $lines[0] == 'KEY' ) continue;
            if( $lines[0] == 'UNIQUE' ) continue;
            
            if( $lines[0] == 'PRIMARY' )
            {
                $this->primaryKey = preg_replace("/[\(\)]|,$/", '', $lines[count($lines)-1]);
                continue;
            }
            //字段名稱、類型
            $this->fields[$lines[0]] = array('type' => '',  'length' => '', 'unsigned' => FALSE, 'autokey' => FALSE, 'null' => TRUE, 'default' => '', 'em' => '', 'comment' => '');
            $this->fields[$lines[0]]['type'] = strtoupper(preg_replace("/\(.*$|,/", '', $lines[1]));
            $this->fields[$lines[0]]['length'] = preg_replace("/^.*\(|\)/", '', $lines[1]);
            if(preg_match("#[^0-9]#", $this->fields[$lines[0]]['length']))
            {
                if($this->fields[$lines[0]]['type'] == 'SET'
                    || $this->fields[$lines[0]]['type'] == 'ENUM')
                {
                    $this->fields[$lines[0]]['em'] = preg_replace("/'/", '', $this->fields[$lines[0]]['length']);
                }
                $this->fields[$lines[0]]['length'] = 0;
            }
            
            //把特定類型的數據加入數組中
            foreach($parArray as $v)
            {
                $tmpstr = "if(in_array(\$this->fields[\$lines[0]]['type'], \$this->{$v}Types))
                {
                    \$this->{$v}Fields[] = \$lines[0];
                }";
                eval($tmpstr);
            }
            if( !in_array($this->fields[$lines[0]]['type'], $this->textTypes) 
                && !in_array($this->fields[$lines[0]]['type'], $this->binTypes) )
            {
                $prikeyTmp .= ($prikeyTmp=='' ? $lines[0] : ','.$lines[0]);
            }
            
            //分析其它屬性
            // echo $line;exit;
            if(preg_match("#unsigned#i", $line))
            {
                $this->fields[$lines[0]]['unsigned'] = TRUE;
            }
            if(preg_match("#auto_increment#i", $line))
            {
                $this->fields[$lines[0]]['autokey'] = TRUE;
                $this->autoField = $lines[0];
            }
            if(preg_match("#NOT NULL#i", $line))
            {
                $this->fields[$lines[0]]['null'] = FALSE;
            }
            if(preg_match("#default#i", $line))
            {
                preg_match("#default '(.*?)'#i", $line, $dfmatchs);
                $this->fields[$lines[0]]['default'] = isset($dfmatchs[1])? $dfmatchs[1] : NULL;
            }
            if(preg_match("#comment#i", $line))
            {
                preg_match("#comment '(.*?)'#i", $line, $cmmatchs);
                $this->fields[$lines[0]]['comment'] = isset($cmmatchs[1])? $cmmatchs[1] : NULL;
            }
            
        }//end for
        if( $this->primaryKey=='' )
        {
            $this->primaryKey = $prikeyTmp;
        }
    }
    
    /**
    * 增加搜索條件
    * @parem $fieldname 字段名稱
    * @parem $fieldvalue 傳入的 value 值必須先經過轉義
    * @parem $condition 條件 >、<、=、<> 、like、%like%、%like、like%
    * @parem $linkmode AND 或 OR
    */
    function AddSearchParameter($fieldname, $fieldvalue, $condition, $linkmode='AND')
    {
        $c = count($this->searchParameters);
        //對於指定了多個字段，使用 CONCAT 進行聯結（通常是like操作）
        if( preg_match('/,/', $fieldname) )
        {
            $fs = explode(',', $fieldname);
            $fieldname = "CONCAT(";
            $ft = '';
            foreach($fs as $f)
            {
                $f = trim($f);
                $ft .= ($ft=='' ? "`{$f}`" : ",`{$f}`");
            }
            $fieldname .= "{$ft}) ";
        }
        $this->searchParameters[$c]['field'] = $fieldname;
        $this->searchParameters[$c]['value'] = $fieldvalue;
        $this->searchParameters[$c]['condition'] = $condition;
        $this->searchParameters[$c]['mode'] = $linkmode;
    }

    // 獲取搜索條件
    function GetSearchQuery()
    {
        $wquery = '';
        if( count( $this->searchParameters ) == 0 )
        {
            return '';
        }
        else
        {
            foreach($this->searchParameters as $k=>$v)
            {
                if( preg_match("/like/i", $v['condition']) )
                {
                    $v['value'] = preg_replace("/like/i", $v['value'], $v['condition']);
                }
                $v['condition'] = preg_replace("/%/", '', $v['condition']);
                if( $wquery=='' )
                {
                    if(!preg_match("/\./", $v['field'])) $v['field'] = "{$v['field']}";
                    $wquery .= "WHERE ".$v['field']." {$v['condition']} '{$v['value']}' ";
                }
                else
                {
                    if(!preg_match("/\./", $v['field'])) $v['field'] = "{$v['field']}";
                    $wquery .= $v['mode']." ".$v['field']." {$v['condition']} '{$v['value']}' ";
                }
            }
        }
        return $wquery ;
    }
    
    //把從表單傳遞回來的數值進行處理
    function GetData($fname)
    {
        $reValue = '';
        $ftype = $this->fields[$fname]['type'];
        $GLOBALS[$fname] = isset($GLOBALS[$fname])? $GLOBALS[$fname] : @request::$forms[$fname];
        //二進制單獨處理
        if( in_array($ftype, $this->binTypes) )
        {
            return $this->GetBinData($fname);
        }
        //沒有這個變量返回默認值
        else if( !isset($GLOBALS[$fname]) )
        {
            if( isset($this->fields[$fname]['default']) )
            {
                return $this->fields[$fname]['default'];
            }
            else
            {
                if(in_array($ftype, $this->intTypes) || in_array($ftype, $this->floatTypes)) {
                    return 0;
                }
                else if(in_array($ftype, $this->charTypes) || in_array($ftype, $this->textTypes)) {
                    return '';
                }
                else {
                    return 'NULL';
                }
            }
        }
        //處理整數
        else if( preg_match("#YEAR|INT#", $ftype) )
        {
            // $temp = isset($GLOBALS[$fname][0])? $GLOBALS[$fname][0] : 0;
            $negTag = is_int($GLOBALS[$fname]) && $GLOBALS[$fname]< 0 ? '-' : $GLOBALS[$fname];
            $reValue = preg_replace("#[^0-9]#", '', $GLOBALS[$fname]);
            $reValue = empty($reValue) ? 0 : intval($reValue);
            if($negTag=='-' && !$this->fields[$fname]['unsigned']
                 && $reValue != 0 && $ftype != 'YEAR')
            {
                $reValue = intval('-'.$reValue);
            }
        }
        //處理小數類型
        else if(in_array($ftype, $this->floatTypes))
        {
            $negTag = $GLOBALS[$fname][0];
            $reValue = preg_replace("#[^0-9\.]|^\.#", '', $GLOBALS[$fname]);
            $reValue = empty($reValue) ? 0 : doubleval($reValue);
            if($negTag=='-' && !$this->fields[$fname]['unsigned'] && $reValue != 0)
            {
                $reValue = intval('-'.$reValue);
            }
        }
        //字符串類型
        else if(in_array($ftype, $this->charTypes))
        {
            $reValue = cn_substrR($this->StringSafe($GLOBALS[$fname]), $this->fields[$fname]['length']);
        }
        //文本類型
        else if(in_array($ftype, $this->textTypes))
        {
            $reValue = $this->StringSafe($GLOBALS[$fname]);
        }
        //SET類型
        else if($ftype=='SET')
        {
            $sysSetArr = explode(',', $this->fields[$fname]['em']);
            if( !is_array($GLOBALS[$fname]) )
            {
                $setArr[] = $GLOBALS[$fname];
            }
            else
            {
                $setArr = $GLOBALS[$fname];
            }
            $reValues = array();
            foreach($setArr as $a)
            {
                if(in_array($a, $sysSetArr)) $reValues[] = $a;
            }
            $reValue = count($reValues)==0 ? 'NULL' : join(',', $reValues);
        }
        //枚舉類型
        else if($ftype=='ENUM')
        {
            $sysEnumArr = explode(',', $this->fields[$fname]['em']);
            if(in_array($GLOBALS[$fname], $sysEnumArr)) $reValue = $GLOBALS[$fname];
            else $reValue = 'NULL';
        }
        //時間日期類型
        else if(in_array($ftype, $this->dateTypes))
        {
            if($ftype=='TIMESTAMP')
            {
                $reValue = GetMkTime($GLOBALS[$fname]);
            }
            else
            {
                $reValue = preg_replace("#[^0-9 :-]#", '', $GLOBALS[$fname]);
            }
        }
        return $reValue;
    }
    
    //對請求的字符串進行安全處理
    function StringSafe($str, $safestep=-1)
    {
        $safestep = ($safestep > -1) ? $safestep : $this->stringSafe;
        //過濾危險的HTML(默認級別)
        if($safestep == 1)
        {
            $str = preg_replace("#script:#i", "ｓｃｒｉｐｔ：", $str);
            $str = preg_replace("#<[\/]{0,1}(link|meta|ifr|fra|scr)[^>]*>#isU", '', $str);
            $str = preg_replace("#[\r\n\t ]{1,}#", ' ', $str);
            return $str;
        }
        //完全禁止HTML
        //並轉換一些不安全字符串（如：eval(、union、CONCAT(、--、等）
        else if($this->stringSafe == 2)
        {
            $str = addslashes(htmlspecialchars(stripslashes($str)));
            $str = preg_replace("#eval#i", 'ｅｖａｌ', $str);
            $str = preg_replace("#union#i", 'ｕｎｉｏｎ', $str);
            $str = preg_replace("#concat#i", 'ｃｏｎｃａｔ', $str);
            $str = preg_replace("#--#", '－－', $str);
            $str = preg_replace("#[\r\n\t ]{1,}#", ' ', $str);
            return $str;
        }
        //不作安全處理
        else
        {
            return $str;
        }
    }
    //保存二進制文件數據
    //為了安全起見，對二進制數據保存使用base64編碼後存入
    function GetBinData($fname)
    {
        $lurdtmp = DEDEDATA.'/lurdtmp';
        if(!isset($_FILES[$fname]['tmp_name']) || !is_uploaded_file($_FILES[$fname]['tmp_name']))
        {
            return '';
        }
        else
        {
            $tmpfile = $lurdtmp.'/'.md5( time() . Sql::ExecTime() . mt_rand(1000, 5000) ).'.tmp';
            $rs = move_uploaded_file($_FILES[$fname]['tmp_name'], $tmpfile);
            if(!$rs) return '';
            $fp = fopen($tmpfile, 'r');
            $data = base64_encode(fread($fp, filesize($tmpfile)));
            fclose($fp);
            return $data;
        }
    }

    //格式化浮點數字
    function FormatFloat($fvalue, $ftype='')
    {
        if($ftype=='') $ftype='%0.4f';
        return sprintf($ftype, $fvalue);
    }
    
    //獲得默認時間格式
    function GetDateTimeDf($ftype)
    {
        if($ftype=='DATE') return 'Y-m-d';
        else if($ftype=='TIME') return 'H:i:s';
        else if($ftype=='YEAR') return 'Y';
        else return 'Y-m-d H:i:s';
    }
    
    //格式化日期
    function FormatDate($fvalue, $ftype, $fformat='')
    {
        if($ftype=='INT' || $ftype='TIMESTAMP' ) return MyDate($fvalue, $fformat);
        else return $fvalue;
    }

}
?>