kd = $kd; $this->gb_fields = $field_array; $this->db_using = NULL; $this->db_driver = NULL; $this->sql_table = NULL; $this->sort_field = NULL; $this->sort_type = NULL; } ## --------------------- ## ## -----+++ Pri +++----- ## ## --------------------- ## function getAllRecords() { switch ($this->db_using) { case "FLAT" : $records_array = $this->db_driver->parseXMLEntry(); return $records_array; break; case "SQL" : break; } } // this callback function is used to sort function _cmp($array_a, $array_b) { $array_a[$this->sort_field] = strtolower($array_a[$this->sort_field]); $array_b[$this->sort_field] = strtolower($array_b[$this->sort_field]); if ($array_a[$this->sort_field] == $array_b[$this->sort_field]) return 0; if ($this->sort_type == "DESC") { return ( $array_a[$this->sort_field] < $array_b[$this->sort_field] ) ? 1 : -1; } else return ( $array_a[$this->sort_field] < $array_b[$this->sort_field] ) ? -1 : 1; } // each value of $array is an array function makeSafeOutput(&$array) { switch ($this->db_using) { case "FLAT": foreach (array_keys($array) as $k) { ValidIO::makeSafeOutputFLAT($array[$k]); } break; case "SQL": foreach (array_keys($array) as $k) { ValidIO::makeSafeOutputSQL($array[$k]); } break; } } ## --------------------- ## ## -----+++ Pub +++----- ## ## --------------------- ## function gbConfig($db_info) { if ( !is_array($db_info) ) { $this->db_using = "FLAT"; $this->db_driver = new XMLdb($db_info, $this->gb_fields); } else { $this->db_using = "SQL"; $this->sql_table = $db_info[4]; $this->db_driver = new SQL($db_info[0], $db_info[1], $db_info[2], $db_info[3]); } } function putIntoDB($data_array) { switch ($this->db_using) { case "FLAT" : ValidIO::makeSafeInputFLAT($data_array); if ( !$this->db_driver->addNewEntry($data_array) ) die("Could not put data into DB now or your permission has been denied."); break; case "SQL" : ValidIO::makeSafeInputSQL($data_array); // prepare next record's ID $id = $this->getMaxID() + 1; // prepare data $values = implode("', '", $data_array); $values = "'" . $id . "', '" . $values . "'"; $sql = "INSERT INTO " . $this->sql_table . " VALUES (" . $values . ")"; $this->db_driver->query($sql); break; } } function getRecords($sort_field = "id", $sort_type = "ASC", $from = 0, $limit = 0) { // prepare for callback function _cmp($array_a, $array_b) $this->sort_field = ( in_array(strval($sort_field), $this->gb_fields) ) ? $sort_field : 'id'; $this->sort_type = ( strtoupper($sort_type) == "DESC" ) ? "DESC" : "ASC"; if ($from < 0) { $from = 0; } switch ($this->db_using) { case "FLAT" : // sort $all_records = $this->getAllRecords(); usort($all_records, array($this, "_cmp")); // return the records limited by $from and $limit $record_total = count($all_records); $record_max = $record_total - 1; if ($from > $record_max) { $from = $record_max; } $to = $from + $limit; if ($to < $from) { $to = $from + 1; } if ($to == $from || $to > $record_total) { $to = $record_total; } $results = array(); for ($i = $from; $i < $to; $i++) { $results[] = $all_records[$i]; } break; case "SQL" : if ($limit == 0) { $limit = $this->getRecordsTotal(); } // " WHERE kd = '".$this->kd."' ". $sql = "SELECT * FROM " . $this->sql_table . " WHERE kd = '".$this->kd."' ". " ORDER BY " . $this->sort_field . " " . $this->sort_type . " LIMIT " . $from . ", " . $limit; //echo $sql; $this->db_driver->query($sql); $results = $this->db_driver->fetchArray(); break; } $this->makeSafeOutput($results); return $results; } function deleteRecord($id) { $id = intval($id); switch ($this->db_using) { case "FLAT" : if (!$this->db_driver->deleteEntry($id)) die("Could not delete this record (#" . $id . ") now. Try again."); break; case "SQL" : $sql = "DELETE FROM " . $this->sql_table . " WHERE " . $this->gb_fields[0] . " = '" . $id . "'"; $this->db_driver->query($sql); break; } } function getToEdit($id) { $id = intval($id); switch ($this->db_using) { case "FLAT" : $record = $this->db_driver->getOneEntry($id); ValidIO::makeSafeOutputFLAT($record); break; case "SQL" : $sql = "SELECT * FROM " . $this->sql_table . " WHERE " . $this->gb_fields[0] . " = '" . $id . "' LIMIT 0, 1"; $this->db_driver->query($sql); $record_array = $this->db_driver->fetchArray(); $record = $record_array[0]; break; } return $record; } function updateRecord($id, $data_array) { $id = intval($id); switch ($this->db_using) { case "FLAT" : ValidIO::makeSafeInputFLAT($data_array); if ( !$this->db_driver->addNewEntry($data_array, $id) ) die("Could not edit this record (#" . $id . ") now."); break; case "SQL" : ValidIO::makeSafeInputSQL($data_array); $set = NULL; $c = count($data_array) - 1; for ($i = 0; $i <= $c ; $i++) { $j = $i + 1; $set .= ($i != $c) ? $this->gb_fields[$j] . " = '" . $data_array[$i] . "', " : $this->gb_fields[$j] . " = '" . $data_array[$i] . "'"; } $sql = "UPDATE " . $this->sql_table . " SET " . $set . " WHERE " . $this->gb_fields[0] . " = '" . $id . "'"; $this->db_driver->query($sql); break; } } function getMaxID() { switch ($this->db_using) { case "FLAT" : return $this->db_driver->getMaxID(); break; case "SQL" : return $this->db_driver->getMaxID($this->sql_table, $this->gb_fields[0]); break; } } function getRecordsTotal() { switch ($this->db_using) { case "FLAT" : return $this->db_driver->getEntryTotal(); break; case "SQL" : return $this->db_driver->getRowsTotal($this->sql_table, "kd = '" . $this->kd . "'"); break; } } function checkUser() { return $this->db_driver->getRowsTotal("user", "kd = '" . $this->kd . "'"); } } // END CLASS Guestbook # ---===---------------===--- # # ---=== PRIVATE CLASS ===--- # # ---===---------------===--- # class XMLdb { var $xml_db; var $xml_fields; var $xml_fields_total; var $xml_parser; var $xml_results; var $xml_temp; var $cur_tag; /* ============================================================= // This CONSTRUCTOR will create an XML file, which is considered // as Flat DB, whose form is like that: // // // // // // ]> // // // =============================================================== */ function XMLdb($filename, $field_array) { $this->xml_db = $filename; $this->xml_fields = array(); $this->xml_results = array(); $this->xml_temp = array(); $this->cur_tag = NULL; foreach ($field_array as $v) { $this->xml_fields[] = strtoupper($v); } $this->xml_fields_total = count($this->xml_fields); if ( !file_exists($this->xml_db) ) { $xml = "\r\n"; $xml .= "xml_fields_total - 1; for ($i = 0; $i <= $c; $i++) { $xml_GB_tags .= $this->xml_fields[$i]; $xml_GB_tags .= ( $i != $c ) ? ", " : ")>\r\n"; $xml_elements .= "\txml_fields[$i] . " (#PCDATA)>\r\n"; } $xml .= $xml_GB_tags; $xml .= "\t\t\r\n"; $xml .= $xml_elements; $xml .= "]>\r\n"; $xml .= "\r\n"; $xml .= ""; if ( !$this->makeXMLdatabase($xml) ) { echo "

"; echo "

"; $this->dumpStructure($xml); die("

"); } } } ## --------------------- ## ## -----+++ Pri +++----- ## ## --------------------- ## function makeXMLdatabase($xml) { ignore_user_abort(true); $fp = fopen($this->xml_db, "x+b"); if (!$fp) return false; else { if (flock($fp, 2)) { fwrite($fp, $xml); fflush($fp); flock($fp, 3); } else return false; fclose($fp); } ignore_user_abort(false); return true; } function dumpStructure($content) { echo nl2br(preg_replace("/\t/", "    ", htmlspecialchars($content))); } function makeXMLEntry($id, $data_array) { $xml = "\t\r\n"; for ($i = 0; $i < $this->xml_fields_total; $i++) { if ( !empty($data_array[$i]) ) $xml .= "\t\t<" . $this->xml_fields[$i] . ">" . $data_array[$i] . "xml_fields[$i] . ">\r\n"; } $xml .= "\t\r\n"; return $xml; } function streamWriteNewEntry($fp, $xml) { fseek($fp, -12, SEEK_END); fwrite($fp, $xml); fwrite($fp, ""); fflush($fp); } function streamDeleteEntry($fp, $id) { fseek($fp, 0, SEEK_END); $filesize = ftell($fp); rewind($fp); $text = preg_replace("/\t.*?<\/GB>\r\n/is", NULL, fread($fp, $filesize), 1); rewind($fp); fwrite($fp, $text); fflush($fp); ftruncate($fp, ftell($fp)); } function streamGetIDTags($fp) { fseek($fp, 0, SEEK_END); $filesize = ftell($fp); rewind($fp); $text = fread($fp, $filesize); preg_match_all("//si", $text, $re); return $re[0]; } function streamGetMaxID($fp) { $id_tags_array = $this->streamGetIDTags($fp); foreach ($id_tags_array as $k => $v) { $id_tags_array[$k] = preg_replace("/[^\d]/", NULL, $v); } sort($id_tags_array); return end($id_tags_array); } function startElementHandler($xml, $element, $attribute) { $this->cur_tag = $element; if ( strcmp($element, "GB") == 0 ) { $this->xml_temp['id'] = $attribute['ID']; } } function cdataHandler($xml, $data) { $data = eregi_replace(">" . "[[:space:]]+" . "<", "><", $data); if ( in_array($this->cur_tag, $this->xml_fields) ) { $this->xml_temp[strtolower($this->cur_tag)] .= $data; } } function endElementHandler($xml, $element) { if ( strcmp($element, "GB") == 0 ) { $this->xml_results[] = $this->xml_temp; $this->xml_temp = array(); $this->cur_tag = NULL; } } ## --------------------- ## ## -----+++ Pub +++----- ## ## --------------------- ## // Values of $data_array must be arranged in order of $this->xml_fields // If $id is NULL, this function will increase id's value automatically // If $id is other than NULL, this function will delete the entry whose // id is equal to this id's value and add a new entry with this id. function addNewEntry($data_array, $id = NULL) { ignore_user_abort(true); $fp = fopen($this->xml_db, "r+b"); if (!$fp) return false; else { if (flock($fp, 2)) { if ($id == NULL) { // get the last record's ID $last_id = $this->streamGetMaxID($fp); $id = $last_id + 1; } else { $this->streamDeleteEntry($fp, $id); } // prepare data to put into flat db $xml = $this->makeXMLEntry($id, $data_array); // write new record $this->streamWriteNewEntry($fp, $xml); flock($fp, 3); } else return false; fclose($fp); } ignore_user_abort(false); return true; } function parseXMLEntry() { $this->xml_parser = xml_parser_create("UTF-8"); xml_set_object($this->xml_parser, $this); xml_set_element_handler($this->xml_parser, "startElementHandler", "endElementHandler"); xml_set_character_data_handler($this->xml_parser, "cdataHandler"); xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, 1); $fp = fopen($this->xml_db, "rb"); if (!$fp) return false; else { while ($data = fread($fp, filesize($this->xml_db))) { xml_parse($this->xml_parser, $data, feof($fp)) or die("FLAT DB error at line " . xml_get_current_line_number($this->xml_parser) . ""); } xml_parser_free($this->xml_parser); fclose($fp); return $this->xml_results; } } function deleteEntry($id) { ignore_user_abort(true); $fp = fopen($this->xml_db, "r+b"); if (!$fp) return false; else { if (flock($fp, 2)) { $this->streamDeleteEntry($fp, $id); flock($fp, 3); } else return false; fclose($fp); } ignore_user_abort(false); return true; } function getOneEntry($id) { $fp = @fopen($this->xml_db, "rb"); if (!$fp) return false; else { while (!feof($fp)) { if ( preg_match("//i", fgets($fp, 4096), $re) ) { $text = NULL; while ( !preg_match("/<\/GB>/i", $buffer = fgets($fp, 4096)) ) { $text .= $buffer; } break; } } fclose($fp); $re = array(); preg_match_all("/(<([\S]+)[^>]*>)(.*)(<\/\\2>)/is", $text, $re); $record = array(); $record['id'] = $id; for ($i = 0; $i < $this->xml_fields_total; $i++) { $record[strtolower($re[2][$i])] = $re[3][$i]; } } return $record; } function getMaxID() { $fp = fopen($this->xml_db, "rb"); if (!fp) return false; else { if (flock($fp, 2)) { $max_id = $this->streamGetMaxID($fp); flock($fp, 3); } else return false; fclose($fp); } return $max_id; } function getEntryTotal() { $fp = fopen($this->xml_db, "rb"); if (!fp) return false; else { if (flock($fp, 2)) { $id_tags = $this->streamGetIDTags($fp); flock($fp, 3); } else return false; fclose($fp); } return count($id_tags); } } // END CLASS XMLdb # ---===---------------===--- # # ---=== PRIVATE CLASS ===--- # # ---===---------------===--- # class SQL { var $result; function SQL($host, $user, $pass, $db) { @mysql_connect($host, $user, $pass) or die("Could not connect to host."); @mysql_select_db($db) or die("Could not select db."); } function query($sql) { $this->result = @mysql_query($sql) ; if (strtolower(gettype($this->result)) == "resource") { return $this->result; } } function numRows() { return @mysql_num_rows($this->result); } function fetchArray() { while ($row = @mysql_fetch_array($this->result)) $re[] = $row; return $re; } function getRowsTotal($table, $where) { $sql = "SELECT * FROM " . $table . " WHERE ". $where; $re = mysql_num_rows($this->query($sql)); if ($re) return $re; else return 0; } function getMaxID($table, $id_field) { $sql = "SELECT MAX(" . $id_field . ") FROM " . $table; $re = mysql_fetch_row($this->query($sql)); return $re[0]; } } // END CLASS SQL # ---===---------------===--- # # ---=== PRIVATE CLASS ===--- # # ---===---------------===--- # class ValidIO { function makeSafeInputFLAT(&$input) { $pattern = array("/&/", "//"); $replace = array("&", "<", ">"); if ( get_magic_quotes_gpc() ) { if ( is_array($input) ) { foreach ($input as $k => $v) { $input[$k] = preg_replace($pattern, $replace, trim($v)); } } else { $input = preg_replace($pattern, $replace, trim($input)); } } else { if ( is_array($input) ) { foreach ($input as $k => $v) { $input[$k] = addslashes(preg_replace($pattern, $replace, trim($v))); } } else { $input = addslashes(preg_replace($pattern, $replace, trim($input))); } } } function makeSafeInputSQL(&$input) { if ( get_magic_quotes_gpc() ) { if ( is_array($input) ) { foreach ($input as $k => $v) { $input[$k] = trim($v); } } else { $input = trim($input); } } else { if ( is_array($input) ) { foreach ($input as $k => $v) { $input[$k] = addslashes(trim($v)); } } else { $input = addslashes(trim($input)); } } } function makeSafeOutputFLAT(&$output) { $pattern = array("/</", "/>/", "/&/"); $replace = array("<", ">", "&"); if ( is_array($output) ) { foreach ($output as $k => $v) { $output[$k] = stripslashes(htmlspecialchars(preg_replace($pattern, $replace, $v), ENT_QUOTES)); } } else { $output = stripslashes(htmlspecialchars(preg_replace($pattern, $replace, $output), ENT_QUOTES)); } } function makeSafeOutputSQL(&$output) { if ( is_array($output) ) { foreach ($output as $k => $v) { $output[$k] = htmlspecialchars($v, ENT_QUOTES); } } else { $output = htmlspecialchars($output, ENT_QUOTES); } } }//END CLASS ValidInput ?>