ShlinkProxy.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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;
  12. use Exception;
  13. /**
  14. * ShlinkProxy
  15. *
  16. * Forwards a URL for shortening to shlink and stores the result.
  17. */
  18. class ShlinkProxy
  19. {
  20. /**
  21. * error message
  22. *
  23. * @access private
  24. * @var string
  25. */
  26. private $_error = '';
  27. /**
  28. * shortened URL
  29. *
  30. * @access private
  31. * @var string
  32. */
  33. private $_url = '';
  34. /**
  35. * constructor
  36. *
  37. * initializes and runs PrivateBin
  38. *
  39. * @access public
  40. * @param string $link
  41. */
  42. public function __construct(Configuration $conf, $link)
  43. {
  44. if (!str_starts_with($link, $conf->getKey('basepath') . '?')) {
  45. $this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.';
  46. return;
  47. }
  48. $shlink_api_url = $conf->getKey('apiurl', 'shlink');
  49. $shlink_api_key = $conf->getKey('apikey', 'shlink');
  50. if (empty($shlink_api_url) || empty($shlink_api_key)) {
  51. $this->_error = 'Error calling Shlink. Probably a configuration issue, like wrong or missing "apiurl" or "apikey".';
  52. return;
  53. }
  54. $data = file_get_contents(
  55. $shlink_api_url, false, stream_context_create(
  56. array(
  57. 'http' => array(
  58. 'method' => 'POST',
  59. 'header' => "Content-Type: application/json\r\n" .
  60. "X-Api-Key: " . $shlink_api_key . "\r\n",
  61. 'content' => json_encode(
  62. array(
  63. 'longUrl' => $link,
  64. )
  65. ),
  66. ),
  67. )
  68. )
  69. );
  70. if ($data === false) {
  71. $http_response_header = $http_response_header ?? [];
  72. $statusCode = '';
  73. if (!empty($http_response_header) && preg_match('/HTTP\/\d+\.\d+\s+(\d+)/', $http_response_header[0], $matches)) {
  74. $statusCode = $matches[1];
  75. }
  76. $this->_error = 'Error calling shlink. HTTP request failed for URL ' . $shlink_api_url . '. Status code: ' . $statusCode;
  77. error_log('Error calling shlink: HTTP request failed for URL ' . $shlink_api_url . '. Status code: ' . $statusCode);
  78. return;
  79. }
  80. try {
  81. $data = Json::decode($data);
  82. } catch (Exception $e) {
  83. $this->_error = 'Error calling shlink. Probably a configuration issue, like wrong or missing "apiurl" or "apikey".';
  84. error_log('Error calling shlink: ' . $e->getMessage());
  85. return;
  86. }
  87. if (
  88. !is_null($data) &&
  89. // array_key_exists('statusCode', $data) &&
  90. // $data['statusCode'] == 200 &&
  91. array_key_exists('shortUrl', $data)
  92. ) {
  93. $this->_url = $data['shortUrl'];
  94. } else {
  95. $this->_error = 'Error parsing shlink response.';
  96. }
  97. }
  98. /**
  99. * Returns the (untranslated) error message
  100. *
  101. * @access public
  102. * @return string
  103. */
  104. public function getError()
  105. {
  106. return $this->_error;
  107. }
  108. /**
  109. * Returns the shortened URL
  110. *
  111. * @access public
  112. * @return string
  113. */
  114. public function getUrl()
  115. {
  116. return $this->_url;
  117. }
  118. /**
  119. * Returns true if any error has occurred
  120. *
  121. * @access public
  122. * @return bool
  123. */
  124. public function isError()
  125. {
  126. return !empty($this->_error);
  127. }
  128. }