/** * Connect to a database using PDO */ public function connect($config = array()) { if ($this->connected() !== true) { $dsn = array(); // look for connection details in $_ENV $env_dbfile = Utils::getValue(@$_ENV['Sqlite_Database'], 'biscuit.sqlite3'); $env_charset = Utils::getValue(@$_ENV['Sqlite_Charset'], 'utf8'); // look for connection details in $config $dbfile = Utils::getValue(@$config['dbfile'], $env_dbfile); $charset = Utils::getValue(@$config['charset'], $env_charset); // build connection dns if (!empty($dbfile)) { $dsn[] = trim($dbfile); } if (!empty($charset)) { $dsn[] = 'charset=' . trim($charset); } // merge options if (!empty($config['options']) && is_array($config['options'])) { $this->options = array_merge($this->options, $config['options']); } // connect try { $dsn = 'sqlite:' . implode(';', $dsn); $this->pdo = new PDO($dsn, null, null, $this->options); return true; } catch (PDOException $e) { return $this->error($e->getMessage()); } catch (Exception $e) { return $this->error($e->getMessage()); } } return true; }
/** * Look for timezone offset value saved in cookie by JS (in seconds) */ public function lookupJsCookie($name = '') { $name = Sanitize::toKey($name); $value = Utils::getValue(@$_COOKIE[$name], null); if (is_numeric($value)) { $this->setTimezoneOffset(intval($value)); } }
/** * Constructor */ public function __construct($key = '', $method = '') { // try to resolve a key, will look for "CryptKey" in _ENV. $cryptKey = Utils::getValue(@$_ENV['CryptKey'], ''); $cryptKey = Utils::getValue($key, $cryptKey); // try to resolve a method, will look for "CryptMethod" in _ENV. $cryptMethod = Utils::getValue(@$_ENV['CryptMethod'], ''); $cryptMethod = Utils::getValue($method, $cryptMethod); // set inital values $this->setCryptKey($cryptKey); $this->setCryptMethod($cryptMethod); }
/** * Connect to a MySQL database */ public function connect($config = array()) { if ($this->connected() !== true) { $dsn = array(); // look for connection details in $_ENV $env_host = Utils::getValue(@$_ENV['MySql_Host'], 'localhost'); $env_port = Utils::getValue(@$_ENV['MySql_Port'], '3306'); $env_username = Utils::getValue(@$_ENV['MySql_Username'], 'root'); $env_password = Utils::getValue(@$_ENV['MySql_Password'], ''); $env_dbname = Utils::getValue(@$_ENV['MySql_DbName'], 'appdata'); $env_charset = Utils::getValue(@$_ENV['MySql_Charset'], 'utf8'); // look for connection details in $config $host = Utils::getValue(@$config['host'], $env_host); $port = Utils::getValue(@$config['port'], $env_port); $username = Utils::getValue(@$config['username'], $env_username); $password = Utils::getValue(@$config['password'], $env_password); $dbname = Utils::getValue(@$config['dbname'], $env_dbname); $charset = Utils::getValue(@$config['charset'], $env_charset); // build connection dns if (!empty($host)) { $dsn[] = 'host=' . trim($host); } if (!empty($port)) { $dsn[] = 'port=' . trim($port); } if (!empty($dbname)) { $dsn[] = 'dbname=' . trim($dbname); } if (!empty($charset)) { $dsn[] = 'charset=' . trim($charset); } // merge options if (!empty($config['options']) && is_array($config['options'])) { $this->options = array_merge($this->options, $config['options']); } // connect try { $dsn = 'mysql:' . implode(';', $dsn); $this->pdo = new PDO($dsn, $username, $password, $this->options); return true; } catch (PDOException $e) { return $this->error($e->getMessage()); } catch (Exception $e) { return $this->error($e->getMessage()); } } return true; }
/** * Get the server document root path */ public static function getDocRoot() { $value = Utils::getValue(@$_SERVER['DOCUMENT_ROOT'], '', true); $value = rtrim(str_replace('\\', '/', $value), '/'); return $value; }
/** * Get array of item timestamps */ public function getTimestamps() { $path = $this->getPath(); $now = time(); $created = Utils::getValue(@filectime($path), $now); $modified = Utils::getValue(@filemtime($path), $now); $accessed = Utils::getValue(@fileatime($path), $now); return array('created' => min($created, $modified, $accessed), 'modified' => max($created, $modified), 'accessed' => max($modified, $accessed)); }
/** * Get the formatted error text */ public function getErrorText($text = '') { $text = Utils::getValue($text, 'Too many failed attempts.'); $count = $this->session->get($this->key . '.info.fail_count', 0); $total = $this->session->get($this->key . '.info.fail_total', 0); $last = $this->session->get($this->key . '.info.last_attempt', 0); $keymap = array('attempts' => $total, 'countdown' => Time::toCountdown($last, $this->cd_time), 'count' => '(' . $count . '/' . $this->cd_trigger . ')', 'total' => '(' . $total . '/' . $this->max_attempts . ')'); return (string) Text::set($text)->mapReplace($keymap)->singleSpaces(); }
/** * Extends the session cookie lifetime period */ public function extendCookie($expire = null) { $time = time(); $default = $time + $this->getOption('cookie_lifetime', 0); $expire = Utils::getValue(Sanitize::toTime($expire), $default); if ($expire > $time) { return setcookie(session_name(), session_id(), $expire, $this->getOption('cookie_path'), $this->getOption('cookie_domain'), $this->getOption('cookie_secure'), $this->getOption('cookie_httponly')); } return false; }
/** * Get list of request headers, or single value if $name is provided */ public function getHeaders($name = '', $default = '') { $headers = getallheaders(); if (!empty($name)) { return Utils::getValue(@$headers[$name], $default); } return $headers; }
/** * Merges data with an encoded JSON string */ public static function merge($string = '', $data = array()) { $decoded = self::decode($string); $data = Utils::deepMerge($decoded, $data); return self::encode($data); }
/** * Parse FORM encoded data */ private function _parseForm() { if (!empty($this->boundary)) { $chunks = @preg_split('/[\\-]+' . $this->boundary . '(\\-\\-)?/', $this->input, -1, PREG_SPLIT_NO_EMPTY); $request = array(); $files = array(); $nd = 0; $nf = 0; if (is_array($chunks)) { foreach ($chunks as $index => $chunk) { $chunk = ltrim($chunk, "-\r\n\t\\s "); $lines = explode("\r\n", $chunk); $levels = ''; $name = ''; $file = ''; $type = ''; $value = ''; $path = ''; $copy = false; // skip empty chunks if (empty($chunk) || empty($lines)) { continue; } // extract name/filename if (strpos($lines[0], 'Content-Disposition') !== false) { $line = $this->_line(array_shift($lines)); $name = Utils::getValue(@$line['name'], '', true); $file = Utils::getValue(@$line['filename'], '', true); } // extract content-type if (strpos($lines[0], 'Content-Type') !== false) { $line = $this->_line(array_shift($lines)); $type = Utils::getValue(@$line['content'], '', true); } // rebuild value $value = trim(implode("\r\n", $lines)); // FILES data if (!empty($type)) { // check if file extension is in skip list if (in_array(Sanitize::toExtension($file), $this->skip)) { continue; } // move file data to temporary file on server if (!empty($value)) { $path = str_replace('\\', '/', sys_get_temp_dir() . '/php' . substr(sha1(rand()), 0, 6)); $copy = file_put_contents($path, $value); } // extract multi-level array structure from the property name if (preg_match('/(\\[.*?\\])$/', $name, $tmp)) { $name = str_replace($tmp[1], '', $name); $levels = preg_replace('/\\[\\]/', '[' . $nf . ']', $tmp[1]); } // build final array keys to be parsed $files[$name . '[name]' . $levels] = $file; $files[$name . '[type]' . $levels] = $type; $files[$name . '[tmp_name]' . $levels] = $path; $files[$name . '[error]' . $levels] = !empty($copy) ? 0 : UPLOAD_ERR_NO_FILE; $files[$name . '[size]' . $levels] = !empty($copy) ? filesize($path) : 0; $nf++; } else { $name = preg_replace('/\\[\\]/', '[' . $nd . ']', $name); $request[$name] = $value; $nd++; } } // finalize arrays $_REQUEST = array_merge($_GET, $this->_data($request)); $_FILES = $this->_data($files); return true; } } return false; }
/** * Convert a request path string into routing params */ public function parse() { $this->resetActions(); $this->resetParams(); $this->setArea($this->_default_area); $this->setController($this->_default_controller); $this->addAction('init-action', false); $path = Utils::getValue($this->_path_request, '/'); $path = Sanitize::toPath(@parse_url($path, PHP_URL_PATH)); $path = str_replace(Server::getBasePath(), '', $path); $route = explode('/', trim($path, '/')); if (!empty($route[0]) && $this->areaExists($route[0])) { $this->setArea(array_shift($route)); } if (!empty($route[0])) { $this->setController(array_shift($route)); } if (!empty($route[0])) { $this->addAction(array_shift($route)); } if (!empty($route)) { $this->_params = array_values($route); } if (count($this->_actions) === 1) { $this->addAction($this->_default_action); } }
/** * Send response headers */ public function sendHeaders() { if (headers_sent() === false) { $status = Status::getHeader($this->version, $this->status); $charset = strtolower(Utils::getValue(@mb_internal_encoding(), 'utf-8')); header($status, true); header('Content-type: ' . $this->ctype . '; charset=' . $charset, true); foreach ($this->headers as $key => $data) { header($key . ': ' . $data[0], $data[1]); } return true; } return false; }
/** * Builds the final query using local params */ private function _buildQuery($type, $reset = true) { $query = strtoupper(trim($type)) . ' '; $parts = array(); $fields = array(); $pairs = array(); $keys = array(); $data = array(); $build = ''; // compile query parts from _maps foreach ($this->_maps as $mapcat => $maplist) { $build = ''; $split = $mapcat == 'tables' || $mapcat == 'columns' ? ',' : ' '; foreach ($maplist as $subject => $format) { $subject = $this->_col($subject); $build .= sprintf($format, $subject) . $split; } $parts[$mapcat] = preg_replace('/(AND|OR)$/i', '', trim($build, ', ')); } // compile final query data used for insert/update if (!empty($this->_data['query'])) { $data = array_merge($data, $this->_data['query']); } if (!empty($this->_data['user'])) { $data = array_merge($data, $this->_data['user']); foreach ($this->_data['user'] as $datacol => $dataval) { $cplain = trim($datacol, ': '); $cticked = $this->_col($cplain); $fields[] = $cticked; $pairs[] = $cticked . '= :' . $cplain; $keys[] = ':' . $cplain; } } // set fallback column and table $columns = Utils::getValue(@$parts['columns'], $this->_col('*')); $tables = Utils::getValue(@$parts['tables'], $this->_col($this->_table)); // finalize query string if ($type === 'SELECT') { $query .= $columns . ' FROM ' . $tables . ' '; } if ($type === 'INSERT' || $type === 'REPLACE') { $query .= 'INTO ' . $tables . ' (' . implode(',', $fields) . ') VALUES (' . implode(',', $keys) . ') '; } if ($type === 'UPDATE') { $query .= $tables . ' SET ' . implode(',', $pairs) . ' '; } if ($type === 'DELETE') { $query .= 'FROM ' . $tables . ' '; } if (!empty($parts['joins'])) { $query .= $parts['joins'] . ' '; } if (!empty($parts['where'])) { $query .= 'WHERE ' . $parts['where'] . ' '; } if (!empty($parts['group'])) { $query .= 'GROUP BY ' . $parts['group'] . ' '; } if (!empty($parts['order'])) { $query .= 'ORDER BY ' . $parts['order'] . ' '; } // finalize query $query = $this->_explain . ' ' . $query . ' ' . $this->_limit; $query = trim(preg_replace('/\\s\\s+/', ' ', $query)); // reset and return output if ($reset === true) { $this->reset(); } return array($query, $data); }
/** * Parses a stack trace array and returns a new array */ private function _getBacktrace() { $output = array(); $count = 1; foreach ($this->_error_backtrace as $index => $item) { $file = Utils::getValue(@$item['file'], ''); $line = Utils::getValue(@$item['line'], 0); $class = Utils::getValue(@$item['class'], ''); $function = Utils::getValue(@$item['function'], ''); $type = Utils::getValue(@$item['type'], ''); if (empty($file) || $function === __FUNCTION__) { continue; } $source = $class . $type . $function; $callable = basename(str_replace('\\', '/', $source)); $file = $this->_relativePath($file); $line = (double) $line; $output[] = array('count' => $count, 'file' => $file, 'type' => $type, 'class' => $class, 'function' => $function, 'line' => number_format($line, 0), 'source' => $source, 'callable' => $callable . '()'); $count++; } return $output; }