/** * Creates the time to represent, no timezone is allowed since times don't have timezones * * @throws fValidationException When `$time` is not a valid time * * @param fTime|object|string|integer $time The time to represent, `NULL` is interpreted as now * @return fTime */ public function __construct($time = NULL) { if ($time === NULL) { $timestamp = time(); } elseif (is_numeric($time) && ctype_digit($time)) { $timestamp = (int) $time; } elseif (is_string($time) && in_array(strtoupper($time), array('CURRENT_TIMESTAMP', 'CURRENT_TIME'))) { $timestamp = time(); } else { if (is_object($time) && is_callable(array($time, '__toString'))) { $time = $time->__toString(); } elseif (is_numeric($time) || is_object($time)) { $time = (string) $time; } $time = fTimestamp::callUnformatCallback($time); $timestamp = strtotime($time); } $is_51 = fCore::checkVersion('5.1'); $is_valid = $is_51 && $timestamp !== FALSE || !$is_51 && $timestamp !== -1; if (!$is_valid) { throw new fValidationException('The time specified, %s, does not appear to be a valid time', $time); } $this->time = strtotime(date('1970-01-01 H:i:s', $timestamp)); }
/** * Creates the date to represent, no timezone is allowed since dates don't have timezones * * @throws fValidationException When `$date` is not a valid date * * @param fDate|object|string|integer $date The date to represent, `NULL` is interpreted as today * @return fDate */ public function __construct($date = NULL) { if ($date === NULL) { $timestamp = time(); } elseif (is_numeric($date) && preg_match('#^-?\\d+$#D', $date)) { $timestamp = (int) $date; } elseif (is_string($date) && in_array(strtoupper($date), array('CURRENT_TIMESTAMP', 'CURRENT_DATE'))) { $timestamp = time(); } else { if (is_object($date) && is_callable(array($date, '__toString'))) { $date = $date->__toString(); } elseif (is_numeric($date) || is_object($date)) { $date = (string) $date; } $date = fTimestamp::callUnformatCallback($date); $timestamp = strtotime(fTimestamp::fixISOWeek($date)); } $is_51 = fCore::checkVersion('5.1'); $is_valid = $is_51 && $timestamp !== FALSE || !$is_51 && $timestamp !== -1; if (!$is_valid) { throw new fValidationException('The date specified, %s, does not appear to be a valid date', $date); } $this->date = strtotime(date('Y-m-d 00:00:00', $timestamp)); }
/** * Sets a cookie to be sent back to the browser - uses default parameters set by the other set methods of this class * * The following methods allow for setting default parameters for this method: * * - ::setDefaultExpires(): Sets the default for the `$expires` parameter * - ::setDefaultPath(): Sets the default for the `$path` parameter * - ::setDefaultDomain(): Sets the default for the `$domain` parameter * - ::setDefaultSecure(): Sets the default for the `$secure` parameter * - ::setDefaultHTTPOnly(): Sets the default for the `$httponly` parameter * * @param string $name The name of the cookie to set * @param mixed $value The value of the cookie to set * @param string|integer $expires A relative string to be interpreted by [http://php.net/strtotime strtotime()] or an integer unix timestamp * @param string $path The path this cookie applies to * @param string $domain The domain this cookie applies to * @param boolean $secure If the cookie should only be transmitted over a secure connection * @param boolean $httponly If the cookie should only be readable by HTTP connection, not javascript * @return void */ public static function set($name, $value, $expires = NULL, $path = NULL, $domain = NULL, $secure = NULL, $httponly = NULL) { if ($expires === NULL && self::$default_expires !== NULL) { $expires = self::$default_expires; } if ($path === NULL && self::$default_path !== NULL) { $path = self::$default_path; } if ($domain === NULL && self::$default_domain !== NULL) { $domain = self::$default_domain; } if ($secure === NULL && self::$default_secure !== NULL) { $secure = self::$default_secure; } if ($httponly === NULL && self::$default_httponly !== NULL) { $httponly = self::$default_httponly; } if ($expires && !is_numeric($expires)) { $expires = strtotime($expires); } // Adds support for httponly cookies to PHP 5.0 and 5.1 if (strlen($value) && $httponly && !fCore::checkVersion('5.2')) { $header_string = urlencode($name) . '=' . urlencode($value); if ($expires) { $header_string .= '; expires=' . gmdate('D, d-M-Y H:i:s T', $expires); } if ($path) { $header_string .= '; path=' . $path; } if ($domain) { $header_string .= '; domain=' . $domain; } if ($secure) { $header_string .= '; secure'; } $header_string .= '; httponly'; header('Set-Cookie: ' . $header_string, FALSE); return; // Only pases the httponly parameter if we are on 5.2 since it causes error notices otherwise } elseif (strlen($value) && $httponly) { setcookie($name, $value, $expires, $path, $domain, $secure, TRUE); return; } setcookie($name, $value, $expires, $path, $domain, $secure); }
/** * Checks to make sure the current version of PHP is high enough to support timezone features * * @return void */ private static function checkPHPVersion() { if (!fCore::checkVersion('5.1')) { throw new fEnvironmentException('The %s class takes advantage of the timezone features in PHP 5.1.0 and newer. Unfortunately it appears you are running an older version of PHP.', __CLASS__); } }
/** * Closes the open database connection * * @internal * * @return void */ public function __destruct() { if (!$this->connection) { return; } fCore::debug('Total query time: ' . $this->query_time . ' seconds', $this->debug); if ($this->extension == 'ibm_db2') { db2_close($this->connection); } elseif ($this->extension == 'mssql') { mssql_close($this->connection); } elseif ($this->extension == 'mysql') { mysql_close($this->connection); } elseif ($this->extension == 'mysqli') { // Before 5.2.0 the destructor order would cause mysqli to // close itself which would make this call trigger a warning if (fCore::checkVersion('5.2.0')) { mysqli_close($this->connection); } } elseif ($this->extension == 'oci8') { oci_close($this->connection); } elseif ($this->extension == 'pgsql') { pg_close($this->connection); } elseif ($this->extension == 'sqlite') { sqlite_close($this->connection); } elseif ($this->extension == 'sqlsrv') { sqlsrv_close($this->connection); } elseif ($this->extension == 'pdo') { // PDO objects close their own connections when destroyed } $this->connection = FALSE; }
/** * Reads responses from the server * * @param integer|string $expect The expected number of lines of response or a regex of the last line * @return array The lines of response from the server */ private function read($expect = NULL) { $read = array($this->connection); $write = NULL; $except = NULL; $response = array(); // PHP 5.2.0 to 5.2.5 has a bug on amd64 linux where stream_select() // fails, so we have to fake it - http://bugs.php.net/bug.php?id=42682 static $broken_select = NULL; if ($broken_select === NULL) { $broken_select = strpos(php_uname('m'), '64') !== FALSE && fCore::checkVersion('5.2.0') && !fCore::checkVersion('5.2.6'); } // Fixes an issue with stream_select throwing a warning on PHP 5.3 on Windows if (fCore::checkOS('windows') && fCore::checkVersion('5.3.0')) { $select = @stream_select($read, $write, $except, $this->timeout); } elseif ($broken_select) { $broken_select_buffer = NULL; $start_time = microtime(TRUE); $i = 0; do { if ($i) { usleep(50000); } $char = fgetc($this->connection); if ($char != "" && $char !== FALSE) { $broken_select_buffer = $char; } $i++; } while ($broken_select_buffer === NULL && microtime(TRUE) - $start_time < $this->timeout); $select = $broken_select_buffer !== NULL; } else { $select = stream_select($read, $write, $except, $this->timeout); } if ($select) { while (!feof($this->connection)) { $line = fgets($this->connection); if ($line === FALSE) { break; } $line = substr($line, 0, -2); // When we fake select, we have to handle what we've retrieved if ($broken_select && $broken_select_buffer !== NULL) { $line = $broken_select_buffer . $line; $broken_select_buffer = NULL; } $response[] = $line; // Automatically stop at the termination octet or a bad response if ($this->type == 'pop3' && ($line == '.' || count($response) == 1 && $response[0][0] == '-')) { break; } if ($expect !== NULL) { $matched_number = is_int($expect) && sizeof($response) == $expect; $matched_regex = is_string($expect) && preg_match($expect, $line); if ($matched_number || $matched_regex) { break; } } } } if (fCore::getDebug($this->debug)) { fCore::debug("Received:\n" . join("\r\n", $response), $this->debug); } if ($this->type == 'pop3') { // Remove the termination octet if ($response && $response[sizeof($response) - 1] == '.') { $response = array_slice($response, 0, -1); } // Remove byte-stuffing $lines = count($response); for ($i = 0; $i < $lines; $i++) { if (strlen($response[$i]) && $response[$i][0] == '.') { $response[$i] = substr($response[$i], 1); } } } return $response; }
/** * Reads responses from the server * * @param integer|string $expect The expected number of lines of response or a regex of the last line * @return array The lines of response from the server */ private function read($expect = NULL) { $read = array($this->connection); $write = NULL; $except = NULL; $response = array(); // Fixes an issue with stream_select throwing a warning on PHP 5.3 on Windows if (fCore::checkOS('windows') && fCore::checkVersion('5.3.0')) { $select = @stream_select($read, $write, $except, $this->timeout); } else { $select = stream_select($read, $write, $except, $this->timeout); } if ($select) { while (!feof($this->connection)) { $line = substr(fgets($this->connection), 0, -2); $response[] = $line; // Automatically stop at the termination octet or a bad response if ($this->type == 'pop3' && ($line == '.' || count($response) == 1 && $response[0][0] == '-')) { break; } if ($expect !== NULL) { $matched_number = is_int($expect) && sizeof($response) == $expect; $matched_regex = is_string($expect) && preg_match($expect, $line); if ($matched_number || $matched_regex) { break; } } } } if (fCore::getDebug($this->debug)) { fCore::debug("Recieved:\n" . join("\r\n", $response), $this->debug); } if ($this->type == 'pop3') { // Remove the termination octet if ($response && $response[sizeof($response) - 1] == '.') { $response = array_slice($response, 0, -1); } // Remove byte-stuffing $lines = count($response); for ($i = 0; $i < $lines; $i++) { if (strlen($response[$i]) && $response[$i][0] == '.') { $response[$i] = substr($response[$i], 1); } } } return $response; }
/** * Takes an array of PHP files and caches a version with all short tags converted to regular tags * * @param array $values The file paths to the PHP files * @return array An array of file paths to the corresponding converted PHP files */ private function fixShortTags($values) { $fixed_paths = array(); foreach ($values as $value) { // Check to see if the element is a path relative to the template root if (!preg_match('#^(/|\\\\|[a-z]:(\\\\|/)|\\\\|//|\\./|\\.\\\\)#i', $value)) { $value = $this->root . $value; } $real_value = realpath($value); $cache_path = $this->short_tag_directory . sha1($real_value) . '.php'; $fixed_paths[] = $cache_path; if (file_exists($cache_path) && ($this->short_tag_mode == 'production' || filemtime($cache_path) >= filemtime($real_value))) { continue; } $code = file_get_contents($real_value); $output = ''; $in_php = FALSE; do { if (!$in_php) { $token_regex = '<\\?'; } else { $token_regex .= '/\\*|//|\\#|\'|"|<<<[a-z_]\\w*|<<<\'[a-z_]\\w*\'|\\?>'; } if (!preg_match('#' . $token_regex . '#i', $code, $match)) { $part = $code; $code = ''; $token = NULL; } else { $token = $match[0]; $pos = strpos($code, $token); if ($pos === FALSE) { break; } $part = substr($code, 0, $pos); $code = substr($code, $pos); } $regex = NULL; if ($token == "<?") { $output .= $part; $in_php = TRUE; continue; } elseif ($token == "?>") { $regex = NULL; $in_php = FALSE; } elseif ($token == "//") { $regex = '#^//.*(\\n|$)#D'; } elseif ($token == "#") { $regex = '@^#.*(\\n|$)@D'; } elseif ($token == "/*") { $regex = '#^.{2}.*?(\\*/|$)#sD'; } elseif ($token == "'") { $regex = '#^\'((\\\\.)+|[^\\\\\']+)*(\'|$)#sD'; } elseif ($token == '"') { $regex = '#^"((\\\\.)+|[^\\\\"]+)*("|$)#sD'; } elseif ($token) { $regex = '#\\A<<<\'?([a-zA-Z_]\\w*)\'?.*?^\\1;\\n#sm'; } $part = str_replace('<?=', '<?php echo', $part); $part = preg_replace('#<\\?(?!php)#i', '<?php', $part); // This makes sure that __FILE__ and __DIR__ stay as the // original value since the cached file will be in a different // place with a different filename $part = preg_replace('#(?<=[^a-zA-Z0-9]|^)__FILE__(?=[^a-zA-Z0-9]|$)#iD', "'" . $real_value . "'", $part); if (fCore::checkVersion('5.3')) { $part = preg_replace('#(?<=[^a-zA-Z0-9]|^)__DIR__(?=[^a-zA-Z0-9]|$)#iD', "'" . dirname($real_value) . "'", $part); } $output .= $part; if ($regex) { preg_match($regex, $code, $match); $output .= $match[0]; $code = substr($code, strlen($match[0])); } } while (strlen($code)); file_put_contents($cache_path, $output); } return $fixed_paths; }
/** * Registers a callback for an fActiveRecord method that falls through to fActiveRecord::__callStatic() or hits a predefined method hook * * Only available to PHP 5.3+ which supports the __callStatic magic method. * * The callback should accept the following parameters: * * - **`&$class`**: The class calling the static method * - **`$method_name`**: The method that was called * - **`&$parameters`**: The parameters passed to the method * * @throws fProgrammerException When the PHP version less than 5.3 * * @param mixed $class The class name or instance of the class to register for, `'*'` will register for all classes * @param string $method The method to hook for - this can be a complete method name or `{prefix}*` where `*` will match any column name * @param callback $callback The callback to execute - see method description for parameter list * @return void */ public static function registerActiveRecordStaticMethod($class, $method, $callback) { if (!fCore::checkVersion('5.3')) { throw new fProgrammerException('fORM::registerActiveRecordStaticMethod is only available to PHP 5.3+', $method); } $class = self::getClass($class); if (!isset(self::$active_record_static_method_callbacks[$class])) { self::$active_record_static_method_callbacks[$class] = array(); } if (is_string($callback) && strpos($callback, '::') !== FALSE) { $callback = explode('::', $callback); } self::$active_record_static_method_callbacks[$class][$method] = $callback; self::$cache['getActiveRecordStaticMethod'] = array(); }
/** * Performs a "fixed" stream_select() for the connection * * @param integer $timeout The number of seconds in the timeout * @param integer $utimeout The number of microseconds in the timeout * @return boolean|string TRUE (or a character) is the connection is ready to be read from, FALSE if not */ private function select($timeout, $utimeout) { $read = array($this->connection); $write = NULL; $except = NULL; // PHP 5.2.0 to 5.2.5 had a bug on amd64 linux where stream_select() // fails, so we have to fake it - http://bugs.php.net/bug.php?id=42682 static $broken_select = NULL; if ($broken_select === NULL) { $broken_select = strpos(php_uname('m'), '64') !== FALSE && fCore::checkVersion('5.2.0') && !fCore::checkVersion('5.2.6'); } // Fixes an issue with stream_select throwing a warning on PHP 5.3 on Windows if (fCore::checkOS('windows') && fCore::checkVersion('5.3.0')) { $select = @stream_select($read, $write, $except, $timeout, $utimeout); } elseif ($broken_select) { $broken_select_buffer = NULL; $start_time = microtime(TRUE); $i = 0; do { if ($i) { usleep(50000); } $char = fgetc($this->connection); if ($char != "" && $char !== FALSE) { $broken_select_buffer = $char; } $i++; if ($i > 2) { break; } } while ($broken_select_buffer === NULL && microtime(TRUE) - $start_time < $timeout + $utimeout / 1000000); $select = $broken_select_buffer === NULL ? FALSE : $broken_select_buffer; } else { $select = stream_select($read, $write, $except, $timeout, $utimeout); } return $select; }
/** * Reads lines from the SMTP server * * @param integer|string $expect The expected number of lines of response or a regex of the last line * @return array The lines of response from the server */ private function read($expect) { $read = array($this->connection); $write = NULL; $except = NULL; $response = array(); // Fixes an issue with stream_select throwing a warning on PHP 5.3 on Windows if (fCore::checkOS('windows') && fCore::checkVersion('5.3.0')) { $select = @stream_select($read, $write, $except, $this->timeout); } else { $select = stream_select($read, $write, $except, $this->timeout); } if ($select) { while (!feof($this->connection)) { $read = array($this->connection); $write = $except = NULL; $response[] = substr(fgets($this->connection), 0, -2); if ($expect !== NULL) { $matched_number = is_int($expect) && sizeof($response) == $expect; $matched_regex = is_string($expect) && preg_match($expect, $response[sizeof($response) - 1]); if ($matched_number || $matched_regex) { break; } } elseif (!stream_select($read, $write, $except, 0, 200000)) { break; } } } if (fCore::getDebug($this->debug)) { fCore::debug("Received:\n" . join("\r\n", $response), $this->debug); } $this->handleErrors($response); return $response; }