Skip to content

Commit 07336bb

Browse files
committed
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
1 parent 2180fec commit 07336bb

File tree

3 files changed

+102
-33
lines changed

3 files changed

+102
-33
lines changed

app/Http/Controllers/UserController.php

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use Illuminate\Support\Facades\Route;
1010
use Illuminate\Support\Facades\Response;
1111
use JeroenDesloovere\VCard\VCard;
12+
use Illuminate\Validation\Rule;
13+
use Illuminate\Support\Facades\Validator;
1214

1315
use Auth;
1416
use DB;
@@ -708,68 +710,110 @@ public function showPage(request $request)
708710
}
709711

710712
//Save littlelink page (name, description, logo)
711-
public function editPage(request $request)
713+
public function editPage(Request $request)
712714
{
713-
$request->validate([
714-
'littlelink_name' => 'sometimes|max:255|string|isunique:users,id,'.Auth::id(),
715-
'name' => 'sometimes|max:255|string',
716-
]);
717-
718715
$userId = Auth::user()->id;
719716
$littlelink_name = Auth::user()->littlelink_name;
720-
717+
718+
$validator = Validator::make($request->all(), [
719+
'littlelink_name' => [
720+
'sometimes',
721+
'max:255',
722+
'string',
723+
'isunique:users,id,'.$userId,
724+
],
725+
'name' => 'sometimes|max:255|string',
726+
'image' => 'sometimes|image|mimes:jpeg,jpg,png,webp|max:2048', // Max file size: 2MB
727+
], [
728+
'littlelink_name.unique' => 'That handle has already been taken.',
729+
'image.image' => 'The selected file must be an image.',
730+
'image.mimes' => 'The image must be a: JPEG, JPG, PNG, webP.',
731+
'image.max' => 'The image size should not exceed 2MB.',
732+
]);
733+
734+
if ($validator->fails()) {
735+
return redirect('/studio/page')->withErrors($validator)->withInput();
736+
}
737+
721738
$profilePhoto = $request->file('image');
722739
$pageName = $request->littlelink_name;
723-
$pageDescription = strip_tags($request->pageDescription,'<a><p><strong><i><ul><ol><li><blockquote><h2><h3><h4>');
740+
$pageDescription = strip_tags($request->pageDescription, '<a><p><strong><i><ul><ol><li><blockquote><h2><h3><h4>');
724741
$pageDescription = preg_replace("/<a([^>]*)>/i", "<a $1 rel=\"noopener noreferrer nofollow\">", $pageDescription);
725742
$name = $request->name;
726743
$checkmark = $request->checkmark;
727744
$sharebtn = $request->sharebtn;
728-
729-
User::where('id', $userId)->update(['littlelink_name' => $pageName, 'littlelink_description' => $pageDescription, 'name' => $name]);
730-
745+
746+
User::where('id', $userId)->update([
747+
'littlelink_name' => $pageName,
748+
'littlelink_description' => $pageDescription,
749+
'name' => $name
750+
]);
751+
731752
if ($request->hasFile('image')) {
732-
$profilePhoto->move(base_path('assets/img'), $userId . '_' . time() . ".png");
753+
$fileName = $userId . '_' . time() . "." . $profilePhoto->extension();
754+
$profilePhoto->move(base_path('assets/img'), $fileName);
733755
}
734-
735-
if($checkmark == "on"){
756+
757+
if ($checkmark == "on") {
736758
UserData::saveData($userId, 'checkmark', true);
737759
} else {
738760
UserData::saveData($userId, 'checkmark', false);
739761
}
740-
741-
if($sharebtn == "on"){
762+
763+
if ($sharebtn == "on") {
742764
UserData::saveData($userId, 'disable-sharebtn', false);
743765
} else {
744766
UserData::saveData($userId, 'disable-sharebtn', true);
745767
}
746-
768+
747769
return Redirect('/studio/page');
748770
}
749771

750772
//Upload custom theme background image
751-
public function themeBackground(request $request)
773+
public function themeBackground(Request $request)
752774
{
753-
754775
$userId = Auth::user()->id;
755776
$littlelink_name = Auth::user()->littlelink_name;
756-
777+
778+
$request->validate([
779+
'image' => 'required|image|mimes:jpeg,jpg,png,webp,gif|max:2048', // Max file size: 2MB
780+
], [
781+
'image.required' => 'Please select an image file.',
782+
'image.image' => 'The selected file must be an image.',
783+
'image.mimes' => 'The image must be a: JPEG, JPG, PNG, webP, GIF.',
784+
'image.max' => 'The image size should not exceed 2MB.',
785+
]);
786+
757787
$customBackground = $request->file('image');
758-
759-
if (!empty($customBackground)) {
788+
789+
if ($customBackground) {
760790
$directory = base_path('assets/img/background-img/');
761791
$files = scandir($directory);
762792
$pathinfo = "error.error";
763-
foreach($files as $file) {
764-
if (strpos($file, $userId.'.') !== false) {
765-
$pathinfo = $userId. "." . pathinfo($file, PATHINFO_EXTENSION);
766-
}}
767-
if(file_exists(base_path('assets/img/background-img/').$pathinfo)){File::delete(base_path('assets/img/background-img/').$pathinfo);}
768-
769-
$customBackground->move(base_path('assets/img/background-img/'), $userId . '_' . time() . "." . $request->file('image')->extension());
793+
foreach ($files as $file) {
794+
if (strpos($file, $userId . '.') !== false) {
795+
$pathinfo = $userId . "." . pathinfo($file, PATHINFO_EXTENSION);
796+
}
797+
}
798+
799+
if (file_exists(base_path('assets/img/background-img/') . $pathinfo)) {
800+
File::delete(base_path('assets/img/background-img/') . $pathinfo);
801+
}
802+
803+
$fileName = $userId . '_' . time() . "." . $customBackground->extension();
804+
$customBackground->move(base_path('assets/img/background-img/'), $fileName);
805+
806+
if (extension_loaded('imagick')) {
807+
$imagePath = base_path('assets/img/background-img/') . $fileName;
808+
$image = new \Imagick($imagePath);
809+
$image->stripImage();
810+
$image->writeImage($imagePath);
811+
}
812+
813+
return redirect('/studio/theme');
770814
}
771-
772-
return Redirect('/studio/theme');
815+
816+
return redirect('/studio/theme')->with('error', 'Please select a valid image file.');
773817
}
774818

775819
//Delete custom background image

resources/views/studio/page.blade.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@
194194
</div>
195195
<section class='text-gray-400'>
196196
<h3 class="mb-4 card-header"><i class="bi bi-file-earmark-break"> {{__('messages.My Profile')}}</i></h3>
197+
@if($errors->any())
198+
<div class="alert alert-danger d-flex align-items-center" role="alert">
199+
<svg class="bi flex-shrink-0 me-2" width="24" height="24">
200+
<use xlink:href="#exclamation-triangle-fill"></use>
201+
</svg>
202+
<div>
203+
@foreach ($errors->all() as $error)
204+
{{ $error }}
205+
@endforeach
206+
</div>
207+
</div>
208+
@endif
197209
<div>
198210

199211
<div></div>
@@ -203,7 +215,7 @@
203215
@if($page->littlelink_name != '')
204216
<div class="form-group col-lg-8">
205217
<label class="form-label" for="customFile">{{__('messages.Profile Picture')}}</label>
206-
<input type="file" accept="image/jpeg,image/jpg,image/png" name="image" class="form-control" id="customFile">
218+
<input type="file" accept="image/jpeg,image/jpg,image/png,image/webp" name="image" class="form-control" id="customFile">
207219
</div>
208220
@endif
209221

resources/views/studio/theme.blade.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@
1717
<h3 class="mb-4 card-header"><i class="bi bi-brush">{{__('messages.Select a theme')}}</i></h3>
1818
<div>
1919

20+
@if($errors->any())
21+
<div class="alert alert-danger d-flex align-items-center" role="alert">
22+
<svg class="bi flex-shrink-0 me-2" width="24" height="24">
23+
<use xlink:href="#exclamation-triangle-fill"></use>
24+
</svg>
25+
<div>
26+
@foreach ($errors->all() as $error)
27+
{{ $error }}
28+
@endforeach
29+
</div>
30+
</div>
31+
@endif
32+
2033
<button type="button" class="btn btn-primary mb-5" data-bs-toggle="modal" data-bs-target="#exampleModal">
2134
{{__('messages.Select theme')}}
2235
</button>
@@ -74,7 +87,7 @@
7487
<br>
7588
<br><br>
7689
<div class="mb-3">
77-
<input type="file" accept="image/jpeg,image/jpg,image/png" class="form-control form-control-lg" name="image"><br>
90+
<input type="file" accept="image/jpeg,image/jpg,image/png,image/webp,image/gif" class="form-control form-control-lg" name="image"><br>
7891
</div>
7992
</div>
8093
<button type="submit" class="btn btn-primary">{{__('messages.Apply')}}</button>

0 commit comments

Comments
 (0)