Added hotlink protection and restricting access to the original image to the photo's owner
This commit is contained in:
parent
068ed2018a
commit
08f13b28cb
@ -57,12 +57,14 @@ class ConfigHelper
|
|||||||
'allow_self_registration' => true,
|
'allow_self_registration' => true,
|
||||||
'app_name' => trans('global.app_name'),
|
'app_name' => trans('global.app_name'),
|
||||||
'date_format' => $this->allowedDateFormats()[0],
|
'date_format' => $this->allowedDateFormats()[0],
|
||||||
|
'hotlink_protection' => false,
|
||||||
'items_per_page' => 12,
|
'items_per_page' => 12,
|
||||||
'items_per_page_admin' => 10,
|
'items_per_page_admin' => 10,
|
||||||
'recaptcha_enabled_registration' => false,
|
'recaptcha_enabled_registration' => false,
|
||||||
'recaptcha_secret_key' => '',
|
'recaptcha_secret_key' => '',
|
||||||
'recaptcha_site_key' => '',
|
'recaptcha_site_key' => '',
|
||||||
'require_email_verification' => true,
|
'require_email_verification' => true,
|
||||||
|
'restrict_original_download' => true,
|
||||||
'sender_address' => sprintf('hostmaster@%s', (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost')),
|
'sender_address' => sprintf('hostmaster@%s', (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost')),
|
||||||
'sender_name' => (is_null($currentAppName) ? trans('global.app_name') : $currentAppName),
|
'sender_name' => (is_null($currentAppName) ? trans('global.app_name') : $currentAppName),
|
||||||
'smtp_server' => 'localhost',
|
'smtp_server' => 'localhost',
|
||||||
|
@ -26,6 +26,11 @@ class DbHelper
|
|||||||
return $albums;
|
return $albums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches an album using its URL alias.
|
||||||
|
* @param string $urlAlias URL alias of the album to fetch.
|
||||||
|
* @return Album|null
|
||||||
|
*/
|
||||||
public static function loadAlbumByUrlAlias($urlAlias)
|
public static function loadAlbumByUrlAlias($urlAlias)
|
||||||
{
|
{
|
||||||
return Album::where('url_alias', $urlAlias)->first();
|
return Album::where('url_alias', $urlAlias)->first();
|
||||||
|
@ -49,9 +49,11 @@ class DefaultController extends Controller
|
|||||||
];
|
];
|
||||||
$checkboxKeys = [
|
$checkboxKeys = [
|
||||||
'allow_self_registration',
|
'allow_self_registration',
|
||||||
|
'hotlink_protection',
|
||||||
|
'recaptcha_enabled_registration',
|
||||||
'require_email_verification',
|
'require_email_verification',
|
||||||
|
'restrict_original_download',
|
||||||
'smtp_encryption',
|
'smtp_encryption',
|
||||||
'recaptcha_enabled_registration'
|
|
||||||
];
|
];
|
||||||
$updateKeys = [
|
$updateKeys = [
|
||||||
'app_name',
|
'app_name',
|
||||||
|
@ -16,6 +16,7 @@ use Illuminate\Http\Request;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
|
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
|
||||||
use Symfony\Component\HttpFoundation\File\File;
|
use Symfony\Component\HttpFoundation\File\File;
|
||||||
|
|
||||||
@ -173,6 +174,7 @@ class PhotoController extends Controller
|
|||||||
|
|
||||||
$photo = new Photo();
|
$photo = new Photo();
|
||||||
$photo->album_id = $album->id;
|
$photo->album_id = $album->id;
|
||||||
|
$photo->user_id = Auth::user()->id;
|
||||||
$photo->name = pathinfo($photoFile->getClientOriginalName(), PATHINFO_FILENAME);
|
$photo->name = pathinfo($photoFile->getClientOriginalName(), PATHINFO_FILENAME);
|
||||||
$photo->file_name = $photoFile->getClientOriginalName();
|
$photo->file_name = $photoFile->getClientOriginalName();
|
||||||
$photo->storage_file_name = $savedFile->getFilename();
|
$photo->storage_file_name = $savedFile->getFilename();
|
||||||
@ -223,7 +225,7 @@ class PhotoController extends Controller
|
|||||||
{
|
{
|
||||||
if ($fileInfo->isDir())
|
if ($fileInfo->isDir())
|
||||||
{
|
{
|
||||||
if ($fileInfo->getFilename() == '__MACOSX')
|
if ($fileInfo->getFilename() == '__MACOSX' || substr($fileInfo->getFilename(), 0, 1) == '.')
|
||||||
{
|
{
|
||||||
@rmdir($fileInfo->getPathname());
|
@rmdir($fileInfo->getPathname());
|
||||||
}
|
}
|
||||||
@ -246,6 +248,7 @@ class PhotoController extends Controller
|
|||||||
|
|
||||||
$photo = new Photo();
|
$photo = new Photo();
|
||||||
$photo->album_id = $album->id;
|
$photo->album_id = $album->id;
|
||||||
|
$photo->user_id = Auth::user()->id;
|
||||||
$photo->name = pathinfo($photoFile->getFilename(), PATHINFO_FILENAME);
|
$photo->name = pathinfo($photoFile->getFilename(), PATHINFO_FILENAME);
|
||||||
$photo->file_name = $photoFile->getFilename();
|
$photo->file_name = $photoFile->getFilename();
|
||||||
$photo->storage_file_name = $savedFile->getFilename();
|
$photo->storage_file_name = $savedFile->getFilename();
|
||||||
|
@ -2,12 +2,26 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
use Illuminate\Routing\Controller as BaseController;
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class Controller extends BaseController
|
class Controller extends BaseController
|
||||||
{
|
{
|
||||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets either the authenticated user, or a user object representing the anonymous user.
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
protected function getUser()
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
return (is_null($user)
|
||||||
|
? User::anonymous()
|
||||||
|
: $user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ use App\Helpers\DbHelper;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests;
|
use App\Http\Requests;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class AlbumController extends Controller
|
class AlbumController extends Controller
|
||||||
@ -22,7 +23,7 @@ class AlbumController extends Controller
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->authorize('album.view', $album);
|
$this->authorizeForUser($this->getUser(), 'album.view', $album);
|
||||||
|
|
||||||
$photos = $album->photos()
|
$photos = $album->photos()
|
||||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
||||||
@ -33,13 +34,4 @@ class AlbumController extends Controller
|
|||||||
'photos' => $photos
|
'photos' => $photos
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $id
|
|
||||||
* @return Album
|
|
||||||
*/
|
|
||||||
private static function loadAlbum($urlAlias)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,14 @@ namespace App\Http\Controllers\Gallery;
|
|||||||
|
|
||||||
use App\Album;
|
use App\Album;
|
||||||
use App\Facade\Theme;
|
use App\Facade\Theme;
|
||||||
|
use App\Facade\UserConfig;
|
||||||
use App\Helpers\DbHelper;
|
use App\Helpers\DbHelper;
|
||||||
use app\Http\Controllers\Admin\AlbumController;
|
use app\Http\Controllers\Admin\AlbumController;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Middleware\VerifyCsrfToken;
|
||||||
use App\Photo;
|
use App\Photo;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
class PhotoController extends Controller
|
class PhotoController extends Controller
|
||||||
@ -21,14 +24,38 @@ class PhotoController extends Controller
|
|||||||
App::abort(404);
|
App::abort(404);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$this->authorize('album.view', $album);
|
|
||||||
|
|
||||||
$albumSource = $album->getAlbumSource();
|
$this->authorizeForUser($this->getUser(), 'album.view', $album);
|
||||||
|
|
||||||
|
if (UserConfig::get('hotlink_protection'))
|
||||||
|
{
|
||||||
|
$referrer = $request->headers->get('Referer');
|
||||||
|
|
||||||
|
if (!is_null($referrer))
|
||||||
|
{
|
||||||
|
$hostname = parse_url($referrer, PHP_URL_HOST);
|
||||||
|
if (strtolower($hostname) != strtolower($request->getHttpHost()))
|
||||||
|
{
|
||||||
|
App::abort(403);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
App::abort(403);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$thumbnail = $request->get('t');
|
|
||||||
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
|
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
|
||||||
|
|
||||||
return response()->file($albumSource->getPathToPhoto($photo, $thumbnail));
|
$thumbnail = $request->get('t');
|
||||||
|
if (is_null($thumbnail))
|
||||||
|
{
|
||||||
|
Gate::forUser($this->getUser())->authorize('photo.download_original', $photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->file($album->getAlbumSource()->getPathToPhoto($photo, $thumbnail));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($albumUrlAlias, $photoFilename)
|
public function show($albumUrlAlias, $photoFilename)
|
||||||
@ -40,12 +67,15 @@ class PhotoController extends Controller
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->authorize('album.view', $album);
|
$this->authorizeForUser($this->getUser(), 'album.view', $album);
|
||||||
|
|
||||||
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
|
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);
|
||||||
|
|
||||||
|
$isOriginalAllowed = Gate::forUser($this->getUser())->allows('photo.download_original', $photo);
|
||||||
|
|
||||||
return Theme::render('gallery.photo', [
|
return Theme::render('gallery.photo', [
|
||||||
'album' => $album,
|
'album' => $album,
|
||||||
|
'is_original_allowed' => $isOriginalAllowed,
|
||||||
'photo' => $photo
|
'photo' => $photo
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ class Photo extends Model
|
|||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'album_id',
|
'album_id',
|
||||||
|
'user_id',
|
||||||
'name',
|
'name',
|
||||||
'description',
|
'description',
|
||||||
'file_name',
|
'file_name',
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Album;
|
use App\Album;
|
||||||
|
use App\Facade\UserConfig;
|
||||||
|
use App\Photo;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
@ -30,8 +32,18 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
return (!$album->is_private || $album->user_id == $user->id);
|
return (!$album->is_private || $album->user_id == $user->id);
|
||||||
});
|
});
|
||||||
Gate::define('admin-access', function ($user) {
|
Gate::define('admin-access', function ($user)
|
||||||
|
{
|
||||||
return $user->is_admin;
|
return $user->is_admin;
|
||||||
});
|
});
|
||||||
|
Gate::define('photo.download_original', function ($user, Photo $photo)
|
||||||
|
{
|
||||||
|
if (!UserConfig::get('restrict_original_download'))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($user->id == $photo->user_id);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,15 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
use Notifiable;
|
use Notifiable;
|
||||||
|
|
||||||
|
public static function anonymous()
|
||||||
|
{
|
||||||
|
$user = new User();
|
||||||
|
$user->id = -1;
|
||||||
|
$user->name = 'Anonymous';
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddPhotoUserColumn extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('photos', function (Blueprint $table) {
|
||||||
|
$table->unsignedInteger('user_id');
|
||||||
|
|
||||||
|
$table->foreign('user_id')
|
||||||
|
->references('id')->on('users')
|
||||||
|
->onDelete('no action');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('photos', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('photos_user_id_foreign');
|
||||||
|
$table->dropColumn('user_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
7
public/themes/base/css/app.css
vendored
7
public/themes/base/css/app.css
vendored
@ -0,0 +1,7 @@
|
|||||||
|
.no-margin-bottom {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-padding {
|
||||||
|
padding: 0;
|
||||||
|
}
|
4
public/themes/bootstrap3/theme.css
vendored
4
public/themes/bootstrap3/theme.css
vendored
@ -12,6 +12,10 @@ body {
|
|||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content-body {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
div.breadcrumb {
|
div.breadcrumb {
|
||||||
margin-top: -20px;
|
margin-top: -20px;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,9 @@ return [
|
|||||||
'no_albums_text' => 'You have no photo albums yet. Click the button below to create one.',
|
'no_albums_text' => 'You have no photo albums yet. Click the button below to create one.',
|
||||||
'no_albums_title' => 'No Photo Albums',
|
'no_albums_title' => 'No Photo Albums',
|
||||||
'open_album' => 'Open album',
|
'open_album' => 'Open album',
|
||||||
|
'settings_image_protection' => 'Image Protection',
|
||||||
'settings_link' => 'Settings',
|
'settings_link' => 'Settings',
|
||||||
|
'settings_recaptcha' => 'reCAPTCHA settings',
|
||||||
'settings_save_action' => 'Update Settings',
|
'settings_save_action' => 'Update Settings',
|
||||||
'settings_saved_message' => 'The settings were updated successfully.',
|
'settings_saved_message' => 'The settings were updated successfully.',
|
||||||
'settings_test_email_action' => 'Send a test e-mail',
|
'settings_test_email_action' => 'Send a test e-mail',
|
||||||
|
@ -14,6 +14,10 @@ return [
|
|||||||
'realname_label' => 'Your name:',
|
'realname_label' => 'Your name:',
|
||||||
'register_action' => 'Create account',
|
'register_action' => 'Create account',
|
||||||
'remember_me_label' => 'Remember me',
|
'remember_me_label' => 'Remember me',
|
||||||
|
'settings_hotlink_protection' => 'Prevent hot-linking to images',
|
||||||
|
'settings_hotlink_protection_help' => 'With this option enabled, direct linking to images is not allowed. Photos can only be viewed through Blue Twilight.',
|
||||||
|
'settings_restrict_originals_download' => 'Restrict access to original images',
|
||||||
|
'settings_restrict_originals_download_help' => 'With this option enabled, only the photo\'s owner can download the original high-resolution images.',
|
||||||
'upload_action' => 'Upload',
|
'upload_action' => 'Upload',
|
||||||
'save_action' => 'Save Changes'
|
'save_action' => 'Save Changes'
|
||||||
];
|
];
|
@ -15,7 +15,7 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-sm-8">
|
<div class="col-xs-12 col-sm-8 content-body">
|
||||||
@include (Theme::viewName('partials.admin_sysinfo_widget'))
|
@include (Theme::viewName('partials.admin_sysinfo_widget'))
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<fieldset style="margin-top: 30px;">
|
<fieldset style="margin-top: 30px;">
|
||||||
<legend>reCAPTCHA settings</legend>
|
<legend>@lang('admin.settings_recaptcha')</legend>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{!! Form::label('recaptcha_site_key', 'Site key:', ['class' => 'control-label']) !!}
|
{!! Form::label('recaptcha_site_key', 'Site key:', ['class' => 'control-label']) !!}
|
||||||
@ -155,6 +155,26 @@
|
|||||||
{!! Form::text('recaptcha_secret_key', old('recaptcha_secret_key'), ['class' => 'form-control']) !!}
|
{!! Form::text('recaptcha_secret_key', old('recaptcha_secret_key'), ['class' => 'form-control']) !!}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset style="margin-top: 20px;">
|
||||||
|
<legend>@lang('admin.settings_image_protection')</legend>
|
||||||
|
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="restrict_original_download" @if (UserConfig::get('restrict_original_download'))checked="checked"@endif>
|
||||||
|
<strong>@lang('forms.settings_restrict_originals_download')</strong><br/>
|
||||||
|
@lang('forms.settings_restrict_originals_download_help')
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkbox" style="margin-top: 20px;">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="hotlink_protection" @if (UserConfig::get('hotlink_protection'))checked="checked"@endif>
|
||||||
|
<strong>@lang('forms.settings_hotlink_protection')</strong><br/>
|
||||||
|
@lang('forms.settings_hotlink_protection_help')
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
@extends('themes.base.layout')
|
@extends('themes.base.layout')
|
||||||
@section('title', 'Welcome')
|
@section('title', $photo->name)
|
||||||
|
|
||||||
@section('breadcrumb')
|
@section('breadcrumb')
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
@ -25,55 +25,64 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-sm-8">
|
<div class="col-xs-12 col-sm-8 content-body">
|
||||||
<a href="{{ $photo->thumbnailUrl() }}"><img src="{{ $photo->thumbnailUrl('fullsize') }}" alt="" class="img-thumbnail"/></a>
|
@if ($is_original_allowed)
|
||||||
|
<a href="{{ $photo->thumbnailUrl() }}">
|
||||||
|
@endif
|
||||||
|
<img src="{{ $photo->thumbnailUrl('fullsize') }}" alt="" class="img-thumbnail"/>
|
||||||
|
@if ($is_original_allowed)
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-12 col-sm-4">
|
<div class="col-xs-12 col-sm-4">
|
||||||
<p>Information about this photo:</p>
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Information about this photo:</div>
|
||||||
|
<div class="panel-body no-padding">
|
||||||
|
<table class="table table-striped photo-metadata no-margin-bottom">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="metadata_name">File name:</td>
|
||||||
|
<td class="metadata_value">{{ $photo->file_name }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<table class="table table-striped photo-metadata">
|
@if (strlen($photo->taken_at) > 0)
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<td class="metadata_name">Date taken:</td>
|
||||||
<th>Name</th>
|
<td class="metadata_value">{{ date(UserConfig::get('date_format'), strtotime($photo->taken_at)) }}</td>
|
||||||
<th>Value</th>
|
</tr>
|
||||||
</tr>
|
@endif
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="metadata_name">File name:</td>
|
|
||||||
<td class="metadata_value">{{ $photo->file_name }}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
@if (strlen($photo->taken_at) > 0)
|
@if (strlen($photo->camera_make) > 0)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="metadata_name">Date taken:</td>
|
<td class="metadata_name">Camera make:</td>
|
||||||
<td class="metadata_value">{{ date(UserConfig::get('date_format'), strtotime($photo->taken_at)) }}</td>
|
<td class="metadata_value">{{ $photo->camera_make }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (strlen($photo->camera_make) > 0)
|
@if (strlen($photo->camera_model) > 0)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="metadata_name">Camera make:</td>
|
<td class="metadata_name">Camera model:</td>
|
||||||
<td class="metadata_value">{{ $photo->camera_make }}</td>
|
<td class="metadata_value">{{ $photo->camera_model }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (strlen($photo->camera_model) > 0)
|
@if (strlen($photo->camera_software) > 0)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="metadata_name">Camera model:</td>
|
<td class="metadata_name">Camera software:</td>
|
||||||
<td class="metadata_value">{{ $photo->camera_model }}</td>
|
<td class="metadata_value">{{ $photo->camera_software }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endif
|
@endif
|
||||||
|
</tbody>
|
||||||
@if (strlen($photo->camera_software) > 0)
|
</table>
|
||||||
<tr>
|
</div>
|
||||||
<td class="metadata_name">Camera software:</td>
|
</div>
|
||||||
<td class="metadata_value">{{ $photo->camera_software }}</td>
|
|
||||||
</tr>
|
|
||||||
@endif
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user