aboutsummaryrefslogtreecommitdiff
path: root/lib/lib_rss.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lib_rss.php')
-rw-r--r--lib/lib_rss.php78
1 files changed, 58 insertions, 20 deletions
diff --git a/lib/lib_rss.php b/lib/lib_rss.php
index 8eb89c578..c93243eff 100644
--- a/lib/lib_rss.php
+++ b/lib/lib_rss.php
@@ -85,6 +85,32 @@ spl_autoload_register('classAutoloader');
//</Auto-loading>
/**
+ * @param array<mixed,mixed> $array
+ * @phpstan-assert-if-true array<string,mixed> $array
+ */
+function is_array_keys_string(array $array): bool {
+ foreach ($array as $key => $value) {
+ if (!is_string($key)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * @param array<mixed,mixed> $array
+ * @phpstan-assert-if-true array<mixed,string> $array
+ */
+function is_array_values_string(array $array): bool {
+ foreach ($array as $value) {
+ if (!is_string($value)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
* Memory efficient replacement of `echo json_encode(...)`
* @param array<mixed>|mixed $json
* @param int $optimisationDepth Number of levels for which to perform memory optimisation
@@ -231,6 +257,7 @@ function timestamptodate(int $t, bool $hour = true): string {
* Decode HTML entities but preserve XML entities.
*/
function html_only_entity_decode(?string $text): string {
+ /** @var array<string,string>|null $htmlEntitiesOnly */
static $htmlEntitiesOnly = null;
if ($htmlEntitiesOnly === null) {
$htmlEntitiesOnly = array_flip(array_diff(
@@ -252,7 +279,7 @@ function sensitive_log($log): array|string {
foreach ($log as $k => $v) {
if (in_array($k, ['api_key', 'Passwd', 'T'], true)) {
$log[$k] = '██';
- } elseif (is_array($v) || is_string($v)) {
+ } elseif ((is_array($v) && is_array_keys_string($v)) || is_string($v)) {
$log[$k] = sensitive_log($v);
} else {
return '';
@@ -298,7 +325,9 @@ function customSimplePie(array $attributes = [], array $curl_options = []): \Sim
}
if (!empty($attributes['curl_params']) && is_array($attributes['curl_params'])) {
foreach ($attributes['curl_params'] as $co => $v) {
- $curl_options[$co] = $v;
+ if (is_int($co)) {
+ $curl_options[$co] = $v;
+ }
}
}
$simplePie->set_curl_options($curl_options);
@@ -366,13 +395,18 @@ function sanitizeHTML(string $data, string $base = '', ?int $maxLength = null):
if ($maxLength !== null) {
$data = mb_strcut($data, 0, $maxLength, 'UTF-8');
}
+ /** @var \SimplePie\SimplePie|null $simplePie */
static $simplePie = null;
- if ($simplePie == null) {
+ if ($simplePie === null) {
$simplePie = customSimplePie();
$simplePie->enable_cache(false);
$simplePie->init();
}
- $result = html_only_entity_decode($simplePie->sanitize->sanitize($data, \SimplePie\SimplePie::CONSTRUCT_HTML, $base));
+ $sanitized = $simplePie->sanitize->sanitize($data, \SimplePie\SimplePie::CONSTRUCT_HTML, $base);
+ if (!is_string($sanitized)) {
+ return '';
+ }
+ $result = html_only_entity_decode($sanitized);
if ($maxLength !== null && strlen($result) > $maxLength) {
//Sanitizing has made the result too long so try again shorter
$data = mb_strcut($result, 0, (2 * $maxLength) - strlen($result) - 2, 'UTF-8');
@@ -504,6 +538,9 @@ function httpGet(string $url, string $cachePath, string $type = 'html', array $a
// TODO: Implement HTTP 1.1 conditional GET If-Modified-Since
$ch = curl_init();
+ if ($ch === false) {
+ return '';
+ }
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => ['Accept: ' . $accept],
@@ -592,9 +629,10 @@ function lazyimg(string $content): string {
/** @return numeric-string */
function uTimeString(): string {
$t = @gettimeofday();
- $result = $t['sec'] . str_pad('' . $t['usec'], 6, '0', STR_PAD_LEFT);
- /** @var numeric-string @result */
- return $result;
+ $sec = is_numeric($t['sec']) ? (int)$t['sec'] : 0;
+ $usec = is_numeric($t['usec']) ? (int)$t['usec'] : 0;
+ $result = ((string)$sec) . str_pad((string)$usec, 6, '0', STR_PAD_LEFT);
+ return ctype_digit($result) ? $result : '0';
}
function invalidateHttpCache(string $username = ''): bool {
@@ -606,7 +644,7 @@ function invalidateHttpCache(string $username = ''): bool {
}
/**
- * @return array<string>
+ * @return list<string>
*/
function listUsers(): array {
$final_list = [];
@@ -712,9 +750,9 @@ function checkCIDR(string $ip, string $range): bool {
* Use CONN_REMOTE_ADDR (if available, to be robust even when using Apache mod_remoteip) or REMOTE_ADDR environment variable to determine the connection IP.
*/
function connectionRemoteAddress(): string {
- $remoteIp = $_SERVER['CONN_REMOTE_ADDR'] ?? '';
+ $remoteIp = is_string($_SERVER['CONN_REMOTE_ADDR'] ?? null) ? $_SERVER['CONN_REMOTE_ADDR'] : '';
if ($remoteIp == '') {
- $remoteIp = $_SERVER['REMOTE_ADDR'] ?? '';
+ $remoteIp = is_string($_SERVER['REMOTE_ADDR'] ?? null) ? $_SERVER['REMOTE_ADDR'] : '';
}
if ($remoteIp == 0) {
$remoteIp = '';
@@ -752,17 +790,17 @@ function checkTrustedIP(): bool {
}
function httpAuthUser(bool $onlyTrusted = true): string {
- if (!empty($_SERVER['REMOTE_USER'])) {
+ if (!empty($_SERVER['REMOTE_USER']) && is_string($_SERVER['REMOTE_USER'])) {
return $_SERVER['REMOTE_USER'];
}
- if (!empty($_SERVER['REDIRECT_REMOTE_USER'])) {
+ if (!empty($_SERVER['REDIRECT_REMOTE_USER']) && is_string($_SERVER['REDIRECT_REMOTE_USER'])) {
return $_SERVER['REDIRECT_REMOTE_USER'];
}
if (!$onlyTrusted || checkTrustedIP()) {
- if (!empty($_SERVER['HTTP_REMOTE_USER'])) {
+ if (!empty($_SERVER['HTTP_REMOTE_USER']) && is_string($_SERVER['HTTP_REMOTE_USER'])) {
return $_SERVER['HTTP_REMOTE_USER'];
}
- if (!empty($_SERVER['HTTP_X_WEBAUTH_USER'])) {
+ if (!empty($_SERVER['HTTP_X_WEBAUTH_USER']) && is_string($_SERVER['HTTP_X_WEBAUTH_USER'])) {
return $_SERVER['HTTP_X_WEBAUTH_USER'];
}
}
@@ -872,14 +910,14 @@ function recursive_unlink(string $dir): bool {
/**
* Remove queries where $get is appearing.
* @param string $get the get attribute which should be removed.
- * @param array<int,array<string,string|int>> $queries an array of queries.
- * @return array<int,array<string,string|int>> without queries where $get is appearing.
+ * @param array<int,array{get?:string,name?:string,order?:string,search?:string,state?:int,url?:string}> $queries an array of queries.
+ * @return array<int,array{get?:string,name?:string,order?:string,search?:string,state?:int,url?:string}> without queries where $get is appearing.
*/
function remove_query_by_get(string $get, array $queries): array {
$final_queries = [];
- foreach ($queries as $key => $query) {
+ foreach ($queries as $query) {
if (empty($query['get']) || $query['get'] !== $get) {
- $final_queries[$key] = $query;
+ $final_queries[] = $query;
}
}
return $final_queries;
@@ -901,7 +939,7 @@ const SHORTCUT_KEYS = [
/**
* @param array<string> $shortcuts
- * @return array<string>
+ * @return list<string>
*/
function getNonStandardShortcuts(array $shortcuts): array {
$standard = strtolower(implode(' ', SHORTCUT_KEYS));
@@ -911,7 +949,7 @@ function getNonStandardShortcuts(array $shortcuts): array {
return $shortcut !== '' && stripos($standard, $shortcut) === false;
});
- return $nonStandard;
+ return array_values($nonStandard);
}
function errorMessageInfo(string $errorTitle, string $error = ''): string {