kopia lustrzana https://github.com/nextcloud/social
-TNCRequest
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>pull/1537/head
rodzic
69128016ab
commit
3bce7b4dd1
|
@ -76,40 +76,5 @@ class Application extends App implements IBootstrap {
|
|||
$manager = $context->getServerContainer()
|
||||
->getNotificationManager();
|
||||
$manager->registerNotifierService(Notifier::class);
|
||||
|
||||
try {
|
||||
$context->injectFn(Closure::fromCallable([$this, 'checkUpgradeStatus']));
|
||||
} catch (Throwable $e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register Navigation Tab
|
||||
*
|
||||
* @param IServerContainer $container
|
||||
*/
|
||||
protected function checkUpgradeStatus(IServerContainer $container) {
|
||||
$upgradeChecked = $container->getConfig()
|
||||
->getAppValue(Application::APP_NAME, 'update_checked', '');
|
||||
|
||||
if ($upgradeChecked === '0.3') {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$configService = $container->query(ConfigService::class);
|
||||
$updateService = $container->query(UpdateService::class);
|
||||
} catch (QueryException $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = new SchemaWrapper($container->get(IDBConnection::class));
|
||||
if ($schema->hasTable('social_a2_stream')) {
|
||||
$updateService->checkUpdateStatus();
|
||||
}
|
||||
|
||||
$configService->setAppValue('update_checked', '0.3');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1263,7 +1263,6 @@ class CoreRequestBuilder {
|
|||
* this just empty all tables from the app.
|
||||
*/
|
||||
public function emptyAll() {
|
||||
/** @var ISchemaWrapper|SchemaWrapper $schema */
|
||||
$schema = new SchemaWrapper(Server::get(IDBConnection::class));
|
||||
foreach (array_keys(self::$tables) as $table) {
|
||||
if ($schema->hasTable($table)) {
|
||||
|
@ -1279,7 +1278,6 @@ class CoreRequestBuilder {
|
|||
* this just empty all tables from the app.
|
||||
*/
|
||||
public function uninstallSocialTables() {
|
||||
/** @var ISchemaWrapper|SchemaWrapper $schema */
|
||||
$schema = new SchemaWrapper(Server::get(IDBConnection::class));
|
||||
foreach (array_keys(self::$tables) as $table) {
|
||||
if ($schema->hasTable($table)) {
|
||||
|
|
|
@ -107,7 +107,7 @@ class RequestQueueRequest extends RequestQueueRequestBuilder {
|
|||
*/
|
||||
public function getFromToken(string $token, int $status = -1): array {
|
||||
$qb = $this->getRequestQueueSelectSql();
|
||||
$this->limitToToken($qb, $token);
|
||||
$qb->limitToToken($token);
|
||||
|
||||
if ($status > -1) {
|
||||
$this->limitToStatus($qb, $status);
|
||||
|
|
|
@ -67,9 +67,9 @@ class RequestQueueRequestBuilder extends CoreRequestBuilder {
|
|||
/**
|
||||
* Base of the Sql Select request for Shares
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
* @return SocialQueryBuilder
|
||||
*/
|
||||
protected function getRequestQueueSelectSql(): IQueryBuilder {
|
||||
protected function getRequestQueueSelectSql(): SocialQueryBuilder {
|
||||
$qb = $this->getQueryBuilder();
|
||||
|
||||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
|
|
|
@ -30,14 +30,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Social\Service;
|
||||
|
||||
use OCA\Social\Tools\Exceptions\RequestContentException;
|
||||
use OCA\Social\Tools\Exceptions\RequestNetworkException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
|
||||
use OCA\Social\Tools\Exceptions\RequestServerException;
|
||||
use OCA\Social\Tools\Model\NCRequest;
|
||||
use OCA\Social\Tools\Model\Request;
|
||||
use OCA\Social\Tools\Traits\TArrayTools;
|
||||
use Exception;
|
||||
use OCA\Social\AP;
|
||||
use OCA\Social\Db\FollowsRequest;
|
||||
|
@ -58,6 +50,14 @@ use OCA\Social\Model\ActivityPub\Actor\Person;
|
|||
use OCA\Social\Model\ActivityPub\Object\Tombstone;
|
||||
use OCA\Social\Model\InstancePath;
|
||||
use OCA\Social\Model\RequestQueue;
|
||||
use OCA\Social\Tools\Exceptions\RequestContentException;
|
||||
use OCA\Social\Tools\Exceptions\RequestNetworkException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
|
||||
use OCA\Social\Tools\Exceptions\RequestServerException;
|
||||
use OCA\Social\Tools\Model\NCRequest;
|
||||
use OCA\Social\Tools\Model\Request;
|
||||
use OCA\Social\Tools\Traits\TArrayTools;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
|
@ -190,12 +190,9 @@ class ActivityService {
|
|||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function request(ACore $activity): string {
|
||||
// $this->saveActivity($activity);
|
||||
|
||||
$author = $this->getAuthorFromItem($activity);
|
||||
$instancePaths = $this->generateInstancePaths($activity);
|
||||
$token =
|
||||
$this->requestQueueService->generateRequestQueue($instancePaths, $activity, $author);
|
||||
$token = $this->requestQueueService->generateRequestQueue($instancePaths, $activity, $author);
|
||||
|
||||
if ($token === '') {
|
||||
return '<request token not needed>';
|
||||
|
@ -212,8 +209,7 @@ class ActivityService {
|
|||
return $token;
|
||||
}
|
||||
|
||||
$requests =
|
||||
$this->requestQueueService->getRequestFromToken($token, RequestQueue::STATUS_STANDBY);
|
||||
$requests = $this->requestQueueService->getRequestFromToken($token, RequestQueue::STATUS_STANDBY);
|
||||
if (sizeof($requests) > 0) {
|
||||
$this->curlService->asyncWithToken($token);
|
||||
}
|
||||
|
@ -245,6 +241,7 @@ class ActivityService {
|
|||
$this->logger->error("Error while trying to init request", [
|
||||
'exception' => $e,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,20 +30,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Social\Service;
|
||||
|
||||
use OCA\Social\Tools\Exceptions\ArrayNotFoundException;
|
||||
use OCA\Social\Tools\Exceptions\MalformedArrayException;
|
||||
use OCA\Social\Tools\Exceptions\RequestContentException;
|
||||
use OCA\Social\Tools\Exceptions\RequestNetworkException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
|
||||
use OCA\Social\Tools\Exceptions\RequestServerException;
|
||||
use OCA\Social\Tools\Model\NCRequest;
|
||||
use OCA\Social\Tools\Model\Request;
|
||||
use OCA\Social\Tools\Traits\TNCRequest;
|
||||
use OCA\Social\Tools\Traits\TArrayTools;
|
||||
use OCA\Social\Tools\Traits\TPathTools;
|
||||
use OCA\Social\Tools\Traits\TNCSetup;
|
||||
use OCA\Social\Tools\Traits\TNCLogger;
|
||||
use Exception;
|
||||
use OCA\Social\AP;
|
||||
use OCA\Social\Exceptions\HostMetaException;
|
||||
|
@ -55,42 +41,49 @@ use OCA\Social\Exceptions\RetrieveAccountFormatException;
|
|||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Exceptions\UnauthorizedFediverseException;
|
||||
use OCA\Social\Model\ActivityPub\Actor\Person;
|
||||
use OCA\Social\Tools\Exceptions\ArrayNotFoundException;
|
||||
use OCA\Social\Tools\Exceptions\MalformedArrayException;
|
||||
use OCA\Social\Tools\Exceptions\RequestContentException;
|
||||
use OCA\Social\Tools\Exceptions\RequestNetworkException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
|
||||
use OCA\Social\Tools\Exceptions\RequestServerException;
|
||||
use OCA\Social\Tools\Model\NCRequest;
|
||||
use OCA\Social\Tools\Model\Request;
|
||||
use OCA\Social\Tools\Traits\TArrayTools;
|
||||
use OCA\Social\Tools\Traits\TPathTools;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class CurlService {
|
||||
use TArrayTools;
|
||||
use TNCSetup;
|
||||
use TNCLogger;
|
||||
use TPathTools;
|
||||
use TNCRequest {
|
||||
retrieveJson as retrieveJsonOrig;
|
||||
doRequest as doRequestOrig;
|
||||
}
|
||||
|
||||
public const ASYNC_REQUEST_TOKEN = '/async/request/{token}';
|
||||
public const USER_AGENT = 'Nextcloud Social';
|
||||
|
||||
private ConfigService $configService;
|
||||
private FediverseService $fediverseService;
|
||||
private MiscService $miscService;
|
||||
private LoggerInterface $logger;
|
||||
|
||||
private int $maxDownloadSize;
|
||||
private bool $maxDownloadSizeReached = false;
|
||||
|
||||
/**
|
||||
* CurlService constructor.
|
||||
*
|
||||
* @param ConfigService $configService
|
||||
* @param FediverseService $fediverseService
|
||||
* @param MiscService $miscService
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(
|
||||
ConfigService $configService, FediverseService $fediverseService, MiscService $miscService
|
||||
ConfigService $configService,
|
||||
FediverseService $fediverseService,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->configService = $configService;
|
||||
$this->fediverseService = $fediverseService;
|
||||
$this->miscService = $miscService;
|
||||
|
||||
$maxDlSize = $this->configService->getAppValue(ConfigService::SOCIAL_MAX_SIZE) * (1024 * 1024);
|
||||
$this->setMaxDownloadSize($maxDlSize);
|
||||
$this->setup('app', 'social');
|
||||
$this->logger = $logger;
|
||||
$this->maxDownloadSize = $this->configService->getAppValue(ConfigService::SOCIAL_MAX_SIZE) * 1048576;
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,7 +101,7 @@ class CurlService {
|
|||
* @throws UnauthorizedFediverseException
|
||||
*/
|
||||
public function webfingerAccount(string &$account): array {
|
||||
$this->debug('webfingerAccount', ['account' => $account]);
|
||||
$this->logger->debug('webfingerAccount', ['account' => $account]);
|
||||
$account = $this->withoutBeginAt($account);
|
||||
|
||||
// we consider an account is like an email
|
||||
|
@ -136,7 +129,7 @@ class CurlService {
|
|||
$request->setProtocols($protocols);
|
||||
$result = $this->retrieveJson($request);
|
||||
|
||||
$this->notice('webfingerAccount, request result', false, ['request' => $request]);
|
||||
$this->logger->notice('webfingerAccount, request result', ['request' => $request]);
|
||||
|
||||
$subject = $this->get('subject', $result, '');
|
||||
list($type, $temp) = explode(':', $subject, 2);
|
||||
|
@ -160,12 +153,12 @@ class CurlService {
|
|||
$request->setHost($host);
|
||||
$request->setProtocols($protocols);
|
||||
|
||||
$this->debug('hostMeta', ['host' => $host, 'protocols' => $protocols]);
|
||||
$this->logger->debug('hostMeta', ['host' => $host, 'protocols' => $protocols]);
|
||||
|
||||
try {
|
||||
$result = $this->retrieveJson($request);
|
||||
} catch (Exception $e) {
|
||||
$this->exception($e, self::$NOTICE, ['request' => $request]);
|
||||
$this->logger->notice('during hostMeta', ['request' => $request, 'exception' => $e]);
|
||||
|
||||
throw new HostMetaException(get_class($e) . ' - ' . $e->getMessage());
|
||||
}
|
||||
|
@ -200,7 +193,7 @@ class CurlService {
|
|||
* @throws UnauthorizedFediverseException
|
||||
*/
|
||||
public function retrieveAccount(string &$account): Person {
|
||||
$this->debug('retrieveAccount', ['account' => $account]);
|
||||
$this->logger->debug('retrieveAccount', ['account' => $account]);
|
||||
$result = $this->webfingerAccount($account);
|
||||
|
||||
try {
|
||||
|
@ -212,7 +205,9 @@ class CurlService {
|
|||
$id = $this->get('href', $link, '');
|
||||
$data = $this->retrieveObject($id);
|
||||
|
||||
$this->debug('retrieveAccount, details', ['link' => $link, 'data' => $data, 'account' => $account]);
|
||||
$this->logger->debug(
|
||||
'retrieveAccount, details', ['link' => $link, 'data' => $data, 'account' => $account]
|
||||
);
|
||||
|
||||
/** @var Person $actor */
|
||||
$actor = AP::$activityPub->getItemFromData($data);
|
||||
|
@ -244,17 +239,17 @@ class CurlService {
|
|||
* @throws UnauthorizedFediverseException
|
||||
*/
|
||||
public function retrieveObject($id): array {
|
||||
$this->debug('retrieveObject', ['id' => $id]);
|
||||
$this->logger->debug('retrieveObject', ['id' => $id]);
|
||||
$url = parse_url($id);
|
||||
$this->mustContains(['path', 'host', 'scheme'], $url);
|
||||
$request = new NCRequest($url['path'], Request::TYPE_GET);
|
||||
$request->setHost($url['host']);
|
||||
$request->setProtocol($url['scheme']);
|
||||
|
||||
$this->debug('retrieveObject', ['request' => $request]);
|
||||
$this->logger->debug('retrieveObject', ['request' => $request]);
|
||||
|
||||
$result = $this->retrieveJson($request);
|
||||
$this->notice('retrieveObject, request result', false, ['request' => $request]);
|
||||
$this->logger->notice('retrieveObject, request result', ['request' => $request]);
|
||||
|
||||
if (is_array($result)) {
|
||||
$result['_host'] = $request->getHost();
|
||||
|
@ -275,7 +270,8 @@ class CurlService {
|
|||
try {
|
||||
return $this->retrieveJsonOrig($request);
|
||||
} catch (RequestNetworkException | RequestContentException $e) {
|
||||
$this->exception($e, self::$NOTICE, ['request' => $request]);
|
||||
$this->logger->notice('during retrieveJson', ['request' => $request, 'exception' => $e]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +287,6 @@ class CurlService {
|
|||
* @throws RequestResultSizeException
|
||||
* @throws RequestServerException
|
||||
*/
|
||||
// migration ?
|
||||
public function doRequest(NCRequest $request): string {
|
||||
$this->fediverseService->authorized($request->getAddress());
|
||||
$this->configService->configureRequest($request);
|
||||
|
@ -331,9 +326,255 @@ class CurlService {
|
|||
$this->retrieveJson($request);
|
||||
} catch (RequestResultNotJsonException $e) {
|
||||
} catch (Exception $e) {
|
||||
$this->miscService->log(
|
||||
'Cannot initiate AsyncWithToken ' . json_encode($token) . ' (' . get_class($e)
|
||||
. ' - ' . json_encode($e) . ')', 1
|
||||
$this->logger->error('Cannot initiate AsyncWithToken', ['token' => $token, 'exception' => $e]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param NCRequest $request
|
||||
*
|
||||
* @return array
|
||||
* @throws RequestContentException
|
||||
* @throws RequestNetworkException
|
||||
* @throws RequestResultNotJsonException
|
||||
* @throws RequestResultSizeException
|
||||
* @throws RequestServerException
|
||||
*/
|
||||
public function retrieveJsonOrig(NCRequest $request): array {
|
||||
$result = $this->doRequestOrig($request);
|
||||
|
||||
if (strpos($request->getContentType(), 'application/xrd') === 0) {
|
||||
$xml = simplexml_load_string($result);
|
||||
$result = json_encode($xml, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
$result = json_decode((string)$result, true);
|
||||
if (is_array($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
throw new RequestResultNotJsonException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws RequestContentException
|
||||
* @throws RequestNetworkException
|
||||
* @throws RequestResultSizeException
|
||||
* @throws RequestServerException
|
||||
*/
|
||||
public function doRequestOrig(Request $request): string {
|
||||
$this->maxDownloadSizeReached = false;
|
||||
|
||||
$ignoreProtocolOnErrors = [7];
|
||||
$result = '';
|
||||
foreach ($request->getProtocols() as $protocol) {
|
||||
$request->setUsedProtocol($protocol);
|
||||
$curl = $this->initRequest($request);
|
||||
|
||||
$result = curl_exec($curl);
|
||||
$this->logger->debug('[>>] ' . json_encode($request) . ' result: ' . json_encode($result));
|
||||
|
||||
if (in_array(curl_errno($curl), $ignoreProtocolOnErrors)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->maxDownloadSizeReached === true) {
|
||||
throw new RequestResultSizeException();
|
||||
}
|
||||
|
||||
$this->parseRequestResult($curl, $request);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string)$result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
private function initRequest(Request $request) {
|
||||
$curl = $this->generateCurlRequest($request);
|
||||
$this->initRequestHeaders($curl, $request);
|
||||
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, $request->getUserAgent());
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $request->getTimeout());
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $request->getTimeout());
|
||||
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_BINARYTRANSFER, $request->isBinary());
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $request->isVerifyPeer());
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, $request->isFollowLocation());
|
||||
|
||||
curl_setopt($curl, CURLOPT_BUFFERSIZE, 128);
|
||||
curl_setopt($curl, CURLOPT_NOPROGRESS, false);
|
||||
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION,
|
||||
/**
|
||||
* @param $downloadSize
|
||||
* @param int $downloaded
|
||||
* @param $uploadSize
|
||||
* @param int $uploaded
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function ($downloadSize, int $downloaded, $uploadSize, int $uploaded) {
|
||||
if ($downloaded > $this->maxDownloadSize) {
|
||||
$this->maxDownloadSizeReached = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
|
||||
return $curl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
private function generateCurlRequest(Request $request) {
|
||||
$url = $request->getUsedProtocol() . '://' . $request->getHost() . $request->getParsedUrl();
|
||||
if ($request->getType() !== Request::TYPE_GET) {
|
||||
$curl = curl_init($url);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
|
||||
|
||||
return $curl;
|
||||
}
|
||||
|
||||
$curl = curl_init($url . $request->getQueryString());
|
||||
switch ($request->getType()) {
|
||||
case Request::TYPE_POST:
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
break;
|
||||
case Request::TYPE_PUT:
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
|
||||
break;
|
||||
case Request::TYPE_DELETE:
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
||||
break;
|
||||
}
|
||||
|
||||
return $curl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestGet(Request $request) {
|
||||
if ($request->getType() !== Request::TYPE_GET) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestHeaders($curl, Request $request) {
|
||||
$headers = [];
|
||||
foreach ($request->getHeaders() as $name => $value) {
|
||||
$headers[] = $name . ': ' . $value;
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestContentException
|
||||
* @throws RequestServerException
|
||||
* @throws RequestNetworkException
|
||||
*/
|
||||
private function parseRequestResult($curl, Request $request): void {
|
||||
$this->parseRequestResultCurl($curl, $request);
|
||||
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
$contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
||||
$request->setContentType((!is_string($contentType)) ? '' : $contentType);
|
||||
$request->setResultCode($code);
|
||||
|
||||
$this->parseRequestResultCode301($code, $request);
|
||||
$this->parseRequestResultCode4xx($code, $request);
|
||||
$this->parseRequestResultCode5xx($code, $request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestNetworkException
|
||||
*/
|
||||
private function parseRequestResultCurl($curl, Request $request) {
|
||||
$errno = curl_errno($curl);
|
||||
if ($errno > 0) {
|
||||
throw new RequestNetworkException(
|
||||
$errno . ' - ' . curl_error($curl) . ' - ' . json_encode(
|
||||
$request, JSON_UNESCAPED_SLASHES
|
||||
), $errno
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestContentException
|
||||
*/
|
||||
private function parseRequestResultCode301(int $code, Request $request) {
|
||||
if ($code === 301) {
|
||||
throw new RequestContentException(
|
||||
'301 - ' . json_encode($request, JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestContentException
|
||||
*/
|
||||
private function parseRequestResultCode4xx(int $code, Request $request) {
|
||||
if ($code === 404 || $code === 410) {
|
||||
throw new RequestContentException(
|
||||
$code . ' - ' . json_encode($request, JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestServerException
|
||||
*/
|
||||
private function parseRequestResultCode5xx(int $code, Request $request) {
|
||||
if ($code === 500) {
|
||||
throw new RequestServerException(
|
||||
$code . ' - ' . json_encode($request, JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,21 +55,17 @@ use OCA\Social\Model\ActivityPub\Actor\Person;
|
|||
use OCA\Social\Model\ActivityPub\Object\Follow;
|
||||
use OCA\Social\Model\ActivityPub\OrderedCollection;
|
||||
use OCA\Social\Model\InstancePath;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class FollowService {
|
||||
use TArrayTools;
|
||||
|
||||
|
||||
private FollowsRequest $followsRequest;
|
||||
|
||||
private ActivityService $activityService;
|
||||
|
||||
private CacheActorService $cacheActorService;
|
||||
|
||||
private ConfigService $configService;
|
||||
|
||||
private MiscService $miscService;
|
||||
|
||||
private LoggerInterface $logger;
|
||||
|
||||
private ?Person $viewer = null;
|
||||
|
||||
|
@ -81,17 +77,20 @@ class FollowService {
|
|||
* @param ActivityService $activityService
|
||||
* @param CacheActorService $cacheActorService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(
|
||||
FollowsRequest $followsRequest, ActivityService $activityService,
|
||||
CacheActorService $cacheActorService, ConfigService $configService, MiscService $miscService
|
||||
FollowsRequest $followsRequest,
|
||||
ActivityService $activityService,
|
||||
CacheActorService $cacheActorService,
|
||||
ConfigService $configService,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->followsRequest = $followsRequest;
|
||||
$this->activityService = $activityService;
|
||||
$this->cacheActorService = $cacheActorService;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -75,8 +75,7 @@ class RequestQueueService {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateRequestQueue(array $instancePaths, ACore $item, string $author
|
||||
): string {
|
||||
public function generateRequestQueue(array $instancePaths, ACore $item, string $author): string {
|
||||
$activity = json_encode($item, JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$token = '';
|
||||
|
@ -99,6 +98,9 @@ class RequestQueueService {
|
|||
|
||||
|
||||
/**
|
||||
* deciding if we run request on main thread,
|
||||
* based on set priority, and number of request linked to one token
|
||||
*
|
||||
* @param string $token
|
||||
*
|
||||
* @return RequestQueue
|
||||
|
|
|
@ -125,7 +125,7 @@ class SignatureService {
|
|||
* @param RequestQueue $queue
|
||||
*
|
||||
* @throws ActorDoesNotExistException
|
||||
* @throws SocialAppConfigException // TODO: implement in TNCRequest ?
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function signRequest(NCRequest $request, RequestQueue $queue): void {
|
||||
$date = gmdate(self::DATE_HEADER);
|
||||
|
|
|
@ -1,342 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* Some tools for myself.
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace OCA\Social\Tools\Traits;
|
||||
|
||||
use OCA\Social\Tools\Exceptions\RequestContentException;
|
||||
use OCA\Social\Tools\Exceptions\RequestNetworkException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
|
||||
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
|
||||
use OCA\Social\Tools\Exceptions\RequestServerException;
|
||||
use OCA\Social\Tools\Model\Request;
|
||||
|
||||
/**
|
||||
* Trait TNCRequest
|
||||
*
|
||||
* @package OCA\Social\Tools\Traits
|
||||
*/
|
||||
trait TNCRequest {
|
||||
/** @var int */
|
||||
private $maxDownloadSize = 100;
|
||||
|
||||
/** @var bool */
|
||||
private $maxDownloadSizeReached = false;
|
||||
|
||||
|
||||
/**
|
||||
* @param int $size
|
||||
*/
|
||||
public function setMaxDownloadSize(int $size) {
|
||||
$this->maxDownloadSize = $size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return array
|
||||
* @throws RequestContentException
|
||||
* @throws RequestNetworkException
|
||||
* @throws RequestResultNotJsonException
|
||||
* @throws RequestResultSizeException
|
||||
* @throws RequestServerException
|
||||
*/
|
||||
public function retrieveJson(Request $request): array {
|
||||
$result = $this->doRequest($request);
|
||||
|
||||
if (strpos($request->getContentType(), 'application/xrd') === 0) {
|
||||
$xml = simplexml_load_string($result);
|
||||
$result = json_encode($xml, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
$result = json_decode((string)$result, true);
|
||||
if (is_array($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
throw new RequestResultNotJsonException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws RequestContentException
|
||||
* @throws RequestNetworkException
|
||||
* @throws RequestResultSizeException
|
||||
* @throws RequestServerException
|
||||
*/
|
||||
public function doRequest(Request $request): string {
|
||||
$this->maxDownloadSizeReached = false;
|
||||
|
||||
$ignoreProtocolOnErrors = [7];
|
||||
$result = '';
|
||||
foreach ($request->getProtocols() as $protocol) {
|
||||
$request->setUsedProtocol($protocol);
|
||||
|
||||
$curl = $this->initRequest($request);
|
||||
|
||||
$this->initRequestGet($request);
|
||||
$this->initRequestPost($curl, $request);
|
||||
$this->initRequestPut($curl, $request);
|
||||
$this->initRequestDelete($curl, $request);
|
||||
|
||||
$this->initRequestHeaders($curl, $request);
|
||||
|
||||
$result = curl_exec($curl);
|
||||
|
||||
if (in_array(curl_errno($curl), $ignoreProtocolOnErrors)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->maxDownloadSizeReached === true) {
|
||||
throw new RequestResultSizeException();
|
||||
}
|
||||
|
||||
$this->parseRequestResult($curl, $request);
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
private function initRequest(Request $request) {
|
||||
$curl = $this->generateCurlRequest($request);
|
||||
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, $request->getUserAgent());
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $request->getTimeout());
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $request->getTimeout());
|
||||
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_BINARYTRANSFER, $request->isBinary());
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $request->isVerifyPeer());
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, $request->isFollowLocation());
|
||||
|
||||
curl_setopt($curl, CURLOPT_BUFFERSIZE, 128);
|
||||
curl_setopt($curl, CURLOPT_NOPROGRESS, false);
|
||||
curl_setopt(
|
||||
/**
|
||||
* @param $downloadSize
|
||||
* @param int $downloaded
|
||||
* @param $uploadSize
|
||||
* @param int $uploaded
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
$curl, CURLOPT_PROGRESSFUNCTION,
|
||||
function ($downloadSize, int $downloaded, $uploadSize, int $uploaded) {
|
||||
if ($downloaded > ($this->maxDownloadSize * (1024 * 1024))) {
|
||||
$this->maxDownloadSizeReached = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
|
||||
return $curl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
private function generateCurlRequest(Request $request) {
|
||||
$url = $request->getUsedProtocol() . '://' . $request->getHost() . $request->getParsedUrl();
|
||||
if ($request->getType() !== Request::TYPE_GET) {
|
||||
$curl = curl_init($url);
|
||||
} else {
|
||||
$curl = curl_init($url . $request->getQueryString());
|
||||
}
|
||||
|
||||
return $curl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestGet(Request $request) {
|
||||
if ($request->getType() !== Request::TYPE_GET) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestPost($curl, Request $request) {
|
||||
if ($request->getType() !== Request::TYPE_POST) {
|
||||
return;
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestPut($curl, Request $request) {
|
||||
if ($request->getType() !== Request::TYPE_PUT) {
|
||||
return;
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestDelete($curl, Request $request) {
|
||||
if ($request->getType() !== Request::TYPE_DELETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestHeaders($curl, Request $request) {
|
||||
$headers = $request->getHeaders();
|
||||
$headersCurl = [];
|
||||
foreach ($headers as $name => $value) {
|
||||
$headersCurl[] = $name . ': ' . $value;
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headersCurl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestContentException
|
||||
* @throws RequestServerException
|
||||
* @throws RequestNetworkException
|
||||
*/
|
||||
private function parseRequestResult($curl, Request $request) {
|
||||
$this->parseRequestResultCurl($curl, $request);
|
||||
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
$contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
||||
$request->setContentType((!is_string($contentType)) ? '' : $contentType);
|
||||
$request->setResultCode($code);
|
||||
|
||||
$this->parseRequestResultCode301($code, $request);
|
||||
$this->parseRequestResultCode4xx($code, $request);
|
||||
$this->parseRequestResultCode5xx($code, $request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestNetworkException
|
||||
*/
|
||||
private function parseRequestResultCurl($curl, Request $request) {
|
||||
$errno = curl_errno($curl);
|
||||
if ($errno > 0) {
|
||||
throw new RequestNetworkException(
|
||||
$errno . ' - ' . curl_error($curl) . ' - ' . json_encode(
|
||||
$request, JSON_UNESCAPED_SLASHES
|
||||
), $errno
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestContentException
|
||||
*/
|
||||
private function parseRequestResultCode301(int $code, Request $request) {
|
||||
if ($code === 301) {
|
||||
throw new RequestContentException(
|
||||
'301 - ' . json_encode($request, JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestContentException
|
||||
*/
|
||||
private function parseRequestResultCode4xx(int $code, Request $request) {
|
||||
if ($code === 404 || $code === 410) {
|
||||
throw new RequestContentException(
|
||||
$code . ' - ' . json_encode($request, JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws RequestServerException
|
||||
*/
|
||||
private function parseRequestResultCode5xx(int $code, Request $request) {
|
||||
if ($code === 500) {
|
||||
throw new RequestServerException(
|
||||
$code . ' - ' . json_encode($request, JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue