Utils.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. <?php
  2. namespace app\common\services;
  3. use Illuminate\Filesystem\Filesystem;
  4. use Illuminate\Support\Facades\Cookie;
  5. use Illuminate\Support\Facades\DB;
  6. use Log;
  7. use Carbon\Carbon;
  8. use Illuminate\Support\Str;
  9. use Storage as LaravelStorage;
  10. class Utils
  11. {
  12. /**
  13. * Returns the client IP address.
  14. *
  15. * This method is defined because Symfony's Request::getClientIp() needs "setTrustedProxies()"
  16. * which sucks when load balancer is enabled.
  17. *
  18. * @return string
  19. */
  20. public static function getClientIp()
  21. {
  22. if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
  23. $ip = $_SERVER['HTTP_CLIENT_IP'];
  24. } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  25. $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
  26. } else {
  27. $ip = $_SERVER['REMOTE_ADDR'];
  28. }
  29. return $ip;
  30. }
  31. /**
  32. * Checks whether the request is secure or not.
  33. * True is always returned when "X-Forwarded-Proto" header is set.
  34. *
  35. * This method is defined because Symfony's Request::isSecure() needs "setTrustedProxies()"
  36. * which sucks when load balancer is enabled.
  37. *
  38. * @return bool
  39. */
  40. public static function isRequestSecure()
  41. {
  42. if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
  43. return true;
  44. if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
  45. return true;
  46. if (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on')
  47. return true;
  48. return false;
  49. }
  50. /**
  51. * Compares two "PHP-standardized" version number strings.
  52. * Unlike version_compare(), this method will determine that versions with suffix are lower.
  53. *
  54. * e.g. 3.2-beta > 3.2-alpha
  55. * 3.2 > 3.2-beta
  56. * 3.2 > 3.2-pre-release
  57. * 3.2 > 3.2-pr8
  58. *
  59. * @param string $version1
  60. * @param string $version2
  61. * @param string $operator
  62. * @return mixed
  63. */
  64. public static function versionCompare($version1, $version2, $operator = null)
  65. {
  66. $versions = [$version1, $version2];
  67. // pre-processing for version contains hyphen
  68. foreach ([0, 1] as $offset) {
  69. if (false !== ($result = self::parseVersionWithHyphen($versions[$offset]))) {
  70. $versions[$offset] = $result;
  71. } else {
  72. $versions[$offset] = ['main' => $versions[$offset], 'sub' => ''];
  73. }
  74. }
  75. if (version_compare($versions[0]['main'], $versions[1]['main'], '=')) {
  76. $sub1 = $versions[0]['sub'];
  77. $sub2 = $versions[1]['sub'];
  78. // v3.2-pr < v3.2
  79. if ($sub1 != "" || $sub2 != "") {
  80. // if both of sub-versions are not empty
  81. if ($sub1 != "" && $sub2 != "") {
  82. return version_compare($sub1, $sub2, $operator);
  83. } else {
  84. $result = version_compare($sub1, $sub2, $operator);
  85. // reverse the result since version_compare() will determine that "beta" > ""
  86. return ($operator == "=") ? $result : !$result;
  87. }
  88. }
  89. }
  90. return version_compare($versions[0]['main'], $versions[1]['main'], $operator);
  91. }
  92. public static function parseVersionWithHyphen($version)
  93. {
  94. preg_match('/([^-]*)-(.*)/', $version, $matches);
  95. if (isset($matches[2])) {
  96. return [
  97. 'main' => $matches[1],
  98. 'sub' => $matches[2]
  99. ];
  100. }
  101. return false;
  102. }
  103. /**
  104. * Rename uploaded file
  105. *
  106. * @param array $file files uploaded via HTTP POST
  107. * @return string $hash sha256 hash of file
  108. */
  109. public static function upload($file)
  110. {
  111. $path = 'tmp'.time();
  112. $absolute_path = storage_path("textures/$path");
  113. try {
  114. if (false === move_uploaded_file($file['tmp_name'], $absolute_path)) {
  115. throw new \Exception('Failed to remove uploaded files, please check the permission', 1);
  116. }
  117. } catch (\Exception $e) {
  118. Log::warning("Failed to move uploaded file, $e");
  119. } finally {
  120. if (file_exists($absolute_path)) {
  121. $hash = hash_file('sha256', $absolute_path);
  122. if (!LaravelStorage::disk('textures')->has($hash)) {
  123. LaravelStorage::disk('textures')->move($path, $hash);
  124. } else {
  125. // delete the temp file
  126. unlink($absolute_path);
  127. }
  128. return $hash;
  129. } else {
  130. Log::warning("Failed to upload file $path");
  131. }
  132. }
  133. }
  134. public static function download($url, $path)
  135. {
  136. @set_time_limit(0);
  137. touch($path);
  138. Log::info("[File Downloader] Download started, source: $url");
  139. Log::info("[File Downloader] ======================================");
  140. $ctx = stream_context_create([
  141. "ssl"=>[
  142. "verify_peer"=>false,
  143. "verify_peer_name"=>false,
  144. ]
  145. ]);
  146. if ($fp = fopen($url, "rb", false, $ctx)) {
  147. if (!$download_fp = fopen($path, "wb", false, $ctx)) {
  148. return false;
  149. }
  150. while (!feof($fp)) {
  151. if (!file_exists($path)) {
  152. // cancel downloading if destination is no longer available
  153. fclose($download_fp);
  154. return false;
  155. }
  156. Log::info("[Download] 1024 bytes wrote");
  157. fwrite($download_fp, fread($fp, 1024 * 8 ), 1024 * 8);
  158. }
  159. fclose($download_fp);
  160. fclose($fp);
  161. Log::info("[File Downloader] Finished downloading, data stored to: $path");
  162. Log::info("[File Downloader] ===========================================");
  163. return true;
  164. } else {
  165. return false;
  166. }
  167. }
  168. public static function getRemoteFileSize($url)
  169. {
  170. $regex = '/^Content-Length: *+\K\d++$/im';
  171. if (!$fp = @fopen($url, 'rb')) {
  172. return false;
  173. }
  174. if (
  175. isset($http_response_header) &&
  176. preg_match($regex, implode("\n", $http_response_header), $matches)
  177. ) {
  178. return (int)$matches[0];
  179. }
  180. return strlen(stream_get_contents($fp));
  181. }
  182. public static function getTimeFormatted($timestamp = 0)
  183. {
  184. return ($timestamp == 0) ? Carbon::now()->toDateTimeString() : Carbon::createFromTimestamp($timestamp)->toDateTimeString();
  185. }
  186. /**
  187. * Replace content of string according to given rules.
  188. *
  189. * @param string $str
  190. * @param array $rules
  191. * @return string
  192. */
  193. public static function getStringReplaced($str, $rules)
  194. {
  195. foreach ($rules as $search => $replace) {
  196. $str = str_replace($search, $replace, $str);
  197. }
  198. return $str;
  199. }
  200. /**
  201. * Convert error number of uploading files to human-readable text.
  202. *
  203. * @param int $errno
  204. * @return string
  205. */
  206. public static function convertUploadFileError($errno = 0)
  207. {
  208. $phpFileUploadErrors = [
  209. 0 => 'There is no error, the file uploaded with success',
  210. 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
  211. 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
  212. 3 => 'The uploaded file was only partially uploaded',
  213. 4 => 'No file was uploaded',
  214. 6 => 'Missing a temporary folder',
  215. 7 => 'Failed to write file to disk.',
  216. 8 => 'A PHP extension stopped the file upload.',
  217. ];
  218. return $phpFileUploadErrors[$errno];
  219. }
  220. public static function fieldexists($table, $field)
  221. {
  222. $prefix = DB::getTablePrefix();
  223. $tb = $prefix . $table;
  224. $res = DB::select("Describe {$tb} {$field}");
  225. if (!empty($res)) {
  226. return true;
  227. } else {
  228. return false;
  229. }
  230. }
  231. public static function dataEncrypt(&$data)
  232. {
  233. foreach ($data as $key => &$val) {
  234. if (!empty($val)) {
  235. switch ($key) {
  236. case 'alipay_app_id':
  237. case 'rsa_private_key':
  238. case 'rsa_public_key':
  239. case 'alipay_number':
  240. case 'alipay_name':
  241. $val = encrypt($val);
  242. break;
  243. }
  244. }
  245. }
  246. }
  247. public static function dataDecrypt(&$data)
  248. {
  249. foreach ($data as $key => &$val) {
  250. if (!empty($val)) {
  251. switch ($key) {
  252. case 'alipay_app_id':
  253. case 'rsa_private_key':
  254. case 'rsa_public_key':
  255. case 'alipay_number':
  256. case 'alipay_name':
  257. $val = decrypt($val);
  258. break;
  259. }
  260. }
  261. }
  262. }
  263. public static function mkdirs($path)
  264. {
  265. $filesystem = app(Filesystem::class);
  266. if (!$filesystem->isDirectory($path)) {
  267. $filesystem->makeDirectory($path, 0755, true);
  268. }
  269. return $filesystem->isDirectory($path);
  270. }
  271. /**
  272. * 清除uniacid
  273. *
  274. */
  275. public static function removeUniacid()
  276. {
  277. Cookie::queue('uniacid',null,time() - 2160000, '/');
  278. Cookie::queue('uniacid',null,time() - 2160000, '/admin');
  279. Cookie::queue('uniacid',null,time() - 2160000,'/admin/shop');
  280. }
  281. /**
  282. * 保存uniacid
  283. */
  284. public static function addUniacid($uniacid = null)
  285. {
  286. if (is_null($uniacid)) {
  287. $uniacid = request()->uniacid;
  288. }
  289. Cookie::queue('uniacid',$uniacid,time() + 2160000, '/admin');
  290. Cookie::queue('uniacid',$uniacid,time() + 2160000,'/admin/shop');
  291. }
  292. }