the browser-facing portion of osu!
at master 2.2 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace App\Models; 7 8class BeatmapFile 9{ 10 private $parsed = false; 11 private $backgroundImage; 12 13 public static function parse(string $content) 14 { 15 // strip utf8 bom 16 $content = strip_utf8_bom($content); 17 18 // check file 'header' 19 if (!starts_with($content, 'osu file format v')) { 20 return false; 21 } 22 23 // TODO: parse more stuff? ^_^b 24 $matching = false; 25 $lines = explode("\n", $content); 26 foreach ($lines as $line) { 27 $line = trim($line); 28 29 if ($matching) { 30 $parts = explode(',', $line); 31 // Background Image, e.g.: 32 // 0,0,"bg.jpg",0,0 33 if (count($parts) > 2 && $parts[0] === '0') { 34 $imageFilename = str_replace('"', '', $parts[2]); 35 break; 36 } 37 // Storyboard Layer (for when BG isn't defined, e.g. old beatmap) 38 // This *should* appear after the above BG in a valid .osu file, e.g.: 39 // 4,0,0,"evangelion_20_640.jpg",0,0 40 if (count($parts) > 2 && ($parts[0] === '4' || $parts[0] === 'Sprite')) { 41 $imageFilename = str_replace('"', '', $parts[3]); 42 break; 43 } 44 } 45 46 if ($line === '[Events]') { 47 $matching = true; 48 } 49 50 if ($line === '[HitObjects]') { 51 // Too far, give up 52 break; 53 } 54 } 55 56 $file = new static(); 57 $file->parsed = true; 58 59 if (isset($imageFilename)) { 60 // older beatmaps may not have sanitized paths 61 $file->backgroundImage = str_replace('\\', '/', $imageFilename); 62 } else { 63 $file->backgroundImage = false; 64 } 65 66 return $file; 67 } 68 69 public function backgroundImage() 70 { 71 if (!$this->parsed) { 72 return false; 73 } 74 75 return $this->backgroundImage; 76 } 77}