Passed
Push — master ( 4f5b3b...1c5d75 )
by Darko
09:48
created

GetNzbController   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 27
eloc 84
c 0
b 0
f 0
dl 0
loc 160
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
F getNzb() 0 153 27
1
<?php
2
3
namespace App\Http\Controllers;
4
5
use App\Models\Release;
6
use App\Models\User;
7
use App\Models\UserDownload;
8
use App\Models\UsersRelease;
9
use Blacklight\NZB;
10
use Blacklight\utility\Utility;
11
use Illuminate\Http\Request;
12
use Illuminate\Support\Facades\File;
13
use Illuminate\Support\Facades\Log;
14
15
class GetNzbController extends BasePageController
16
{
17
    /**
18
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Foundation\Application|\Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\STS\ZipStream\ZipStream|\Symfony\Component\HttpFoundation\StreamedResponse
19
     *
20
     * @throws \Exception
21
     */
22
    public function getNzb(Request $request, $guid = null)
23
    {
24
25
        // If guid is passed as URL parameter, merge it into request as 'id'
26
        if ($guid !== null && ! $request->has('id')) {
27
            $request->merge(['id' => $guid]);
28
        }
29
30
        // Page is accessible only by the rss token, or logged in users.
31
        if ($request->user()) {
32
            $uid = $this->userdata->id;
33
            $userName = $this->userdata->username;
34
            $maxDownloads = $this->userdata->role->downloadrequests;
0 ignored issues
show
Bug introduced by
The property downloadrequests does not seem to exist on Spatie\Permission\Models\Role.
Loading history...
35
            $rssToken = $this->userdata->api_token;
36
            if ($this->userdata->hasRole('Disabled')) {
37
                return Utility::showApiError(101);
38
            }
39
        } else {
40
            if ($request->missing('r')) {
41
                return Utility::showApiError(200);
42
            }
43
44
            $res = User::getByRssToken($request->input('r'));
45
            if (! $res) {
46
                return Utility::showApiError(100);
47
            }
48
49
            $uid = $res['id'];
50
            $userName = $res->username;
51
            $rssToken = $res['api_token'];
52
            $maxDownloads = $res->role->downloadrequests;
53
            if ($res->hasRole('Disabled')) {
54
                return Utility::showApiError(101);
55
            }
56
        }
57
58
        // Check download limit on user role.
59
        $requests = UserDownload::getDownloadRequests($uid);
60
        if ($requests > $maxDownloads) {
61
            return Utility::showApiError(501);
62
        }
63
64
        if (! $request->input('id')) {
65
            return Utility::showApiError(200, 'Parameter id is required');
66
        }
67
68
        // Remove any suffixed id with .nzb which is added to help weblogging programs see nzb traffic.
69
        $request->merge(['id' => str_ireplace('.nzb', '', $request->input('id'))]);
70
71
        // User requested a zip of guid,guid,guid releases.
72
        if ($request->has('zip') && $request->input('zip') === '1') {
73
            $guids = explode(',', $request->input('id'));
74
            if ($requests + \count($guids) > $maxDownloads) {
75
                return Utility::showApiError(501);
76
            }
77
78
            $zip = getStreamingZip($guids);
79
            if ($zip !== '') {
0 ignored issues
show
introduced by
The condition $zip !== '' is always true.
Loading history...
80
                User::incrementGrabs($uid, \count($guids));
81
                foreach ($guids as $guid) {
82
                    Release::updateGrab($guid);
83
                    UserDownload::addDownloadRequest($uid, $guid);
84
85
                    if ($request->has('del') && (int) $request->input('del') === 1) {
86
                        UsersRelease::delCartByUserAndRelease($guid, $uid);
87
                    }
88
                }
89
90
                Log::channel('zipped')->info('User '.$userName.' downloaded zipped files from site with IP: '.$request->ip());
91
92
                return $zip;
93
            }
94
95
            return response()->json(['message' => 'Unable to create .zip file'], 404);
96
        }
97
98
        $nzbPath = (new NZB)->getNZBPath($request->input('id'));
99
100
        if (! File::exists($nzbPath)) {
101
            return Utility::showApiError(300, 'NZB file not found!');
102
        }
103
104
        $relData = Release::getByGuid($request->input('id'));
105
        if ($relData === null) {
106
            return Utility::showApiError(300, 'Release not found!');
107
        }
108
109
        // Update release and user actions
110
        Release::updateGrab($request->input('id'));
111
        UserDownload::addDownloadRequest($uid, $relData['id']);
112
        User::incrementGrabs($uid);
113
114
        if ($request->has('del') && (int) $request->input('del') === 1) {
115
            UsersRelease::delCartByUserAndRelease($request->input('id'), $uid);
116
        }
117
118
        // Build headers
119
        $headers = [
120
            'Content-Type' => 'application/x-nzb',
121
            'Expires' => now()->addYear()->toRfc7231String(),
122
            'X-DNZB-Failure' => url('/failed').'?guid='.$request->input('id').'&userid='.$uid.'&api_token='.$rssToken,
123
            'X-DNZB-Category' => e($relData['category_name']), // Escape category name
124
            'X-DNZB-Details' => url('/details/'.$request->input('id')),
125
        ];
126
127
        if (! empty($relData['imdbid']) && $relData['imdbid'] > 0) {
128
            $headers['X-DNZB-MoreInfo'] = 'http://www.imdb.com/title/tt'.$relData['imdbid'];
129
        } elseif (! empty($relData['tvdb']) && $relData['tvdb'] > 0) {
130
            $headers['X-DNZB-MoreInfo'] = 'http://www.thetvdb.com/?tab=series&id='.$relData['tvdb'];
131
        }
132
133
        if ((int) $relData['nfostatus'] === 1) {
134
            $headers['X-DNZB-NFO'] = url('/nfo/'.$request->input('id'));
135
        }
136
137
        $headers += ['X-DNZB-RCode' => '200',
138
            'X-DNZB-RText' => 'OK, NZB content follows.', ];
139
140
        // Raising this value may increase performance
141
        $buffer_size = 1000000;
142
        $bytes = '696';
143
144
        // Open our file (in binary mode)
145
        $zd = gzopen($nzbPath, 'rb');
146
147
        $insert = '    <file poster="[email protected]'.$uid.'" date="'.now()->timestamp.'" subject="&quot;release.nfo&quot; yEnc (1/1) 546">
148
		<groups>
149
			<group>alt.binaries.test</group>
150
		</groups>
151
		<segments>
152
			<segment bytes="'.$bytes.'" number="1">[email protected]</segment>
153
		</segments>
154
	</file>';
155
156
        $final = '';
157
        // Keep repeating until the end of the input file
158
        while (! gzeof($zd)) {
159
            // Read buffer-size bytes
160
            $contents = gzread($zd, $buffer_size);
161
            $tmp = preg_replace('/file poster=\"/i', 'file poster="'.$uid.'-', $contents, 10);
162
            $final .= $tmp;
163
        }
164
165
        $final = preg_replace('/<\/nzb>/i', $insert.PHP_EOL.'</nzb>'.PHP_EOL, $final, 1);
166
167
        gzclose($zd);
168
169
        // Sanitize file name
170
        $cleanName = str_replace([',', ' ', '/', '\\'], '_', $relData['searchname']);
171
172
        return response()->streamDownload(function () use ($final) {
173
            echo $final;
174
        }, $cleanName.'.nzb', $headers);
175
    }
176
}
177