soselo/base.php

916 lines
26 KiB
PHP

<?php
require 'config/application.php';
$session = null;
if (isset($_SERVER['REQUEST_URI'])) {
if (!isset($_COOKIE['_session']) || !file_exists('/tmp/apcontrol-sessions')) {
if (substr($_SERVER['REQUEST_URI'],0,5) === '/api/') {
http_response_code(403); die('<h3>403, API Forbidden</h3>');
}
header('Location: login.php'); die;
}
$session = trim($_COOKIE['_session']);
$ps_sess = explode('.', $session);
$sessions = explode("\n", trim(file_get_contents('/tmp/apcontrol-sessions')));
if (!in_array($session, $sessions) || !isset($GLOBALS['appconf']['users'][$ps_sess[0]])) {
if (substr($_SERVER['REQUEST_URI'],0,5) === '/api/') {
http_response_code(403); die('<h3>403, API Forbidden</h3>');
}
header('Location: login.php'); die;
}
unset($sessions);
unset($ps_sess);
}
function __session_delete($user) {
if (!file_exists('/tmp/apcontrol-sessions'))
return false;
$newsessions = [];
$sessions = explode("\n", trim(file_get_contents('/tmp/apcontrol-sessions')));
foreach ($sessions as $session) {
$ps = explode('.', $session);
if ($ps[0] !== $user)
$newsessions []= $session;
}
file_put_contents('/tmp/apcontrol-sessions', implode("\n", $newsessions));
return true;
}
if (!file_exists($GLOBALS['appconf']['data_dir']))
mkdir($GLOBALS['appconf']['data_dir']);
// global variables
$GLOBALS['_cache'] = [];
$GLOBALS['supported_ap_software'] = [
'mastodon',
];
// functions
function apiresult($data, $code=200) {
if (isset($GLOBALS['IS_PHP']) && $GLOBALS['IS_PHP']) {
$GLOBALS['api_data'] = $data;
return false;
}
if (isset($_SERVER['REQUEST_URI'])) {
if ($code !== 200) http_response_code($code);
header('Content-Type: application/json');
}
if (isset($GLOBALS['http_cache_config'])
&& gettype($data) !== 'string'
&& !isset($data['error'])
&& !isset($data['ok']))
content_cache__put($GLOBALS['http_cache_config']['key'],
'ondemand,'.$GLOBALS['http_cache_config']['seconds'], $data);
if (gettype($data) !== 'string')
echo json_encode($data);
else echo $data;
die;
}
function no_http() {
if (isset($_SERVER['REQUEST_URI']))
die('<h3>Forbidden, this method can only be called from shell</h3>');
}
function arg($arg, $default=null, $validator=null) {
$arg = trim($arg);
$type = null;
$require = false;
if (strpos($arg,'*') === 0) {
$require = true;
$arg = substr($arg, 1);
}
if (strpos($arg,'s:') === 0) {
$type = 'string';
$arg = substr($arg, 2);
} else if (strpos($arg,'i:') === 0) {
$type = 'integer';
$arg = substr($arg, 2);
} else if (strpos($arg,'d:') === 0) {
$type = 'double';
$arg = substr($arg, 2);
} else if (strpos($arg, 'b:') === 0) {
$type = 'boolean';
$arg = substr($arg, 2);
} else if (strpos($arg,'b64:') === 0) {
$type = 'base64';
$arg = substr($arg, 4);
} else if (strpos($arg,'set:') === 0) {
$type = 'exists';
$arg = substr($arg, 4);
}
$ps = explode('.', $arg);
$value = null;
$arr = null;
switch (strtolower($ps[0])) {
case 'get':
$arr = '_GET';
break;
case 'post':
$arr = '_POST';
break;
}
if ($arr === null)
$arr = $ps[0];
eval('$value = isset($'.$arr.'["'.$ps[1].'"]) ? $'.$arr.'["'.$ps[1].'"] : null;');
if ($type === 'exists')
return $value !== null;
if ($value === null)
return !$require ? $default : apiresult(['error' => '<'.$arg.'> parameter must be specified'], 400);
if (gettype($value) === 'string')
$value = trim($value);
if ($type === 'string')
$value = strval($value);
else if ($type === 'integer')
$value = intval($value);
else if ($type === 'double')
$value = doubleval($value);
else if ($type === 'boolean')
$value = in_array($value,[1,"1","yes","true"]) ? true : false;
else if ($type === 'base64')
$value = base64_decode($value);
if ($validator !== null) {
$bool = false;
eval('$bool = '.$validator.'($value);');
if (!$bool)
return apiresult(['error' => '<'.$arg.'> parameter validation has failed'], 400);
}
return $value;
}
function mod_php($module_name=null) {
$null_mod = false;
if ($module_name === null) {
$null_mod = true;
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
$fl = preg_replace('#^'.__DIR__.'#', '', $trace[0]['file']);
$fl = trim($fl, '/');
$module_name = substr($fl, 0, strrpos($fl,'/'));
}
$is_php_set = isset($GLOBALS['IS_PHP']) && $GLOBALS['IS_PHP'];
if (!$null_mod) {
$GLOBALS['IS_PHP'] = true;
unset($GLOBALS['api_data']);
}
if (!file_exists($module_name.'/mod.php'))
return 'does_not_exist';
require $module_name.'/mod.php';
if (!$null_mod) {
if (!$is_php_set)
unset($GLOBALS['IS_PHP']);
return $GLOBALS['api_data'];
}
}
function filedb_exists($ns, $file=''){ return file_exists(filedb_getdir($ns,$file)); }
function filedb_getdir($ns, $file='') {
$dir = $GLOBALS['appconf']['data_dir'];
$ns = trim($ns, '/');
$_ = realpath($dir.'/'.$ns);
if ($_ === false) {
$_ = filedb_put($ns);
if ($_ === false)
return false;
$_ = realpath($dir.'/'.$ns);
}
$dir = $_;
if (strpos($dir, $GLOBALS['appconf']['data_dir']) === false)
return false;
return $dir.'/'.$file;
}
function filedb_put($ns, $file='', $content=null) {
$dir = $GLOBALS['appconf']['data_dir'];
$ns = trim($ns, '/');
foreach (explode('/', $ns) as $d) {
$dir .= '/'.$d;
if (!file_exists($dir))
mkdir($dir);
}
$dir = realpath($dir);
if (strpos($dir, $GLOBALS['appconf']['data_dir']) === false)
return false;
if ($file === '')
return true;
$content_file = $dir.'/'.$file;
if ($content === null)
return touch($content_file);
return file_put_contents($content_file, $content);
}
function filedb_del($ns, $file='') {
$file = filedb_getdir($ns, $file);
if ($file === false || !file_exists($file))
return false;
if (is_dir($file))
return rmdir($file);
return unlink($file);
}
function filedb_delall($ns) {
if (!filedb_exists($ns))
return false;
foreach (scandir(filedb_getdir($ns)) as $fil) {
if (in_array($fil, ['.','..']))
continue;
filedb_del($ns, $fil);
}
return true;
}
function filedb_get($ns, $file) {
$file = filedb_getdir($ns, $file);
if ($file === false)
return false;
if (!file_exists($file))
return null;
return file_get_contents($file);
}
function instance_config($software=null, $instance=null) {
if ($software === null) {
foreach ($GLOBALS['supported_ap_software'] as $sf) {
$result = instance_config($sf);
if ($result !== null)
return $result;
}
return null;
}
if (!in_array($software, $GLOBALS['supported_ap_software']))
return null;
if ($instance === null && isset($_GET['instance']))
$instance = trim($_GET['instance']);
if ($instance === null)
return apiresult(['error' => '<instance> GET argument must be provided'], 400);
$GLOBALS['ap_instance'] = $instance;
$GLOBALS['ap_software'] = $software;
if (isset($GLOBALS['_cache'][$software.$instance]))
return $GLOBALS['_cache'][$software.$instance];
mod_php('api/v1/config/get');
if (!isset($GLOBALS['api_data']))
return null;
$found = false;
foreach ($GLOBALS['api_data']['hosts'][$software] as $ins_cfg) {
if ($ins_cfg['instance'] === $instance) {
$found = $ins_cfg;
}
}
if ($found === false)
return null;
$config = [];
$config_raw = explode("\n", trim($found['config']));
foreach ($config_raw as $ln) {
$k = substr($ln, 0, strpos($ln,'='));
$v = substr($ln, strpos($ln,'=')+1);
$config[$k] = $v;
}
$GLOBALS['_cache'][$software.$instance] = $config;
return $config;
}
function instance_config_require($software, $instance=null) {
$config = instance_config($software, $instance);
if ($config === null)
apiresult(['error' => 'instance parameter is incorrect. Does not exist'], 400);
return $config;
}
function instance_http_get($url) { return instance_http_request($url, 'GET'); }
function instance_http_post($url, $data=null) { return instance_http_request($url, 'POST', $data); }
function instance_http_delete($url) { return instance_http_request($url, 'DELETE'); }
function instance_http_request($url, $method, $data=null) {
$software = null;
if (isset($_SERVER['REQUEST_URI'])) {
$huri = substr(trim($_SERVER['REQUEST_URI']), 7);
$ps = explode('/', trim($huri, '/'));
if ($ps[0] !== 'http' || !in_array($ps[1], $GLOBALS['supported_ap_software']))
return apiresult(['error' => 'this method can only be called from api/v1/http/<software> URIs'], 500);
$software = $ps[1];
}
if ($software === null && isset($GLOBALS['ap_software']))
$software = $GLOBALS['ap_software'];
$config = instance_config($software);
$url = $config['instance_url'].$url;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if ($method === 'POST' || $method === 'DELETE') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if ($data !== null)
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if (isset($config['api_authkey'])) {
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer '.$config['api_authkey'],
]);
}
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
function valid_mastodon_account_id($id) {
return preg_match('/^\d+$/', strval($id));
}
function valid_for_path($str) {
return strpos($str, '/') === false;
}
function valid_uuid($str) {
return preg_match('/^[a-z0-9\-]+$/', trim($str));
}
// source: https://stackoverflow.com/questions/1755144/how-to-validate-domain-name-in-php
function valid_domain_name($domain_name)
{
return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
&& preg_match("/^.{1,253}$/", $domain_name)
&& preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));
}
function remove_accents($string) {
if ( !preg_match('/[\x80-\xff]/', $string) )
return $string;
$chars = array(
// Decompositions for Latin-1 Supplement
chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
chr(195).chr(191) => 'y',
// Decompositions for Latin Extended-A
chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
chr(197).chr(190) => 'z', chr(197).chr(191) => 's'
);
$string = strtr($string, $chars);
return $string;
}
if (!function_exists('str_starts_with')) {
function str_starts_with($haystack, $needle) {
return (string)$needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0;
}
}
function set_chat_at($str, $i, $c) {
return substr($str, 0, $i).$c.substr($str, $i+1);
}
function normalize_word_sound($word, $cback=null) {
$hashes = [
'4:a', '3:e', '1:i', '0:o',
'5:s', 'b:v', '8:b', 'k:c',
'y:i', 'que:kee', 'q:k',
];
foreach ($hashes as $hash) {
$hash = explode(':', $hash);
if ($cback !== null)
$word = $cback($word, $hash);
else $word = str_replace($hash[0], $hash[1], $word);
}
return $word;
}
function normalize_for_search($str, $wsound=true) {
if (trim($str) === '') return '';
$str = trim(strip_tags(str_replace('>', '> ', $str)));
$str = strtolower(remove_accents($str));
$str = preg_replace('/[^a-z0-9]+/', ' ', $str);
$str = preg_replace('/\s+/', ' ', $str);
$words = explode(' ', trim($str));
$newwords = [];
foreach ($words as $word) {
if (trim($word) === '')
continue;
if ($wsound)
$word = normalize_word_sound($word);
$nword = '';
if (strlen($word) <= 3) {
$newwords [] = $word;
continue;
}
for ($i = 0; $i < strlen($word); $i++) {
if ($i === 0) {
$nword .= $word[0];
continue;
}
if ($word[$i] !== $word[$i-1]) {
$nword .= $word[$i];
}
}
$newwords [] = $nword;
}
return trim(implode(' ', $newwords));
}
function parse_comparing_expression($expr) {
$expr = preg_replace('/\n/', ' ', $expr);
$expr = preg_replace('/\s+/', ' ', $expr);
$p_expr = $expr;
$quot = false;
for ($i = 0; $i < strlen($p_expr); $i++) {
if ($p_expr[$i] === '"') {
$quot = !$quot;
continue;
}
if ($quot) {
if ($p_expr[$i] === '(')
$p_expr = set_chat_at($p_expr, $i, 'º');
else if ($p_expr[$i] === ')')
$p_expr = set_chat_at($p_expr, $i, 'ª');
}
}
$p_expr = preg_replace('/\(|\)/', ' ', $p_expr);
$p_expr = preg_replace('/\s+/', ' ', $p_expr);
$p_expr = preg_split('/OR|AND(\sNOT)?/', $p_expr);
$p_expr = str_replace('º', '(', $p_expr);
$p_expr = str_replace('ª', ')', $p_expr);
foreach ($p_expr as &$e) $e = trim($e);
return [
'original' => $expr,
'parsed' => $p_expr,
];
}
function matches_comparing_expression($expr, $o_text, $debug=false) {
if (gettype($expr) === 'string')
$expr = parse_comparing_expression($expr);
$result = $expr['original'];
if ($debug) {
echo '<h2>Original</h2>';
echo '<pre>'.$o_text.'</pre>';
}
$text = normalize_for_search($o_text);
$i_text = null;
if (strpos($expr['original'], '=') !== false)
$i_text = normalize_for_search($o_text, false);
if ($debug) {
echo '<h2>Normalized</h2>';
echo '<pre>'.$text.'</pre>';
echo '<br><br>';
}
$m_text_words = explode(' ', $text);
$i_text_words = null;
if ($i_text !== null)
$i_text_words = explode(' ', $i_text);
$o_text_words = null;
if (preg_match('/(^|\s)\*\w+/', $expr['original']))
{
$nw_text_words = [];
$o_text_words = explode(' ', $o_text);
foreach ($o_text_words as $o)
if ($o !== '')
$nw_text_words []= $o;
$o_text_words = $nw_text_words;
}
foreach ($expr['parsed'] as $t)
{
$bool = false;
$t = trim($t);
$selector = substr($t, 0, strpos($t, ' '));
$content = substr($t, strpos($t, ' ')+1);
$content = trim(trim(trim($content), '"'));
$o_bool = ($selector[0] === '*' && $o_text_words !== null);
$i_bool = ($selector[0] === '=' && $i_text_words !== null);
if ($o_bool || $i_bool)
$selector = substr($selector, 1);
switch ($selector)
{
case 'words':
case 'hasall':
$ws = explode(' ', $content);
$hasall = true;
foreach ($ws as $w)
{
if ($o_bool) {
if (!in_array($w, $o_text_words)) {
$hasall = false;
break;
}
continue;
}
if ($i_bool) {
if (!in_array(normalize_for_search($w, false), $i_text_words)) {
$hasall = false;
break;
}
continue;
}
if (!in_array(normalize_for_search($w), $m_text_words)) {
$hasall = false;
break;
}
}
$bool = $hasall;
if ($debug) {
echo '<br><br>';
echo '<h3>words</h3>';
echo '<pre>';
echo $content;
echo '</pre>';
echo '<br>Result: ';
var_dump($bool);
echo '<br>';
}
break;
case 'anyword':
case 'hasany':
$ws = explode(' ', $content);
$hasany = false;
foreach ($ws as $w)
{
if ($o_bool) {
if (in_array($w, $o_text_words)) {
$hasany = true;
break;
}
continue;
}
if ($i_bool) {
if (in_array(normalize_for_search($w, false), $i_text_words)) {
$hasany = true;
break;
}
continue;
}
if (in_array(normalize_for_search($w), $m_text_words)) {
$hasany = true;
break;
}
}
$bool = $hasany;
if ($debug) {
echo '<br><br>';
echo '<h3>hasany</h3>';
echo '<pre>';
echo $content;
echo '</pre>';
echo '<br>Result: ';
var_dump($bool);
echo '<br>';
}
break;
case 'has':
case 'includes':
case 'contains':
$a = null; $b = null;
if ($o_bool) {
$a = str_replace(' ', '', $o_text);
$b = str_replace(' ', '', $content);
} else if ($i_bool) {
$a = str_replace(' ', '', $i_text);
$b = str_replace(' ', '', normalize_for_search($content, false));
} else {
$a = str_replace(' ', '', $text);
$b = str_replace(' ', '', normalize_for_search($content));
}
if ($debug) {
echo '<br><br>';
echo '<h3>contains</h3>';
echo '<pre>';
echo $content;
echo '</pre>';
}
$bool = strpos($a, $b) !== false;
if ($debug) {
echo '<br>Result: ';
var_dump($bool);
echo '<br>';
}
unset($a); unset($b);
break;
case 'regex':
case 'matches':
if (strlen($content) === 0)
continue 2;
if (!$o_bool)
{
$content = normalize_word_sound($content, function($w, $h) {
if ($h[0] === 'b')
return preg_replace('/([^\\\])b/', '\1'.$h[1], $w);
if (preg_match('/^\d$/', $h[0])) {
$b = false;
for ($i = 0; $i < strlen($w); $i++) {
if (in_array($w[$i], ['{','}','[',']'])) {
$b = !$b;
continue;
}
if (!$b && $w[$i] === $h[0])
$w = set_chat_at($w, $i, $h[1]);
}
return $w;
}
return str_replace($h[0], $h[1], $w);
});
preg_match_all('/\w{4,}/', $content, $mts);
foreach ((isset($mts[0]) ? $mts[0] : []) as $m)
$content = preg_replace('/\b'.$m.'\b/', normalize_for_search($m, !$i_bool), $content);
}
if ($content[0] != '^')
$content = '^.*'.$content;
if ($content[strlen($content)-1] != '$')
$content .= '.*$';
$content = str_replace('#', '\#', $content);
if ($debug) {
echo '<br><br>';
echo '<h3>regex</h3>';
echo '<pre>';
echo $content;
echo '</pre>';
}
$bool = false;
if ($o_bool)
$bool = preg_match('#'.$content.'#i', $o_text) === 1;
else $bool = preg_match('#'.$content.'#', $text) === 1;
if ($debug) {
echo '<br>Result: ';
var_dump($bool);
echo '<br>';
}
break;
case 'len':
case 'length':
case 'size':
$bool = false;
if (preg_match('/^(\<|\>)\=?\s*\d+$/', $content))
eval('$bool = strlen($o_text) '.$content.';');
break;
}
$result = str_replace($t, $bool ? 'true' : 'false', $result);
}
$result = str_replace('OR', '||', $result);
$result = str_replace('AND', '&&', $result);
$result = str_replace('NOT ', '!', $result);
$result = str_replace('NOT', '!', $result);
try {
if ($debug) {
echo '<br><hr>';
echo '<h3>Final result</h3>';
echo '<br>eval: ';
var_dump($result);
}
eval('$result = '.$result.';');
if ($debug) {
echo '<br>';
echo '<br>result: ';
var_dump($result);
die;
}
} catch (\Throwable $e) {
return apiresult(['error' => 'Query contains errors, please correct it and try again.']);
}
return in_array($result, [0,false]) ? false : true;
}
function http_cache($seconds, $data=null) {
if ($data === null)
$data = $_GET;
$cache_key = sha1('http_cache'.json_encode($data));
$cache = content_cache__get($cache_key);
if ($cache !== null)
return apiresult($cache);
$GLOBALS['http_cache_config'] = [
'seconds' => $seconds,
'key' => $cache_key
];
}
function _cachekey_construct(...$keys) {
$nkeys = [];
foreach ($keys as $key)
$nkeys []= _cachekey($key);
return implode(',', $nkeys);
}
function _cachekey($str) {
return preg_replace('/[^a-z0-9\_]+/', '', strtolower($str));
}
function content_cache__exists($key) {
$cache_dir = $GLOBALS['appconf']['data_dir'].'/cache';
if (!file_exists($cache_dir)) {
mkdir($cache_dir);
return false;
}
$key = md5($key);
$cache_file = null;
foreach (scandir($cache_dir) as $fil) {
if (strpos($fil, $key) !== false) {
$cache_file = $cache_dir.'/'.$fil;
$ps = explode(',',$fil);
array_splice($ps, 0, 1);
if ($ps[0] !== 'always' && count($ps) > 1)
$ps[1] = intval($ps[1]);
return (object)[
'file' => $cache_file,
'config' => $ps
];
}
}
return false;
}
function content_cache__get($key) {
$cfg = content_cache__exists($key);
if ($cfg === false)
return null;
$ms = time() - filemtime($cfg->file);
if ($cfg->config[0] === 'ondemand' &&
$ms > $cfg->config[1]) {
unlink($cfg->file);
return null;
}
$fname = basename($cfg->file);
$ps = explode(',', $fname);
if (count($ps) === 2 && $ps[1] === 'always') {
$dir = filedb_getdir('cron/db');
foreach (scandir($dir) as $fl) {
if (in_array($fl,['.','..']))
continue;
if (strpos($fl, ','.$ps[0].',') !== false) {
$data = @unserialize(filedb_get('cron/db',$fl));
if ($data === false) break;
$data['last_accessed'] = time();
file_put_contents($dir.'/'.$fl, serialize($data));
break;
}
}
}
return unserialize(file_get_contents($cfg->file));
}
function content_cache__put($key, $config, $data) {
$cache_dir = $GLOBALS['appconf']['data_dir'].'/cache';
if (!file_exists($cache_dir))
mkdir($cache_dir);
$ps = explode(',', trim($config));
$cache_file = $cache_dir.'/'.md5($key);
if ($ps[0] === 'always')
$cache_file .= ','.$ps[0];
else if ($ps[0] === 'ondemand')
$cache_file .= ','.$config;
return file_put_contents($cache_file, serialize($data));
}
function cronjob_db_create__check_cachecfg($software, $instance, $sql, $cache=null) {
if ($cache === null)
return false;
$ps = explode(',',trim($cache));
if ($ps[0] !== 'always')
return false;
return cronjob_db_create($software, $instance, $sql, intval($ps[1]));
}
function cronjob_db_create($software, $instance, $sql, $time=3600) {
$job_key = md5($software.$instance.$sql);
$dir_crons = $GLOBALS['appconf']['data_dir'].'/cron';
if (!file_exists($dir_crons))
mkdir($dir_crons);
$dir_crons_db = $dir_crons.'/db';
if (!file_exists($dir_crons_db))
mkdir($dir_crons_db);
$cron_file = $software.','.$instance.','.$job_key;
$result_file = $dir_crons_db.'/'.$cron_file.','.$time;
if (!file_exists($result_file)) {
file_put_contents($result_file, serialize(
['last_accessed' => time(), 'sql' => $sql]));
touch($result_file, 1000);
}
$result_fname = basename($result_file);
foreach (scandir($dir_crons_db) as $fl) {
if (in_array($fl,['.','..']))
continue;
if (strpos($fl, $cron_file) !== false && $fl !== $result_fname)
unlink($dir_crons_db.'/'.$fl);
}
return $cron_file;
}
// classes
require 'classes/PgDatabase.php';
require 'classes/RedisDatabase.php';