Multiple fixes and improvements
- Fixed JS exploit using SVG - Improved security - Now sanitizing EXIF and metadata - Now allowing multiple file types as profile picture - Added error messages
This commit is contained in:
parent
2180fec604
commit
07336bb34c
|
@ -9,6 +9,8 @@ use Illuminate\Support\Facades\Schema;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\Facades\Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
use JeroenDesloovere\VCard\VCard;
|
use JeroenDesloovere\VCard\VCard;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
use Auth;
|
use Auth;
|
||||||
use DB;
|
use DB;
|
||||||
|
@ -708,68 +710,110 @@ class UserController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
//Save littlelink page (name, description, logo)
|
//Save littlelink page (name, description, logo)
|
||||||
public function editPage(request $request)
|
public function editPage(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
|
||||||
'littlelink_name' => 'sometimes|max:255|string|isunique:users,id,'.Auth::id(),
|
|
||||||
'name' => 'sometimes|max:255|string',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$userId = Auth::user()->id;
|
$userId = Auth::user()->id;
|
||||||
$littlelink_name = Auth::user()->littlelink_name;
|
$littlelink_name = Auth::user()->littlelink_name;
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'littlelink_name' => [
|
||||||
|
'sometimes',
|
||||||
|
'max:255',
|
||||||
|
'string',
|
||||||
|
'isunique:users,id,'.$userId,
|
||||||
|
],
|
||||||
|
'name' => 'sometimes|max:255|string',
|
||||||
|
'image' => 'sometimes|image|mimes:jpeg,jpg,png,webp|max:2048', // Max file size: 2MB
|
||||||
|
], [
|
||||||
|
'littlelink_name.unique' => 'That handle has already been taken.',
|
||||||
|
'image.image' => 'The selected file must be an image.',
|
||||||
|
'image.mimes' => 'The image must be a: JPEG, JPG, PNG, webP.',
|
||||||
|
'image.max' => 'The image size should not exceed 2MB.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return redirect('/studio/page')->withErrors($validator)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
$profilePhoto = $request->file('image');
|
$profilePhoto = $request->file('image');
|
||||||
$pageName = $request->littlelink_name;
|
$pageName = $request->littlelink_name;
|
||||||
$pageDescription = strip_tags($request->pageDescription,'<a><p><strong><i><ul><ol><li><blockquote><h2><h3><h4>');
|
$pageDescription = strip_tags($request->pageDescription, '<a><p><strong><i><ul><ol><li><blockquote><h2><h3><h4>');
|
||||||
$pageDescription = preg_replace("/<a([^>]*)>/i", "<a $1 rel=\"noopener noreferrer nofollow\">", $pageDescription);
|
$pageDescription = preg_replace("/<a([^>]*)>/i", "<a $1 rel=\"noopener noreferrer nofollow\">", $pageDescription);
|
||||||
$name = $request->name;
|
$name = $request->name;
|
||||||
$checkmark = $request->checkmark;
|
$checkmark = $request->checkmark;
|
||||||
$sharebtn = $request->sharebtn;
|
$sharebtn = $request->sharebtn;
|
||||||
|
|
||||||
User::where('id', $userId)->update(['littlelink_name' => $pageName, 'littlelink_description' => $pageDescription, 'name' => $name]);
|
User::where('id', $userId)->update([
|
||||||
|
'littlelink_name' => $pageName,
|
||||||
|
'littlelink_description' => $pageDescription,
|
||||||
|
'name' => $name
|
||||||
|
]);
|
||||||
|
|
||||||
if ($request->hasFile('image')) {
|
if ($request->hasFile('image')) {
|
||||||
$profilePhoto->move(base_path('assets/img'), $userId . '_' . time() . ".png");
|
$fileName = $userId . '_' . time() . "." . $profilePhoto->extension();
|
||||||
|
$profilePhoto->move(base_path('assets/img'), $fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($checkmark == "on"){
|
if ($checkmark == "on") {
|
||||||
UserData::saveData($userId, 'checkmark', true);
|
UserData::saveData($userId, 'checkmark', true);
|
||||||
} else {
|
} else {
|
||||||
UserData::saveData($userId, 'checkmark', false);
|
UserData::saveData($userId, 'checkmark', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($sharebtn == "on"){
|
if ($sharebtn == "on") {
|
||||||
UserData::saveData($userId, 'disable-sharebtn', false);
|
UserData::saveData($userId, 'disable-sharebtn', false);
|
||||||
} else {
|
} else {
|
||||||
UserData::saveData($userId, 'disable-sharebtn', true);
|
UserData::saveData($userId, 'disable-sharebtn', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect('/studio/page');
|
return Redirect('/studio/page');
|
||||||
}
|
}
|
||||||
|
|
||||||
//Upload custom theme background image
|
//Upload custom theme background image
|
||||||
public function themeBackground(request $request)
|
public function themeBackground(Request $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
$userId = Auth::user()->id;
|
$userId = Auth::user()->id;
|
||||||
$littlelink_name = Auth::user()->littlelink_name;
|
$littlelink_name = Auth::user()->littlelink_name;
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'image' => 'required|image|mimes:jpeg,jpg,png,webp,gif|max:2048', // Max file size: 2MB
|
||||||
|
], [
|
||||||
|
'image.required' => 'Please select an image file.',
|
||||||
|
'image.image' => 'The selected file must be an image.',
|
||||||
|
'image.mimes' => 'The image must be a: JPEG, JPG, PNG, webP, GIF.',
|
||||||
|
'image.max' => 'The image size should not exceed 2MB.',
|
||||||
|
]);
|
||||||
|
|
||||||
$customBackground = $request->file('image');
|
$customBackground = $request->file('image');
|
||||||
|
|
||||||
if (!empty($customBackground)) {
|
if ($customBackground) {
|
||||||
$directory = base_path('assets/img/background-img/');
|
$directory = base_path('assets/img/background-img/');
|
||||||
$files = scandir($directory);
|
$files = scandir($directory);
|
||||||
$pathinfo = "error.error";
|
$pathinfo = "error.error";
|
||||||
foreach($files as $file) {
|
foreach ($files as $file) {
|
||||||
if (strpos($file, $userId.'.') !== false) {
|
if (strpos($file, $userId . '.') !== false) {
|
||||||
$pathinfo = $userId. "." . pathinfo($file, PATHINFO_EXTENSION);
|
$pathinfo = $userId . "." . pathinfo($file, PATHINFO_EXTENSION);
|
||||||
}}
|
}
|
||||||
if(file_exists(base_path('assets/img/background-img/').$pathinfo)){File::delete(base_path('assets/img/background-img/').$pathinfo);}
|
}
|
||||||
|
|
||||||
$customBackground->move(base_path('assets/img/background-img/'), $userId . '_' . time() . "." . $request->file('image')->extension());
|
if (file_exists(base_path('assets/img/background-img/') . $pathinfo)) {
|
||||||
|
File::delete(base_path('assets/img/background-img/') . $pathinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = $userId . '_' . time() . "." . $customBackground->extension();
|
||||||
|
$customBackground->move(base_path('assets/img/background-img/'), $fileName);
|
||||||
|
|
||||||
|
if (extension_loaded('imagick')) {
|
||||||
|
$imagePath = base_path('assets/img/background-img/') . $fileName;
|
||||||
|
$image = new \Imagick($imagePath);
|
||||||
|
$image->stripImage();
|
||||||
|
$image->writeImage($imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect('/studio/theme');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect('/studio/theme');
|
return redirect('/studio/theme')->with('error', 'Please select a valid image file.');
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delete custom background image
|
//Delete custom background image
|
||||||
|
|
|
@ -194,6 +194,18 @@
|
||||||
</div>
|
</div>
|
||||||
<section class='text-gray-400'>
|
<section class='text-gray-400'>
|
||||||
<h3 class="mb-4 card-header"><i class="bi bi-file-earmark-break"> {{__('messages.My Profile')}}</i></h3>
|
<h3 class="mb-4 card-header"><i class="bi bi-file-earmark-break"> {{__('messages.My Profile')}}</i></h3>
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
||||||
|
<svg class="bi flex-shrink-0 me-2" width="24" height="24">
|
||||||
|
<use xlink:href="#exclamation-triangle-fill"></use>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
{{ $error }}
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<div></div>
|
<div></div>
|
||||||
|
@ -203,7 +215,7 @@
|
||||||
@if($page->littlelink_name != '')
|
@if($page->littlelink_name != '')
|
||||||
<div class="form-group col-lg-8">
|
<div class="form-group col-lg-8">
|
||||||
<label class="form-label" for="customFile">{{__('messages.Profile Picture')}}</label>
|
<label class="form-label" for="customFile">{{__('messages.Profile Picture')}}</label>
|
||||||
<input type="file" accept="image/jpeg,image/jpg,image/png" name="image" class="form-control" id="customFile">
|
<input type="file" accept="image/jpeg,image/jpg,image/png,image/webp" name="image" class="form-control" id="customFile">
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,19 @@
|
||||||
<h3 class="mb-4 card-header"><i class="bi bi-brush">{{__('messages.Select a theme')}}</i></h3>
|
<h3 class="mb-4 card-header"><i class="bi bi-brush">{{__('messages.Select a theme')}}</i></h3>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="alert alert-danger d-flex align-items-center" role="alert">
|
||||||
|
<svg class="bi flex-shrink-0 me-2" width="24" height="24">
|
||||||
|
<use xlink:href="#exclamation-triangle-fill"></use>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
{{ $error }}
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<button type="button" class="btn btn-primary mb-5" data-bs-toggle="modal" data-bs-target="#exampleModal">
|
<button type="button" class="btn btn-primary mb-5" data-bs-toggle="modal" data-bs-target="#exampleModal">
|
||||||
{{__('messages.Select theme')}}
|
{{__('messages.Select theme')}}
|
||||||
</button>
|
</button>
|
||||||
|
@ -74,7 +87,7 @@
|
||||||
<br>
|
<br>
|
||||||
<br><br>
|
<br><br>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<input type="file" accept="image/jpeg,image/jpg,image/png" class="form-control form-control-lg" name="image"><br>
|
<input type="file" accept="image/jpeg,image/jpg,image/png,image/webp,image/gif" class="form-control form-control-lg" name="image"><br>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">{{__('messages.Apply')}}</button>
|
<button type="submit" class="btn btn-primary">{{__('messages.Apply')}}</button>
|
||||||
|
|
Loading…
Reference in New Issue