| 1 | <?php |
|---|
| 2 | /** |
|---|
| 3 | * copyright 2011 Stephen Just <stephenjust@users.sf.net> |
|---|
| 4 | * |
|---|
| 5 | * This file is part of stkaddons |
|---|
| 6 | * |
|---|
| 7 | * stkaddons is free software: you can redistribute it and/or modify |
|---|
| 8 | * it under the terms of the GNU General Public License as published by |
|---|
| 9 | * the Free Software Foundation, either version 3 of the License, or |
|---|
| 10 | * (at your option) any later version. |
|---|
| 11 | * |
|---|
| 12 | * stkaddons is distributed in the hope that it will be useful, |
|---|
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | * GNU General Public License for more details. |
|---|
| 16 | * |
|---|
| 17 | * You should have received a copy of the GNU General Public License |
|---|
| 18 | * along with stkaddons. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 19 | */ |
|---|
| 20 | |
|---|
| 21 | function parseUpload($file,$revision = false) |
|---|
| 22 | { |
|---|
| 23 | if (!is_array($file)) |
|---|
| 24 | throw new UploadException(htmlspecialchars(_('Failed to upload your file.'))); |
|---|
| 25 | |
|---|
| 26 | // Check for file upload errors |
|---|
| 27 | $upload_error = file_upload_error($file); |
|---|
| 28 | if ($upload_error !== false) |
|---|
| 29 | throw new UploadException($upload_error); |
|---|
| 30 | |
|---|
| 31 | // This won't be set when uploading addons/revisions |
|---|
| 32 | if (!isset($_POST['upload-type'])) $_POST['upload-type'] = NULL; |
|---|
| 33 | |
|---|
| 34 | // Check file-extension for uploaded file |
|---|
| 35 | $fileext = check_extension($file['name'], $_POST['upload-type']); |
|---|
| 36 | |
|---|
| 37 | // Generate a unique file name for the uploaded file |
|---|
| 38 | $fileid = uniqid(true); |
|---|
| 39 | |
|---|
| 40 | // Set upload directory |
|---|
| 41 | if ($_POST['upload-type'] == 'image') |
|---|
| 42 | $file_dir = 'images/'; |
|---|
| 43 | else |
|---|
| 44 | $file_dir = NULL; |
|---|
| 45 | |
|---|
| 46 | // Make sure file at this path doesn't already exist |
|---|
| 47 | while (file_exists(UP_LOCATION.$file_dir.$fileid.'.'.$fileext)) |
|---|
| 48 | $fileid = uniqid(); |
|---|
| 49 | |
|---|
| 50 | // Handle image uploads |
|---|
| 51 | if ($_POST['upload-type'] == 'image') |
|---|
| 52 | { |
|---|
| 53 | if (!move_uploaded_file($file['tmp_name'],UP_LOCATION.'images/'.$fileid.'.'.$fileext)) |
|---|
| 54 | throw new UploadException(htmlspecialchars(_('Failed to move uploaded file.'))); |
|---|
| 55 | |
|---|
| 56 | // Add database record for image |
|---|
| 57 | $addon_id = Addon::cleanId($_GET['name']); |
|---|
| 58 | $addon_type = mysql_real_escape_string($_GET['type']); |
|---|
| 59 | $newImageQuery = 'CALL `'.DB_PREFIX.'create_file_record` '. |
|---|
| 60 | "('$addon_id','$addon_type','image','images/$fileid.$fileext',@a)"; |
|---|
| 61 | $newImageHandle = sql_query($newImageQuery); |
|---|
| 62 | if (!$newImageHandle) |
|---|
| 63 | { |
|---|
| 64 | unlink(UP_LOCATION.'images/'.$fileid.'.'.$fileext); |
|---|
| 65 | throw new UploadException(htmlspecialchars(_('Failed to associate image file with addon.'))); |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | echo htmlspecialchars(_('Successfully uploaded image.')).'<br />'; |
|---|
| 69 | echo '<span style="font-size: large"><a href="addons.php?type='.$_GET['type'].'&name='.$_GET['name'].'">'.htmlspecialchars(_('Continue.')).'</a></span><br />'; |
|---|
| 70 | return true; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | // Move the archive to a working directory |
|---|
| 74 | mkdir(UP_LOCATION.'temp/'.$fileid); |
|---|
| 75 | if (!move_uploaded_file($file['tmp_name'],UP_LOCATION.'temp/'.$fileid.'/'.$fileid.'.'.$fileext)) |
|---|
| 76 | throw new UploadException(htmlspecialchars(_('Failed to move uploaded file.'))); |
|---|
| 77 | |
|---|
| 78 | // Extract archive |
|---|
| 79 | if (!extract_archive(UP_LOCATION.'temp/'.$fileid.'/'.$fileid.'.'.$fileext, |
|---|
| 80 | UP_LOCATION.'temp/'.$fileid.'/', |
|---|
| 81 | $fileext)) |
|---|
| 82 | { |
|---|
| 83 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | // Find XML file |
|---|
| 87 | if ($_POST['upload-type'] != 'source') |
|---|
| 88 | { |
|---|
| 89 | $xml_file = find_xml(UP_LOCATION.'temp/'.$fileid); |
|---|
| 90 | $xml_dir = dirname($xml_file); |
|---|
| 91 | if (!$xml_file) { |
|---|
| 92 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 93 | throw new UploadException(htmlspecialchars(_('Invalid archive file. The archive must contain the addon\'s xml file.'))); |
|---|
| 94 | } |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | // Check for invalid files |
|---|
| 98 | if ($_POST['upload-type'] != 'source') |
|---|
| 99 | $invalid_files = type_check($xml_dir); |
|---|
| 100 | else |
|---|
| 101 | { |
|---|
| 102 | $xml_dir = UP_LOCATION.'temp/'.$fileid; |
|---|
| 103 | $invalid_files = type_check($xml_dir, true); |
|---|
| 104 | } |
|---|
| 105 | if (is_array($invalid_files) && count($invalid_files != 0)) |
|---|
| 106 | { |
|---|
| 107 | echo '<span class="warning">'.htmlspecialchars(_('Some invalid files were found in the uploaded add-on. These files have been removed from the archive:')).' '.implode(', ',$invalid_files).'</span><br />'; |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | if ($_POST['upload-type'] != 'source') |
|---|
| 111 | { |
|---|
| 112 | // Define addon type |
|---|
| 113 | if (preg_match('/kart\.xml$/',$xml_file)) |
|---|
| 114 | { |
|---|
| 115 | $addon_type = 'karts'; |
|---|
| 116 | echo htmlspecialchars(_('Upload was recognized as a kart.')).'<br />'; |
|---|
| 117 | } |
|---|
| 118 | else |
|---|
| 119 | { |
|---|
| 120 | $addon_type = 'tracks'; |
|---|
| 121 | echo htmlspecialchars(_('Upload was recognized as a track.')).'<br />'; |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | // Read XML |
|---|
| 125 | $parsed_xml = read_xml($xml_file,$addon_type); |
|---|
| 126 | if (!$parsed_xml) |
|---|
| 127 | { |
|---|
| 128 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 129 | throw new UploadException(htmlspecialchars(_('Failed to read the add-on\'s XML file. Please make sure you are using the latest version of the kart or track exporter.'))); |
|---|
| 130 | } |
|---|
| 131 | // Write new XML file |
|---|
| 132 | $fhandle = fopen($xml_file,'w'); |
|---|
| 133 | if (!fwrite($fhandle,$parsed_xml['xml'])) { |
|---|
| 134 | echo '<span class="error">'.htmlspecialchars(_('Failed to write new XML file:')).'</span><br />'; |
|---|
| 135 | } |
|---|
| 136 | fclose($fhandle); |
|---|
| 137 | |
|---|
| 138 | // Handle arenas |
|---|
| 139 | if ($parsed_xml['attributes']['arena'] == 'Y') { |
|---|
| 140 | echo htmlspecialchars(_('This track is an arena.')).'<br />'; |
|---|
| 141 | $addon_type = 'arenas'; |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | // Check for valid license file |
|---|
| 145 | $license_file = find_license(UP_LOCATION.'temp/'.$fileid); |
|---|
| 146 | if ($license_file === false) |
|---|
| 147 | { |
|---|
| 148 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 149 | throw new UploadException(htmlspecialchars(_('A valid License.txt file was not found. Please add a License.txt file to your archive and re-submit it.'))); |
|---|
| 150 | } |
|---|
| 151 | $parsed_xml['attributes']['license'] = $license_file; |
|---|
| 152 | |
|---|
| 153 | // Get addon id |
|---|
| 154 | $addon_id = NULL; |
|---|
| 155 | if (isset($_GET['name'])) |
|---|
| 156 | $addon_id = Addon::cleanId($_GET['name']); |
|---|
| 157 | if (!preg_match('/^[a-z0-9\-]+_?[0-9]*$/i',$addon_id) || $addon_id == NULL) |
|---|
| 158 | $addon_id = Addon::generateId($addon_type,$parsed_xml['attributes']['name']); |
|---|
| 159 | |
|---|
| 160 | // Save addon icon or screenshot |
|---|
| 161 | if ($addon_type == 'karts') |
|---|
| 162 | { |
|---|
| 163 | $image_file = $xml_dir.'/'.$parsed_xml['attributes']['icon-file']; |
|---|
| 164 | } |
|---|
| 165 | else |
|---|
| 166 | { |
|---|
| 167 | $image_file = $xml_dir.'/'.$parsed_xml['attributes']['screenshot']; |
|---|
| 168 | } |
|---|
| 169 | // Check if file exists |
|---|
| 170 | if (!file_exists($image_file)) |
|---|
| 171 | { |
|---|
| 172 | $image_file = false; |
|---|
| 173 | } |
|---|
| 174 | if ($image_file !== false) { |
|---|
| 175 | // Get image file extension |
|---|
| 176 | preg_match('/\.([a-z]+)$/i',$image_file,$imageext); |
|---|
| 177 | // Save file |
|---|
| 178 | copy($image_file,UP_LOCATION.'images/'.$fileid.'.'.$imageext[1]); |
|---|
| 179 | $parsed_xml['attributes']['image'] = $fileid.'.'.$imageext[1]; |
|---|
| 180 | |
|---|
| 181 | // Record image file in database |
|---|
| 182 | $newImageQuery = 'CALL `'.DB_PREFIX.'create_file_record` '. |
|---|
| 183 | "('$addon_id','$addon_type','image','images/$fileid.{$imageext[1]}',@a)"; |
|---|
| 184 | $newImageHandle = sql_query($newImageQuery); |
|---|
| 185 | if (!$newImageHandle) |
|---|
| 186 | { |
|---|
| 187 | echo '<span class="error">'.htmlspecialchars(_('Failed to associate image file with addon.')).mysql_error().'</span><br />'; |
|---|
| 188 | unlink(UP_LOCATION.'images/'.$fileid.'.'.$imageext[1]); |
|---|
| 189 | $parsed_xml['attributes']['image'] = 0; |
|---|
| 190 | } |
|---|
| 191 | else |
|---|
| 192 | { |
|---|
| 193 | $getInsertIdQuery = 'SELECT @a'; |
|---|
| 194 | $getInsertIdHandle = sql_query($getInsertIdQuery); |
|---|
| 195 | if (!$getInsertIdHandle) $parsed_xml['attributes']['fileid'] = 0; |
|---|
| 196 | $iid_result = mysql_fetch_array($getInsertIdHandle); |
|---|
| 197 | // Get ID of previously inserted image |
|---|
| 198 | $parsed_xml['attributes']['image'] = $iid_result[0]; |
|---|
| 199 | } |
|---|
| 200 | } |
|---|
| 201 | |
|---|
| 202 | // Initialize the status flag |
|---|
| 203 | $parsed_xml['attributes']['status'] = 0; |
|---|
| 204 | |
|---|
| 205 | // Check to make sure all image dimensions are powers of 2 |
|---|
| 206 | if (!image_check($xml_dir)) |
|---|
| 207 | { |
|---|
| 208 | echo '<span class="warning">'.htmlspecialchars(_('Some images in this add-on do not have dimensions that are a power of two.')) |
|---|
| 209 | .' '.htmlspecialchars(_('This may cause display errors on some video cards.')).'</span><br />'; |
|---|
| 210 | $parsed_xml['attributes']['status'] += F_TEX_NOT_POWER_OF_2; |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | $filetype = 'addon'; |
|---|
| 214 | } |
|---|
| 215 | else |
|---|
| 216 | { |
|---|
| 217 | $addon_id = Addon::cleanId($_GET['name']); |
|---|
| 218 | $addon_type = mysql_real_escape_string($_GET['type']); |
|---|
| 219 | $filetype = 'source'; |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | // Validate addon type field |
|---|
| 223 | if (!Addon::isAllowedType($addon_type)) |
|---|
| 224 | { |
|---|
| 225 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 226 | throw new UploadException(htmlspecialchars(_('Invalid add-on type.'))); |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | // Repack zip file |
|---|
| 230 | if (!repack_zip($xml_dir,UP_LOCATION.$fileid.'.zip')) |
|---|
| 231 | { |
|---|
| 232 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 233 | throw new UploadException(htmlspecialchars(_('Failed to re-pack archive file.'))); |
|---|
| 234 | } |
|---|
| 235 | |
|---|
| 236 | // Record addon's file in database |
|---|
| 237 | $newAddonFileQuery = 'CALL `'.DB_PREFIX.'create_file_record` '. |
|---|
| 238 | "('$addon_id','$addon_type','$filetype','$fileid.zip',@a)"; |
|---|
| 239 | $newAddonFileHandle = sql_query($newAddonFileQuery); |
|---|
| 240 | if (!$newAddonFileHandle) |
|---|
| 241 | { |
|---|
| 242 | echo '<span class="error">'.htmlspecialchars(_('Failed to associate archive file with addon.')).'</span><br />'; |
|---|
| 243 | unlink(UP_LOCATION.$fileid.'.zip'); |
|---|
| 244 | if ($_POST['upload-type'] != 'source') |
|---|
| 245 | $parsed_xml['attributes']['fileid'] = 0; |
|---|
| 246 | } |
|---|
| 247 | else |
|---|
| 248 | { |
|---|
| 249 | $getInsertIdQuery = 'SELECT @a'; |
|---|
| 250 | $getInsertIdHandle = sql_query($getInsertIdQuery); |
|---|
| 251 | if (!$getInsertIdHandle) $parsed_xml['attributes']['fileid'] = 0; |
|---|
| 252 | $iid_result = mysql_fetch_array($getInsertIdHandle); |
|---|
| 253 | // Get ID of previously inserted file |
|---|
| 254 | if ($_POST['upload-type'] != 'source') |
|---|
| 255 | $parsed_xml['attributes']['fileid'] = $iid_result[0]; |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | if ($_POST['upload-type'] == 'source') |
|---|
| 259 | { |
|---|
| 260 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 261 | echo htmlspecialchars(_('Successfully uploaded source archive.')).'<br />'; |
|---|
| 262 | echo '<span style="font-size: large"><a href="addons.php?type='.$addon_type.'&name='.$addon_id.'">'.htmlspecialchars(_('Continue.')).'</a></span><br />'; |
|---|
| 263 | return true; |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | // Set first revision to be "latest" |
|---|
| 267 | if ($revision == false) |
|---|
| 268 | $parsed_xml['attributes']['status'] += F_LATEST; |
|---|
| 269 | |
|---|
| 270 | // Create addon |
|---|
| 271 | $addon = new coreAddon($addon_type); |
|---|
| 272 | |
|---|
| 273 | // Make sure only the original uploader can make a new revision |
|---|
| 274 | if ($revision == true) |
|---|
| 275 | { |
|---|
| 276 | $addon->selectById($addon_id); |
|---|
| 277 | if (!$addon->addonCurrent) |
|---|
| 278 | { |
|---|
| 279 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 280 | throw new UploadException(htmlspecialchars(_('You are trying to add a new revision of an add-on that does not exist.'))); |
|---|
| 281 | } |
|---|
| 282 | if ($_SESSION['userid'] != $addon->addonCurrent['uploader'] |
|---|
| 283 | && !$_SESSION['role']['manageaddons']) |
|---|
| 284 | { |
|---|
| 285 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 286 | throw new UploadException(htmlspecialchars(_('You do not have the necessary permissions to perform this action.'))); |
|---|
| 287 | } |
|---|
| 288 | } |
|---|
| 289 | |
|---|
| 290 | if (!$addon->addAddon($fileid,$addon_id,$parsed_xml['attributes'])) |
|---|
| 291 | { |
|---|
| 292 | echo '<span class="error">'.htmlspecialchars(_('Failed to create add-on.')).'</span><br />'; |
|---|
| 293 | } |
|---|
| 294 | rmdir_recursive(UP_LOCATION.'temp/'.$fileid); |
|---|
| 295 | writeAssetXML(); |
|---|
| 296 | writeNewsXML(); |
|---|
| 297 | echo htmlspecialchars(_('Your add-on was uploaded successfully. It will be reviewed by our moderators before becoming publicly available.')).'<br /><br />'; |
|---|
| 298 | echo '<a href="upload.php?type='.$addon_type.'&name='.$addon_id.'&action=file">'.htmlspecialchars(_('Click here to upload the sources to your add-on now.')).'</a><br />'; |
|---|
| 299 | echo htmlspecialchars(_('(Uploading the sources to your add-on enables others to improve your work and also ensure your add-on will not be lost in the future if new SuperTuxKart versions are not compatible with the current format.)')).'<br /><br />'; |
|---|
| 300 | echo '<a href="addons.php?type='.$addon_type.'&name='.$addon_id.'">'.htmlspecialchars(_('Click here to view your add-on.')).'</a><br />'; |
|---|
| 301 | } |
|---|
| 302 | |
|---|
| 303 | function check_extension($filename,$type = NULL) |
|---|
| 304 | { |
|---|
| 305 | // Check file-extension for uploaded file |
|---|
| 306 | if ($type == 'image') |
|---|
| 307 | { |
|---|
| 308 | if (!preg_match('/\.(png|jpg|jpeg)$/i',$filename,$fileext)) |
|---|
| 309 | throw new UploadException(htmlspecialchars(_('Uploaded image files must be either PNG or Jpeg files.'))); |
|---|
| 310 | } |
|---|
| 311 | else |
|---|
| 312 | { |
|---|
| 313 | // File extension must be .zip, .tgz, .tar, .tar.gz, tar.bz2, .tbz |
|---|
| 314 | if (!preg_match('/\.(zip|t[bg]z|tar|tar\.gz|tar\.bz2)$/i',$filename,$fileext)) |
|---|
| 315 | throw new UploadException(htmlspecialchars(_('The file you uploaded was not the correct type.'))); |
|---|
| 316 | } |
|---|
| 317 | return $fileext[1]; |
|---|
| 318 | } |
|---|
| 319 | |
|---|
| 320 | function extract_archive($file,$destination,$fileext = NULL) |
|---|
| 321 | { |
|---|
| 322 | if (!file_exists($file)) |
|---|
| 323 | { |
|---|
| 324 | echo '<span class="error">'.htmlspecialchars(_('The file to extract does not exist.')).'</span><br />'; |
|---|
| 325 | } |
|---|
| 326 | |
|---|
| 327 | if ($fileext == NULL) |
|---|
| 328 | $fileext = pathinfo($file, PATHINFO_EXTENSION); |
|---|
| 329 | |
|---|
| 330 | // Extract archive |
|---|
| 331 | switch ($fileext) { |
|---|
| 332 | // Handle archives using ZipArchive class |
|---|
| 333 | case 'zip': |
|---|
| 334 | $archive = new ZipArchive; |
|---|
| 335 | if (!$archive->open($file)) { |
|---|
| 336 | echo '<span class="error">'.htmlspecialchars(_('Could not open archive file. It may be corrupted.')).'</span><br />'; |
|---|
| 337 | unlink($file); |
|---|
| 338 | return false; |
|---|
| 339 | } |
|---|
| 340 | if (!$archive->extractTo($destination)) |
|---|
| 341 | { |
|---|
| 342 | echo '<span class="error">'.htmlspecialchars(_('Failed to extract archive file.')).' (zip)</span><br />'; |
|---|
| 343 | unlink($file); |
|---|
| 344 | return false; |
|---|
| 345 | } |
|---|
| 346 | $archive->close(); |
|---|
| 347 | unlink($file); |
|---|
| 348 | break; |
|---|
| 349 | |
|---|
| 350 | // Handle archives using Archive_Tar class |
|---|
| 351 | case 'tar': |
|---|
| 352 | case 'tar.gz': |
|---|
| 353 | case 'tgz': |
|---|
| 354 | case 'gz': |
|---|
| 355 | case 'tbz': |
|---|
| 356 | case 'tar.bz2': |
|---|
| 357 | case 'bz2': |
|---|
| 358 | require_once('Archive/Tar.php'); |
|---|
| 359 | $compression = NULL; |
|---|
| 360 | if ($fileext == 'tar.gz' || $fileext == 'tgz' || $fileext == 'gz') |
|---|
| 361 | { |
|---|
| 362 | $compression = 'gz'; |
|---|
| 363 | } |
|---|
| 364 | elseif ($fileext == 'tbz' || $fileext == 'tar.bz2' || $fileext == 'bz2') |
|---|
| 365 | { |
|---|
| 366 | $compression = 'bz2'; |
|---|
| 367 | } |
|---|
| 368 | $archive = new Archive_Tar($file, $compression); |
|---|
| 369 | if (!$archive) |
|---|
| 370 | { |
|---|
| 371 | echo '<span class="error">'.htmlspecialchars(_('Could not open archive file. It may be corrupted.')).'</span><br />'; |
|---|
| 372 | unlink($file); |
|---|
| 373 | return false; |
|---|
| 374 | } |
|---|
| 375 | if (!$archive->extract($destination)) |
|---|
| 376 | { |
|---|
| 377 | echo '<span class="error">'.htmlspecialchars(_('Failed to extract archive file.')).' ('.$compression.')</span><br />'; |
|---|
| 378 | unlink($file); |
|---|
| 379 | return false; |
|---|
| 380 | } |
|---|
| 381 | unlink($file); |
|---|
| 382 | break; |
|---|
| 383 | |
|---|
| 384 | default: |
|---|
| 385 | echo '<span class="error">'.htmlspecialchars(_('Unknown archive type.')).'</span><br />'; |
|---|
| 386 | unlink($file); |
|---|
| 387 | return false; |
|---|
| 388 | } |
|---|
| 389 | return true; |
|---|
| 390 | } |
|---|
| 391 | |
|---|
| 392 | function file_upload_error($upload) |
|---|
| 393 | { |
|---|
| 394 | if (!is_array($upload)) |
|---|
| 395 | { |
|---|
| 396 | return htmlspecialchars(_('Upload is invalid.')); |
|---|
| 397 | } |
|---|
| 398 | switch ($upload['error']) |
|---|
| 399 | { |
|---|
| 400 | default: |
|---|
| 401 | return htmlspecialchars(_('Unknown file upload error.')); |
|---|
| 402 | case UPLOAD_ERR_OK: |
|---|
| 403 | return false; |
|---|
| 404 | case UPLOAD_ERR_INI_SIZE: |
|---|
| 405 | return htmlspecialchars(_('Uploaded file is too large.')); |
|---|
| 406 | case UPLOAD_ERR_FORM_SIZE: |
|---|
| 407 | return htmlspecialchars(_('Uploaded file is too large.')); |
|---|
| 408 | case UPLOAD_ERR_PARTIAL: |
|---|
| 409 | return htmlspecialchars(_('Uploaded file is incomplete.')); |
|---|
| 410 | case UPLOAD_ERR_NO_FILE: |
|---|
| 411 | return htmlspecialchars(_('No file was uploaded.')); |
|---|
| 412 | case UPLOAD_ERR_NO_TMP_DIR: |
|---|
| 413 | return htmlspecialchars(_('There is no TEMP directory to store the uploaded file in.')); |
|---|
| 414 | case UPLOAD_ERR_CANT_WRITE: |
|---|
| 415 | return htmlspecialchars(_('Unable to write uploaded file to disk.')); |
|---|
| 416 | } |
|---|
| 417 | } |
|---|
| 418 | |
|---|
| 419 | function find_xml($dir) |
|---|
| 420 | { |
|---|
| 421 | if(is_dir($dir)) |
|---|
| 422 | { |
|---|
| 423 | foreach(scandir($dir) as $file) |
|---|
| 424 | { |
|---|
| 425 | if(is_dir($dir."/".$file) && $file != "." && $file != "..") |
|---|
| 426 | { |
|---|
| 427 | $name = find_xml($dir."/".$file); |
|---|
| 428 | if($name != false) |
|---|
| 429 | { |
|---|
| 430 | return $name; |
|---|
| 431 | } |
|---|
| 432 | } |
|---|
| 433 | else if(file_exists($dir."/kart.xml")) |
|---|
| 434 | { |
|---|
| 435 | return $dir."/kart.xml"; |
|---|
| 436 | } |
|---|
| 437 | else if(file_exists($dir."/track.xml")) |
|---|
| 438 | { |
|---|
| 439 | return $dir."/track.xml"; |
|---|
| 440 | } |
|---|
| 441 | } |
|---|
| 442 | } |
|---|
| 443 | return false; |
|---|
| 444 | } |
|---|
| 445 | |
|---|
| 446 | function find_license($dir) |
|---|
| 447 | { |
|---|
| 448 | if(is_dir($dir)) |
|---|
| 449 | { |
|---|
| 450 | foreach(scandir($dir) as $file) |
|---|
| 451 | { |
|---|
| 452 | // Check recursively |
|---|
| 453 | if(is_dir($dir."/".$file) && $file != "." && $file != "..") |
|---|
| 454 | { |
|---|
| 455 | $name = find_license($dir."/".$file); |
|---|
| 456 | // The file was found in a recursive lookup |
|---|
| 457 | if($name != false) |
|---|
| 458 | { |
|---|
| 459 | return $name; |
|---|
| 460 | } |
|---|
| 461 | } |
|---|
| 462 | else if(file_exists($dir.'/License.txt')) |
|---|
| 463 | { |
|---|
| 464 | return file_get_contents($dir.'/License.txt'); |
|---|
| 465 | } |
|---|
| 466 | else if (file_exists($dir.'/license.txt')) |
|---|
| 467 | { |
|---|
| 468 | return file_get_contents($dir.'/license.txt'); |
|---|
| 469 | } |
|---|
| 470 | } |
|---|
| 471 | } |
|---|
| 472 | return false; |
|---|
| 473 | } |
|---|
| 474 | |
|---|
| 475 | function read_xml($file,$type) |
|---|
| 476 | { |
|---|
| 477 | // Can't use XMLReader because we don't know the names of all our attributes |
|---|
| 478 | $reader = xml_parser_create(); |
|---|
| 479 | |
|---|
| 480 | // Remove whitespace at beginning and end of file |
|---|
| 481 | $xmlContents = trim(file_get_contents($file)); |
|---|
| 482 | // Remove amperstands (&) because they cause problems |
|---|
| 483 | $xmlContents = str_replace('& ','& ',$xmlContents); |
|---|
| 484 | |
|---|
| 485 | if (!xml_parse_into_struct($reader,$xmlContents,$vals,$index)) |
|---|
| 486 | { |
|---|
| 487 | echo 'XML Error: '.xml_error_string(xml_get_error_code($reader)).'<br />'; |
|---|
| 488 | return false; |
|---|
| 489 | } |
|---|
| 490 | |
|---|
| 491 | // Set up the XMLWriter to modify the XML file |
|---|
| 492 | $writer = new XMLWriter(); |
|---|
| 493 | $writer->openMemory(); |
|---|
| 494 | $writer->startDocument('1.0'); |
|---|
| 495 | $writer->setIndent(true); |
|---|
| 496 | $writer->setIndentString(' '); |
|---|
| 497 | |
|---|
| 498 | $groups_found = false; |
|---|
| 499 | $attributes = array(); |
|---|
| 500 | // Cycle through all of the xml file's elements |
|---|
| 501 | foreach ($vals AS $val) |
|---|
| 502 | { |
|---|
| 503 | if ($val['type'] == 'close') |
|---|
| 504 | { |
|---|
| 505 | $writer->endElement(); |
|---|
| 506 | continue; |
|---|
| 507 | } |
|---|
| 508 | if ($val['type'] == 'open' || $val['type'] == 'complete') |
|---|
| 509 | $writer->startElement(strtolower($val['tag'])); |
|---|
| 510 | if (isset($val['attributes'])) |
|---|
| 511 | { |
|---|
| 512 | foreach ($val['attributes'] AS $attribute => $value) |
|---|
| 513 | { |
|---|
| 514 | // XML parser returns tag names in all uppercase |
|---|
| 515 | if (strtolower($val['tag']).'s' == $type) |
|---|
| 516 | { |
|---|
| 517 | $attribute = strtolower($attribute); |
|---|
| 518 | if ($attribute != 'groups') |
|---|
| 519 | { |
|---|
| 520 | $attributes[$attribute] = $value; |
|---|
| 521 | } |
|---|
| 522 | else |
|---|
| 523 | { |
|---|
| 524 | $attributes[$attribute] = 'Add-Ons'; |
|---|
| 525 | $value = 'Add-Ons'; |
|---|
| 526 | } |
|---|
| 527 | } |
|---|
| 528 | $writer->writeAttribute(strtolower($attribute),$value); |
|---|
| 529 | } |
|---|
| 530 | } |
|---|
| 531 | if ($val['type'] == 'complete') |
|---|
| 532 | $writer->endElement(); |
|---|
| 533 | } |
|---|
| 534 | $writer->endDocument(); |
|---|
| 535 | $new_xml = $writer->flush(); |
|---|
| 536 | |
|---|
| 537 | // Make sure certain attributes exist |
|---|
| 538 | if (!array_key_exists('arena',$attributes)) |
|---|
| 539 | $attributes['arena'] = '0'; |
|---|
| 540 | if (!array_key_exists('designer',$attributes)) |
|---|
| 541 | $attributes['designer'] = ''; |
|---|
| 542 | |
|---|
| 543 | return array('xml'=>$new_xml,'attributes'=>$attributes); |
|---|
| 544 | } |
|---|
| 545 | |
|---|
| 546 | function image_check($path) |
|---|
| 547 | { |
|---|
| 548 | if (!file_exists($path)) |
|---|
| 549 | return false; |
|---|
| 550 | if (!is_dir($path)) |
|---|
| 551 | return false; |
|---|
| 552 | // Check supported image types |
|---|
| 553 | $imagetypes = imagetypes(); |
|---|
| 554 | $imageFileExts = array(); |
|---|
| 555 | if ($imagetypes & IMG_GIF) |
|---|
| 556 | $imageFileExts[] = 'gif'; |
|---|
| 557 | if ($imagetypes & IMG_PNG) |
|---|
| 558 | $imageFileExts[] = 'png'; |
|---|
| 559 | if ($imagetypes & IMG_JPG) |
|---|
| 560 | { |
|---|
| 561 | $imageFileExts[] = 'jpg'; |
|---|
| 562 | $imageFileExts[] = 'jpeg'; |
|---|
| 563 | } |
|---|
| 564 | if ($imagetypes & IMG_WBMP) |
|---|
| 565 | $imageFileExts[] = 'wbmp'; |
|---|
| 566 | if ($imagetypes & IMG_XPM) |
|---|
| 567 | $imageFileExts[] = 'xpm'; |
|---|
| 568 | |
|---|
| 569 | |
|---|
| 570 | foreach (scandir($path) AS $file) |
|---|
| 571 | { |
|---|
| 572 | // Don't check current and parent directory |
|---|
| 573 | if ($file == '.' || $file == '..') |
|---|
| 574 | continue; |
|---|
| 575 | // Make sure the whole path is there |
|---|
| 576 | $file = $path.'/'.$file; |
|---|
| 577 | // Dig into deeper directories |
|---|
| 578 | if (is_dir($file)) { |
|---|
| 579 | if (!image_check($file)) |
|---|
| 580 | return false; |
|---|
| 581 | continue; |
|---|
| 582 | } |
|---|
| 583 | // Don't check files that aren't images |
|---|
| 584 | if (!preg_match('/\.('.implode('|',$imageFileExts).')$/i',$file)) |
|---|
| 585 | continue; |
|---|
| 586 | |
|---|
| 587 | // If we're still in the loop, there is an image to check |
|---|
| 588 | $image_size = getimagesize($file); |
|---|
| 589 | // Make sure dimensions are powers of 2 |
|---|
| 590 | if (($image_size[0] & ($image_size[0]-1)) || ($image_size[0] <= 0)) |
|---|
| 591 | return false; |
|---|
| 592 | if (($image_size[1] & ($image_size[1]-1)) || ($image_size[1] <= 0)) |
|---|
| 593 | return false; |
|---|
| 594 | } |
|---|
| 595 | |
|---|
| 596 | |
|---|
| 597 | return true; |
|---|
| 598 | } |
|---|
| 599 | |
|---|
| 600 | function type_check($path, $source = false) |
|---|
| 601 | { |
|---|
| 602 | if (!file_exists($path)) |
|---|
| 603 | return false; |
|---|
| 604 | if (!is_dir($path)) |
|---|
| 605 | return false; |
|---|
| 606 | // Make a list of approved file types |
|---|
| 607 | if ($source === false) |
|---|
| 608 | $approved_types = ConfigManager::get_config('allowed_addon_exts'); |
|---|
| 609 | else |
|---|
| 610 | $approved_types = ConfigManager::get_config('allowed_source_exts'); |
|---|
| 611 | $approved_types = explode(',',$approved_types); |
|---|
| 612 | $removed_files = array(); |
|---|
| 613 | |
|---|
| 614 | foreach (scandir($path) AS $file) |
|---|
| 615 | { |
|---|
| 616 | // Don't check current and parent directory |
|---|
| 617 | if ($file == '.' || $file == '..') |
|---|
| 618 | continue; |
|---|
| 619 | // Make sure the whole path is there |
|---|
| 620 | $file = $path.'/'.$file; |
|---|
| 621 | // Dig into deeper directories |
|---|
| 622 | if (is_dir($file)) |
|---|
| 623 | { |
|---|
| 624 | $dir_result = type_check($file, $source); |
|---|
| 625 | if (is_array($dir_result)) |
|---|
| 626 | { |
|---|
| 627 | foreach ($dir_result AS $result) |
|---|
| 628 | { |
|---|
| 629 | $removed_files[] = $result; |
|---|
| 630 | } |
|---|
| 631 | } |
|---|
| 632 | continue; |
|---|
| 633 | } |
|---|
| 634 | // Remove files with unapproved extensions |
|---|
| 635 | if (!preg_match('/\.('.implode('|',$approved_types).')$/i',$file)) |
|---|
| 636 | { |
|---|
| 637 | $removed_files[] = basename($file); |
|---|
| 638 | unlink($file); |
|---|
| 639 | } |
|---|
| 640 | } |
|---|
| 641 | if (count($removed_files) == 0) |
|---|
| 642 | return true; |
|---|
| 643 | return $removed_files; |
|---|
| 644 | } |
|---|
| 645 | |
|---|
| 646 | function repack_zip($path_zip, $to) |
|---|
| 647 | { |
|---|
| 648 | $zip = new ZipArchive(); |
|---|
| 649 | $filename = $to; |
|---|
| 650 | |
|---|
| 651 | if(file_exists($filename)) |
|---|
| 652 | unlink($filename); |
|---|
| 653 | |
|---|
| 654 | if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) |
|---|
| 655 | { |
|---|
| 656 | echo("Cannot open <$filename>\n"); |
|---|
| 657 | return false; |
|---|
| 658 | } |
|---|
| 659 | repack_internal($zip, $path_zip); |
|---|
| 660 | $succes = $zip->close(); |
|---|
| 661 | if(!$succes) |
|---|
| 662 | { |
|---|
| 663 | echo "Can't close the zip\n"; |
|---|
| 664 | return false; |
|---|
| 665 | } |
|---|
| 666 | return true; |
|---|
| 667 | } |
|---|
| 668 | |
|---|
| 669 | function repack_internal($zip, $path_zip) |
|---|
| 670 | { |
|---|
| 671 | foreach(scandir($path_zip) as $file) |
|---|
| 672 | { |
|---|
| 673 | if($file == ".." || $file == ".") |
|---|
| 674 | continue; |
|---|
| 675 | if(is_dir($path_zip."/".$file)) |
|---|
| 676 | { |
|---|
| 677 | // Skip over .svn directories that may exist |
|---|
| 678 | if (preg_match('/\.svn$/i',$path_zip.'/'.$file)) |
|---|
| 679 | continue; |
|---|
| 680 | repack_internal($zip, $path_zip."/".$file); |
|---|
| 681 | } |
|---|
| 682 | else if(!$zip->addFile($path_zip."/".$file, $file)) |
|---|
| 683 | { |
|---|
| 684 | echo "Can't add this file: ".$file."\n"; |
|---|
| 685 | return false; |
|---|
| 686 | } |
|---|
| 687 | if(!file_exists($path_zip."/".$file)) |
|---|
| 688 | { |
|---|
| 689 | echo "Can't add this file (it doesn't exist): ".$file."\n"; |
|---|
| 690 | return false; |
|---|
| 691 | } |
|---|
| 692 | } |
|---|
| 693 | } |
|---|
| 694 | ?> |
|---|