/** * Generate the downloadable path for a song. * * @param Song $song * * @return string */ protected function fromSong(Song $song) { if ($s3Params = $song->s3_params) { // The song is hosted on Amazon S3. // We download it back to our local server first. $localPath = rtrim(sys_get_temp_dir(), '/') . '/' . basename($s3Params['key']); $url = $song->getObjectStoragePublicUrl(); abort_unless($url, 404); // The following function require allow_url_fopen to be ON. // We're just assuming that to be the case here. copy($url, $localPath); } else { // The song is hosted locally. Make sure the file exists. abort_unless(file_exists($song->path), 404); $localPath = $song->path; } // The BinaryFileResponse factory only accept ASCII-only file names. if (ctype_print($localPath)) { return $localPath; } // For those with high-byte characters in names, we copy it into a safe name // as a workaround. $newPath = rtrim(sys_get_temp_dir(), '/') . '/' . utf8_decode(basename($song->path)); if ($s3Params) { // If the file is downloaded from S3, we rename it directly. // This will save us some disk space. rename($localPath, $newPath); } else { // Else we copy it to another file to not mess up the original one. copy($localPath, $newPath); } return $newPath; }
/** * Controller constructor. */ public function __construct() { parent::__construct(); $this->types = Enum::getTypes(); abort_unless($this->types, 500, 'Enum Resources is empty!...'); $this->switchType(); }
/** * Remove a song whose info matches with data sent from AWS. * * @param RemoveSongRequest $request * * @return \Illuminate\Http\JsonResponse */ public function remove(RemoveSongRequest $request) { abort_unless($song = Song::byPath("s3://{$request->bucket}/{$request->key}"), 404); $song->delete(); event(new LibraryChanged()); return response()->json(); }
/** * Serve the callback request from Last.fm. * * @param Request $request * @param Lastfm $lastfm * * @return \Illuminate\Http\Response */ public function callback(Request $request, Lastfm $lastfm) { abort_unless($token = $request->input('token'), 500, 'Something wrong happened.'); // Get the session key using the obtained token. abort_unless($sessionKey = $lastfm->getSessionKey($token), 500, 'Invalid token key.'); $this->auth->user()->savePreference('lastfm_session_key', $sessionKey); return view('api.lastfm.callback'); }
/** * @param string $type * * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function enum($type) { abort_unless(in_array($type, ['language', 'security', 'writer', 'publisher', 'pplace']), 404); $this->buildHeading([trans("ilib::common.statistics"), trans("ilib::common.statistics_{$type}")], 'fa-bar-chart', ['#' => trans("ilib::common.statistics")]); $couters = DB::table('ebooks')->leftJoin('enums', "ebooks.{$type}_id", '=', 'enums.id')->groupBy('enums.title')->select(DB::raw('COUNT(*) AS enum_count'), 'enums.title as title')->orderBy('enum_count', 'desc')->get(); $type_title = trans("ebook::common.{$type}_id"); return view('ilib::backend.statistics.enum', compact('type_title', 'couters')); }
/** * BaseStreamer constructor. * * @param $song Song */ public function __construct(Song $song) { $this->song = $song; abort_unless(file_exists($this->song->path), 404); // Hard code the content type instead of relying on PHP's fileinfo() // or even Symfony's MIMETypeGuesser, since they appear to be wrong sometimes. $this->contentType = 'audio/' . pathinfo($this->song->path, PATHINFO_EXTENSION); // Turn off error reporting to make sure our stream isn't interfered. @error_reporting(0); }
/** * Redeem the given coupon code. * * @param Request $request * @param Team $team * @return Response */ public function redeem(Request $request, Team $team) { abort_unless($request->user()->ownsTeam($team), 403); $this->validate($request, ['coupon' => 'required']); // We will verify that the coupon can actually be redeemed. In some cases even // valid coupons can not get redeemed by an existing user if this coupon is // running as a promotion for brand new registrations to the application. if (!$this->coupons->canBeRedeemed($request->coupon)) { return response()->json(['coupon' => ['This coupon code is invalid.']], 422); } Spark::interact(RedeemCoupon::class, [$team, $request->coupon]); }
/** * On-the-fly stream the current song while transcoding. */ public function stream() { $ffmpeg = env('FFMPEG_PATH', '/usr/local/bin/ffmpeg'); abort_unless(is_executable($ffmpeg), 500, 'Transcoding requires valid ffmpeg settings.'); $bitRate = filter_var($this->bitrate, FILTER_SANITIZE_NUMBER_INT); // Since we can't really know the content length of a file while it's still being transcoded, // "calculating" it (like below) will be much likely to result in net::ERR_CONTENT_LENGTH_MISMATCH errors. // Better comment these for now. // // header('Accept-Ranges: bytes'); // $bytes = round(($this->song->length * $bitRate * 1024) / 8); // header("Content-Length: $bytes"); header('Content-Type: audio/mpeg'); header('Content-Disposition: attachment; filename="' . basename($this->song->path) . '"'); $args = ['-i ' . escapeshellarg($this->song->path), '-map 0:0', '-v 0', "-ab {$bitRate}k", '-f mp3', '-']; if ($this->startTime) { array_unshift($args, "-ss {$this->startTime}"); } passthru("{$ffmpeg} " . implode($args, ' ')); }
/** * Update the given team's name. * * @param Request $request * @param \Laravel\Spark\Team $team * @return Response */ public function update(Request $request, $team) { abort_unless($request->user()->ownsTeam($team), 404); $this->validate($request, ['name' => 'required|max:255']); $team->forceFill(['name' => $request->name])->save(); }
/** * Download the invoice with the given ID. * * @param Request $request * @param Team $team * @param string $id * @return Response */ public function download(Request $request, Team $team, $id) { abort_unless($request->user()->ownsTeam($team), 403); $invoice = $team->localInvoices()->where('id', $id)->firstOrFail(); return $team->downloadInvoice($invoice->provider_id, ['id' => $invoice->id] + Spark::invoiceDataFor($team)); }
/** * Stream the current song using the most basic PHP method: readfile() * Credits: DaveRandom @ http://stackoverflow.com/a/4451376/794641. */ public function stream() { // Get the 'Range' header if one was sent if (isset($_SERVER['HTTP_RANGE'])) { // IIS/Some Apache versions $range = $_SERVER['HTTP_RANGE']; } elseif (function_exists('apache_request_headers') && ($apache = apache_request_headers())) { // Try Apache again $headers = []; foreach ($apache as $header => $val) { $headers[strtolower($header)] = $val; } $range = isset($headers['range']) ? $headers['range'] : false; } else { // We can't get the header/there isn't one set $range = false; } // Get the data range requested (if any) $fileSize = filesize($this->song->path); if ($range) { $partial = true; list($param, $range) = explode('=', $range); // Bad request - range unit is not 'bytes' abort_unless(strtolower(trim($param)) === 'bytes', 400); $range = explode(',', $range); $range = explode('-', $range[0]); // We only deal with the first requested range // Bad request - 'bytes' parameter is not valid abort_unless(count($range) === 2, 400); if ($range[0] === '') { // First number missing, return last $range[1] bytes $end = $fileSize - 1; $start = $end - intval($range[0]); } elseif ($range[1] === '') { // Second number missing, return from byte $range[0] to end $start = intval($range[0]); $end = $fileSize - 1; } else { // Both numbers present, return specific range $start = intval($range[0]); $end = intval($range[1]); if ($end >= $fileSize || !$start && (!$end || $end == $fileSize - 1)) { // Invalid range/whole file specified, return whole file $partial = false; } } $length = $end - $start + 1; } else { // No range requested $length = filesize($this->song->path); $partial = false; } // Send standard headers header("Content-Type: {$this->contentType}"); header("Content-Length: {$length}"); header('Content-Disposition: attachment; filename="' . basename($this->song->path) . '"'); header('Accept-Ranges: bytes'); // if requested, send extra headers and part of file... if ($partial) { header('HTTP/1.1 206 Partial Content'); header("Content-Range: bytes {$start}-{$end}/{$fileSize}"); // Error out if we can't read the file abort_unless($fp = fopen($this->song->path, 'r'), 500); if ($start) { fseek($fp, $start); } while ($length) { // Read in blocks of 8KB so we don't chew up memory on the server $read = $length > 8192 ? 8192 : $length; $length -= $read; echo fread($fp, $read); } fclose($fp); } else { // ...otherwise just send the whole file readfile($this->song->path); } exit; }
/** * Update the team's extra billing information. * * @param Request $request * @param Team $team * @return Response */ public function update(Request $request, Team $team) { abort_unless($request->user()->ownsTeam($team), 403); $this->validate($request, ['information' => 'max:2048']); $team->forceFill(['extra_billing_information' => $request->information])->save(); }
/** * Cancel / delete the given invitation. * * @param Request $request * @param \Laravel\Spark\Invitation $invitation * @return Response */ public function destroy(Request $request, Invitation $invitation) { abort_unless($request->user()->ownsTeam($invitation->team), 404); $invitation->delete(); }
/** * Cancel the team's subscription. * * @param Request $request * @param Team $team * @return Response */ public function destroy(Request $request, Team $team) { abort_unless($request->user()->ownsTeam($team), 403); $team->subscription()->cancel(); event(new SubscriptionCancelled($team->fresh())); }
/** * @param \Minhbang\Ebook\Ebook $ebook * @param string $slug * * @return bool */ protected function checkPermission($ebook, $slug) { abort_unless($slug == $ebook->slug, 404); /** @var User $user */ $user = user(); /** @var Reader $reader */ $reader = Reader::find($user->id); return $user->hasRole('tv.*') || $ebook->isPublished() && $reader && $reader->canRead($ebook); }
/** * Switch the current team the user is viewing. * * @param Request $request * @param \Laravel\Spark\Team $team * @return Response */ public function switchCurrentTeam(Request $request, $team) { abort_unless($request->user()->onTeam($team), 404); $request->user()->switchToTeam($team); return back(); }
/** * Reject the given invitations. * * @param Request $request * @param \Laravel\Spark\Invitation $invitation * @return Response */ public function reject(Request $request, Invitation $invitation) { abort_unless($request->user()->id == $invitation->user_id, 404); $invitation->delete(); }
/** * Show the team settings dashboard. * * @param Request $request * @param Team $team * @return Response */ public function show(Request $request, $team) { abort_unless($request->user()->onTeam($team), 404); return view('spark::settings.teams.team-settings', compact('team')); }
/** * Update the given team member. * * @param Request $request * @param \Laravel\Spark\Team $team * @param mixed $member * @return Response */ public function update(Request $request, $team, $member) { abort_unless($request->user()->ownsTeam($team), 404); $this->interaction($request, UpdateTeamMember::class, [$team, $member, $request->all()]); }
public static function findBySlug(string $slug) : Article { $article = Article::online()->where('slug->' . content_locale(), $slug)->first(); abort_unless($article, 404); return $article; }
/** * Update the payment method for the user. * * @param UpdatePaymentMethodRequest $request * @param Team $team * @return Response */ public function update(UpdatePaymentMethodRequest $request, Team $team) { abort_unless($request->user()->ownsTeam($team), 403); Spark::interact(UpdatePaymentMethod::class, [$team, $request->all()]); }