PK lPر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 lPC 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 lPM$^ ^ lib/framework.phpnu ٘ $v) {
if ($v == 'modules') {
return $parts[($i - 1)];
}
}
return 'unknown';
}
PK lPZx% %
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 lP> >
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'));
}
}
/**
* @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 lPwb lib/ini_set.phpnu ٘ 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 (!defined('HHVM_VERSION') && !$disabled) {
ini_set('open_basedir', $base);
}
PK lPEf
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'),
);
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_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 {
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 lPİ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 lPVe2 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 lPq! ! 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 lPa a 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 $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';
}
/**
* 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 lPX Z) Z) 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 ($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 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();
}
/**
* 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 lP'g" g" 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;
/* used to indicate failed auth */
public $auth_failed = false;
/* 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);
}
else {
$this->auth_failed = true;
}
}
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)) {
$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 lPIS$b! b! 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 lP?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 lP1=| 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 lP<): : 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 lPꁀ> > 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 lPr 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)/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 lP % 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 lPE)T9 9 lib/config.phpnu ٘ VERSION);
/* flag indicating failed decryption */
public $decrypt_failed = false;
/* if decryption fails, save the encrypted payload */
public $encrypted_str;
/**
* 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 lP`F lib/session_redis.phpnu ٘ conn = new Hm_Redis($this->site_config);
return $this->conn->is_active();
}
}
PK lPL5 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 lP`
lib/crypt_sodium.phpnu ٘ =5.3"
},
"require-dev": {
"php": ">=5.6",
"phpunit/phpunit": "^5.0",
"satooshi/php-coveralls": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Base32\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Riesen",
"email": "chris.riesen@gmail.com",
"homepage": "http://christianriesen.com",
"role": "Developer"
}
],
"description": "Base32 encoder/decoder according to RFC 4648",
"homepage": "https://github.com/ChristianRiesen/base32",
"keywords": [
"base32",
"decode",
"encode",
"rfc4648"
],
"time": "2018-11-02T09:03:50+00:00"
},
{
"name": "codeitnowin/barcode",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/codeitnowin/barcode-generator.git",
"reference": "6325a15ae904ec401b947e1a3e868de1c2cc80b0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/codeitnowin/barcode-generator/zipball/6325a15ae904ec401b947e1a3e868de1c2cc80b0",
"reference": "6325a15ae904ec401b947e1a3e868de1c2cc80b0",
"shasum": ""
},
"require": {
"ext-gd": "*",
"php": ">=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"
],
"time": "2018-10-25T18:32:10+00:00"
},
{
"name": "erusev/parsedown",
"version": "1.8.0-beta-5",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown.git",
"reference": "c26a2ee4bf8ba0270daab7da0353f2525ca6564a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/c26a2ee4bf8ba0270daab7da0353f2525ca6564a",
"reference": "c26a2ee4bf8ba0270daab7da0353f2525ca6564a",
"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"
],
"time": "2018-06-11T18:15:32+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "d85d39da4576a6934b72480be6978fb10c860021"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021",
"reference": "d85d39da4576a6934b72480be6978fb10c860021",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"require-dev": {
"simpletest/simpletest": "^1.1"
},
"type": "library",
"autoload": {
"psr-0": {
"HTMLPurifier": "library/"
},
"files": [
"library/HTMLPurifier.composer.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"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"
],
"time": "2018-02-23T01:58:20+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v2.0.18",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/0a58ef6e3146256cc3dc7cc393927bcc7d1b72db",
"reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db",
"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"
],
"time": "2019-01-03T20:59:08+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": "1.1.0"
}
PK lP
RELEASE_NOTESnu ٘ This is a placeholder for the release notes that will be updated each time we
create a relase. New development goes on in this branch, so be aware things
may break!
PK lP3 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 lPV 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 lPh| modules/nasa/README.mdnu ٘ ## NASA
This module set uses the NASA API to provide the APOD (Astronomy Picture Of the
Day) inside Cypht. It ads 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 lP