3 namespace wcf\system\background\job
;
5 use BadMethodCallException
;
6 use GuzzleHttp\Psr7\Response
;
7 use wcf\data\unfurl\url\UnfurlUrl
;
8 use wcf\data\unfurl\url\UnfurlUrlAction
;
9 use wcf\system\message\unfurl\exception\DownloadFailed
;
10 use wcf\system\message\unfurl\exception\ParsingFailed
;
11 use wcf\system\message\unfurl\exception\UrlInaccessible
;
12 use wcf\system\message\unfurl\UnfurlResponse
;
13 use wcf\util\FileUtil
;
14 use wcf\util\StringUtil
;
17 * Represents a background job to get information for an url.
19 * @author Joshua Ruesweg
20 * @copyright 2001-2020 WoltLab GmbH
21 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
22 * @package WoltLabSuite\Core\System\Background\Job
25 final class UnfurlUrlBackgroundJob
extends AbstractBackgroundJob
33 * UnfurlURLJob constructor.
35 * @param UnfurlUrl $url
37 public function __construct(UnfurlUrl
$url)
39 $this->urlID
= $url->urlID
;
45 public function retryAfter()
47 switch ($this->getFailures()) {
63 public function perform()
65 $unfurlUrl = new UnfurlUrl($this->urlID
);
68 $unfurlResponse = UnfurlResponse
::fetch($unfurlUrl->url
);
70 if (empty(StringUtil
::trim($unfurlResponse->getTitle()))) {
71 $this->save(UnfurlUrl
::STATUS_REJECTED
);
76 $title = StringUtil
::truncate($unfurlResponse->getTitle(), 255);
78 if ($unfurlResponse->getDescription()) {
79 $description = StringUtil
::truncate($unfurlResponse->getDescription());
82 if ($unfurlResponse->getImageUrl()) {
84 $image = $this->downloadImage($unfurlResponse->getImage());
85 $imageData = \
getimagesizefromstring($image);
86 if ($imageData !== false) {
87 $imageType = $this->validateImage($imageData);
88 if (!(MODULE_IMAGE_PROXY || IMAGE_ALLOW_EXTERNAL_SOURCE
)) {
89 $imageHash = $this->saveImage($imageData, $image);
94 $imageType = UnfurlUrl
::IMAGE_NO_IMAGE
;
97 if ($imageType === UnfurlUrl
::IMAGE_NO_IMAGE
) {
98 $imageUrl = $imageHash = "";
100 $imageUrl = $unfurlResponse->getImageUrl();
102 } catch (UrlInaccessible | DownloadFailed
$e) {
103 $imageType = UnfurlUrl
::IMAGE_NO_IMAGE
;
104 $imageUrl = $imageHash = "";
107 $imageType = UnfurlUrl
::IMAGE_NO_IMAGE
;
108 $imageUrl = $imageHash = "";
112 UnfurlUrl
::STATUS_SUCCESSFUL
,
119 } catch (UrlInaccessible | ParsingFailed
$e) {
120 if (\ENABLE_DEBUG_MODE
) {
121 \wcf\functions\exception\
logThrowable($e);
124 $this->save(UnfurlUrl
::STATUS_REJECTED
);
128 private function downloadImage(Response
$imageResponse): string
131 while (!$imageResponse->getBody()->eof()) {
132 $image .= $imageResponse->getBody()->read(8192);
134 if ($imageResponse->getBody()->tell() >= UnfurlResponse
::MAX_IMAGE_SIZE
) {
138 $imageResponse->getBody()->close();
143 private function validateImage(array $imageData): string
145 $isSquared = $imageData[0] === $imageData[1];
147 (!$isSquared && ($imageData[0] < 300 && $imageData[1] < 150))
148 || \
min($imageData[0], $imageData[1]) < 50
150 return UnfurlUrl
::IMAGE_NO_IMAGE
;
153 return UnfurlUrl
::IMAGE_SQUARED
;
155 return UnfurlUrl
::IMAGE_COVER
;
160 private function saveImage(array $imageData, string $image): string
162 switch ($imageData[2]) {
169 case \IMAGETYPE_JPEG
:
174 throw new DownloadFailed();
177 $imageHash = \
sha1($image);
179 $path = WCF_DIR
. 'images/unfurlUrl/' . \
substr($imageHash, 0, 2);
180 FileUtil
::makePath($path);
182 $fileLocation = $path . '/' . $imageHash . '.' . $extension;
184 \file_put_contents
($fileLocation, $image);
186 @\touch
($fileLocation);
188 return $imageHash . '.' . $extension;
191 private function save(
194 string $description = "",
195 string $imageType = UnfurlUrl
::IMAGE_NO_IMAGE
,
196 string $imageUrl = "",
197 string $imageHash = ""
200 case UnfurlUrl
::STATUS_PENDING
:
201 case UnfurlUrl
::STATUS_REJECTED
:
202 case UnfurlUrl
::STATUS_SUCCESSFUL
:
206 throw new BadMethodCallException("Invalid status '{$status}' given.");
209 switch ($imageType) {
210 case UnfurlUrl
::IMAGE_COVER
:
211 case UnfurlUrl
::IMAGE_NO_IMAGE
:
212 case UnfurlUrl
::IMAGE_SQUARED
:
216 throw new BadMethodCallException("Invalid imageType '{$imageType}' given.");
219 $urlAction = new UnfurlUrlAction([$this->urlID
], 'update', [
223 'description' => $description,
224 'imageType' => $imageType,
225 'imageUrl' => $imageUrl,
226 'imageHash' => $imageHash,
227 'lastFetch' => TIME_NOW
,
230 $urlAction->executeAction();
236 public function onFinalFailure()
238 $this->save(UnfurlUrl
::STATUS_REJECTED
);