34341c250bb451c981b891750382d8a84c5f488c
[WebKit-https.git] / Websites / perf.webkit.org / public / include / uploaded-file-helpers.php
1 <?php
2
3 define('MEGABYTES', 1024 * 1024);
4
5 function format_uploaded_file($file_row)
6 {
7     return array(
8         'id' => $file_row['file_id'],
9         'size' => $file_row['file_size'],
10         'createdAt' => Database::to_js_time($file_row['file_created_at']),
11         'mime' => $file_row['file_mime'],
12         'filename' => $file_row['file_filename'],
13         'extension' => $file_row['file_extension'],
14         'author' => $file_row['file_author'],
15         'sha256' => $file_row['file_sha256']);
16 }
17
18 function uploaded_file_path_for_row($file_row)
19 {
20     return config_path('uploadDirectory', $file_row['file_id'] . $file_row['file_extension']);
21 }
22
23 function validate_uploaded_file($field_name)
24 {
25     if (array_get($_SERVER, 'CONTENT_LENGTH') && empty($_POST) && empty($_FILES))
26         exit_with_error('FileSizeLimitExceeded');
27
28     if (!is_dir(config_path('uploadDirectory', '')))
29         exit_with_error('NotSupported');
30
31     $input_file = array_get($_FILES, $field_name);
32     if (!$input_file)
33         exit_with_error('NoFileSpecified');
34
35     if ($input_file['error'] == UPLOAD_ERR_INI_SIZE || $input_file['error'] == UPLOAD_ERR_FORM_SIZE)
36         exit_with_error('FileSizeLimitExceeded');
37
38     if ($input_file['error'] != UPLOAD_ERR_OK)
39         exit_with_error('FailedToUploadFile', array('name' => $input_file['name'], 'error' => $input_file['error']));
40
41     if (config('uploadFileLimitInMB') * MEGABYTES < $input_file['size'])
42         exit_with_error('FileSizeLimitExceeded');
43
44     return $input_file;
45 }
46
47 function query_total_file_size($db, $user)
48 {
49     if ($user)
50         $count_result = $db->query_and_fetch_all('SELECT sum(file_size) as "sum" FROM uploaded_files WHERE file_deleted_at IS NULL AND file_author = $1', array($user));
51     else
52         $count_result = $db->query_and_fetch_all('SELECT sum(file_size) as "sum" FROM uploaded_files WHERE file_deleted_at IS NULL AND file_author IS NULL');
53     if (!$count_result)
54         return FALSE;
55     return intval($count_result[0]["sum"]);
56 }
57
58 function create_uploaded_file_from_form_data($input_file)
59 {
60     $file_sha256 = hash_file('sha256', $input_file['tmp_name']);
61     if (!$file_sha256)
62         exit_with_error('FailedToComputeSHA256');
63
64     $matches = array();
65     $file_extension = null;
66     if (preg_match('/(\.[a-zA-Z0-9]{1,5}){1,2}$/', $input_file['name'], $matches)) {
67         $file_extension = $matches[0];
68         assert(strlen($file_extension) <= 16);
69     }
70
71     return array(
72         'author' => remote_user_name(),
73         'filename' => $input_file['name'],
74         'extension' => $file_extension,
75         'mime' => $input_file['type'], // Sanitize MIME types.
76         'size' => $input_file['size'],
77         'sha256' => $file_sha256
78     );
79 }
80
81 function upload_file_in_transaction($db, $input_file, $remote_user, $additional_work = NULL)
82 {
83     // FIXME: Cleanup old files.
84
85     if (config('uploadUserQuotaInMB') * MEGABYTES - query_total_file_size($db, $remote_user) < $input_file['size'])
86         exit_with_error('FileSizeQuotaExceeded');
87
88     $uploaded_file = create_uploaded_file_from_form_data($input_file);
89
90     $db->begin_transaction();
91     $file_row = $db->select_or_insert_row('uploaded_files', 'file',
92         array('sha256' => $uploaded_file['sha256'], 'deleted_at' => null), $uploaded_file, '*');
93     if (!$file_row)
94         exit_with_error('FailedToInsertFileData');
95
96     // A concurrent session may have inserted another file.
97     if (config('uploadUserQuotaInMB') * MEGABYTES < query_total_file_size($db, $remote_user)) {
98         $db->rollback_transaction();
99         exit_with_error('FileSizeQuotaExceeded');
100     }
101
102     if ($additional_work) {
103         $error = $additional_work($db, $file_row);
104         if ($error) {
105             $db->rollback_transaction();
106             exit_with_error($error['status'], $error);
107         }
108     }
109
110     $new_path = uploaded_file_path_for_row($file_row);
111     if (!move_uploaded_file($input_file['tmp_name'], $new_path)) {
112         $db->rollback_transaction();
113         exit_with_error('FailedToMoveUploadedFile');
114     }
115
116     $db->commit_transaction();
117
118     return format_uploaded_file($file_row);
119 }
120
121 ?>