summaryrefslogtreecommitdiff
path: root/public/upload.php
blob: 9eecf304c89ec225b8ddd62a5c20289f1780439a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/../config.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/utils.php';

if ($_SERVER['REQUEST_METHOD'] != 'POST') {
    json_response(null, 'Method not allowed', 405);
    exit;
}

if (!is_dir(FILE_DIRECTORY) && !mkdir(FILE_DIRECTORY, 0777, true)) {
    json_response(null, 'Failed to create a directory for user files', 500);
    exit();
}

try {
    $url = isset($_POST['url']) ? $_POST['url'] ?: null : null;
    $file = isset($_FILES['file']) ? $_FILES['file'] ?: null : null;
    if (empty($file['tmp_name'])) {
        $file = null;
    }
    $paste = isset($_POST['paste']) ? $_POST['paste'] ?: null : null;
    $file_data = null;

    if (!(isset($file) ^ isset($url) ^ isset($paste)) || (isset($file) && isset($url) && isset($paste))) {
        throw new RuntimeException('You can upload only one type of content: file, URL or text');
    }

    if (FILEEXT_ENABLED && isset($url) && !empty($url)) {
        $output = [];
        exec('yt-dlp -f "worst" --get-filename -o "%(filesize_approx)s %(ext)s %(duration)s" ' . escapeshellarg($url) . '', $output);
        if (empty($output)) {
            throw new RuntimeException('Bad URL');
        }

        $output = explode(' ', $output[0]);

        // TODO: some videos don't have duration
        $duration = intval($output[2]);
        if ($duration > FILEEXT_MAX_DURATION) {
            throw new RuntimeException(sprintf("File must be under %d minutes", FILEEXT_MAX_DURATION / 60));
        }

        if (!array_key_exists($output[1], FILE_ACCEPTED_MIME_TYPES)) {
            throw new RuntimeException("Unsupported extension: {$output[1]}");
        }

        $file_data = [
            'size' => intval($output[0]),
            'mime' => FILE_ACCEPTED_MIME_TYPES[$output[1]],
            'extension' => $output[1]
        ];
    } else if (isset($paste)) {
        $file_data = [
            'size' => strlen($paste),
            'mime' => 'text/plain',
            'extension' => 'txt'
        ];
    } else if (isset($file)) {
        if (
            !isset($file['error']) ||
            is_array($file['error'])
        ) {
            throw new RuntimeException('Invalid parameters.');
        }

        // checking file error
        switch ($file['error']) {
            case UPLOAD_ERR_OK:
                break;
            case UPLOAD_ERR_NO_FILE:
                throw new RuntimeException('No file sent.');
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                throw new RuntimeException('Exceeded filesize limit.');
            default:
                throw new RuntimeException('Unknown errors.');
        }

        // checking file mimetype
        $finfo = new finfo(FILEINFO_MIME_TYPE);
        if (false === $file_ext = array_search($finfo->file($file['tmp_name']), FILE_ACCEPTED_MIME_TYPES, true)) {
            throw new RuntimeException("Invalid file format.");
        }

        $file_data = [
            'size' => $file['size'],
            'mime' => FILE_ACCEPTED_MIME_TYPES[$file_ext],
            'extension' => $file_ext
        ];
    }

    if (!$file_data) {
        throw new RuntimeException('No URL or file specified');
    }

    $file_id = generate_random_char_sequence(FILE_ID_CHARACTERS, FILE_ID_LENGTH);
    $file_data['id'] = $file_id;

    if (isset($url)) {
        $result = 0;
        $output = [];

        exec(sprintf(
            'yt-dlp -f "worst" -o "%s/%s.%s" %s 2>&1',
            FILE_DIRECTORY,
            $file_id,
            $file_data['extension'],
            escapeshellarg($url)
        ), $output, $result);

        if ($result != 0) {
            error_log(sprintf("Failed to download a file (URL: %s): %s", $url, implode('\n', $output)));
            throw new RuntimeException('Failed to download a file! Try again later.');
        }
    } else if (isset($paste) && !file_put_contents(FILE_DIRECTORY . sprintf('/%s.%s', $file_id, $file_data['extension']), $paste)) {
        throw new RuntimeException('Failed to paste a text! Try again later.');
    } else if (isset($file) && !move_uploaded_file($file['tmp_name'], FILE_DIRECTORY . sprintf('/%s.%s', $file_id, $file_data['extension']))) {
        throw new RuntimeException("Failed to save the file. Try again later.");
    }

    json_response($file_data, null, 201);
} catch (RuntimeException $e) {
    json_response(null, $e->getMessage(), 400);
}