AbstractProxy.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <?php declare(strict_types=1);
  2. /**
  3. * PrivateBin
  4. *
  5. * a zero-knowledge paste bin
  6. *
  7. * @link https://github.com/PrivateBin/PrivateBin
  8. * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
  9. * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
  10. */
  11. namespace PrivateBin\Proxy;
  12. use Exception;
  13. use PrivateBin\Configuration;
  14. use PrivateBin\Json;
  15. /**
  16. * AbstractProxy
  17. *
  18. * Forwards a URL for shortening and stores the result.
  19. */
  20. abstract class AbstractProxy
  21. {
  22. /**
  23. * error message
  24. *
  25. * @access private
  26. * @var string
  27. */
  28. private $_error = '';
  29. /**
  30. * shortened URL
  31. *
  32. * @access private
  33. * @var string
  34. */
  35. private $_url = '';
  36. /**
  37. * constructor
  38. *
  39. * initializes and runs the proxy class
  40. *
  41. * @access public
  42. * @param Configuration $conf
  43. * @param string $link
  44. */
  45. public function __construct(Configuration $conf, string $link)
  46. {
  47. if (!str_starts_with($link, $conf->getKey('basepath') . '?')) {
  48. $this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.';
  49. return;
  50. }
  51. $proxyUrl = $this->_getProxyUrl($conf);
  52. if (empty($proxyUrl)) {
  53. $this->_error = 'Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.';
  54. $this->logErrorWithClassName($this->_error);
  55. return;
  56. }
  57. $data = file_get_contents($proxyUrl, false,
  58. stream_context_create(
  59. array(
  60. 'http' => $this->_getProxyPayload($conf, $link),
  61. )
  62. )
  63. );
  64. if ($data === false) {
  65. $http_response_header = $http_response_header ?? array();
  66. $statusCode = '';
  67. if (!empty($http_response_header) && preg_match('/HTTP\/\d+\.\d+\s+(\d+)/', $http_response_header[0], $matches)) {
  68. $statusCode = $matches[1];
  69. }
  70. $this->_error = 'Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.';
  71. $this->logErrorWithClassName($this->_error . ' Status code: ' . $statusCode);
  72. return;
  73. }
  74. try {
  75. $jsonData = Json::decode($data);
  76. } catch (Exception $e) {
  77. $this->_error = 'Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.';
  78. $this->logErrorWithClassName('Error calling proxy: ' . $e->getMessage());
  79. return;
  80. }
  81. $url = $this->_extractShortUrl($jsonData);
  82. if ($url === null || empty($url)) {
  83. $this->_error = 'Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.';
  84. $this->logErrorWithClassName('Error calling proxy: ' . $data);
  85. } else {
  86. $this->_url = $url;
  87. }
  88. }
  89. private function logErrorWithClassName(string $error)
  90. {
  91. error_log('[' . get_class($this) . '] ' . $error);
  92. }
  93. /**
  94. * Returns the (untranslated) error message
  95. *
  96. * @access public
  97. * @return string
  98. */
  99. public function getError()
  100. {
  101. return $this->_error;
  102. }
  103. /**
  104. * Returns the shortened URL
  105. *
  106. * @access public
  107. * @return string
  108. */
  109. public function getUrl()
  110. {
  111. return $this->_url;
  112. }
  113. /**
  114. * Returns true if any error has occurred
  115. *
  116. * @access public
  117. * @return bool
  118. */
  119. public function isError()
  120. {
  121. return !empty($this->_error);
  122. }
  123. /**
  124. * Abstract method to get the payload to send to the URL shortener
  125. *
  126. * @access protected
  127. * @param Configuration $conf
  128. * @param string $link
  129. * @return array
  130. */
  131. abstract protected function _getProxyPayload(Configuration $conf, string $link): array;
  132. /**
  133. * Abstract method to extract the shortUrl from the response
  134. *
  135. * @param array $data
  136. * @return ?string
  137. */
  138. abstract protected function _extractShortUrl(array $data): ?string;
  139. /**
  140. * Abstract method to get the proxy URL
  141. *
  142. * @param Configuration $conf
  143. * @return string
  144. */
  145. abstract protected function _getProxyUrl(Configuration $conf): string;
  146. }