MOON
Server: Apache
System: Linux e2e-78-16.ssdcloudindia.net 3.10.0-1160.45.1.el7.x86_64 #1 SMP Wed Oct 13 17:20:51 UTC 2021 x86_64
User: imensosw (1005)
PHP: 7.4.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: /home/imensosw/www/mpl.imenso.co/app/Models/Song.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Song extends Model
{
    public function songable()
    {
        return $this->morphTo();
    }

    public function album()
    {
        if (get_class($this->songable) == \App\Models\Album::class) {
            return $this->songable;
        } else {
            return false;
        }
    }

    public function artist()
    {
        return $this->album()->artist;
    }

    public function likes()
    {
        return $this->morphMany(\App\Models\Like::class, 'likeable');
    }

    public function files()
    {
        return $this->morphMany(\App\Models\File::class, 'fileable');
    }

    public static function addNew($data)
    {
        $song = new self;
        $song->name = $data->name;
        $song->save();

        $song->uploadMP3($data->song);
        $song->calculateDuration();

        return $song;
    }

    public function editSong($data)
    {
        $this->name = $data->name;
        $this->save();

        if ($data->hasFile('song')) {
            $this->uploadMP3($data->song);
            $this->calculateDuration();
        }

        return $this;
    }

    public static function lz($num)
    {
        return (strlen($num) < 2) ? "0{$num}" : $num;
    }

    public function showDuration()
    {
        $total_seconds = $this->duration;

        $remaining_seconds = $total_seconds;

        $hours = floor($total_seconds / 3600);
        $remaining_seconds -= ($hours * 3600);

        $minutes = floor($remaining_seconds / 60);
        $remaining_seconds -= ($minutes * 60);

        $seconds = $remaining_seconds;

        return $hours > 0 ? $hours.':'.self::lz($minutes).':'.self::lz($seconds) : $minutes.':'.self::lz($seconds);
    }

    public function calculateDuration()
    {
        $this->duration = self::getMP3Duration($this->file(3)->src);
        $this->save();
    }

    public function uploadMP3($file)
    {
        $filename = $this->id.'-'.time().'-song.'.$file->getClientOriginalExtension();

        $web_location = 'music/songs/'.$filename;
        $server_location = public_path('music/songs/');

        $file->move($server_location, $filename);
        $this->deleteFile(3);
        $this->setFile(3, $web_location);
    }

    public function deleteFile($type_id)
    {
        if ($this->files()->where('type_id', $type_id)->count() > 0) {
            $this->files()->where('type_id', $type_id)->first()->remove();
        }
    }

    public function file($file_type_id = 0)
    {
        if ($this->files()->where('type_id', $file_type_id)->count() > 0) {
            return $this->files()->where('type_id', $file_type_id)->first();
        } else {
            $file = new File;
            $file->src = '';

            return $file;
        }
    }

    public function setFile($type_id, $location)
    {
        $file = new File;
        $file->src = $location;
        $file->fileable_id = $this->id;
        $file->fileable_type = self::class;
        $file->type_id = $type_id;
        $file->save();
    }

    public function assignToNews(News $news)
    {
        $this->songable_id = $news->id;
        $this->songable_type = \App\Models\News::class;
        $this->save();
    }

    public function remove()
    {
        $this->delete();
    }

    public function moveUp()
    {
        $this->orderby -= 10;
        $previous_song = self::where('songable_id', $this->songable_id)->where('songable_type', \App\Models\Album::class)->where('orderby', $this->orderby)->first();
        $previous_song->orderby += 10;
        $previous_song->save();
        $this->save();
    }

    public function moveDown()
    {
        $this->orderby += 10;
        $next_song = self::where('songable_id', $this->songable_id)->where('songable_type', \App\Models\Album::class)->where('orderby', $this->orderby)->first();
        $next_song->orderby -= 10;
        $next_song->save();
        $this->save();
    }

    public static function getMP3Duration($filename)
    {
        $fd = fopen($filename, 'rb');

        $duration = 0;
        $block = fread($fd, 100);
        $offset = self::skipID3v2Tag($block);
        fseek($fd, $offset, SEEK_SET);

        while (! feof($fd)) {
            $block = fread($fd, 10);
            if (strlen($block) < 10) {
                break;
            } elseif ($block[0] == "\xff" && (ord($block[1]) & 0xe0)) {
                $info = self::parseFrameHeader(substr($block, 0, 4));
                if (empty($info['Framesize'])) {
                    return $duration;
                } //some corrupt mp3 files

                fseek($fd, $info['Framesize'] - 10, SEEK_CUR);
                $duration += ($info['Samples'] / $info['Sampling Rate']);
            } elseif (substr($block, 0, 3) == 'TAG') {
                fseek($fd, 128 - 10, SEEK_CUR);
            //skip over id3v1 tag size
            } else {
                fseek($fd, -9, SEEK_CUR);
            }
            if (isset($use_cbr_estimate) && ! empty($info)) {
                $kbps = ($bitrate * 1000) / 8;
                $datasize = filesize($filename) - $offset;

                return round($datasize / $kbps);
            }
        }

        return round($duration);
    }

    public static function parseFrameHeader($fourbytes)
    {
        $versions = [
            0x0 => '2.5', 0x1 => 'x', 0x2 => '2', 0x3 => '1', // x=>'reserved'
        ];

        static $layers = [
            0x0 => 'x', 0x1 => '3', 0x2 => '2', 0x3 => '1', // x=>'reserved'
        ];

        static $bitrates = [
            'V1L1' => [0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448],
            'V1L2' => [0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384],
            'V1L3' => [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320],
            'V2L1' => [0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256],
            'V2L2' => [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
            'V2L3' => [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
        ];

        static $sample_rates = [
            '1'   => [44100, 48000, 32000],
            '2'   => [22050, 24000, 16000],
            '2.5' => [11025, 12000, 8000],
        ];
        static $samples = [
            1 => [1 => 384, 2 => 1152, 3 => 1152], //MPEGv1,     Layers 1,2,3
            2 => [1 => 384, 2 => 1152, 3 => 576], //MPEGv2/2.5, Layers 1,2,3
        ];

        //$b0=ord($fourbytes[0]);//will always be 0xff
        $b1 = ord($fourbytes[1]);
        $b2 = ord($fourbytes[2]);
        $b3 = ord($fourbytes[3]);

        $version_bits = ($b1 & 0x18) >> 3;
        $version = $versions[$version_bits];
        $simple_version = ($version == '2.5' ? 2 : $version);

        $layer_bits = ($b1 & 0x06) >> 1;
        $layer = $layers[$layer_bits];

        $protection_bit = ($b1 & 0x01);
        $bitrate_key = sprintf('V%dL%d', $simple_version, $layer);
        $bitrate_idx = ($b2 & 0xf0) >> 4;
        $bitrate = isset($bitrates[$bitrate_key][$bitrate_idx]) ? $bitrates[$bitrate_key][$bitrate_idx] : 0;

        $sample_rate_idx = ($b2 & 0x0c) >> 2; //0xc => b1100
        $sample_rate = isset($sample_rates[$version][$sample_rate_idx]) ? $sample_rates[$version][$sample_rate_idx] : 0;
        $padding_bit = ($b2 & 0x02) >> 1;
        $private_bit = ($b2 & 0x01);
        $channel_mode_bits = ($b3 & 0xc0) >> 6;
        $mode_extension_bits = ($b3 & 0x30) >> 4;
        $copyright_bit = ($b3 & 0x08) >> 3;
        $original_bit = ($b3 & 0x04) >> 2;
        $emphasis = ($b3 & 0x03);

        $info = [];
        $info['Version'] = $version; //MPEGVersion
        $info['Layer'] = $layer;
        //$info['Protection Bit'] = $protection_bit; //0=> protected by 2 byte CRC, 1=>not protected
        $info['Bitrate'] = $bitrate;
        $info['Sampling Rate'] = $sample_rate;
        //$info['Padding Bit'] = $padding_bit;
        //$info['Private Bit'] = $private_bit;
        //$info['Channel Mode'] = $channel_mode_bits;
        //$info['Mode Extension'] = $mode_extension_bits;
        //$info['Copyright'] = $copyright_bit;
        //$info['Original'] = $original_bit;
        //$info['Emphasis'] = $emphasis;
        $info['Framesize'] = self::framesize($layer, $bitrate, $sample_rate, $padding_bit);
        $info['Samples'] = $samples[$simple_version][$layer];

        return $info;
    }

    public static function skipID3v2Tag(&$block)
    {
        if (substr($block, 0, 3) == 'ID3') {
            $id3v2_major_version = ord($block[3]);
            $id3v2_minor_version = ord($block[4]);
            $id3v2_flags = ord($block[5]);
            $flag_unsynchronisation = $id3v2_flags & 0x80 ? 1 : 0;
            $flag_extended_header = $id3v2_flags & 0x40 ? 1 : 0;
            $flag_experimental_ind = $id3v2_flags & 0x20 ? 1 : 0;
            $flag_footer_present = $id3v2_flags & 0x10 ? 1 : 0;
            $z0 = ord($block[6]);
            $z1 = ord($block[7]);
            $z2 = ord($block[8]);
            $z3 = ord($block[9]);

            if ((($z0 & 0x80) == 0) && (($z1 & 0x80) == 0) && (($z2 & 0x80) == 0) && (($z3 & 0x80) == 0)) {
                $header_size = 10;
                $tag_size = (($z0 & 0x7f) * 2097152) + (($z1 & 0x7f) * 16384) + (($z2 & 0x7f) * 128) + ($z3 & 0x7f);
                $footer_size = $flag_footer_present ? 10 : 0;

                return $header_size + $tag_size + $footer_size; //bytes to skip
            }
        }

        return 0;
    }

    public static function framesize($layer, $bitrate, $sample_rate, $padding_bit)
    {
        if ($layer == 1) {
            return intval(((12 * $bitrate * 1000 / $sample_rate) + $padding_bit) * 4);
        //layer 2, 3
        } else {
            return intval(((144 * $bitrate * 1000) / $sample_rate) + $padding_bit);
        }
    }
}