Skip to content
Snippets Groups Projects
db_mysql.inc.php 43.2 KiB
Newer Older
			foreach($rows as $row) {
				$name = $row['Field'];
				$default = $row['Default'];
				$key = $row['Key'];
				$extra = $row['Extra'];
				$isnull = $row['Null'];
				$type = $row['Type'];


				$column = array();

				$column['name'] = $name;
				//$column['type'] = $type;
				$column['defaultValue'] = $default;
				if(stristr($key, 'PRI')) $column['option'] = 'primary';
				if(stristr($isnull, 'YES')) {
					$column['notNull'] = false;
				} else {
					$column['notNull'] = true;
				}
				if($extra == 'auto_increment') $column['autoInc'] = true;


				// Type in Metatype umsetzen

				if(stristr($type, 'int(')) $metaType = 'int32';
				if(stristr($type, 'bigint')) $metaType = 'int64';
				if(stristr($type, 'char')) {
					$metaType = 'char';
					$tmp_typeValue = explode('(', $type);
					$column['typeValue'] = substr($tmp_typeValue[1], 0, -1);
				}
				if(stristr($type, 'varchar')) {
					$metaType = 'varchar';
					$tmp_typeValue = explode('(', $type);
					$column['typeValue'] = substr($tmp_typeValue[1], 0, -1);
				}
				if(stristr($type, 'text')) $metaType = 'text';
				if(stristr($type, 'double')) $metaType = 'double';
				if(stristr($type, 'blob')) $metaType = 'blob';


				$column['type'] = $metaType;

				$columns[] = $column;
			}
			return $columns;
		} else {
			return false;
		}


		//$this->createTable('tester',$columns);

		/*
	 $result = mysql_list_fields($go_info["server"]["db_name"],$table_name);
	 $fields = mysql_num_fields ($result);
	 $i = 0;
	 $table = mysql_field_table ($result, $i);
	 while ($i < $fields) {
	 $name  = mysql_field_name  ($result, $i);
	 $type  = mysql_field_type  ($result, $i);
	 $len   = mysql_field_len   ($result, $i);
	 $flags = mysql_field_flags ($result, $i);
	 print_r($flags);

	 $columns = array(name => $name,
	 type =>     "",
	 defaultValue =>  "",
	 isnull =>   1,
	 option =>   "");
	 $returnvar[] = $columns;

	 $i++;
	 }
       */



	}

	public function mapType($metaType, $typeValue) {
		$metaType = strtolower($metaType);
		switch ($metaType) {
		case 'int16':
			return 'smallint';
			break;
		case 'int32':
			return 'int';
			break;
		case 'int64':
			return 'bigint';
			break;
		case 'double':
			return 'double';
			break;
		case 'char':
			return 'char';
			break;
		case 'varchar':
			if($typeValue < 1) die('Database failure: Length required for these data types.');
			return 'varchar('.$typeValue.')';
			break;
		case 'text':
			return 'text';
			break;
		case 'blob':
			return 'blob';
			break;
		$app->error('Unknown meta type: '.$metaType);
		return false;
	/**
	 * Get the database type (mariadb or mysql)
	 *
	 * @access public
	 * @return string 'mariadb' or string 'mysql'
	 */
	public function getDatabaseType() {
		$tmp = $this->queryOneRecord('SELECT VERSION() as version');
		if(stristr($tmp['version'],'mariadb')) {
			return 'mariadb';
		} else {
			return 'mysql';
		}
	}

	/**
	 * Get the database version
	 *
	 * @access public
	 * @param bool   $major_version_only = true will return the major version only, e.g. 8 for MySQL 8
	 * @return string version number
	 */

	public function getDatabaseVersion($major_version_only = false) {
		$tmp = $this->queryOneRecord('SELECT VERSION() as version');
		$version = explode('-', $tmp['version']);
		if($major_version_only == true) {
			$version_parts = explode('.', $version[0]);
			return $version_parts[0];
		} else {
			return $version[0];
		}
	}
	/**
	 * Get a mysql password hash
	 *
	 * @access public
	 * @param string $password cleartext password
	 * @param string $hash_type MySQL hash type to use. either mysql_native_password or caching_sha2_password
	 * @return string  Password hash
	 */

	public function getPasswordHash($password, $hash_type = 'mysql_native_password') {
		if($hash_type == 'caching_sha2_password') {
			$password_hash = $this->mysqlSha256Crypt($password, $this->genSalt(20), 5000);
		} else {
			$password_hash = '*' . strtoupper(sha1(sha1($password, true)));
	/**
	 * @param $size int length of salt in bytes
	 *
	 * @return string
	 */
	private function genSalt($size) {
		if($salt === false) {
			throw new Exception('Cannot generate salt.');
		}
		for($i = 0; $i < $size; $i++) {
			if($ord == 36 /* $ */) {
		return $salt;
	}

	/**
	 * this is the SHA256 algorithm of the crypt unix call – the only difference is that we do not truncate the salt to 16 chars
	 * @see https://www.akkadia.org/drepper/SHA-crypt.txt
	 * @see https://github.com/mysql/mysql-server/blob/trunk/mysys/crypt_genhash_impl.cc
	 *
	 * @param string $plaintext the plain text password
	 * @param string $salt the raw salt (needs to be 20 bytes long)
	 * @param int $rounds number of rounds. MySQL default is 5000.  Must be between 1000 and 4095000 (0xFFF * 1000)
	 *
	 * @return string hashed password in MySQL format
	 */
	private function mysqlSha256Crypt($plaintext, $salt, $rounds) {
		$plaintext_len = strlen($plaintext);
		$salt_len = strlen($salt);

		// 1
		$ctxA = hash_init('sha256');
		// 2
		hash_update($ctxA, $plaintext);
		// 3
		hash_update($ctxA, $salt);
		// 4
		$ctxB = hash_init('sha256');
		// 5
		hash_update($ctxB, $plaintext);
		// 6
		hash_update($ctxB, $salt);
		// 7
		hash_update($ctxB, $plaintext);
		// 8
		$B = hash_final($ctxB, true);
		// 9
		for($i = $plaintext_len; $i > 32; $i -= 32) {
		// 10
		hash_update($ctxA, substr($B, 0, $i));
		// 11
		for($i = $plaintext_len; $i > 0; $i >>= 1) {
			if(($i & 1) != 0) {
				hash_update($ctxA, $B);
			} else {
				hash_update($ctxA, $plaintext);
			}
		}
		// 12
		$A = hash_final($ctxA, true);
		// 13
		$ctxDP = hash_init('sha256');
		// 14
		for($i = 0; $i < $plaintext_len; $i++) {
			hash_update($ctxDP, $plaintext);
		}
		// 15
		$DP = hash_final($ctxDP, true);
		// 16
		$P = "";
		for($i = $plaintext_len; $i > 32; $i -= 32) {
			$P .= $DP;
		}
		$P .= substr($DP, 0, $i);
		// 17
		$ctxDS = hash_init('sha256');
		// 18
		for($i = 0; $i < 16 + ord($A[0]); $i++) {
			hash_update($ctxDS, $salt);
		}
		// 19
		$DS = hash_final($ctxDS, true);
		// 20
		$S = "";
		for($i = $salt_len; $i >= 32; $i -= 32) {
		for($i = 0; $i < $rounds; $i++) {
				hash_update($ctxC, $P);
			} else {
				hash_update($ctxC, $i == 0 ? $A : $C);
			}
				hash_update($ctxC, $i == 0 ? $A : $C);
			} else {
				hash_update($ctxC, $P);
			}
			$C = hash_final($ctxC, true);
		}
		$b64result = str_repeat(' ', 43);
		$p = 0;
		$b64_from_24bit = function($B2, $B1, $B0, $N) use (&$b64result, &$p) {
			$b64_alphabet = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			$w = ($B2 << 16) | ($B1 << 8) | $B0;
			$n = $N;
			while(--$n >= 0) {
				$b64result[$p++] = $b64_alphabet[$w & 0x3f];
				$w = $w >> 6;
			}
		};
		$b64_from_24bit(ord($C[0]), ord($C[10]), ord($C[20]), 4);
		$b64_from_24bit(ord($C[21]), ord($C[1]), ord($C[11]), 4);
		$b64_from_24bit(ord($C[12]), ord($C[22]), ord($C[2]), 4);
		$b64_from_24bit(ord($C[3]), ord($C[13]), ord($C[23]), 4);
		$b64_from_24bit(ord($C[24]), ord($C[4]), ord($C[14]), 4);
		$b64_from_24bit(ord($C[15]), ord($C[25]), ord($C[5]), 4);
		$b64_from_24bit(ord($C[6]), ord($C[16]), ord($C[26]), 4);
		$b64_from_24bit(ord($C[27]), ord($C[7]), ord($C[17]), 4);
		$b64_from_24bit(ord($C[18]), ord($C[28]), ord($C[8]), 4);
		$b64_from_24bit(ord($C[9]), ord($C[19]), ord($C[29]), 4);
		$b64_from_24bit(0, ord($C[31]), ord($C[30]), 3);

		// we do not truncate $salt to 16 chars since MySQL does not do that and uses 20 bytes salts
		return sprintf('$A$%03x$%s%s', $rounds / 1000, $salt, $b64result);
	}
/**
 * database query result class
 *
 * @package pxFramework
 *
 */
class db_result {

	/**
	 *
	 * @var mysqli_result|null
	 * @access private
	 */
	private $_iResId = null;
	/** @var mysqli|null  */
	private $_iConnection = null;



	/**
	 *
	 *
	 * @access private
	 */
	public function __construct($iResId, $iConnection) {
		$this->_iResId = $iResId;
		$this->_iConnection = $iConnection;
	}



	/**
	 * get count of result rows
	 *
	 * Returns the amount of rows in the result set
	 *
	 * @access public
	 * @return int amount of rows
	 */
	public function rows() {
		if(!is_object($this->_iResId)) return 0;
		$iRows = mysqli_num_rows($this->_iResId);
		if(!$iRows) $iRows = 0;
		return $iRows;
	}



	/**
	 * Get number of affected rows
	 *
	 * Returns the amount of rows affected by the previous query
	 *
	 * @access public
	 * @return int amount of affected rows
	 */
	public function affected() {
		if(!is_object($this->_iConnection)) return 0;
		$iRows = mysqli_affected_rows($this->_iConnection);
		if(!$iRows) $iRows = 0;
		return $iRows;
	}



	/**
	 * Frees the result set
	 *
	 * @access public
	 */
	public function free() {
		if(!is_object($this->_iResId)) return;

		mysqli_free_result($this->_iResId);
		return;
	}



	/**
	 * Get a result row (associative)
	 *
	 * Returns the next row in the result set. To be used in a while loop like while($currow = $result->get()) { do something ... }
	 *
	 * @access public
	 * @return array result row
	 */
	public function get() {
		$aItem = null;

		if(is_object($this->_iResId)) {
			$aItem = mysqli_fetch_assoc($this->_iResId);
			if(!$aItem) $aItem = null;
		}
		return $aItem;
	}



	/**
	 * Get a result row (array with numeric index)
	 *
	 * @access public
	 * @return array result row
	 */
	public function getAsRow() {
		$aItem = null;

		if(is_object($this->_iResId)) {
			$aItem = mysqli_fetch_row($this->_iResId);
			if(!$aItem) $aItem = null;
		}
		return $aItem;
	}

}

/**
 * database query result class
 *
 * emulates a db result set out of an array so you can use array results and db results the same way
 *
 * @package pxFramework
 * @see db_result
 *
 *
 */
class fakedb_result {

	/**
	 *
	 *
	 * @access private
	 */
	private $aResultData = array();

	/**
	 *
	 *
	 * @access private
	 */
	private $aLimitedData = array();



	/**
	 *
	 *
	 * @access private
	 */
		$this->aResultData = $aData;
		$this->aLimitedData = $aData;
		reset($this->aLimitedData);
	}



	/**
	 * get count of result rows
	 *
	 * Returns the amount of rows in the result set
	 *
	 * @access public
	 * @return int amount of rows
	 */
	// Gibt die Anzahl Zeilen zurück
	public function rows() {
		return count($this->aLimitedData);
	}



	/**
	 * Frees the result set
	 *
	 * @access public
	 */
	// Gibt ein Ergebnisset frei
	public function free() {
		$this->aResultData = array();
		$this->aLimitedData = array();
		return;
	}



	/**
	 * Get a result row (associative)
	 *
	 * Returns the next row in the result set. To be used in a while loop like while($currow = $result->get()) { do something ... }
	 *
	 * @access public
	 * @return array result row
	 */
	// Gibt eine Ergebniszeile zurück
	public function get() {
		$aItem = null;

		if(!is_array($this->aLimitedData)) return $aItem;

		foreach($this->aLimitedData as $vKey => $aItem) {
			if(!$aItem) $aItem = null;
		}
		return $aItem;
	}



	/**
	 * Get a result row (array with numeric index)
	 *
	 * @access public
	 * @return array result row
	 */
	public function getAsRow() {
		return $this->get();
	}



	/**
	 * Limit the result (like a LIMIT x,y in a SQL query)
	 *
	 * @access public
	 * @param int     $iStart offset to start read
	 * @param int     $iLength amount of datasets to read
	 */
	public function limit_result($iStart, $iLength) {
		$this->aLimitedData = array_slice($this->aResultData, $iStart, $iLength, true);
	}

}