Location: PHPKode > scripts > DbProxy > dbproxy/assets/DbProxy.php
<?php
    /**
    * "Takes an XML file, parses it and dynamically creates specific wrapper functions that connect
    * to a database to read/write data."
    * @author: Claudius Tiberiu Iacob <hide@address.com>
    * @license: Creative Commons Attribution Share Alike - Claudius Tiberiu Iacob 2009
    */

    class DbProxy extends ParamsProxy {

    	const FAILURE = "FAILURE";
    	const SUCCESS = "SUCCESS";
    	const NOT_CONFIGURED = "NOT_CONFIGURED";
        const CANNOT_REDEFINE_STUB = "CANNOT_REDEFINE_STUB";
        const ILLEGAL_STUB_NAME = "ILLEGAL_STUB_NAME";
        const ILLEGAL_STUB_ARGUMENTS = "ILLEGAL_STUB_ARGUMENTS";
        const MISSING_STUB_QUERY = "MISSING_STUB_QUERY";
        const ILLEGAL_STUB_QUERY = "ILLEGAL_STUB_QUERY";
        const ILLEGAL_STUB_OUTPUT_TYPE = "ILLEGAL_STUB_OUTPUT_TYPE";
        const UNMATCHED_STUB_ARGUMENTS = "UNMATCHED_STUB_ARGUMENTS";
        const SQL_QUERY_FAILED = "SQL_QUERY_FAILED";
        const CLASS_NOT_REGISTERED = "CLASS_NOT_REGISTERED";
        const INVALID_CONNECTION_SETTINGS = "INVALID_CONNECTION_SETTINGS";
        const INVALID_DB_NAME = "INVALID_DB_NAME";
        const INVALID_HOST_NAME = "INVALID_HOST_NAME";
        const INVALID_USER_NAME = "INVALID_USER_NAME";
        const INVALID_USER_PASSWORD = "INVALID_USER_PASSWORD";
        const ROOT_LOGIN_IS_INSECURE = "ROOT_LOGIN_IS_INSECURE";
        const CONNECTION_FAILED = "CONNECTION_FAILED";
        const NOT_CALLABLE_STUB = "NOT_CALLABLE_STUB";
        const NO_STUBS = "NO_STUBS";
        const NO_CONNECTION_SETTINGS = "NO_CONNECTION_SETTINGS";
        const ARGUMENTS_MISSMATCH = "ARGUMENTS_MISSMATCH";

        private $isInitialized = false;
        private $stubs = null;
        private $resourceLinks = null;
        private $currClientClsName = null;
        private $clientConfigFileName = "dbAccess.xml";
        private $connectionStubName = "connection";
        private $paramsKeyName = "queryParams";
        private $templateKeyName = "queryTemplate";
        private $outputTypeKeyName = "queryResultType";
        private $paramsListDelimiter = ",";
        private $outputType_string = "string";
        private $outputType_number = "number";
        private $outputType_boolean = "boolean";
        private $outputType_array = "array";
        private $outputType_null = "null";
        private $dbKeyName = "dbName";
        private $hostKeyName = "dbHost";
        private $userKeyName = "dbUser";
        private $passKeyName = "dbPassword";
        private $mysqlForbiddenChars = null;
        private $safePass = null;
        private $fqdnHost = null;
        private $encIdentifierNamePatt = null;
        private $identifierMaxChars = 64;
		private $digitToLettersMap = null;

        public function __construct () {
			// Try to make sure we work on UTF-8 encoded strings:
			if (!headers_sent ()) {
				header('Content-type: text/html; charset=utf-8', true);
			}
			mb_language('uni');
			mb_internal_encoding('UTF-8');
			parent::__construct();
			$this->stubs = array ();
			$this->resourceLinks = array();
			$this->mysqlForbiddenChars = array (0, 10, 13, 92, 39, 34, 26, 45, 96);
			$this->safePass = $this->safePassPattern();
			$this->fqdnHost = $this->hostPattern();
			$this->encIdentifierNamePatt = $this->makeEncIdentifierPattern ();
			$this->digitToLettersMap = array (48 => "A", 49 => "B", 50 => "C", 51 => "D", 52 => "F", 53 => "G",
				54 => "H", 55 => "I", 56 => "J", 57 => "K");

        }

        protected function getConfigFileName () {
             return $this->clientConfigFileName;
        }

        protected function applyParams ($targetInstance, $params) {
            parent::applyParams($this, $params);
        }

        public function configure ($instance) {
            $this->currClientClsName = get_class ($instance);
            parent::configure($instance);
            $this->proofConfiguration ();
			$this->isInitialized = true;
        }

        private function proofConfiguration () {
            if (count ($this->stubs) == 0) {
                trigger_error(DbProxy::NO_STUBS, E_USER_ERROR);
            }
            $hasCSets = false;
            $hasStubs = false;
            foreach ($this->stubs as $key => $value) {
                if (preg_match('/__'.$this->connectionStubName.'$/', $key) === 1) {
                     $hasCSets = true;
                } else {
                     $hasStubs = true;
                }
            }
            if (!$hasCSets) {
                trigger_error(DbProxy::NO_CONNECTION_SETTINGS, E_USER_ERROR);
            }
            if (!hasStubs) {
                trigger_error(DbProxy::NO_STUBS, E_USER_ERROR);
            }
        }

        private function __call ($funcName, $arguments) {
            $fname = preg_replace('/^set/', "", $funcName);
            $trace = debug_backtrace();
            $callingClsName = $trace[2]["class"];
            $parentClassName = $this->getParentClassName();
            if ($callingClsName === $parentClassName) {
                // building stubs
                $fname = trim ($fname);
                if ($fname === "") {
                     trigger_error(DbProxy::ILLEGAL_STUB_NAME);
                }
                if (strpos($fname, " ") !== false) {
                    trigger_error(DbProxy::ILLEGAL_STUB_NAME);
                }
                if (strpos($fname, "__") === 0) {
                    trigger_error(DbProxy::ILLEGAL_STUB_NAME);
                }
                if (preg_match('/^[_a-zA-Z]?[_a-zA-Z0-9]*$/', $fname) === 0) {
                    trigger_error(DbProxy::ILLEGAL_STUB_NAME);
                }
                $fname = strtolower($fname[0]) . substr($fname, 1);
                if (array_key_exists($fname, $this->stubs)) {
                    trigger_error(DbProxy::CANNOT_REDEFINE_STUB, E_USER_ERROR);
                }
                if (strcasecmp($fname, $this->connectionStubName) === 0) {
                    // setup custom connection for this class
                    $cnData = $arguments[0];
                    if (!is_array($cnData)) {
                        trigger_error(DbProxy::INVALID_CONNECTION_SETTINGS, E_USER_ERROR);
                    }
                    if (!array_key_exists($this->dbKeyName, $cnData)) {
                        trigger_error(DbProxy::INVALID_CONNECTION_SETTINGS, E_USER_ERROR);
                    }
                    if (!array_key_exists($this->hostKeyName, $cnData)) {
                        trigger_error(DbProxy::INVALID_CONNECTION_SETTINGS, E_USER_ERROR);
                    }
                    if (!array_key_exists($this->userKeyName, $cnData)) {
                        trigger_error(DbProxy::INVALID_CONNECTION_SETTINGS, E_USER_ERROR);
                    }
                    if (!array_key_exists($this->passKeyName, $cnData)) {
                        trigger_error(DbProxy::INVALID_CONNECTION_SETTINGS, E_USER_ERROR);
                    }
                    $cDbName = $cnData[$this->dbKeyName];
                    $cDbName = trim ($cDbName);
                    if ($cDbName === "") {
                        trigger_error(DbProxy::INVALID_DB_NAME, E_USER_ERROR);
                    }
                    $cDbHost = $cnData[$this->hostKeyName];
                    if (strpos($cDbHost, "http://") === 0) {
                        $cDbHost = substr($cDbHost, 7);
                    } elseif (strpos($cDbHost, "https://") === 0) {
                        $cDbHost = substr($cDbHost, 8);
                    }
                    $cDbHost = trim ($cDbHost);
                    if ($cDbHost === "") {
                        trigger_error(DbProxy::INVALID_HOST_NAME, E_USER_ERROR);
                    }
                    if (strlen($cDbHost) > 255) {
                        trigger_error(DbProxy::INVALID_HOST_NAME, E_USER_ERROR);
                    }
                    $cDbHost = strtolower($cDbHost);
                    if (preg_match ($this->fqdnHost, $cDbHost) === 0) {
                        trigger_error(DbProxy::INVALID_HOST_NAME, E_USER_ERROR);
                    }
                    $cDbUser = $cnData[$this->userKeyName];
                    $cDbUser = trim ($cDbUser);
                    if ($cDbUser === "") {
                        trigger_error(DbProxy::INVALID_USER_NAME, E_USER_ERROR);
                    }
                    if (preg_match('/[a-zA-Z0-9_]+/', $cDbUser) === 0) {
                        trigger_error(DbProxy::INVALID_USER_NAME, E_USER_ERROR);
                    }
                    if ($cDbUser === "root") {
                         trigger_error(DbProxy::ROOT_LOGIN_IS_INSECURE, E_USER_ERROR);
                    }
                    $cDBPass = $cnData[$this->passKeyName];
                    $cDBPass = trim ($cDBPass);
                    if ($cDBPass === "") {
                        trigger_error(DbProxy::INVALID_USER_PASSWORD);
                    }
                    if (preg_match($this->safePass, $cDBPass) === 0) {
                        trigger_error(DbProxy::INVALID_USER_PASSWORD);
                    }
                    $link = @mysql_connect($cDbHost, $cDbUser, $cDBPass);
                    if ($link === false) {
                        trigger_error(DbProxy::CONNECTION_FAILED . "\n" . mysql_errno() . ": " .
                            $this->makeReadable(mysql_error()), E_USER_ERROR);
                    }
                    $res = mysql_query("USE " . $cDbName);
                    if ($res === false) {
                        trigger_error(DbProxy::INVALID_DB_NAME . "\n" . mysql_errno() . ": " .
                            $this->makeReadable (mysql_error()), E_USER_ERROR);
                    }
                    $this->resourceLinks [$this->currClientClsName] = $link;
                    $this->stubs[$this->currClientClsName . "__" . $this->connectionStubName] = array (
                        $cDbUser, $cDBPass, $cDbHost, $cDbName);
                } else {
                    // setup operations for this class
                    $fdata = $arguments[0];
                    if (!is_array($fdata)) {
                        trigger_error(DbProxy::ILLEGAL_STUB_ARGUMENTS, E_USER_ERROR);
                    }
                    $fArgs = "";
                    $fArgsList = array();
                    if (array_key_exists($this->paramsKeyName, $fdata)) {
                        $fArgs = $fdata[$this->paramsKeyName];
                        $fArgs = trim ($fArgs);
                        if ($fArgs !== "") {
	                        $fArgs = explode($this->paramsListDelimiter, $fArgs);
	                        for ($i=0; $i<count($fArgs); $i++) {
	                            $fArg = $fArgs[$i];
	                            $fArg = trim ($fArg);
	                            if ($fArg === "") {
	                                trigger_error(DbProxy::ILLEGAL_STUB_ARGUMENTS, E_USER_ERROR);
	                            }
	                            if (strpos($fArg, " ") !== false) {
	                                trigger_error(DbProxy::ILLEGAL_STUB_ARGUMENTS, E_USER_ERROR);
	                            }
	                            if (strpos($fArg, "__") === 0) {
	                                trigger_error(DbProxy::ILLEGAL_STUB_ARGUMENTS, E_USER_ERROR);
	                            }
	                            if (preg_match('/^[_a-zA-Z]?[_a-zA-Z0-9]*$/', $fArg) === 0) {
	                                trigger_error(DbProxy::ILLEGAL_STUB_ARGUMENTS, E_USER_ERROR);
	                            }
	                            array_push($fArgsList, $fArg);
	                        }
                        }
                        if (!array_key_exists($this->templateKeyName, $fdata)) {
                            trigger_error(DbProxy::MISSING_STUB_QUERY, E_USER_ERROR);
                        }
                    }
                    $fTempl = $fdata[$this->templateKeyName];
                    $fTempl = trim ($fTempl);
                    $fTempl = preg_replace('/[\n\r\t]/', " ", $fTempl);
                    $fTempl = preg_replace('/\s{2,}/', " ", $fTempl);
                    if ($fTempl === "") {
                        trigger_error(DbProxy::ILLEGAL_STUB_QUERY, E_USER_ERROR);
                    }
                    $fOutType = $this->outputType_array;
                    if (array_key_exists($this->outputTypeKeyName, $fdata)) {
                        $fOutType = $fdata[$this->outputTypeKeyName];
                        $fOutType = trim ($fOutType);
                        if ($fOutType === "") {
                            trigger_error(DbProxy::ILLEGAL_STUB_OUTPUT_TYPE, E_USER_ERROR);
                        }
                        $fOutType = strtolower ($fOutType);
                        if ($fOutType !== $this->outputType_string &&
                            $fOutType !== $this->outputType_number &&
                            $fOutType !== $this->outputType_boolean &&
                            $fOutType !== $this->outputType_array &&
                            $fOutType !== $this->outputType_null) {
                            trigger_error(DbProxy::ILLEGAL_STUB_OUTPUT_TYPE, E_USER_ERROR);
                        }
                    }
                    $this->stubs[$this->currClientClsName . "__" . $fname] =  array ($fArgsList, $fTempl,
                        $fOutType);
                }
            } else {
                // merely use a stub
        		if (!$this->isInitialized) {
					trigger_error(DbProxy::NOT_CONFIGURED, E_USER_ERROR);
        		}
                $stubName = $this->currClientClsName . "__" . $fname;
                if ($stubName === $this->currClientClsName . "__" . $this->connectionStubName) {
                    trigger_error(DbProxy::NOT_CALLABLE_STUB, E_USER_ERROR);
                }
                if (!array_key_exists($stubName, $this->stubs)) {
                    trigger_error (DbProxy::CLASS_NOT_REGISTERED, E_USER_ERROR);
                }
                return $this->runStub($arguments, $this->stubs[$stubName]);
            }
        }

        private function runStub ($arguments, $stub) {
            $argList = $stub[0];
            if (count($argList) !== count ($arguments)) {
                trigger_error(DbProxy::ARGUMENTS_MISSMATCH, E_USER_ERROR);
            }
            $template = $stub[1];
            $outputType = $stub[2];
            for ($i=0; $i<count($arguments); $i++) {
                $argVal = $arguments[$i];
                $argName = $argList[$i];
                $template = $this->fillInQueryTemplate($template, $argName, $argVal);
            }
            $this->proofQuery($template);
            $result = @$this->executeQuery($template);
            $ret =  $this->fetchQueryResult($result, $outputType);
            if ($outputType !== $this->outputType_null) {
                return $ret;
            }
        }

        private function fillInQueryTemplate ($template, $paramName, $paramValue) {
            $paramValue = $this->unicodeEncode ($paramValue);
            $template = str_replace('%' . $paramName . '%', $paramValue, $template);
            return $template;
        }

        private function proofQuery ($query) {
            if (preg_match('/\x25[^\x25]+\x25/', $query) !== 0) {
                trigger_error(DbProxy::UNMATCHED_STUB_ARGUMENTS, E_USER_ERROR);
            }
        }

        private function getClientResource ($clientClsName) {
            return $this->resourceLinks[$clientClsName];
        }

        private function executeQuery ($query) {
            return mysql_query ($query, $this->getClientResource($this->currClientClsName));
        }

        private function fetchQueryResult ($result, $type) {
            $fetchedResult = array ();
            $numRows = 0;
            $affectedRows = 0;
            if (!is_resource($result)) {
                if ($result === false) {
                    $err = mysql_error($this->getClientResource($this->currClientClsName));
                    $err = $this->makeReadable($err);
                    $err = trim ($err);
                    if ($err !== "") {
                        $errNo = mysql_errno($this->getClientResource($this->currClientClsName));
                        trigger_error(DbProxy::SQL_QUERY_FAILED . "\n" . $errNo . ": " . $err,
                            E_USER_ERROR);
                    }
                }
                $affectedRows = mysql_affected_rows ($this->getClientResource ($this->
                	currClientClsName));
            } else {
                if ($type !== $this->outputType_null) {
                    if ($type !== $this->outputType_boolean) {
                        while ($row = mysql_fetch_array ($result, MYSQL_NUM)) {
                            array_push($fetchedResult, $row);
                        }
                    }
                    $numRows = mysql_num_rows ($result);
                    $affectedRows = mysql_affected_rows ($this->getClientResource (
                        $this->currClientClsName));
                    mysql_freeresult($result);
                } else {
                    mysql_freeresult($result);
                    return null;
                }
            }
            switch ($type) {
                case $this->outputType_boolean:
                    if ($result === false) {
                        return false;
                    } else {
                        $numericAnswer = max($affectedRows, $numRows);
                        if ($numericAnswer > 0) {
                            return true;
                        }
                    }
                    return false;
                    break;
                case $this->outputType_number:
                    if (count ($fetchedResult) === 1) {
                        foreach ($fetchedResult as $row) {
                            if (count ($row) === 1) {
                                foreach ($row as $value) {
									// Attempt to recognize the result as a numeric value:
                                	$value = $this->convertNumericStr ($value);
                                	// Case 1:
                                	// Result is a numeric string literal:
                                    if (is_int($value) || is_float($value)) {
                                        return $value;
                                    }
                                	// Case 2:
                                	// Result is not a numeric string literal; however, there's allways
                                	// the chance that we're dealing with some number that was stored in
                                	// the database AS A STRING, and hence, it was ENCODDED.
                                	//
                                	// Therefore, we attempt to decode it and will try to recognize it
                                	// as a valid number one more time.
                                	//
                                	// NOTE:
                                	// The encodding algorithm doesn't produce valid numerics, so we're
                                	// on the safe side.
                                    if (is_string ($value)) {
                                        $value = $this->unicodeDecode ($value);
                                        if (is_string ($value) && is_numeric ($value)) {
											return $this->convertNumericStr ($value);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    // The result itself failed to be interpreted as a number, so we fallback to our
                    // last resource of numeric information for this transaction:
                    $numericAnswer = max($affectedRows, $numRows);
                    return $numericAnswer;
                    break;
                case $this->outputType_array:
                    if (count ($fetchedResult) > 0) {
                        for ($i=0; $i<count($fetchedResult); $i++) {
                            $decodedRow = array ();
                            $row = $fetchedResult[$i];
                            foreach ($row as $key => $value) {
                                if (is_string ($value)) { // can also be null
                                    $value = $this->unicodeDecode($value);
                                }
                                $decodedRow [$this->unicodeDecode($key)] = $value;
                            }
                            $fetchedResult[$i] = $decodedRow;
                        }
                    }
                    return $fetchedResult;
                    break;
                case $this->outputType_string:
                    if (count ($fetchedResult) === 1) {
                        foreach ($fetchedResult as $row) {
                            if (count ($row) === 1) {
                                foreach ($row as $value) {
                                    if (is_string($value)) {
                                        $value = $this->unicodeDecode($value);
                                        return $value;
                                    }
                                    if (is_int ($value) || is_float ($value)) {
                                        return "" . $value;
                                    }
                                    if (is_bool ($value)) {
                                        return $value? "true" : "false";
                                    }
                                }
                            }
                        }
                    } elseif (count ($fetchedResult) > 0) {
                        $ret = "";
                        for ($i=0; $i<count($fetchedResult); $i++) {
                            $row = $fetchedResult[$i];
                            foreach ($row as $key => $value) {
                                if (is_string($value)) {
                                    $value = $this->unicodeDecode($value);
                                }
                                $key = $this->unicodeDecode($key);
                                if ($ret !== "") {
                                    $ret .= "&";
                                }
                                $ret .= $key . "_" . $i . "=" . $value;
                            }
                        }
                        return $ret;
                    } elseif (max ($affectedRows, $numRows) > 0) {
                        if ($numRows > $affectedRows) {
                            return $numRows . " rows in set";
                        }
                        if ($affectedRows > $numRows) {
                            return $affectedRows . " rows affected";
                        }
                    } elseif ($fetchedResult === true) {
                        return DbProxy::SUCCESS;
                    }
                    return DbProxy::FAILURE;
                    break;
            }
            return null;
        }

		private function convertNumericStr ($value) {
	        $isNegative = $value[0] == "-";
	        $hasDecimalPart = (stripos($value,".") !== false);
	        $hasExponentialPart = (stripos($value,"e") !== false);
	        $converted = 0;
	        if ($hasDecimalPart || $hasExponentialPart) {
	            $converted = (float) $value;
	        } else {
	           $converted = (int) $value;
	        }
	        if ($isNegative && $converted > 0) {
	           $converted *= -1;
	        }
	        if ("" . $converted === $value) {
	            return $converted;
	        }
		}

		private function getUnicodePoints ($utf8String) {
			return utf8ToUnicode ($utf8String);
		}

		private function getUtf8String ($unicodePoints) {
			return unicodeToUtf8 ($unicodePoints);
		}

        private function unicodeEncode ($value) {
            if (is_int($value) || is_float($value)) {
				return $value;
            }
            $points = $this->getUnicodePoints($value);
			$ret = array ();
            for ($i=0; $i<count($points); $i++) {
            	$point = $points [$i];
            	$point = dechex ($point);
				$point = strtoupper ($point);
                $encPointChars = array ();
                $encPoint = "";
                /* Requirements:
                 * - first char must be an upercase letter, but not letter E
                 * - subsequent chars can be digits or upercase letters, as long as these letters are
                 *   different than the subset of letters used by the first char
                 */
                for ($j=0; $j<strlen($point); $j++) {
					$char = ord ($point [$j]);
					if ($j == 0) {
						// first char, digits:
						if ($char >= 48 && $char <= 57) {
							$encChar = $this->digitToLettersMap [$char];
						} else {
							// first char, A to F letters:
							$char += 11;
							$encChar = chr ($char);
						}
					} else {
						// subsequent chars, digits (leave unchanged):
						if ($char >= 48 && $char <= 57) {
							$encChar = $point [$j];
						} else {
							// subsequent chars, A to F letters:
							$char +=17;
							$encChar = chr ($char);
						}
					}
					$encPointChars[$j] = $encChar;
                }
                $encPoint = implode("", $encPointChars);
                $ret[$i] = $encPoint;
			}
			return implode ("", $ret);
        }

        private function unicodeDecode ($value) {
			if (is_int($value)) { // could be the key of an array
				return $value;
        	} elseif (is_string($value)) {
				if (is_numeric($value)) {
					return $this->convertNumericStr ($value);
				}
				$tokens = array ();
				$token = array ();
				for ($i=0; $i<strlen($value); $i++) {
					$chIndex = ord ($value[$i]);
					// Upper letters A to K (except E) are the delimiters
					if ($chIndex >= 65 && $chIndex <= 75) {
						if (count ($token) !== 0) {
							array_push ($tokens, strtoupper (implode ("", $token)));
							$token = array ();
						}
					}
					array_push($token, $value[$i]);
				}
				// add last token by hand
				array_push ($tokens, strtoupper (implode ("", $token)));
				$points = array ();
				foreach ($tokens as $encToken) {
					$unencToken = array ();
					$unencChar = "";
					for ($j=0; $j<strlen($encToken); $j++) {
						$char = ord ($encToken [$j]);
						if ($j == 0) {
							// first char, uppercase letters, A to K (except E):
							if ($char >= 65 && $char <= 75) {
								$result = array_search(chr ($char), $this->digitToLettersMap, true);
								$unencChar = chr ($result);
							} else {
								// first char, uppercase letters L to K
								$unencChar = chr ($char - 11);
							}
						} else {
							// subsequent chars, digits (accept as they are):
							if ($char >= 48 && $char <= 57) {
								$unencChar = chr ($char);
							} else {
								// subsequent chars, uppercase letters R to W
								$unencChar = chr ($char - 17);
							}
						}
						$unencToken [$j] = $unencChar;
					}
					$unencToken = implode ("", $unencToken);
					array_push($points, hexdec($unencToken));
				}
				return $this->getUtf8String ($points);
        	}
        	return null;
        }

        private function makeReadable ($str) {
        	$matches = array ();
        	$pattern = $this->encIdentifierNamePatt;
            preg_match_all($pattern, $str, $matches);
            if (count ($matches) === 0) {
				return $str;
            }
            foreach ($matches[0] as $match) {
            	$match = trim ($match, "\"'`");
				$str = str_replace($match, $this->unicodeDecode($match), $str);
            }
            return $str;
        }

        private function getThisClassName () {
            $ret = array ();
            $name = get_class($this);
            preg_match('/\w+$/', $name, $ret);
            return $ret[0];
        }

        private function getParentClassName () {
            $ret = array();
            $name = get_parent_class($this);
            preg_match('/\w+$/', $name, $ret);
            return $ret[0];
        }

        private function safePassPattern () {
            $patt = '';
            for ($i=33; $i<127; $i++) {
                if (array_search($i, $this->mysqlForbiddenChars, true) === false) {
                   $patt .= '\\x' . dechex($i);
                }
            }
            $patt = '/^[' .  $patt . ']+$/';
            return $patt;
        }

        private function hostPattern () {
            $patt = '/^(?:[a-z0-9])(?:[a-z0-9\-]{0,62}?)';
            for ($i; $i<126; $i++) {
                $patt .= '(?:\.(?:[a-z0-9\-]{1,62}?))?';
            }
            $patt .= '(?:\.(?:[a-z0-9\-]{0,62}?))?';
            $patt .= '(?:[a-z0-9])$/';
            return $patt;
        }

        private function makeEncIdentifierPattern () {
			return "/(\\x22|\\x27|\\x60)[ABCDFGHIJKLMNOPQ][0123456789RSTUVW]{1}" .
				str_repeat("(?:[ABCDFGHIJKLMNOPQ][0123456789RSTUVW]{1})?",
					($this->identifierMaxChars - 2) / 2) . "\\1/";
        }
    }
?>
Return current item: DbProxy