2006-08-19 07:04:45 +00:00
|
|
|
<?php
|
2013-03-27 05:40:07 +00:00
|
|
|
define('LABEL_BASE_INDEX', -1024);
|
2013-03-27 12:14:27 +00:00
|
|
|
define('PLUGIN_FEED_BASE_INDEX', -128);
|
2013-03-27 05:40:07 +00:00
|
|
|
|
2022-02-20 08:04:15 +00:00
|
|
|
/** @deprecated by Config::SCHEMA_VERSION */
|
2021-03-04 06:22:24 +00:00
|
|
|
define('SCHEMA_VERSION', Config::SCHEMA_VERSION);
|
2021-03-02 12:03:01 +00:00
|
|
|
|
2020-12-12 15:53:08 +00:00
|
|
|
if (version_compare(PHP_VERSION, '8.0.0', '<')) {
|
|
|
|
libxml_disable_entity_loader(true);
|
|
|
|
}
|
|
|
|
|
2019-06-20 05:40:02 +00:00
|
|
|
libxml_use_internal_errors(true);
|
2014-12-08 11:49:54 +00:00
|
|
|
|
2016-07-07 07:02:55 +00:00
|
|
|
// separate test because this is included before sanity checks
|
|
|
|
if (function_exists("mb_internal_encoding")) mb_internal_encoding("UTF-8");
|
|
|
|
|
2010-11-07 15:14:48 +00:00
|
|
|
date_default_timezone_set('UTC');
|
2010-11-10 20:59:23 +00:00
|
|
|
if (defined('E_DEPRECATED')) {
|
|
|
|
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
|
|
|
|
} else {
|
|
|
|
error_reporting(E_ALL & ~E_NOTICE);
|
|
|
|
}
|
2005-11-23 18:08:01 +00:00
|
|
|
|
2021-02-22 11:41:09 +00:00
|
|
|
ini_set('display_errors', "false");
|
|
|
|
ini_set('display_startup_errors', "false");
|
2019-12-19 05:37:19 +00:00
|
|
|
|
2021-02-22 19:51:12 +00:00
|
|
|
// config.php is optional
|
|
|
|
if (stream_resolve_include_path("config.php"))
|
|
|
|
require_once "config.php";
|
|
|
|
|
2021-02-22 18:47:48 +00:00
|
|
|
require_once "autoload.php";
|
|
|
|
|
|
|
|
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
2008-04-21 04:53:19 +00:00
|
|
|
define('SUBSTRING_FOR_DATE', 'SUBSTRING_FOR_DATE');
|
|
|
|
} else {
|
|
|
|
define('SUBSTRING_FOR_DATE', 'SUBSTRING');
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @return bool|int|null|string
|
|
|
|
*/
|
2021-02-25 09:46:13 +00:00
|
|
|
function get_pref(string $pref_name, int $owner_uid = null) {
|
2021-02-25 09:53:20 +00:00
|
|
|
return Prefs::get($pref_name, $owner_uid ? $owner_uid : $_SESSION["uid"], $_SESSION["profile"] ?? null);
|
2021-02-22 20:25:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @param bool|int|string $value
|
|
|
|
*/
|
|
|
|
function set_pref(string $pref_name, $value, int $owner_uid = null, bool $strip_tags = true): bool {
|
2021-02-25 09:46:13 +00:00
|
|
|
return Prefs::set($pref_name, $value, $owner_uid ? $owner_uid : $_SESSION["uid"], $_SESSION["profile"] ?? null, $strip_tags);
|
2021-02-22 20:25:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @return array<string, string>
|
|
|
|
*/
|
|
|
|
function get_translations(): array {
|
2021-02-12 18:20:04 +00:00
|
|
|
$t = array(
|
2019-01-30 14:57:28 +00:00
|
|
|
"auto" => __("Detect automatically"),
|
2014-08-14 08:09:16 +00:00
|
|
|
"ar_SA" => "العربيّة (Arabic)",
|
2022-04-18 10:04:29 +00:00
|
|
|
"be" => "Беларуская",
|
2015-03-11 12:36:45 +00:00
|
|
|
"bg_BG" => "Bulgarian",
|
2014-06-03 04:56:40 +00:00
|
|
|
"da_DA" => "Dansk",
|
2009-11-22 20:18:54 +00:00
|
|
|
"ca_CA" => "Català",
|
2013-03-19 13:39:08 +00:00
|
|
|
"cs_CZ" => "Česky",
|
2007-08-11 15:40:27 +00:00
|
|
|
"en_US" => "English",
|
2014-06-03 04:56:40 +00:00
|
|
|
"el_GR" => "Ελληνικά",
|
2014-06-03 04:56:49 +00:00
|
|
|
"es_ES" => "Español (España)",
|
2014-06-03 04:56:40 +00:00
|
|
|
"es_LA" => "Español",
|
2009-04-26 12:42:33 +00:00
|
|
|
"de_DE" => "Deutsch",
|
2020-10-01 07:19:04 +00:00
|
|
|
"fa" => "Persian (Farsi)",
|
2007-08-11 15:40:27 +00:00
|
|
|
"fr_FR" => "Français",
|
2022-08-22 16:10:06 +00:00
|
|
|
"gl" => "Galego",
|
2008-02-26 07:57:09 +00:00
|
|
|
"hu_HU" => "Magyar (Hungarian)",
|
2008-11-02 16:42:39 +00:00
|
|
|
"it_IT" => "Italiano",
|
2008-09-25 03:56:59 +00:00
|
|
|
"ja_JP" => "日本語 (Japanese)",
|
2013-03-18 21:13:30 +00:00
|
|
|
"lv_LV" => "Latviešu",
|
2008-04-08 05:13:57 +00:00
|
|
|
"nb_NO" => "Norwegian bokmål",
|
2013-03-23 05:21:57 +00:00
|
|
|
"nl_NL" => "Dutch",
|
2012-10-06 14:27:53 +00:00
|
|
|
"pl_PL" => "Polski",
|
2013-04-01 15:10:26 +00:00
|
|
|
"ru_RU" => "Русский",
|
2007-10-26 07:19:54 +00:00
|
|
|
"pt_BR" => "Portuguese/Brazil",
|
2014-03-21 11:56:26 +00:00
|
|
|
"pt_PT" => "Portuguese/Portugal",
|
2013-04-01 11:51:04 +00:00
|
|
|
"zh_CN" => "Simplified Chinese",
|
2014-02-12 12:30:24 +00:00
|
|
|
"zh_TW" => "Traditional Chinese",
|
2019-01-30 14:14:07 +00:00
|
|
|
"uk_UA" => "Українська",
|
2013-04-01 17:35:00 +00:00
|
|
|
"sv_SE" => "Svenska",
|
2013-12-24 09:27:57 +00:00
|
|
|
"fi_FI" => "Suomi",
|
2013-12-08 18:47:29 +00:00
|
|
|
"tr_TR" => "Türkçe");
|
2007-08-11 14:25:51 +00:00
|
|
|
|
2021-02-12 18:20:04 +00:00
|
|
|
return $t;
|
2007-08-11 14:25:51 +00:00
|
|
|
}
|
|
|
|
|
2020-09-17 15:56:29 +00:00
|
|
|
require_once "lib/gettext/gettext.inc.php";
|
2007-03-06 10:33:06 +00:00
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function startup_gettext(): void {
|
2011-03-17 16:05:28 +00:00
|
|
|
|
2021-02-12 18:20:04 +00:00
|
|
|
$selected_locale = "";
|
|
|
|
|
|
|
|
// https://www.codingwithjesse.com/blog/use-accept-language-header/
|
|
|
|
if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
|
|
|
$valid_langs = [];
|
|
|
|
$translations = array_keys(get_translations());
|
|
|
|
|
|
|
|
array_shift($translations); // remove "auto"
|
2007-08-10 16:16:43 +00:00
|
|
|
|
2021-02-12 18:20:04 +00:00
|
|
|
// full locale first
|
|
|
|
foreach ($translations as $t) {
|
|
|
|
$lang = strtolower(str_replace("_", "-", (string)$t));
|
|
|
|
$valid_langs[$lang] = $t;
|
|
|
|
|
|
|
|
$lang = substr($lang, 0, 2);
|
2022-08-12 18:21:38 +00:00
|
|
|
$valid_langs[$lang] ??= $t;
|
2021-02-12 18:20:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// break up string into pieces (languages and q factors)
|
|
|
|
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',
|
|
|
|
$_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
|
|
|
|
|
|
|
|
if (count($lang_parse[1])) {
|
|
|
|
// create a list like "en" => 0.8
|
|
|
|
$langs = array_combine($lang_parse[1], $lang_parse[4]);
|
|
|
|
|
|
|
|
if (is_array($langs)) {
|
|
|
|
// set default to 1 for any without q factor
|
|
|
|
foreach ($langs as $lang => $val) {
|
|
|
|
if ($val === '') $langs[$lang] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort list based on value
|
|
|
|
arsort($langs, SORT_NUMERIC);
|
|
|
|
|
|
|
|
foreach (array_keys($langs) as $lang) {
|
|
|
|
$lang = strtolower($lang);
|
|
|
|
|
|
|
|
foreach ($valid_langs as $vlang => $vlocale) {
|
|
|
|
if ($vlang == $lang) {
|
|
|
|
$selected_locale = $vlocale;
|
|
|
|
break 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-03-18 16:25:06 +00:00
|
|
|
}
|
2007-08-10 16:16:43 +00:00
|
|
|
|
2021-02-05 21:12:15 +00:00
|
|
|
if (!empty($_SESSION["uid"]) && get_schema_version() >= 120) {
|
2021-02-25 11:49:58 +00:00
|
|
|
$pref_locale = get_pref(Prefs::USER_LANGUAGE, $_SESSION["uid"]);
|
2013-04-27 13:12:48 +00:00
|
|
|
|
2021-02-12 18:20:04 +00:00
|
|
|
if (!empty($pref_locale) && $pref_locale != 'auto') {
|
|
|
|
$selected_locale = $pref_locale;
|
2013-04-29 11:54:23 +00:00
|
|
|
}
|
2011-03-18 16:25:06 +00:00
|
|
|
}
|
2008-12-16 07:13:09 +00:00
|
|
|
|
2021-02-12 18:20:04 +00:00
|
|
|
if ($selected_locale) {
|
2011-03-18 16:25:06 +00:00
|
|
|
if (defined('LC_MESSAGES')) {
|
2021-02-12 18:20:04 +00:00
|
|
|
_setlocale(LC_MESSAGES, $selected_locale);
|
2011-03-18 16:25:06 +00:00
|
|
|
} else if (defined('LC_ALL')) {
|
2021-02-12 18:20:04 +00:00
|
|
|
_setlocale(LC_ALL, $selected_locale);
|
2007-05-19 04:46:29 +00:00
|
|
|
}
|
2007-03-06 10:33:06 +00:00
|
|
|
|
2013-03-21 19:47:44 +00:00
|
|
|
_bindtextdomain("messages", "locale");
|
2011-03-18 16:25:06 +00:00
|
|
|
_textdomain("messages");
|
|
|
|
_bind_textdomain_codeset("messages", "UTF-8");
|
2007-05-19 05:13:35 +00:00
|
|
|
}
|
2011-03-18 16:25:06 +00:00
|
|
|
}
|
|
|
|
|
2017-05-04 11:22:23 +00:00
|
|
|
require_once 'controls.php';
|
2021-02-16 11:23:00 +00:00
|
|
|
require_once 'controls_compat.php';
|
2005-08-21 15:35:22 +00:00
|
|
|
|
2021-08-23 07:56:31 +00:00
|
|
|
ini_set('user_agent', Config::get_user_agent());
|
2010-11-17 09:52:17 +00:00
|
|
|
|
2020-09-22 06:04:33 +00:00
|
|
|
/* compat shims */
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @deprecated by Config::get_version()
|
|
|
|
*
|
|
|
|
* @return array<string, mixed>|string
|
|
|
|
*/
|
2021-03-01 10:43:37 +00:00
|
|
|
function get_version() {
|
|
|
|
return Config::get_version();
|
|
|
|
}
|
|
|
|
|
2022-02-20 08:04:15 +00:00
|
|
|
/** @deprecated by Config::get_schema_version() */
|
2021-11-11 21:37:34 +00:00
|
|
|
function get_schema_version(): int {
|
2021-03-01 07:20:21 +00:00
|
|
|
return Config::get_schema_version();
|
|
|
|
}
|
|
|
|
|
2022-02-20 08:04:15 +00:00
|
|
|
/** @deprecated by Debug::log() */
|
2021-11-11 21:37:34 +00:00
|
|
|
function _debug(string $msg): void {
|
|
|
|
Debug::log($msg);
|
2013-09-15 18:57:50 +00:00
|
|
|
}
|
|
|
|
|
2022-02-20 08:04:15 +00:00
|
|
|
|
|
|
|
/** @deprecated by Feeds::_get_counters()
|
|
|
|
* @param int|string $feed feed id or tag name
|
|
|
|
* @param bool $is_cat
|
|
|
|
* @return int
|
|
|
|
* @throws PDOException
|
|
|
|
*/
|
|
|
|
function getFeedUnread($feed, bool $is_cat = false): int {
|
2021-02-15 12:43:07 +00:00
|
|
|
return Feeds::_get_counters($feed, $is_cat, true, $_SESSION["uid"]);
|
2020-09-23 10:04:26 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 19:59:25 +00:00
|
|
|
/**
|
|
|
|
* @deprecated by Sanitizer::sanitize()
|
|
|
|
*
|
|
|
|
* @param array<int, string>|null $highlight_words Words to highlight in the HTML output.
|
|
|
|
*
|
|
|
|
* @return false|string The HTML, or false if an error occurred.
|
|
|
|
*/
|
|
|
|
function sanitize(string $str, bool $force_remove_images = false, int $owner = null, string $site_url = null, array $highlight_words = null, int $article_id = null) {
|
2020-09-22 06:04:33 +00:00
|
|
|
return Sanitizer::sanitize($str, $force_remove_images, $owner, $site_url, $highlight_words, $article_id);
|
2019-11-17 10:17:21 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @deprecated by UrlHelper::fetch()
|
|
|
|
*
|
|
|
|
* @param array<string, bool|int|string>|string $params
|
|
|
|
* @return bool|string false if something went wrong, otherwise string contents
|
|
|
|
*/
|
2020-09-22 06:04:33 +00:00
|
|
|
function fetch_file_contents($params) {
|
|
|
|
return UrlHelper::fetch($params);
|
2006-08-28 03:49:08 +00:00
|
|
|
}
|
2005-08-25 06:46:24 +00:00
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @deprecated by UrlHelper::rewrite_relative()
|
|
|
|
*
|
|
|
|
* Converts a (possibly) relative URL to a absolute one, using provided base URL.
|
|
|
|
* Provides some exceptions for additional schemes like data: if called with owning element/attribute.
|
|
|
|
*
|
|
|
|
* @param string $base_url Base URL (i.e. from where the document is)
|
|
|
|
* @param string $rel_url Possibly relative URL in the document
|
|
|
|
*
|
|
|
|
* @return string Absolute URL
|
|
|
|
*/
|
2021-05-21 12:39:41 +00:00
|
|
|
function rewrite_relative_url($base_url, $rel_url) {
|
|
|
|
return UrlHelper::rewrite_relative($base_url, $rel_url);
|
2020-09-22 06:04:33 +00:00
|
|
|
}
|
2005-11-18 05:17:17 +00:00
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @deprecated by UrlHelper::validate()
|
|
|
|
*
|
|
|
|
* @return bool|string false if something went wrong, otherwise the URL string
|
|
|
|
*/
|
|
|
|
function validate_url(string $url) {
|
2020-09-22 06:04:33 +00:00
|
|
|
return UrlHelper::validate($url);
|
|
|
|
}
|
2005-11-18 05:17:17 +00:00
|
|
|
|
2022-02-20 08:04:15 +00:00
|
|
|
/** @deprecated by UserHelper::authenticate() */
|
2021-11-11 21:37:34 +00:00
|
|
|
function authenticate_user(string $login = null, string $password = null, bool $check_only = false, string $service = null): bool {
|
2020-09-22 06:04:33 +00:00
|
|
|
return UserHelper::authenticate($login, $password, $check_only, $service);
|
2005-11-18 05:17:17 +00:00
|
|
|
}
|
2006-05-16 07:33:51 +00:00
|
|
|
|
2022-02-20 08:04:15 +00:00
|
|
|
/** @deprecated by TimeHelper::smart_date_time() */
|
2021-11-11 20:12:47 +00:00
|
|
|
function smart_date_time(int $timestamp, int $tz_offset = 0, int $owner_uid = null, bool $eta_min = false): string {
|
2020-09-23 10:04:26 +00:00
|
|
|
return TimeHelper::smart_date_time($timestamp, $tz_offset, $owner_uid, $eta_min);
|
|
|
|
}
|
|
|
|
|
2022-02-20 08:04:15 +00:00
|
|
|
/** @deprecated by TimeHelper::make_local_datetime() */
|
2021-11-11 20:12:47 +00:00
|
|
|
function make_local_datetime(string $timestamp, bool $long, int $owner_uid = null, bool $no_smart_dt = false, bool $eta_min = false): string {
|
2020-09-23 10:04:26 +00:00
|
|
|
return TimeHelper::make_local_datetime($timestamp, $long, $owner_uid, $no_smart_dt, $eta_min);
|
|
|
|
}
|
|
|
|
|
2021-03-01 07:20:21 +00:00
|
|
|
// this returns Config::SELF_URL_PATH sans ending slash
|
2022-02-20 08:04:15 +00:00
|
|
|
/** @deprecated by Config::get_self_url() */
|
2021-11-11 21:37:34 +00:00
|
|
|
function get_self_url_prefix(): string {
|
2021-03-01 07:20:21 +00:00
|
|
|
return Config::get_self_url();
|
2011-03-28 05:45:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-01 07:20:21 +00:00
|
|
|
/* end compat shims */
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* This is used for user http parameters unless HTML code is actually needed.
|
|
|
|
*
|
|
|
|
* @param mixed $param
|
|
|
|
*
|
2021-11-23 14:01:08 +00:00
|
|
|
* @return mixed|null
|
2021-11-11 21:37:34 +00:00
|
|
|
*/
|
2017-12-03 20:35:38 +00:00
|
|
|
function clean($param) {
|
|
|
|
if (is_array($param)) {
|
2021-02-05 21:17:41 +00:00
|
|
|
return array_map("trim", array_map("strip_tags", $param));
|
2017-12-03 20:35:38 +00:00
|
|
|
} else if (is_string($param)) {
|
2021-02-05 20:41:32 +00:00
|
|
|
return trim(strip_tags($param));
|
2017-12-03 20:35:38 +00:00
|
|
|
} else {
|
2021-02-22 11:41:09 +00:00
|
|
|
return $param;
|
2017-12-03 20:35:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-04 10:40:54 +00:00
|
|
|
function with_trailing_slash(string $str) : string {
|
|
|
|
if (substr($str, -1) === "/") {
|
|
|
|
return $str;
|
|
|
|
} else {
|
|
|
|
return "$str/";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function make_password(int $length = 12): string {
|
2012-01-25 06:47:32 +00:00
|
|
|
$password = "";
|
2019-03-05 17:18:50 +00:00
|
|
|
$possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ*%+^";
|
2012-01-25 06:47:32 +00:00
|
|
|
|
2019-03-05 17:18:50 +00:00
|
|
|
$i = 0;
|
2012-01-25 06:47:32 +00:00
|
|
|
|
|
|
|
while ($i < $length) {
|
2019-03-05 17:18:50 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
$idx = function_exists("random_int") ? random_int(0, strlen($possible) - 1) : mt_rand(0, strlen($possible) - 1);
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$idx = mt_rand(0, strlen($possible) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
$char = substr($possible, $idx, 1);
|
2012-01-25 06:47:32 +00:00
|
|
|
|
|
|
|
if (!strstr($password, $char)) {
|
|
|
|
$password .= $char;
|
|
|
|
$i++;
|
|
|
|
}
|
|
|
|
}
|
2019-03-05 17:18:50 +00:00
|
|
|
|
2012-01-25 06:47:32 +00:00
|
|
|
return $password;
|
2005-11-18 09:00:18 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function validate_csrf(?string $csrf_token): bool {
|
2021-02-12 18:21:23 +00:00
|
|
|
return isset($csrf_token) && hash_equals($_SESSION['csrf_token'] ?? "", $csrf_token);
|
2011-12-26 08:02:52 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function truncate_string(string $str, int $max_len, string $suffix = '…'): string {
|
2014-02-02 19:17:13 +00:00
|
|
|
if (mb_strlen($str, "utf-8") > $max_len) {
|
2010-11-25 09:05:48 +00:00
|
|
|
return mb_substr($str, 0, $max_len, "utf-8") . $suffix;
|
2005-11-24 07:25:09 +00:00
|
|
|
} else {
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
}
|
2005-11-26 06:40:47 +00:00
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function mb_substr_replace(string $original, string $replacement, int $position, int $length): string {
|
2018-12-24 09:44:10 +00:00
|
|
|
$startString = mb_substr($original, 0, $position, "UTF-8");
|
|
|
|
$endString = mb_substr($original, $position + $length, mb_strlen($original), "UTF-8");
|
|
|
|
|
|
|
|
$out = $startString . $replacement . $endString;
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function truncate_middle(string $str, int $max_len, string $suffix = '…'): string {
|
2018-12-24 09:44:10 +00:00
|
|
|
if (mb_strlen($str) > $max_len) {
|
|
|
|
return mb_substr_replace($str, $suffix, $max_len / 2, mb_strlen($str) - $max_len);
|
2016-02-17 13:42:13 +00:00
|
|
|
} else {
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-20 13:11:44 +00:00
|
|
|
/** Convert values accepted by tt-rss as true/false to PHP booleans
|
|
|
|
* @see https://tt-rss.org/wiki/ApiReference#boolean-values
|
|
|
|
* @param null|string $s null values are considered false
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
function sql_bool_to_bool(?string $s): bool {
|
2017-12-02 19:39:34 +00:00
|
|
|
return $s && ($s !== "f" && $s !== "false"); //no-op for PDO, backwards compat for legacy layer
|
2005-12-30 04:11:48 +00:00
|
|
|
}
|
2011-03-17 16:05:28 +00:00
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function bool_to_sql_bool(bool $s): int {
|
2017-12-05 21:12:28 +00:00
|
|
|
return $s ? 1 : 0;
|
2009-02-07 10:40:43 +00:00
|
|
|
}
|
2005-12-30 04:11:48 +00:00
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function file_is_locked(string $filename): bool {
|
2021-02-22 18:47:48 +00:00
|
|
|
if (file_exists(Config::get(Config::LOCK_DIRECTORY) . "/$filename")) {
|
2013-05-29 03:46:14 +00:00
|
|
|
if (function_exists('flock')) {
|
2021-02-22 18:47:48 +00:00
|
|
|
$fp = @fopen(Config::get(Config::LOCK_DIRECTORY) . "/$filename", "r");
|
2013-05-29 03:46:14 +00:00
|
|
|
if ($fp) {
|
|
|
|
if (flock($fp, LOCK_EX | LOCK_NB)) {
|
|
|
|
flock($fp, LOCK_UN);
|
|
|
|
fclose($fp);
|
|
|
|
return false;
|
|
|
|
}
|
2007-09-25 03:23:29 +00:00
|
|
|
fclose($fp);
|
2013-05-29 03:46:14 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
2007-09-25 03:23:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
2006-02-13 13:08:23 +00:00
|
|
|
}
|
2013-05-29 03:46:14 +00:00
|
|
|
return true; // consider the file always locked and skip the test
|
|
|
|
} else {
|
|
|
|
return false;
|
2006-02-13 13:08:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @return resource|false A file pointer resource on success, or false on error.
|
|
|
|
*/
|
|
|
|
function make_lockfile(string $filename) {
|
2021-02-22 18:47:48 +00:00
|
|
|
$fp = fopen(Config::get(Config::LOCK_DIRECTORY) . "/$filename", "w");
|
2006-02-12 07:21:52 +00:00
|
|
|
|
2013-02-25 17:28:51 +00:00
|
|
|
if ($fp && flock($fp, LOCK_EX | LOCK_NB)) {
|
2013-06-07 05:39:12 +00:00
|
|
|
$stat_h = fstat($fp);
|
2021-02-22 18:47:48 +00:00
|
|
|
$stat_f = stat(Config::get(Config::LOCK_DIRECTORY) . "/$filename");
|
2013-06-07 05:39:12 +00:00
|
|
|
|
2013-06-11 08:55:47 +00:00
|
|
|
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
|
|
|
if ($stat_h["ino"] != $stat_f["ino"] ||
|
|
|
|
$stat_h["dev"] != $stat_f["dev"]) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2013-06-07 05:39:12 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 14:05:02 +00:00
|
|
|
if (function_exists('posix_getpid')) {
|
|
|
|
fwrite($fp, posix_getpid() . "\n");
|
|
|
|
}
|
2006-02-12 07:21:52 +00:00
|
|
|
return $fp;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @param mixed $val
|
|
|
|
*/
|
|
|
|
function checkbox_to_sql_bool($val): int {
|
2017-12-03 06:26:11 +00:00
|
|
|
return ($val == "on") ? 1 : 0;
|
2014-03-21 11:55:28 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function uniqid_short(): string {
|
2021-02-22 11:41:09 +00:00
|
|
|
return uniqid(base_convert((string)rand(), 10, 36));
|
2015-08-03 16:21:06 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function T_sprintf(): string {
|
2017-05-04 12:13:02 +00:00
|
|
|
$args = func_get_args();
|
|
|
|
return vsprintf(__(array_shift($args)), $args);
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function T_nsprintf(): string {
|
2021-01-07 15:16:42 +00:00
|
|
|
$args = func_get_args();
|
|
|
|
return vsprintf(_ngettext(array_shift($args), array_shift($args), array_shift($args)), $args);
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function init_plugins(): bool {
|
2021-02-22 18:47:48 +00:00
|
|
|
PluginHost::getInstance()->load(Config::get(Config::PLUGINS), PluginHost::KIND_ALL);
|
2017-05-04 12:13:02 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!function_exists('gzdecode')) {
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @return false|string The decoded string or false if an error occurred.
|
|
|
|
*/
|
|
|
|
function gzdecode(string $string) { // no support for 2nd argument
|
2017-05-04 12:13:02 +00:00
|
|
|
return file_get_contents('compress.zlib://data:who/cares;base64,'.
|
|
|
|
base64_encode($string));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function get_random_bytes(int $length): string {
|
2020-09-17 05:59:18 +00:00
|
|
|
if (function_exists('random_bytes')) {
|
|
|
|
return random_bytes($length);
|
|
|
|
} else if (function_exists('openssl_random_pseudo_bytes')) {
|
2017-05-04 12:13:02 +00:00
|
|
|
return openssl_random_pseudo_bytes($length);
|
|
|
|
} else {
|
|
|
|
$output = "";
|
|
|
|
|
|
|
|
for ($i = 0; $i < $length; $i++)
|
|
|
|
$output .= chr(mt_rand(0, 255));
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function read_stdin(): ?string {
|
2017-05-04 12:13:02 +00:00
|
|
|
$fp = fopen("php://stdin", "r");
|
|
|
|
|
|
|
|
if ($fp) {
|
|
|
|
$line = trim(fgets($fp));
|
|
|
|
fclose($fp);
|
|
|
|
return $line;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @param object|string $class
|
|
|
|
*/
|
|
|
|
function implements_interface($class, string $interface): bool {
|
|
|
|
$class_implemented_interfaces = class_implements($class);
|
|
|
|
|
|
|
|
if ($class_implemented_interfaces) {
|
|
|
|
return in_array($interface, $class_implemented_interfaces);
|
|
|
|
}
|
|
|
|
return false;
|
2017-05-04 12:13:02 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function get_theme_path(string $theme): string {
|
2017-05-04 12:13:02 +00:00
|
|
|
$check = "themes/$theme";
|
|
|
|
if (file_exists($check)) return $check;
|
|
|
|
|
|
|
|
$check = "themes.local/$theme";
|
|
|
|
if (file_exists($check)) return $check;
|
2021-03-11 04:44:58 +00:00
|
|
|
|
|
|
|
return "";
|
2017-05-04 12:13:02 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function theme_exists(string $theme): bool {
|
2018-12-09 08:37:26 +00:00
|
|
|
return file_exists("themes/$theme") || file_exists("themes.local/$theme");
|
2017-05-04 12:13:02 +00:00
|
|
|
}
|
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
/**
|
|
|
|
* @param array<int, mixed> $arr
|
|
|
|
*/
|
|
|
|
function arr_qmarks(array $arr): string {
|
2018-01-30 07:44:31 +00:00
|
|
|
return str_repeat('?,', count($arr) - 1) . '?';
|
|
|
|
}
|
2018-12-02 17:07:57 +00:00
|
|
|
|
2021-11-11 21:37:34 +00:00
|
|
|
function get_scripts_timestamp(): int {
|
2018-12-02 17:07:57 +00:00
|
|
|
$files = glob("js/*.js");
|
|
|
|
$ts = 0;
|
|
|
|
|
|
|
|
foreach ($files as $file) {
|
|
|
|
$file_ts = filemtime($file);
|
|
|
|
if ($file_ts > $ts) $ts = $file_ts;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $ts;
|
2018-12-06 16:37:20 +00:00
|
|
|
}
|
2019-12-18 11:27:40 +00:00
|
|
|
|