function email_plugin_notify($check,$check_result,$subscription,$alt_email=false) { global $status_array; $user = new User($subscription->getUserId()); $email = new fEmail(); // This sets up fSMTP to connect to the gmail SMTP server // with a 5 second timeout. Gmail requires a secure connection. $smtp = new fSMTP(sys_var('smtp_server'), sys_var('smtp_port'), TRUE, 5); $smtp->authenticate(sys_var('smtp_user'), sys_var('smtp_pass')); if ($alt_email) { $email_address = usr_var('alt_email',$user->getUserId()); } else { $email_address = $user->getEmail(); } $email->addRecipient($email_address, $user->getUsername()); // Set who the email is from $email->setFromEmail(sys_var('email_from'), sys_var('email_from_display')); // Set the subject include UTF-8 curly quotes $email->setSubject(str_replace('{check_name}', $check->prepareName(), sys_var('email_subject'))); // Set the body to include a string containing UTF-8 $state = $status_array[$check_result->getStatus()]; $email->setHTMLBody("<p>$state Alert for {$check->prepareName()} </p><p>The check returned {$check_result->prepareValue()}</p><p>Warning Threshold is : ". $check->getWarn() . "</p><p>Error Threshold is : ". $check->getError() . '</p><p>View Alert Details : <a href="' . fURL::getDomain() . '/' . CheckResult::makeURL('list',$check_result) . '">'.$check->prepareName()."</a></p>"); $email->setBody(" $state Alert for {$check->prepareName()} The check returned {$check_result->prepareValue()} Warning Threshold is : ". $check->getWarn() . " Error Threshold is : ". $check->getError() . " "); try { $message_id = $email->send($smtp); } catch ( fConnectivityException $e) { fCore::debug("email send failed",FALSE); } }
function email_notify($check,$check_result,$subscription) { global $status_array; $user = new User($subscription->getUserId()); echo 'email plugin!'; $email = new fEmail(); // This sets up fSMTP to connect to the gmail SMTP server // with a 5 second timeout. Gmail requires a secure connection. $smtp = new fSMTP('smtp.gmail.com', 465, TRUE, 5); $smtp->authenticate('*****@*****.**', 'example'); $email->addRecipient($user->getEmail(), $user->getUsername()); // Set who the email is from $email->setFromEmail('*****@*****.**','Tattle'); // Set the subject include UTF-8 curly quotes $email->setSubject('Tattle : Alert for ' . $check->prepareName()); // Set the body to include a string containing UTF-8 $state = $status_array[$check_result->getStatus()]; $email->setHTMLBody("<p>$state Alert for {$check->prepareName()} </p><p>The check returned {$check_result->prepareValue()}</p><p>Warning Threshold is : ". $check->getWarn() . "</p><p>Error Threshold is : ". $check->getError() . '</p><p>View Alert Details : <a href="' . $fURL::getDomain() . '/' . CheckResult::makeURL('list',$check_result) . '">'.$check->prepareName()."</a></p>"); $email->setBody(" $state Alert for {$check->prepareName()} The check returned {$check_result->prepareValue()} Warning Threshold is : ". $check->getWarn() . " Error Threshold is : ". $check->getError() . " "); try { $message_id = $email->send($smtp); } catch ( fConnectivityException $e) { fCore::debug("email send failed",FALSE); } }
public function setUp() { $_SERVER['SERVER_NAME'] = 'flourishlib.com'; if (defined('EMAIL_DEBUG')) { fCore::enableDebugging(TRUE); } }
/** * Finishing placing elements if buffering was used * * @internal * * @return void */ public function __destruct() { // The __destruct method can't throw unhandled exceptions intelligently, so we will always catch here just in case try { $this->placeBuffered(); } catch (Exception $e) { fCore::handleException($e); } }
public function setUp() { if (defined('SKIPPING') || !defined('EMAIL_PASSWORD')) { $this->markTestSkipped(); } $_SERVER['SERVER_NAME'] = 'flourishlib.com'; if (defined('EMAIL_DEBUG')) { fCore::enableDebugging(TRUE); } }
function hipchat_master_notify($check, $check_result, $subscription, $toUser = true) { global $status_array; global $debug; if (!is_callable('curl_init')) { fCore::debug("!!! WARNING !!! function curl_init() not found, probably php-curl is not installed"); } $state = $status_array[$check_result->getStatus()]; if (strtolower($state) == 'ok') { $color = sys_var('hipchat_ok_color'); } elseif (strtolower($state) == 'warning') { $color = sys_var('hipchat_warning_color'); } elseif (strtolower($state) == 'error') { $color = sys_var('hipchat_error_color'); } $url = $GLOBALS['TATTLE_DOMAIN'] . '/' . CheckResult::makeURL('list', $check_result); $data = array('color' => $color, 'notify' => sys_var('hipchat_notify') == 'true' ? true : false, 'message_format' => 'html', 'message' => "<b>" . $check->prepareName() . "</b><br />The check returned: {$check_result->getValue()}<br />View Alert Details : <a href=\"" . $url . "\">" . $url . "</a>"); if ($debug && $toUser == false) { $url = 'https://api.hipchat.com/v2/room?auth_token=' . sys_var('hipchat_apikey'); $c = curl_init(); curl_setopt($c, CURLOPT_URL, $url); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); fCore::debug("Rooms: " . curl_exec($c) . "\n", FALSE); fCore::debug("URL: " . 'https://api.hipchat.com/v2/room/' . strtolower(sys_var('hipchat_room')) . '/notification?auth_token=' . sys_var('hipchat_apikey') . "\n", FALSE); fCore::debug("Data: " . print_r($data, true) . "\n", FALSE); } if ($toUser == false) { $url = 'https://api.hipchat.com/v2/room/' . strtolower(sys_var('hipchat_room')) . '/notification?auth_token=' . sys_var('hipchat_apikey'); } else { $url = 'https://api.hipchat.com/v2/user/' . usr_var('hipchat_user', $subscription->getUserId()) . '/message?auth_token=' . sys_var('hipchat_apikey'); } fCore::debug("HipChat Calling: {$url}", FALSE); $c = curl_init(); curl_setopt($c, CURLOPT_URL, $url); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen(json_encode($data)))); curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($data)); $response = curl_exec($c); if ($response === false) { fCore::debug("Curl error: " . curl_error($c) . "\n", FALSE); } echo "\n\nResponse: " . curl_getinfo($c, CURLINFO_HTTP_CODE) . ' - ' . $response . "\n\n"; }
/** * 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)); }
public function tearDown() { // There seems to be an issue with the sybase driver on netbsd which this // test triggers, causing a segfault if (DB_TYPE == 'mssql' && fCore::checkOS('netbsd')) { return; } if (defined('SKIPPING')) { return; } fORMDatabase::retrieve()->enableDebugging(FALSE); fORMRelated::reset(); }
/** * Throws an exception if the directory has been deleted * * @return void */ protected function tossIfDeleted() { if ($this->deleted) { throw new fProgrammerException("The action requested can not be performed because the directory has been deleted\n\nBacktrace for fDirectory::delete() call:\n%s", fCore::backtrace(0, $this->deleted)); } }
/** * Adds the email address the email will be bounced to * * This email address will be set to the `Return-Path` header. * * @param string $email The email address to bounce to * @return void */ public function setBounceToEmail($email) { if (ini_get('safe_mode') && !fCore::checkOS('windows')) { throw new fProgrammerException('It is not possible to set a Bounce-To Email address when safe mode is enabled on a non-Windows server'); } if (!$email) { return; } $this->bounce_to_email = $this->combineNameEmail('', $email); }
/** * Translates Flourish SQL into the dialect for the current database * * @internal * * @param array $statements The SQL statements to translate * @return array The translated SQL statements all ready for execution. Statements that have been translated will have string key of the number, `:` and the original SQL, all other will have a numeric key. */ public function translate($statements) { $output = array(); foreach ($statements as $number => $sql) { // These fixes don't need to know about strings $new_sql = $this->translateBasicSyntax($sql); if (in_array($this->database->getType(), array('mssql', 'oracle', 'db2'))) { $new_sql = $this->translateLimitOffsetToRowNumber($new_sql); } // SQL Server does not like to give unicode results back to PHP without some coersion if ($this->database->getType() == 'mssql') { $new_sql = $this->fixMSSQLNationalColumns($new_sql); } // Oracle has this nasty habit of silently translating empty strings to null if ($this->database->getType() == 'oracle') { $new_sql = $this->fixOracleEmptyStrings($new_sql); } $extra_statements = array(); $new_sql = $this->translateCreateTableStatements($new_sql, $extra_statements); if ($sql != $new_sql || $extra_statements) { fCore::debug(self::compose("Original SQL:%s", "\n" . $sql), $this->debug); $translated_sql = $new_sql; if ($extra_statements) { $translated_sql .= '; ' . join('; ', $extra_statements); } fCore::debug(self::compose("Translated SQL:%s", "\n" . $translated_sql), $this->debug); } $output = array_merge($output, array($number . ':' . $sql => $new_sql), $extra_statements); } return $output; }
/** * @dataProvider serverProvider */ public function testListGet($type, $host, $port, $secure, $username, $password) { $mailbox = new fMailbox($type, $host, $username, $password, $port, $secure, 5); fMailbox::addSMIMEPair('*****@*****.**', './email/tests@flourishlib.com.crt', './email/tests@flourishlib.com.key', EMAIL_PASSWORD); $messages = array(); foreach ($mailbox->listMessages() as $uid => $overview) { $info = $mailbox->fetchMessage($uid); if (!isset($info['headers'])) { fCore::expose($info); } $messages[$info['headers']['message-id']] = array('subject' => $info['headers']['subject'], 'from' => $info['headers']['from']['mailbox'] . '@' . $info['headers']['from']['host'], 'to' => $info['headers']['to'][0]['mailbox'] . '@' . $info['headers']['from']['host'], 'verified' => !empty($info['verified']) ? $info['verified'] : NULL, 'decrypted' => !empty($info['decrypted']) ? $info['decrypted'] : NULL); } $expected_output = array('<*****@*****.**>' => array('subject' => 'A Tést of Iñtërnâtiônàlizætiøn', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'UTF-8 …', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'More UTF-8: ⅞ ⅝ ⅜ ⅛', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Attachments Test', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Inline Images and Attachments', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Multiple To and Cc', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Re: Multiple To and Cc', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Re: Multiple To and Cc', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Re: Multiple To and Cc', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Re: Multiple To and Cc', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'Re: Multiple To and Cc', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'This message has been signed', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => TRUE, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'This message has also been signed', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => TRUE, 'decrypted' => NULL)); if ($username == '*****@*****.**') { $expected_output['<*****@*****.**>'] = array('subject' => 'This message is signed and encrypted', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => TRUE, 'decrypted' => TRUE); $expected_output['<*****@*****.**>'] = array('subject' => 'This message is encrypted', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => TRUE); } $expected_output = array_merge($expected_output, array('<*****@*****.**>' => array('subject' => 'This is a test of fEmail signing', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => TRUE, 'decrypted' => NULL), '<*****@*****.**>' => array('subject' => 'This is a test of fEmail encryption', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => NULL, 'decrypted' => TRUE), '<*****@*****.**>' => array('subject' => 'This is a test of fEmail encryption + signing', 'from' => '*****@*****.**', 'to' => '*****@*****.**', 'verified' => TRUE, 'decrypted' => TRUE))); $this->assertEquals($expected_output, $messages); }
/** * Makes sure that the PRNG has been seeded with a fairly secure value * * @return void */ private static function seedRandom() { static $seeded = FALSE; if ($seeded) { return; } $old_level = error_reporting(error_reporting() & ~E_WARNING); $bytes = NULL; // On linux/unix/solaris we should be able to use /dev/urandom if (!fCore::checkOS('windows') && ($handle = fopen('/dev/urandom', 'rb'))) { $bytes = fread($handle, 32); fclose($handle); // On windows we should be able to use the Cryptographic Application Programming Interface COM object } elseif (fCore::checkOS('windows') && class_exists('COM', FALSE)) { try { // This COM object no longer seems to work on PHP 5.2.9+, no response on the bug report yet $capi = new COM('CAPICOM.Utilities.1'); $bytes = base64_decode($capi->getrandom(32, 0)); unset($capi); } catch (Exception $e) { } } // If we could not use the OS random number generators we get some of the most unique info we can if (!$bytes) { $bytes = microtime(TRUE) . uniqid('', TRUE) . join('', stat(__FILE__)) . disk_free_space(__FILE__); } error_reporting($old_level); $seed = md5($bytes); $seed = base_convert($seed, 16, 10); $seed = (double) substr($seed, 0, 13) + (double) substr($seed, 14, 13); mt_srand($seed); $seeded = TRUE; }
/** * 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__); } }
/** * Clears the WHOLE cache of every key, use with caution! * * xcache may require a login or password depending on your ini settings. * * @return boolean If the cache was successfully cleared */ public function clear() { switch ($this->type) { case 'apc': return apc_clear_cache('user'); case 'database': $this->data_store->query("DELETE FROM %r", $this->config['table']); return TRUE; case 'directory': $files = array_diff(scandir($this->config['path']), array('.', '..')); $success = TRUE; foreach ($files as $file) { $success = unlink($this->config['path'] . $file) && $success; } return $success; case 'file': $this->data_store = array(); $this->config['state'] = 'dirty'; return TRUE; case 'memcache': return $this->data_store->flush(); case 'redis': return $this->data_store->flushDB(); case 'xcache': fCore::startErrorCapture(); xcache_clear_cache(XC_TYPE_VAR, 0); return (bool) fCore::stopErrorCapture(); } }
/** * Removes any invalid UTF-8 characters from a string or array of strings * * @param array|string $value The string or array of strings to clean * @return string The cleaned string */ public static function clean($value) { if (!is_array($value)) { if (self::$can_ignore_invalid === NULL) { self::$can_ignore_invalid = !in_array(strtolower(ICONV_IMPL), array('unknown', 'ibm iconv')); } fCore::startErrorCapture(E_NOTICE); $value = self::iconv('UTF-8', 'UTF-8' . (self::$can_ignore_invalid ? '//IGNORE' : ''), (string) $value); fCore::stopErrorCapture(); return $value; } $keys = array_keys($value); $num_keys = sizeof($keys); for ($i = 0; $i < $num_keys; $i++) { $value[$keys[$i]] = self::clean($value[$keys[$i]]); } return $value; }
/** * Opens the session for writing, is automatically called by ::clear(), ::get() and ::set() * * A `Cannot send session cache limiter` warning will be triggered if this, * ::add(), ::clear(), ::delete(), ::get() or ::set() is called after output * has been sent to the browser. To prevent such a warning, explicitly call * this method before generating any output. * * @param boolean $cookie_only_session_id If the session id should only be allowed via cookie - this is a security issue and should only be set to `FALSE` when absolutely necessary * @return void */ public static function open($cookie_only_session_id = TRUE) { if (self::$open) { return; } self::$open = TRUE; if (self::$normal_timespan === NULL) { self::$normal_timespan = ini_get('session.gc_maxlifetime'); } if (self::$backend && self::exists() && session_module_name() != 'user') { throw new fProgrammerException('A custom backend was provided by %1$s, however the session has already been started, so it can not be used', __CLASS__ . '::setBackend()'); } // If the session is already open, we just piggy-back without setting options if (!self::exists()) { if ($cookie_only_session_id) { ini_set('session.use_cookies', 1); ini_set('session.use_only_cookies', 1); } // If we are using a custom backend we have to set the session handler if (self::$backend && session_module_name() != 'user') { session_set_save_handler(array('fSession', 'openCache'), array('fSession', 'closeCache'), array('fSession', 'readCache'), array('fSession', 'writeCache'), array('fSession', 'destroyCache'), array('fSession', 'gcCache')); } // https://bugs.php.net/bug.php?id=68063 // Fix warning with Bad IDs fCore::startErrorCapture(); $started = session_start(); fCore::stopErrorCapture(); if (!$started) { session_regenerate_id(TRUE); session_start(); } } // If the session has existed for too long, reset it if (isset($_SESSION['fSession::expires']) && $_SESSION['fSession::expires'] < $_SERVER['REQUEST_TIME']) { $_SESSION = array(); self::regenerateID(); } if (!isset($_SESSION['fSession::type'])) { $_SESSION['fSession::type'] = 'normal'; } // We store the expiration time for a session to allow for both normal and persistent sessions if ($_SESSION['fSession::type'] == 'persistent' && self::$persistent_timespan) { $_SESSION['fSession::expires'] = $_SERVER['REQUEST_TIME'] + self::$persistent_timespan; } else { $_SESSION['fSession::expires'] = $_SERVER['REQUEST_TIME'] + self::$normal_timespan; } }
/** * Sends commands to the IMAP or POP3 server * * @param string $command The command to send * @param integer $expected The number of lines or regex expected for a POP3 command * @return array The response from the server */ private function write($command, $expected = NULL) { if (!$this->connection) { throw new fProgrammerException('Unable to send data since the connection has already been closed'); } if ($this->type == 'imap') { $identifier = 'a' . str_pad($this->command_num++, 4, '0', STR_PAD_LEFT); $command = $identifier . ' ' . $command; } if (substr($command, -2) != "\r\n") { $command .= "\r\n"; } if (fCore::getDebug($this->debug)) { fCore::debug("Sending:\n" . trim($command), $this->debug); } $res = fwrite($this->connection, $command); if ($res === FALSE) { throw new fConnectivityException('Unable to write data to %1$s server %2$s on port %3$s', strtoupper($this->type), $this->host, $this->port); } if ($this->type == 'imap') { return $this->read('#^' . $identifier . '#'); } elseif ($this->type == 'pop3') { return $this->read($expected); } }
/** * 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(); }
/** * Runs a single query and times it, removes any old unbuffered queries before starting * * @param string $sql The SQL statement to execute * @param string $result_type The type of result object to return, fResult or fUnbufferedResult * @return fResult|fUnbufferedResult The result for the query */ private function runQuery($sql, $result_type) { if ($this->unbuffered_result) { $this->unbuffered_result->__destruct(); $this->unbuffered_result = NULL; } $start_time = microtime(TRUE); if (!($result = $this->handleTransactionQueries($sql, $result_type))) { $result = new $result_type($this, $this->type == 'mssql' ? $this->schema_info['character_set'] : NULL); $result->setSQL($sql); if ($result_type == 'fResult') { $this->executeQuery($result); } else { $this->executeUnbufferedQuery($result); } } // Write some debugging info $query_time = microtime(TRUE) - $start_time; $this->query_time += $query_time; fCore::debug(self::compose('Query time was %1$s seconds for:%2$s', $query_time, "\n" . $result->getSQL()), $this->debug); if ($this->slow_query_threshold && $query_time > $this->slow_query_threshold) { trigger_error(self::compose('The following query took %1$s milliseconds, which is above the slow query threshold of %2$s:%3$s', $query_time, $this->slow_query_threshold, "\n" . $result->getSQL()), E_USER_WARNING); } return $result; }
/** * 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; }
public function tearDown() { fCore::reset(); }
/** * @dataProvider exposeProvider */ public function testExpose($value, $expected_output) { ob_start(); fCore::expose($value); $output = ob_get_clean(); $this->assertEquals($expected_output, $output); }
fCore::debug("next check is lt then now\n", FALSE); } else { fCore::debug("not less then now\n", FALSE); } // If It's been more then the Repeat Delay or the Status has changed if ($next_check->lt($end) || $check->getLastCheckStatus() != $result) { fCore::debug("Send Notification \n", FALSE); fCore::debug("State :" . $result . ":\n", FALSE); $check_result = new CheckResult(); $check_result->setCheckId($check->getCheckId()); $check_result->setStatus($result); $check_result->setValue($check_value); $check_result->setState(0); $check->setLastCheckStatus($result); $check->setLastCheckValue($check_value); $check->setLastCheckTime($end); $check_result->store(); $check->store(); $subscriptions = Subscription::findAll($check->getCheckId()); foreach ($subscriptions as $subscription) { $notify_function = $subscription->getMethod() . '_notify'; if (function_exists($notify_function)) { $notify_result = $notify_function($check, $check_result, $subscription); } } } else { fCore::debug("Skip Notification \n", FALSE); } } fCore::debug("check done moving to next \n\n", FALSE); }
/** * Warns the user about bugs in the DBLib driver for MSSQL, fixes some bugs * * @param array $row The row from the database * @return array The fixed row */ private function fixDblibMSSQLDriver($row) { static $using_dblib = array(); if (!isset($using_dblib[$this->extension])) { // If it is not a windows box we are definitely not using dblib if (!fCore::checkOS('windows')) { $using_dblib[$this->extension] = FALSE; // Check this windows box for dblib } else { ob_start(); phpinfo(INFO_MODULES); $module_info = ob_get_contents(); ob_end_clean(); if ($this->extension == 'pdo_mssql') { $using_dblib[$this->extension] = preg_match('#MSSQL_70#i', $module_info, $match); } else { $using_dblib[$this->extension] = !preg_match('#FreeTDS#i', $module_info, $match); } } } if (!$using_dblib[$this->extension]) { return $row; } foreach ($row as $key => $value) { if ($value === ' ') { $row[$key] = ''; if (!self::$silence_notices) { trigger_error(self::compose('A single space was detected coming out of the database and was converted into an empty string - see %s for more information', 'http://bugs.php.net/bug.php?id=26315'), E_USER_NOTICE); } } if (!self::$silence_notices && strlen($key) == 30) { trigger_error(self::compose('A column name exactly 30 characters in length was detected coming out of the database - this column name may be truncated, see %s for more information.', 'http://bugs.php.net/bug.php?id=23990'), E_USER_NOTICE); } if (!self::$silence_notices && strlen($value) == 256) { trigger_error(self::compose('A value exactly 255 characters in length was detected coming out of the database - this value may be truncated, see %s for more information.', 'http://bugs.php.net/bug.php?id=37757'), E_USER_NOTICE); } } return $row; }
/** * 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); }
/** * Translates Flourish SQL into the dialect for the current database * * @internal * * @param array $statements The SQL statements to translate * @param array &$rollback_statements SQL statements to rollback the returned SQL statements if something goes wrong - only applicable for MySQL `ALTER TABLE` statements * @return array The translated SQL statements all ready for execution. Statements that have been translated will have string key of the number, `:` and the original SQL, all other will have a numeric key. */ public function translate($statements, &$rollback_statements = NULL) { $output = array(); foreach ($statements as $number => $sql) { $new_sql = $this->translateBasicSyntax($sql); $new_sql = $this->translateCastClauses($new_sql); if (in_array($this->database->getType(), array('mssql', 'oracle', 'db2'))) { $new_sql = $this->translateLimitOffsetToRowNumber($new_sql); } // SQL Server does not like to give unicode results back to PHP without some coersion if ($this->database->getType() == 'mssql') { $new_sql = $this->fixMSSQLNationalColumns($new_sql); } if ($this->database->getType() == 'oracle') { // Oracle has this nasty habit of silently translating empty strings to null $new_sql = $this->fixOracleEmptyStrings($new_sql); $new_sql = $this->uppercaseIdentifiers($new_sql); } if ($this->database->getType() == 'db2') { $new_sql = $this->uppercaseIdentifiers($new_sql); } $extra_statements = array(); if (preg_match('#^\\s*(CREATE|DROP|ALTER|COMMENT)\\b#i', $new_sql)) { if (!isset($this->schema_translation)) { $this->schema_translation = new fSQLSchemaTranslation($this->database); } list($new_sql, $extra_statements) = $this->schema_translation->translate($new_sql, $rollback_statements); } if ($sql != $new_sql || $extra_statements) { fCore::debug(self::compose("Original SQL:%s", "\n" . $sql), $this->debug); $translated_sql = $new_sql; if ($extra_statements) { $translated_sql .= '; ' . join('; ', $extra_statements); } fCore::debug(self::compose("Translated SQL:%s", "\n" . $translated_sql), $this->debug); } $output = array_merge($output, array($number . ':' . $sql => $new_sql), array_values($extra_statements)); } return $output; }
/** * Runs a single statement and times it, removes any old unbuffered queries before starting * * @param string|fStatement $statement The SQL statement or prepared statement to execute * @param string $result_type The type of result object to return, fResult or fUnbufferedResult * @return fResult|fUnbufferedResult The result for the query */ private function run($statement, $result_type = NULL, $params = array()) { if ($this->unbuffered_result) { $this->unbuffered_result->__destruct(); $this->unbuffered_result = NULL; } $start_time = microtime(TRUE); if (is_object($statement)) { $sql = $statement->getSQL(); } else { $sql = $statement; } if (!($result = $this->handleTransactionQueries($sql, $result_type))) { if ($result_type) { $result = new $result_type($this, $this->type == 'mssql' ? $this->schema_info['character_set'] : NULL); $result->setSQL($sql); if ($result_type == 'fResult') { $this->performQuery($statement, $result, $params); } else { $this->performUnbufferedQuery($statement, $result, $params); } } else { $this->perform($statement, $params); } } // Write some debugging info $query_time = microtime(TRUE) - $start_time; $this->query_time += $query_time; if (fCore::getDebug($this->debug)) { fCore::debug(self::compose('Query time was %1$s seconds for:%2$s', $query_time, "\n" . $sql), $this->debug); } if ($this->hook_callbacks['run']) { foreach ($this->hook_callbacks['run'] as $callback) { $callback_params = array($this, is_object($statement) ? array($statement, $params) : $sql, $query_time, $result); call_user_func_array($callback, $callback_params); } } if ($result_type) { return $result; } }
/** * Processes a form and produces output dependent upon the context in which process() is called. * * If the form is not being submitted, then it will be rendered in its initial state using the ->value() you set on each * element and showing placeholders if set (how these are shown depends on the renderer too.) * * If the form is being submitted, then it will validate the inputs using any supplied rules and finally validate the form * as a whole unit. You can supply validation rules or even callbacks for any element or the whole form. * * If the validation fails, the form will be re-rendered with the previous input values and with the errors shown. * * If the validation passes, then the success method will be called. It can take whatever actions are needed to handle the form * and it can redirect if needed or simply return some output that will then be rendered in place of the form. **/ public function process() { $submitted = false; $form_ok = true; $src = strtoupper($this->_method); $this->_form_id = $this->_fingerprint(); $r = $this->_renderer; // // Has process been called following a form submission? Submission => method matches form // if (strtoupper($_SERVER['REQUEST_METHOD']) === $src) { $array = "_{$src}"; $submitted = !empty($GLOBALS[$array]); } $r->setSubmitting($submitted); if ($submitted) { if (true == $this->_meta['show_submitted']) { fCore::expose(array($array => $GLOBALS[$array])); } // Signal to the renderer that a submission is underway. This allows it to conditionally add // classes when rendering $r->setSubmitting(true); // Do the id and token match what is expected? $id_ok = $this->_form_id === fRequest::get('_form_id'); if (!$id_ok) { return '<p>An unexpected error occured. Form id mismatch.</p>'; } $this->_form_token = fRequest::get('_form_token'); $token_ok = fxCSRFToken::check($this->_form_id, $this->_form_token); if (!$token_ok) { return '<p>An unexpected error occured. Token mismatch.</p>'; } // // Iterate over elements, populating their values & evaluating them // foreach ($this->_elements as $e) { if (!is_string($e)) { $e->_getSubmittedValue()->_validate($this->errors, $this); } } if (empty($this->errors)) { // // Run the form validator (if any) // $validator = $this->_validation_cb; if (is_callable($validator)) { $v = $validator($this); $form_ok = true === $v; } if ($form_ok) { if (is_callable($this->_onSuccess)) { $fn = $this->_onSuccess; return $fn($this); } else { throw new fxProgrammerException("Form submission successful but no onSuccess callback defined."); } } else { return $v; } } } fxCSRFToken::clear($this->_form_id); $this->_form_token = fxCSRFToken::generate($this->_form_id); if (true == $this->_show_form_elements) { fCore::expose($this); } elseif (true == $this->_show_form_errors) { fCore::expose($this->errors); } if (!$this->_form_id || !$this->_form_token) { throw new fxProgrammerException("Form cannot be rendered without _form_id and _form_token being defined."); } return $this->renderUsing($this->_renderer, $this, $this->id); }