403, API Forbidden'); } 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('

403, API Forbidden

'); } 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('

Forbidden, this method can only be called from shell

'); } 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, '/'); $dir = realpath($dir.'/'.$ns); 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' => ' 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/ 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 '

Original

'; echo '
'.$o_text.'
'; } $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 '

Normalized

'; echo '
'.$text.'
'; echo '

'; } $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 '

'; echo '

words

'; echo '
';
					echo $content;
					echo '
'; echo '
Result: '; var_dump($bool); echo '
'; } 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 '

'; echo '

hasany

'; echo '
';
					echo $content;
					echo '
'; echo '
Result: '; var_dump($bool); echo '
'; } 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 '

'; echo '

contains

'; echo '
';
					echo $content;
					echo '
'; } $bool = strpos($a, $b) !== false; if ($debug) { echo '
Result: '; var_dump($bool); echo '
'; } 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 '

'; echo '

regex

'; echo '
';
					echo $content;
					echo '
'; } $bool = false; if ($o_bool) $bool = preg_match('#'.$content.'#i', $o_text) === 1; else $bool = preg_match('#'.$content.'#', $text) === 1; if ($debug) { echo '
Result: '; var_dump($bool); echo '
'; } 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 '

'; echo '

Final result

'; echo '
eval: '; var_dump($result); } eval('$result = '.$result.';'); if ($debug) { echo '
'; echo '
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';