PK
SرZ> > lib/module.phpnu ٘ check_overwrite($name, $this->protected, 'protected', $value)) {
return false;
}
if (!$this->check_overwrite($name, $this->appendable, 'protected', $value)) {
return false;
}
if ($protected) {
$this->protected[] = $name;
}
$this->output[$name] = $value;
return true;
}
/**
* append a value to an array, create it if does not exist
* @param string $name array name
* @param string $value value to add
* @return bool true on success
*/
public function append($name, $value) {
if (!$this->check_overwrite($name, $this->protected, 'protected', $value)) {
return false;
}
if (array_key_exists($name, $this->output)) {
if (is_array($this->output[$name])) {
$this->output[$name][] = $value;
return true;
}
else {
Hm_Debug::add(sprintf('Tried to append %s to scaler %s', $value, $name));
return false;
}
}
else {
$this->output[$name] = array($value);
$this->appendable[] = $name;
return true;
}
}
/**
* Sanitize input string
* @param string $string text to sanitize
* @param bool $special_only only use htmlspecialchars not htmlentities
* @return string sanitized value
*/
public function html_safe($string, $special_only=false) {
if ($special_only) {
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8");
}
return htmlentities($string, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8");
}
/**
* Concatenate a value
* @param string $name name to add to
* @param string $value value to add
* @return bool true on success
*/
public function concat($name, $value) {
if (array_key_exists($name, $this->output)) {
if (is_string($this->output[$name])) {
$this->output[$name] .= $value;
return true;
}
else {
Hm_Debug::add(sprintf('Could not append %s to %s', print_r($value,true), $name));
return false;
}
}
else {
$this->output[$name] = $value;
return true;
}
}
/**
* Return module output from process()
* @return array
*/
public function module_output() {
return $this->output;
}
/**
* Return protected output field list
* @return array
*/
public function output_protected() {
return $this->protected;
}
/**
* Fetch an output value
* @param string $name key to fetch the value for
* @param mixed $default default return value if not found
* @param string $typed if a default value is given, typecast the result to it's type
* @return mixed value if found or default
*/
public function get($name, $default=NULL, $typed=true) {
if (array_key_exists($name, $this->output)) {
$val = $this->output[$name];
if (!is_null($default) && $typed) {
if (gettype($default) != gettype($val)) {
Hm_Debug::add(sprintf('TYPE CONVERSION: %s to %s for %s', gettype($val), gettype($default), $name));
settype($val, gettype($default));
}
}
return $val;
}
return $default;
}
/**
* Check for a key
* @param string $name key name
* @return bool true if found
*/
public function exists($name) {
return array_key_exists($name, $this->output);
}
/**
* Check to see if a value matches a list
* @param string $name name to check
* @param array $values list to check against
* @return bool true if found
*/
public function in($name, $values) {
if (array_key_exists($name, $this->output) && in_array($this->output[$name], $values, true)) {
return true;
}
return false;
}
}
/**
* Methods used to validate handler module operations, like the HTTP request
* type and target/origin values
*/
trait Hm_Handler_Validate {
/**
* Validate HTTP request type, only GET and POST are allowed
* @param object $session
* @param object $request
* @return bool
*/
public function validate_method($session, $request) {
if (!in_array(strtolower($request->method), array('get', 'post'), true)) {
if ($session->loaded) {
$session->destroy($request);
Hm_Debug::add(sprintf('LOGGED OUT: invalid method %s', $request->method));
}
return false;
}
return true;
}
/**
* Validate that the request has matching source and target origins
* @return bool
*/
public function validate_origin($session, $request, $config) {
if (!$session->loaded) {
return true;
}
list($source, $target) = $this->source_and_target($request, $config);
if (!$this->validate_target($target, $source, $session, $request) ||
!$this->validate_source($target, $source, $session, $request)) {
return false;
}
return true;
}
/**
* Find source and target values for validate_origin
* @return string[]
*/
private function source_and_target($request, $config) {
$source = false;
$target = $config->get('cookie_domain', false);
if ($target == 'none') {
$target = false;
}
$server_vars = array(
'HTTP_REFERER' => 'source',
'HTTP_ORIGIN' => 'source',
'HTTP_HOST' => 'target',
'HTTP_X_FORWARDED_HOST' => 'target'
);
foreach ($server_vars as $header => $type) {
if (array_key_exists($header, $request->server) && $request->server[$header]) {
$$type = $request->server[$header];
}
}
return array($source, $target);
}
/**
* @param string $target
* @param string $source
* @return boolean
*/
private function validate_target($target, $source, $session, $request) {
if (!$target || !$source) {
$session->destroy($request);
Hm_Debug::add('LOGGED OUT: missing target origin');
return false;
}
return true;
}
/**
* @param string $target
* @param string $source
* @return boolean
*/
private function validate_source($target, $source, $session, $request) {
$source = parse_url($source);
if (!is_array($source) || !array_key_exists('host', $source)) {
$session->destroy($request);
Hm_Debug::add('LOGGED OUT: invalid source origin');
return false;
}
if (array_key_exists('port', $source)) {
$source['host'] .= ':'.$source['port'];
}
if ($source['host'] !== $target) {
$session->destroy($request);
Hm_Debug::add('LOGGED OUT: invalid source origin');
return false;
}
return true;
}
}
/**
* Base class for data input processing modules, called "handler modules"
*
* All modules that deal with processing input data extend from this class.
* It provides access to input and state through the following member variables:
*
* $session The session interface object
* $request The HTTP request details object
* $config The site config object
* $user_config The user settings object for the current user
*
* Modules that extend this class need to override the process function
* Modules can pass information to the output modules using the out() and append() methods,
* and see data from other modules with the get() method
* @abstract
*/
abstract class Hm_Handler_Module {
use Hm_Module_Output;
use Hm_Handler_Validate;
/* session object */
public $session;
/* request object */
public $request;
/* site configuration object */
public $config;
/* current request id */
protected $page = '';
/* user settings */
public $user_config;
public $cache;
/**
* Assign input and state sources
* @param object $parent instance of the Hm_Request_Handler class
* @param string $page page id
* @param array $output data from handler modules
* @param array $protected list of protected output names
*/
public function __construct($parent, $page, $output=array(), $protected=array()) {
$this->session = $parent->session;
$this->request = $parent->request;
$this->cache = $parent->cache;
$this->page = $page;
$this->config = $parent->site_config;
$this->user_config = $parent->user_config;
$this->output = $output;
$this->protected = $protected;
}
/**
* @return string
*/
private function invalid_ajax_key() {
if (DEBUG_MODE) {
Hm_Debug::add('REQUEST KEY check failed');
Hm_Debug::load_page_stats();
Hm_Debug::show();
}
Hm_Functions::cease(json_encode(array('status' => 'not callable')));;
return 'exit';
}
/**
* @return string
*/
private function invalid_http_key() {
if ($this->session->loaded) {
$this->session->destroy($this->request);
Hm_Debug::add('LOGGED OUT: request key check failed');
}
Hm_Dispatch::page_redirect('?page=home');
return 'redirect';
}
/**
* Validate a form key. If this is a non-empty POST form from an
* HTTP request or AJAX update, it will take the user to the home
* page if the page_key value is either not present or not valid
* @return false|string
*/
public function process_key() {
if (empty($this->request->post)) {
return false;
}
$key = array_key_exists('hm_page_key', $this->request->post) ? $this->request->post['hm_page_key'] : false;
$valid = Hm_Request_Key::validate($key);
if ($valid) {
return false;
}
if ($this->request->type == 'AJAX') {
return $this->invalid_ajax_key();
}
else {
return $this->invalid_http_key();
}
}
/**
* Validate a value in a HTTP POST form
* @param mixed $val
* @return mixed
*/
private function check_field($val) {
switch (true) {
case is_array($val):
case trim($val) !== '':
case $val === '0':
case $val === 0:
return $val;
default:
return NULL;
}
}
/**
* Process an HTTP POST form
* @param array $form list of required field names in the form
* @return array tuple with a bool indicating success, and an array of valid form values
*/
public function process_form($form) {
$new_form = array();
foreach($form as $name) {
if (!array_key_exists($name, $this->request->post)) {
continue;
}
$val = $this->check_field($this->request->post[$name]);
if ($val !== NULL) {
$new_form[$name] = $val;
}
}
return array((count($form) === count($new_form)), $new_form);
}
/**
* Determine if a module set is enabled
* @param string $name the module set name to check for
* @return bool
*/
public function module_is_supported($name) {
return in_array(strtolower($name), $this->config->get_modules(true), true);
}
/**
* Handler modules need to override this method to do work
*/
abstract public function process();
}
/**
* Base class for output modules
* All modules that output data to a request must extend this class and define
* an output() method. It provides form validation, html sanitizing,
* and string translation services to modules
* @abstract
*/
abstract class Hm_Output_Module {
use Hm_Module_Output;
/* translated language strings */
protected $lstr = array();
/* langauge name */
protected $lang = false;
/* UI layout direction */
protected $dir = 'ltr';
/* Output format (AJAX or HTML5) */
protected $format = '';
/**
* Constructor
* @param array $input data from handler modules
* @param array $protected list of protected keys
*/
public function __construct($input, $protected) {
$this->output = $input;
$this->protected = $protected;
}
/**
* Return a translated string if possible
* @param string $string the string to be translated
* @return string translated string
*/
public function trans($string) {
if (array_key_exists($string, $this->lstr)) {
if ($this->lstr[$string] === false) {
return strip_tags($string);
}
else {
return strip_tags($this->lstr[$string]);
}
}
else {
Hm_Debug::add(sprintf('TRANSLATION NOT FOUND :%s:', $string));
}
return str_replace('\n', '
', strip_tags($string));
}
/**
* Build output by calling module specific output functions
* @param string $format output type, either HTML5 or AJAX
* @param array $lang_str list of language translation strings
* @return string
*/
public function output_content($format, $lang_str) {
$this->lstr = $lang_str;
$this->format = str_replace('Hm_Format_', '', $format);
if (array_key_exists('interface_lang', $lang_str)) {
$this->lang = $lang_str['interface_lang'];
}
if (array_key_exists('interface_direction', $lang_str)) {
$this->dir = $lang_str['interface_direction'];
}
return $this->output();
}
/**
* Output modules need to override this method to add to a page or AJAX response
* @return string
*/
abstract protected function output();
}
/**
* Placeholder classes for disabling a module in a set. These allow a module set
* to replace another module set's assignments with "false" to disable them
*/
class Hm_Output_ extends Hm_Output_Module { protected function output() {} }
class Hm_Handler_ extends Hm_Handler_Module { public function process() {} }
PK
SC C lib/webdav_formats.phpnu ٘ 1 line
* @param string $str string input
* @return string
*/
private function unfold($str) {
return preg_replace("/\n\s{1}/m", '', $str);
}
/**
* Process the value portion of an input line
* @param string $value value to process
* @param string $type property type
* @return array
*/
private function process_value($value, $type=false) {
$res = array();
foreach ($this->split_value($value, ',', -1) as $val) {
$res[] = str_replace(array('\n', '\,'), array("\n", ','), $val);
}
return $res;
}
/**
* Validate a property
* @param string $prop property name
* @return boolean
*/
private function invalid_prop($prop) {
if (strtolower(substr($prop, 0, 2)) == 'x-') {
return false;
}
foreach ($this->properties as $name => $value) {
if (strtolower($prop) == strtolower($value)) {
return false;
}
}
Hm_Debug::add(sprintf("%s invalid prop found: %s", $this->format, $prop));
return true;
}
/**
* Validate a paramater
* @param string $param parameter to validate
* @return boolean
*/
private function invalid_param($param) {
foreach ($this->parameters as $val) {
if (strtolower($param) == strtolower($val)) {
return false;
}
}
Hm_Debug::add(sprintf("%s invalid param found: %s",
$this->format, $param));
return true;
}
/**
* Parse a property value
* @param string $prop property to parse
* @return array
*/
private function parse_prop($prop) {
$vals = $this->split_value($prop, ';', -1);
$res = array(
'prop' => $vals[0],
'params' => array()
);
if (count($vals) > 1) {
$res['params'] = $this->parse_prop_params($vals);
}
return $res;
}
/**
* Parse parameters in a property field
* @param array $vals list of parameters
* @return array
*/
private function parse_prop_params($vals) {
$res = array();
array_shift($vals);
foreach ($vals as $val) {
$pair = $this->split_value($val, '=', 2);
if (count($pair) > 1) {
if ($this->invalid_param($pair[0])) {
continue;
}
$res[strtolower($pair[0])] = $this->flatten(
$this->process_value($pair[1]));
}
}
return $res;
}
}
/**
* Class for parsing vCard/iCal data
*/
class Hm_Card_Parse {
use Hm_Card_Line_Parse;
/* input format version */
protected $version = '';
/* original input data unchanged */
protected $raw_card = '';
/* placeholder for parsed data */
protected $data = array();
/* list of valid parameters for the file type */
protected $parameters = array();
/* list of valid properties for the file type */
protected $properties = array();
/**
* init
*/
public function __construct() {
}
/**
* Import a single set of values
* @param string $str string data from the input file
* @return boolean
*/
public function import($str) {
$this->data = array();
$this->raw_card = $str;
$lines = explode("\n", $this->unfold($this->standard_eol($str)));
if ($this->is_valid($lines)) {
return $this->parse($lines);
}
return false;
}
/**
* Load an already parsed card
* @param array $data parsed card data
* @return void
*/
public function import_parsed($data) {
if (array_key_exists('raw', $data)) {
$this->raw_card = $data['raw'];
unset($data['raw']);
}
$this->data = $data;
}
/**
* Return parsed data for an input
* @return array
*/
public function raw_data() {
return $this->raw_card;
}
/**
* Format as vcard
*/
public function build_card() {
$new_card = array();
foreach ($this->data as $name => $val) {
if (method_exists($this, 'format_vcard_'.$name)) {
$res = $this->{'format_vcard_'.$name}();
}
else {
$res = $this->format_vcard_generic($name);
}
if (is_array($res) && $res) {
$new_card = array_merge($new_card, $res);
}
elseif ($res) {
$new_card[] = $res;
}
}
return implode("\n", $new_card);
}
/**
* Return parsed data for an input
* @return array
*/
public function parsed_data() {
return $this->data;
}
/**
* Get the value for a field
*/
public function fld_val($name, $type=false, $default=false, $all=false) {
if (!array_key_exists($name, $this->data)) {
return $default;
}
$fld = $this->data[$name];
if ($all) {
return $fld;
}
foreach ($fld as $vals) {
if ($this->is_type($type, $vals)) {
if (array_key_exists('formatted', $vals)) {
return $vals['formatted']['values'];
}
return $vals['values'];
}
}
if (array_key_exists('formatted', $fld[0])) {
return $fld[0]['formatted']['values'];
}
else {
return $fld[0]['values'];
}
}
/**
* Look for a sepcific type
*/
private function is_type($type, $vals) {
if (!$type) {
return false;
}
if (!array_key_exists('type', $vals)) {
return false;
}
if (is_array($vals['type']) && in_array($type, $vals['type'])) {
return true;
}
elseif (strtolower($type) == strtolower($vals['type'])) {
return true;
}
return false;
}
/**
* Flatten a list with 1 value to a scaler
* @param array $arr list to flatten
* @return array
*/
private function flatten($arr) {
if (is_array($arr) && count($arr) == 1) {
return array_pop($arr);
}
return $arr;
}
/**
* Parse input file
* @param array $lines lines of input to parse
* @return boolean
*/
private function parse($lines) {
foreach ($lines as $line) {
$id = md5($line);
$vals = $this->split_value($line, ':', 2);
$prop = $this->parse_prop($vals[0]);
if ($this->invalid_prop($prop['prop'])) {
continue;
}
$data = $prop['params'];
$data['values'] = $this->flatten(
$this->process_value($vals[1], $prop['prop']));
$data['id'] = $id;
if (array_key_exists(strtolower($prop['prop']), $this->data)) {
$this->data[strtolower($prop['prop'])][] = $data;
}
else {
$this->data[strtolower($prop['prop'])] = array($data);
}
}
$this->data['raw'] = $this->raw_card;
$this->parse_values();
return count($this->data) > 0;
}
/**
* Top level validation of input data
* @param array $lines input data by line
* @return boolean
*/
private function is_valid($lines) {
$res = true;
if (count($lines) < 4) {
$res = false;
}
if (count($lines) > 0 && strtolower(substr($lines[0], 0, 5)) != 'begin') {
$res = false;
}
if (count($lines) > 1 && strtolower(substr($lines[1], 0, 7)) != 'version') {
$res = false;
}
if (count($lines) && strtolower(substr($lines[(count($lines) - 1)], 0, 3)) != 'end') {
$res = false;
}
if (!$res) {
Hm_Debug::add(sprintf('Invalid %s format', $this->format));
return false;
}
$version = $this->split_value($lines[1], ':', 2);
if (count($version) > 1) {
$this->version = $version[1];
}
return true;
}
/**
* Parse values that require it
* @return void
*/
private function parse_values() {
foreach ($this->data as $prop => $values) {
$method = sprintf('parse_%s', $prop);
if (method_exists($this, $method)) {
$this->data[$prop] = $this->$method($values);
}
}
}
/**
* Catch-all for formatting vcard fields that don't need specific formatting
* @param string $name the field name
* @return array
*/
protected function format_vcard_generic($name) {
$res = array();
if (in_array($name, array('raw'), true)) {
return;
}
$vals = $this->fld_val($name, false, array(), true);
if (count($vals) == 0) {
$res;
}
foreach ($vals as $val) {
$name = substr($name, 0, 2) == 'x-' ? $name : strtoupper($name);
$params = array_merge(array($name), $this->build_vcard_params($val));
$res[] = sprintf("%s:%s", implode(';', $params), $val['values']);
}
return $res;
}
/**
* Build the vcard entry paramater string
* @param array field values
* @return array
*/
protected function build_vcard_params($fld_val) {
$props = array();
foreach ($this->parameters as $param) {
if (array_key_exists(strtolower($param), $fld_val)) {
$props[] = sprintf('%s=%s', strtoupper($param),
$this->combine($fld_val[strtolower($param)]));
}
}
return $props;
}
/**
* Combine an array value if needed, return formatted value
* @param mixed $val the value to combine
* @return string
*/
protected function combine($val) {
if (is_array($val)) {
return implode(',', array_map(array($this, 'vcard_format'), $val));
}
return $this->vcard_format($val);
}
/**
* Clean a vcard value
* TODO: make escaping more robust
* @param string $val the value to format
* @return string
*/
protected function vcard_format($val) {
return str_replace(array(',', "\n"), array('\,', '\n'), $val);
}
}
/**
* Class for parsing vCard data
*/
class Hm_VCard extends Hm_Card_Parse {
protected $format = 'vCard';
protected $raw_card = '';
protected $data = array();
protected $parameters = array(
'TYPE', 'PREF', 'LABEL', 'VALUE', 'LANGUAGE',
'MEDIATYPE', 'ALTID', 'PID', 'CALSCALE',
'SORT-AS', 'GEO', 'TZ'
);
protected $properties = array(
'BEGIN', 'VERSION', 'END', 'FN', 'N',
'KIND', 'BDAY', 'ANNIVERSARY', 'GENDER',
'PRODID', 'REV', 'UID', 'SOURCE', 'XML',
'NICKNAME', 'PROTO', 'ADR', 'TEL',
'EMAIL', 'IMPP', 'LANG', 'TZ', 'GEO',
'TITLE', 'ROLE', 'LOGO', 'ORG', 'MEMBER',
'RELATED', 'CATEGORIES', 'NOTE', 'SOUND',
'CLIENTPIDMAP', 'PHOTO', 'URL', 'KEY',
'FBURL', 'CALADRURI', 'CALURI'
);
/* CONVERT VCARD INPUT */
/**
* Parse the name field
* @param array $vals name field values
* @return array
*/
protected function parse_n($vals) {
foreach ($vals as $index => $name) {
$flds = $this->split_value($name['values'], ';', 5);
$vals[$index]['values'] = array(
'lastname' => $flds[0],
'firstname' => $flds[1],
'additional' => $flds[2],
'prefixes' => $flds[3],
'suffixes' => $flds[4]
);
}
return $vals;
}
/**
* Convert an address from vcard to an internal struct
* @param array $vals address values
* @return array
*/
protected function format_addr($vals) {
$name = 'address';
if (array_key_exists('type', $vals)) {
$name = sprintf('%s_address', strtolower($vals['type']));
}
$vals = $vals['values'];
$street = $vals['street'];
if (!$street && $vals['po']) {
$steet = $vals['po'];
}
$value = sprintf('%s, %s, %s, %s, %s', $street, $vals['locality'], $vals['region'],
$vals['country'], $vals['postal_code']);
return array('name' => $name, 'values' => $value);
}
/**
* Parse an address field value
* @param array $vals address values
* @return array
*/
protected function parse_adr($vals) {
foreach ($vals as $index => $addr) {
$flds = $this->split_value($addr['values'], ';', 7);
$vals[$index]['values'] = array(
'po' => $flds[0],
'apartment' => $flds[1],
'street' => $flds[2],
'locality' => $flds[3],
'region' => $flds[4],
'postal_code' => $flds[5],
'country' => $flds[6]
);
$vals[$index]['formatted'] = $this->format_addr($vals[$index]);
}
return $vals;
}
/* CONVERT TO VCARD OUTPUT */
/**
* Format a name field for vcard output
* @return string
*/
protected function format_vcard_n() {
$n = $this->fld_val('n');
return sprintf("N:%s;%s;%s;%s;%s", $n['lastname'], $n['firstname'],
$n['additional'], $n['prefixes'], $n['suffixes']);
}
/**
* Format addresses to vcard
* @return array
*/
protected function format_vcard_adr() {
$res = array();
foreach ($this->fld_val('adr', array(), false, true) as $adr) {
$parts = $adr['values'];
$params = array_merge(array('ADR'), $this->build_vcard_params($adr));
$res[] = sprintf('%s:%s;%s;%s;%s;%s;%s;%s', implode(';', $params),
$parts['po'], $parts['apartment'], $parts['street'], $parts['locality'],
$parts['region'], $parts['postal_code'], $parts['country']);
}
return $res;
}
}
/**
* Class for parsing iCal data
*/
class Hm_ICal extends Hm_Card_Parse {
protected $format = 'iCal';
protected $raw_card = '';
protected $data = array();
protected $parameters = array(
'ALTREP', 'CN', 'CUTYPE', 'DELEGATED-FROM',
'DELEGATED-TO', 'DIR', 'ENCODING', 'FMTTYPE',
'FBTYPE', 'LANGUAGE', 'MEMBER', 'PARTSTAT',
'RANGE', 'RELATED', 'RELTYPE', 'ROLE', 'RSVP',
'SENT-BY', 'TZID', 'VALUE'
);
protected $properties = array(
'BEGIN', 'VERSION', 'END', 'CALSCALE',
'METHOD', 'PRODID', 'ATTACH', 'CATEGORIES',
'CLASS', 'COMMENT', 'DESCRIPTION', 'GEO',
'LOCATION', 'PERCENT-COMPLETE', 'PRIORITY',
'RESOURCES', 'STATUS', 'SUMMARY', 'COMPLETED',
'DTEND', 'DUE', 'DTSTART', 'DURATION', 'FREEBUSY',
'TRANSP', 'TZID', 'TZNAME', 'TZOFFSETFROM',
'TZOFFSETTO', 'TZURL', 'ATTENDEE', 'CONTACT',
'ORGANIZER', 'RECURRENCE-ID', 'RELATED-TO',
'URL', 'UID', 'EXDATE', 'EXRULE', 'RDATE',
'RRULE', 'ACTION', 'REPEAT', 'TRIGGER',
'CREATED', 'DTSTAMP', 'LAST-MODIFIED',
'SEQUENCE', 'REQUEST-STATUS'
);
protected function parse_due($vals) {
return $this->parse_dt($vals);
}
protected function parse_dtstamp($vals) {
return $this->parse_dt($vals);
}
protected function parse_dtend($vals) {
return $this->parse_dt($vals);
}
protected function parse_dtstart($vals) {
return $this->parse_dt($vals);
}
protected function parse_trigger($vals) {
return $this->parse_dt($vals);
}
protected function parse_dt($vals) {
foreach ($vals as $index => $dates) {
$dt = $vals[0]['values'];
if (substr($dt, -1, 1) == 'Z') {
$vals[0]['tzid'] = 'UTC';
$dt = substr($dt, 0, -1);
}
$vals[$index]['values'] = date_parse_from_format('Ymd\THis', $dt);
}
return $vals;
}
}
PK
So lib/framework.phpnu ٘ = 7.3) {
return setcookie($name, $value, array(
'expires' => $lifetime,
'path' => $path,
'domain' => $domain,
'secure' => $secure,
'httponly' => $html_only,
'samesite' => 'Strict')
);
}
else {
return setcookie($name, $value, $lifetime, $path, $domain, $secure, $html_only);
}
}
/**
* @param string $header
* @return void
*/
public static function header($header) {
header($header);
}
/**
* @param string $msg
* @return null
*/
public static function cease($msg='') {
die($msg);
}
/**
* @return boolean
*/
public static function session_destroy() {
if (session_status() === PHP_SESSION_ACTIVE) {
return session_destroy();
}
return false;
}
/**
* @return boolean
*/
public static function session_start() {
return session_start();
}
/**
* @return boolean
*/
public static function error_log($str) {
return error_log($str);
}
/**
* @param resource|false $handle
* @param integer $name
*/
public static function c_setopt($handle, $name, $value) {
if ($handle !== false) {
curl_setopt($handle, $name, $value);
}
}
/**
* @return resource|false
*/
public static function c_init() {
return curl_init();
}
/**
* @param resource $handle
*/
public static function c_exec($handle) {
return curl_exec($handle);
}
/**
* @param resource $handle
*/
public static function c_status($ch) {
return curl_getinfo($ch, CURLINFO_HTTP_CODE);
}
/**
* @param string $func
*/
public static function function_exists($func) {
return function_exists($func);
}
/**
* @param string $class
*/
public static function class_exists($class) {
return class_exists($class, false);
}
/**
* @param integer $size
*/
public static function random_bytes($size) {
return random_bytes($size);
}
/**
* @return Memcached
*/
public static function memcached() {
return new Memcached();
}
/**
* @return Redis
*/
public static function redis() {
return new Redis();
}
/**
* @param integer $type input type
* @param array $filters filter list
* @return array filtered list
*/
public static function filter_input_array($type, $filters) {
return filter_input_array($type, $filters, false);
}
/**
* @param string $server host to connect to
* @param integer $port port to connect to
* @param integer $errno error number
* @param string $errstr error string
* @param integer $mode connection mode
* @param resource $ctx context
*/
public static function stream_socket_client($server, $port, &$errno, &$errstr, $timeout, $mode, $ctx) {
return @stream_socket_client($server.':'.$port, $errno, $errstr, $timeout, $mode, $ctx);
}
/**
* @param resource $resource socket connection
* @return boolean
*/
public static function stream_ended($resource) {
if (!is_resource($resource) || feof($resource)) {
return true;
}
return false;
}
/**
* @param resource $socket socket connection to flip to TLS
* @return boolean
*/
public static function stream_socket_enable_crypto($socket, $type) {
return stream_socket_enable_crypto($socket, true, $type);
}
}
}
/**
* See if a function already exists
* @param string $name function name to check
* @return boolean
*/
function hm_exists($name) {
$bt = debug_backtrace();
$caller = array_shift($bt);
$module = hm_get_module_from_path($caller['file']);
if (function_exists($name)) {
Hm_Debug::add(sprintf('Function in %s replaced: %s', $module, $name));
return true;
}
return false;
}
/**
* Return the module set name from a file path
* @param string $path file path
* @return string
*/
function hm_get_module_from_path($path) {
$data = pathinfo($path);
if (!is_array($data) || !array_key_exists('dirname', $data)) {
return 'unknown';
}
$parts = array_reverse(explode(DIRECTORY_SEPARATOR, $data['dirname']));
foreach ($parts as $i => $v) {
if ($v == 'modules') {
return $parts[($i - 1)];
}
}
return 'unknown';
}
PK
SZx% %
lib/crypt.phpnu ٘ is_active()) {
if (!$just_logged_in) {
$user = $session->get('username', '');
$key = $session->get('request_key', '');
}
else {
$session->set('request_key', Hm_Crypt::unique_id());
}
}
$site_id = '';
if (defined('SITE_ID')) {
$site_id = SITE_ID;
}
self::$site_hash = $session->build_fingerprint($request->server, $key.$user.$site_id);
}
/**
* Return the request key
* @return string request key
*/
public static function generate() {
return self::$site_hash;
}
/**
* Validate a request key
* @param string $key value to check
* @return bool true on success
*/
public static function validate($key) {
return $key === self::$site_hash;
}
}
class Hm_Crypt_Base {
static protected $method = 'aes-256-cbc';
static protected $hmac = 'sha512';
static protected $password_rounds = 86000;
static protected $encryption_rounds = 100;
static protected $hmac_rounds = 101;
/**
* Convert ciphertext to plaintext
* @param string $string ciphertext to decrypt
* @param string $key encryption key
* @return string|false decrypted text
*/
public static function plaintext($string, $key) {
$string = base64_decode($string);
/* bail if the crypt text is invalid */
if (!$string || strlen($string) <= 200) {
return false;
}
/* get the payload and salt */
$crypt_string = substr($string, 192);
$salt = substr($string, 0, 128);
/* check the signature. Temporarily allow the same key for hmac validation, eventually remove the $encryption_rounds
* check and require the hmac_rounds check only! */
if (!self::check_hmac($crypt_string, substr($string, 128, 64), $salt, $key, self::$hmac_rounds) &&
!self::check_hmac($crypt_string, substr($string, 128, 64), $salt, $key, self::$encryption_rounds)) {
Hm_Debug::add('HMAC verification failed');
return false;
}
/* generate remaining keys */
$iv = self::pbkdf2($key, $salt, 16, self::$encryption_rounds, self::$hmac);
$crypt_key = self::pbkdf2($key, $salt, 32, self::$encryption_rounds, self::$hmac);
/* return the decrpted text */
return openssl_decrypt($crypt_string, self::$method, $crypt_key, OPENSSL_RAW_DATA, $iv);
}
/**
* Check hmac signature
* @param string $crypt_string payload to check
* @param string $hmac signature to check
* @param string $salt from generate_salt()
* @param string $key supplied key for the encryption
* @param integer $rounds iterations
* @return boolean
*/
public static function check_hmac($crypt_string, $hmac, $salt, $key, $rounds) {
$hmac_key = self::pbkdf2($key, $salt, 32, $rounds, self::$hmac);
/* make sure the crypt text has not been tampered with */
return self::hash_compare($hmac, hash_hmac(self::$hmac, $crypt_string, $hmac_key, true));
}
/**
* Convert plaintext into ciphertext
* @param string $string plaintext to encrypt
* @param string $key encryption key
* @return string encrypted text
*/
public static function ciphertext($string, $key) {
/* generate a strong salt */
$salt = self::generate_salt();
/* build required keys */
$iv = self::pbkdf2($key, $salt, 16, self::$encryption_rounds, self::$hmac);
$crypt_key = self::pbkdf2($key, $salt, 32, self::$encryption_rounds, self::$hmac);
$hmac_key = self::pbkdf2($key, $salt, 32, self::$hmac_rounds, self::$hmac);
/* encrypt the string */
$crypt_string = openssl_encrypt($string, self::$method, $crypt_key, OPENSSL_RAW_DATA, $iv);
/* build a hash of the crypted text */
$hmac = hash_hmac(self::$hmac, $crypt_string, $hmac_key, true);
/* return the salt, hash, and crypt text */
return base64_encode($salt.$hmac.$crypt_string);
}
/**
* Generate a strong random salt (hopefully)
* @return string
*/
public static function generate_salt() {
/* generate random bytes */
return self::random(128);
}
/**
* Compare password hashes
*
* @param string $a hash
* @param string $b hash
* @return bool
*/
private static function hash_equals($a, $b) {
$res = 0;
$len = strlen($a);
for ($i = 0; $i < $len; $i++) {
$res |= ord($a[$i]) ^ ord($b[$i]);
}
return $res === 0;
}
/**
* Compare password hashes with hash_equals is available, otherwise use
* timing attack safe comparison
*
* @param string $a hash
* @param string $b hash
* @return bool
*/
public static function hash_compare($a, $b) {
if (!is_string($a) || !is_string($b) || strlen($a) !== strlen($b)) {
return false;
}
/* requires PHP >= 5.6 */
if (Hm_Functions::function_exists('hash_equals')) {
return hash_equals($a, $b);
}
return self::hash_equals($a, $b);
}
/**
* Key derivation wth pbkdf2: http://en.wikipedia.org/wiki/PBKDF2
* @param string $key payload
* @param string $salt random string from generate_salt
* @return string[]
*/
protected static function keygen($key, $salt) {
return array($salt, self::pbkdf2($key, $salt, 32, self::$encryption_rounds, self::$hmac));
}
/**
* Key derivation wth pbkdf2: http://en.wikipedia.org/wiki/PBKDF2
* @param string $key payload
* @param string $salt random string from generate_salt
* @param integer $length result length
* @param integer $count iterations
* @param string $algo hash algorithm to use
* @return string
*/
public static function pbkdf2($key, $salt, $length, $count, $algo) {
/* requires PHP >= 5.5 */
if (Hm_Functions::function_exists('openssl_pbkdf2')) {
return openssl_pbkdf2($key, $salt, $length, $count, $algo);
}
/* manual version */
$size = strlen(hash($algo, '', true));
$len = ceil($length / $size);
$result = '';
for ($i = 1; $i <= $len; $i++) {
$tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
$res = $tmp;
for ($j = 1; $j < $count; $j++) {
$tmp = hash_hmac($algo, $tmp, $key, true);
$res ^= $tmp;
}
$result .= $res;
}
return substr($result, 0, $length);
}
/**
* Hash a password using PBKDF2 or PHP password_hash if availble
* @param string $password password to hash
* @param string $salt salt to use, if false generate a new one
* @param int $count interations for PBKDF2
* @param string $algo PBKDF2 algo, defaults to sha512
* @param string $type Can be either pbkdf2 or php
* @return string
*/
public static function hash_password($password, $salt=false, $count=false, $algo='sha512', $type='php') {
if (function_exists('password_hash') && $type === 'php') {
return password_hash($password, PASSWORD_DEFAULT);
}
if ($salt === false) {
$salt = self::generate_salt();
}
if ($count === false) {
$count = self::$password_rounds;
}
return sprintf("%s:%s:%s:%s", $algo, $count, base64_encode($salt), base64_encode(
self::pbkdf2($password, $salt, 32, $count, $algo)));
}
/**
* Check a password against it's stored hash
* @param string $password clear text password
* @param string $hash hashed password
* @return bool
*/
public static function check_password($password, $hash) {
$type = 'php';
if (substr($hash, 0, 6) === 'sha512') {
$type = 'pbkdf2';
}
if (function_exists('password_verify') && $type === 'php') {
return password_verify($password, $hash);
}
if (count(explode(':', $hash)) == 4) {
list($algo, $count, $salt,,) = explode(':', $hash);
return self::hash_compare(self::hash_password($password, base64_decode($salt), $count, $algo, $type), $hash);
}
return false;
}
/**
* Return a unique-enough-key for session cookie ids
* @param int $size length of the result
* @return string
*/
public static function unique_id($size=128) {
return base64_encode(openssl_random_pseudo_bytes($size));
}
/**
* Generate a random string
* @param int $size
* @return string
*/
public static function random($size=128) {
try {
return Hm_Functions::random_bytes($size);
}
catch (Exception $e) {
Hm_Functions::cease('No reliable random byte source found');
}
}
}
PK
So? ?
lib/cache.phpnu ٘ 0) {
self::update_count($data, 'read', 0);
}
if (count($data[1]) > 0) {
self::update_count($data, 'unread', 1);
}
}
/**
* @param array $data uids to merge
* @param string $type uid type (read or unread)
* @param integer $pos position in the $data array
* @return void
*/
private static function update_count($data, $type, $pos) {
self::$$type = array_combine($data[$pos], array_fill(0, count($data[$pos]), 0));
}
/**
* Determine if a UID has been unread
* @param string $uid UID to search for
* @return bool true if te UID exists
*/
public static function is_unread($uid) {
return array_key_exists($uid, self::$unread);
}
/**
* Determine if a UID has been read
* @param string $uid UID to search for
* @return bool true if te UID exists
*/
public static function is_read($uid) {
return array_key_exists($uid, self::$read);
}
/**
* Return all the UIDs
* @return array list of known UIDs
*/
public static function dump() {
return array(array_keys(self::$read), array_keys(self::$unread));
}
/**
* Add a UID to the unread list
* @param string $uid uid to add
*/
public static function unread($uid) {
self::$unread[$uid] = 0;
if (array_key_exists($uid, self::$read)) {
unset(self::$read[$uid]);
}
}
/**
* Add a UID to the read list
* @param string $uid uid to add
*/
public static function read($uid) {
self::$read[$uid] = 0;
if (array_key_exists($uid, self::$unread)) {
unset(self::$unread[$uid]);
}
}
}
/**
* Shared utils for Redis and Memcached
* @package framework
* @subpackage cache
*/
trait Hm_Cache_Base {
public $supported;
private $enabled;
private $server;
private $config;
private $port;
private $cache_con;
/**
* @return boolean
*/
abstract protected function connect();
/*
* @return boolean
*/
public function is_active() {
if (!$this->enabled) {
return false;
}
elseif (!$this->configured()) {
return false;
}
elseif (!$this->cache_con) {
return $this->connect();
}
return true;
}
/**
* @param string $key cache key to delete
*/
public function del($key) {
if (!$this->is_active()) {
return false;
}
return $this->cache_con->delete($key);
}
/**
* @param string $key key to set
* @param string|string $val value to set
* @param integer $lifetime lifetime of the cache entry
* @param string $crypt_key encryption key
* @return boolean
*/
public function set($key, $val, $lifetime=600, $crypt_key='') {
if (!$this->is_active()) {
return false;
}
return $this->cache_con->set($key, $this->prep_in($val, $crypt_key), $lifetime);
}
/**
* @param string $key name of value to fetch
* @param string $crypt_key encryption key
* @return false|array|string
*/
public function get($key, $crypt_key='') {
if (!$this->is_active()) {
return false;
}
return $this->prep_out($this->cache_con->get($key), $crypt_key);
}
/**
* @param array|string $data data to prep
* @param string $crypt_key encryption key
* @return string|array
*/
private function prep_in($data, $crypt_key) {
if ($crypt_key) {
return Hm_Crypt::ciphertext(Hm_transform::stringify($data), $crypt_key);
}
return $data;
}
/**
* @param array $data data to prep
* @param string $crypt_key encryption key
* @return false|array|string
*/
private function prep_out($data, $crypt_key) {
if ($crypt_key && is_string($data) && trim($data)) {
return Hm_transform::unstringify(Hm_Crypt::plaintext($data, $crypt_key), 'base64_decode', true);
}
return $data;
}
/**
* @return boolean
*/
private function configured() {
if (!$this->server || !$this->port) {
Hm_Debug::add(sprintf('%s enabled but no server or port found', $this->type));
return false;
}
if (!$this->supported) {
Hm_Debug::add(sprintf('%s enabled but not supported by PHP', $this->type));
return false;
}
return true;
}
}
/**
* Redis cache
* @package framework
* @subpackage cache
*/
class Hm_Redis {
use Hm_Cache_Base;
private $type = 'Redis';
private $db_index;
/**
* @param Hm_Config $config site config object
*/
public function __construct($config) {
$this->server = $config->get('redis_server', false);
$this->port = $config->get('redis_port', false);
$this->enabled = $config->get('enable_redis', false);
$this->db_index = $config->get('redis_index', 0);
$this->socket = $config->get('redis_socket', '');
$this->supported = Hm_Functions::class_exists('Redis');
$this->config = $config;
}
/**
* @return boolean
*/
private function connect() {
$this->cache_con = Hm_Functions::redis();
try {
if ($this->socket) {
$con = $this->cache_con->connect($this->socket);
}
else {
$con = $this->cache_con->connect($this->server, $this->port);
}
if ($con) {
$this->auth();
$this->cache_con->select($this->db_index);
return true;
}
else {
$this->cache_con = false;
return false;
}
}
catch (Exception $oops) {
Hm_Debug::add('Redis connect failed');
$this->cache_con = false;
return false;
}
}
/**
* @return void
*/
private function auth() {
if ($this->config->get('redis_pass')) {
$this->cache_con->auth($this->config->get('redis_pass'));
}
}
/**
* @param string $key cache key to delete
*/
public function del($key) {
if (!$this->is_active()) {
return false;
}
return $this->cache_con->del($key);
}
/**
* @return boolean
*/
public function close() {
if (!$this->is_active()) {
return false;
}
return $this->cache_con->close();
}
}
/**
* Memcached cache
* @package framework
* @subpackage cache
*/
class Hm_Memcached {
use Hm_Cache_Base;
private $type = 'Memcached';
/**
* @param Hm_Config $config site config object
*/
public function __construct($config) {
$this->server = $config->get('memcached_server', false);
$this->port = $config->get('memcached_port', false);
$this->enabled = $config->get('enable_memcached', false);
$this->supported = Hm_Functions::class_exists('Memcached');
$this->config = $config;
}
/**
* @return void
*/
private function auth() {
if ($this->config->get('memcached_auth')) {
$this->cache_con->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
$this->cache_con->setSaslAuthData($this->config->get('memcached_user'),
$this->config->get('memcached_pass'));
}
}
/*
* @return boolean
*/
private function connect() {
$this->cache_con = Hm_Functions::memcached();
$this->auth();
if (!$this->cache_con->addServer($this->server, $this->port)) {
Hm_Debug::add('Memcached addServer failed');
$this->cache_con = false;
return false;
}
return true;
}
/**
* @return mixed
*/
public function last_err() {
if (!$this->is_active()) {
return false;
}
return $this->cache_con->getResultCode();
}
/**
* @return boolean
*/
public function close() {
if (!$this->is_active()) {
return false;
}
return $this->cache_con->quit();
}
}
/**
* @package framework
* @subpackage cache
*/
class Hm_Noop_Cache {
public function del($key) {
return true;
}
public function set($key, $val, $lifetime, $crypt_key) {
return false;
}
}
/**
* Generic cache
* @package framework
* @subpackage cache
*/
class Hm_Cache {
private $backend;
private $session;
public $type;
/**
* @param Hm_Config $config site config object
* @param object $session session object
* @return void
*/
public function __construct($config, $session) {
$this->session = $session;
if (!$this->check_redis($config) && !$this->check_memcache($config)) {
$this->check_session($config);
}
Hm_Debug::add(sprintf('CACHE backend using: %s', $this->type));
}
/**
* @param Hm_Config $config site config object
* @return void
*/
private function check_session($config) {
$this->type = 'noop';
$this->backend = new Hm_Noop_Cache();
if ($config->get('allow_session_cache')) {
$this->type = 'session';
}
}
/**
* @param Hm_Config $config site config object
* @return boolean
*/
private function check_redis($config) {
if ($config->get('enable_redis', false)) {
$backend = new Hm_Redis($config);
if ($backend->is_active()) {
$this->type = 'redis';
$this->backend = $backend;
return true;
}
}
return false;
}
/**
* @param Hm_Config $config site config object
* @return boolean
*/
private function check_memcache($config) {
if ($config->get('enable_memcached', false)) {
$backend = new Hm_Memcached($config);
if ($backend->is_active()) {
$this->type = 'memcache';
$this->backend = $backend;
return true;
}
}
return false;
}
/**
* @param string $key key name
* @param string $msg_type log message
* @return void
*/
private function log($key, $msg_type) {
switch ($msg_type) {
case 'save':
Hm_Debug::add(sprintf('CACHE: saving "%s" using %s', $key, $this->type));
break;
case 'hit':
Hm_Debug::add(sprintf('CACHE: hit for "%s" using %s', $key, $this->type));
break;
case 'miss':
Hm_Debug::add(sprintf('CACHE: miss for "%s" using %s', $key, $this->type));
break;
case 'del':
Hm_Debug::add(sprintf('CACHE: deleting "%s" using %s', $key, $this->type));
break;
}
}
/**
* @param string $key name of value to cache
* @param mixed $val value to cache
* @param integer $lifetime how long to cache (if applicable for the backend)
* @param boolean $session store in the session instead of the enabled cache
* @return boolean
*/
public function set($key, $val, $lifetime=600, $session=false) {
if ($session || $this->type == 'session') {
return $this->session_set($key, $val, false);
}
return $this->generic_set($key, $val, $lifetime);
}
/**
* @param string $key name of value to fetch
* @param mixed $default value to return if not found
* @param boolean $session fetch from the session instead of the enabled cache
* @return mixed
*/
public function get($key, $default=false, $session=false) {
if ($session || $this->type == 'session') {
return $this->session_get($key, $default);
}
return $this->{$this->type.'_get'}($key, $default);
}
/**
* @param string $key name to delete
* @param boolean $session fetch from the session instead of the enabled cache
* @return boolean
*/
public function del($key, $session=false) {
if ($session || $this->type == 'session') {
return $this->session_del($key);
}
return $this->generic_del($key);
}
/**
* @param string $key name of value to fetch
* @param mixed $default value to return if not found
* @return mixed
*/
private function redis_get($key, $default) {
$res = $this->backend->get($this->key_hash($key), $this->session->enc_key);
if (!$res) {
$this->log($key, 'miss');
return $default;
}
$this->log($key, 'hit');
return $res;
}
/**
* @param string $key name of value to fetch
* @param mixed $default value to return if not found
* @return mixed
*/
private function memcache_get($key, $default) {
$res = $this->backend->get($this->key_hash($key), $this->session->enc_key);
if (!$res && $this->backend->last_err() == Memcached::RES_NOTFOUND) {
$this->log($key, 'miss');
return $default;
}
$this->log($key, 'hit');
return $res;
}
/*
* @param string $key name of value to cache
* @param mixed $val value to cache
* @param integer $lifetime how long to cache (if applicable for the backend)
* @return boolean
*/
private function session_set($key, $val, $lifetime) {
$this->log($key, 'save');
$this->session->set($this->key_hash($key), $val);
return true;
}
/**
* @param string $key name of value to fetch
* @param mixed $default value to return if not found
* @return mixed
*/
private function session_get($key, $default) {
$res = $this->session->get($this->key_hash($key), $default);
if ($res === $default) {
$this->log($key, 'miss');
return $default;
}
$this->log($key, 'hit');
return $res;
}
/**
* @param string $key name to delete
* @return boolean
*/
private function session_del($key) {
$this->log($key, 'del');
return $this->session->del($this->key_hash($key));
}
/**
* @param string $key name of value to fetch
* @param mixed $default value to return if not found
* @return mixed
*/
private function noop_get($key, $default) {
return $default;
}
/*
* @param string $key key to make the hash unique
* @return string
*/
private function key_hash($key) {
return sprintf('hm_cache_%s', hash('sha256', (sprintf('%s%s%s%s', $key, SITE_ID,
$this->session->get('fingerprint'), $this->session->get('username')))));
}
/**
* @param string $key name to delete
* @return boolean
*/
private function generic_del($key) {
$this->log($key, 'del');
return $this->backend->del($this->key_hash($key));
}
/**
* @param string $key name of value to cache
* @param mixed $val value to cache
* @param integer $lifetime how long to cache (if applicable for the backend)
* @return boolean
*/
private function generic_set($key, $val, $lifetime) {
$this->log($key, 'save');
return $this->backend->set($this->key_hash($key), $val, $lifetime, $this->session->enc_key);
}
}
PK
S7N_ _ lib/ini_set.phpnu ٘ = 7.3) {
ini_set('session.cookie_samesite', 'Strict');
}
/* HTTPS required for session cookie */
if (!$config->get('disable_tls', false)) {
ini_set('session.cookie_secure', 1);
}
/* gc max lifetime */
ini_set('session.gc_maxlifetime', 1440);
/* disable trans sid */
ini_set('session.use_trans_sid', 0);
/* don't allow dynamic page caching */
ini_set('session.cache_limiter', 'nocache');
/* session hash mechanism */
if ((float) substr(phpversion(), 0, 3) === 5.6) {
ini_set('session.hash_function', 1);
}
else {
ini_set('session.hash_function', 'sha256');
}
/* session name */
ini_set('session.name', 'hm_session');
/* disable remote includes */
ini_set('allow_url_include', 0);
/* when display_errors is on PHP returns a 200 when it should be a 500 */
ini_set('display_errors', 0);
ini_set('display_start_up_errors', 0);
$tmp_dir = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir();
$base = dirname(dirname(__FILE__)).PATH_SEPARATOR.$tmp_dir.PATH_SEPARATOR.'/dev/urandom';
$disabled = $config->get('disable_open_basedir', false);
foreach (array('app_data_dir', 'user_settings_dir', 'attachment_dir') as $dir) {
if ($config->get($dir, false) && is_readable($config->get($dir, false))) {
$base .= PATH_SEPARATOR.$config->get($dir, false);
}
}
if (!$disabled) {
ini_set('open_basedir', $base);
}
PK
SEf
f
lib/sodium_compat.phpnu ٘ $site_config->get('db_driver', false),
'db_host' => $site_config->get('db_host', false),
'db_name' => $site_config->get('db_name', false),
'db_user' => $site_config->get('db_user', false),
'db_pass' => $site_config->get('db_pass', false),
'db_socket' => $site_config->get('db_socket', false),
'db_conn_type' => $site_config->get('db_connection_type', 'host'),
'db_port' => $site_config->get('db_port', false),
);
foreach (self::$required_config as $v) {
if (!self::$config[$v]) {
Hm_Debug::add(sprintf('Missing configuration setting for %s', $v));
}
}
}
/**
* Return a unique key for a DB connection
* @return string md5 of the DB settings
*/
static private function db_key() {
return md5(self::$config['db_driver'].
self::$config['db_host'].
self::$config['db_port'].
self::$config['db_name'].
self::$config['db_user'].
self::$config['db_pass'].
self::$config['db_conn_type'].
self::$config['db_socket']
);
}
/**
* Build a DSN to connect to the db with
* @return string
*/
static public function build_dsn() {
if (self::$config['db_driver'] == 'sqlite') {
return sprintf('%s:%s', self::$config['db_driver'], self::$config['db_socket']);
}
if (self::$config['db_conn_type'] == 'socket') {
return sprintf('%s:unix_socket=%s;dbname=%s', self::$config['db_driver'], self::$config['db_socket'], self::$config['db_name']);
}
else {
if (self::$config['db_port']) {
return sprintf('%s:host=%s;port=%s;dbname=%s', self::$config['db_driver'], self::$config['db_host'], self::$config['db_port'], self::$config['db_name']);
}
else {
return sprintf('%s:host=%s;dbname=%s', self::$config['db_driver'], self::$config['db_host'], self::$config['db_name']);
}
}
}
/**
* @param object|false $dbh PDO connection object
* @param string $sql sql with placeholders to execute
* @param array $args values to insert into the sql
* @param bool $type optional type of sql query
* @param bool $all optional flag to return multiple rows
* @return boolean|integer|array
*/
static public function execute($dbh, $sql, $args, $type=false, $all=false) {
if (!$dbh) {
return false;
}
if (!$type) {
$type = self::execute_type($sql);
}
$sql = $dbh->prepare($sql);
if (!$sql || !$sql->execute($args)) {
return false;
}
if ($type == 'modify' || $type == 'insert') {
return $sql->rowCount();
}
if ($all) {
return $sql->fetchAll(PDO::FETCH_ASSOC);
}
return $sql->fetch(PDO::FETCH_ASSOC);
}
/**
* @param string $sql query string
* @return string
*/
static private function execute_type($sql) {
switch(substr($sql, 0, 1)) {
case 'd':
case 'u':
case 'i':
return 'modify';
case 's':
default:
return 'select';
}
}
/**
* Connect to a DB server
* @param object $site_config site settings
* @return object|false database connection on success
*/
static public function connect($site_config) {
self::parse_config($site_config);
$key = self::db_key();
if (array_key_exists($key, self::$dbh) && self::$dbh[$key]) {
return self::$dbh[$key];
}
$dsn = self::build_dsn();
try {
self::$dbh[$key] = new PDO($dsn, self::$config['db_user'], self::$config['db_pass']);
self::$dbh[$key]->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Hm_Debug::add(sprintf('Connecting to dsn: %s', $dsn));
return self::$dbh[$key];
}
catch (Exception $oops) {
Hm_Debug::add($oops->getMessage());
self::$dbh[$key] = false;
return false;
}
}
}
PK
SİDj. j. lib/auth.phpnu ٘ site_config = $config;
}
/**
* This is the method new auth mechs need to override.
* @param string $user username
* @param string $pass password
* @return bool true if the user is authenticated, false otherwise
*/
abstract public function check_credentials($user, $pass);
/**
* Optional method for auth mech to save login details
* @param object $session session object
* @return void
*/
public function save_auth_detail($session) {}
}
/**
* Stub for dynamic authentication
*/
class Hm_Auth_Dynamic extends Hm_Auth {
public function check_credentials($user, $pass) {
return false;
}
}
/**
* Authenticate against an included DB
*/
class Hm_Auth_DB extends Hm_Auth {
/* bool flag indicating this is an internal user setup */
static public $internal_users = true;
/* database conneciton handle */
public $dbh;
/**
* Send the username and password to the configured DB for authentication
* @param string $user username
* @param string $pass password
* @return bool true if authentication worked
*/
public function check_credentials($user, $pass) {
$this->connect();
$row = Hm_DB::execute($this->dbh, 'select hash from hm_user where username = ?', array($user));
if ($row && array_key_exists('hash', $row) && $row['hash'] && Hm_Crypt::check_password($pass, $row['hash'])) {
return true;
}
sleep(2);
Hm_Debug::add(sprintf('DB AUTH failed for %s', $user));
return false;
}
/**
* Delete a user account from the db
* @param string $user username
* @return bool true if successful
*/
public function delete($user) {
$this->connect();
if (Hm_DB::execute($this->dbh, 'delete from hm_user where username = ?', array($user))) {
return true;
}
return false;
}
/**
* Create a new or re-use an existing DB connection
* @return bool true if the connection is available
*/
protected function connect() {
$this->dbh = Hm_DB::connect($this->site_config);
if ($this->dbh) {
return true;
}
Hm_Debug::add(sprintf('Unable to connect to the DB auth server %s', $this->site_config->get('db_host')));
return false;
}
/**
* Change the password for a user in the DB
* @param string $user username
* @param string $pass password
* @return bool true on success
*/
public function change_pass($user, $pass) {
$this->connect();
$hash = Hm_Crypt::hash_password($pass);
if (Hm_DB::execute($this->dbh, 'update hm_user set hash=? where username=?', array($hash, $user))) {
return true;
}
return false;
}
/**
* Create a new user in the DB
* @param string $user username
* @param string $pass password
* @return integer
*/
public function create($user, $pass) {
$this->connect();
$result = 0;
$res = Hm_DB::execute($this->dbh, 'select username from hm_user where username = ?', array($user));
if (!empty($res)) {
$result = 1;
}
else {
$hash = Hm_Crypt::hash_password($pass);
if (Hm_DB::execute($this->dbh, 'insert into hm_user values(?,?)', array($user, $hash))) {
$result = 2;
}
}
return $result;
}
}
/**
* Authenticate against an IMAP server
*/
class Hm_Auth_IMAP extends Hm_Auth {
/**
* Assign site config, get required libs
* @param object $config site config
*/
public function __construct($config) {
$this->site_config = $config;
require_once APP_PATH.'modules/imap/hm-imap.php';
}
/* IMAP authentication server settings */
private $imap_settings = array();
/**
* @param object $imap imap connection object
* @return boolean
*/
private function check_connection($imap) {
$imap->connect($this->imap_settings);
if ($imap->get_state() == 'authenticated') {
return true;
}
elseif ($imap->get_state() != 'connected') {
Hm_Debug::add($imap->show_debug(true));
Hm_Debug::add(sprintf('Unable to connect to the IMAP auth server %s', $this->imap_settings['server']));
return false;
}
else {
Hm_Debug::add($imap->show_debug(true));
Hm_Debug::add(sprintf('IMAP AUTH failed for %s', $this->imap_settings['username']));
return false;
}
}
/**
* Send the username and password to the configured IMAP server for authentication
* @param string $user username
* @param string $pass password
* @return bool true if authentication worked
*/
public function check_credentials($user, $pass) {
$imap = new Hm_IMAP();
list($server, $port, $tls) = get_auth_config($this->site_config, 'imap');
if (!$user || !$pass || !$server || !$port) {
Hm_Debug::add($imap->show_debug(true));
Hm_Debug::add('Invalid IMAP auth configuration settings');
return false;
}
$this->imap_settings = array('server' => $server, 'port' => $port,
'tls' => $tls, 'username' => $user, 'password' => $pass,
'no_caps' => false, 'blacklisted_extensions' => array('enable')
);
return $this->check_connection($imap);
}
/**
* Save IMAP server details
* @param object $session session object
* @return void
*/
public function save_auth_detail($session) {
$session->set('imap_auth_server_settings', $this->imap_settings);
}
}
/**
* Authenticate against a POP3 server
*/
class Hm_Auth_POP3 extends Hm_Auth {
/* POP3 authentication server settings */
private $pop3_settings = array();
/**
* Assign site config, get required libs
* @param object $config site config
*/
public function __construct($config) {
$this->site_config = $config;
require_once APP_PATH.'modules/pop3/hm-pop3.php';
}
/**
* @param object $pop3 pop3 connection object
* @param string $user username to login with
* @param string $pass password to login with
* @param string $server server to login to
* @return boolean
*/
private function check_connection($pop3, $user, $pass, $server) {
if (!$pop3->connect()) {
Hm_Debug::add($pop3->puke());
Hm_Debug::add(sprintf('Unable to connect to the POP3 auth server %s', $server));
return false;
}
if (!$pop3->auth($user, $pass)) {
Hm_Debug::add($pop3->puke());
Hm_Debug::add(sprintf('POP3 AUTH failed for %s', $user));
return false;
}
return true;
}
/**
* Send the username and password to the configured POP3 server for authentication
* @param string $user username
* @param string $pass password
* @return bool true if authentication worked
*/
public function check_credentials($user, $pass) {
$pop3 = new Hm_POP3();
list($server, $port, $tls) = get_auth_config($this->site_config, 'pop3');
if ($user && $pass && $server && $port) {
$this->pop3_settings = array(
'server' => $server,
'port' => $port,
'tls' => $tls,
'username' => $user,
'password' => $pass,
'no_caps' => true
);
$pop3->server = $server;
$pop3->port = $port;
$pop3->tls = $tls;
return $this->check_connection($pop3, $user, $pass, $server);
}
Hm_Debug::add($pop3->puke());
Hm_Debug::add('Invalid POP3 auth configuration settings');
return false;
}
/**
* Save POP3 server details
* @param object $session session object
* @return void
*/
public function save_auth_detail($session) {
$session->set('pop3_auth_server_settings', $this->pop3_settings);
}
}
/**
* Authenticate against an LDAP server
*/
class Hm_Auth_LDAP extends Hm_Auth {
protected $config = array();
protected $fh;
protected $source = 'ldap';
/**
* Build connect uri
* @return string
*/
private function connect_details() {
$prefix = 'ldaps://';
$server = $this->apply_config_value('server', 'localhost');
$port = $this->apply_config_value('port', 389);
if (array_key_exists('enable_tls', $this->config) && !$this->config['enable_tls']) {
$prefix = 'ldap://';
}
return $prefix.$server.':'.$port;
}
/**
* @param string $name
* @param mixed $default
* @return mixed
*/
private function apply_config_value($name, $default) {
if (array_key_exists($name, $this->config) && trim($this->config[$name])) {
return $this->config[$name];
}
return $default;
}
/**
* Check a username and password
* @param string $user username
* @param string $pass password
* @return boolean
*/
public function check_credentials($user, $pass) {
list($server, $port, $tls) = get_auth_config($this->site_config, 'ldap');
$base_dn = $this->site_config->get('ldap_auth_base_dn', false);
if ($server && $port && $base_dn) {
$user = sprintf('cn=%s,%s', $user, $base_dn);
$this->config = array(
'server' => $server,
'port' => $port,
'enable_tls' => $tls,
'base_dn' => $base_dn,
'user' => $user,
'pass' => $pass
);
return $this->connect();
}
Hm_Debug::add('Invalid LDAP auth configuration settings');
return false;
}
/**
* Connect and auth to the LDAP server
* @return boolean
*/
public function connect() {
if (!Hm_Functions::function_exists('ldap_connect')) {
return false;
}
$uri = $this->connect_details();
$this->fh = @ldap_connect($uri);
if ($this->fh) {
ldap_set_option($this->fh, LDAP_OPT_PROTOCOL_VERSION, 3);
return $this->auth();
}
Hm_Debug::add(sprintf('Unable to connect to the LDAP auth server %s', $this->config['server']));
return false;
}
/**
* Authenticate to the LDAP server
* @return boolean
*/
protected function auth() {
$result = @ldap_bind($this->fh, $this->config['user'], $this->config['pass']);
ldap_unbind($this->fh);
if (!$result) {
Hm_Debug::add(sprintf('LDAP AUTH failed for %s', $this->config['user']));
}
return $result;
}
}
/*
* @param object $config site config object
* @param string $prefix settings prefix
* @return array
*/
function get_auth_config($config, $prefix) {
$server = $config->get($prefix.'_auth_server', false);
$port = $config->get($prefix.'_auth_port', false);
$tls = $config->get($prefix.'_auth_tls', false);
return array($server, $port, $tls);
}
PK
SVe2 2 lib/modules_exec.phpnu ٘ $args) {
list($output, $protected, $type) = $this->run_output_module($input, $protected, $name,
$args, $active_session, $request->format, $this->get_current_language());
if ($type != 'JSON') {
$list_output[] = $output;
}
else {
$input = $output;
}
}
if (!empty($list_output)) {
$this->output_response = $list_output;
$this->output_data = $input;
}
else {
$this->output_response = $input;
$this->output_data = $input;
}
}
/**
* Run a single output modules and return the results
* @param array $input handler output
* @param array $protected list of protected output
* @param string $name handler module name
* @param array $args module arguments
* @param bool $active_session true if the session is active
* @param string $format HTML5 or JSON format
* @param array $lang_str translation lookup array
* @return array
*/
public function run_output_module($input, $protected, $name, $args, $active_session, $format, $lang_str) {
$name = "Hm_Output_$name";
if (!class_exists($name)) {
Hm_Debug::add(sprintf('Output module %s activated but not found', $name));
return $this->output_result($input, $protected, false);
}
if ($args[1] && !$active_session) {
return $this->output_result($input, $protected, false);
}
$mod = new $name($input, $protected);
return $this->process_result($mod, $format, $lang_str, $protected);
}
/**
* @param object $mod output module
* @param string $format output format type
* @param array $lang_str translation lookup array
* @param array protected output
* @return array
*/
private function process_result($mod, $format, $lang_str, $protected) {
$mod_output = false;
if ($format == 'Hm_Format_JSON') {
$mod->output_content($format, $lang_str, $protected);
$input = $mod->module_output();
$protected = $mod->output_protected();
}
else {
$mod_output = $mod->output_content($format, $lang_str, array());
$input = $mod->module_output();
}
return $this->output_result($input, $protected, $mod_output);
}
/**
* @param array $input module input
* @param array $protected protected output
* @param string|false http output module result
* @return array
*/
private function output_result($input, $protected, $mod_output) {
if (!$mod_output) {
return array($input, $protected, 'JSON');
}
return array($mod_output, $protected, 'HTML5');
}
}
/**
* Handler module execution methods
*/
trait Hm_Handler_Module_Exec {
public $request;
public $site_config;
public $handler_response = array();
public $page = '';
public $session;
/**
* Setup a default language translation
* @return void
*/
abstract public function default_language();
/**
* Run all the handler modules for a page and merge the results
* @param Hm_Request $request details about the request
* @param object $session session interface
* @param string $page page id
* @return void
*/
public function run_handler_modules($request, $session, $page) {
$input = $this->handler_response;
$protected = array();
$this->request = $request;
$this->session = $session;
$this->cache = new Hm_Cache($this->site_config, $session);
$modules = Hm_Handler_Modules::get_for_page($page);
foreach ($modules as $name => $args) {
list($input, $protected) = $this->run_handler_module($input, $protected, $name, $args, $session);
}
if ($input) {
$this->handler_response = $input;
}
$this->default_language();
$this->merge_response($request, $session, $page);
}
/**
* Run a single handler and return the results
* @param array $input handler output so far for this page
* @param array $protected list of protected output
* @param string $name handler module name
* @param array $args module arguments
* @param object $session session interface
*/
public function run_handler_module($input, $protected, $name, $args, $session) {
$name = "Hm_Handler_$name";
if (class_exists($name)) {
if (!$args[1] || ($args[1] && $session->is_active())) {
$mod = new $name($this, $this->page, $input, $protected);
$mod->process($input);
$input = $mod->module_output();
$protected = $mod->output_protected();
}
}
else {
Hm_Debug::add(sprintf('Handler module %s activated but not found', $name));
}
return array($input, $protected);
}
/**
* Merge the combined response from the handler modules with some default values
* @param Hm_Request $request request details
* @param object $session session interface
* @param string $page page id
* @return void
*/
public function merge_response($request, $session, $page) {
$this->handler_response = array_merge($this->handler_response, array(
'router_page_name' => $page,
'router_request_type' => $request->type,
'router_sapi_name' => $request->sapi,
'router_format_name' => $request->format,
'router_login_state' => $session->is_active(),
'router_url_path' => $request->path,
'router_module_list' => $this->site_config->get_modules(),
'router_app_name' => $this->site_config->get('app_name', 'HM3')
));
}
}
/**
* Class to setup, load, and execute module sets
*/
class Hm_Module_Exec {
use Hm_Output_Module_Exec;
use Hm_Handler_Module_Exec;
public $user_config;
public $filters = array();
public $handlers = array();
public $outputs = array();
/**
* @param object $config site config
*/
public function __construct($config) {
$this->site_config = $config;
$this->user_config = load_user_config_object($config);
$this->process_module_setup();
}
/**
* Build a list of module properties
* @return void
*/
public function process_module_setup() {
if (DEBUG_MODE) {
$this->setup_debug_modules();
}
else {
$this->setup_production_modules();
}
}
/**
* Look for translation strings based on the current language setting
* return array
*/
public function get_current_language() {
if (array_key_exists('language', $this->handler_response)) {
$lang = $this->handler_response['language'];
}
else {
$lang = 'en';
}
$strings = array();
if (file_exists(APP_PATH.'language/'.$lang.'.php')) {
$strings = require APP_PATH.'language/'.$lang.'.php';
}
return $strings;
}
/**
* Setup a default language translation
* @return void
*/
public function default_language() {
if (!array_key_exists('language', $this->handler_response)) {
$default_lang = $this->site_config->get('default_language', false);
if ($default_lang) {
$this->handler_response['language'] = $default_lang;
}
}
}
/**
* Get module data when in production mode
* @return void
*/
public function setup_production_modules() {
$this->filters = $this->site_config->get('input_filters', array());
$this->handlers = $this->site_config->get('handler_modules', array());
$this->outputs = $this->site_config->get('output_modules', array());
}
/**
* Get module data when in debug mode
* @return void
*/
public function setup_debug_modules() {
$filters = array('allowed_output' => array(), 'allowed_get' => array(), 'allowed_cookie' => array(),
'allowed_post' => array(), 'allowed_server' => array(), 'allowed_pages' => array());
$modules = $this->site_config->get_modules();
foreach ($modules as $name) {
if (is_readable(sprintf(APP_PATH."modules/%s/setup.php", $name))) {
$filters = self::merge_filters($filters, require sprintf(APP_PATH."modules/%s/setup.php", $name));
}
}
$this->filters = $filters;
}
/**
* Merge input filters from module sets
* @param array $existing already collected filters
* @param array $new new filters to merge
* @return array merged list
*/
static public function merge_filters($existing, $new) {
foreach (array('allowed_output', 'allowed_get', 'allowed_cookie', 'allowed_post', 'allowed_server', 'allowed_pages') as $v) {
if (array_key_exists($v, $new)) {
if ($v == 'allowed_pages' || $v == 'allowed_output') {
$existing[$v] = array_merge($existing[$v], $new[$v]);
}
else {
$existing[$v] += $new[$v];
}
}
}
return $existing;
}
/**
* Return the subset of active modules from a supplied list
* @param array $mod_list list of modules
* @return array filter list
*/
public function get_active_mods($mod_list) {
return array_unique(array_values(array_map(function($v) { return $v[0]; }, $mod_list)));
}
/**
* Load modules into a module manager
* @param string $class name of the module manager to use
* @param array $module_sets list of modules by page
* @param string $page page id
* @return void
*/
public function load_modules($class, $module_sets, $page) {
foreach ($module_sets as $mod_page => $modlist) {
foreach ($modlist as $name => $vals) {
if ($page == $mod_page) {
$class::add($mod_page, $name, $vals[1], false, 'after', true, $vals[0]);
}
}
}
$class::try_queued_modules();
$class::process_all_page_queue();
$class::try_queued_modules();
$class::process_replace_queue();
}
/**
* Load all module sets and include required modules.php files
* @param string $page page id
* @return void
*/
public function load_module_sets($page) {
$this->load_modules('Hm_Handler_Modules', $this->handlers, $page);
$this->load_modules('Hm_Output_Modules', $this->outputs, $page);
$active_mods = array_unique(array_merge($this->get_active_mods(Hm_Output_Modules::get_for_page($page)),
$this->get_active_mods(Hm_Handler_Modules::get_for_page($page))));
if (!count($active_mods)) {
Hm_Functions::cease('No module assignments found');
}
$mods = $this->site_config->get_modules();
$this->load_module_set_files($mods, $active_mods);
}
/**
* Load module set definition files
* @param array $mods modules to load
* @param array $active_mods list of active modules
* @return void
*/
public function load_module_set_files($mods, $active_mods) {
foreach ($mods as $name) {
if (in_array($name, $active_mods, true) && is_readable(sprintf(APP_PATH.'modules/%s/modules.php', $name))) {
require sprintf(APP_PATH.'modules/%s/modules.php', $name);
}
}
}
}
PK
Sq! ! lib/api.phpnu ٘ format = $format;
}
/**
* Execute command
* @param string $url url to fetch content from
* @param array $headers HTTP header array
* @param array $post post fields
* @return array
*/
public function command($url, $headers=array(), $post=array(), $body='', $method=false) {
$ch = Hm_Functions::c_init();
$this->curl_setopt($ch, $url, $headers);
$this->curl_setopt_post($ch, $post);
if ($method) {
Hm_Functions::c_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
}
if ($body) {
Hm_Functions::c_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
return $this->curl_result($ch);
}
/**
* Setup curl options
* @param resource|false $ch curl connection
* @param string $url url to fetch content from
* @param array $headers HTTP headers
* @return void
*/
private function curl_setopt($ch, $url, $headers) {
Hm_Functions::c_setopt($ch, CURLOPT_URL, $url);
Hm_Functions::c_setopt($ch, CURLOPT_USERAGENT, 'hm3');
Hm_Functions::c_setopt($ch, CURLOPT_HTTPHEADER, $headers);
Hm_Functions::c_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
Hm_Functions::c_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if ($this->format == 'binary') {
Hm_Functions::c_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
}
}
/**
* Setup optional post properties
* @param resource|false $ch curl connection
* @param array $post post fields
* @return void
*/
private function curl_setopt_post($ch, $post) {
if (!empty($post)) {
Hm_Functions::c_setopt($ch, CURLOPT_POST, true);
Hm_Functions::c_setopt($ch, CURLOPT_POSTFIELDS, $this->format_post_data($post));
}
}
/**
* Process a curl request result
* @param resource $ch curl connection
* @return array
*/
private function curl_result($ch) {
$curl_result = Hm_Functions::c_exec($ch);
$this->last_status = Hm_Functions::c_status($ch);
if ($this->format != 'json') {
return $curl_result;
}
$result = @json_decode($curl_result, true);
if ($result === NULL) {
return array();
}
return $result;
}
/**
* Format key value pairs into post field format
* @param array $data fields to format
* @return string
*/
private function format_post_data($data) {
$post = array();
if (!is_array($data)) {
return $data;
}
foreach ($data as $name => $value) {
$post[] = urlencode($name).'='.urlencode($value);
}
return implode('&', $post);
}
}
PK
S.sd d lib/output.phpnu ٘ output_content($response, $input['http_headers']);
}
else {
$this->output_content($response, array());
}
}
}
/**
* Output request responses using HTTP
*/
class Hm_Output_HTTP extends Hm_Output {
/**
* Send HTTP headers
* @param array $headers headers to send
* @return void
*/
protected function output_headers($headers) {
foreach ($headers as $name => $value) {
Hm_Functions::header($name.': '.$value);
}
}
/**
* Send response content to the browser
* @param mixed $content data to send
* @param array $headers HTTP headers to set
* @return void
*/
protected function output_content($content, $headers=array()) {
$this->output_headers($headers);
ob_end_clean();
echo $content;
}
}
/**
* Data URLs for icons used by the interface.
*/
class Hm_Image_Sources {
public static $power = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M3%200v4h1v-4h-1zm-1.281%201.438l-.375.313c-.803.64-1.344%201.634-1.344%202.75%200%201.929%201.571%203.5%203.5%203.5s3.5-1.571%203.5-3.5c0-1.116-.529-2.11-1.344-2.75l-.375-.313-.625.781.375.313c.585.46.969%201.165.969%201.969%200%201.391-1.109%202.5-2.5%202.5s-2.5-1.109-2.5-2.5c0-.804.361-1.509.938-1.969l.406-.313-.625-.781z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $home = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200l-4%203h1v4h2v-2h2v2h2v-4.031l1%20.031-4-3z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $box = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v1h8v-1h-8zm0%202v5.906c0%20.06.034.094.094.094h7.813c.06%200%20.094-.034.094-.094v-5.906h-2.969v1.031h-2.031v-1.031h-3z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $env_closed = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%201v1l4%202%204-2v-1h-8zm0%202v4h8v-4l-4%202-4-2z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $env_open = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200l-4%202v6h8v-6l-4-2zm0%201.125l3%201.5v1.875l-3%201.5-3-1.5v-1.875l3-1.5zm-2%201.875v1l2%201%202-1v-1h-4z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $star = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v8h1v-8h-1zm2%200v4h2v1h4l-2-1.969%202-2.031h-3v-1h-3z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $globe = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200c-2.21%200-4%201.79-4%204s1.79%204%204%204%204-1.79%204-4-1.79-4-4-4zm0%201c.333%200%20.637.086.938.188-.214.197-.45.383-.406.563.04.18.688.13.688.5%200%20.27-.425.346-.125.656.35.35-.636.978-.656%201.438-.03.83.841.969%201.531.969.424%200%20.503.195.469.438-.546.758-1.438%201.25-2.438%201.25-.378%200-.729-.09-1.063-.219.224-.442-.313-1.344-.781-1.625-.226-.226-.689-.114-.969-.219-.092-.271-.178-.545-.188-.844.031-.05.081-.094.156-.094.19%200%20.454.374.594.344.18-.04-.742-1.313-.313-1.563.2-.12.609.394.469-.156-.12-.51.366-.276.656-.406.26-.11.455-.414.125-.594l-.219-.188c.45-.27.972-.438%201.531-.438zm2.313%201.094c.184.222.323.481.438.75l-.188.219c-.29.27-.327-.212-.438-.313-.13-.11-.638.025-.688-.125-.077-.181.499-.418.875-.531z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $doc = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v8h7v-4h-4v-4h-3zm4%200v3h3l-3-3zm-3%202h1v1h-1v-1zm0%202h1v1h-1v-1zm0%202h4v1h-4v-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $monitor = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M.344%200a.5.5%200%200%200-.344.5v5a.5.5%200%200%200%20.5.5h2.5v1h-1c-.55%200-1%20.45-1%201h6c0-.55-.45-1-1-1h-1v-1h2.5a.5.5%200%200%200%20.5-.5v-5a.5.5%200%200%200-.5-.5h-7a.5.5%200%200%200-.094%200%20.5.5%200%200%200-.063%200zm.656%201h6v4h-6v-4z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $cog = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M3.5%200l-.5%201.188-.281.125-1.188-.5-.719.719.5%201.188-.125.281-1.188.5v1l1.188.5.125.313-.5%201.156.719.719%201.188-.5.281.125.5%201.188h1l.5-1.188.281-.125%201.188.5.719-.719-.5-1.188.125-.281%201.188-.5v-1l-1.188-.5-.125-.281.469-1.188-.688-.719-1.188.5-.281-.125-.5-1.188h-1zm.5%202.5c.83%200%201.5.67%201.5%201.5s-.67%201.5-1.5%201.5-1.5-.67-1.5-1.5.67-1.5%201.5-1.5z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $people = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M5.5%200c-.51%200-.949.355-1.219.875.45.54.719%201.275.719%202.125%200%20.29-.034.574-.094.844.18.11.374.156.594.156.83%200%201.5-.9%201.5-2s-.67-2-1.5-2zm-3%201c-.828%200-1.5.895-1.5%202s.672%202%201.5%202%201.5-.895%201.5-2-.672-2-1.5-2zm4.75%203.156c-.43.51-1.018.824-1.688.844.27.38.438.844.438%201.344v.656h2v-1.656c0-.52-.31-.968-.75-1.188zm-6.5%201c-.44.22-.75.668-.75%201.188v1.656h5v-1.656c0-.52-.31-.968-.75-1.188-.44.53-1.06.844-1.75.844s-1.31-.314-1.75-.844z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $caret = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M2%200v8l4-4-4-4z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $folder = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v2h8v-1h-5v-1h-3zm0%203v4.5c0%20.28.22.5.5.5h7c.28%200%20.5-.22.5-.5v-4.5h-8z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $chevron = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M1.5%201l-1.5%201.5%204%204%204-4-1.5-1.5-2.5%202.5-2.5-2.5z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $check = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M6.406%201l-.719.688-2.781%202.781-.781-.781-.719-.688-1.406%201.406.688.719%201.5%201.5.719.688.719-.688%203.5-3.5.688-.719-1.406-1.406z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $refresh = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200c-2.201%200-4%201.799-4%204s1.799%204%204%204c1.104%200%202.092-.456%202.813-1.188l-.688-.688c-.54.548-1.289.875-2.125.875-1.659%200-3-1.341-3-3s1.341-3%203-3c.834%200%201.545.354%202.094.906l-1.094%201.094h3v-3l-1.188%201.188c-.731-.72-1.719-1.188-2.813-1.188z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $big_caret_left = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M6%200l-4%204%204%204v-8z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $search = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M3.5%200c-1.927%200-3.5%201.573-3.5%203.5s1.573%203.5%203.5%203.5c.592%200%201.166-.145%201.656-.406a1%201%200%200%200%20.125.125l1%201a1.016%201.016%200%201%200%201.438-1.438l-1-1a1%201%200%200%200-.156-.125c.266-.493.438-1.059.438-1.656%200-1.927-1.573-3.5-3.5-3.5zm0%201c1.387%200%202.5%201.113%202.5%202.5%200%20.661-.241%201.273-.656%201.719l-.031.031a1%201%200%200%200-.125.125c-.442.397-1.043.625-1.688.625-1.387%200-2.5-1.113-2.5-2.5s1.113-2.5%202.5-2.5z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $spreadsheet = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M.75%200c-.402%200-.75.348-.75.75v5.5c0%20.402.348.75.75.75h6.5c.402%200%20.75-.348.75-.75v-5.5c0-.402-.348-.75-.75-.75h-6.5zm.25%201h1v1h-1v-1zm2%200h4v1h-4v-1zm-2%202h1v1h-1v-1zm2%200h4v1h-4v-1zm-2%202h1v1h-1v-1zm2%200h4v1h-4v-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $info = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M5%200c-.552%200-1%20.448-1%201s.448%201%201%201%201-.448%201-1-.448-1-1-1zm-1.5%202.5c-.83%200-1.5.67-1.5%201.5h1c0-.28.22-.5.5-.5s.5.22.5.5-1%201.64-1%202.5c0%20.86.67%201.5%201.5%201.5s1.5-.67%201.5-1.5h-1c0%20.28-.22.5-.5.5s-.5-.22-.5-.5c0-.36%201-1.84%201-2.5%200-.81-.67-1.5-1.5-1.5z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $bug = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M3.5%200c-1.19%200-1.978%201.69-1.188%202.5l-.281.219-1.313-.656a.5.5%200%200%200-.344-.063.5.5%200%200%200-.094.938l1.156.563c-.09.156-.186.328-.25.5h-.688a.5.5%200%200%200-.094%200%20.502.502%200%201%200%20.094%201h.5c0%20.227.023.445.063.656l-.781.406a.5.5%200%201%200%20.438.875l.656-.344c.245.46.59.844%201%201.094.35-.19.625-.439.625-.719v-1.438a.5.5%200%200%200%200-.094v-.813a.5.5%200%200%200%200-.219c.045-.231.254-.406.5-.406.28%200%20.5.22.5.5v.875a.5.5%200%200%200%200%20.094v.063a.5.5%200%200%200%200%20.094v1.344c0%20.27.275.497.625.688.41-.245.755-.604%201-1.063l.656.344a.5.5%200%201%200%20.438-.875l-.781-.406c.04-.211.063-.429.063-.656h.5a.5.5%200%201%200%200-1h-.688c-.064-.172-.16-.344-.25-.5l1.156-.563a.5.5%200%200%200-.313-.938.5.5%200%200%200-.125.063l-1.313.656-.281-.219c.78-.83.003-2.5-1.188-2.5z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $code = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M5%201l-3%206h1l3-6h-1zm-4%201l-1%202%201%202h1l-1-2%201-2h-1zm5%200l1%202-1%202h1l1-2-1-2h-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $person = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200c-1.105%200-2%201.119-2%202.5s.895%202.5%202%202.5%202-1.119%202-2.5-.895-2.5-2-2.5zm-2.094%205c-1.07.04-1.906.92-1.906%202v1h8v-1c0-1.08-.836-1.96-1.906-2-.54.61-1.284%201-2.094%201-.81%200-1.554-.39-2.094-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $rss = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M1%200v1c3.32%200%206%202.68%206%206h1c0-3.86-3.14-7-7-7zm0%202v1c2.221%200%204%201.779%204%204h1c0-2.759-2.241-5-5-5zm0%202v1c1.109%200%202%20.891%202%202h1c0-1.651-1.349-3-3-3zm0%202c-.552%200-1%20.448-1%201s.448%201%201%201%201-.448%201-1-.448-1-1-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $rss_alt = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v2c3.331%200%206%202.669%206%206h2c0-4.409-3.591-8-8-8zm0%203v2c1.67%200%203%201.33%203%203h2c0-2.75-2.25-5-5-5zm0%203v2h2c0-1.11-.89-2-2-2z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $caret_left = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M6%200l-4%204%204%204v-8z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $caret_right = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M2%200v8l4-4-4-4z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $calendar = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v2h7v-2h-7zm0%203v4.906c0%20.06.034.094.094.094h6.813c.06%200%20.094-.034.094-.094v-4.906h-7zm1%201h1v1h-1v-1zm2%200h1v1h-1v-1zm2%200h1v1h-1v-1zm-4%202h1v1h-1v-1zm2%200h1v1h-1v-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $circle_check = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200c-2.21%200-4%201.79-4%204s1.79%204%204%204%204-1.79%204-4-1.79-4-4-4zm2%201.781l.719.719-3.219%203.219-1.719-1.719.719-.719%201%201%202.5-2.5z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $circle_x = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200c-2.21%200-4%201.79-4%204s1.79%204%204%204%204-1.79%204-4-1.79-4-4-4zm-1.5%201.781l1.5%201.5%201.5-1.5.719.719-1.5%201.5%201.5%201.5-.719.719-1.5-1.5-1.5%201.5-.719-.719%201.5-1.5-1.5-1.5.719-.719z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $key = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M5.5%200c-1.38%200-2.5%201.12-2.5%202.5%200%20.16.033.297.063.438l-3.063%203.063v2h3v-2h2v-1l.063-.063c.14.03.277.063.438.063%201.38%200%202.5-1.12%202.5-2.5s-1.12-2.5-2.5-2.5zm.5%201c.55%200%201%20.45%201%201s-.45%201-1%201-1-.45-1-1%20.45-1%201-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $save = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M3%200v3h-2l3%203%203-3h-2v-3h-2zm-3%207v1h8v-1h-8z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $plus = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M3%200v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $minus = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%203v2h8v-2h-8z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $book = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M1%200l-.188.031c-.39.08-.701.391-.781.781l-.031.188v5.5c0%20.83.67%201.5%201.5%201.5h5.5v-1h-5.5c-.28%200-.5-.22-.5-.5s.22-.5.5-.5h5.5v-5.5c0-.28-.22-.5-.5-.5h-.5v3l-1-1-1%201v-3h-3z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $paperclip = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M5%200c-.514%200-1.021.201-1.406.594l-2.781%202.719c-1.07%201.07-1.07%202.805%200%203.875%201.07%201.07%202.805%201.07%203.875%200l1.25-1.25-.688-.688-.906.875-.344.375c-.69.69-1.81.69-2.5%200-.682-.682-.668-1.778%200-2.469l2.781-2.719v-.031c.389-.395%201.037-.4%201.438%200%20.388.381.378%201.006%200%201.406l-2.5%202.469c-.095.095-.28.095-.375%200-.095-.095-.095-.28%200-.375l.375-.344.594-.625-.688-.688-.875.875-.094.094c-.485.485-.485%201.265%200%201.75.485.485%201.265.485%201.75%200l2.5-2.438c.78-.78.785-2.041%200-2.813-.39-.39-.893-.594-1.406-.594z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $tags = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%201v2l3%203%201.5-1.5.5-.5-2-2-1-1h-2zm3.406%200l3%203-1.188%201.219.781.781%202-2-3-3h-1.594zm-1.906%201c.28%200%20.5.22.5.5s-.22.5-.5.5-.5-.22-.5-.5.22-.5.5-.5z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $tag = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v3l5%205%203-3-5-5h-3zm2%201c.55%200%201%20.45%201%201s-.45%201-1%201-1-.45-1-1%20.45-1%201-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $history = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%200v1h.5c.28%200%20.5.22.5.5v4c0%20.28-.22.5-.5.5h-.5v1h3v-1h-.5c-.28%200-.5-.22-.5-.5v-1.5h3v1.5c0%20.28-.22.5-.5.5h-.5v1h3v-1h-.5c-.28%200-.5-.22-.5-.5v-4c0-.28.22-.5.5-.5h.5v-1h-3v1h.5c.28%200%20.5.22.5.5v1.5h-3v-1.5c0-.28.22-.5.5-.5h.5v-1h-3z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $sent = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M5%200v2c-4%200-5%202.05-5%205%20.52-1.98%202-3%204-3h1v2l3-3.156-3-2.844z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $unlocked = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200c-1.099%200-2%20.901-2%202h1c0-.561.439-1%201-1%20.561%200%201%20.439%201%201v2h-4v4h6v-4h-1v-2c0-1.099-.901-2-2-2z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $lock = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4%200c-1.099%200-2%20.901-2%202v1h-1v4h6v-4h-1v-1c0-1.099-.901-2-2-2zm0%201c.561%200%201%20.439%201%201v1h-2v-1c0-.561.439-1%201-1z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $audio = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M1.188%201c-.734.722-1.188%201.748-1.188%202.844%200%201.095.454%202.09%201.188%202.813l.688-.719c-.546-.538-.875-1.269-.875-2.094s.329-1.587.875-2.125l-.688-.719zm5.625%200l-.688.719c.552.552.875%201.289.875%202.125%200%20.836-.327%201.554-.875%202.094l.688.719c.732-.72%201.188-1.708%201.188-2.813%200-1.104-.459-2.115-1.188-2.844zm-4.219%201.406c-.362.362-.594.889-.594%201.438%200%20.548.232%201.045.594%201.406l.688-.719c-.178-.178-.281-.416-.281-.688%200-.272.103-.54.281-.719l-.688-.719zm2.813%200l-.688.719c.183.183.281.434.281.719s-.099.505-.281.688l.688.719c.357-.357.594-.851.594-1.406%200-.555-.236-1.08-.594-1.438z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $camera = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M4.094%200c-.06%200-.105.044-.125.094l-.938%201.813c-.02.05-.065.094-.125.094h-1.406c-.83%200-1.5.67-1.5%201.5v4.406c0%20.06.034.094.094.094h7.813c.06%200%20.094-.034.094-.094v-5.813c0-.06-.034-.094-.094-.094h-.813c-.06%200-.105-.044-.125-.094l-.938-1.813c-.02-.05-.065-.094-.125-.094h-1.813zm-2.594%203c.28%200%20.5.22.5.5s-.22.5-.5.5-.5-.22-.5-.5.22-.5.5-.5zm3.5%200c1.1%200%202%20.9%202%202s-.9%202-2%202-2-.9-2-2%20.9-2%202-2zm0%201c-.55%200-1%20.45-1%201s.45%201%201%201%201-.45%201-1-.45-1-1-1z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E';
public static $menu = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M0%201v1h8v-1h-8zm0%202.969v1h8v-1h-8zm0%203v1h8v-1h-8z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $pencil = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M6%200l-1%201%202%202%201-1-2-2zm-2%202l-4%204v2h2l4-4-2-2z%22%20%2F%3E%0A%3C%2Fsvg%3E';
public static $w = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AgKARwCjOZMwQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAA2UlEQVQ4y+3ToUrDURTH8Q/MwdCFMbSIj7BgHWgSBnsAGZjEbPYVfICFubSwtGbwH8xisRnWBcMQFLUpglrO5PBn7gHECzfc7/3xO4ffuZf/BV8L9lbc7cX5BbVg2yWtKp4S2Enmo8T3Ez9Akbs4S8JBsBpeEz9P+osw+Vm7SfgYXfUwTfwdTazjGWtQCYN7HKKBVdzgCENsRiYV3KGFN0zKYZ6mapdRpY7jxK9wje6iabRK6Y6Db+Aj2CcesPLbSG+TQSfxIvH+sjdxEqJZymc+trlB+4/9g28CnkONSGOI8gAAAABJRU5ErkJggg==';
public static $save_reminder = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AgSFQseE+bgxAAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAS0lEQVQ4y6WTSQoAMAgDk/z/z+21lK6ON5UZEIklNdXLIbAkhcBVgccmBP4VeDUMgV8FPi1D4JvAL7eFwDuBf/4aAs8CV0NB0sirA+jtAijusTaJAAAAAElFTkSuQmCC';
public static $edit = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%0A%20%20%3Cpath%20d%3D%22M6%200l-1%201%202%202%201-1-2-2zm-2%202l-4%204v2h2l4-4-2-2z%22%20%2F%3E%0A%3C%2Fsvg%3E';
}
/**
* Message list struct used for user notices and system debug
*/
trait Hm_List {
/* message list */
private static $msgs = array();
/**
* Add a message
* @param string $string message to add
* @return void
*/
public static function add($string) {
self::$msgs[] = self::str($string, false);
}
/**
* Return all messages
* @return array all messages
*/
public static function get() {
return self::$msgs;
}
/**
* Flush all messages
* @return null
*/
public static function flush() {
self::$msgs = array();
}
/**
* Stringify a value
* @param mixed $mixed value to stringify
* @return string
*/
public static function str($mixed, $return_type=true) {
$type = gettype($mixed);
if (in_array($type, array('array', 'object'), true)) {
$str = print_r($mixed, true);
}
elseif ($return_type) {
$str = sprintf("%s: %s", $type, $mixed);
}
else {
$str = (string) $mixed;
}
return $str;
}
/**
* Log all messages
* @return bool
*/
public static function show() {
return Hm_Functions::error_log(print_r(self::$msgs, true));
}
}
/**
* Notices the user sees
*/
class Hm_Msgs { use Hm_List; }
/**
* System debug notices
*/
class Hm_Debug {
use Hm_List;
/**
* Add page execution stats to the Hm_Debug list
* @return void
*/
public static function load_page_stats() {
self::add(sprintf("PHP version %s", phpversion()));
self::add(sprintf("Zend version %s", zend_version()));
self::add(sprintf("Peak Memory: %d", (memory_get_peak_usage(true)/1024)));
self::add(sprintf("PID: %d", getmypid()));
self::add(sprintf("Included files: %d", count(get_included_files())));
}
}
/**
* Easy to use error logging
* @param mixed $mixed vaule to send to the log
* @return boolean|null
*/
function elog($mixed) {
if (DEBUG_MODE) {
$bt = debug_backtrace();
$caller = array_shift($bt);
Hm_Debug::add(sprintf('ELOG called in %s at line %d', $caller['file'], $caller['line']));
return Hm_Functions::error_log(Hm_Debug::str($mixed));
}
}
PK
S~m(7, 7, lib/dispatch.phpnu ٘ post) && $request->type == 'HTTP') {
$this->forward_messages($session, $request);
$session->end();
$this->redirect_to_url($mod_exec);
$this->redirect_to_current($request);
return true;
}
return false;
}
/**
* Redirect to the current url
* @param Hm_Request $request
* @return void
*/
private function redirect_to_current($request) {
if (array_key_exists('REQUEST_URI', $request->server)) {
Hm_Dispatch::page_redirect($this->validate_request_uri($request->server['REQUEST_URI']));
}
}
/**
* Redirect to a specified url
* @param object $mod_exec
* @return void
*/
private function redirect_to_url($mod_exec) {
if (array_key_exists('redirect_url', $mod_exec->handler_response) && $mod_exec->handler_response['redirect_url']) {
Hm_Dispatch::page_redirect($mod_exec->handler_response['redirect_url']);
}
}
/**
* Forward messages on a POST redirect
* @param object $session session object
* @return void
*/
private function forward_messages($session, $request) {
$msgs = Hm_Msgs::get();
if (!empty($msgs)) {
$session->secure_cookie($request, 'hm_msgs', base64_encode(json_encode($msgs)));
}
}
/**
* Validate a request uri
* @param string $uri URI to validate
* @return string
*/
public function validate_request_uri($uri) {
if ($uri === '') {
return '/';
}
$parts = parse_url($uri);
if (array_key_exists('scheme', $parts)) {
return '/';
}
if ($parts === false || !array_key_exists('path', $parts) || strpos($parts['path'], '..') !== false) {
return '/';
}
return $uri;
}
/**
* Redirect the page after a POST form is submitted and forward any user notices
* @param Hm_Request $request request object
* @param Hm_Module_Exec $mod_exec module manager object
* @param object $session session object
* @return string|false
*/
public function check_for_redirect($request, $mod_exec, $session) {
if (array_key_exists('no_redirect', $mod_exec->handler_response) && $mod_exec->handler_response['no_redirect']) {
return 'noredirect';
}
if ($this->post_redirect($request, $session, $mod_exec)) {
return 'redirect';
}
elseif (array_key_exists('redirect_url', $mod_exec->handler_response) &&
$mod_exec->handler_response['redirect_url']) {
$session->end();
$this->redirect_to_url($mod_exec);
return 'redirect';
}
elseif ($this->unpack_messages($request, $session)) {
return 'msg_forward';
}
return false;
}
/**
* Unpack forwarded messages
* @param Hm_Request $request request object
* @param object $session session object
* @return boolean
*/
public function unpack_messages($request, $session) {
if (array_key_exists('hm_msgs', $request->cookie) && trim($request->cookie['hm_msgs'])) {
$msgs = @json_decode(base64_decode($request->cookie['hm_msgs']), true);
if (is_array($msgs)) {
array_walk($msgs, function($v) { Hm_Msgs::add($v); });
}
$session->delete_cookie($request, 'hm_msgs');
return true;
}
return false;
}
/**
* Perform an HTTP redirect
* @param string $url url to redirect to
* @param int $status current HTTP status
* @return void
*/
static public function page_redirect($url, $status=false) {
if (DEBUG_MODE) {
Hm_Debug::add(sprintf('Redirecting to %s', $url));
Hm_Debug::load_page_stats();
Hm_Debug::show();
}
if ($status == 303) {
Hm_Debug::add('Redirect loop found');
Hm_Functions::cease('Redirect loop discovered');
}
Hm_Functions::header('HTTP/1.1 303 Found');
Hm_Functions::header('Location: '.$url);
Hm_Functions::cease();
}
}
/**
* Page request router that ties all the framework pieces together
* @package framework
* @subpackage dispatch
*/
class Hm_Dispatch {
use Hm_Dispatch_Redirect;
public $site_config;
public $request;
public $session;
public $module_exec;
public $page;
public $output;
/**
* Setup object needed to process a request
* @param object $config site configuration
*/
public function __construct($config) {
/* get the site config defined in the hm3.rc file */
$this->site_config = $config;
/* check for the site module set override */
$this->load_site_lib();
/* setup a session handler, but don't actually start a session yet */
$session_config = new Hm_Session_Setup($this->site_config);
$this->session = $session_config->setup_session();
/* instantiate the module runner */
$this->module_exec = new Hm_Module_Exec($this->site_config);
/* process request input using the white-lists defined in modules */
$this->request = new Hm_Request($this->module_exec->filters, $config);
/* do it */
$this->process_request();
}
/**
* Possibly include the site module lib.php overrides
* @return void
*/
private function load_site_lib() {
if (!is_array($this->site_config->get_modules()) || !in_array('site', $this->site_config->get_modules(), true)) {
return;
}
if (is_readable(APP_PATH.'modules/site/lib.php')) {
Hm_Debug::add('Including site module set lib.php');
require APP_PATH.'modules/site/lib.php';
}
}
/**
* Process a request
* @return void
*/
private function process_request() {
/* get the request identifier */
$this->get_page($this->module_exec->filters, $this->request);
/* load up the module requirements */
$this->module_exec->load_module_sets($this->page);
/* run handler modules to process input and perform actions */
$this->module_exec->run_handler_modules($this->request, $this->session, $this->page);
/* clean up any network connections */
$this->close_connections();
/* check for update settings on login */
$this->save_settings_on_login();
/* check to see if a handler module told us to redirect the browser */
$this->check_for_redirect($this->request, $this->module_exec, $this->session);
/* save and close a session if one is open */
$active_session = $this->save_session();
/* run the output formatting modules */
$this->module_exec->run_output_modules($this->request, $active_session, $this->page,
$this->module_exec->handler_response);
/* output content to the browser */
$this->render_output();
}
/**
* Check for a flag to save settings on login
*/
private function save_settings_on_login() {
if (!$this->session->loaded) {
return;
}
if ($this->module_exec->user_config->save_on_login) {
$this->module_exec->user_config->save($this->request->post['username'], $this->request->post['password']);
}
}
/**
* Close network connections if they exist
* @return void
*/
private function close_connections() {
foreach (array('Hm_IMAP_List', 'Hm_POP3_List', 'Hm_SMTP_List') as $class) {
if (Hm_Functions::class_exists($class)) {
$class::clean_up();
}
}
}
/**
* Close and save the session
* @return bool true if the session is active
*/
private function save_session() {
$res = $this->session->is_active();
$this->session->end();
return $res;
}
/**
* Format and send the request output to the browser
* @return void
*/
private function render_output() {
$formatter = new $this->request->format($this->site_config);
$class = $this->site_config->get('output_class', 'Hm_Output_HTTP');
$renderer = new $class;
$content = $formatter->content($this->module_exec->output_response, $this->request->allowed_output);
/* TODO: might be a good idea to use a custom render class that can return
* the output on demand */
$this->output = $renderer->send_response($content, $this->module_exec->output_data);
}
/**
* Get a list of valid pages
* @param array $filters list of filters
* @param return array
*/
private function get_pages($filters) {
$pages = array();
if (array_key_exists('allowed_pages', $filters)) {
$pages = $filters['allowed_pages'];
}
return $pages;
}
/**
* Check for a valid ajax request
* @param Hm_Request $request request details
* @param array $filters list of filters
* @return boolean
*/
public function validate_ajax_request($request, $filters) {
if (array_key_exists('hm_ajax_hook', $request->post)) {
if (in_array($request->post['hm_ajax_hook'], $this->get_pages($filters), true)) {
return true;
}
else {
Hm_Functions::cease(json_encode(array('status' => 'not callable')));;
}
}
return false;
}
/**
* Determine the page id
* @param array $filters list of filters
* @param Hm_Request $request request details
* @return void
*/
public function get_page($filters, $request) {
$this->page = 'notfound';
if ($request->type == 'AJAX' && $this->validate_ajax_request($request, $filters)) {
$this->page = $request->post['hm_ajax_hook'];
}
elseif (array_key_exists('page', $request->get) && in_array($request->get['page'], $this->get_pages($filters), true)) {
$this->page = $request->get['page'];
}
elseif (!array_key_exists('page', $request->get)) {
$this->page = 'home';
}
$this->module_exec->page = $this->page;
Hm_Debug::add('Page ID: '.$this->page);
}
/**
* Check to see if PHP is configured properly
* @return bool
*/
static public function is_php_setup() {
return
(float) substr(phpversion(), 0, 3) >= 5.4 &&
Hm_Functions::function_exists('mb_strpos') &&
Hm_Functions::function_exists('curl_exec') &&
Hm_Functions::function_exists('openssl_random_pseudo_bytes') &&
Hm_Functions::class_exists('PDO');
}
}
PK
S" " lib/session_php.phpnu ٘ load_auth_mech();
return $this->auth_mech->check_credentials($user, $pass);
}
/**
* Save auth detail if i'ts needed (mech specific)
* @return void
*/
public function save_auth_detail() {
$this->auth_mech->save_auth_detail($this);
}
/**
* Call the configuration authentication method to change the user password
* @param string $user username
* @param string $pass password
* @return bool true if the password was changed
*/
public function change_pass($user, $pass) {
$this->load_auth_mech();
return $this->auth_mech->change_pass($user, $pass);
}
/**
* Call the configuration authentication method to create an account
* @param string $user username
* @param string $pass password
* @return bool true if the account was created
*/
public function create($user, $pass) {
$this->load_auth_mech();
return $this->auth_mech->create($user, $pass);
}
}
/**
* PHP session data methods
* @package framework
* @subpackage session
*/
abstract class Hm_PHP_Session_Data extends Hm_Session {
/**
* @param Hm_Request $request request details
* @return void
*/
protected function validate_session_data($request) {
if ($this->existing && count($this->data) == 0) {
$this->destroy($request);
}
else {
Hm_Debug::add('LOGGED IN');
$this->active = true;
}
}
/**
* @param Hm_Request $request request details
* @return void
*/
protected function start_session_data($request) {
if (array_key_exists('data', $_SESSION)) {
$data = $this->plaintext($_SESSION['data']);
if (is_array($data)) {
$this->data = $data;
}
elseif (!$this->loaded) {
$this->destroy($request);
Hm_Debug::add('Mismatched session level encryption key');
}
}
}
/**
* Return a session value, or a user settings value stored in the session
* @param string $name session value name to return
* @param mixed $default value to return if $name is not found
* @param bool $user if true, only search the user_data section of the session
* @return mixed the value if found, otherwise $default
*/
public function get($name, $default=false, $user=false) {
if ($user) {
return array_key_exists('user_data', $this->data) && array_key_exists($name, $this->data['user_data']) ? $this->data['user_data'][$name] : $default;
}
else {
return array_key_exists($name, $this->data) ? $this->data[$name] : $default;
}
}
/**
* Save a value in the session
* @param string $name the name to save
* @param string $value the value to save
* @param bool $user if true, save in the user_data section of the session
* @return void
*/
public function set($name, $value, $user=false) {
if ($user) {
$this->data['user_data'][$name] = $value;
}
else {
$this->data[$name] = $value;
}
}
/**
* Delete a value from the session
* @param string $name name of value to delete
* @return void
*/
public function del($name) {
if (array_key_exists($name, $this->data)) {
unset($this->data[$name]);
return true;
}
return false;
}
/**
* Save session data
* @return void
*/
public function save_data() {
$enc_data = $this->ciphertext($this->data);
$_SESSION = array('data' => $enc_data);
session_write_close();
$_SESSION = array();
}
}
/**
* PHP Sessions that extend the base session class
* @package framework
* @subpackage session
*/
class Hm_PHP_Session extends Hm_PHP_Session_Data {
use Hm_Session_Auth;
/* data store connection used by classes that extend this */
public $conn;
/* flag to indicate an existing session */
protected $existing = false;
/**
* Setup newly authenticated session
* @param Hm_Request $request
* @param boolean $fingerprint
* @return null
*/
protected function authed($request, $fingerprint) {
$this->set_key($request);
$this->loaded = true;
$this->start($request);
if ($fingerprint) {
$this->set_fingerprint($request);
}
else {
$this->set('fingerprint', '');
}
$this->save_auth_detail();
$this->just_started();
}
/**
* Check for an existing session or a new user/pass login request
* @param object $request request details
* @param string $user username
* @param string $pass password
* @return bool
*/
public function check($request, $user=false, $pass=false, $fingerprint=true) {
if ($user !== false && $pass !== false) {
if ($this->auth($user, $pass)) {
$this->authed($request, $fingerprint);
}
}
elseif (array_key_exists($this->cname, $request->cookie)) {
$this->get_key($request);
$this->existing = true;
$this->start($request);
$this->check_fingerprint($request);
}
return $this->is_active();
}
/**
* Start the session. This could be an existing session or a new login
* @param Hm_Request $request request details
* @return void
*/
public function start($request) {
if (array_key_exists($this->cname, $request->cookie)) {
session_id($request->cookie[$this->cname]);
}
list($secure, $path, $domain) = $this->set_session_params($request);
session_set_cookie_params($this->lifetime, $path, $domain, $secure);
Hm_Functions::session_start();
$this->session_key = session_id();
$this->start_session_data($request);
$this->validate_session_data($request);
}
/**
* Setup the cookie params for a session cookie
* @param Hm_Request $request request details
* @return array list of cookie fields
*/
public function set_session_params($request) {
$path = false;
if ($request->tls) {
$secure = true;
}
else {
$secure = false;
}
if (isset($request->path)) {
$path = $request->path;
}
$domain = $this->site_config->get('cookie_domain', false);
if (!$domain && array_key_exists('HTTP_HOST', $request->server)) {
$host = parse_url($request->server['HTTP_HOST'], PHP_URL_HOST);
if (trim($host)) {
$domain = $host;
}
else {
$domain = $request->server['HTTP_HOST'];
}
}
if ($domain == 'none') {
$domain = '';
}
return array($secure, $path, $domain);
}
/**
* Write session data to avoid locking, keep session active, but don't allow writing
* @return void
*/
public function close_early() {
$this->session_closed = true;
$this->save_data();
}
/**
* Destroy a session for good
* @param Hm_Request $request request details
* @return void
*/
public function destroy($request) {
if (function_exists('delete_uploaded_files')) {
delete_uploaded_files($this);
}
session_unset();
Hm_Functions::session_destroy();
$params = session_get_cookie_params();
$this->delete_cookie($request, $this->cname, $params['path'], $params['domain']);
$this->delete_cookie($request, 'hm_id');
$this->delete_cookie($request, 'hm_reload_folders');
$this->delete_cookie($request, 'hm_msgs');
$this->active = false;
}
/**
* End a session after a page request is complete. This only closes the session and
* does not destroy it
* @return void
*/
public function end() {
if ($this->active) {
if (!$this->session_closed) {
$this->save_data();
}
$this->active = false;
}
}
}
PK
S8i! i! lib/servers.phpnu ٘ $server) {
self::disconnect($index);
}
}
}
/**
* Disconnect from a server
* @param int $id the server id to disconnect
* @return void
*/
public static function disconnect($id) {
if (self::$server_list[$id]['connected'] && self::$server_list[$id]['object']) {
if (method_exists(self::$server_list[$id]['object'], 'disconnect')) {
self::$server_list[$id]['object']->disconnect();
}
self::$server_list[$id]['connected'] = false;
}
}
}
/**
* Server list manager
* @package framework
* @subpackage servers
*/
trait Hm_Server_Modify {
use Hm_Server_Connect;
/**
* Update the oauth2 password and password expiration
* @param int $id server id
* @param string $pass new password
* @param int $expiry new password expiration timestamp
* @return bool
*/
public static function update_oauth2_token($id, $pass, $expiry) {
if (!array_key_exists($id, self::$server_list)) {
return false;
}
if (!array_key_exists('auth', self::$server_list[$id])) {
return false;
}
if (self::$server_list[$id]['auth'] != 'xoauth2') {
return false;
}
self::$server_list[$id]['pass'] = $pass;
self::$server_list[$id]['expiration'] = $expiry;
self::$server_list[$id]['object'] = false;
return true;
}
/**
* Remove the username and password from a connection
* @param int $id server id
* @return void
*/
public static function forget_credentials($id) {
if (array_key_exists($id, self::$server_list)) {
unset(self::$server_list[$id]['user']);
unset(self::$server_list[$id]['pass']);
}
}
/**
* Toggle the hidden status of a server
* @param int $id server id
* @param int $hide bool
* @return void
*/
public static function toggle_hidden($id, $hide) {
if (array_key_exists($id, self::$server_list)) {
self::$server_list[$id]['hide'] = $hide;
}
}
}
/**
* Struct that makes it easy for a module set to manage a list of server connections
* @package framework
* @subpackage servers
*/
trait Hm_Server_List {
use Hm_Server_Modify;
/**
* Add a server definition
* @param array $atts server details
* @param int $id server id
* @return void
*/
public static function add($atts, $id=false) {
$atts['object'] = false;
$atts['connected'] = false;
if ($id !== false) {
self::$server_list[$id] = $atts;
}
else {
self::$server_list[] = $atts;
}
}
/**
* Remove a server
* @param int $id server id
* @return bool true on success
*/
public static function del($id) {
if (array_key_exists($id, self::$server_list)) {
unset(self::$server_list[$id]);
return true;
}
return false;
}
/**
* Return all server details
* @param int $id if not false, return details for this server only
* @param bool $full true to return passwords for server connections. CAREFUL!
* @return array server details
*/
public static function dump($id=false, $full=false) {
$list = array();
if ($id !== false) {
return self::get($id, $full);
}
foreach (self::$server_list as $index => $server) {
if (!$full) {
$server = self::clean($server);
}
$list[$index] = $server;
}
return $list;
}
/**
* @param int $id server id to fetch
* @param bool $full true to return passwords for server connections. CAREFUL!
* @return array
*/
public static function get($id, $full) {
if (array_key_exists($id, self::$server_list)) {
$server = self::$server_list[$id];
if (!$full) {
return self::clean($server);
}
return $server;
}
return array();
}
/*
* @param array $server
* @return array
*/
public static function clean($server) {
if (!array_key_exists('pass', $server) || !$server['pass']) {
$server['nopass'] = true;
}
unset($server['pass']);
return $server;
}
/**
* Fetch a server by the username and servername
* @param string $username the user associated with the server
* @param string $servername the host associated with the server
* @return array|false
*/
public static function fetch($username, $servername) {
foreach (self::$server_list as $id => $server) {
if (self::match($server, $username, $servername)) {
if (array_key_exists('pass', $server)) {
unset($server['pass']);
}
$server['id'] = $id;
return $server;
}
}
return false;
}
/**
* @param array $server server details
* @param string $user username
* @param string $name server name
* @return boolean
*/
private static function match($server, $user, $name) {
if (array_key_exists('user', $server) && array_key_exists('server', $server)) {
if ($user == $server['user'] && $name == $server['server']) {
return true;
}
}
return false;
}
}
PK
S?w\a
lib/session_memcached.phpnu ٘ db_start($request);
}
/**
* save data on session start
* @return boolean|integer|array
*/
public function insert_session_row() {
return $this->save_data();
}
/**
* update memcache with current data
* @return boolean|integer|array
*/
public function save_data() {
$enc_data = $this->ciphertext($this->data);
return $this->conn->set($this->session_key, $enc_data, $this->cache_lifetime);
}
/**
* End a session after a page request is complete. This only closes the session and
* does not destroy it
* @return void
*/
public function end() {
if ($this->active && !$this->session_closed) {
$this->save_data();
$this->conn->close();
}
$this->active = false;
}
/**
* Close a session early, but don't destroy it
* @return void
*/
public function close_early() {
$this->session_closed = true;
$this->save_data();
$this->conn->close();
}
/**
* Destroy a session for good
* @param object $request request details
* @return void
*/
public function destroy($request) {
if (Hm_Functions::function_exists('delete_uploaded_files')) {
delete_uploaded_files($this);
}
$this->conn->del($this->session_key);
$this->delete_cookie($request, $this->cname);
$this->delete_cookie($request, 'hm_id');
$this->session_closed = true;
$this->conn->close();
$this->active = false;
Hm_Request_Key::load($this, $request, false);
}
/**
* @return boolean
*/
public function connect() {
$this->conn = new Hm_Memcached($this->site_config);
return $this->conn->is_active();
}
/**
* Get session data from the DB
* @param string $key session key
* @return mixed array results or false on failure
*/
public function get_session_data($key) {
return $this->plaintext($this->conn->get($key));
}
}
PK
S1=| lib/session_db.phpnu ٘ upsert('insert');
}
/**
* Connect to the configured DB
* @return bool true on success
*/
public function connect() {
return ($this->dbh = Hm_DB::connect($this->site_config)) ? true : false;
}
/**
* Start the session. This could be an existing session or a new login
* @param object $request request details
* @return void
*/
public function start($request) {
$this->db_start($request);
}
/**
* Start a new session
* @param object $request request details
* @return void
*/
public function start_new($request) {
$this->session_key = Hm_Crypt::unique_id();
$this->secure_cookie($request, $this->cname, $this->session_key);
if ($this->insert_session_row()) {
Hm_Debug::add('LOGGED IN');
$this->active = true;
return;
}
Hm_Debug::add('Failed to start a new session');
}
/**
* Continue an existing session
* @param string $key session key
* @return void
*/
public function start_existing($key) {
$this->session_key = $key;
$data = $this->get_session_data($key);
if (is_array($data)) {
Hm_Debug::add('LOGGED IN');
$this->active = true;
$this->data = $data;
}
}
/**
* Get session data from the DB
* @param string $key session key
* @return mixed array results or false on failure
*/
public function get_session_data($key) {
$results = Hm_DB::execute($this->dbh, 'select data from hm_user_session where hm_id=?', array($key));
if (is_array($results) && array_key_exists('data', $results)) {
return $this->plaintext($results['data']);
}
Hm_Debug::add('DB SESSION failed to read session data');
return false;
}
/**
* End a session after a page request is complete. This only closes the session and
* does not destroy it
* @return void
*/
public function end() {
if (!$this->session_closed && $this->active) {
$this->save_data();
}
$this->active = false;
}
/**
* Write session data to the db
* @return boolean|integer|array
*/
public function save_data() {
return $this->upsert('update');
}
/**
* Close a session early, but don't destroy it
* @return void
*/
public function close_early() {
$this->session_closed = true;
$this->save_data();
}
/**
* Update or insert a row
* @param string $type type of action (insert or update)
* @return boolean|integer|array
*/
public function upsert($type) {
$res = false;
$params = array(':key' => $this->session_key, ':data' => $this->ciphertext($this->data));
if ($type == 'update') {
$res = Hm_DB::execute($this->dbh, 'update hm_user_session set data=:data where hm_id=:key', $params);
}
elseif ($type == 'insert') {
$res = Hm_DB::execute($this->dbh, 'insert into hm_user_session values(:key, :data, current_date)', $params);
}
if (!$res) {
Hm_Debug::add('DB SESSION failed to write session data');
}
return $res;
}
/**
* Destroy a session for good
* @param object $request request details
* @return void
*/
public function destroy($request) {
if (Hm_Functions::function_exists('delete_uploaded_files')) {
delete_uploaded_files($this);
}
Hm_DB::execute($this->dbh, 'delete from hm_user_session where hm_id=?', array($this->session_key));
$this->delete_cookie($request, $this->cname);
$this->delete_cookie($request, 'hm_id');
$this->delete_cookie($request, 'hm_reload_folders');
$this->delete_cookie($request, 'hm_msgs');
$this->active = false;
Hm_Request_Key::load($this, $request, false);
}
/**
* Start the session. This could be an existing session or a new login
* @param object $request request details
* @return void
*/
public function db_start($request) {
if ($this->connect()) {
if ($this->loaded) {
$this->start_new($request);
}
elseif (!array_key_exists($this->cname, $request->cookie)) {
$this->destroy($request);
}
else {
$this->start_existing($request->cookie[$this->cname]);
}
}
}
}
PK
S<): : lib/format.phpnu ٘ config = $config;
}
/**
* Return combined output from all modules. Must be overridden by specific
* output classes
* @param array $allowed_output allowed fields for JSON responses
* @return mixed combined output
*/
abstract protected function content($input, $allowed_output);
}
/**
* Handles JSON formatted results for AJAX requests
*/
class Hm_Format_JSON extends HM_Format {
/**
* Run modules and merge + filter the result array
* @param array $output data from the handler modules
* @param array $allowed_output allowed fields for JSON responses
* @return string encoded data to be sent to the browser
*/
public function content($output, $allowed_output) {
$output['router_user_msgs'] = Hm_Msgs::get();
$output = $this->filter_all_output($output, $allowed_output);
if ($this->config->get('encrypt_ajax_requests', false)) {
$output = array('payload' => Hm_Crypt_Base::ciphertext(json_encode($output, JSON_FORCE_OBJECT), Hm_Request_Key::generate()));
}
return json_encode($output, JSON_FORCE_OBJECT);
}
/**
* Filter data against module set white lists before sending it to the browser
* @param array $data output module data to filter
* @param array $allowed set of white list filters
* @return array filtered data
*/
public function filter_all_output($data, $allowed) {
foreach ($data as $name => $value) {
if (!array_key_exists($name, $allowed)) {
unset($data[$name]);
continue;
}
$new_value = $this->filter_output($name, $value, $allowed);
if ($new_value === NULL) {
unset($data[$name]);
continue;
}
$data[$name] = $new_value;
}
return $data;
}
/**
* Filter a single output value
* @param string $name
* @param mixed $value
* @param array $allowed
* @return mixed
*/
private function filter_output($name, $value, $allowed) {
if ($allowed[$name][1]) {
$new_value = filter_var($value, $allowed[$name][0], $allowed[$name][1]);
}
else {
$new_value = filter_var($value, $allowed[$name][0]);
}
if ($new_value === false && $allowed[$name] != FILTER_VALIDATE_BOOLEAN) {
return NULL;
}
return $new_value;
}
}
/**
* Handles HTML5 formatted results for normal HTTP requests
*/
class Hm_Format_HTML5 extends HM_Format {
/**
* Collect and return content from modules for HTTP requests
* @param array $output data from the output modules
* @param array $allowed_output allowed fields for JSON responses
* @return string HTML5 content
*/
public function content($output, $allowed_output) {
if (array_key_exists('router_module_list', $output)) {
unset($output['router_module_list']);
}
return implode('', $output);
}
}
/**
* binary safe wrapper around json encode/decode using base64
*/
class Hm_Transform {
/**
* Convert an array to a string
* @param mixed $data data to be transformed to a string
* @param string $encoding encoding to use for values
* @return string on success, false on failure
*/
public static function stringify($data, $encoding='base64_encode') {
if (is_string($data)) {
return $data;
}
if (!is_array($data)) {
return (string) $data;
}
return @json_encode(self::hm_encode($data, $encoding));
}
/**
* @param string $data
* @return array|false
*/
public static function convert($data) {
if (substr($data, 0, 2) === 'a:') {
return @unserialize($data);
}
elseif (substr($data, 0, 1) === '{' || substr($data, 0, 1) === '[') {
return @json_decode($data, true);
}
return false;
}
/**
* Convert a stringified array back to an array
* @param string|false $data data to be transformed from a string
* @param string $encoding encoding to use for values
* @param boolean $return return original string if true
* @return mixed array on success, false or original string on failure
*/
public static function unstringify($data, $encoding='base64_decode', $return=false) {
if (!is_string($data) || !trim($data)) {
return false;
}
$result = self::convert($data);
if (is_array($result)) {
return self::hm_encode($result, $encoding);
}
if ($return) {
return $data;
}
return false;
}
/**
* Recursively encode values in an array
* @param array $data data to encode values for
* @param string $encoding the type of encoding to use
* @return array
*/
public static function hm_encode($data, $encoding) {
$result = array();
foreach ($data as $name => $val) {
if (is_array($val)) {
$result[$name] = self::hm_encode($val, $encoding);
}
else {
if (is_string($val)) {
$result[$name] = $encoding($val);
}
else {
$result[$name] = $val;
}
}
}
return $result;
}
}
PK
Sꁀ> > lib/modules.phpnu ٘ = self::$queue_limit) {
$requeue = false;
}
foreach (self::$module_queue as $vals) {
if (!self::add($vals[0], $vals[1], $vals[2], $vals[3], $vals[4], $requeue, $vals[5])) {
$new_queue[] = $vals;
}
}
self::$module_queue = $new_queue;
self::$queue_attempts++;
}
}
/**
* Trait used as the basic logic for module management
*
* Two classes use this trait, Hm_Handler_Modules and Hm_Output_Modules.
* These are the interfaces module sets use (indirectly) to interact with a request
* and produce output to the browser.
*/
trait Hm_Modules {
use Hm_Modules_Queue;
/**
* Load a complete formatted module list
* @param array $mod_list list of module assignments
* @return void
*/
public static function load($mod_list) {
self::$module_list = $mod_list;
}
/**
* Assign the module set name
* @param string $source the name of the module set (imap, pop3, core, etc)
* @return void
*/
public static function set_source($source) {
self::$source = $source;
}
/**
* Add a module to every defined page
* @param string $module the module to add
* @param bool $logged_in true if the module requires the user to be logged in
* @param string $marker the module to insert before or after
* @param string $placement "before" or "after" the $marker module
* @param string $source the module set containing this module
* @return void
*/
public static function add_to_all_pages($module, $logged_in, $marker, $placement, $source) {
foreach (self::$module_list as $page => $modules) {
if (!preg_match("/^ajax_/", $page)) {
self::add($page, $module, $logged_in, $marker, $placement, true, $source);
}
}
}
/**
* Add a module to a single page
* @param string $page the page to assign the module to
* @param string $module the module to add
* @param bool $logged_in true if the module requires the user to be logged in
* @param string $marker the module to insert before or after
* @param string $placement "before" or "after" the $marker module
* @param bool $queue true to attempt to re-insert the module later on failure
* @param string $source the module set containing this module
* @return bool true if the module was added or was already registered
*/
public static function add($page, $module, $logged_in, $marker=false, $placement='after', $queue=true, $source=false) {
self::add_page($page);
if (array_key_exists($module, self::$module_list[$page])) {
Hm_Debug::add(sprintf("Already registered module for %s re-attempted: %s", $page, $module));
return true;
}
$source === false ? $source = self::$source : false;
$inserted = self::insert_module($marker, $page, $module, $logged_in, $placement, $source);
if (!$inserted) {
self::queue_module($queue, $page, $module, $logged_in, $marker, $placement, $source);
}
return $inserted;
}
/**
* @param string $page page id to add
* @return boolean
*/
private static function add_page($page) {
if (!array_key_exists($page, self::$module_list)) {
self::$module_list[$page] = array();
return true;
}
return false;
}
/**
* @param string|false $marker the module to insert before or after
* @param string $page the page to assign the module to
* @param string $module the module to add
* @param bool $logged_in true if the module requires the user to be logged in
* @param string $placement "before" or "after" the $marker module
* @param string $source the module set containing this module
* @return boolean
*/
private static function insert_module($marker, $page, $module, $logged_in, $placement, $source) {
if ($marker !== false) {
$inserted = self::insert_at_marker($marker, $page, $module, $logged_in, $placement, $source);
}
else {
self::$module_list[$page][$module] = array($source, $logged_in);
$inserted = true;
}
return $inserted;
}
/**
* Insert a module before or after another one
* @param string $marker the module to insert before or after
* @param string $page the page to assign the module to
* @param string $module the module to add
* @param bool $logged_in true if the module requires the user to be logged in
* @param string $placement "before" or "after" the $marker module
* @param string $source the module set containing this module
* @return boolean
*/
private static function insert_at_marker($marker, $page, $module, $logged_in, $placement, $source) {
$inserted = false;
$mods = array_keys(self::$module_list[$page]);
$index = array_search($marker, $mods);
if ($index !== false) {
if ($placement == 'after') {
$index++;
}
$list = self::$module_list[$page];
self::$module_list[$page] = array_merge(array_slice($list, 0, $index),
array($module => array($source, $logged_in)),
array_slice($list, $index));
$inserted = true;
}
return $inserted;
}
/**
* Replace an already assigned module with a different one
* @param string $target module name to replace
* @param string $replacement module name to swap in
* @param string $page page to replace assignment on, try all pages if false
* @param string $source module set source
* @return void
*/
public static function replace($target, $replacement, $page=false, $source=false) {
$found = false;
if ($page !== false) {
if (array_key_exists($page, self::$module_list) && array_key_exists($target, self::$module_list[$page])) {
self::$module_list[$page] = self::swap_key($target, $replacement, self::$module_list[$page], $source);
$found = true;
}
}
else {
foreach (self::$module_list as $page => $modules) {
if (array_key_exists($target, $modules)) {
self::$module_list[$page] = self::swap_key($target, $replacement, self::$module_list[$page], $source);
$found = true;
}
}
}
if (!$found) {
self::queue_replacement_module($target, $replacement, $page);
}
}
/**
* Helper function to swap the key of an array and maintain it's value
* @param string $target array key to replace
* @param string $replacement array key to swap in
* @param array $modules list of modules
* @param string $source module set source
* @return array new list with the key swapped out
*/
private static function swap_key($target, $replacement, $modules, $source) {
if (!$source) {
$source = self::$source;
}
$keys = array_keys($modules);
$values = array_values($modules);
$size = count($modules);
for ($i = 0; $i < $size; $i++) {
if ($keys[$i] == $target) {
$keys[$i] = $replacement;
$values[$i][0] = $source;
break;
}
}
return array_combine($keys, $values);
}
/**
* Delete a module from the internal list
* @param string $page page to delete from
* @param string $module module name to delete
* @return void
*/
public static function del($page, $module) {
if (array_key_exists($page, self::$module_list) && array_key_exists($module, self::$module_list[$page])) {
unset(self::$module_list[$page][$module]);
}
}
/**
* Return all the modules assigned to a given page
* @param string $page the request name
* @return array list of assigned modules
*/
public static function get_for_page($page) {
$res = array();
if (array_key_exists($page, self::$module_list)) {
$res = array_merge($res, self::$module_list[$page]);
}
return $res;
}
/**
* Return all modules for all pages
* @return array list of all modules
*/
public static function dump() {
return self::$module_list;
}
}
/**
* Class to manage all the input processing modules
*/
class Hm_Handler_Modules { use Hm_Modules; }
/**
* Class to manage all the output modules
*/
class Hm_Output_Modules { use Hm_Modules; }
/**
* MODULE SET FUNCTIONS
*
* This is the functional interface used by module sets to
* setup data handlers and output modules in their setup.php files.
* They are easier to use than dealing directly with the class instances
*/
/**
* Add a module set name to the input processing manager
* @param string $source module set name
* @return void
*/
function handler_source($source) {
Hm_Handler_Modules::set_source($source);
}
/**
* Add a module set name to the output module manager
* @param string $source module set name
* @return void
*/
function output_source($source) {
Hm_Output_Modules::set_source($source);
}
/**
* Replace an already assigned module with a different one
* @param string $type either output or handler
* @param string $target module name to replace
* @param string $replacement module to swap in
* @param string $page request id, otherwise try all page names
* $return void
*/
function replace_module($type, $target, $replacement, $page=false) {
if ($type == 'handler') {
Hm_Handler_Modules::replace($target, $replacement, $page);
}
elseif ($type == 'output') {
Hm_Output_Modules::replace($target, $replacement, $page);
}
}
/**
* Add an input handler module to a specific page
* @param string $mod name of the module to add
* @param bool $logged_in true if the module should only fire when logged in
* @param string $source the module set containing the module code
* @param string $marker the module name used to determine where to insert
* @param string $placement "before" or "after" the $marker module name
* @param bool $queue true if the module should be queued and retryed on failure
* @return void
*/
function add_handler($page, $mod, $logged_in, $source=false, $marker=false, $placement='after', $queue=true) {
Hm_Handler_Modules::add($page, $mod, $logged_in, $marker, $placement, $queue, $source);
}
/**
* Add an output module to a specific page
* @param string $mod name of the module to add
* @param bool $logged_in true if the module should only fire when logged in
* @param string $source the module set containing the module code
* @param string $marker the module name used to determine where to insert
* @param string $placement "before" or "after" the $marker module name
* @param bool $queue true if the module should be queued and retryed on failure
* @return void
*/
function add_output($page, $mod, $logged_in, $source=false, $marker=false, $placement='after', $queue=true) {
Hm_Output_Modules::add($page, $mod, $logged_in, $marker, $placement, $queue, $source);
}
/**
* Add an input or output module to all possible pages
* @param string $type either output or handler
* @param string $mod name of the module to add
* @param bool $logged_in true if the module should only fire when logged in
* @param string $source the module set containing the module code
* @param string $marker the module name used to determine where to insert
* @param string $placement "before" or "after" the $marker module name
* @return void
*/
function add_module_to_all_pages($type, $mod, $logged_in, $source, $marker, $placement) {
if ($type == 'output') {
Hm_Output_Modules::queue_module_for_all_pages($mod, $logged_in, $marker, $placement, $source);
}
elseif ( $type == 'handler') {
Hm_Handler_Modules::queue_module_for_all_pages($mod, $logged_in, $marker, $placement, $source);
}
}
PK
S= " " lib/request.phpnu ٘ get('always_mobile_ui', false)) {
$this->always_mobile = true;
}
$this->filters = $filters;
$this->filter_request_input();
$this->get_other_request_details();
$this->files = $_FILES;
if (!$config->get('disable_empty_superglobals', false)) {
$this->empty_super_globals();
}
Hm_Debug::add('Using sapi: '.$this->sapi);
Hm_Debug::add('Request type: '.$this->type);
Hm_Debug::add('Request path: '.$this->path);
Hm_Debug::add('TLS request: '.intval($this->tls));
Hm_Debug::add('Mobile request: '.intval($this->mobile));
}
/**
* Sanitize and filter user and server input
* @return void
*/
private function filter_request_input() {
if (array_key_exists('allowed_server', $this->filters)) {
$this->server = $this->filter_input(INPUT_SERVER, $this->filters['allowed_server']);
$this->env = $this->filter_input(INPUT_ENV, $this->filters['allowed_server']);
}
if (array_key_exists('allowed_post', $this->filters)) {
$this->post = $this->filter_input(INPUT_POST, $this->filters['allowed_post']);
}
if (array_key_exists('allowed_get', $this->filters)) {
$this->get = $this->filter_input(INPUT_GET, $this->filters['allowed_get']);
}
if (array_key_exists('allowed_cookie', $this->filters)) {
$this->cookie = $this->filter_input(INPUT_COOKIE, $this->filters['allowed_cookie']);
}
}
/**
* Collect other useful details about a request
* @return void
*/
private function get_other_request_details() {
$this->sapi = php_sapi_name();
if (array_key_exists('allowed_output', $this->filters)) {
$this->allowed_output = $this->filters['allowed_output'];
}
if (array_key_exists('REQUEST_URI', $this->server)) {
$this->path = $this->get_clean_url_path($this->server['REQUEST_URI']);
}
if (array_key_exists('REQUEST_METHOD', $this->server)) {
$this->method = $this->server['REQUEST_METHOD'];
}
elseif (array_key_exists('REQUEST_METHOD', $this->env)) {
$this->method = $this->env['REQUEST_METHOD'];
$this->server = $this->env;
}
$this->get_request_type();
$this->is_tls();
$this->is_mobile();
}
/**
* Empty out super globals.
* @return void
*/
private function empty_super_globals() {
$_POST = array();
$_SERVER = array();
$_GET = array();
$_COOKIE = array();
$_FILES = array();
$_REQUEST = array();
$_ENV = array();
$GLOBALS = array();
}
/**
* Filter specified input against module defined filters
* @param type string the type of input (POST, GET, COOKIE, etc)
* @param filters array list of input filters from module sets
* @return array filtered input data
*/
public function filter_input($type, $filters) {
$data = Hm_Functions::filter_input_array($type, $filters);
if ($data === false || $data === NULL) {
return array();
}
return $data;
}
/**
* Look at the HTTP_USER_AGENT value and set a mobile OS flag
* @return void
*/
private function is_mobile() {
if ($this->always_mobile) {
$this->mobile = true;
return;
}
if (array_key_exists('HTTP_USER_AGENT', $this->server)) {
if (preg_match("/(iphone|ipod|ipad|android|blackberry|webos|opera mini)/i", $this->server['HTTP_USER_AGENT'])) {
$this->mobile = true;
}
}
}
/**
* Determine if a request was done over TLS
* @return void
*/
private function is_tls() {
if (array_key_exists('HTTPS', $this->server) && strtolower($this->server['HTTPS']) == 'on') {
$this->tls = true;
}
elseif (array_key_exists('REQUEST_SCHEME', $this->server) && strtolower($this->server['REQUEST_SCHEME']) == 'https') {
$this->tls = true;
}
}
/**
* Determine the request type, either AJAX or HTTP
* @return void
*/
private function get_request_type() {
if ($this->is_ajax()) {
$this->type = 'AJAX';
$this->format = 'Hm_Format_JSON';
}
else {
$this->type = 'HTTP';
$this->format = 'Hm_Format_HTML5';
}
}
/**
* Determine if a request is an AJAX call
* @return bool true if the request is from an AJAX call
*/
public function is_ajax() {
return array_key_exists('HTTP_X_REQUESTED_WITH', $this->server) && strtolower($this->server['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
}
/**
* Make sure a url path is sane
* @param string $uri path to check
* @return string clean url path
*/
private function get_clean_url_path($uri) {
if (strpos($uri, '?') !== false) {
$parts = explode('?', $uri, 2);
$path = $parts[0];
}
else {
$path = $uri;
}
$path = str_replace('index.php', '', $path);
if (substr($path, -1) != '/') {
$path .= '/';
}
return $path;
}
}
PK
S % lib/oauth2.phpnu ٘ client_id = $id;
$this->client_secret = $secret;
$this->redirect_uri = $uri;
$this->api = new Hm_API_Curl();
}
/**
* Build a URL to request an authorization
* @param string $url host to request authorization from
* @param string $scope oauth2 scope
* @param string $state current state of the oauth2 flow
* @param string $login_hint optional username
* @return string
*/
public function request_authorization_url($url, $scope, $state, $login_hint=false) {
$res = sprintf('%s?response_type=code&scope=%s&state=%s&'.
'approval_prompt=force&access_type=offline&client_id=%s&redirect_uri=%s',
$url, $scope, $state, $this->client_id, $this->redirect_uri);
if ($login_hint !== false) {
$res .= '&login_hint='.$login_hint;
}
return $res;
}
/**
* Use curl to exchange an authorization code for a token
* @param string $url url to post to
* @param string $authorization_code oauth2 auth code
* @param array $headers HTTP headers to add to the request
* @return array
*/
public function request_token($url, $authorization_code, $headers=array()) {
return $this->api->command($url, $headers, array('code' => $authorization_code, 'client_id' => $this->client_id,
'client_secret' => $this->client_secret, 'redirect_uri' => $this->redirect_uri, 'grant_type' => 'authorization_code'));
}
/**
* Use curl to refresh an access token
* @param string $url url to to post to
* @param string $refresh_token oauth2 refresh token
* @return array
*/
public function refresh_token($url, $refresh_token) {
return $this->api->command($url, array(), array('client_id' => $this->client_id, 'client_secret' => $this->client_secret,
'refresh_token' => $refresh_token, 'grant_type' => 'refresh_token'));
}
}
PK
SyV>: >: lib/config.phpnu ٘ VERSION);
/* flag indicating failed decryption */
public $decrypt_failed = false;
/* if decryption fails, save the encrypted payload */
public $encrypted_str;
/* flag to save config after page handling */
public $save_on_login = false;
/**
* This method must be overriden by classes extending this one
* @param string $source source or identifier to determine the source
* @param string $key encryption key
*/
abstract public function load($source, $key);
/**
* Return all config values
* @return array list of config values
*/
public function dump() {
return $this->config;
}
/**
* Delete a setting
* @param string $name config option name
* @return bool true on success
*/
public function del($name) {
if (array_key_exists($name, $this->config)) {
unset($this->config[$name]);
return true;
}
return false;
}
/**
* Return a versoin number
* @return float
*/
public function version() {
if (array_key_exists('version', $this->config)) {
return $this->config['version'];
}
return .1;
}
/**
* Set a config value
* @param string $name config value name
* @param string $value config value
* @return void
*/
public function set($name, $value) {
$this->config[$name] = $value;
}
/**
* Return a config value if it exists
* @param string $name config value name
* @param false|string $default value to return if the name is not found
* @return mixed found value, otherwise $default
*/
public function get($name, $default=false) {
return array_key_exists($name, $this->config) ? $this->config[$name] : $default;
}
/**
* Set the timezone
* @return void
*/
public function set_tz() {
date_default_timezone_set($this->get('timezone_setting', 'UTC'));
}
/**
* Shuffle the config value order
* @return void
*/
public function shuffle() {
$new_config = array();
$keys = array_keys($this->config);
shuffle($keys);
foreach ($keys as $key) {
$new_config[$key] = $this->config[$key];
}
$this->config = $new_config;
}
/**
* Decode user settings with json_decode or unserialize depending
* on the format
* @param string|false $data serialized or json encoded string
* @return mixed array, or false on failure
*/
public function decode($data) {
if (!is_string($data) || !trim($data)) {
return false;
}
return Hm_Transform::convert($data);
}
/**
* Filter out default auth and SMTP servers so they don't get saved
* to the permanent user config. These are dynamically reloaded on
* login
* @return array of items removed
*/
public function filter_servers() {
$removed = array();
$excluded = array('pop3_servers', 'imap_servers','smtp_servers');
$no_password = $this->get('no_password_save_setting', false);
foreach ($this->config as $key => $vals) {
if (in_array($key, $excluded, true)) {
foreach ($vals as $index => $server) {
if (array_key_exists('default', $server) && $server['default']) {
$removed[$key][$index] = $server;
unset($this->config[$key][$index]);
}
elseif (!array_key_exists('server', $server)) {
$removed[$key][$index] = $server;
unset($this->config[$key][$index]);
}
else {
$this->config[$key][$index]['object'] = false;
if ($no_password) {
if (!array_key_exists('auth', $server) || $server['auth'] != 'xoauth2') {
$removed[$key][$index]['pass'] = $server['pass'];
unset($this->config[$key][$index]['pass']);
}
}
}
}
}
}
return $removed;
}
/**
* Restore server definitions removed before saving
* @param array $removed server info to restore
* @return void
*/
public function restore_servers($removed) {
foreach ($removed as $key => $vals) {
foreach ($vals as $index => $server) {
if (is_array($server)) {
$this->config[$key][$index] = $server;
}
else {
$this->config[$key][$index]['pass'] = $server;
}
}
}
}
}
/**
* File based user settings
*/
class Hm_User_Config_File extends Hm_Config {
/* config values */
private $site_config;
/* encrption flag */
private $crypt;
/* username */
private $username;
/**
* Load site configuration
* @param object $config site config
*/
public function __construct($config) {
$this->crypt = crypt_state($config);
$this->site_config = $config;
$this->config = array_merge($this->config, $config->user_defaults);
}
/**
* Get the filesystem path for a user settings file
* @param string $username username
* @return string filepath to the user config file
*/
public function get_path($username) {
$path = $this->site_config->get('user_settings_dir', false);
return sprintf('%s/%s.txt', $path, $username);
}
/**
* Load the settings for a user
* @param string $username username
* @param string $key key to decrypt the user data
* @return void
*/
public function load($username, $key) {
$this->username = $username;
$source = $this->get_path($username);
if (is_readable($source)) {
$str_data = file_get_contents($source);
if ($str_data) {
if (!$this->crypt) {
$data = $this->decode($str_data);
}
else {
$data = $this->decode(Hm_Crypt::plaintext($str_data, $key));
}
if (is_array($data)) {
$this->config = array_merge($this->config, $data);
$this->set_tz();
}
else {
$this->decrypt_failed = true;
$this->encrypted_str = $str_data;
}
}
}
}
/**
* Reload from outside input
* @param array $data new user data
* @param string $username
* @return void
*/
public function reload($data, $username=false) {
$this->username = $username;
$this->config = $data;
$this->set_tz();
}
/**
* Save user settings to a file
* @param string $username username
* @param string $key encryption key
* @return void
*/
public function save($username, $key) {
$this->shuffle();
$destination = $this->get_path($username);
$removed = $this->filter_servers();
if (!$this->crypt) {
$data = json_encode($this->config);
}
else {
$data = Hm_Crypt::ciphertext(json_encode($this->config), $key);
}
file_put_contents($destination, $data);
$this->restore_servers($removed);
}
/**
* Set a config value
* @param string $name config value name
* @param string $value config value
* @return void
*/
public function set($name, $value) {
$this->config[$name] = $value;
if (!$this->crypt) {
$this->save($this->username, false);
}
}
}
/**
* DB based user settings
*/
class Hm_User_Config_DB extends Hm_Config {
/* site configuration */
private $site_config;
/* DB connection handle */
private $dbh;
/* encrption class */
private $crypt;
/* username */
private $username;
/**
* Load site config
* @param object $config site config
*/
public function __construct($config) {
$this->crypt = crypt_state($config);
$this->site_config = $config;
$this->config = array_merge($this->config, $config->user_defaults);
}
/**
* @param string $username
* @return boolean
*/
private function new_settings($username) {
$res = Hm_DB::execute($this->dbh, 'insert into hm_user_settings values(?,?)', array($username, ''));
Hm_Debug::add(sprintf("created new row in hm_user_settings for %s", $username));
$this->config = array();
return $res ? true : false;
}
/**
* @param array $data
* @param string $key
* @return boolean
*/
private function decrypt_settings($data, $key) {
if (!$this->crypt) {
$data = $this->decode($data['settings']);
}
else {
$data = $this->decode(Hm_Crypt::plaintext($data['settings'], $key));
}
if (is_array($data)) {
$this->config = array_merge($this->config, $data);
$this->set_tz();
return true;
}
else {
$this->decrypt_failed = true;
return false;
}
}
/**
* Load the user settings from the DB
* @param string $username username
* @param string $key encryption key
* @return boolean
*/
public function load($username, $key) {
$this->username = $username;
$this->connect();
$data = Hm_DB::execute($this->dbh, 'select * from hm_user_settings where username=?', array($username));
if (!$data || !array_key_exists('settings', $data)) {
return $this->new_settings($username);
}
return $this->decrypt_settings($data, $key);
}
/**
* Reload from outside input
* @param array $data new user data
* @param string $username
* @return void
*/
public function reload($data, $username=false) {
$this->username = $username;
$this->config = $data;
$this->set_tz();
}
/**
* Connect to a configured DB
* @return bool true on success
*/
public function connect() {
return ($this->dbh = Hm_DB::connect($this->site_config)) ? true : false;
}
/**
* Save user settings to the DB
* @param string $username username
* @param string $key encryption key
* @return integer|boolean|array
*/
public function save($username, $key) {
$this->shuffle();
$removed = $this->filter_servers();
if (!$this->crypt) {
$config = json_encode($this->config);
}
else {
$config = Hm_Crypt::ciphertext(json_encode($this->config), $key);
}
$this->connect();
if (Hm_DB::execute($this->dbh, 'update hm_user_settings set settings=? where username=?', array($config, $username))) {
Hm_Debug::add(sprintf("Saved user data to DB for %s", $username));
$res = true;
}
else {
$res = Hm_DB::execute($this->dbh, 'insert into hm_user_settings values(?,?)', array($username, $config));
}
$this->restore_servers($removed);
return $res;
}
/**
* Set a config value
* @param string $name config value name
* @param string $value config value
* @return void
*/
public function set($name, $value) {
$this->config[$name] = $value;
if (!$this->crypt) {
$this->save($this->username, false);
}
}
}
/**
* File based site configuration
*/
class Hm_Site_Config_File extends Hm_Config {
public $user_defaults = array();
/**
* Load data based on source
* @param string $source source location for site configuration
*/
public function __construct($source) {
$this->load($source, false);
}
/**
* Load site data from a file
* @param string $source file path to the site configuration
* @param string $key encryption key (unsued in this class)
* @return void
*/
public function load($source, $key) {
if (is_readable($source)) {
$data = $this->decode(file_get_contents($source));
if ($data) {
$this->config = array_merge($this->config, $data);
$this->get_user_defaults();
}
}
}
/*
* Determine default values for users without any settings
* @return void
*/
private function get_user_defaults() {
foreach ($this->config as $name => $val) {
if (substr($name, 0, 15) == 'default_setting') {
$this->user_defaults[substr($name, 16).'_setting'] = $val;
}
}
}
/**
* Return a list of modules as an array
* @return array|false
*/
public function get_modules() {
$mods = $this->get('modules');
if (is_string($mods)) {
return explode(',', $mods);
}
return $mods;
}
}
/**
* Load a user config object
* @param object $config site configuration
* @return object
*/
function load_user_config_object($config) {
$type = $config->get('user_config_type', 'file');
if (strstr($type, ':')) {
list($type, $class) = explode(':', $type);
}
switch ($type) {
case 'DB':
$user_config = new Hm_User_Config_DB($config);
Hm_Debug::add("Using DB user configuration");
break;
case 'custom':
if (class_exists($class)) {
$user_config = new $class($config);
Hm_Debug::add("Using custom user configuration: $class");
break;
} else {
Hm_Debug::add("User configuration class does not exist: $class");
}
default:
$user_config = new Hm_User_Config_File($config);
Hm_Debug::add("Using file based user configuration");
break;
}
return $user_config;
}
/**
* Determine encryption for user settings
* @param object $config site configuration
* @return boolean
*/
function crypt_state($config) {
if ($config->get('single_server_mode') &&
in_array($config->get('auth_type'), array('IMAP', 'POP3'), true)) {
return false;
}
return true;
}
PK
S`F lib/session_redis.phpnu ٘ conn = new Hm_Redis($this->site_config);
return $this->conn->is_active();
}
}
PK
SL5 L5 lib/session_base.phpnu ٘ site_config->get('disable_fingerprint')) {
return;
}
$id = $this->build_fingerprint($request->server);
$fingerprint = $this->get('fingerprint', null);
if ($fingerprint === false) {
$this->set_fingerprint($request);
return;
}
if (!$fingerprint || $fingerprint !== $id) {
Hm_Debug::add('HTTP header fingerprint check failed');
$this->destroy($request);
}
}
/**
* Browser request properties to build a fingerprint with
* @return array
*/
private function fingerprint_flds() {
$flds = array('HTTP_USER_AGENT', 'REQUEST_SCHEME', 'HTTP_ACCEPT_LANGUAGE',
'HTTP_ACCEPT_CHARSET', 'HTTP_HOST');
if (!$this->site_config->get('allow_long_session') && !$this->site_config->get('disable_ip_check')) {
$flds[] = 'REMOTE_ADDR';
}
return $flds;
}
/**
* Build HTTP header "fingerprint"
* @param array $env server env values
* @return string fingerprint value
*/
public function build_fingerprint($env, $input='') {
$id = $input;
foreach ($this->fingerprint_flds() as $val) {
$id .= (array_key_exists($val, $env)) ? $env[$val] : '';
}
return hash('sha256', $id);
}
/**
* Save a fingerprint in the session
* @param object $request request details
* @return void
*/
protected function set_fingerprint($request) {
$id = $this->build_fingerprint($request->server);
$this->set('fingerprint', $id);
}
}
/**
* Base class for session management. All session interaction happens through
* classes that extend this.
* @abstract
*/
abstract class Hm_Session {
use Hm_Session_Fingerprint;
/* set to true if the session was just loaded on this request */
public $loaded = false;
/* set to true if the session is active */
public $active = false;
/* set to true if the user authentication is local (DB) */
public $internal_users = false;
/* key used to encrypt session data */
public $enc_key = '';
/* authentication class name */
public $auth_class;
/* site config object */
public $site_config;
/* session data */
protected $data = array();
/* session cookie name */
protected $cname = 'hm_session';
/* authentication object */
protected $auth_mech;
/* close early flag */
protected $session_closed = false;
/* session key */
public $session_key = '';
/* session lifetime */
public $lifetime = 0;
/**
* check for an active session or an attempt to start one
* @param object $request request object
* @return bool
*/
abstract protected function check($request);
/**
* Start the session. This could be an existing session or a new login
* @param object $request request details
* @return void
*/
abstract protected function start($request);
/**
* Call the configured authentication method to check user credentials
* @param string $user username
* @param string $pass password
* @return bool true if the authentication was successful
*/
abstract protected function auth($user, $pass);
/**
* Delete a value from the session
* @param string $name name of value to delete
* @return void
*/
abstract protected function del($name);
/**
* End a session after a page request is complete. This only closes the session and
* does not destroy it
* @return void
*/
abstract protected function end();
/**
* Setup initial data
* @param object $config site config
* @param string $auth_type authentication class
*/
public function __construct($config, $auth_type='Hm_Auth_DB') {
$this->site_config = $config;
$this->auth_class = $auth_type;
$this->internal_users = $auth_type::$internal_users;
}
/**
* Lazy loader for the auth mech so modules can define their own
* overrides
* @return void
*/
protected function load_auth_mech() {
if (!is_object($this->auth_mech)) {
$this->auth_mech = new $this->auth_class($this->site_config);
}
}
/**
* Dump current session contents
* @return array
*/
public function dump() {
return $this->data;
}
/**
* Method called on a new login
* @return void
*/
protected function just_started() {
$this->set('login_time', time());
}
/**
* Record session level changes not yet saved in persistant storage
* @param string $value short description of the unsaved value
* @return void
*/
public function record_unsaved($value) {
$this->data['changed_settings'][] = $value;
}
/**
* Returns bool true if the session is active
* @return bool
*/
public function is_active() {
return $this->active;
}
/**
* Returns bool true if the user is an admin
* @return bool
*/
public function is_admin() {
if (!$this->active) {
return false;
}
$admins = array_filter(explode(',', $this->site_config->get('admin_users', '')));
if (empty($admins)) {
return false;
}
$user = $this->get('username', '');
if (!strlen($user)) {
return false;
}
return in_array($user, $admins, true);
}
/**
* Encrypt session data
* @param array $data session data to encrypt
* @return string encrypted session data
*/
public function ciphertext($data) {
return Hm_Crypt::ciphertext(Hm_transform::stringify($data), $this->enc_key);
}
/**
* Decrypt session data
* @param string $data encrypted session data
* @return false|array decrpted session data
*/
public function plaintext($data) {
return Hm_transform::unstringify(Hm_Crypt::plaintext($data, $this->enc_key));
}
/**
* Set the session level encryption key
* @param Hm_Request $request request details
* @return void
*/
protected function set_key($request) {
$this->enc_key = Hm_Crypt::unique_id();
$this->secure_cookie($request, 'hm_id', $this->enc_key);
}
/**
* Fetch the current encryption key
* @param object $request request details
* @return void
*/
public function get_key($request) {
if (array_key_exists('hm_id', $request->cookie)) {
$this->enc_key = $request->cookie['hm_id'];
}
else {
Hm_Debug::add('Unable to get session encryption key');
}
}
/**
* @param Hm_Request $request request object
* @return string
*/
private function cookie_domain($request) {
$domain = $this->site_config->get('cookie_domain', false);
if ($domain == 'none') {
return '';
}
if (!$domain && array_key_exists('HTTP_HOST', $request->server)) {
$domain = $request->server['HTTP_HOST'];
}
return $domain;
}
/**
* @param Hm_Request $request request object
* @return string
*/
private function cookie_path($request) {
$path = $this->site_config->get('cookie_path', false);
if ($path == 'none') {
$path = '';
}
if (!$path) {
$path = $request->path;
}
return $path;
}
/**
* Set a cookie, secure if possible
* @param object $request request details
* @param string $name cookie name
* @param string $value cookie value
* @param string $path cookie path
* @param string $domain cookie domain
* @return boolean
*/
public function secure_cookie($request, $name, $value, $path='', $domain='') {
list($path, $domain, $html_only) = $this->prep_cookie_params($request, $name, $path, $domain);
return Hm_Functions::setcookie($name, $value, $this->lifetime, $path, $domain, $request->tls, $html_only);
}
/**
* Prep cookie paramaters
* @param object $request request details
* @param string $name cookie name
* @param string $path cookie path
* @param string $domain cookie domain
* @return array
*/
private function prep_cookie_params($request, $name, $path, $domain) {
$html_only = true;
if ($name == 'hm_reload_folders') {
$html_only = false;
}
if ($name != 'hm_reload_folders' && !$path && isset($request->path)) {
$path = $this->cookie_path($request);
}
if (!$domain) {
$domain = $this->cookie_domain($request);
}
if (preg_match("/:\d+$/", $domain, $matches)) {
$domain = str_replace($matches[0], '', $domain);
}
return array($path, $domain, $html_only);
}
/**
* Delete a cookie
* @param object $request request details
* @param string $name cookie name
* @param string $path cookie path
* @param string $domain cookie domain
* @return boolean
*/
public function delete_cookie($request, $name, $path='', $domain='') {
list($path, $domain, $html_only) = $this->prep_cookie_params($request, $name, $path, $domain);
return Hm_Functions::setcookie($name, '', time()-3600, $path, $domain, $request->tls, $html_only);
}
}
/**
* Setup the session and authentication classes based on the site config
*/
class Hm_Session_Setup {
private $config;
private $auth_type;
private $session_type;
/**
* @param object $config site configuration
*/
public function __construct($config) {
$this->config = $config;
$this->auth_type = $config->get('auth_type', false);
$this->session_type = $config->get('session_type', false);
}
/**
* @return object
*/
public function setup_session() {
$auth_class = $this->setup_auth();
$session_class = $this->get_session_class();
if (!Hm_Functions::class_exists($auth_class)) {
Hm_Functions::cease('Invalid auth configuration');
}
Hm_Debug::add(sprintf('Using %s with %s', $session_class, $auth_class));
return new $session_class($this->config, $auth_class);
}
/**
* @return string
*/
private function get_session_class() {
$custom_session_class = $this->config->get('session_class', 'Custom_Session');
if ($this->session_type == 'DB') {
$session_class = 'Hm_DB_Session';
}
elseif ($this->session_type == 'MEM') {
$session_class = 'Hm_Memcached_Session';
}
elseif ($this->session_type == 'REDIS') {
$session_class = 'Hm_Redis_Session';
}
elseif ($this->session_type == 'custom' && class_exists($custom_session_class)) {
$session_class = $custom_session_class;
}
else {
$session_class = 'Hm_PHP_Session';
}
return $session_class;
}
/**
* @return string
*/
private function setup_auth() {
$auth_class = $this->standard_auth();
if ($auth_class === false) {
$auth_class = $this->dynamic_auth();
}
if ($auth_class === false) {
$auth_class = $this->custom_auth();
}
if ($auth_class === false) {
Hm_Functions::cease('Invalid auth configuration');
$auth_class = 'Hm_Auth_None';
}
return $auth_class;
}
/**
* @return string|false
*/
private function dynamic_auth() {
if ($this->auth_type == 'dynamic' && in_array('dynamic_login', $this->config->get_modules(), true)) {
return 'Hm_Auth_Dynamic';
}
return false;
}
/**
* @return string|false
*/
private function standard_auth() {
if ($this->auth_type && in_array($this->auth_type, array('DB', 'LDAP', 'IMAP', 'POP3'), true)) {
return sprintf('Hm_Auth_%s', $this->auth_type);
}
return false;
}
/**
* @return string|false
*/
private function custom_auth() {
$custom_auth_class = $this->config->get('auth_class', 'Custom_Auth');
if ($this->auth_type == 'custom' && Hm_Functions::class_exists($custom_auth_class)) {
return 'Custom_Auth';
}
return false;
}
}
PK
S`
lib/crypt_sodium.phpnu ٘ =5.3.2"
},
"type": "library",
"autoload": {
"psr-4": {
"CodeItNow\\": "CodeItNow/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Akhtar Khan",
"email": "er.akhtarkhan@gmail.com"
}
],
"description": "Barcode & Qr Code generator library by http://www.codeitnow.in. You can use it with Custom PHP application or any PHP Framework such as Laravel, Cakephp, Yii, Codeigneter etc.",
"homepage": "http://www.codeitnow.in",
"keywords": [
"Symfony2",
"barcode",
"cakephp",
"code",
"generator",
"laravel",
"qr",
"qrcode",
"symfony"
],
"support": {
"issues": "https://github.com/codeitnowin/barcode-generator/issues",
"source": "https://github.com/codeitnowin/barcode-generator/tree/v3.0.5"
},
"time": "2021-02-19T15:33:44+00:00"
},
{
"name": "erusev/parsedown",
"version": "1.8.0-beta-7",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown.git",
"reference": "fe7a50eceb4a3c867cc9fa9c0aa906b1067d1955"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/fe7a50eceb4a3c867cc9fa9c0aa906b1067d1955",
"reference": "fe7a50eceb4a3c867cc9fa9c0aa906b1067d1955",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35"
},
"type": "library",
"autoload": {
"psr-0": {
"Parsedown": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Emanuil Rusev",
"email": "hello@erusev.com",
"homepage": "http://erusev.com"
}
],
"description": "Parser for Markdown.",
"homepage": "http://parsedown.org",
"keywords": [
"markdown",
"parser"
],
"support": {
"issues": "https://github.com/erusev/parsedown/issues",
"source": "https://github.com/erusev/parsedown/tree/1.8.0-beta-7"
},
"time": "2019-03-17T18:47:21+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.13.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"require-dev": {
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
},
"type": "library",
"autoload": {
"psr-0": {
"HTMLPurifier": "library/"
},
"files": [
"library/HTMLPurifier.composer.php"
],
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/master"
},
"time": "2020-06-29T00:56:53+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v2.0.19",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/446fc9faa5c2a9ddf65eb7121c0af7e857295241",
"reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"type": "library",
"autoload": {
"files": [
"lib/random.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"polyfill",
"pseudorandom",
"random"
],
"support": {
"email": "info@paragonie.com",
"issues": "https://github.com/paragonie/random_compat/issues",
"source": "https://github.com/paragonie/random_compat"
},
"time": "2020-10-15T10:06:57+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"erusev/parsedown": 10
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.4",
"ext-mbstring": "*",
"ext-json": "*",
"ext-curl": "*",
"ext-openssl": "*",
"ext-session": "*"
},
"platform-dev": [],
"plugin-api-version": "2.0.0"
}
PK
SfAx
RELEASE_NOTESnu ٘ Cypht 1.3.0
-----------
It has been 3 YEARS since we last offered a stable release and the
list of changes is gigantic. The detailed commit list is in the
CHANGES file. This release is stable, but not perfect. There are
known issues documented at Github. It is however light years ahead
of the last stable release and even with known issues far more
stable and superior in just about every way.
Many thanks to everyone supporting the project in any way they can.
Special thanks to the Tiki WIki team for all the incredible help
they have provided (https://tiki.org/). This will be the first of
a more regular release schedule, at least more regular than every
3 years!
Jason Munro
jason@cypht.org
PK
S3 3 modules/nasa/setup.phpnu ٘ array(
'nasa_apod',
'ajax_nasa_connect',
'ajax_nasa_disconnect',
),
'allowed_post' => array(
'api_key' => FILTER_SANITIZE_STRING,
'nasa_disconnect' => FILTER_VALIDATE_BOOLEAN,
),
'allowed_get' => array(
'apod_date' => FILTER_SANITIZE_STRING,
),
'allowed_output' => array(
'nasa_action_status' => array(FILTER_VALIDATE_BOOLEAN, false),
),
);
PK
SV modules/nasa/site.jsnu ٘ 'use strict';
var nasa_disconnect = function(event) {
if (!hm_delete_prompt()) {
return false;
}
event.preventDefault();
Hm_Ajax.request(
[{'name': 'hm_ajax_hook', 'value': 'ajax_nasa_disconnect'},
{'name': 'nasa_disconnect', 'value': true}],
nasa_disconnect_result
);
return false;
};
var nasa_connect = function(event) {
event.preventDefault();
var key = $('.nasa_api_key').val();
if (key.length) {
Hm_Ajax.request(
[{'name': 'hm_ajax_hook', 'value': 'ajax_nasa_connect'},
{'name': 'api_key', 'value': key}],
nasa_connect_result
);
}
return false;
};
var nasa_connect_result = function(res) {
if (res.nasa_action_status) {
$('.nasa_connect_inner_1').hide();
$('.nasa_connect_inner_2').show();
Hm_Folders.reload_folders(true);
}
};
var nasa_disconnect_result = function(res) {
$('.nasa_api_key').val('');
$('.nasa_connect_inner_1').show();
$('.nasa_connect_inner_2').hide();
Hm_Folders.reload_folders(true);
};
if (hm_page_name() == 'servers') {
$('.nasa_api_connect').on("click", nasa_connect);
$('.nasa_api_disconnect').on("click", nasa_disconnect);
}
PK
Sp modules/nasa/README.mdnu ٘ ## NASA
This module set uses the NASA API to provide the APOD (Astronomy Picture Of the
Day) inside Cypht. It adds a menu entry and a page that display the image and
description, and a dialog in the Settings->Server page to configure that API.
PK
S