Issues (435)

app/Http/Controllers/GetNzbController.php (3 issues)

Labels
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
14
class GetNzbController extends BasePageController
15
{
16
    /**
17
     * @throws \Exception
18
     */
19
    public function getNzb(Request $request, $guid = null)
20
    {
21
22
        // If guid is passed as URL parameter, merge it into request as 'id'
23
        if ($guid !== null && ! $request->has('id')) {
24
            $request->merge(['id' => $guid]);
25
        }
26
27
        // Page is accessible only by the rss token, or logged in users.
28
        if ($request->user()) {
29
            $uid = $this->userdata->id;
30
            $maxDownloads = $this->userdata->role->downloadrequests;
0 ignored issues
show
The property downloadrequests does not seem to exist on Spatie\Permission\Models\Role.
Loading history...
31
            $rssToken = $this->userdata->api_token;
32
            if ($this->userdata->hasRole('Disabled')) {
33
                return Utility::showApiError(101);
34
            }
35
        } else {
36
            if ($request->missing('r')) {
37
                return Utility::showApiError(200);
38
            }
39
40
            $res = User::getByRssToken($request->input('r'));
41
            if (! $res) {
42
                return Utility::showApiError(100);
43
            }
44
45
            $uid = $res['id'];
46
            $rssToken = $res['api_token'];
47
            $maxDownloads = $res->role->downloadrequests;
48
            if ($res->hasRole('Disabled')) {
49
                return Utility::showApiError(101);
50
            }
51
        }
52
53
        // Check download limit on user role.
54
        $requests = UserDownload::getDownloadRequests($uid);
55
        if ($requests > $maxDownloads) {
56
            return Utility::showApiError(501);
57
        }
58
59
        if (! $request->input('id')) {
60
            return Utility::showApiError(200, 'Parameter id is required');
61
        }
62
63
        // Remove any suffixed id with .nzb which is added to help weblogging programs see nzb traffic.
64
        $request->merge(['id' => str_ireplace('.nzb', '', $request->input('id'))]);
65
66
        // User requested a zip of guid,guid,guid releases.
67
        if ($request->has('zip') && $request->input('zip') === '1') {
68
            $guids = explode(',', $request->input('id'));
69
            if ($requests + \count($guids) > $maxDownloads) {
70
                return Utility::showApiError(501);
71
            }
72
73
            $zip = getStreamingZip($guids);
74
            if ($zip !== '') {
75
                User::incrementGrabs($uid, \count($guids));
76
                foreach ($guids as $guid) {
77
                    Release::updateGrab($guid);
78
                    UserDownload::addDownloadRequest($uid, $guid);
79
80
                    if ($request->has('del') && (int) $request->input('del') === 1) {
81
                        UsersRelease::delCartByUserAndRelease($guid, $uid);
82
                    }
83
                }
84
85
                return $zip;
86
            }
87
88
            return response()->json(['message' => 'Unable to create .zip file'], 404);
89
        }
90
91
        $nzbPath = (new NZB)->getNZBPath($request->input('id'));
92
93
        if (! File::exists($nzbPath)) {
94
            return Utility::showApiError(300, 'NZB file not found!');
95
        }
96
97
        $relData = Release::getByGuid($request->input('id'));
98
        if ($relData === null) {
99
            return Utility::showApiError(300, 'Release not found!');
100
        }
101
102
        // Update release and user actions
103
        Release::updateGrab($request->input('id'));
104
        UserDownload::addDownloadRequest($uid, $relData['id']);
105
        User::incrementGrabs($uid);
106
107
        if ($request->has('del') && (int) $request->input('del') === 1) {
108
            UsersRelease::delCartByUserAndRelease($request->input('id'), $uid);
109
        }
110
111
        // Build headers
112
        $headers = [
113
            'Content-Type' => 'application/x-nzb',
114
            'Expires' => now()->addYear()->toRfc7231String(),
115
            'X-DNZB-Failure' => url('/failed').'?guid='.$request->input('id').'&userid='.$uid.'&api_token='.$rssToken,
116
            'X-DNZB-Category' => e($relData['category_name']), // Escape category name
117
            'X-DNZB-Details' => url('/details/'.$request->input('id')),
118
        ];
119
120
        if (! empty($relData['imdbid']) && $relData['imdbid'] > 0) {
121
            $headers['X-DNZB-MoreInfo'] = 'http://www.imdb.com/title/tt'.$relData['imdbid'];
122
        } elseif (! empty($relData['tvdb']) && $relData['tvdb'] > 0) {
123
            $headers['X-DNZB-MoreInfo'] = 'http://www.thetvdb.com/?tab=series&id='.$relData['tvdb'];
124
        }
125
126
        if ((int) $relData['nfostatus'] === 1) {
127
            $headers['X-DNZB-NFO'] = url('/nfo/'.$request->input('id'));
128
        }
129
130
        $headers['X-DNZB-RCode'] = '200';
131
        $headers['X-DNZB-RText'] = 'OK, NZB content follows.';
132
133
        // Sanitize file name
134
        $cleanName = str_replace([',', ' ', '/', '\\'], '_', $relData['searchname']);
135
136
        // Stream the file content
137
        return response()->streamDownload(function () use ($nzbPath) {
138
            $bufferSize = 1000000; // 1 MB chunks
139
            $gz = gzopen($nzbPath, 'rb');
140
141
            if (! $gz) {
0 ignored issues
show
$gz is of type resource, thus it always evaluated to false.
Loading history...
142
                throw new RuntimeException('Failed to open gzipped file for streaming.');
0 ignored issues
show
The type App\Http\Controllers\RuntimeException was not found. Did you mean RuntimeException? If so, make sure to prefix the type with \.
Loading history...
143
            }
144
145
            while (! gzeof($gz)) {
146
                echo gzread($gz, $bufferSize);
147
                flush(); // Ensure chunks are sent immediately
148
            }
149
150
            gzclose($gz);
151
        }, $cleanName.'.nzb', $headers);
152
    }
153
}
154