Completed
Push — master ( 488ec0...489dce )
by Elf
03:34
created

Helper::sampleEncrypt()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 2
dl 0
loc 20
ccs 0
cts 13
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace ElfSundae\Laravel\Support;
4
5
use Ramsey\Uuid\Uuid;
6
use Illuminate\Http\Request;
7
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
8
9
class Helper
10
{
11
    /**
12
     * Generate a Gravatar URL.
13
     *
14
     * @see https://gravatar.com/site/implement/images/
15
     *
16
     * @param  string  $email
17
     * @param  int  $size
18
     * @param  string  $default
19
     * @param  string  $rating
20
     * @return string
21
     */
22
    public static function gravatar($email, $size = 120, $default = null, $rating = null)
23
    {
24
        if (is_null($default)) {
25
            $default = config('support.gravatar.default');
26
        }
27
28
        if (is_null($rating)) {
29
            $rating = config('support.gravatar.rating');
30
        }
31
32
        $query = http_build_query(array_filter(compact('size', 'default', 'rating')));
33
        if ($query) {
34
            $query = '?'.$query;
35
        }
36
37
        return app('url')->assetFrom(
38
            config('support.gravatar.host', 'https://www.gravatar.com/avatar'),
39
            md5(strtolower(trim($email))).$query
40
        );
41
    }
42
43
    /**
44
     * Generate a version 4 (random) UUID.
45
     *
46
     * @param  bool  $hex
47
     * @return string
48
     */
49
    public static function uuid($hex = false)
50
    {
51
        $uuid = Uuid::uuid4();
52
53
        return $hex ? $uuid->getHex() : $uuid->toString();
54
    }
55
56
    /**
57
     * Add JSON type to the "Accept" header for the current request.
58
     *
59
     * @see https://laravel-china.org/topics/3430/modify-request-headers-incomplete-raiders
60
     *
61
     * @param  callable  $determination
62
     * @param  callable  $callback
63
     * @return mixed
64
     */
65
    public static function addAcceptableJsonType($determination = null, $callback = null)
66
    {
67
        return app()->rebinding('request', function ($app, $request) use ($determination, $callback) {
68
            if (is_null($determination) || call_user_func($determination, $request)) {
69
                $accept = $request->headers->get('Accept');
70
71
                if (! str_contains($accept, ['/json', '+json'])) {
72
                    $accept = rtrim('application/json,'.$accept, ',');
73
74
                    $request->headers->set('Accept', $accept);
75
                    $request->server->set('HTTP_ACCEPT', $accept);
76
                    $_SERVER['HTTP_ACCEPT'] = $accept;
77
78
                    if ($callback) {
79
                        call_user_func($callback, $request);
80
                    }
81
                }
82
            }
83
        });
84
    }
85
86
    /**
87
     * Get file extension for MIME type.
88
     *
89
     * @param  string  $mimeType
90
     * @param  string  $prefix
91
     * @return string|null
92
     */
93
    public static function fileExtensionForMimeType($mimeType, $prefix = '')
94
    {
95
        $extension = ExtensionGuesser::getInstance()->guess($mimeType);
96
97
        if (! is_null($extension)) {
98
            if ('jpeg' == $extension) {
99
                $extension = 'jpg';
100
            }
101
102
            return $prefix.$extension;
103
        }
104
    }
105
106
    /**
107
     * Convert an iOS platform to the device model name.
108
     *
109
     * @see https://www.theiphonewiki.com/wiki/Models
110
     * @see https://support.hockeyapp.net/kb/client-integration-ios-mac-os-x-tvos/ios-device-types
111
     *
112
     * @param  string  $platform
113
     * @return string
114
     */
115
    public static function iDeviceModel($platform)
116
    {
117
        static $iDeviceModels = null;
118
119
        if (is_null($iDeviceModels)) {
120
            $iDeviceModels = [
121
                'i386' => 'Simulator',
122
                'x86_64' => 'Simulator',
123
124
                'iPhone1,1' => 'iPhone',
125
                'iPhone1,2' => 'iPhone 3G',
126
                'iPhone2,1' => 'iPhone 3GS',
127
                'iPhone3,1' => 'iPhone 4',
128
                'iPhone3,2' => 'iPhone 4',
129
                'iPhone3,3' => 'iPhone 4',
130
                'iPhone4,1' => 'iPhone 4S',
131
                'iPhone5,1' => 'iPhone 5',
132
                'iPhone5,2' => 'iPhone 5',
133
                'iPhone5,3' => 'iPhone 5c',
134
                'iPhone5,4' => 'iPhone 5c',
135
                'iPhone6,1' => 'iPhone 5s',
136
                'iPhone6,2' => 'iPhone 5s',
137
                'iPhone7,1' => 'iPhone 6 Plus',
138
                'iPhone7,2' => 'iPhone 6',
139
                'iPhone8,1' => 'iPhone 6s',
140
                'iPhone8,2' => 'iPhone 6s Plus',
141
                'iPhone8,4' => 'iPhone SE',
142
                'iPhone9,1' => 'iPhone 7',
143
                'iPhone9,2' => 'iPhone 7 Plus',
144
                'iPhone9,3' => 'iPhone 7',
145
                'iPhone9,4' => 'iPhone 7 Plus',
146
147
                'iPod1,1' => 'iPod touch',
148
                'iPod2,1' => 'iPod touch 2G',
149
                'iPod3,1' => 'iPod touch 3G',
150
                'iPod4,1' => 'iPod touch 4G',
151
                'iPod5,1' => 'iPod touch 5G',
152
                'iPod7,1' => 'iPod touch 6G',
153
154
                'iPad1,1' => 'iPad',
155
                'iPad2,1' => 'iPad 2',
156
                'iPad2,2' => 'iPad 2',
157
                'iPad2,3' => 'iPad 2',
158
                'iPad2,4' => 'iPad 2',
159
                'iPad2,5' => 'iPad mini',
160
                'iPad2,6' => 'iPad mini',
161
                'iPad2,7' => 'iPad mini',
162
                'iPad3,1' => 'iPad 3',
163
                'iPad3,2' => 'iPad 3',
164
                'iPad3,3' => 'iPad 3',
165
                'iPad3,4' => 'iPad 4',
166
                'iPad3,5' => 'iPad 4',
167
                'iPad3,6' => 'iPad 4',
168
                'iPad4,1' => 'iPad Air',
169
                'iPad4,2' => 'iPad Air',
170
                'iPad4,3' => 'iPad Air',
171
                'iPad4,4' => 'iPad mini 2',
172
                'iPad4,5' => 'iPad mini 2',
173
                'iPad4,6' => 'iPad mini 2',
174
                'iPad4,7' => 'iPad mini 3',
175
                'iPad4,8' => 'iPad mini 3',
176
                'iPad4,9' => 'iPad mini 3',
177
                'iPad5,1' => 'iPad mini 4',
178
                'iPad5,2' => 'iPad mini 4',
179
                'iPad5,3' => 'iPad Air 2',
180
                'iPad5,4' => 'iPad Air 2',
181
                'iPad6,3' => 'iPad Pro',
182
                'iPad6,4' => 'iPad Pro',
183
                'iPad6,7' => 'iPad Pro',
184
                'iPad6,8' => 'iPad Pro',
185
186
                'AppleTV2,1' => 'Apple TV 2G',
187
                'AppleTV3,1' => 'Apple TV 3G',
188
                'AppleTV3,2' => 'Apple TV 3G',
189
                'AppleTV5,3' => 'Apple TV 4G',
190
191
                'Watch1,1' => 'Apple Watch',
192
                'Watch1,2' => 'Apple Watch',
193
                'Watch2,6' => 'Apple Watch Series 1',
194
                'Watch2,7' => 'Apple Watch Series 1',
195
                'Watch2,3' => 'Apple Watch Series 2',
196
                'Watch2,4' => 'Apple Watch Series 2',
197
            ];
198
        }
199
200
        return isset($iDeviceModels[$platform]) ? $iDeviceModels[$platform] : $platform;
201
    }
202
203
    /**
204
     * Get the mail homepage.
205
     *
206
     * @param  string  $address
207
     * @return string|null
208
     */
209
    public static function mailHomepage($address)
210
    {
211
        if (preg_match('#@([a-z0-9.-]+)#i', $address, $match)) {
212
            $list = [
213
                'qq.com' => 'https://mail.qq.com',
214
                'vip.qq.com' => 'https://mail.qq.com',
215
                '126.com' => 'http://www.126.com',
216
                'gmail.com' => 'https://mail.google.com',
217
                '139.com' => 'http://mail.10086.cn',
218
                'wo.cn' => 'http://mail.wo.com.cn',
219
                'sina.com' => 'http://mail.sina.com.cn',
220
                'sina.cn' => 'http://mail.sina.com.cn',
221
                'vip.sina.com' => 'http://mail.sina.com.cn',
222
            ];
223
224
            $domain = strtolower($match[1]);
225
226
            return isset($list[$domain]) ? $list[$domain] : 'http://mail.'.$domain;
227
        }
228
    }
229
230
    /**
231
     * Encrypt ASCII string via XOR.
232
     *
233
     * @param  string  $text
234
     * @param  string|null  $key
235
     * @return string
236
     */
237
    public static function sampleEncrypt($text, $key = null)
238
    {
239
        $text = (string) $text;
240
        if (is_null($key)) {
241
            $key = app('encrypter')->getKey();
242
        }
243
244
        // 生成随机字符串
245
        $random = str_random(strlen($text));
246
247
        // 按字符拼接:随机字符串 + 随机字符串异或原文
248
        $tmp = static::sampleEncryption($text, $random, function ($a, $b) {
249
            return $b.($a ^ $b);
250
        });
251
252
        // 异或 $tmp 和 $key
253
        $result = static::sampleEncryption($tmp, $key);
254
255
        return urlsafe_base64_encode($result);
256
    }
257
258
    /**
259
     * Decrypt string via XOR.
260
     *
261
     * @param  string  $text
262
     * @param  string|null  $key
263
     * @return string
264
     */
265
    public static function sampleDecrypt($text, $key = null)
266
    {
267
        if (is_null($key)) {
268
            $key = app('encrypter')->getKey();
269
        }
270
271
        $tmp = static::sampleEncryption(urlsafe_base64_decode($text), $key);
272
        $tmpLength = strlen($tmp);
273
        $result = '';
274
        for ($i = 0; $i < $tmpLength, ($i + 1) < $tmpLength; $i += 2) {
275
            $result .= $tmp[$i] ^ $tmp[$i + 1];
276
        }
277
278
        return $result;
279
    }
280
281
    /**
282
     * Do a sample XOR encryption.
283
     *
284
     * @param  string  $text
285
     * @param  string  $key
286
     * @param  \Closure|null  $callback `($a, $b, $index)`
287
     * @return string
288
     */
289
    protected static function sampleEncryption($text, $key, $callback = null)
290
    {
291
        // 对 $text 和 $key 的每个字符进行运算。
292
        // $callback 为 null 时默认进行异或运算。
293
        // $callback 参数: 第 i 位 $text, 第 i 位 $key, 下标 i
294
        // $callback 返回 false 时,结束字符循环.
295
296
        $text = (string) $text;
297
        $key = (string) $key;
298
        $keyLength = strlen($key);
299
        if (is_null($callback)) {
300
            $callback = function ($a, $b) {
301
                return $a ^ $b;
302
            };
303
        }
304
305
        $result = '';
306
        $textLength = strlen($text);
307
        for ($i = 0; $i < $textLength; $i++) {
308
            $tmp = $callback($text[$i], $key[$i % $keyLength], $i);
309
            if (false === $tmp) {
310
                break;
311
            }
312
            $result .= $tmp;
313
        }
314
315
        return $result;
316
    }
317
318
    /**
319
     * Convert an integer to a string.
320
     * It is useful to shorten a database ID to URL keyword, e.g. 54329 to 'xkE'.
321
     *
322
     * @param  int $number
323
     * @param  string|null  $characters
324
     * @return string
325
     */
326
    public static function int2string($number, string $characters = null)
327
    {
328
        $number = (int) $number;
329
        if ($number < 0) {
330
            return '';
331
        }
332
333
        if (is_null($characters)) {
334
            $characters = config('support.int2string');
335
        }
336
337
        $charactersLength = strlen($characters);
338
        $string = '';
339
340
        while ($number >= $charactersLength) {
341
            $mod = (int) bcmod($number, $charactersLength);
342
            $number = (int) bcdiv($number, $charactersLength);
343
            $string = $characters[$mod].$string;
344
        }
345
346
        return $characters[$number].$string;
347
    }
348
349
    /**
350
     * Convert an `int2string` generated string back to an integer.
351
     *
352
     * @param  string  $string
353
     * @param  string|null  $characters
354
     * @return int
355
     */
356
    public static function string2int($string, string $characters = null)
357
    {
358
        $string = strrev($string);
359
        $stringLength = strlen($string);
360
361
        if (is_null($characters)) {
362
            $characters = config('support.int2string');
363
        }
364
        $charactersLength = strlen($characters);
365
366
        $number = 0;
367
        for ($i = 0; $i < $stringLength; $i++) {
368
            $index = strpos($characters, $string[$i]);
369
            $number = (int) bcadd($number, bcmul($index, bcpow($charactersLength, $i)));
370
        }
371
372
        return $number;
373
    }
374
}
375