|
|
@@ -63,6 +63,7 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
private int $ttl = self::TTL_DEFAULT;
|
|
|
private bool $mute = false;
|
|
|
private string $hash = '';
|
|
|
+ private string $hashFavicon = '';
|
|
|
private string $lockPath = '';
|
|
|
private string $hubUrl = '';
|
|
|
private string $selfUrl = '';
|
|
|
@@ -91,11 +92,31 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
public function hash(): string {
|
|
|
if ($this->hash == '') {
|
|
|
$salt = FreshRSS_Context::systemConf()->salt;
|
|
|
- $this->hash = hash('crc32b', $salt . $this->url);
|
|
|
+ $params = $this->url;
|
|
|
+ $curl_params = $this->attributeArray('curl_params');
|
|
|
+ if (is_array($curl_params)) {
|
|
|
+ // Content provided through a proxy may be completely different
|
|
|
+ $params .= is_string($curl_params[CURLOPT_PROXY] ?? null) ? $curl_params[CURLOPT_PROXY] : '';
|
|
|
+ }
|
|
|
+ $this->hash = sha1($salt . $params);
|
|
|
}
|
|
|
return $this->hash;
|
|
|
}
|
|
|
|
|
|
+ public function hashFavicon(): string {
|
|
|
+ if ($this->hashFavicon == '') {
|
|
|
+ $salt = FreshRSS_Context::systemConf()->salt;
|
|
|
+ $params = $this->website(fallback: true);
|
|
|
+ $curl_params = $this->attributeArray('curl_params');
|
|
|
+ if (is_array($curl_params)) {
|
|
|
+ // Content provided through a proxy may be completely different
|
|
|
+ $params .= is_string($curl_params[CURLOPT_PROXY] ?? null) ? $curl_params[CURLOPT_PROXY] : '';
|
|
|
+ }
|
|
|
+ $this->hashFavicon = hash('crc32b', $salt . $params);
|
|
|
+ }
|
|
|
+ return $this->hashFavicon;
|
|
|
+ }
|
|
|
+
|
|
|
public function url(bool $includeCredentials = true): string {
|
|
|
return $includeCredentials ? $this->url : \SimplePie\Misc::url_remove_credentials($this->url);
|
|
|
}
|
|
|
@@ -133,10 +154,19 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
public function name(bool $raw = false): string {
|
|
|
return $raw || $this->name != '' ? $this->name : (preg_replace('%^https?://(www[.])?%i', '', $this->url) ?? '');
|
|
|
}
|
|
|
- /** @return string HTML-encoded URL of the Web site of the feed */
|
|
|
- public function website(): string {
|
|
|
- return $this->website;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param bool $fallback true to return the URL of the feed if the Web site is blank
|
|
|
+ * @return string HTML-encoded URL of the Web site of the feed
|
|
|
+ */
|
|
|
+ public function website(bool $fallback = false): string {
|
|
|
+ $url = $this->website;
|
|
|
+ if ($fallback && !preg_match('%^https?://.%i', $url)) {
|
|
|
+ $url = $this->url;
|
|
|
+ }
|
|
|
+ return $url;
|
|
|
}
|
|
|
+
|
|
|
public function description(): string {
|
|
|
return $this->description;
|
|
|
}
|
|
|
@@ -227,16 +257,13 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
|
|
|
public function faviconPrepare(bool $force = false): void {
|
|
|
require_once(LIB_PATH . '/favicons.php');
|
|
|
- $url = $this->website;
|
|
|
- if ($url == '') {
|
|
|
- $url = $this->url;
|
|
|
- }
|
|
|
- $txt = FAVICONS_DIR . $this->hash() . '.txt';
|
|
|
+ $url = $this->website(fallback: true);
|
|
|
+ $txt = FAVICONS_DIR . $this->hashFavicon() . '.txt';
|
|
|
if (@file_get_contents($txt) !== $url) {
|
|
|
file_put_contents($txt, $url);
|
|
|
}
|
|
|
if (FreshRSS_Context::$isCli || $force) {
|
|
|
- $ico = FAVICONS_DIR . $this->hash() . '.ico';
|
|
|
+ $ico = FAVICONS_DIR . $this->hashFavicon() . '.ico';
|
|
|
$ico_mtime = @filemtime($ico);
|
|
|
$txt_mtime = @filemtime($txt);
|
|
|
if ($txt_mtime != false &&
|
|
|
@@ -251,12 +278,15 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
}
|
|
|
|
|
|
public static function faviconDelete(string $hash): void {
|
|
|
+ if (!ctype_xdigit($hash)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
$path = DATA_PATH . '/favicons/' . $hash;
|
|
|
@unlink($path . '.ico');
|
|
|
@unlink($path . '.txt');
|
|
|
}
|
|
|
public function favicon(): string {
|
|
|
- return Minz_Url::display('/f.php?' . $this->hash());
|
|
|
+ return Minz_Url::display('/f.php?' . $this->hashFavicon());
|
|
|
}
|
|
|
|
|
|
public function _id(int $value): void {
|
|
|
@@ -268,6 +298,7 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
*/
|
|
|
public function _url(string $value, bool $validate = true): void {
|
|
|
$this->hash = '';
|
|
|
+ $this->hashFavicon = '';
|
|
|
$url = $value;
|
|
|
if ($validate) {
|
|
|
$url = checkUrl($url);
|
|
|
@@ -297,6 +328,7 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
$this->name = $value == '' ? '' : trim($value);
|
|
|
}
|
|
|
public function _website(string $value, bool $validate = true): void {
|
|
|
+ $this->hashFavicon = '';
|
|
|
if ($validate) {
|
|
|
$value = checkUrl($value);
|
|
|
}
|
|
|
@@ -1037,7 +1069,7 @@ class FreshRSS_Feed extends Minz_Model {
|
|
|
}
|
|
|
|
|
|
private function faviconRebuild(): void {
|
|
|
- FreshRSS_Feed::faviconDelete($this->hash());
|
|
|
+ FreshRSS_Feed::faviconDelete($this->hashFavicon());
|
|
|
$this->faviconPrepare(true);
|
|
|
}
|
|
|
|